1
0
mirror of https://github.com/taigrr/arduinolibs synced 2025-01-18 04:33:12 -08:00

Add a snooze feature to the alarm clock

This commit is contained in:
Rhys Weatherley 2012-05-23 13:02:12 +10:00
parent dce1ede576
commit a872972c9d
3 changed files with 87 additions and 31 deletions

View File

@ -50,6 +50,7 @@
// Offsets of settings in the realtime clock's NVRAM.
#define SETTING_24HOUR 0 // 0: 12 hour, 1: 24 hour
#define SETTING_ALARM_TIMEOUT 1 // Timeout in minutes for the alarm
#define SETTING_SNOOZE 2 // 0: no snooze, 1: snooze
// Initialize the LCD
FreetronicsLCD lcd;
@ -75,6 +76,7 @@ SetAlarm alarm2(mainForm, "Alarm 2", 1);
SetAlarm alarm3(mainForm, "Alarm 3", 2);
SetAlarm alarm4(mainForm, "Alarm 4", 3);
IntField alarmTimeout(mainForm, "Alarm timeout", 2, 10, 1, 2, " minutes");
BoolField snooze(mainForm, "Snooze alarm", "On", "Off", false);
SetTime setTime(mainForm, "Set current time");
SetDate setDate(mainForm, "Set current date");
BoolField hourMode(mainForm, "Hour display", "24 hour clock", "12 hour clock", false);
@ -112,6 +114,7 @@ void setup() {
frontScreen.set24HourMode(is24HourClock);
alarmTimeout.setValue(rtc.readByte(SETTING_ALARM_TIMEOUT));
alarmMelody.setLoopDuration(60000UL * alarmTimeout.value());
snooze.setValue(rtc.readByte(SETTING_SNOOZE) != 0);
// Set the initial time and date and find the next alarm to be triggered.
RTCTime time;
@ -171,6 +174,8 @@ void loop() {
} else if (alarmTimeout.isCurrent()) {
rtc.writeByte(SETTING_ALARM_TIMEOUT, (byte)alarmTimeout.value());
alarmMelody.setLoopDuration(60000UL * alarmTimeout.value());
} else if (snooze.isCurrent()) {
rtc.writeByte(SETTING_SNOOZE, (byte)snooze.value());
}
prevHour = 24; // Force an update of the main screen.
findNextAlarm(); // Update the time of the next alarm event.
@ -191,12 +196,28 @@ inline int timeToAlarm(const RTCTime &currentTime, const RTCAlarm &alarm)
{
int mins1 = currentTime.hour * 60 + currentTime.minute;
int mins2 = alarm.hour * 60 + alarm.minute;
if (mins1 < mins2)
if (mins1 <= mins2)
return mins2 - mins1;
else
return 24 * 60 + mins2 - mins1;
}
// Add 9 minutes to an alarm to get its snooze time.
RTCAlarm adjustForSnooze(const RTCAlarm &alarm)
{
if (!alarm.flags)
return alarm;
RTCAlarm snooze;
snooze.hour = alarm.hour;
snooze.minute = alarm.minute + 9;
if (snooze.minute >= 60) {
snooze.hour = (snooze.hour + 1) % 24;
snooze.minute %= 60;
}
snooze.flags = alarm.flags;
return snooze;
}
// Find the time of the next alarm to be triggered.
void findNextAlarm()
{
@ -215,9 +236,22 @@ void findNextAlarm()
findNextAlarm(currentTime, alarm2.alarmValue());
findNextAlarm(currentTime, alarm3.alarmValue());
findNextAlarm(currentTime, alarm4.alarmValue());
if (snooze.value()) {
findNextAlarm(currentTime, adjustForSnooze(alarm1.alarmValue()));
findNextAlarm(currentTime, adjustForSnooze(alarm2.alarmValue()));
findNextAlarm(currentTime, adjustForSnooze(alarm3.alarmValue()));
findNextAlarm(currentTime, adjustForSnooze(alarm4.alarmValue()));
}
// Set the alarm indicator on the front screen.
frontScreen.setAlarmActive(nextAlarm.flags != 0);
if (nextAlarm.flags) {
if (snooze.value())
frontScreen.setAlarmMode(FrontScreenField::Snooze);
else
frontScreen.setAlarmMode(FrontScreenField::AlarmOn);
} else {
frontScreen.setAlarmMode(FrontScreenField::AlarmOff);
}
}
void findNextAlarm(const RTCTime &currentTime, const RTCAlarm &alarm)
{

View File

@ -40,7 +40,7 @@ FrontScreenField::FrontScreenField(Form &form)
, _voltageTrunc(36)
, _batteryBars(IND_BATTERY_FULL)
#endif
, _alarmActive(false)
, _alarmMode(FrontScreenField::AlarmOff)
, _hourMode(false)
{
_date.day = 1;
@ -124,10 +124,45 @@ void FrontScreenField::setVoltage(int voltage)
#endif
void FrontScreenField::setAlarmActive(bool active)
static uint8_t alarmActive1[8] = {
B00100,
B01001,
B10010,
B00000,
B10010,
B01001,
B00100,
B00000
};
static uint8_t alarmActive2[8] = {
B11000,
B10100,
B10011,
B10011,
B10011,
B10100,
B11000,
B00000
};
static uint8_t alarmSnooze[8] = {
B11110,
B00100,
B01000,
B11110,
B00000,
B00000,
B00000,
B00000
};
void FrontScreenField::setAlarmMode(AlarmMode mode)
{
if (_alarmActive != active) {
_alarmActive = active;
if (_alarmMode != mode) {
_alarmMode = mode;
if (mode == Snooze)
lcd()->createChar(IND_ALARM_ACTIVE1, alarmSnooze);
else
lcd()->createChar(IND_ALARM_ACTIVE1, alarmActive1);
if (isCurrent())
updateAlarm();
}
@ -211,8 +246,8 @@ void FrontScreenField::updateAlarm()
#else
lcd()->setCursor(14, 0);
#endif
lcd()->write(_alarmActive ? IND_ALARM_ACTIVE1 : ' ');
lcd()->write(_alarmActive ? IND_ALARM_ACTIVE2 : ' ');
lcd()->write(_alarmMode != AlarmOff ? IND_ALARM_ACTIVE1 : ' ');
lcd()->write(_alarmMode != AlarmOff ? IND_ALARM_ACTIVE2 : ' ');
}
#ifdef USE_VOLTAGE_MONITOR
@ -277,26 +312,6 @@ static uint8_t batteryFull[8] = {
B00000
};
#endif
static uint8_t alarmActive1[8] = {
B00100,
B01001,
B10010,
B00000,
B10010,
B01001,
B00100,
B00000
};
static uint8_t alarmActive2[8] = {
B11000,
B10100,
B10011,
B10011,
B10011,
B10100,
B11000,
B00000
};
void FrontScreenField::registerIndicators()
{

View File

@ -47,8 +47,15 @@ public:
void setVoltage(int voltage);
#endif
bool isAlarmActive() const { return _alarmActive; }
void setAlarmActive(bool active);
enum AlarmMode
{
AlarmOff,
AlarmOn,
Snooze
};
AlarmMode isAlarmMode() const { return _alarmMode; }
void setAlarmMode(AlarmMode mode);
bool is24HourMode() const { return _hourMode; }
void set24HourMode(bool value);
@ -61,7 +68,7 @@ private:
int _voltageTrunc;
int _batteryBars;
#endif
bool _alarmActive;
AlarmMode _alarmMode;
bool _hourMode;
void updateDate();