#include #include #include #include #include #include #include #include "lights.h" static unsigned char prev_jiffies_8; static void hw_setup() { init_battery(); init_pwm(); init_adc(); init_tmr(); init_buttons(); init_pwmled(); init_gpio(); init_ambient(); init_pattern(); init_control(); set_sleep_mode(SLEEP_MODE_IDLE); } static void inline hw_suspend() { susp_pwm(); susp_adc(); susp_tmr(); susp_gpio(); susp_ambient(); susp_buttons(); } void power_down(unsigned char err) { hw_suspend(); do { if (err) gpio_set(0, 1); // G'night set_sleep_mode(SLEEP_MODE_PWR_DOWN); sleep_enable(); sleep_bod_disable(); sei(); sleep_cpu(); // G'morning cli(); sleep_disable(); // allow wakeup by long button-press only } while (!buttons_wait_for_release()); // ok, so I will wake up hw_setup(); } static void inline first_boot() { unsigned char mcusr_save; // disable the WDT if running wdt_reset(); mcusr_save = MCUSR; MCUSR = 0; wdt_disable(); if (mcusr_save & _BV(WDRF)) // was watchdog reset? gpio_set(0, 1); init_log(mcusr_save); power_usi_disable(); // Once for lifetime ACSRA |= _BV(ACD); // disable analog comparator log_set_state(3); hw_setup(); power_down(mcusr_save & _BV(WDRF)); prev_jiffies_8 = jiffies; sei(); } static void inline do_timer() { // For now, we run them all in their own atomic blocks ATOMIC_BLOCK(ATOMIC_FORCEON) { timer_check_buttons(); } ATOMIC_BLOCK(ATOMIC_FORCEON) { patterns_next_tick(); } ATOMIC_BLOCK(ATOMIC_FORCEON) { pwm_disable_if_not_needed(); } ATOMIC_BLOCK(ATOMIC_FORCEON) { timer_start_slow_adcs(); } ATOMIC_BLOCK(ATOMIC_FORCEON) { if ((jiffies & 0x7FF) == 0) ambient_log_min_max(); } } static void inline main_loop_iteration() { unsigned char jiffies_8; /* * we use only lower 8-bits in order to * avoid the need for locking of 16-bit * accesses. */ cli(); if (TIMER1_IS_ON()) { set_sleep_mode(SLEEP_MODE_IDLE); } else if (adc_is_on) { set_sleep_mode(SLEEP_MODE_ADC); } else { set_sleep_mode(SLEEP_MODE_PWR_DOWN); } sleep_enable(); // keep BOD active, no sleep_bod_disable(); sei(); sleep_cpu(); sleep_disable(); jiffies_8 = jiffies; if (jiffies_8 != prev_jiffies_8) { // was timer IRQ if (jiffies_8 - prev_jiffies_8 > 1) { // overrun log_byte(0xee); log_byte(jiffies_8 - prev_jiffies_8); log_flush(); } prev_jiffies_8 = jiffies_8; do_timer(); } } int main(void) { first_boot(); while (1) main_loop_iteration(); #if 0 DDRB |= _BV(PB2); while (1) { PORTB |= _BV( PB2 ); _delay_ms(200); PORTB &=~ _BV( PB2 ); _delay_ms(200); } #endif }