d

Dependencies:   BME280 DOGS102 DS1820 MMA845x_timmeh MTS-Serial libmDot_Australia915Mhz mbed-rtos mbed

Fork of mDot_TTN_OTAA_Node by Thing Innovations

Files at this revision

API Documentation at this revision

Comitter:
1994timmeh
Date:
Wed Jan 11 04:12:39 2017 +0000
Parent:
16:290c505e3851
Commit message:
Thing

Changed in this revision

DOGS102.lib Show annotated file Show diff for this revision Revisions of this file
GPS/GPSPARSER.cpp Show annotated file Show diff for this revision Revisions of this file
GPS/GPSPARSER.h Show annotated file Show diff for this revision Revisions of this file
MMA845x.lib Show annotated file Show diff for this revision Revisions of this file
MTS-Serial.lib Show annotated file Show diff for this revision Revisions of this file
main.cpp Show annotated file Show diff for this revision Revisions of this file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/DOGS102.lib	Wed Jan 11 04:12:39 2017 +0000
@@ -0,0 +1,1 @@
+https://developer.mbed.org/teams/Multi-Hackers/code/DOGS102/#e66152f036d9
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/GPS/GPSPARSER.cpp	Wed Jan 11 04:12:39 2017 +0000
@@ -0,0 +1,483 @@
+/**
+ * @file    NemaParser.cpp
+ * @brief   NEMA String to Packet Parser - NEMA strings to compact packet data
+ * @author  Tim Barr
+ * @version 1.01
+ * @see     http://www.kh-gps.de/nmea.faq
+ * @see     http://www.catb.org/gpsd/NMEA.html
+ *
+ * Copyright (c) 2015
+ *
+ * Licensed under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * 09/16/15 TAB V1.01 Changed report rate of GGA and GSA NEMA sentences
+ * 09/22/15 TAB V1.02 Fixed status value for no GPS detected. Increased report rate
+ *              of GSV, GGA, and GSA NEMA Sentences
+ *
+ * TODO: Add speed, compass direction, error (DOP) data. Make init more generic
+ */
+
+#include "GPSPARSER.h"
+
+using namespace mts;
+
+GPSPARSER::GPSPARSER(MTSSerial *uart):_getSentenceThread(&GPSPARSER::startSentenceThread,this),
+      _led_state(0),
+      _tick_running(false)
+{
+    _gps_uart = uart;
+    _gps_uart->baud(9600);    //set GPS baud rate here
+
+    _gps_latitude.degrees = 0;
+    _gps_longitude.degrees = 0;
+    _timestamp.tm_sec = 0;
+    _timestamp.tm_min = 0;
+    _timestamp.tm_hour = 0;
+    _timestamp.tm_mday = 0;
+    _timestamp.tm_mon = 0;
+    _timestamp.tm_year = 0;
+    _timestamp.tm_wday = 0;
+    _timestamp.tm_yday = 0;
+    _timestamp.tm_isdst = -1; // time is UTC so no Daylight savings time
+
+    _gps_status = false;
+    _fix_status = 1;
+    _num_satellites =0;
+    _gps_detected = false;
+
+    return;
+}
+
+GPSPARSER::~GPSPARSER(void)
+{
+    if (_gps_detected)
+        _getSentenceThread.terminate();
+}
+
+void GPSPARSER::startSentenceThread(void const *p)
+{
+    GPSPARSER *instance = (GPSPARSER*)p;
+    instance->readNemaSentence();
+}
+
+int GPSPARSER::readNemaSentence (void) {
+//    logInfo("===== READING GPS ======\n\r");
+    // this code is specific to the Skytraq Venus GPS chip. This code could be re-written to detect another type of
+    // GPS device. Maybe read serial port for a specific time and detect $GP from NEMA string
+
+    // Sets Skytraq Venus GPS to output GGA,GSA,GSV every 10 seconds, and RMC every second, no ZDA,GLL,VTG
+    // setup string for GPS                       GGA  GSA  GSV  GLL  RMC  VTG  ZDA       cksum
+    char init_gps[16] = {0xA0,0xA1,0x00,0x09,0x08,0x0A,0x0A,0x0A,0x00,0x01,0x00,0x00,0x00,0x03,0x0D,0x0A};
+    char chk_char;
+    uint8_t calc_cksum;
+    uint8_t nema_cksum;
+    char nema_id[2];
+    char nema_str[80];
+    char cksum_str[2];
+
+//    _getSentenceThread.signal_wait(START_THREAD);
+//    logInfo("GPS starting\r\n");
+
+    _gps_uart->rxClear();
+    _gps_uart->write(init_gps, sizeof(init_gps));
+    
+    while (! _gps_uart->readable()) {
+//        logInfo("GPS UART NOT READABLE\n\r");
+        osDelay(1000);
+    }
+        
+    do {
+        _gps_uart->read(chk_char);
+    } while ((chk_char != 0xA0) && (!_gps_uart->rxEmpty()));
+    
+    if (chk_char == 0xA0) {
+        _gps_uart->read(chk_char);
+//        logInfo("read char %#X\r\n", chk_char);
+        if (chk_char == 0xA1) {
+            _gps_uart->read(chk_char);
+            //logInfo("read char %#X\r\n", chk_char);
+            _gps_uart->read(chk_char);
+            //logInfo("read char %#X\r\n", chk_char);
+            _gps_uart->read(chk_char);
+            //logInfo("read char %#X\r\n", chk_char);
+            if (chk_char == 0x83) {
+                _gps_detected = true;
+            }
+        }
+    }
+
+//    logInfo("GPS detected %s\r\n", _gps_detected ? "true" : "false");
+
+    if (! _gps_detected) {
+        _fix_status = 0;
+        return;
+    }
+
+        if (_gps_uart->readable() > 80) {
+            do {
+                _gps_uart->read(chk_char);
+//                logInfo("read char %#X\r\n", chk_char);
+            } while ((chk_char != '$') && (!_gps_uart->rxEmpty()));
+
+            if (chk_char == '$') {
+                _gps_uart->read(nema_id,2);
+                if (strpbrk(nema_id,"GP") != NULL) {
+                    uint8_t i = 0;
+                    calc_cksum = 0x17;          // 8 bit XOR of G and P checksum seed
+                    nema_cksum = 0;             // initialize nema string checksum
+                    memset(nema_str,0x00,80);   // clear nema_str array
+                    do {
+                        _gps_uart->read(chk_char);
+                        if ((chk_char != 0x0D) && (chk_char != '*')) {
+                            nema_str[i++] = chk_char;
+                            calc_cksum ^= chk_char;         // 8 bit XOR checksum
+                        }
+                        if (chk_char == '*') {
+                            _gps_uart->read(cksum_str,2);
+                            nema_cksum = (uint8_t)strtoul(cksum_str,NULL,16);
+                        }
+                    } while (( chk_char != 0x0D) && !_gps_uart->rxEmpty());
+                    
+//                    logInfo("STR %s\n", nema_str);
+
+                    if (nema_cksum == calc_cksum) {
+                        if (strncmp (nema_str,"GGA",3) == 0) {
+                            parseGGA(nema_str);
+                        } else if (strncmp (nema_str,"GSA",3) == 0) {
+                            parseGSA(nema_str);
+                        } else if (strncmp (nema_str,"GSV",3) == 0) {
+                            parseGSV(nema_str);
+                        } else if (strncmp (nema_str,"GLL",3) == 0) {
+                            parseGLL(nema_str);
+                        } else if (strncmp (nema_str,"RMC",3) == 0) {
+                            parseRMC(nema_str);
+                        } else if (strncmp (nema_str,"VTG",3) == 0) {
+                            parseVTG(nema_str);
+                        } else if (strncmp (nema_str,"ZDA",3) == 0) {
+                            parseZDA(nema_str);
+                        } else {
+//                            logInfo("Unknown NEMA String Type\r\n");
+                        }
+                        
+                        return 1;
+                    } else {
+//                        logInfo("NEMA String checksum error %x != %x\r\n",nema_cksum,calc_cksum);
+                        return 0;
+                    }
+                }
+            } else
+//                logInfo("RX empty before all data read\r\n");
+                return 0;
+        }
+        return 0;
+
+//        if (_led) {
+//            if (_fix_status >= 2) {
+//                if (_tick_running) {
+//                    _tick.detach();
+//                    _tick_running = false;
+//                }
+////                _led->setPWM(NCP5623B::LED_3, 8);
+//            } else {
+//                if (! _tick_running) {
+//                    _tick.attach(this, &GPSPARSER::blinker, 0.5);
+//                    _tick_running = true;
+//                }
+//            }
+//        }
+
+}
+
+uint8_t GPSPARSER::parseGGA(char *nema_buf)
+{
+    char* token_str;
+    uint8_t ret = 0;
+
+    _mutex.lock();
+
+    token_str = strtok(nema_buf, ",");
+// skip timestamp
+    token_str = strtok(NULL, ",");
+// skip latitude degrees minutes
+    token_str = strtok(NULL, ",");
+    token_str = strtok(NULL, ",");
+// skip longitude degree minutes
+    token_str = strtok(NULL, ",");
+    token_str = strtok(NULL, ",");
+// read fix quality
+    token_str = strtok(NULL, ",");
+    _fix_quality = atoi(token_str);
+// skip number of satellites and horizontal dilution
+    token_str = strtok(NULL, ",");
+    token_str = strtok(NULL, ",");
+// read msl altitude in meters
+    token_str = strtok(NULL, ",");
+    _msl_altitude = atoi(token_str);
+
+    _mutex.unlock();
+
+    return ret;
+}
+
+uint8_t GPSPARSER::parseGSA(char *nema_buf)
+{
+    char* token_str;
+    uint8_t ret = 0;
+
+    _mutex.lock();
+
+    token_str = strtok(nema_buf, ",");
+    token_str = strtok(NULL, ",");
+// read fix status
+    token_str = strtok(NULL, ",");
+    _fix_status = atoi(token_str);
+// read satellite PRNs
+    for (uint8_t i=0; i<12; i++) {
+        token_str = strtok(NULL, ",");
+        _satellite_prn[i] = atoi(token_str);
+    }
+
+    _mutex.unlock();
+
+    return ret;
+}
+
+uint8_t GPSPARSER::parseGSV(char *nema_buf)
+{
+    char* token_str;
+    uint8_t ret = 0;
+
+    _mutex.lock();
+
+    token_str = strtok(nema_buf, ",");
+// skip number of sentences and sentence number for now
+    token_str = strtok(NULL, ",");
+    token_str = strtok(NULL, ",");
+// read Number of satellites
+    token_str = strtok(NULL, ",");
+    _num_satellites = atoi(token_str);
+// add code to read satellite specs if needed
+
+    _mutex.unlock();
+
+    return ret;
+}
+
+uint8_t GPSPARSER::parseRMC(char *nema_buf)
+{
+    char* token_str;
+    char temp_str[6];
+    uint8_t ret = 0;
+
+    _mutex.lock();
+
+    token_str = strtok(nema_buf, ",");
+// read timestamp
+    token_str = strtok(NULL, ",");
+    strncpy(temp_str,token_str,2);
+    _timestamp.tm_hour = atoi(temp_str);
+    memset(temp_str,0x00,6);
+    strncpy(temp_str,token_str+2,2);
+    _timestamp.tm_min = atoi(temp_str);
+    memset(temp_str,0x00,6);
+    strncpy(temp_str,token_str+4,2);
+    _timestamp.tm_sec = atoi(temp_str);
+// set gps_status  true = active
+    token_str = strtok(NULL, ",");
+    memset(temp_str,0x00,6);
+    strncpy(temp_str,token_str,1);
+    if (temp_str[0] == 'A')
+        _gps_status = true;
+    else
+        _gps_status = false;
+// read latitude degrees minutes
+    token_str = strtok(NULL, ".");
+    memset(temp_str,0x00,6);
+    strncpy(temp_str,token_str,2);
+    _gps_latitude.degrees = atoi(temp_str);
+    memset(temp_str,0x00,6);
+    strncpy(temp_str,token_str+2,2);
+    _gps_latitude.minutes = atoi(temp_str);
+// read fractional minutes
+    token_str = strtok(NULL, ",");
+    _gps_latitude.seconds = atoi(token_str);
+// read latitude hemisphere change sign if 'S'
+    token_str = strtok(NULL, ",");
+    if (token_str[0] == 'S')
+        _gps_latitude.degrees *= -1;
+// read longitude degree minutes
+    token_str = strtok(NULL, ".");
+    memset(temp_str,0x00,6);
+    strncpy(temp_str,token_str,3);
+    _gps_longitude.degrees = atoi(temp_str);
+    memset(temp_str,0x00,6);
+    strncpy(temp_str,token_str+3,2);
+    _gps_longitude.minutes = atoi(temp_str);
+// read fractional minutes
+    token_str = strtok(NULL, ",");
+    _gps_longitude.seconds = atoi(token_str);
+// read longitude hemisphere change sign if 'W'
+    token_str = strtok(NULL, ",");
+    if (token_str[0] == 'W')
+        _gps_longitude.degrees *= -1;
+// skip speed and track angle
+    token_str = strtok(NULL, ",");
+    token_str = strtok(NULL, ",");
+// read date
+    token_str = strtok(NULL, ",");
+    memset(temp_str,0x00,6);
+    strncpy(temp_str,token_str,2);
+    _timestamp.tm_mday = atoi(temp_str);
+    memset(temp_str,0x00,6);
+    strncpy(temp_str,token_str+2,2);
+    _timestamp.tm_mon = atoi(temp_str) - 1;
+    memset(temp_str,0x00,6);
+    strncpy(temp_str,token_str+4,2);
+    _timestamp.tm_year = atoi(temp_str) + 100;
+
+    _mutex.unlock();
+
+    return ret;
+}
+
+uint8_t GPSPARSER::parseVTG(char *nema_buf)
+{
+    uint8_t ret = 0;
+    //logInfo("ParseVTG****\r\n");
+    //logInfo(nema_buf);
+    //logInfo("\r\n");
+    return ret;
+}
+
+uint8_t GPSPARSER::parseGLL(char *nema_buf)
+{
+    uint8_t ret = 0;
+    //logInfo("ParseGLL*****\r\n");
+    //logInfo(nema_buf);
+    //logInfo("\r\n");
+    return ret;
+}
+
+uint8_t GPSPARSER::parseZDA(char *nema_buf)
+{
+    uint8_t ret = 0;
+    //logInfo("ParseZDA******\r\n");
+    //logInfo(nema_buf);
+    //logInfo("\r\n");
+    return ret;
+}
+
+bool GPSPARSER::gpsDetected(void)
+{
+    bool detected;
+
+    _mutex.lock();
+    detected =  _gps_detected;
+    _mutex.unlock();
+
+    return detected;
+}
+
+GPSPARSER::longitude GPSPARSER::getLongitude(void)
+{
+    longitude lon;
+
+    _mutex.lock();
+    lon = _gps_longitude;
+    _mutex.unlock();
+
+    return lon;
+}
+
+GPSPARSER::latitude GPSPARSER::getLatitude(void)
+{
+    latitude lat;
+
+    _mutex.lock();
+    lat = _gps_latitude;
+    _mutex.unlock();
+
+    return lat;
+}
+
+struct tm GPSPARSER::getTimestamp(void) {
+    struct tm time;
+
+    _mutex.lock();
+    time = _timestamp;
+    _mutex.unlock();
+
+    return time;
+}
+
+bool GPSPARSER::getLockStatus(void)
+{
+    bool status;
+
+    _mutex.lock();
+    status = _gps_status;
+    _mutex.unlock();
+
+    return status;
+}
+
+uint8_t GPSPARSER::getFixStatus(void)
+{
+    uint8_t fix;
+
+    _mutex.lock();
+    fix = _fix_status;
+    _mutex.unlock();
+
+    return fix;
+}
+
+uint8_t GPSPARSER::getFixQuality(void)
+{
+    uint8_t fix;
+
+    _mutex.lock();
+    fix = _fix_quality;
+    _mutex.unlock();
+
+    return fix;
+}
+
+uint8_t GPSPARSER::getNumSatellites(void)
+{
+    uint8_t sats;
+
+    _mutex.lock();
+    sats = _num_satellites;
+    _mutex.unlock();
+
+    return sats;
+}
+
+int16_t GPSPARSER::getAltitude(void)
+{
+    int16_t alt;
+
+    _mutex.lock();
+    alt = _msl_altitude;
+    _mutex.unlock();
+
+    return alt;
+}
+
+void GPSPARSER::blinker()
+{
+    _led_state = (_led_state == 0) ? 8 : 0;
+//    _led->setPWM(NCP5623B::LED_3, _led_state);
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/GPS/GPSPARSER.h	Wed Jan 11 04:12:39 2017 +0000
@@ -0,0 +1,209 @@
+/**
+ * @file    GpsParser.h
+ * @brief   NEMA String to Packet Parser - NEMA strings to compact packet data
+ * @author  Tim Barr
+ * @version 1.0
+ * @see     http://www.kh-gps.de/nmea.faq
+ * @see     http://www.catb.org/gpsd/NMEA.html
+ * @see     http://www.skytraq.com.tw/products/Venus638LPx_PB_v3.pdf
+ *
+ * Copyright (c) 2015
+ *
+ * Licensed under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+#ifndef GPSPARSER_H
+#define GPSPARSER_H
+
+#include "mbed.h"
+#include "rtos.h"
+#include "MTSSerial.h"
+#include <string>
+#include <vector>
+#include <ctime>
+#include "MTSLog.h"
+#define START_THREAD 1
+
+using namespace mts;
+
+class GPSPARSER
+{
+public:
+
+    /**
+     * @typedef struct latitude
+     * @brief latitude degrees, minutes, seconds structure
+     * range of degrees : 0 to 90 signed (negative degrees is South)
+     * range of minutes : 0 to 60 unsigned
+     * Range of seconds : 0-9999 unsigned or 1/10000 of a minute.
+     * Multiply by 6 and divide or modulus by 1000 to get seconds and fractional seconds
+     */
+    typedef struct{int8_t degrees; uint8_t minutes; uint16_t seconds;} latitude;
+    
+    /**
+     * @typedef struct longitude
+     * @brief longitude degrees, minutes, seconds structure negative degrees is West
+     * range of degrees : 0 to 180 signed (negative degrees is West)
+     * range of minutes : 0 to 60 unsigned
+     * Range of seconds : 0-9999 unsigned or 1/10000 of a minute.
+     * Multiply by 6 and divide or modulus by 1000 to get seconds and fractional seconds
+     */
+    typedef struct{int16_t degrees; uint8_t minutes; uint16_t seconds;} longitude;
+    
+    /**
+     * @typdef satellite_prn
+     * @brief satellite prn list, up to 12 valid
+     */
+    typedef uint8_t satellite_prn[12];
+
+    /** Create the GPSPARSER object
+     *  @param uart - an MTSSerial object
+     *  @param led - an NCP5623B led controller object
+     */ 
+    GPSPARSER(MTSSerial *uart);
+
+    /** destroy the GPSPARSER object
+     */ 
+    ~GPSPARSER(void);
+    
+    /** GPS device detected
+     *  @return boolean whether GPS device detected
+     */
+    bool gpsDetected(void);
+
+    /** get longitude structure
+     *  @return last valid NEMA string longitude data
+     */
+    longitude getLongitude(void);
+
+    /** get latitude structure
+     *  @return last valid NEMA string latitude data
+     */
+    latitude getLatitude(void);
+
+    /** get timestamp structure
+     *  @return last valid NEMA string time and date data
+     *  uses tm struc from ctime standard library
+     */
+    struct tm getTimestamp(void);
+
+    /** get GPS Lock status
+     *  @return boolean of last valid NEMA string lock status data
+     */
+    bool getLockStatus(void);
+
+    /** get GPS Fix status
+     *  @return last valid NEMA Fix status data
+     *  1 = no fix
+     *  2 = 2D fix - latitude, longitude, time only valid
+     *  3 = 3D fix - all data valid
+     */
+    uint8_t getFixStatus(void);
+
+    /** get GPS Fix qualty
+     *  @return last valid NEMA string Fix Quality data
+     *  0 = invalid
+     *  1 = GPS fix (SPS)
+     *  2 = DGPS fix
+     *  3 = PPS fix
+     *  4 = Real Time Kinematic
+     *  5 = Float RTK
+     *  6 = estimated (dead reckoning) (2.3 feature)
+     *  7 = Manual input mode
+     *  8 = Simulation mode
+     */
+    uint8_t getFixQuality(void);
+
+    /** get number of visible satellites
+     *  @return last valid NEMA string number of satellites visible
+     */
+    uint8_t getNumSatellites(void);
+
+    /** get calculated altitude
+     *  @return last valid NEMA string altitude data in meters 
+     */
+    int16_t getAltitude(void);
+    
+    /** Read NEMA sentences from specified serial port and call specific sentence parser
+     */
+    int readNemaSentence (void);
+    
+    char rmc_buf[100];
+
+private:
+
+    std::string _nema_buff;
+    bool _gps_detected;
+    latitude _gps_latitude;
+    longitude _gps_longitude;
+    struct tm _timestamp;
+    bool _gps_status;
+    uint8_t _fix_status;
+    uint8_t _fix_quality;
+    uint8_t _num_satellites;
+    satellite_prn _satellite_prn;
+    int16_t _msl_altitude;
+    
+    MTSSerial *_gps_uart;
+    Thread _getSentenceThread;
+//    NCP5623B* _led;
+    int8_t _led_state;
+    Ticker _tick;
+    bool _tick_running;
+    Mutex _mutex;
+    
+    /** Start sentence parser thread
+     *  
+     */
+    static void startSentenceThread (void const *p);
+
+    /** Parse GGA NEMA sentence
+     *  @return status of parser attempt
+     */
+    uint8_t parseGGA(char *nema_buf);
+
+    /** Parse GSA NEMA sentence
+     *  @return status of parser attempt
+     */
+    uint8_t parseGSA(char *nema_buf);
+
+    /** Parse GSV NEMA sentence
+     *  @return status of parser attempt
+     */
+    uint8_t parseGSV(char *nema_buf);
+
+    /** Parse RMC NEMA sentence
+     *  @return status of parser attempt
+     */
+    uint8_t parseRMC(char *nema_buf);
+
+    /** Parse VTG NEMA sentence
+     *  @return status of parser attempt
+     */
+    uint8_t parseVTG(char *nema_buf);
+
+    /** Parse GLL NEMA sentence
+     *  @return status of parser attempt
+     */
+    uint8_t parseGLL(char *nema_buff);
+
+    /** Parse ZDA NEMA sentence
+     *  @return status of parser attempt
+     */
+    uint8_t parseZDA(char *nema_buff);
+
+    void blinker();
+
+};
+#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/MMA845x.lib	Wed Jan 11 04:12:39 2017 +0000
@@ -0,0 +1,1 @@
+https://developer.mbed.org/users/1994timmeh/code/MMA845x_timmeh/#555f8ba0c959
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/MTS-Serial.lib	Wed Jan 11 04:12:39 2017 +0000
@@ -0,0 +1,1 @@
+http://mbed.org/teams/MultiTech/code/MTS-Serial/#4afbbafcd6b3
--- a/main.cpp	Thu Jan 05 05:55:42 2017 +0000
+++ b/main.cpp	Wed Jan 11 04:12:39 2017 +0000
@@ -11,7 +11,7 @@
  * (You need to use your own device IDs, the ones shown here are examples only)
  *
  *./ttnctl devices register 0080000000000000
