summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJoel Challis <git@zvecr.com>2025-08-17 01:14:48 +0100
committerGitHub <noreply@github.com>2025-08-17 01:14:48 +0100
commitcc696a2ae838a9639335ca8eb3cb3b794c06bc33 (patch)
tree901b54bda536acb5503c6cf924b0f30bca1a174e
parentf29d8117bf877a4df1f88f40e0131f4465748540 (diff)
Refactor battery driver (#25550)
-rw-r--r--builddefs/build_test.mk1
-rw-r--r--builddefs/common_features.mk14
-rw-r--r--builddefs/generic_features.mk1
-rw-r--r--builddefs/testlist.mk1
-rw-r--r--data/mappings/info_config.hjson8
-rw-r--r--data/mappings/info_rules.hjson1
-rw-r--r--data/schemas/keyboard.jsonschema22
-rw-r--r--docs/_sidebar.json1
-rw-r--r--docs/drivers/battery.md69
-rw-r--r--docs/features/battery.md55
-rw-r--r--docs/reference_info_json.md26
-rw-r--r--drivers/battery/battery_adc.c25
-rw-r--r--keyboards/handwired/onekey/keymaps/battery/config.h2
-rw-r--r--keyboards/handwired/onekey/keymaps/battery/keymap.c3
-rw-r--r--keyboards/handwired/onekey/keymaps/battery/keymap.json4
-rw-r--r--keyboards/handwired/onekey/keymaps/battery/rules.mk1
-rw-r--r--keyboards/handwired/promethium/config.h2
-rw-r--r--keyboards/handwired/promethium/keyboard.json7
-rw-r--r--keyboards/handwired/promethium/rules.mk1
-rw-r--r--quantum/battery/battery.c (renamed from drivers/battery/battery.c)0
-rw-r--r--quantum/battery/battery.h (renamed from drivers/battery/battery.h)0
-rw-r--r--quantum/battery/tests/battery_tests.cpp97
-rw-r--r--quantum/battery/tests/rules.mk7
-rw-r--r--quantum/battery/tests/testlist.mk2
-rw-r--r--quantum/keyboard.c6
-rw-r--r--quantum/quantum.h4
26 files changed, 287 insertions, 73 deletions
diff --git a/builddefs/build_test.mk b/builddefs/build_test.mk
index 0c5c98e2a3..ccdad1b4e7 100644
--- a/builddefs/build_test.mk
+++ b/builddefs/build_test.mk
@@ -62,6 +62,7 @@ include $(BUILDDEFS_PATH)/common_features.mk
62include $(BUILDDEFS_PATH)/generic_features.mk 62include $(BUILDDEFS_PATH)/generic_features.mk
63include $(PLATFORM_PATH)/common.mk 63include $(PLATFORM_PATH)/common.mk
64include $(TMK_PATH)/protocol.mk 64include $(TMK_PATH)/protocol.mk
65include $(QUANTUM_PATH)/battery/tests/rules.mk
65include $(QUANTUM_PATH)/debounce/tests/rules.mk 66include $(QUANTUM_PATH)/debounce/tests/rules.mk
66include $(QUANTUM_PATH)/encoder/tests/rules.mk 67include $(QUANTUM_PATH)/encoder/tests/rules.mk
67include $(QUANTUM_PATH)/os_detection/tests/rules.mk 68include $(QUANTUM_PATH)/os_detection/tests/rules.mk
diff --git a/builddefs/common_features.mk b/builddefs/common_features.mk
index c122afcff9..1da13997b5 100644
--- a/builddefs/common_features.mk
+++ b/builddefs/common_features.mk
@@ -945,21 +945,25 @@ ifeq ($(strip $(DIP_SWITCH_ENABLE)), yes)
945 endif 945 endif
946endif 946endif
947 947
948ifeq ($(strip $(BATTERY_ENABLE)), yes)
949 BATTERY_DRIVER_REQUIRED := yes
950endif
951
948VALID_BATTERY_DRIVER_TYPES := adc custom vendor 952VALID_BATTERY_DRIVER_TYPES := adc custom vendor
949 953
950BATTERY_DRIVER ?= adc 954BATTERY_DRIVER ?= none
951ifeq ($(strip $(BATTERY_DRIVER_REQUIRED)), yes) 955ifeq ($(strip $(BATTERY_DRIVER_REQUIRED)), yes)
952 ifeq ($(filter $(BATTERY_DRIVER),$(VALID_BATTERY_DRIVER_TYPES)),) 956 ifeq ($(filter $(BATTERY_DRIVER),$(VALID_BATTERY_DRIVER_TYPES)),)
953 $(call CATASTROPHIC_ERROR,Invalid BATTERY_DRIVER,BATTERY_DRIVER="$(BATTERY_DRIVER)" is not a valid battery driver) 957 $(call CATASTROPHIC_ERROR,Invalid BATTERY_DRIVER,BATTERY_DRIVER="$(BATTERY_DRIVER)" is not a valid battery driver)
954 endif 958 endif
955 959
956 OPT_DEFS += -DBATTERY_DRIVER 960 OPT_DEFS += -DBATTERY_DRIVER_$(strip $(shell echo $(BATTERY_DRIVER) | tr '[:lower:]' '[:upper:]'))
957 OPT_DEFS += -DBATTERY_$(strip $(shell echo $(BATTERY_DRIVER) | tr '[:lower:]' '[:upper:]'))
958 961
959 COMMON_VPATH += $(DRIVER_PATH)/battery 962 COMMON_VPATH += $(DRIVER_PATH)/battery
960 963
961 SRC += battery.c 964 ifneq ($(strip $(BATTERY_DRIVER)), custom)
962 SRC += battery_$(strip $(BATTERY_DRIVER)).c 965 SRC += battery_$(strip $(BATTERY_DRIVER)).c
966 endif
963 967
964 # add extra deps 968 # add extra deps
965 ifeq ($(strip $(BATTERY_DRIVER)), adc) 969 ifeq ($(strip $(BATTERY_DRIVER)), adc)
diff --git a/builddefs/generic_features.mk b/builddefs/generic_features.mk
index c826514431..6d394977bd 100644
--- a/builddefs/generic_features.mk
+++ b/builddefs/generic_features.mk
@@ -21,6 +21,7 @@ SPACE_CADET_ENABLE ?= yes
21GENERIC_FEATURES = \ 21GENERIC_FEATURES = \
22 AUTO_SHIFT \ 22 AUTO_SHIFT \
23 AUTOCORRECT \ 23 AUTOCORRECT \
24 BATTERY \
24 BOOTMAGIC \ 25 BOOTMAGIC \
25 CAPS_WORD \ 26 CAPS_WORD \
26 COMBO \ 27 COMBO \
diff --git a/builddefs/testlist.mk b/builddefs/testlist.mk
index 74a794adcd..2e81fe576b 100644
--- a/builddefs/testlist.mk
+++ b/builddefs/testlist.mk
@@ -1,6 +1,7 @@
1TEST_LIST = $(sort $(patsubst %/test.mk,%, $(shell find $(ROOT_DIR)tests -type f -name test.mk))) 1TEST_LIST = $(sort $(patsubst %/test.mk,%, $(shell find $(ROOT_DIR)tests -type f -name test.mk)))
2FULL_TESTS := $(notdir $(TEST_LIST)) 2FULL_TESTS := $(notdir $(TEST_LIST))
3 3
4include $(QUANTUM_PATH)/battery/tests/testlist.mk
4include $(QUANTUM_PATH)/debounce/tests/testlist.mk 5include $(QUANTUM_PATH)/debounce/tests/testlist.mk
5include $(QUANTUM_PATH)/encoder/tests/testlist.mk 6include $(QUANTUM_PATH)/encoder/tests/testlist.mk
6include $(QUANTUM_PATH)/os_detection/tests/testlist.mk 7include $(QUANTUM_PATH)/os_detection/tests/testlist.mk
diff --git a/data/mappings/info_config.hjson b/data/mappings/info_config.hjson
index a160e490c7..4c53aa4339 100644
--- a/data/mappings/info_config.hjson
+++ b/data/mappings/info_config.hjson
@@ -43,6 +43,14 @@
43 "BOOTMAGIC_ROW": {"info_key": "bootmagic.matrix.0", "value_type": "int"}, 43 "BOOTMAGIC_ROW": {"info_key": "bootmagic.matrix.0", "value_type": "int"},
44 "BOOTMAGIC_ROW_RIGHT": {"info_key": "split.bootmagic.matrix.0", "value_type": "int"}, 44 "BOOTMAGIC_ROW_RIGHT": {"info_key": "split.bootmagic.matrix.0", "value_type": "int"},
45 45
46 // Battery
47 "BATTERY_SAMPLE_INTERVAL": {"info_key": "battery.sample_interval", "value_type": "int"},
48 "BATTERY_ADC_PIN": {"info_key": "battery.adc.pin"},
49 "BATTERY_ADC_REF_VOLTAGE_MV": {"info_key": "battery.adc.reference_voltage", "value_type": "int"},
50 "BATTERY_ADC_VOLTAGE_DIVIDER_R1": {"info_key": "battery.adc.divider_r1", "value_type": "int"},
51 "BATTERY_ADC_VOLTAGE_DIVIDER_R2": {"info_key": "battery.adc.divider_r2", "value_type": "int"},
52 "BATTERY_ADC_RESOLUTION": {"info_key": "battery.adc.resolution", "value_type": "int"},
53
46 // Caps Word 54 // Caps Word
47 "BOTH_SHIFTS_TURNS_ON_CAPS_WORD": {"info_key": "caps_word.both_shifts_turns_on", "value_type": "flag"}, 55 "BOTH_SHIFTS_TURNS_ON_CAPS_WORD": {"info_key": "caps_word.both_shifts_turns_on", "value_type": "flag"},
48 "CAPS_WORD_IDLE_TIMEOUT": {"info_key": "caps_word.idle_timeout", "value_type": "int"}, 56 "CAPS_WORD_IDLE_TIMEOUT": {"info_key": "caps_word.idle_timeout", "value_type": "int"},
diff --git a/data/mappings/info_rules.hjson b/data/mappings/info_rules.hjson
index d43d83c3ea..5ecd5c12b3 100644
--- a/data/mappings/info_rules.hjson
+++ b/data/mappings/info_rules.hjson
@@ -13,6 +13,7 @@
13 13
14 "AUDIO_DRIVER": {"info_key": "audio.driver"}, 14 "AUDIO_DRIVER": {"info_key": "audio.driver"},
15 "BACKLIGHT_DRIVER": {"info_key": "backlight.driver"}, 15 "BACKLIGHT_DRIVER": {"info_key": "backlight.driver"},
16 "BATTERY_DRIVER": {"info_key": "battery.driver"},
16 "BLUETOOTH_DRIVER": {"info_key": "bluetooth.driver"}, 17 "BLUETOOTH_DRIVER": {"info_key": "bluetooth.driver"},
17 "BOARD": {"info_key": "board"}, 18 "BOARD": {"info_key": "board"},
18 "BOOTLOADER": {"info_key": "bootloader", "warn_duplicate": false}, 19 "BOOTLOADER": {"info_key": "bootloader", "warn_duplicate": false},
diff --git a/data/schemas/keyboard.jsonschema b/data/schemas/keyboard.jsonschema
index 3775b66c1a..93b1c82b1c 100644
--- a/data/schemas/keyboard.jsonschema
+++ b/data/schemas/keyboard.jsonschema
@@ -188,6 +188,28 @@
188 "as_caps_lock": {"type": "boolean"} 188 "as_caps_lock": {"type": "boolean"}
189 } 189 }
190 }, 190 },
191 "battery": {
192 "type": "object",
193 "additionalProperties": false,
194 "properties": {
195 "driver": {
196 "type": "string",
197 "enum": ["adc", "custom", "vendor"]
198 },
199 "adc": {
200 "type": "object",
201 "additionalProperties": false,
202 "properties": {
203 "pin": {"$ref": "./definitions.jsonschema#/mcu_pin"},
204 "reference_voltage": {"type": "integer"},
205 "divider_r1": {"type": "integer"},
206 "divider_r2": {"type": "integer"},
207 "resolution": {"type": "integer"}
208 }
209 },
210 "sample_interval": {"type": "integer"}
211 }
212 },
191 "bluetooth": { 213 "bluetooth": {
192 "type": "object", 214 "type": "object",
193 "additionalProperties": false, 215 "additionalProperties": false,
diff --git a/docs/_sidebar.json b/docs/_sidebar.json
index ee4709a650..eec345b788 100644
--- a/docs/_sidebar.json
+++ b/docs/_sidebar.json
@@ -175,6 +175,7 @@
175 ] 175 ]
176 }, 176 },
177 { "text": "Audio", "link": "/features/audio" }, 177 { "text": "Audio", "link": "/features/audio" },
178 { "text": "Battery", "link": "/features/battery" },
178 { "text": "Bootmagic", "link": "/features/bootmagic" }, 179 { "text": "Bootmagic", "link": "/features/bootmagic" },
179 { "text": "Converters", "link": "/feature_converters" }, 180 { "text": "Converters", "link": "/feature_converters" },
180 { "text": "Custom Matrix", "link": "/custom_matrix" }, 181 { "text": "Custom Matrix", "link": "/custom_matrix" },
diff --git a/docs/drivers/battery.md b/docs/drivers/battery.md
index e482ffc8b6..ae07668cc0 100644
--- a/docs/drivers/battery.md
+++ b/docs/drivers/battery.md
@@ -1,6 +1,6 @@
1# Battery Driver 1# Battery Driver
2 2
3This driver provides support for sampling battery level. 3This driver provides support for directly sampling battery level.
4 4
5## Usage 5## Usage
6 6
@@ -10,21 +10,17 @@ To use this driver, add the following to your `rules.mk`:
10BATTERY_DRIVER_REQUIRED = yes 10BATTERY_DRIVER_REQUIRED = yes
11``` 11```
12 12
13## Basic Configuration {#basic-configuration} 13::::info Note
14 14This is already configured for you if you are using the [Battery](../features/battery) feature.
15Add the following to your `config.h`: 15::::
16
17|Define |Default |Description |
18|--------------------------|--------|--------------------------------------------------|
19|`BATTERY_SAMPLE_INTERVAL` |`30000` |The time between battery samples in milliseconds. |
20 16
21## Driver Configuration {#driver-configuration} 17## Driver Configuration {#driver-configuration}
22 18
23Driver selection can be configured in `rules.mk` as `BATTERY_DRIVER`. Valid values are `adc` (default), `vendor`, or `custom`. See below for information on individual drivers. 19Driver selection can be configured in `rules.mk` as `BATTERY_DRIVER`. Valid values are `adc`, `vendor`, or `custom`. See below for information on individual drivers.
24 20
25### ADC Driver {#adc-driver} 21### ADC Driver {#adc-driver}
26 22
27This is the default battery driver. The default configuration assumes the battery is connected to a ADC capable pin through a voltage divider. 23The default configuration assumes the battery is connected to a ADC capable pin through a voltage divider.
28 24
29```make 25```make
30BATTERY_DRIVER = adc 26BATTERY_DRIVER = adc
@@ -32,42 +28,25 @@ BATTERY_DRIVER = adc
32 28
33The following `#define`s apply only to the `adc` driver: 29The following `#define`s apply only to the `adc` driver:
34 30
35|Define |Default |Description | 31|Define |Default |Description |
36|-----------------------------|--------------|--------------------------------------------------------------| 32|---------------------------------|--------------|--------------------------------------------------------------|
37|`BATTERY_PIN` |*Not defined* |The GPIO pin connected to the voltage divider. | 33|`BATTERY_ADC_PIN` |*Not defined* |The GPIO pin connected to the voltage divider. |
38|`BATTERY_REF_VOLTAGE_MV` |`3300` |The ADC reverence voltage, in millivolts. | 34|`BATTERY_ADC_REF_VOLTAGE_MV` |`3300` |The ADC reverence voltage, in millivolts. |
39|`BATTERY_VOLTAGE_DIVIDER_R1` |`100` |The voltage divider resistance, in kOhm. Set to 0 to disable. | 35|`BATTERY_ADC_VOLTAGE_DIVIDER_R1` |`100` |The voltage divider resistance, in kOhm. Set to 0 to disable. |
40|`BATTERY_VOLTAGE_DIVIDER_R2` |`100` |The voltage divider resistance, in kOhm. Set to 0 to disable. | 36|`BATTERY_ADC_VOLTAGE_DIVIDER_R2` |`100` |The voltage divider resistance, in kOhm. Set to 0 to disable. |
41|`BATTERY_ADC_RESOLUTION` |`10` |The ADC resolution configured for the ADC Driver. | 37|`BATTERY_ADC_RESOLUTION` |`10` |The ADC resolution configured for the ADC Driver. |
42
43## Functions
44
45### `uint8_t battery_get_percent(void)` {#api-battery-get-percent}
46
47Sample battery level.
48
49#### Return Value {#api-battery-get-percent-return}
50
51The battery percentage, in the range 0-100.
52 38
53## Callbacks 39### Custom Driver {#custom-driver}
54 40
55### `void battery_percent_changed_user(uint8_t level)` {#api-battery-percent-changed-user} 41A custom driver is expected to implement the following interface:
56 42
57User hook called when battery level changed. 43```c
44void battery_driver_init(void) {
45 // Perform any initialisation here
46}
58 47
59### Arguments {#api-battery-percent-changed-user-arguments} 48uint8_t battery_driver_sample_percent(void) {
60 49 // Read and return current state here
61 - `uint8_t level` 50 return value;
62 The battery percentage, in the range 0-100. 51}
63 52```
64---
65
66### `void battery_percent_changed_kb(uint8_t level)` {#api-battery-percent-changed-kb}
67
68Keyboard hook called when battery level changed.
69
70### Arguments {#api-battery-percent-changed-kb-arguments}
71
72 - `uint8_t level`
73 The battery percentage, in the range 0-100.
diff --git a/docs/features/battery.md b/docs/features/battery.md
new file mode 100644
index 0000000000..f5c725efb9
--- /dev/null
+++ b/docs/features/battery.md
@@ -0,0 +1,55 @@
1# Battery
2
3This feature provides the high level abstraction for sampling battery level.
4
5## Usage
6
7To use this driver, add the following to your `rules.mk`:
8
9```make
10BATTERY_ENABLE = yes
11```
12
13## Basic Configuration {#basic-configuration}
14
15Add the following to your `config.h`:
16
17|Define |Default |Description |
18|--------------------------|--------|--------------------------------------------------|
19|`BATTERY_SAMPLE_INTERVAL` |`30000` |The time between battery samples in milliseconds. |
20
21## Driver Configuration {#driver-configuration}
22
23See the [Battery Driver](../drivers/battery) documentation for more information.
24
25## Functions
26
27### `uint8_t battery_get_percent(void)` {#api-battery-get-percent}
28
29Sample battery level.
30
31#### Return Value {#api-battery-get-percent-return}
32
33The battery percentage, in the range 0-100.
34
35## Callbacks
36
37### `void battery_percent_changed_user(uint8_t level)` {#api-battery-percent-changed-user}
38
39User hook called when battery level changed.
40
41### Arguments {#api-battery-percent-changed-user-arguments}
42
43 - `uint8_t level`
44 The battery percentage, in the range 0-100.
45
46---
47
48### `void battery_percent_changed_kb(uint8_t level)` {#api-battery-percent-changed-kb}
49
50Keyboard hook called when battery level changed.
51
52### Arguments {#api-battery-percent-changed-kb-arguments}
53
54 - `uint8_t level`
55 The battery percentage, in the range 0-100.
diff --git a/docs/reference_info_json.md b/docs/reference_info_json.md
index cf22317613..84377ef36c 100644
--- a/docs/reference_info_json.md
+++ b/docs/reference_info_json.md
@@ -179,6 +179,32 @@ Configures the [Backlight](features/backlight) feature.
179 * `pins` <Badge type="info">Array: Pin</Badge> 179 * `pins` <Badge type="info">Array: Pin</Badge>
180 * A list of GPIO pins connected to the backlight LEDs (`software` and `timer` drivers only). 180 * A list of GPIO pins connected to the backlight LEDs (`software` and `timer` drivers only).
181 181
182## Battery
183
184Configures the [Battery](features/battery) feature.
185
186* `battery`
187 * `adc`
188 * `pin` <Badge type="info">Pin</Badge> <Badge>Required</Badge>
189 * The GPIO pin connected to the voltage divider.
190 * `reference_voltage` <Badge type="info">Number</Badge>
191 * The ADC reverence voltage, in millivolts.
192 * Default: `3300`
193 * `divider_r1` <Badge type="info">Number</Badge>
194 * The voltage divider resistance, in kOhm. Set to 0 to disable.
195 * Default: `100`
196 * `divider_r2` <Badge type="info">Number</Badge>
197 * The voltage divider resistance, in kOhm. Set to 0 to disable.
198 * Default: `100`
199 * `resolution` <Badge type="info">Number</Badge>
200 * The ADC resolution configured for the ADC Driver.
201 * Default: `10`
202 * `driver` <Badge type="info">String</Badge> <Badge>Required</Badge>
203 * The driver to use. Must be one of `adc`, `custom`, `vendor`.
204 * `sample_interval` <Badge type="info">Number</Badge>
205 * The delay between sampling the battery in milliseconds.
206 * Default: `30000` (30 s)
207
182## Wireless/Bluetooth {#bluetooth} 208## Wireless/Bluetooth {#bluetooth}
183 209
184Configures the [Wireless](features/wireless) feature. 210Configures the [Wireless](features/wireless) feature.
diff --git a/drivers/battery/battery_adc.c b/drivers/battery/battery_adc.c
index cf0e69cb48..145265b5db 100644
--- a/drivers/battery/battery_adc.c
+++ b/drivers/battery/battery_adc.c
@@ -1,23 +1,24 @@
1// Copyright 2025 QMK 1// Copyright 2025 QMK
2// SPDX-License-Identifier: GPL-2.0-or-later 2// SPDX-License-Identifier: GPL-2.0-or-later
3 3
4#include "battery_driver.h"
4#include "analog.h" 5#include "analog.h"
5#include "gpio.h" 6#include "gpio.h"
6 7
7#ifndef BATTERY_PIN 8#ifndef BATTERY_ADC_PIN
8# error("BATTERY_PIN not configured!") 9# error("BATTERY_ADC_PIN not configured!")
9#endif 10#endif
10 11
11#ifndef BATTERY_REF_VOLTAGE_MV 12#ifndef BATTERY_ADC_REF_VOLTAGE_MV
12# define BATTERY_REF_VOLTAGE_MV 3300 13# define BATTERY_ADC_REF_VOLTAGE_MV 3300
13#endif 14#endif
14 15
15#ifndef BATTERY_VOLTAGE_DIVIDER_R1 16#ifndef BATTERY_ADC_VOLTAGE_DIVIDER_R1
16# define BATTERY_VOLTAGE_DIVIDER_R1 100 17# define BATTERY_VOLTAGE_DIVIDER_R1 100
17#endif 18#endif
18 19
19#ifndef BATTERY_VOLTAGE_DIVIDER_R2 20#ifndef BATTERY_ADC_VOLTAGE_DIVIDER_R2
20# define BATTERY_VOLTAGE_DIVIDER_R2 100 21# define BATTERY_ADC_VOLTAGE_DIVIDER_R2 100
21#endif 22#endif
22 23
23// TODO: infer from adc config? 24// TODO: infer from adc config?
@@ -26,16 +27,16 @@
26#endif 27#endif
27 28
28void battery_driver_init(void) { 29void battery_driver_init(void) {
29 gpio_set_pin_input(BATTERY_PIN); 30 gpio_set_pin_input(BATTERY_ADC_PIN);
30} 31}
31 32
32uint16_t battery_driver_get_mv(void) { 33uint16_t battery_driver_get_mv(void) {
33 uint32_t raw = analogReadPin(BATTERY_PIN); 34 uint32_t raw = analogReadPin(BATTERY_ADC_PIN);
34 35
35 uint32_t bat_mv = raw * BATTERY_REF_VOLTAGE_MV / (1 << BATTERY_ADC_RESOLUTION); 36 uint32_t bat_mv = raw * BATTERY_ADC_REF_VOLTAGE_MV / (1 << BATTERY_ADC_RESOLUTION);
36 37
37#if BATTERY_VOLTAGE_DIVIDER_R1 > 0 && BATTERY_VOLTAGE_DIVIDER_R2 > 0 38#if BATTERY_VOLTAGE_DIVIDER_R1 > 0 && BATTERY_ADC_VOLTAGE_DIVIDER_R2 > 0
38 bat_mv = bat_mv * (BATTERY_VOLTAGE_DIVIDER_R1 + BATTERY_VOLTAGE_DIVIDER_R2) / BATTERY_VOLTAGE_DIVIDER_R2; 39 bat_mv = bat_mv * (BATTERY_VOLTAGE_DIVIDER_R1 + BATTERY_ADC_VOLTAGE_DIVIDER_R2) / BATTERY_ADC_VOLTAGE_DIVIDER_R2;
39#endif 40#endif
40 41
41 return bat_mv; 42 return bat_mv;
diff --git a/keyboards/handwired/onekey/keymaps/battery/config.h b/keyboards/handwired/onekey/keymaps/battery/config.h
index 8a1c05d436..b93bfe9000 100644
--- a/keyboards/handwired/onekey/keymaps/battery/config.h
+++ b/keyboards/handwired/onekey/keymaps/battery/config.h
@@ -3,4 +3,4 @@
3 3
4#pragma once 4#pragma once
5 5
6#define BATTERY_PIN ADC_PIN 6#define BATTERY_ADC_PIN ADC_PIN
diff --git a/keyboards/handwired/onekey/keymaps/battery/keymap.c b/keyboards/handwired/onekey/keymaps/battery/keymap.c
index 74191e83fc..793a6ed87e 100644
--- a/keyboards/handwired/onekey/keymaps/battery/keymap.c
+++ b/keyboards/handwired/onekey/keymaps/battery/keymap.c
@@ -2,7 +2,6 @@
2// SPDX-License-Identifier: GPL-2.0-or-later 2// SPDX-License-Identifier: GPL-2.0-or-later
3 3
4#include QMK_KEYBOARD_H 4#include QMK_KEYBOARD_H
5#include "battery.h"
6 5
7const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = { 6const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = {
8 LAYOUT_ortho_1x1(KC_A) 7 LAYOUT_ortho_1x1(KC_A)
@@ -14,8 +13,6 @@ void keyboard_post_init_user(void) {
14// debug_matrix=false; 13// debug_matrix=false;
15// debug_keyboard=true; 14// debug_keyboard=true;
16// debug_mouse=false; 15// debug_mouse=false;
17
18 battery_init();
19} 16}
20 17
21void housekeeping_task_user(void) { 18void housekeeping_task_user(void) {
diff --git a/keyboards/handwired/onekey/keymaps/battery/keymap.json b/keyboards/handwired/onekey/keymaps/battery/keymap.json
index c641dfe773..7232d6d899 100644
--- a/keyboards/handwired/onekey/keymaps/battery/keymap.json
+++ b/keyboards/handwired/onekey/keymaps/battery/keymap.json
@@ -1,6 +1,10 @@
1{ 1{
2 "config": { 2 "config": {
3 "battery": {
4 "driver": "adc"
5 },
3 "features": { 6 "features": {
7 "battery": true,
4 "console": true 8 "console": true
5 } 9 }
6 } 10 }
diff --git a/keyboards/handwired/onekey/keymaps/battery/rules.mk b/keyboards/handwired/onekey/keymaps/battery/rules.mk
deleted file mode 100644
index 06908179ae..0000000000
--- a/keyboards/handwired/onekey/keymaps/battery/rules.mk
+++ /dev/null
@@ -1 +0,0 @@
1BATTERY_DRIVER_REQUIRED = yes
diff --git a/keyboards/handwired/promethium/config.h b/keyboards/handwired/promethium/config.h
index 974a4f951f..c63d3eaead 100644
--- a/keyboards/handwired/promethium/config.h
+++ b/keyboards/handwired/promethium/config.h
@@ -64,8 +64,6 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
64 64
65#define PS2_MOUSE_INIT_DELAY 2000 65#define PS2_MOUSE_INIT_DELAY 2000
66 66
67#define BATTERY_PIN B5
68
69#ifndef __ASSEMBLER__ // assembler doesn't like enum in .h file 67#ifndef __ASSEMBLER__ // assembler doesn't like enum in .h file
70enum led_sequence { 68enum led_sequence {
71 LED_IND_LINUX, 69 LED_IND_LINUX,
diff --git a/keyboards/handwired/promethium/keyboard.json b/keyboards/handwired/promethium/keyboard.json
index fa72908039..2e47bd186a 100644
--- a/keyboards/handwired/promethium/keyboard.json
+++ b/keyboards/handwired/promethium/keyboard.json
@@ -10,6 +10,12 @@
10 "ws2812": { 10 "ws2812": {
11 "pin": "B5" 11 "pin": "B5"
12 }, 12 },
13 "battery": {
14 "driver": "adc",
15 "adc": {
16 "pin": "B5"
17 }
18 },
13 "bluetooth": { 19 "bluetooth": {
14 "driver": "bluefruit_le" 20 "driver": "bluefruit_le"
15 }, 21 },
@@ -22,6 +28,7 @@
22 "nkro": true, 28 "nkro": true,
23 "ps2_mouse": true, 29 "ps2_mouse": true,
24 "ps2": true, 30 "ps2": true,
31 "battery": true,
25 "bluetooth": true 32 "bluetooth": true
26 }, 33 },
27 "build": { 34 "build": {
diff --git a/keyboards/handwired/promethium/rules.mk b/keyboards/handwired/promethium/rules.mk
index 4012f8ca29..ecadca399c 100644
--- a/keyboards/handwired/promethium/rules.mk
+++ b/keyboards/handwired/promethium/rules.mk
@@ -5,7 +5,6 @@ PS2_DRIVER = interrupt
5CUSTOM_MATRIX = yes 5CUSTOM_MATRIX = yes
6 6
7WS2812_DRIVER_REQUIRED = yes 7WS2812_DRIVER_REQUIRED = yes
8BATTERY_DRIVER_REQUIRED = yes
9 8
10SRC += rgbsps.c 9SRC += rgbsps.c
11SRC += matrix.c 10SRC += matrix.c
diff --git a/drivers/battery/battery.c b/quantum/battery/battery.c
index faf3c5a214..faf3c5a214 100644
--- a/drivers/battery/battery.c
+++ b/quantum/battery/battery.c
diff --git a/drivers/battery/battery.h b/quantum/battery/battery.h
index 0985723eaa..0985723eaa 100644
--- a/drivers/battery/battery.h
+++ b/quantum/battery/battery.h
diff --git a/quantum/battery/tests/battery_tests.cpp b/quantum/battery/tests/battery_tests.cpp
new file mode 100644
index 0000000000..ee011be8a8
--- /dev/null
+++ b/quantum/battery/tests/battery_tests.cpp
@@ -0,0 +1,97 @@
1// Copyright 2025 QMK
2// SPDX-License-Identifier: GPL-2.0-or-later
3
4#include "gtest/gtest.h"
5#include "gmock/gmock.h"
6
7using testing::_;
8
9class BatteryDriverMock {
10 public:
11 virtual ~BatteryDriverMock() {}
12
13 // mock methods
14 MOCK_METHOD0(battery_driver_init, void(void));
15 MOCK_METHOD0(battery_driver_sample_percent, uint8_t(void));
16 MOCK_METHOD1(battery_percent_changed_kb, void(uint8_t));
17};
18
19class BatteryTest : public ::testing::Test {
20 public:
21 BatteryTest() {
22 _batteryDriverMock.reset(new ::testing::NiceMock<BatteryDriverMock>());
23 }
24 virtual ~BatteryTest() {
25 _batteryDriverMock.reset();
26 }
27
28 static std::unique_ptr<BatteryDriverMock> _batteryDriverMock;
29};
30
31std::unique_ptr<BatteryDriverMock> BatteryTest::_batteryDriverMock;
32
33extern "C" {
34#include "quantum/battery/battery.h"
35#include "timer.h"
36
37void advance_time(uint32_t ms);
38
39void battery_driver_init(void) {
40 if (BatteryTest::_batteryDriverMock) {
41 BatteryTest::_batteryDriverMock->battery_driver_init();
42 }
43}
44
45uint8_t battery_driver_sample_percent(void) {
46 if (BatteryTest::_batteryDriverMock) {
47 return BatteryTest::_batteryDriverMock->battery_driver_sample_percent();
48 }
49 return 255;
50}
51
52void battery_percent_changed_kb(uint8_t level) {
53 if (BatteryTest::_batteryDriverMock) {
54 BatteryTest::_batteryDriverMock->battery_percent_changed_kb(level);
55 }
56}
57}
58
59TEST_F(BatteryTest, TestInit) {
60 // init driver and initial sample
61 EXPECT_CALL(*_batteryDriverMock, battery_driver_init()).Times(1);
62 EXPECT_CALL(*_batteryDriverMock, battery_driver_sample_percent()).Times(1);
63
64 battery_init();
65}
66
67TEST_F(BatteryTest, TestSampleCached) {
68 // sample before timeout
69 EXPECT_CALL(*_batteryDriverMock, battery_driver_sample_percent()).Times(0);
70
71 advance_time(1);
72 battery_task();
73}
74
75TEST_F(BatteryTest, TestSampleNotCached) {
76 // sample after timeout
77 EXPECT_CALL(*_batteryDriverMock, battery_driver_sample_percent()).Times(1);
78
79 advance_time(60000);
80 battery_task();
81}
82
83TEST_F(BatteryTest, TestGet) {
84 // sample does not directly sample
85 EXPECT_CALL(*_batteryDriverMock, battery_driver_sample_percent()).Times(0);
86
87 battery_get_percent();
88}
89
90TEST_F(BatteryTest, TestChanged) {
91 // callbacks on value changed
92 EXPECT_CALL(*_batteryDriverMock, battery_percent_changed_kb(_)).Times(1);
93
94 battery_task();
95 advance_time(60000);
96 battery_task();
97}
diff --git a/quantum/battery/tests/rules.mk b/quantum/battery/tests/rules.mk
new file mode 100644
index 0000000000..86980f1020
--- /dev/null
+++ b/quantum/battery/tests/rules.mk
@@ -0,0 +1,7 @@
1VPATH += $(DRIVER_PATH)/battery
2
3battery_SRC := \
4 $(PLATFORM_PATH)/timer.c \
5 $(PLATFORM_PATH)/$(PLATFORM_KEY)/timer.c \
6 $(QUANTUM_PATH)/battery/battery.c \
7 $(QUANTUM_PATH)/battery/tests/battery_tests.cpp \
diff --git a/quantum/battery/tests/testlist.mk b/quantum/battery/tests/testlist.mk
new file mode 100644
index 0000000000..e91da865a0
--- /dev/null
+++ b/quantum/battery/tests/testlist.mk
@@ -0,0 +1,2 @@
1TEST_LIST += \
2 battery \
diff --git a/quantum/keyboard.c b/quantum/keyboard.c
index bf4890a51d..173c696e2d 100644
--- a/quantum/keyboard.c
+++ b/quantum/keyboard.c
@@ -122,7 +122,7 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
122#ifdef SPLIT_KEYBOARD 122#ifdef SPLIT_KEYBOARD
123# include "split_util.h" 123# include "split_util.h"
124#endif 124#endif
125#ifdef BATTERY_DRIVER 125#ifdef BATTERY_ENABLE
126# include "battery.h" 126# include "battery.h"
127#endif 127#endif
128#ifdef BLUETOOTH_ENABLE 128#ifdef BLUETOOTH_ENABLE
@@ -532,7 +532,7 @@ void keyboard_init(void) {
532 // init after split init 532 // init after split init
533 pointing_device_init(); 533 pointing_device_init();
534#endif 534#endif
535#ifdef BATTERY_DRIVER 535#ifdef BATTERY_ENABLE
536 battery_init(); 536 battery_init();
537#endif 537#endif
538#ifdef BLUETOOTH_ENABLE 538#ifdef BLUETOOTH_ENABLE
@@ -779,7 +779,7 @@ void keyboard_task(void) {
779 joystick_task(); 779 joystick_task();
780#endif 780#endif
781 781
782#ifdef BATTERY_DRIVER 782#ifdef BATTERY_ENABLE
783 battery_task(); 783 battery_task();
784#endif 784#endif
785 785
diff --git a/quantum/quantum.h b/quantum/quantum.h
index 0036cd784b..176c8a292d 100644
--- a/quantum/quantum.h
+++ b/quantum/quantum.h
@@ -63,6 +63,10 @@
63# include "bootmagic.h" 63# include "bootmagic.h"
64#endif 64#endif
65 65
66#ifdef BATTERY_ENABLE
67# include "battery.h"
68#endif
69
66#ifdef DEFERRED_EXEC_ENABLE 70#ifdef DEFERRED_EXEC_ENABLE
67# include "deferred_exec.h" 71# include "deferred_exec.h"
68#endif 72#endif