1 /***************************************************************************//**
2  * @file
3  * @brief DCDC Coulomb Counter (DCDC_COULOMB_COUNTER) peripheral API
4  *******************************************************************************
5  * # License
6  * <b>Copyright 2024 Silicon Laboratories Inc. www.silabs.com</b>
7  *******************************************************************************
8  *
9  * SPDX-License-Identifier: Zlib
10  *
11  * The licensor of this software is Silicon Laboratories Inc.
12  *
13  * This software is provided 'as-is', without any express or implied
14  * warranty. In no event will the authors be held liable for any damages
15  * arising from the use of this software.
16  *
17  * Permission is granted to anyone to use this software for any purpose,
18  * including commercial applications, and to alter it and redistribute it
19  * freely, subject to the following restrictions:
20  *
21  * 1. The origin of this software must not be misrepresented; you must not
22  *    claim that you wrote the original software. If you use this software
23  *    in a product, an acknowledgment in the product documentation would be
24  *    appreciated but is not required.
25  * 2. Altered source versions must be plainly marked as such, and must not be
26  *    misrepresented as being the original software.
27  * 3. This notice may not be removed or altered from any source distribution.
28  *
29  ******************************************************************************/
30 
31 #ifndef SL_HAL_DCDC_COULOMB_COUNTER_H
32 #define SL_HAL_DCDC_COULOMB_COUNTER_H
33 
34 #include "em_device.h"
35 
36 #if defined(DCDC_COUNT) && (DCDC_COUNT > 0) && defined(DCDC_CCCTRL_CCEN)
37 
38 #ifdef __cplusplus
39 extern "C" {
40 #endif
41 
42 #include <stdbool.h>
43 #include "sl_hal_dcdc_coulomb_counter_compat.h"
44 #include "sl_enum.h"
45 #include "em_cmu.h"
46 #include "em_emu.h"
47 
48 /***************************************************************************//**
49  * @addtogroup dcdccoulombcounter
50  * @{
51  ******************************************************************************/
52 
53 /*******************************************************************************
54  *********************************   ENUM   ************************************
55  ******************************************************************************/
56 
57 /** DCDC_COULOMB_COUNTER supported energy mode. */
SL_ENUM(sl_hal_dcdc_coulomb_counter_emode_t)58 SL_ENUM(sl_hal_dcdc_coulomb_counter_emode_t) {
59   SL_HAL_DCDC_COULOMB_COUNTER_EM0 = 0, /**< EM0/1 energy mode. */
60   SL_HAL_DCDC_COULOMB_COUNTER_EM2 = 1, /**< EM2/3 energy mode. */
61 };
62 
63 /** DCDC_COULOMB_COUNTER Calibration Load Current Level setting. */
SL_ENUM(sl_hal_dcdc_coulomb_counter_calibration_load_level_t)64 SL_ENUM(sl_hal_dcdc_coulomb_counter_calibration_load_level_t) {
65   SL_HAL_DCDC_COULOMB_COUNTER_CAL_LOAD0 = _DCDC_CCCALCTRL_CCLVL_LOAD0, /**< Nominal Load 0.25mA. */
66   SL_HAL_DCDC_COULOMB_COUNTER_CAL_LOAD1 = _DCDC_CCCALCTRL_CCLVL_LOAD1, /**< Nominal Load 0.50mA. */
67   SL_HAL_DCDC_COULOMB_COUNTER_CAL_LOAD2 = _DCDC_CCCALCTRL_CCLVL_LOAD2, /**< Nominal Load 1.00mA. */
68   SL_HAL_DCDC_COULOMB_COUNTER_CAL_LOAD3 = _DCDC_CCCALCTRL_CCLVL_LOAD3, /**< Nominal Load 1.50mA. */
69   SL_HAL_DCDC_COULOMB_COUNTER_CAL_LOAD4 = _DCDC_CCCALCTRL_CCLVL_LOAD4, /**< Nominal Load 2.00mA. */
70   SL_HAL_DCDC_COULOMB_COUNTER_CAL_LOAD5 = _DCDC_CCCALCTRL_CCLVL_LOAD5, /**< Nominal Load 4.00mA. */
71   SL_HAL_DCDC_COULOMB_COUNTER_CAL_LOAD6 = _DCDC_CCCALCTRL_CCLVL_LOAD6, /**< Nominal Load 6.00mA. */
72   SL_HAL_DCDC_COULOMB_COUNTER_CAL_LOAD7 = _DCDC_CCCALCTRL_CCLVL_LOAD7, /**< Nominal Load 8.00mA. */
73 };
74 
75 /*******************************************************************************
76  *******************************   STRUCTS   ***********************************
77  ******************************************************************************/
78 
79 /// DCDC_COULOMB_COUNTER configuration structure.
80 typedef struct {
81   uint16_t counter_threshold_em0;      ///< Coulomb Counter Threshold in EM0.
82   uint16_t counter_threshold_em2;      ///< Coulomb Counter Threshold in EM2.
83 } sl_hal_dcdc_coulomb_counter_config_t;
84 
85 /// DCDC_COULOMB_COUNTER calibration configuration structure.
86 typedef struct {
87   CMU_Select_TypeDef reference_clk;                                     ///< Coulomb Counter Calibration Reference Clock.
88   int8_t cal_count;                                                     ///< Coulomb Counter Calibration Reference Count.
89   sl_hal_dcdc_coulomb_counter_emode_t cal_emode;                        ///< Coulomb Counter Calibration Energy Mode.
90   sl_hal_dcdc_coulomb_counter_calibration_load_level_t cal_load_level;  ///< Coulomb Counter Calibration Power Load.
91 } sl_hal_dcdc_coulomb_counter_calibration_config_t;
92 
93 /// Suggested default values for DCDC_COULOMB_COUNTER configuration structure.
94 #define DCDC_COULOMB_COUNTER_CONFIG_DEFAULT                              \
95   {                                                                      \
96     0x8000,                         /* Coulomb Counter EM0 Threshold. */ \
97     0x8000,                         /* Coulomb Counter EM2 Threshold. */ \
98   }
99 
100 /// Suggested default values for DCDC_COULOMB_COUNTER calibration configuration structure.
101 #define DCDC_COULOMB_COUNTER_CALIBRATION_CONFIG_DEFAULT                                              \
102   {                                                                                                  \
103     cmuSelect_HFXO,                             /* Coulomb Counter Calibration Reference Clock.   */ \
104     8,                                          /* Coulomb Counter Calibration Reference Count.   */ \
105     SL_HAL_DCDC_COULOMB_COUNTER_EM0,            /* Coulomb Counter Calibration DC-DC energy mode. */ \
106     SL_HAL_DCDC_COULOMB_COUNTER_CAL_LOAD3,      /* Coulomb Counter Calibration Load.              */ \
107   }
108 
109 /*******************************************************************************
110  *****************************   PROTOTYPES   **********************************
111  ******************************************************************************/
112 
113 /***************************************************************************//**
114  * Initializes DCDC_COULOMB_COUNTER module.
115  *
116  * @param[in] p_config  A pointer to the DCDC_COULOMB_COUNTER initialization
117  *                      structure variable.
118  ******************************************************************************/
119 void sl_hal_dcdc_coulomb_counter_init(const sl_hal_dcdc_coulomb_counter_config_t *p_config);
120 
121 /***************************************************************************//**
122  * Enables DCDC_COULOMB_COUNTER module.
123  ******************************************************************************/
sl_hal_dcdc_coulomb_counter_enable(void)124 __STATIC_INLINE void sl_hal_dcdc_coulomb_counter_enable(void)
125 {
126   EMU_DCDCSync(_DCDC_SYNCBUSY_MASK);
127   DCDC->CCCTRL_SET = DCDC_CCCTRL_CCEN;
128 }
129 
130 /***************************************************************************//**
131  * Disables DCDC_COULOMB_COUNTER module.
132  ******************************************************************************/
133 void sl_hal_dcdc_coulomb_counter_disable(void);
134 
135 /***************************************************************************//**
136  * Waits for the DCDC_COULOMB_COUNTER to complete START command.
137  ******************************************************************************/
sl_hal_dcdc_coulomb_counter_wait_start(void)138 __STATIC_INLINE void sl_hal_dcdc_coulomb_counter_wait_start(void)
139 {
140   EMU_DCDCSync(_DCDC_SYNCBUSY_MASK);
141   while ((DCDC->CCSTATUS & _DCDC_CCSTATUS_CCRUNNING_MASK) == 0U) {
142     /* Wait for counters to start. */
143   }
144 }
145 
146 /***************************************************************************//**
147  * Waits for the DCDC_COULOMB_COUNTER to complete STOP command.
148  ******************************************************************************/
sl_hal_dcdc_coulomb_counter_wait_stop(void)149 __STATIC_INLINE void sl_hal_dcdc_coulomb_counter_wait_stop(void)
150 {
151   EMU_DCDCSync(_DCDC_SYNCBUSY_MASK);
152   while ((DCDC->CCSTATUS & _DCDC_CCSTATUS_CCRUNNING_MASK) == DCDC_CCSTATUS_CCRUNNING) {
153     /* Wait for counters to stop. */
154   }
155 }
156 
157 /***************************************************************************//**
158  * Waits for the DCDC_COULOMB_COUNTER to complete CLR command.
159  ******************************************************************************/
sl_hal_dcdc_coulomb_counter_wait_clear_counters(void)160 __STATIC_INLINE void sl_hal_dcdc_coulomb_counter_wait_clear_counters(void)
161 {
162   EMU_DCDCSync(_DCDC_SYNCBUSY_MASK);
163   while ((DCDC->CCSTATUS & _DCDC_CCSTATUS_CLRBSY_MASK) == DCDC_CCSTATUS_CLRBSY) {
164     /* Wait for counters to clear. */
165   }
166 }
167 
168 /***************************************************************************//**
169  * Starts DCDC_COULOMB_COUNTER operation.
170  *
171  * @note This function will send a start command to the DCDC_COULOMB_COUNTER peripheral.
172  *       The sl_hal_dcdc_coulomb_counter_wait_start() function can be used to wait for the start
173  *       command to be executed.
174  *
175  * @note This function requires the DCDC_COULOMB_COUNTER to be enabled.
176  ******************************************************************************/
sl_hal_dcdc_coulomb_counter_start(void)177 __STATIC_INLINE void sl_hal_dcdc_coulomb_counter_start(void)
178 {
179   EMU_DCDCSync(_DCDC_SYNCBUSY_MASK);
180   DCDC->CCCMD_SET = DCDC_CCCMD_START;
181 }
182 
183 /***************************************************************************//**
184  * Stops the DCDC_COULOMB_COUNTER operation.
185  *
186  * @note This function will send a stop command to the DCDC_COULOMB_COUNTER peripheral.
187  *       The sl_hal_dcdc_coulomb_counter_wait_stop() function can be used to wait for the stop
188  *       command to be executed.
189  *
190  * @note This function requires the DCDC_COULOMB_COUNTER to be enabled.
191  ******************************************************************************/
sl_hal_dcdc_coulomb_counter_stop(void)192 __STATIC_INLINE void sl_hal_dcdc_coulomb_counter_stop(void)
193 {
194   EMU_DCDCSync(_DCDC_SYNCBUSY_MASK);
195   DCDC->CCCMD_SET = DCDC_CCCMD_STOP;
196 }
197 
198 /***************************************************************************//**
199  * Clears the DCDC_COULOMB_COUNTER counters.
200  *
201  * @note This function will send a clear command to the DCDC_COULOMB_COUNTER peripheral.
202  *       The sl_hal_dcdc_coulomb_counter_wait_clear_counters() function can be used
203  *       to wait for the clear command to be executed.
204  *
205  * @note This function requires the DCDC_COULOMB_COUNTER to be enabled.
206  ******************************************************************************/
sl_hal_dcdc_coulomb_counter_clear_counters(void)207 __STATIC_INLINE void sl_hal_dcdc_coulomb_counter_clear_counters(void)
208 {
209   EMU_DCDCSync(_DCDC_SYNCBUSY_MASK);
210   DCDC->CCCMD_SET = DCDC_CCCMD_CLR;
211 }
212 
213 /***************************************************************************//**
214  * Gets the DCDC_COULOMB_COUNTER count for the selected energy mode.
215  *
216  * @param[in] emode  The energy mode requested will select the appropriate counter.
217  *
218  * @return Coulomb Counter Count Value.
219  ******************************************************************************/
220 uint32_t sl_hal_dcdc_coulomb_counter_get_count(sl_hal_dcdc_coulomb_counter_emode_t emode);
221 
222 /***************************************************************************//**
223  * Gets DCDC_COULOMB_COUNTER STATUS register value.
224  *
225  * @return  Current STATUS register value.
226  ******************************************************************************/
sl_hal_dcdc_coulomb_counter_get_status(void)227 __STATIC_INLINE uint32_t sl_hal_dcdc_coulomb_counter_get_status(void)
228 {
229   return DCDC->CCSTATUS;
230 }
231 
232 /***************************************************************************//**
233  * Enables one or more DCDC_COULOMB_COUNTER interrupts.
234  *
235  * @note  Depending on the use, a pending interrupt may already be set prior to
236  *        enabling the interrupt. To ignore a pending interrupt, consider using
237  *        sl_hal_dcdc_coulomb_counter_clear_interrupts() prior to enabling the interrupt.
238  *
239  * @param[in] flags   DCDC_COULOMB_COUNTER interrupt sources to enable.
240  *                    Use a set of interrupt flags OR-ed together to set
241  *                    multiple interrupt sources.
242  ******************************************************************************/
sl_hal_dcdc_coulomb_counter_enable_interrupts(uint32_t flags)243 __STATIC_INLINE void sl_hal_dcdc_coulomb_counter_enable_interrupts(uint32_t flags)
244 {
245   DCDC->CCIEN_SET = flags;
246 }
247 
248 /***************************************************************************//**
249  * Disables one or more DCDC_COULOMB_COUNTER interrupts.
250  *
251  * @param[in] flags   DCDC_COULOMB_COUNTER interrupt sources to disable.
252  *                    Use a set of interrupt flags OR-ed together to disable
253  *                    multiple interrupt sources.
254  ******************************************************************************/
sl_hal_dcdc_coulomb_counter_disable_interrupts(uint32_t flags)255 __STATIC_INLINE void sl_hal_dcdc_coulomb_counter_disable_interrupts(uint32_t flags)
256 {
257   DCDC->CCIEN_CLR = flags;
258 }
259 
260 /***************************************************************************//**
261  * Clears one or more pending DCDC_COULOMB_COUNTER interrupts.
262  *
263  * @param[in] flags   DCDC_COULOMB_COUNTER interrupt sources to clear.
264  *                    Use a set of interrupt flags OR-ed together to clear
265  *                    multiple interrupt sources.
266  ******************************************************************************/
sl_hal_dcdc_coulomb_counter_clear_interrupts(uint32_t flags)267 __STATIC_INLINE void sl_hal_dcdc_coulomb_counter_clear_interrupts(uint32_t flags)
268 {
269   DCDC->CCIF_CLR = flags;
270 }
271 
272 /***************************************************************************//**
273  * Gets pending DCDC_COULOMB_COUNTER interrupt flags.
274  *
275  * @note  Event bits are not cleared by using this function.
276  *
277  * @return  Pending DCDC_COULOMB_COUNTER interrupt sources.
278  *          Returns a set of interrupt flags OR-ed together for multiple
279  *          interrupt sources.
280  ******************************************************************************/
sl_hal_dcdc_coulomb_counter_get_interrupts(void)281 __STATIC_INLINE uint32_t sl_hal_dcdc_coulomb_counter_get_interrupts(void)
282 {
283   return DCDC->CCIF;
284 }
285 
286 /***************************************************************************//**
287  * Gets enabled and pending DCDC_COULOMB_COUNTER interrupt flags.
288  * Useful for handling more interrupt sources in the same interrupt handler.
289  *
290  * @note  Interrupt flags are not cleared by using this function.
291  *
292  * @return  Pending and enabled DCDC_COULOMB_COUNTER interrupt sources.
293  *          The return value is the bitwise AND of
294  *          - the enabled interrupt sources in DCDC_COULOMB_COUNTER_IEN and
295  *          - the pending interrupt flags DCDC_COULOMB_COUNTER_IF.
296  ******************************************************************************/
sl_hal_dcdc_coulomb_counter_get_enabled_interrupts(void)297 __STATIC_INLINE uint32_t sl_hal_dcdc_coulomb_counter_get_enabled_interrupts(void)
298 {
299   uint32_t ccif = DCDC->CCIF & _DCDC_CCIF_MASK;
300   uint32_t ccien = DCDC->CCIEN & _DCDC_CCIEN_MASK;
301 
302   return ccif & ccien;
303 }
304 
305 /***************************************************************************//**
306  * Sets one or more pending DCDC_COULOMB_COUNTER interrupts from Software.
307  *
308  * @param[in] flags   DCDC_COULOMB_COUNTER interrupt sources to set to pending.
309  *                    Use a set of interrupt flags OR-ed together to set
310  *                    multiple interrupt sources.
311  ******************************************************************************/
sl_hal_dcdc_coulomb_counter_set_interrupts(uint32_t flags)312 __STATIC_INLINE void sl_hal_dcdc_coulomb_counter_set_interrupts(uint32_t flags)
313 {
314   DCDC->CCIF_SET = flags;
315 }
316 
317 /***************************************************************************//**
318  * Initializes the calibration of the DCDC Coulomb Counter.
319  *
320  * @param[in] config  DCDC_COULOMB_COUNTER calibration configuration structure.
321  *
322  * @note The charge per pulse is measured using known on-chip calibration
323  *       loads, a PRS channel, and the CMU RC oscillator calibration circuitry.
324  ******************************************************************************/
325 void sl_hal_dcdc_coulomb_counter_cal_init(sl_hal_dcdc_coulomb_counter_calibration_config_t config);
326 
327 /***************************************************************************//**
328  * Starts DCDC_COULOMB_COUNTER calibration sequence.
329  ******************************************************************************/
330 void sl_hal_dcdc_coulomb_counter_cal_start(void);
331 
332 /***************************************************************************//**
333  * Stops DCDC_COULOMB_COUNTER calibration sequence.
334  *
335  * @note The Calibration Load will be disabled.
336  ******************************************************************************/
337 void sl_hal_dcdc_coulomb_counter_cal_stop(void);
338 
339 /***************************************************************************//**
340  * Enables the Calibration Load.
341  ******************************************************************************/
342 void sl_hal_dcdc_coulomb_counter_enable_cal_load(void);
343 
344 /***************************************************************************//**
345  * Disables the Calibration Load.
346  ******************************************************************************/
347 void sl_hal_dcdc_coulomb_counter_disable_cal_load(void);
348 
349 /***************************************************************************//**
350  * Sets the Calibration Load level.
351  *
352  * @param[in] emode       The energy mode requested will adjust the compensation circuit.
353  * @param[in] load_level  The load level to adjust the load current.
354  ******************************************************************************/
355 void sl_hal_dcdc_coulomb_counter_set_cal_load_level(sl_hal_dcdc_coulomb_counter_emode_t emode,
356                                                     sl_hal_dcdc_coulomb_counter_calibration_load_level_t load_level);
357 
358 /***************************************************************************//**
359  * Gets the calibration load current from the stored value
360  * in DEVINFO as measured during production testing.
361  *
362  * @param[in] load_level  The load level requested.
363  *
364  * @return The calibration load current.
365  *
366  * @note The returned value can be converted into uA by dividing by 5.
367  *
368  * @note Each calibration load setting is a 16-bit value
369  *       with each LSB representing 200 nA.
370  ******************************************************************************/
371 uint16_t sl_hal_dcdc_coulomb_counter_get_cal_load_current(sl_hal_dcdc_coulomb_counter_calibration_load_level_t load_level);
372 
373 /***************************************************************************//**
374  * Gets the frequency (in Hz) of the CMU Calibration Up-Counter source.
375  *
376  * @return The frequency (in Hz) of the currently selected CMU Up-Counter clock
377  *         source.
378  ******************************************************************************/
379 uint32_t sl_hal_dcdc_coulomb_counter_get_cal_reference_freq(void);
380 
381 /***************************************************************************//**
382  * Sets the calibration Halt Flag.
383  ******************************************************************************/
sl_hal_dcdc_coulomb_counter_set_calhalt(void)384 __STATIC_INLINE void sl_hal_dcdc_coulomb_counter_set_calhalt(void)
385 {
386   DCDC->CCCALCTRL_SET = DCDC_CCCALCTRL_CCCALHALT;
387 }
388 
389 /***************************************************************************//**
390  * Gets the calibration Halt Flag.
391  *
392  * @return true if Halt Flag is set.
393  ******************************************************************************/
sl_hal_dcdc_coulomb_counter_calhalt_is_set(void)394 __STATIC_INLINE bool sl_hal_dcdc_coulomb_counter_calhalt_is_set(void)
395 {
396   return (DCDC->CCCALCTRL & _DCDC_CCCALCTRL_CCCALHALT_MASK) == DCDC_CCCALCTRL_CCCALHALT;
397 }
398 
399 /** @} (end addtogroup dcdccoulombcounter) */
400 
401 #ifdef __cplusplus
402 }
403 #endif
404 
405 #endif /* defined(DCDC_COULOMB_COUNTER_COUNT) && (DCDC_COULOMB_COUNTER_COUNT > 0) && defined(DCDC_CCCTRL_CCEN) */
406 #endif /* SL_HAL_DCDC_COULOMB_COUNTER_H */
407