Allows easy usage of the LPC1768 RTC interrupts

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

The RTC library allows easy access to the LPC1768s interrupt sources on its RTC. There are two different interrupt sources: periodic interrupts, for example every new second, hour, etc, and an alarm, which is called at a specified time.

Time initialization

This library only allows easy usage of the RTC interrupts. You have to initialize the time functions (so the RTC) the normal way specified here: http://mbed.org/handbook/Time?action=view&revision=11592

Hello World!

#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);
}

Periodic interrupts

Periodic interrups can be attached by using:

RTC::attach([function], [TimeUnit]);

The TimeUnit specifies which unit should increase for the function to be called. This function is useful if you are making for example a clock: You can simply connect the display update to an RTC interrupt. Of course you can do something similar by using timer objects, but they aren't timed exactly correct, and it is nicer to do it directly on the RTC.

Alarm function

The LPC1768's RTC also allows for one alarm to be activated. The alarm goes off the first time there is a compare match on a specified time and the current time. All fields of the normal C tm structure are supported (http://www.cplusplus.com/reference/ctime/tm/), set a field at -1 for it to be ignored. The RTC::getDefaultTM() function helps with that, it returns a tm structure with every field initialized to -1, so don't care.

So if you want to make an alarm that gets called every monday, every 5 minutes and 30 seconds after the hour, you would use:

tm t = RTC::getDefaultTM();
t.tm_sec = 30;     //30 seconds
t.tm_min = 5;      //5 minute
t.tm_wday = 1;     //monday
RTC::alarm([yourFunction], t);

Attaching member functions

For compactness of the documentation attaching member functions of objects isn't included. However it works exactly the same as for example attaching one to a Ticker object: http://mbed.org/users/mbed_official/code/mbed/docs/63cdd78b2dc1/classmbed_1_1Ticker.html#af92f41ff11906b1f96fa6bbe0b17aa29

Disclaimer

Believe it or not, but I didn't test every possible combination of alarm settings / interrupts. So especially for the larger timescales there is an increased chance on bugs.

Committer:
Sissors
Date:
Fri Dec 07 20:50:43 2012 +0000
Revision:
1:be9d058ee5c7
Parent:
0:39767ffe05e6
v1.0;

Who changed what in which revision?

