1 /*
2  * Copyright (c) 2022-2023, Texas Instruments Incorporated
3  * All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions
7  * are met:
8  *
9  * *  Redistributions of source code must retain the above copyright
10  *    notice, this list of conditions and the following disclaimer.
11  *
12  * *  Redistributions in binary form must reproduce the above copyright
13  *    notice, this list of conditions and the following disclaimer in the
14  *    documentation and/or other materials provided with the distribution.
15  *
16  * *  Neither the name of Texas Instruments Incorporated nor the names of
17  *    its contributors may be used to endorse or promote products derived
18  *    from this software without specific prior written permission.
19  *
20  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
21  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
22  * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
23  * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
24  * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
25  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
26  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
27  * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
28  * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
29  * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
30  * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31  */
32 /*!****************************************************************************
33  *  @file       BatteryMonitor.h
34  *
35  *  @brief      Battery Monitor driver
36  *
37  *  @anchor ti_drivers_BatteryMonitor_Overview
38  *  # Overview #
39  *  The Battery Monitor driver provides services related to measuring and
40  *  reacting to the current supply voltage of the device, and changes to it.
41  *
42  *  The two main services provided are:
43  *      - Getting the current supply voltage
44  *      - Providing notification callbacks when the supply voltage changes
45  *
46  *  @anchor ti_drivers_BatteryMonitor_Usage
47  *  # Usage #
48  *
49  *  ## Initialisation #
50  *  Unlike most drivers, there is only a single instance of the Battery Monitor
51  *  driver that is always available once #BatteryMonitor_init() is called.
52  *  #BatteryMonitor_init() should be called once before using other Battery
53  *  Monitor driver APIs. Subsequent #BatteryMonitor_init() calls will have no
54  *  effect.
55  *
56  *  ## Getting the Current Supply Voltage #
57  *  The driver can read the current supply voltage and return it. The resolution
58  *  is device-specific (see device-specific Battery Monitor documentation), but
59  *  the voltage will always be encoded as an unsigned integer in millivolts
60  *  (mV).
61  *
62  *  ## Notifications #
63  *  The Battery Monitor driver can notify the application when the supply
64  *  voltage crosses an application-defined threshold.
65  *
66  *  There are three default use cases for this:
67  *      - High threshold.
68  *        The application will receive a notification callback when
69  *        currentVoltage >= thresholdHigh.
70  *      - Low threshold.
71  *        The application will receive a notification callback when
72  *        currentVoltage <= thresholdLow.
73  *      - Range threshold.
74  *        The application will receive a notification callback when
75  *        currentVoltage >= thresholdHigh || currentVoltage <=
76  *        thresholdLow. This setup addresses use cases
77  *        where a notification is required when the supply voltage changes by a
78  *        certain amount regardless of whether it is up or down.
79  *
80  *  ### Registering Notifications
81  *  There are three functions that register a notification for the application:
82  *      - #BatteryMonitor_registerNotifyHigh()
83  *      - #BatteryMonitor_registerNotifyLow()
84  *      - #BatteryMonitor_registerNotifyRange()
85  *
86  *  Multiple notifications may be registered. The different parts of the
87  *  application and drivers that need to respond to a supply voltage change do
88  *  not need to know of one another.
89  *  Each notification must have its own #BatteryMonitor_NotifyObj and must be
90  *  registered individually.
91  *
92  *  ### Notification Callbacks
93  *  Once the supply voltage crosses the smallest "high threshold" or largest
94  *  "low threshold amongst the registered notifications, the driver will
95  *  iterate over the entire list of registered notification and check which
96  *  ones have triggered. Notifications that have triggered are removed from the
97  *  list of registered notifications before their callback function is invoked.
98  *
99  *  If an application wishes to re-register a notification that just triggered
100  *  and was unregistered, it may register it again from within the notification
101  *  callback or another context.
102  *
103  *  It is possible to determine whether the high or low threshold triggered
104  *  the notification callback as follows:
105  *      - currentVoltage <= thresholdVoltage: Low threshold triggered
106  *      - currentVoltage >= thresholdVoltage: High threshold triggered
107  *  This information is only reasonably useful when registering a notification
108  *  with both a high and low threshold using
109  *  #BatteryMonitor_registerNotifyRange(). Even then, the expected basic use
110  *  case only cares about the current voltage and adding an offset to it when
111  *  registering the notification again.
112  *
113  *  ### Unregistering Notifications
114  *  Registered notifications are unregistered in two ways:
115  *      - Automatically when a notification triggers
116  *      - By calling #BatteryMonitor_unregisterNotify()
117  *
118  *  Unregistered notifications may be registered again at any time.
119  *
120  *  @anchor ti_drivers_BatteryMonitor_Synopsis
121  *  # Synopsis #
122  *  @anchor ti_drivers_BatteryMonitor_Synopsis_Code
123  *  @code
124  *  #include <ti/drivers/BatteryMonitor.h>
125  *
126  *  #define WINDOW_DELTA_MILLIVOLT 300
127  *
128  *  BatteryMonitor_init();
129  *
130  *  currentVoltage = BatteryMonitor_getVoltage();
131  *
132  *  result = BatteryMonitor_registerNotifyRange(&notifyObject,
133  *                                              currentVoltage + WINDOW_DELTA_MILLIVOLT,
134  *                                              currentVoltage - WINDOW_DELTA_MILLIVOLT,
135  *                                              myNotifyFxn,
136  *                                              clientArg);
137  *  @endcode
138  *
139  *  @anchor ti_drivers_BatteryMonitor_Examples
140  *  # Examples #
141  *
142  *  ## Register a High Threshold Notification #
143  *
144  *  @code
145  *
146  *  // The notification will trigger when the supply voltage reaches 3.5V
147  *  #define THRESHOLD_CUTOFF_MILLIVOLT 3500
148  *
149  *  #include <ti/drivers/BatteryMonitor.h>
150  *
151  *  void thresholdNotifyFxn(uint16_t currentVoltage,
152  *                          uint16_t thresholdVoltage,
153  *                          uintptr_t clientArg,
154  *                          BatteryMonitor_NotifyObj *notifyObject) {
155  *     // Post a semaphore, set a flag, or otherwise act upon the voltage change.
156  *  }
157  *
158  *  ...
159  *
160  *  // Initialize the Battery Monitor driver and register a notification.
161  *
162  *  BatteryMonitor_init();
163  *
164  *  int_fast16_t status = BatteryMonitor_registerNotifyHigh(notifyObject,
165  *                                                          THRESHOLD_CUTOFF_MILLIVOLT,
166  *                                                          thresholdNotifyFxn,
167  *                                                          NULL);
168  *
169  *  if (status != BatteryMonitor_STATUS_SUCCESS) {
170  *      // Handle error
171  *  }
172  *
173  *  @endcode
174  *
175  *  ## Register a Range Threshold Notification and re-register in Callback #
176  *
177  *  @code
178  *
179  *  #define THRESHOLD_DELTA_MILLIVOLT 300
180  *
181  *  #include <ti/drivers/BatteryMonitor.h>
182  *
183  *
184  *  void deltaNotificationFxn(uint16_t currentVoltage,
185  *                            uint16_t thresholdVoltage,
186  *                            uintptr_t clientArg,
187  *                            BatteryMonitor_NotifyObj *notifyObject) {
188  *      int_fast16_t status;
189  *
190  *      status = BatteryMonitor_registerNotifyRange(notifyObject,
191  *                                          currentVoltage + THRESHOLD_DELTA_MILLIVOLT,
192  *                                          currentVoltage - THRESHOLD_DELTA_MILLIVOLT,
193  *                                          deltaNotificationFxn,
194  *                                          clientArg);
195  *
196  *      if (status != BatteryMonitor_STATUS_SUCCESS) {
197  *          while(1);
198  *      }
199  *  }
200  *
201  *   ...
202  *
203  *  // Initialize the Battery Monitor driver and register a notification.
204  *
205  *  BatteryMonitor_init();
206  *
207  *  BatteryMonitor_NotifyObj rangeNotifyObject;
208  *
209  *  uint16_t currentVoltage = BatteryMonitor_getVoltage();
210  *
211  *  int_fast16_t status = BatteryMonitor_registerNotifyRange(6rangeNotifyObject,
212  *                                                        currentVoltage + THRESHOLD_DELTA_MILLIVOLT,
213  *                                                        currentVoltage - THRESHOLD_DELTA_MILLIVOLT,
214  *                                                        deltaNotificationFxn,
215  *                                                        (uintptr_t)NULL);
216  *  @endcode
217  */
218 
219 #ifndef ti_drivers_BatteryMonitor__include
220 #define ti_drivers_BatteryMonitor__include
221 
222 #include <stdbool.h>
223 #include <stddef.h>
224 #include <stdint.h>
225 
226 #include <ti/drivers/utils/List.h>
227 
228 #ifdef __cplusplus
229 extern "C" {
230 #endif
231 
232 /*!
233  * Common Battery Monitor status code reservation offset.
234  * Battery Monitor driver implementations should offset status codes with
235  * BatteryMonitor_STATUS_RESERVED growing negatively.
236  *
237  * Example implementation specific status codes:
238  * @code
239  * #define BatteryMonitorXYZ_STATUS_ERROR0    BatteryMonitor_STATUS_RESERVED - 0
240  * #define BatteryMonitorXYZ_STATUS_ERROR1    BatteryMonitor_STATUS_RESERVED - 1
241  * #define BatteryMonitorXYZ_STATUS_ERROR2    BatteryMonitor_STATUS_RESERVED - 2
242  * @endcode
243  */
244 #define BatteryMonitor_STATUS_RESERVED (-32)
245 
246 /*!
247  * @brief   Successful status code.
248  *
249  * Functions return BatteryMonitor_STATUS_SUCCESS if the function was executed
250  * successfully.
251  */
252 #define BatteryMonitor_STATUS_SUCCESS (0)
253 
254 /*!
255  * @brief   Generic error status code.
256  *
257  * Functions return BatteryMonitor_STATUS_ERROR if the function was not executed
258  * successfully.
259  */
260 #define BatteryMonitor_STATUS_ERROR (-1)
261 
262 /* @cond NODOC
263  *
264  * Type declaration for the notification object made separately from the
265  * struct definition because of the circular dependency between
266  * #BatteryMonitor_NotifyFxn() and #BatteryMonitor_NotifyObj.
267  */
268 typedef struct BatteryMonitor_NotifyObj BatteryMonitor_NotifyObj;
269 /* @endcond */
270 
271 /*!
272  *  @brief Function prototype for a notification callback.
273  *
274  *  @param [in]     currentVoltage      Current supply voltage in millivolts
275  *
276  *  @param [in]     thresholdVoltage    Voltage threshold in millivolts that
277  *                                      caused this notification callback.
278  *
279  *  @param [in]     clientArg           Argument provided by the application
280  *                                      during registration.
281  *
282  *  @param [in/out] notifyObject        Pointer to notification object that was
283  *                                      registered previously. This may be used
284  *                                      to register the notification again with
285  *                                      updated inputs from within the
286  *                                      notification callback.
287  */
288 typedef void (*BatteryMonitor_NotifyFxn)(uint16_t currentVoltage,
289                                          uint16_t thresholdVoltage,
290                                          uintptr_t clientArg,
291                                          BatteryMonitor_NotifyObj *notifyObject);
292 
293 /*!
294  *  @brief Battery Monitor notify object structure.
295  *
296  *  This structure specification is for internal use. Notification clients must
297  *  pre-allocate a notify object when registering for a notification;
298  *  #BatteryMonitor_registerNotifyHigh(), #BatteryMonitor_registerNotifyLow(),
299  *  or #BatteryMonitor_registerNotifyRange() will take care initializing the
300  *  internal elements appropriately.
301  */
302 struct BatteryMonitor_NotifyObj
303 {
304     List_Elem link;                     /*!< For placing on the notify list */
305     BatteryMonitor_NotifyFxn notifyFxn; /*!< Application callback function */
306     uint16_t thresholdHigh;             /*!< High threshold in millivolts */
307     uint16_t thresholdLow;              /*!< Low threshold in millivolts */
308     uintptr_t clientArg;                /*!< Application provided arg */
309     bool isRegistered;                  /*!< Is the notification active */
310 };
311 
312 /*!
313  *  @brief This function initializes the Battery Monitor driver.
314  *
315  *  This function initializes the internal state of the Battery Monitor driver.
316  *  It must be called before calling any other Battery Monitor functions.
317  *  Subsequent calls to this function have no effect.
318  */
319 void BatteryMonitor_init(void);
320 
321 /*!
322  *  @brief Gets the current supply voltage in millivolts.
323  *
324  *  @return Current supply voltage in millivolts
325  */
326 uint16_t BatteryMonitor_getVoltage(void);
327 
328 /*!
329  *  @brief Registers a notification with a high threshold.
330  *
331  *  This function registers a Battery Monitor notification with a high
332  *  threshold. Once the supply voltage rises above @c thresholdHigh,
333  *  the notification is automatically unregistered and function @c notifyFxn is
334  *  called.
335  *
336  *  @param  notifyObject        Structure to be initialized. After returning,
337  *                              it will contain the data necessary to issue a
338  *                              notification callback. The memory of the
339  *                              structure must persist while the notification
340  *                              is registered.
341  *
342  *  @param  [in] thresholdHigh  Threshold supply voltage in millivolts
343  *
344  *  @param  [in] notifyFxn      Callback function that is called once the
345  *                              supply voltage rises above @c thresholdHigh.
346  *
347  *  @param  [in] clientArg      Application-specified argument
348  *
349  *  @retval #BatteryMonitor_STATUS_SUCCESS The notification was successfully
350  *                                         registered.
351  *  @retval #BatteryMonitor_STATUS_ERROR   There was an error during
352  *                                         registration.
353  *
354  *  @pre BatteryMonitor_init() called
355  */
356 int_fast16_t BatteryMonitor_registerNotifyHigh(BatteryMonitor_NotifyObj *notifyObject,
357                                                uint16_t thresholdHigh,
358                                                BatteryMonitor_NotifyFxn notifyFxn,
359                                                uintptr_t clientArg);
360 
361 /*!
362  *  @brief Registers a notification with a low threshold.
363  *
364  *  This function registers a Battery Monitor notification with a low threshold.
365  *  Once the supply voltage falls below @c thresholdLow, the notification is
366  *  automatically unregistered and function @c notifyFxn is called.
367  *
368  *  @param  notifyObject        Structure to be initialized. After returning,
369  *                              it will contain the data necessary to issue a
370  *                              notification callback. The memory of the
371  *                              structure must persist while the notification
372  *                              is registered.
373  *
374  *  @param  [in] thresholdLow   Threshold supply voltage in millivolts
375  *
376  *  @param  [in] notifyFxn      Callback function that is called once the
377  *                              supply voltage falls below @c thresholdLow.
378  *
379  *  @param  [in] clientArg      Application-specified argument
380  *
381  *  @retval #BatteryMonitor_STATUS_SUCCESS The notification was successfully
382  *                                         registered.
383  *  @retval #BatteryMonitor_STATUS_ERROR   There was an error during registration.
384  *
385  *  @pre BatteryMonitor_init() called
386  */
387 int_fast16_t BatteryMonitor_registerNotifyLow(BatteryMonitor_NotifyObj *notifyObject,
388                                               uint16_t thresholdLow,
389                                               BatteryMonitor_NotifyFxn notifyFxn,
390                                               uintptr_t clientArg);
391 
392 /*!
393  *  @brief Registers a notification with both a high and low threshold.
394  *
395  *  This function registers a Battery Monitor notification with a high and low
396  *  threshold. Once the supply voltage rises above @c thresholdHigh or
397  *  falls below @c thresholdLow, the notification is automatically unregistered
398  *  and function @c notifyFxn is called.
399  *
400  *  @param  notifyObject        Structure to be initialized. After returning,
401  *                              it will contain the data necessary to issue a
402  *                              notification callback. The memory of the
403  *                              structure must persist while the notification
404  *                              is registered.
405  *
406  *  @param  [in] thresholdHigh  High threshold supply voltage in millivolts
407  *
408  *  @param  [in] thresholdLow   Low threshold supply voltage in millivolts
409  *
410  *  @param  [in] notifyFxn      Callback function that is called once the
411  *                              supply voltage falls below
412  *                              @c thresholdLow, or rises above
413  *                              @c thresholdHigh.
414  *
415  *  @param  [in] clientArg      Application-specified argument
416  *
417  *  @retval #BatteryMonitor_STATUS_SUCCESS The notification was successfully
418  *                                         registered
419  *  @retval #BatteryMonitor_STATUS_ERROR   There was an error during
420  *                                         registration
421  *
422  *  @pre BatteryMonitor_init() called
423  */
424 int_fast16_t BatteryMonitor_registerNotifyRange(BatteryMonitor_NotifyObj *notifyObject,
425                                                 uint16_t thresholdHigh,
426                                                 uint16_t thresholdLow,
427                                                 BatteryMonitor_NotifyFxn notifyFxn,
428                                                 uintptr_t clientArg);
429 
430 /*!
431  *  @brief Unregisters a currently registered notification.
432  *
433  *  This function unregisters a currently registered notification.
434  *
435  *  @param  notifyObject    Notification to unregister.
436  *
437  *  @retval #BatteryMonitor_STATUS_SUCCESS The notification was successfully
438  *                                         unregistered.
439  *  @retval #BatteryMonitor_STATUS_ERROR   There was an error during
440  *                                         unregistration.
441  *
442  *  @pre Register @c notifyObject with #BatteryMonitor_registerNotifyHigh(),
443  *       #BatteryMonitor_registerNotifyLow(), or #BatteryMonitor_registerNotifyRange()
444  */
445 int_fast16_t BatteryMonitor_unregisterNotify(BatteryMonitor_NotifyObj *notifyObject);
446 
447 /*!
448  *  @brief Get the high threshold of a notification.
449  *
450  *  @warning This function should not be called on a @c notifyObject registered
451  *  with #BatteryMonitor_registerNotifyLow(). The high threshold value returned
452  *  in that case will be a device-specific invalid voltage.
453  *
454  *  @param  notifyObject    Notification to get the high threshold of.
455  *
456  *  @return High threshold in millivolts.
457  *
458  *  @pre Register @c notifyObject with #BatteryMonitor_registerNotifyHigh(),
459  *       or #BatteryMonitor_registerNotifyRange()
460  */
BatteryMonitor_getThresholdHigh(BatteryMonitor_NotifyObj * notifyObject)461 static inline uint16_t BatteryMonitor_getThresholdHigh(BatteryMonitor_NotifyObj *notifyObject)
462 {
463     return notifyObject->thresholdHigh;
464 }
465 
466 /*!
467  *  @brief Get the low threshold of a notification.
468  *
469  *  @warning This function should not be called on a @c notifyObject registered
470  *  with #BatteryMonitor_registerNotifyHigh(). The low threshold value returned
471  *  in that case will be a device-specific invalid voltage.
472  *
473  *  @param  notifyObject    Notification to get the low threshold of.
474  *
475  *  @return Low threshold in millivolts.
476  *
477  *  @pre Register @c notifyObject with #BatteryMonitor_registerNotifyLow(),
478  *       or #BatteryMonitor_registerNotifyRange()
479  */
BatteryMonitor_getThresholdLow(BatteryMonitor_NotifyObj * notifyObject)480 static inline uint16_t BatteryMonitor_getThresholdLow(BatteryMonitor_NotifyObj *notifyObject)
481 {
482     return notifyObject->thresholdLow;
483 }
484 
485 /*!
486  *  @brief Get the high and low threshold of a notification.
487  *
488  *  @warning This function should not be called on a @c notifyObject registered
489  *  with #BatteryMonitor_registerNotifyLow() or
490  *  #BatteryMonitor_registerNotifyHigh(). The unconfigured threshold value
491  *  returned in that case will be a device-specific invalid voltage.
492  *
493  *  @param  notifyObject            Notification to get the high and low threshold
494  *                                  of.
495  *
496  *  @param [out]    thresholdHigh   High threshold value in millivolts written
497  *                                  back by this function.
498  *
499  *  @param [out]    thresholdLow    Low threshold value in millivolts written
500  *                                  back by this function.
501  *
502  *  @pre Register @c notifyObject with #BatteryMonitor_registerNotifyRange()
503  */
BatteryMonitor_getThresholdRange(BatteryMonitor_NotifyObj * notifyObject,uint16_t * thresholdHigh,uint16_t * thresholdLow)504 static inline void BatteryMonitor_getThresholdRange(BatteryMonitor_NotifyObj *notifyObject,
505                                                     uint16_t *thresholdHigh,
506                                                     uint16_t *thresholdLow)
507 {
508     *thresholdHigh = notifyObject->thresholdHigh;
509     *thresholdLow  = notifyObject->thresholdLow;
510 }
511 
512 /*!
513  *  @brief Get the application-provided clientArg of a notification.
514  *
515  *  @param  notifyObject    Notification to get the clientArg of.
516  *
517  *  @return The clientArg provided during registration.
518  *
519  *  @pre Register @c notifyObject with #BatteryMonitor_registerNotifyHigh(),
520  *       #BatteryMonitor_registerNotifyLow(), or #BatteryMonitor_registerNotifyRange()
521  */
BatteryMonitor_getClientArg(BatteryMonitor_NotifyObj * notifyObject)522 static inline uintptr_t BatteryMonitor_getClientArg(BatteryMonitor_NotifyObj *notifyObject)
523 {
524     return notifyObject->clientArg;
525 }
526 
527 /*!
528  *  @brief Get the notifyFxn provided during registration.
529  *
530  *  @param  notifyObject    Notification to get the notifyFxn of.
531  *
532  *  @return The notifyFxn provided during registration
533  *
534  *  @pre Register @c notifyObject with #BatteryMonitor_registerNotifyHigh(),
535  *       #BatteryMonitor_registerNotifyLow(), or #BatteryMonitor_registerNotifyRange()
536  */
BatteryMonitor_getNotifyFxn(BatteryMonitor_NotifyObj * notifyObject)537 static inline BatteryMonitor_NotifyFxn BatteryMonitor_getNotifyFxn(BatteryMonitor_NotifyObj *notifyObject)
538 {
539     return notifyObject->notifyFxn;
540 }
541 
542 #ifdef __cplusplus
543 }
544 #endif
545 
546 #endif /* ti_drivers_BatteryMonitor__include */
547