From f9df15f2003aee8c3e39810d090cfb9fc38768c3 Mon Sep 17 00:00:00 2001 From: SG Date: Sat, 31 Jan 2026 23:57:41 +0000 Subject: [PATCH 1/2] Ability to switch between current source and external analog module on a fly --- src/core/app_state.c | 15 ++++--- src/core/app_state.h | 2 +- src/core/elrs.c | 4 +- src/core/main.c | 2 +- src/ui/page_imagesettings.c | 2 +- src/ui/page_input.c | 3 +- src/ui/page_osd.c | 2 +- src/ui/page_source.c | 87 ++++++++++++++++++++++++++++--------- src/ui/page_source.h | 1 + 9 files changed, 86 insertions(+), 32 deletions(-) diff --git a/src/core/app_state.c b/src/core/app_state.c index 0f041121..6407ec27 100755 --- a/src/core/app_state.c +++ b/src/core/app_state.c @@ -73,17 +73,19 @@ void app_exit_menu() { app_switch_to_av_in(); break; case SOURCE_ANALOG: - app_switch_to_analog(); + app_switch_to_analog(false); break; } } -void app_switch_to_analog() { +void app_switch_to_analog(bool force_external) { system_exec("aww 0x0300b084 0x00001555"); // Set vdpo clock driver strength to level 2. Refer datasheet 12.7.5.11 Analog_Module_Power(0, 1); if (GOGGLE_VER_2) { - if (g_setting.source.analog_module == SETTING_SOURCES_ANALOG_MODULE_INTERNAL) { + if (force_external) { + RTC6715_Open(0, 0); + } else if (g_setting.source.analog_module == SETTING_SOURCES_ANALOG_MODULE_INTERNAL) { RTC6715_Open(1, g_setting.record.audio_source == SETTING_RECORD_AUDIO_SOURCE_AV_IN); RTC6715_SetCH(g_setting.source.analog_channel - 1); } else { @@ -101,8 +103,11 @@ void app_switch_to_analog() { lv_timer_handler(); Display_Osd(g_setting.record.osd); - g_setting.autoscan.last_source = SETTING_AUTOSCAN_SOURCE_ANALOG; - ini_putl("autoscan", "last_source", g_setting.autoscan.last_source, SETTING_INI); + if(!force_external){ + // save only if not forced to external module + g_setting.autoscan.last_source = SETTING_AUTOSCAN_SOURCE_ANALOG; + ini_putl("autoscan", "last_source", g_setting.autoscan.last_source, SETTING_INI); + } // audio in&out dvr_select_audio_source(g_setting.record.audio_source); diff --git a/src/core/app_state.h b/src/core/app_state.h index c0400b21..aa0c6bff 100755 --- a/src/core/app_state.h +++ b/src/core/app_state.h @@ -37,7 +37,7 @@ void app_state_push(app_state_t state); void app_switch_to_menu(); void app_exit_menu(); -void app_switch_to_analog(); +void app_switch_to_analog(bool force_external); void app_switch_to_av_in(); void app_switch_to_hdmi_in(); void app_switch_to_hdzero(bool is_default); diff --git a/src/core/elrs.c b/src/core/elrs.c index 2643338a..d2e9e6b0 100755 --- a/src/core/elrs.c +++ b/src/core/elrs.c @@ -275,7 +275,7 @@ void msp_process_packet() { beep(); pthread_mutex_lock(&lvgl_mutex); dvr_cmd(DVR_STOP); - app_switch_to_analog(); + app_switch_to_analog(false); app_state_push(APP_STATE_VIDEO); pthread_mutex_unlock(&lvgl_mutex); } @@ -327,7 +327,7 @@ void msp_process_packet() { g_setting.scan.channel = chan; beep(); pthread_mutex_lock(&lvgl_mutex); - app_switch_to_analog(); + app_switch_to_analog(false); app_state_push(APP_STATE_VIDEO); pthread_mutex_unlock(&lvgl_mutex); break; diff --git a/src/core/main.c b/src/core/main.c index bb6a3ca5..a55ea8a6 100644 --- a/src/core/main.c +++ b/src/core/main.c @@ -102,7 +102,7 @@ void start_running(void) { app_state_push(APP_STATE_VIDEO); if (source == SETTING_AUTOSCAN_SOURCE_ANALOG) { // analog g_hw_stat.av_pal[1] = g_setting.source.analog_format; - app_switch_to_analog(); + app_switch_to_analog(false); g_source_info.source = SOURCE_ANALOG; } else if (source == SETTING_AUTOSCAN_SOURCE_AV_IN) { // AV in g_hw_stat.av_pal[0] = g_setting.source.analog_format; diff --git a/src/ui/page_imagesettings.c b/src/ui/page_imagesettings.c index b473174d..326b20ee 100755 --- a/src/ui/page_imagesettings.c +++ b/src/ui/page_imagesettings.c @@ -131,7 +131,7 @@ static void page_imagesettings_enter() { break; case SOURCE_ANALOG: - app_switch_to_analog(); + app_switch_to_analog(false); g_bShowIMS = true; break; } diff --git a/src/ui/page_input.c b/src/ui/page_input.c index 98075754..fc188fe9 100644 --- a/src/ui/page_input.c +++ b/src/ui/page_input.c @@ -51,7 +51,7 @@ static void nop() {} static void rollerNop(uint8_t key) { (void)key; } static const action_t btnActions[] = { - {.id = 10, .name = "None", .functionPtr = &nop}, + {.id = 11, .name = "None", .functionPtr = &nop}, {.id = 0, .name = "Toggle OSD", .functionPtr = &osd_toggle}, {.id = 1, .name = "Main menu", .functionPtr = &app_switch_to_menu}, {.id = 2, .name = "Toggle DVR", .functionPtr = &dvr_toggle}, @@ -62,6 +62,7 @@ static const action_t btnActions[] = { {.id = 7, .name = "Star DVR", .functionPtr = &dvr_star}, {.id = 8, .name = "Toggle source", .functionPtr = &source_toggle}, {.id = 9, .name = "Cycle source", .functionPtr = &source_cycle}, + {.id = 10, .name = "Toggle cam", .functionPtr = &source_toggle_cam}, }; static const action_t rollerActions[] = { diff --git a/src/ui/page_osd.c b/src/ui/page_osd.c index f48d5718..30db2fea 100644 --- a/src/ui/page_osd.c +++ b/src/ui/page_osd.c @@ -122,7 +122,7 @@ static void open_element_pos_preview() { break; case SOURCE_ANALOG: - app_switch_to_analog(); + app_switch_to_analog(false); break; } diff --git a/src/ui/page_source.c b/src/ui/page_source.c index 46728dd6..378b6fce 100755 --- a/src/ui/page_source.c +++ b/src/ui/page_source.c @@ -27,7 +27,18 @@ static lv_coord_t col_dsc[] = {160, 200, 200, 160, 160, 160, LV_GRID_TEMPLATE_LAST}; static lv_coord_t row_dsc[] = {60, 60, 60, 60, 60, 60, 60, 60, 60, 60, LV_GRID_TEMPLATE_LAST}; -static lv_obj_t *label[5]; +typedef enum { + LABEL_HDZERO, + LABEL_ANALOG, + LABEL_HDMI, + LABEL_AVIN, + LABEL_OLED, + + LABEL_MAX, +} source_type_t; + +static lv_obj_t *label[LABEL_MAX]; + static uint8_t oled_tst_mode = 0; // 0=Normal,1=CB; 2-Grid; 3=All Black; 4=All White,5=Boot logo static bool in_sourcepage = false; static btn_group_t btn_group0, btn_group1, btn_group2, btn_group3, btn_group4; @@ -61,16 +72,16 @@ static lv_obj_t *page_source_create(lv_obj_t *parent, panel_arr_t *arr) { create_select_item(arr, cont); - label[0] = create_label_item(cont, "HDZero", 1, row++, 3); + label[LABEL_HDZERO] = create_label_item(cont, "HDZero", 1, row++, 3); if (GOGGLE_VER_2) { - label[1] = create_label_item(cont, "Analog", 1, row++, 3); + label[LABEL_ANALOG] = create_label_item(cont, "Analog", 1, row++, 3); } else { - label[1] = create_label_item(cont, _lang("Expansion Module"), 1, row++, 3); + label[LABEL_ANALOG] = create_label_item(cont, _lang("Expansion Module"), 1, row++, 3); } snprintf(buf, sizeof(buf), "HDMI %s", _lang("In")); - label[2] = create_label_item(cont, buf, 1, row++, 3); + label[LABEL_HDMI] = create_label_item(cont, buf, 1, row++, 3); snprintf(buf, sizeof(buf), "AV %s", _lang("In")); - label[3] = create_label_item(cont, buf, 1, row++, 3); + label[LABEL_AVIN] = create_label_item(cont, buf, 1, row++, 3); create_btn_group_item(&btn_group0, cont, 2, _lang("HDZero Band"), _lang("Raceband"), _lang("Lowband"), "", "", row++); btn_group_set_sel(&btn_group0, g_setting.source.hdzero_band); @@ -91,10 +102,10 @@ static lv_obj_t *page_source_create(lv_obj_t *parent, panel_arr_t *arr) { snprintf(buf, sizeof(buf), "< %s", _lang("Back")); if (g_setting.storage.selftest) { - label[4] = create_label_item(cont, "OLED Pattern: Normal", 1, row++, 3); + label[LABEL_OLED] = create_label_item(cont, "OLED Pattern: Normal", 1, row++, 3); create_label_item(cont, buf, 1, row++, 3); } else { - label[4] = NULL; + label[LABEL_OLED] = NULL; create_label_item(cont, buf, 1, row++, 3); } pp_source.p_arr.max = row; @@ -132,7 +143,7 @@ void source_status_timer() { } snprintf(buf, sizeof(buf), "HDZero: L%d", ch); } - lv_label_set_text(label[0], buf); + lv_label_set_text(label[LABEL_HDZERO], buf); // analog if (GOGGLE_VER_2) { @@ -144,22 +155,22 @@ void source_status_timer() { } else { snprintf(buf, sizeof(buf), "%s: %s", _lang("Expansion Module"), state2string(g_source_info.av_bay_status)); } - lv_label_set_text(label[1], buf); + lv_label_set_text(label[LABEL_ANALOG], buf); // hdmi in snprintf(buf, sizeof(buf), "HDMI %s: %s", _lang("In"), state2string(g_source_info.hdmi_in_status)); - lv_label_set_text(label[2], buf); + lv_label_set_text(label[LABEL_HDMI], buf); // av in snprintf(buf, sizeof(buf), "AV %s: %s", _lang("In"), state2string(g_source_info.av_in_status)); - lv_label_set_text(label[3], buf); + lv_label_set_text(label[LABEL_AVIN], buf); - if (g_setting.storage.selftest && label[3]) { + if (g_setting.storage.selftest && label[LABEL_AVIN]) { uint8_t oled_tm = oled_tst_mode & 0x0F; char *pattern_label[6] = {"Normal", "Color Bar", "Grid", "All Black", "All White", "Boot logo"}; char str[32]; snprintf(str, sizeof(buf), "OLED Pattern: %s", pattern_label[oled_tm]); - lv_label_set_text(label[4], str); + lv_label_set_text(label[LABEL_OLED], str); } } @@ -185,8 +196,8 @@ static void page_source_select_av_in() { dvr_enable_line_out(true); } -static void page_source_select_analog() { - app_switch_to_analog(); +static void page_source_select_analog(bool force_external) { + app_switch_to_analog(force_external); app_state_push(APP_STATE_VIDEO); g_source_info.source = SOURCE_ANALOG; dvr_select_audio_source(g_setting.record.audio_source); @@ -197,7 +208,7 @@ void source_toggle() { beep_dur(BEEP_SHORT); switch (g_source_info.source) { case SOURCE_HDZERO: - page_source_select_analog(); + page_source_select_analog(false); break; case SOURCE_ANALOG: page_source_select_hdzero(); @@ -225,7 +236,7 @@ void source_cycle() { page_source_select_hdzero(); break; case SOURCE_AV_IN: - page_source_select_analog(); + page_source_select_analog(false); break; case SOURCE_HDMI_IN: page_source_select_av_in(); @@ -233,6 +244,42 @@ void source_cycle() { } } +#include "driver/rtc6715.h" +void source_toggle_cam() { + static bool camera_enabled = false; + static source_info_t source_info_backup; + + if (!camera_enabled) { + camera_enabled = true; + source_info_backup = g_source_info; + + if (g_source_info.source == SOURCE_ANALOG) { + RTC6715_Open(0, 0); + } else { + page_source_select_analog(true); + } + } else { + camera_enabled = false; + g_source_info = source_info_backup; + switch (g_source_info.source) { + case SOURCE_HDZERO: + page_source_select_hdzero(); + break; + case SOURCE_ANALOG: + // page_source_select_analog(false); + RTC6715_Open(1, g_setting.record.audio_source == SETTING_RECORD_AUDIO_SOURCE_AV_IN); + RTC6715_SetCH(g_setting.source.analog_channel - 1); + break; + case SOURCE_AV_IN: + page_source_select_av_in(); + break; + case SOURCE_HDMI_IN: + page_source_select_hdmi_in(); + break; + } + } +} + static void page_source_on_click(uint8_t key, int sel) { switch (sel) { case 0: // HDZero in @@ -240,7 +287,7 @@ static void page_source_on_click(uint8_t key, int sel) { break; case 1: // Analog - page_source_select_analog(); + page_source_select_analog(false); break; case 2: // hdmi_in @@ -287,7 +334,7 @@ static void page_source_on_click(uint8_t key, int sel) { break; case 8: - if (g_setting.storage.selftest && label[4]) { + if (g_setting.storage.selftest && label[LABEL_OLED]) { uint8_t oled_te = (oled_tst_mode != 0); uint8_t oled_tm = (oled_tst_mode & 0x0F) - 1; // LOGI("OLED TE=%d,TM=%d",oled_te,oled_tm); diff --git a/src/ui/page_source.h b/src/ui/page_source.h index aeb2d0b9..e0b67ebc 100755 --- a/src/ui/page_source.h +++ b/src/ui/page_source.h @@ -13,6 +13,7 @@ extern page_pack_t pp_source; void source_status_timer(); void source_toggle(); void source_cycle(); +void source_toggle_cam(); #ifdef __cplusplus } From 44dfe0bd05870743752373d6e253dbdd8da819f4 Mon Sep 17 00:00:00 2001 From: SG Date: Sat, 31 Jan 2026 23:59:51 +0000 Subject: [PATCH 2/2] fix input ids --- src/ui/page_input.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/ui/page_input.c b/src/ui/page_input.c index fc188fe9..543b79d3 100644 --- a/src/ui/page_input.c +++ b/src/ui/page_input.c @@ -51,7 +51,7 @@ static void nop() {} static void rollerNop(uint8_t key) { (void)key; } static const action_t btnActions[] = { - {.id = 11, .name = "None", .functionPtr = &nop}, + {.id = 10, .name = "None", .functionPtr = &nop}, {.id = 0, .name = "Toggle OSD", .functionPtr = &osd_toggle}, {.id = 1, .name = "Main menu", .functionPtr = &app_switch_to_menu}, {.id = 2, .name = "Toggle DVR", .functionPtr = &dvr_toggle}, @@ -62,7 +62,7 @@ static const action_t btnActions[] = { {.id = 7, .name = "Star DVR", .functionPtr = &dvr_star}, {.id = 8, .name = "Toggle source", .functionPtr = &source_toggle}, {.id = 9, .name = "Cycle source", .functionPtr = &source_cycle}, - {.id = 10, .name = "Toggle cam", .functionPtr = &source_toggle_cam}, + {.id = 11, .name = "Toggle cam", .functionPtr = &source_toggle_cam}, }; static const action_t rollerActions[] = {