hattori&ide

Dependencies:   mbed

Committer:
hattori_atsushi
Date:
Sun Dec 18 08:16:01 2022 +0000
Revision:
0:f77369cabd75
hattori

Who changed what in which revision?

UserRevisionLine numberNew contents of line
hattori_atsushi 0:f77369cabd75 1 #include "RTC.h"
hattori_atsushi 0:f77369cabd75 2
hattori_atsushi 0:f77369cabd75 3 FunctionPointer RTC::attachCB[6];
hattori_atsushi 0:f77369cabd75 4 FunctionPointer RTC::alarmCB;
hattori_atsushi 0:f77369cabd75 5
hattori_atsushi 0:f77369cabd75 6 bool RTC::initialRun = true;
hattori_atsushi 0:f77369cabd75 7
hattori_atsushi 0:f77369cabd75 8
hattori_atsushi 0:f77369cabd75 9 void RTC::attach(void (*function)(void), TimeUnit interval)
hattori_atsushi 0:f77369cabd75 10 {
hattori_atsushi 0:f77369cabd75 11 //Set the function pointer
hattori_atsushi 0:f77369cabd75 12 attachCB[interval].attach(function);
hattori_atsushi 0:f77369cabd75 13 _attach(interval);
hattori_atsushi 0:f77369cabd75 14 }
hattori_atsushi 0:f77369cabd75 15
hattori_atsushi 0:f77369cabd75 16 template<typename T>
hattori_atsushi 0:f77369cabd75 17 void RTC::attach(T *object, void (T::*member)(void), TimeUnit interval)
hattori_atsushi 0:f77369cabd75 18 {
hattori_atsushi 0:f77369cabd75 19 //Set the function pointer
hattori_atsushi 0:f77369cabd75 20 attachCB[interval].attach(object, member);
hattori_atsushi 0:f77369cabd75 21 _attach(interval);
hattori_atsushi 0:f77369cabd75 22 }
hattori_atsushi 0:f77369cabd75 23
hattori_atsushi 0:f77369cabd75 24
hattori_atsushi 0:f77369cabd75 25 void RTC::_attach(TimeUnit interval)
hattori_atsushi 0:f77369cabd75 26 {
hattori_atsushi 0:f77369cabd75 27 //Disable IRQs, dont want them to happen while busy here
hattori_atsushi 0:f77369cabd75 28 NVIC_DisableIRQ(RTC_IRQn);
hattori_atsushi 0:f77369cabd75 29
hattori_atsushi 0:f77369cabd75 30 //Set the IRQ vector
hattori_atsushi 0:f77369cabd75 31 NVIC_SetVector(RTC_IRQn, (uint32_t)&RTC::IRQHandler);
hattori_atsushi 0:f77369cabd75 32
hattori_atsushi 0:f77369cabd75 33 //If this is the first time it is called, delete all interrupt sources
hattori_atsushi 0:f77369cabd75 34 //We need to do this because RTC unit isnt affected by system resets apparently
hattori_atsushi 0:f77369cabd75 35 if (initialRun) {
hattori_atsushi 0:f77369cabd75 36 LPC_RTC->CIIR = 0;
hattori_atsushi 0:f77369cabd75 37 LPC_RTC->AMR = 255;
hattori_atsushi 0:f77369cabd75 38 initialRun = false;
hattori_atsushi 0:f77369cabd75 39 LPC_RTC->ILR = 0x03;
hattori_atsushi 0:f77369cabd75 40 }
hattori_atsushi 0:f77369cabd75 41
hattori_atsushi 0:f77369cabd75 42 //Set/reset correct interrupt source
hattori_atsushi 0:f77369cabd75 43 switch (interval) {
hattori_atsushi 0:f77369cabd75 44 case Second:
hattori_atsushi 0:f77369cabd75 45 LPC_RTC->CIIR |= 1;
hattori_atsushi 0:f77369cabd75 46 break;
hattori_atsushi 0:f77369cabd75 47 case Minute:
hattori_atsushi 0:f77369cabd75 48 LPC_RTC->CIIR |= 2;
hattori_atsushi 0:f77369cabd75 49 break;
hattori_atsushi 0:f77369cabd75 50 case Hour:
hattori_atsushi 0:f77369cabd75 51 LPC_RTC->CIIR |= 4;
hattori_atsushi 0:f77369cabd75 52 break;
hattori_atsushi 0:f77369cabd75 53 case Day:
hattori_atsushi 0:f77369cabd75 54 LPC_RTC->CIIR |= 56;
hattori_atsushi 0:f77369cabd75 55 break;
hattori_atsushi 0:f77369cabd75 56 case Month:
hattori_atsushi 0:f77369cabd75 57 LPC_RTC->CIIR |= 64;
hattori_atsushi 0:f77369cabd75 58 break;
hattori_atsushi 0:f77369cabd75 59 case Year:
hattori_atsushi 0:f77369cabd75 60 LPC_RTC->CIIR |= 128;
hattori_atsushi 0:f77369cabd75 61 break;
hattori_atsushi 0:f77369cabd75 62 }
hattori_atsushi 0:f77369cabd75 63
hattori_atsushi 0:f77369cabd75 64
hattori_atsushi 0:f77369cabd75 65 //We can always enable IRQs, since if all IRQs are disabled by the user the RTC hardware will never raise its IRQ flag anyway
hattori_atsushi 0:f77369cabd75 66 NVIC_EnableIRQ(RTC_IRQn);
hattori_atsushi 0:f77369cabd75 67 }
hattori_atsushi 0:f77369cabd75 68
hattori_atsushi 0:f77369cabd75 69 void RTC::detach(TimeUnit interval)
hattori_atsushi 0:f77369cabd75 70 {
hattori_atsushi 0:f77369cabd75 71 switch (interval) {
hattori_atsushi 0:f77369cabd75 72 case Second:
hattori_atsushi 0:f77369cabd75 73 LPC_RTC->CIIR &= ~1;
hattori_atsushi 0:f77369cabd75 74 break;
hattori_atsushi 0:f77369cabd75 75 case Minute:
hattori_atsushi 0:f77369cabd75 76 LPC_RTC->CIIR &= ~2;
hattori_atsushi 0:f77369cabd75 77 break;
hattori_atsushi 0:f77369cabd75 78 case Hour:
hattori_atsushi 0:f77369cabd75 79 LPC_RTC->CIIR &= ~4;
hattori_atsushi 0:f77369cabd75 80 break;
hattori_atsushi 0:f77369cabd75 81 case Day:
hattori_atsushi 0:f77369cabd75 82 LPC_RTC->CIIR &= ~56;
hattori_atsushi 0:f77369cabd75 83 break;
hattori_atsushi 0:f77369cabd75 84 case Month:
hattori_atsushi 0:f77369cabd75 85 LPC_RTC->CIIR &= ~64;
hattori_atsushi 0:f77369cabd75 86 break;
hattori_atsushi 0:f77369cabd75 87 case Year:
hattori_atsushi 0:f77369cabd75 88 LPC_RTC->CIIR &= ~128;
hattori_atsushi 0:f77369cabd75 89 break;
hattori_atsushi 0:f77369cabd75 90 }
hattori_atsushi 0:f77369cabd75 91 attachCB[interval].attach(NULL);
hattori_atsushi 0:f77369cabd75 92 }
hattori_atsushi 0:f77369cabd75 93
hattori_atsushi 0:f77369cabd75 94
hattori_atsushi 0:f77369cabd75 95 void RTC::alarm(void (*function)(void), tm alarmTime)
hattori_atsushi 0:f77369cabd75 96 {
hattori_atsushi 0:f77369cabd75 97 //Set the function pointer
hattori_atsushi 0:f77369cabd75 98 alarmCB.attach(function);
hattori_atsushi 0:f77369cabd75 99 _alarm(alarmTime);
hattori_atsushi 0:f77369cabd75 100 }
hattori_atsushi 0:f77369cabd75 101
hattori_atsushi 0:f77369cabd75 102 template<typename T>
hattori_atsushi 0:f77369cabd75 103 void RTC::alarm(T *object, void (T::*member)(void), tm alarmTime)
hattori_atsushi 0:f77369cabd75 104 {
hattori_atsushi 0:f77369cabd75 105 //Set the function pointer
hattori_atsushi 0:f77369cabd75 106 alarmCB.attach(object, member);
hattori_atsushi 0:f77369cabd75 107 _alarm(alarmTime);
hattori_atsushi 0:f77369cabd75 108 }
hattori_atsushi 0:f77369cabd75 109
hattori_atsushi 0:f77369cabd75 110
hattori_atsushi 0:f77369cabd75 111 void RTC::_alarm(tm alarmTime)
hattori_atsushi 0:f77369cabd75 112 {
hattori_atsushi 0:f77369cabd75 113 //Disable IRQs, dont want them to happen while busy here
hattori_atsushi 0:f77369cabd75 114 NVIC_DisableIRQ(RTC_IRQn);
hattori_atsushi 0:f77369cabd75 115
hattori_atsushi 0:f77369cabd75 116 //Set the IRQ vector
hattori_atsushi 0:f77369cabd75 117 NVIC_SetVector(RTC_IRQn, (uint32_t)&RTC::IRQHandler);
hattori_atsushi 0:f77369cabd75 118
hattori_atsushi 0:f77369cabd75 119 //If this is the first time it is called, delete all interrupt sources
hattori_atsushi 0:f77369cabd75 120 //We need to do this because RTC unit isnt affected by system resets apparently
hattori_atsushi 0:f77369cabd75 121 if (initialRun) {
hattori_atsushi 0:f77369cabd75 122 LPC_RTC->CIIR = 0;
hattori_atsushi 0:f77369cabd75 123 LPC_RTC->AMR = 255;
hattori_atsushi 0:f77369cabd75 124 initialRun = false;
hattori_atsushi 0:f77369cabd75 125 LPC_RTC->ILR = 0x03;
hattori_atsushi 0:f77369cabd75 126 }
hattori_atsushi 0:f77369cabd75 127
hattori_atsushi 0:f77369cabd75 128 //Set the alarm register
hattori_atsushi 0:f77369cabd75 129 if ((alarmTime.tm_sec>=0) && (alarmTime.tm_sec<60)) {
hattori_atsushi 0:f77369cabd75 130 LPC_RTC->ALSEC = alarmTime.tm_sec;
hattori_atsushi 0:f77369cabd75 131 LPC_RTC->AMR &= ~1;
hattori_atsushi 0:f77369cabd75 132 } else
hattori_atsushi 0:f77369cabd75 133 LPC_RTC->AMR |= 1;
hattori_atsushi 0:f77369cabd75 134
hattori_atsushi 0:f77369cabd75 135 if ((alarmTime.tm_min>=0) && (alarmTime.tm_min<60)) {
hattori_atsushi 0:f77369cabd75 136 LPC_RTC->ALMIN = alarmTime.tm_min;
hattori_atsushi 0:f77369cabd75 137 LPC_RTC->AMR &= ~2;
hattori_atsushi 0:f77369cabd75 138 } else
hattori_atsushi 0:f77369cabd75 139 LPC_RTC->AMR |= 2;
hattori_atsushi 0:f77369cabd75 140
hattori_atsushi 0:f77369cabd75 141 if ((alarmTime.tm_hour>=0) && (alarmTime.tm_hour<24)) {
hattori_atsushi 0:f77369cabd75 142 LPC_RTC->ALHOUR = alarmTime.tm_hour;
hattori_atsushi 0:f77369cabd75 143 LPC_RTC->AMR &= ~4;
hattori_atsushi 0:f77369cabd75 144 } else
hattori_atsushi 0:f77369cabd75 145 LPC_RTC->AMR |= 4;
hattori_atsushi 0:f77369cabd75 146
hattori_atsushi 0:f77369cabd75 147 if ((alarmTime.tm_mday>=1) && (alarmTime.tm_mday<32)) {
hattori_atsushi 0:f77369cabd75 148 LPC_RTC->ALDOM = alarmTime.tm_mday;
hattori_atsushi 0:f77369cabd75 149 LPC_RTC->AMR &= ~8;
hattori_atsushi 0:f77369cabd75 150 } else
hattori_atsushi 0:f77369cabd75 151 LPC_RTC->AMR |= 8;
hattori_atsushi 0:f77369cabd75 152
hattori_atsushi 0:f77369cabd75 153 if ((alarmTime.tm_wday>=0) && (alarmTime.tm_wday<7)) {
hattori_atsushi 0:f77369cabd75 154 LPC_RTC->ALDOW = alarmTime.tm_wday;
hattori_atsushi 0:f77369cabd75 155 LPC_RTC->AMR &= ~16;
hattori_atsushi 0:f77369cabd75 156 } else
hattori_atsushi 0:f77369cabd75 157 LPC_RTC->AMR |= 16;
hattori_atsushi 0:f77369cabd75 158
hattori_atsushi 0:f77369cabd75 159 if ((alarmTime.tm_yday>0) && (alarmTime.tm_yday<367)) {
hattori_atsushi 0:f77369cabd75 160 LPC_RTC->ALDOY = alarmTime.tm_yday;
hattori_atsushi 0:f77369cabd75 161 LPC_RTC->AMR &= ~32;
hattori_atsushi 0:f77369cabd75 162 } else
hattori_atsushi 0:f77369cabd75 163 LPC_RTC->AMR |= 32;
hattori_atsushi 0:f77369cabd75 164
hattori_atsushi 0:f77369cabd75 165 if ((alarmTime.tm_mon>=0) && (alarmTime.tm_mon<12)) {
hattori_atsushi 0:f77369cabd75 166 LPC_RTC->ALMON = alarmTime.tm_mon + 1; //Different definitions
hattori_atsushi 0:f77369cabd75 167 LPC_RTC->AMR &= ~64;
hattori_atsushi 0:f77369cabd75 168 } else
hattori_atsushi 0:f77369cabd75 169 LPC_RTC->AMR |= 64;
hattori_atsushi 0:f77369cabd75 170
hattori_atsushi 0:f77369cabd75 171 if ((alarmTime.tm_year>=0) && (alarmTime.tm_year<1000)) {
hattori_atsushi 0:f77369cabd75 172 LPC_RTC->ALYEAR = alarmTime.tm_year + 1900; //Different definitions
hattori_atsushi 0:f77369cabd75 173 LPC_RTC->AMR &= ~128;
hattori_atsushi 0:f77369cabd75 174 } else
hattori_atsushi 0:f77369cabd75 175 LPC_RTC->AMR |= 128;
hattori_atsushi 0:f77369cabd75 176
hattori_atsushi 0:f77369cabd75 177 //DOY and DOW register normally not set
hattori_atsushi 0:f77369cabd75 178 time_t t = time(NULL);
hattori_atsushi 0:f77369cabd75 179 LPC_RTC->DOY = localtime(&t)->tm_yday+1;
hattori_atsushi 0:f77369cabd75 180 LPC_RTC->DOW = localtime(&t)->tm_wday;
hattori_atsushi 0:f77369cabd75 181
hattori_atsushi 0:f77369cabd75 182 //We can always enable IRQs, since if all IRQs are disabled by the user the RTC hardware will never raise its IRQ flag anyway
hattori_atsushi 0:f77369cabd75 183 NVIC_EnableIRQ(RTC_IRQn);
hattori_atsushi 0:f77369cabd75 184 }
hattori_atsushi 0:f77369cabd75 185
hattori_atsushi 0:f77369cabd75 186 void RTC::alarmOff( void )
hattori_atsushi 0:f77369cabd75 187 {
hattori_atsushi 0:f77369cabd75 188 LPC_RTC->AMR = 255;
hattori_atsushi 0:f77369cabd75 189 alarmCB.attach(NULL);
hattori_atsushi 0:f77369cabd75 190 }
hattori_atsushi 0:f77369cabd75 191
hattori_atsushi 0:f77369cabd75 192
hattori_atsushi 0:f77369cabd75 193 void RTC::IRQHandler( void )
hattori_atsushi 0:f77369cabd75 194 {
hattori_atsushi 0:f77369cabd75 195 if ((LPC_RTC->ILR & 0x01) == 0x01) {
hattori_atsushi 0:f77369cabd75 196 //Attach interrupt
hattori_atsushi 0:f77369cabd75 197 attachCB[0].call();
hattori_atsushi 0:f77369cabd75 198
hattori_atsushi 0:f77369cabd75 199 //If seconds zero
hattori_atsushi 0:f77369cabd75 200 if (LPC_RTC->SEC == 0) {
hattori_atsushi 0:f77369cabd75 201 attachCB[1].call();
hattori_atsushi 0:f77369cabd75 202
hattori_atsushi 0:f77369cabd75 203 //If minutes zero
hattori_atsushi 0:f77369cabd75 204 if (LPC_RTC->MIN == 0) {
hattori_atsushi 0:f77369cabd75 205 attachCB[2].call();
hattori_atsushi 0:f77369cabd75 206
hattori_atsushi 0:f77369cabd75 207 //If hours zero
hattori_atsushi 0:f77369cabd75 208 if (LPC_RTC->HOUR == 0) {
hattori_atsushi 0:f77369cabd75 209 attachCB[3].call();
hattori_atsushi 0:f77369cabd75 210
hattori_atsushi 0:f77369cabd75 211 //If days zero
hattori_atsushi 0:f77369cabd75 212 if (LPC_RTC->DOM == 0) {
hattori_atsushi 0:f77369cabd75 213 attachCB[4].call();
hattori_atsushi 0:f77369cabd75 214
hattori_atsushi 0:f77369cabd75 215 //If month zero
hattori_atsushi 0:f77369cabd75 216 if (LPC_RTC->MONTH == 0)
hattori_atsushi 0:f77369cabd75 217 attachCB[5].call();
hattori_atsushi 0:f77369cabd75 218 }
hattori_atsushi 0:f77369cabd75 219 }
hattori_atsushi 0:f77369cabd75 220 }
hattori_atsushi 0:f77369cabd75 221 }
hattori_atsushi 0:f77369cabd75 222 }
hattori_atsushi 0:f77369cabd75 223
hattori_atsushi 0:f77369cabd75 224 if ((LPC_RTC->ILR & 0x02) == 0x02)
hattori_atsushi 0:f77369cabd75 225 alarmCB.call();
hattori_atsushi 0:f77369cabd75 226
hattori_atsushi 0:f77369cabd75 227
hattori_atsushi 0:f77369cabd75 228
hattori_atsushi 0:f77369cabd75 229 //Reset interrupt status
hattori_atsushi 0:f77369cabd75 230 LPC_RTC->ILR = 0x03;
hattori_atsushi 0:f77369cabd75 231 }
hattori_atsushi 0:f77369cabd75 232
hattori_atsushi 0:f77369cabd75 233 tm RTC::getDefaultTM( void ) {
hattori_atsushi 0:f77369cabd75 234 struct tm t;
hattori_atsushi 0:f77369cabd75 235 t.tm_sec = -1;
hattori_atsushi 0:f77369cabd75 236 t.tm_min = -1;
hattori_atsushi 0:f77369cabd75 237 t.tm_hour = -1;
hattori_atsushi 0:f77369cabd75 238 t.tm_mday = -1;
hattori_atsushi 0:f77369cabd75 239 t.tm_wday = -1;
hattori_atsushi 0:f77369cabd75 240 t.tm_yday = -1;
hattori_atsushi 0:f77369cabd75 241 t.tm_mon = -1;
hattori_atsushi 0:f77369cabd75 242 t.tm_year = -1;
hattori_atsushi 0:f77369cabd75 243
hattori_atsushi 0:f77369cabd75 244 return t;
hattori_atsushi 0:f77369cabd75 245 }