mirror of
				https://github.com/taigrr/arduinolibs
				synced 2025-01-18 04:33:12 -08:00 
			
		
		
		
	Alarms that fire only Mon-Fri or Sat&Sun
This commit is contained in:
		
							parent
							
								
									08ba3a7d0f
								
							
						
					
					
						commit
						5e877e5bb3
					
				| @ -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. | ||||
|  | ||||
| @ -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); | ||||
|     } | ||||
| } | ||||
| 
 | ||||
|  | ||||
| @ -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 <RTC.h> | ||||
| 
 | ||||
| #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); | ||||
| } | ||||
| @ -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 <RTC.h> | ||||
| 
 | ||||
| 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 | ||||
| @ -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); | ||||
| } | ||||
|  | ||||
| @ -23,16 +23,43 @@ | ||||
| #ifndef SetAlarm_h | ||||
| #define SetAlarm_h | ||||
| 
 | ||||
| #include "EditTime.h" | ||||
| #include "Field.h" | ||||
| #include <RTC.h> | ||||
| 
 | ||||
| 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 | ||||
|  | ||||
| @ -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); | ||||
| } | ||||
|  | ||||
| @ -23,17 +23,28 @@ | ||||
| #ifndef SetTime_h | ||||
| #define SetTime_h | ||||
| 
 | ||||
| #include "EditTime.h" | ||||
| #include "Field.h" | ||||
| #include <RTC.h> | ||||
| 
 | ||||
| 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 | ||||
|  | ||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user