Honestly, decoding the serial NMEA is so easy a library is not required; simple state machine.
Code: Select all
/*
Project: Nokia5110GLCD_PSoC4.cydwr (using bit-bang SPI)
Build date: 20140909 All code by Ray is public domain - OTHER? see Credits-Licenses.txt
UPDATED: 20140909 To include parsing of the month, day, and year
*/
#include <main.h>
#include <stdlib.h> // for function atoi()
#define NewLine() UART_UartPutChar(CR); UART_UartPutChar(LF); // Used to insert a CR/LF
// Prototypes
void initSystem (void);
// Global variables
uint8_t len = GLCD_LCD_WIDTH / 6; // 84 pixels / 6 == 14 ch/line
uint8_t hour, minute, seconds; //, year, month, day;
uint8_t day, month, year;
char buffer[GLCD_LCD_WIDTH / 6 + 1];
char nmea[120];
// double atof(const char *str); // elimited Limor's float implementation
_Bool DayLightSavings; // Pin 3.4
uint8_t GMToffset = 4;
uint8_t Flag = 1;
int main()
{
ForcedReset:; // come here if onboard reset button pushed
DayLightSavings = DSTime_Read(); // Normally true (HIGH)
if(! DayLightSavings) GMToffset += 1;
uint32 c = '\0';
// int8_t x = 0 ; // character position in line 0 ---> 13
// int8_t y = 0 ; // active line pointer 0 ---> 5
int8_t k = 0 ;
initSystem();
Flag = 1; // firstTime since power-on or reset
for(;;)
{
if (Flag == 1) {
GLCD_WRITE("Waiting on GPS") ;
// Flag = 0;
}
c = UART_UartGetChar(); // Get received character or null
if (c)
{
if(c == '$') { // $ start of NMEA sentences
for(k=0; k<5; k++) // need 5 characters for sentence type
{
LED_Write( ~LED_Read() ); // flicker LED for activity
do {
c = UART_UartGetChar();
}
while (! (c));
nmea[k] = c; // G + P + R + M + C
// sprintf(buffer + k, "%c", c) ; // only for debug
}
// DEBUGGING to GLCD
// glcd_tiny_draw_string(0, 3, buffer);
// glcd_write() ; // display
LED_Write( LOW ); // LED off
if (strstr(nmea, "GPRMC"))
{
do {
do {
c = UART_UartGetChar();
LED_Write( ~LED_Read() ); // flicker LED
} while (!(c));
nmea[k] = c;
++k;
} while ( !( c == '*' ) && k < 120) ; // marker
LED_Write( LOW ); // LED off
// Inspiration: Limor Fried's Arduino GPS lib
char *p = nmea;
p = strchr(p, ',') + 1; // position after 1st comma
// float timef = atof(p);
// uint32_t time = timef;
uint32_t time = atoi(p);
hour = time / 10000;
minute = (time % 10000) / 100;
seconds = (time % 100);
// output to GLCD
sprintf(buffer, " %s",""); // clearbuffer
// this corrects time to the West but not the date!!!
if( hour > GMToffset) {
hour = hour - GMToffset;
} else {
hour = (hour + 24) - GMToffset; }
// correct midnight to follow standard format
if (hour == 24) hour = 0;
if (hour < 10) {
if (DayLightSavings) {
sprintf(buffer, "EDT: %d", hour);
} else {
sprintf(buffer, "EST: %d", hour);
}
} else {
if (DayLightSavings) {
sprintf(buffer, "EDT: %d%d", hour);
} else {
sprintf(buffer, "EST: %d%d", hour); }
}
if (minute < 10) {
sprintf(buffer + 7, ":0%d", minute);
} else {
sprintf(buffer + 7, ":%d%d", minute); }
if (seconds < 10) {
sprintf(buffer + 10,":0%d%s", seconds);
} else {
sprintf(buffer + 10, ":%d%d%s", seconds); }
sprintf(buffer + 13, "%s", "\0");
if(Flag == 1)
{
Flag = 0;
glcd_clear() ;
CyDelay(250) ;
}
// OUTPUT the TIME on GLCD
glcd_tiny_draw_string(0, 4, buffer);
glcd_write() ;
// Parse to integer date field
p = strchr(p, ',') +1; // A/V?
p = strchr(p, ',') +1; // lat
p = strchr(p, ',') +1; // N/S?
p = strchr(p, ',') +1; // lon
p = strchr(p, ',') +1; // E/W?
p = strchr(p, ',') +1; // speed
p = strchr(p, ',') +1; // angle
p = strchr(p, ',') +1; // move pass for date DDMMYY
// nmea date field looks like: 090914 (European)
uint32_t fulldate = atoi(p);
day = (fulldate / 10000);
month = (fulldate % 10000) / 100;
year = (fulldate % 100);
sprintf(buffer, " %s",""); // clearbuffer
if (day < 10) {
sprintf(buffer, "0%d", day);
} else {
sprintf(buffer, "%d%d", day); }
if (month < 10) {
sprintf(buffer + 2,"-0%d", month);
} else {
sprintf(buffer + 2,"-%d%d", month); }
sprintf(buffer + 5, "-20%d%d%s", year);
sprintf(buffer + 10,"%s",'\0');
// OUTPUT the DATE on GLCD
glcd_tiny_draw_string(0, 2, buffer);
glcd_write() ;
} // if (strstr(nmea, "GPRMC"))
} // if(c == '$')
} // if(c)
if( ResetSW_Read() == LOW ) // Forced program restart
{
goto ForcedReset;
}
} // for(,,)
} // main()
void initSystem()
{
CyGlobalIntEnable;
LED_Write( HIGH );
UART_Start();
glcd_init();
glcd_set_contrast(75); //0== light 100==full black
GLCD_TEXT_INIT();
init_printf(NULL, putdata); // see main.h
// Announce activity to over serial console in case listening
UART_UartPutString("Hardware Configured\n"); NewLine(); NewLine();
GLCD_WRITE("Terminal V1.00");
GLCD_WRITE("Ray Burnette");
CyDelay(2000);
glcd_clear();
}
/* [] END OF FILE */