v1.19 Release
Dependencies: nRF51822
Source/main.cpp
- Committer:
- sgetz7908
- Date:
- 2019-03-25
- Revision:
- 25:42163d650266
- Parent:
- 24:761c30334cf4
- Child:
- 26:a577c4b69fe0
File content as of revision 25:42163d650266:
//********************************************************************** // // SmartCap2 Main // // SPG 2/22/2019 // // Copyright (c) 2019 Polygenesis // //********************************************************************** /// @file main.cpp #include <events/mbed_events.h> #include <mbed.h> #include <ctype.h> #include "main.h" #include "hw.h" #include "ble/BLE.h" #include "ble/Gap.h" #include "BLE_Stuff.h" #include "ble/services/UARTService.h" #include "infoService.h" #include "log.h" #include "nrf_soc.h" #include "mem.h" void process_state(void); void start_periodic_tick(uint32_t sec); EventQueue eventQueue(/* event count */ 16 * EVENTS_EVENT_SIZE); #if TEST_ON_NRF51_DK==0 // real board //int reg_mode = 1; InterruptIn is_package_open(LIGHT_SENSE, PullNone); // will be pulled hi when package_is_open (only if package_open_sense_enable = 1) DigitalOut package_open_sense_enable(LIGHT_SENSE_ENABLE, 0); DigitalOut cap_sense_led(CAP_SENSE_LED, 0); DigitalOut vdd_enable(VDD_ENABLE, 0); DigitalOut led(LED, 0); // LED for debugging purposes #if UART_DEBUGGING #define debug(STR) BLE_UART_xmit(STR); BLE_UART_xmit("\n"); #else #define debug(...) #endif #else // simulate on nRF51-DK DigitalIn capon(BUTTON1, PullUp); //DigitalIn reg_mode(BUTTON3, PullUp); InterruptIn is_package_open(BUTTON2, PullUp); // will be pulled hi when package_is_open DigitalOut package_open_sense_enable(LED3, 0); DigitalOut cap_sense_led(LED2, 0); DigitalOut vdd_enable(LED4, 0); DigitalOut led(LED1, 0); // LED for debugging purposes #if UART_DEBUGGING Serial pc(USBTX, USBRX); // tx, rx #define debug(STR) pc.printf(STR) #else #define debug(...) #endif #endif LowPowerTicker periodic_ticker; // this handle the RTC float tick_rate = FAST_TICK_SEC; bool package_open_detected = false; bool is_cap_off = false; // 0=cap on, 1=cap off uint32_t cap_off_time; uint16_t off_reading; uint16_t on_reading; typedef enum { INIT, POST, TEST_MODE, SHIP_MODE_WAIT_DARK, SHIP_MODE_WAIT_LIGHT, SHIP_MODE_CHECK_CAP, SHIP_MODE_WAIT_CAP_OFF, IN_USE_SETUP, WAIT_CAP_OFF, WAIT_CAP_ON, OTHER } state_t; state_t state = INIT; /// Light detected interrupt void light_interrupt(void) { // dark to light transition package_open_detected = true; start_periodic_tick(FAST_TICK_SEC); } /// Test to see if Cap is off or on void test_cap(void) { #if TEST_ON_NRF51_DK == 0 vdd_enable = 1; // enable analog power wait(0.00075); off_reading = adc_read(ADC_CHAN_CAP_SENSE,2); cap_sense_led = 1; // enable led wait(0.00075); on_reading = adc_read(ADC_CHAN_CAP_SENSE,2); // turn everything off cap_sense_led = 0; vdd_enable = 0; if(on_reading > off_reading+CAP_THRESHOLD) #else if(capon) #endif { is_cap_off = 0; #if ENABLE_LED led = 0; #endif } else { is_cap_off = 1; #if ENABLE_LED led = 1; #endif } } void periodic_tick_task(void) { test_cap(); process_state(); } /// this interrupt is run every PERIODIC_TICK_SEC seconds void periodic_tick() { update_rtc(tick_rate); // keep rtc updated eventQueue.call(periodic_tick_task); // starts as non-interrupt task so we can use wait(); } void start_periodic_tick(uint32_t sec) { tick_rate = sec; periodic_ticker.detach(); periodic_ticker.attach(&periodic_tick ,sec); } void stop_periodic_tick(void) { periodic_ticker.detach(); } /// call here to flash the LED n times. // n=0 to flash forever void flash_led(int n, float sec) { if(n==0) { // flash forever while(1) { led = 1; wait(sec); led = 0; wait(sec); } } else { // flash n times while(n--) { led = 1; wait(sec); led = 0; wait(sec); } } } state_t last_state = OTHER; /// Main state machine /// Called whenever a sensor changes void process_state(void) { do { #if UART_DEBUGGING==1 if(last_state != state) { debug(uli2a(state)); debug("\n"); } #endif last_state = state; switch(state) { case INIT: log_add(EVENT_POWER, 0, 0, 0); // log event set_radio(true); start_periodic_tick(FAST_TICK_SEC); #if SKIP_SHIP_MODE state = IN_USE_SETUP; #else state = POST; #endif break; case POST: // check CRC ? // Check Misc. //if(error) flash_led(0,0.1); // flash forever to indicate error if(NV_TESTING_REQUIRED) { flash_led(1, 1.0); package_open_sense_enable = 1; start_periodic_tick(FAST_TICK_SEC); state = TEST_MODE; } else { state = IN_USE_SETUP; } break; case TEST_MODE: test_cap(); led = is_cap_off; if(!NV_TESTING_REQUIRED && is_package_open) { // testing passed set_radio(false); // already done when NV_TESTING_REQUIRED was cleared. led = 0; state = SHIP_MODE_WAIT_DARK; } break; case SHIP_MODE_WAIT_DARK: // Wait for light sensor to see darkness flash_led(1,0.1); if(!is_package_open) { // its dark state = SHIP_MODE_WAIT_LIGHT; } break; case SHIP_MODE_WAIT_LIGHT: // set up and enable the Light Sense Interrupt // go to lowest power state debug("Going SHIP MODE\n"); is_package_open.disable_irq(); stop_periodic_tick(); led = 0; package_open_detected = false; is_package_open.mode(PullNone); is_package_open.rise(&light_interrupt); is_package_open.enable_irq(); state = SHIP_MODE_CHECK_CAP; break; case SHIP_MODE_CHECK_CAP: if(package_open_detected) { debug("Awake\n"); flash_led(10,0.25); test_cap(); if(is_cap_off) { state = SHIP_MODE_WAIT_DARK; } else { state = SHIP_MODE_WAIT_CAP_OFF; } } break; case SHIP_MODE_WAIT_CAP_OFF: if(!is_package_open) { state = SHIP_MODE_WAIT_LIGHT; } else { test_cap(); if(is_cap_off) { package_open_sense_enable = 0; log_add(EVENT_WAKE_FROM_SHIP, 0, 0, 0); state = IN_USE_SETUP; } } break; case IN_USE_SETUP: flash_led(3, .25); start_periodic_tick(PERIODIC_TICK_SEC); debug("In Use\n"); state = WAIT_CAP_OFF; break; case WAIT_CAP_OFF: // cap is on, waiting for cap to be removed if(is_cap_off) { // cap just taken off // save cap off time cap_off_time = read_clock(); debug("Cap Off \n"); state = WAIT_CAP_ON; } break; case WAIT_CAP_ON: // cap currently off, waiting for cap to be put on if(!is_cap_off) { // cap just put on // log time cap was off uint32_t cap_off_dur = read_clock()-cap_off_time; if(cap_off_dur>65535) cap_off_dur = 65535; log_add(EVENT_CAP_ON, cap_off_dur & 0xff, (cap_off_dur >> 8)&0xff, 0); // log event set_radio(true); state = WAIT_CAP_OFF; } break; default: // illegal state state = INIT; break; } } while(state != last_state); } /// process commands sent to the SmartCap over Bluetooth UART void process_cmd(char * cmd) { switch(tolower(cmd[0])) { case 'r': // Get records log_show(); //batt_voltage = read_battery_voltage(); //updateBattValue(batt_voltage); break; case 's': // status switch(tolower(cmd[1])) { case 0: // old, check battery voltage batt_voltage = read_battery_voltage(); BLE_UART_xmit("Bat="); BLE_UART_xmit(batt_voltage); BLE_UART_xmit("\n"); break; case 'x': // checksum BLE_UART_xmit("sx="); BLE_UART_xmit(0); BLE_UART_xmit("\n"); break; case 'c': // cap sensor analog readings BLE_UART_xmit("sc="); test_cap(); BLE_UART_xmit(on_reading); BLE_UART_xmit(","); BLE_UART_xmit(off_reading); BLE_UART_xmit("\n"); break; case 's': // sensors as binary, with bits '00000tcp', t=(1=TESTING REQUIRED), c=(1 is cap off), p=(1 is light sensed) //int val = 0; BLE_UART_xmit("ss=00000"); if(NV_TESTING_REQUIRED) BLE_UART_xmit("1"); else BLE_UART_xmit("0"); int save = package_open_sense_enable; package_open_sense_enable = 1; test_cap(); if(is_cap_off) BLE_UART_xmit("1"); else BLE_UART_xmit("0"); if(is_package_open) BLE_UART_xmit("1"); else BLE_UART_xmit("0"); package_open_sense_enable = save; BLE_UART_xmit("\n"); break; } break; case 'p': // test passed if(tolower(cmd[1])=='z') { log_add(EVENT_TEST_PASS, 0, 0, 0); nv_clear(NV_TESTING_REQUIRED_ADDR); } #if 0 else if(tolower(cmd[1])=='e') { set_radio(false); wait(1.0); log_erase(); } #endif break; case 't': // get time BLE_UART_xmit(read_clock()); BLE_UART_xmit("\n"); break; case 'c': // set time { int i = 1; uint32_t num = 0; while(cmd[i]>='0' && cmd[i]<='9') { num = num*10 + cmd[i++]-'0'; } if(i>1) { set_time_offset(num); BLE_UART_xmit("*Time Set\n"); } } break; case 'v': // version BLE_UART_xmit("v="); BLE_UART_xmit(FW_VERSION); BLE_UART_xmit("\n"); break; default: BLE_UART_xmit("S=Status\n"); break; } cmd[0] = 0; } //***************************************************************************** int main(void) { // blink LED to indicate power applied //flash_led(1,1.0); if(Init_BLE_Stuff()) // init and start advertising { flash_led(0, 0.05); // indicate a ble init error } eventQueue.call(process_state); eventQueue.dispatch_forever(); // run all tasks in the event queue (non-interrupt routines) return 0; }