#include "display_manager.h" #include "../../../screen_res/logo_mono.c" // #include #include "basic/ssd1306/driver_ssd1306.h" #include "basic/ssd1306/driver_ssd1306_basic.h" #include "basic/ssd1306/wave_drawer.h" #include "board/board_battery_state.h" #include "config.h" #include "font.h" #include "heart_wave_sample_service.h" #include "one_conduction_board.h" PageState_t g_pageState; void dsp_mgr_change_to_page(page_t page) { // g_pageState.page = page; g_pageState.last_page = page; g_pageState.page_change_to_page_time = znordic_getpower_on_s(); g_pageState.in_prompt = false; memset(g_pageState.prompt, 0, sizeof(g_pageState.prompt)); } uint32_t dsp_mgr_get_page_elapsed_time_s(void) { // return znordic_getpower_on_s() - g_pageState.page_change_to_page_time; } void dsp_mgr_schedule(void) {} PageState_t* dsp_mgr_get_state(void) { return NULL; } int compute_x_pos_by_center(int16_t x, int16_t width) { return x - width / 2; } int compute_y_pos_by_center(int16_t y, int16_t height) { return y - height / 2; } #define SCREEN_CENTER_X 64 #define SCREEN_CENTER_Y 32 #define CHARGE_BATTERY_WIDTH (12 * 1.2) #define CHARGE_BATTERY_HEIGHT (22 * 1.2) #define MAIN_PAGE_BATTERY_WIDTH (12) // 首页电池宽度 #define MAIN_PAGE_BATTERY_HEIGHT (22) // 首页电池高度 /******************************************************************************* * 充电页面 * *******************************************************************************/ /** * 显示元素: * 1.电池电量 * --------------- * | _ | * | | | | * | | * --------------- * * 动画效果: * 1. 电池电量变化 * */ static uint32_t m_nowshowbatterylevel; // 当前显示的电池电量 void dsp_mgr_change_to_chargingPage() { ssd1306_basic_clear(); uint8_t x = compute_x_pos_by_center(SCREEN_CENTER_X, CHARGE_BATTERY_WIDTH); uint8_t y = compute_y_pos_by_center(SCREEN_CENTER_Y, CHARGE_BATTERY_HEIGHT); uint8_t xchange, ychange; ssd1306_basic_draw_battery_level(x, y, &xchange, &ychange, BoardBattery_get_battery_level(), CHARGE_BATTERY_WIDTH, CHARGE_BATTERY_HEIGHT); m_nowshowbatterylevel = BoardBattery_get_battery_level(); ssd1306_basic_gram_update(); dsp_mgr_change_to_page(kPage_chargingPage); } void chargingPage_set_batteryLevel(int batteryLevel) { uint8_t x = compute_x_pos_by_center(SCREEN_CENTER_X, CHARGE_BATTERY_WIDTH); uint8_t y = compute_y_pos_by_center(SCREEN_CENTER_Y, CHARGE_BATTERY_HEIGHT); uint8_t xchange, ychange; ssd1306_basic_draw_battery_level(x, y, &xchange, &ychange, batteryLevel, CHARGE_BATTERY_WIDTH, CHARGE_BATTERY_HEIGHT); ssd1306_basic_gram_update(); } void chargingPage_schedule() { // static uint32_t last_update_time = 0; if (znordic_haspassed_ms(last_update_time) < 300) { return; } last_update_time = znordic_getpower_on_ms(); m_nowshowbatterylevel += 5; if (m_nowshowbatterylevel > 100) { m_nowshowbatterylevel = BoardBattery_get_battery_level(); } chargingPage_set_batteryLevel(m_nowshowbatterylevel); } /******************************************************************************* * 欢迎页面 * *******************************************************************************/ void dsp_mgr_change_to_welcome() { /** * @brief 切换到欢迎界面 * 1. 加载屏幕外设 * 2. 打开屏幕电源 * 3. 初始化开机页面 */ // ssd1306_basic_string(0, 0, "123456789123456789123", 21, 0, SSD1306_FONT_12); ssd1306_basic_draw_screen((const char*)gImage_logo_mono); ssd1306_basic_gram_update(); dsp_mgr_change_to_page(kPage_welcome); } void welcomePage_schedule() {} /******************************************************************************* * 首页 * *******************************************************************************/ static bool m_main_page_colon_state = false; void mainPage_show(bool colon_state) { static ztm_t now; int16_t batterylevel; uint8_t xchange, ychange; uint8_t x, y; x = compute_x_pos_by_center(SCREEN_CENTER_X, fontclocklib.widthPixel * 5 + MAIN_PAGE_BATTERY_WIDTH); y = compute_y_pos_by_center(SCREEN_CENTER_Y, fontclocklib.heightPixel + 1); znordic_rtc_gettime(&now); batterylevel = BoardBattery_get_battery_level(); ssd1306_basic_clear_gram(); // ZLOGI("mainPage_show %d %d", colon_state, x, y); ssd1306_basic_draw_str(x, y, &xchange, &ychange, fmt("%02d:%02d", now.tm_hour, now.tm_min), &fontclocklib); x = x + 6 + xchange; ssd1306_basic_draw_battery_level(x, y, &xchange, &ychange, batterylevel, MAIN_PAGE_BATTERY_WIDTH, MAIN_PAGE_BATTERY_HEIGHT); ssd1306_basic_gram_update(); m_main_page_colon_state = colon_state; dsp_mgr_change_to_page(kPage_main); } void dsp_mgr_change_to_main() { mainPage_show(true); } void mainPage_updateState() { mainPage_show(!m_main_page_colon_state); } void mainPage_schedule() { static uint32_t last_update_time = 0; if (znordic_haspassed_ms(last_update_time) < 300) { return; } last_update_time = znordic_getpower_on_ms(); mainPage_updateState(); } /******************************************************************************* * 保持静止页面 * *******************************************************************************/ static int m_prepare_page_progress = 0; void PreparePage_show(int progress) { m_prepare_page_progress = progress; ssd1306_basic_clear_gram(); uint8_t x = 0; uint8_t y = 0; uint8_t xchange, ychange; x = compute_x_pos_by_center(SCREEN_CENTER_X, font24x24_zh_lib.widthPixel * 4); y = compute_y_pos_by_center(SCREEN_CENTER_Y, font24x24_zh_lib.heightPixel); ssd1306_basic_draw_str(x, y, &xchange, &ychange, "保持静止", &font24x24_zh_lib); if (progress == 0) { ssd1306_basic_draw_str(x - font8x8_xo_lib.widthPixel, y - font8x8_xo_lib.heightPixel, &xchange, &ychange, "xxxx", &font8x8_xo_lib); } else if (progress == 1) { ssd1306_basic_draw_str(x - font8x8_xo_lib.widthPixel, y - font8x8_xo_lib.heightPixel, &xchange, &ychange, "oxxx", &font8x8_xo_lib); } else if (progress == 2) { ssd1306_basic_draw_str(x - font8x8_xo_lib.widthPixel, y - font8x8_xo_lib.heightPixel, &xchange, &ychange, "ooxx", &font8x8_xo_lib); } else if (progress == 3) { ssd1306_basic_draw_str(x - font8x8_xo_lib.widthPixel, y - font8x8_xo_lib.heightPixel, &xchange, &ychange, "ooox", &font8x8_xo_lib); } else if (progress == 4) { ssd1306_basic_draw_str(x - font8x8_xo_lib.widthPixel, y - font8x8_xo_lib.heightPixel, &xchange, &ychange, "oooo", &font8x8_xo_lib); } ssd1306_basic_gram_update(); } void dsp_mgr_change_to_preparePage() { PreparePage_show(0); dsp_mgr_change_to_page(kPage_preparePage); } void dsp_mgr_preparePage_set_progress(int progress) { PreparePage_show(progress); } int dsp_mgr_preparePage_get_progress() { return m_prepare_page_progress; } void PreparePage_schedule() {} /******************************************************************************* * 采样页面 * *******************************************************************************/ #define SMAPLE_PAGE_START_X 1 #define SMAPLE_PAGE_START_Y 1 typedef struct { wave_drawer_t wave_drawer; int wave_drawser_x; int wave_drawser_y; int wave_drawser_hight; int wave_drawser_width; int progress_x; int progress_y; int progress_width; int progress_hight; int heartrate_x; int heartrate_y; } sample_page_state_t; sample_page_state_t m_sample_page_state; #if 0 void dsp_mgr_change_to_sampling(int progress_s, int heartrate) { // sample_page_state_t* sps = &m_sample_page_state; sps->wave_drawser_x = SMAPLE_PAGE_START_X; sps->wave_drawser_y = SMAPLE_PAGE_START_Y; sps->wave_drawser_hight = 40; sps->wave_drawser_width = 120; sps->progress_x = SMAPLE_PAGE_START_X + 1; sps->progress_y = SMAPLE_PAGE_START_Y + sps->wave_drawser_hight + 3 + 4; sps->progress_width = 80; sps->progress_hight = 8; sps->heartrate_x = sps->progress_x + sps->progress_width + 2; sps->heartrate_y = sps->progress_y - 4; int progress = progress_s / SAMPLE_MIN_TIME_S * 25; ssd1306_basic_clear_gram(); wave_drawer_init(&sps->wave_drawer, sps->wave_drawser_x, sps->wave_drawser_y, sps->wave_drawser_width, sps->wave_drawser_hight); wave_drawer_draw_border(&sps->wave_drawer); uint8_t xchange, ychange; ssd1306_basic_draw_progress(sps->progress_x, sps->progress_y, sps->progress_width, sps->progress_hight, 25, progress); if (heartrate <= 0) { ssd1306_basic_draw_str(sps->heartrate_x, sps->heartrate_y, &xchange, &ychange, "<>-- ", &font_asicc16x8_lib); } else { ssd1306_basic_draw_str(sps->heartrate_x, sps->heartrate_y, &xchange, &ychange, fmt("<>%3d", heartrate), &font_asicc16x8_lib); } ssd1306_basic_gram_update(); dsp_mgr_change_to_page(kPage_sampling); } void samplePage_update_state(int progress_s, int wave_y, int heartrate, bool update_screen) { // sample_page_state_t* sps = &m_sample_page_state; uint8_t xchange, ychange; int progress = progress_s / SAMPLE_MIN_TIME_S * 25; if (progress_s / 10 == 0) { ssd1306_basic_draw_str(sps->progress_x, sps->progress_y - 8, &xchange, &ychange, "xxx", &font8x8_xo_lib); } else if (progress_s / 10 == 1) { ssd1306_basic_draw_str(sps->progress_x, sps->progress_y - 8, &xchange, &ychange, "oxx", &font8x8_xo_lib); } else if (progress_s / 10 == 2) { ssd1306_basic_draw_str(sps->progress_x, sps->progress_y - 8, &xchange, &ychange, "oox", &font8x8_xo_lib); } else if (progress_s / 10 == 3) { ssd1306_basic_draw_str(sps->progress_x, sps->progress_y - 8, &xchange, &ychange, "ooo", &font8x8_xo_lib); } wave_drawer_draw_next_point(&sps->wave_drawer, wave_y); ssd1306_basic_draw_progress(sps->progress_x, sps->progress_y, sps->progress_width, sps->progress_hight, 25, progress); if (heartrate <= 0) { ssd1306_basic_draw_str(sps->heartrate_x, sps->heartrate_y, &xchange, &ychange, "<>-- ", &font_asicc16x8_lib); } else { ssd1306_basic_draw_str(sps->heartrate_x, sps->heartrate_y, &xchange, &ychange, fmt("<>%3d", heartrate), &font_asicc16x8_lib); } if (update_screen) ssd1306_basic_gram_update(); } #endif void dsp_mgr_change_to_sampling(int progress_s, int heartrate) { // sample_page_state_t* sps = &m_sample_page_state; sps->progress_x = SMAPLE_PAGE_START_X + 10; sps->progress_y = SMAPLE_PAGE_START_Y + 3; sps->progress_width = 100; sps->progress_hight = 8; sps->wave_drawser_x = SMAPLE_PAGE_START_X + 5; sps->wave_drawser_y = SMAPLE_PAGE_START_Y + sps->progress_hight + 5; sps->wave_drawser_hight = 45; sps->wave_drawser_width = 85; sps->heartrate_x = sps->wave_drawser_x + sps->wave_drawser_width + 1; sps->heartrate_y = sps->wave_drawser_y + 5; int progress = progress_s / SAMPLE_MIN_TIME_S * 25; uint8_t xchange, ychange; ssd1306_basic_clear_gram(); /** * @brief * ================= * | | 心 * | wave | * | | 心率 */ ssd1306_basic_draw_progress(sps->progress_x, sps->progress_y, sps->progress_width, sps->progress_hight, 25, progress); // ssd1306_basic_draw_str(sps->progress_x + sps->progress_width + 2, sps->progress_y, &xchange, &ychange, "x", &font8x8_xo_lib); wave_drawer_init(&sps->wave_drawer, sps->wave_drawser_x, sps->wave_drawser_y, sps->wave_drawser_width, sps->wave_drawser_hight); // wave_drawer_draw_border(&sps->wave_drawer); 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 { ssd1306_basic_draw_str(sps->heartrate_x, sps->heartrate_y + 20, &xchange, &ychange, fmt("%3d", heartrate), &font_asicc16x8_lib); } ssd1306_basic_gram_update(); dsp_mgr_change_to_page(kPage_sampling); } 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; ssd1306_basic_draw_progress(sps->progress_x, sps->progress_y, sps->progress_width, sps->progress_hight, 25, progress); // if (progress_s / 10 >= 3) { // ssd1306_basic_draw_str(sps->progress_x + sps->progress_width + 2, sps->progress_y, &xchange, &ychange, "o", &font8x8_xo_lib); // } 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; } if (heartrate <= 0) { ssd1306_basic_draw_str(sps->heartrate_x, sps->heartrate_y + 20, &xchange, &ychange, "-- ", &font_asicc16x8_lib); } else { if (heartrate >= 100) { ssd1306_basic_draw_str(sps->heartrate_x, sps->heartrate_y + 20, &xchange, &ychange, fmt("%d", heartrate), &font_asicc16x8_lib); } else { ssd1306_basic_draw_str(sps->heartrate_x + 4, sps->heartrate_y + 20, &xchange, &ychange, fmt("%d", heartrate), &font_asicc16x8_lib); } } wave_drawer_draw_next_point(&sps->wave_drawer, wave_y); if (update_screen) ssd1306_basic_gram_update(); } void samplePage_schedule() { static int count = 0; count++; int capturetime = hwss_has_captured_time_ms(); 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, hwss_read_heart_rate(), count % 30 == 0, count % 10 == 0); } /******************************************************************************* * samplingError * *******************************************************************************/ void dsp_mgr_change_to_samplingError() { /** * @brief * 不足30秒[X] */ ssd1306_basic_clear_gram(); uint8_t x; uint8_t y; x = compute_x_pos_by_center(SCREEN_CENTER_X, font24x24_zh_lib.widthPixel * 3 + font12x24_asiic_lib.widthPixel * 2); y = compute_y_pos_by_center(SCREEN_CENTER_Y, font24x24_zh_lib.heightPixel); uint8_t xchange, ychange; ssd1306_basic_draw_str(x, y, &xchange, &ychange, "不足", &font24x24_zh_lib); x = x + xchange; ssd1306_basic_draw_str(x, y, &xchange, &ychange, "30", &font12x24_asiic_lib); x = x + xchange; ssd1306_basic_draw_str(x, y, &xchange, &ychange, "秒", &font24x24_zh_lib); x = x + xchange; ssd1306_basic_gram_update(); dsp_mgr_change_to_page(kPage_samplingError); } void dsp_mgr_change_to_sampleSuc() { /** * @brief * 1.进度条 * 2.提示信息 */ ssd1306_basic_clear(); uint8_t x = 0; uint8_t y = 0; uint8_t xchange, ychange; x = compute_x_pos_by_center(SCREEN_CENTER_X, font24x24_zh_lib.widthPixel * 4); y = compute_y_pos_by_center(SCREEN_CENTER_Y, font24x24_zh_lib.heightPixel); ssd1306_basic_draw_str(x, y, &xchange, &ychange, "采集完成", &font24x24_zh_lib); ssd1306_basic_gram_update(); dsp_mgr_change_to_page(kPage_storagingSuc); } /******************************************************************************* * SCHEDULE * *******************************************************************************/ APP_TIMER_DEF(m_dsp_mgr_schedule_tmr); static void dsp_mgr_schedule_tmr_cb(void* p_context) { // if (g_pageState.page == kPage_chargingPage) { chargingPage_schedule(); } else if (g_pageState.page == kPage_welcome) { welcomePage_schedule(); } else if (g_pageState.page == kPage_main) { mainPage_schedule(); } else if (g_pageState.page == kPage_preparePage) { PreparePage_schedule(); } else if (g_pageState.page == kPage_sampling) { samplePage_schedule(); } } void dsp_mgr_init(void) { static bool timer_inited = false; SingleLeadECG_screen_init(); 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(12), NULL)); timer_inited = true; } void dsp_mgr_uninit(void) { app_timer_stop(m_dsp_mgr_schedule_tmr); SingleLeadECG_screen_deinit(); }