init

Dependencies:   aconno_I2C Lis2dh12 WatchdogTimer

main.cpp

Committer:
pathfindr
Date:
2018-11-14
Revision:
6:388d3c7efdd9
Parent:
5:8f8951127724
Child:
7:e9a19750700d

File content as of revision 6:388d3c7efdd9:

#include "main.h"
#include "board.h"
#include "modes.h"

//include "nrf_soc.h"

//#include "ATCommand.h"

//LowPowerTicker ticker; //no impact on power consumption

//------------------------------------------------------------------------------
//Function declarations- Local
//------------------------------------------------------------------------------ 
static void mainStateEngine(void);
static void mode_mtu(void);
static void selftest(void);
static void LEDon(void);
static void LEDoff(void);

//------------------------------------------------------------------------------
//Var declarations- Local
//------------------------------------------------------------------------------ 
bool accel_healthy = false;
bool firstBoot = false;
bool requireSoftReset = false;

//------------------------------------------------------------------------------
//Var declarations- RETAINED NOINIT RAM
//------------------------------------------------------------------------------ 
#if defined ( __CC_ARM )
/** THIS IS THE MBED ONLINE COMPILER TOOLCHAIN*/
static uint8_t          RET_mode                __attribute__((section("noinit"),zero_init));        
static uint32_t         RET_unixtime_backup     __attribute__((section("noinit"),zero_init));
static char             RET_buffer[64]          __attribute__((section("noinit"),zero_init));
#elif defined ( __GNUC__ )
#elif defined ( __ICCARM__ )
#endif

char RET_pf_identifier[9]; //includes null byte at end
int RET_interval_setting = 720;
int RET_interval_hours_failsafe = 24;
int RET_motioncheck_interval_seconds = 60;
int RET_gps_timeout = 180;
int RET_gsm_timeout = 120;
bool RET_gsmtimedout = false;
int RET_beacon_scan = 0;
int RET_accel_awake_thr = 11;
int RET_accel_awake_triggercount = 0;
int RET_accel_alarm_thr = 127;
unsigned long RET_unixtime_configrun = 0;
unsigned long RET_unixtime_lastpost = 0;
unsigned long RET_unixtime_nextpost = 0;
unsigned long RET_unixtime_nextpost_failsafe = 0;
unsigned long RET_unixtime_framestart = 0;
unsigned long RET_motionstarttime = 0;
unsigned long RET_motionstoptime = 0;
int RET_gsm_failcount = 0;
int RET_serverresponse_failcount = 0;
int RET_motionconsecutive = 0;
int RET_no_motionconsecutive = 0;
bool RET_wethinkinmotion = false;
bool RET_wethinkhasmoved = false;
bool RET_haveservertime = false;
float RET_operationTimeHours = 0;
float RET_operationFrameTimeHours = 0;
int RET_operationCount = 0;
char RET_operationTimeString[100];


//------------------------------------------------------------------------------
//Pin states
//------------------------------------------------------------------------------ 
DigitalOut led1(PN_LED);
DigitalOut vreg_en(PN_VREG_EN);
DigitalOut gsm_pwkey(PN_GSM_PWR_KEY);
DigitalOut lis3dh_cs(PN_SPI_CS0);
DigitalOut flash_cs(PN_SPI_CS1);
DigitalIn lis3dh_int1(PN_ACC_INT1); //IMPACT
DigitalIn lis3dh_int2(PN_ACC_INT2); //DISTURBED

//------------------------------------------------------------------------------
//Peripherals
//------------------------------------------------------------------------------ 
//BLE myble;
#if NEED_CONSOLE_OUTPUT
Serial uart(PN_UART_TX, PN_UART_RX, 115200);
#endif
//ATSerial atserial(PN_UART_TX, PN_UART_RX, 115200);
WatchdogTimer watchdog(65.0); //Do not set to less than 4500ms or can cause issues with softdevice

//------------------------------------------------------------------------------
//Singletons
//------------------------------------------------------------------------------
NVStore &nvstore = NVStore::get_instance();



