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(¬ifyObject,
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