init
Dependencies: aconno_I2C Lis2dh12 WatchdogTimer
main.cpp
- Committer:
- pathfindr
- Date:
- 2018-12-17
- Revision:
- 16:3bf5f1a5f869
- Parent:
- 15:7aad9a7f970c
- Child:
- 17:ba55c026b1d6
File content as of revision 16:3bf5f1a5f869:
#include "main.h" //include "nrf_soc.h" //------------------------------------------------------------------------------ //FUNCTION PROTOTYPES //------------------------------------------------------------------------------ static void mainStateEngine(void); static void selftest(void); static void buttonPress(void); static void buttonRelease(void); //------------------------------------------------------------------------------ //GLOBAL VARS / CLEARED ON SLEEP (IF USING SOFT REBOOT HACK) //------------------------------------------------------------------------------ char* GLOBAL_defaultApi = "b:gps2,d:3"; bool GLOBAL_accel_healthy = false; bool GLOBAL_requireSoftReset = false; bool GLOBAL_motionFlagTriggered = false; bool GLOBAL_debugLED = false; bool GLOBAL_needToConfigureLis3dh = false; bool GLOBAL_registeredOnNetwork = false; long long GLOBAL_imei = 0; float GLOBAL_voltage = 0.0; time_t GLOBAL_RTCunixtime = 0; time_t GLOBAL_wakeTime = 0; //------------------------------------------------------------------------------ //RETAINED NOINIT RAM VARS //------------------------------------------------------------------------------ #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[6] __attribute__((section("noinit"),zero_init)); //SETTINGS static int RET_setting_firmware __attribute__((section("noinit"),zero_init)); static uint8_t RET_setting_location_accuracy __attribute__((section("noinit"),zero_init)); static uint32_t RET_setting_location_tx_interval_mins __attribute__((section("noinit"),zero_init)); 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_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)); static time_t RET_setting_motion_stop_seconds __attribute__((section("noinit"),zero_init)); static uint16_t RET_setting_impact_g __attribute__((section("noinit"),zero_init)); static uint8_t RET_setting_impact_alert __attribute__((section("noinit"),zero_init)); static uint16_t RET_setting_connection_timeout __attribute__((section("noinit"),zero_init)); static uint16_t RET_setting_beacon_interval_seconds __attribute__((section("noinit"),zero_init)); static uint16_t RET_setting_beacon_scan __attribute__((section("noinit"),zero_init)); //STATE static uint8_t RET_coldBoot __attribute__((section("noinit"),zero_init)); static bool RET_haveSettings __attribute__((section("noinit"),zero_init)); static uint8_t RET_state __attribute__((section("noinit"),zero_init)); static uint8_t RET_state_prev __attribute__((section("noinit"),zero_init)); static uint8_t RET_buttonPressCount __attribute__((section("noinit"),zero_init)); static time_t RET_buttonPressTime __attribute__((section("noinit"),zero_init)); static time_t RET_buttonReleaseTime __attribute__((section("noinit"),zero_init)); static time_t RET_buttonHoldTime __attribute__((section("noinit"),zero_init)); static time_t RET_RTCunixtime __attribute__((section("noinit"),zero_init)); static long RET_RTCmicros __attribute__((section("noinit"),zero_init)); //MOTION STATE static bool RET_motionTriggered __attribute__((section("noinit"),zero_init)); static time_t RET_motionStartTime __attribute__((section("noinit"),zero_init)); static time_t RET_motionStopTime __attribute__((section("noinit"),zero_init)); static bool RET_motionPendingOnState __attribute__((section("noinit"),zero_init)); static bool RET_motionPendingOffState __attribute__((section("noinit"),zero_init)); static bool RET_motionState __attribute__((section("noinit"),zero_init)); static float RET_motionTotalActivityHours __attribute__((section("noinit"),zero_init)); static char RET_activityData[100] __attribute__((section("noinit"),zero_init)); //IMPACT static bool RET_impactTriggered __attribute__((section("noinit"),zero_init)); //EVENT HANDLING static time_t RET_eventTime_location_log __attribute__((section("noinit"),zero_init)); static time_t RET_eventTime_location_tx __attribute__((section("noinit"),zero_init)); static time_t RET_eventTime_environmental_log __attribute__((section("noinit"),zero_init)); 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)); #elif defined ( __GNUC__ ) #elif defined ( __ICCARM__ ) #endif //------------------------------------------------------------------------------ //GPIO //------------------------------------------------------------------------------ InterruptIn button(PN_IN_BUTTON); //This causes wake from sleep DigitalOut vreg_en(PN_VREG_EN); //------------------------------------------------------------------------------ //PERIPHERALS //------------------------------------------------------------------------------ //BLE myble; extern WatchdogTimer watchdog(240.0); //Do not set to less than 4500ms or can cause issues with softdevice //SERIAL DEBUG? #if CONSOLE_DEBUG Serial uart(PN_UART_TX, PN_UART_RX, 115200); #endif //------------------------------------------------------------------------------ //TIMERS //------------------------------------------------------------------------------ LowPowerTicker RTCticker; //no impact on power consumption //------------------------------------------------------------------------------ //THREAD SEMAPHORES //------------------------------------------------------------------------------ Semaphore mainthread; //------------------------------------------------------------------------------ //SINGLETONS //------------------------------------------------------------------------------ //NVStore &nvstore = NVStore::get_instance(); //------------------------------------------------------------------------------ // LOW LEVEL FUNCS //------------------------------------------------------------------------------ void turnOffEverything() { vreg_en = 0; LED1off(); } void gotoSleep(long sleep_milliseconds) { turnOffEverything(); watchdog.kick(); if (GLOBAL_requireSoftReset) { //dont need to clear this var as reset changes it back to false system_reset(); } mainthread.wait(sleep_milliseconds); } void RTCtick() { RET_RTCmicros += 100; RET_RTCunixtime = (RET_RTCmicros / 1000); GLOBAL_RTCunixtime = RET_RTCunixtime; //button logic - check for hold if (RET_buttonHoldTime > 4000) { RET_buttonHoldTime = 0; RET_buttonPressCount = 0; RET_state_prev = RET_state; RET_state = STATE_BUTTONHOLD; mainthread.release(); } else { if((RET_RTCmicros - RET_buttonPressTime) > 500) { switch (RET_buttonPressCount) { case 1 : RET_state_prev = RET_state; RET_state = STATE_BUTTONPRESS1; mainthread.release(); break; case 2 : RET_state_prev = RET_state; RET_state = STATE_BUTTONPRESS2; mainthread.release(); break; default : //do nothing break; } RET_buttonPressCount = 0; } } } void factoryReset() { DEBUG("Factory Reset \n"); Thread::wait(500); //wait to ensure that devices are turned off //IDENTITY RET_imei = 0; memset(RET_pf_identifier,0,sizeof(RET_pf_identifier)); //SETTINGS RET_setting_firmware = 0; RET_setting_location_accuracy = 1; RET_setting_location_tx_interval_mins = 1440; RET_setting_location_tx_failsafe_hrs = (7*24); //7 days RET_setting_location_timeout = 180; RET_setting_activity_tx_interval_mins = 0; RET_setting_environmental_tx_interval_mins = 0; RET_setting_motion_g = 11; RET_setting_motion_start_seconds = 120; RET_setting_motion_stop_seconds = 120; RET_setting_impact_g = 0; RET_setting_impact_alert = 0; RET_setting_connection_timeout = 180; RET_setting_beacon_interval_seconds = 10; RET_setting_beacon_scan = 0; //STATE RET_coldBoot = 1; RET_haveSettings = 0; RET_state = STATE_SETUP; RET_state_prev = RET_state; RET_RTCunixtime = 0; RET_RTCmicros = 0; RET_buttonPressCount = 0; RET_buttonPressTime = 0; RET_buttonReleaseTime = 0; RET_buttonHoldTime = 0; RET_RTCunixtime = 0; RET_RTCmicros = 0; //MOTION STATE RET_motionTriggered = 0; RET_motionStartTime = 0; RET_motionStopTime = 0; RET_motionPendingOnState = 0; RET_motionPendingOffState = 0; RET_motionState = 0; RET_motionTotalActivityHours = 0.0; memset(RET_activityData,0,sizeof(RET_activityData)); //IMPACT RET_impactTriggered = 0; //EVENT HANDLING RET_eventTime_location_log = 0; RET_eventTime_location_tx = 0; RET_eventTime_environmental_log = 0; RET_eventTime_environmental_tx = 0; RET_eventTime_activity_tx = 0; RET_eventTime_wakeFromDormant = 0; //OTHER LOCAL GLOBALS GLOBAL_requireSoftReset = false; //PERIPHERAL RESET lis3dh_configureForSleep(10,127); } void copyRETtoGLOBAL() { GLOBAL_imei = RET_imei; } void selfTest() { //Accelerometer 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); } } //------------------------------------------------------------------------------ // USER BUTTON HANDLING //------------------------------------------------------------------------------ void buttonPress() { RET_buttonPressTime = RET_RTCmicros; } void buttonRelease() { RET_buttonHoldTime = (RET_RTCmicros - RET_buttonPressTime); //debounce catch if((RET_RTCmicros - RET_buttonPressTime) >= 100) { RET_buttonPressCount ++; } } //------------------------------------------------------------------------------ // MOTION FUNCS //------------------------------------------------------------------------------ void checkMotion() { if (lis3dh_int2) { if (GLOBAL_debugLED) LED1blink(2,100); RET_motionTriggered = true; GLOBAL_needToConfigureLis3dh = true; //interrupt has fire so need to clear it if (!RET_motionPendingOnState) { RET_motionPendingOnState = true; RET_motionPendingOffState = false; // Log start motion time RET_motionStartTime = RET_RTCunixtime; } } else { if (GLOBAL_debugLED) LED1blink(2,500); RET_motionTriggered = false; RET_motionPendingOnState = false; if (!RET_motionPendingOffState) { RET_motionPendingOffState = true; //log stop motion time RET_motionStopTime = RET_RTCunixtime; } } //calculate motion state if (RET_motionPendingOnState) { //check if above threshold time_t inMotionForSeconds = (RET_RTCunixtime - RET_motionStartTime); if (inMotionForSeconds >= RET_setting_motion_start_seconds) { RET_motionState = true; if (GLOBAL_debugLED) LED1blink(10,100); } } if (RET_motionPendingOffState) { time_t noMotionForSeconds = (RET_RTCunixtime - RET_motionStopTime); if (noMotionForSeconds >= RET_setting_motion_stop_seconds) { RET_motionState = false; RET_motionTotalActivityHours += (float(RET_motionStopTime - RET_motionStartTime) / 3600.0); if (GLOBAL_debugLED) LED1blink(5,500); } } } //------------------------------------------------------------------------------ // UPDATE OPERATING SETTINGS //------------------------------------------------------------------------------ bool saveSettings(char* settingsBuffer) { //process result int matchCount = 0; char TEMP_a[6]; int TEMP_b = 0; int TEMP_c = 0; int TEMP_d = 0; int TEMP_e = 0; int TEMP_f = 0; int TEMP_g = 0; int TEMP_h = 0; int TEMP_i = 0; int TEMP_j = 0; int TEMP_k = 0; int TEMP_l = 0; int TEMP_m = 0; int TEMP_n = 0; time_t TEMP_o = 0; if ( (matchCount = sscanf(settingsBuffer,"a:%c%c%c%c%c%c,b:%d,c:%d,d:%d,e:%d,f:%d,g:%d,h:%d,i:%d,j:%d,k:%d,l:%d,m:%d,n:%d,0:%u", &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) ) > 0 ) { DEBUG("VALUES: a:%s,b:%d,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\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); RET_haveSettings = true; return true; } else { RET_haveSettings = false; return false; } } //------------------------------------------------------------------------------ // SETUP //------------------------------------------------------------------------------ bool setup() { DEBUG("SETUP\n"); bool pass = true; Modem modem(PN_UART_TX, PN_UART_RX, PN_UART_CTS, PN_UART_RTS, PN_GSM_PWR_KEY, PN_VREG_EN); if (modem.on()) { RET_imei = modem.getIMEI(); GLOBAL_imei = RET_imei; DEBUG("imei: %lld \n",RET_imei); if (modem.registerOnNetwork(3,60000)) { char* bytestosend; sprintf(bytestosend,"(im:%lld,%s,v:%.2f,fr:1,z:SETUP,c:1)\0",GLOBAL_imei,GLOBAL_defaultApi,GLOBAL_voltage); char* result = modem.USSDmessage(bytestosend, false, 2, GLOBAL_defaultApi); if (result != "err") { DEBUG("result: %s \n",result); saveSettings(result); } } else { //FAILUREMODE modem failed to register on network } } else { pass = false; //FAILUREMODE Modem failed to turn on } //while (1) { // Thread::wait(60000); // watchdog.kick(); //} //RESULT if (pass) { return true; } else { return false; } } //------------------------------------------------------------------------------ // STATE ENGINE //------------------------------------------------------------------------------ void mainStateEngine() { DEBUG("StateEngine:%d \n",RET_state); switch(RET_state) { case STATE_SETUP : factoryReset(); if (setup()) { copyRETtoGLOBAL(); RET_state = STATE_NORMAL; } break; case STATE_NORMAL : //check and log motion checkMotion(); //EVENTS //Location if(RET_RTCunixtime > RET_eventTime_location_log && RET_eventTime_location_log > 0) { //getdata_environmental(); //event_location_log(); } if(RET_RTCunixtime > RET_eventTime_location_tx && RET_eventTime_location_tx > 0) { //getdata_battery(); //event_location_broadcast(); } //Environmental 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); } if(RET_RTCunixtime > RET_eventTime_environmental_tx && RET_eventTime_environmental_tx > 0) { //event_environmental_bc(); //Filesystem filesystem(PN_SPI_MOSI,PN_SPI_MISO,PN_SPI_CLK,PN_SPI_CS1); } //Activity if(RET_RTCunixtime > RET_eventTime_activity_tx && RET_eventTime_activity_tx > 0) { //event_activity_bc(); } break; case STATE_DORMANT : if (RET_RTCunixtime > RET_eventTime_wakeFromDormant) { RET_state = STATE_NORMAL; } break; case STATE_BUTTONPRESS1 : LED1blink(1,300); RET_state = RET_state_prev; break; case STATE_BUTTONPRESS2 : LED1blink(3,300); RET_state = RET_state_prev; break; case STATE_BUTTONHOLD : LED1blink(10,300); RET_eventTime_wakeFromDormant = (RET_RTCunixtime + (48*3600)); //48hrs RET_state = STATE_DORMANT; break; default : RET_state = STATE_SETUP; } } //------------------------------------------------------------------------------ // MAIN //------------------------------------------------------------------------------ int main() { RTCticker.attach(&RTCtick, 0.1); turnOffEverything(); button.fall(&buttonPress); //does this affect power? button.rise(&buttonRelease); //CHECK IF THIS IS RESET //0x00000004 == soft reset //0x00000002 == watchdog //0x00000001 == button/hardreset if (NRF_POWER->RESETREAS != 0xffffffff) { switch(NRF_POWER->RESETREAS) { case 0x00000001 : DEBUG("reset_reason: 0x%08x. - Hard Reset\n",NRF_POWER->RESETREAS); RET_coldBoot = 1; break; case 0x00000002 : DEBUG("reset_reason: 0x%08x. - Watchdog\n",NRF_POWER->RESETREAS); break; case 0x00000004 : DEBUG("reset_reason: 0x%08x. - Soft reset\n",NRF_POWER->RESETREAS); break; } NRF_POWER->RESETREAS = 0xffffffff; } //CHECK FOR FIRST BOOT if (RET_coldBoot == 1) factoryReset(); //COPY ESSENTIAL VALUES FROM RET TO GLOBAL copyRETtoGLOBAL(); while(true) { //SLEEP if (RET_coldBoot != 1) gotoSleep(10000); //THIS HAS TO BE THE FIRST ITEM IN THE MAIN LOOP watchdog.kick(); //LOG START TIME GLOBAL_wakeTime = RET_RTCunixtime; //MAIN LOGIC DEBUG("State: %i time: %i, %i, %i, %i \n", RET_state, RET_RTCmicros, RET_RTCunixtime, RET_buttonHoldTime, RET_buttonPressCount); mainStateEngine(); //PRE-SLEEP ACTIONS if (GLOBAL_needToConfigureLis3dh) { //ONLY RESET ACCELL IF WE NEED TO lis3dh_configureForSleep(10,127); } RET_coldBoot = 0; } }