Implement battery level interface (#24666)

Co-authored-by: Nick Brassel <nick@tzarc.org>
This commit is contained in:
Joel Challis 2025-02-28 05:46:14 +00:00 committed by GitHub
parent 312f42945d
commit 6ee806f376
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
12 changed files with 275 additions and 0 deletions

31
drivers/battery/battery.c Normal file
View file

@ -0,0 +1,31 @@
// Copyright 2025 QMK
// SPDX-License-Identifier: GPL-2.0-or-later
#include "battery_driver.h"
#include "battery.h"
#include "timer.h"
#ifndef BATTERY_SAMPLE_INTERVAL
# define BATTERY_SAMPLE_INTERVAL 30000
#endif
static uint8_t last_bat_level = 100;
void battery_init(void) {
battery_driver_init();
last_bat_level = battery_driver_sample_percent();
}
void battery_task(void) {
static uint32_t bat_timer = 0;
if (timer_elapsed32(bat_timer) > BATTERY_SAMPLE_INTERVAL) {
last_bat_level = battery_driver_sample_percent();
bat_timer = timer_read32();
}
}
uint8_t battery_get_percent(void) {
return last_bat_level;
}

34
drivers/battery/battery.h Normal file
View file

@ -0,0 +1,34 @@
// Copyright 2025 QMK
// SPDX-License-Identifier: GPL-2.0-or-later
#pragma once
#include <stdint.h>
/**
* \file
*
* \defgroup battery Battery API
*
* \brief API to query battery status.
* \{
*/
/**
* \brief Initialize the battery driver.
*/
void battery_init(void);
/**
* \brief Perform housekeeping tasks.
*/
void battery_task(void);
/**
* \brief Sample battery level.
*
* \return The battery percentage, in the range 0-100.
*/
uint8_t battery_get_percent(void);
/** \} */

View file

@ -0,0 +1,55 @@
// Copyright 2025 QMK
// SPDX-License-Identifier: GPL-2.0-or-later
#include "analog.h"
#include "gpio.h"
#ifndef BATTERY_PIN
# error("BATTERY_PIN not configured!")
#endif
#ifndef BATTERY_REF_VOLTAGE_MV
# define BATTERY_REF_VOLTAGE_MV 3300
#endif
#ifndef BATTERY_VOLTAGE_DIVIDER_R1
# define BATTERY_VOLTAGE_DIVIDER_R1 100
#endif
#ifndef BATTERY_VOLTAGE_DIVIDER_R2
# define BATTERY_VOLTAGE_DIVIDER_R2 100
#endif
// TODO: infer from adc config?
#ifndef BATTERY_ADC_RESOLUTION
# define BATTERY_ADC_RESOLUTION 10
#endif
void battery_driver_init(void) {
gpio_set_pin_input(BATTERY_PIN);
}
uint16_t battery_driver_get_mv(void) {
uint32_t raw = analogReadPin(BATTERY_PIN);
uint32_t bat_mv = raw * BATTERY_REF_VOLTAGE_MV / (1 << BATTERY_ADC_RESOLUTION);
#if BATTERY_VOLTAGE_DIVIDER_R1 > 0 && BATTERY_VOLTAGE_DIVIDER_R2 > 0
bat_mv = bat_mv * (BATTERY_VOLTAGE_DIVIDER_R1 + BATTERY_VOLTAGE_DIVIDER_R2) / BATTERY_VOLTAGE_DIVIDER_R2;
#endif
return bat_mv;
}
uint8_t battery_driver_sample_percent(void) {
uint16_t bat_mv = battery_driver_get_mv();
// https://github.com/zmkfirmware/zmk/blob/3f7c9d7cc4f46617faad288421025ea2a6b0bd28/app/module/drivers/sensor/battery/battery_common.c#L33
if (bat_mv >= 4200) {
return 100;
} else if (bat_mv <= 3450) {
return 0;
}
return bat_mv * 2 / 15 - 459;
}

View file

@ -0,0 +1,29 @@
// Copyright 2025 QMK
// SPDX-License-Identifier: GPL-2.0-or-later
#pragma once
#include <stdint.h>
/**
* \file
*
* \defgroup battery Battery Driver API
*
* \brief API to query battery status.
* \{
*/
/**
* \brief Initialize the battery driver. This function must be called only once, before any of the below functions can be called.
*/
void battery_driver_init(void);
/**
* \brief Sample battery level.
*
* \return The battery percentage, in the range 0-100.
*/
uint8_t battery_driver_sample_percent(void);
/** \} */