void main(void) { initialize(); /* // test: write alphabet while (1) { for (int i = 'A'; i <= 'Z'+1; i++) { set_char_at(i, 0); set_char_at(i+1, 1); set_char_at(i+2, 2); set_char_at(i+3, 3); if (get_digits() == 6) { set_char_at(i+4, 4); set_char_at(i+5, 5); } _delay_ms(250); } } */ uint8_t hour = 0, min = 0, sec = 0; // Counters used when setting time int16_t time_to_set = 0; uint16_t button_released_timer = 0; uint16_t button_speed = 25; set_string("--------"); piezo_init(); beep(500, 1); beep(1000, 1); beep(500, 1); while (1) { get_button_state(&buttons); // When alarming: // any button press cancels alarm if (g_alarming) { read_rtc(clock_mode); // fixme: if keydown is detected here, wait for keyup and clear state // this prevents going into the menu when disabling the alarm if (buttons.b1_keydown || buttons.b1_keyup || buttons.b2_keydown || buttons.b2_keyup) { buttons.b1_keyup = 0; // clear state buttons.b2_keyup = 0; // clear state g_alarming = false; } else { alarm(); } } // If both buttons are held: // * If the ALARM BUTTON SWITCH is on the LEFT, go into set time mode // * If the ALARM BUTTON SWITCH is on the RIGHT, go into set alarm mode else if (clock_state == STATE_CLOCK && buttons.both_held) { if (g_alarm_switch) { clock_state = STATE_SET_ALARM; show_set_alarm(); rtc_get_alarm_s(&hour, &min, &sec); time_to_set = hour*60 + min; } else { clock_state = STATE_SET_CLOCK; show_set_time(); rtc_get_time_s(&hour, &min, &sec); time_to_set = hour*60 + min; } set_blink(true); // wait until both buttons are released while (1) { _delay_ms(50); get_button_state(&buttons); if (buttons.none_held) break; } } // Set time or alarm else if (clock_state == STATE_SET_CLOCK || clock_state == STATE_SET_ALARM) { // Check if we should exit STATE_SET_CLOCK or STATE_SET_ALARM if (buttons.none_held) { set_blink(true); button_released_timer++; button_speed = 50; } else { set_blink(false); button_released_timer = 0; button_speed++; } // exit mode after no button has been touched for a while if (button_released_timer >= 160) { set_blink(false); button_released_timer = 0; button_speed = 1; // fixme: should be different in 12h mode if (clock_state == STATE_SET_CLOCK) rtc_set_time_s(time_to_set / 60, time_to_set % 60, 0); else rtc_set_alarm_s(time_to_set / 60, time_to_set % 60, 0); clock_state = STATE_CLOCK; } // Increase / Decrease time counter if (buttons.b1_repeat) time_to_set+=(button_speed/100); if (buttons.b1_keyup) time_to_set++; if (buttons.b2_repeat) time_to_set-=(button_speed/100); if (buttons.b2_keyup) time_to_set--; if (time_to_set >= 1440) time_to_set = 0; if (time_to_set < 0) time_to_set = 1439; show_time_setting(time_to_set / 60, time_to_set % 60, 0); } // Left button enters menu else if (clock_state == STATE_CLOCK && buttons.b2_keyup) { clock_state = STATE_MENU_BRIGHTNESS; show_setting_int("BRIT", "BRITE", g_brightness, false); buttons.b2_keyup = 0; // clear state } // Right button toggles display mode else if (clock_state == STATE_CLOCK && buttons.b1_keyup) { clock_mode++; if (clock_mode == MODE_LAST) clock_mode = MODE_NORMAL; buttons.b1_keyup = 0; // clear state } else if (clock_state >= STATE_MENU_BRIGHTNESS) { if (buttons.none_held) button_released_timer++; else button_released_timer = 0; if (button_released_timer >= 80) { button_released_timer = 0; clock_state = STATE_CLOCK; } switch (clock_state) { case STATE_MENU_BRIGHTNESS: if (buttons.b1_keyup) { g_brightness++; buttons.b1_keyup = false; if (g_brightness > 10) g_brightness = 1; eeprom_update_byte(&b_brightness, g_brightness); if (shield == SHIELD_IV17) show_setting_string("BRIT", "BRITE", (g_brightness % 2 == 0) ? " lo" : " hi", true); else show_setting_int("BRIT", "BRITE", g_brightness, true); set_brightness(g_brightness); } break; case STATE_MENU_24H: if (buttons.b1_keyup) { g_24h_clock = !g_24h_clock; eeprom_update_byte(&b_24h_clock, g_24h_clock); show_setting_string("24H", "24H", g_24h_clock ? " on" : " off", true); buttons.b1_keyup = false; } break; case STATE_MENU_VOL: if (buttons.b1_keyup) { g_volume = !g_volume; eeprom_update_byte(&b_volume, g_volume); show_setting_string("VOL", "VOL", g_volume ? " hi" : " lo", true); piezo_init(); beep(1000, 1); buttons.b1_keyup = false; } break; case STATE_MENU_TEMP: if (buttons.b1_keyup) { g_show_temp = !g_show_temp; eeprom_update_byte(&b_show_temp, g_show_temp); show_setting_string("TEMP", "TEMP", g_show_temp ? " on" : " off", true); buttons.b1_keyup = false; } break; case STATE_MENU_DOTS: if (buttons.b1_keyup) { g_show_dots = !g_show_dots; eeprom_update_byte(&b_show_dots, g_show_dots); show_setting_string("DOTS", "DOTS", g_show_dots ? " on" : " off", true); buttons.b1_keyup = false; } break; default: break; // do nothing } if (buttons.b2_keyup) { clock_state++; // show temperature setting only when running on a DS3231 if (clock_state == STATE_MENU_TEMP && !rtc_is_ds3231()) clock_state++; // don't show dots settings for shields that have no dots if (clock_state == STATE_MENU_DOTS && !g_has_dots) clock_state++; if (clock_state == STATE_MENU_LAST) clock_state = STATE_MENU_BRIGHTNESS; switch (clock_state) { case STATE_MENU_BRIGHTNESS: show_setting_int("BRIT", "BRITE", g_brightness, false); break; case STATE_MENU_VOL: show_setting_string("VOL", "VOL", g_volume ? " hi" : " lo", false); break; case STATE_MENU_24H: show_setting_string("24H", "24H", g_24h_clock ? " on" : " off", false); break; case STATE_MENU_DOTS: show_setting_string("DOTS", "DOTS", g_show_dots ? " on" : " off", false); break; case STATE_MENU_TEMP: show_setting_string("TEMP", "TEMP", g_show_temp ? " on" : " off", false); break; default: break; // do nothing } buttons.b2_keyup = 0; // clear state } } else { // read RTC only aprox every 15ms static uint16_t cnt = 0; if (cnt++ % 15 == 0) read_rtc(clock_mode); } // fixme: alarm should not be checked when setting time or alarm if (g_alarm_switch && rtc_check_alarm()) g_alarming = true; _delay_ms(10); } }
void initialize(void) { PIEZO_DDR |= _BV(PIEZO_LOW_BIT); PIEZO_DDR |= _BV(PIEZO_HIGH_BIT); PIEZO_LOW_OFF; PIEZO_HIGH_OFF; // Set buttons as inputs BUTTON_DDR &= ~(_BV(BUTTON1_BIT)); BUTTON_DDR &= ~(_BV(BUTTON2_BIT)); SWITCH_DDR &= ~(_BV(SWITCH_BIT)); // Enable pullups for buttons BUTTON_PORT |= _BV(BUTTON1_BIT); BUTTON_PORT |= _BV(BUTTON2_BIT); SWITCH_PORT |= _BV(SWITCH_BIT); LED_DDR |= _BV(LED_BIT); // indicator led for (int i = 0; i < 5; i++) { LED_HIGH; _delay_ms(100); LED_LOW; _delay_ms(100); } sei(); twi_init_master(); rtc_init(); rtc_set_ds1307(); //rtc_set_time_s(16, 59, 50); //rtc_set_alarm_s(17,0,0); piezo_init(); beep(440, 1); globals_init(); display_init(g_brightness); g_alarm_switch = get_alarm_switch(); #ifdef FEATURE_FLW g_has_eeprom = has_eeprom(); // if (!g_has_eeprom) beep(440,2); // debug if (!g_has_eeprom) g_flw_enabled = false; if (tm_ && g_has_eeprom) seed_random(tm_->Hour * 10000 + tm_->Minute + 100 + tm_->Second); #endif beep(1320, 1); menu_init(); // must come after display, flw init rtc_get_alarm_s(&alarm_hour, &alarm_min, &alarm_sec); // set up interrupt for alarm switch PCICR |= (1 << PCIE2); PCMSK2 |= (1 << PCINT18); #ifdef FEATURE_WmGPS // setup uart for GPS gps_init(g_gps_enabled); #endif #ifdef FEATURE_AUTO_DST if (g_DST_mode) DSTinit(tm_, g_DST_Rules); // re-compute DST start, end #endif }