Harry Keane / X_NUCLEO_GNSS1A1

Dependents:   A_TeseoLocationNEW A_TeseoLocation

Files at this revision

API Documentation at this revision

Comitter:
apalmieri
Date:
Fri Nov 09 17:06:11 2018 +0000
Child:
1:02afb9b6f2c6
Commit message:
Initial commit

Changed in this revision

Components/Teseo/Teseo.cpp Show annotated file Show diff for this revision Revisions of this file
Components/Teseo/Teseo.h Show annotated file Show diff for this revision Revisions of this file
Middlewares/NMEAParser.c Show annotated file Show diff for this revision Revisions of this file
Middlewares/NMEAParser.h Show annotated file Show diff for this revision Revisions of this file
Middlewares/NMEAUtils.c Show annotated file Show diff for this revision Revisions of this file
Middlewares/NMEAUtils.h Show annotated file Show diff for this revision Revisions of this file
README.md Show annotated file Show diff for this revision Revisions of this file
TeseoConfig.h Show annotated file Show diff for this revision Revisions of this file
createTeseoGNSS.cpp Show annotated file Show diff for this revision Revisions of this file
module.json Show annotated file Show diff for this revision Revisions of this file
--- /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>&copy; 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>&copy; 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>&copy; 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>&copy; 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>&copy; 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>&copy; 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>&copy; 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>&copy; 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"
+  }
+}