Erik - / RTC

Dependents:   Mini_DK_clk MakerBotServer GT-ACQUAPLUS_Consumo GT-ACQUAPLUS_Eficiencia ... more

Files at this revision

API Documentation at this revision

Comitter:
Sissors
Date:
Fri Dec 07 20:50:43 2012 +0000
Parent:
0:39767ffe05e6
Commit message:
v1.0;

Changed in this revision

RTC.cpp Show annotated file Show diff for this revision Revisions of this file
RTC.h Show annotated file Show diff for this revision Revisions of this file
diff -r 39767ffe05e6 -r be9d058ee5c7 RTC.cpp
--- a/RTC.cpp	Wed Dec 05 21:03:44 2012 +0000
+++ b/RTC.cpp	Fri Dec 07 20:50:43 2012 +0000
@@ -5,8 +5,25 @@
 
 bool RTC::initialRun = true;
 
+
 void RTC::attach(void (*function)(void), TimeUnit interval)
 {
+    //Set the function pointer
+    attachCB[interval].attach(function);
+    _attach(interval);
+}
+
+template<typename T>
+void RTC::attach(T *object, void (T::*member)(void), TimeUnit interval)
+{
+    //Set the function pointer
+    attachCB[interval].attach(object, member);
+    _attach(interval);
+}
+
+
+void RTC::_attach(TimeUnit interval)
+{
     //Disable IRQs, dont want them to happen while busy here
     NVIC_DisableIRQ(RTC_IRQn);
 
@@ -22,61 +39,76 @@
         LPC_RTC->ILR = 0x03;
     }
 
-    //Set the function pointer
-    attachCB[interval].attach(function);
-
+    //Set/reset correct interrupt source
+    switch (interval) {
+        case Second:
+            LPC_RTC->CIIR |= 1;
+            break;
+        case Minute:
+            LPC_RTC->CIIR |= 2;
+            break;
+        case Hour:
+            LPC_RTC->CIIR |= 4;
+            break;
+        case Day:
+            LPC_RTC->CIIR |= 56;
+            break;
+        case Month:
+            LPC_RTC->CIIR |= 64;
+            break;
+        case Year:
+            LPC_RTC->CIIR |= 128;
+            break;
+    }
 
-    //Set/reset correct interrupt source
-    if (function == NULL) {
-        switch (interval) {
-            case Second:
-                LPC_RTC->CIIR &= ~1;
-                break;
-            case Minute:
-                LPC_RTC->CIIR &= ~2;
-                break;
-            case Hour:
-                LPC_RTC->CIIR &= ~4;
-                break;
-            case Day:
-                LPC_RTC->CIIR &= ~56;
-                break;
-            case Month:
-                LPC_RTC->CIIR &= ~64;
-                break;
-            case Year:
-                LPC_RTC->CIIR &= ~128;
-                break;
-        }
-    } else {
-        switch (interval) {
-            case Second:
-                LPC_RTC->CIIR |= 1;
-                break;
-            case Minute:
-                LPC_RTC->CIIR |= 2;
-                break;
-            case Hour:
-                LPC_RTC->CIIR |= 4;
-                break;
-            case Day:
-                LPC_RTC->CIIR |= 56;
-                break;
-            case Month:
-                LPC_RTC->CIIR |= 64;
-                break;
-            case Year:
-                LPC_RTC->CIIR |= 128;
-                break;
-        }
-    }
 
     //We can always enable IRQs, since if all IRQs are disabled by the user the RTC hardware will never raise its IRQ flag anyway
     NVIC_EnableIRQ(RTC_IRQn);
 }
 
+void RTC::detach(TimeUnit interval)
+{
+    switch (interval) {
+        case Second:
+            LPC_RTC->CIIR &= ~1;
+            break;
+        case Minute:
+            LPC_RTC->CIIR &= ~2;
+            break;
+        case Hour:
+            LPC_RTC->CIIR &= ~4;
+            break;
+        case Day:
+            LPC_RTC->CIIR &= ~56;
+            break;
+        case Month:
+            LPC_RTC->CIIR &= ~64;
+            break;
+        case Year:
+            LPC_RTC->CIIR &= ~128;
+            break;
+    }
+    attachCB[interval].attach(NULL);
+}
 
