#include "lights.h"
+#define WAKEUP_LIMIT 5 // times 100 ms
static uint16_t button_start[N_BUTTONS];
static unsigned char prev_pin;
void init_buttons()
{
- DDRA &= ~(_BV(PA3) | _BV(PA4));
- PORTA |= _BV(PA3) | _BV(PA4);
+ DDRA &= ~(_BV(PA3) | _BV(PA4)); // set as input
+ PORTA |= _BV(PA3) | _BV(PA4); // enable internal pull-ups
+
+ GIMSK &= ~(_BV(PCIE0) | _BV(PCIE1)); // disable pin-change IRQs
+ PCMSK0 = 0; // disable pin-change IRQs on all pins of port A
+ PCMSK1 = 0; // disable pin-change IRQs on all pins of port B
button_start[0] = 0;
button_start[1] = 0;
user_params_state = 0;
}
+void susp_buttons()
+{
+ DDRA &= ~(_BV(PA3) | _BV(PA4)); // set as input
+ PORTA |= _BV(PA3) | _BV(PA4); // enable internal pull-ups
+
+ GIMSK &= ~_BV(PCIE1); // disable pin-change IRQ on port B
+ GIMSK |= _BV(PCIE0);
+
+ PCMSK0 = _BV(PCINT3) | _BV(PCINT4);
+ // disable pin-change IRQs on all pins except PA3,PA4
+ PCMSK1 = 0; // disable pin-change IRQs on all pins of port B
+}
+
static void handle_button(unsigned char button, unsigned char cur,
unsigned char prev)
{
}
}
+unsigned char buttons_wait_for_release()
+{
+ uint16_t wake_count = 0;
+ unsigned char pin;
+
+ do {
+ if (wake_count++ > WAKEUP_LIMIT)
+ gpio_set(0, 1); // inform the user
+
+ _delay_ms(100);
+
+ pin = PINA & (_BV(PA3) | _BV(PA4));
+ } while (!(pin & _BV(PA3)) || !(pin & _BV(PA4)));
+
+ gpio_set(0, 0);
+
+ return wake_count > WAKEUP_LIMIT;
+
+}
+
+ISR(PCINT_vect)
+{
+ // empty - let it wake us from sleep, but do nothing else
+}
+
/* buttons.c */
#define MAX_USER_PARAMS 3
void init_buttons();
+void susp_buttons();
void timer_check_buttons();
unsigned char get_user_param(unsigned char param);
pattern_t *status_pattern_select(unsigned char n);
+unsigned char buttons_wait_for_release();
/* battery.c */
extern volatile unsigned char battery_100mv;
static void hw_setup()
{
wdt_enable(WDTO_1S);
+
init_battery();
init_pwm();
init_adc();
susp_adc();
susp_tmr();
susp_gpio();
+ susp_buttons();
+
wdt_disable();
}
-
void power_down()
{
- 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();
-
- // Disable PCINT14
- GIMSK &= ~_BV(PCIE1);
- PCMSK1 &= ~_BV(PCINT14);
-
- // 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);
- }
- // ok, so I will wake up
- log_byte(0xb1);
- log_word(wake_count);
- log_flush();
+ do {
+ // G'night
+ set_sleep_mode(SLEEP_MODE_PWR_DOWN);
+ sleep_enable();
+ sleep_bod_disable();
+ sei();
+ sleep_cpu();
- hw_setup();
-}
+ // G'morning
+ cli();
+ sleep_disable();
+ // allow wakeup by long button-press only
+ } while (!buttons_wait_for_release());
-ISR(PCINT_vect)
-{
- GIMSK &= ~_BV(PCIE1);
- PCMSK1 &= ~_BV(PCINT14);
+ // ok, so I will wake up
+ hw_setup();
}
int main(void)