Alarm library for use with mbed.

Revision:
2:23e65cacea5a
Parent:
1:f4c7f13e5553
--- a/AlarmTimeDate.cpp	Sun Oct 31 08:13:17 2010 +0000
+++ b/AlarmTimeDate.cpp	Mon Nov 15 23:22:07 2010 +0000
@@ -1,6 +1,11 @@
 #include "mbed.h"
 #include "AlarmTimeDate.h"
 
+volatile uint8_t AlarmTimeDate::iRTCIsSet = 0u;
+volatile uint8_t AlarmTimeDate::iIsrCount = 0u;
+volatile uint8_t AlarmTimeDate::iPad0 = 0u;
+volatile uint8_t AlarmTimeDate::iPad1 = 0u;
+
 static AlarmTimeDate* list = NULL;
 
 void AlarmTimeDate::PrintAlarm() {
@@ -171,7 +176,12 @@
 }
 
 void AlarmTimeDate::Set() {
-    struct tm* localt = localtime(&iTime);
+    time_t seconds = time(NULL);
+    if (iTime <= seconds) seconds++;
+    else seconds = iTime;
+    struct tm* localt = localtime(&seconds);
+    __disable_irq();
+    iRTCIsSet = 1;
     LPC_RTC->ALSEC = localt->tm_sec;
     LPC_RTC->ALMIN = localt->tm_min;
     LPC_RTC->ALHOUR = localt->tm_hour;
@@ -179,9 +189,11 @@
     LPC_RTC->ALMON = localt->tm_mon+1;
     LPC_RTC->ALYEAR = localt->tm_year+1900;
     LPC_RTC->AMR = (uint8_t)~0xcfu; // match those above
+    __enable_irq();
 }
 
 void AlarmTimeDate::Expire() {
+    time_t expiry = time(NULL);
     iFn(iPtr);
     struct tm * sectm;
     switch (Repeat()) {
@@ -191,8 +203,9 @@
         case EDailyNoWeeked:
             sectm = localtime(&iTime);
             if (sectm->tm_wday==6)
-                iTime+=7*24*3600;  // its friday, skip it to sunday
+                iTime+=2*24*3600;  // its friday, skip it to sunday
             iTime+=24*3600;
+            break;
         case EWeekly:
             iTime+=7*24*3600;
             break;
@@ -201,8 +214,8 @@
             break;
         case EMonthly:
             sectm = localtime(&iTime);
-            if (++sectm->tm_mon==32) {
-                sectm->tm_mon=1;
+            if (++sectm->tm_mon==12) {
+                sectm->tm_mon=0;
                 sectm->tm_year++;
             }
             iTime = mktime(sectm);
@@ -213,7 +226,8 @@
             iTime = mktime(sectm);
             break;
         default:
-            iTime = 0;
+            // could have been reset
+            if ( expiry >= iTime ) iTime = 0;
     }
 }
 
@@ -227,10 +241,22 @@
 
 void AlarmTimeDate::RTCISR() {
     LPC_RTC->ILR = 0x3;
+    iRTCIsSet = 0;
+    iIsrCount++;
+    printf("I:%d\n",iIsrCount);
 }
 
 void AlarmTimeDate::Tick(SleepFn aFn,void* aParam) {
-    if (aFn) aFn(aParam); // sleep first
+redo:
+    printf("ticking %d\n",++iPad0);
+    if (aFn) printf("Sleeping at %x\n",time(NULL));
+    if (aFn && iRTCIsSet) {
+        aFn(aParam);
+    }
+    __disable_irq();
+    if (iIsrCount) iIsrCount--;
+    __enable_irq();
+    if (aFn ) printf("waking at %x\n",time(NULL));
     AlarmTimeDate* p = list;
     AlarmTimeDate* toSet = NULL;
     time_t seconds = time(NULL);
@@ -239,7 +265,6 @@
         if (p->iTime && p->iTime <= seconds) p->Expire();
         p = p->iNext;
     }
-    seconds = time(NULL);
     p = list;
     while (p) {
         if (p->iTime) {
@@ -256,6 +281,10 @@
         p = p->iNext;
     }
     if (toSet) {
+        printf("found something to set %x\n",toSet->iTime);
         toSet->Set();
     }
-}
+
+    printf("ticking done %d:%d\n",--iPad0,iIsrCount);
+    if (iIsrCount) goto redo;
+}
\ No newline at end of file