diff --git a/iv.c b/iv.c index 34774ea..86930c1 100644 --- a/iv.c +++ b/iv.c @@ -126,6 +126,10 @@ static uint16_t snoozetimer = 0; */ static inline void sleep(void) { + // ensure all timer2 registers are written before sleeping + while(ASSR & (_BV(TCN2UB) | _BV(OCR2AUB) | _BV(OCR2BUB) | + _BV(TCR2AUB) | _BV(TCR2BUB) )); + asm volatile("sei $ sleep" : : : "memory"); } @@ -573,7 +577,7 @@ static void flip_display(transition_t* trans) } // called @ (F_CPU/256) = ~30khz (31.25 khz) -SIGNAL (SIG_OVERFLOW0) { +SIGNAL (TIMER0_OVF_vect) { // allow other interrupts to go off while we're doing display updates sei(); @@ -628,13 +632,13 @@ SIGNAL (SIG_OVERFLOW0) { // We use the pin change interrupts to detect when buttons are pressed // This interrupt detects switches 1 and 3 -SIGNAL(SIG_PIN_CHANGE2) { +SIGNAL(PCINT2_vect) { button_change_intr(0, !(PIND & _BV(BUTTON1))); button_change_intr(2, !(PIND & _BV(BUTTON3))); } // Just button #2 -SIGNAL(SIG_PIN_CHANGE0) { +SIGNAL(PCINT0_vect) { button_change_intr(1, !(PINB & _BV(BUTTON2))); } @@ -768,8 +772,20 @@ static void set_brite(void) */ SIGNAL (TIMER2_COMPA_vect) { struct timedate td; - CLKPR = _BV(CLKPCE); //MEME - CLKPR = 0; + + // write to unused timer2 register: the sleep code will ensure this value + // gets written before going to sleep--something that requires one full + // quartz crystal clock cycle. This is important because this interrupt + // must take at least one full quartz crystal cycle for reliable sleep. + OCR2B = 0; + + // for reliable low-voltage operation during sleep (1.7-3.0v), clock + // must not be set above 2 MHz; so only increase clock speed if powered + // by external adapter + if (!(ACSR & _BV(ACO))) { + CLKPR = _BV(CLKPCE); // MEME + CLKPR = 0; + } td = timedate; @@ -813,7 +829,7 @@ SIGNAL (TIMER2_COMPA_vect) { } //Alarm Switch -SIGNAL(SIG_INTERRUPT0) { +SIGNAL(INT0_vect) { uint8_t state; state = (ALARM_PIN & _BV(ALARM)); @@ -825,7 +841,7 @@ SIGNAL(SIG_INTERRUPT0) { } -SIGNAL(SIG_COMPARATOR) { +SIGNAL(ANALOG_COMP_vect) { //DEBUGP("COMP"); if (ACSR & _BV(ACO)) { //DEBUGP("HIGH"); @@ -1644,15 +1660,17 @@ static void clock_init(void) * correction. */ // Turn on the RTC by selecting the external 32khz crystal - ASSR = _BV(AS2); // use crystal + if(! TCCR2A) { // only configure crystal if not already configured + ASSR = _BV(AS2); // use crystal - TCNT2 = 0; - OCR2A = DRIFT_BASELINE; /* +/- drift correction */ - TCCR2A = _BV(WGM21); - TCCR2B = _BV(CS22) | _BV(CS21); + TCNT2 = 0; + OCR2A = DRIFT_BASELINE; /* +/- drift correction */ + TCCR2A = _BV(WGM21); + TCCR2B = _BV(CS22) | _BV(CS21); - // enable interrupt - TIMSK2 = _BV(OCIE1A); + // enable interrupt + TIMSK2 = _BV(OCIE1A); + } // enable all interrupts! sei(); @@ -1689,9 +1707,11 @@ void gotosleep(void) { ALARM_DDR &= ~_BV(ALARM); - // reduce the clock speed + // reduce the clock speed; division by four + // the original firmware divides by 256, but the resultant system clock + // speed is too slow for reliable asynchronous timer (timer2) operation CLKPR = _BV(CLKPCE); - CLKPR = _BV(CLKPS3); + CLKPR = _BV(CLKPS1); SMCR = _BV(SM1) | _BV(SM0) | _BV(SE); // power-save mode