1 /*
2  * Copyright 2024 Embeint Inc
3  *
4  * SPDX-License-Identifier: Apache-2.0
5  */
6 
7 #ifndef ZEPHYR_INCLUDE_DRIVERS_SENSOR_BATTERY_H_
8 #define ZEPHYR_INCLUDE_DRIVERS_SENSOR_BATTERY_H_
9 
10 #include <stdint.h>
11 #include <errno.h>
12 
13 #include <zephyr/devicetree.h>
14 #include <zephyr/math/interpolation.h>
15 #include <zephyr/sys/util_macro.h>
16 
17 #ifdef __cplusplus
18 extern "C" {
19 #endif
20 
21 /**
22  * @brief battery API
23  * @defgroup battery_apis battery APIs
24  * @{
25  */
26 
27 /* Battery chemistry enumeration.
28  * Value names must match those from dts/bindings/battery.yaml
29  */
30 enum battery_chemistry {
31 	BATTERY_CHEMISTRY_UNKNOWN = 0,
32 	BATTERY_CHEMISTRY_NICKEL_CADMIUM,
33 	BATTERY_CHEMISTRY_NICKEL_METAL_HYDRIDE,
34 	BATTERY_CHEMISTRY_LITHIUM_ION,
35 	BATTERY_CHEMISTRY_LITHIUM_ION_POLYMER,
36 	BATTERY_CHEMISTRY_LITHIUM_ION_IRON_PHOSPHATE,
37 	BATTERY_CHEMISTRY_LITHIUM_ION_MANGANESE_OXIDE,
38 };
39 
40 /* Length of open circuit voltage table */
41 #define BATTERY_OCV_TABLE_LEN 11
42 
43 /**
44  * @brief Get the battery chemistry enum value
45  *
46  * @param node_id node identifier
47  */
48 #define BATTERY_CHEMISTRY_DT_GET(node_id)                                                          \
49 	UTIL_CAT(BATTERY_CHEMISTRY_, DT_STRING_UPPER_TOKEN_OR(node_id, device_chemistry, UNKNOWN))
50 
51 /**
52  * @brief Get the OCV curve for a given table
53  *
54  * @param node_id node identifier
55  * @param table table to retrieve
56  */
57 #define BATTERY_OCV_TABLE_DT_GET(node_id, table)                                                   \
58 	COND_CODE_1(DT_NODE_HAS_PROP(node_id, table),                                              \
59 		    ({DT_FOREACH_PROP_ELEM_SEP(node_id, table, DT_PROP_BY_IDX, (,))}), ({-1}))
60 
61 /**
62  * @brief Convert an OCV table and battery voltage to a charge percentage
63  *
64  * @param ocv_table Open circuit voltage curve
65  * @param voltage_uv Battery voltage in microVolts
66  *
67  * @returns Battery state of charge in milliPercent
68  */
battery_soc_lookup(const int32_t ocv_table[BATTERY_OCV_TABLE_LEN],uint32_t voltage_uv)69 static inline int32_t battery_soc_lookup(const int32_t ocv_table[BATTERY_OCV_TABLE_LEN],
70 					 uint32_t voltage_uv)
71 {
72 	static const int32_t soc_axis[BATTERY_OCV_TABLE_LEN] = {
73 		0, 10000, 20000, 30000, 40000, 50000, 60000, 70000, 80000, 90000, 100000};
74 
75 	/* Convert voltage to SoC */
76 	return linear_interpolate(ocv_table, soc_axis, BATTERY_OCV_TABLE_LEN, voltage_uv);
77 }
78 
79 /**
80  * @}
81  */
82 
83 #ifdef __cplusplus
84 }
85 #endif
86 
87 #endif /* ZEPHYR_INCLUDE_DRIVERS_SENSOR_BATTERY_H_ */
88