- * INFO Generating random AppKey...             
+ * INFO Generating random AppKey...
  * INFO Registered device                        AppKey=000102030405060708090A0B0C0D0E0F DevEUI=0080000000000000
  *
  * or to specify the same AppKey for a new device or to reregister the same device again:
@@ -43,16 +43,36 @@
 #include "MTSText.h"
 #include <string>
 #include <vector>
+#include "MMA845x.h"
+#include "GPSPARSER.h"
+#include "DOGS102.h"
+#include "font_6x8.h"
 
 using namespace mts;
 
 #define MIN(a,b) (((a)<(b))?(a):(b))
 #define MAX(a,b) (((a)>(b))?(a):(b))
 
+#define NUMSAMPLES 1000
+
+
+
+typedef struct {
+    int lat_d;
+    int lat_m;
+    int lat_s;
+    int lng_d;
+    int lng_m;
+    int lng_s;
+    int x;
+    int y;
+    int z;
+} Coordinate;
+
 // AppEUI
-uint8_t AppEUI[8]={0x02, 0x00, 0x00, 0x00, 0x00, 0xEE, 0xFF, 0xC0};
+uint8_t AppEUI[8]= {0x02, 0x00, 0x00, 0x00, 0x00, 0xEE, 0xFF, 0xC0};
 // AppKey
