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.
This commit is contained in:
paulb-nl 2018-02-04 16:01:11 +01:00
parent 0905620b4d
commit 4e4f5749ea
6 changed files with 111 additions and 11 deletions

View File

@ -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:

View File

@ -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,

View File

@ -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;

View File

@ -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) } } },
{ "<Import sett. >", 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("<Fw. update >","<ファームウェアアップデート>"), OPT_FUNC_CALL, { .fun = { fw_update, NULL } } },
}))

View File

@ -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;

View File

@ -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;