Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
Dependents: A_TeseoLocationNEW A_TeseoLocation
Revision 0:a77f1f1f8318, committed 2018-11-09
- Comitter:
- apalmieri
- Date:
- Fri Nov 09 17:06:11 2018 +0000
- Child:
- 1:02afb9b6f2c6
- Commit message:
- Initial commit
Changed in this revision
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/Components/Teseo/Teseo.cpp Fri Nov 09 17:06:11 2018 +0000
@@ -0,0 +1,1010 @@
+/**
+*******************************************************************************
+* @file Teseo.h
+* @author AST / Central Lab
+* @version V1.0.0
+* @date May-2017
+* @brief Teseo Location Class
+*
+*******************************************************************************
+* @attention
+*
+* <h2><center>© COPYRIGHT(c) 2017 STMicroelectronics</center></h2>
+*
+* Licensed under MCD-ST Liberty SW License Agreement V2, (the "License");
+* You may not use this file except in compliance with the License.
+* You may obtain a copy of the License at:
+*
+* http://www.st.com/software_license_agreement_liberty_v2
+*
+* Redistribution and use in source and binary forms, with or without modification,
+* are permitted provided that the following conditions are met:
+* 1. Redistributions of source code must retain the above copyright notice,
+* this list of conditions and the following disclaimer.
+* 2. Redistributions in binary form must reproduce the above copyright notice,
+* this list of conditions and the following disclaimer in the documentation
+* and/or other materials provided with the distribution.
+* 3. Neither the name of STMicroelectronics nor the names of its contributors
+* may be used to endorse or promote products derived from this software
+* without specific prior written permission.
+*
+* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
+* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*
+********************************************************************************
+*/
+
+#include "Teseo.h"
+
+static char TESEO_NAME[] = "Teseo-LIV3F";
+/*
+static char _OK[] = "OK";
+static char _Failed[] = "Failed";
+*/
+
+struct teseoCmd {
+ char *cmd;
+};
+
+static struct teseoCmd teseoCmds[] = {
+ [Teseo::TEST] = {
+ .cmd = (char*)"$\n\r",
+ },
+ [Teseo::GETSWVER] = {
+ .cmd = (char*)"$PSTMGETSWVER,6\n\r",
+ },
+ [Teseo::FORCESTANDBY] = {
+ .cmd = (char*)"$PSTMFORCESTANDBY,00010\n\r",
+ },
+ [Teseo::RFTESTON] = {
+ .cmd = (char*)"$PSTMRFTESTON,16\n\r",
+ },
+ [Teseo::RFTESTOFF] = {
+ .cmd = (char*)"$PSTMRFTESTOFF\n\r",
+ },
+ [Teseo::LOWPOWER] = {
+ .cmd = (char*)"$PSTMLOWPOWERONOFF,1,0,000,05,0,1,000,1,00010,01,0,0,1,01\n\r",
+ },
+ [Teseo::FWUPDATE] = {
+ .cmd = (char*)"$PSTMFWUPGRADE\n\r",
+ }
+};
+
+Teseo::Teseo(PinName resetPin,
+ PinName wakeupPin,
+ PinName ppsPin,
+ PinName uartTxPin,
+ PinName uartRxPin,
+ Serial *serialDebug):
+ _loc_led2(LOC_LED2),
+ _reset(resetPin, 1),
+ _pps(ppsPin),
+ _wakeup(wakeupPin, 0),
+ _uartRx(uartRxPin),
+ _uartTx(uartTxPin),
+ _serialDebug(serialDebug)
+{
+ wait_ms(POWERON_STABLE_SIGNAL_DELAY_MS);
+ _uart = NULL;
+ _i2c = NULL;
+
+ _locState = TESEO_LOC_STATE_IDLE;
+
+ deviceInfo = TESEO_NAME;
+}
+
+Teseo::Teseo(PinName resetPin,
+ PinName wakeupPin,
+ PinName ppsPin,
+ PinName uartTxPin,
+ PinName uartRxPin,
+ I2C *i2cBus,
+ Serial *serialDebug):
+ _loc_led2(LOC_LED2),
+ _reset(resetPin, 1),
+ _pps(ppsPin),
+ _wakeup(wakeupPin, 0),
+ _uartRx(uartRxPin),
+ _uartTx(uartTxPin),
+ _serialDebug(serialDebug),
+ _i2c(i2cBus)
+{
+ wait_ms(POWERON_STABLE_SIGNAL_DELAY_MS);
+ _uart = NULL;
+
+ _locState = TESEO_LOC_STATE_IDLE;
+
+ deviceInfo = TESEO_NAME;
+}
+
+void
+Teseo::TeseoLocRegOutput(teseo_app_output_callback app_output_cb, teseo_app_event_callback app_event_cb)
+{
+ appOutCb = app_output_cb;
+ appEventCb = app_event_cb;
+}
+
+int
+Teseo::EnableLowPower()
+{
+ SendCommand(LOWPOWER);
+ return 0;
+}
+
+void
+Teseo::_ResetFast(Serial *serialDebug)
+{
+ if (serialDebug)
+ serialDebug->printf("%s: Resetting...", TESEO_NAME);
+
+ _reset.write(0);
+
+ wait_ms(5);
+
+ _reset.write(1);
+
+ wait_ms(70);
+
+ if (serialDebug)
+ serialDebug->printf("Done...\n\r");
+}
+
+void
+Teseo::_Reset(Serial *serialDebug)
+{
+ if (serialDebug)
+ serialDebug->printf("%s: Resetting...", TESEO_NAME);
+
+ //_pps.output();
+ //_pps.write(0);
+
+ //wait_ms(500);
+
+ _reset.write(1);
+
+ wait_ms(500);
+
+ _reset.write(0);
+ //_pps.write(0);
+
+ wait_ms(500);
+
+ _reset.write(1);
+
+ if (serialDebug)
+ serialDebug->printf("Done...\n\r");
+
+ //_pps.write(1);
+
+ //wait_ms(1000);
+
+ //_pps.input();
+}
+
+void
+Teseo::_SendString(char *buf, int len)
+{
+ for (int i = 0; i < len; ++i) {
+ while (!_uart->writeable());
+ _uart->putc(buf[i]);
+ }
+}
+
+int
+Teseo::_WakeUp()
+{
+ wait_ms(100);
+
+ _wakeup.write(1);
+
+ wait_ms(500);
+
+ _wakeup.write(0);
+
+ return 0;
+}
+
+int
+Teseo::_CRC(char *buf, int size)
+{
+ int i = 0, ch = 0;
+
+ if (buf[0] == '$') {
+ ++i;
+ }
+
+ if (size) {
+ for (; i < size; ++i) {
+ ch ^= buf[i];
+ }
+ } else {
+ for (; buf[i] != 0; ++i) {
+ ch ^= buf[i];
+ }
+ }
+
+ return ch;
+}
+
+void
+Teseo::SendCommand(Teseo::eCmd c)
+{
+ char crc[3];
+
+ sprintf(crc, "*%02X", _CRC(teseoCmds[c].cmd, -1));
+
+ _SendString(teseoCmds[c].cmd, strlen(teseoCmds[c].cmd));
+ _SendString(crc, 3);
+}
+
+void
+Teseo::SendCommand(char *cmd)
+{
+ char crc[5];
+
+ sprintf(crc, "*%02X\n\r", _CRC(cmd, strlen(cmd)));
+ //printf("CRC=%s\n\r", crc);
+
+ _SendString(cmd, strlen(cmd));
+ _SendString(crc, 5);
+}
+
+/** TBC */
+int
+Teseo::_CheckI2C()
+{
+ if (!_i2c)
+ return -1;
+
+ _i2c->start();
+ int res = _i2c->write((TESEO_I2C_ADDRESS << 1) | 1);
+ _i2c->stop();
+ /*
+ * @returns
+ * '0' - NAK was received
+ * '1' - ACK was received,
+ * '2' - timeout
+ */
+ return res == 1 ? 0 : -1;
+}
+
+void
+Teseo::ReadSentence(Teseo::eMsg msg)
+{
+ eStatus status = TESEO_STATUS_FAILURE;
+
+ do {
+ osEvent evt = queue.get();
+ if (evt.status == osEventMessage) {
+ struct _teseoMsg *message = (struct _teseoMsg *)evt.value.p;
+ if (message->len > 0) {
+ status = _GetMsg(msg, message->buf);
+ }
+
+ mpool.free(message);
+ }
+ } while (status != TESEO_STATUS_SUCCESS);
+}
+
+void
+Teseo::_InitUART(int br)
+{
+ _uart = new (std::nothrow) Serial(_uartRx, _uartTx);
+ if(_uart != NULL) {
+ _uart->format(8, SerialBase::None, 1);
+ _uart->baud(br);
+ } else {
+ TESEO_LOG_INFO("Error allocating UART.\r\n");
+ }
+}
+
+bool
+Teseo::setPowerMode(GPSProvider::PowerMode_t pwrMode)
+{
+ /* TBI */
+ return false;
+}
+
+void
+Teseo::eventHandler(eTeseoLocEventType event, uint32_t data)
+{
+ if (appEventCb) {
+ appEventCb(event, data);
+ }
+}
+
+void
+Teseo::ReadProcess(void)
+{
+ char c;
+
+ struct _teseoMsg *msg = mpool.alloc();
+ msg->len = 0;
+
+ while(true) {
+ if (_uart->readable()) {
+ c = _uart->getc();
+
+ if (c == '$') {
+ queue.put(msg);
+ msg = mpool.alloc();
+ msg->len = 0;
+ }
+ msg->buf[msg->len++] = c;
+
+ } else {
+ Thread::yield(); //wait_us(100); Allow other threads to run
+ }
+ }
+}
+
+static void
+_UARTStreamProcess(Teseo *gnss)
+{
+ gnss->ReadProcess();
+}
+
+void
+Teseo::start(void)
+{
+ if(_locState == TESEO_LOC_STATE_IDLE) {
+
+ _InitUART();
+ _locState = TESEO_LOC_STATE_RUN;
+
+ // Start thread for UART listener and set the highest priority
+ serialStreamThread = new (std::nothrow) Thread();
+ if(serialStreamThread != NULL) {
+ serialStreamThread->set_priority(osPriorityRealtime);
+ serialStreamThread->start(callback(_UARTStreamProcess, this));
+ } else {
+ TESEO_LOG_INFO("Error allocating serialStreamThread\r\n");
+ }
+
+ eventHandler(TESEO_LOC_EVENT_START_RESULT, 0);
+ } else {
+ TESEO_LOG_INFO("Already started\r\n");
+ }
+}
+
+void
+Teseo::stop(void)
+{
+ if(_locState == TESEO_LOC_STATE_IDLE) {
+ return;
+ }
+ // Stop thread for UART listener
+ if(serialStreamThread != NULL) {
+ serialStreamThread->terminate();
+ delete serialStreamThread;
+ }
+
+ if(_uart != NULL) {
+ delete _uart;
+ _uart = NULL;
+ }
+
+ _locState = TESEO_LOC_STATE_IDLE;
+ eventHandler(TESEO_LOC_EVENT_STOP_RESULT, 0);
+}
+
+void
+Teseo::outputHandler(uint32_t msgId, uint32_t msgType, tTeseoData *pData)
+{
+ switch(msgId) {
+ case LOC_OUTPUT_LOCATION:
+
+ if(pData->gpgga_data.valid == VALID) {
+ lastLocation.valid = true;
+ lastLocation.lat = pData->gpgga_data.xyz.lat;
+ lastLocation.lon = pData->gpgga_data.xyz.lon;
+ lastLocation.altitude = pData->gpgga_data.xyz.alt;
+ lastLocation.numGPSSVs = pData->gpgga_data.sats;
+ lastLocation.utcTime = pData->gpgga_data.utc.utc;
+ } else {
+ lastLocation.valid = false;
+ }
+
+ if (locationCallback) {
+ locationCallback(&lastLocation);
+ }
+
+ break;
+
+ case LOC_OUTPUT_PSTM: {
+ Teseo::ePSTMsg msg = (Teseo::ePSTMsg)msgType;
+ int code;
+
+ switch(msg) {
+ case PSTMGEOFENCE: {
+
+ /* Geofence enabling */
+ if(pData->geofence_data.op == GNSS_FEATURE_EN_MSG) {
+ code = pData->geofence_data.result ?
+ GPS_ERROR_FEATURE_ENABLING : GPS_ERROR_NONE;
+
+ if (code == GPS_ERROR_NONE) {
+ saveConfigParams();
+ }
+ }
+
+ /* Geofence configuration */
+ if(pData->geofence_data.op == GNSS_GEOFENCE_CFG_MSG) {
+ code = pData->geofence_data.result ?
+ GPS_ERROR_GEOFENCE_CFG : GPS_ERROR_NONE;
+ if (geofenceCfgMessageCallback) {
+ geofenceCfgMessageCallback(code);
+ }
+ }
+
+ /* Geofence Status */
+ if(pData->geofence_data.op == GNSS_GEOFENCE_STATUS_MSG) {
+ code = pData->geofence_data.result ? GPS_ERROR_GEOFENCE_STATUS : GPS_ERROR_NONE;
+ if(code == GPS_ERROR_NONE) {
+ geofenceStatus.timestamp.hh = pData->geofence_data.timestamp.hh;
+ geofenceStatus.timestamp.mm = pData->geofence_data.timestamp.mm;
+ geofenceStatus.timestamp.ss = pData->geofence_data.timestamp.ss;
+ geofenceStatus.timestamp.day = pData->geofence_data.timestamp.day;
+ geofenceStatus.timestamp.month = pData->geofence_data.timestamp.month;
+ geofenceStatus.timestamp.year = pData->geofence_data.timestamp.year;
+ geofenceStatus.currentStatus = pData->geofence_data.status;
+ geofenceStatus.numGeofences = MAX_GEOFENCES_NUM;
+ }
+ if (geofenceStatusMessageCallback) {
+ geofenceStatusMessageCallback(&geofenceStatus, code);
+ }
+ }
+
+ /* Geofence Alarm */
+ if(pData->geofence_data.op == GNSS_GEOFENCE_ALARM_MSG) {
+ code = pData->geofence_data.result ? GPS_ERROR_GEOFENCE_STATUS : GPS_ERROR_NONE;
+ if(code == GPS_ERROR_NONE) {
+ geofenceStatus.timestamp.hh = pData->geofence_data.timestamp.hh;
+ geofenceStatus.timestamp.mm = pData->geofence_data.timestamp.mm;
+ geofenceStatus.timestamp.ss = pData->geofence_data.timestamp.ss;
+ geofenceStatus.currentStatus = pData->geofence_data.status;
+ geofenceStatus.idAlarm = pData->geofence_data.idAlarm;
+ }
+ if (geofenceStatusMessageCallback) {
+ geofenceStatusMessageCallback(&geofenceStatus, code);
+ }
+ }
+ }
+ break;
+
+ case PSTMODO: {
+ /* Odometer enabling */
+ if(pData->odo_data.op == GNSS_FEATURE_EN_MSG) {
+
+ code = pData->odo_data.result ?
+ GPS_ERROR_FEATURE_ENABLING : GPS_ERROR_NONE;
+
+ if (code == GPS_ERROR_NONE) {
+ saveConfigParams();
+ }
+ }
+
+ /* Odometer start */
+ if(pData->odo_data.op == GNSS_ODO_START_MSG) {
+ code = pData->odo_data.result ?
+ GPS_ERROR_ODO_START : GPS_ERROR_NONE;
+ }
+ /* Odometer stop */
+ if(pData->odo_data.op == GNSS_ODO_STOP_MSG) {
+ code = pData->odo_data.result ?
+ GPS_ERROR_ODO_STOP : GPS_ERROR_NONE;
+ }
+ }
+ break;
+
+ case PSTMDATALOG: {
+ /* Datalog enabling */
+ if(pData->datalog_data.op == GNSS_FEATURE_EN_MSG) {
+
+ code = pData->datalog_data.result ?
+ GPS_ERROR_FEATURE_ENABLING : GPS_ERROR_NONE;
+
+ if (code == GPS_ERROR_NONE) {
+ saveConfigParams();
+ }
+ }
+ /* Datalog create */
+ if(pData->datalog_data.op == GNSS_DATALOG_CFG_MSG) {
+ code = pData->datalog_data.result ?
+ GPS_ERROR_DATALOG_CFG : GPS_ERROR_NONE;
+ }
+ /* Datalog start */
+ if(pData->datalog_data.op == GNSS_DATALOG_START_MSG) {
+ code = pData->datalog_data.result ?
+ GPS_ERROR_DATALOG_START : GPS_ERROR_NONE;
+ }
+ /* Datalog stop */
+ if(pData->datalog_data.op == GNSS_DATALOG_STOP_MSG) {
+ code = pData->datalog_data.result ?
+ GPS_ERROR_DATALOG_STOP : GPS_ERROR_NONE;
+ }
+ /* Datalog erase */
+ if(pData->datalog_data.op == GNSS_DATALOG_ERASE_MSG) {
+ code = pData->datalog_data.result ?
+ GPS_ERROR_DATALOG_ERASE : GPS_ERROR_NONE;
+ }
+ }
+ break;
+
+ case PSTMSGL: {
+ /* Msg List cfg */
+ code = pData->ack ?
+ GPS_ERROR_MSGLIST_CFG : GPS_ERROR_NONE;
+
+ if (code == GPS_ERROR_NONE) {
+ saveConfigParams();
+ }
+ }
+ break;
+
+ case PSTMSAVEPAR: {
+ code = pData->ack ?
+ GPS_ERROR_SAVEPAR : GPS_ERROR_NONE;
+
+ if (code == GPS_ERROR_NONE) {
+ reset();
+ }
+ }
+ break;
+
+ } /* end switch */
+ } /* end case LOC_OUTPUT_PSTM */
+
+ break;
+
+ default:
+ break;
+ }
+
+ if (appOutCb) {
+ appOutCb(msgId, msgType, pData);
+ }
+
+}
+
+
+eStatus
+Teseo::_GetMsg(Teseo::eMsg msg, uint8_t *buffer)
+{
+ eStatus status = TESEO_STATUS_FAILURE;
+
+ switch(msg) {
+
+ case GPGGA:
+ status = (eStatus)parse_gpgga(&pData.gpgga_data, buffer);
+ if(status == TESEO_STATUS_SUCCESS) {
+ outputHandler(LOC_OUTPUT_LOCATION, msg, &pData);
+ }
+ break;
+
+ case GNS:
+ status = (eStatus)parse_gnsmsg(&pData.gns_data, buffer);
+ if(status == TESEO_STATUS_SUCCESS) {
+ outputHandler(LOC_OUTPUT_NMEA, msg, &pData);
+ }
+ break;
+
+ case GPGST:
+ status = (eStatus)parse_gpgst(&pData.gpgst_data, buffer);
+ if(status == TESEO_STATUS_SUCCESS) {
+ outputHandler(LOC_OUTPUT_NMEA, msg, &pData);
+ }
+ break;
+
+ case GPRMC:
+ status = (eStatus)parse_gprmc(&pData.gprmc_data, buffer);
+ if(status == TESEO_STATUS_SUCCESS) {
+ outputHandler(LOC_OUTPUT_NMEA, msg, &pData);
+ }
+ break;
+
+ case GSA:
+ status = (eStatus)parse_gsamsg(&pData.gsa_data, buffer);
+ if(status == TESEO_STATUS_SUCCESS) {
+ outputHandler(LOC_OUTPUT_NMEA, msg, &pData);
+ }
+ break;
+
+ case GSV:
+ status = (eStatus)parse_gsvmsg(&pData.gsv_data, buffer);
+ if(status == TESEO_STATUS_SUCCESS) {
+ outputHandler(LOC_OUTPUT_NMEA, msg, &pData);
+ }
+ break;
+
+ default:
+ break;
+
+ }
+
+ return status;
+}
+
+void
+Teseo::setVerboseMode(int level)
+{
+ cfgMessageList(level);
+}
+
+void
+Teseo::_GetLocationMsg(Teseo::eMsg msg, uint8_t *buffer)
+{
+ eStatus status;
+
+#if 0
+ _serialDebug->printf("\n\r --------------------->\n\r");
+ for (int i = 0; i < TESEO_RXBUF_LEN ; ++i) {
+ _serialDebug->putc((int)buffer[i]);
+ }
+ _serialDebug->printf("\n\r<---------------------\n\r");
+#endif
+
+ status = (eStatus)parse_gpgga(&pData.gpgga_data, buffer);
+ if(status == TESEO_STATUS_SUCCESS) {
+ outputHandler(LOC_OUTPUT_LOCATION, msg, &pData);
+ }
+}
+
+void
+Teseo::_GetPSTMsg(Teseo::ePSTMsg msg, uint8_t *buffer)
+{
+ eStatus status;
+
+#if 0
+ _serialDebug->printf("\n\r --------------------->\n\r");
+ for (int i = 0; i < TESEO_RXBUF_LEN ; ++i) {
+ _serialDebug->putc((int)buffer[i]);
+ }
+ _serialDebug->printf("\n\r<---------------------\n\r");
+#endif
+
+ switch(msg) {
+
+ case PSTMGEOFENCE:
+ status = (eStatus)parse_pstmgeofence(&pData.geofence_data, buffer);
+ if(status == TESEO_STATUS_SUCCESS) {
+ outputHandler(LOC_OUTPUT_PSTM, msg, &pData);
+ }
+ break;
+ case PSTMODO:
+ status = (eStatus)parse_pstmodo(&pData.odo_data, buffer);
+ if(status == TESEO_STATUS_SUCCESS) {
+ outputHandler(LOC_OUTPUT_PSTM, msg, &pData);
+ }
+ break;
+ case PSTMDATALOG:
+ status = (eStatus)parse_pstmdatalog(&pData.datalog_data, buffer);
+ if(status == TESEO_STATUS_SUCCESS) {
+ outputHandler(LOC_OUTPUT_PSTM, msg, &pData);
+ }
+ break;
+ case PSTMSGL:
+ status = (eStatus)parse_pstmsgl(&pData.ack, buffer);
+ if(status == TESEO_STATUS_SUCCESS) {
+ outputHandler(LOC_OUTPUT_PSTM, msg, &pData);
+ }
+ break;
+ case PSTMSAVEPAR:
+ status = (eStatus)parse_pstmsavepar(&pData.ack, buffer);
+ if(status == TESEO_STATUS_SUCCESS) {
+ outputHandler(LOC_OUTPUT_PSTM, msg, &pData);
+ }
+ break;
+
+ default:
+ break;
+ }
+ /* Recover the normal state */
+
+}
+
+void
+Teseo::process(void)
+{
+ osEvent evt = queue.get();
+ if (evt.status == osEventMessage) {
+ struct _teseoMsg *message = (struct _teseoMsg *)evt.value.p;
+ if (message->len > 0) {
+
+ for(int m = 0; m < PSTM_NMEA_MSGS_NUM; m++) {
+ _GetPSTMsg((ePSTMsg)m, message->buf);
+ }
+ for(int m = 0; m < NMEA_MSGS_NUM; m++) {
+ _GetMsg((eMsg)m, message->buf);
+ }
+ }
+
+ mpool.free(message);
+ }
+}
+
+uint32_t
+Teseo::ioctl(uint32_t command, void *arg)
+{
+ /* TBI */
+ return 0;
+}
+
+void
+Teseo::lpmGetImmediateLocation(void)
+{
+ /* TBI */
+}
+
+const GPSProvider::LocationUpdateParams_t *
+Teseo::getLastLocation(void) const
+{
+ return &lastLocation;
+}
+
+void
+Teseo::reset(void)
+{
+ _ResetFast(_serialDebug);
+}
+
+gps_provider_error_t
+Teseo::cfgMessageList(int level)
+{
+ int lowMask = 0x2;
+ int highMask = 0x80000;
+
+ if(level == 2) {
+ lowMask = 0x18004F;
+ }
+
+ sprintf(_teseoCmd, "$PSTMCFGMSGL,%d,%d,%x,%x",
+ 0, /*NMEA 0*/
+ 1, /*Rate*/
+ lowMask,
+ highMask);
+
+ SendCommand(_teseoCmd);
+
+ return GPS_ERROR_NONE;
+}
+
+gps_provider_error_t
+Teseo::saveConfigParams(void)
+{
+ sprintf(_teseoCmd, "$PSTMSAVEPAR");
+ SendCommand(_teseoCmd);
+
+ return GPS_ERROR_NONE;
+}
+
+bool
+Teseo::isGeofencingSupported(void)
+{
+ return true;
+}
+
+gps_provider_error_t
+Teseo::enableGeofence(void)
+{
+ //$PSTMCFGGEOFENCE,<en>,<tol>*<checksum><cr><lf>
+ sprintf(_teseoCmd, "$PSTMCFGGEOFENCE,%d,%d",1,1);
+ SendCommand(_teseoCmd);
+
+ return GPS_ERROR_NONE;
+}
+
+//FIXME!
+gps_provider_error_t
+Teseo::cfgGeofenceCircle(void)
+{
+ GPSGeofence::GeofenceCircle_t circle = {
+ .id = 0,
+ .enabled = 1,
+ .tolerance = 1,
+ .lat = 40.336055,
+ .lon = 18.120611,
+ .radius = 200
+ };
+
+ sprintf(_teseoCmd, "$PSTMCFGGEOCIR,%d,%d,%lf,%lf,%lf",
+ circle.id,
+ circle.enabled,
+ circle.lat,
+ circle.lon,
+ circle.radius);
+ SendCommand(_teseoCmd);
+
+ sprintf(_teseoCmd, "$PSTMSAVEPAR");
+ SendCommand(_teseoCmd);
+
+ return GPS_ERROR_NONE;
+}
+
+
+gps_provider_error_t
+Teseo::configGeofences(GPSGeofence *geofences[], unsigned geofenceCount)
+{
+ uint8_t trials;
+
+ if(geofenceCount > MAX_GEOFENCES_NUM) {
+ return GPS_ERROR_GEOFENCE_MAX_EXCEEDED;
+ }
+
+ for(uint8_t i = 0; i < geofenceCount; i++) {
+ trials = 1;
+ //printf("Teseo::configGeofences id=%d\r\n", (geofences[i]->getGeofenceCircle()).id);
+ /*
+ printf("Teseo::configGeofences en=%d\r\n", en);
+ printf("Teseo::configGeofences tol=%d\r\n", (geofences[i]->getGeofenceCircle()).tolerance);
+ printf("Teseo::configGeofences lat=%02f\r\n", (geofences[i]->getGeofenceCircle()).lat);
+ printf("Teseo::configGeofences lon=%02f\r\n", (geofences[i]->getGeofenceCircle()).lon);
+ printf("Teseo::configGeofences radius=%02f\r\n", (geofences[i]->getGeofenceCircle()).radius);
+ */
+ sprintf(_teseoCmd, "$PSTMGEOFENCECFG,%d,%d,%d,%lf,%lf,%lf",
+ (geofences[i]->getGeofenceCircle()).id,
+ (geofences[i]->getGeofenceCircle()).enabled,
+ (geofences[i]->getGeofenceCircle()).tolerance,
+ (geofences[i]->getGeofenceCircle()).lat,
+ (geofences[i]->getGeofenceCircle()).lon,
+ (geofences[i]->getGeofenceCircle()).radius);
+
+ do{
+ trials--;
+
+ SendCommand(_teseoCmd);
+ /*
+ sprintf(_teseoCmd, "$PSTMCFGGEOFENCE,%d,%d\n\r",1,1);
+
+ //sprintf(_teseoCmd, "$PSTMGETSWVER,6");
+ SendCommand(_teseoCmd);
+
+ sprintf(_teseoCmd, "$PSTMSAVEPAR\n\r");
+ SendCommand(_teseoCmd);
+ */
+ //printf("Teseo::configGeofences _teseoCmd=%s\r\n", _teseoCmd);
+ } while (trials > 0);
+ }
+ //printf("Teseo::configGeofences sizeof(geofences)=%d numGeofences=%d strlen(_teseoCmd)=%d\r\n", sizeof(geofences), numGeofences, strlen(_teseoCmd));
+
+ return GPS_ERROR_NONE;
+}
+
+gps_provider_error_t
+Teseo::geofenceReq(void)
+{
+ sprintf(_teseoCmd, "$PSTMGEOFENCEREQ");
+ SendCommand(_teseoCmd);
+
+ return GPS_ERROR_NONE;
+}
+
+bool
+Teseo::isDataloggingSupported(void)
+{
+ return true;
+}
+
+gps_provider_error_t
+Teseo::enableDatalog(void)
+{
+ //$PSTMCFGLOG,<en>,<circ>,<rectype>,<oneshot>,<rate>,<speed>,<dist>*<checksum><cr><lf>
+ sprintf(_teseoCmd, "$PSTMCFGLOG,%d,%d,%d,%d,%u,%u,%u",
+ 1, //Enable/Disable the log
+ 1, //Enable/Disable circular mode
+ 1, //Record type
+ 0, //Enable/Disable one shot mode
+ 5, //time interval in seconds between two consecutive logged records
+ 0, //minimum speed threshold
+ 0 //distance threshold
+ );
+ SendCommand(_teseoCmd);
+
+ return GPS_ERROR_NONE;
+}
+
+gps_provider_error_t
+Teseo::configDatalog(GPSDatalog *datalog)
+{
+ //printf("Teseo::configDatalog 0x%03x\r\n", (datalog->getEnableBufferFullAlarm())<<1|(datalog->getEnableCircularBuffer()));
+ //$PSTMLOGCREATE,<cfg>,<min-rate>,<min-speed>,<min-position>,<logmask>*<checksum><cr><lf>
+ sprintf(_teseoCmd, "$PSTMLOGCREATE,%03x,%u,%u,%u,%d",
+ (datalog->getEnableBufferFullAlarm())<<1|(datalog->getEnableCircularBuffer()),
+ datalog->getMinRate(),
+ datalog->getMinSpeed(),
+ datalog->getMinPosition(),
+ datalog->getLogMask()
+ );
+ SendCommand(_teseoCmd);
+
+ return GPS_ERROR_NONE;
+}
+
+gps_provider_error_t
+Teseo::startDatalog(void)
+{
+ sprintf(_teseoCmd, "$PSTMLOGSTART");
+ SendCommand(_teseoCmd);
+
+ return GPS_ERROR_NONE;
+}
+
+gps_provider_error_t
+Teseo::stopDatalog(void)
+{
+ sprintf(_teseoCmd, "$PSTMLOGSTOP");
+ SendCommand(_teseoCmd);
+
+ return GPS_ERROR_NONE;
+}
+
+gps_provider_error_t
+Teseo::eraseDatalog(void)
+{
+ sprintf(_teseoCmd, "$PSTMLOGERASE");
+ SendCommand(_teseoCmd);
+
+ return GPS_ERROR_NONE;
+}
+
+gps_provider_error_t
+Teseo::logReqStatus(void)
+{
+ /* TBI */
+ return GPS_ERROR_NONE;
+}
+
+gps_provider_error_t
+Teseo::logReqQuery(GPSProvider::LogQueryParams_t &logReqQuery)
+{
+ /* TBI */
+ return GPS_ERROR_NONE;
+}
+
+bool
+Teseo::isOdometerSupported(void)
+{
+ return true;
+}
+
+gps_provider_error_t
+Teseo::enableOdo(void)
+{
+ //$PSTMCFGODO,<en>,<enmsg>,<alarm>*<checksum><cr><lf>
+ sprintf(_teseoCmd, "$PSTMCFGODO,1,1,1");
+ SendCommand(_teseoCmd);
+
+ return GPS_ERROR_NONE;
+}
+
+gps_provider_error_t
+Teseo::startOdo(unsigned alarmDistance)
+{
+ sprintf(_teseoCmd, "$PSTMODOSTART,%08x", alarmDistance);
+ SendCommand(_teseoCmd);
+
+ return GPS_ERROR_NONE;
+}
+
+gps_provider_error_t
+Teseo::stopOdo(void)
+{
+ sprintf(_teseoCmd, "$PSTMODOSTOP");
+ SendCommand(_teseoCmd);
+
+ return GPS_ERROR_NONE;
+}
+gps_provider_error_t
+Teseo::resetOdo(void)
+{
+ /* TBI */
+ return GPS_ERROR_NONE;
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/Components/Teseo/Teseo.h Fri Nov 09 17:06:11 2018 +0000
@@ -0,0 +1,369 @@
+/**
+*******************************************************************************
+* @file Teseo.h
+* @author AST / Central Lab
+* @version V1.0.0
+* @date May-2017
+* @brief Teseo Location Class
+*
+*******************************************************************************
+* @attention
+*
+* <h2><center>© COPYRIGHT(c) 2017 STMicroelectronics</center></h2>
+*
+* Licensed under MCD-ST Liberty SW License Agreement V2, (the "License");
+* You may not use this file except in compliance with the License.
+* You may obtain a copy of the License at:
+*
+* http://www.st.com/software_license_agreement_liberty_v2
+*
+* Redistribution and use in source and binary forms, with or without modification,
+* are permitted provided that the following conditions are met:
+* 1. Redistributions of source code must retain the above copyright notice,
+* this list of conditions and the following disclaimer.
+* 2. Redistributions in binary form must reproduce the above copyright notice,
+* this list of conditions and the following disclaimer in the documentation
+* and/or other materials provided with the distribution.
+* 3. Neither the name of STMicroelectronics nor the names of its contributors
+* may be used to endorse or promote products derived from this software
+* without specific prior written permission.
+*
+* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
+* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*
+********************************************************************************
+*/
+
+#ifndef __TESEO_H__
+#define __TESEO_H__
+
+#include "mbed.h"
+#include "GPSProviderImplBase.h"
+
+#include "TeseoConfig.h"
+#include "NMEAParser.h"
+
+#define STD_UART_BAUD 9600// 9600
+#define FWU_UART_BAUD 115200
+#define TESEO_I2C_ADDRESS 0x3A
+#define POWERON_STABLE_SIGNAL_DELAY_MS 150
+
+/** Indicates the outputted location information */
+#define LOC_OUTPUT_LOCATION (1)
+#define LOC_OUTPUT_NMEA (2)
+#define LOC_OUTPUT_PSTM (3)
+
+#if 1
+#define TESEO_LOG_INFO(...)
+#else
+#define TESEO_LOG_INFO(...) { \
+ if (_serialDebug != NULL) { \
+ (_serialDebug->printf(__VA_ARGS__)); \
+ } \
+ }
+#endif
+
+/**
+ * @brief Constant that indicates the maximum number of nmea messages to be processed.
+ */
+#define NMEA_MSGS_NUM 6 //Note: update this constant coherently to eMsg enum type
+
+/**
+ * @brief Constant that indicates the maximum number of proprietary nmea messages to be processed.
+ */
+#define PSTM_NMEA_MSGS_NUM 5 //Note: update this constant coherently to ePSTMsg enum type
+
+/**
+ * @brief Constant that indicates the maximum number of positions that can be stored.
+ */
+#define MAX_STOR_POS 64
+
+/**
+ * @brief Constant that indicates the lenght of the buffer that stores the GPS data read by the GPS expansion.
+ */
+
+#define TESEO_RXBUF_LEN 256//90
+#define TESEO_RXQUEUE_LEN 8
+
+/**
+ * @brief Enumeration structure that containes the two success states of a process
+ */
+typedef enum {
+ TESEO_STATUS_SUCCESS = 0, /**< Success status */
+ TESEO_STATUS_FAILURE = 1 /**< Failure status */
+} eStatus;
+
+/** Location event definitions */
+typedef enum {
+ /** Start result event */
+ TESEO_LOC_EVENT_START_RESULT,
+ /** Stop result event */
+ TESEO_LOC_EVENT_STOP_RESULT,
+} eTeseoLocEventType;
+
+/** Teseo Location state */
+typedef enum {
+ TESEO_LOC_STATE_IDLE,
+ TESEO_LOC_STATE_RUN,
+ TESEO_LOC_STATE_FEATURE,
+ TESEO_LOC_STATE_DEBUG
+} eTeseoLocState;
+
+/**
+ * @brief Enumeration structure that containes the two states of a debug process
+ */
+typedef enum {
+ DEBUG_OFF = 0, /**< In this case, nothing will be printed on the console (nmea strings, positions and so on) */
+ DEBUG_ON = 1 /**< In this case, nmea strings and just acquired positions will be printed on the console */
+} eDebugState;
+
+/**
+ * @brief Data structure that contains the driver informations
+ */
+typedef struct TeseoData {
+ eDebugState debug; /**< Debug status */
+ GPGGA_Infos gpgga_data; /**< $GPGGA Data holder */
+ GNS_Infos gns_data; /**< $--GNS Data holder */
+ GPGST_Infos gpgst_data; /**< $GPGST Data holder */
+ GPRMC_Infos gprmc_data; /**< $GPRMC Data holder */
+ GSA_Infos gsa_data; /**< $--GSA Data holder */
+ GSV_Infos gsv_data; /**< $--GSV Data holder */
+
+ Geofence_Infos geofence_data; /**< Geofence Data holder */
+ Odometer_Infos odo_data; /**< Odometer Data holder */
+ Datalog_Infos datalog_data; /**< Datalog Data holder */
+
+ Ack_Info ack; /**< */
+
+} tTeseoData;
+
+/** Application register this out callback function and Teseo class will pass outputted information to application */
+typedef void (*teseo_app_output_callback)(uint32_t msgId, uint32_t msgType, tTeseoData *pData);
+/** Application register this event callback function and Teseo class will pass internal processing event to application */
+typedef void (*teseo_app_event_callback)(eTeseoLocEventType event, uint32_t data);
+
+class Teseo : public GPSProviderImplBase {
+public:
+
+ typedef enum {
+ TEST,
+ GETSWVER,
+ FORCESTANDBY,
+ RFTESTON,
+ RFTESTOFF,
+ LOWPOWER,
+ FWUPDATE
+ } eCmd;
+
+ /** NMEA messages types */
+ typedef enum {
+ GPGGA,
+ GNS,
+ GPGST,
+ GPRMC,
+ GSA,
+ GSV,
+ } eMsg;
+
+ /** NMEA proprietary messages types */
+ typedef enum {
+ PSTMGEOFENCE,
+ PSTMODO,
+ PSTMDATALOG,
+ PSTMSGL,
+ PSTMSAVEPAR
+ } ePSTMsg;
+
+private:
+
+ eTeseoLocState _locState;
+
+ DigitalOut _loc_led2;
+ DigitalOut _reset;
+ DigitalOut _pps;
+ DigitalOut _wakeup;
+ PinName _uartRx;
+ PinName _uartTx;
+
+ Serial *_uart;
+ Serial *_serialDebug;
+ I2C *_i2c;
+
+ tTeseoData pData;
+ GPGGA_Infos stored_positions[MAX_STOR_POS];
+
+ int FwWaitAck();
+
+ Thread *serialStreamThread;
+
+ /**
+ * Command string
+ */
+ char _teseoCmd[TESEO_RXBUF_LEN];
+
+ /**
+ * Message struct
+ */
+ struct _teseoMsg {
+ uint8_t len;
+ uint8_t buf[TESEO_RXBUF_LEN];
+ };
+
+public:
+
+ /** Constructor: Teseo
+ * Create the Teseo, accept specified configuration
+ *
+ * @param [in] resetPin
+ * GPIO pin to control location chip reset.
+ * @param [in] wakeupPin
+ * GPIO pin to detect if the chip is still wakeup.
+ * @param [in] ppsPin
+ * GPIO pin... .
+ * @param [in] uartTxPin
+ * GPIO pin for serial Tx channel between the host and the GNSS controller.
+ * @param [in] uartRxPin
+ * GPIO pin for serial Rx channel between the host and the GNSS controller.
+ * @param [in] serialDebug
+ * The debug port for diagnostic messages; can be NULL.
+ */
+ Teseo(PinName resetPin,
+ PinName wakeupPin,
+ PinName ppsPin,
+ PinName uartTxPin,
+ PinName uartRxPin,
+ Serial *serialDebug = NULL);
+
+ /** Constructor: Teseo
+ * Create the Teseo, accept specified configuration
+ *
+ * @param [in] resetPin
+ * GPIO pin to control location chip reset.
+ * @param [in] wakeupPin
+ * GPIO pin to detect if the chip is still wakeup.
+ * @param [in] ppsPin
+ * GPIO pin... .
+ * @param [in] uartTxPin
+ * GPIO pin for serial Tx channel between the host and the GNSS controller.
+ * @param [in] uartRxPin
+ * GPIO pin for serial Rx channel between the host and the GNSS controller.
+ * @param [in] i2cBus
+ * I2C Bus not supported yet.
+ * @param [in] serialDebug
+ * The debug port for diagnostic messages; can be NULL.
+ */
+ Teseo(PinName resetPin,
+ PinName wakeupPin,
+ PinName ppsPin,
+ PinName uartTxPin,
+ PinName uartRxPin,
+ I2C *i2cBus,
+ Serial *serialDebug = NULL);
+
+ /** Register output callback and event callback functions
+ * @param app_output_cb Teseo class output the location and satellite information to application
+ * @param app_event_cb Teseo class output the start and stop result to application
+ */
+ void TeseoLocRegOutput(teseo_app_output_callback app_output_cb, teseo_app_event_callback app_event_cb);
+
+ void SendCommand(Teseo::eCmd c);
+ void SendCommand(char *cmd);
+
+ int EnableLowPower();
+
+ void ReadSentence(Teseo::eMsg msg);
+
+ eStatus WakeStatus(void){
+ return _wakeup.read() ? TESEO_STATUS_SUCCESS : TESEO_STATUS_FAILURE;
+ }
+
+ void ReadProcess(void);
+
+private:
+
+ virtual bool setPowerMode(GPSProvider::PowerMode_t pwrMode);
+ virtual void start(void);
+ virtual void stop(void);
+ virtual void process(void);
+ virtual uint32_t ioctl(uint32_t command, void *arg);
+ virtual void lpmGetImmediateLocation(void);
+ virtual void reset(void);
+ virtual const GPSProvider::LocationUpdateParams_t *getLastLocation(void) const;
+
+ gps_provider_error_t cfgMessageList(int level);
+ gps_provider_error_t saveConfigParams(void);
+
+ /** Set NMEA stream verbosity */
+ virtual void setVerboseMode(int level);
+
+ /** Geofencing */
+ virtual bool isGeofencingSupported(void);
+ virtual gps_provider_error_t enableGeofence(void);
+ virtual gps_provider_error_t configGeofences(GPSGeofence *geofences[], unsigned geofenceCount);
+ virtual gps_provider_error_t geofenceReq(void);
+ gps_provider_error_t cfgGeofenceCircle(void);
+
+ /** Datalogging */
+ virtual bool isDataloggingSupported(void);
+ virtual gps_provider_error_t enableDatalog(void);
+ virtual gps_provider_error_t configDatalog(GPSDatalog *datalog);
+ virtual gps_provider_error_t startDatalog(void);
+ virtual gps_provider_error_t stopDatalog(void);
+ virtual gps_provider_error_t eraseDatalog(void);
+ virtual gps_provider_error_t logReqStatus(void);
+ virtual gps_provider_error_t logReqQuery(GPSProvider::LogQueryParams_t &logReqQuery);
+
+ /* Odometer */
+ virtual bool isOdometerSupported(void);
+ virtual gps_provider_error_t enableOdo(void);
+ virtual gps_provider_error_t startOdo(unsigned alarmDistance);
+ virtual gps_provider_error_t stopOdo(void);
+ virtual gps_provider_error_t resetOdo(void);
+
+ void _InitUART(int br = STD_UART_BAUD);
+ void _ResetFast(Serial *serialDebug = NULL);
+ void _Reset(Serial *serialDebug = NULL);
+ void _SendString(char *buf, int len);
+ int _WakeUp();
+ int _CRC(char *buf, int size);
+ int _CheckI2C();
+ /**
+ * @brief This function gets a chunck of NMEA messages
+ * @param msg NMEA message to search for
+ * @retval eStatus TESEO_STATUS_SUCCESS if the parse process goes ok, TESEO_FAILURE if it doesn't
+ */
+ eStatus _GetMsg(Teseo::eMsg msg, uint8_t *buffer);
+ /**
+ * @brief This function gets a chunck of PSTM NMEA messages
+ * @param msg PSTM NMEA message to search for
+ * @retval eStatus TESEO_STATUS_SUCCESS if the parse process goes ok, TESEO_FAILURE if it doesn't
+ */
+ void _GetPSTMsg(Teseo::ePSTMsg msg, uint8_t *buffer);
+ void _GetLocationMsg(Teseo::eMsg msg, uint8_t *buffer);
+
+ void _LocLed2Set(void){
+ _loc_led2.write(1);
+ }
+ void _LocLed2Reset(void){
+ _loc_led2.write(0);
+ }
+
+ void outputHandler(uint32_t msgId, uint32_t msgType, tTeseoData *pData);
+ void eventHandler(eTeseoLocEventType event, uint32_t data);
+
+ teseo_app_output_callback appOutCb;
+ teseo_app_event_callback appEventCb;
+
+ MemoryPool<struct _teseoMsg, TESEO_RXQUEUE_LEN> mpool;
+ Queue<struct _teseoMsg, TESEO_RXQUEUE_LEN> queue;
+};
+
+#endif /*__TESEO_H__*/
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/Middlewares/NMEAParser.c Fri Nov 09 17:06:11 2018 +0000
@@ -0,0 +1,923 @@
+/**
+*******************************************************************************
+* @file NMEAParser.c
+* @author AST / Central Lab
+* @version V1.0.0
+* @date 18-May-2017
+* @brief NMEA sentence parser
+*
+*******************************************************************************
+* @attention
+*
+* <h2><center>© COPYRIGHT(c) 2017 STMicroelectronics</center></h2>
+*
+* Licensed under MCD-ST Liberty SW License Agreement V2, (the "License");
+* You may not use this file except in compliance with the License.
+* You may obtain a copy of the License at:
+*
+* http://www.st.com/software_license_agreement_liberty_v2
+*
+* Redistribution and use in source and binary forms, with or without modification,
+* are permitted provided that the following conditions are met:
+* 1. Redistributions of source code must retain the above copyright notice,
+* this list of conditions and the following disclaimer.
+* 2. Redistributions in binary form must reproduce the above copyright notice,
+* this list of conditions and the following disclaimer in the documentation
+* and/or other materials provided with the distribution.
+* 3. Neither the name of STMicroelectronics nor the names of its contributors
+* may be used to endorse or promote products derived from this software
+* without specific prior written permission.
+*
+* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
+* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*
+********************************************************************************
+*/
+
+#include "string.h"
+#include "NMEAParser.h"
+#include "NMEAUtils.h"
+
+/** @defgroup Middlewares
+ * @brief Contains all platform independent modules (eg. NMEA Sentence Parser, ...).
+ * @{
+ */
+
+/** @defgroup ST
+ * @{
+ */
+
+/** @defgroup LIB_NMEA
+ * @{
+ */
+
+/** @defgroup NMEA_PARSER
+ * @{
+ */
+
+/** @addtogroup NMEA_PARSER_PUBLIC_FUNCTIONS
+ * @{
+ */
+/**
+ * @brief Function that makes the parsing of the $GPGGA NMEA string with all Global Positioning System Fixed data.
+ * @param gpgga_data Pointer to GPGGA_Infos struct
+ * @param NMEA NMEA string read by the Gps expansion
+ * @retval ParseStatus_Typedef PARSE_SUCC if the parsing process goes ok, PARSE_FAIL if it doesn't
+ */
+ParseStatus_Typedef parse_gpgga(GPGGA_Infos *gpgga_data, uint8_t *NMEA)
+{
+ uint8_t app[MAX_MSG_LEN][MAX_MSG_LEN];
+ uint8_t valid_msg = 0;
+
+ ParseStatus_Typedef status = PARSE_FAIL;
+
+ if(NMEA == NULL)
+ return status;
+
+ /* clear the app[][] buffer */
+ for (uint8_t i=0; i<MAX_MSG_LEN; i++) {
+ memset(app[i], 0, MAX_MSG_LEN);
+ }
+
+ for(unsigned i = 0, j = 0, k = 0; NMEA[i] != '\n' && i < strlen((char *)NMEA) - 1; i++)
+ {
+ if ((NMEA[i] == ',') || (NMEA[i] == '*')) {
+ app[j][k] = '\0';
+
+ if (strcmp((char *)app[0], "$GPGGA") == 0) {
+ j++;
+ k = 0;
+ valid_msg = 1;
+ continue;
+ }
+ else {
+ while(NMEA[i++] != '\n');
+ j = k = 0;
+ }
+ }
+ app[j][k++] = NMEA[i];
+ }
+
+ if (valid_msg == 1) {
+ unsigned int valid;
+ sscanf ((char *)app[6], "%u", &valid);
+ gpgga_data->valid = (GPS_ValidTypedef)valid;
+ if (gpgga_data->valid == VALID) {
+ scan_utc ((char *)app[1], &gpgga_data->utc);
+ sscanf ((char *)app[2], "%lf", &gpgga_data->xyz.lat);
+ sscanf ((char *)app[3], "%c", &gpgga_data->xyz.ns);
+ sscanf ((char *)app[4], "%lf", &gpgga_data->xyz.lon);
+ sscanf ((char *)app[5], "%c", &gpgga_data->xyz.ew);
+ sscanf ((char *)app[7], "%d", &gpgga_data->sats);
+ sscanf ((char *)app[8], "%f", &gpgga_data->acc);
+ sscanf ((char *)app[9], "%f", &gpgga_data->xyz.alt);
+ sscanf ((char *)app[10], "%c", &gpgga_data->xyz.mis);
+ sscanf ((char *)app[11], "%d", &gpgga_data->geoid.height);
+ sscanf ((char *)app[12], "%c", &gpgga_data->geoid.mis);
+ sscanf ((char *)app[13], "%d", &gpgga_data->update);
+ sscanf ((char *)app[14], "%x", &gpgga_data->checksum);
+
+ valid_msg = 0;
+ status = PARSE_SUCC;
+ }
+ }
+ return status;
+}
+
+/**
+ * @brief Function that makes the parsing of the string read by the Gps expansion, capturing the right parameters from it.
+ * @param gns_data Pointer to GNS_Infos struct
+ * @param NMEA NMEA string read by the Gps expansion
+ * @retval ParseStatus_Typedef PARSE_SUCC if the parsing process goes ok, PARSE_FAIL if it doesn't
+ */
+ParseStatus_Typedef parse_gnsmsg (GNS_Infos *gns_data, uint8_t *NMEA)
+{
+ uint8_t app[MAX_MSG_LEN][MAX_MSG_LEN];
+ uint8_t valid_msg = 0;
+
+ ParseStatus_Typedef status = PARSE_FAIL;
+
+ if(NMEA == NULL)
+ return status;
+
+ /* clear the app[][] buffer */
+ for (uint8_t i=0; i<MAX_MSG_LEN; i++) {
+ memset(app[i], 0, MAX_MSG_LEN);
+ }
+
+ for (unsigned i = 0, j = 0, k = 0; NMEA[i] != '\n' && i < strlen((char *)NMEA) - 1; i++)
+ {
+ if ((NMEA[i] == ',') || (NMEA[i] == '*')) {
+ app[j][k] = '\0';
+
+ if ((strcmp((char *)app[0], "$GPGNS") == 0) ||
+ (strcmp((char *)app[0], "$GLGNS") == 0) ||
+ (strcmp((char *)app[0], "$GAGNS") == 0) ||
+ (strcmp((char *)app[0], "$BDGNS") == 0) ||
+ (strcmp((char *)app[0], "$QZGNS") == 0) ||
+ (strcmp((char *)app[0], "$GNGNS") == 0))
+ {
+ j++;
+ k = 0;
+ valid_msg = 1;
+ continue;
+ }
+ else {
+ while (NMEA[i++] != '\n');
+ j = k = 0;
+ }
+ }
+ app[j][k++] = NMEA[i];
+ }
+
+ if (valid_msg == 1) {
+ sscanf ((char *)app[0], "%s", gns_data->constellation);
+ scan_utc ((char *)app[1], &gns_data->utc);
+ sscanf ((char *)app[2], "%lf", &gns_data->xyz.lat);
+ sscanf ((char *)app[3], "%c", &gns_data->xyz.ns);
+ sscanf ((char *)app[4], "%lf", &gns_data->xyz.lon);
+ sscanf ((char *)app[5], "%c", &gns_data->xyz.ew);
+ sscanf ((char *)app[6], "%c", &gns_data->gps_mode);
+ sscanf ((char *)app[7], "%c", &gns_data->glonass_mode);
+ sscanf ((char *)app[8], "%d", &gns_data->sats);
+ sscanf ((char *)app[9], "%f", &gns_data->hdop);
+ sscanf ((char *)app[10], "%f", &gns_data->xyz.alt);
+ sscanf ((char *)app[11], "%f", &gns_data->geo_sep);
+ sscanf ((char *)app[12], "%c", &gns_data->dgnss_age);
+ sscanf ((char *)app[13], "%c", &gns_data->dgnss_ref);
+ sscanf ((char *)app[14], "%x", &gns_data->checksum);
+
+ valid_msg = 0;
+ status = PARSE_SUCC;
+ }
+
+ return status;
+}
+
+/**
+ * @brief Function that makes the parsing of the $GPGST NMEA string with GPS Pseudorange Noise Statistics.
+ * @param GPGST_Infos Pointer to a GPGST_Infos struct
+ * @param NMEA NMEA string read by the Gps expansion.
+ * @retval ParseStatus_Typedef PARSE_SUCC if the parsing process goes ok, PARSE_FAIL if it doesn't
+ */
+ParseStatus_Typedef parse_gpgst (GPGST_Infos *gpgst_data, uint8_t *NMEA)
+{
+ uint8_t app[MAX_MSG_LEN][MAX_MSG_LEN];
+ uint8_t valid_msg = 0;
+
+ ParseStatus_Typedef status = PARSE_FAIL;
+
+ if(NMEA == NULL)
+ return status;
+
+ /* clear the app[][] buffer */
+ for (uint8_t i=0; i<MAX_MSG_LEN; i++) {
+ memset(app[i], 0, MAX_MSG_LEN);
+ }
+
+ for (unsigned i = 0, j = 0, k = 0; NMEA[i] != '\n' && i < strlen((char *)NMEA) - 1; i++)
+ {
+ if ((NMEA[i] == ',') || (NMEA[i] == '*')) {
+ app[j][k] = '\0';
+
+ if (strcmp((char *)app[0], "$GPGST") == 0)
+ {
+ j++;
+ k = 0;
+ valid_msg = 1;
+ continue;
+ }
+ else {
+ while (NMEA[i++] != '\n');
+ j = k = 0;
+ }
+ }
+ app[j][k++] = NMEA[i];
+ }
+
+ if (valid_msg == 1) {
+ scan_utc ((char *)app[1], &gpgst_data->utc);
+ sscanf ((char *)app[2], "%f", &gpgst_data->EHPE);
+ sscanf ((char *)app[3], "%f", &gpgst_data->semi_major_dev);
+ sscanf ((char *)app[4], "%f", &gpgst_data->semi_minor_dev);
+ sscanf ((char *)app[5], "%f", &gpgst_data->semi_major_angle);
+ sscanf ((char *)app[6], "%f", &gpgst_data->lat_err_dev);
+ sscanf ((char *)app[7], "%f", &gpgst_data->lon_err_dev);
+ sscanf ((char *)app[8], "%f", &gpgst_data->alt_err_dev);
+ sscanf ((char *)app[9], "%x", &gpgst_data->checksum);
+
+ valid_msg = 0;
+ status = PARSE_SUCC;
+ }
+
+ return status;
+}
+
+/**
+ * @brief Function that makes the parsing of the $GPRMC NMEA string with Recommended Minimum Specific GPS/Transit data.
+ * @param GPRMC_Infos Pointer to a GPRMC_Infos struct
+ * @param NMEA NMEA string read by the Gps expansion.
+ * @retval ParseStatus_Typedef PARSE_SUCC if the parsing process goes ok, PARSE_FAIL if it doesn't
+ */
+ParseStatus_Typedef parse_gprmc (GPRMC_Infos *gprmc_data, uint8_t *NMEA)
+{
+ uint8_t app[MAX_MSG_LEN][MAX_MSG_LEN];
+ uint8_t valid_msg = 0;
+
+ ParseStatus_Typedef status = PARSE_FAIL;
+
+ if(NMEA == NULL)
+ return status;
+
+ /* clear the app[][] buffer */
+ for (uint8_t i=0; i<MAX_MSG_LEN; i++) {
+ memset(app[i], 0, MAX_MSG_LEN);
+ }
+
+ for (unsigned i = 0, j = 0, k = 0; NMEA[i] != '\n' && i < strlen((char *)NMEA) - 1; i++)
+ {
+ if ((NMEA[i] == ',') || (NMEA[i] == '*')) {
+ app[j][k] = '\0';
+
+ if (strcmp((char *)app[0], "$GPRMC") == 0)
+ {
+ j++;
+ k = 0;
+ valid_msg = 1;
+ continue;
+ }
+ else {
+ while (NMEA[i++] != '\n');
+ j = k = 0;
+ }
+ }
+ app[j][k++] = NMEA[i];
+ }
+
+ if (valid_msg == 1) {
+ scan_utc ((char *)app[1], &gprmc_data->utc);
+ sscanf ((char *)app[2], "%c", &gprmc_data->status);
+ sscanf ((char *)app[3], "%lf", &gprmc_data->xyz.lat);
+ sscanf ((char *)app[4], "%c", &gprmc_data->xyz.ns);
+ sscanf ((char *)app[5], "%lf", &gprmc_data->xyz.lon);
+ sscanf ((char *)app[6], "%c", &gprmc_data->xyz.ew);
+ sscanf ((char *)app[7], "%f", &gprmc_data->speed);
+ sscanf ((char *)app[8], "%f", &gprmc_data->trackgood);
+ sscanf ((char *)app[9], "%d", &gprmc_data->date);
+ sscanf ((char *)app[10], "%f", &gprmc_data->mag_var);
+ sscanf ((char *)app[11], "%c", &gprmc_data->mag_var_dir);
+ /* WARNING: from received msg, it seems there is another data (app[12]) before the checksum */
+ sscanf ((char *)app[13], "%x", &gprmc_data->checksum);
+
+ valid_msg = 0;
+ status = PARSE_SUCC;
+ }
+
+ return status;
+}
+
+/**
+ * @brief Function that makes the parsing of the string read by the Gps expansion, capturing the right parameters from it.
+ * @param GSA_Infos Pointer to a GSA_Infos struct
+ * @param NMEA NMEA string read by the Gps expansion.
+ * @retval ParseStatus_Typedef PARSE_SUCC if the parsing process goes ok, PARSE_FAIL if it doesn't
+ */
+ParseStatus_Typedef parse_gsamsg (GSA_Infos *gsa_data, uint8_t *NMEA)
+{
+ uint8_t app[MAX_MSG_LEN][MAX_MSG_LEN];
+ uint8_t valid_msg = 0;
+
+ ParseStatus_Typedef status = PARSE_FAIL;
+
+ if(NMEA == NULL)
+ return status;
+
+ /* clear the app[][] buffer */
+ for (uint8_t i=0; i<19; i++) {
+ memset(app[i], 0, 19);
+ }
+
+ for (unsigned i = 0, j = 0, k = 0; NMEA[i] != '\n' && i < strlen((char *)NMEA) - 1; i++)
+ {
+ if ((NMEA[i] == ',') || (NMEA[i] == '*')) {
+ app[j][k] = '\0';
+
+ if ((strcmp((char *)app[0], "$GPGSA") == 0) ||
+ (strcmp((char *)app[0], "$GLGSA") == 0) ||
+ (strcmp((char *)app[0], "$GAGSA") == 0) ||
+ (strcmp((char *)app[0], "$BDGSA") == 0) ||
+ (strcmp((char *)app[0], "$GNGSA") == 0))
+ {
+ j++;
+ k = 0;
+ valid_msg = 1;
+ continue;
+ }
+ else {
+ while (NMEA[i++] != '\n');
+ j = k = 0;
+ }
+ }
+ app[j][k++] = NMEA[i];
+ }
+
+ if (valid_msg == 1) {
+ sscanf ((char *)app[0], "%s", gsa_data->constellation);
+ sscanf ((char *)app[1], "%c", &gsa_data->operating_mode);
+ sscanf ((char *)app[2], "%d", &gsa_data->current_mode);
+ for (uint8_t i=0; i<MAX_SAT_NUM; i++) {
+ sscanf ((char *)app[3+i], "%d", &gsa_data->sat_prn[i]);
+ }
+ sscanf ((char *)app[15], "%f", &gsa_data->pdop);
+ sscanf ((char *)app[16], "%f", &gsa_data->hdop);
+ sscanf ((char *)app[17], "%f", &gsa_data->vdop);
+ sscanf ((char *)app[18], "%x", &gsa_data->checksum);
+
+ valid_msg = 0;
+ status = PARSE_SUCC;
+ }
+
+ return status;
+}
+
+/**
+ * @brief Function that makes the parsing of the string read by the Gps expansion, capturing the right parameters from it.
+ * @param GSV_Infos Pointer to a GSV_Infos struct
+ * @param NMEA NMEA string read by the Gps expansion.
+ * @retval ParseStatus_Typedef PARSE_SUCC if the parsing process goes ok, PARSE_FAIL if it doesn't
+ */
+ParseStatus_Typedef parse_gsvmsg(GSV_Infos *gsv_data, uint8_t *NMEA)
+{
+ uint8_t app[32][16];
+ uint8_t app_idx;
+ uint8_t gsv_idx = 0;
+ int msg_amount = 1;
+ int curr_msg;
+ uint8_t right_msg = 0;
+ uint8_t valid_gsv_msg = 0;
+ unsigned i, j, k;
+ unsigned l = 0;
+
+ ParseStatus_Typedef status = PARSE_FAIL;
+
+ if(NMEA == NULL)
+ return status;
+
+ while (right_msg < msg_amount)
+ {
+ /* clear the app[][] buffer */
+ for (uint8_t pos=0; pos<32; pos++) {
+ memset(app[pos], 0, 16);
+ }
+
+ for (i = l, j = 0, k = 0; NMEA[i] != '\n' && i < strlen((char *)NMEA) - 1; i++)
+ {
+ if (NMEA[i] == ',') {
+ app[j][k] = '\0';
+
+ if ((strcmp((char *)app[0], "$GPGSV") == 0) ||
+ (strcmp((char *)app[0], "$GLGSV") == 0) ||
+ (strcmp((char *)app[0], "$GAGSV") == 0) ||
+ (strcmp((char *)app[0], "$BDGSV") == 0) ||
+ (strcmp((char *)app[0], "$QZGSV") == 0) ||
+ (strcmp((char *)app[0], "$GNGSV") == 0))
+ {
+ j++;
+ k = 0;
+ valid_gsv_msg = 1;
+ continue;
+ }
+ else {
+ while (NMEA[i++] != '\n');
+ j = k = 0;
+ }
+ }
+ if ((NMEA[i] == '*') && (k!=0)) {
+ j++;
+ k=0;
+ }
+ app[j][k++] = NMEA[i];
+ }
+
+ l = i;
+
+ if (valid_gsv_msg == 1) {
+ valid_gsv_msg = 0;
+ sscanf((char *)app[1], "%d", &msg_amount);
+ sscanf((char *)app[2], "%d", &curr_msg);
+ if (curr_msg == right_msg+1) {
+ valid_gsv_msg = 1;
+ right_msg++;
+ }
+ }
+ else {
+ right_msg = msg_amount;
+ }
+
+ if (valid_gsv_msg == 1) {
+ sscanf((char *)app[0], "%s", gsv_data->constellation);
+ sscanf((char *)app[1], "%d", &gsv_data->amount);
+ sscanf((char *)app[2], "%d", &gsv_data->number);
+ sscanf((char *)app[3], "%d", &gsv_data->tot_sats);
+ app_idx = 4;
+ while (app[app_idx][0] != '*') {
+ sscanf((char *)app[app_idx++], "%d", &gsv_data->gsv_sat_i[gsv_idx].prn);
+ sscanf((char *)app[app_idx++], "%d", &gsv_data->gsv_sat_i[gsv_idx].elev);
+ sscanf((char *)app[app_idx++], "%d", &gsv_data->gsv_sat_i[gsv_idx].azim);
+ if (app[app_idx][0] != '*') {
+ sscanf((char *)app[app_idx++], "%d", &gsv_data->gsv_sat_i[gsv_idx].cn0);
+ }
+ else {
+ sscanf("", "%d", &gsv_data->gsv_sat_i[gsv_idx].cn0);
+ }
+ gsv_idx++;
+ }
+
+ valid_gsv_msg = 0;
+
+ status = PARSE_SUCC;
+ }
+ }
+
+ return status;
+}
+
+/**
+ * @brief
+ * @param Geofence_Infos Pointer to a Geofence_Infos struct
+ * @param NMEA NMEA string read by the Gps expansion.
+ * @retval ParseStatus_Typedef PARSE_SUCC if the parsing process goes ok, PARSE_FAIL if it doesn't
+ */
+ParseStatus_Typedef parse_pstmgeofence(Geofence_Infos *geofence_data, uint8_t *NMEA)
+{
+ uint8_t app[MAX_MSG_LEN][MAX_MSG_LEN];
+ uint8_t valid_msg = 0;
+
+ ParseStatus_Typedef status = PARSE_FAIL;
+
+ if(NMEA == NULL)
+ return status;
+
+ /* clear the app[][] buffer */
+ for (uint8_t i=0; i<MAX_MSG_LEN; i++) {
+ memset(app[i], 0, MAX_MSG_LEN);
+ }
+
+ for(unsigned i = 0, j = 0, k = 0; NMEA[i] != '\n' && i < strlen((char *)NMEA) - 1; i++)
+ {
+ if ((NMEA[i] == ',') || (NMEA[i] == '*')) {
+ app[j][k] = '\0';
+
+ if ((strcmp((char *)app[0], "$PSTMCFGGEOFENCEOK") == 0) ||
+ (strcmp((char *)app[0], "$PSTMCFGGEOFENCEERROR") == 0) ||
+ (strcmp((char *)app[0], "$PSTMGEOFENCECFGOK") == 0) ||
+ (strcmp((char *)app[0], "$PSTMGEOFENCECFGERROR") == 0) ||
+ (strcmp((char *)app[0], "$PSTMGEOFENCESTATUS") == 0) ||
+ (strcmp((char *)app[0], "$PSTMGEOFENCE") == 0) ||
+ (strcmp((char *)app[0], "$PSTMGEOFENCEREQERROR") == 0)) {
+ j++;
+ k = 0;
+ valid_msg = 1;
+ continue;
+ }
+ else {
+ while(NMEA[i++] != '\n');
+ j = k = 0;
+ }
+ }
+ app[j][k++] = NMEA[i];
+ }
+
+ if (valid_msg == 1) {
+ /* Enabling */
+ if (strcmp((char *)app[0], "$PSTMCFGGEOFENCEOK") == 0) {
+ geofence_data->op = GNSS_FEATURE_EN_MSG;
+ geofence_data->result = 0;
+ }
+ if (strcmp((char *)app[0], "$PSTMCFGGEOFENCEERROR") == 0) {
+ geofence_data->op = GNSS_FEATURE_EN_MSG;
+ geofence_data->result = 1;
+ }
+ /* Configuring */
+ if (strcmp((char *)app[0], "$PSTMGEOFENCECFGOK") == 0) {
+ geofence_data->op = GNSS_GEOFENCE_CFG_MSG;
+ geofence_data->result = 0;
+ }
+ if (strcmp((char *)app[0], "$PSTMGEOFENCECFGERROR") == 0) {
+ geofence_data->op = GNSS_GEOFENCE_STATUS_MSG;
+ geofence_data->result = 1;
+ }
+ /* Querying Status */
+ if (strcmp((char *)app[0], "$PSTMGEOFENCESTATUS") == 0) {
+ geofence_data->op = GNSS_GEOFENCE_STATUS_MSG;
+ geofence_data->result = 0;
+ sscanf((char *)app[1], "%02d%02d%02d", &geofence_data->timestamp.hh,&geofence_data->timestamp.mm,&geofence_data->timestamp.ss);
+ sscanf((char *)app[2], "%04d%02d%02d", &geofence_data->timestamp.year,&geofence_data->timestamp.month,&geofence_data->timestamp.day);
+ for(uint8_t i = 0; i<MAX_GEOFENCES_NUM; i++) {
+ sscanf((char *)app[3+i], "%d", &geofence_data->status[i]);
+ }
+ }
+ /* Alarm Msg */
+ if (strcmp((char *)app[0], "$PSTMGEOFENCE") == 0) {
+ geofence_data->op = GNSS_GEOFENCE_ALARM_MSG;
+ geofence_data->result = 0;
+ sscanf((char *)app[1], "%02d%02d%02d", &geofence_data->timestamp.hh,&geofence_data->timestamp.mm,&geofence_data->timestamp.ss);
+ sscanf((char *)app[2], "%04d%02d%02d", &geofence_data->timestamp.year,&geofence_data->timestamp.month,&geofence_data->timestamp.day);
+ sscanf((char *)app[3], "%d", &geofence_data->idAlarm);
+ sscanf((char *)app[9], "%d", &geofence_data->status[geofence_data->idAlarm]);
+ }
+
+ valid_msg = 0;
+ status = PARSE_SUCC;
+ }
+ return status;
+}
+
+/**
+ * @brief
+ * @param Odometer_Infos Pointer to a Odometer_Infos struct
+ * @param NMEA NMEA string read by the Gps expansion.
+ * @retval ParseStatus_Typedef PARSE_SUCC if the parsing process goes ok, PARSE_FAIL if it doesn't
+ */
+ParseStatus_Typedef parse_pstmodo(Odometer_Infos *odo_data, uint8_t *NMEA)
+{
+ uint8_t app[MAX_MSG_LEN][MAX_MSG_LEN];
+ uint8_t valid_msg = 0;
+
+ ParseStatus_Typedef status = PARSE_FAIL;
+
+ if(NMEA == NULL)
+ return status;
+
+ /* clear the app[][] buffer */
+ for (uint8_t i=0; i<MAX_MSG_LEN; i++) {
+ memset(app[i], 0, MAX_MSG_LEN);
+ }
+
+ for(unsigned i = 0, j = 0, k = 0; NMEA[i] != '\n' && i < strlen((char *)NMEA) - 1; i++)
+ {
+ if ((NMEA[i] == ',') || (NMEA[i] == '*')) {
+ app[j][k] = '\0';
+
+ if ((strcmp((char *)app[0], "$PSTMCFGODOOK") == 0) ||
+ (strcmp((char *)app[0], "$PSTMCFGODOERROR") == 0) ||
+ (strcmp((char *)app[0], "$PSTMODOSTARTOK") == 0) ||
+ (strcmp((char *)app[0], "$PSTMODOSTARTERROR") == 0) ||
+ (strcmp((char *)app[0], "$PSTMODOSTOPOK") == 0) ||
+ (strcmp((char *)app[0], "$PSTMODOSTOPERROR") == 0)) {
+ j++;
+ k = 0;
+ valid_msg = 1;
+ continue;
+ }
+ else {
+ while(NMEA[i++] != '\n');
+ j = k = 0;
+ }
+ }
+ app[j][k++] = NMEA[i];
+ }
+
+ if (valid_msg == 1) {
+ /* Enabling */
+ if (strcmp((char *)app[0], "$PSTMCFGODOOK") == 0) {
+ odo_data->op = GNSS_FEATURE_EN_MSG;
+ odo_data->result = 0;
+ }
+ if (strcmp((char *)app[0], "$PSTMCFGODOERROR") == 0) {
+ odo_data->op = GNSS_FEATURE_EN_MSG;
+ odo_data->result = 1;
+ }
+
+ /* Start */
+ if (strcmp((char *)app[0], "$PSTMODOSTARTOK") == 0) {
+ odo_data->op = GNSS_ODO_START_MSG;
+ odo_data->result = 0;
+ }
+ if (strcmp((char *)app[0], "$PSTMODOSTARTERROR") == 0) {
+ odo_data->op = GNSS_ODO_START_MSG;
+ odo_data->result = 1;
+ }
+
+ /* Stop */
+ if (strcmp((char *)app[0], "$PSTMODOSTOPOK") == 0) {
+ odo_data->op = GNSS_ODO_STOP_MSG;
+ odo_data->result = 0;
+ }
+ if (strcmp((char *)app[0], "$PSTMODOSTOPERROR") == 0) {
+ odo_data->op = GNSS_ODO_STOP_MSG;
+ odo_data->result = 1;
+ }
+
+ valid_msg = 0;
+ status = PARSE_SUCC;
+ }
+ return status;
+}
+
+/**
+ * @brief
+ * @param Datalog_Infos Pointer to a Datalog_Infos struct
+ * @param NMEA NMEA string read by the Gps expansion.
+ * @retval ParseStatus_Typedef PARSE_SUCC if the parsing process goes ok, PARSE_FAIL if it doesn't
+ */
+ParseStatus_Typedef parse_pstmdatalog(Datalog_Infos *datalog_data, uint8_t *NMEA)
+{
+ uint8_t app[MAX_MSG_LEN][MAX_MSG_LEN];
+ uint8_t valid_msg = 0;
+
+ ParseStatus_Typedef status = PARSE_FAIL;
+
+ if(NMEA == NULL)
+ return status;
+
+ /* clear the app[][] buffer */
+ for (uint8_t i=0; i<MAX_MSG_LEN; i++) {
+ memset(app[i], 0, MAX_MSG_LEN);
+ }
+
+ for(unsigned i = 0, j = 0, k = 0; NMEA[i] != '\n' && i < strlen((char *)NMEA) - 1; i++)
+ {
+ if ((NMEA[i] == ',') || (NMEA[i] == '*')) {
+ app[j][k] = '\0';
+
+ if ((strcmp((char *)app[0], "$PSTMCFGLOGOK") == 0) ||
+ (strcmp((char *)app[0], "$PSTMCFGLOGERROR") == 0) ||
+ (strcmp((char *)app[0], "$PSTMLOGCREATEOK") == 0) ||
+ (strcmp((char *)app[0], "$PSTMLOGCREATEERROR") == 0) ||
+ (strcmp((char *)app[0], "$PSTMLOGSTARTOK") == 0) ||
+ (strcmp((char *)app[0], "$PSTMLOGSTARTERROR") == 0) ||
+ (strcmp((char *)app[0], "$PSTMLOGSTOPOK") == 0) ||
+ (strcmp((char *)app[0], "$PSTMLOGSTOPERROR") == 0) ||
+ (strcmp((char *)app[0], "$PSTMLOGERASEOK") == 0) ||
+ (strcmp((char *)app[0], "$PSTMLOGERASEERROR") == 0)) {
+ j++;
+ k = 0;
+ valid_msg = 1;
+ continue;
+ }
+ else {
+ while(NMEA[i++] != '\n');
+ j = k = 0;
+ }
+ }
+ app[j][k++] = NMEA[i];
+ }
+
+ if (valid_msg == 1) {
+ /* Enabling */
+ if (strcmp((char *)app[0], "$PSTMCFGLOGOK") == 0) {
+ datalog_data->op = GNSS_FEATURE_EN_MSG;
+ datalog_data->result = 0;
+ }
+ if (strcmp((char *)app[0], "$PSTMCFGLOGERROR") == 0) {
+ datalog_data->op = GNSS_FEATURE_EN_MSG;
+ datalog_data->result = 1;
+ }
+ /* Configuring */
+ if (strcmp((char *)app[0], "$PSTMLOGCREATEOK") == 0) {
+ datalog_data->op = GNSS_DATALOG_CFG_MSG;
+ datalog_data->result = 0;
+ }
+ if (strcmp((char *)app[0], "$PSTMLOGCREATEERROR") == 0) {
+ datalog_data->op = GNSS_DATALOG_CFG_MSG;
+ datalog_data->result = 1;
+ }
+ /* Start */
+ if (strcmp((char *)app[0], "$PSTMLOGSTARTOK") == 0) {
+ datalog_data->op = GNSS_DATALOG_START_MSG;
+ datalog_data->result = 0;
+ }
+ if (strcmp((char *)app[0], "$PSTMLOGSTARTERROR") == 0) {
+ datalog_data->op = GNSS_DATALOG_START_MSG;
+ datalog_data->result = 1;
+ }
+ /* Stop */
+ if (strcmp((char *)app[0], "$PSTMLOGSTOPOK") == 0) {
+ datalog_data->op = GNSS_DATALOG_STOP_MSG;
+ datalog_data->result = 0;
+ }
+ if (strcmp((char *)app[0], "$PSTMLOGSTOPERROR") == 0) {
+ datalog_data->op = GNSS_DATALOG_STOP_MSG;
+ datalog_data->result = 1;
+ }
+ /* Erase */
+ if (strcmp((char *)app[0], "$PSTMLOGERASEOK") == 0) {
+ datalog_data->op = GNSS_DATALOG_ERASE_MSG;
+ datalog_data->result = 0;
+ }
+ if (strcmp((char *)app[0], "$PSTMLOGERASEERROR") == 0) {
+ datalog_data->op = GNSS_DATALOG_ERASE_MSG;
+ datalog_data->result = 1;
+ }
+
+ valid_msg = 0;
+ status = PARSE_SUCC;
+ }
+ return status;
+}
+
+/**
+ * @brief
+ * @param Ack_Info Ack from Teseo
+ * @param NMEA NMEA string read by the Gps expansion.
+ * @retval ParseStatus_Typedef PARSE_SUCC if the parsing process goes ok, PARSE_FAIL if it doesn't
+ */
+ParseStatus_Typedef parse_pstmsgl(Ack_Info *ack, uint8_t *NMEA)
+{
+ uint8_t app[MAX_MSG_LEN][MAX_MSG_LEN];
+ uint8_t valid_msg = 0;
+
+ ParseStatus_Typedef status = PARSE_FAIL;
+
+ if(NMEA == NULL)
+ return status;
+
+ /* clear the app[][] buffer */
+ for (uint8_t i=0; i<MAX_MSG_LEN; i++) {
+ memset(app[i], 0, MAX_MSG_LEN);
+ }
+
+ for(unsigned i = 0, j = 0, k = 0; NMEA[i] != '\n' && i < strlen((char *)NMEA) - 1; i++)
+ {
+ if ((NMEA[i] == ',') || (NMEA[i] == '*')) {
+ app[j][k] = '\0';
+
+ if ((strcmp((char *)app[0], "$PSTMCFGMSGLOK") == 0) ||
+ (strcmp((char *)app[0], "$PSTMCFGMSGLERROR") == 0)) {
+ j++;
+ k = 0;
+ valid_msg = 1;
+ continue;
+ }
+ else {
+ while(NMEA[i++] != '\n');
+ j = k = 0;
+ }
+ }
+ app[j][k++] = NMEA[i];
+ }
+
+ if (valid_msg == 1) {
+ /* Enabling */
+ if (strcmp((char *)app[0], "$PSTMCFGMSGLOK") == 0) {
+ *ack = 0;
+ }
+ if (strcmp((char *)app[0], "$PSTMCFGMSGLERROR") == 0) {
+ *ack = 1;
+ }
+
+ valid_msg = 0;
+ status = PARSE_SUCC;
+ }
+ return status;
+}
+
+/**
+ * @brief
+ * @param Ack_Info Ack from Teseo
+ * @param NMEA NMEA string read by the Gps expansion.
+ * @retval ParseStatus_Typedef PARSE_SUCC if the parsing process goes ok, PARSE_FAIL if it doesn't
+ */
+ParseStatus_Typedef parse_pstmsavepar(Ack_Info *ack, uint8_t *NMEA)
+{
+ uint8_t app[MAX_MSG_LEN][MAX_MSG_LEN];
+ uint8_t valid_msg = 0;
+
+ ParseStatus_Typedef status = PARSE_FAIL;
+
+ if(NMEA == NULL)
+ return status;
+
+ /* clear the app[][] buffer */
+ for (uint8_t i=0; i<MAX_MSG_LEN; i++) {
+ memset(app[i], 0, MAX_MSG_LEN);
+ }
+
+ for(unsigned i = 0, j = 0, k = 0; NMEA[i] != '\n' && i < strlen((char *)NMEA) - 1; i++)
+ {
+ if ((NMEA[i] == ',') || (NMEA[i] == '*')) {
+ app[j][k] = '\0';
+
+ if ((strcmp((char *)app[0], "$PSTMSAVEPAROK") == 0) ||
+ (strcmp((char *)app[0], "$PSTMSAVEPARERROR") == 0)) {
+ j++;
+ k = 0;
+ valid_msg = 1;
+ continue;
+ }
+ else {
+ while(NMEA[i++] != '\n');
+ j = k = 0;
+ }
+ }
+ app[j][k++] = NMEA[i];
+ }
+
+ if (valid_msg == 1) {
+ /* Enabling */
+ if (strcmp((char *)app[0], "$PSTMSAVEPAROK") == 0) {
+ *ack = 0;
+ }
+ if (strcmp((char *)app[0], "$PSTMSAVEPARERROR") == 0) {
+ *ack = 1;
+ }
+
+ valid_msg = 0;
+ status = PARSE_SUCC;
+ }
+ return status;
+}
+
+/**
+ * @brief This function makes a copy of the datas stored into gps_t into the 'info' param
+ * @param info Instance of a GPGGA_Infos object where there are the infos to be copied
+ * @param gps_t Instance of a GPGGA_Infos object pointer where the infos stored into gps_t have to be copied
+ * @retval None
+ */
+void copy_data(GPGGA_Infos *info, GPGGA_Infos gps_t){
+ info->acc = gps_t.acc;
+ info->geoid.height = gps_t.geoid.height;
+ info->geoid.mis = gps_t.geoid.mis;
+ info->sats = gps_t.sats;
+ info->update = gps_t.update;
+ info->utc.hh = gps_t.utc.hh;
+ info->utc.mm = gps_t.utc.mm;
+ info->utc.ss = gps_t.utc.ss;
+ info->utc.utc = gps_t.utc.utc;
+ info->valid = gps_t.valid;
+ info->xyz.alt = gps_t.xyz.alt;
+ info->xyz.lat = gps_t.xyz.lat;
+ info->xyz.lon = gps_t.xyz.lon;
+ info->xyz.ew = gps_t.xyz.ew;
+ info->xyz.ns = gps_t.xyz.ns;
+ info->xyz.mis = gps_t.xyz.mis;
+ info->checksum = gps_t.checksum;
+}
+/**
+* @}
+*/
+
+/**
+* @}
+*/
+
+/**
+* @}
+*/
+
+/**
+ * @}
+ */
+
+/**
+* @}
+*/
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/Middlewares/NMEAParser.h Fri Nov 09 17:06:11 2018 +0000
@@ -0,0 +1,359 @@
+/**
+*******************************************************************************
+* @file NMEAParser.h
+* @author AST / Central Lab
+* @version V1.0.0
+* @date 18-May-2017
+* @brief NMEA sentence parser
+*
+*******************************************************************************
+* @attention
+*
+* <h2><center>© COPYRIGHT(c) 2017 STMicroelectronics</center></h2>
+*
+* Licensed under MCD-ST Liberty SW License Agreement V2, (the "License");
+* You may not use this file except in compliance with the License.
+* You may obtain a copy of the License at:
+*
+* http://www.st.com/software_license_agreement_liberty_v2
+*
+* Redistribution and use in source and binary forms, with or without modification,
+* are permitted provided that the following conditions are met:
+* 1. Redistributions of source code must retain the above copyright notice,
+* this list of conditions and the following disclaimer.
+* 2. Redistributions in binary form must reproduce the above copyright notice,
+* this list of conditions and the following disclaimer in the documentation
+* and/or other materials provided with the distribution.
+* 3. Neither the name of STMicroelectronics nor the names of its contributors
+* may be used to endorse or promote products derived from this software
+* without specific prior written permission.
+*
+* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
+* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*
+********************************************************************************
+*/
+
+/* Define to prevent recursive inclusion -------------------------------------*/
+#ifndef __NMEA_PARSER_H
+#define __NMEA_PARSER_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include <stdio.h>
+#include <stdint.h>
+
+/** @defgroup Middlewares
+ * @brief Contains all platform independent modules (eg. NMEA Sentence Parser, ...).
+ * @{
+ */
+
+/** @defgroup ST
+ * @{
+ */
+
+/** @defgroup LIB_NMEA
+ * @{
+ */
+
+/** @defgroup NMEA_PARSER
+ * @{
+ */
+
+/** @addtogroup NMEA_PARSER_CONSTANTS_DEFINITIONS
+ * @{
+ */
+/**
+ * @brief Constant that indicates the maximum lenght of an NMEA sentence
+ */
+#define MAX_NMEA_SENTENCE_LEN 80
+
+/**
+ * @brief Constant that indicates the maximum number of satellites.
+ */
+#define MAX_SAT_NUM 12
+
+/**
+ * @brief Constant that indicates the maximum lenght of a string.
+ */
+#define MAX_STR_LEN 32
+
+/**
+ * @brief Constant that indicates the maximum lenght of NMEA message field.
+ */
+#define MAX_MSG_LEN 32//19
+/**
+ * @}
+ */
+
+#define MAX_GEOFENCES_NUM 8
+
+/** @addtogroup NMEA_PARSER_TYPES_DEFINITIONS
+ * @{
+ */
+/**
+ * @brief Enumeration structure that containes the types of feature messages
+ */
+typedef enum {
+ GNSS_FEATURE_EN_MSG = 0,
+ GNSS_GEOFENCE_CFG_MSG,
+ GNSS_GEOFENCE_STATUS_MSG,
+ GNSS_GEOFENCE_ALARM_MSG,
+ GNSS_ODO_START_MSG,
+ GNSS_ODO_STOP_MSG,
+ GNSS_DATALOG_CFG_MSG,
+ GNSS_DATALOG_START_MSG,
+ GNSS_DATALOG_STOP_MSG,
+ GNSS_DATALOG_ERASE_MSG
+} ParseFeatureMsg_Typedef;
+
+/**
+ * @brief Enumeration structure that containes the two success states of a parsing process
+ */
+typedef enum {
+ PARSE_SUCC = 0, /**< Success status */
+ PARSE_FAIL = 1 /**< Fail status */
+} ParseStatus_Typedef;
+
+/**
+ * @brief Enumeration structure that containes the tipologies of Gps fixing process got from a NMEA string
+ */
+typedef enum {
+ INVALID = 0, /**< Invalid Fix status */
+ VALID = 1, /**< Valid Fix status */
+ DGPS_FIX = 2, /**< DGPS Fix status */
+ PPS_FIX = 3, /**< PPS Fix status */
+ REAL_TIME = 4, /**< Real Time Fix status */
+ FLOAT_REAL_TIME = 5, /**< Float Real Time Fix status */
+ ESTIMATED = 6, /**< Estimated Fix status */
+ MANUAL_MODE = 7, /**< Manual Mode Fix status */
+ SIMULATION_MODE = 8 /**< Simulation Mode Fix status */
+} GPS_ValidTypedef;
+
+/**
+ * @brief Data structure that contains the coordinates informations
+ */
+typedef struct Coords {
+ double lat; /**< Latitude */
+ double lon; /**< Longitude */
+ float alt; /**< Altitude */
+ uint8_t ns; /**< Nord / Sud latitude type */
+ uint8_t ew; /**< East / West longitude type */
+ uint8_t mis; /**< Altitude unit misure */
+} Coords;
+
+/**
+ * @brief Data structure that contains the Gps geoids informations
+ */
+typedef struct Geoid_Info {
+ int height; /**< Geoid height */
+ uint8_t mis; /**< Geoid height misure unit */
+} Geoid_Info;
+
+/**
+ * @brief Data structure that contains the UTC informations
+ */
+typedef struct UTC_Info {
+ int utc; /**< UTC Info */
+ int hh; /**< Hours */
+ int mm; /**< Minutes */
+ int ss; /**< Seconds */
+} UTC_Info;
+
+/**
+ * @brief Data structure that contains the UTC informations
+ */
+typedef struct GSV_SAT_Info {
+ int prn; /**< PRN */
+ int elev; /**< Elevation of satellite in degree, 0 ... 90 */
+ int azim; /**< Azimuth of satellite in degree, ref. "North, " 0 ... 359 */
+ int cn0; /**< Carrier to noise ratio for satellite in dB, 0 ... 99 */
+} GSV_SAT_Info;
+
+/**
+ * @brief Data structure that contains all of the informations about the GPS position
+ */
+typedef struct GPGGA_Infos {
+ UTC_Info utc; /**< UTC Time */
+ Coords xyz; /**< Coords data member */
+ float acc; /**< GPS Accuracy */
+ int sats; /**< Number of satellities acquired */
+ GPS_ValidTypedef valid; /**< GPS Signal fix quality */
+ Geoid_Info geoid; /**< Geoids data info member */
+ int update; /**< Update time from the last acquired GPS Info */
+ int checksum; /**< Checksum of the message bytes */
+} GPGGA_Infos;
+
+/**
+ * @brief Data structure that contains all of the informations about the fix data for single or
+ * combined satellite navigation system.
+ */
+typedef struct GNS_Infos {
+ char constellation[MAX_STR_LEN]; /**< Constellation enabled: GPGNS (GPS), GLGNS (GLONASS), GAGNS (GALILEO), BDGNS (BEIDOU), QZGNS (QZSS), GNGNS (more than one) */
+ UTC_Info utc; /**< UTC Time */
+ Coords xyz; /**< Coords data member */
+ char gps_mode; /**< N = NO Fix, A = Autonomous, D = Differential GPS, E = Estimated (dead reckoning mode) */
+ char glonass_mode; /**< N = NO Fix, A = Autonomous, D = Differential Glonass, E = Estimated (dead reckoning mode) */
+ int sats; /**< Number of satellities acquired */
+ float hdop; /**< Horizontal Dilution of Precision, max: 99.0 */
+ float geo_sep; /**< Geoidal separation, meter */
+ char dgnss_age; /**< Not supported */
+ char dgnss_ref; /**< Not supported */
+ int checksum; /**< Checksum of the message bytes */
+} GNS_Infos;
+
+/**
+ * @brief Data structure that contains all of the GPS Pseudorange Noise Statistics.
+ */
+typedef struct GPGST_Infos {
+ UTC_Info utc; /**< UTC Time */
+ float EHPE; /**< Equivalent Horizontal Position Error */
+ float semi_major_dev; /**< Standard deviation (meters) of semi-major axis of error ellipse */
+ float semi_minor_dev; /**< Standard deviation (meters) of semi-minor axis of error ellipse */
+ float semi_major_angle; /**< Orientation of semi-major axis of error ellipse (true north degrees) */
+ float lat_err_dev; /**< Standard deviation (meters) of latitude error */
+ float lon_err_dev; /**< Standard deviation (meters) of longitude error */
+ float alt_err_dev; /**< Standard deviation (meters) of altitude error */
+ int checksum; /**< Checksum of the message bytes */
+} GPGST_Infos;
+
+/**
+ * @brief Data structure that contains all the Recommended Minimum Specific GPS/Transit data.
+ */
+typedef struct GPRMC_Infos {
+ UTC_Info utc; /**< UTC Time */
+ char status; /**< “A” = valid, “V” = Warning */
+ Coords xyz; /**< Coords data member */
+ float speed; /**< Speed over ground in knots */
+ float trackgood; /**< Course made good */
+ int date; /**< Date of Fix */
+ float mag_var; /**< Magnetic Variation */
+ char mag_var_dir; /**< Magnetic Variation Direction */
+ int checksum; /**< Checksum of the message bytes */
+} GPRMC_Infos;
+
+/**
+ * @brief Data structure that contains all of the informations about the GSA satellites
+ */
+typedef struct GSA_Infos {
+ char constellation[MAX_STR_LEN]; /**< Constellation enabled: GPGSA (GPS), GLGSA (GLONASS), GAGSA (GALILEO), BDGSA (BEIDOU), GNGSA (more than one) */
+ char operating_mode; /**< Operating Mode: 'M' = Manual, 'A' = Auto (2D/3D) */
+ int current_mode; /**< Current Mode: 1. no fix available, 2. 2D, 3. 3D */
+ int sat_prn[MAX_SAT_NUM]; /**< Satellites list used in position fix (max N 12) */
+ float pdop; /**< Position Dilution of Precision, max: 99.0 */
+ float hdop; /**< Horizontal Dilution of Precision, max: 99.0 */
+ float vdop; /**< Vertical Dilution of Precision, max: 99.0 */
+ int checksum; /**< Checksum of the message bytes */
+} GSA_Infos;
+
+/**
+ * @brief Data structure that contains all of the informations about the GSV satellites
+ */
+typedef struct GSV_Infos {
+ char constellation[MAX_STR_LEN]; /**< Constellation enabled: GPGSV (GPS), GLGSV (GLONASS), GAGSV (GALILEO), BDGSV (BEIDOU), QZGSV (QZSS), GNGSV (more than one) */
+ int amount; /**< Total amount of GSV messages, max. 3 */
+ int number; /**< Continued GSV number of this message */
+ int tot_sats; /**< Total Number of Satellites in view, max. 12 */
+ GSV_SAT_Info gsv_sat_i[MAX_SAT_NUM]; /**< Satellite info */
+ int checksum; /**< Checksum of the message bytes */
+} GSV_Infos;
+
+/**
+ * @brief Data structure that contains timestamp
+ */
+typedef struct Timestamp_Info {
+ int hh; /**< Hours */
+ int mm; /**< Minutes */
+ int ss; /**< Seconds */
+ int year; /**< Year */
+ int month; /**< Month */
+ int day; /**< Day */
+} Timestamp_Info;
+
+/**
+ * @brief Data structure that contains all of the information about Geofence
+ */
+typedef struct Geofence_Infos {
+ uint8_t op; /**< Geofence type message (configuration/status) */
+ uint8_t result; /**< Geofence cfg/request result (OK/ERROR) */
+ int idAlarm; /**< Id of the circle raising the alarm */
+ Timestamp_Info timestamp;
+ int status[MAX_GEOFENCES_NUM];
+} Geofence_Infos;
+
+/**
+ * @brief Data structure that contains all of the information about Ododmeter
+ */
+typedef struct Odometer_Infos {
+ uint8_t op; /**< Odometer type message (configuration/status) */
+ uint8_t result; /**< Odometer cfg/request result (OK/ERROR) */
+} Odometer_Infos;
+
+/**
+ * @brief Data structure that contains all of the information about Datalog
+ */
+typedef struct Datalog_Infos {
+ uint8_t op; /**< Datalog type message (configuration/status) */
+ uint8_t result; /**< Datalog cfg/request result (OK/ERROR) */
+} Datalog_Infos;
+
+/**
+ * @brief Ack from Teseo
+ */
+typedef uint8_t Ack_Info;
+
+/**
+ * @}
+ */
+
+/** @addtogroup NMEA_PARSER_PUBLIC_FUNCTIONS
+ * @{
+ */
+ParseStatus_Typedef parse_gpgga (GPGGA_Infos *gpgga_data, uint8_t *NMEA);
+ParseStatus_Typedef parse_gnsmsg (GNS_Infos *gns_data, uint8_t *NMEA);
+ParseStatus_Typedef parse_gpgst (GPGST_Infos *gpgst_data, uint8_t *NMEA);
+ParseStatus_Typedef parse_gprmc (GPRMC_Infos *gprmc_data, uint8_t *NMEA);
+ParseStatus_Typedef parse_gsamsg (GSA_Infos *gsa_data, uint8_t *NMEA);
+ParseStatus_Typedef parse_gsvmsg (GSV_Infos *gsv_data, uint8_t *NMEA);
+void copy_data (GPGGA_Infos *, GPGGA_Infos);
+
+ParseStatus_Typedef parse_pstmgeofence(Geofence_Infos *geofence_data, uint8_t *NMEA);
+ParseStatus_Typedef parse_pstmodo(Odometer_Infos *odo_data, uint8_t *NMEA);
+ParseStatus_Typedef parse_pstmdatalog(Datalog_Infos *datalog_data, uint8_t *NMEA);
+ParseStatus_Typedef parse_pstmsgl(Ack_Info *ack, uint8_t *NMEA);
+ParseStatus_Typedef parse_pstmsavepar(Ack_Info *ack, uint8_t *NMEA);
+/**
+ * @}
+ */
+
+/**
+ * @}
+ */
+
+/**
+ * @}
+ */
+
+/**
+ * @}
+ */
+
+/**
+ * @}
+ */
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/Middlewares/NMEAUtils.c Fri Nov 09 17:06:11 2018 +0000
@@ -0,0 +1,123 @@
+/**
+*******************************************************************************
+* @file NMEA_utils.c
+* @author AST / Central Lab
+* @version V1.0.0
+* @date 18-May-2017
+* @brief NMEA utilities
+*
+*******************************************************************************
+* @attention
+*
+* <h2><center>© COPYRIGHT(c) 2017 STMicroelectronics</center></h2>
+*
+* Licensed under MCD-ST Liberty SW License Agreement V2, (the "License");
+* You may not use this file except in compliance with the License.
+* You may obtain a copy of the License at:
+*
+* http://www.st.com/software_license_agreement_liberty_v2
+*
+* Redistribution and use in source and binary forms, with or without modification,
+* are permitted provided that the following conditions are met:
+* 1. Redistributions of source code must retain the above copyright notice,
+* this list of conditions and the following disclaimer.
+* 2. Redistributions in binary form must reproduce the above copyright notice,
+* this list of conditions and the following disclaimer in the documentation
+* and/or other materials provided with the distribution.
+* 3. Neither the name of STMicroelectronics nor the names of its contributors
+* may be used to endorse or promote products derived from this software
+* without specific prior written permission.
+*
+* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
+* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*
+********************************************************************************
+*/
+
+#include "string.h"
+#include "NMEAUtils.h"
+
+/** @defgroup Middlewares
+ * @brief Contains all platform independent modules (eg. NMEA Sentence Parser, ...).
+ * @{
+ */
+
+/** @defgroup ST
+ * @{
+ */
+
+/** @defgroup LIB_NMEA
+ * @{
+ */
+
+/** @defgroup NMEA_UTILS
+ * @{
+ */
+
+/** @addtogroup NMEA_UTILS_PUBLIC_FUNCTIONS
+ * @{
+ */
+/**
+ * @brief Scans a string with UTC info and fills all fields of a
+ * UTC_Info struct
+ * @param utc_str NMEA UTC string
+ * @param utc The UTC_Info struct to fill
+ * @retval None
+ */
+void scan_utc (char* utc_str, UTC_Info* utc) {
+
+ sscanf(utc_str, "%d", &utc->utc);
+
+ utc->hh = (utc->utc / 10000);
+ utc->mm = (utc->utc - (utc->hh * 10000)) / 100;
+ utc->ss = utc->utc - ((utc->hh * 10000) + (utc->mm * 100));
+
+ return;
+}
+
+/**
+ * @brief Scans a bidimensional array with longitude and latitude infos and
+ * fills the relative fields of a Coords struct
+ * @param xy_str NMEA string with latitude and longitude infos
+ * @param str_offset NMEA string with latitude and longitude infos
+ * @param utc The Coords struct to fill
+ * @retval None
+ */
+void scan_xy (char* xy_str, uint8_t str_offset, Coords* xy)
+{
+ //printf("NMEA (xy_str): %s\n\r", xy_str);
+ sscanf(xy_str, "%lf", &xy->lat);
+ sscanf(xy_str+str_offset, "%c", &xy->ns);
+ sscanf(xy_str+(2*str_offset), "%lf", &xy->lon);
+ sscanf(xy_str+(3*str_offset), "%c", &xy->ew);
+
+ return;
+}
+
+/**
+* @}
+*/
+
+/**
+* @}
+*/
+
+/**
+* @}
+*/
+
+/**
+ * @}
+ */
+
+/**
+* @}
+*/
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/Middlewares/NMEAUtils.h Fri Nov 09 17:06:11 2018 +0000
@@ -0,0 +1,104 @@
+/**
+*******************************************************************************
+* @file NMEAUtils.h
+* @author AST / Central Lab
+* @version V1.0.0
+* @date 19-May-2017
+* @brief NMEA utilities
+*
+*******************************************************************************
+* @attention
+*
+* <h2><center>© COPYRIGHT(c) 2017 STMicroelectronics</center></h2>
+*
+* Licensed under MCD-ST Liberty SW License Agreement V2, (the "License");
+* You may not use this file except in compliance with the License.
+* You may obtain a copy of the License at:
+*
+* http://www.st.com/software_license_agreement_liberty_v2
+*
+* Redistribution and use in source and binary forms, with or without modification,
+* are permitted provided that the following conditions are met:
+* 1. Redistributions of source code must retain the above copyright notice,
+* this list of conditions and the following disclaimer.
+* 2. Redistributions in binary form must reproduce the above copyright notice,
+* this list of conditions and the following disclaimer in the documentation
+* and/or other materials provided with the distribution.
+* 3. Neither the name of STMicroelectronics nor the names of its contributors
+* may be used to endorse or promote products derived from this software
+* without specific prior written permission.
+*
+* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
+* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*
+********************************************************************************
+*/
+
+/* Define to prevent recursive inclusion -------------------------------------*/
+#ifndef __NMEA_UTILS_H
+#define __NMEA_UTILS_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include <stdio.h>
+#include <stdint.h>
+
+#include "NMEAParser.h"
+
+/** @defgroup Middlewares
+ * @brief Contains all platform independent modules (eg. NMEA Sentence Parser, ...).
+ * @{
+ */
+
+/** @defgroup ST
+ * @{
+ */
+
+/** @defgroup LIB_NMEA
+ * @{
+ */
+
+/** @defgroup NMEA_UTILS
+ * @{
+ */
+
+/** @addtogroup NMEA_UTILS_PUBLIC_FUNCTIONS
+ * @{
+ */
+void scan_utc (char* utc_str, UTC_Info* utc);
+void scan_xy (char* xy_str, uint8_t offset, Coords* xyz);
+/**
+ * @}
+ */
+
+/**
+ * @}
+ */
+
+/**
+ * @}
+ */
+
+/**
+ * @}
+ */
+
+/**
+ * @}
+ */
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/README.md Fri Nov 09 17:06:11 2018 +0000 @@ -0,0 +1,55 @@ +# Teseo-LIV3F + +GPSProvider wrapper library for STMicroelectronics' X-NUCLEO-GNSS1A1 Expansion Board. + +## Overview + +This is the Github repo including drivers for ST’s Teseo-LIV3F Global Navigation Satellite System (GNSS) device and middleware for the NMEA protocol support. +This firmware package implements the port of the [GPSProvider](https://github.com/apalmieriGH/GPSProvider/) to STMicroelectronics' X-NUCLEO-GNSS1A1 GNSS Expansion Board. + +The key features of the package are: +* Complete software to build applications using Teseo-LIV3F GNSS device +* Middleware for the NMEA protocol support + +Furthermore the package provides the following advanced features: +* Geofencing - allows the Teseo-LIV3F receiver to raise a NMEA message when the resolved GNSS position is close to or entering or exiting from a specific circle +* Odometer - provides information on the traveled distance using only the resolved GNSS position +* Data Logging - allows the Teseo-LIV3F receiver to save locally on the flash the resolved GNSS position to be retrieved on demand from the Host + +## Hardware description + +The X-NUCLEO-GNSS1A1 is a Global Navigation Satellite System Expansion Board usable with the STM32 Nucleo system and other Arduino compatible platforms. It is designed around the STMicroelectronics Teseo-LIV3F GNSS receiver IC working on multiple constellations (GPS/Galileo/Glonass/BeiDou/QZSS). + +The Teseo-LIV3F module is designed for top performance in a minimal space. Within its 10x10mm compact size, Teseo-LIV3F offers superior accuracy thanks to the on board 26MHz Temperature Compensated Crystal Oscillator (TCXO) and a reduced Time To First Fix (TTFF) relying to its dedicated 32KHz Real Time Clock (RTC) oscillator. + +The X-NUCLEO-GNSS1A1, hosting the Teseo-LIV3F, is compatible with Arduino UNO R3 connector layout and interfaces with the MCU via the UART channel. +To connect by serial port the GNSS receiver and the host the following parameters must be used: +* 8 data bits +* No parity +* 1 stop bit +* 9600 bauds + +A GPS/GLONASS/Beidou antenna, distributed along with the X-NUCLEO-GNSS1A1 Expansion Board, must be connected to the antenna connector present on the Expansion Board. +For the X-NUCLEO-GNSS1A1 proper operations, the following jumper settings must be used: +* J2 open +* J3 closed +* J4 closed +* J5 open +* J6 closed +* J7 closed +* J8 open +* J9 closed +* J10 open +* J11 closed +* J12 closed +* J13 closed +* J14 closed +* J15 closed + +## Tested platforms + +This firmware has been tested on STM32 NUCLEO-F401RE + +## Example Application + +To run GNSS example applications using X-NUCLEO-GNSS1A1 Expansion Board based on mbed OS and built with [mbed-cli](https://github.com/ARMmbed/mbed-cli/), please refer to [TeseoLocation](https://github.com/apalmieriGH/TeseoLocation/) page. \ No newline at end of file
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/TeseoConfig.h Fri Nov 09 17:06:11 2018 +0000 @@ -0,0 +1,56 @@ +/** + ****************************************************************************** + * @file teseo_config.h + * @author AST / Central Labs + * @version V1.0 + * @date May, 2017 + * @brief Configuration header file for the X_NUCLEO_PLC01A1 expansion board. + ****************************************************************************** + * @attention + * + * <h2><center>© COPYRIGHT(c) 2017 STMicroelectronics</center></h2> + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. Neither the name of STMicroelectronics nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************** + */ + +/* Define to prevent recursive inclusion -------------------------------------*/ + +#ifndef __TESEO_CONFIG_H__ +#define __TESEO_CONFIG_H__ + +/* I2C. */ + +/* TESEO PINs. */ +#define TESEO_PIN_RESET D7 +#define TESEO_PIN_WAKEUP D13 +#define TESEO_PIN_PPS NC//D6 + +/* UART */ +#define TESEO_PIN_RX D8 +#define TESEO_PIN_TX D2 + +#define LOC_LED2 D6 + +#endif /* __TESEO_CONFIG_H__ */ \ No newline at end of file
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/createTeseoGNSS.cpp Fri Nov 09 17:06:11 2018 +0000
@@ -0,0 +1,713 @@
+/**
+ ******************************************************************************
+ * @file createTeseoGNSS.cpp
+ * @author AST/CL
+ * @version V1.1.0
+ * @date May, 2017
+ * @brief .
+ ******************************************************************************
+ * @attention
+ *
+ * <h2><center>© COPYRIGHT(c) 2017 STMicroelectronics</center></h2>
+ *
+ * Redistribution and use in source and binary forms, with or without modification,
+ * are permitted provided that the following conditions are met:
+ * 1. Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ * 3. Neither the name of STMicroelectronics nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ ******************************************************************************
+ */
+
+#include "mbed.h"
+#include "Teseo.h"
+#include "GPSProviderImplBase.h"
+
+#include "TeseoConfig.h"
+
+static void _AppOutputCallback(uint32_t msgId, uint32_t msgType, tTeseoData *pData);
+static void _AppEventCallback(eTeseoLocEventType event, uint32_t data);
+static char msg[256];
+
+static char *geofenceCirclePosition[] = {
+ "Unknown",
+ "Outside",
+ "Boundary",
+ "Inside"
+};
+
+extern Serial serialDebug;
+#define TESEO_APP_LOG_INFO(...) serialDebug.printf(__VA_ARGS__)
+
+GPSProviderImplBase *
+createGPSProviderInstance(void)
+{
+ static Teseo gnss(TESEO_PIN_RESET,
+ TESEO_PIN_WAKEUP,
+ TESEO_PIN_PPS,
+ TESEO_PIN_TX,
+ TESEO_PIN_RX,
+ &serialDebug);
+
+ /* Register output callback and event callback functions */
+ gnss.TeseoLocRegOutput(_AppOutputCallback, _AppEventCallback);
+
+ return &gnss;
+}
+
+/**
+ * @brief This function prints on the console the info about Fix data for single or combined satellite navigation system
+ * @param pData
+ * @retval None
+ */
+static void
+GetGNSMsgInfos(tTeseoData *pData)
+{
+// char msg[256];
+
+ TESEO_APP_LOG_INFO("\r\n");
+
+ sprintf(msg, "Constellation:\t\t[ %s ]\t",
+ pData->gns_data.constellation);
+ TESEO_APP_LOG_INFO(msg);
+
+ if (strcmp(pData->gns_data.constellation, "$GPGSV") == 0) {
+ TESEO_APP_LOG_INFO("-- only GPS constellation is enabled\n\r");
+ }
+ else if (strcmp(pData->gns_data.constellation, "$GLGSV") == 0) {
+ TESEO_APP_LOG_INFO("-- only GLONASS constellation is enabled\n\r");
+ }
+ else if (strcmp(pData->gns_data.constellation, "$GAGSV") == 0) {
+ TESEO_APP_LOG_INFO("-- only GALILEO constellation is enabled\n\r");
+ }
+ else if (strcmp(pData->gns_data.constellation, "$BDGSV") == 0) {
+ TESEO_APP_LOG_INFO("-- only BEIDOU constellation is enabled\n\r");
+ }
+ else if (strcmp(pData->gns_data.constellation, "$QZGSV") == 0) {
+ TESEO_APP_LOG_INFO("-- only QZSS constellation is enabled\n\r");
+ }
+ else if (strcmp(pData->gns_data.constellation, "$GNGSV") == 0) {
+ TESEO_APP_LOG_INFO("-- message to report all satellites for all enabled constellations\n\r");
+ }
+
+ sprintf(msg, "UTC:\t\t\t[ %02d:%02d:%02d ]\n\r",
+ pData->gns_data.utc.hh,
+ pData->gns_data.utc.mm,
+ pData->gns_data.utc.ss);
+ TESEO_APP_LOG_INFO(msg);
+
+ sprintf(msg,"Latitude:\t\t[ %.0f' %d'' %c ]\n\r",
+ (pData->gns_data.xyz.lat - ((int)pData->gns_data.xyz.lat % 100)) / 100,
+ ((int)pData->gns_data.xyz.lat % 100),
+ pData->gns_data.xyz.ns);
+ TESEO_APP_LOG_INFO(msg);
+
+ sprintf(msg,"Longitude:\t\t[ %.0f' %d'' %c ]\n\r",
+ (pData->gns_data.xyz.lon - ((int)pData->gns_data.xyz.lon % 100)) / 100,
+ ((int)pData->gns_data.xyz.lon % 100),
+ pData->gns_data.xyz.ew);
+ TESEO_APP_LOG_INFO(msg);
+
+ sprintf(msg,"Satellites locked:\t[ %d ]\n\r",
+ pData->gns_data.sats);
+ TESEO_APP_LOG_INFO(msg);
+
+ sprintf(msg,"HDOP:\t\t\t[ %.01f ]\n\r",
+ pData->gns_data.hdop);
+ TESEO_APP_LOG_INFO(msg);
+
+ sprintf(msg,"Altitude:\t\t[ %.01f ]\n\r",
+ pData->gns_data.xyz.alt);
+ TESEO_APP_LOG_INFO(msg);
+
+ sprintf(msg,"Geoid infos:\t\t[ %.01f ]\n\r",
+ pData->gns_data.geo_sep);
+ TESEO_APP_LOG_INFO(msg);
+
+ // sprintf(msg,"ID - Checksum:\t\t[ *%x ]\n\r",
+ // (pData->gns_data.checksum);
+ // TESEO_APP_LOG_INFO(msg);
+
+ TESEO_APP_LOG_INFO("\n\n\r");
+
+ return;
+}
+
+/**
+ * @brief This function prints on the console the info about GPS Pseudorange Noise Statistics
+ * @param pData
+ * @retval None
+ */
+static void
+GetGPGSTInfos(tTeseoData *pData)
+{
+// char msg[256];
+
+ TESEO_APP_LOG_INFO("\r\n");
+
+ sprintf(msg, "UTC:\t\t\t[ %02d:%02d:%02d ]\n\r",
+ pData->gpgst_data.utc.hh,
+ pData->gpgst_data.utc.mm,
+ pData->gpgst_data.utc.ss);
+ TESEO_APP_LOG_INFO(msg);
+
+ sprintf(msg,"EHPE:\t\t[ %.01f ]\n\r",
+ pData->gpgst_data.EHPE);
+ TESEO_APP_LOG_INFO(msg);
+
+ sprintf(msg,"Semi-major Dev:\t\t[ %.01f ]\n\r",
+ pData->gpgst_data.semi_major_dev);
+ TESEO_APP_LOG_INFO(msg);
+
+ sprintf(msg,"Semi-minor Dev:\t\t[ %.01f ]\n\r",
+ pData->gpgst_data.semi_minor_dev);
+ TESEO_APP_LOG_INFO(msg);
+
+ sprintf(msg,"Semi-maior Angle:\t\t[ %.01f ]\n\r",
+ pData->gpgst_data.semi_major_angle);
+ TESEO_APP_LOG_INFO(msg);
+
+ sprintf(msg,"Lat Err Dev:\t\t[ %.01f ]\n\r",
+ pData->gpgst_data.lat_err_dev);
+ TESEO_APP_LOG_INFO(msg);
+
+ sprintf(msg,"Lon Err Dev:\t\t[ %.01f ]\n\r",
+ pData->gpgst_data.lon_err_dev);
+ TESEO_APP_LOG_INFO(msg);
+
+ sprintf(msg,"Alt Err Dev:\t\t[ %.01f ]\n\r",
+ pData->gpgst_data.alt_err_dev);
+ TESEO_APP_LOG_INFO(msg);
+
+// sprintf(msg,"ID - Checksum:\t\t[ *%x ]\n\r",
+// pData->gpgst_data.checksum);
+// TESEO_APP_LOG_INFO(msg);
+
+ TESEO_APP_LOG_INFO("\n\n\r");
+
+ return;
+}
+
+/**
+ * @brief This function prints on the console the info about Recommended Minimum Specific GPS/Transit data got by the most recent reception process
+ * @param pData
+ * @retval None
+ */
+static void
+GetGPRMCInfos(tTeseoData *pData)
+{
+// char msg[256];
+
+ TESEO_APP_LOG_INFO("\r\n");
+
+ sprintf(msg, "UTC:\t\t\t\t[ %02d:%02d:%02d ]\n\r",
+ pData->gprmc_data.utc.hh,
+ pData->gprmc_data.utc.mm,
+ pData->gprmc_data.utc.ss);
+ TESEO_APP_LOG_INFO(msg);
+
+ sprintf(msg,"Status:\t\t\t\t[ %c ]\t\t",
+ pData->gprmc_data.status);
+ TESEO_APP_LOG_INFO(msg);
+ if (pData->gprmc_data.status == 'A') {
+ TESEO_APP_LOG_INFO("-- Valid (reported in 2D and 3D fix conditions)\n\r");
+ }
+ else if (pData->gprmc_data.status == 'V') {
+ TESEO_APP_LOG_INFO("-- Warning (reported in NO FIX conditions)\n\r");
+ }
+ else {
+ TESEO_APP_LOG_INFO("-- Unknown status\n\r");
+ }
+
+ sprintf(msg,"Latitude:\t\t\t[ %.0f' %02d'' %c ]\n\r",
+ ((pData->gprmc_data.xyz.lat - ((int)pData->gprmc_data.xyz.lat % 100))) / 100,
+ ((int)pData->gprmc_data.xyz.lat % 100),
+ pData->gprmc_data.xyz.ns);
+ TESEO_APP_LOG_INFO(msg);
+
+ sprintf(msg,"Longitude:\t\t\t[ %.0f' %02d'' %c ]\n\r",
+ ((pData->gprmc_data.xyz.lon - ((int)pData->gprmc_data.xyz.lon % 100))) / 100,
+ ((int)pData->gprmc_data.xyz.lon % 100),
+ pData->gprmc_data.xyz.ew);
+ TESEO_APP_LOG_INFO(msg);
+
+ sprintf(msg,"Speed over ground (knots):\t[ %.01f ]\n\r",
+ pData->gprmc_data.speed);
+ TESEO_APP_LOG_INFO(msg);
+
+ sprintf(msg,"Trackgood:\t\t\t[ %.01f ]\n\r",
+ pData->gprmc_data.trackgood);
+ TESEO_APP_LOG_INFO(msg);
+
+ sprintf(msg,"Date (ddmmyy):\t\t\t[ %d ]\n\r",
+ pData->gprmc_data.date);
+ TESEO_APP_LOG_INFO(msg);
+
+ sprintf(msg,"Magnetic Variation:\t\t[ %.01f ]\n\r",
+ pData->gprmc_data.mag_var);
+ TESEO_APP_LOG_INFO(msg);
+
+ if (pData->gprmc_data.mag_var_dir != 'E' &&
+ pData->gprmc_data.mag_var_dir != 'W') {
+ sprintf(msg,"Magnetic Var. Direction:\t[ - ]\n\r");
+ }
+ else {
+ sprintf(msg,"Magnetic Var. Direction:\t[ %c ]\n\r",
+ pData->gprmc_data.mag_var_dir);
+ }
+ TESEO_APP_LOG_INFO(msg);
+
+// sprintf(msg,"Checksum:\t\t[ *%x ]\n\r",
+// pData->gprmc_data.checksum);
+// TESEO_APP_LOG_INFO(msg);
+
+ TESEO_APP_LOG_INFO("\n\n\r");
+
+ return;
+}
+
+/**
+ * @brief This function prints on the console the info about GNSS satellites got by the most recent reception process
+ * @param pData
+ * @retval None
+ */
+static void
+GetGSAMsgInfos(tTeseoData *pData)
+{
+// char msg[256];
+
+ TESEO_APP_LOG_INFO("\r\n");
+
+ sprintf(msg, "Constellation:\t\t[ %s ]\t",
+ pData->gsa_data.constellation);
+ TESEO_APP_LOG_INFO(msg);
+
+ if (strcmp(pData->gsa_data.constellation, "$GPGSA") == 0) {
+ TESEO_APP_LOG_INFO("-- only GPS constellation is enabled\n\r");
+ }
+ else if (strcmp(pData->gsa_data.constellation, "$GLGSA") == 0) {
+ TESEO_APP_LOG_INFO("-- only GLONASS constellation is enabled\n\r");
+ }
+ else if (strcmp(pData->gsa_data.constellation, "$GAGSA") == 0) {
+ TESEO_APP_LOG_INFO("-- only GALILEO constellation is enabled\n\r");
+ }
+ else if (strcmp(pData->gsa_data.constellation, "$BDGSA") == 0) {
+ TESEO_APP_LOG_INFO("-- only BEIDOU constellation is enabled\n\r");
+ }
+ else if (strcmp(pData->gsa_data.constellation, "$GNGSA") == 0) {
+ TESEO_APP_LOG_INFO("-- more than one constellation is enabled\n\r");
+ }
+
+ sprintf(msg, "Operating Mode:\t\t[ %c ]\t\t",
+ pData->gsa_data.operating_mode);
+ TESEO_APP_LOG_INFO(msg);
+ if (pData->gsa_data.operating_mode == 'A') {
+ TESEO_APP_LOG_INFO("-- Auto (2D/3D)\n\r");
+ }
+ else if (pData->gsa_data.operating_mode == 'M') {
+ TESEO_APP_LOG_INFO("-- Manual\n\r");
+ }
+
+ sprintf(msg,"Current Mode:\t\t[ %d ]\t\t",
+ pData->gsa_data.current_mode);
+ TESEO_APP_LOG_INFO(msg);
+ if (pData->gsa_data.current_mode == 1) {
+ TESEO_APP_LOG_INFO("-- no fix available\n\r");
+ }
+ else if (pData->gsa_data.current_mode == 2) {
+ TESEO_APP_LOG_INFO("-- 2D\n\r");
+ }
+ else if (pData->gsa_data.current_mode == 3) {
+ TESEO_APP_LOG_INFO("-- 3D\n\r");
+ }
+
+ for (uint8_t i=0; i<12; i++) {
+ sprintf(msg,"SatPRN%02d:\t\t[ %d ]\n\r", i+1,
+ pData->gsa_data.sat_prn[i]);
+ TESEO_APP_LOG_INFO(msg);
+ }
+
+ sprintf(msg,"PDOP:\t\t\t[ %.01f ]\n\r",
+ pData->gsa_data.pdop);
+ TESEO_APP_LOG_INFO(msg);
+
+ sprintf(msg,"HDOP:\t\t\t[ %.01f ]\n\r",
+ pData->gsa_data.hdop);
+ TESEO_APP_LOG_INFO(msg);
+
+ sprintf(msg,"VDOP:\t\t\t[ %.01f ]\n\r",
+ pData->gsa_data.vdop);
+ TESEO_APP_LOG_INFO(msg);
+
+// sprintf(msg,"ID - Checksum:\t\t[ *%x ]\n\r",
+// pData->gsa_data.checksum);
+// TESEO_APP_LOG_INFO(msg);
+
+ TESEO_APP_LOG_INFO("\n\n\r");
+
+}
+
+/**
+ * @brief This function prints on the console the info about GNSS satellites got by the most recent reception process
+ * @param pData
+ * @retval None
+ */
+static void
+GetGSVMsgInfos(tTeseoData *pData)
+{
+ uint8_t i;
+ uint8_t tot_sats = pData->gsv_data.tot_sats;
+// char msg[256];
+
+ char degree_sym = 248;
+
+ TESEO_APP_LOG_INFO("\r\n");
+
+ sprintf(msg, "Constellation:\t\t[ %s ]\t",
+ pData->gsv_data.constellation);
+ TESEO_APP_LOG_INFO(msg);
+
+ if (strcmp(pData->gsv_data.constellation, "$GPGSV") == 0) {
+ TESEO_APP_LOG_INFO("-- message to report all GPS satellites\n\r");
+ }
+ else if (strcmp(pData->gsv_data.constellation, "$GLGSV") == 0) {
+ TESEO_APP_LOG_INFO("-- message to report all GLONASS satellites\n\r");
+ }
+ else if (strcmp(pData->gsv_data.constellation, "$GAGSV") == 0) {
+ TESEO_APP_LOG_INFO("-- message to report all GALILEO satellites\n\r");
+ }
+ else if (strcmp(pData->gsv_data.constellation, "$BDGSV") == 0) {
+ TESEO_APP_LOG_INFO("-- message to report all BEIDOU satellites\n\r");
+ }
+ else if (strcmp(pData->gsv_data.constellation, "$QZGSV") == 0) {
+ TESEO_APP_LOG_INFO("-- message to report all QZSS satellites\n\r");
+ }
+ else if (strcmp(pData->gsv_data.constellation, "$GNGSV") == 0) {
+ TESEO_APP_LOG_INFO("-- message to report all satellites for all enabled constellations\n\r");
+ }
+
+ /* debug */
+// sprintf(msg,"Tot Messages:\t\t[ %d ]\n\r",
+// ((tTeseoData *)(handle->pData))->gsv_data.amount);
+// TESEO_APP_LOG_INFO(msg);
+//
+// sprintf(msg,"Message Num:\t\t[ %d ]\n\r",
+// ((tTeseoData *)(handle->pData))->gsv_data.number);
+// TESEO_APP_LOG_INFO(msg);
+
+ sprintf(msg,"Num of Satellites:\t[ %d ]\n\r", tot_sats);
+ TESEO_APP_LOG_INFO(msg);
+
+ TESEO_APP_LOG_INFO("\n\r");
+
+ for (i=0; i<tot_sats; i++) {
+ sprintf(msg,"Sat%02dPRN:\t\t[ %03d ]\n\r", i+1,
+ pData->gsv_data.gsv_sat_i[i].prn);
+ TESEO_APP_LOG_INFO(msg);
+
+ sprintf(msg,"Sat%02dElev (%c):\t\t[ %03d ]\n\r", i+1, degree_sym,
+ pData->gsv_data.gsv_sat_i[i].elev);
+ TESEO_APP_LOG_INFO(msg);
+
+ sprintf(msg,"Sat%02dAzim (%c):\t\t[ %03d ]\n\r", i+1, degree_sym,
+ pData->gsv_data.gsv_sat_i[i].azim);
+ TESEO_APP_LOG_INFO(msg);
+
+ sprintf(msg,"Sat%02dCN0 (dB):\t\t[ %03d ]\n\r", i+1,
+ pData->gsv_data.gsv_sat_i[i].cn0);
+ TESEO_APP_LOG_INFO(msg);
+
+ TESEO_APP_LOG_INFO("\n\r");
+ }
+
+ TESEO_APP_LOG_INFO("\r\n");
+
+}
+
+/**
+ * @brief This function prints on the console the info Geofence
+ * @param pData
+ * @retval None
+ */
+static void
+GetGeofenceInfos(tTeseoData *pData)
+{
+// char msg[256];
+
+ TESEO_APP_LOG_INFO("\r\n");
+
+ if(pData->geofence_data.op == GNSS_FEATURE_EN_MSG) {
+ sprintf(msg, "Geofence Enabling:\t\t[ %s ]\t",
+ pData->geofence_data.result ? "ERROR" : "OK");
+ TESEO_APP_LOG_INFO(msg);
+ }
+ if(pData->geofence_data.op == GNSS_GEOFENCE_CFG_MSG) {
+ sprintf(msg, "Geofence Configuration:\t\t[ %s ]\t",
+ pData->geofence_data.result ? "ERROR" : "OK");
+ TESEO_APP_LOG_INFO(msg);
+ }
+ if(pData->geofence_data.op == GNSS_GEOFENCE_STATUS_MSG) {
+ sprintf(msg, "Geofence Status:\t\t[ %s ]\t",
+ pData->geofence_data.result ? "ERROR" : "OK");
+ TESEO_APP_LOG_INFO(msg);
+ if(pData->geofence_data.result == 0) {
+ TESEO_APP_LOG_INFO("\r\n");
+ sprintf(msg, "Time/Date:\t\t%02d:%02d:%02d %02d/%02d/%04d\n",
+ pData->geofence_data.timestamp.hh,
+ pData->geofence_data.timestamp.mm,
+ pData->geofence_data.timestamp.ss,
+ pData->geofence_data.timestamp.day,
+ pData->geofence_data.timestamp.month,
+ pData->geofence_data.timestamp.year);
+ TESEO_APP_LOG_INFO(msg);
+
+ for(uint8_t i = 0; i<MAX_GEOFENCES_NUM; i++) {
+ sprintf(msg, "Position circle[%d]:\t%s\n",
+ i, geofenceCirclePosition[pData->geofence_data.status[i]]);
+ TESEO_APP_LOG_INFO(msg);
+ }
+ }
+ }
+ if(pData->geofence_data.op == GNSS_GEOFENCE_ALARM_MSG) {
+ sprintf(msg, "Geofence Alarm:\t\t[ %s ]\t",
+ pData->geofence_data.result ? "ERROR" : "OK");
+ TESEO_APP_LOG_INFO(msg);
+ if(pData->geofence_data.result == 0) {
+ TESEO_APP_LOG_INFO("\r\n");
+ sprintf(msg, "Time:\t\t%02d:%02d:%02d\n",
+ pData->geofence_data.timestamp.hh,
+ pData->geofence_data.timestamp.mm,
+ pData->geofence_data.timestamp.ss);
+ TESEO_APP_LOG_INFO(msg);
+ int i = pData->geofence_data.idAlarm;
+ sprintf(msg, "Position circle[%d]:\t%s\n",
+ i, geofenceCirclePosition[pData->geofence_data.status[i]]);
+ TESEO_APP_LOG_INFO(msg);
+ }
+ }
+ TESEO_APP_LOG_INFO("\r\n");
+
+}
+
+/**
+ * @brief This function prints on the console the info about Odometer
+ * @param pData
+ * @retval None
+ */
+static void
+GetOdometerInfos(tTeseoData *pData)
+{
+// char msg[256];
+
+ TESEO_APP_LOG_INFO("\r\n");
+
+ if(pData->odo_data.op == GNSS_FEATURE_EN_MSG) {
+ sprintf(msg, "Odometer Enabling:\t\t[ %s ]\t",
+ pData->odo_data.result ? "ERROR" : "OK");
+ TESEO_APP_LOG_INFO(msg);
+ }
+ if((pData->odo_data.op == GNSS_ODO_START_MSG) ||
+ (pData->odo_data.op == GNSS_ODO_STOP_MSG)) {
+ sprintf(msg, "Odometer Operation:\t\t[ %s ]\t",
+ pData->odo_data.result ? "ERROR" : "OK");
+ TESEO_APP_LOG_INFO(msg);
+ }
+ TESEO_APP_LOG_INFO("\r\n");
+
+}
+
+/**
+ * @brief This function prints on the console the info about Datalog
+ * @param pData
+ * @retval None
+ */
+static void
+GetDatalogInfos(tTeseoData *pData)
+{
+// char msg[256];
+
+ TESEO_APP_LOG_INFO("\r\n");
+
+ if(pData->datalog_data.op == GNSS_FEATURE_EN_MSG) {
+ sprintf(msg, "Datalog Enabling:\t\t[ %s ]\t",
+ pData->datalog_data.result ? "ERROR" : "OK");
+ TESEO_APP_LOG_INFO(msg);
+ }
+ if(pData->datalog_data.op == GNSS_DATALOG_CFG_MSG) {
+ sprintf(msg, "Datalog Configuring:\t\t[ %s ]\t",
+ pData->datalog_data.result ? "ERROR" : "OK");
+ TESEO_APP_LOG_INFO(msg);
+ }
+ if(pData->datalog_data.op == GNSS_DATALOG_START_MSG) {
+ sprintf(msg, "Datalog Start:\t\t[ %s ]\t",
+ pData->datalog_data.result ? "ERROR" : "OK");
+ TESEO_APP_LOG_INFO(msg);
+ }
+ if(pData->datalog_data.op == GNSS_DATALOG_STOP_MSG) {
+ sprintf(msg, "Datalog Stop:\t\t[ %s ]\t",
+ pData->datalog_data.result ? "ERROR" : "OK");
+ TESEO_APP_LOG_INFO(msg);
+ }
+ if(pData->datalog_data.op == GNSS_DATALOG_ERASE_MSG) {
+ sprintf(msg, "Datalog Erase:\t\t[ %s ]\t",
+ pData->datalog_data.result ? "ERROR" : "OK");
+ TESEO_APP_LOG_INFO(msg);
+ }
+ TESEO_APP_LOG_INFO("\r\n");
+
+}
+
+/**
+ * @brief This function prints on the console the ack about Message List cfg
+ * @param pData
+ * @retval None
+ */
+static void
+GetMsgListAck(tTeseoData *pData)
+{
+// char msg[256];
+
+ TESEO_APP_LOG_INFO("\r\n");
+
+ sprintf(msg, "Msg List config:\t\t[ %s ]\t",
+ pData->ack ? "ERROR" : "OK");
+ TESEO_APP_LOG_INFO(msg);
+
+ TESEO_APP_LOG_INFO("\r\n");
+}
+
+/**
+ * @brief This function prints on the console the ack about Message List cfg
+ * @param pData
+ * @retval None
+ */
+static void
+GetAck(tTeseoData *pData)
+{
+// char msg[256];
+
+ TESEO_APP_LOG_INFO("\r\n");
+
+ sprintf(msg, "Params configuration:\t\t[ %s ]\t",
+ pData->ack ? "ERROR" : "OK");
+ TESEO_APP_LOG_INFO(msg);
+
+ TESEO_APP_LOG_INFO("\r\n");
+}
+
+void
+_AppOutputCallback(uint32_t msgId, uint32_t msgType, tTeseoData *pData)
+{
+ switch (msgId) {
+ case LOC_OUTPUT_LOCATION: {
+ // Output last location
+ TESEO_APP_LOG_INFO("Loc: lat=%lf, lon=%lf, alt=%f\r\n", pData->gpgga_data.xyz.lat, pData->gpgga_data.xyz.lon, pData->gpgga_data.xyz.alt);
+ break;
+ }
+ case LOC_OUTPUT_NMEA: {
+ //return;
+ Teseo::eMsg msg = (Teseo::eMsg)msgType;
+ switch(msg) {
+ case Teseo::GNS:
+ // GET Fix data for single or combined Satellite navigation system
+ GetGNSMsgInfos(pData);
+ break;
+
+ case Teseo::GPGST:
+ // GET GPS Pseudorange Noise Statistics
+ GetGPGSTInfos(pData);
+ break;
+
+ case Teseo::GPRMC:
+ // GET Recommended Minimum Specific GPS/Transit data
+ GetGPRMCInfos(pData);
+ break;
+
+ case Teseo::GSA:
+ // GET GPS DOP and Active Satellites
+ GetGSAMsgInfos(pData);
+ break;
+
+ case Teseo::GSV:
+ // GET GPS Satellites in View
+ GetGSVMsgInfos(pData);
+ break;
+
+ default:
+ break;
+ }
+ break;
+ }
+ case LOC_OUTPUT_PSTM: {
+ Teseo::ePSTMsg msg = (Teseo::ePSTMsg)msgType;
+ switch(msg) {
+ case Teseo::PSTMGEOFENCE:
+ // GET Geofence info
+ GetGeofenceInfos(pData);
+ break;
+ case Teseo::PSTMODO:
+ // GET Geofence info
+ GetOdometerInfos(pData);
+ break;
+ case Teseo::PSTMDATALOG:
+ // GET Datalog info
+ GetDatalogInfos(pData);
+ break;
+ case Teseo::PSTMSGL:
+ // GET Message List ack
+ GetMsgListAck(pData);
+ break;
+ case Teseo::PSTMSAVEPAR:
+ // GET SAVE PAR ack
+ GetAck(pData);
+ break;
+ default:
+ break;
+ }
+ break;
+ }
+
+ default:
+ break;
+ }
+}
+
+
+void
+_AppEventCallback(eTeseoLocEventType event, uint32_t data)
+{
+ switch (event) {
+ case TESEO_LOC_EVENT_START_RESULT:
+ if (data != 0) {
+ TESEO_APP_LOG_INFO("start failed.\r\n");
+ } else {
+ TESEO_APP_LOG_INFO("start OK.\r\n");
+ }
+ break;
+ case TESEO_LOC_EVENT_STOP_RESULT:
+ if (data != 0) {
+ TESEO_APP_LOG_INFO("stop failed.\r\n");
+ } else {
+ TESEO_APP_LOG_INFO("stop OK.\r\n");
+ }
+ break;
+ default:
+ break;
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/module.json Fri Nov 09 17:06:11 2018 +0000
@@ -0,0 +1,31 @@
+{
+ "name": "Teseo-LIV3F",
+ "version": "1.0.0",
+ "description": "GPSProvider wrapper library for STMicroelectronics' X-NUCLEO-GNSS1A1 Expansion Board.",
+ "keywords": [
+ "expansion",
+ "board",
+ "x-nucleo",
+ "nucleo",
+ "ST",
+ "STM",
+ "GPS",
+ "GNSS"
+ ],
+ "author": "Andrea Palmieri",
+ "repository": {
+ "url": "https://github.com/apalmieriGH/Teseo-LIV3F.git",
+ "type": "git"
+ },
+ "homepage": "https://github.com/apalmieriGH/Teseo-LIV3F",
+ "licenses": [
+ {
+ "url": "https://spdx.org/licenses/Apache-2.0",
+ "type": "Apache-2.0"
+ }
+ ],
+ "dependencies": {
+ "mbed-drivers": ">=0.11.3",
+ "GPSProvider": "^1.0.0"
+ }
+}