void gotoSleep(long sleep_milliseconds) {
    //accelerometer.configureForSleep();
    
    if (requireSoftReset) { //dont need to clear this var as reset changes it back to false
        RET_unixtime_backup = time(NULL); //save unixtime for reset
        //NVIC_SystemReset();
        system_reset();
    }
    ThisThread::sleep_for(sleep_milliseconds);    
}

void LED1on(long flash_milliseconds = 0) {
    led1 = 0;
    if (flash_milliseconds > 0) {
        ThisThread::sleep_for(flash_milliseconds);
        led1 = 1;
    }
}
void LED1off() {
    led1 = 1;
}

bool GSMon() {
    //power on GSM
    vreg_en = 1;
    ThisThread::sleep_for(500);
    gsm_pwkey = 0;
    ThisThread::sleep_for(1500);
    gsm_pwkey = 1;
    LED1on(1000);
}

void setup_CS_LIS3DH()
{
    //Without this setup CS lines of AT45 & LIS3DH are in conflict, causing huge current consumption    
    lis3dh_cs = 1; //not selected
    flash_cs = 1; //not selected
    //AT_RS = 0; //asserted == reset state
    //wait_ms(100);
    //AT_RS = 1;
}

void lis3dh_configureForSleep() {
    //init
    LIS3DH lis3dh(PN_SPI_MOSI, PN_SPI_MISO, PN_SPI_CS0, PN_SPI_CLK);
    requireSoftReset = true; //WE HAVE STARTED SPI SO NEED THIS
    //Mode
    lis3dh.InitLIS3DH(LIS3DH_NORMAL, LIS3DH_ODR_25Hz, LIS3DH_FULLSCALE_8);   
    lis3dh.LIS3DH_SetIntMode(LIS3DH_INT_MODE_6D_MOVEMENT); 
    //Int1
    lis3dh.LIS3DH_SetInt1Pin(LIS3DH_CLICK_ON_PIN_INT1_DISABLE | LIS3DH_I1_INT1_ON_PIN_INT1_ENABLE |              
                    LIS3DH_I1_INT2_ON_PIN_INT1_DISABLE | LIS3DH_I1_DRDY1_ON_INT1_DISABLE | LIS3DH_I1_DRDY2_ON_INT1_DISABLE |
                    LIS3DH_WTM_ON_INT1_DISABLE | LIS3DH_INT1_OVERRUN_DISABLE );
    lis3dh.LIS3DH_SetInt1Threshold(10);             
    lis3dh.LIS3DH_SetIntConfiguration(LIS3DH_INT1_ZHIE_ENABLE | LIS3DH_INT1_ZLIE_ENABLE |
                                       LIS3DH_INT1_YHIE_ENABLE | LIS3DH_INT1_YLIE_ENABLE |
                                       LIS3DH_INT1_XHIE_ENABLE | LIS3DH_INT1_XLIE_ENABLE );   
    lis3dh.LIS3DH_SetInt1Duration(0);
    lis3dh.LIS3DH_Int1LatchEnable(MEMS_ENABLE);
    //HP filter
    lis3dh.LIS3DH_SetHPFMode(LIS3DH_HPM_AUTORESET_INT);
    lis3dh.LIS3DH_SetFilterDataSel(MEMS_ENABLE);
    lis3dh.LIS3DH_HPFAOI1Enable(MEMS_ENABLE);
    lis3dh.LIS3DH_HPFAOI2Enable(MEMS_ENABLE);
}

void resetState() {
    firstBoot = true;
    
    //RESET VARS
    RET_mode = 0;
    RET_unixtime_backup = 0;
    set_time(RET_unixtime_backup);
    
    //SET IDENTIFIER
    uint32_t nv_value = 12345678;
    int rc = nvstore.set(NV_IDENTIFIER, sizeof(nv_value), &nv_value);
}

