@@ -181,8 +181,6 @@ void STM32LowPower::enableWakeupFrom(STM32RTC *rtc, voidFuncPtr callback, void *
181
181
*/
182
182
void STM32LowPower::programRtcWakeUp (uint32_t ms, LP_Mode lp_mode)
183
183
{
184
- uint32_t epoc;
185
- uint32_t sec;
186
184
STM32RTC &rtc = STM32RTC::getInstance ();
187
185
STM32RTC::Source_Clock clkSrc = rtc.getClockSource ();
188
186
@@ -207,21 +205,108 @@ void STM32LowPower::programRtcWakeUp(uint32_t ms, LP_Mode lp_mode)
207
205
}
208
206
rtc.configForLowPower (clkSrc);
209
207
208
+ setAlarmTime (ms, rtc);
209
+ }
210
+
211
+ static bool isLeapYear (uint8_t year2k)
212
+ {
213
+ int year = year2k + 2000 ;
214
+
215
+ // if year not divisible by 4 - not a leap year
216
+ // else if year divisible by 4 and not by 100 - a leap year
217
+ // else if year divisible by 400 - a leap year
218
+ return (year % 4 != 0 ) ? false : (year % 100 != 0 ) ? true : year % 400 == 0 ;
219
+ }
220
+
221
+ void STM32LowPower::setAlarmTime (uint32_t ms, STM32RTC &rtc)
222
+ {
210
223
if (ms != 0 ) {
211
- // Convert millisecond to second
212
- sec = ms / 1000 ;
213
-
214
- uint32_t epoc_ms;
215
- ms = ms % 1000 ;
216
- epoc = rtc.getEpoch (&epoc_ms);
217
-
218
- // Update epoch_ms - might need to add a second to epoch
219
- epoc_ms += ms;
220
- if (epoc_ms >= 1000 ) {
221
- sec ++;
222
- epoc_ms -= 1000 ;
224
+ uint16_t subSecondsToAdd = ms % 1000 ;
225
+
226
+ ms = ms / 1000 ;
227
+ uint8_t daysToAdd = ms / 86400 ;
228
+ uint8_t hoursToAdd = (ms - daysToAdd * 86400 ) / 3600 ;
229
+ uint8_t minutesToAdd = (ms - daysToAdd * 86400 - hoursToAdd * 3600 ) / 60 ;
230
+ uint8_t secondsToAdd = (ms - daysToAdd * 86400 - hoursToAdd * 3600 - minutesToAdd * 60 );
231
+
232
+ uint8_t hrCurrent, minCurrent, secCurrent;
233
+ uint32_t subSecondsCurrent;
234
+ STM32RTC::AM_PM period;
235
+ rtc.getTime (&hrCurrent, &minCurrent, &secCurrent, &subSecondsCurrent, &period);
236
+
237
+ uint8_t weekDay, currentDay, currentMonth, currentYear;
238
+ rtc.getDate (&weekDay, ¤tDay, ¤tMonth, ¤tYear);
239
+
240
+ uint32_t ss = subSecondsCurrent + subSecondsToAdd;
241
+ if (ss >= 1000 ) {
242
+ ss -= 1000 ;
243
+ secondsToAdd++;
244
+ }
245
+
246
+ if (secondsToAdd >= 60 ) {
247
+ secondsToAdd = 0 ;
248
+ minutesToAdd++;
223
249
}
250
+ uint8_t s = secCurrent + secondsToAdd;
251
+ if (s >= 60 ) {
252
+ s -= 60 ;
253
+ minutesToAdd++;
254
+ }
255
+
256
+ if (minutesToAdd >= 60 ) {
257
+ minutesToAdd -= 60 ;
258
+ hoursToAdd++;
259
+ }
260
+ uint8_t m = minCurrent + minutesToAdd;
261
+ if (m >= 60 ) {
262
+ m -= 60 ;
263
+ hoursToAdd++;
264
+ }
265
+
266
+ if (hoursToAdd >= 24 ) {
267
+ hoursToAdd -= 24 ;
268
+ daysToAdd++;
269
+ }
270
+ uint8_t h = hrCurrent + hoursToAdd;
271
+ if (rtc._format == STM32RTC::Hour_Format::HOUR_12) {
272
+ if (h >= 24 ) {
273
+ h -= 24 ;
274
+ daysToAdd++;
275
+ } else if (h >= 12 ) {
276
+ if (period == STM32RTC::AM_PM::AM) {
277
+ period = STM32RTC::AM_PM::PM;
278
+ } else {
279
+ period = STM32RTC::AM_PM::AM;
280
+ daysToAdd++;
281
+ }
282
+
283
+ if (h > 12 ) {
284
+ h -= 12 ;
285
+ }
286
+ }
287
+ } else if (h >= 24 ) {
288
+ h -= 24 ;
289
+ daysToAdd++;
290
+ }
291
+
292
+ // numbers of days in each month (february is calculated based on leap year)
293
+ static uint8_t daysInMonths[] = {31 , 0 , 31 , 30 , 31 , 30 , 31 , 31 , 30 , 31 , 30 , 31 };
294
+ uint8_t endDay;
295
+ if (currentMonth == 2 ) {
296
+ endDay = isLeapYear (currentYear) ? 29 : 28 ;
297
+ } else {
298
+ endDay = daysInMonths[currentMonth];
299
+ }
300
+
301
+ uint8_t d = currentDay + daysToAdd;
302
+ if (d > endDay) {
303
+ d -= endDay;
304
+ }
305
+
306
+ // month-year overflow isn't handled because its not supported by RTC's alarm
224
307
225
- rtc.setAlarmEpoch (epoc + sec, STM32RTC::MATCH_DHHMMSS, epoc_ms);
308
+ rtc.setAlarmTime (h, m, s, ss, period);
309
+ rtc.setAlarmDay (d);
310
+ rtc.enableAlarm (STM32RTC::Alarm_Match::MATCH_DHHMMSS);
226
311
}
227
312
}
0 commit comments