feat(keyboard): 添加蓝牙HID支持和电池状态事件
- 添加BLE相关模块:ble_adv_ctrl_module、ble_adv_uuid16、ble_bas_module、 ble_hid_module - 新增电池状态事件(bat_state_event)用于监控电池电量、充电状态 - 在多个事件中添加HID_TRANSPORT_BLE支持,包括hid_led_event、 set_protocol_event等 - 更新配置文件prj.conf以启用蓝牙功能、HID服务和设置系统 - 修改电池模块以计算并报告电池SOC百分比 - 集成CAF设置加载器以管理蓝牙配对信息
This commit is contained in:
@@ -1,5 +1,6 @@
|
||||
#include <stdbool.h>
|
||||
#include <stdint.h>
|
||||
#include <string.h>
|
||||
|
||||
#include <app_event_manager.h>
|
||||
|
||||
@@ -16,11 +17,15 @@
|
||||
#include <zephyr/logging/log.h>
|
||||
#include <zephyr/pm/device.h>
|
||||
|
||||
#include "bat_state_event.h"
|
||||
|
||||
LOG_MODULE_REGISTER(MODULE, LOG_LEVEL_INF);
|
||||
|
||||
#define VBATT_NODE DT_PATH(vbatt)
|
||||
#define IP5306_NODE DT_NODELABEL(ip5306)
|
||||
#define BATTERY_SAMPLE_INTERVAL K_SECONDS(1)
|
||||
#define BATTERY_SOC_MIN_MV 3300
|
||||
#define BATTERY_SOC_MAX_MV 4200
|
||||
|
||||
BUILD_ASSERT(DT_NODE_HAS_STATUS(VBATT_NODE, okay),
|
||||
"Missing /vbatt voltage-divider node in devicetree");
|
||||
@@ -30,6 +35,12 @@ BUILD_ASSERT(DT_NODE_HAS_STATUS(IP5306_NODE, okay),
|
||||
static const struct device *const vbatt_dev = DEVICE_DT_GET(VBATT_NODE);
|
||||
static const struct device *const ip5306_dev = DEVICE_DT_GET(IP5306_NODE);
|
||||
static struct k_work_delayable battery_sample_work;
|
||||
static struct {
|
||||
bool valid;
|
||||
uint8_t soc;
|
||||
bool charging;
|
||||
bool full;
|
||||
} last_bat_state;
|
||||
static bool initialized;
|
||||
static bool running;
|
||||
|
||||
@@ -52,6 +63,48 @@ static int measurement_enable(bool enable)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static uint8_t battery_soc_from_mv(int voltage_mv)
|
||||
{
|
||||
const int span_mv = BATTERY_SOC_MAX_MV - BATTERY_SOC_MIN_MV;
|
||||
int bucket;
|
||||
|
||||
if (voltage_mv <= BATTERY_SOC_MIN_MV) {
|
||||
return 0U;
|
||||
}
|
||||
|
||||
if (voltage_mv >= BATTERY_SOC_MAX_MV) {
|
||||
return 100U;
|
||||
}
|
||||
|
||||
bucket = ((voltage_mv - BATTERY_SOC_MIN_MV) * 10 + (span_mv / 2)) / span_mv;
|
||||
|
||||
return (uint8_t)(bucket * 10);
|
||||
}
|
||||
|
||||
static void submit_bat_state_event(uint8_t soc, bool charging, bool full)
|
||||
{
|
||||
struct bat_state_event *event;
|
||||
|
||||
if (last_bat_state.valid &&
|
||||
(last_bat_state.soc == soc) &&
|
||||
(last_bat_state.charging == charging) &&
|
||||
(last_bat_state.full == full)) {
|
||||
return;
|
||||
}
|
||||
|
||||
last_bat_state.valid = true;
|
||||
last_bat_state.soc = soc;
|
||||
last_bat_state.charging = charging;
|
||||
last_bat_state.full = full;
|
||||
|
||||
event = new_bat_state_event();
|
||||
event->soc = soc;
|
||||
event->charging = charging;
|
||||
event->full = full;
|
||||
|
||||
APP_EVENT_SUBMIT(event);
|
||||
}
|
||||
|
||||
static void battery_sample_fn(struct k_work *work)
|
||||
{
|
||||
struct ip5306_status pmic_status;
|
||||
@@ -84,8 +137,9 @@ static void battery_sample_fn(struct k_work *work)
|
||||
}
|
||||
|
||||
voltage_mv = sensor_value_to_mv(&voltage);
|
||||
// LOG_INF("Battery: %d mV, charging=%d, full=%d",
|
||||
// voltage_mv, pmic_status.charging, pmic_status.full);
|
||||
submit_bat_state_event(battery_soc_from_mv(voltage_mv),
|
||||
pmic_status.charging,
|
||||
pmic_status.full);
|
||||
|
||||
reschedule:
|
||||
if (running) {
|
||||
@@ -112,6 +166,7 @@ static int module_init(void)
|
||||
}
|
||||
|
||||
k_work_init_delayable(&battery_sample_work, battery_sample_fn);
|
||||
memset(&last_bat_state, 0, sizeof(last_bat_state));
|
||||
power_manager_restrict(MODULE_IDX(MODULE), POWER_MANAGER_LEVEL_SUSPENDED);
|
||||
|
||||
return 0;
|
||||
|
||||
Reference in New Issue
Block a user