-uint8_t AppKey[16]={0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16};
+uint8_t AppKey[16]= {0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16};
 
 // Some defines for the LoRa configuration
 /*
@@ -74,30 +94,59 @@
  * DR3 - SF7BW125
  * DR4 - SF8BW500
  */
-#define LORA_SF mDot::DR5
+#define LORA_SF mDot::DR4
 #define LORA_ACK 0
-#define LORA_TXPOWER 14
+#define LORA_TXPOWER 20
 
 // Ignoring sub band for EU modules.
 static uint8_t config_frequency_sub_band = 1;
+volatile int stoppls = 0;
 
-// DS18B20 OneWire pin
-// D13 on Dev Board, pin 18 on mDot, Compatible with Oxford Flood Network PCB temperature sensor.
-//#define DATA_PIN     PA_5
-// A1 on Dev Board, pin 19 on mDot
-#define DATA_PIN     PC_13
-
-// Temperature sensor object
-DS1820 probe(DATA_PIN);
-
-// BME280 Temperature/Humidity/Pressure sensor
-//BME280 sensor(I2C_SDA, I2C_SCL);
+SPI lcd_spi(SPI1_MOSI, SPI1_MISO, SPI1_SCK);
+DigitalOut lcd_spi_cs(SPI1_CS, 1);
+DigitalOut lcd_cd(XBEE_ON_SLEEP, 1);
 
 // Serial via USB for debugging only
 Serial pc(USBTX,USBRX);
 
