From 4e4f5749ea1ba7302a70529c0a37c741e16d8a68 Mon Sep 17 00:00:00 2001 From: paulb-nl Date: Sun, 4 Feb 2018 16:01:11 +0100 Subject: [PATCH] Add auto input switching Cycle through inputs until sync is found or limit has been reached. RGsB or YPbPr defaults can be set per input. Stay on current physical input for a short time when sync is lost. Press right button on the remote for next input. --- software/sys_controller/ossc/av_controller.c | 89 +++++++++++++++++--- software/sys_controller/ossc/av_controller.h | 5 ++ software/sys_controller/ossc/controls.c | 8 +- software/sys_controller/ossc/menu.c | 7 ++ software/sys_controller/ossc/userdata.c | 9 ++ software/sys_controller/ossc/userdata.h | 4 + 6 files changed, 111 insertions(+), 11 deletions(-) diff --git a/software/sys_controller/ossc/av_controller.c b/software/sys_controller/ossc/av_controller.c index 911d5ce..3f86c29 100644 --- a/software/sys_controller/ossc/av_controller.c +++ b/software/sys_controller/ossc/av_controller.c @@ -41,6 +41,7 @@ #include "HDMI_TX.h" #include "hdmitx.h" #include "sd_io.h" +#include "sys/alt_timestamp.h" #define STABLE_THOLD 1 #define MIN_LINES_PROGRESSIVE 200 @@ -69,6 +70,7 @@ alt_u8 stable_frames; alt_u8 update_cur_vm; alt_u8 vm_sel, vm_edit, profile_sel, profile_sel_menu, input_profiles[AV_LAST], lt_sel, def_input, profile_link, lcd_bl_timeout; +alt_u8 auto_input, auto_av1_ypbpr, auto_av2_ypbpr = 1, auto_av3_ypbpr; alt_u16 tc_h_samplerate, tc_h_synclen, tc_h_bporch, tc_h_active, tc_v_synclen, tc_v_bporch, tc_v_active; char row1[LCD_ROW_LEN+1], row2[LCD_ROW_LEN+1], menu_row1[LCD_ROW_LEN+1], menu_row2[LCD_ROW_LEN+1]; @@ -785,6 +787,12 @@ int main() alt_u32 input_vec; + alt_u32 auto_input_timestamp = 300 * (alt_timestamp_freq() >> 10); + alt_u8 auto_input_changed = 0; + alt_u8 auto_input_ctr = 0; + alt_u8 auto_input_current_ctr = AUTO_CURRENT_MAX_COUNT; + alt_u8 auto_input_keep_current = 0; + int init_stat, man_input_change; init_stat = init_hw(); @@ -806,6 +814,9 @@ int main() while (1) {} } + // start timer for auto input + alt_timestamp_start(); + // Mainloop while(1) { // Read remote control and PCB button status @@ -826,11 +837,68 @@ int main() btn_code = 0; } + // Auto input switching + if (auto_input != AUTO_OFF && cm.avinput != AV_TESTPAT && !cm.sync_active && !menu_active + && alt_timestamp() >= auto_input_timestamp && auto_input_ctr < AUTO_MAX_COUNT) { + + // Keep switching on the same physical input when set to Current input or a short time after losing sync. + auto_input_keep_current = (auto_input == AUTO_CURRENT_INPUT || auto_input_current_ctr < AUTO_CURRENT_MAX_COUNT); + + switch(cm.avinput) { + case AV1_RGBs: + target_input = auto_av1_ypbpr ? AV1_YPBPR : AV1_RGsB; + break; + case AV1_RGsB: + case AV1_YPBPR: + target_input = auto_input_keep_current ? AV1_RGBs : (auto_av2_ypbpr ? AV2_YPBPR : AV2_RGsB); + break; + case AV2_YPBPR: + case AV2_RGsB: + target_input = auto_input_keep_current ? target_input : AV3_RGBHV; + break; + case AV3_RGBHV: + target_input = AV3_RGBs; + break; + case AV3_RGBs: + target_input = auto_av3_ypbpr ? AV3_YPBPR : AV3_RGsB; + break; + case AV3_RGsB: + case AV3_YPBPR: + target_input = auto_input_keep_current ? AV3_RGBHV : AV1_RGBs; + break; + default: + break; + } + + auto_input_ctr++; + + if (auto_input_current_ctr < AUTO_CURRENT_MAX_COUNT) + auto_input_current_ctr++; + + // For input linked profile loading below + auto_input_changed = 1; + + // reset timer + alt_timestamp_start(); + } + man_input_change = parse_control(); if (menu_active) display_menu(0); + // Only auto load profile when input is manually changed or when sync is active after automatic switch. + if ((target_input != cm.avinput && man_input_change) || (auto_input_changed && cm.sync_active)) { + // The input changed, so load the appropriate profile if + // input->profile link is enabled + if (profile_link && (profile_sel != input_profiles[target_input])) { + profile_sel = input_profiles[target_input]; + read_userdata(profile_sel); + } + + auto_input_changed = 0; + } + if (target_input != cm.avinput) { target_tvp = TVP_INPUT1; @@ -873,13 +941,6 @@ int main() printf("### SWITCH MODE TO %s ###\n", avinput_str[target_input]); - // The input changed, so load the appropriate profile if - // input->profile link is enabled - if (profile_link && (profile_sel != input_profiles[target_input])) { - profile_sel = input_profiles[target_input]; - read_userdata(profile_sel); - } - cm.avinput = target_input; cm.sync_active = 0; ths_source_sel(target_ths, (cm.cc.video_lpf > 1) ? (VIDEO_LPF_MAX-cm.cc.video_lpf) : THS_LPF_BYPASS); @@ -895,9 +956,14 @@ int main() strncpy(row2, " NO SYNC", LCD_ROW_LEN+1); if (!menu_active) lcd_write_status(); - // record last input if it was selected manually - if ((def_input == AV_LAST) && man_input_change) - write_userdata(INIT_CONFIG_SLOT); + if (man_input_change) { + // record last input if it was selected manually + if (def_input == AV_LAST) + write_userdata(INIT_CONFIG_SLOT); + // Reset auto input timer when input is manually changed + auto_input_ctr = 0; + alt_timestamp_start(); + } } // Check here to enable regardless of input @@ -933,6 +999,9 @@ int main() strncpy(row2, " NO SYNC", LCD_ROW_LEN+1); if (!menu_active) lcd_write_status(); + alt_timestamp_start();// reset auto input timer + auto_input_ctr = 0; + auto_input_current_ctr = 0; } break; case MODE_CHANGE: diff --git a/software/sys_controller/ossc/av_controller.h b/software/sys_controller/ossc/av_controller.h index bb02520..dcb1ad1 100644 --- a/software/sys_controller/ossc/av_controller.h +++ b/software/sys_controller/ossc/av_controller.h @@ -61,6 +61,11 @@ #define FPGA_SCANLINEMODE_V 2 #define FPGA_SCANLINEMODE_ALT 3 +#define AUTO_OFF 0 +#define AUTO_CURRENT_INPUT 1 +#define AUTO_MAX_COUNT 100 +#define AUTO_CURRENT_MAX_COUNT 6 + // In reverse order of importance typedef enum { NO_CHANGE = 0, diff --git a/software/sys_controller/ossc/controls.c b/software/sys_controller/ossc/controls.c index 65db3c1..00e062f 100644 --- a/software/sys_controller/ossc/controls.c +++ b/software/sys_controller/ossc/controls.c @@ -119,6 +119,8 @@ int parse_control() alt_u8* pmcfg_ptr[] = { &pt_only, &tc.pm_240p, &tc.pm_384p, &tc.pm_480i, &tc.pm_480p, &tc.pm_480p, &tc.pm_1080i }; alt_u8 valid_pm[] = { 0x1, 0x1f, 0x3, 0xf, 0x3, 0x3, 0x3 }; + avinput_t next_input = (cm.avinput == AV3_YPBPR) ? AV1_RGBs : (cm.avinput+1); + if (remote_code) printf("RCODE: 0x%.4lx, %d\n", remote_code, remote_rpt); @@ -239,6 +241,10 @@ int parse_control() lcd_write_status(); menu_active = 0; break; + case RC_RIGHT: + if (!menu_active) + man_target_input = next_input; + break; default: break; } @@ -246,7 +252,7 @@ int parse_control() Button_Check: if (btn_code & PB0_BIT) - man_target_input = (cm.avinput == AV3_YPBPR) ? AV1_RGBs : (cm.avinput+1); + man_target_input = next_input; if (btn_code & PB1_BIT) tc.sl_mode = tc.sl_mode < SL_MODE_MAX ? tc.sl_mode + 1 : 0; diff --git a/software/sys_controller/ossc/menu.c b/software/sys_controller/ossc/menu.c index ce3cffa..396068d 100644 --- a/software/sys_controller/ossc/menu.c +++ b/software/sys_controller/ossc/menu.c @@ -42,6 +42,7 @@ extern alt_u16 tc_h_samplerate, tc_h_synclen, tc_h_bporch, tc_h_active, tc_v_syn extern alt_u32 remote_code; extern alt_u16 rc_keymap[REMOTE_MAX_KEYS]; extern alt_u8 vm_sel, profile_sel_menu, lt_sel, def_input, profile_link, lcd_bl_timeout; +extern alt_u8 auto_input, auto_av1_ypbpr, auto_av2_ypbpr, auto_av3_ypbpr; alt_u8 menu_active; @@ -66,6 +67,8 @@ static const char *sl_id_desc[] = { LNG("Top","ウエ"), LNG("Bottom","シタ") static const char *audio_dw_sampl_desc[] = { LNG("Off (fs = 96kHz)","オフ (fs = 96kHz)"), "2x (fs = 48kHz)" }; static const char *lt_desc[] = { "Top-left", "Center", "Bottom-right" }; static const char *lcd_bl_timeout_desc[] = { "Off", "3s", "10s", "30s" }; +static const char *rgsb_ypbpr_desc[] = { "RGsB", "YPbPr" }; +static const char *auto_input_desc[] = { "Off", "Current input", "All inputs" }; static void sampler_phase_disp(alt_u8 v) { sniprintf(menu_row2, LCD_ROW_LEN+1, LNG("%d deg","%d ド"), (v*1125)/100); } static void sync_vth_disp(alt_u8 v) { sniprintf(menu_row2, LCD_ROW_LEN+1, "%d mV", (v*1127)/100); } @@ -181,6 +184,10 @@ MENU(menu_settings, P99_PROTECT({ \ { LNG("Link input->prof","Link input->prof"), OPT_AVCONFIG_SELECTION, { .sel = { &profile_link, OPT_WRAP, SETTING_ITEM(off_on_desc) } } }, { "", OPT_FUNC_CALL, { .fun = { import_userdata, NULL } } }, { LNG("Initial input","ショキニュウリョク"), OPT_AVCONFIG_SELECTION, { .sel = { &def_input, OPT_WRAP, SETTING_ITEM(avinput_str) } } }, + { "Autodetect input", OPT_AVCONFIG_SELECTION, { .sel = { &auto_input, OPT_WRAP, SETTING_ITEM(auto_input_desc) } } }, + { "Auto AV1 Y/Gs", OPT_AVCONFIG_SELECTION, { .sel = { &auto_av1_ypbpr, OPT_WRAP, SETTING_ITEM(rgsb_ypbpr_desc) } } }, + { "Auto AV2 Y/Gs", OPT_AVCONFIG_SELECTION, { .sel = { &auto_av2_ypbpr, OPT_WRAP, SETTING_ITEM(rgsb_ypbpr_desc) } } }, + { "Auto AV3 Y/Gs", OPT_AVCONFIG_SELECTION, { .sel = { &auto_av3_ypbpr, OPT_WRAP, SETTING_ITEM(rgsb_ypbpr_desc) } } }, { "LCD BL timeout", OPT_AVCONFIG_SELECTION, { .sel = { &lcd_bl_timeout, OPT_WRAP, SETTING_ITEM(lcd_bl_timeout_desc) } } }, { LNG("","<ファームウェアアップデート>"), OPT_FUNC_CALL, { .fun = { fw_update, NULL } } }, })) diff --git a/software/sys_controller/ossc/userdata.c b/software/sys_controller/ossc/userdata.c index 93aab7c..bf41926 100644 --- a/software/sys_controller/ossc/userdata.c +++ b/software/sys_controller/ossc/userdata.c @@ -38,6 +38,7 @@ extern alt_u8 input_profiles[AV_LAST]; extern alt_u8 profile_sel; extern alt_u8 def_input, profile_link; extern alt_u8 lcd_bl_timeout; +extern alt_u8 auto_input, auto_av1_ypbpr, auto_av2_ypbpr, auto_av3_ypbpr; extern SD_DEV sdcard_dev; extern char menu_row1[LCD_ROW_LEN+1], menu_row2[LCD_ROW_LEN+1]; @@ -68,6 +69,10 @@ int write_userdata(alt_u8 entry) ((ude_initcfg*)databuf)->def_input = def_input; ((ude_initcfg*)databuf)->profile_link = profile_link; ((ude_initcfg*)databuf)->lcd_bl_timeout = lcd_bl_timeout; + ((ude_initcfg*)databuf)->auto_input = auto_input; + ((ude_initcfg*)databuf)->auto_av1_ypbpr = auto_av1_ypbpr; + ((ude_initcfg*)databuf)->auto_av2_ypbpr = auto_av2_ypbpr; + ((ude_initcfg*)databuf)->auto_av3_ypbpr = auto_av3_ypbpr; memcpy(((ude_initcfg*)databuf)->keys, rc_keymap, sizeof(rc_keymap)); retval = write_flash_page(databuf, sizeof(ude_initcfg), (USERDATA_OFFSET+entry*SECTORSIZE)/PAGESIZE); if (retval != 0) @@ -145,6 +150,10 @@ int read_userdata(alt_u8 entry) target_input = def_input; else if (((ude_initcfg*)databuf)->last_input < AV_LAST) target_input = ((ude_initcfg*)databuf)->last_input; + auto_input = ((ude_initcfg*)databuf)->auto_input; + auto_av1_ypbpr = ((ude_initcfg*)databuf)->auto_av1_ypbpr; + auto_av2_ypbpr = ((ude_initcfg*)databuf)->auto_av2_ypbpr; + auto_av3_ypbpr = ((ude_initcfg*)databuf)->auto_av3_ypbpr; profile_link = ((ude_initcfg*)databuf)->profile_link; profile_sel = input_profiles[AV_TESTPAT]; // Global profile lcd_bl_timeout = ((ude_initcfg*)databuf)->lcd_bl_timeout; diff --git a/software/sys_controller/ossc/userdata.h b/software/sys_controller/ossc/userdata.h index 2e08903..de2f49b 100644 --- a/software/sys_controller/ossc/userdata.h +++ b/software/sys_controller/ossc/userdata.h @@ -53,6 +53,10 @@ typedef struct { avinput_t last_input; avinput_t def_input; alt_u8 lcd_bl_timeout; + alt_u8 auto_input; + alt_u8 auto_av1_ypbpr; + alt_u8 auto_av2_ypbpr; + alt_u8 auto_av3_ypbpr; alt_u16 keys[REMOTE_MAX_KEYS]; } __attribute__((packed, __may_alias__)) ude_initcfg;