Files
blinky/src/mode_switch_module.c

217 lines
4.8 KiB
C
Raw Normal View History

#include <stdbool.h>
#include <stdint.h>
#include <app_event_manager.h>
#define MODULE mode_switch_module
#include <caf/events/module_state_event.h>
#include <caf/events/power_event.h>
#include <zephyr/device.h>
#include <zephyr/devicetree.h>
#include <zephyr/drivers/sensor.h>
#include <zephyr/kernel.h>
#include <zephyr/logging/log.h>
#include <zephyr/pm/device.h>
#include "module_lifecycle.h"
#include "mode_switch_event.h"
LOG_MODULE_REGISTER(MODULE, LOG_LEVEL_INF);
#define MODE_SWITCH_ADC_NODE DT_NODELABEL(mode_switch_adc)
#define MODE_SWITCH_SAMPLE_INTERVAL K_MSEC(500)
#define MODE_SWITCH_USB_MAX_MV 825
#define MODE_SWITCH_24G_MAX_MV 2475
BUILD_ASSERT(DT_NODE_EXISTS(MODE_SWITCH_ADC_NODE),
"Missing mode_switch_adc node in devicetree");
struct mode_switch_module_ctx {
struct module_lifecycle_ctx lc;
const struct device *mode_switch_adc_dev;
struct k_work_delayable mode_switch_sample_work;
enum mode_switch_mode last_mode;
};
static int do_init(void);
static int do_start(void);
static int do_stop(void);
static const struct module_lifecycle_cfg lifecycle_cfg = {
.mode = ML_MODE_POWER,
.stopped_state = MODULE_STATE_STANDBY,
};
static const struct module_lifecycle_ops lifecycle_ops = {
.do_init = do_init,
.do_start = do_start,
.do_stop = do_stop,
};
static struct mode_switch_module_ctx ctx = {
.lc = {
.state = LC_UNINIT,
.cfg = &lifecycle_cfg,
.ops = &lifecycle_ops,
},
.mode_switch_adc_dev = DEVICE_DT_GET(MODE_SWITCH_ADC_NODE),
};
static enum mode_switch_mode detect_mode(uint16_t voltage_mv)
{
if (voltage_mv < MODE_SWITCH_USB_MAX_MV) {
return MODE_SWITCH_USB;
}
if (voltage_mv < MODE_SWITCH_24G_MAX_MV) {
return MODE_SWITCH_24G;
}
return MODE_SWITCH_BLE;
}
static int mode_switch_enable(bool enable)
{
enum pm_device_action action = enable ? PM_DEVICE_ACTION_RESUME
: PM_DEVICE_ACTION_SUSPEND;
int err = pm_device_action_run(ctx.mode_switch_adc_dev, action);
if (err && (err != -EALREADY) && (err != -ENOTSUP)) {
LOG_ERR("Cannot %s mode switch ADC (%d)",
enable ? "resume" : "suspend", err);
return err;
}
return 0;
}
static void mode_switch_sample_fn(struct k_work *work)
{
struct sensor_value voltage;
int err;
ARG_UNUSED(work);
if (!module_lifecycle_is_running(&ctx.lc)) {
return;
}
err = sensor_sample_fetch(ctx.mode_switch_adc_dev);
if (err) {
LOG_WRN("Mode switch ADC sample fetch failed (%d)", err);
goto reschedule;
}
err = sensor_channel_get(ctx.mode_switch_adc_dev, SENSOR_CHAN_VOLTAGE,
&voltage);
if (err) {
LOG_WRN("Mode switch ADC channel get failed (%d)", err);
goto reschedule;
}
uint16_t sample_mv = (uint16_t)((voltage.val1 * 1000) + (voltage.val2 / 1000));
enum mode_switch_mode mode = detect_mode(sample_mv);
if ((ctx.last_mode == MODE_SWITCH_INVALID) || (mode != ctx.last_mode)) {
feat(events): 添加事件提交函数到各个头文件中 为多个事件头文件添加了静态内联提交函数,包括: - bat_state_event: 添加submit_bat_state_event函数 - ble_serial_rx_event: 添加submit_ble_serial_rx_event函数 - ble_serial_tx_event: 添加submit_ble_serial_tx_event函数 - cdc_proto_tx_event: 添加submit_cdc_proto_tx_event函数 - datetime_event: 添加submit_datetime_event函数 - encoder_event: 添加submit_encoder_event函数 - function_bitmap_update_event: 添加submit_function_bitmap_update_event函数 - hid_led_event: 添加submit_hid_led_event函数 - hid_report_sent_event: 添加submit_hid_report_sent_event函数 - hid_transport_state_event: 添加submit_hid_transport_state_event函数 - hid_tx_report_event: 添加submit_hid_tx_report_event函数 - key_function_event: 添加submit_key_function_event函数 - keyboard_hid_report_event: 添加submit_keyboard_hid_report_event函数 - led_strip_en_event: 添加submit_led_strip_en_event函数 - mode_switch_event: 添加submit_mode_switch_event函数 - set_protocol_event: 添加submit_set_protocol_event函数 - theme_rgb_update_event: 添加submit_theme_rgb_update_event函数 - time_sync_event: 添加submit_time_sync_event函数 - usb_cdc_rx_event: 添加submit_usb_cdc_rx_event函数 - usb_cdc_tx_event: 添加submit_usb_cdc_tx_event函数 - usb_device_state_event: 添加submit_usb_device_state_event函数 - usb_function_ready_event: 添加submit_usb_function_ready_event函数 - usb_prepare_event: 添加submit_usb_prepare_event函数 这些函数提供了一致的事件提交接口,简化了事件创建和提交过程。
2026-04-14 16:42:04 +08:00
submit_mode_switch_event(mode, sample_mv);
ctx.last_mode = mode;
}
reschedule:
if (module_lifecycle_is_running(&ctx.lc)) {
k_work_reschedule(&ctx.mode_switch_sample_work,
MODE_SWITCH_SAMPLE_INTERVAL);
}
}
static int do_init(void)
{
if (!device_is_ready(ctx.mode_switch_adc_dev)) {
LOG_ERR("Mode switch ADC device not ready");
return -ENODEV;
}
k_work_init_delayable(&ctx.mode_switch_sample_work, mode_switch_sample_fn);
ctx.last_mode = MODE_SWITCH_INVALID;
return 0;
}
static int do_start(void)
{
int err;
if (module_lifecycle_is_running(&ctx.lc)) {
return 0;
}
err = mode_switch_enable(true);
if (err) {
return err;
}
k_work_reschedule(&ctx.mode_switch_sample_work, K_NO_WAIT);
return 0;
}
static int do_stop(void)
{
if (!module_lifecycle_is_running(&ctx.lc)) {
return 0;
}
(void)k_work_cancel_delayable(&ctx.mode_switch_sample_work);
(void)mode_switch_enable(false);
return 0;
}
static bool app_event_handler(const struct app_event_header *aeh)
{
if (is_module_state_event(aeh)) {
const struct module_state_event *event = cast_module_state_event(aeh);
if (check_state(event, MODULE_ID(main), MODULE_STATE_READY)) {
(void)module_set_lifecycle(&ctx.lc, LC_RUNNING);
return false;
}
if (check_state(event, MODULE_ID(mode_policy_module),
MODULE_STATE_READY)) {
if (ctx.last_mode != MODE_SWITCH_INVALID) {
submit_mode_switch_event(ctx.last_mode, 0U);
}
return false;
}
return false;
}
if (is_power_down_event(aeh)) {
if (module_lifecycle_is_initialized(&ctx.lc)) {
(void)module_set_lifecycle(&ctx.lc, LC_STOPPED);
}
return false;
}
if (is_wake_up_event(aeh)) {
if (module_lifecycle_is_initialized(&ctx.lc)) {
(void)module_set_lifecycle(&ctx.lc, LC_RUNNING);
}
return false;
}
__ASSERT_NO_MSG(false);
return false;
}
APP_EVENT_LISTENER(MODULE, app_event_handler);
APP_EVENT_SUBSCRIBE(MODULE, module_state_event);
APP_EVENT_SUBSCRIBE_EARLY(MODULE, power_down_event);
APP_EVENT_SUBSCRIBE(MODULE, wake_up_event);