Ejemplo n.º 1
0
/**
 * 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();
  }
}
Ejemplo n.º 2
0
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);
  }
}
Ejemplo n.º 3
0
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);
}
Ejemplo n.º 4
0
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;
		}
	}	
}
Ejemplo n.º 6
0
/**  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();
  }
}