From 1f2425b8341626bf27f42c3dc5e28d9a7e8a75ad Mon Sep 17 00:00:00 2001 From: zhaohe Date: Tue, 30 Jan 2024 18:31:30 +0800 Subject: [PATCH] update --- README.md | 4 ++-- app/src/one_conduction/device_state.c | 16 ++++++++++++++-- app/src/one_conduction/device_state.h | 13 +++++++++++-- app/src/one_conduction/display_manager.c | 17 +++++++++++++---- app/src/one_conduction/font.h | 5 +++-- app/src/one_conduction/one_conduction_board.c | 24 +++++++++++++++++++++--- app/src/one_conduction/one_conduction_board.h | 2 +- app/src/one_conduction/one_conduction_main.c | 26 +++++++++++++++++++++----- 8 files changed, 86 insertions(+), 21 deletions(-) diff --git a/README.md b/README.md index 5f40851..75e982e 100644 --- a/README.md +++ b/README.md @@ -257,7 +257,7 @@ TODO: 14. 支持掉落事件 OK TESTOK 6. 支持电池电量采集 OK - 8. 采集完30秒,蜂鸣器滴一声,采集完成,蜂鸣器滴一声 + 8. 采集完30秒,蜂鸣器滴一声,采集完成,蜂鸣器滴一声 OK 16. 调整UI位置 11. 死机后一直重启的BUG OK 12. 修改蓝牙名称 OK @@ -273,7 +273,7 @@ TODO: 11. 数据掉电不丢失 12. 优化定时器周期 13. 支持低电量事件 - 14. 添加设备激活逻辑,根据设备是否通过过时间来判断当前是否彻底断电。 + 15. 优化蜂鸣器的声音 ``` \ No newline at end of file diff --git a/app/src/one_conduction/device_state.c b/app/src/one_conduction/device_state.c index ed49810..243c1b5 100644 --- a/app/src/one_conduction/device_state.c +++ b/app/src/one_conduction/device_state.c @@ -11,5 +11,17 @@ void ds_change_to_state(device_state_t state) { m_change_to_cur_state_tp = znordic_getpower_on_ms(); } -uint32_t ds_cur_state_haspassed_ms() { return znordic_haspassed_ms(m_change_to_cur_state_tp); } -device_state_t ds_now_state() { return m_device_state; } \ No newline at end of file +uint32_t ds_cur_state_haspassed_ms() { return znordic_haspassed_ms(m_change_to_cur_state_tp); } +device_state_t ds_now_state() { return m_device_state; } + +static sample_capture_state_t m_sample_capture_state; + +sample_capture_state_t* sample_capture_state_get() { // + return &m_sample_capture_state; +} +void sample_capture_state_reset() { // + m_sample_capture_state.is_over30s = false; +}; +void sample_capture_state_set_is_over30s(bool over30s) { // + m_sample_capture_state.is_over30s = over30s; +} diff --git a/app/src/one_conduction/device_state.h b/app/src/one_conduction/device_state.h index f9c90b3..9a6f645 100644 --- a/app/src/one_conduction/device_state.h +++ b/app/src/one_conduction/device_state.h @@ -1,5 +1,6 @@ #pragma once #include +#include typedef enum { kplod_connected_event = 0, // 导联连接事件 @@ -24,8 +25,7 @@ typedef struct { struct { uint32_t frameIndex; uint16_t data; - } - frame_data; + } frame_data; } val; } app_event_t; @@ -76,3 +76,12 @@ void app_event_process_cb(void* p_event_data, uint16_t event_size); void ds_change_to_state(device_state_t state); uint32_t ds_cur_state_haspassed_ms(); device_state_t ds_now_state(); + +typedef struct { + bool is_over30s; +} sample_capture_state_t; + +sample_capture_state_t* sample_capture_state_get(); + +void sample_capture_state_reset(); +void sample_capture_state_set_is_over30s(bool over30s); diff --git a/app/src/one_conduction/display_manager.c b/app/src/one_conduction/display_manager.c index 3401146..615c324 100644 --- a/app/src/one_conduction/display_manager.c +++ b/app/src/one_conduction/display_manager.c @@ -319,10 +319,11 @@ void dsp_mgr_change_to_sampling(int progress_s, int heartrate) { // dsp_mgr_change_to_page(kPage_sampling); } -void samplePage_update_state(int progress_s, int wave_y, int heartrate, bool update_screen) { // +void samplePage_update_state(int progress_s, int wave_y, int heartrate, bool updateHeart, bool update_screen) { // sample_page_state_t* sps = &m_sample_page_state; uint8_t xchange, ychange; + static bool heart_logo_state = false; int progress = progress_s / SAMPLE_MIN_TIME_S * 25; @@ -332,8 +333,15 @@ void samplePage_update_state(int progress_s, int wave_y, int heartrate, bool upd // } else { // ssd1306_basic_draw_str(sps->progress_x + sps->progress_width + 2, sps->progress_y, &xchange, &ychange, "x", &font8x8_xo_lib); // } + if (update_screen && updateHeart) { + if (heart_logo_state) { + ssd1306_basic_draw_str(sps->heartrate_x + 2, sps->heartrate_y, &xchange, &ychange, "<>", &font_asicc16x8_lib); + } else { + ssd1306_basic_draw_str(sps->heartrate_x + 2, sps->heartrate_y, &xchange, &ychange, " ", &font_asicc16x8_lib); + } + heart_logo_state = !heart_logo_state; + } - ssd1306_basic_draw_str(sps->heartrate_x + 2, sps->heartrate_y, &xchange, &ychange, "<>", &font_asicc16x8_lib); if (heartrate <= 0) { ssd1306_basic_draw_str(sps->heartrate_x, sps->heartrate_y + 20, &xchange, &ychange, "-- ", &font_asicc16x8_lib); } else { @@ -350,7 +358,7 @@ void samplePage_schedule() { int wave_y = (int)hwss_read_val(); int heartrate = (int)hwss_read_heart_rate(); // ZLOGI("samplePage_schedule %d %d %d", capturetime, wave_y, heartrate); - samplePage_update_state(capturetime / 1000, wave_y, 123, count % 10 == 0); + samplePage_update_state(capturetime / 1000, wave_y, 123, count % 10 == 0, count % 5 == 0); } /******************************************************************************* @@ -424,7 +432,8 @@ void dsp_mgr_init(void) { if (!timer_inited) { ZERROR_CHECK(app_timer_create(&m_dsp_mgr_schedule_tmr, APP_TIMER_MODE_REPEATED, dsp_mgr_schedule_tmr_cb)); } - ZERROR_CHECK(app_timer_start(m_dsp_mgr_schedule_tmr, APP_TIMER_TICKS(10), NULL)); + // 此处周期决定采样一个页面显示的宽度 + ZERROR_CHECK(app_timer_start(m_dsp_mgr_schedule_tmr, APP_TIMER_TICKS(25), NULL)); timer_inited = true; } void dsp_mgr_uninit(void) { diff --git a/app/src/one_conduction/font.h b/app/src/one_conduction/font.h index aeed828..179ea34 100644 --- a/app/src/one_conduction/font.h +++ b/app/src/one_conduction/font.h @@ -261,12 +261,13 @@ const unsigned char font_asicc_code_16x8[] = { 0X00, 0XF8, 0XFC, 0XFE, 0XFE, 0XFE, 0XFE, 0XFC, 0X00, 0X00, 0X03, 0X07, 0X0F, 0X1F, 0X3F, 0X7F, /*?右半*/ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /*" "*/ }; static FontLibrary_t font_asicc16x8_lib = { .font = font_asicc_code_16x8, - .fontIndex = "0123456789-:<>", // <> 这两个符号是心形的左右半边 - .fontIndexLen = 14, + .fontIndex = "0123456789-:<> ", // <> 这两个符号是心形的左右半边 + .fontIndexLen = 16, .fontCode = kgbk, .isAscii = true, .widthPixel = 8, diff --git a/app/src/one_conduction/one_conduction_board.c b/app/src/one_conduction/one_conduction_board.c index e73fc9d..8eab403 100644 --- a/app/src/one_conduction/one_conduction_board.c +++ b/app/src/one_conduction/one_conduction_board.c @@ -110,8 +110,21 @@ static nrf_drv_pwm_config_t const m_beep_pwm0_config0 = { .load_mode = NRF_PWM_LOAD_INDIVIDUAL, .step_mode = NRF_PWM_STEP_AUTO, }; -void SingleLeadECG_beep_init() { APP_ERROR_CHECK(nrfx_pwm_init(&m_beep_pwm0, &m_beep_pwm0_config0, NULL)); } -void SingleLeadECG_beep_deinit() { nrfx_pwm_uninit(&m_beep_pwm0); } +APP_TIMER_DEF(m_beep_tmr); // 蜂鸣器自动关闭定时器 +bool m_beep_tmr_is_inited = false; +static void beep_tmr_handler(void *context) { SingleLeadECG_beep_set_state(false); } +void SingleLeadECG_beep_init() { + if (!m_beep_tmr_is_inited) { + m_beep_tmr_is_inited = true; + app_timer_create(&m_beep_tmr, APP_TIMER_MODE_SINGLE_SHOT, beep_tmr_handler); + } + + APP_ERROR_CHECK(nrfx_pwm_init(&m_beep_pwm0, &m_beep_pwm0_config0, NULL)); +} +void SingleLeadECG_beep_deinit() { + SingleLeadECG_beep_set_state(false); + nrfx_pwm_uninit(&m_beep_pwm0); +} void SingleLeadECG_beep_set_state(bool state) { if (state) { @@ -121,6 +134,11 @@ void SingleLeadECG_beep_set_state(bool state) { nrfx_pwm_stop(&m_beep_pwm0, true); } } +void SingleLeadECG_beep_trigger_once() { + SingleLeadECG_beep_set_state(true); + app_timer_start(m_beep_tmr, APP_TIMER_TICKS(200), NULL); +} + /******************************************************************************* * SCREEN * *******************************************************************************/ @@ -254,7 +272,7 @@ int16_t SingleLeadECG_battery_val() { // static const float maxv = 4.0; static const float minv = 3.5; - float voltage = SingleLeadECG_battery_get_adc_val() / 4096.0 * 3.3 / 2.0* 3; + float voltage = SingleLeadECG_battery_get_adc_val() / 4096.0 * 3.3 / 2.0 * 3; if (voltage > maxv) voltage = maxv; if (voltage < minv) voltage = minv; diff --git a/app/src/one_conduction/one_conduction_board.h b/app/src/one_conduction/one_conduction_board.h index 940eee1..f2c33f6 100644 --- a/app/src/one_conduction/one_conduction_board.h +++ b/app/src/one_conduction/one_conduction_board.h @@ -22,6 +22,7 @@ void SingleLeadECG_adc_module_deinit(); void SingleLeadECG_beep_init(); void SingleLeadECG_beep_deinit(); void SingleLeadECG_beep_set_state(bool state); +void SingleLeadECG_beep_trigger_once(); /******************************************************************************* * EEPROM * @@ -72,6 +73,5 @@ void SingleLeadECG_battery_deinit(); int16_t SingleLeadECG_battery_get_adc_val(); int16_t SingleLeadECG_battery_val(); - void SingleLeadECG_battery_charge_detect_io_init(); bool SingleLeadECG_battery_charge_get_state(); diff --git a/app/src/one_conduction/one_conduction_main.c b/app/src/one_conduction/one_conduction_main.c index e82456d..7a3ddfa 100644 --- a/app/src/one_conduction/one_conduction_main.c +++ b/app/src/one_conduction/one_conduction_main.c @@ -123,6 +123,8 @@ static void power_on() { ble_cmder_init(); ble_cmder_start_adv(); + // SingleLeadECG_beep_trigger_once(); + m_poweronflag = true; ZERROR_CHECK(app_timer_start(m_state_machine_driver_tmr, APP_TIMER_TICKS(100), NULL)); // 200HZ采样 } @@ -262,6 +264,7 @@ void app_event_process_cb(void* p_event_data, uint16_t event_size) { 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; @@ -324,6 +327,10 @@ void app_event_process_cb(void* p_event_data, uint16_t event_size) { // 单帧实时上报 ble_cmder_try_report_one_sample_data(p_event->val.frame_data.frameIndex, p_event->val.frame_data.data); } else if (p_event->eventType == kplod_disconnected_event || !m_plod_state_connected_state) { + /******************************************************************************* + * 导联断开 * + *******************************************************************************/ + if (hwss_has_captured_time_ms() < (SAMPLE_MIN_TIME_S * 1000)) { // 采集不足30秒 ble_cmder_try_report_sensor_drop_event(0x01, 0); @@ -337,28 +344,37 @@ void app_event_process_cb(void* p_event_data, uint16_t event_size) { ds_change_to_state(kdevice_state_sampling_error); hwss_stop_capture(); } + } else { // 采集超过30秒 /******************************************************************************* * 切换到采集完成页面 * *******************************************************************************/ if (!always_capture) { + SingleLeadECG_beep_trigger_once(); sample_data_mgr_close(m_cur_fd); dsp_mgr_change_to_sampleSuc(); ds_change_to_state(kdevice_state_sampling_complete); hwss_stop_capture(); } } + } else { + if (hwss_has_captured_time_ms() >= (SAMPLE_MIN_TIME_S * 1000)) { + if (!sample_capture_state_get()->is_over30s) { + SingleLeadECG_beep_trigger_once(); + sample_capture_state_set_is_over30s(true); + } + } } } else if (ds_now_state() == kdevice_state_sampling_complete) { - if (ds_cur_state_haspassed_ms() >= 2000) { - ZLOGI("ds_cur_state_haspassed_ms() %d> 2000", ds_cur_state_haspassed_ms()); + 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() >= 2000) || (ds_cur_state_haspassed_ms() >= 1000 && m_plod_state_connected_state)) { - ZLOGI("ds_cur_state_haspassed_ms() %d> 2000", ds_cur_state_haspassed_ms()); + if ((ds_cur_state_haspassed_ms() >= 3000) || (ds_cur_state_haspassed_ms() >= 1000 && m_plod_state_connected_state)) { + 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(); } @@ -400,7 +416,7 @@ void one_conduction_main() { znordic_rtc_gettime(&tm); NRF_LOG_INFO("RTC time :%d-%d-%d %d:%d:%d", tm.tm_year + 1900, tm.tm_mon + 1, tm.tm_mday, tm.tm_hour, tm.tm_min, tm.tm_sec); static char ble_name[20]; - sn_t sn; + sn_t sn; device_info_read_sn(&sn); memcpy(ble_name, sn.sn, sizeof(sn.sn));