aboutsummaryrefslogtreecommitdiff
path: root/drivers/battery/battery_adc.c
blob: cf0e69cb48a346547d0d8a255717e2c7e80bb222 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
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;
}