Allows easy usage of the LPC1768 RTC interrupts

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

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers RTC.cpp Source File

RTC.cpp

00001 #include "RTC.h"
00002 
00003 FunctionPointer RTC::attachCB[6];
00004 FunctionPointer RTC::alarmCB;
00005 
00006 bool RTC::initialRun = true;
00007 
00008 
00009 void RTC::attach(void (*function)(void), TimeUnit interval)
00010 {
00011     //Set the function pointer
00012     attachCB[interval].attach(function);
00013     _attach(interval);
00014 }
00015 
00016 template<typename T>
00017 void RTC::attach(T *object, void (T::*member)(void), TimeUnit interval)
00018 {
00019     //Set the function pointer
00020     attachCB[interval].attach(object, member);
00021     _attach(interval);
00022 }
00023 
00024 
00025 void RTC::_attach(TimeUnit interval)
00026 {
00027     //Disable IRQs, dont want them to happen while busy here
00028     NVIC_DisableIRQ(RTC_IRQn);
00029 
00030     //Set the IRQ vector
00031     NVIC_SetVector(RTC_IRQn, (uint32_t)&RTC::IRQHandler);
00032 
00033     //If this is the first time it is called, delete all interrupt sources
00034     //We need to do this because RTC unit isnt affected by system resets apparently
00035     if (initialRun) {
00036         LPC_RTC->CIIR = 0;
00037         LPC_RTC->AMR = 255;
00038         initialRun = false;
00039         LPC_RTC->ILR = 0x03;
00040     }
00041 
00042     //Set/reset correct interrupt source
00043     switch (interval) {
00044         case Second:
00045             LPC_RTC->CIIR |= 1;
00046             break;
00047         case Minute:
00048             LPC_RTC->CIIR |= 2;
00049             break;
00050         case Hour:
00051             LPC_RTC->CIIR |= 4;
00052             break;
00053         case Day:
00054             LPC_RTC->CIIR |= 56;
00055             break;
00056         case Month:
00057             LPC_RTC->CIIR |= 64;
00058             break;
00059         case Year:
00060             LPC_RTC->CIIR |= 128;
00061             break;
00062     }
00063 
00064 
00065     //We can always enable IRQs, since if all IRQs are disabled by the user the RTC hardware will never raise its IRQ flag anyway
00066     NVIC_EnableIRQ(RTC_IRQn);
00067 }
00068 
00069 void RTC::detach(TimeUnit interval)
00070 {
00071     switch (interval) {
00072         case Second:
00073             LPC_RTC->CIIR &= ~1;
00074             break;
00075         case Minute:
00076             LPC_RTC->CIIR &= ~2;
00077             break;
00078         case Hour:
00079             LPC_RTC->CIIR &= ~4;
00080             break;
00081         case Day:
00082             LPC_RTC->CIIR &= ~56;
00083             break;
00084         case Month:
00085             LPC_RTC->CIIR &= ~64;
00086             break;
00087         case Year:
00088             LPC_RTC->CIIR &= ~128;
00089             break;
00090     }
00091     attachCB[interval].attach(NULL);
00092 }
00093 
00094 
00095 void RTC::alarm(void (*function)(void), tm alarmTime)
00096 {
00097     //Set the function pointer
00098     alarmCB.attach(function);
00099     _alarm(alarmTime);
00100 }
00101 
00102 template<typename T>
00103 void RTC::alarm(T *object, void (T::*member)(void), tm alarmTime)
00104 {
00105     //Set the function pointer
00106     alarmCB.attach(object, member);
00107     _alarm(alarmTime);
00108 }
00109 
00110 
00111 void RTC::_alarm(tm alarmTime)
00112 {
00113     //Disable IRQs, dont want them to happen while busy here
00114     NVIC_DisableIRQ(RTC_IRQn);
00115 
00116     //Set the IRQ vector
00117     NVIC_SetVector(RTC_IRQn, (uint32_t)&RTC::IRQHandler);
00118 
00119     //If this is the first time it is called, delete all interrupt sources
00120     //We need to do this because RTC unit isnt affected by system resets apparently
00121     if (initialRun) {
00122         LPC_RTC->CIIR = 0;
00123         LPC_RTC->AMR = 255;
00124         initialRun = false;
00125         LPC_RTC->ILR = 0x03;
00126     }
00127 
00128     //Set the alarm register
00129     if ((alarmTime.tm_sec>=0) && (alarmTime.tm_sec<60)) {
00130         LPC_RTC->ALSEC = alarmTime.tm_sec;
00131         LPC_RTC->AMR &= ~1;
00132     } else
00133         LPC_RTC->AMR |= 1;
00134 
00135     if ((alarmTime.tm_min>=0) && (alarmTime.tm_min<60)) {
00136         LPC_RTC->ALMIN = alarmTime.tm_min;
00137         LPC_RTC->AMR &= ~2;
00138     } else
00139         LPC_RTC->AMR |= 2;
00140 
00141     if ((alarmTime.tm_hour>=0) && (alarmTime.tm_hour<24)) {
00142         LPC_RTC->ALHOUR = alarmTime.tm_hour;
00143         LPC_RTC->AMR &= ~4;
00144     } else
00145         LPC_RTC->AMR |= 4;
00146 
00147     if ((alarmTime.tm_mday>=1) && (alarmTime.tm_mday<32)) {
00148         LPC_RTC->ALDOM = alarmTime.tm_mday;
00149         LPC_RTC->AMR &= ~8;
00150     } else
00151         LPC_RTC->AMR |= 8;
00152 
00153     if ((alarmTime.tm_wday>=0) && (alarmTime.tm_wday<7)) {
00154         LPC_RTC->ALDOW = alarmTime.tm_wday;
00155         LPC_RTC->AMR &= ~16;
00156     } else
00157         LPC_RTC->AMR |= 16;
00158 
00159     if ((alarmTime.tm_yday>0) && (alarmTime.tm_yday<367)) {
00160         LPC_RTC->ALDOY = alarmTime.tm_yday;
00161         LPC_RTC->AMR &= ~32;
00162     } else
00163         LPC_RTC->AMR |= 32;
00164 
00165     if ((alarmTime.tm_mon>=0) && (alarmTime.tm_mon<12)) {
00166         LPC_RTC->ALMON = alarmTime.tm_mon + 1;   //Different definitions
00167         LPC_RTC->AMR &= ~64;
00168     } else
00169         LPC_RTC->AMR |= 64;
00170 
00171     if ((alarmTime.tm_year>=0) && (alarmTime.tm_year<1000)) {
00172         LPC_RTC->ALYEAR = alarmTime.tm_year + 1900;   //Different definitions
00173         LPC_RTC->AMR &= ~128;
00174     } else
00175         LPC_RTC->AMR |= 128;
00176 
00177     //DOY and DOW register normally not set
00178     time_t t = time(NULL);
00179     LPC_RTC->DOY = localtime(&t)->tm_yday+1;
00180     LPC_RTC->DOW = localtime(&t)->tm_wday;
00181 
00182     //We can always enable IRQs, since if all IRQs are disabled by the user the RTC hardware will never raise its IRQ flag anyway
00183     NVIC_EnableIRQ(RTC_IRQn);
00184 }
00185 
00186 void RTC::alarmOff( void )
00187 {
00188     LPC_RTC->AMR = 255;
00189     alarmCB.attach(NULL);
00190 }
00191 
00192 
00193 void RTC::IRQHandler( void )
00194 {
00195     if ((LPC_RTC->ILR & 0x01) == 0x01) {
00196         //Attach interrupt
00197         attachCB[0].call();
00198 
00199         //If seconds zero
00200         if (LPC_RTC->SEC == 0) {
00201             attachCB[1].call();
00202 
00203             //If minutes zero
00204             if (LPC_RTC->MIN == 0) {
00205                 attachCB[2].call();
00206 
00207                 //If hours zero
00208                 if (LPC_RTC->HOUR == 0) {
00209                     attachCB[3].call();
00210 
00211                     //If days zero
00212                     if (LPC_RTC->DOM == 0) {
00213                         attachCB[4].call();
00214 
00215                         //If month zero
00216                         if (LPC_RTC->MONTH == 0)
00217                             attachCB[5].call();
00218                     }
00219                 }
00220             }
00221         }
00222     }
00223 
00224     if ((LPC_RTC->ILR & 0x02) == 0x02)
00225         alarmCB.call();
00226 
00227 
00228 
00229     //Reset interrupt status
00230     LPC_RTC->ILR = 0x03;
00231 }
00232 
00233 tm RTC::getDefaultTM( void ) {
00234     struct tm t;
00235     t.tm_sec = -1;   
00236     t.tm_min = -1;    
00237     t.tm_hour = -1;   
00238     t.tm_mday = -1;
00239     t.tm_wday = -1;
00240     t.tm_yday = -1;   
00241     t.tm_mon = -1;    
00242     t.tm_year = -1; 
00243     
00244     return t;
00245     }