#include #include #include "aproject_config/config.h" #include "ify_hrs_protocol/heart_rate_sensor_protocol.h" #include "zdatachannel_service.h" // #include "app_basic_service/device_version_info_mgr.h" #include "app_basic_service/zapp.h" #include "app_service/base_hardware/adc_mgr.h" #include "app_service/base_hardware/hardware_power_mgr.h" #include "app_service/battery_mgr_service.h" #include "app_service/beep_ctrl.h" #include "app_service/display_ctrl_service/display_mgr.h" #include "app_service/ecg_service/ecg_service.h" #include "app_service/light_ctrl.h" #include "zble_module.h" // #include "ble_data_processer_utils.h" #include "nrf_fstorage.h" #include "nrf_fstorage_sd.h" /*********************************************************************************************************************** * GLOBAL * ***********************************************************************************************************************/ static bool m_poweron_flag; static uint16_t m_capture_prepare_progress = 0; /******************************************************************************* * UTILS * *******************************************************************************/ /*********************************************************************************************************************** * 蓝牙连接事件处理 * ***********************************************************************************************************************/ static void process_on_connect(void* arg) { if (zapp_state_machine_now_state() == kstate_standby) { zapp_state_machine_change_state(kstate_welcomPage); } if (m_poweron_flag) { light_ctrl_set_green_light_effect(kLightEffect_slowFlash); } } static void process_on_disconnect(void* arg) { if (m_poweron_flag) { light_ctrl_set_green_light_effect(kLightEffect_quickFlash); } } void on_zble_event(zble_event_t* event) { if (event->eventType == kzble_event_connected) { zapp_exec_in_main_context(NULL, process_on_connect, NULL); } else if (event->eventType == kzble_event_disconnected) { zapp_exec_in_main_context(NULL, process_on_disconnect, NULL); } } /*********************************************************************************************************************** * 蓝牙消息处理 * ***********************************************************************************************************************/ void one_conduction_process_rx_packet(uint8_t* rx, int len) { ify_hrs_packet_t* rxheader = (ify_hrs_packet_t*)rx; ify_hrs_packet_t* txheader = bletxbuf_get(); ify_hrs_cmd_t cmd = (ify_hrs_cmd_t)rxheader->cmd; if (len < sizeof(ify_hrs_packet_t)) { ZLOGI("rx len error:%d", len); return; } bletxbuf_clear(); txheader->cmd = rxheader->cmd; txheader->frame_index = rxheader->frame_index; txheader->frame_type = kifyhrs_pt_cmd_receipt; ZLOGI("rx cmd:%d index:%d datalen:%d", cmd, rxheader->frame_index, len - sizeof(ify_hrs_packet_t)); NRF_LOG_HEXDUMP_INFO(rx, len); if (cmd == ify_hrs_cmd_read_device_version) { device_version_info_receipt_t* receipt = (device_version_info_receipt_t*)txheader->data; uint16_t sendlen = sizeof(ify_hrs_packet_t) + sizeof(device_version_info_receipt_t); receipt->blestack_version = device_info_read_blestack_version(); receipt->bootloader_version = device_info_read_bootloader_version(); receipt->firmware_version = device_info_read_firmware_version(); receipt->hardware_version = device_info_read_hardware_version(); zdatachannel_data_send2((uint8_t*)txheader, sendlen); } else if (cmd == ify_hrs_cmd_read_sensor_info) { sensor_info_receipt_t* receipt = (sensor_info_receipt_t*)txheader->data; uint16_t sendlen = sizeof(ify_hrs_packet_t) + sizeof(sensor_info_receipt_t); receipt->sensor_num = 1; receipt->sensor_precision = SAMPLE_PRECISION; receipt->sensor_sample_rate = SAMPLE_RATE / 10; receipt->sensor0_pos = kifyhrs_sensor_pos_none; receipt->sensor1_pos = kifyhrs_sensor_pos_none; receipt->sensor2_pos = kifyhrs_sensor_pos_none; zdatachannel_data_send2((uint8_t*)txheader, sendlen); } else if (cmd == ify_hrs_cmd_read_sn) { read_sn_receipt_t* receipt = (read_sn_receipt_t*)txheader->data; uint16_t sendlen = sizeof(ify_hrs_packet_t) + sizeof(read_sn_receipt_t); device_info_read_sn((sn_t*)&receipt->sn); zdatachannel_data_send2((uint8_t*)txheader, sendlen); } else if (cmd == ify_hrs_cmd_reset) { NVIC_SystemReset(); } else if (cmd == ify_hrs_cmd_read_time) { read_time_receipt_t* receipt = (read_time_receipt_t*)txheader->data; uint16_t sendlen = sizeof(ify_hrs_packet_t) + sizeof(read_time_receipt_t); static ztm_t ztm; znordic_rtc_gettime(&ztm); receipt->year = (ztm.tm_year + 1900 - 2000); receipt->month = ztm.tm_mon + 1; receipt->day = ztm.tm_mday; receipt->hour = ztm.tm_hour; receipt->minute = ztm.tm_min; receipt->second = ztm.tm_sec; zdatachannel_data_send2((uint8_t*)txheader, sendlen); } else if (cmd == ify_hrs_cmd_sync_time) { sync_time_cmd_t* cmd = (sync_time_cmd_t*)rxheader->data; uint16_t sendlen = sizeof(ify_hrs_packet_t); device_info_write_active_flag(true); znordic_rtc_settime(cmd->year + 2000, cmd->month, cmd->day, cmd->hour, cmd->minute, cmd->second); zdatachannel_data_send2((uint8_t*)txheader, sendlen); } /*********************************************************************************************************************** * 基础指令 * ***********************************************************************************************************************/ else if (cmd == ify_hrs_cmd_read_device_state) { device_state_receipt_t* receipt = (device_state_receipt_t*)txheader->data; uint16_t sendlen = sizeof(ify_hrs_packet_t) + sizeof(device_state_receipt_t); receipt->drop_state0 = (0); receipt->drop_state1 = 0x00; receipt->device_state0.sampling_state = (zapp_state_machine_now_state() == kstate_capture); receipt->device_state0.report_state = 0; receipt->device_state0.low_battery = (0 < APP_LOW_BATTERY_WARNING_LIMIT); receipt->device_state0.full_storge = false; receipt->device_state1 = 0; receipt->powerlevel = battery_mgr_service_get_battery_level(); receipt->storage_item_num = 0; zdatachannel_data_send2((uint8_t*)txheader, sendlen); } else if (cmd == ify_hrs_cmd_start_realtime_preview) { if (zapp_state_machine_now_state() != kstate_mainPage && zapp_state_machine_now_state() != kstate_welcomPage) { send_error_receipt(rxheader, kifyhrs_ecode_invalid_state); return; } static app_event_t event; event.eventType = kappevent_start_capture; zapp_ebus_push_event(&event); send_success_receipt(rxheader, 0); } else if (cmd == ify_hrs_cmd_stop_realtime_preview) { if (zapp_state_machine_now_state() != kstate_capture) { send_error_receipt(rxheader, kifyhrs_ecode_invalid_state); return; } static app_event_t event; event.eventType = kappevent_stop_capture; zapp_ebus_push_event(&event); send_success_receipt(rxheader, 0); } /*********************************************************************************************************************** * 测试 * ***********************************************************************************************************************/ else if (cmd == ify_hrs_cmd_set_ecg_in_test_mode) { int32_t testmode = *(int32_t*)rxheader->data; ecg_service_set_in_test_mode(testmode); send_success_receipt(rxheader, 0); } else if (cmd == ify_hrs_cmd_set_ecg_report_data_in_raw_mode) { int32_t testmode = *(int32_t*)rxheader->data; ecg_service_set_report_data_in_raw_mode(testmode); send_success_receipt(rxheader, 0); } else if (cmd == ify_hrs_cmd_ecg_subic_read_reg) { uint8_t addr = *(uint8_t*)rxheader->data; uint8_t val = ecg_service_subic_read_reg(addr); txheader->data[0] = val; zdatachannel_data_send2((uint8_t*)txheader, sizeof(ify_hrs_packet_t) + 1); } else if (cmd == ify_hrs_cmd_ecg_subic_write_reg) { uint8_t addr = *(uint8_t*)rxheader->data; uint8_t val = *(uint8_t*)(rxheader->data + 1); ecg_service_subic_write_reg(addr, val); send_success_receipt(rxheader, 0); } else { send_error_receipt(rxheader, kifyhrs_ecode_cmd_not_support); } } /*********************************************************************************************************************** * 事件处理 * ***********************************************************************************************************************/ // extern int32_t maxval; // extern int32_t minval; // extern int32_t nowval100; void on_zapp_ebus_event(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 (p_event->eventType == kappevent_tmr_1s_scheduler_event) { // ZLOGI("tmr event. %d %d %d", nowval100, minval, maxval); // ZLOGI("tmr event."); } app_event_type_t event = p_event->eventType; if (zapp_state_machine_now_state() == kstate_standby) { /** * @brief * 1. 充电切换到充电状态 */ if (event == kappevent_state_machine_state_enter) { /** * @brief 关机 */ ZLOGI("power off"); dsp_mgr_change_page(kpage_poweroff); battery_mgr_service_change_state_to_standy(); beep_unload(); light_ctrl_unload(); dsp_mgr_unload(); ecg_service_unload(); // battery_mgr_service_change_state_to_standy(); hardware_power_mgr_main_power_supply_set(false); m_poweron_flag = false; } else if (event == kappevent_state_machine_state_exit) { /** * @brief 开机 */ ZLOGI("power on"); hardware_power_mgr_main_power_supply_set(true); battery_mgr_service_change_state_to_poweron(); beep_load(); light_ctrl_load(); dsp_mgr_load(); ecg_service_load(); m_poweron_flag = true; if (zble_module_is_connected()) { light_ctrl_set_green_light_effect(kLightEffect_slowFlash); } } else { if (p_event->eventType == kappevent_battery_start_charge) { zapp_state_machine_change_state(kstate_charging); } else if (!device_info_get_active_flag() && zapp_state_machine_haspassed_ms() >= 60000) { ZLOGI_BLOCK("rtc not setted, power system off"); ZERROR_CHECK(sd_power_system_off()); } } } else if (zapp_state_machine_now_state() == kstate_welcomPage) { /** * @brief * 延迟1.5s切换到主页面 */ if (event == kappevent_state_machine_state_enter) { dsp_mgr_change_page(kpage_welcome); } else if (event == kappevent_state_machine_state_exit) { } else { if (p_event->eventType == kappevent_start_capture) { zapp_state_machine_change_state(kstate_prepare_capture); } else if (zapp_state_machine_haspassed_ms() >= 2000) { zapp_state_machine_change_state(kstate_mainPage); beep_set_effect(POWER_ON_EFFECT); } } } else if (zapp_state_machine_now_state() == kstate_mainPage) { /** * @brief * 1. 断开连接->切换到关机状态 * 2. 开始采集指令->切换到采集状态 * 3. 充电中事件->切换到充电状态 * */ if (event == kappevent_state_machine_state_enter) { dsp_mgr_change_page(kpage_main); } else if (event == kappevent_state_machine_state_exit) { } else { if (zble_module_has_disconnected_ms() >= 3000) { zapp_state_machine_change_state(kstate_standby); } else if (event == kappevent_start_capture) { zapp_state_machine_change_state(kstate_prepare_capture); } else if (event == kappevent_battery_start_charge) { zapp_state_machine_change_state(kstate_charging); } } } else if (zapp_state_machine_now_state() == kstate_prepare_capture) { /** * @brief * 1. 停止采集指令->切换到MainPage * 2. 断开连接 ->切换到关机状态 * 3. 检查leadoff状态 */ if (event == kappevent_state_machine_state_enter) { m_capture_prepare_progress = 0; dsp_mgr_change_page(kpage_sample_prepare); ecg_service_start_capture(); beep_set_effect(START_SAMPLE_EFFECT); } else if (event == kappevent_state_machine_state_exit) { } else { if (zble_module_has_disconnected_ms() >= 5000) { ecg_service_stop_capture(); zapp_state_machine_change_state(kstate_standby); } else if (event == kappevent_stop_capture) { ecg_service_stop_capture(); zapp_state_machine_change_state(kstate_mainPage); } else { if (event == kappevent_tmr_1s_scheduler_event) { if (!ecg_leadoff_detect() && zapp_state_machine_haspassed_ms() > 1500) { m_capture_prepare_progress++; if (m_capture_prepare_progress < 4) { dsp_mgr_page_sample_prepare_set_progress(m_capture_prepare_progress); } else { /** * @brief 开始采集 */ zapp_state_machine_change_state(kstate_capture); beep_set_effect(POWER_ON_EFFECT); } } else { m_capture_prepare_progress = 0; dsp_mgr_page_sample_prepare_set_progress(m_capture_prepare_progress); } } } } } else if (zapp_state_machine_now_state() == kstate_capture) { /** * @brief * 1. 停止采集指令->切换到MainPage * 2. 断开连接 ->切换到关机状态 */ if (event == kappevent_state_machine_state_enter) { ecg_service_start_capture(); dsp_mgr_change_page(kpage_sampling); } else if (event == kappevent_state_machine_state_exit) { ecg_service_stop_capture(); beep_set_effect(STOP_SAMPLE_EFFECT); } else { if (zble_module_has_disconnected_ms() >= 1000) { zapp_state_machine_change_state(kstate_standby); } else if (event == kappevent_stop_capture) { zapp_state_machine_change_state(kstate_mainPage); } else if (event == kecg_data_report_event) { report_ecg_data(p_event); } } } else if (zapp_state_machine_now_state() == kstate_charging) { /** * @brief * 1. 充电结束事件->切换到待机 */ if (event == kappevent_state_machine_state_enter) { dsp_mgr_change_page(kpage_charging_page); } else if (event == kappevent_state_machine_state_exit) { } else { if (event == kappevent_battery_end_charge) { if (!zble_module_is_connected()) { zapp_state_machine_change_state(kstate_standby); } else { zapp_state_machine_change_state(kstate_mainPage); } } } } else if (zapp_state_machine_now_state() == kstate_test) { // extern int32_t maxval; // extern int32_t minval; extern uint8_t m_leadoff_raw_state; ZLOGI("tmr event. %d %x", ecg_leadoff_detect(), m_leadoff_raw_state); } } /*********************************************************************************************************************** * 状态切换 * ***********************************************************************************************************************/ void on_state_change(state_machine_event_t event, device_state_t state) { /** * @brief 状态退出 */ static app_event_t appevent; if (event == kstate_event_enter) { appevent.eventType = kappevent_state_machine_state_enter; on_zapp_ebus_event(&appevent, sizeof(app_event_t)); } else { appevent.eventType = kappevent_state_machine_state_exit; on_zapp_ebus_event(&appevent, sizeof(app_event_t)); } } void one_conduction_main() { device_info_init(); sn_t sn; device_info_read_sn(&sn); ZLOGI("one_conduction_main %s active:%d", sn.sn, device_info_get_active_flag()); ZLOG_FLUSH(); zapp_ebus_reg_event_listener(on_zapp_ebus_event); zapp_state_machine_reg_state_change_listener(on_state_change); zble_module_reglistener(on_zble_event); adc_mgr_init(); hardware_power_mgr_init(); battery_mgr_service_init(); battery_mgr_service_load(); light_ctrl_init(); beep_init(); dsp_mgr_init(); ecg_service_init(); // zapp_state_machine_change_state(kstate_prepare_capture); zble_module_start_adv(); zapp_start_schedule(); }