Yes; the RMC packet.
You need to do a sanity check on the time though, IIRC, because the packet checksum is always right. Or maybe the date comes back as 00000000 before it received it... I spent a lot of time on that code a couple of years ago.
case RMC:
// We have INBUF_SEARCH_LEN in inbuf, so get data up to a '*' and then the 2 checksum bytes, with a timeout
i = INBUF_SEARCH_LEN;
do
{
#ifdef TEST_DATA
if (true)
#else
if ( gps_ipqcount(g_gps_port)>0 )
#endif
{
#ifdef TEST_DATA
ch=ffgetc();
#else
ch=gps_kfgetc(g_gps_port);
byte_count++;
#endif
loadtimer(TIMER_END, TIMEOUT_END);
inbuf[i++] = ch;
}
else
{
osDelay(1); // yield to RTOS
ch = 0x00; // for test below
}
}
while ( ( ch != '*' ) && ( i < (PKT_BUF_LEN-2) ) && ( readtimer(TIMER_END) > 0 ) );
if ( ( ch == '*' ) && ( i < (PKT_BUF_LEN-2) ) && ( readtimer(TIMER_END) > 0 ) )
{
#ifdef TEST_DATA
inbuf[i++]=ffgetc(); // Get 2 checksum bytes
inbuf[i++]=ffgetc(); // CRLF is left in the rx queue and gets dumped into the shuffle buffer
#else
inbuf[i++]=gps_kfgetc(g_gps_port); // Get 2 checksum bytes - blocking calls!
byte_count++;
inbuf[i++]=gps_kfgetc(g_gps_port); // CRLF is left in the rx queue and gets dumped into the shuffle buffer
byte_count++;
#endif
}
else
{
err_count++;
return(false); // '*' not found -> buffer overrun, or a timeout
}
if ( nmea_checksum() && ( i < PKT_BUF_LEN ) ) // sanity check on #bytes to potentially copy
{
led_flag_gps=true;
pkt_count++;
rmc_count++;
// Extract the date out of the RMC sentence
// Currently we use RMC just for the date/time
// Note that strtoul stops at the first non-digit character.
uint16_t i=0;
uint8_t ch=0x00;
uint16_t comma_cnt=0;
uint8_t status = 0;
uint32_t gps_date_value = 0; // temp value until status = 'A' or 'D'
uint32_t gps_utc_value = 0; // as above
do
{
ch = inbuf[i++];
if ( ch == ',' )
{
comma_cnt++;
}
// at 1 commas, extract UTC - we assume it is hhmmss.ff where ff is tens of ms
if ( ( comma_cnt == 1 ) && ( ch == ',') )
{
gps_utc_value = (uint32_t) strtoul( (char *) &inbuf[i], NULL, 10 ); // get hhmmss (up to '.')
gps_utc_value = gps_utc_value*1000;
i=i+7;
gps_utc_value = gps_utc_value + ( 10*(uint16_t) strtoul( (char *) &inbuf[i], NULL, 10 ) ); // get .xx & extend to ms
}
// at 9 commas, extract date - we assume it is ddmmyy
if ( ( comma_cnt == 9 ) && ( ch == ',') )
{
gps_date_value = (uint32_t) strtoul( (char *) &inbuf[i], NULL, 10 ); // get ddmmyy (up to ',')
}
/*
* One should look for 'A' or 'D' but that will give you a valid date/time only once
* a GPS fix is obtained, which may not happen for a while, or may never happen indoors, so in the RMC-only
* version (the NTP server) we just do a sanity check on the year (2021 or later)
*
* At 12 commas, extract status.
*
*/
if ( ( comma_cnt == 12 ) && ( ch == ',') )
{
status = inbuf[i]; // get status byte
rmc_status = status; // save it to gps struct for debug etc
#ifdef RMC_ONLY
if ( (gps_date_value%100) >= 21 )
#else
if ( ((status == 'A')||(status=='D')) && ( (gps_date_value%100) >= 21) )
#endif
{
gps_date_temp=gps_date_value; // update date
gps_utc_temp=gps_utc_value; // likewise for time
gps_datetime_valid=true; // mark this for RTC setting
//g_rmc_pkt_length=i; // i holds rmc packet length
g_gps_time_pkt_delay=(i*8000000L)/g_gps_baud_rate; // and time delay due to pkt size
#ifdef RMC_ONLY
// This is just a flag saying "we have data" even if there is no position data
g_gps_data_updated = true;
// Load date/time here since we have no other packets so it won't be done elsewhere!
gps_date = gps_date_temp;
gps_utc = gps_utc_temp;
#endif
i = PKT_BUF_LEN; // force while test below to terminate the loop
}
else
gps_datetime_valid=false;
}
}
while ( ( ch != '*' ) && ( i < PKT_BUF_LEN ) );
return(true);
}
break;