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