diff --git a/software/sys_controller/ossc/av_controller.c b/software/sys_controller/ossc/av_controller.c index 0cd49de..88952f0 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]; @@ -786,6 +788,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(); @@ -807,6 +815,9 @@ int main() while (1) {} } + // start timer for auto input + alt_timestamp_start(); + // Mainloop while(1) { // Read remote control and PCB button status @@ -827,11 +838,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; @@ -874,13 +942,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); @@ -896,9 +957,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 @@ -934,6 +1000,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 e80a176..5b41f20 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); } @@ -180,6 +183,10 @@ MENU(menu_settings, P99_PROTECT({ \ { LNG("Link prof->input","Link prof->input"), OPT_AVCONFIG_NUMVALUE, { .num = { &tc.link_av, OPT_WRAP, AV1_RGBs, AV_LAST, link_av_desc } } }, { LNG("Link input->prof","Link input->prof"), OPT_AVCONFIG_SELECTION, { .sel = { &profile_link, OPT_WRAP, SETTING_ITEM(off_on_desc) } } }, { 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) } } }, #ifndef DEBUG { "", OPT_FUNC_CALL, { .fun = { import_userdata, 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;