Support KL25z requirements
Fork of RTC by
Revision 1:be9d058ee5c7, committed 2012-12-07
- 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); };