1 /***************************************************************************//**
2 * \file cyhal_rtc.h
3 *
4 * \brief
5 * Provides a high level interface for interacting with the Real Time Clock on
6 * Cypress devices.  This interface abstracts out the chip specific details.
7 * If any chip specific functionality is necessary, or performance is critical
8 * the low level functions can be used directly.
9 *
10 ********************************************************************************
11 * \copyright
12 * Copyright 2018-2022 Cypress Semiconductor Corporation (an Infineon company) or
13 * an affiliate of Cypress Semiconductor Corporation
14 *
15 * SPDX-License-Identifier: Apache-2.0
16 *
17 * Licensed under the Apache License, Version 2.0 (the "License");
18 * you may not use this file except in compliance with the License.
19 * You may obtain a copy of the License at
20 *
21 *     http://www.apache.org/licenses/LICENSE-2.0
22 *
23 * Unless required by applicable law or agreed to in writing, software
24 * distributed under the License is distributed on an "AS IS" BASIS,
25 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
26 * See the License for the specific language governing permissions and
27 * limitations under the License.
28 *******************************************************************************/
29 
30 /**
31 * \addtogroup group_hal_rtc RTC (Real-Time Clock)
32 * \ingroup group_hal
33 * \{
34 * High level interface for interacting with the real-time clock (RTC).
35 *
36 * The real time clock provides tracking of the current time and date, as
37 * well as the ability to trigger a callback at a specific time in the future.
38 *
39 * \section section_rtc_features Features
40 * * Configurable interrupt and callback assignment on RTC event \ref cyhal_rtc_event_t
41 * * Set alarm for a specific time and date \ref cyhal_rtc_set_alarm
42 * * Daylight Savings Time adjustment
43 *
44 * \section section_rtc_quickstart Quick Start
45 *
46 * Initialise the RTC using \ref cyhal_rtc_init. Set the current time and date using \ref cyhal_rtc_write. <br>
47 * See \ref subsection_rtc_snippet_1 to initialize RTC, read and write current date and time to the RTC peripheral.
48 * See \ref subsection_rtc_snippet_2 to set an alarm event on a specific time and date.
49 *
50 * \section section_rtc_snippets Code snippets
51 * \subsection subsection_rtc_snippet_1 Snippet 1: Initialize RTC, write and read current time and date
52 * The following code snippet initialises the RTC using the \ref cyhal_rtc_init. The current date and time are set using \ref cyhal_rtc_write.
53 * The current date and time is read from the RTC using \ref cyhal_rtc_read. The time structure <b> tm </b>, contains the calendar date and time which
54 * are broken down into its components. This structure is declared in standard C library time.h which is included by HAL.
55 * \snippet hal_rtc.c snippet_cyhal_rtc_read_write_data_time
56 *
57 * \subsection subsection_rtc_snippet_2 Snippet 2: RTC Alarm using Callbacks
58 *  The following code snippet configures the RTC to trigger an alarm event on a specified date and time using \ref cyhal_rtc_set_alarm.
59 *  A callback is registered to handle the alarm event using \ref cyhal_rtc_register_callback.
60 * \snippet hal_rtc.c snippet_cyhal_set_alarm_callback
61 */
62 
63 #pragma once
64 
65 #include <stdint.h>
66 #include <stdbool.h>
67 #include <time.h>
68 #include "cy_result.h"
69 #include "cyhal_hw_types.h"
70 
71 #if defined(__cplusplus)
72 extern "C" {
73 #endif
74 
75 /** \addtogroup group_hal_results_rtc RTC HAL Results
76  *  RTC specific return codes
77  *  \ingroup group_hal_results
78  *  \{ *//**
79  */
80 
81 /** RTC not initialized */
82 #define CY_RSLT_RTC_NOT_INITIALIZED                     \
83     (CY_RSLT_CREATE_EX(CY_RSLT_TYPE_ERROR, CY_RSLT_MODULE_ABSTRACTION_HAL, CYHAL_RSLT_MODULE_RTC, 0))
84 /** Bad argument */
85 #define CY_RSLT_RTC_BAD_ARGUMENT                        \
86     (CY_RSLT_CREATE_EX(CY_RSLT_TYPE_ERROR, CY_RSLT_MODULE_ABSTRACTION_HAL, CYHAL_RSLT_MODULE_RTC, 1))
87 /** Unsupported feature */
88 #define CYHAL_RTC_RSLT_ERR_NOT_SUPPORTED      \
89     (CY_RSLT_CREATE_EX(CY_RSLT_TYPE_ERROR, CY_RSLT_MODULE_ABSTRACTION_HAL, CYHAL_RSLT_MODULE_RTC, 2))
90 
91 /**
92  * \}
93  */
94 
95 /** RTC interrupt triggers */
96 typedef enum {
97     CYHAL_RTC_ALARM, /**< Alarm triggered event */
98 } cyhal_rtc_event_t;
99 
100 /** @brief Defines which fields should be active for the alarm. */
101 typedef struct
102 {
103     uint8_t en_sec : 1; /**< Enable match of seconds */
104     uint8_t en_min : 1; /**< Enable match of minutes */
105     uint8_t en_hour : 1; /**< Enable match of hours */
106     uint8_t en_day : 1; /**< Enable match of day of week */
107     uint8_t en_date : 1; /**< Enable match of date in month */
108     uint8_t en_month : 1; /**< Enable match of month */
109 } cyhal_alarm_active_t;
110 
111 /** Enumeration used to configure the DST format
112  *
113  * \note In areas of the world that practice DST, when it should begin and end is not unique. It
114  * can either be in fixed DST format or in relative DST format.
115  */
116 typedef enum
117 {
118     CYHAL_RTC_DST_RELATIVE,        /**< Relative DST format. eg: Begins on the last Sunday of March
119                                     and ends on the last Sunday of October. */
120     CYHAL_RTC_DST_FIXED            /**< Fixed DST format. eg: Begins on 21st March
121                                     and ends on 21st September. */
122 } cyhal_rtc_dst_format_t;
123 
124 /**
125 * Day Light Savings Time (DST) structure for setting when to apply. It allows to
126 * set the DST time and date using a fixed or relative time format.
127 */
128 typedef struct
129 {
130     cyhal_rtc_dst_format_t format;   /**< DST format. See /ref cyhal_rtc_dst_format_t.
131                                           Based on this value other structure elements
132                                           should be filled or could be ignored */
133     uint32_t hour;                   /**< Hour in 24hour format, range[0-23] */
134     union
135     {
136         uint32_t dayOfMonth;         /**< Day of Month, range[1-31]. */
137         struct /* format = CYHAL_RTC_DST_FIXED */
138         {
139             uint32_t dayOfWeek;      /**< Day of the week, starting on Sunday, range[0-6] */
140             uint32_t weekOfMonth;    /**< Week of month, range[0-5]. Where 5 => Last week of month */
141         };                           /**< Anonymous struct specifying the week number plus day of week */
142     };                               /**< Anonymous union for the day as either a specific day (dayOfMonth)
143                                           or as a week number (weekOfMonth) plus day of week (dayOfWeek) */
144     uint32_t month;                  /**< Month value, range[1-12]. */
145 } cyhal_rtc_dst_t;
146 
147 /** Handler for RTC events (eg: alarm) */
148 typedef void (*cyhal_rtc_event_callback_t)(void *callback_arg, cyhal_rtc_event_t event);
149 
150 /** Initialize the RTC peripheral
151  *
152  * Power up the RTC in preparation for access. This function must be called
153  * before any other RTC functions are called. This does not change the state
154  * of the RTC. It just enables access to it.
155  * @note Before calling this, make sure all necessary System Clocks are setup
156  * correctly. Generally this means making sure the RTC has access to a crystal
157  * oscillator for optimal accuracy and operation in low power.
158  * @note Previously set time configurations are retained. This will only reset
159  * the time if no prior configuration can be determined.
160  *
161  * @param[out] obj  Pointer to an RTC object. The caller must allocate the memory
162  *  for this object but the init function will initialize its contents.
163  * @return The status of the init request
164  */
165 cy_rslt_t cyhal_rtc_init(cyhal_rtc_t *obj);
166 
167 /** Initialize the RTC peripheral using a configurator generated configuration struct
168  *
169  * Power up the RTC in preparation for access. This function must be called
170  * before any other RTC functions are called. This does not change the state
171  * of the RTC. It just enables access to it.
172  * NOTE: Before calling this, make sure all necessary System Clocks are setup
173  * correctly. Generally this means making sure the RTC has access to a crystal
174  * oscillator for optimal accuracy and operation in low power.
175  * NOTE: Previously set time configurations are retained. This will only reset
176  * the time if no prior configuration can be determined.
177  *
178  * @param[out] obj  Pointer to an RTC object. The caller must allocate the memory
179  *  for this object but the init function will initialize its contents.
180  * @param[in] cfg   Configuration structure generated by a configurator.
181  * @return The status of the init request
182  */
183 cy_rslt_t cyhal_rtc_init_cfg(cyhal_rtc_t *obj, const cyhal_rtc_configurator_t *cfg);
184 
185 /** Deinitialize RTC
186  *
187  * Frees resources associated with the RTC and disables CPU access. This
188  * only affects the CPU domain and not the time keeping logic.
189  * After this function is called no other RTC functions should be called
190  * except for rtc_init.
191  *
192  * @param[in,out] obj RTC object
193  */
194 void cyhal_rtc_free(cyhal_rtc_t *obj);
195 
196 /** Check if the RTC has the time set and is counting
197  *
198  * @param[in] obj RTC object
199  * @return Whether the RTC is enabled or not
200  */
201 bool cyhal_rtc_is_enabled(cyhal_rtc_t *obj);
202 
203 /** Get the current time and date from the RTC peripheral
204  *
205  * @param[in]  obj RTC object
206  * @param[out] time The current time (see: https://en.cppreference.com/w/cpp/chrono/c/tm)
207  * @return The status of the read request
208  */
209 cy_rslt_t cyhal_rtc_read(cyhal_rtc_t *obj, struct tm *time);
210 
211 /** Write the specified time and date to the RTC peripheral
212  *
213  * @param[in] obj  RTC object
214  * @param[in] time The time to be set (see: https://en.cppreference.com/w/cpp/chrono/c/tm)
215  * @return The status of the write request
216  */
217 cy_rslt_t cyhal_rtc_write(cyhal_rtc_t *obj, const struct tm *time);
218 
219 /** Write the specified time and date values to the RTC peripheral
220   * @param[in] obj   RTC object
221   * @param[in] sec   Second to set (0-59)
222   * @param[in] min   Minute to set (0-59)
223   * @param[in] hour  Hour to set (0-23)
224   * @param[in] day   Day of month to set (1-31)
225   * @param[in] month Month to set (1-12)
226   * @param[in] year  4-digit year to set
227   * @return The status of the write request
228   */
229 cy_rslt_t cyhal_rtc_write_direct(cyhal_rtc_t *obj, uint32_t sec, uint32_t min, uint32_t hour,
230                                  uint32_t day, uint32_t month, uint32_t year);
231 
232 /** Set the start and end time for Day Light Savings
233  *
234  * Calling this function will allow alarms to account for daylight saving time.
235  * This means that the RTC will be adjusted when a daylight saving time
236  * transition occurs, meaning times passed to \ref cyhal_rtc_set_alarm()
237  * will be interpreted as being in DST/not in DST as appropriate.
238  *
239  * @param[in] obj  RTC object
240  * @param[in] start When Day Light Savings time should start
241  * @param[in] stop When Day Light Savings time should end
242  * @return The status of the set_dst request
243  */
244 cy_rslt_t cyhal_rtc_set_dst(cyhal_rtc_t *obj, const cyhal_rtc_dst_t *start, const cyhal_rtc_dst_t *stop);
245 
246 /** Checks to see if Day Light Savings Time is currently active. This should only be called after
247  * \ref cyhal_rtc_set_dst().
248  *
249  * @param[in] obj  RTC object
250  * @return Boolean indicating whether the current date/time is within the specified DST start/stop window.
251  */
252 bool cyhal_rtc_is_dst(cyhal_rtc_t *obj);
253 
254 /** Set an alarm (interrupt) for the specified time and date using the RTC peripheral
255  *
256  * This requires that a callback handler is registered by \ref cyhal_rtc_register_callback and that
257  * the \ref CYHAL_RTC_ALARM event is enabled by \ref cyhal_rtc_enable_event.
258  *
259  * @param[in] obj    RTC object
260  * @param[in] time   The alarm time to be set (see: https://en.cppreference.com/w/cpp/chrono/c/tm)
261  * @param[in] active The set of fields that are checked to trigger the alarm
262  * @return The status of the set_alarm request
263  */
264 cy_rslt_t cyhal_rtc_set_alarm(cyhal_rtc_t *obj, const struct tm *time, cyhal_alarm_active_t active);
265 
266 /** Set an alarm (interrupt) at a specified number of seconds in the future
267  *
268  * This requires that a callback handler is registered by \ref cyhal_rtc_register_callback and that
269  * the \ref CYHAL_RTC_ALARM event is enabled by \ref cyhal_rtc_enable_event.
270  *
271  * @param[in] obj     RTC object
272  * @param[in] seconds The number of seconds in the future for the alarm to be
273  * set to. Because alarms cannot match the year (see \ref cyhal_alarm_active_t)
274  * the maximum number of seconds allowed is 365d*24h*60m*60s == 31,536,000s
275  * @return The status of the set_alarm_by_seconds request
276  */
277 cy_rslt_t cyhal_rtc_set_alarm_by_seconds(cyhal_rtc_t *obj, const uint32_t seconds);
278 
279 /** Register a RTC event callback handler
280  *
281  * This function will be called when one of the events enabled by \ref cyhal_rtc_enable_event occurs.
282  *
283  * @param[in] obj          The RTC object
284  * @param[in] callback     The callback handler which will be invoked when the alarm event fires
285  * @param[in] callback_arg Generic argument that will be provided to the callback when called
286  */
287 void cyhal_rtc_register_callback(cyhal_rtc_t *obj, cyhal_rtc_event_callback_t callback, void *callback_arg);
288 
289 /** Configure RTC event (eg: alarm) enablement.
290  *
291  * When an enabled event occurs, the function specified by \ref cyhal_rtc_register_callback will be called.
292  *
293  * @param[in] obj            The RTC object
294  * @param[in] event          The RTC event type
295  * @param[in] intr_priority  The priority for NVIC interrupt events
296  * @param[in] enable         True to turn on interrupts, False to turn off
297  */
298 void cyhal_rtc_enable_event(cyhal_rtc_t *obj, cyhal_rtc_event_t event, uint8_t intr_priority, bool enable);
299 
300 #if defined(__cplusplus)
301 }
302 #endif
303 
304 #ifdef CYHAL_RTC_IMPL_HEADER
305 #include CYHAL_RTC_IMPL_HEADER
306 #endif /* CYHAL_RTC_IMPL_HEADER */
307 
308 /** \} group_hal_rtc */
309