-int main()
+MMA845x_DATA accldata;
+
+void gpsthread(void const *args)
 {
+    while(1) {
+        GPSPARSER *instance = (GPSPARSER*)args;
+        instance->readNemaSentence();
+    }
+}
+
+void acclthread(void const *args) {
+    
+    /* Create global i2c handle */
+    I2C i2chandle = I2C(PC_9, PA_8);
+
+    MMA845x instance = MMA845x(i2chandle, MMA845x::SA0_VSS);
+
+    instance.setCommonParameters(MMA845x::RANGE_8g,MMA845x::RES_MAX,MMA845x::LN_OFF,
+                                   MMA845x::DR_50,MMA845x::OS_NORMAL,MMA845x::HPF_OFF );
+
+    instance.activeMode();
+
+    /* Accelerometer testing code */
+    while(1) {
+        
+        if (!stoppls) {
+            int result = instance.getStatus();
+            if((result & MMA845x::XYZDR) != 0 ) {
+                accldata = instance.getXYZ();
+    
+                logInfo("Accl: %d %d %d\n\r", instance.getXYZ()._x, instance.getXYZ()._y, instance.getXYZ()._z);
+            }
+        }
+        
+    }
+}
+
+int main() {
     int32_t ret;
     mDot* dot;
     std::vector<uint8_t> send_data;
@@ -105,25 +154,29 @@
     std::vector<uint8_t> nwkId;
     std::vector<uint8_t> nwkKey;
 
-    float temperature = 0.0;
-    float humidity = 0.0;
-    float pressure = 0.0;
+    dot = mDot::getInstance();
+    dot->setLogLevel(MTSLog::INFO_LEVEL);
+    logInfo("Starting...\n\r");
 
-    pc.baud(115200);
-    pc.printf("TTN OTAA mDot LoRa Temperature sensor\n\r");
+    GPSPARSER* gps;
+    MTSSerial gps_serial(XBEE_DOUT, XBEE_DIN, 256, 2048);
+    gps = new GPSPARSER(&gps_serial);
+    Thread gpst(gpsthread, gps);
 
-    // get a mDot handle
-    dot = mDot::getInstance();
+    Thread acclt(acclthread);
 
-//    dot->setLogLevel(MTSLog::WARNING_LEVEL);
-    dot->setLogLevel(MTSLog::TRACE_LEVEL);
+    DOGS102* lcd = new DOGS102(lcd_spi, lcd_spi_cs, lcd_cd);
+    
+    DigitalIn button(PA_11);
+    button.mode(PullUp);
 
+#ifdef ENABLE_LORA
     logInfo("Checking Config");
 
     uint8_t *it = AppEUI;
     for (uint8_t i = 0; i<8; i++)
         nwkId.push_back((uint8_t) *it++);
-    
+
     it = AppKey;
     for (uint8_t i = 0; i<16; i++)
         nwkKey.push_back((uint8_t) *it++);
@@ -209,21 +262,21 @@
 
     // Display LoRa parameters
     // Display label and values in different colours, show pretty values not numeric values where applicable
-/*
-    pc.printf("Public Network: %s\r\n", (char*)(dot->getPublicNetwork() ? "Yes" : "No") );
-    pc.printf("Frequency: %s\r\n", (char*)mDot::FrequencyBandStr(dot->getFrequencyBand()).c_str() );
-    pc.printf("Sub Band: %s\r\n", (char*)mDot::FrequencySubBandStr(dot->getFrequencySubBand()).c_str() );
-    pc.printf("Join Mode: %s\r\n", (char*)mDot::JoinModeStr(dot->getJoinMode()).c_str() );
-    pc.printf("Join Retries: %d\r\n", dot->getJoinRetries() );
-    pc.printf("Join Byte Order: %s\r\n", (char*)(dot->getJoinByteOrder() == 0 ? "LSB" : "MSB") );
-    pc.printf("Link Check Count: %d\r\n", dot->getLinkCheckCount() );
-    pc.printf("Link Check Thold: %d\r\n", dot->getLinkCheckThreshold() );
-    pc.printf("Tx Data Rate: %s\r\n", (char*)mDot::DataRateStr(dot->getTxDataRate()).c_str() );
-    pc.printf("Tx Power: %d\r\n", dot->getTxPower() );
-    pc.printf("TxWait: %s, ", (dot->getTxWait() ? "Y" : "N" ));
-    pc.printf("CRC: %s, ", (dot->getCrc() ? "Y" : "N") );
-    pc.printf("Ack: %s\r\n", (dot->getAck() ? "Y" : "N")  );
-*/
+    /*
+        pc.printf("Public Network: %s\r\n", (char*)(dot->getPublicNetwork() ? "Yes" : "No") );
+        pc.printf("Frequency: %s\r\n", (char*)mDot::FrequencyBandStr(dot->getFrequencyBand()).c_str() );
+        pc.printf("Sub Band: %s\r\n", (char*)mDot::FrequencySubBandStr(dot->getFrequencySubBand()).c_str() );
+        pc.printf("Join Mode: %s\r\n", (char*)mDot::JoinModeStr(dot->getJoinMode()).c_str() );
+        pc.printf("Join Retries: %d\r\n", dot->getJoinRetries() );
+        pc.printf("Join Byte Order: %s\r\n", (char*)(dot->getJoinByteOrder() == 0 ? "LSB" : "MSB") );
+        pc.printf("Link Check Count: %d\r\n", dot->getLinkCheckCount() );
+        pc.printf("Link Check Thold: %d\r\n", dot->getLinkCheckThreshold() );
+        pc.printf("Tx Data Rate: %s\r\n", (char*)mDot::DataRateStr(dot->getTxDataRate()).c_str() );
+        pc.printf("Tx Power: %d\r\n", dot->getTxPower() );
+        pc.printf("TxWait: %s, ", (dot->getTxWait() ? "Y" : "N" ));
+        pc.printf("CRC: %s, ", (dot->getCrc() ? "Y" : "N") );
+        pc.printf("Ack: %s\r\n", (dot->getAck() ? "Y" : "N")  );
+    */
     logInfo("Joining Network");
 
     while ((ret = dot->joinNetwork()) != mDot::MDOT_OK) {
@@ -234,49 +287,98 @@
     logInfo("Joined Network");
 
     // Display Network session key and data session key from Join command
-/*
-    std::vector<uint8_t> tmp = dot->getNetworkSessionKey();
-    pc.printf("Network Session Key: ");
-    pc.printf("%s\r\n", mts::Text::bin2hexString(tmp, " ").c_str());
+    /*
+        std::vector<uint8_t> tmp = dot->getNetworkSessionKey();
+        pc.printf("Network Session Key: ");
+        pc.printf("%s\r\n", mts::Text::bin2hexString(tmp, " ").c_str());
 
-    tmp = dot->getDataSessionKey();
-    pc.printf("Data Session Key: ");
-    pc.printf("%s\r\n", mts::Text::bin2hexString(tmp, " ").c_str());
-*/
-    // Set the Temperature sesnor resolution, 9 bits is enough and makes it faster to provide a reading.
-    probe.setResolution(9);
+        tmp = dot->getDataSessionKey();
+        pc.printf("Data Session Key: ");
+        pc.printf("%s\r\n", mts::Text::bin2hexString(tmp, " ").c_str());
+    */
+#endif /* ENABLE_LORA */
 
     char dataBuf[50];
+    uint16_t count = 0;
+    Coordinate points[NUMSAMPLES];
+    int mode = 0;
     while( 1 ) {
-            // Output data as JSON e.g. {"t":21.3}
-//            temperature = sensor.getTemperature();
-//            humidity = sensor.getHumidity();
-//            pressure = sensor.getPressure();
+        
+        lcd->writeText(0, 0, font_6x8, "Not saving", 10);
+        
+        if (!button.read()) {
+            count = 0;
+            mode = 1; 
+        }
+
+        if (mode) {
+            
+            lcd->writeText(0, 0, font_6x8, "Saving    ", 10);
+            
+            Coordinate a = { gps->getLongitude().degrees, gps->getLongitude().minutes, gps->getLongitude().seconds, gps->getLatitude().degrees, gps->getLatitude().minutes, gps->getLatitude().seconds , accldata._x, accldata._y, accldata._z};
+            points[count] = a;
+            count++;
+        }
+
+        lcd->writeText(0, 1, font_6x8, (gps->getLockStatus() ? "GPS Locked " : "No GPS Lock"), 11);
+
+        if (gps->getLockStatus()) {
+
+            sprintf(dataBuf, "Lat: %d,%d,%d", gps->getLatitude().degrees, gps->getLatitude().minutes, gps->getLatitude().seconds);
+            lcd->writeText(0, 2, font_6x8, dataBuf, strlen(dataBuf));
+
+            sprintf(dataBuf, "Long: %d,%d,%d", gps->getLongitude().degrees, gps->getLongitude().minutes, gps->getLongitude().seconds);
+            lcd->writeText(0, 3, font_6x8, dataBuf, strlen(dataBuf));
+
+            sprintf(dataBuf, "Sat: %d", gps->getNumSatellites());
+            lcd->writeText(0, 4, font_6x8, dataBuf, strlen(dataBuf));
+
+        }
+
+        sprintf(dataBuf, "%04d,%04d,%04d  ", accldata._x, accldata._y, accldata._z);
+        lcd->writeText(0, 5, font_6x8, dataBuf, strlen(dataBuf));
+
+        sprintf(dataBuf, "Time: %02d", gps->getTimestamp().tm_sec);
+        lcd->writeText(0, 6, font_6x8, dataBuf, strlen(dataBuf));
 
-            //Start temperature conversion, wait until ready
-        probe.convertTemperature(true, DS1820::all_devices);
-            // Output data as JSON e.g. {"t":21.3}
-        temperature = probe.temperature();
-        sprintf(dataBuf, "{\"t\":%3.1f}", temperature );
-//            sprintf(dataBuf, "%3.1f,%3.1f,%04.2f", temperature,humidity,pressure );
-        pc.printf("%s\n",dataBuf);
-            send_data.clear();
-            // probably not the most efficent way to do this
-            for( int i=0; i< strlen(dataBuf); i++ )
-                send_data.push_back( dataBuf[i] );
+
+#ifdef ENABLE_LORA
+        send_data.clear();
+        // probably not the most efficent way to do this
+        for( int i=0; i< strlen(dataBuf); i++ ) {
+            send_data.push_back( dataBuf[i] );
+        }
+
+        if ((ret = dot->send(send_data)) != mDot::MDOT_OK) {
+            logError("failed to send: [%d][%s]", ret, mDot::getReturnCodeString(ret).c_str());
+        } else {
+            logInfo("send data: %s", Text::bin2hexString(send_data).c_str());
+        }
+#endif /* ENABLE_LORA */
+
+        sprintf(dataBuf, "C: %03d B: %d", count, button.read());
+        lcd->writeText(0, 7, font_6x8, dataBuf, strlen(dataBuf));
 
-            if ((ret = dot->send(send_data)) != mDot::MDOT_OK) {
-                logError("failed to send: [%d][%s]", ret, mDot::getReturnCodeString(ret).c_str());
-            } else {
-                logInfo("send data: %s", Text::bin2hexString(send_data).c_str());
-            }
-
-           // Should  sleep here and wakeup after a set 5 minute interval.
-            // in the 868 (EU) frequency band, we need to wait until another channel is available before transmitting again
-            uint32_t sleep_time = std::max((uint32_t)1000, (uint32_t)dot->getNextTxMs()) / 1000;
-//wait_ms(2000);
-            // go to sleep and wake up automatically sleep_time seconds later
-            dot->sleep(sleep_time, mDot::RTC_ALARM);
+        osDelay(1000/50);
+        
+        if (count == NUMSAMPLES && mode) {
+            // Stop sampling
+            stoppls = 1;
+            while (1) {   
+                sprintf(dataBuf, "C: %03d B: %d", count, button.read());
+                lcd->writeText(0, 7, font_6x8, dataBuf, strlen(dataBuf)); 
+                
+                if (!button.read()) {
+                    logInfo("Starting...");
+                    for (int i = 0; i < NUMSAMPLES; i++) {
+                        logInfo("%d,%d,%d,%d,%d,%d,%d,%d,%d", points[i].lat_d, points[i].lat_m, points[i].lat_s, points[i].lng_d, points[i].lng_m, points[i].lng_s, points[i].x, points[i].y, points[i].z);
+                        osDelay(1);
+                    }
+                    logInfo("DONE");
+                }
+                
+                osDelay(100);
+            }    
+        }
     }
-
 }