summaryrefslogtreecommitdiff
path: root/quantum
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 /quantum
parentf29d8117bf877a4df1f88f40e0131f4465748540 (diff)
Refactor battery driver (#25550)
Diffstat (limited to 'quantum')
-rw-r--r--quantum/battery/battery.c41
-rw-r--r--quantum/battery/battery.h46
-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
7 files changed, 200 insertions, 3 deletions
diff --git a/quantum/battery/battery.c b/quantum/battery/battery.c
new file mode 100644
index 0000000000..faf3c5a214
--- /dev/null
+++ b/quantum/battery/battery.c
@@ -0,0 +1,41 @@
1// Copyright 2025 QMK
2// SPDX-License-Identifier: GPL-2.0-or-later
3
4#include "battery_driver.h"
5#include "battery.h"
6#include "timer.h"
7
8#ifndef BATTERY_SAMPLE_INTERVAL
9# define BATTERY_SAMPLE_INTERVAL 30000
10#endif
11
12static uint8_t last_bat_level = 100;
13
14void battery_init(void) {
15 battery_driver_init();
16
17 last_bat_level = battery_driver_sample_percent();
18}
19
20__attribute__((weak)) void battery_percent_changed_user(uint8_t level) {}
21__attribute__((weak)) void battery_percent_changed_kb(uint8_t level) {}
22
23static void handle_percent_changed(void) {
24 battery_percent_changed_user(last_bat_level);
25 battery_percent_changed_kb(last_bat_level);
26}
27
28void battery_task(void) {
29 static uint32_t bat_timer = 0;
30 if (timer_elapsed32(bat_timer) > BATTERY_SAMPLE_INTERVAL) {
31 last_bat_level = battery_driver_sample_percent();
32
33 handle_percent_changed();
34
35 bat_timer = timer_read32();
36 }
37}
38
39uint8_t battery_get_percent(void) {
40 return last_bat_level;
41}
diff --git a/quantum/battery/battery.h b/quantum/battery/battery.h
new file mode 100644
index 0000000000..0985723eaa
--- /dev/null
+++ b/quantum/battery/battery.h
@@ -0,0 +1,46 @@
1// Copyright 2025 QMK
2// SPDX-License-Identifier: GPL-2.0-or-later
3
4#pragma once
5
6#include <stdint.h>
7
8/**
9 * \file
10 *
11 * \defgroup battery Battery API
12 *
13 * \brief API to query battery status.
14 * \{
15 */
16
17/**
18 * \brief Initialize the battery driver.
19 */
20void battery_init(void);
21
22/**
23 * \brief Perform housekeeping tasks.
24 */
25void battery_task(void);
26
27/**
28 * \brief Sample battery level.
29 *
30 * \return The battery percentage, in the range 0-100.
31 */
32uint8_t battery_get_percent(void);
33
34/**
35 * \brief user hook called when battery level changed.
36 *
37 */
38void battery_percent_changed_user(uint8_t level);
39
40/**
41 * \brief keyboard hook called when battery level changed.
42 *
43 */
44void battery_percent_changed_kb(uint8_t level);
45
46/** \} */
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