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