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.
 
 
 
 

391 lines
15 KiB

#include <math.h>
#include "app_event.h"
#include "app_event_distribute.h"
#include "basic/device_version_info_mgr.h"
#include "ble_cmd_process_service.h"
#include "board/board_adc_module_ctrl.h"
#include "board/board_battery_state.h"
#include "board/board_beep_ctrl.h"
#include "board/board_ecg_sensor.h"
#include "board/board_light_ctrl.h"
#include "config.h"
#include "display_manager.h"
#include "heart_wave_sample_service.h"
#include "one_conduction_board.h"
#include "sample_data_manager.h"
#include "zble_module.h"
#include "zdatachannel_service.h"
#include "znordic.h"
/*******************************************************************************
* GLOBAL *
*******************************************************************************/
APP_TIMER_DEF(m_state_machine_driver_tmr); // 状态机驱动定时器
// APP_TIMER_DEF(m_plod_state_event_detect_tmr); // 导联连接状态检测定时器
// APP_TIMER_DEF(m_charge_event_detect_tmr); // 充电事件检测
static int m_cur_fd;
static sample_data_filename_t sampledata_file_name;
#define SCHED_MAX_EVENT_DATA_SIZE MAX(sizeof(app_event_t), APP_TIMER_SCHED_EVENT_DATA_SIZE)
/*******************************************************************************
* 函数声明 *
*******************************************************************************/
// 业务事件处理函数
/*******************************************************************************
* 事件生成器 *
*******************************************************************************/
// static void m_charge_event_detect_tmr_cb(void* p_context) { //
// static app_event_t appevent;
// memset(&appevent, 0, sizeof(appevent));
// static bool ischarging = false;
// }
static void state_machine_driver_tmr_cb(void* p_context) { //
static app_event_t appevent;
appevent.eventType = kevent_tmr_scheduler_event;
AppEvent_pushEvent(&appevent);
}
/*******************************************************************************
* 事件处理 *
*******************************************************************************/
static bool m_poweronflag;
static void power_on() {
if (m_poweronflag) {
return;
}
BoardBeepCtrl_load();
BoardEcgSensor_load();
BoardBattery_load();
hwss_init();
sample_data_mgr_init();
dsp_mgr_init();
ble_cmder_init();
ble_cmder_start_adv();
m_poweronflag = true;
}
static void power_off() {
if (!m_poweronflag) return;
dsp_mgr_uninit();
sample_data_mgr_uninit();
hwss_uninit();
BoardEcgSensor_unload();
BoardBattery_unload();
BoardLight_unload();
BoardBeepCtrl_unload();
ble_cmder_stop_adv();
ble_cmder_uninit();
m_poweronflag = false;
}
/*******************************************************************************
* 状态切换方法 *
*******************************************************************************/
/**
* @brief 切换到充电中状态
*/
static void state_machine__change_to_charging_state() { //
if (ds_now_state() == kdevice_state_home) {
// 已开机 DO Nothing
} else if (ds_now_state() == kdevice_state_standby) {
power_on();
} else {
ZASSERT(false);
}
// 切换到充电显示页面
dsp_mgr_change_to_chargingPage();
ds_change_to_state(kdevice_state_charging);
}
/**
* @brief 切换到待机状态
*/
static void state_machine__change_to_standby_state() {
ZLOGI_BLOCK("change to standby");
power_off();
ds_change_to_state(kdevice_state_standby);
}
/**
* @brief 切换到开机中画面
*/
static void state_machine__change_to_poweroning_state() {
power_on();
dsp_mgr_change_to_welcome();
ds_change_to_state(kdevice_state_poweron);
}
/**
* @brief 切换到首页
*/
static void state_machine__change_to_home_state() {
ds_change_to_state(kdevice_state_home);
dsp_mgr_change_to_main();
}
void ENTER_DEEP_SLEEP() {
// 进入深度睡眠前,使能唤醒引脚
BoardEcgSensor_set_sence_state();
BoardBattery_sence_gpio_init_before_sleep();
// nrf_sdh_disable_request();
app_timer_stop_all();
// nrf_sdh_disable_request();
sd_power_system_off();
NVIC_SystemReset();
}
static void app_event_listener(void* p_event_data, uint16_t event_size) {
if (!p_event_data) return;
app_event_t* p_event = (app_event_t*)p_event_data;
if (ds_now_state() != kdevice_state_standby) {
if (zdatachannel_is_connected()) {
BoardLight_setGreenLightEffect(kLightEffect_slowFlash);
} else {
BoardLight_setGreenLightEffect(kLightEffect_quickFlash);
}
}
/*******************************************************************************
* 待机状态 *
*******************************************************************************/
if (ds_now_state() == kdevice_state_standby) {
ZLOGI("standby......");
// 充电事件触发 --> 切换到充电页面
if (BoardBattery_get_charging_state()) {
state_machine__change_to_charging_state();
}
// 导联连接事件触发 --> 切换到开机中页面
else if (BoardEcgSensor_plod_get_connected_state()) {
state_machine__change_to_poweroning_state();
}
// 10秒后,如果RTC未被设置过,则进入超低功耗
else if (ds_cur_state_haspassed_ms() >= 2000) {
if (!znordic_rtc_has_setted()) {
ENTER_DEEP_SLEEP();
}
}
}
/*******************************************************************************
* 充电状态 *
*******************************************************************************/
else if (ds_now_state() == kdevice_state_charging) {
if (!BoardBattery_get_charging_state()) {
state_machine__change_to_standby_state();
}
}
/*******************************************************************************
* 开机中 *
*******************************************************************************/
else if (ds_now_state() == kdevice_state_poweron) {
if (ds_cur_state_haspassed_ms() >= 1500) {
state_machine__change_to_home_state();
}
}
/*******************************************************************************
* 首页 *
*******************************************************************************/
else if (ds_now_state() == kdevice_state_home) {
// 如果用户长时间不操作,自动切换到待机状态
if (!zdatachannel_is_connected() && //
!BoardEcgSensor_plod_get_connected_state_after_filter() && //
BoardEcgSensor_plod_state_has_disconnected_ms() >= 3000 && //
ds_cur_state_haspassed_ms() >= AUTOMATIC_SLEEP_TIME) {
state_machine__change_to_standby_state();
}
// 如果用户继续保持静止,切换到采集页面
else if (BoardEcgSensor_plod_get_connected_state_after_filter() && ds_cur_state_haspassed_ms() > 1500) {
// dsp_mgr_change_to_preparePage
ds_change_to_state(kdevice_state_keep_still);
dsp_mgr_change_to_preparePage();
}
// ZLOGI("bt:%d plod:%d has_disc:%d state:%d", zdatachannel_is_connected(), BoardEcgSensor_plod_get_connected_state_after_filter(), plod_state_has_disconnected_ms(), ds_cur_state_haspassed_ms());
}
/*******************************************************************************
* 保持静止页面 *
*******************************************************************************/
else if (ds_now_state() == kdevice_state_keep_still) {
if (!BoardEcgSensor_plod_get_connected_state_after_filter()) {
// 如果用户未保持静止,切换到首页
state_machine__change_to_home_state();
} else {
/*******************************************************************************
* 页面加载中 *
*******************************************************************************/
if (ds_cur_state_haspassed_ms() >= (KEEP_STILL_OVERTIME_MS_1P5 * 5)) {
/**
* @brief
*
* 1. 启动采样定时器
* 2. 切换状态
* 3. 切换页面
*/
ds_change_to_state(kdevice_state_sampling);
dsp_mgr_change_to_sampling(0, 0);
hwss_start_capture();
static ztm_t tm;
memset(&sampledata_file_name, 0, sizeof(sampledata_file_name));
znordic_rtc_gettime(&tm);
sample_capture_state_reset();
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;
m_cur_fd = sample_data_mgr_open(&sampledata_file_name, kwrflag_write_only);
BoardBeepCtrl_setEffect(kBoardBeepEffect_oneShortBeep);
} else if (ds_cur_state_haspassed_ms() >= (KEEP_STILL_OVERTIME_MS_1P5 * 4)) {
if (dsp_mgr_preparePage_get_progress() != 4) {
dsp_mgr_preparePage_set_progress(4);
}
} else if (ds_cur_state_haspassed_ms() >= (KEEP_STILL_OVERTIME_MS_1P5 * 3)) {
if (dsp_mgr_preparePage_get_progress() != 3) {
dsp_mgr_preparePage_set_progress(3);
}
} else if (ds_cur_state_haspassed_ms() >= (KEEP_STILL_OVERTIME_MS_1P5 * 2)) {
if (dsp_mgr_preparePage_get_progress() != 2) {
dsp_mgr_preparePage_set_progress(2);
}
} else if (ds_cur_state_haspassed_ms() >= (KEEP_STILL_OVERTIME_MS_1P5 * 1)) {
if (dsp_mgr_preparePage_get_progress() != 1) {
dsp_mgr_preparePage_set_progress(1);
}
}
}
}
/*******************************************************************************
* 采样页面逻辑 *
*******************************************************************************/
else if (ds_now_state() == kdevice_state_sampling) {
/*******************************************************************************
* 采样数据存储 *
*******************************************************************************/
if (p_event->eventType == kevent_capture_256data_event) {
if (hwss_has_captured_time_ms() <= (MAX_STORAGE_TIMEOUT_S * 1000)) {
sample_data_mgr_write(m_cur_fd, p_event->val.capture_data_cache, 256);
}
}
/*******************************************************************************
* 实时采样数据上报 *
*******************************************************************************/
if (p_event->eventType == kevent_capture_little_data_block_event) {
// 单帧实时上报
ZASSERT(LITTLE_DATA_BLOCK_FRAME_NUM == 5);
ble_cmder_try_report_one_sample_data(p_event->val.little_data_block.frameIndex, //
p_event->val.little_data_block.data[0].data, //
p_event->val.little_data_block.data[1].data, //
p_event->val.little_data_block.data[2].data, //
p_event->val.little_data_block.data[3].data, //
p_event->val.little_data_block.data[4].data);
}
/*******************************************************************************
* 采样足30秒事件捕获 *
*******************************************************************************/
if (hwss_has_captured_time_ms() >= (SAMPLE_MIN_TIME_S * 1000)) {
if (!sample_capture_state_get()->is_over30s) {
BoardBeepCtrl_setEffect(kBoardBeepEffect_oneShortBeep);
sample_capture_state_set_is_over30s(true);
}
}
/*******************************************************************************
* 采样结束判定 *
*******************************************************************************/
bool capture_end = false;
if (hwss_has_captured_time_ms() >= (MAX_STORAGE_TIMEOUT_S * 1000)) {
capture_end = true;
} else if (p_event->eventType == kplod_disconnected_event) {
ble_cmder_try_report_sensor_drop_event(0x01, 0);
capture_end = true;
}
if (capture_end) {
if (sample_capture_state_get()->is_over30s) {
sample_data_mgr_close(m_cur_fd);
dsp_mgr_change_to_sampleSuc();
BoardBeepCtrl_setEffect(kBoardBeepEffect_oneShortBeep);
ds_change_to_state(kdevice_state_sampling_complete);
hwss_stop_capture();
} else {
// 采样不足三十秒
// 停止采样
hwss_stop_capture();
// 关闭文件
sample_data_mgr_close(m_cur_fd);
// 删除文件
sample_data_mgr_delete_file(&sampledata_file_name);
// 切换到采集出错页面
dsp_mgr_change_to_samplingError();
BoardBeepCtrl_setEffect(kBoardBeepEffect_threeShortBeep);
ds_change_to_state(kdevice_state_sampling_error);
}
}
}
/*******************************************************************************
* 采样完成页面 *
*******************************************************************************/
else if (ds_now_state() == kdevice_state_sampling_complete) {
if (ds_cur_state_haspassed_ms() >= 3000) {
ZLOGI("ds_cur_state_haspassed_ms() %d> 3000", ds_cur_state_haspassed_ms());
state_machine__change_to_home_state();
ble_cmder_report_sample_finish_event();
}
}
/*******************************************************************************
* 采样错误页面 *
*******************************************************************************/
else if (ds_now_state() == kdevice_state_sampling_error) {
if ((ds_cur_state_haspassed_ms() >= 3000) || //
(ds_cur_state_haspassed_ms() >= 1000 && BoardEcgSensor_plod_get_connected_state_after_filter())) {
ZLOGI("ds_cur_state_haspassed_ms() %d> 3000", ds_cur_state_haspassed_ms());
state_machine__change_to_home_state();
ble_cmder_report_sample_finish_event();
}
}
}
/*******************************************************************************
* MAIN_CODE *
*******************************************************************************/
void one_conduction_main() {
BoardBeepCtrl_init();
AppEvent_regListener(app_event_listener);
BoardBattery_init();
BoardEcgSensor_init();
BoardLight_Init();
BoardLight_load();
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(300), NULL));
state_machine__change_to_poweroning_state();
znordic_loop();
}