From: Jan "Yenya" Kasprzak Date: Sun, 30 Sep 2012 20:23:08 +0000 (+0200) Subject: power-off function X-Git-Tag: gerber-fab-20121029-1711~27 X-Git-Url: https://www.fi.muni.cz/~kas/git//home/kas/public_html/git/?p=bike-lights.git;a=commitdiff_plain;h=33c451a9ba18c59b405d735b2420bc7b549643a4 power-off function TODO: factor it out from main.c, probably. --- diff --git a/firmware/buttons.c b/firmware/buttons.c index 84dd8da..9a4c7e1 100644 --- a/firmware/buttons.c +++ b/firmware/buttons.c @@ -1,53 +1,59 @@ #include #include #include +#include #include "lights.h" static uint16_t button_start[N_BUTTONS]; static unsigned char button_pressed[N_BUTTONS]; - -static unsigned char sleep_after_release; +static unsigned char just_waked_up; void init_buttons() { + unsigned char i; + DDRB &= ~(_BV(PB4) | _BV(PB6)); PORTB |= _BV(PB4) | _BV(PB6); - sleep_after_release = 0; - // log_byte(PORTB); -} + for (i=0; i < N_BUTTONS; i++) { + button_start[i] = 0; + button_pressed[i] = 0; + } -static void inline long_press(unsigned char n) -{ - sleep_after_release = 1; - gpio_set(1, 1); + just_waked_up = 1; + + // log_byte(PORTB); } static void do_sleep() { - // led_set_status(2); - // MCUCR |= _BV(ISC00); // any edge generates IRQ log_byte(0xb0); log_flush(); - set_sleep_mode(SLEEP_MODE_PWR_DOWN); - PORTA = 0; - PORTB = 0; - DDRA = 0; - DDRB = 0; - GIMSK |= _BV(INT0); // enable INT0 - sleep_enable(); - sei(); - sleep_cpu(); - sleep_disable(); - cli(); - GIMSK &= ~_BV(INT0); // disable INT0 - hw_setup(); + + hw_suspend(); + gpio_before_poweroff(); // Set the status LED on again + + while((PINB & _BV(PB6)) == 0) + ; // wait for button release + + _delay_ms(100); + + susp_gpio(); // disable the status LED + + power_down(); +} + +static void inline long_press(unsigned char n) +{ + if (n == 0) + do_sleep(); } static void inline short_press(unsigned char n) { - led_set_status(1); + if (n == 0) + gpio_set(2,1); } void timer_check_buttons() @@ -58,15 +64,18 @@ void timer_check_buttons() pinb & _BV(PB6), pinb & _BV(PB4), }; + for (i = 0; i < N_BUTTONS; i++) { if (!port_states[i]) { // is pressed + if (i == 0 && just_waked_up) + continue; if (button_pressed[i] == 0) { // begin of button press button_pressed[i] = 1; button_start[i] = jiffies; #if 0 - // log_byte(0xC0); - // log_word(jiffies); + log_byte(0xC0); + log_word(jiffies); #endif } else if (button_pressed[i] == 1) { // been already pressed @@ -78,6 +87,8 @@ void timer_check_buttons() } } } else { // is not pressed + if (i == 0) + just_waked_up = 0; if (button_pressed[i]) { // just depressed uint16_t duration = jiffies - button_start[i]; #if 1 @@ -88,17 +99,8 @@ void timer_check_buttons() button_pressed[i] = 0; if (duration > 6 && duration < 30) short_press(i); - if (sleep_after_release) - do_sleep(); } } } } -ISR(INT0_vect) -{ - hw_setup(); - log_byte(0xbb); - log_flush(); -} - diff --git a/firmware/lights.h b/firmware/lights.h index d7f0065..c866349 100644 --- a/firmware/lights.h +++ b/firmware/lights.h @@ -24,16 +24,19 @@ void inline log_word(uint16_t word) { } /* adc.c */ void init_adc(); +void susp_adc(); void timer_start_adcs(); /* pwm.c */ void init_pwm(); +void susp_pwm(); void pwm_off(unsigned char n); void pwm_set(unsigned char n, uint16_t stride); /* tmr.c */ extern volatile uint16_t jiffies; void init_tmr(); +void susp_tmr(); /* pwmled.c */ void pwmled_init(); @@ -44,7 +47,9 @@ unsigned char pwmled_enabled(unsigned char n); /* gpio.c */ void gpio_init(); +void susp_gpio(); void gpio_set(unsigned char n, unsigned char on); +void gpio_before_poweroff(); /* ambient.c */ void ambient_init(); @@ -60,8 +65,10 @@ void led_set_status(unsigned char status); void init_buttons(); void timer_check_buttons(); -/* init.c */ +/* main.c */ void hw_setup(); +void hw_suspend(); +void power_down(); #endif /* !LIGHTS_H__ */ diff --git a/firmware/main.c b/firmware/main.c index efebdab..5db08b1 100644 --- a/firmware/main.c +++ b/firmware/main.c @@ -2,12 +2,14 @@ #include #include #include +#include #include #include "lights.h" void hw_setup() { + wdt_enable(WDTO_1S); init_pwm(); init_adc(); init_tmr(); @@ -21,17 +23,59 @@ void hw_setup() set_sleep_mode(SLEEP_MODE_IDLE); } -int main(void) +void hw_suspend() { - log_init(); - wdt_enable(WDTO_1S); + susp_pwm(); + susp_adc(); + susp_tmr(); + susp_gpio(); + wdt_disable(); +} + + +void power_down() +{ + // 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(); - _delay_ms(100); + // Disable PCINT14 + GIMSK &= ~_BV(PCIE1); + PCMSK1 &= ~_BV(PCINT14); hw_setup(); +} + + +ISR(PCINT_vect) +{ + GIMSK &= ~_BV(PCIE1); + PCMSK1 &= ~_BV(PCINT14); +} + +int main(void) +{ + log_init(); + power_usi_disable(); // Once for lifetime log_set_state(3); + hw_setup(); + hw_suspend(); + power_down(); + sei(); #if 1 while (1) {