init

Dependencies:   aconno_I2C Lis2dh12 WatchdogTimer

Files at this revision

API Documentation at this revision

Comitter:
pathfindr
Date:
Sat Dec 22 19:33:35 2018 +0000
Parent:
21:e0b866630c27
Child:
23:a3b0ccf75ca5
Commit message:
2

Changed in this revision

README.md 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
main.h Show annotated file Show diff for this revision Revisions of this file
modem.cpp Show annotated file Show diff for this revision Revisions of this file
modem.h Show annotated file Show diff for this revision Revisions of this file
--- a/README.md	Thu Dec 20 22:04:45 2018 +0000
+++ b/README.md	Sat Dec 22 19:33:35 2018 +0000
@@ -3,13 +3,12 @@
 1) Add watchdog kicks to modem functions
 2) USSDmessage index needs to work
 3) clean up timeouts, do we hard code them or send as vars particlulary connectivity ones
-Should we shut down network registration while getting gps fix?
 4) check LNA power on GPS
 5) improve gps fix quality logic
 6) sometimes its setting back to srtate 0 and getting stuck in loop 
 7) what happens if the setup fails, it should sleep for x hrs and then try again, need to check that and make its o
-
-
+8) should we use 2g when possible
+9) does 3g use less power
 
 
 
--- a/main.cpp	Thu Dec 20 22:04:45 2018 +0000
+++ b/main.cpp	Sat Dec 22 19:33:35 2018 +0000
@@ -24,6 +24,7 @@
 bool GLOBAL_debugLED = false;
 bool GLOBAL_needToConfigureLis3dh = false;
 bool GLOBAL_registeredOnNetwork = false;
+bool GLOBAL_modemOn = false;
 long long GLOBAL_imei = 0;
 float GLOBAL_voltage = 0.0;
 time_t GLOBAL_RTCunixtime = 0;
@@ -35,7 +36,6 @@
 #if defined ( __CC_ARM ) /** THIS IS THE MBED ONLINE COMPILER TOOLCHAIN*/ //MUST BE STATICS
 //IDENTITY
 static long long        RET_imei                                        __attribute__((section("noinit"),zero_init));
-static char             RET_pf_identifier[7]                            __attribute__((section("noinit"),zero_init));
 //SETTINGS
 static int              RET_setting_firmware                            __attribute__((section("noinit"),zero_init));
 static uint8_t          RET_setting_location_mode                       __attribute__((section("noinit"),zero_init));
@@ -44,7 +44,7 @@
 static uint32_t         RET_setting_location_tx_failsafe_hrs            __attribute__((section("noinit"),zero_init));
 static uint16_t         RET_setting_location_timeout                    __attribute__((section("noinit"),zero_init));
 static uint8_t          RET_setting_activity_mode                       __attribute__((section("noinit"),zero_init));
-static uint32_t         RET_setting_activity_tx_interval_mins           __attribute__((section("noinit"),zero_init));
+static uint32_t         RET_setting_activity_tx_interval_hrs           __attribute__((section("noinit"),zero_init));
 static uint32_t         RET_setting_environmental_tx_interval_mins      __attribute__((section("noinit"),zero_init));
 static uint16_t         RET_setting_motion_g                            __attribute__((section("noinit"),zero_init));
 static time_t           RET_setting_motion_start_seconds                __attribute__((section("noinit"),zero_init));
@@ -75,8 +75,6 @@
 static bool             RET_motionState                                 __attribute__((section("noinit"),zero_init));
 static float            RET_motionTotalActivityHours                    __attribute__((section("noinit"),zero_init));
 static char             RET_activityData[130]                           __attribute__((section("noinit"),zero_init));
-//TO MAKE THE ABOVE BIGGER YOU NEED TO ALLOCATE MORE NOINIT MEMORY!!!!!
-
 //IMPACT
 static bool             RET_impactTriggered                             __attribute__((section("noinit"),zero_init));
 //EVENTS LOGGING
@@ -88,6 +86,8 @@
 static time_t           RET_eventTime_environmental_tx                  __attribute__((section("noinit"),zero_init));
 static time_t           RET_eventTime_activity_tx                       __attribute__((section("noinit"),zero_init));
 static time_t           RET_eventTime_wakeFromDormant                   __attribute__((section("noinit"),zero_init));
+//DUPLICATES
+static time_t           RET_RTCunixtime2                                __attribute__((section("noinit"),zero_init));
 #elif defined ( __GNUC__ )
 #elif defined ( __ICCARM__ )
 #endif
@@ -120,11 +120,6 @@
 Semaphore mainthread;
 
 //------------------------------------------------------------------------------
-//SINGLETONS
-//------------------------------------------------------------------------------
-//NVStore &nvstore = NVStore::get_instance();
-
-//------------------------------------------------------------------------------
 // LOW LEVEL FUNCS
 //------------------------------------------------------------------------------ 
 void turnOffEverything() {
@@ -144,14 +139,30 @@
     RET_state = state;
     DEBUG("STATEREADBACK %d\n",RET_state)
 }
