Alarm library for use with mbed.

Committer:
charlesgt
Date:
Sat Oct 30 23:41:22 2010 +0000
Revision:
0:33dddd0644c5
Child:
1:f4c7f13e5553
First alpha, not quite working yet

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 0:33dddd0644c5 185 struct tm * sectm;
charlesgt 0:33dddd0644c5 186 switch (Repeat()) {
charlesgt 0:33dddd0644c5 187 case EDaily:
charlesgt 0:33dddd0644c5 188 iTime+=24*3600;
charlesgt 0:33dddd0644c5 189 break;
charlesgt 0:33dddd0644c5 190 case EDailyNoWeeked:
charlesgt 0:33dddd0644c5 191 sectm = localtime(&iTime);
charlesgt 0:33dddd0644c5 192 if (sectm->tm_wday==6)
charlesgt 0:33dddd0644c5 193 iTime+=7*24*3600; // its friday, skip it to sunday
charlesgt 0:33dddd0644c5 194 iTime+=24*3600;
charlesgt 0:33dddd0644c5 195 case EWeekly:
charlesgt 0:33dddd0644c5 196 iTime+=7*24*3600;
charlesgt 0:33dddd0644c5 197 break;
charlesgt 0:33dddd0644c5 198 case EFortNightly:
charlesgt 0:33dddd0644c5 199 iTime+=14*24*3600;
charlesgt 0:33dddd0644c5 200 break;
charlesgt 0:33dddd0644c5 201 case EMonthly:
charlesgt 0:33dddd0644c5 202 sectm = localtime(&iTime);
charlesgt 0:33dddd0644c5 203 if (++sectm->tm_mon==32) {
charlesgt 0:33dddd0644c5 204 sectm->tm_mon=1;
charlesgt 0:33dddd0644c5 205 sectm->tm_year++;
charlesgt 0:33dddd0644c5 206 }
charlesgt 0:33dddd0644c5 207 iTime = mktime(sectm);
charlesgt 0:33dddd0644c5 208 break;
charlesgt 0:33dddd0644c5 209 case EYearly:
charlesgt 0:33dddd0644c5 210 sectm = localtime(&iTime);
charlesgt 0:33dddd0644c5 211 sectm->tm_year++;
charlesgt 0:33dddd0644c5 212 iTime = mktime(sectm);
charlesgt 0:33dddd0644c5 213 break;
charlesgt 0:33dddd0644c5 214 default:
charlesgt 0:33dddd0644c5 215 iTime = 0;
charlesgt 0:33dddd0644c5 216 }
charlesgt 0:33dddd0644c5 217 printf( "Calling %x\n",iFn);
charlesgt 0:33dddd0644c5 218 iFn(iPtr);
charlesgt 0:33dddd0644c5 219 }
charlesgt 0:33dddd0644c5 220
charlesgt 0:33dddd0644c5 221 void AlarmTimeDate::Init() {
charlesgt 0:33dddd0644c5 222 LPC_RTC->CIIR = 0;
charlesgt 0:33dddd0644c5 223 LPC_RTC->ILR = 0x3;
charlesgt 0:33dddd0644c5 224 LPC_RTC->AMR = 0xffu;
charlesgt 0:33dddd0644c5 225 NVIC_SetVector(RTC_IRQn, (uint32_t)&RTCISR);
charlesgt 0:33dddd0644c5 226 NVIC_EnableIRQ(RTC_IRQn);
charlesgt 0:33dddd0644c5 227 }
charlesgt 0:33dddd0644c5 228
charlesgt 0:33dddd0644c5 229 void AlarmTimeDate::RTCISR() {
charlesgt 0:33dddd0644c5 230 LPC_RTC->ILR = 0x3;
charlesgt 0:33dddd0644c5 231 }
charlesgt 0:33dddd0644c5 232
charlesgt 0:33dddd0644c5 233 void AlarmTimeDate::Tick(SleepFn aFn,void* aParam) {
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 if (aFn) aFn(aParam);
charlesgt 0:33dddd0644c5 262 }