You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
343 lines
11 KiB
343 lines
11 KiB
#include "device_ctrl_service.h"
|
|
|
|
#include "app_event_distribute.h"
|
|
#include "board/board_battery_state.h"
|
|
#include "board/board_beep_ctrl.h"
|
|
#include "board/board_button.h"
|
|
#include "board/board_light_ctrl.h"
|
|
#include "board/board_sdcard_driver.h"
|
|
#include "heart_wave_sample_service.h"
|
|
#include "sample_data_manager_service.h"
|
|
#include "zble_module.h"
|
|
#include "zdatachannel_service.h"
|
|
//
|
|
APP_TIMER_DEF(m_state_machine_driver_tmr); // 状态机驱动定时器
|
|
static device_state_t m_device_state = kdevice_state_standby; // 设备状态
|
|
static uint32_t m_change_to_cur_state_tp = 0; // 切换到当前状态的时间戳
|
|
static int m_sample_data_fd = -1; // 采集数据文件描述符
|
|
|
|
/*******************************************************************************
|
|
* 函数列表 *
|
|
*******************************************************************************/
|
|
|
|
void DeviceCtrl_change_to_state(device_state_t state);
|
|
uint32_t DeviceCtrl_cur_state_haspassed_ms();
|
|
device_state_t DeviceCtrl_now_state();
|
|
|
|
/*******************************************************************************
|
|
* 事件路由 *
|
|
*******************************************************************************/
|
|
|
|
static void state_machine_driver_tmr_cb(void* p_context) { //
|
|
static app_event_t appevent;
|
|
appevent.eventType = kevent_tmr_scheduler;
|
|
AppEvent_pushEvent(&appevent);
|
|
}
|
|
/**
|
|
* @brief 按键事件处理
|
|
*/
|
|
static void board_button_cb(ButtonIndex_t pin_no, ButtonAction_t button_action) { //
|
|
static app_event_t event;
|
|
event.eventType = button_action == kButtonAction_push ? kevent_button_push_event : kevent_button_release_event;
|
|
AppEvent_pushEvent(&event);
|
|
}
|
|
|
|
static void zble_event_listener(zble_event_t* ble_event) { //
|
|
static app_event_t event;
|
|
if (ble_event->eventType == kzble_event_connected) {
|
|
event.eventType = kevent_ble_connect_event;
|
|
AppEvent_pushEvent(&event);
|
|
} else if (ble_event->eventType == kzble_event_disconnected) {
|
|
event.eventType = kevent_ble_disconnect_event;
|
|
AppEvent_pushEvent(&event);
|
|
}
|
|
}
|
|
|
|
/*******************************************************************************
|
|
* 事件处理 *
|
|
*******************************************************************************/
|
|
static bool m_ispoweron = false;
|
|
static bool m_drop_state_triggered = false;
|
|
static void poweroff() {
|
|
if (!m_ispoweron) return;
|
|
BoardBeepCtrl_unload();
|
|
BoardLight_unload();
|
|
BoardBattery_unload();
|
|
BoardButton_unload();
|
|
SampleDataMgr_unloadDriver();
|
|
hwss_unload();
|
|
DeviceCtrl_change_to_state(kdevice_state_standby);
|
|
zble_module_stop_adv();
|
|
BoardLight_setGreenLightEffect(kLightEffect_close);
|
|
|
|
// 进入深度睡眠前,使能唤醒引脚
|
|
BoardButton_enable_sense();
|
|
app_timer_stop_all();
|
|
// 系统进入深度睡眠
|
|
sd_power_system_off();
|
|
NVIC_SystemReset();
|
|
m_ispoweron = false;
|
|
}
|
|
static void poweron() {
|
|
if (m_ispoweron) {
|
|
return;
|
|
}
|
|
|
|
BoardBeepCtrl_load();
|
|
BoardLight_load();
|
|
BoardBattery_load();
|
|
BoardButton_load();
|
|
SampleDataMgr_loadDriver();
|
|
hwss_load();
|
|
DeviceCtrl_change_to_state(kdevice_state_ready);
|
|
zble_module_start_adv();
|
|
BoardLight_setGreenLightEffect(kLightEffect_slowFlash);
|
|
m_ispoweron = true;
|
|
}
|
|
|
|
static sample_data_filename_t* cratefilename() {
|
|
static ztm_t tm;
|
|
static sample_data_filename_t sampledata_file_name;
|
|
memset(&sampledata_file_name, 0, sizeof(sampledata_file_name));
|
|
znordic_rtc_gettime(&tm);
|
|
|
|
sampledata_file_name.year = tm.tm_year + 1900 - 2000;
|
|
sampledata_file_name.month = tm.tm_mon + 1;
|
|
sampledata_file_name.day = tm.tm_mday;
|
|
sampledata_file_name.hour = tm.tm_hour;
|
|
sampledata_file_name.min = tm.tm_min;
|
|
sampledata_file_name.sec = tm.tm_sec;
|
|
return &sampledata_file_name;
|
|
}
|
|
|
|
static void prvf_change_to_standby_state() {
|
|
poweroff();
|
|
DeviceCtrl_change_to_state(kdevice_state_standby);
|
|
}
|
|
static void prvf_change_to_ready_state() {
|
|
poweron();
|
|
DeviceCtrl_change_to_state(kdevice_state_ready);
|
|
BoardBeepCtrl_setEffect(kBoardBeepEffect_oneShortBeep);
|
|
}
|
|
static const char* dropstate(uint8_t drop0, uint8_t drop1) {
|
|
static char state[128];
|
|
sprintf(state, "drop0:%d%d%d%d-%d%d%d%d drop1:%d%d%d%d-%d%d%d%d", //
|
|
drop0 & 0x80 ? 1 : 0, drop0 & 0x40 ? 1 : 0, drop0 & 0x20 ? 1 : 0, drop0 & 0x10 ? 1 : 0, //
|
|
drop0 & 0x08 ? 1 : 0, drop0 & 0x04 ? 1 : 0, drop0 & 0x02 ? 1 : 0, drop0 & 0x01 ? 1 : 0, //
|
|
drop1 & 0x80 ? 1 : 0, drop1 & 0x40 ? 1 : 0, drop1 & 0x20 ? 1 : 0, drop1 & 0x10 ? 1 : 0, //
|
|
drop1 & 0x08 ? 1 : 0, drop1 & 0x04 ? 1 : 0, drop1 & 0x02 ? 1 : 0, drop1 & 0x01 ? 1 : 0 //
|
|
);
|
|
return state;
|
|
}
|
|
static void prvf_change_to_sample_state() { //
|
|
if (m_device_state == kdevice_state_sampling) {
|
|
return;
|
|
}
|
|
DeviceCtrl_change_to_state(kdevice_state_sampling);
|
|
}
|
|
|
|
static void app_event_listener(void* p_event_data, uint16_t event_size) { //
|
|
app_event_t* event = (app_event_t*)p_event_data;
|
|
static bool inited;
|
|
if (!inited) {
|
|
nrf_gpio_cfg_input(BUTTON_PIN, NRF_GPIO_PIN_NOPULL);
|
|
inited = true;
|
|
}
|
|
ZLOGI("button %d", nrf_gpio_pin_read(BUTTON_PIN));
|
|
|
|
/*******************************************************************************
|
|
* 状态无关事件处理 *
|
|
*******************************************************************************/
|
|
if (event->eventType == kevent_ble_connect_event) {
|
|
BoardLight_setGreenLightEffect(kLightEffect_open);
|
|
return;
|
|
} else if (event->eventType == kevent_ble_disconnect_event) {
|
|
BoardLight_setGreenLightEffect(kLightEffect_slowFlash);
|
|
return;
|
|
}
|
|
|
|
/*******************************************************************************
|
|
* 状态机 *
|
|
*******************************************************************************/
|
|
// ZLOGI("state %d", m_device_state);
|
|
if (m_device_state == kdevice_state_standby) {
|
|
// 休眠模式现在是深度睡眠,所以永远不会触发这个回调
|
|
}
|
|
|
|
//
|
|
else if (m_device_state == kdevice_state_ready) {
|
|
if (!zble_module_is_connected() && DeviceCtrl_cur_state_haspassed_ms() > APP_AUTO_SLEEP_TIMEOUT_MS) {
|
|
ZLOGI("auto sleep");
|
|
prvf_change_to_standby_state();
|
|
}
|
|
|
|
if (event->eventType == kevent_start_sample_cmd_event) {
|
|
ZLOGI("start sample");
|
|
// SD卡连接到单片机
|
|
SampleDataMgr_changeToLocalMode();
|
|
// 创建文件
|
|
m_sample_data_fd = SampleDataMgr_open(cratefilename(), kwrflag_write_only);
|
|
ZASSERT(m_sample_data_fd > 0);
|
|
// 切换到采集状态
|
|
prvf_change_to_sample_state();
|
|
// 开始采集
|
|
hwss_start_capture();
|
|
|
|
{
|
|
static app_event_t event;
|
|
event.eventType = kevent_sample_start_event;
|
|
AppEvent_pushEvent(&event);
|
|
}
|
|
|
|
BoardBeepCtrl_setEffect(kBoardBeepEffect_oneShortBeep);
|
|
}
|
|
}
|
|
//
|
|
else if (m_device_state == kdevice_state_sampling) {
|
|
// 采集的字节长度超过最大字节长度,停止采集
|
|
|
|
if (event->eventType == kevent_capture_data_block_event) {
|
|
SampleDataMgr_write(m_sample_data_fd, (uint8_t*)event->val.block_sensor_data.data, event->val.block_sensor_data.len);
|
|
}
|
|
|
|
uint8_t drop0 = hwss_get_drop_state0();
|
|
uint8_t drop1 = hwss_get_drop_state1();
|
|
|
|
if ((drop0 || drop1) && event->eventType == kevent_tmr_scheduler) {
|
|
ZLOGI("[%d] drop %s", znordic_getpower_on_ms(), dropstate(drop0, drop1));
|
|
}
|
|
|
|
bool stopcapture = false;
|
|
if (SampleDataMgr_getFileSizeByFd(m_sample_data_fd) > SDCARD_MAX_FILE_SIZE) {
|
|
ZLOGI("stop sample because file size is too large");
|
|
stopcapture = true;
|
|
} else if (event->eventType == kevent_stop_sample_cmd_event) {
|
|
ZLOGI("stop sample because stop sample event");
|
|
stopcapture = true;
|
|
}
|
|
|
|
if (stopcapture) {
|
|
// 关闭文件
|
|
SampleDataMgr_close(m_sample_data_fd);
|
|
// SD卡连接到外部typec
|
|
SampleDataMgr_changeToExtMode();
|
|
// 停止采集
|
|
hwss_stop_capture();
|
|
// 切换到待机状态
|
|
prvf_change_to_ready_state();
|
|
|
|
{
|
|
static app_event_t event;
|
|
event.eventType = kevent_sample_stop_event;
|
|
AppEvent_pushEvent(&event);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
void DeviceCtrl_startSample() {
|
|
ZLOGI("start sample");
|
|
static app_event_t event;
|
|
event.eventType = kevent_start_sample_cmd_event;
|
|
AppEvent_pushEvent(&event);
|
|
}
|
|
void DeviceCtrl_stopSample() {
|
|
ZLOGI("stop sample");
|
|
static app_event_t event;
|
|
event.eventType = kevent_stop_sample_cmd_event;
|
|
AppEvent_pushEvent(&event);
|
|
}
|
|
|
|
/*******************************************************************************
|
|
* EXTERN *
|
|
*******************************************************************************/
|
|
|
|
void DeviceCtrl_init() {
|
|
// 蜂鸣器初始化
|
|
BoardBeepCtrl_init();
|
|
// 板载指示灯初始化
|
|
BoardLight_Init();
|
|
// 按键初始化
|
|
BoardButton_Init(board_button_cb);
|
|
// 电池初始化
|
|
BoardBattery_init();
|
|
// SD卡初始化
|
|
SampleDataMgr_init();
|
|
// 心电采集服务初始化
|
|
hwss_init();
|
|
// 注册事件监听
|
|
AppEvent_regListener(app_event_listener);
|
|
// 监听蓝牙事件
|
|
zble_module_reglistener(zble_event_listener);
|
|
// 切换到待机状态
|
|
prvf_change_to_ready_state();
|
|
|
|
ZERROR_CHECK(app_timer_create(&m_state_machine_driver_tmr, APP_TIMER_MODE_REPEATED, state_machine_driver_tmr_cb));
|
|
ZERROR_CHECK(app_timer_start(m_state_machine_driver_tmr, APP_TIMER_TICKS(100), NULL)); // 200HZ采样
|
|
}
|
|
|
|
/*******************************************************************************
|
|
* UTILS *
|
|
*******************************************************************************/
|
|
void DeviceCtrl_change_to_state(device_state_t state) {
|
|
ZLOGI("change state from %s to %s", ds2str(m_device_state), ds2str(state));
|
|
m_device_state = state;
|
|
m_change_to_cur_state_tp = znordic_getpower_on_ms();
|
|
}
|
|
uint32_t DeviceCtrl_cur_state_haspassed_ms() { return znordic_haspassed_ms(m_change_to_cur_state_tp); }
|
|
device_state_t DeviceCtrl_now_state() { return m_device_state; }
|
|
|
|
#if 0
|
|
static void DeviceCtrl_test() {
|
|
/**
|
|
* @brief
|
|
* 1. 测试蜂鸣器
|
|
* 2. 测试按键
|
|
* 3. 测试LED
|
|
* 4. 测试指示灯
|
|
* . SD卡
|
|
* 5. 测试电池电量采集
|
|
*/
|
|
#if 0
|
|
//蜂鸣器测试
|
|
BoardBeepCtrl_init();
|
|
BoardBeepCtrl_load();
|
|
BoardBeepCtrl_setEffect(kBoardBeepEffect_continuousShortBeep);
|
|
#endif
|
|
|
|
#if 1
|
|
// BoardButton_Init(board_button_cb);
|
|
|
|
#endif
|
|
|
|
#if 0
|
|
BoardLight_Init();
|
|
BoardLight_load();
|
|
BoardLight_setGreenLightEffect(kLightEffect_slowFlash);
|
|
#endif
|
|
#if 0
|
|
Board_sdcardInit();
|
|
Board_sdcardConnectToInternal();
|
|
Board_sdcardConnectToExt();
|
|
|
|
Board_sdcardConnectToInternal();
|
|
Board_sdcardConnectToExt();
|
|
|
|
#endif
|
|
#if 0
|
|
sample_data_mgr_init();
|
|
sample_data_mgr_loadDriver();
|
|
sample_data_mgr_change_to_local_mode();
|
|
|
|
sample_data_filename_t filename;
|
|
int fd = sample_data_mgr_open(&filename, kwrflag_write_only);
|
|
sample_data_mgr_write(fd, "123456", 6);
|
|
sample_data_mgr_close(fd);
|
|
sample_data_mgr_change_to_ext_mode();
|
|
#endif
|
|
#if 1
|
|
// 蜂鸣器测试
|
|
|
|
#endif
|
|
}
|
|
#endif
|