#include "main.h" #include "clock.h" #include "timebase.h" #include "dcf77.h" #include "lcd.h" #include #include #include #ifdef WHOPR #include "clock.c" #include "timebase.c" #include "dcf77.c" #include "lcd.c" #endif #define B_SW_BACK PINB5 #define B_SW_FRWD PINB6 #define A_OCPL_A PA5 #define A_OCPL_B PA6 #define EE_HOUR 0 #define EE_MINUTE 1 #define EE_CKSUM 2 #define EE_BOOTC 4 static uint8_t ext_hour, ext_minute; static uint16_t bootcount; #define WAIT 64 uint8_t waitctr = 0; enum stepstate { STEP_INACTIVE = 0, STEP_ACTIVE, } stepstate = STEP_INACTIVE; const char PROGMEM disp[2] = {'_', '+'}; const char PROGMEM status[8] = "oksya+a-"; const char PROGMEM zone[4] = "?12?"; const char PROGMEM cksumfail[] = "cksum fail"; static void puttwo(uint8_t arg) { uint8_t b = '0', a = '0' + arg; while (a > '9') b++, a -= 10; lcd_put(b); lcd_put(a); } static void puttime(void) { const char * PROGMEM msg; lcd_line1(); puttwo(time.year); puttwo(time.month); puttwo(time.day); lcd_put(' '); puttwo(time.hour); puttwo(time.minute); puttwo(time.second); lcd_line2(); lcd_put(time.flags & FLAG_SUMMERTIME_PENDING ? '!' : ' '); lcd_put(zone[is_cet() + (is_cest() << 1)]); lcd_put(time.flags & FLAG_LEAP_SECOND ? '!' : ' '); msg = &status[0]; if (time.year <= 10) msg = &status[2]; if (~PINB & (1 << B_SW_FRWD)) msg = &status[4]; if (~PINB & (1 << B_SW_BACK)) msg = &status[6]; lcd_puts(msg, 2); lcd_put(__LPM(&disp[stepstate])); puttwo(ext_hour); puttwo(ext_minute); lcd_put(' '); puttwo(bootcount / 100); puttwo(bootcount % 100); } static uint8_t setaccel; static void countfwd(void) { cli(); ext_minute++; if (ext_minute == 60) { ext_minute = 0; ext_hour++; if (ext_hour == 12) ext_hour = 0; } sei(); } static void step_set(void) { if (ext_minute & 1) { PORTA &= ~(1 << A_OCPL_A); } else { PORTA &= ~(1 << A_OCPL_B); } } static void step_end(void) { PORTA |= (1 << A_OCPL_A); PORTA |= (1 << A_OCPL_B); } static void perform(void) { if (waitctr) return; step_end(); if (~PINB & (1 << B_SW_BACK)) { waitctr = setaccel; if (setaccel > 3) setaccel--; cli(); if (ext_minute) ext_minute--; else { ext_minute = 59; if (ext_hour) ext_hour--; else ext_hour = 11; } sei(); return; } if (~PINB & (1 << B_SW_FRWD)) { waitctr = setaccel; if (setaccel > 3) setaccel--; countfwd(); return; } setaccel = WAIT; if (time.year <= 10) return; PORTA &= ~(1 << PA2); uint8_t hbuf, mbuf, hdelta; cli(); hbuf = time.hour; mbuf = time.minute; sei(); if (hbuf >= 12) hbuf -= 12; switch (stepstate) { case STEP_INACTIVE: if (hbuf == ext_hour && mbuf <= ext_minute) break; hdelta = 11 + ext_hour - hbuf; while (hdelta >= 12) hdelta -=12; if (hdelta < 3) break; countfwd(); step_set(); stepstate = STEP_ACTIVE; waitctr = WAIT; break; case STEP_ACTIVE: stepstate = STEP_INACTIVE; waitctr = WAIT; break; } } extern void __vectors(void) __attribute__((noreturn)); __attribute__ ((noreturn)) ISR (ANA_COMP_vect) { PORTA = 0xff; eeprom_write_byte((void *)EE_HOUR, ext_hour); eeprom_write_byte((void *)EE_MINUTE, ext_minute); eeprom_write_byte((void *)EE_CKSUM, ext_hour ^ ext_minute ^ 0xff); do _delay_ms(100); while (ACSR & (1 << ACO)); __vectors(); } int __attribute__((OS_main)) main( void ) { PORTA = 0xFF; // enable pull ups PORTB = 0xFF; DDRA |= (1 << PA4) | (1 << PA3) | (1 << PA2) | (1 << A_OCPL_A) | (1 << A_OCPL_B); MCUCR = 0; ACSR = (1 << ACBG) | (1 << ACIS1) | (1 << ACIS0) | (1 << ACIE); _delay_ms(1); ACSR |= (1 << ACI); timebase_init(); lcd_init(); ext_hour = eeprom_read_byte((void *)EE_HOUR); ext_minute = eeprom_read_byte((void *)EE_MINUTE); uint8_t ec = eeprom_read_byte((void *)EE_CKSUM); if ((ec ^ ext_hour ^ ext_minute) != 0xff) { lcd_puts(cksumfail, sizeof(cksumfail) - 1); while (1) ; } bootcount = eeprom_read_word((void *)EE_BOOTC); eeprom_write_word((void *)EE_BOOTC, ++bootcount); /* last pulse may not have been long enough */ step_set(); _delay_ms(1000); step_end(); sei(); for(;;){ bool do_puttime = false; scan_dcf77(); #if 1 if( DCF77_PIN & 1<