Skip to content

Commit

Permalink
Fix #3
Browse files Browse the repository at this point in the history
This fix the issue where alarms set to go off at Midnight (on a daily or weekly basis)
will fail and act as if the alarm is disabled.

Note that the definition of "dtINVALID_TIME" changed (see below).

The following changes have been made to TimeAlarms.cpp:
-AlarmClass::updateNextTrigget(): Only rely on Mode.isEnabled to determine if enabled
or not (no longer check value as it is redundent)
-TimeAlarmsClass::enable(): Changed how a valid alarm is checked to allow for a value
of 0 only on alarms that should accept it
-TimeAlarmsClass::enable(): Now the alarm is disabled if we don't have safe conditions to
enable it
-TimeAlarmsClass::free(): When freeing an alarm, we set .onTickHandler to NULL to avoid
confusion
-TimeAlarmsClass::create(): Changed how a valid alarm is checked to allow for a value of 0
only on alarms that should accept it

The following changes have been made to TimeAlarms.h:
-Add macro: dtUseAbsoluteValue to simplify checking of the value parameter
-dtINVALID_TIME: Change definition from 0 to (time_t)(-1) as now a value of 0 can be
valid. Now the highest possible value is used.
-move 'TimeAlarmsClass::free()' to the public portion of the class so we can always use it
to properly free alarms.
  • Loading branch information
oortael committed Dec 21, 2015
1 parent da72ec1 commit bc81d4a
Show file tree
Hide file tree
Showing 2 changed files with 24 additions and 19 deletions.
25 changes: 14 additions & 11 deletions TimeAlarms.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@ AlarmClass::AlarmClass()

void AlarmClass::updateNextTrigger()
{
if( (value != 0) && Mode.isEnabled )
if( Mode.isEnabled )
{
time_t time = now();
if( dtIsAlarm(Mode.alarmType) && nextTrigger <= time ) // update alarm if next trigger is not yet in the future
Expand Down Expand Up @@ -85,7 +85,7 @@ void AlarmClass::updateNextTrigger()
}
else // its not a recognized alarm type - this should not happen
{
Mode.isEnabled = 0; // Disable the alarm
Mode.isEnabled = false; // Disable the alarm
}
}
if( Mode.alarmType == dtTimer)
Expand All @@ -94,10 +94,6 @@ void AlarmClass::updateNextTrigger()
nextTrigger = time + value; // add the value to previous time (this ensures delay always at least Value seconds)
}
}
else
{
Mode.isEnabled = 0; // Disable if the value is 0
}
}

//**************************************************************
Expand Down Expand Up @@ -170,8 +166,15 @@ AlarmID_t TimeAlarmsClass::alarmRepeat(time_t value, OnTick_t onTickHandler){ //
void TimeAlarmsClass::enable(AlarmID_t ID)
{
if(isAllocated(ID)) {
Alarm[ID].Mode.isEnabled = (Alarm[ID].value != 0) && (Alarm[ID].onTickHandler != 0) ; // only enable if value is non zero and a tick handler has been set
Alarm[ID].updateNextTrigger(); // trigger is updated whenever this is called, even if already enabled
if (( ! (dtUseAbsoluteValue(Alarm[ID].Mode.alarmType) && (Alarm[ID].value == 0)) ) && (Alarm[ID].onTickHandler != NULL))
{
Alarm[ID].Mode.isEnabled = true; // only enable if value is non zero and a tick handler has been set (is not NULL, value is non zero ONLY for dtTimer & dtExplicitAlarm (the rest can have 0 to account for midnight))
Alarm[ID].updateNextTrigger(); // trigger is updated whenever this is called, even if already enabled
}
else
{
Alarm[ID].Mode.isEnabled = false;
}
}
}

Expand All @@ -186,7 +189,7 @@ AlarmID_t TimeAlarmsClass::alarmRepeat(time_t value, OnTick_t onTickHandler){ //
{
if(isAllocated(ID))
{
Alarm[ID].value = value;
Alarm[ID].value = value; //note: we don't check value as we do it in enable()
enable(ID); // update trigger time
}
}
Expand Down Expand Up @@ -215,7 +218,7 @@ AlarmID_t TimeAlarmsClass::alarmRepeat(time_t value, OnTick_t onTickHandler){ //
{
Alarm[ID].Mode.isEnabled = false;
Alarm[ID].Mode.alarmType = dtNotAllocated;
Alarm[ID].onTickHandler = 0;
Alarm[ID].onTickHandler = NULL;
Alarm[ID].value = 0;
Alarm[ID].nextTrigger = 0;
}
Expand Down Expand Up @@ -333,7 +336,7 @@ AlarmID_t TimeAlarmsClass::alarmRepeat(time_t value, OnTick_t onTickHandler){ //
// attempt to create an alarm and return true if successful
AlarmID_t TimeAlarmsClass::create( time_t value, OnTick_t onTickHandler, uint8_t isOneShot, dtAlarmPeriod_t alarmType, uint8_t isEnabled)
{
if( ! (dtIsAlarm(alarmType) && now() < SECS_PER_YEAR)) // only create alarm ids if the time is at least Jan 1 1971
if( ! ( (dtIsAlarm(alarmType) && now() < SECS_PER_YEAR) || (dtUseAbsoluteValue(alarmType) && (value == 0)) ) ) // only create alarm ids if the time is at least Jan 1 1971
{
for(uint8_t id = 0; id < dtNBR_ALARMS; id++)
{
Expand Down
18 changes: 10 additions & 8 deletions TimeAlarms.h
Original file line number Diff line number Diff line change
Expand Up @@ -13,25 +13,26 @@

typedef enum { dtMillisecond, dtSecond, dtMinute, dtHour, dtDay } dtUnits_t;

typedef struct {
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
// 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 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 0L
#define dtINVALID_TIME (time_t)(-1)

class AlarmClass; // forward reference
typedef void (*OnTick_t)(); // alarm callback function typedef
Expand Down Expand Up @@ -94,11 +95,12 @@ class TimeAlarmsClass
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); // return the value for the given timer
dtAlarmPeriod_t readType(AlarmID_t ID); // 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
void free(AlarmID_t ID); // free the id to allow its reuse
uint8_t count(); // returns the number of allocated timers
time_t getNextTrigger(); // returns the time of the next scheduled alarm
bool isAllocated(AlarmID_t ID); // returns true if this id is allocated
Expand All @@ -109,7 +111,7 @@ extern TimeAlarmsClass Alarm; // make an instance for the user

/*==============================================================================
* MACROS
*============================================================================*/
*============================================================================*/

/* public */
#define waitUntilThisSecond(_val_) waitForDigits( _val_, dtSecond)
Expand Down

0 comments on commit bc81d4a

Please sign in to comment.