// TimeAlarms.h - Arduino Time alarms header for use with Time library #ifndef TimeAlarms_h #define TimeAlarms_h #include #include "TimeLib.h" #if !defined(dtNBR_ALARMS ) #if defined(__AVR__) #define dtNBR_ALARMS 6 // max is 255 #elif defined(ESP8266) #define dtNBR_ALARMS 20 // for esp8266 chip - max is 255 #else #define dtNBR_ALARMS 12 // assume non-AVR has more memory #endif #endif #define USE_SPECIALIST_METHODS // define this for testing typedef enum { dtMillisecond, dtSecond, dtMinute, dtHour, dtDay } dtUnits_t; typedef struct { uint8_t alarmType :4 ; // enumeration of daily/weekly (in future: // biweekly/semimonthly/monthly/annual) // note that the current API only supports daily // or weekly alarm periods uint8_t isEnabled :1 ; // the timer is only actioned if isEnabled is true uint8_t isOneShot :1 ; // the timer will be de-allocated after trigger is processed } AlarmMode_t; // new time based alarms should be added just before dtLastAlarmType typedef enum { dtNotAllocated, dtTimer, dtExplicitAlarm, dtDailyAlarm, dtWeeklyAlarm, dtLastAlarmType } dtAlarmPeriod_t ; // in future: dtBiweekly, dtMonthly, dtAnnual // macro to return true if the given type is a time based alarm, false if timer or not allocated #define dtIsAlarm(_type_) (_type_ >= dtExplicitAlarm && _type_ < dtLastAlarmType) #define dtUseAbsoluteValue(_type_) (_type_ == dtTimer || _type_ == dtExplicitAlarm) typedef uint8_t AlarmID_t; typedef AlarmID_t AlarmId; // Arduino friendly name #define dtINVALID_ALARM_ID 255 #define dtINVALID_TIME (time_t)(-1) #define AlarmHMS(_hr_, _min_, _sec_) (_hr_ * SECS_PER_HOUR + _min_ * SECS_PER_MIN + _sec_) typedef void (*OnTick_t)(); // alarm callback function typedef // class defining an alarm instance, only used by dtAlarmsClass class AlarmClass { public: AlarmClass(); OnTick_t onTickHandler; void updateNextTrigger(); time_t value; time_t nextTrigger; AlarmMode_t Mode; }; // class containing the collection of alarms class TimeAlarmsClass { private: AlarmClass Alarm[dtNBR_ALARMS]; void serviceAlarms(); uint8_t isServicing; uint8_t servicedAlarmId; // the alarm currently being serviced AlarmID_t create(time_t value, OnTick_t onTickHandler, uint8_t isOneShot, dtAlarmPeriod_t alarmType); public: TimeAlarmsClass(); // functions to create alarms and timers // trigger once at the given time in the future AlarmID_t triggerOnce(time_t value, OnTick_t onTickHandler) { if (value <= 0) return dtINVALID_ALARM_ID; return create(value, onTickHandler, true, dtExplicitAlarm); } // trigger once at given time of day AlarmID_t alarmOnce(time_t value, OnTick_t onTickHandler) { if (value <= 0 || value > SECS_PER_DAY) return dtINVALID_ALARM_ID; return create(value, onTickHandler, true, dtDailyAlarm); } AlarmID_t alarmOnce(const int H, const int M, const int S, OnTick_t onTickHandler) { return alarmOnce(AlarmHMS(H,M,S), onTickHandler); } // trigger once on a given day and time AlarmID_t alarmOnce(const timeDayOfWeek_t DOW, const int H, const int M, const int S, OnTick_t onTickHandler) { time_t value = (DOW-1) * SECS_PER_DAY + AlarmHMS(H,M,S); if (value <= 0) return dtINVALID_ALARM_ID; return create(value, onTickHandler, true, dtWeeklyAlarm); } // trigger daily at given time of day AlarmID_t alarmRepeat(time_t value, OnTick_t onTickHandler) { if (value > SECS_PER_DAY) return dtINVALID_ALARM_ID; return create(value, onTickHandler, false, dtDailyAlarm); } AlarmID_t alarmRepeat(const int H, const int M, const int S, OnTick_t onTickHandler) { return alarmRepeat(AlarmHMS(H,M,S), onTickHandler); } // trigger weekly at a specific day and time AlarmID_t alarmRepeat(const timeDayOfWeek_t DOW, const int H, const int M, const int S, OnTick_t onTickHandler) { time_t value = (DOW-1) * SECS_PER_DAY + AlarmHMS(H,M,S); if (value <= 0) return dtINVALID_ALARM_ID; return create(value, onTickHandler, false, dtWeeklyAlarm); } // trigger once after the given number of seconds AlarmID_t timerOnce(time_t value, OnTick_t onTickHandler) { if (value <= 0) return dtINVALID_ALARM_ID; return create(value, onTickHandler, true, dtTimer); } AlarmID_t timerOnce(const int H, const int M, const int S, OnTick_t onTickHandler) { return timerOnce(AlarmHMS(H,M,S), onTickHandler); } // trigger at a regular interval AlarmID_t timerRepeat(time_t value, OnTick_t onTickHandler) { if (value <= 0) return dtINVALID_ALARM_ID; return create(value, onTickHandler, false, dtTimer); } AlarmID_t timerRepeat(const int H, const int M, const int S, OnTick_t onTickHandler) { return timerRepeat(AlarmHMS(H,M,S), onTickHandler); } void delay(unsigned long ms); // utility methods uint8_t getDigitsNow( dtUnits_t Units) const; // returns the current digit value for the given time unit void waitForDigits( uint8_t Digits, dtUnits_t Units); void waitForRollover(dtUnits_t Units); // low level methods void enable(AlarmID_t ID); // enable the alarm to trigger void disable(AlarmID_t ID); // prevent the alarm from triggering AlarmID_t getTriggeredAlarmId() const; // returns the currently triggered alarm id bool getIsServicing() const; // returns isServicing void write(AlarmID_t ID, time_t value); // write the value (and enable) the alarm with the given ID time_t read(AlarmID_t ID) const; // return the value for the given timer dtAlarmPeriod_t readType(AlarmID_t ID) const; // return the alarm type for the given alarm ID void free(AlarmID_t ID); // free the id to allow its reuse #ifndef USE_SPECIALIST_METHODS private: // the following methods are for testing and are not documented as part of the standard library #endif uint8_t count() const; // returns the number of allocated timers time_t getNextTrigger() const; // returns the time of the next scheduled alarm time_t getNextTrigger(AlarmID_t ID) const; // returns the time of scheduled alarm bool isAllocated(AlarmID_t ID) const; // returns true if this id is allocated bool isAlarm(AlarmID_t ID) const; // returns true if id is for a time based alarm, false if its a timer or not allocated }; extern TimeAlarmsClass Alarm; // make an instance for the user /*============================================================================== * MACROS *============================================================================*/ /* public */ #define waitUntilThisSecond(_val_) waitForDigits( _val_, dtSecond) #define waitUntilThisMinute(_val_) waitForDigits( _val_, dtMinute) #define waitUntilThisHour(_val_) waitForDigits( _val_, dtHour) #define waitUntilThisDay(_val_) waitForDigits( _val_, dtDay) #define waitMinuteRollover() waitForRollover(dtSecond) #define waitHourRollover() waitForRollover(dtMinute) #define waitDayRollover() waitForRollover(dtHour) #endif /* TimeAlarms_h */