Alarm library for use with mbed.
AlarmTimeDate.cpp@1:f4c7f13e5553, 2010-10-31 (annotated)
- Committer:
- charlesgt
- Date:
- Sun Oct 31 08:13:17 2010 +0000
- Revision:
- 1:f4c7f13e5553
- Parent:
- 0:33dddd0644c5
- Child:
- 2:23e65cacea5a
Alpha version most not tested. Should move to using lists for expired, set and unset alarms, but example code should work now
Who changed what in which revision?
User | Revision | Line number | New contents of line |
---|---|---|---|
charlesgt | 0:33dddd0644c5 | 1 | #include "mbed.h" |
charlesgt | 0:33dddd0644c5 | 2 | #include "AlarmTimeDate.h" |
charlesgt | 0:33dddd0644c5 | 3 | |
charlesgt | 0:33dddd0644c5 | 4 | static AlarmTimeDate* list = NULL; |
charlesgt | 0:33dddd0644c5 | 5 | |
charlesgt | 0:33dddd0644c5 | 6 | void AlarmTimeDate::PrintAlarm() { |
charlesgt | 0:33dddd0644c5 | 7 | if (!iTime) printf("Alarm %x is not set\n",this); |
charlesgt | 0:33dddd0644c5 | 8 | else printf("Alarm %x will expire next at %s\n",this,ctime(&iTime)); |
charlesgt | 0:33dddd0644c5 | 9 | } |
charlesgt | 0:33dddd0644c5 | 10 | |
charlesgt | 0:33dddd0644c5 | 11 | void AlarmTimeDate::PrintAlarms() { |
charlesgt | 0:33dddd0644c5 | 12 | AlarmTimeDate* p = list; |
charlesgt | 0:33dddd0644c5 | 13 | while (p) { |
charlesgt | 0:33dddd0644c5 | 14 | p->PrintAlarm(); |
charlesgt | 0:33dddd0644c5 | 15 | p = p->iNext; |
charlesgt | 0:33dddd0644c5 | 16 | } |
charlesgt | 0:33dddd0644c5 | 17 | } |
charlesgt | 0:33dddd0644c5 | 18 | |
charlesgt | 0:33dddd0644c5 | 19 | AlarmTimeDate::AlarmTimeDate(AlarmCbFn aFn, void* aPtr) |
charlesgt | 0:33dddd0644c5 | 20 | :iTime(0),iFn(aFn),iPtr(aPtr) { |
charlesgt | 0:33dddd0644c5 | 21 | Queue(); |
charlesgt | 0:33dddd0644c5 | 22 | } |
charlesgt | 0:33dddd0644c5 | 23 | |
charlesgt | 0:33dddd0644c5 | 24 | AlarmTimeDate::AlarmTimeDate(AlarmCbFn aFn, void* aPtr, int aHours, |
charlesgt | 0:33dddd0644c5 | 25 | int aMins, int aSecs, int aDayM, int aMon, int aYear) |
charlesgt | 0:33dddd0644c5 | 26 | :iFn(aFn),iPtr(aPtr) { |
charlesgt | 0:33dddd0644c5 | 27 | struct tm sectm; |
charlesgt | 0:33dddd0644c5 | 28 | sectm.tm_sec = aSecs; |
charlesgt | 0:33dddd0644c5 | 29 | sectm.tm_min = aMins; |
charlesgt | 0:33dddd0644c5 | 30 | sectm.tm_hour = aHours; |
charlesgt | 0:33dddd0644c5 | 31 | sectm.tm_mday = aDayM; |
charlesgt | 0:33dddd0644c5 | 32 | sectm.tm_mon = aMon-1; |
charlesgt | 0:33dddd0644c5 | 33 | sectm.tm_year = aYear-1970; |
charlesgt | 0:33dddd0644c5 | 34 | iTime = mktime(§m); |
charlesgt | 0:33dddd0644c5 | 35 | Queue(); |
charlesgt | 0:33dddd0644c5 | 36 | } |
charlesgt | 0:33dddd0644c5 | 37 | |
charlesgt | 0:33dddd0644c5 | 38 | AlarmTimeDate::AlarmTimeDate(AlarmCbFn aFn, void* aPtr, int aHours, int aMins, |
charlesgt | 0:33dddd0644c5 | 39 | int aSecs, bool aSkipWeekends) |
charlesgt | 0:33dddd0644c5 | 40 | :iFn(aFn),iPtr(aPtr) { |
charlesgt | 0:33dddd0644c5 | 41 | // current time |
charlesgt | 0:33dddd0644c5 | 42 | time_t seconds = time(NULL); |
charlesgt | 0:33dddd0644c5 | 43 | struct tm * sectm = localtime(&seconds); |
charlesgt | 0:33dddd0644c5 | 44 | sectm->tm_sec = aSecs; |
charlesgt | 0:33dddd0644c5 | 45 | sectm->tm_min = aMins; |
charlesgt | 0:33dddd0644c5 | 46 | sectm->tm_hour = aHours; |
charlesgt | 0:33dddd0644c5 | 47 | time_t secs2 = mktime(sectm); |
charlesgt | 0:33dddd0644c5 | 48 | if (secs2<=seconds) { |
charlesgt | 0:33dddd0644c5 | 49 | secs2+=24*3600; // move forward one day if alarm is set for hours:mins:secs before current time |
charlesgt | 0:33dddd0644c5 | 50 | sectm = localtime(&secs2); |
charlesgt | 0:33dddd0644c5 | 51 | } |
charlesgt | 0:33dddd0644c5 | 52 | if (aSkipWeekends && !sectm->tm_wday) { // set on a Sunday but skipping weekends move to Monday |
charlesgt | 0:33dddd0644c5 | 53 | secs2+=24*3600; // move forward one day if alarm is set for hours:mins:secs before current time |
charlesgt | 0:33dddd0644c5 | 54 | sectm = localtime(&secs2); |
charlesgt | 0:33dddd0644c5 | 55 | } |
charlesgt | 0:33dddd0644c5 | 56 | if (aSkipWeekends && sectm->tm_wday==6) { // set on a Saturday but skipping weekends move to Monday |
charlesgt | 0:33dddd0644c5 | 57 | secs2+=2*24*3600; // move forward one day if alarm is set for hours:mins:secs before current time |
charlesgt | 0:33dddd0644c5 | 58 | sectm = localtime(&secs2); |
charlesgt | 0:33dddd0644c5 | 59 | } |
charlesgt | 0:33dddd0644c5 | 60 | iTime = mktime(sectm); |
charlesgt | 0:33dddd0644c5 | 61 | if (aSkipWeekends) SetRepeat(EDailyNoWeeked); |
charlesgt | 0:33dddd0644c5 | 62 | else SetRepeat(EDaily); |
charlesgt | 0:33dddd0644c5 | 63 | Queue(); |
charlesgt | 0:33dddd0644c5 | 64 | } |
charlesgt | 0:33dddd0644c5 | 65 | |
charlesgt | 0:33dddd0644c5 | 66 | AlarmTimeDate::AlarmTimeDate(AlarmCbFn aFn, void* aPtr, int aHours, int aMins, |
charlesgt | 0:33dddd0644c5 | 67 | int aSecs, int aDayW, bool aFortNightly) |
charlesgt | 0:33dddd0644c5 | 68 | :iFn(aFn),iPtr(aPtr) { |
charlesgt | 0:33dddd0644c5 | 69 | // current time |
charlesgt | 0:33dddd0644c5 | 70 | time_t seconds = time(NULL); |
charlesgt | 0:33dddd0644c5 | 71 | struct tm * sectm = localtime(&seconds); |
charlesgt | 0:33dddd0644c5 | 72 | sectm->tm_sec = aSecs; |
charlesgt | 0:33dddd0644c5 | 73 | sectm->tm_min = aMins; |
charlesgt | 0:33dddd0644c5 | 74 | sectm->tm_hour = aHours; |
charlesgt | 0:33dddd0644c5 | 75 | sectm->tm_wday = aDayW; |
charlesgt | 0:33dddd0644c5 | 76 | time_t secs2 = mktime(sectm); |
charlesgt | 0:33dddd0644c5 | 77 | if (secs2<=seconds && !aFortNightly) { |
charlesgt | 0:33dddd0644c5 | 78 | secs2+=7*24*3600; // move forward one week if alarm is set for hours:mins:secs:week day before current time |
charlesgt | 0:33dddd0644c5 | 79 | sectm = localtime(&secs2); |
charlesgt | 0:33dddd0644c5 | 80 | } |
charlesgt | 0:33dddd0644c5 | 81 | if (secs2<=seconds && !aFortNightly) { |
charlesgt | 0:33dddd0644c5 | 82 | secs2+=14*24*3600; // move forward one fornight if alarm is set for hours:mins:secs:week day before current time |
charlesgt | 0:33dddd0644c5 | 83 | sectm = localtime(&secs2); |
charlesgt | 0:33dddd0644c5 | 84 | } |
charlesgt | 0:33dddd0644c5 | 85 | iTime = mktime(sectm); |
charlesgt | 0:33dddd0644c5 | 86 | if (aFortNightly) SetRepeat(EFortNightly); |
charlesgt | 0:33dddd0644c5 | 87 | else SetRepeat(EWeekly); |
charlesgt | 0:33dddd0644c5 | 88 | Queue(); |
charlesgt | 0:33dddd0644c5 | 89 | } |
charlesgt | 0:33dddd0644c5 | 90 | |
charlesgt | 0:33dddd0644c5 | 91 | AlarmTimeDate::AlarmTimeDate(AlarmCbFn aFn, void* aPtr, int aHours, int aMins, |
charlesgt | 0:33dddd0644c5 | 92 | int aSecs, int aDayM) |
charlesgt | 0:33dddd0644c5 | 93 | :iFn(aFn),iPtr(aPtr) { |
charlesgt | 0:33dddd0644c5 | 94 | // current time |
charlesgt | 0:33dddd0644c5 | 95 | time_t seconds = time(NULL); |
charlesgt | 0:33dddd0644c5 | 96 | struct tm * sectm = localtime(&seconds); |
charlesgt | 0:33dddd0644c5 | 97 | sectm->tm_sec = aSecs; |
charlesgt | 0:33dddd0644c5 | 98 | sectm->tm_min = aMins; |
charlesgt | 0:33dddd0644c5 | 99 | sectm->tm_hour = aHours; |
charlesgt | 0:33dddd0644c5 | 100 | sectm->tm_mday = aDayM; |
charlesgt | 0:33dddd0644c5 | 101 | time_t secs2 = mktime(sectm); |
charlesgt | 0:33dddd0644c5 | 102 | if (secs2<=seconds) { |
charlesgt | 0:33dddd0644c5 | 103 | if (sectm->tm_mon==11) { |
charlesgt | 0:33dddd0644c5 | 104 | sectm->tm_mon = 0; |
charlesgt | 0:33dddd0644c5 | 105 | sectm->tm_year++; |
charlesgt | 0:33dddd0644c5 | 106 | } else { |
charlesgt | 0:33dddd0644c5 | 107 | sectm->tm_mon++; |
charlesgt | 0:33dddd0644c5 | 108 | } |
charlesgt | 0:33dddd0644c5 | 109 | } |
charlesgt | 0:33dddd0644c5 | 110 | iTime = mktime(sectm); |
charlesgt | 0:33dddd0644c5 | 111 | SetRepeat(EMonthly); |
charlesgt | 0:33dddd0644c5 | 112 | Queue(); |
charlesgt | 0:33dddd0644c5 | 113 | } |
charlesgt | 0:33dddd0644c5 | 114 | |
charlesgt | 0:33dddd0644c5 | 115 | AlarmTimeDate::AlarmTimeDate(AlarmCbFn aFn, void* aPtr, int aHours, int aMins, |
charlesgt | 0:33dddd0644c5 | 116 | int aSecs, int aDayM, int aMon) |
charlesgt | 0:33dddd0644c5 | 117 | :iFn(aFn),iPtr(aPtr) { |
charlesgt | 0:33dddd0644c5 | 118 | // current time |
charlesgt | 0:33dddd0644c5 | 119 | time_t seconds = time(NULL); |
charlesgt | 0:33dddd0644c5 | 120 | struct tm * sectm = localtime(&seconds); |
charlesgt | 0:33dddd0644c5 | 121 | sectm->tm_sec = aSecs; |
charlesgt | 0:33dddd0644c5 | 122 | sectm->tm_min = aMins; |
charlesgt | 0:33dddd0644c5 | 123 | sectm->tm_hour = aHours; |
charlesgt | 0:33dddd0644c5 | 124 | sectm->tm_mday = aDayM; |
charlesgt | 0:33dddd0644c5 | 125 | sectm->tm_mon = aMon-1; |
charlesgt | 0:33dddd0644c5 | 126 | time_t secs2 = mktime(sectm); |
charlesgt | 0:33dddd0644c5 | 127 | if (secs2<=seconds) { // if programmed late in the year |
charlesgt | 0:33dddd0644c5 | 128 | sectm->tm_year++; |
charlesgt | 0:33dddd0644c5 | 129 | } |
charlesgt | 0:33dddd0644c5 | 130 | iTime = mktime(sectm); |
charlesgt | 0:33dddd0644c5 | 131 | SetRepeat(EYearly); |
charlesgt | 0:33dddd0644c5 | 132 | Queue(); |
charlesgt | 0:33dddd0644c5 | 133 | } |
charlesgt | 0:33dddd0644c5 | 134 | |
charlesgt | 0:33dddd0644c5 | 135 | AlarmTimeDate::AlarmTimeDate(AlarmCbFn aFn, void* aPtr, struct tm* aTm ) |
charlesgt | 0:33dddd0644c5 | 136 | :iFn(aFn),iPtr(aPtr) { |
charlesgt | 0:33dddd0644c5 | 137 | iTime = mktime(aTm); |
charlesgt | 0:33dddd0644c5 | 138 | Queue(); |
charlesgt | 0:33dddd0644c5 | 139 | } |
charlesgt | 0:33dddd0644c5 | 140 | |
charlesgt | 0:33dddd0644c5 | 141 | AlarmTimeDate::AlarmTimeDate(AlarmCbFn aFn, void* aPtr, time_t aSec ) |
charlesgt | 0:33dddd0644c5 | 142 | :iTime(aSec),iFn(aFn),iPtr(aPtr) { |
charlesgt | 0:33dddd0644c5 | 143 | Queue(); |
charlesgt | 0:33dddd0644c5 | 144 | } |
charlesgt | 0:33dddd0644c5 | 145 | |
charlesgt | 0:33dddd0644c5 | 146 | AlarmTimeDate::~AlarmTimeDate() { |
charlesgt | 0:33dddd0644c5 | 147 | DeQueue(); |
charlesgt | 0:33dddd0644c5 | 148 | Tick(NULL,NULL); |
charlesgt | 0:33dddd0644c5 | 149 | } |
charlesgt | 0:33dddd0644c5 | 150 | |
charlesgt | 0:33dddd0644c5 | 151 | void AlarmTimeDate::Queue() { |
charlesgt | 0:33dddd0644c5 | 152 | iNext = list; |
charlesgt | 0:33dddd0644c5 | 153 | list = this; |
charlesgt | 0:33dddd0644c5 | 154 | Tick(NULL,NULL); |
charlesgt | 0:33dddd0644c5 | 155 | } |
charlesgt | 0:33dddd0644c5 | 156 | |
charlesgt | 0:33dddd0644c5 | 157 | void AlarmTimeDate::DeQueue() { |
charlesgt | 0:33dddd0644c5 | 158 | AlarmTimeDate* p = list; |
charlesgt | 0:33dddd0644c5 | 159 | AlarmTimeDate* prev = NULL; |
charlesgt | 0:33dddd0644c5 | 160 | while (p) { |
charlesgt | 0:33dddd0644c5 | 161 | if (p==this) { |
charlesgt | 0:33dddd0644c5 | 162 | if (!prev) list = iNext; |
charlesgt | 0:33dddd0644c5 | 163 | else { |
charlesgt | 0:33dddd0644c5 | 164 | prev->iNext = iNext; |
charlesgt | 0:33dddd0644c5 | 165 | } |
charlesgt | 0:33dddd0644c5 | 166 | break; |
charlesgt | 0:33dddd0644c5 | 167 | } |
charlesgt | 0:33dddd0644c5 | 168 | prev = p; |
charlesgt | 0:33dddd0644c5 | 169 | p = p->iNext; |
charlesgt | 0:33dddd0644c5 | 170 | } |
charlesgt | 0:33dddd0644c5 | 171 | } |
charlesgt | 0:33dddd0644c5 | 172 | |
charlesgt | 0:33dddd0644c5 | 173 | void AlarmTimeDate::Set() { |
charlesgt | 0:33dddd0644c5 | 174 | struct tm* localt = localtime(&iTime); |
charlesgt | 0:33dddd0644c5 | 175 | LPC_RTC->ALSEC = localt->tm_sec; |
charlesgt | 0:33dddd0644c5 | 176 | LPC_RTC->ALMIN = localt->tm_min; |
charlesgt | 0:33dddd0644c5 | 177 | LPC_RTC->ALHOUR = localt->tm_hour; |
charlesgt | 0:33dddd0644c5 | 178 | LPC_RTC->ALDOM = localt->tm_mday; |
charlesgt | 0:33dddd0644c5 | 179 | LPC_RTC->ALMON = localt->tm_mon+1; |
charlesgt | 0:33dddd0644c5 | 180 | LPC_RTC->ALYEAR = localt->tm_year+1900; |
charlesgt | 0:33dddd0644c5 | 181 | LPC_RTC->AMR = (uint8_t)~0xcfu; // match those above |
charlesgt | 0:33dddd0644c5 | 182 | } |
charlesgt | 0:33dddd0644c5 | 183 | |
charlesgt | 0:33dddd0644c5 | 184 | void AlarmTimeDate::Expire() { |
charlesgt | 1:f4c7f13e5553 | 185 | iFn(iPtr); |
charlesgt | 0:33dddd0644c5 | 186 | struct tm * sectm; |
charlesgt | 0:33dddd0644c5 | 187 | switch (Repeat()) { |
charlesgt | 0:33dddd0644c5 | 188 | case EDaily: |
charlesgt | 0:33dddd0644c5 | 189 | iTime+=24*3600; |
charlesgt | 0:33dddd0644c5 | 190 | break; |
charlesgt | 0:33dddd0644c5 | 191 | case EDailyNoWeeked: |
charlesgt | 0:33dddd0644c5 | 192 | sectm = localtime(&iTime); |
charlesgt | 0:33dddd0644c5 | 193 | if (sectm->tm_wday==6) |
charlesgt | 0:33dddd0644c5 | 194 | iTime+=7*24*3600; // its friday, skip it to sunday |
charlesgt | 0:33dddd0644c5 | 195 | iTime+=24*3600; |
charlesgt | 0:33dddd0644c5 | 196 | case EWeekly: |
charlesgt | 0:33dddd0644c5 | 197 | iTime+=7*24*3600; |
charlesgt | 0:33dddd0644c5 | 198 | break; |
charlesgt | 0:33dddd0644c5 | 199 | case EFortNightly: |
charlesgt | 0:33dddd0644c5 | 200 | iTime+=14*24*3600; |
charlesgt | 0:33dddd0644c5 | 201 | break; |
charlesgt | 0:33dddd0644c5 | 202 | case EMonthly: |
charlesgt | 0:33dddd0644c5 | 203 | sectm = localtime(&iTime); |
charlesgt | 0:33dddd0644c5 | 204 | if (++sectm->tm_mon==32) { |
charlesgt | 0:33dddd0644c5 | 205 | sectm->tm_mon=1; |
charlesgt | 0:33dddd0644c5 | 206 | sectm->tm_year++; |
charlesgt | 0:33dddd0644c5 | 207 | } |
charlesgt | 0:33dddd0644c5 | 208 | iTime = mktime(sectm); |
charlesgt | 0:33dddd0644c5 | 209 | break; |
charlesgt | 0:33dddd0644c5 | 210 | case EYearly: |
charlesgt | 0:33dddd0644c5 | 211 | sectm = localtime(&iTime); |
charlesgt | 0:33dddd0644c5 | 212 | sectm->tm_year++; |
charlesgt | 0:33dddd0644c5 | 213 | iTime = mktime(sectm); |
charlesgt | 0:33dddd0644c5 | 214 | break; |
charlesgt | 0:33dddd0644c5 | 215 | default: |
charlesgt | 0:33dddd0644c5 | 216 | iTime = 0; |
charlesgt | 0:33dddd0644c5 | 217 | } |
charlesgt | 0:33dddd0644c5 | 218 | } |
charlesgt | 0:33dddd0644c5 | 219 | |
charlesgt | 0:33dddd0644c5 | 220 | void AlarmTimeDate::Init() { |
charlesgt | 0:33dddd0644c5 | 221 | LPC_RTC->CIIR = 0; |
charlesgt | 0:33dddd0644c5 | 222 | LPC_RTC->ILR = 0x3; |
charlesgt | 0:33dddd0644c5 | 223 | LPC_RTC->AMR = 0xffu; |
charlesgt | 0:33dddd0644c5 | 224 | NVIC_SetVector(RTC_IRQn, (uint32_t)&RTCISR); |
charlesgt | 0:33dddd0644c5 | 225 | NVIC_EnableIRQ(RTC_IRQn); |
charlesgt | 0:33dddd0644c5 | 226 | } |
charlesgt | 0:33dddd0644c5 | 227 | |
charlesgt | 0:33dddd0644c5 | 228 | void AlarmTimeDate::RTCISR() { |
charlesgt | 0:33dddd0644c5 | 229 | LPC_RTC->ILR = 0x3; |
charlesgt | 0:33dddd0644c5 | 230 | } |
charlesgt | 0:33dddd0644c5 | 231 | |
charlesgt | 0:33dddd0644c5 | 232 | void AlarmTimeDate::Tick(SleepFn aFn,void* aParam) { |
charlesgt | 1:f4c7f13e5553 | 233 | if (aFn) aFn(aParam); // sleep first |
charlesgt | 0:33dddd0644c5 | 234 | AlarmTimeDate* p = list; |
charlesgt | 0:33dddd0644c5 | 235 | AlarmTimeDate* toSet = NULL; |
charlesgt | 0:33dddd0644c5 | 236 | time_t seconds = time(NULL); |
charlesgt | 0:33dddd0644c5 | 237 | time_t toSetTime = 0; |
charlesgt | 0:33dddd0644c5 | 238 | while (p) { |
charlesgt | 0:33dddd0644c5 | 239 | if (p->iTime && p->iTime <= seconds) p->Expire(); |
charlesgt | 0:33dddd0644c5 | 240 | p = p->iNext; |
charlesgt | 0:33dddd0644c5 | 241 | } |
charlesgt | 0:33dddd0644c5 | 242 | seconds = time(NULL); |
charlesgt | 0:33dddd0644c5 | 243 | p = list; |
charlesgt | 0:33dddd0644c5 | 244 | while (p) { |
charlesgt | 0:33dddd0644c5 | 245 | if (p->iTime) { |
charlesgt | 0:33dddd0644c5 | 246 | if (!toSet) { |
charlesgt | 0:33dddd0644c5 | 247 | toSet = p; |
charlesgt | 0:33dddd0644c5 | 248 | toSetTime = p->iTime; |
charlesgt | 0:33dddd0644c5 | 249 | } else { |
charlesgt | 0:33dddd0644c5 | 250 | if (p->iTime < toSetTime) { |
charlesgt | 0:33dddd0644c5 | 251 | toSet = p; |
charlesgt | 0:33dddd0644c5 | 252 | toSetTime = p->iTime; |
charlesgt | 0:33dddd0644c5 | 253 | } |
charlesgt | 0:33dddd0644c5 | 254 | } |
charlesgt | 0:33dddd0644c5 | 255 | }; |
charlesgt | 0:33dddd0644c5 | 256 | p = p->iNext; |
charlesgt | 0:33dddd0644c5 | 257 | } |
charlesgt | 0:33dddd0644c5 | 258 | if (toSet) { |
charlesgt | 0:33dddd0644c5 | 259 | toSet->Set(); |
charlesgt | 0:33dddd0644c5 | 260 | } |
charlesgt | 0:33dddd0644c5 | 261 | } |