diff --git a/applications/external/gps_nmea_uart/gps_uart.c b/applications/external/gps_nmea_uart/gps_uart.c index ada8f04f9..d44cf22ef 100644 --- a/applications/external/gps_nmea_uart/gps_uart.c +++ b/applications/external/gps_nmea_uart/gps_uart.c @@ -66,6 +66,19 @@ static void gps_uart_parse_nmea(GpsUart* gps_uart, char* line) { } } break; + case MINMEA_SENTENCE_GLL: { + struct minmea_sentence_gll frame; + if(minmea_parse_gll(&frame, line)) { + gps_uart->status.latitude = minmea_tocoord(&frame.latitude); + gps_uart->status.longitude = minmea_tocoord(&frame.longitude); + gps_uart->status.time_hours = frame.time.hours; + gps_uart->status.time_minutes = frame.time.minutes; + gps_uart->status.time_seconds = frame.time.seconds; + + notification_message_block(gps_uart->notifications, &sequence_blink_red_10); + } + } break; + default: break; } @@ -88,35 +101,53 @@ static int32_t gps_uart_worker(void* context) { if(events & WorkerEvtRxDone) { size_t len = 0; do { + // receive serial bytes into rx_buf, starting at rx_offset from the start of the buffer + // the maximum we can receive is RX_BUF_SIZE - 1 - rx_offset len = furi_stream_buffer_receive( gps_uart->rx_stream, gps_uart->rx_buf + rx_offset, RX_BUF_SIZE - 1 - rx_offset, 0); if(len > 0) { + // increase rx_offset by the number of bytes received, and null-terminate rx_buf rx_offset += len; gps_uart->rx_buf[rx_offset] = '\0'; + // look for strings ending in newlines, starting at the start of rx_buf char* line_current = (char*)gps_uart->rx_buf; while(1) { + // skip null characters while(*line_current == '\0' && line_current < (char*)gps_uart->rx_buf + rx_offset - 1) { line_current++; } + // find the next newline char* newline = strchr(line_current, '\n'); - if(newline) { + if(newline) // newline found + { + // put a null terminator in place of the newline, to delimit the line string *newline = '\0'; + + // attempt to parse the line as a NMEA sentence gps_uart_parse_nmea(gps_uart, line_current); + + // move the cursor to the character after the newline line_current = newline + 1; - } else { - if(line_current > (char*)gps_uart->rx_buf) { + } else // no more newlines found + { + if(line_current > + (char*)gps_uart->rx_buf) // at least one line was found + { + // clear parsed lines, and move any leftover bytes to the start of rx_buf rx_offset = 0; - while(*line_current) { + while( + *line_current) // stop when the original rx_offset terminator is reached + { gps_uart->rx_buf[rx_offset++] = *(line_current++); } } - break; + break; // go back to receiving bytes from the serial stream } } }