void mainStateEngine() {
    
    RET_mode = MODE_NORMAL;
    
    
    switch(RET_mode) {
        case MODE_SETUP :
            resetState();
            //selftest();
            break;
            
        case MODE_NORMAL :
            
            if (RET_requireMotionFlag) {
                   bool MotionFlagTriggered = false;
                   
                   //check interrupt
                   if (lis3dh_int2) {
                       MotionFlagTriggered = true;
                   }
            }
            
            break;
            
        case MODE_DORMANT :
           
            break;
            
        case MODE_OFF_48HRS :
           
            break;
      
        default :
            RET_mode = MODE_SETUP;
    }
}


int main() {
    led1 = 1;
    
    //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);
                resetState();
            break;
            case 0x00000002  :
                DEBUG("reset_reason: 0x%08x. - Watchdog\n",NRF_POWER->RESETREAS);
                set_time(RET_unixtime_backup);
            break;
            case 0x00000004  :
                DEBUG("reset_reason: 0x%08x. - Soft reset\n",NRF_POWER->RESETREAS);
                set_time(RET_unixtime_backup);
            break;
        }
        NRF_POWER->RESETREAS = 0xffffffff;
    }
    
    while(true) {
        //GOTO TO SLEEP
        if (!firstBoot) gotoSleep(60000);
        LED1on(20);
        watchdog.kick();
        
        //MAIN STATE ENGINE
        mainStateEngine();
    }
}



/*
void initMotion() {
    //CHECK FOR ANY MOTION
    if (!accelerometer.selfTest()) {
        if (exceptions.find("A.") < 0) {
            exceptions += "A.";
        }
        DEBUG("Couldnt start accelerometer");
    } else {
        accel_healthy = true;
    }
}
*/

/*
void mode_mtu() {
                bool accel_awake = accelerometer.getINT2();
            
                //CHECK FOR MOTION
                if (accel_awake == true) {
                    LED1on(50);
                    RET_motionconsecutive ++;
                    RET_no_motionconsecutive = 0;
                    
                    //this is needed to ensure accel_awake_triggercount is 1 or higher for mode 2
                    if (RET_accel_awake_triggercount == 0) {
                        RET_accel_awake_triggercount = 1;
                    }
                    
                    if (RET_motionconsecutive == RET_accel_awake_triggercount && RET_wethinkinmotion == false) {
                        RET_wethinkinmotion = true;
                        RET_motionstarttime = (time(NULL) - ((RET_accel_awake_triggercount+1) * RET_motioncheck_interval_seconds));
                        long eventEpoch = RET_motionstarttime;
                        long epochoffsetminutes = ((eventEpoch - RET_unixtime_framestart) / 60);
                        
                        char buf[20];
                        sprintf(buf,"1.%i!", epochoffsetminutes); 
                        strcat(RET_operationTimeString, buf);
                        RET_operationCount ++;

                        DEBUG("%s", RET_operationTimeString);
                        
                        LEDon(100);
                        LEDon(100);
                        LEDon(100);
                        LEDon(100);
                    }
                } else if (accel_awake == false) {
                    RET_no_motionconsecutive ++;
                    RET_motionconsecutive = 0;
                      if (RET_no_motionconsecutive == RET_accel_awake_triggercount && RET_wethinkinmotion == true) {
                        RET_wethinkinmotion = false;
                        // log engine stop
                        RET_motionstoptime = (time(NULL) - ((RET_accel_awake_triggercount+1) * RET_motioncheck_interval_seconds));
                        long eventEpoch = RET_motionstoptime;
                        long epochoffsetminutes = ((eventEpoch - RET_unixtime_framestart) / 60);
                        
                        char buf[20];
                        sprintf(buf,"0.%i!", epochoffsetminutes); 
                        strcat(RET_operationTimeString, buf);
                        
                        RET_operationFrameTimeHours = (float(RET_motionstoptime - RET_motionstarttime) / 3600.0);
                        RET_operationTimeHours += RET_operationFrameTimeHours;
                        
                        //test by posting on every stop event
                        //doOperationTimePost = true;
                        
                        DEBUG("%i", RET_operationTimeHours);
                        LEDon(500);
                    }
                }
            

            // Check time interval for location run
            if (time(NULL) > RET_unixtime_nextpost_failsafe) {
                //setfailsafetime(); //these must be before gpsPost, incase gpsPost fails, then stuck in broadcast loop
                //gpsPost();
            }
            
            //Check for operatingTime post time or if data buffer is full for force post
            if (RET_operationFrameTimeHours > 0.0) {
                if (time(NULL) > RET_unixtime_nextpost || strlen(RET_operationTimeString) > 60) {
                    //only bother if we actual have data to post
                    //setwaketime(); //these must be before gpsPost, incase gpsPost fails, then stuck in broadcast loop
                    //uploadOperationTimeData();
                }
            }   

}
*/





