void main(void) { struct tm* t = NULL; char buf[32]; uint8_t hour, min, sec; uartInit(); uartSetBaudRate(9600); uartSendString("DS RTC Library Test\n"); LED_DDR |= _BV(LED_BIT); // indicator led for (int i = 0; i < 5; i++) { LED_HIGH; _delay_ms(100); LED_LOW; _delay_ms(100); } uartSendString("Before Init\n"); twi_init_master(); rtc_init(); rtc_set_time_s(12, 0, 50); uartSendString("After Init\n"); if (rtc_is_ds1307()) uartSendString("DS1307\n"); else uartSendString("DS3231\n"); rtc_set_alarm_s(12, 1, 0); rtc_get_alarm_s(&hour, &min, &sec); sprintf(buf, "Alarm is set -%d:%d:%d-\n", hour, min, sec); uartSendString(buf); uartSendString("---\n"); uartSendString("---\n"); uartSendString("---\n"); while (1) { t = rtc_get_time(); sprintf(buf, "%d:%d:%d\n", t->hour, t->min, t->sec); uartSendString(buf); uartSendString("---\n"); if (rtc_check_alarm()) uartSendString("ALARM!\n"); _delay_ms(500); } }
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 display_time(display_mode_t mode) // (wm) runs approx every 100 ms { static uint16_t counter = 0; #ifdef FEATURE_AUTO_DATE if (mode == MODE_DATE) { show_date(tm_, g_Region, (scroll_ctr++) * 10 / 38); // show date from last rtc_get_time() call } else #endif if (mode == MODE_ALARM_TEXT) { show_alarm_text(); } else if (mode == MODE_ALARM_TIME) { if (g_alarm_switch) { rtc_get_alarm_s(&alarm_hour, &alarm_min, &alarm_sec); show_alarm_time(alarm_hour, alarm_min, 0); } else { show_alarm_off(); } } // alternate temp and time every 2.5 seconds else if (g_show_temp && rtc_is_ds3231() && counter > 250) { int8_t t; uint8_t f; ds3231_get_temp_int(&t, &f); show_temp(t, f); } else { tm_ = rtc_get_time(); if (tm_ == NULL) return; #ifdef FEATURE_SET_DATE g_dateyear = tm_->Year; // save year for Menu g_datemonth = tm_->Month; // save month for Menu g_dateday = tm_->Day; // save day for Menu #endif #ifdef FEATURE_AUTO_DST if (tm_->Second%10 == 0) // check DST Offset every 10 seconds (60?) setDSToffset(g_DST_mode); if ((tm_->Hour == 0) && (tm_->Minute == 0) && (tm_->Second == 0)) { // MIDNIGHT! g_DST_updated = false; if (g_DST_mode) DSTinit(tm_, g_DST_Rules); // re-compute DST start, end } #endif #ifdef FEATURE_AUTO_DATE if (g_AutoDate && (tm_->Second == g_autotime) ) { save_mode = clock_mode; // save current mode clock_mode = MODE_DATE; // display date now g_show_special_cnt = g_autodisp; // show date for g_autodisp ms scroll_ctr = 0; // reset scroll position } else #endif #ifdef FEATURE_FLW if (mode == MODE_FLW) { if ((tm_->Second >= g_autotime - 3) && (tm_->Second < g_autotime)) show_time(tm_, g_24h_clock, 0); // show time briefly each minute else show_flw(tm_); // otherwise show FLW } else #endif show_time(tm_, g_24h_clock, mode); } counter++; if (counter == 500) counter = 0; }
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 = 2; switch (shield) { case(SHIELD_IV6): set_string("IV-6"); break; case(SHIELD_IV17): set_string("IV17"); break; case(SHIELD_IV18): set_string("IV18"); break; case(SHIELD_IV22): set_string("IV22"); break; default: break; } // piezo_init(); // beep(440, 1); // beep(1320, 1); beep(440, 1); _delay_ms(500); //set_string("--------"); while (1) { // <<< ===================== MAIN LOOP ===================== >>> get_button_state(&buttons); // When alarming: // any button press cancels alarm if (g_alarming) { display_time(clock_mode); // read and display time (??) // 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 (menu_state == STATE_CLOCK && buttons.both_held) { if (g_alarm_switch) { menu_state = STATE_SET_ALARM; show_set_alarm(); rtc_get_alarm_s(&alarm_hour, &alarm_min, &alarm_sec); time_to_set = alarm_hour*60 + alarm_min; } else { menu_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 (menu_state == STATE_SET_CLOCK || menu_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 = 1; } 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 >= MENU_TIMEOUT) { set_blink(false); button_released_timer = 0; button_speed = 1; // fixme: should be different in 12h mode if (menu_state == STATE_SET_CLOCK) { rtc_set_time_s(time_to_set / 60, time_to_set % 60, 0); #if defined FEATURE_AUTO_DST g_DST_updated = false; // allow automatic DST adjustment again #endif } else { alarm_hour = time_to_set / 60; alarm_min = time_to_set % 60; alarm_sec = 0; rtc_set_alarm_s(alarm_hour, alarm_min, alarm_sec); } menu_state = STATE_CLOCK; } // Increase / Decrease time counter if (buttons.b1_repeat) time_to_set+=(button_speed/10); if (buttons.b1_keyup) time_to_set++; if (buttons.b2_repeat) time_to_set-=(button_speed/10); 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); } else if (menu_state == STATE_CLOCK && buttons.b2_keyup) { // Left button enters menu menu_state = STATE_MENU; // if (get_digits() < 8) // only set first time flag for 4 or 6 digit displays // menu_update = false; // set first time flag // show_setting_int("BRIT", "BRITE", g_brightness, false); menu(0); // show first menu item buttons.b2_keyup = 0; // clear state } // Right button toggles display mode else if (menu_state == STATE_CLOCK && buttons.b1_keyup) { clock_mode++; #ifdef FEATURE_FLW if (clock_mode == MODE_FLW && !g_has_eeprom) clock_mode++; if (clock_mode == MODE_FLW && !g_flw_enabled) clock_mode++; #endif #ifdef FEATURE_AUTO_DATE if (clock_mode == MODE_DATE) { g_show_special_cnt = g_autodisp; // show date for g_autodisp ms scroll_ctr = 0; // reset scroll position } #endif if (clock_mode == MODE_LAST) clock_mode = MODE_NORMAL; buttons.b1_keyup = 0; // clear state } else if (menu_state == STATE_MENU) { if (buttons.none_held) button_released_timer++; else button_released_timer = 0; if (button_released_timer >= MENU_TIMEOUT) { button_released_timer = 0; menu_state = STATE_CLOCK; } if (buttons.b1_keyup) { // right button menu(1); // right button buttons.b1_keyup = false; } // if (buttons.b1_keyup) if (buttons.b2_keyup) { // left button menu(2); // left button buttons.b2_keyup = 0; // clear state } } else { if (g_show_special_cnt>0) { g_show_special_cnt--; if (g_show_special_cnt == 0) { switch (clock_mode) { case MODE_ALARM_TEXT: clock_mode = MODE_ALARM_TIME; g_show_special_cnt = 10; break; case MODE_ALARM_TIME: clock_mode = MODE_NORMAL; break; #ifdef FEATURE_AUTO_DATE case MODE_DATE: clock_mode = save_mode; // 11oct12/wbp break; #endif default: clock_mode = MODE_NORMAL; } } } // read RTC & update display approx every 100ms (wm) display_time(clock_mode); // read RTC and display time } // fixme: alarm should not be checked when setting time or alarm // fixme: alarm will be missed if time goes by Second=0 while in menu if (g_alarm_switch && rtc_check_alarm_cached(tm_, alarm_hour, alarm_min, alarm_sec)) g_alarming = true; #ifdef FEATURE_AUTO_DIM if ((g_AutoDim) && (tm_->Minute == 0) && (tm_->Second == 0)) { // Auto Dim enabled? if (tm_->Hour == g_AutoDimHour) set_brightness(g_AutoDimLevel); else if (tm_->Hour == g_AutoBrtHour) set_brightness(g_AutoBrtLevel); } #endif #ifdef FEATURE_WmGPS if (g_gps_enabled) { if (gpsDataReady()) { parseGPSdata(gpsNMEA()); // get the GPS serial stream and possibly update the clock } else _delay_ms(2); } else _delay_ms(2); #endif _delay_ms(74); // tuned so loop runs 10 times a second } // while (1) } // main()
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 }