1 /***************************************************************************//**
2 * \file cy_rtc.c
3 * \version 2.50
4 *
5 * This file provides constants and parameter values for the APIs for the
6 * Real-Time Clock (RTC).
7 *
8 ********************************************************************************
9 * \copyright
10 * Copyright 2016-2020 Cypress Semiconductor Corporation
11 * SPDX-License-Identifier: Apache-2.0
12 *
13 * Licensed under the Apache License, Version 2.0 (the "License");
14 * you may not use this file except in compliance with the License.
15 * You may obtain a copy of the License at
16 *
17 * http://www.apache.org/licenses/LICENSE-2.0
18 *
19 * Unless required by applicable law or agreed to in writing, software
20 * distributed under the License is distributed on an "AS IS" BASIS,
21 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
22 * See the License for the specific language governing permissions and
23 * limitations under the License.
24 *******************************************************************************/
25
26 #include "cy_device.h"
27
28 #if defined (CY_IP_MXS40SRSS_RTC) || defined (CY_IP_MXS28SRSS) || defined (CY_IP_MXS40SSRSS)
29
30 #include "cy_rtc.h"
31
32 CY_MISRA_DEVIATE_BLOCK_START('MISRA C-2012 Rule 2.2', 3, \
33 'The unused code due to weak implementation can be overwritten further and then interrupt handler can call it.');
34 #if defined(__cplusplus)
35 extern "C" {
36 #endif
37
38 #if defined (CY_IP_MXS40SRSS_RTC)
39 #define CONVERT_BCD_TO_DEC(bcdNum) Cy_RTC_ConvertBcdToDec(bcdNum)
40 #define CONVERT_DEC_TO_BCD(decNum) Cy_RTC_ConvertDecToBcd(decNum)
41 #elif defined (CY_IP_MXS28SRSS) || defined (CY_IP_MXS40SSRSS)
42 #define CONVERT_BCD_TO_DEC(bcdNum) (bcdNum)
43 #define CONVERT_DEC_TO_BCD(decNum) (decNum)
44 #endif /* CY_IP_MXS40SRSS_RTC, CY_IP_MXS28SRSS, CY_IP_MXS40SSRSS */
45
46 /** RTC days in months table */
47 uint8_t const cy_RTC_daysInMonthTbl[CY_RTC_MONTHS_PER_YEAR] = {CY_RTC_DAYS_IN_JANUARY,
48 CY_RTC_DAYS_IN_FEBRUARY,
49 CY_RTC_DAYS_IN_MARCH,
50 CY_RTC_DAYS_IN_APRIL,
51 CY_RTC_DAYS_IN_MAY,
52 CY_RTC_DAYS_IN_JUNE,
53 CY_RTC_DAYS_IN_JULY,
54 CY_RTC_DAYS_IN_AUGUST,
55 CY_RTC_DAYS_IN_SEPTEMBER,
56 CY_RTC_DAYS_IN_OCTOBER,
57 CY_RTC_DAYS_IN_NOVEMBER,
58 CY_RTC_DAYS_IN_DECEMBER};
59
60 /* Static functions */
61 static void ConstructTimeDate(cy_stc_rtc_config_t const *timeDate, uint32_t *timeBcd, uint32_t *dateBcd);
62 static void ConstructAlarmTimeDate(cy_stc_rtc_alarm_t const *alarmDateTime, uint32_t *alarmTimeBcd,
63 uint32_t *alarmDateBcd);
64 static uint32_t RelativeToFixed(cy_stc_rtc_dst_format_t const *convertDst);
65
66
67 /*******************************************************************************
68 * Function Name: Cy_RTC_Init
69 ****************************************************************************//**
70 *
71 * Initializes the RTC driver.
72 *
73 * \param *config
74 * The pointer to the RTC configuration structure, see \ref cy_stc_rtc_config_t.
75 *
76 * \return
77 * Checking result. If the pointer is NULL, returns an error.
78 * See \ref cy_en_rtc_status_t.
79 *
80 *******************************************************************************/
Cy_RTC_Init(cy_stc_rtc_config_t const * config)81 cy_en_rtc_status_t Cy_RTC_Init(cy_stc_rtc_config_t const *config)
82 {
83 return(Cy_RTC_SetDateAndTime(config));
84 }
85
86
87 /*******************************************************************************
88 * Function Name: Cy_RTC_SetDateAndTime
89 ****************************************************************************//**
90 *
91 * Sets the time and date values into the RTC_TIME and RTC_DATE registers.
92 *
93 * \param dateTime
94 * The pointer to the RTC configuration structure, see \ref cy_stc_rtc_config_t.
95 *
96 * \return
97 * A validation check result of date and month. Returns an
98 * error, if the date range is invalid. See \ref cy_en_rtc_status_t.
99 *
100 * \note
101 * The function may return CY_RTC_INVALID_STATE if the RTC is
102 * busy with previous update. In such situation, user should
103 * call this function repetitively with appropriate parameters
104 * to ensure that RTC is updated with provided arguments.
105 *
106 *******************************************************************************/
Cy_RTC_SetDateAndTime(cy_stc_rtc_config_t const * dateTime)107 cy_en_rtc_status_t Cy_RTC_SetDateAndTime(cy_stc_rtc_config_t const *dateTime)
108 {
109 cy_en_rtc_status_t retVal = CY_RTC_BAD_PARAM;
110
111 if (NULL != dateTime)
112 {
113 uint32_t tmpDaysInMonth;
114
115 CY_ASSERT_L3(CY_RTC_IS_SEC_VALID(dateTime->sec));
116 CY_ASSERT_L3(CY_RTC_IS_MIN_VALID(dateTime->min));
117 CY_ASSERT_L3(CY_RTC_IS_HOUR_VALID(dateTime->hour));
118 CY_ASSERT_L3(CY_RTC_IS_DOW_VALID(dateTime->dayOfWeek));
119 CY_ASSERT_L3(CY_RTC_IS_MONTH_VALID(dateTime->month));
120 CY_ASSERT_L3(CY_RTC_IS_YEAR_SHORT_VALID(dateTime->year));
121
122 /* Check dateTime->date input */
123 tmpDaysInMonth = Cy_RTC_DaysInMonth(dateTime->month, (dateTime->year + CY_RTC_TWO_THOUSAND_YEARS));
124
125 if ((dateTime->date > 0U) && (dateTime->date <= tmpDaysInMonth))
126 {
127 uint32_t interruptState;
128 uint32_t tmpTime;
129 uint32_t tmpDate;
130
131 ConstructTimeDate(dateTime, &tmpTime, &tmpDate);
132
133 /* The RTC AHB registers can be updated only under condition that the
134 * Write bit is set and the RTC busy bit is cleared (CY_RTC_BUSY = 0).
135 */
136 interruptState = Cy_SysLib_EnterCriticalSection();
137 retVal = Cy_RTC_WriteEnable(CY_RTC_WRITE_ENABLED);
138 if (retVal == CY_RTC_SUCCESS)
139 {
140 BACKUP_RTC_TIME = tmpTime;
141 BACKUP_RTC_DATE = tmpDate;
142
143 /* Clear the RTC Write bit to finish RTC register update */
144 retVal = Cy_RTC_WriteEnable(CY_RTC_WRITE_DISABLED);
145 }
146 Cy_SysLib_ExitCriticalSection(interruptState);
147 }
148 }
149 return(retVal);
150 }
151
152
153 /*******************************************************************************
154 * Function Name: Cy_RTC_GetDateAndTime
155 ****************************************************************************//**
156 *
157 * Gets the current RTC time and date. The AHB RTC Time and Date register values
158 * are stored into the *dateTime structure.
159 *
160 * \param dateTime
161 * The RTC time and date structure. See \ref group_rtc_data_structures.
162 *
163 *******************************************************************************/
Cy_RTC_GetDateAndTime(cy_stc_rtc_config_t * dateTime)164 void Cy_RTC_GetDateAndTime(cy_stc_rtc_config_t* dateTime)
165 {
166 uint32_t tmpTime;
167 uint32_t tmpDate;
168
169 CY_ASSERT_L1(NULL != dateTime);
170
171 /* Read the current RTC time and date to validate the input parameters */
172 Cy_RTC_SyncFromRtc();
173
174 /* Write the AHB RTC registers date and time into the local variables and
175 * updating the dateTime structure elements
176 */
177 tmpTime = BACKUP_RTC_TIME;
178 tmpDate = BACKUP_RTC_DATE;
179 dateTime->sec = CONVERT_BCD_TO_DEC(_FLD2VAL(BACKUP_RTC_TIME_RTC_SEC, tmpTime));
180 dateTime->min = CONVERT_BCD_TO_DEC(_FLD2VAL(BACKUP_RTC_TIME_RTC_MIN, tmpTime));
181 dateTime->hrFormat = ((_FLD2BOOL(BACKUP_RTC_TIME_CTRL_12HR, tmpTime)) ? CY_RTC_12_HOURS : CY_RTC_24_HOURS);
182
183 /* Read the current hour mode to know how many hour bits should be converted
184 * In the 24-hour mode, the hour value is presented in [21:16] bits in the
185 * BCD format.
186 * In the 12-hour mode the hour value is presented in [20:16] bits in the BCD
187 * format and bit [21] is present: 0 - AM; 1 - PM.
188 */
189 if (dateTime->hrFormat != CY_RTC_24_HOURS)
190 {
191 dateTime->hour =
192 CONVERT_BCD_TO_DEC((tmpTime & CY_RTC_BACKUP_RTC_TIME_RTC_12HOUR) >> BACKUP_RTC_TIME_RTC_HOUR_Pos);
193 dateTime->amPm = ((0U != (tmpTime & CY_RTC_BACKUP_RTC_TIME_RTC_PM)) ? CY_RTC_PM : CY_RTC_AM);
194 }
195 else
196 {
197 dateTime->hour = CONVERT_BCD_TO_DEC(_FLD2VAL(BACKUP_RTC_TIME_RTC_HOUR, tmpTime));
198 dateTime->amPm = CY_RTC_AM;
199 }
200 dateTime->dayOfWeek = CONVERT_BCD_TO_DEC(_FLD2VAL(BACKUP_RTC_TIME_RTC_DAY, tmpTime));
201
202 dateTime->date = CONVERT_BCD_TO_DEC(_FLD2VAL(BACKUP_RTC_DATE_RTC_DATE, tmpDate));
203 dateTime->month = CONVERT_BCD_TO_DEC(_FLD2VAL(BACKUP_RTC_DATE_RTC_MON, tmpDate));
204 dateTime->year = CONVERT_BCD_TO_DEC(_FLD2VAL(BACKUP_RTC_DATE_RTC_YEAR, tmpDate));
205 }
206
207
208 /*******************************************************************************
209 * Function Name: Cy_RTC_SetAlarmDateAndTime
210 ****************************************************************************//**
211 *
212 * Sets alarm time and date values into the ALMx_TIME and ALMx_DATE registers.
213 *
214 * \param alarmDateTime
215 * The alarm configuration structure, see \ref cy_stc_rtc_alarm_t.
216 *
217 * \param alarmIndex
218 * The alarm index to be configured, see \ref cy_en_rtc_alarm_t.
219 *
220 * \return
221 * A validation check result of date and month. Returns an
222 * error, if the date range is invalid. See \ref cy_en_rtc_status_t.
223 *
224 * \note
225 * The function may return CY_RTC_INVALID_STATE if the RTC is
226 * busy with previous update. In such situation, user should
227 * call this function repetitively with appropriate parameters
228 * to ensure that RTC is updated with provided arguments.
229 *
230 *******************************************************************************/
Cy_RTC_SetAlarmDateAndTime(cy_stc_rtc_alarm_t const * alarmDateTime,cy_en_rtc_alarm_t alarmIndex)231 cy_en_rtc_status_t Cy_RTC_SetAlarmDateAndTime(cy_stc_rtc_alarm_t const *alarmDateTime, cy_en_rtc_alarm_t alarmIndex)
232 {
233 cy_en_rtc_status_t retVal = CY_RTC_BAD_PARAM;
234
235 if (NULL != alarmDateTime)
236 {
237 uint32_t tmpYear;
238 uint32_t tmpDaysInMonth;
239
240 CY_ASSERT_L3(CY_RTC_IS_ALARM_IDX_VALID(alarmIndex));
241
242 CY_ASSERT_L3(CY_RTC_IS_SEC_VALID(alarmDateTime->sec));
243 CY_ASSERT_L3(CY_RTC_IS_ALARM_EN_VALID(alarmDateTime->secEn));
244
245 CY_ASSERT_L3(CY_RTC_IS_MIN_VALID(alarmDateTime->min));
246 CY_ASSERT_L3(CY_RTC_IS_ALARM_EN_VALID(alarmDateTime->minEn));
247
248 CY_ASSERT_L3(CY_RTC_IS_HOUR_VALID(alarmDateTime->hour));
249 CY_ASSERT_L3(CY_RTC_IS_ALARM_EN_VALID(alarmDateTime->hourEn));
250
251 CY_ASSERT_L3(CY_RTC_IS_DOW_VALID(alarmDateTime->dayOfWeek));
252 CY_ASSERT_L3(CY_RTC_IS_ALARM_EN_VALID(alarmDateTime->dayOfWeekEn));
253
254 CY_ASSERT_L3(CY_RTC_IS_MONTH_VALID(alarmDateTime->month));
255 CY_ASSERT_L3(CY_RTC_IS_ALARM_EN_VALID(alarmDateTime->monthEn));
256
257 CY_ASSERT_L3(CY_RTC_IS_ALARM_EN_VALID(alarmDateTime->dateEn));
258
259 CY_ASSERT_L3(CY_RTC_IS_ALARM_EN_VALID(alarmDateTime->almEn));
260
261 /* Read the current RTC year to validate alarmDateTime->date */
262 Cy_RTC_SyncFromRtc();
263
264 tmpYear =
265 CY_RTC_TWO_THOUSAND_YEARS + CONVERT_BCD_TO_DEC(_FLD2VAL(BACKUP_RTC_DATE_RTC_YEAR, BACKUP_RTC_DATE));
266 tmpDaysInMonth = Cy_RTC_DaysInMonth(alarmDateTime->month, tmpYear);
267
268 if ((alarmDateTime->date > 0U) && (alarmDateTime->date <= tmpDaysInMonth))
269 {
270 uint32_t interruptState;
271 uint32_t tmpAlarmTime;
272 uint32_t tmpAlarmDate;
273
274 ConstructAlarmTimeDate(alarmDateTime, &tmpAlarmTime, &tmpAlarmDate);
275
276 /* The RTC AHB registers can be updated only under condition that the
277 * Write bit is set and the RTC busy bit is cleared (RTC_BUSY = 0).
278 */
279 interruptState = Cy_SysLib_EnterCriticalSection();
280 retVal = Cy_RTC_WriteEnable(CY_RTC_WRITE_ENABLED);
281 if (CY_RTC_SUCCESS == retVal)
282 {
283 /* Update the AHB RTC registers with formed values */
284 if (alarmIndex != CY_RTC_ALARM_2)
285 {
286 BACKUP_ALM1_TIME = tmpAlarmTime;
287 BACKUP_ALM1_DATE = tmpAlarmDate;
288 }
289 else
290 {
291 BACKUP_ALM2_TIME = tmpAlarmTime;
292 BACKUP_ALM2_DATE = tmpAlarmDate;
293 }
294
295 /* Clear the RTC Write bit to finish RTC update */
296 retVal = Cy_RTC_WriteEnable(CY_RTC_WRITE_DISABLED);
297 }
298 Cy_SysLib_ExitCriticalSection(interruptState);
299 }
300 }
301 return(retVal);
302 }
303
304
305 /*******************************************************************************
306 * Function Name: Cy_RTC_GetAlarmDateAndTime
307 ****************************************************************************//**
308 *
309 * Returns the current alarm time and date values from the ALMx_TIME and
310 * ALMx_DATE registers.
311 *
312 * \param alarmDateTime
313 * The alarm configuration structure, see \ref cy_stc_rtc_alarm_t.
314 *
315 * \param alarmIndex
316 * The alarm index to be configured, see \ref cy_en_rtc_alarm_t.
317 *
318 *******************************************************************************/
Cy_RTC_GetAlarmDateAndTime(cy_stc_rtc_alarm_t * alarmDateTime,cy_en_rtc_alarm_t alarmIndex)319 void Cy_RTC_GetAlarmDateAndTime(cy_stc_rtc_alarm_t *alarmDateTime, cy_en_rtc_alarm_t alarmIndex)
320 {
321 uint32_t tmpAlarmTime;
322 uint32_t tmpAlarmDate;
323 cy_en_rtc_hours_format_t curHoursFormat;
324
325 CY_ASSERT_L1(NULL != alarmDateTime);
326 CY_ASSERT_L3(CY_RTC_IS_ALARM_IDX_VALID(alarmIndex));
327
328 /* Read the current RTC time and date to validate the input parameters */
329 Cy_RTC_SyncFromRtc();
330
331 curHoursFormat = Cy_RTC_GetHoursFormat();
332
333 /* Write the AHB RTC registers into the local variables and update the
334 * alarmDateTime structure elements
335 */
336 if (alarmIndex != CY_RTC_ALARM_2)
337 {
338 tmpAlarmTime = BACKUP_ALM1_TIME;
339 tmpAlarmDate = BACKUP_ALM1_DATE;
340
341 alarmDateTime->sec = CONVERT_BCD_TO_DEC(_FLD2VAL(BACKUP_ALM1_TIME_ALM_SEC, tmpAlarmTime));
342 alarmDateTime->secEn =
343 ((_FLD2BOOL(BACKUP_ALM1_TIME_ALM_SEC_EN, tmpAlarmTime)) ? CY_RTC_ALARM_ENABLE : CY_RTC_ALARM_DISABLE);
344 alarmDateTime->min = CONVERT_BCD_TO_DEC(_FLD2VAL(BACKUP_ALM1_TIME_ALM_MIN, tmpAlarmTime));
345 alarmDateTime->minEn =
346 ((_FLD2BOOL(BACKUP_ALM1_TIME_ALM_MIN_EN, tmpAlarmTime)) ? CY_RTC_ALARM_ENABLE : CY_RTC_ALARM_DISABLE);
347
348 /* Read the current hour mode to know how many hour bits to convert.
349 * In the 24-hour mode, the hour value is presented in [21:16] bits in
350 * the BCD format.
351 * In the 12-hour mode, the hour value is presented in [20:16] bits in
352 * the BCD format and bit [21] is present: 0 - AM; 1 - PM.
353 */
354 if (curHoursFormat != CY_RTC_24_HOURS)
355 {
356 alarmDateTime->hour =
357 CONVERT_BCD_TO_DEC((tmpAlarmTime & CY_RTC_BACKUP_RTC_TIME_RTC_12HOUR)
358 >> BACKUP_ALM1_TIME_ALM_HOUR_Pos);
359
360 /* In the structure, the hour value should be presented in the 24-hour mode. In
361 * that condition the firmware checks the AM/PM status and adds 12 hours to
362 * the converted hour value if the PM bit is set.
363 */
364 if ((alarmDateTime->hour < CY_RTC_HOURS_PER_HALF_DAY) &&
365 (0U != (BACKUP_ALM1_TIME & CY_RTC_BACKUP_RTC_TIME_RTC_PM)))
366 {
367 alarmDateTime->hour += CY_RTC_HOURS_PER_HALF_DAY;
368 }
369
370 /* Set zero hour, as the 12 A hour is zero hour in 24-hour format */
371 if ((alarmDateTime->hour == CY_RTC_HOURS_PER_HALF_DAY) &&
372 (0U == (BACKUP_ALM1_TIME & CY_RTC_BACKUP_RTC_TIME_RTC_PM)))
373 {
374 alarmDateTime->hour = 0U;
375 }
376
377 }
378 else
379 {
380 alarmDateTime->hour = CONVERT_BCD_TO_DEC(_FLD2VAL(BACKUP_ALM1_TIME_ALM_HOUR, tmpAlarmTime));
381 }
382 alarmDateTime->hourEn =
383 ((_FLD2BOOL(BACKUP_ALM1_TIME_ALM_HOUR_EN, tmpAlarmTime)) ? CY_RTC_ALARM_ENABLE : CY_RTC_ALARM_DISABLE);
384
385 alarmDateTime->dayOfWeek = CONVERT_BCD_TO_DEC(_FLD2VAL(BACKUP_ALM1_TIME_ALM_DAY, tmpAlarmTime));
386 alarmDateTime->dayOfWeekEn =
387 ((_FLD2BOOL(BACKUP_ALM1_TIME_ALM_DAY_EN, tmpAlarmTime)) ? CY_RTC_ALARM_ENABLE : CY_RTC_ALARM_DISABLE);
388
389 alarmDateTime->date = CONVERT_BCD_TO_DEC(_FLD2VAL(BACKUP_ALM1_DATE_ALM_DATE, tmpAlarmDate));
390 alarmDateTime->dateEn =
391 ((_FLD2BOOL(BACKUP_ALM1_DATE_ALM_DATE_EN, tmpAlarmDate)) ? CY_RTC_ALARM_ENABLE : CY_RTC_ALARM_DISABLE);
392
393 alarmDateTime->month = CONVERT_BCD_TO_DEC(_FLD2VAL(BACKUP_ALM1_DATE_ALM_MON, tmpAlarmDate));
394 alarmDateTime->monthEn =
395 ((_FLD2BOOL(BACKUP_ALM1_DATE_ALM_MON_EN, tmpAlarmDate)) ? CY_RTC_ALARM_ENABLE : CY_RTC_ALARM_DISABLE);
396
397 alarmDateTime->almEn =
398 ((_FLD2BOOL(BACKUP_ALM1_DATE_ALM_EN, tmpAlarmDate)) ? CY_RTC_ALARM_ENABLE : CY_RTC_ALARM_DISABLE);
399 }
400 else
401 {
402 tmpAlarmTime = BACKUP_ALM2_TIME;
403 tmpAlarmDate = BACKUP_ALM2_DATE;
404
405 alarmDateTime->sec = CONVERT_BCD_TO_DEC(_FLD2VAL(BACKUP_ALM2_TIME_ALM_SEC, tmpAlarmTime));
406 alarmDateTime->secEn =
407 ((_FLD2BOOL(BACKUP_ALM2_TIME_ALM_SEC_EN, tmpAlarmTime)) ? CY_RTC_ALARM_ENABLE : CY_RTC_ALARM_DISABLE);
408
409 alarmDateTime->min = CONVERT_BCD_TO_DEC(_FLD2VAL(BACKUP_ALM2_TIME_ALM_MIN, tmpAlarmTime));
410 alarmDateTime->minEn =
411 ((_FLD2BOOL(BACKUP_ALM2_TIME_ALM_MIN_EN, tmpAlarmTime)) ? CY_RTC_ALARM_ENABLE : CY_RTC_ALARM_DISABLE);
412
413 /* Read the current hour mode to know how many hour bits to convert.
414 * In the 24-hour mode, the hour value is presented in [21:16] bits in
415 * the BCD format.
416 * In the 12-hour mode the hour value is presented in [20:16] bits in
417 * the BCD format and bit [21] is present: 0 - AM; 1 - PM.
418 */
419 if (curHoursFormat != CY_RTC_24_HOURS)
420 {
421 alarmDateTime->hour = CONVERT_BCD_TO_DEC((tmpAlarmTime & CY_RTC_BACKUP_RTC_TIME_RTC_12HOUR) >>
422 BACKUP_ALM2_TIME_ALM_HOUR_Pos);
423 /* In the structure, the hour value should be presented in the 24-hour mode. In
424 * that condition the firmware checks the AM/PM status and adds 12 hours to
425 * the converted hour value if the PM bit is set.
426 */
427 if ((alarmDateTime->hour < CY_RTC_HOURS_PER_HALF_DAY) &&
428 (0U != (BACKUP_ALM2_TIME & CY_RTC_BACKUP_RTC_TIME_RTC_PM)))
429 {
430 alarmDateTime->hour += CY_RTC_HOURS_PER_HALF_DAY;
431 }
432 /* Set zero hour, as the 12 am hour is zero hour in 24-hour format */
433 else if ((alarmDateTime->hour == CY_RTC_HOURS_PER_HALF_DAY) &&
434 (0U == (BACKUP_ALM2_TIME & CY_RTC_BACKUP_RTC_TIME_RTC_PM)))
435 {
436 alarmDateTime->hour = 0U;
437 }
438 else
439 {
440 /* No corrections are required */
441 }
442 }
443 else
444 {
445 alarmDateTime->hour = CONVERT_BCD_TO_DEC(_FLD2VAL(BACKUP_ALM2_TIME_ALM_HOUR, tmpAlarmTime));
446 }
447 alarmDateTime->hourEn =
448 ((_FLD2BOOL(BACKUP_ALM2_TIME_ALM_HOUR_EN, tmpAlarmTime)) ? CY_RTC_ALARM_ENABLE : CY_RTC_ALARM_DISABLE);
449
450 alarmDateTime->dayOfWeek = CONVERT_BCD_TO_DEC(_FLD2VAL(BACKUP_ALM2_TIME_ALM_DAY, tmpAlarmTime));
451 alarmDateTime->dayOfWeekEn =
452 ((_FLD2BOOL(BACKUP_ALM2_TIME_ALM_DAY_EN, tmpAlarmTime)) ? CY_RTC_ALARM_ENABLE : CY_RTC_ALARM_DISABLE);
453
454 alarmDateTime->date = CONVERT_BCD_TO_DEC(_FLD2VAL(BACKUP_ALM2_DATE_ALM_DATE, tmpAlarmDate));
455 alarmDateTime->dateEn =
456 ((_FLD2BOOL(BACKUP_ALM2_DATE_ALM_DATE_EN, tmpAlarmDate)) ? CY_RTC_ALARM_ENABLE : CY_RTC_ALARM_DISABLE);
457
458 alarmDateTime->month = CONVERT_BCD_TO_DEC(_FLD2VAL(BACKUP_ALM2_DATE_ALM_MON, tmpAlarmDate));
459 alarmDateTime->monthEn =
460 ((_FLD2BOOL(BACKUP_ALM2_DATE_ALM_MON_EN, tmpAlarmDate)) ? CY_RTC_ALARM_ENABLE : CY_RTC_ALARM_DISABLE);
461
462 alarmDateTime->almEn =
463 ((_FLD2BOOL(BACKUP_ALM2_DATE_ALM_EN, tmpAlarmDate)) ? CY_RTC_ALARM_ENABLE : CY_RTC_ALARM_DISABLE);
464 }
465 }
466
467
468 /*******************************************************************************
469 * Function Name: Cy_RTC_SetDateAndTimeDirect
470 ****************************************************************************//**
471 *
472 * Sets the time and date values into the RTC_TIME and RTC_DATE registers using
473 * direct time parameters.
474 *
475 * \param sec The second valid range is [0-59].
476 *
477 * \param min The minute valid range is [0-59].
478 *
479 * \param hour
480 * The hour valid range is [0-23]. This parameter should be presented in the
481 * 24-hour format.
482 *
483 * The function reads the current 12/24-hour mode, then converts the hour value
484 * properly as the mode.
485 *
486 * \param date
487 * The date valid range is [1-31], if the month of February is
488 * selected as the Month parameter, then the valid range is [0-29].
489 *
490 * \param month The month valid range is [1-12].
491 *
492 * \param year The year valid range is [0-99].
493 *
494 * \return
495 * A validation check result of date and month. Returns an
496 * error, if the date range is invalid or the RTC time and date set was
497 * cancelled: the RTC Write bit was not set, the RTC was synchronizing.
498 * See \ref cy_en_rtc_status_t.
499 *
500 *******************************************************************************/
Cy_RTC_SetDateAndTimeDirect(uint32_t sec,uint32_t min,uint32_t hour,uint32_t date,uint32_t month,uint32_t year)501 cy_en_rtc_status_t Cy_RTC_SetDateAndTimeDirect(uint32_t sec, uint32_t min, uint32_t hour,
502 uint32_t date, uint32_t month, uint32_t year)
503 {
504 uint32_t tmpDaysInMonth;
505 cy_en_rtc_status_t retVal = CY_RTC_BAD_PARAM;
506
507 CY_ASSERT_L3(CY_RTC_IS_SEC_VALID(sec));
508 CY_ASSERT_L3(CY_RTC_IS_MIN_VALID(min));
509 CY_ASSERT_L3(CY_RTC_IS_HOUR_VALID(hour));
510 CY_ASSERT_L3(CY_RTC_IS_MONTH_VALID(month));
511 CY_ASSERT_L3(CY_RTC_IS_YEAR_SHORT_VALID(year));
512
513 /* Check date input */
514 tmpDaysInMonth = Cy_RTC_DaysInMonth(month, (year + CY_RTC_TWO_THOUSAND_YEARS));
515
516 if ((date > 0U) && (date <= tmpDaysInMonth))
517 {
518 cy_stc_rtc_config_t curTimeAndDate;
519 uint32_t tmpTime;
520 uint32_t tmpDate;
521 uint32_t interruptState;
522
523 /* Fill the date and time structure */
524 curTimeAndDate.sec = sec;
525 curTimeAndDate.min = min;
526
527 /* Read the current hour mode */
528 Cy_RTC_SyncFromRtc();
529
530 if (CY_RTC_12_HOURS != Cy_RTC_GetHoursFormat())
531 {
532 curTimeAndDate.hrFormat = CY_RTC_24_HOURS;
533 curTimeAndDate.hour = hour;
534 }
535 else
536 {
537 curTimeAndDate.hrFormat = CY_RTC_12_HOURS;
538
539 /* Convert the 24-hour format input value into the 12-hour format */
540 if (hour >= CY_RTC_HOURS_PER_HALF_DAY)
541 {
542 /* The current hour is more than 12 or equal 12, in the 24-hour
543 * format. Set the PM bit and convert the hour: hour = hour - 12,
544 * except that the hour is 12.
545 */
546 curTimeAndDate.hour =
547 (hour > CY_RTC_HOURS_PER_HALF_DAY) ? ((uint32_t) hour - CY_RTC_HOURS_PER_HALF_DAY) : hour;
548
549 curTimeAndDate.amPm = CY_RTC_PM;
550 }
551 else
552 {
553 /* The current hour is less than 12 AM. The zero hour is equal
554 * to 12:00 AM
555 */
556 curTimeAndDate.hour = ((hour == 0U) ? CY_RTC_HOURS_PER_HALF_DAY : hour);
557 curTimeAndDate.amPm = CY_RTC_AM;
558 }
559 }
560 curTimeAndDate.dayOfWeek = Cy_RTC_ConvertDayOfWeek(date, month, (year + CY_RTC_TWO_THOUSAND_YEARS));
561 curTimeAndDate.date = date;
562 curTimeAndDate.month = month;
563 curTimeAndDate.year = year;
564
565 ConstructTimeDate(&curTimeAndDate, &tmpTime, &tmpDate);
566
567 /* The RTC AHB register can be updated only under condition that the
568 * Write bit is set and the RTC busy bit is cleared (CY_RTC_BUSY = 0).
569 */
570 interruptState = Cy_SysLib_EnterCriticalSection();
571 retVal = Cy_RTC_WriteEnable(CY_RTC_WRITE_ENABLED);
572 if (retVal == CY_RTC_SUCCESS)
573 {
574 BACKUP_RTC_TIME = tmpTime;
575 BACKUP_RTC_DATE = tmpDate;
576
577 /* Clear the RTC Write bit to finish RTC register update */
578 retVal = Cy_RTC_WriteEnable(CY_RTC_WRITE_DISABLED);
579 }
580 Cy_SysLib_ExitCriticalSection(interruptState);
581 }
582
583 return(retVal);
584 }
585
586
587 /*******************************************************************************
588 * Function Name: Cy_RTC_SetAlarmDateAndTimeDirect
589 ****************************************************************************//**
590 *
591 * Sets alarm time and date values into the ALMx_TIME and ALMx_DATE
592 * registers using direct time parameters. ALM_DAY_EN is default 0 (=ignore) for
593 * this function.
594 *
595 * \param sec The alarm second valid range is [0-59].
596 *
597 * \param min The alarm minute valid range is [0-59].
598 *
599 * \param hour
600 * The valid range is [0-23].
601 * This parameter type is always in the 24-hour type. This function reads the
602 * current 12/24-hour mode, then converts the hour value properly as the mode.
603 *
604 * \param date
605 * The valid range is [1-31], if the month of February is selected as
606 * the Month parameter, then the valid range is [0-29].
607 *
608 * \param month The alarm month valid range is [1-12].
609 *
610 * \param alarmIndex
611 * The alarm index to be configured, see \ref cy_en_rtc_alarm_t.
612 *
613 * \return
614 * A validation check result of date and month. Returns an
615 * error, if the date range is invalid. See \ref cy_en_rtc_status_t.
616 *
617 *******************************************************************************/
Cy_RTC_SetAlarmDateAndTimeDirect(uint32_t sec,uint32_t min,uint32_t hour,uint32_t date,uint32_t month,cy_en_rtc_alarm_t alarmIndex)618 cy_en_rtc_status_t Cy_RTC_SetAlarmDateAndTimeDirect(uint32_t sec, uint32_t min, uint32_t hour,
619 uint32_t date, uint32_t month, cy_en_rtc_alarm_t alarmIndex)
620 {
621 uint32_t tmpDaysInMonth;
622 uint32_t tmpCurrentYear;
623 cy_en_rtc_status_t retVal = CY_RTC_BAD_PARAM;
624
625 CY_ASSERT_L3(CY_RTC_IS_SEC_VALID(sec));
626 CY_ASSERT_L3(CY_RTC_IS_MIN_VALID(min));
627 CY_ASSERT_L3(CY_RTC_IS_HOUR_VALID(hour));
628 CY_ASSERT_L3(CY_RTC_IS_MONTH_VALID(month));
629 CY_ASSERT_L3(CY_RTC_IS_ALARM_IDX_VALID(alarmIndex));
630
631 /* Read the current time to validate the input parameters */
632 Cy_RTC_SyncFromRtc();
633
634 /* Get the current year value to calculate */
635 tmpCurrentYear =
636 CONVERT_BCD_TO_DEC(_FLD2VAL(BACKUP_RTC_DATE_RTC_YEAR, BACKUP_RTC_DATE));
637
638 tmpDaysInMonth = Cy_RTC_DaysInMonth(month, (tmpCurrentYear + CY_RTC_TWO_THOUSAND_YEARS));
639
640 if ((date > 0U) && (date <= tmpDaysInMonth))
641 {
642 uint32_t tmpAlarmTime;
643 uint32_t tmpAlarmDate;
644 uint32_t interruptState;
645 cy_stc_rtc_alarm_t alarmDateTime;
646
647 /* Fill the alarm structure */
648 alarmDateTime.sec = sec;
649 alarmDateTime.secEn = CY_RTC_ALARM_ENABLE;
650 alarmDateTime.min = min;
651 alarmDateTime.minEn = CY_RTC_ALARM_ENABLE;
652 alarmDateTime.hour = hour;
653 alarmDateTime.hourEn = CY_RTC_ALARM_ENABLE;
654 alarmDateTime.dayOfWeek = CY_RTC_SUNDAY;
655 alarmDateTime.dayOfWeekEn = CY_RTC_ALARM_DISABLE;
656
657 alarmDateTime.date = date;
658 alarmDateTime.dateEn = CY_RTC_ALARM_ENABLE;
659 alarmDateTime.month = month;
660 alarmDateTime.monthEn = CY_RTC_ALARM_ENABLE;
661 alarmDateTime.almEn = CY_RTC_ALARM_ENABLE;
662
663 ConstructAlarmTimeDate(&alarmDateTime, &tmpAlarmTime, &tmpAlarmDate);
664
665 /* The RTC AHB register can be updated only under condition that the
666 * Write bit is set and the RTC busy bit is cleared (CY_RTC_BUSY = 0).
667 */
668 interruptState = Cy_SysLib_EnterCriticalSection();
669 retVal = Cy_RTC_WriteEnable(CY_RTC_WRITE_ENABLED);
670 if (retVal == CY_RTC_SUCCESS)
671 {
672 if (alarmIndex != CY_RTC_ALARM_2)
673 {
674 BACKUP_ALM1_TIME = tmpAlarmTime;
675 BACKUP_ALM1_DATE = tmpAlarmDate;
676 }
677 else
678 {
679 BACKUP_ALM2_TIME = tmpAlarmTime;
680 BACKUP_ALM2_DATE = tmpAlarmDate;
681 }
682
683 /* Clear the RTC Write bit to finish RTC register update */
684 retVal = Cy_RTC_WriteEnable(CY_RTC_WRITE_DISABLED);
685 }
686 Cy_SysLib_ExitCriticalSection(interruptState);
687 }
688
689 return(retVal);
690 }
691
692
693 /*******************************************************************************
694 * Function Name: Cy_RTC_SetHoursFormat
695 ****************************************************************************//**
696 *
697 * Sets the 12/24-hour mode.
698 *
699 * \param hoursFormat
700 * The current hour format, see \ref cy_en_rtc_hours_format_t.
701 *
702 * \return
703 * A validation check result of RTC register update. See \ref cy_en_rtc_status_t.
704 *
705 *******************************************************************************/
Cy_RTC_SetHoursFormat(cy_en_rtc_hours_format_t hoursFormat)706 cy_en_rtc_status_t Cy_RTC_SetHoursFormat(cy_en_rtc_hours_format_t hoursFormat)
707 {
708 uint32_t curTime;
709 cy_en_rtc_status_t retVal = CY_RTC_BAD_PARAM;
710
711 CY_ASSERT_L3(CY_RTC_IS_HRS_FORMAT_VALID(hoursFormat));
712
713 /* Read the current time to validate the input parameters */
714 Cy_RTC_SyncFromRtc();
715 curTime = BACKUP_RTC_TIME;
716
717 /* Hour format can be changed in condition that current hour format is not
718 * the same as requested in function argument
719 */
720 if (hoursFormat != Cy_RTC_GetHoursFormat())
721 {
722 uint32_t hourValue;
723
724 /* Convert the current hour value from 24H into the 12H format */
725 if (hoursFormat == CY_RTC_12_HOURS)
726 {
727 hourValue = CONVERT_BCD_TO_DEC(_FLD2VAL(BACKUP_RTC_TIME_RTC_HOUR, curTime));
728 if (hourValue >= CY_RTC_HOURS_PER_HALF_DAY)
729 {
730 /* The current hour is more than 12 or equal 12 in the 24-hour
731 * mode. Set the PM bit and convert the hour: hour = hour - 12.
732 */
733 hourValue = (uint32_t) (hourValue - CY_RTC_HOURS_PER_HALF_DAY);
734 hourValue = ((0U != hourValue) ? hourValue : CY_RTC_HOURS_PER_HALF_DAY);
735
736 curTime = (_CLR_SET_FLD32U(curTime, BACKUP_RTC_TIME_RTC_HOUR, CONVERT_DEC_TO_BCD(hourValue)));
737 curTime |= CY_RTC_BACKUP_RTC_TIME_RTC_PM;
738 }
739 else if (hourValue < 1U)
740 {
741 /* The current hour in the 24-hour mode is 0 which is equal
742 * to 12:00 AM
743 */
744 curTime =
745 (_CLR_SET_FLD32U(curTime, BACKUP_RTC_TIME_RTC_HOUR,
746 CONVERT_DEC_TO_BCD(CY_RTC_HOURS_PER_HALF_DAY)));
747 /* Set the AM bit */
748 curTime &= ((uint32_t) ~CY_RTC_BACKUP_RTC_TIME_RTC_PM);
749 }
750 else
751 {
752 /* The current hour is less than 12 */
753 curTime = (_CLR_SET_FLD32U(curTime, BACKUP_RTC_TIME_RTC_HOUR, CONVERT_DEC_TO_BCD(hourValue)));
754 curTime &= ((uint32_t) ~CY_RTC_BACKUP_RTC_TIME_RTC_PM);
755 }
756
757 curTime |= BACKUP_RTC_TIME_CTRL_12HR_Msk;
758 }
759 /* Convert the hour value into 24H format value */
760 else
761 {
762 /* Mask the AM/PM bit as the hour value is in [20:16] bits */
763 hourValue =
764 CONVERT_BCD_TO_DEC(_FLD2VAL(BACKUP_RTC_TIME_RTC_HOUR,
765 (curTime & (uint32_t) ~CY_RTC_BACKUP_RTC_TIME_RTC_PM)));
766 /* Add 12 hours in condition that current time is in PM period */
767 if ((hourValue < CY_RTC_HOURS_PER_HALF_DAY) && (0U != (curTime & CY_RTC_BACKUP_RTC_TIME_RTC_PM)))
768 {
769 hourValue += CY_RTC_HOURS_PER_HALF_DAY;
770 }
771
772 /* Current hour is 12 AM which is equal to zero hour in 24-hour format */
773 if ((hourValue == CY_RTC_HOURS_PER_HALF_DAY) && (0U == (curTime & CY_RTC_BACKUP_RTC_TIME_RTC_PM)))
774 {
775 hourValue = 0U;
776 }
777
778 curTime = (_CLR_SET_FLD32U(curTime, BACKUP_RTC_TIME_RTC_HOUR, CONVERT_DEC_TO_BCD(hourValue)));
779 curTime &= (uint32_t) ~BACKUP_RTC_TIME_CTRL_12HR_Msk;
780 }
781
782 /* Writing corrected hour value and hour format bit into the RTC AHB
783 * register. The RTC AHB register can be updated only under condition
784 * that the Write bit is set and the RTC busy bit is cleared
785 * (CY_RTC_BUSY = 0).
786 */
787 uint32_t interruptState;
788
789 interruptState = Cy_SysLib_EnterCriticalSection();
790 retVal = Cy_RTC_WriteEnable(CY_RTC_WRITE_ENABLED);
791 if (retVal == CY_RTC_SUCCESS)
792 {
793 BACKUP_RTC_TIME = curTime;
794 /* Clear the RTC Write bit to finish RTC register update */
795 retVal = Cy_RTC_WriteEnable(CY_RTC_WRITE_DISABLED);
796 }
797 Cy_SysLib_ExitCriticalSection(interruptState);
798 }
799 return(retVal);
800 }
801
802 #if defined (CY_IP_MXS40SRSS_RTC)
803
804 /*******************************************************************************
805 * Function Name: Cy_RTC_SelectFrequencyPrescaler()
806 ****************************************************************************//**
807 *
808 * Selects the RTC pre-scaler value and changes its clock frequency.
809 * If the external 32.768 kHz WCO is absent on the board, the RTC can
810 * be driven by a 32.768kHz square clock source or an external 50-Hz or 60-Hz
811 * sine-wave clock source, for example the wall AC frequency.
812 *
813 * \param clkSel clock frequency, see \ref cy_en_rtc_clock_freq_t.
814 *
815 * In addition to generating the 32.768 kHz clock from external crystals, the WCO
816 * can be sourced by an external clock source (50 Hz or 60Hz), even the wall AC
817 * frequency as a timebase. The API helps select between the RTC sources:
818 * * A 32.768 kHz digital clock source.
819 * * An external 50-Hz or 60-Hz sine-wave clock source.
820 *
821 * If you want to use an external 50-Hz or 60-Hz sine-wave clock source to
822 * drive the RTC, the next procedure is required:
823 * -# Disable the WCO <br>
824 * -# Bypass the WCO using the Cy_SysClk_WcoBypass() function.
825 * -# Configure both wco_out and wco_in pins. Note that only one of the wco pins
826 * should be driven and the other wco pin should be floating, which depends on
827 * the source that drives the RTC (*1).
828 * -# Call Cy_RTC_SelectFrequencyPrescaler(CY_RTC_FREQ_60_HZ), if you want to
829 * drive the WCO, for example, with a 60 Hz source.
830 * -# Enable the WCO.
831 *
832 * If you want to use the WCO after using an external 50-Hz or 60-Hz sine-wave
833 * clock source:
834 * -# Disable the WCO.
835 * -# Switch-off the WCO bypass using the Cy_SysClk_WcoBypass() function.
836 * -# Drive off the wco pin with an external signal source.
837 * -# Call Cy_RTC_SelectFrequencyPrescaler(CY_RTC_FREQ_WCO_32768_HZ).
838 * -# Enable the WCO.
839 *
840 * (1) - Refer to the device TRM to know how to configure the wco pins properly
841 * and which wco pin should be driven/floating.
842 *
843 * \warning
844 * There is a limitation to the external clock source frequencies. Only two
845 * frequencies are allowed - 50 Hz or 60 Hz. Note that this limitation is related
846 * to the RTC pre-scaling feature presented in this function. This
847 * limitation is not related to WCO external clock sources which can drive the
848 * WCO in Bypass mode.
849 *
850 * \note
851 * This API is available for CAT1A devices.
852 *
853 *******************************************************************************/
Cy_RTC_SelectFrequencyPrescaler(cy_en_rtc_clock_freq_t clkSel)854 void Cy_RTC_SelectFrequencyPrescaler(cy_en_rtc_clock_freq_t clkSel)
855 {
856 CY_ASSERT_L3(CY_RTC_IS_CLK_VALID(clkSel));
857
858 BACKUP_CTL = (_CLR_SET_FLD32U(BACKUP_CTL, BACKUP_CTL_PRESCALER, (uint32_t) clkSel));
859 }
860 #endif /* CY_IP_MXS40SRSS_RTC */
861
862 /*******************************************************************************
863 * Function Name: Cy_RTC_SelectClockSource()
864 ****************************************************************************//**
865 * \param clkSel Source clock, see \ref cy_rtc_clk_select_sources_t
866 * Selects the source clock for RTC.
867 *
868 * \note
869 * This API is available for CAT1B devices.
870 *
871 *******************************************************************************/
Cy_RTC_SelectClockSource(cy_rtc_clk_select_sources_t clkSel)872 void Cy_RTC_SelectClockSource(cy_rtc_clk_select_sources_t clkSel)
873 {
874 CY_ASSERT_L3(CY_RTC_IS_SRC_CLK_SELECT_VALID(clkSel));
875
876 BACKUP_CTL = (_CLR_SET_FLD32U(BACKUP_CTL, BACKUP_CTL_CLK_SEL, (uint32_t) clkSel));
877 }
878
879 /*******************************************************************************
880 * Function Name: Cy_RTC_EnableDstTime
881 ****************************************************************************//**
882 *
883 * The function sets the DST time and configures the ALARM2 interrupt register
884 * with the appropriate DST time. This function sets the DST stop time if the
885 * current time is already in the DST period. The DST period is a period of time
886 * between the DST start time and DST stop time. The DST start time and DST stop
887 * time is presented in the DST configuration structure,
888 * see \ref cy_stc_rtc_dst_t.
889 *
890 * \param dstTime
891 * The DST configuration structure, see \ref cy_stc_rtc_dst_t.
892 *
893 * \param timeDate
894 * The time and date structure. The the appropriate DST time is
895 * set based on this time and date, see \ref cy_stc_rtc_config_t.
896 *
897 * \return
898 * cy_en_rtc_status_t A validation check result of RTC register update.
899 *
900 *******************************************************************************/
Cy_RTC_EnableDstTime(cy_stc_rtc_dst_t const * dstTime,cy_stc_rtc_config_t const * timeDate)901 cy_en_rtc_status_t Cy_RTC_EnableDstTime(cy_stc_rtc_dst_t const *dstTime, cy_stc_rtc_config_t const *timeDate)
902 {
903 cy_en_rtc_status_t retVal = CY_RTC_BAD_PARAM;
904
905 if ((NULL != dstTime) && (NULL != timeDate))
906 {
907 if (Cy_RTC_GetDstStatus(dstTime, timeDate))
908 {
909 retVal = Cy_RTC_SetNextDstTime(&dstTime->stopDst);
910 }
911 else
912 {
913 retVal = Cy_RTC_SetNextDstTime(&dstTime->startDst);
914 }
915
916 Cy_RTC_SetInterruptMask(CY_RTC_INTR_ALARM2);
917 }
918
919 return (retVal);
920 }
921
922
923 /*******************************************************************************
924 * Function Name: Cy_RTC_SetNextDstTime
925 ****************************************************************************//**
926 *
927 * A low-level DST function sets ALARM2 for a next DST event.
928 * If Cy_RTC_GetDSTStatus() is true(=1), the next DST event should be
929 * the DST stop, then this function should be called with the DST stop time.
930 * Used by the \ref Cy_RTC_EnableDstTime and \ref Cy_RTC_DstInterrupt functions.
931 *
932 * If the time format(.format) is relative option(=0), the
933 * RelativeToFixed() is called to convert to a fixed date.
934 *
935 * \param nextDst
936 * The structure with time at which a next DST event should occur
937 * (ALARM2 interrupt should occur). See \ref cy_stc_rtc_config_t.
938 *
939 * \return
940 * A validation check result of RTC register update. See \ref cy_en_rtc_status_t.
941 *
942 *******************************************************************************/
Cy_RTC_SetNextDstTime(cy_stc_rtc_dst_format_t const * nextDst)943 cy_en_rtc_status_t Cy_RTC_SetNextDstTime(cy_stc_rtc_dst_format_t const *nextDst)
944 {
945 cy_en_rtc_status_t retVal = CY_RTC_BAD_PARAM;
946
947 if (NULL != nextDst)
948 {
949 CY_ASSERT_L3(CY_RTC_IS_DST_FORMAT_VALID(nextDst->format));
950 uint32_t tryesToSetup = CY_RTC_TRYES_TO_SETUP_DST;
951 cy_stc_rtc_alarm_t dstAlarmTimeAndDate;
952
953 /* Configure an alarm structure based on the DST structure */
954 dstAlarmTimeAndDate.sec = 0U;
955 dstAlarmTimeAndDate.secEn = CY_RTC_ALARM_ENABLE;
956 dstAlarmTimeAndDate.min = 0U;
957 dstAlarmTimeAndDate.minEn = CY_RTC_ALARM_ENABLE;
958 dstAlarmTimeAndDate.hour = nextDst->hour;
959 dstAlarmTimeAndDate.hourEn = CY_RTC_ALARM_ENABLE;
960 dstAlarmTimeAndDate.dayOfWeek = nextDst->dayOfWeek;
961 dstAlarmTimeAndDate.dayOfWeekEn = CY_RTC_ALARM_DISABLE;
962
963 /* Calculate a day-of-month value for the relative DST start structure */
964 if (CY_RTC_DST_FIXED != nextDst->format)
965 {
966 dstAlarmTimeAndDate.date = RelativeToFixed(nextDst);
967 }
968 else
969 {
970 dstAlarmTimeAndDate.date = nextDst->dayOfMonth;
971 }
972 dstAlarmTimeAndDate.dateEn = CY_RTC_ALARM_ENABLE;
973 dstAlarmTimeAndDate.month = nextDst->month;
974 dstAlarmTimeAndDate.monthEn = CY_RTC_ALARM_ENABLE;
975 dstAlarmTimeAndDate.almEn = CY_RTC_ALARM_ENABLE;
976
977 while((retVal != CY_RTC_SUCCESS) && (0U != tryesToSetup))
978 {
979 retVal = Cy_RTC_SetAlarmDateAndTime(&dstAlarmTimeAndDate, CY_RTC_ALARM_2);
980 --tryesToSetup;
981
982 /* Delay after try to set the DST */
983 Cy_SysLib_DelayUs(CY_RTC_DELAY_AFTER_DST_US);
984 }
985
986 if (tryesToSetup == 0U)
987 {
988 retVal = CY_RTC_TIMEOUT;
989 }
990 }
991
992 return (retVal);
993 }
994
995
996 /*******************************************************************************
997 * Function Name: Cy_RTC_GetDstStatus
998 ****************************************************************************//**
999 *
1000 * A low-level DST function returns the current DST status using given time
1001 * information. This function is used in the initial state of a system.
1002 * If the DST is enabled, the system sets the DST start or stop as a result of
1003 * this function.
1004 * Used by the \ref Cy_RTC_EnableDstTime and \ref Cy_RTC_DstInterrupt functions.
1005 *
1006 * \param dstTime The DST configuration structure, see \ref cy_stc_rtc_dst_t.
1007 *
1008 * \param timeDate
1009 * The time and date structure. The the appropriate DST time is
1010 * set based on this time and date, see \ref cy_stc_rtc_config_t.
1011 *
1012 * \return
1013 * False - The current date and time is out of the DST period.
1014 * True - The current date and time is in the DST period.
1015 *
1016 *******************************************************************************/
Cy_RTC_GetDstStatus(cy_stc_rtc_dst_t const * dstTime,cy_stc_rtc_config_t const * timeDate)1017 bool Cy_RTC_GetDstStatus(cy_stc_rtc_dst_t const *dstTime, cy_stc_rtc_config_t const *timeDate)
1018 {
1019 uint32_t dstStartTime;
1020 uint32_t currentTime;
1021 uint32_t dstStopTime;
1022 uint32_t dstStartDayOfMonth;
1023 uint32_t dstStopDayOfMonth;
1024 bool status = false;
1025
1026 CY_ASSERT_L1(NULL != dstTime);
1027 CY_ASSERT_L1(NULL != timeDate);
1028
1029 /* Calculate a day-of-month value for the relative DST start structure */
1030 if (CY_RTC_DST_RELATIVE != dstTime->startDst.format)
1031 {
1032 dstStartDayOfMonth = dstTime->startDst.dayOfMonth;
1033 }
1034 else
1035 {
1036 dstStartDayOfMonth = RelativeToFixed(&dstTime->startDst);
1037 }
1038
1039 /* Calculate the day of a month value for the relative DST stop structure */
1040 if (CY_RTC_DST_RELATIVE != dstTime->stopDst.format)
1041 {
1042 dstStopDayOfMonth = dstTime->stopDst.dayOfMonth;
1043 }
1044 else
1045 {
1046 dstStopDayOfMonth = RelativeToFixed(&dstTime->stopDst);
1047 }
1048
1049 /* The function forms the date and time values for the DST start time,
1050 * the DST Stop Time and for the Current Time. The function that compares
1051 * the three formed values returns "true" under condition that:
1052 * dstStartTime < currentTime < dstStopTime.
1053 * The date and time value are formed this way:
1054 * [13-10] - Month
1055 * [9-5] - Day of Month
1056 * [0-4] - Hour
1057 */
1058 dstStartTime = ((uint32_t) (dstTime->startDst.month << CY_RTC_DST_MONTH_POSITION) |
1059 (dstStartDayOfMonth << CY_RTC_DST_DAY_OF_MONTH_POSITION) | (dstTime->startDst.hour));
1060
1061 currentTime = ((uint32_t) (timeDate->month << CY_RTC_DST_MONTH_POSITION) |
1062 (timeDate->date << CY_RTC_DST_DAY_OF_MONTH_POSITION) | (timeDate->hour));
1063
1064 dstStopTime = ((uint32_t) (dstTime->stopDst.month << CY_RTC_DST_MONTH_POSITION) |
1065 (dstStopDayOfMonth << CY_RTC_DST_DAY_OF_MONTH_POSITION) | (dstTime->stopDst.hour));
1066
1067 if ((dstStartTime <= currentTime) && (dstStopTime > currentTime))
1068 {
1069 status = true;
1070
1071 if (1UL == (dstStopTime - currentTime)) /* Check for the 'an hour before/after stop DST event' period */
1072 {
1073 cy_stc_rtc_alarm_t alarm;
1074 uint32_t locDate = (CY_RTC_DST_FIXED != dstTime->startDst.format) ? RelativeToFixed(&dstTime->startDst) : dstTime->startDst.dayOfMonth;
1075 Cy_RTC_GetAlarmDateAndTime(&alarm, CY_RTC_ALARM_2);
1076
1077 /* If Alarm2 is set for the "Start DST" event - the "Stop DST" event is already passed: */
1078 if ((alarm.almEn == CY_RTC_ALARM_ENABLE ) &&
1079 (alarm.monthEn == CY_RTC_ALARM_ENABLE ) &&
1080 (alarm.month == dstTime->startDst.month) &&
1081 (alarm.dateEn == CY_RTC_ALARM_ENABLE ) &&
1082 (alarm.date == locDate ) &&
1083 (alarm.dayOfWeekEn == CY_RTC_ALARM_DISABLE ) &&
1084 (alarm.hourEn == CY_RTC_ALARM_ENABLE ) &&
1085 (alarm.hour == dstTime->startDst.hour ) &&
1086 (alarm.minEn == CY_RTC_ALARM_ENABLE ) &&
1087 (alarm.min == 0UL ) &&
1088 (alarm.secEn == CY_RTC_ALARM_ENABLE ) &&
1089 (alarm.sec == 0UL ))
1090 {
1091 status = false;
1092 }
1093 /* Otherwise, including the case when Alarm2 is not set at all (DST is not enabled yet) - return true. */
1094 }
1095 }
1096
1097 return (status);
1098 }
1099
1100
1101 /*******************************************************************************
1102 * Function Name: Cy_RTC_Alarm1Interrupt
1103 ****************************************************************************//**
1104 *
1105 * A blank weak interrupt handler function which indicates assert of the RTC
1106 * alarm 1 interrupt.
1107 *
1108 * Function implementation should be defined in user source code in condition
1109 * that such event handler is required. If such event is not required user
1110 * should not do any actions.
1111 *
1112 * This function is called in the general RTC interrupt handler
1113 * Cy_RTC_Interrupt() function.
1114 *
1115 *******************************************************************************/
Cy_RTC_Alarm1Interrupt(void)1116 __WEAK void Cy_RTC_Alarm1Interrupt(void)
1117 {
1118 /* weak blank function */
1119 }
1120
1121
1122 /*******************************************************************************
1123 * Function Name: Cy_RTC_Alarm2Interrupt
1124 ****************************************************************************//**
1125 *
1126 * A blank weak interrupt handler function which indicates assert of the RTC
1127 * alarm 2 interrupt.
1128 *
1129 * Function implementation should be defined in user source code in condition
1130 * that such event handler is required. If such event is not required user
1131 * should not do any actions.
1132 *
1133 * This function is called in the general RTC interrupt handler
1134 * Cy_RTC_Interrupt() function. Cy_RTC_Alarm2Interrupt() function is
1135 * ignored in Cy_RTC_Interrupt() function if DST is enabled. Refer to
1136 * Cy_RTC_Interrupt() description.
1137 *
1138 *******************************************************************************/
Cy_RTC_Alarm2Interrupt(void)1139 __WEAK void Cy_RTC_Alarm2Interrupt(void)
1140 {
1141 /* weak blank function */
1142 }
1143
1144
1145 /*******************************************************************************
1146 * Function Name: Cy_RTC_DstInterrupt
1147 ****************************************************************************//**
1148 *
1149 * This is a processing handler against the DST event. It adjusts the current
1150 * time using the DST start/stop parameters and registers the next DST event time
1151 * into the ALARM2 interrupt.
1152 *
1153 * \param dstTime The DST configuration structure, see \ref cy_stc_rtc_dst_t.
1154 *
1155 *******************************************************************************/
Cy_RTC_DstInterrupt(cy_stc_rtc_dst_t const * dstTime)1156 void Cy_RTC_DstInterrupt(cy_stc_rtc_dst_t const *dstTime)
1157 {
1158 cy_stc_rtc_config_t curDateTime;
1159
1160 Cy_RTC_GetDateAndTime(&curDateTime);
1161
1162 if (Cy_RTC_GetDstStatus(dstTime, &curDateTime))
1163 {
1164 /* Under condition that the DST start time was selected as 23:00, and
1165 * the time adjusting occurs, the other time and date values should be
1166 * corrected (day of the week, date, month and year).
1167 */
1168 if (curDateTime.hour > CY_RTC_MAX_HOURS_24H)
1169 {
1170 /* Incrementing day of the week value as hour adjusted next day of
1171 * the week and date. Correcting hour value as its incrementation
1172 * adjusted it out of valid range [0-23].
1173 */
1174 curDateTime.dayOfWeek++;
1175 curDateTime.hour = 0U;
1176
1177 /* Correct a day of the week if its incrementation adjusted it out
1178 * of valid range [1-7].
1179 */
1180 if (curDateTime.dayOfWeek > CY_RTC_SATURDAY)
1181 {
1182 curDateTime.dayOfWeek = CY_RTC_SUNDAY;
1183 }
1184
1185 curDateTime.date++;
1186
1187 /* Correct a day of a month if its incrementation adjusted it out of
1188 * the valid range [1-31]. Increment month value.
1189 */
1190 if (curDateTime.date > Cy_RTC_DaysInMonth(curDateTime.month,
1191 (curDateTime.year + CY_RTC_TWO_THOUSAND_YEARS)))
1192 {
1193 curDateTime.date = CY_RTC_FIRST_DAY_OF_MONTH;
1194 curDateTime.month++;
1195 }
1196
1197 /* Correct a month if its incrementation adjusted it out of the
1198 * valid range [1-12]. Increment year value.
1199 */
1200 if (curDateTime.month > CY_RTC_MONTHS_PER_YEAR)
1201 {
1202 curDateTime.month = CY_RTC_JANUARY;
1203 curDateTime.year++;
1204 }
1205 }
1206 else
1207 {
1208 curDateTime.hour++;
1209 }
1210
1211 (void) Cy_RTC_SetDateAndTime(&curDateTime);
1212 (void) Cy_RTC_SetNextDstTime(&dstTime->stopDst);
1213 }
1214 else
1215 {
1216 if (curDateTime.hour < 1U)
1217 {
1218 /* Decrementing day of the week time and date values as hour
1219 * adjusted next day of the week and date. Correct hour value as
1220 * its incrementation adjusted it out of valid range [0-23].
1221 */
1222 curDateTime.hour = CY_RTC_MAX_HOURS_24H;
1223 curDateTime.dayOfWeek--;
1224
1225 /* Correct a day of the week if its incrementation adjusted it out
1226 * of the valid range [1-7].
1227 */
1228 if (curDateTime.dayOfWeek < CY_RTC_SUNDAY)
1229 {
1230 curDateTime.dayOfWeek = CY_RTC_SUNDAY;
1231 }
1232
1233 curDateTime.date--;
1234
1235 /* Correct a day of a month value if its incrementation adjusted it
1236 * out of the valid range [1-31]. Decrement month value.
1237 */
1238 if (curDateTime.date < CY_RTC_FIRST_DAY_OF_MONTH)
1239 {
1240 curDateTime.date =
1241 Cy_RTC_DaysInMonth(curDateTime.month, (curDateTime.year + CY_RTC_TWO_THOUSAND_YEARS));
1242 curDateTime.month--;
1243 }
1244
1245 /* Correct a month if its increment pushed it out of the valid
1246 * range [1-12]. Decrement year value.
1247 */
1248 if (curDateTime.month < CY_RTC_JANUARY)
1249 {
1250 curDateTime.month = CY_RTC_DECEMBER;
1251 curDateTime.year--;
1252 }
1253 }
1254 else
1255 {
1256 curDateTime.hour--;
1257 }
1258
1259 (void) Cy_RTC_SetDateAndTime(&curDateTime);
1260 (void) Cy_RTC_SetNextDstTime(&dstTime->startDst);
1261 }
1262 }
1263
1264
1265 /*******************************************************************************
1266 * Function Name: Cy_RTC_CenturyInterrupt
1267 ****************************************************************************//**
1268 *
1269 * This is a weak function and it should be redefined in user source code
1270 * in condition that such event handler is required.
1271 * By calling this function, it indicates the year reached 2100. It
1272 * should add an adjustment to avoid the Y2K problem.
1273 *
1274 * Function implementation should be defined in user source code in condition
1275 * that such event handler is required. If such event is not required user
1276 * should not do any actions.
1277 *
1278 *******************************************************************************/
Cy_RTC_CenturyInterrupt(void)1279 __WEAK void Cy_RTC_CenturyInterrupt(void)
1280 {
1281 /* weak blank function */
1282 }
1283
1284
1285 /*******************************************************************************
1286 * Function Name: Cy_RTC_GetInterruptStatus
1287 ****************************************************************************//**
1288 *
1289 * Returns a status of RTC interrupt requests.
1290 *
1291 * \return
1292 * Bit mapping information, see \ref group_rtc_macros_interrupts.
1293 *
1294 *******************************************************************************/
Cy_RTC_GetInterruptStatus(void)1295 uint32_t Cy_RTC_GetInterruptStatus(void)
1296 {
1297 return(BACKUP_INTR);
1298 }
1299
1300
1301 /*******************************************************************************
1302 * Function Name: Cy_RTC_GetInterruptStatusMasked
1303 ****************************************************************************//**
1304 *
1305 * Returns an interrupt request register masked by the interrupt mask. Returns a
1306 * result of the bitwise AND operation between the corresponding interrupt
1307 * request and mask bits.
1308 *
1309 * \return
1310 * Bit mapping information, see \ref group_rtc_macros_interrupts.
1311 *
1312 *******************************************************************************/
Cy_RTC_GetInterruptStatusMasked(void)1313 uint32_t Cy_RTC_GetInterruptStatusMasked(void)
1314 {
1315 return(BACKUP_INTR_MASKED);
1316 }
1317
1318
1319 /*******************************************************************************
1320 * Function Name: Cy_RTC_GetInterruptMask
1321 ****************************************************************************//**
1322 *
1323 * Returns an interrupt mask.
1324 *
1325 * \return
1326 * Bit mapping information, see \ref group_rtc_macros_interrupts.
1327 *
1328 *******************************************************************************/
Cy_RTC_GetInterruptMask(void)1329 uint32_t Cy_RTC_GetInterruptMask(void)
1330 {
1331 return (BACKUP_INTR_MASK);
1332 }
1333
1334
1335 /*******************************************************************************
1336 * Function Name: Cy_RTC_SetInterrupt
1337 ****************************************************************************//**
1338 *
1339 * Sets a software interrupt request
1340 *
1341 * \param interruptMask
1342 * Bit mask, see \ref group_rtc_macros_interrupts.
1343 *
1344 *******************************************************************************/
Cy_RTC_SetInterrupt(uint32_t interruptMask)1345 void Cy_RTC_SetInterrupt(uint32_t interruptMask)
1346 {
1347 CY_ASSERT_L3(CY_RTC_INTR_VALID(interruptMask));
1348
1349 BACKUP_INTR_SET = interruptMask;
1350 }
1351
1352
1353 /*******************************************************************************
1354 * Function Name: Cy_RTC_ClearInterrupt
1355 ****************************************************************************//**
1356 *
1357 * Clears RTC interrupts by setting each bit.
1358 *
1359 * \param
1360 * interruptMask The bit mask of interrupts to set,
1361 * see \ref group_rtc_macros_interrupts.
1362 *
1363 *******************************************************************************/
Cy_RTC_ClearInterrupt(uint32_t interruptMask)1364 void Cy_RTC_ClearInterrupt(uint32_t interruptMask)
1365 {
1366 CY_ASSERT_L3(CY_RTC_INTR_VALID(interruptMask));
1367
1368 BACKUP_INTR = interruptMask;
1369
1370 (void) BACKUP_INTR;
1371 }
1372
1373
1374 /*******************************************************************************
1375 * Function Name: Cy_RTC_SetInterruptMask
1376 ****************************************************************************//**
1377 *
1378 * Configures which bits of the interrupt request register that triggers an
1379 * interrupt event.
1380 *
1381 * \param interruptMask
1382 * The bit mask of interrupts to set, see \ref group_rtc_macros_interrupts.
1383 *
1384 *******************************************************************************/
Cy_RTC_SetInterruptMask(uint32_t interruptMask)1385 void Cy_RTC_SetInterruptMask(uint32_t interruptMask)
1386 {
1387 CY_ASSERT_L3(CY_RTC_INTR_VALID(interruptMask));
1388
1389 BACKUP_INTR_MASK = interruptMask;
1390 }
1391
1392
1393 /*******************************************************************************
1394 * Function Name: Cy_RTC_Interrupt
1395 ****************************************************************************//**
1396 *
1397 * The interrupt handler function which should be called in user provided
1398 * RTC interrupt function.
1399 *
1400 * This is the handler of the RTC interrupt in CPU NVIC. The handler checks
1401 * which RTC interrupt was asserted and calls the respective RTC interrupt
1402 * handler functions: Cy_RTC_Alarm1Interrupt(), Cy_RTC_Alarm2Interrupt() or
1403 * Cy_RTC_DstInterrupt(), and Cy_RTC_CenturyInterrupt().
1404 *
1405 * The order of the RTC handler functions execution is incremental.
1406 * Cy_RTC_Alarm1Interrupt() is run as the first one and Cy_RTC_CenturyInterrupt()
1407 * is called as the last one.
1408 *
1409 * This function clears the RTC interrupt every time when it is called.
1410 *
1411 * Cy_RTC_DstInterrupt() function is called instead of Cy_RTC_Alarm2Interrupt()
1412 * in condition that the mode parameter is true.
1413 *
1414 * \param dstTime
1415 * The daylight saving time configuration structure, see \ref cy_stc_rtc_dst_t.
1416 *
1417 * \param mode
1418 * False - if the DST is disabled.
1419 * True - if DST is enabled.
1420 *
1421 * \note This function is required to be called in user interrupt handler.
1422 *
1423 *******************************************************************************/
Cy_RTC_Interrupt(cy_stc_rtc_dst_t const * dstTime,bool mode)1424 void Cy_RTC_Interrupt(cy_stc_rtc_dst_t const *dstTime, bool mode)
1425 {
1426 uint32_t interruptStatus;
1427 interruptStatus = Cy_RTC_GetInterruptStatusMasked();
1428
1429 Cy_RTC_ClearInterrupt(interruptStatus);
1430
1431 if (0U != (CY_RTC_INTR_ALARM1 & interruptStatus))
1432 {
1433 Cy_RTC_Alarm1Interrupt();
1434 }
1435
1436 if (0U != (CY_RTC_INTR_ALARM2 & interruptStatus))
1437 {
1438 if (mode)
1439 {
1440 Cy_RTC_DstInterrupt(dstTime);
1441 }
1442 else
1443 {
1444 Cy_RTC_Alarm2Interrupt();
1445 }
1446 }
1447
1448 if (0U != (CY_RTC_INTR_CENTURY & interruptStatus))
1449 {
1450 Cy_RTC_CenturyInterrupt();
1451 }
1452 }
1453
1454
1455 /*******************************************************************************
1456 * Function Name: Cy_RTC_DeepSleepCallback
1457 ****************************************************************************//**
1458 *
1459 * This function checks the RTC_BUSY bit to avoid data corruption before
1460 * enters the Deep Sleep mode.
1461 *
1462 * \param callbackParams
1463 * The structure with the SysPm callback parameters,
1464 * see \ref cy_stc_syspm_callback_params_t
1465 *
1466 * \param mode
1467 * Callback mode, see \ref cy_en_syspm_callback_mode_t.
1468 *
1469 * \return
1470 * The SysPm return status, see \ref cy_en_syspm_status_t.
1471 *
1472 * \note The *base and *context elements are required to be present in
1473 * the parameter structure because this function uses the SysPm driver
1474 * callback type.
1475 * The SysPm driver callback function type requires implementing the function
1476 * with next parameters and return value:
1477 *
1478 * cy_en_syspm_status_t (*Cy_SysPmCallback)
1479 * (cy_stc_syspm_callback_params_t *callbackParams, cy_en_syspm_callback_mode_t mode);
1480 *
1481 *******************************************************************************/
Cy_RTC_DeepSleepCallback(const cy_stc_syspm_callback_params_t * callbackParams,cy_en_syspm_callback_mode_t mode)1482 cy_en_syspm_status_t Cy_RTC_DeepSleepCallback(const cy_stc_syspm_callback_params_t *callbackParams, cy_en_syspm_callback_mode_t mode)
1483 {
1484 cy_en_syspm_status_t retVal = CY_SYSPM_FAIL;
1485
1486 if (callbackParams != NULL)
1487 {
1488 switch(mode)
1489 {
1490 case CY_SYSPM_CHECK_READY:
1491 {
1492 if (CY_RTC_AVAILABLE == Cy_RTC_GetSyncStatus())
1493 {
1494 retVal = CY_SYSPM_SUCCESS;
1495 }
1496 }
1497 break;
1498
1499 case CY_SYSPM_CHECK_FAIL:
1500 {
1501 retVal = CY_SYSPM_SUCCESS;
1502 }
1503 break;
1504
1505 case CY_SYSPM_BEFORE_TRANSITION:
1506 {
1507 retVal = CY_SYSPM_SUCCESS;
1508 }
1509 break;
1510
1511 case CY_SYSPM_AFTER_TRANSITION:
1512 {
1513 retVal = CY_SYSPM_SUCCESS;
1514 }
1515 break;
1516
1517 default:
1518 /* Unknown state */
1519 break;
1520 }
1521 }
1522 return (retVal);
1523 }
1524
1525
1526 /*******************************************************************************
1527 * Function Name: Cy_RTC_HibernateCallback
1528 ****************************************************************************//**
1529 *
1530 * This function checks the RTC_BUSY bit to avoid data corruption before
1531 * enters the Hibernate mode.
1532 *
1533 * \param callbackParams
1534 * structure with the syspm callback parameters,
1535 * see \ref cy_stc_syspm_callback_params_t.
1536 *
1537 * \param mode
1538 * Callback mode, see \ref cy_en_syspm_callback_mode_t
1539 *
1540 * \return
1541 * The syspm return status, see \ref cy_en_syspm_status_t
1542 *
1543 * \note The *base and *context elements are required to be present in
1544 * the parameter structure because this function uses the SysPm driver
1545 * callback type.
1546 * The SysPm driver callback function type requires implementing the function
1547 * with next parameters and return value:
1548 *
1549 * cy_en_syspm_status_t (*Cy_SysPmCallback)
1550 * (cy_stc_syspm_callback_params_t *callbackParams, cy_en_syspm_callback_mode_t mode);
1551 *
1552 *******************************************************************************/
Cy_RTC_HibernateCallback(const cy_stc_syspm_callback_params_t * callbackParams,cy_en_syspm_callback_mode_t mode)1553 cy_en_syspm_status_t Cy_RTC_HibernateCallback(const cy_stc_syspm_callback_params_t *callbackParams, cy_en_syspm_callback_mode_t mode)
1554 {
1555 return (Cy_RTC_DeepSleepCallback(callbackParams, mode));
1556 }
1557
1558
1559 /*******************************************************************************
1560 * Function Name: ConstructTimeDate
1561 ****************************************************************************//**
1562 *
1563 * Returns BCD time and BCD date in the format used in APIs from individual
1564 * elements passed.
1565 * Converted BCD time(*timeBcd) and BCD date(*dateBcd) are matched with RTC_TIME
1566 * and RTC_DATE bit fields format.
1567 *
1568 * \param timeDate
1569 * The structure of time and date, see \ref cy_stc_rtc_config_t.
1570 *
1571 * \param timeBcd
1572 * The BCD-formatted time variable which has the same bit masks as the
1573 * RTC_TIME register:
1574 *
1575 * [0:6] - Calendar seconds in BCD, the range 0-59. \n
1576 * [14:8] - Calendar minutes in BCD, the range 0-59. \n
1577 * [21:16] - Calendar hours in BCD, value depends on the 12/24-hour mode. \n
1578 * 12HR: [21]:0 = AM, 1 = PM, [20:16] = 1 - 12; \n
1579 * 24HR: [21:16] = 0-23. \n
1580 * [22] - Selects the 12/24-hour mode: 1 - 12-hour, 0 - 24-hour. \n
1581 * [26:24] - A calendar day of the week, the range 1 - 7, where 1 - Sunday. \n
1582 *
1583 * \param dateBcd
1584 * The BCD-formatted time variable which has the same bit masks as the
1585 * RTC_DATE register:
1586 *
1587 * [5:0] - A calendar day of a month in BCD, the range 1-31. \n
1588 * [12:8] - A calendar month in BCD, the range 1-12. \n
1589 * [23:16] - A calendar year in BCD, the range 0-99. \n
1590 *
1591 *******************************************************************************/
ConstructTimeDate(cy_stc_rtc_config_t const * timeDate,uint32_t * timeBcd,uint32_t * dateBcd)1592 static void ConstructTimeDate(cy_stc_rtc_config_t const *timeDate, uint32_t *timeBcd, uint32_t *dateBcd)
1593 {
1594 uint32_t tmpTime;
1595 uint32_t tmpDate;
1596
1597 /* Prepare the RTC TIME value based on the structure obtained */
1598 tmpTime = (_VAL2FLD(BACKUP_RTC_TIME_RTC_SEC, CONVERT_DEC_TO_BCD(timeDate->sec)));
1599 tmpTime |= (_VAL2FLD(BACKUP_RTC_TIME_RTC_MIN, CONVERT_DEC_TO_BCD(timeDate->min)));
1600
1601 /* Read the current hour mode to know how many hour bits to convert.
1602 * In the 24-hour mode, the hour value is presented in [21:16] bits in the
1603 * BCD format.
1604 * In the 12-hour mode, the hour value is presented in [20:16] bits in the
1605 * BCD format and bit [21] is present: 0 - AM; 1 - PM.
1606 */
1607 if (timeDate->hrFormat != CY_RTC_24_HOURS)
1608 {
1609 if (CY_RTC_AM != timeDate->amPm)
1610 {
1611 /* Set the PM bit */
1612 tmpTime |= CY_RTC_BACKUP_RTC_TIME_RTC_PM;
1613 }
1614 else
1615 {
1616 /* Set the AM bit */
1617 tmpTime &= ((uint32_t) ~CY_RTC_BACKUP_RTC_TIME_RTC_PM);
1618 }
1619 tmpTime |= BACKUP_RTC_TIME_CTRL_12HR_Msk;
1620 tmpTime |=
1621 (_VAL2FLD(BACKUP_RTC_TIME_RTC_HOUR,
1622 (CONVERT_DEC_TO_BCD(timeDate->hour) & ((uint32_t) ~CY_RTC_12HRS_PM_BIT))));
1623 }
1624 else
1625 {
1626 tmpTime &= ((uint32_t) ~BACKUP_RTC_TIME_CTRL_12HR_Msk);
1627 tmpTime |= (_VAL2FLD(BACKUP_RTC_TIME_RTC_HOUR, CONVERT_DEC_TO_BCD(timeDate->hour)));
1628 }
1629 tmpTime |= (_VAL2FLD(BACKUP_RTC_TIME_RTC_DAY, CONVERT_DEC_TO_BCD(timeDate->dayOfWeek)));
1630 /* Prepare the RTC Date value based on the structure obtained */
1631 tmpDate = (_VAL2FLD(BACKUP_RTC_DATE_RTC_DATE, CONVERT_DEC_TO_BCD(timeDate->date)));
1632 tmpDate |= (_VAL2FLD(BACKUP_RTC_DATE_RTC_MON, CONVERT_DEC_TO_BCD(timeDate->month)));
1633 tmpDate |= (_VAL2FLD(BACKUP_RTC_DATE_RTC_YEAR, CONVERT_DEC_TO_BCD(timeDate->year)));
1634 /* Update the parameter values with prepared values */
1635 *timeBcd = tmpTime;
1636 *dateBcd = tmpDate;
1637 }
1638
1639
1640 /*******************************************************************************
1641 * Function Name: ConstructAlarmTimeDate
1642 ****************************************************************************//**
1643 *
1644 * Returns the BCD time and BCD date in the format used in APIs from individual
1645 * elements passed for alarm.
1646 * Converted BCD time(*alarmTimeBcd) and BCD date(*alarmDateBcd) should be
1647 * matched with the ALMx_TIME and ALMx_DATE bit fields format.
1648 *
1649 * \param alarmDateTime
1650 * The structure of time and date, see \ref cy_stc_rtc_alarm_t.
1651 *
1652 * \param alarmTimeBcd
1653 * The BCD-formatted time variable which has the same bit masks as the
1654 * ALMx_TIME register time fields:
1655 *
1656 * [0:6] - Alarm seconds in BCD, the range 0-59. \n
1657 * [7] - Alarm seconds Enable: 0 - ignore, 1 - match. \n
1658 * [14:8] - Alarm minutes in BCD, the range 0-59. \n
1659 * [15] - Alarm minutes Enable: 0 - ignore, 1 - match. \n
1660 * [21:16] - Alarm hours in BCD, value depending on the 12/24-hour mode
1661 * (RTC_CTRL_12HR) \n
1662 * 12HR: [21]:0 = AM, 1 = PM, [20:16] = 1 - 12; \n
1663 * 24HR: [21:16] = the range 0-23. \n
1664 * [23] - Alarm hours Enable: 0 - ignore, 1 - match. \n
1665 * [26:24] - An alarm day of the week, the range 1 - 7, where 1 - Monday. \n
1666 * [31] - An alarm day of the week Enable: 0 - ignore, 1 - match. \n
1667 *
1668 * \param alarmDateBcd
1669 * The BCD-formatted date variable which has the same bit masks as the
1670 * ALMx_DATE register date fields:
1671 *
1672 * [5:0] - An alarm day of a month in BCD, the range 1-31. \n
1673 * [7] - An alarm day of a month Enable: 0 - ignore, 1 - match. \n
1674 * [12:8] - An alarm month in BCD, the range 1-12. \n
1675 * [15] - An alarm month Enable: 0 - ignore, 1 - match. \n
1676 * [31] - The Enable alarm: 0 - Alarm is disabled, 1 - Alarm is enabled. \n
1677 *
1678 * This function reads current AHB register RTC_TIME value to know hour mode.
1679 * It is recommended to call Cy_RTC_SyncFromRtc() function before calling the
1680 * ConstructAlarmTimeDate() functions.
1681 *
1682 * Construction is based on RTC_ALARM1 register bit fields.
1683 *
1684 *******************************************************************************/
ConstructAlarmTimeDate(cy_stc_rtc_alarm_t const * alarmDateTime,uint32_t * alarmTimeBcd,uint32_t * alarmDateBcd)1685 static void ConstructAlarmTimeDate(cy_stc_rtc_alarm_t const *alarmDateTime, uint32_t *alarmTimeBcd,
1686 uint32_t *alarmDateBcd)
1687 {
1688 uint32_t tmpAlarmTime;
1689 uint32_t tmpAlarmDate;
1690 uint32_t hourValue;
1691
1692 /* Prepare the RTC ALARM value based on the structure obtained */
1693 tmpAlarmTime = (_VAL2FLD(BACKUP_ALM1_TIME_ALM_SEC, CONVERT_DEC_TO_BCD(alarmDateTime->sec)));
1694 tmpAlarmTime |= (_VAL2FLD(BACKUP_ALM1_TIME_ALM_SEC_EN, alarmDateTime->secEn));
1695 tmpAlarmTime |= (_VAL2FLD(BACKUP_ALM1_TIME_ALM_MIN, CONVERT_DEC_TO_BCD(alarmDateTime->min)));
1696 tmpAlarmTime |= (_VAL2FLD(BACKUP_ALM1_TIME_ALM_MIN_EN, alarmDateTime->minEn));
1697
1698 /* Read the current hour mode to know how many hour bits to convert.
1699 * In the 24-hour mode, the hour value is presented in [21:16] bits in the
1700 * BCD format.
1701 * In the 12-hour mode, the hour value is presented in [20:16] bits in the
1702 * BCD format and bit [21] is present: 0 - AM; 1 - PM
1703 */
1704 Cy_RTC_SyncFromRtc();
1705 if (CY_RTC_24_HOURS != Cy_RTC_GetHoursFormat())
1706 {
1707 /* Convert the hour from the 24-hour mode into the 12-hour mode */
1708 if (alarmDateTime->hour >= CY_RTC_HOURS_PER_HALF_DAY)
1709 {
1710 /* The current hour is more than 12 in the 24-hour mode. Set the PM
1711 * bit and converting hour: hour = hour - 12
1712 */
1713 hourValue = (uint32_t) alarmDateTime->hour - CY_RTC_HOURS_PER_HALF_DAY;
1714 hourValue = ((0U != hourValue) ? hourValue : CY_RTC_HOURS_PER_HALF_DAY);
1715 tmpAlarmTime |=
1716 CY_RTC_BACKUP_RTC_TIME_RTC_PM | (_VAL2FLD(BACKUP_ALM1_TIME_ALM_HOUR, CONVERT_DEC_TO_BCD(hourValue)));
1717 }
1718 else if (alarmDateTime->hour < 1U)
1719 {
1720 /* The current hour in the 24-hour mode is 0 which is equal to 12:00 AM */
1721 tmpAlarmTime = (tmpAlarmTime & ((uint32_t) ~CY_RTC_BACKUP_RTC_TIME_RTC_PM)) |
1722 (_VAL2FLD(BACKUP_ALM1_TIME_ALM_HOUR, CY_RTC_HOURS_PER_HALF_DAY));
1723 }
1724 else
1725 {
1726 /* The current hour is less than 12. Set the AM bit */
1727 tmpAlarmTime = (tmpAlarmTime & ((uint32_t) ~CY_RTC_BACKUP_RTC_TIME_RTC_PM)) |
1728 (_VAL2FLD(BACKUP_ALM1_TIME_ALM_HOUR, CONVERT_DEC_TO_BCD(alarmDateTime->hour)));
1729 }
1730 tmpAlarmTime |= BACKUP_RTC_TIME_CTRL_12HR_Msk;
1731 }
1732 else
1733 {
1734 tmpAlarmTime |= (_VAL2FLD(BACKUP_ALM1_TIME_ALM_HOUR, CONVERT_DEC_TO_BCD(alarmDateTime->hour)));
1735 tmpAlarmTime &= ((uint32_t) ~BACKUP_RTC_TIME_CTRL_12HR_Msk);
1736 }
1737 tmpAlarmTime |= (_VAL2FLD(BACKUP_ALM1_TIME_ALM_HOUR_EN, alarmDateTime->hourEn));
1738 tmpAlarmTime |= (_VAL2FLD(BACKUP_ALM1_TIME_ALM_DAY, CONVERT_DEC_TO_BCD(alarmDateTime->dayOfWeek)));
1739 tmpAlarmTime |= (_VAL2FLD(BACKUP_ALM1_TIME_ALM_DAY_EN, alarmDateTime->dayOfWeekEn));
1740
1741 /* Prepare the RTC ALARM DATE value based on the obtained structure */
1742 tmpAlarmDate = (_VAL2FLD(BACKUP_ALM1_DATE_ALM_DATE, CONVERT_DEC_TO_BCD(alarmDateTime->date)));
1743 tmpAlarmDate |= (_VAL2FLD(BACKUP_ALM1_DATE_ALM_DATE_EN, alarmDateTime->dateEn));
1744 tmpAlarmDate |= (_VAL2FLD(BACKUP_ALM1_DATE_ALM_MON, CONVERT_DEC_TO_BCD(alarmDateTime->month)));
1745 tmpAlarmDate |= (_VAL2FLD(BACKUP_ALM1_DATE_ALM_MON_EN, alarmDateTime->monthEn));
1746 tmpAlarmDate |= (_VAL2FLD(BACKUP_ALM1_DATE_ALM_EN, alarmDateTime->almEn));
1747
1748 /* Update the parameter values with prepared values */
1749 *alarmTimeBcd = tmpAlarmTime;
1750 *alarmDateBcd = tmpAlarmDate;
1751 }
1752
1753
1754 /*******************************************************************************
1755 * Function Name: RelativeToFixed
1756 ****************************************************************************//**
1757 *
1758 * Converts time from a relative format to a fixed format to set the ALARM2.
1759 *
1760 * \param convertDst
1761 * The DST structure, its appropriate elements should be converted.
1762 *
1763 * \return
1764 * The current date of a month.
1765 *
1766 *******************************************************************************/
RelativeToFixed(cy_stc_rtc_dst_format_t const * convertDst)1767 static uint32_t RelativeToFixed(cy_stc_rtc_dst_format_t const *convertDst)
1768 {
1769 uint32_t currentYear;
1770 uint32_t currentDay;
1771 uint32_t currentWeek;
1772 uint32_t daysInMonth;
1773 uint32_t tmpDayOfMonth;
1774
1775 /* Read the current year */
1776 Cy_RTC_SyncFromRtc();
1777
1778 currentYear =
1779 CY_RTC_TWO_THOUSAND_YEARS + CONVERT_BCD_TO_DEC(_FLD2VAL(BACKUP_RTC_DATE_RTC_YEAR, BACKUP_RTC_DATE));
1780 currentDay = CY_RTC_FIRST_DAY_OF_MONTH;
1781 currentWeek = CY_RTC_FIRST_WEEK_OF_MONTH;
1782 daysInMonth = Cy_RTC_DaysInMonth(convertDst->month, currentYear);
1783 tmpDayOfMonth = currentDay;
1784
1785 while((currentWeek <= convertDst->weekOfMonth) && (currentDay <= daysInMonth))
1786 {
1787 if (convertDst->dayOfWeek == Cy_RTC_ConvertDayOfWeek(currentDay, convertDst->month, currentYear))
1788 {
1789 tmpDayOfMonth = currentDay;
1790 currentWeek++;
1791 }
1792 currentDay++;
1793 }
1794 return(tmpDayOfMonth);
1795 }
1796
1797 #if defined(__cplusplus)
1798 }
1799 #endif
1800
1801 CY_MISRA_BLOCK_END('MISRA C-2012 Rule 2.2');
1802 #endif /* CY_IP_MXS40SRSS_RTC, CY_IP_MXS28SRSS, CY_IP_MXS40SSRSS */
1803
1804 /* [] END OF FILE */
1805