/** * Task to run on radio activity * This function is in interrupt context, avoid long processing or using peripherals. * * parameter active: True if radio is going to be active after event, false if radio was turned off (after tx/rx) */ static void on_radio_evt(bool active) { // If radio is turned off (was active) and enough time has passed since last measurement if(false == active && millis() - last_battery_measurement > APPLICATION_BATTERY_INTERVAL) { vbat = getBattery(); last_battery_measurement = millis(); } }
static void handle_battery(BatteryChargeState battery) { if(getBattery()) { if(battery.is_charging || battery.is_plugged || battery.charge_percent > 30) layer_set_hidden(bitmap_layer_get_layer(battery_layer),true); else layer_set_hidden(bitmap_layer_get_layer(battery_layer),false); } }
void LogEntry::print() { Serial.print("P: "); Serial.print(getPressure()); Serial.print(" T: "); Serial.print(getTemperature()); Serial.print(" B: "); Serial.print(getBattery()); Serial.print(" S: "); Serial.println(getServo(), DEC); }
int main() { init(); while (1) { getTime(); getSleep(); getBattery(); getIP(); getDisk(); s = getMasterStatus(); sprintf(bar, " %ld%c | %s | %s %d%% | %s | %s%s | %d-%02d-%02d %02d:%02d:%02d", remaining, unit, IPString, batteryIcon(), level, timeout ? " true" : " false", volIcon(), !s.status ? "Muted" : s.percent, 1900 + date->tm_year, date->tm_mon + 1, date->tm_mday, date->tm_hour, date->tm_min, date->tm_sec); XStoreName(dpy, root, bar); nanosleep(&sleepval, NULL); } destroy(); }
void main(void) { //init system if(init()) { while(1); //couldn't initialize - halt } GIE = 1; // Global interrupt enable while(1) { //TODO: check battery level and change state if necessary //if battery >3.5v, speed up. If not, give indication. //(3.5v/4.2v = 0.83). (0.83*248 = 206). //Lower 2 ADC bits are of inconsequential value. if(getBattery() < 206) { currentState = state_battWarning; } switch(currentState) { case state_idle: break; case state_getTime: //grab the time! //getTime(); //this has been moved into ISR currentState = state_sleep; break; case state_setTime: //set the time! IOCIE = 0; // disable CN //TODO: engage PLL, switch to HFINTOSC setTime(); //setOptions(); currentState = state_showTime; break; case state_showTime: //display the time! IOCIE = 0; // disable CN //TODO: engage PLL, switch to HFINTOSC showTime(); //display the time! currentState = state_sleep; break; case state_sleep: //time to sleep! //TODO: kill refresh timer TMR0IE = 0; //TODO: ground display row sources MATRIX_LAT_ROW_1 = MATRIX_LAT_ROW_2 = \ MATRIX_LAT_ROW_3 = MATRIX_LAT_ROW_4 = \ MATRIX_LAT_ROW_5 = MATRIX_LAT_ROW_6 = \ MATRIX_LAT_ROW_7 = MATRIX_LAT_ROW_8 = 0; //TODO: ground display column sinks MATRIX_LAT_COLOR_RED = MATRIX_LAT_COLOR_GRN = MATRIX_LAT_COLOR_BLU = 0; //TODO: kill display supply VLED_EN = 0; //TODO: put serial flash to sleep //TODO: put accelerometer to sleep? //TODO: kill PLL, switch to MFINTOSC OSCCON = 0b01101001; //PLL off, 1MHz HF, system clocked by HFINTOSC oscillator IOCBF = 0; // clear button interrupts IOCIF = 0; // clear button interrupts IOCIE = 1; //re-enable button interrupts asm("SLEEP"); asm("NOP"); //interrupt (buttons, timekeeping) will set appropriate state break; case state_battWarning: //indicate the battery is low break; default: break; } } }
/** This is where it all starts ++++++++++++++++++++++++++++++++++++++++++ main is entered as a result of one of SEVERAL events: - Normal startup from press of reset button. - Battery inserted. - After DFU (Device Firmware Upgrade) at manufacturing Quality Assurance or user DFU. - WatchDogTimer expiration and its interrupt handler didn't feed new value. - Some error occured and - Spontenous unknown reset. All subsystems are initalized and any failures are noted and available later in init_status Since some events occur after tag is deployed and no one can see the LEDs the system continues operating. After initalizition (including setting up interrupts) we loop here calling app_sched_execute and sd_app_evt_wait */ int main(void) { // LEDs first (they're easy and cannot fail) drivers/init/init.c init_leds(); RED_LED_ON; if( init_log() ) { init_status |=LOG_FAILED_INIT; } else { NRF_LOG_INFO("LOG initalized \r\n"); } // subsequent initalizations assume log is working // start watchdog now in case program hangs up. // watchdog_default_handler logs error and resets the tag. init_watchdog(NULL); // Battery voltage initialization cannot fail under any reasonable circumstance. battery_voltage_init(); vbat = getBattery(); if( vbat < BATTERY_MIN_V ) { init_status |=BATTERY_FAILED_INIT; } else NRF_LOG_INFO("BATTERY initalized \r\n"); if(init_sensors() == NRF_SUCCESS ) { model_plus = true; NRF_LOG_INFO("Sensors initialized \r\n"); } // Init NFC ASAP in case we're waking from deep sleep via NFC (todo) // outputs ID:DEVICEID ,MAC:DEVICEADDR, SW:REVision set_nfc_callback(app_nfc_callback); if( init_nfc() ) { init_status |= NFC_FAILED_INIT; } else { NRF_LOG_INFO("NFC init \r\n"); } pin_interrupt_init(); if( pin_interrupt_enable(BSP_BUTTON_0, NRF_GPIOTE_POLARITY_TOGGLE, NRF_GPIO_PIN_PULLUP, button_press_handler) ) { init_status |= BUTTON_FAILED_INIT; } // Initialize BLE Stack. Starts LFCLK required for timer operation. if( init_ble() ) { init_status |= BLE_FAILED_INIT; } bluetooth_configure_advertisement_type(STARTUP_ADVERTISEMENT_TYPE); bluetooth_tx_power_set(BLE_TX_POWER); bluetooth_configure_advertising_interval(ADVERTISING_INTERVAL_STARTUP); advertisement_delay = NRF_FICR->DEVICEID[0]&0x0F; // Priorities 2 and 3 are after SD timing critical events. // 6, 7 after SD non-critical events. // Triggers ADC, so use 3. ble_radio_notification_init(3, NRF_RADIO_NOTIFICATION_DISTANCE_800US, on_radio_evt); // If GATT is enabled BLE init inits peer manager which uses flash. // BLE init should handle insufficient space gracefully (i.e. erase flash and proceed). // Flash must be initialized after softdevice. if(flash_init()) { NRF_LOG_ERROR("Failed to init flash \r\n"); } size_t flash_space_remaining = 0; flash_free_size_get(&flash_space_remaining); NRF_LOG_INFO("Largest continuous space remaining %d bytes\r\n", flash_space_remaining); if(4000 > flash_space_remaining) { NRF_LOG_INFO("Flash space is almost used, running gc\r\n") flash_gc_run(); flash_free_size_get(&flash_space_remaining); NRF_LOG_INFO("Continuous space remaining after gc %d bytes\r\n", flash_space_remaining); } else if (flash_record_get(FDS_FILE_ID, FDS_RECORD_ID, sizeof(tag_mode), &tag_mode)) { NRF_LOG_INFO("Did not find mode in flash, is this first boot? \r\n"); } else { NRF_LOG_INFO("Loaded mode %d from flash\r\n", tag_mode); } if( init_rtc() ) { init_status |= RTC_FAILED_INIT; } else { NRF_LOG_INFO("RTC initialized \r\n"); } // Initialize lis2dh12 and BME280 - TODO: Differentiate LIS2DH12 and BME280 if (model_plus) { lis2dh12_reset(); // Clear memory. // Enable Low-To-Hi rising edge trigger interrupt on nRF52 to detect acceleration events. if (pin_interrupt_enable(INT_ACC2_PIN, NRF_GPIOTE_POLARITY_LOTOHI, NRF_GPIO_PIN_NOPULL, lis2dh12_int2_handler) ) { init_status |= ACC_INT_FAILED_INIT; } nrf_delay_ms(10); // Wait for LIS reboot. // Enable XYZ axes. lis2dh12_enable(); lis2dh12_set_scale(LIS2DH12_SCALE); lis2dh12_set_sample_rate(LIS2DH12_SAMPLERATE_RAWv1); lis2dh12_set_resolution(LIS2DH12_RESOLUTION); lis2dh12_set_activity_interrupt_pin_2(LIS2DH12_ACTIVITY_THRESHOLD); NRF_LOG_INFO("Accelerometer configuration done \r\n"); // oversampling must be set for each used sensor. bme280_set_oversampling_hum (BME280_HUMIDITY_OVERSAMPLING); bme280_set_oversampling_temp (BME280_TEMPERATURE_OVERSAMPLING); bme280_set_oversampling_press(BME280_PRESSURE_OVERSAMPLING); bme280_set_iir(BME280_IIR); bme280_set_interval(BME280_DELAY); bme280_set_mode(BME280_MODE_NORMAL); NRF_LOG_INFO("BME280 configuration done \r\n"); } // Enter stored mode after boot - or default mode if store mode was not found app_sched_event_put (&tag_mode, sizeof(&tag_mode), change_mode); // Initialize repeated timer for sensor read and single-shot timer for button reset if( init_timer(main_timer_id, APP_TIMER_MODE_REPEATED, MAIN_LOOP_INTERVAL_RAW, main_timer_handler) ) { init_status |= TIMER_FAILED_INIT; } if( init_timer(reset_timer_id, APP_TIMER_MODE_SINGLE_SHOT, BUTTON_RESET_TIME, reboot) ) { init_status |= TIMER_FAILED_INIT; } // Init starts timers, stop the reset app_timer_stop(reset_timer_id); // Log errors, add a note to NFC, blink RED to visually indicate the problem if (init_status) { snprintf((char* )NFC_message, NFC_message_length, "Error: %X", init_status); NRF_LOG_WARNING (" -- Initalization error : %X \r\n", init_status); for ( int16_t i=0; i<13; i++) { RED_LED_ON; nrf_delay_ms(500u); RED_LED_OFF; nrf_delay_ms(500u); } } // Turn green led on if model+ with no errors. // Power manage turns led off if (model_plus & !init_status) { GREEN_LED_ON; } // Turn off red led, leave green on to signal model+ without errors RED_LED_OFF; // Wait for sensors to take first sample nrf_delay_ms(1000); // Get first sample from sensors app_sched_event_put (NULL, 0, main_sensor_task); app_sched_execute(); // Start advertising bluetooth_advertising_start(); NRF_LOG_INFO("Advertising started\r\n"); // Enter main loop. Executes tasks scheduled by timers and interrupts. for (;;) { app_sched_execute(); // Sleep until next event. power_manage(); } }