From 5e877e5bb3dbc8f356094ca8f0a33ffc9cb3d0f1 Mon Sep 17 00:00:00 2001 From: Rhys Weatherley Date: Sun, 17 Jun 2012 11:50:04 +1000 Subject: [PATCH] Alarms that fire only Mon-Fri or Sat&Sun --- doc/alarm-clock.dox | 2 + .../RTC/examples/AlarmClock/AlarmClock.pde | 52 ++-- .../RTC/examples/AlarmClock/EditTime.cpp | 223 ------------------ libraries/RTC/examples/AlarmClock/EditTime.h | 53 ----- .../RTC/examples/AlarmClock/SetAlarm.cpp | 212 ++++++++++++++++- libraries/RTC/examples/AlarmClock/SetAlarm.h | 31 ++- libraries/RTC/examples/AlarmClock/SetTime.cpp | 117 ++++++++- libraries/RTC/examples/AlarmClock/SetTime.h | 15 +- 8 files changed, 391 insertions(+), 314 deletions(-) delete mode 100644 libraries/RTC/examples/AlarmClock/EditTime.cpp delete mode 100644 libraries/RTC/examples/AlarmClock/EditTime.h diff --git a/doc/alarm-clock.dox b/doc/alarm-clock.dox index a0de40cb..24205763 100644 --- a/doc/alarm-clock.dox +++ b/doc/alarm-clock.dox @@ -36,6 +36,8 @@ Field, SoftI2C, DS1307RTC (or DS3232RTC), Melody and \li Up to 4 configurable alarm times, plus a snooze alarm. \li Three alarm sounds to choose from. \li Configurable alarm timeout between 2 and 10 seconds. +\li Alarms can be configured to only sound on Monday to Friday + or on Saturday and Sunday. \li Single button to activate the back light and/or stop the alarm. \li Up, down, left, and right buttons to change clock settings. \li MOSFET that controls the power to a separate radio circuit. diff --git a/libraries/RTC/examples/AlarmClock/AlarmClock.pde b/libraries/RTC/examples/AlarmClock/AlarmClock.pde index 4d645788..3eeca523 100644 --- a/libraries/RTC/examples/AlarmClock/AlarmClock.pde +++ b/libraries/RTC/examples/AlarmClock/AlarmClock.pde @@ -155,10 +155,26 @@ void loop() { setTime.updateCurrentTime(); // Trigger an alarm if necessary. - if (time.second == 0 && nextAlarm.flags && !alarmMelody.isPlaying()) { + if (time.second == 0 && (nextAlarm.flags & 0x01) && !alarmMelody.isPlaying()) { if (time.hour == nextAlarm.hour && time.minute == nextAlarm.minute) { + // We have a match on time; now check the day of week. + RTCDate date = frontScreen.date(); + RTC::DayOfWeek day = RTC::dayOfWeek(&date); + SetAlarm::Days matchDays = SetAlarm::days(&nextAlarm); + bool matched; + if (matchDays == SetAlarm::AnyDay) + matched = true; + else if (matchDays == SetAlarm::MondayToFriday && + day >= RTC::Monday && day <= RTC::Friday) + matched = true; + else if (matchDays == SetAlarm::SaturdayAndSunday && + day >= RTC::Saturday && day <= RTC::Sunday) + matched = true; + else + matched = false; findNextAlarm(); - alarmMelody.play(); + if (matched) + alarmMelody.play(); } } } @@ -231,7 +247,7 @@ inline int timeToAlarm(const RTCTime ¤tTime, const RTCAlarm &alarm) // Add 9 minutes to an alarm to get its snooze time. RTCAlarm adjustForSnooze(const RTCAlarm &alarm) { - if (!alarm.flags) + if (!(alarm.flags & 0x01)) return alarm; RTCAlarm snooze; snooze.hour = alarm.hour; @@ -258,19 +274,19 @@ void findNextAlarm() nextAlarm.hour = 0; nextAlarm.minute = 0; nextAlarm.flags = 0; - findNextAlarm(currentTime, alarm1.alarmValue()); - findNextAlarm(currentTime, alarm2.alarmValue()); - findNextAlarm(currentTime, alarm3.alarmValue()); - findNextAlarm(currentTime, alarm4.alarmValue()); + findNextAlarm(currentTime, alarm1.value()); + findNextAlarm(currentTime, alarm2.value()); + findNextAlarm(currentTime, alarm3.value()); + findNextAlarm(currentTime, alarm4.value()); if (snooze.value()) { - findNextAlarm(currentTime, adjustForSnooze(alarm1.alarmValue())); - findNextAlarm(currentTime, adjustForSnooze(alarm2.alarmValue())); - findNextAlarm(currentTime, adjustForSnooze(alarm3.alarmValue())); - findNextAlarm(currentTime, adjustForSnooze(alarm4.alarmValue())); + findNextAlarm(currentTime, adjustForSnooze(alarm1.value())); + findNextAlarm(currentTime, adjustForSnooze(alarm2.value())); + findNextAlarm(currentTime, adjustForSnooze(alarm3.value())); + findNextAlarm(currentTime, adjustForSnooze(alarm4.value())); } // Set the alarm indicator on the front screen. - if (nextAlarm.flags) { + if (nextAlarm.flags & 0x01) { if (snooze.value()) frontScreen.setAlarmMode(FrontScreenField::Snooze); else @@ -281,17 +297,21 @@ void findNextAlarm() } void findNextAlarm(const RTCTime ¤tTime, const RTCAlarm &alarm) { - if (!alarm.flags) + if (!(alarm.flags & 0x01)) return; // Alarm is disabled. - if (!nextAlarm.flags) { + if (!(nextAlarm.flags & 0x01)) { // First valid alarm. nextAlarm = alarm; return; } - if (timeToAlarm(currentTime, nextAlarm) > - timeToAlarm(currentTime, alarm)) { + int timeToNext = timeToAlarm(currentTime, nextAlarm); + int timeToCurr = timeToAlarm(currentTime, alarm); + if (timeToNext > timeToCurr) { // Found an alarm that is closer in time. nextAlarm = alarm; + } else if (timeToNext == timeToCurr) { + // Same time; combine the day indicators. + SetAlarm::combineDays(&nextAlarm, &alarm); } } diff --git a/libraries/RTC/examples/AlarmClock/EditTime.cpp b/libraries/RTC/examples/AlarmClock/EditTime.cpp deleted file mode 100644 index b32eec88..00000000 --- a/libraries/RTC/examples/AlarmClock/EditTime.cpp +++ /dev/null @@ -1,223 +0,0 @@ -/* - * Copyright (C) 2012 Southern Storm Software, Pty Ltd. - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * the rights to use, copy, modify, merge, publish, distribute, sublicense, - * and/or sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included - * in all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS - * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER - * DEALINGS IN THE SOFTWARE. - */ - -#include "EditTime.h" -#include - -#define EDIT_ENABLED 0 -#define EDIT_HOUR 1 -#define EDIT_MINUTE_TENS 2 -#define EDIT_MINUTE 3 - -extern bool is24HourClock; - -EditTime::EditTime(Form &form, const String &label) - : Field(form, label) - , isAlarm(false) - , alarmEnabled(false) - , editField(EDIT_HOUR) -{ - _value.hour = 0; - _value.minute = 0; - _value.second = 0; -} - -int EditTime::dispatch(int event) -{ - RTCTime newValue; - if (event == LCD_BUTTON_UP) { - newValue = _value; - if (editField == EDIT_HOUR) { - newValue.hour = (newValue.hour + 1) % 24; - } else if (editField == EDIT_MINUTE_TENS) { - newValue.minute = (newValue.minute + 10) % 60; - } else if (editField == EDIT_MINUTE) { - newValue.minute = (newValue.minute + 1) % 60; - } else if (editField == EDIT_ENABLED) { - alarmEnabled = !alarmEnabled; - if (alarmEnabled) - editField = EDIT_HOUR; - printTime(); - return FORM_CHANGED; - } - newValue.second = 0; - _value = newValue; - printTime(); - return FORM_CHANGED; - } else if (event == LCD_BUTTON_DOWN) { - newValue = _value; - if (editField == EDIT_HOUR) { - newValue.hour = (newValue.hour + 23) % 24; - } else if (editField == EDIT_MINUTE_TENS) { - newValue.minute = (newValue.minute + 50) % 60; - } else if (editField == EDIT_MINUTE) { - newValue.minute = (newValue.minute + 59) % 60; - } else if (editField == EDIT_ENABLED) { - alarmEnabled = !alarmEnabled; - if (alarmEnabled) - editField = EDIT_HOUR; - printTime(); - return FORM_CHANGED; - } - newValue.second = 0; - _value = newValue; - printTime(); - return FORM_CHANGED; - } else if (event == LCD_BUTTON_LEFT) { - if (isAlarm) { - if (editField != EDIT_ENABLED) { - --editField; - printTime(); - return 0; - } - } else { - if (editField != EDIT_HOUR) { - --editField; - printTime(); - return 0; - } - } - } else if (event == LCD_BUTTON_RIGHT) { - if (isAlarm) { - if (alarmEnabled) { - if (editField != EDIT_MINUTE) { - ++editField; - printTime(); - return 0; - } - } - } else { - if (editField != EDIT_MINUTE) { - ++editField; - printTime(); - return 0; - } - } - } - return -1; -} - -void EditTime::enterField(bool reverse) -{ - Field::enterField(reverse); - if (isAlarm) { - if (alarmEnabled) { - if (reverse) - editField = EDIT_MINUTE; - else - editField = EDIT_ENABLED; - } else { - editField = EDIT_ENABLED; - } - } else { - if (reverse) - editField = EDIT_MINUTE; - else - editField = EDIT_HOUR; - } - printTime(); - lcd()->cursor(); -} - -void EditTime::exitField() -{ - lcd()->noCursor(); - Field::exitField(); -} - -void EditTime::setValue(const RTCTime &value) -{ - _value = value; - isAlarm = false; - if (isCurrent()) - printTime(); -} - -RTCAlarm EditTime::alarmValue() const -{ - RTCAlarm alarm; - alarm.hour = _value.hour; - alarm.minute = _value.minute; - alarm.flags = alarmEnabled ? 1 : 0; - return alarm; -} - -void EditTime::setAlarmValue(const RTCAlarm &value) -{ - _value.hour = value.hour; - _value.minute = value.minute; - _value.second = 0; - isAlarm = true; - alarmEnabled = ((value.flags & 0x01) != 0); - if (isCurrent()) - printTime(); -} - -void EditTime::printTime() -{ - lcd()->setCursor(0, 1); - int hour = _value.hour; - int minute = _value.minute; - int timeCol = 0; - bool pm; - if (isAlarm) { - if (alarmEnabled) { - lcd()->print("On "); - timeCol = 3; - } else { - lcd()->print("Off "); - lcd()->setCursor(0, 1); - return; - } - } - if (is24HourClock) { - lcd()->write('0' + hour / 10); - lcd()->write('0' + hour % 10); - pm = false; - } else if (hour == 0 || hour == 12) { - lcd()->write('1'); - lcd()->write('2'); - pm = (hour == 12); - } else if (hour < 12) { - lcd()->write('0' + hour / 10); - lcd()->write('0' + hour % 10); - pm = false; - } else { - hour -= 12; - lcd()->write('0' + hour / 10); - lcd()->write('0' + hour % 10); - pm = true; - } - lcd()->write(':'); - lcd()->write('0' + minute / 10); - lcd()->write('0' + minute % 10); - if (!is24HourClock) - lcd()->print(pm ? "pm" : "am"); - if (editField == EDIT_ENABLED) - lcd()->setCursor(0, 1); - else if (editField == EDIT_HOUR) - lcd()->setCursor(timeCol + 1, 1); - else if (editField == EDIT_MINUTE_TENS) - lcd()->setCursor(timeCol + 3, 1); - else if (editField == EDIT_MINUTE) - lcd()->setCursor(timeCol + 4, 1); -} diff --git a/libraries/RTC/examples/AlarmClock/EditTime.h b/libraries/RTC/examples/AlarmClock/EditTime.h deleted file mode 100644 index cd95ef07..00000000 --- a/libraries/RTC/examples/AlarmClock/EditTime.h +++ /dev/null @@ -1,53 +0,0 @@ -/* - * Copyright (C) 2012 Southern Storm Software, Pty Ltd. - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * the rights to use, copy, modify, merge, publish, distribute, sublicense, - * and/or sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included - * in all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS - * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER - * DEALINGS IN THE SOFTWARE. - */ - -#ifndef EditTime_h -#define EditTime_h - -#include "Field.h" -#include - -class EditTime : public Field { -public: - EditTime(Form &form, const String &label); - - int dispatch(int event); - - void enterField(bool reverse); - void exitField(); - - RTCTime value() const { return _value; } - void setValue(const RTCTime &value); - - RTCAlarm alarmValue() const; - void setAlarmValue(const RTCAlarm &value); - -protected: - bool isAlarm; - bool alarmEnabled; - RTCTime _value; - uint8_t editField; - - void printTime(); -}; - -#endif diff --git a/libraries/RTC/examples/AlarmClock/SetAlarm.cpp b/libraries/RTC/examples/AlarmClock/SetAlarm.cpp index 69e45d4b..bddee885 100644 --- a/libraries/RTC/examples/AlarmClock/SetAlarm.cpp +++ b/libraries/RTC/examples/AlarmClock/SetAlarm.cpp @@ -23,22 +23,216 @@ #include "SetAlarm.h" #include "Clock.h" +#define EDIT_ENABLED 0 +#define EDIT_HOUR 1 +#define EDIT_MINUTE_TENS 2 +#define EDIT_MINUTE 3 +#define EDIT_DAYS 4 + +extern bool is24HourClock; + SetAlarm::SetAlarm(Form &form, const String &label, uint8_t alarmNum) - : EditTime(form, label) + : Field(form, label) , _alarmNum(alarmNum) { RTCAlarm alarm; - rtc.readAlarm(_alarmNum, &alarm); - setAlarmValue(alarm); + rtc.readAlarm(_alarmNum, &_value); } int SetAlarm::dispatch(int event) { - int result = EditTime::dispatch(event); - if (result == FORM_CHANGED) { - // Update the alarm details in the realtime clock chip. - RTCAlarm alarm = alarmValue(); - rtc.writeAlarm(_alarmNum, &alarm); + RTCAlarm newValue; + if (event == LCD_BUTTON_UP) { + newValue = _value; + if (editField == EDIT_HOUR) { + newValue.hour = (newValue.hour + 1) % 24; + } else if (editField == EDIT_MINUTE_TENS) { + newValue.minute = (newValue.minute + 10) % 60; + } else if (editField == EDIT_MINUTE) { + newValue.minute = (newValue.minute + 1) % 60; + } else if (editField == EDIT_ENABLED) { + newValue.flags ^= 0x01; + if (newValue.flags & 0x01) + editField = EDIT_HOUR; + setValue(newValue); + return FORM_CHANGED; + } else if (editField == EDIT_DAYS) { + Days d = days(); + switch (d) { + case AnyDay: d = SaturdayAndSunday; break; + case MondayToFriday: d = AnyDay; break; + case SaturdayAndSunday: d = MondayToFriday; break; + } + setDays(d); + return FORM_CHANGED; + } + setValue(newValue); + return FORM_CHANGED; + } else if (event == LCD_BUTTON_DOWN) { + newValue = _value; + if (editField == EDIT_HOUR) { + newValue.hour = (newValue.hour + 23) % 24; + } else if (editField == EDIT_MINUTE_TENS) { + newValue.minute = (newValue.minute + 50) % 60; + } else if (editField == EDIT_MINUTE) { + newValue.minute = (newValue.minute + 59) % 60; + } else if (editField == EDIT_ENABLED) { + newValue.flags ^= 0x01; + if (newValue.flags & 0x01) + editField = EDIT_HOUR; + setValue(newValue); + return FORM_CHANGED; + } else if (editField == EDIT_DAYS) { + Days d = days(); + switch (d) { + case AnyDay: d = MondayToFriday; break; + case MondayToFriday: d = SaturdayAndSunday; break; + case SaturdayAndSunday: d = AnyDay; break; + } + setDays(d); + return FORM_CHANGED; + } + setValue(newValue); + return FORM_CHANGED; + } else if (event == LCD_BUTTON_LEFT) { + if (editField != EDIT_ENABLED) { + --editField; + printAlarm(); + return 0; + } + } else if (event == LCD_BUTTON_RIGHT) { + if (isEnabled() && editField != EDIT_DAYS) { + ++editField; + printAlarm(); + return 0; + } } - return result; + return -1; +} + +void SetAlarm::enterField(bool reverse) +{ + Field::enterField(reverse); + if (isEnabled()) { + if (reverse) + editField = EDIT_DAYS; + else + editField = EDIT_ENABLED; + } else { + editField = EDIT_ENABLED; + } + printAlarm(); + lcd()->cursor(); +} + +void SetAlarm::exitField() +{ + lcd()->noCursor(); + Field::exitField(); +} + +void SetAlarm::setValue(const RTCAlarm &value) +{ + _value = value; + rtc.writeAlarm(_alarmNum, &_value); + if (isCurrent()) + printAlarm(); +} + +SetAlarm::Days SetAlarm::days() const +{ + return days(&_value); +} + +void SetAlarm::setDays(Days days) +{ + _value.flags &= 0xE1; + _value.flags |= (((uint8_t)days) << 1); + rtc.writeAlarm(_alarmNum, &_value); + if (isCurrent()) + printAlarm(); +} + +SetAlarm::Days SetAlarm::days(const RTCAlarm *alarm) +{ + // 4 bits are allocated for day indicators, to allow for later expansion. + uint8_t d = (alarm->flags >> 1) & 0x0F; + if (d > SaturdayAndSunday) + d = AnyDay; + return (Days)d; +} + +// Combine the day flags for two alarms; e.g., if one is Mon-Fri and +// the other is Sat,Sun, then the result is AnyDay. +void SetAlarm::combineDays(RTCAlarm *alarm1, const RTCAlarm *alarm2) +{ + uint8_t d1 = (alarm1->flags >> 1) & 0x0F; + if (d1 > SaturdayAndSunday) + d1 = AnyDay; + uint8_t d2 = (alarm2->flags >> 1) & 0x0F; + if (d2 > SaturdayAndSunday) + d2 = AnyDay; + if (d1 != d2) + d1 = AnyDay; + alarm1->flags &= 0xE1; + alarm1->flags |= (((uint8_t)d1) << 1); +} + +static const char *daysShort[] = {" Mo-Su", " Mo-Fr", " Sa,Su"}; +static const char *daysLong[] = {" Any day", " Mon-Fri", " Sat,Sun"}; + +void SetAlarm::printAlarm() +{ + lcd()->setCursor(0, 1); + int hour = _value.hour; + int minute = _value.minute; + int timeCol = 3; + int dayCol; + bool pm; + if (isEnabled()) { + lcd()->print("On "); + } else { + lcd()->print("Off "); + lcd()->setCursor(0, 1); + return; + } + if (is24HourClock) { + lcd()->write('0' + hour / 10); + lcd()->write('0' + hour % 10); + pm = false; + } else if (hour == 0 || hour == 12) { + lcd()->write('1'); + lcd()->write('2'); + pm = (hour == 12); + } else if (hour < 12) { + lcd()->write('0' + hour / 10); + lcd()->write('0' + hour % 10); + pm = false; + } else { + hour -= 12; + lcd()->write('0' + hour / 10); + lcd()->write('0' + hour % 10); + pm = true; + } + lcd()->write(':'); + lcd()->write('0' + minute / 10); + lcd()->write('0' + minute % 10); + if (is24HourClock) { + dayCol = timeCol + 6; + lcd()->print(daysLong[days()]); + } else { + lcd()->print(pm ? "pm" : "am"); + lcd()->print(daysShort[days()]); + dayCol = timeCol + 8; + } + if (editField == EDIT_ENABLED) + lcd()->setCursor(0, 1); + else if (editField == EDIT_HOUR) + lcd()->setCursor(timeCol + 1, 1); + else if (editField == EDIT_MINUTE_TENS) + lcd()->setCursor(timeCol + 3, 1); + else if (editField == EDIT_MINUTE) + lcd()->setCursor(timeCol + 4, 1); + else if (editField == EDIT_DAYS) + lcd()->setCursor(dayCol, 1); } diff --git a/libraries/RTC/examples/AlarmClock/SetAlarm.h b/libraries/RTC/examples/AlarmClock/SetAlarm.h index 86bd7d00..51ad1202 100644 --- a/libraries/RTC/examples/AlarmClock/SetAlarm.h +++ b/libraries/RTC/examples/AlarmClock/SetAlarm.h @@ -23,16 +23,43 @@ #ifndef SetAlarm_h #define SetAlarm_h -#include "EditTime.h" +#include "Field.h" +#include -class SetAlarm : public EditTime { +class SetAlarm : public Field { public: SetAlarm(Form &form, const String &label, uint8_t alarmNum); int dispatch(int event); + void enterField(bool reverse); + void exitField(); + + RTCAlarm value() const { return _value; } + void setValue(const RTCAlarm &value); + + enum Days + { + AnyDay, + MondayToFriday, + SaturdayAndSunday + }; + + Days days() const; + void setDays(Days days); + + static Days days(const RTCAlarm *alarm); + + static void combineDays(RTCAlarm *alarm1, const RTCAlarm *alarm2); + private: uint8_t _alarmNum; + RTCAlarm _value; + uint8_t editField; + + bool isEnabled() const { return (_value.flags & 0x01) != 0; } + + void printAlarm(); }; #endif diff --git a/libraries/RTC/examples/AlarmClock/SetTime.cpp b/libraries/RTC/examples/AlarmClock/SetTime.cpp index 61ad6a3d..92ca0ec8 100644 --- a/libraries/RTC/examples/AlarmClock/SetTime.cpp +++ b/libraries/RTC/examples/AlarmClock/SetTime.cpp @@ -23,27 +23,88 @@ #include "SetTime.h" #include "Clock.h" +#define EDIT_HOUR 0 +#define EDIT_MINUTE_TENS 1 +#define EDIT_MINUTE 2 + +extern bool is24HourClock; + SetTime::SetTime(Form &form, const String &label) - : EditTime(form, label) + : Field(form, label) + , editField(EDIT_HOUR) { + _value.hour = 0; + _value.minute = 0; + _value.second = 0; } int SetTime::dispatch(int event) { - int result = EditTime::dispatch(event); - if (result == FORM_CHANGED) { - // Update the realtime clock with the new value. - RTCTime time = value(); - rtc.writeTime(&time); + RTCTime newValue; + if (event == LCD_BUTTON_UP) { + newValue = _value; + if (editField == EDIT_HOUR) { + newValue.hour = (newValue.hour + 1) % 24; + } else if (editField == EDIT_MINUTE_TENS) { + newValue.minute = (newValue.minute + 10) % 60; + } else if (editField == EDIT_MINUTE) { + newValue.minute = (newValue.minute + 1) % 60; + } + newValue.second = 0; + setValue(newValue); + return FORM_CHANGED; + } else if (event == LCD_BUTTON_DOWN) { + newValue = _value; + if (editField == EDIT_HOUR) { + newValue.hour = (newValue.hour + 23) % 24; + } else if (editField == EDIT_MINUTE_TENS) { + newValue.minute = (newValue.minute + 50) % 60; + } else if (editField == EDIT_MINUTE) { + newValue.minute = (newValue.minute + 59) % 60; + } + newValue.second = 0; + setValue(newValue); + return FORM_CHANGED; + } else if (event == LCD_BUTTON_LEFT) { + if (editField != EDIT_HOUR) { + --editField; + printTime(); + return 0; + } + } else if (event == LCD_BUTTON_RIGHT) { + if (editField != EDIT_MINUTE) { + ++editField; + printTime(); + return 0; + } } - return result; + return -1; } void SetTime::enterField(bool reverse) { - // Read the current time when the field is entered. + Field::enterField(reverse); rtc.readTime(&_value); - EditTime::enterField(reverse); + if (reverse) + editField = EDIT_MINUTE; + else + editField = EDIT_HOUR; + printTime(); + lcd()->cursor(); +} + +void SetTime::exitField() +{ + lcd()->noCursor(); + Field::exitField(); +} + +void SetTime::setValue(const RTCTime &value) +{ + _value = value; + rtc.writeTime(&_value); + if (isCurrent()) + printTime(); } void SetTime::updateCurrentTime() @@ -57,3 +118,41 @@ void SetTime::updateCurrentTime() } } } + +void SetTime::printTime() +{ + lcd()->setCursor(0, 1); + int hour = _value.hour; + int minute = _value.minute; + int timeCol = 0; + bool pm; + if (is24HourClock) { + lcd()->write('0' + hour / 10); + lcd()->write('0' + hour % 10); + pm = false; + } else if (hour == 0 || hour == 12) { + lcd()->write('1'); + lcd()->write('2'); + pm = (hour == 12); + } else if (hour < 12) { + lcd()->write('0' + hour / 10); + lcd()->write('0' + hour % 10); + pm = false; + } else { + hour -= 12; + lcd()->write('0' + hour / 10); + lcd()->write('0' + hour % 10); + pm = true; + } + lcd()->write(':'); + lcd()->write('0' + minute / 10); + lcd()->write('0' + minute % 10); + if (!is24HourClock) + lcd()->print(pm ? "pm" : "am"); + if (editField == EDIT_HOUR) + lcd()->setCursor(timeCol + 1, 1); + else if (editField == EDIT_MINUTE_TENS) + lcd()->setCursor(timeCol + 3, 1); + else if (editField == EDIT_MINUTE) + lcd()->setCursor(timeCol + 4, 1); +} diff --git a/libraries/RTC/examples/AlarmClock/SetTime.h b/libraries/RTC/examples/AlarmClock/SetTime.h index e13ca654..5dffe31a 100644 --- a/libraries/RTC/examples/AlarmClock/SetTime.h +++ b/libraries/RTC/examples/AlarmClock/SetTime.h @@ -23,17 +23,28 @@ #ifndef SetTime_h #define SetTime_h -#include "EditTime.h" +#include "Field.h" +#include -class SetTime : public EditTime { +class SetTime : public Field { public: SetTime(Form &form, const String &label); int dispatch(int event); void enterField(bool reverse); + void exitField(); + + RTCTime value() const { return _value; } + void setValue(const RTCTime &value); void updateCurrentTime(); + +protected: + RTCTime _value; + uint8_t editField; + + void printTime(); }; #endif