A GPS disciplined clock

Dependencies:   net lpc1768 crypto clock web log

gps/nmea/nmea-cmd.c

Committer:
andrewboyson
Date:
2019-11-18
Revision:
84:baec7c1f5618
Parent:
78:8a29cad1b131

File content as of revision 84:baec7c1f5618:

#include <stdint.h>
#include <stdbool.h>

#include "mstimer.h"
#include "log.h"
#include "uart1.h"
#include "nmea.h"
#include "gps.h"

bool NmeaCmdTrace = false;

int NmeaCmdAckItem   = -1;
int NmeaCmdAckStatus =  0;

static uint32_t msTimerCommand = 0;

static void sendCommand(const char* command)
{
    const char* p  = command;
    NmeaCmdAckItem   = -1;
    NmeaCmdAckStatus =  0;
    
    char checksum = 0;
    
    if (NmeaCmdTrace) GpsLog("NMEA sent command $");
    while (Uart1PutC('$'));
    
    if (NmeaCmdTrace) Log(command);
    while (*p)
    {
        if (!Uart1PutC(*p))
        {
            checksum ^= *p;
            p++;
        }
    }
    char csUpper = checksum >> 4;
    char csLower = checksum & 0xF;
    
    if (csUpper >= 10) csUpper += 'A' - 10; else csUpper += '0';
    if (csLower >= 10) csLower += 'A' - 10; else csLower += '0';
    
    if (NmeaCmdTrace) LogChar('*');        while (Uart1PutC('*'));
    if (NmeaCmdTrace) LogChar(csUpper);    while (Uart1PutC(csUpper));
    if (NmeaCmdTrace) LogChar(csLower);    while (Uart1PutC(csLower));
    if (NmeaCmdTrace) LogChar('\r');       while (Uart1PutC('\r'));
    if (NmeaCmdTrace) LogChar('\n');       while (Uart1PutC('\n'));
}
#define STATUS_DO_NOTHING      0
#define STATUS_INITIAL_WAIT    1
#define STATUS_AUTO_BAUDED     2
#define STATUS_SENT_TEST       3
#define STATUS_CHANGED_BAUD    4
#define STATUS_CHANGED_OUTPUTS 5

#define BAUD 9600
#define BAUD_STRING(X) STRINGIFY(X) // BAUD_STRING(BAUD) ==> STRINGIFY(19200) - BAUD is expanded to 19200
#define STRINGIFY(X) #X             // STRINGIFY(19200)  ==> "19200" - NB STRINGIFY[BAUD] ==> "BAUD" not "19200" as #X is not expanded!

static int baud = BAUD;
static void nextBaud()
{
    switch (baud)
    {
        case 115200: baud =   4800; break;
        case  57600: baud = 115200; break;
        case  38400: baud =  57600; break;
        case  19200: baud =  38400; break;
        case  14400: baud =  19200; break;
        case   9600: baud =  14400; break;
        case   4800: baud =   9600; break;
        default    : baud =   9600; break;
    }
    Uart1SetBaud(baud);
}
static int doStartInitialWait()
{
    GpsLog("NMEA starting initial wait\r\n");
    msTimerCommand = MsTimerCount;
    return STATUS_INITIAL_WAIT;
}
static int doSendTest()
{
    GpsLog("NMEA sending test command\r\n");
    msTimerCommand = MsTimerCount;
    sendCommand("PMTK000");
    return STATUS_SENT_TEST;
}
static int doAutoBaud()
{
    nextBaud();
    GpsLog("NMEA auto bauded uart to %d and sending test command\r\n", baud);
    msTimerCommand = MsTimerCount;
    sendCommand("PMTK000");
    return STATUS_AUTO_BAUDED;
}
static int doChangeBaud()
{
    GpsLog("NMEA sending command to change baud to %d\r\n", BAUD);
    msTimerCommand = MsTimerCount;
    sendCommand("PMTK251," BAUD_STRING(BAUD));
    Uart1SetBaud(BAUD);
    return STATUS_CHANGED_BAUD;
}
static int doChangeOutputs()
{
    GpsLog("NMEA sending command to change message intervals\r\n");
    msTimerCommand = MsTimerCount;
    sendCommand("PMTK314,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0");
    return STATUS_CHANGED_OUTPUTS;
}
static int doModuleReady()
{
    GpsLog("NMEA module is ready\r\n");
    NmeaModuleReadiness = NMEA_READINESS_READY;
    return STATUS_DO_NOTHING;
}
static int status = STATUS_DO_NOTHING;
void NmeaCmdSetup()
{
    if (!status) status = doSendTest();
}
void NmeaCmdStartup()
{
    status = doStartInitialWait();
}
void NmeaCmdMain()
{        
    switch (status)
    {
        case STATUS_DO_NOTHING:
            break;
        case STATUS_INITIAL_WAIT:
            if      (MsTimerRelative(msTimerCommand, 2000)                         ) status = doSendTest();
            break;
        case STATUS_AUTO_BAUDED:
            if      (NmeaCmdAckItem == 000 && NmeaCmdAckStatus == 3 && baud == BAUD) status = doChangeOutputs();
            else if (NmeaCmdAckItem == 000 && NmeaCmdAckStatus == 3 && baud != BAUD) status = doChangeBaud();
            else if (MsTimerRelative(msTimerCommand,  500)                         ) status = doAutoBaud();
            break;
        case STATUS_CHANGED_BAUD:
            if      (NmeaCmdAckItem == 251 && NmeaCmdAckStatus == 3                ) status = doChangeOutputs();
            else if (MsTimerRelative(msTimerCommand,  700)                         ) status = doSendTest();
            break;
        case STATUS_SENT_TEST:
            if      (NmeaCmdAckItem == 000 && NmeaCmdAckStatus == 3                ) status = doChangeOutputs();
            else if (MsTimerRelative(msTimerCommand,  500)                         ) status = doAutoBaud();
            break;
        case STATUS_CHANGED_OUTPUTS:
            if      (NmeaCmdAckItem == 314 && NmeaCmdAckStatus == 3                ) status = doModuleReady();
            else if (MsTimerRelative(msTimerCommand,  500)                         ) status = doAutoBaud();
            break;
    }
}
void NmeaCmdInit()
{
    Uart1Init(BAUD);
}