+bool memoryIntegrityCheck() {
+    //Check clocks match and are in range
+    if (RET_RTCunixtime != RET_RTCunixtime && RET_RTCunixtime > 1545412457) {
+        RET_coldBoot = 1;
+        return false;  
+    } else {
+        return true;   
+    } 
+}
 void getBatteryV() {
     NRF52_SAADC batteryIn;
     batteryIn.addChannel(9); // vdd for battery
     batteryIn.calibrate();
-    for (uint8_t i = 1; i < 3; i++) { // need to get it 3 times to get accurate data, first one is always low for some reason
+    for (uint8_t i = 1; i <= 2; i++) { // need to get it 3 times to get accurate data, first one is always low for some reason
         batteryIn.updateData();
         GLOBAL_voltage = (batteryIn.getData()[0])*(1.0/1024.0)*3.65;
     }
+    DEBUG("Voltage:%.2f\n",GLOBAL_voltage);
+}
+float getTemperature() {
+    SI7060 si7060(PN_I2C_SDA, PN_I2C_SCL);
+    float temperature = si7060.getTemperature();
+    DEBUG("Temperature:%.2f\n",temperature);
+    return temperature;  
 }
 //------------------------------------------------------------------------------
 // USER BUTTON HANDLING
@@ -169,6 +180,8 @@
 void RTCtick() {
     //YOU MUST NOT CALL ANY OTHER FUNCTIONS OR DEBUG FROM INSIDE HERE!!! OR IT LOCKS UP THE DEVICE, just change vars
     RET_RTCunixtime += 1;
+    RET_RTCunixtime2 += 1;
+    
     GLOBAL_RTCunixtime = RET_RTCunixtime;
     
     //button logic - check for hold
@@ -210,22 +223,22 @@
     Thread::wait(200); //wait to ensure that devices are turned off
     //IDENTITY 
     RET_imei = 0;
-    memset(RET_pf_identifier,0,sizeof(RET_pf_identifier));
     //STATE
     RET_coldBoot = 1;
     RET_haveSettings = 0;
     RET_state = STATE_SETUP;
     RET_state_prev = RET_state;
     RET_RTCunixtime = 0;
+    RET_RTCunixtime = 2;
     RET_SetupRunAt = 0;
     //SETTINGS
     RET_setting_firmware = 0;
     RET_setting_location_mode = 2;
-    RET_setting_location_accuracy = 1;
+    RET_setting_location_accuracy = 2; // 0 = no location, 1 = cl only, 2 = gps then cl
     RET_setting_location_tx_interval_mins = 1440;
     RET_setting_location_tx_failsafe_hrs = (7*24); //7 days
     RET_setting_location_timeout = 240;
-    RET_setting_activity_tx_interval_mins = 0;
+    RET_setting_activity_tx_interval_hrs = 0;
     RET_setting_environmental_tx_interval_mins = 0;
     RET_setting_motion_g = 11;
     RET_setting_motion_start_seconds = 120;
@@ -255,6 +268,7 @@
     //EVENT HANDLING
     RET_eventTime_location_log = 0;
     RET_eventTime_location_tx = 0;
+    RET_eventTime_location_failsafe_tx = 0;
     RET_eventTime_environmental_log = 0;
     RET_eventTime_environmental_tx = 0;
     RET_eventTime_activity_tx = 0;
@@ -267,13 +281,29 @@
 void copyRETtoGLOBAL() {
     GLOBAL_imei = RET_imei; 
 }
-void selfTest() {
+bool selfTest() {
+    int test_count = 0;
+    int test_pass = 0;
+    
     //Accelerometer
+    test_count ++;
     LIS3DH lis3dh(PN_SPI_MOSI, PN_SPI_MISO, PN_SPI_CS0, PN_SPI_CLK);
     uint8_t lis3dh_id; 
     lis3dh.LIS3DH_GetWHO_AM_I(&lis3dh_id);
-    if (lis3dh_id == 51) {
-        LED1blink(10,50);
+    if (lis3dh_id == 51) {test_pass ++;}
+    
+    //Temperature
+    test_count ++;
+    SI7060 si7060(PN_I2C_SDA, PN_I2C_SCL);
+    float temperature;
+    temperature = si7060.getTemperature();
+    test_pass ++;
+    
+    //Result
+    if (test_count == test_pass) {
+        return true;
+    } else {
+        return false;   
     }
 }
 
@@ -329,26 +359,25 @@
     //process result
     int matchCount = 0;
     int critical_fail_count = 0;
-    char TEMP_a[7]; time_t TEMP_b = 0; int TEMP_c = -1; int TEMP_d = -1; int TEMP_e = -1; int TEMP_f = -1; int TEMP_g = -1; int TEMP_h = -1; int TEMP_i = -1; int TEMP_j = -1; 
+    time_t TEMP_b = 0; int TEMP_c = -1; int TEMP_d = -1; int TEMP_e = -1; int TEMP_f = -1; int TEMP_g = -1; int TEMP_h = -1; int TEMP_i = -1; int TEMP_j = -1; 
     int TEMP_k = -1; int TEMP_l = -1; int TEMP_m = -1; int TEMP_n = -1; int TEMP_o = -1; int TEMP_p = -1; int TEMP_q = -1; int TEMP_r = -1; int TEMP_s = -1;
-    if ( (matchCount = sscanf(settingsBuffer,"a:%c%c%c%c%c%c,b:%u,c:%d,d:%d,e:%d,f:%d,g:%d,h:%d,i:%d,j:%d,k:%d,l:%d,m:%d,n:%d,o:%d,p:%d,q:%d,r:%d,s:%d",
-    &TEMP_a[0],&TEMP_a[1],&TEMP_a[2],&TEMP_a[3],&TEMP_a[4],&TEMP_a[5],&TEMP_b,&TEMP_c,&TEMP_d,&TEMP_e,&TEMP_f,&TEMP_g,&TEMP_h,&TEMP_i,&TEMP_j,&TEMP_k,&TEMP_l,&TEMP_m,&TEMP_n,&TEMP_o,&TEMP_p,&TEMP_q,&TEMP_r,&TEMP_s) ) > 0 ) {
-        DEBUG("VALUES: a:%s,b:%u,c:%d,d:%d,e:%d,f:%d,g:%d,h:%d,i:%d,j:%d,k:%d,l:%d,m:%d,n:%d,o:%d,p:%d,q:%d,r:%d,s:%d\n",
-        TEMP_a,TEMP_b,TEMP_c,TEMP_d,TEMP_e,TEMP_f,TEMP_g,TEMP_h,TEMP_i,TEMP_j,TEMP_k,TEMP_l,TEMP_m,TEMP_n,TEMP_o,TEMP_p,TEMP_q,TEMP_r,TEMP_s);
+    if ( (matchCount = sscanf(settingsBuffer,"b:%u,c:%d,d:%d,e:%d,f:%d,g:%d,h:%d,i:%d,j:%d,k:%d,l:%d,m:%d,n:%d,o:%d,p:%d,q:%d,r:%d,s:%d",
+    &TEMP_b,&TEMP_c,&TEMP_d,&TEMP_e,&TEMP_f,&TEMP_g,&TEMP_h,&TEMP_i,&TEMP_j,&TEMP_k,&TEMP_l,&TEMP_m,&TEMP_n,&TEMP_o,&TEMP_p,&TEMP_q,&TEMP_r,&TEMP_s) ) > 0 ) {
+        DEBUG("VALUES: b:%u,c:%d,d:%d,e:%d,f:%d,g:%d,h:%d,i:%d,j:%d,k:%d,l:%d,m:%d,n:%d,o:%d,p:%d,q:%d,r:%d,s:%d\n",
+        TEMP_b,TEMP_c,TEMP_d,TEMP_e,TEMP_f,TEMP_g,TEMP_h,TEMP_i,TEMP_j,TEMP_k,TEMP_l,TEMP_m,TEMP_n,TEMP_o,TEMP_p,TEMP_q,TEMP_r,TEMP_s);
         
         //FAILUREMODE need to be checking thse against checksums
         char changed;
         //FAILUREMODE need to verify the identifier against a reg exp or similar
-        if(1==1) { memcpy(RET_pf_identifier, TEMP_a, sizeof(TEMP_a));              changed = 'Y'; } else { changed = 'N'; critical_fail_count++; }; DEBUG("RET_pf_identifier:%s..%c\n",RET_pf_identifier,changed);
         if(TEMP_b != 0) { RET_RTCunixtime = TEMP_b;                                changed = 'Y'; } else { changed = 'N'; critical_fail_count++; }; DEBUG("RET_RTCunixtime:%u..%c\n",RET_RTCunixtime,changed);
         if(TEMP_c != -1) { RET_setting_firmware = TEMP_c;                          changed = 'Y'; } else { changed = 'N'; RET_setting_firmware = -1;}; DEBUG("RET_setting_firmware:%d..%c\n",RET_setting_firmware,changed);
         if(TEMP_d != -1) { setState(TEMP_d);                                       changed = 'Y'; } else { changed = 'N'; critical_fail_count++; }; DEBUG("RET_state:%d..%c\n",RET_state,changed);
-        if(TEMP_e != -1) { RET_setting_location_mode = TEMP_e;                     changed = 'Y'; } else { changed = 'N'; }; DEBUG("RET_setting_location_accuracy:%d..%c\n",RET_setting_location_accuracy,changed);
+        if(TEMP_e != -1) { RET_setting_location_mode = TEMP_e;                     changed = 'Y'; } else { changed = 'N'; }; DEBUG("RET_setting_location_mode:%d..%c\n",RET_setting_location_mode,changed);
         if(TEMP_f != -1) { RET_setting_location_accuracy = TEMP_f;                 changed = 'Y'; } else { changed = 'N'; }; DEBUG("RET_setting_location_accuracy:%d..%c\n",RET_setting_location_accuracy,changed);
         if(TEMP_g != -1) { RET_setting_location_tx_interval_mins = TEMP_g;         changed = 'Y'; } else { changed = 'N'; }; DEBUG("RET_setting_location_tx_interval_mins:%d..%c\n",RET_setting_location_tx_interval_mins,changed);
         if(TEMP_h != -1) { RET_setting_location_tx_failsafe_hrs = TEMP_h;          changed = 'Y'; } else { changed = 'N'; }; DEBUG("RET_setting_location_tx_failsafe_hrs:%d..%c\n",RET_setting_location_tx_failsafe_hrs,changed);
         if(TEMP_i != -1) { RET_setting_location_timeout = TEMP_i;                  changed = 'Y'; } else { changed = 'N'; }; DEBUG("RET_setting_location_timeout:%d..%c\n",RET_setting_location_timeout,changed);
-        if(TEMP_j != -1) { RET_setting_activity_tx_interval_mins = TEMP_j;         changed = 'Y'; } else { changed = 'N'; }; DEBUG("RET_setting_activity_tx_interval_mins:%d..%c\n",RET_setting_activity_tx_interval_mins,changed);
+        if(TEMP_j != -1) { RET_setting_activity_tx_interval_hrs = TEMP_j;          changed = 'Y'; } else { changed = 'N'; }; DEBUG("RET_setting_activity_tx_interval_hrs:%d..%c\n",RET_setting_activity_tx_interval_hrs,changed);
         if(TEMP_k != -1) { RET_setting_environmental_tx_interval_mins = TEMP_k;    changed = 'Y'; } else { changed = 'N'; }; DEBUG("RET_setting_environmental_tx_interval_mins:%d..%c\n",RET_setting_environmental_tx_interval_mins,changed);
         if(TEMP_l != -1) { RET_setting_motion_g = TEMP_l;                          changed = 'Y'; } else { changed = 'N'; }; DEBUG("RET_setting_motion_g:%d..%c\n",RET_setting_motion_g,changed);
         if(TEMP_m != -1) { RET_setting_motion_start_seconds = TEMP_m;              changed = 'Y'; } else { changed = 'N'; }; DEBUG("RET_setting_motion_start_seconds:%d..%c\n",RET_setting_motion_start_seconds,changed);
@@ -375,16 +404,15 @@
     }
 }
 bool dumpSettings() {
-    DEBUG("RET_pf_identifier:%s \n",RET_pf_identifier);
     DEBUG("RET_RTCunixtime:%u \n",RET_RTCunixtime);
     DEBUG("RET_setting_firmware:%d \n",RET_setting_firmware);
     DEBUG("RET_state:%d \n",RET_state);
-    DEBUG("RET_setting_location_accuracy:%d \n",RET_setting_location_accuracy);
+    DEBUG("RET_setting_location_mode:%d \n",RET_setting_location_mode);
     DEBUG("RET_setting_location_accuracy:%d \n",RET_setting_location_accuracy);
     DEBUG("RET_setting_location_tx_interval_mins:%d \n",RET_setting_location_tx_interval_mins);
     DEBUG("RET_setting_location_tx_failsafe_hrs:%d \n",RET_setting_location_tx_failsafe_hrs);
     DEBUG("RET_setting_location_timeout:%d \n",RET_setting_location_timeout);
-    DEBUG("RET_setting_activity_tx_interval_mins:%d \n",RET_setting_activity_tx_interval_mins);
+    DEBUG("RET_setting_activity_tx_interval_hrs:%d \n",RET_setting_activity_tx_interval_hrs);
     DEBUG("RET_setting_environmental_tx_interval_mins:%d \n",RET_setting_environmental_tx_interval_mins);
     DEBUG("RET_setting_motion_g:%d \n",RET_setting_motion_g);
     DEBUG("RET_setting_motion_start_seconds:%d \n",RET_setting_motion_start_seconds);
@@ -405,8 +433,8 @@
         RET_eventTime_location_failsafe_tx = (RET_RTCunixtime + (RET_setting_location_tx_failsafe_hrs * 3600));
         DEBUG("EVENTSET - LOCATION FAILSAFE TX at %u\n",RET_eventTime_location_failsafe_tx);
     }
-    if(RET_setting_activity_tx_interval_mins > 0) { 
-        RET_eventTime_activity_tx = (RET_RTCunixtime + (RET_setting_activity_tx_interval_mins * 60));
+    if(RET_setting_activity_tx_interval_hrs > 0) { 
+        RET_eventTime_activity_tx = (RET_RTCunixtime + (RET_setting_activity_tx_interval_hrs * 3600));
         DEBUG("EVENTSET - ACTIVITY TX at %u\n",RET_eventTime_activity_tx);
     }
     if(RET_eventTime_environmental_tx > 0) { 
@@ -426,8 +454,9 @@
         GLOBAL_imei = RET_imei;
         DEBUG("imei: %lld \n",RET_imei);
         if (modem.registerOnNetwork(2,180000)) {
+            int timetaken = (RET_RTCunixtime - GLOBAL_wakeTime);
             char bytestosend[160];
-            snprintf(bytestosend,sizeof(bytestosend),"(%s,im:%lld,v:%.2f,fr:1,z:SETUP,c:1)\0",GLOBAL_defaultApi,GLOBAL_imei,GLOBAL_voltage);
+            snprintf(bytestosend,sizeof(bytestosend),"(%s,im:%lld,f:%d,v:%.2f,e:%d,fr:1,z:SETUP,c:1)\0",GLOBAL_defaultApi,GLOBAL_imei,FW_VERSION,GLOBAL_voltage,timetaken);
             char result[180];
             snprintf(result,sizeof(result),"%s",modem.USSDmessage(bytestosend, true, 2, GLOBAL_defaultApi));
             if (result != "err") {
@@ -456,13 +485,61 @@
 //------------------------------------------------------------------------------
 // EVENTS
 //------------------------------------------------------------------------------ 
-void event_location_tx() {
-    DEBUG("PERFORM LOCATION TX\n");
+void event_shakertest_tx() {
+    DEBUG("SHAKER TEST\n");
     getBatteryV();  
+    float temperature = getTemperature();
+    bool selftestresult = selfTest();
     Modem modem(PN_UART_TX, PN_UART_RX, PN_UART_CTS, PN_UART_RTS, PN_GSM_PWR_KEY, PN_VREG_EN, PN_GSM_WAKE_DISABLE);
     if (modem.on()) {
-        //RET_setting_location_accuracy
-        modem.getLocation(true, 3, true, RET_setting_location_timeout);
+        if (modem.registerOnNetwork(2,180000)) {
+            int timetaken = (RET_RTCunixtime - GLOBAL_wakeTime);
+            char bytestosend[160];
+            snprintf(bytestosend,sizeof(bytestosend),"(%s,f:%d,t:%.2f,v:%.2f,z:SHAKERTEST-%d,e:%d,c:1)\0",GLOBAL_defaultApi,FW_VERSION,temperature,GLOBAL_voltage,selftestresult,timetaken);
+            char result[180];
+            bool getSettings = true;
+            snprintf(result,sizeof(result),"%s",modem.USSDmessage(bytestosend, getSettings, 2, GLOBAL_defaultApi));
+            if (result != "err") {
+                DEBUG("\nfromserver: %s \n",result);
+                if (getSettings) {
+                    saveSettings(result);
+                }
+            }
+        }
+    }
+    //RESETS
+    RET_motionTriggeredInTXInterval = 0;
+    saveEventTimes();
+}
+
+void event_location_tx() {
+    DEBUG("LOCATION TX\n");
+    getBatteryV();
+    float temperature = getTemperature();
+    Modem modem(PN_UART_TX, PN_UART_RX, PN_UART_CTS, PN_UART_RTS, PN_GSM_PWR_KEY, PN_VREG_EN, PN_GSM_WAKE_DISABLE);
+    if (modem.on()) {
+        int timetaken = (RET_RTCunixtime - GLOBAL_wakeTime);
+        char gpsString[70];
+        if (RET_setting_location_accuracy > 0) { 
+            snprintf(gpsString,sizeof(gpsString),"%s",modem.getLocation(RET_setting_location_accuracy, RET_setting_location_timeout));
+            DEBUG("\ngpsString:%s\n",gpsString);
+        } else {
+            DEBUG("localisation disabled\n");
+        }
+        //SEND DATA
+        if (modem.registerOnNetwork(2,180000)) {
+            char bytestosend[160];
+            snprintf(bytestosend,sizeof(bytestosend),"(%s,f:%d,t:%.2f,v:%.2f,z:OK,e:%d,c:1%s)\0",GLOBAL_defaultApi,FW_VERSION,temperature,GLOBAL_voltage,timetaken,gpsString);
+            char result[180];
+            bool getSettings = true;
+            snprintf(result,sizeof(result),"%s",modem.USSDmessage(bytestosend, getSettings, 2, GLOBAL_defaultApi));
+            if (result != "err") {
+                DEBUG("\nfromserver: %s \n",result);
+                if (getSettings) {
+                    saveSettings(result);
+                }
+            }
+        }
     }
     //RESETS
     RET_motionTriggeredInTXInterval = 0;
@@ -475,11 +552,12 @@
     switch(RET_state) {
         case STATE_SETUP :
             DEBUG("STATE:SETUP\n");
+            factoryReset();
             getBatteryV();
             if (setup()) {
                 copyRETtoGLOBAL();
             } else {
-                RET_eventTime_wakeFromDormant = (RET_RTCunixtime + (72*3600)); //72hrs
+                RET_eventTime_wakeFromDormant = (RET_RTCunixtime + (24*3600)); //24hrs
                 setState(STATE_DORMANT);
                 DEBUG("SETSTATE:DORMANT until %u\n",RET_eventTime_wakeFromDormant);
             }
@@ -490,63 +568,32 @@
             checkMotion();
             
             //EVENTS
-            
             //LOCATION
-            //Location Log
-            /*
-            if(RET_RTCunixtime > RET_eventTime_location_log && RET_eventTime_location_log > 0)  { 
-            }
-            */
             bool run_location_tx = false;
-            switch (RET_setting_location_mode) {
-                case 1: //INTERVAL POST
-                    if(RET_RTCunixtime > RET_eventTime_location_tx && RET_eventTime_location_tx > 0) { 
-                        DEBUG("INTERVAL LOC TX...\n");
-                        run_location_tx = true; 
-                    }
-                    break;
-                case 2: //INTERVAL POST WITH MOTION CHECK
-                    if(RET_motionTriggeredInTXInterval && RET_RTCunixtime > RET_eventTime_location_tx && RET_eventTime_location_tx > 0) {
-                        DEBUG("INTERVAL LOC TX WMC...\n"); 
-                        run_location_tx = true; 
-                    }
-                    break;
-                case 3: //POST ON STOP MOTION
-                    if (GLOBAL_motionStopFlagTriggered) {
-                        DEBUG("MOTION STOP LOC TX...\n");
-                        run_location_tx = true;
-                        GLOBAL_motionStopFlagTriggered = false;
-                    }
-                    break;   
+            if(RET_RTCunixtime >= RET_eventTime_location_tx && RET_eventTime_location_tx > 0) { 
+                DEBUG("INTERVAL LOC TX...\n");
+                run_location_tx = true; 
             }
-            //Failsafe timer catchall
-            if(RET_RTCunixtime > RET_eventTime_location_failsafe_tx && RET_eventTime_location_failsafe_tx > 0) { run_location_tx = true; }
-            if (run_location_tx) {event_location_tx();}
+            //Location Failsafe timer catchall
+            if(RET_RTCunixtime >= RET_eventTime_location_failsafe_tx && RET_eventTime_location_failsafe_tx > 0) { run_location_tx = true; }
+            if (run_location_tx) {
+                event_location_tx();
+            }
             
-            //Environmental Log
-            if(RET_RTCunixtime > RET_eventTime_environmental_log && RET_eventTime_environmental_log > 0) {
-                /*
-                Filesystem filesystem(BD_PAGE_ADDRESS,BD_TOTAL_SIZE);
-                SI7060 temperature(PN_I2C_SDA,PN_I2C_SCL);
-                float temperature_c = temperature.getTemperature();
-                DEBUG("Temperature log: %u,%f \n", RET_RTCunixtime,temperature_c);
-                filesystem.addLogEntry_temperature(RET_RTCunixtime,temperature_c);
-                */
-            }
-            //Environmental TX
-            if(RET_RTCunixtime > RET_eventTime_environmental_tx && RET_eventTime_environmental_tx > 0) {
-                //getBatteryV();
-                //event_environmental_bc();
-                //Filesystem filesystem(PN_SPI_MOSI,PN_SPI_MISO,PN_SPI_CLK,PN_SPI_CS1);
-            }
-            //Activity TX
-            if(RET_RTCunixtime > RET_eventTime_activity_tx && RET_eventTime_activity_tx > 0) {
+            //ACTIVITY TX
+            if(RET_RTCunixtime >= RET_eventTime_activity_tx && RET_eventTime_activity_tx > 0) {
                 //event_activity_tx();
+                event_shakertest_tx();
             }
             break;
         case STATE_DORMANT :
-            if (RET_RTCunixtime > RET_eventTime_wakeFromDormant) {
-                setState(STATE_NORMAL);
+            if (RET_RTCunixtime >= RET_eventTime_wakeFromDormant) {
+                if (RET_haveSettings) {
+                    setState(STATE_NORMAL); 
+                } else {
+                    setState(STATE_SETUP); 
+                }
+                
                 DEBUG("WAKING UP FROM DORMANT\n");
             }
             DEBUG("STATE:DORMANT until %u\n",RET_eventTime_wakeFromDormant);
@@ -591,6 +638,7 @@
 //------------------------------------------------------------------------------ 
 int main() {
     turnOffEverything();
+    memoryIntegrityCheck();
     
     //CHECK IF THIS IS RESET
     //0x00000004 == soft reset  //0x00000002 == watchdog  //0x00000001 == button/hardreset 
@@ -622,24 +670,29 @@
     copyRETtoGLOBAL();
     
     while(true) {
-        //SLEEP
-        if (RET_coldBoot != 1) gotoSleep(10000); //THIS HAS TO BE THE FIRST ITEM IN THE MAIN LOOP
+        memoryIntegrityCheck();
         watchdogKick();
         
         //LOG START TIME
         GLOBAL_wakeTime = RET_RTCunixtime;
         
         //MAIN LOGIC
-        DEBUG("STATE:%d, RTC_SECONDS:%u, SETUPAT:%u\n", RET_state, RET_RTCunixtime,RET_SetupRunAt);
-        
-        event_location_tx();
-        while(1) {   
-        }
-
+        DEBUG("STATE:%d, HAVESETTINGS:%d, RTC:%u, BOOTAT:%u, LOC:%u, LOC_FS:%u, ACT:%u \n", RET_state, RET_haveSettings, RET_RTCunixtime,RET_SetupRunAt,RET_eventTime_location_tx,RET_eventTime_location_failsafe_tx,RET_eventTime_activity_tx);
         mainStateEngine();
         
         //PRE-SLEEP ACTIONS
         if (GLOBAL_needToConfigureLis3dh) { lis3dh_configureForSleep(10,127); }
+        if (GLOBAL_modemOn) {
+            DEBUG("SHUTTING DOWN MODEM\n");
+            Modem modem(PN_UART_TX, PN_UART_RX, PN_UART_CTS, PN_UART_RTS, PN_GSM_PWR_KEY, PN_VREG_EN, PN_GSM_WAKE_DISABLE);
+            modem.off(true);
+        }
         RET_coldBoot = 0;
+        
+        //SLEEP DIFFERENT FOR THIS SHAKER TEST VERSION - AS IS WILL GIVE 450ua sleep
+        NRF_UART0->TASKS_SUSPEND = 1;
+        NRF_UART0->ENABLE = 0; //NO MORE SERIAL OR DEBUG OUTPUTS AFTER THIS
+        mainthread.wait(30000);
+        system_reset();
     }
 }
\ No newline at end of file
--- a/main.h	Thu Dec 20 22:04:45 2018 +0000
+++ b/main.h	Sat Dec 22 19:33:35 2018 +0000
@@ -65,6 +65,7 @@
 extern bool GLOBAL_debugLED;
 extern bool GLOBAL_needToConfigureLis3dh;
 extern bool GLOBAL_registeredOnNetwork;
+extern bool GLOBAL_modemOn;
 extern long long GLOBAL_imei;
 extern float GLOBAL_voltage;
 extern time_t GLOBAL_RTCunixtime;
--- a/modem.cpp	Thu Dec 20 22:04:45 2018 +0000
+++ b/modem.cpp	Sat Dec 22 19:33:35 2018 +0000
@@ -50,7 +50,7 @@
     }
     t.stop();
     t.reset();
-    ThisThread::sleep_for(500);
+    ThisThread::sleep_for(250);
     if (havefullmatch) {
         return true;
     } else {
@@ -66,13 +66,26 @@
     _pwrkey = 0;
     Thread::wait(1500);
     _pwrkey = 1;
-    if (ATwaitForWord("RDY",15000)) {
+    
+    GLOBAL_modemOn = true;
+    
+    //CONFIGURE
+    if (ATwaitForWord("RDY",ATTIMEOUT_MED)) {
         //TURN OFF ECHO
         ATsendCMD("ATE0");
-        ATwaitForWord("OK",5000);
+        ATwaitForWord("OK",ATTIMEOUT_SHORT);
+        
+        //ENABLE AIRPLANE MODE CONTROL WITH PIN
+        ATsendCMD("AT+QCFG=\"airplanecontrol\",1");
+        ATwaitForWord("OK",ATTIMEOUT_SHORT);
         
-        ATsendCMD("AT+QCFG=\"airplanecontrol\",1");
-        ATwaitForWord("OK",5000);
+        //PRIORITISE 2G connection (reason being uses less power in some instances and can get cell tower tirangulation)
+        ATsendCMD("AT+QCFG=\"nwscanseq\",1");
+        ATwaitForWord("OK",ATTIMEOUT_SHORT);
+        
+        //2G only
+        //ATsendCMD("AT+QCFG=\"nwscanmode\",1");
+        //ATwaitForWord("OK",ATTIMEOUT_SHORT);
         
         return true;
     } else {
@@ -84,8 +97,9 @@
 {
     if (soft) {
         ATsendCMD("AT+QPOWD=0");
-        ATwaitForWord("OK\r",5000);
+        ATwaitForWord("OK\r",ATTIMEOUT_SHORT);
     }
+    GLOBAL_registeredOnNetwork = false;
     _vreg_en = 0;
 }
 
@@ -94,7 +108,7 @@
     long long imei = 0;
     char ATinBuffer[32];
     ATsendCMD("AT+GSN");
-    ATwaitForWord("\n",5000);
+    ATwaitForWord("\n",ATTIMEOUT_SHORT);
     _uart.scanf("%s", ATinBuffer);
     imei = atoll(ATinBuffer);
     flushSerial();
@@ -103,34 +117,36 @@
 
 bool Modem::registerOnNetwork(int maxAttempts, uint32_t timeout) 
 {
-    int attempt = 0;
-    Timer t;
-    t.start();
-    //DISABLE AIRPLANE MODE
-    _w_disable = 1;
-    flushSerial();
-    //TRY X NUMBER OF TIMES
-    while (attempt <= maxAttempts) {
-        watchdogKick();
-        attempt ++;
-        t.reset();
-        uint32_t startmillis = t.read_ms();
-        uint32_t runtime = 0;
-        while(!GLOBAL_registeredOnNetwork && runtime < timeout) {
-            runtime = (t.read_ms() - startmillis);
-            Thread::wait(1000);
-            ATsendCMD("AT+CREG?");
-            if (ATwaitForWord("+CREG: 0,5",5000)) {
-                flushSerial();
-                GLOBAL_registeredOnNetwork = true;
-            };
+    //CHECK WE ARE NOT ALREADY ON NETOWRK
+    if (!GLOBAL_registeredOnNetwork) {
+        int attempt = 0;
+        Timer t;
+        t.start();
+        //DISABLE AIRPLANE MODE
+        _w_disable = 1;
+        flushSerial();    
+        while (attempt <= maxAttempts) {
+            watchdogKick();
+            attempt ++;
+            t.reset();
+            uint32_t startmillis = t.read_ms();
+            uint32_t runtime = 0;
+            while(!GLOBAL_registeredOnNetwork && runtime < timeout) {
+                runtime = (t.read_ms() - startmillis);
+                Thread::wait(1000);
+                ATsendCMD("AT+CREG?");
+                if (ATwaitForWord("+CREG: 0,5",3000)) {
+                    flushSerial();
+                    GLOBAL_registeredOnNetwork = true;
+                };
+            }
+            if (!GLOBAL_registeredOnNetwork) {
+                off(true);
+                on();   
+            }
         }
-        if (!GLOBAL_registeredOnNetwork) {
-            off(true);
-            on();   
-        }
+        t.stop();
     }
-    t.stop();
     flushSerial();
     if (GLOBAL_registeredOnNetwork) {
         return true;
@@ -149,7 +165,7 @@
         char bytestosend[160];
         snprintf(bytestosend, sizeof(bytestosend), "AT+CUSD=1,\"#469*%s#\"", message);
         ATsendCMD(bytestosend);
-        if (ATwaitForWord("+CUSD: 0",10000)) {
+        if (ATwaitForWord("+CUSD: 0",ATTIMEOUT_MED)) {
             flushSerial();
             sent = true;
         };
@@ -164,7 +180,7 @@
 char* Modem::USSDreceive(int messageIndex) 
 {
     bool received = false;
-    uint32_t timeout = 15000;
+    uint32_t timeout = ATTIMEOUT_MED;
     //int bufferIndex = 0;
     int USSDmessageIndex = 0;
     char ATinBuffer[180];
@@ -176,7 +192,7 @@
     uint32_t runtime = 0;
     while(!received && runtime < timeout) {
         runtime = (t.read_ms() - startmillis);
-        if (ATwaitForWord("+CUSD: 0",5000)) {
+        if (ATwaitForWord("+CUSD: 0",ATTIMEOUT_SHORT)) {
             led1 = 0;
             if ( (matchCount = _uart.scanf(",\"%d#%[^#]",USSDmessageIndex,ATinBuffer) ) > 0 ) {
                 //DEBUG("\ngot:%s \n",ATinBuffer);
@@ -227,21 +243,23 @@
 }
 
 
-void Modem::getLocation(bool gps, bool cellLocate, uint8_t accuracy, uint16_t timeout_seconds) 
+char* Modem::getLocation(uint8_t accuracy, uint16_t timeout_seconds) 
 { 
     flushSerial();
     bool haveGPSFix = false;
     bool haveCellLocateFix = false;
     
-    if (gps) {
-        //TURN ON GPS
-        ATsendCMD("AT+QGPS=1");
-        ATwaitForWord("OK",5000);
-        
+    char gpsDataOut[80];
+    
+    if (accuracy >= 2) {
         //Enable External LNA power - IS DISABLED BY DEFAULT
         ATsendCMD("AT+QGPSCFG=\"lnacontrol\",1");
         ATwaitForWord("OK",5000);
         
+        //TURN ON GPS
+        ATsendCMD("AT+QGPS=1");
+        ATwaitForWord("OK",ATTIMEOUT_SHORT);
+        
         Timer t;
         t.start();
         //TRY UNTIL TIMEOUT
@@ -250,26 +268,113 @@
         uint32_t startmillis = t.read_ms();
         uint32_t runtime = 0;
         while(!haveGPSFix && runtime < (timeout_seconds*1000)) {
+            watchdogKick();
             Thread::wait(5000); //this goes first
             runtime = (t.read_ms() - startmillis);
             ATsendCMD("AT+QGPSLOC=2");
-            if (ATwaitForWord("+QGPSLOC:",5000)) {
+            if (ATwaitForWord("+QGPSLOC: ",ATTIMEOUT_SHORT)) {
                 GPS_fixstage = 1;
                 GPS_fixcount ++;
                 if (GPS_fixcount == 2) { //wait 10 seconds to get a better fix // need to improve this logic
                     haveGPSFix = true;
-                    cellLocate = false; //disable the need for trying cell locate
+                } else {
+                    flushSerial();   
+                }
+            } else {
+                flushSerial();   
+            }
+            if (haveGPSFix) {
+                //+QGPSLOC: 233510.0,52.55415,1.24021,1.2,59.2,2,0.00,0.0,0.0,201218,05
+                int matchCount = 0;
+                float utc;
+                float lat;
+                float lng;
+                float hdp;
+                float alt;
+                uint8_t fix;
+                float cog;
+                float spkm;
+                float spkn;
+                uint32_t date;
+                uint8_t sat;
+                
+                char gpsDataIn[100];
+                _uart.scanf("%s",gpsDataIn);
+                //Example data
+                //115757.0,52.62091,1.29536,0.8,58.2,2,0.00,0.0,0.0,211218,07
+                if ((matchCount = sscanf(gpsDataIn,"%f,%f,%f,%f,%f,%d,%f,%f,%f,%d,%d",&utc,&lat,&lng,&hdp,&alt,&fix,&cog,&spkm,&spkn,&date,&sat)) == 11 ) {
+                    //{“fix”:“GPS”,“sat”:“9",“lat”:“52.913254",“lng”:“-1.455289",“hdp”:“89.0",“spd”:“0.0"}                    
+                    sprintf(gpsDataOut,",g:(fix:GPS,sat:%d,lat:%.6f,lng:%.6f,hdp:%.1f,spd:%.1f)\0",fix,sat,lat,lng,hdp,spkm);
+                    DEBUG("\nGPSOut:%s--\n",gpsDataOut);
                 }
             }
-            watchdogKick();
         }
         //TURN OFF GPS
         ATsendCMD("AT+QGPSEND");
-        ATwaitForWord("OK",5000);
+        ATwaitForWord("OK",ATTIMEOUT_SHORT);
     }
-    if (cellLocate) {
-           
+    
+    //SHALL WE GET CELL LOCATION
+    if (!haveGPSFix && accuracy >= 1) {
+        //PRIORITISE 2G connection (reason being uses less power in some instances and can get cell tower tirangulation)
+        ATsendCMD("AT+QCFG=\"nwscanseq\",0"); // 0 - auto, 1 - 2g priority, 2 - 3g priority
+        ATwaitForWord("OK",ATTIMEOUT_SHORT);
+        
+        _w_disable = 1; //turn off airplane mode
+        registerOnNetwork(3, 60000);
+        
+        //ATsendCMD("AT+QCFG=\"nwscanmode\",1"); // 0 - auto, 1 - 2g, 2 - 3g
+        //ATwaitForWord("OK",ATTIMEOUT_SHORT);
+        
+        
+        //example from home 
+        /*
+        +QENG: "servingcell","NOCONN","2G",234,30,8CC,A34E,20,668,0,-80,0,5,4,26,26,1,-,-,-,-,-,-,-,-,-,"-"
+        +QENG: "neighbourcell","2G",234,30,8CC,A34D,20,656,-89,17,17,0,0
+        +QENG: "neighbourcell","2G",234,30,8CC,678,61,686,-104,2,2,0,0
+        +QENG: "neighbourcell","2G",234,30,8CC,4303,32,676,-104,2,2,0,0
+        +QENG: "neighbourcell","2G",234,30,8CC,B2B2,16,692,-107,-1,-1,0,0
+        https://www.neilson.co.za/mobile-network-geolocation-obtaining-the-cell-ids-the-signal-strength-of-surrounding-towers-from-a-gsm-modem/
+        */
+        
+        ATsendCMD("AT+QENG=\"servingcell\"");
+        ATwaitForWord("OK",ATTIMEOUT_SHORT);
+            
+        while(1) {
+            //ATsendCMD("AT+CREG?");
+            //ATwaitForWord("OK",5000);
+            
+            //wait(10.0);
+            
+            
+            
+            ATsendCMD("AT+QENG=\"neighbourcell\"");
+            ATwaitForWord("OK",ATTIMEOUT_SHORT);
+            
+            wait(2.0);
+            //wait(15.0);
+            //ATwaitForWord("+QENG: \"neighbourcell\"",ATTIMEOUT_MED);
+            
+            /*
+            //+QENG: "servingcell","NOCONN","3G",234,20,8A,CE8B11,10612,320,-75,-76,5,31,39,128,-,-,-,-,-,"-",-
+            char cellDataIn[100];
+            int cellId = 0;
+            int lac = 0;
+            int mcc = 0;
+            int mnc = 0;
+            if ((matchCount = _uart.scanf(",\"  %[^\"],\"%[^\"],%d%d%  %[^#]",&cellId,&lac,&mcc,&mnc)) > 0 ) {
+                sprintf(gpsDataOut,",g:(fix:GPS,sat:%d,lat:%.6f,lng:%.6f,hdp:%.1f,spd:%.1f)\0",fix,sat,lat,lng,hdp,spkm);
+                DEBUG("\nGPSOut:%s--\n",gpsDataOut);
+            }
+            */
+        }
     }
+    
+    //RETURN
+    if (!haveGPSFix && !haveCellLocateFix) {
+        sprintf(gpsDataOut,"");
+    }
+    return gpsDataOut;
 }
 
 Modem::~Modem(){};
\ No newline at end of file
--- a/modem.h	Thu Dec 20 22:04:45 2018 +0000
+++ b/modem.h	Sat Dec 22 19:33:35 2018 +0000
@@ -8,6 +8,9 @@
     #define UC20_BAUDRATE       115200
     #define SIM7600_BAUDRATE    115200
     #define USSD_MAXLENGTH      160
+    #define ATTIMEOUT_SHORT      5000
+    #define ATTIMEOUT_MED       10000
+    #define ATTIMEOUT_LONG      20000
     
     class Modem
     {
@@ -24,7 +27,7 @@
             bool USSDsend(char* message, int maxAttempts);
             char* USSDreceive(int messageIndex);
             char* USSDmessage(char* message, bool needResponse, int maxAttempts, char* api);
-            void getLocation(bool gps, bool cellLocate, uint8_t accuracy, uint16_t timeout_seconds); //accuracy is 1,2,3   low, med, high
+            char* getLocation(uint8_t accuracy, uint16_t timeout_seconds); //accuracy is 1,2,3   low, med, high
             
             //AT
             void flushSerial(void);