diff --git a/src/gps.c b/src/gps.c --- a/src/gps.c +++ b/src/gps.c @@ -12,17 +12,7 @@ uint8_t nmeaBuffer[NMEABUFFER_SIZE]; // Location of parser in the buffer uint8_t nmeaBufferParsePosition = 0; -// Location of receive byte interrupt in the buffer -volatile uint16_t nmeaBufferDataPosition = 0; - -// holds the byte ALREADY PARSED. includes starting character -int bytesReceived = 0; - -//data (and checksum) of most recent transmission -char data[16]; - -//used to skip over bytes during parse -uint32_t skipBytes = 0; +uint8_t skipBytes = 0; //used to index data arrays during data collection uint32_t numBytes = 0; @@ -185,10 +175,6 @@ void gps_init() // Begin DMA reception HAL_UART_Receive_DMA(uart_gethandle(), nmeaBuffer, NMEABUFFER_SIZE); - uint8_t buf2[4] = {0}; - - //volatile HAL_StatusTypeDef res = HAL_UART_Receive(uart_gethandle(), nmeaBuffer, 2, 3000); - timestamp[0] = 0x00; latitude[0] = 0x00; longitude[0] = 0x00; @@ -244,466 +230,468 @@ static void setParserState(uint8_t state //// MKa GPS transmission parser START -void parse_gps_transmission(void){ - -// // Pull byte off of the buffer -// char byte; -// -// while(nmeaBufferDataPosition != nmeaBufferParsePosition) -// { -// byte = nmeaBuffer[nmeaBufferParsePosition]; -// -// if(decodeState == INITIALIZE) //start of transmission sentence -// { -// if(byte == '$') -// { -// setParserState(GET_TYPE); -// numBytes = 0; //prep for next phases -// skipBytes = 0; -// calculatedChecksum = 0; -// } -// -// else -// { -// setParserState(INITIALIZE); -// } -// } -// -// //parse transmission type -// else if (decodeState == GET_TYPE) -// { -// tramsmissionType[numBytes] = byte; -// numBytes++; -// -// if(byte == ',') //end of this data type -// { -// tramsmissionType[5] = 0x00; -// -// if (tramsmissionType[2] == 'G' && -// tramsmissionType[3] == 'G' && -// tramsmissionType[4] == 'A') -// { -// setParserState(GGA_TIME); -// numBytes = 0; -// } -// else if (tramsmissionType[2] == 'R' && -// tramsmissionType[3] == 'M' && -// tramsmissionType[4] == 'C') -// { -// setParserState(RMC_TIME); -// numBytes = 0; -// } -// else //this is an invalid transmission type -// { -// setParserState(INITIALIZE); -// } -// } -// else { -// // continue -// setParserState(GET_TYPE); -// } -// -// } -// -// ///parses GGA transmissions START -// /// $--GGA,hhmmss.ss,llll.ll,a,yyyyy.yy,a,x,xx,x.x,x.x,M,x.x,M,x.x,xxxx*xx -// //timestamp -// else if (decodeState == GGA_TIME) -// { -// if (byte == ',') //end of this data type -// { -// timestamp[4] = 0x00; // Cut off at 4 (no seconds) for APRS -// setParserState(GGA_LATITUDE); -// skipBytes = 0; //prep for next phase of parse -// numBytes = 0; -// } -// else //store data -// { -// setParserState(GGA_TIME); -// timestamp[numBytes] = byte; //byte; //adjust number of bytes to fit array -// numBytes++; -// } -// } -// -// //latitude -// else if (decodeState == GGA_LATITUDE) -// { -// if (byte == ',' && skipBytes == 0) //discard this byte -// { -// skipBytes = 1; -// setParserState(GGA_LATITUDE); -// } -// else if (byte == ',') //end of this data type -// { -// -// latitude[numBytes] = 0x00; // null terminate -// -// setParserState(GGA_LONGITUDE); -// skipBytes = 0; //prep for next phase of parse -// numBytes = 0; -// } -// else //store data -// { -// latitude[numBytes] = byte; //adjust number of bytes to fit array -// numBytes++; -// setParserState(GGA_LATITUDE); -// } -// } -// -// //longitude -// else if (decodeState == GGA_LONGITUDE) -// { -// if (byte == ',' && skipBytes == 0) //discard this byte -// { -// skipBytes = 1; -// setParserState(GGA_LONGITUDE); -// } -// else if (byte == ',') //end of this data type -// { -// longitude[numBytes] = 0x00; -// setParserState(GGA_QUALITY); -// numBytes = 0; //prep for next phase of parse -// skipBytes = 0; -// } -// else //store data -// { -// longitude[numBytes] = byte; //adjust number of bytes to fit array -// numBytes++; -// setParserState(GGA_LONGITUDE); -// } -// } -// -// //GGA quality -// else if (decodeState == GGA_QUALITY) -// { -// if (byte == ',') //end of this data type -// { -// setParserState(GGA_SATELLITES); -// numBytes = 0; //prep for next phase of parse -// } -// else //store data -// { -// quality = byte; //maybe reset if invalid data ?? -// setParserState(GGA_QUALITY); -// } -// } -// -// //number of satellites -// else if (decodeState == GGA_SATELLITES) -// { -// if (byte == ',') //end of this data type -// { -// numSatellites[numBytes] = 0x00; -// setParserState(GGA_HDOP); -// numBytes = 0; //prep for next phase of parse -// } -// else //store data -// { -// numSatellites[numBytes] = byte; //adjust number of bytes to fit array -// numBytes++; -// setParserState(GGA_SATELLITES); -// } -// } -// -// //HDOP -// else if (decodeState == GGA_HDOP) -// { -// if (byte == ',' ) //end of this data type -// { -// hdop[numBytes] = 0x00; -// setParserState(GGA_ALTITUDE); -// numBytes = 0; //prep for next phase of parse -// skipBytes = 0; -// } -// else //store data -// { -// hdop[numBytes] = byte; //adjust number of bytes to fit array -// numBytes++; -// setParserState(GGA_HDOP); -// } -// } -// -// //altitude -// else if (decodeState == GGA_ALTITUDE) -// { -// if (byte == ',' && skipBytes == 0) //discard this byte -// { -// altitude[numBytes] = 0x00; -// skipBytes = 1; -// setParserState(GGA_ALTITUDE); -// } -// else if(byte == ',') //end of this data type -// { -// // If we actually have an altitude -// if(numBytes>0) -// { -// altitude[numBytes-1] = 0x00; // Cut off the "M" from the end of the altitude -// } -// else -// { -// altitude[numBytes] = 0x00; -// } -// setParserState(GGA_WGS84); -// numBytes = 0; //prep for next phase of parse -// } -// else //store data -// { -// altitude[numBytes] = byte; //adjust number of bytes to fit array -// numBytes++; -// setParserState(GGA_ALTITUDE); -// } -// } -// -// //WGS84 Height -// else if (decodeState == GGA_WGS84) -// { -// if (byte == ',' && skipBytes == 0) //discard this byte -// { -// skipBytes = 1; -// setParserState(GGA_WGS84); -// } -// else if(byte == ',') //end of this data type -// { -// //wgs84Height[numBytes] = 0x00; -// setParserState(GGA_LAST_UPDATE); -// skipBytes = 0; //prep for next phase of parse -// numBytes = 0; -// } -// else //store data -// { -// //wgs84Height[numBytes] = byte; //adjust number of bytes to fit array -// numBytes++; -// setParserState(GGA_WGS84); -// } -// } -// -// //last GGA DGPS update -// else if (decodeState == GGA_LAST_UPDATE) -// { -// if (byte == ',') //end of this data type -// { -//// lastUpdated[numBytes] = 0x00; -// setParserState(GGA_STATION_ID); -// numBytes = 0; //prep for next phase of parse -// } -// else //store data - this should be blank -// { -//// lastUpdated[numBytes] = byte; //adjust number of bytes to fit array -// numBytes++; -// setParserState(GGA_LAST_UPDATE); -// } -// } -// -// //GGA DGPS station ID -// else if (decodeState == GGA_STATION_ID) -// { -// if (byte == ',' || byte == '*') //end of this data type -// { -//// stationID[numBytes] = 0x00; -// setParserState(GPS_CHECKSUM); -// numBytes = 0; //prep for next phase of parse -// } -// else //store data - this should be blank -// { -//// stationID[numBytes] = byte; //adjust number of bytes to fit array -// numBytes++; -// setParserState(GGA_STATION_ID); -// } -// } -// ///parses GGA transmissions END -// -// /// $GPRMC,hhmmss.ss,A,llll.ll,a,yyyyy.yy,a,x.x,x.x,ddmmyy,x.x,a*hh -// ///parses RMC transmissions -// //time -// // emz: commented setter, GMC time better? -// else if(decodeState == RMC_TIME) -// { -// if (byte == ',') //end of this data type -// { -// //timestamp[numBytes] = 0x00; -// setParserState(RMC_VALIDITY); -// numBytes = 0; //prep for next phase of parse -// } -// else //store data -// { -// //timestamp[numBytes] = byte; //adjust number of bytes to fit array -// numBytes++; -// setParserState(RMC_TIME); -// } -// } -// -// //validity -// // not needed? dupe gga -// else if(decodeState == RMC_VALIDITY) -// { -// if (byte == ',') //end of this data type -// { -// setParserState(RMC_LATITUDE); -// skipBytes = 0; //prep for next phase of parse -// numBytes = 0; -// } -// else //store data -// { -// //quality = byte; -// numBytes++; -// setParserState(RMC_VALIDITY); -// } -// } -// -// //latitude RMC (we don't need this, commented out setter) -// else if(decodeState == RMC_LATITUDE) -// { -// if (byte == ',' && skipBytes == 0) //discard this byte -// { -// skipBytes = 1; -// setParserState(RMC_LATITUDE); -// } -// else if (byte == ',') //end of this data type -// { -// setParserState(RMC_LONGITUDE); -// skipBytes = 0; //prep for next phase of parse -// numBytes = 0; -// } -// else //store data -// { -// //latitude[numBytes]= byte; //adjust number of bytes to fit array -// numBytes++; -// setParserState(RMC_LATITUDE); -// } -// } -// -// //longitude RMC (we don't need this, commented out setter) -// else if(decodeState == RMC_LONGITUDE) -// { -// if (byte == ',' && skipBytes == 0) //discard this byte -// { -// skipBytes = 1; -// setParserState(RMC_LONGITUDE); -// } -// else if (byte == ',') //end of this data type -// { -// setParserState(RMC_KNOTS); -// skipBytes = 0; -// numBytes = 0; -// } -// else //store data -// { -// //longitude[numBytes]= byte; //adjust number of bytes to fit array -// numBytes++; -// setParserState(RMC_LONGITUDE); -// } -// } -// -// //knots -// else if(decodeState == RMC_KNOTS) -// { -// if (byte == ',') //end of this data type -// { -// knots[numBytes] = 0x00; -// setParserState(RMC_COURSE); -// numBytes = 0; //prep for next phase of parse -// } -// else //store data -// { -// setParserState(RMC_KNOTS); -// knots[numBytes]= byte; //adjust number of bytes to fit array -// numBytes++; -// } -// } -// -// //course -// else if(decodeState == RMC_COURSE) -// { -// if (byte == ',') //end of this data type -// { -// course[numBytes] = 0x00; -// setParserState(RMC_DATE); -// numBytes = 0; //prep for next phase of parse -// } -// else //store data -// { -// setParserState(RMC_COURSE); -// course[numBytes] = byte; //adjust number of bytes to fit array -// numBytes++; -// } -// } -// -// //date -// else if(decodeState == RMC_DATE) -// { -// if (byte == ',') //end of this data type -// { -// // Cut it off at day of month. Also has month and year if we ever need it. -// dayofmonth[2] = 0x00; -// setParserState(RMC_MAG_VARIATION); -// skipBytes = 0; //prep for next phase of parse -// numBytes = 0; -// } -// else //store data -// { -// setParserState(RMC_DATE); -// dayofmonth[numBytes] = byte; //adjust number of bytes to fit array -// numBytes++; -// } -// } -// -// //magnetic variation -// else if(decodeState == RMC_MAG_VARIATION) -// { -// if (byte == '*') //end of this data type -// { -// //variation[numBytes] = 0x00; -// setParserState(GPS_CHECKSUM); -// numBytes = 0; //prep for next phase of parse -// } -// else //store data -// { -// setParserState(RMC_MAG_VARIATION); -// //variation[numBytes] = byte; //adjust number of bytes to fit array -// numBytes++; -// } -// } -// ///parses RMC transmissions END -// -// -// //checksum -// else if (decodeState == GPS_CHECKSUM) -// { -// if (numBytes == 2) //end of data - terminating character ?? -// { -// //checksum calculator for testing http://www.hhhh.org/wiml/proj/nmeaxor.html -// //TODO: must determine what to do with correct and incorrect messages -// receivedChecksum = checksum[0] + (checksum[1]*16); //convert bytes to int -// if(calculatedChecksum==receivedChecksum) -// { -// -// } -// else -// { -// -// } -// -// setParserState(INITIALIZE); -// numBytes = 0; //prep for next phase of parse -// } -// else //store data -// { -// setParserState(GPS_CHECKSUM); -// checksum[numBytes] = byte; //adjust number of bytes to fit array -// numBytes++; -// } -// } -// else { -// setParserState(INITIALIZE); -// } -// -// if (decodeState!=GPS_CHECKSUM && decodeState!=INITIALIZE) //want bytes between '$' and '*' -// { -// //input byte into running checksum -// XORbyteWithChecksum(byte); -// } -// } -// +void parse_gps_transmission(void) +{ + uint16_t nmeaBufferDataPosition = NMEABUFFER_SIZE - uart_get_rxdma_handle()->Instance->CNDTR; + + char byte; + + while(nmeaBufferDataPosition != nmeaBufferParsePosition) + { + // Pull byte off of the buffer + byte = nmeaBuffer[nmeaBufferParsePosition]; + + if(decodeState == INITIALIZE) //start of transmission sentence + { + if(byte == '$') + { + setParserState(GET_TYPE); + numBytes = 0; //prep for next phases + skipBytes = 0; + calculatedChecksum = 0; + } + + else + { + setParserState(INITIALIZE); + } + } + + //parse transmission type + else if (decodeState == GET_TYPE) + { + tramsmissionType[numBytes] = byte; + numBytes++; + + if(byte == ',') //end of this data type + { + tramsmissionType[5] = 0x00; + + if (tramsmissionType[2] == 'G' && + tramsmissionType[3] == 'G' && + tramsmissionType[4] == 'A') + { + setParserState(GGA_TIME); + numBytes = 0; + } + else if (tramsmissionType[2] == 'R' && + tramsmissionType[3] == 'M' && + tramsmissionType[4] == 'C') + { + setParserState(RMC_TIME); + numBytes = 0; + } + else //this is an invalid transmission type + { + setParserState(INITIALIZE); + } + } + else { + // continue + setParserState(GET_TYPE); + } + + } + + ///parses GGA transmissions START + /// $--GGA,hhmmss.ss,llll.ll,a,yyyyy.yy,a,x,xx,x.x,x.x,M,x.x,M,x.x,xxxx*xx + //timestamp + else if (decodeState == GGA_TIME) + { + if (byte == ',') //end of this data type + { + timestamp[4] = 0x00; // Cut off at 4 (no seconds) for APRS + setParserState(GGA_LATITUDE); + skipBytes = 0; //prep for next phase of parse + numBytes = 0; + } + else //store data + { + setParserState(GGA_TIME); + timestamp[numBytes] = byte; //byte; //adjust number of bytes to fit array + numBytes++; + } + } + + //latitude + else if (decodeState == GGA_LATITUDE) + { + if (byte == ',' && skipBytes == 0) //discard this byte + { + skipBytes = 1; + setParserState(GGA_LATITUDE); + } + else if (byte == ',') //end of this data type + { + + latitude[numBytes] = 0x00; // null terminate + + setParserState(GGA_LONGITUDE); + skipBytes = 0; //prep for next phase of parse + numBytes = 0; + } + else //store data + { + latitude[numBytes] = byte; //adjust number of bytes to fit array + numBytes++; + setParserState(GGA_LATITUDE); + } + } + + //longitude + else if (decodeState == GGA_LONGITUDE) + { + if (byte == ',' && skipBytes == 0) //discard this byte + { + skipBytes = 1; + setParserState(GGA_LONGITUDE); + } + else if (byte == ',') //end of this data type + { + longitude[numBytes] = 0x00; + setParserState(GGA_QUALITY); + numBytes = 0; //prep for next phase of parse + skipBytes = 0; + } + else //store data + { + longitude[numBytes] = byte; //adjust number of bytes to fit array + numBytes++; + setParserState(GGA_LONGITUDE); + } + } + + //GGA quality + else if (decodeState == GGA_QUALITY) + { + if (byte == ',') //end of this data type + { + setParserState(GGA_SATELLITES); + numBytes = 0; //prep for next phase of parse + } + else //store data + { + quality = byte; //maybe reset if invalid data ?? + setParserState(GGA_QUALITY); + } + } + + //number of satellites + else if (decodeState == GGA_SATELLITES) + { + if (byte == ',') //end of this data type + { + numSatellites[numBytes] = 0x00; + setParserState(GGA_HDOP); + numBytes = 0; //prep for next phase of parse + } + else //store data + { + numSatellites[numBytes] = byte; //adjust number of bytes to fit array + numBytes++; + setParserState(GGA_SATELLITES); + } + } + + //HDOP + else if (decodeState == GGA_HDOP) + { + if (byte == ',' ) //end of this data type + { + hdop[numBytes] = 0x00; + setParserState(GGA_ALTITUDE); + numBytes = 0; //prep for next phase of parse + skipBytes = 0; + } + else //store data + { + hdop[numBytes] = byte; //adjust number of bytes to fit array + numBytes++; + setParserState(GGA_HDOP); + } + } + + //altitude + else if (decodeState == GGA_ALTITUDE) + { + if (byte == ',' && skipBytes == 0) //discard this byte + { + altitude[numBytes] = 0x00; + skipBytes = 1; + setParserState(GGA_ALTITUDE); + } + else if(byte == ',') //end of this data type + { + // If we actually have an altitude + if(numBytes>0) + { + altitude[numBytes-1] = 0x00; // Cut off the "M" from the end of the altitude + } + else + { + altitude[numBytes] = 0x00; + } + setParserState(GGA_WGS84); + numBytes = 0; //prep for next phase of parse + } + else //store data + { + altitude[numBytes] = byte; //adjust number of bytes to fit array + numBytes++; + setParserState(GGA_ALTITUDE); + } + } + + //WGS84 Height + else if (decodeState == GGA_WGS84) + { + if (byte == ',' && skipBytes == 0) //discard this byte + { + skipBytes = 1; + setParserState(GGA_WGS84); + } + else if(byte == ',') //end of this data type + { + //wgs84Height[numBytes] = 0x00; + setParserState(GGA_LAST_UPDATE); + skipBytes = 0; //prep for next phase of parse + numBytes = 0; + } + else //store data + { + //wgs84Height[numBytes] = byte; //adjust number of bytes to fit array + numBytes++; + setParserState(GGA_WGS84); + } + } + + //last GGA DGPS update + else if (decodeState == GGA_LAST_UPDATE) + { + if (byte == ',') //end of this data type + { +// lastUpdated[numBytes] = 0x00; + setParserState(GGA_STATION_ID); + numBytes = 0; //prep for next phase of parse + } + else //store data - this should be blank + { +// lastUpdated[numBytes] = byte; //adjust number of bytes to fit array + numBytes++; + setParserState(GGA_LAST_UPDATE); + } + } + + //GGA DGPS station ID + else if (decodeState == GGA_STATION_ID) + { + if (byte == ',' || byte == '*') //end of this data type + { +// stationID[numBytes] = 0x00; + setParserState(GPS_CHECKSUM); + numBytes = 0; //prep for next phase of parse + } + else //store data - this should be blank + { +// stationID[numBytes] = byte; //adjust number of bytes to fit array + numBytes++; + setParserState(GGA_STATION_ID); + } + } + ///parses GGA transmissions END + + /// $GPRMC,hhmmss.ss,A,llll.ll,a,yyyyy.yy,a,x.x,x.x,ddmmyy,x.x,a*hh + ///parses RMC transmissions + //time + // emz: commented setter, GMC time better? + else if(decodeState == RMC_TIME) + { + if (byte == ',') //end of this data type + { + //timestamp[numBytes] = 0x00; + setParserState(RMC_VALIDITY); + numBytes = 0; //prep for next phase of parse + } + else //store data + { + //timestamp[numBytes] = byte; //adjust number of bytes to fit array + numBytes++; + setParserState(RMC_TIME); + } + } + + //validity + // not needed? dupe gga + else if(decodeState == RMC_VALIDITY) + { + if (byte == ',') //end of this data type + { + setParserState(RMC_LATITUDE); + skipBytes = 0; //prep for next phase of parse + numBytes = 0; + } + else //store data + { + //quality = byte; + numBytes++; + setParserState(RMC_VALIDITY); + } + } + + //latitude RMC (we don't need this, commented out setter) + else if(decodeState == RMC_LATITUDE) + { + if (byte == ',' && skipBytes == 0) //discard this byte + { + skipBytes = 1; + setParserState(RMC_LATITUDE); + } + else if (byte == ',') //end of this data type + { + setParserState(RMC_LONGITUDE); + skipBytes = 0; //prep for next phase of parse + numBytes = 0; + } + else //store data + { + //latitude[numBytes]= byte; //adjust number of bytes to fit array + numBytes++; + setParserState(RMC_LATITUDE); + } + } + + //longitude RMC (we don't need this, commented out setter) + else if(decodeState == RMC_LONGITUDE) + { + if (byte == ',' && skipBytes == 0) //discard this byte + { + skipBytes = 1; + setParserState(RMC_LONGITUDE); + } + else if (byte == ',') //end of this data type + { + setParserState(RMC_KNOTS); + skipBytes = 0; + numBytes = 0; + } + else //store data + { + //longitude[numBytes]= byte; //adjust number of bytes to fit array + numBytes++; + setParserState(RMC_LONGITUDE); + } + } + + //knots + else if(decodeState == RMC_KNOTS) + { + if (byte == ',') //end of this data type + { + knots[numBytes] = 0x00; + setParserState(RMC_COURSE); + numBytes = 0; //prep for next phase of parse + } + else //store data + { + setParserState(RMC_KNOTS); + knots[numBytes]= byte; //adjust number of bytes to fit array + numBytes++; + } + } + + //course + else if(decodeState == RMC_COURSE) + { + if (byte == ',') //end of this data type + { + course[numBytes] = 0x00; + setParserState(RMC_DATE); + numBytes = 0; //prep for next phase of parse + } + else //store data + { + setParserState(RMC_COURSE); + course[numBytes] = byte; //adjust number of bytes to fit array + numBytes++; + } + } + + //date + else if(decodeState == RMC_DATE) + { + if (byte == ',') //end of this data type + { + // Cut it off at day of month. Also has month and year if we ever need it. + dayofmonth[2] = 0x00; + setParserState(RMC_MAG_VARIATION); + skipBytes = 0; //prep for next phase of parse + numBytes = 0; + } + else //store data + { + setParserState(RMC_DATE); + dayofmonth[numBytes] = byte; //adjust number of bytes to fit array + numBytes++; + } + } + + //magnetic variation + else if(decodeState == RMC_MAG_VARIATION) + { + if (byte == '*') //end of this data type + { + //variation[numBytes] = 0x00; + setParserState(GPS_CHECKSUM); + numBytes = 0; //prep for next phase of parse + } + else //store data + { + setParserState(RMC_MAG_VARIATION); + //variation[numBytes] = byte; //adjust number of bytes to fit array + numBytes++; + } + } + ///parses RMC transmissions END + + + //checksum + else if (decodeState == GPS_CHECKSUM) + { + if (numBytes == 2) //end of data - terminating character ?? + { + //checksum calculator for testing http://www.hhhh.org/wiml/proj/nmeaxor.html + //TODO: must determine what to do with correct and incorrect messages + receivedChecksum = checksum[0] + (checksum[1]*16); //convert bytes to int + if(calculatedChecksum==receivedChecksum) + { + + } + else + { + + } + + setParserState(INITIALIZE); + numBytes = 0; //prep for next phase of parse + } + else //store data + { + setParserState(GPS_CHECKSUM); + checksum[numBytes] = byte; //adjust number of bytes to fit array + numBytes++; + } + } + else { + setParserState(INITIALIZE); + } + + if (decodeState!=GPS_CHECKSUM && decodeState!=INITIALIZE) //want bytes between '$' and '*' + { + //input byte into running checksum + XORbyteWithChecksum(byte); + } + } + }