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

#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