-void RTC::alarm(void (*function)(void), tm time)
+
+void RTC::alarm(void (*function)(void), tm alarmTime)
+{
+    //Set the function pointer
+    alarmCB.attach(function);
+    _alarm(alarmTime);
+}
+
+template<typename T>
+void RTC::alarm(T *object, void (T::*member)(void), tm alarmTime)
+{
+    //Set the function pointer
+    alarmCB.attach(object, member);
+    _alarm(alarmTime);
+}
+
+
+void RTC::_alarm(tm alarmTime)
 {
     //Disable IRQs, dont want them to happen while busy here
     NVIC_DisableIRQ(RTC_IRQn);
@@ -93,53 +125,69 @@
         LPC_RTC->ILR = 0x03;
     }
 
-    //Set the function pointer
-    alarmCB.attach(function);
-    
     //Set the alarm register
-    if ((time.tm_sec>=0) && (time.tm_sec<60)) {
-        LPC_RTC->ALSEC = time.tm_sec;
+    if ((alarmTime.tm_sec>=0) && (alarmTime.tm_sec<60)) {
+        LPC_RTC->ALSEC = alarmTime.tm_sec;
         LPC_RTC->AMR &= ~1;
     } else
         LPC_RTC->AMR |= 1;
 
-    if ((time.tm_min>=0) && (time.tm_min<60)) {
-        LPC_RTC->ALMIN = time.tm_min;
+    if ((alarmTime.tm_min>=0) && (alarmTime.tm_min<60)) {
+        LPC_RTC->ALMIN = alarmTime.tm_min;
         LPC_RTC->AMR &= ~2;
     } else
         LPC_RTC->AMR |= 2;
 
-    if ((time.tm_hour>=0) && (time.tm_hour<24)) {
-        LPC_RTC->ALHOUR = time.tm_hour;
+    if ((alarmTime.tm_hour>=0) && (alarmTime.tm_hour<24)) {
+        LPC_RTC->ALHOUR = alarmTime.tm_hour;
         LPC_RTC->AMR &= ~4;
     } else
         LPC_RTC->AMR |= 4;
 
-    if ((time.tm_mday>=1) && (time.tm_mday<32)) {
-        LPC_RTC->ALDOM = time.tm_mday;
+    if ((alarmTime.tm_mday>=1) && (alarmTime.tm_mday<32)) {
+        LPC_RTC->ALDOM = alarmTime.tm_mday;
         LPC_RTC->AMR &= ~8;
     } else
-        LPC_RTC->AMR |= 8;        
-        
-    if ((time.tm_mon>=0) && (time.tm_mon<12)) {
-        LPC_RTC->ALMON = time.tm_mon + 1;   //Different definitions
+        LPC_RTC->AMR |= 8;
+
+    if ((alarmTime.tm_wday>=0) && (alarmTime.tm_wday<7)) {
+        LPC_RTC->ALDOW = alarmTime.tm_wday;
+        LPC_RTC->AMR &= ~16;
+    } else
+        LPC_RTC->AMR |= 16;
+
+    if ((alarmTime.tm_yday>0) && (alarmTime.tm_yday<367)) {
+        LPC_RTC->ALDOY = alarmTime.tm_yday;
+        LPC_RTC->AMR &= ~32;
+    } else
+        LPC_RTC->AMR |= 32;
+
+    if ((alarmTime.tm_mon>=0) && (alarmTime.tm_mon<12)) {
+        LPC_RTC->ALMON = alarmTime.tm_mon + 1;   //Different definitions
         LPC_RTC->AMR &= ~64;
     } else
-        LPC_RTC->AMR |= 64;    
+        LPC_RTC->AMR |= 64;
 
-    if ((time.tm_year>=0) && (time.tm_year<1000)) {
-        LPC_RTC->ALYEAR = time.tm_year + 1900;   //Different definitions
+    if ((alarmTime.tm_year>=0) && (alarmTime.tm_year<1000)) {
+        LPC_RTC->ALYEAR = alarmTime.tm_year + 1900;   //Different definitions
         LPC_RTC->AMR &= ~128;
     } else
         LPC_RTC->AMR |= 128;
-        
+
+    //DOY and DOW register normally not set
+    time_t t = time(NULL);
+    LPC_RTC->DOY = localtime(&t)->tm_yday+1;
+    LPC_RTC->DOW = localtime(&t)->tm_wday;
+
     //We can always enable IRQs, since if all IRQs are disabled by the user the RTC hardware will never raise its IRQ flag anyway
     NVIC_EnableIRQ(RTC_IRQn);
 }
 
-void RTC::alarmOff( void ) {
+void RTC::alarmOff( void )
+{
     LPC_RTC->AMR = 255;
-    }
+    alarmCB.attach(NULL);
+}
 
 
 void RTC::IRQHandler( void )
@@ -180,4 +228,18 @@
 
     //Reset interrupt status
     LPC_RTC->ILR = 0x03;
-}
\ No newline at end of file
+}
+
+tm RTC::getDefaultTM( void ) {
+    struct tm t;
+    t.tm_sec = -1;   
+    t.tm_min = -1;    
+    t.tm_hour = -1;   
+    t.tm_mday = -1;
+    t.tm_wday = -1;
+    t.tm_yday = -1;   
+    t.tm_mon = -1;    
+    t.tm_year = -1; 
+    
+    return t;
+    }
\ No newline at end of file
diff -r 39767ffe05e6 -r be9d058ee5c7 RTC.h
--- a/RTC.h	Wed Dec 05 21:03:44 2012 +0000
+++ b/RTC.h	Fri Dec 07 20:50:43 2012 +0000
@@ -3,17 +3,116 @@
 
 #include "mbed.h"
 
-
+/**
+* Library to get access to the interrupt functionality of the LPC1768's RTC.
+*
+* This class is completely static: which means you don't have to create an RTC object,
+* there is always one object automatically created when you include this class. Since 
+* there is only one RTC, more than one would make no sense.
+*
+* @code
+* #include "mbed.h"
+* #include "RTC.h"
+*
+* DigitalOut led(LED1);
+*
+* void ledFunction( void )
+* {
+*     led = 1;
+*     RTC::detach(RTC::Second);
+* }
+* 
+* void displayFunction( void )
+* {
+*     time_t seconds = time(NULL);
+*     printf("%s", ctime(&seconds));
+* }
+* 
+* void alarmFunction( void )
+* {
+*     error("Not most useful alarm function");
+* }
+* 
+* int main()
+* {
+*     set_time(1256729737); // Set time to Wed, 28 Oct 2009 11:35:37
+* 
+*     tm t = RTC::getDefaultTM();
+*     t.tm_sec = 5;
+*     t.tm_min = 36;
+* 
+*     RTC::alarm(&alarmFunction, t);
+*     RTC::attach(&displayFunction, RTC::Second);
+*     RTC::attach(&ledFunction, RTC::Minute);
+* 
+*     while(1);
+* }
+* @endcode
+**/
 class RTC {
 public:
+    /**
+    * Available time units for interrupts
+    *
+    * RTC::Second, RTC::Minute, RTC::Hour,
+    * RTC::Day, RTC::Month, RTC::Year
+    */
     enum TimeUnit {Second, Minute, Hour, 
                     Day, Month, Year};
-
+                    
+    /**
+    * Call a function when the specified time unit increases
+    *
+    * You can attach one function for each TimeUnit. When several are
+    * attached the smalles TimeUnit is called first.
+    *
+    * Member functions of a class can be attached the normal way (similar to for example Ticker).
+    *
+    * @param function - the function to call
+    * @param interval - the TimeUnit which specifies the interval
+    */
     static void attach(void (*function)(void), TimeUnit interval);
+    template<typename T>
+        void attach(T *object, void (T::*member)(void), TimeUnit interval);
+    
+    /**
+    * Detach an interrupt function
+    *
+    * @param interval - the TimeUnit of the interrupt to detach
+    */
+    static void detach(TimeUnit interval);
     
-    static void alarm(void (*function)(void), tm time);
+    /**
+    * Call a function when a specified time is reached
+    *
+    * Only one alarm is possible. Make fields of the tm structure -1 for don't care.
+    *
+    * Member functions of a class can be attached the normal way (similar to for example Ticker).
+    *
+    * @param function - the function to call
+    * @param alarmTime - tm structure which specifies when to activate the alarm
+    */
+    static void alarm(void (*function)(void), tm alarmTime);
+    template<typename T>
+        void alarm(T *object, void (T::*member)(void), tm alarmTime);
     
+    /**
+    * Disable the alarm
+    */
     static void alarmOff( void );
+    
+    /**
+    * Returns a default tm structure where each field is initialized
+    * to -1, so it is ignored by the alarm function.
+    *
+    * Available fields: http://www.cplusplus.com/reference/ctime/tm/
+    * Except tm_isdst all of them can be used for the alarm
+    *
+    * @param return - tm structure initialized to -1
+    */
+    static tm getDefaultTM( void );
+    
+    
 
 private:
     static void IRQHandler( void );
@@ -23,6 +122,8 @@
     
     //If someone knows a nicer way to do this, please tell me
     static bool initialRun;
+    static void _attach(TimeUnit interval);
+    static void _alarm(tm alarmTime);
 
 
 };