Support KL25z requirements

Dependents:   kl25z_Usb_Logger

Fork of RTC by Erik -

Files at this revision

API Documentation at this revision

Comitter:
Sissors
Date:
Fri Dec 07 20:50:43 2012 +0000
Parent:
0:39767ffe05e6
Child:
2:b61676bcc5c0
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
--- 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
--- 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);
 
 
 };