UserRevisionLine numberNew contents of line
Sissors 0:39767ffe05e6 1 #ifndef RTC_H
Sissors 0:39767ffe05e6 2 #define RTC_H
Sissors 0:39767ffe05e6 3
Sissors 0:39767ffe05e6 4 #include "mbed.h"
Sissors 0:39767ffe05e6 5
Sissors 1:be9d058ee5c7 6 /**
Sissors 1:be9d058ee5c7 7 * Library to get access to the interrupt functionality of the LPC1768's RTC.
Sissors 1:be9d058ee5c7 8 *
Sissors 1:be9d058ee5c7 9 * This class is completely static: which means you don't have to create an RTC object,
Sissors 1:be9d058ee5c7 10 * there is always one object automatically created when you include this class. Since
Sissors 1:be9d058ee5c7 11 * there is only one RTC, more than one would make no sense.
Sissors 1:be9d058ee5c7 12 *
Sissors 1:be9d058ee5c7 13 * @code
Sissors 1:be9d058ee5c7 14 * #include "mbed.h"
Sissors 1:be9d058ee5c7 15 * #include "RTC.h"
Sissors 1:be9d058ee5c7 16 *
Sissors 1:be9d058ee5c7 17 * DigitalOut led(LED1);
Sissors 1:be9d058ee5c7 18 *
Sissors 1:be9d058ee5c7 19 * void ledFunction( void )
Sissors 1:be9d058ee5c7 20 * {
Sissors 1:be9d058ee5c7 21 * led = 1;
Sissors 1:be9d058ee5c7 22 * RTC::detach(RTC::Second);
Sissors 1:be9d058ee5c7 23 * }
Sissors 1:be9d058ee5c7 24 *
Sissors 1:be9d058ee5c7 25 * void displayFunction( void )
Sissors 1:be9d058ee5c7 26 * {
Sissors 1:be9d058ee5c7 27 * time_t seconds = time(NULL);
Sissors 1:be9d058ee5c7 28 * printf("%s", ctime(&seconds));
Sissors 1:be9d058ee5c7 29 * }
Sissors 1:be9d058ee5c7 30 *
Sissors 1:be9d058ee5c7 31 * void alarmFunction( void )
Sissors 1:be9d058ee5c7 32 * {
Sissors 1:be9d058ee5c7 33 * error("Not most useful alarm function");
Sissors 1:be9d058ee5c7 34 * }
Sissors 1:be9d058ee5c7 35 *
Sissors 1:be9d058ee5c7 36 * int main()
Sissors 1:be9d058ee5c7 37 * {
Sissors 1:be9d058ee5c7 38 * set_time(1256729737); // Set time to Wed, 28 Oct 2009 11:35:37
Sissors 1:be9d058ee5c7 39 *
Sissors 1:be9d058ee5c7 40 * tm t = RTC::getDefaultTM();
Sissors 1:be9d058ee5c7 41 * t.tm_sec = 5;
Sissors 1:be9d058ee5c7 42 * t.tm_min = 36;
Sissors 1:be9d058ee5c7 43 *
Sissors 1:be9d058ee5c7 44 * RTC::alarm(&alarmFunction, t);
Sissors 1:be9d058ee5c7 45 * RTC::attach(&displayFunction, RTC::Second);
Sissors 1:be9d058ee5c7 46 * RTC::attach(&ledFunction, RTC::Minute);
Sissors 1:be9d058ee5c7 47 *
Sissors 1:be9d058ee5c7 48 * while(1);
Sissors 1:be9d058ee5c7 49 * }
Sissors 1:be9d058ee5c7 50 * @endcode
Sissors 1:be9d058ee5c7 51 **/
Sissors 0:39767ffe05e6 52 class RTC {
Sissors 0:39767ffe05e6 53 public:
Sissors 1:be9d058ee5c7 54 /**
Sissors 1:be9d058ee5c7 55 * Available time units for interrupts
Sissors 1:be9d058ee5c7 56 *
Sissors 1:be9d058ee5c7 57 * RTC::Second, RTC::Minute, RTC::Hour,
Sissors 1:be9d058ee5c7 58 * RTC::Day, RTC::Month, RTC::Year
Sissors 1:be9d058ee5c7 59 */
Sissors 0:39767ffe05e6 60 enum TimeUnit {Second, Minute, Hour,
Sissors 0:39767ffe05e6 61 Day, Month, Year};
Sissors 1:be9d058ee5c7 62
Sissors 1:be9d058ee5c7 63 /**
Sissors 1:be9d058ee5c7 64 * Call a function when the specified time unit increases
Sissors 1:be9d058ee5c7 65 *
Sissors 1:be9d058ee5c7 66 * You can attach one function for each TimeUnit. When several are
Sissors 1:be9d058ee5c7 67 * attached the smalles TimeUnit is called first.
Sissors 1:be9d058ee5c7 68 *
Sissors 1:be9d058ee5c7 69 * Member functions of a class can be attached the normal way (similar to for example Ticker).
Sissors 1:be9d058ee5c7 70 *
Sissors 1:be9d058ee5c7 71 * @param function - the function to call
Sissors 1:be9d058ee5c7 72 * @param interval - the TimeUnit which specifies the interval
Sissors 1:be9d058ee5c7 73 */
Sissors 0:39767ffe05e6 74 static void attach(void (*function)(void), TimeUnit interval);
Sissors 1:be9d058ee5c7 75 template<typename T>
Sissors 1:be9d058ee5c7 76 void attach(T *object, void (T::*member)(void), TimeUnit interval);
Sissors 1:be9d058ee5c7 77
Sissors 1:be9d058ee5c7 78 /**
Sissors 1:be9d058ee5c7 79 * Detach an interrupt function
Sissors 1:be9d058ee5c7 80 *
Sissors 1:be9d058ee5c7 81 * @param interval - the TimeUnit of the interrupt to detach
Sissors 1:be9d058ee5c7 82 */
Sissors 1:be9d058ee5c7 83 static void detach(TimeUnit interval);
Sissors 0:39767ffe05e6 84
Sissors 1:be9d058ee5c7 85 /**
Sissors 1:be9d058ee5c7 86 * Call a function when a specified time is reached
Sissors 1:be9d058ee5c7 87 *
Sissors 1:be9d058ee5c7 88 * Only one alarm is possible. Make fields of the tm structure -1 for don't care.
Sissors 1:be9d058ee5c7 89 *
Sissors 1:be9d058ee5c7 90 * Member functions of a class can be attached the normal way (similar to for example Ticker).
Sissors 1:be9d058ee5c7 91 *
Sissors 1:be9d058ee5c7 92 * @param function - the function to call
Sissors 1:be9d058ee5c7 93 * @param alarmTime - tm structure which specifies when to activate the alarm
Sissors 1:be9d058ee5c7 94 */
Sissors 1:be9d058ee5c7 95 static void alarm(void (*function)(void), tm alarmTime);
Sissors 1:be9d058ee5c7 96 template<typename T>
Sissors 1:be9d058ee5c7 97 void alarm(T *object, void (T::*member)(void), tm alarmTime);
Sissors 0:39767ffe05e6 98
Sissors 1:be9d058ee5c7 99 /**
Sissors 1:be9d058ee5c7 100 * Disable the alarm
Sissors 1:be9d058ee5c7 101 */
Sissors 0:39767ffe05e6 102 static void alarmOff( void );
Sissors 1:be9d058ee5c7 103
Sissors 1:be9d058ee5c7 104 /**
Sissors 1:be9d058ee5c7 105 * Returns a default tm structure where each field is initialized
Sissors 1:be9d058ee5c7 106 * to -1, so it is ignored by the alarm function.
Sissors 1:be9d058ee5c7 107 *
Sissors 1:be9d058ee5c7 108 * Available fields: http://www.cplusplus.com/reference/ctime/tm/
Sissors 1:be9d058ee5c7 109 * Except tm_isdst all of them can be used for the alarm
Sissors 1:be9d058ee5c7 110 *
Sissors 1:be9d058ee5c7 111 * @param return - tm structure initialized to -1
Sissors 1:be9d058ee5c7 112 */
Sissors 1:be9d058ee5c7 113 static tm getDefaultTM( void );
Sissors 1:be9d058ee5c7 114
Sissors 1:be9d058ee5c7 115
Sissors 0:39767ffe05e6 116
Sissors 0:39767ffe05e6 117 private:
Sissors 0:39767ffe05e6 118 static void IRQHandler( void );
Sissors 0:39767ffe05e6 119
Sissors 0:39767ffe05e6 120 static FunctionPointer attachCB[6];
Sissors 0:39767ffe05e6 121 static FunctionPointer alarmCB;
Sissors 0:39767ffe05e6 122
Sissors 0:39767ffe05e6 123 //If someone knows a nicer way to do this, please tell me
Sissors 0:39767ffe05e6 124 static bool initialRun;
Sissors 1:be9d058ee5c7 125 static void _attach(TimeUnit interval);
Sissors 1:be9d058ee5c7 126 static void _alarm(tm alarmTime);
Sissors 0:39767ffe05e6 127
Sissors 0:39767ffe05e6 128
Sissors 0:39767ffe05e6 129 };
Sissors 0:39767ffe05e6 130
Sissors 0:39767ffe05e6 131 #endif