/*

int selftest() {
    int result = 0;
    int tests = 0;
    int testscore = 0;
    led1 = 0;
    string failures;
    
    //Accelerometer
    tests ++;
    if (accelerometer.read_id() == 51){
        testscore ++;
    } else {
        //Accelerometer Fail
        failures += 'Ac,';
    };
    
    return result;   
}
*/


/*
void readRegs(uint8_t addr, uint8_t * data, int len) {
    lis3dh_cs = 0;
    for (int i = 0 ; i < len ; i++ ) {    
       spi.write((addr+i)|0x80) ;  // specify address to read
       data[i] = spi.write((addr+i)|0x80) ; 
    } 
    spi.write(0x00) ; // to terminate read mode
    lis3dh_cs = 1;
}

uint8_t read_reg(uint8_t addr)
{
    uint8_t data[1] ;    
    readRegs(addr, data, 1) ;
    return( data[0] ) ;
}
*/












/*
//OPTION 1
    // Switch on both RAM banks when in System OFF mode.
    NRF_POWER->RAMON |= (POWER_RAMON_OFFRAM0_RAM0On << POWER_RAMON_OFFRAM0_Pos) | 
                    (POWER_RAMON_OFFRAM1_RAM1On << POWER_RAMON_OFFRAM1_Pos);

    // Enter System OFF and wait for wake up from GPIO detect signal.
    NRF_POWER->SYSTEMOFF = 0x1;
    

    //spi.close();
    
    //delete spi;  
    //spi_disable();
    
    //spi_free(spi);
    
    //nrf_drv_spi_uninit(spi);
    //nordic_nrf5_spi_initialized[instance] = false;
    //HFCLKSTOP = 0x1;
    
    NRF_SPI0->ENABLE = 0;
    NRF_SPI1->ENABLE = 0;
    NRF_SPI2->ENABLE = 0;
    NRF_TWI0->ENABLE = 0;
    NRF_TWI1->ENABLE = 0;
    
    sd_clock_hfclk_release();
    NRF_POWER->SYSTEMOFF=1;
    //NRF_SPI0->POWER = 0;

    //OPTION 3
    
    *(volatile uint32_t *)0x40003FFC = 0;
    *(volatile uint32_t *)0x40003FFC;
    *(volatile uint32_t *)0x40003FFC = 1;
    
    NRF_SPI0->ENABLE = (SPI_ENABLE_ENABLE_Disabled << SPI_ENABLE_ENABLE_Pos); 
    NRF_SPI1->ENABLE = (SPI_ENABLE_ENABLE_Disabled << SPI_ENABLE_ENABLE_Pos); 
    
    
    if (sleep_manager_can_deep_sleep()) {
        ThisThread::sleep_for(10000);
    } else { 
        led1 = 0;
        wait(50.0);
    }
    
    //system_reset();
*/


        //time_t unixtime = time(NULL);
        //DEBUG("got: %i, %d, %d \n", RET_mode, RET_unixtime, unixtime);
     
/*
uint8_t acc_id;
        lis3dh.LIS3DH_GetWHO_AM_I(&acc_id);
        uart.printf("%i \n\r", acc_id);
        */   
        
/*
 AxesRaw_t                   accel_raw; 
        lis3dh.LIS3DH_GetAccAxesRaw(&accel_raw);
        
        uart.printf("x=");
        uart.printf("%i", accel_raw.AXIS_X);
        uart.printf("   y=");
        uart.printf("%i", accel_raw.AXIS_Y);
        uart.printf("   z=");
        uart.printf("%i", accel_raw.AXIS_Z);
        uart.printf("\n\r");
*/