Alarm library for use with mbed.

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?

UserRevisionLine numberNew 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(&sectm);
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 }