]> www.fi.muni.cz Git - bike-lights.git/blobdiff - firmware/main.c
mudflap for dual rearlights
[bike-lights.git] / firmware / main.c
index ea3bb69d1384dd5840c5e6a90066dda0807a229c..b3fcc654099c4adacf9dd0262dd6d18066e53499 100644 (file)
@@ -1,5 +1,6 @@
 #include <avr/io.h>
 #include <util/delay.h>
+#include <util/atomic.h>
 #include <avr/sleep.h>
 #include <avr/interrupt.h>
 #include <avr/power.h>
@@ -7,87 +8,75 @@
 
 #include "lights.h"
 
+static unsigned char prev_jiffies_8;
+
 static void hw_setup()
 {
-       wdt_enable(WDTO_1S);
        init_battery();
        init_pwm();
        init_adc();
        init_tmr();
        init_buttons();
 
-       pwmled_init();
-       gpio_init();
-       ambient_init();
-       pattern_init();
+       init_pwmled();
+       init_gpio();
+       init_ambient();
+       init_pattern();
+       init_control();
 
        set_sleep_mode(SLEEP_MODE_IDLE);
 }
 
-static void hw_suspend()
+static void inline hw_suspend()
 {
        susp_pwm();
        susp_adc();
        susp_tmr();
        susp_gpio();
-       wdt_disable();
+       susp_ambient();
+       susp_buttons();
 }
 
-
-void power_down()
+void power_down(unsigned char err)
 {
-       uint16_t wake_count = 0;
-       unsigned char btn;
-
        hw_suspend();
-sleep_again:
-       // enable PCINT14, so that user can wake up later
-        GIMSK |= _BV(PCIE1);
-        PCMSK1 |= _BV(PCINT14);
-
-       // G'night
-        set_sleep_mode(SLEEP_MODE_PWR_DOWN);
-        sleep_enable();
-        sleep_bod_disable();
-        sei();
-        sleep_cpu();
-
-       // G'morning
-       cli();
 
-        sleep_disable();
+       do {
+               if (err)
+                       gpio_set(0, 1);
 
-       // Disable PCINT14
-       GIMSK &= ~_BV(PCIE1);
-       PCMSK1 &= ~_BV(PCINT14);
+               // G'night
+               set_sleep_mode(SLEEP_MODE_PWR_DOWN);
+               sleep_enable();
+               sleep_bod_disable();
+               sei();
+               sleep_cpu();
 
-        // allow wakeup by long button-press only
-        for (btn = 0; btn < 5; btn++) {
-                if ((PINB & _BV(PB6)) != 0) {
-                        wake_count++;
-                        goto sleep_again;;
-                }
-                _delay_ms(100);
-        }
+               // G'morning
+               cli();
+               sleep_disable();
 
-       // ok, so I will wake up
-       log_byte(0xb1);
-       log_word(wake_count);
-       log_flush();
+               // allow wakeup by long button-press only
+       } while (!buttons_wait_for_release());
 
+       // ok, so I will wake up
        hw_setup();
 }
 
-
-ISR(PCINT_vect)
+static void inline first_boot()
 {
-       GIMSK &= ~_BV(PCIE1);
-       PCMSK1 &= ~_BV(PCINT14);
-}
+       unsigned char mcusr_save;
 
-int main(void)
-{
-       log_init();
+       // 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
@@ -95,15 +84,78 @@ int main(void)
        log_set_state(3);
 
        hw_setup();
-       power_down();
+       power_down(mcusr_save & _BV(WDRF));
+
+       prev_jiffies_8 = jiffies;
 
        sei();
-#if 1
-       while (1) {
-               wdt_reset();
-               sleep_mode();
+}
+
+static void inline do_timer()
+{
+       // For now, we run them all in their own atomic blocks
+       ATOMIC_BLOCK(ATOMIC_FORCEON) {
+               timer_check_buttons();
        }
-#endif
+       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);