diff --git a/software/sys_controller/inc/video_modes.h b/software/sys_controller/inc/video_modes.h index fbd05df..f71930a 100644 --- a/software/sys_controller/inc/video_modes.h +++ b/software/sys_controller/inc/video_modes.h @@ -70,8 +70,11 @@ typedef enum { GROUP_720P = 8, GROUP_1080I = 9, GROUP_1080P = 10, + GROUP_FIXED_VHZ = 11, // fixed-refresh workstation modes: only matched when the input refresh is within FIXED_VHZ_TOL_X100 } video_group; +#define FIXED_VHZ_TOL_X100 30 // +-0.30 Hz (measured refresh is exact to ~0.01 Hz) + typedef enum { MODE_INTERLACED = (1<<0), //deprecated MODE_CRT = (1<<1), diff --git a/software/sys_controller/src/controls.c b/software/sys_controller/src/controls.c index eb2fb83..63f971b 100644 --- a/software/sys_controller/src/controls.c +++ b/software/sys_controller/src/controls.c @@ -173,8 +173,8 @@ int parse_control() unsigned uart_rx_arg; // one for each video_group - alt_u8* pmcfg_ptr[] = { &pt_only, &tc.pm_240p, &tc.pm_240p, &tc.pm_384p, &tc.pm_480i, &tc.pm_480i, &tc.pm_480p, &tc.pm_480p, &pt_only, &tc.pm_1080i, &pt_only }; - alt_u8 valid_pm[] = { 0x1, 0x3f, 0x3f, 0x7, 0xf, 0xf, 0x7, 0x7, 0x1, 0x3, 0x1 }; + alt_u8* pmcfg_ptr[] = { &pt_only, &tc.pm_240p, &tc.pm_240p, &tc.pm_384p, &tc.pm_480i, &tc.pm_480i, &tc.pm_480p, &tc.pm_480p, &pt_only, &tc.pm_1080i, &pt_only, &pt_only }; + alt_u8 valid_pm[] = { 0x1, 0x3f, 0x3f, 0x7, 0xf, 0xf, 0x7, 0x7, 0x1, 0x3, 0x1, 0x1 }; avinput_t next_input = (cm.avinput == AV3_YPBPR) ? AV1_RGBs : (cm.avinput+1); @@ -315,7 +315,7 @@ int parse_control() break; } - if (video_modes_plm[cm.id].group > GROUP_1080P) { + if (video_modes_plm[cm.id].group > GROUP_FIXED_VHZ) { printf("WARNING: Corrupted mode (id %d)\n", cm.id); break; } diff --git a/software/sys_controller/src/video_modes.c b/software/sys_controller/src/video_modes.c index 96cfc73..473813b 100644 --- a/software/sys_controller/src/video_modes.c +++ b/software/sys_controller/src/video_modes.c @@ -133,7 +133,7 @@ uint32_t calculate_pclk(uint32_t src_clk_hz, mode_data_t *vm_out, vm_proc_config int get_pure_lm_mode(avconfig_t *cc, mode_data_t *vm_in, mode_data_t *vm_out, vm_proc_config_t *vm_conf) { - int i, diff_lines, diff_v_hz_x100, mindiff_id=0, mindiff_lines=1000, mindiff_v_hz_x100=10000, x_rpt_decr=0, skip_hv_mult=0; + int i, diff_lines, diff_v_hz_x100, mindiff_id=0, mindiff_lines=1000, mindiff_v_hz_x100=10000, x_rpt_decr=0, skip_hv_mult=0, settled=0; mode_data_t *mode_preset; mode_flags valid_lm[] = { (MODE_PT | (cc->pt_mode ? (MODE_L5_GEN_4_3<<(cc->pt_mode-1)) : 0)), (MODE_L2 | (MODE_L2<l2_mode)), @@ -146,11 +146,23 @@ int get_pure_lm_mode(avconfig_t *cc, mode_data_t *vm_in, mode_data_t *vm_out, vm uint8_t upsample2x = cc->upsample2x; // one for each video_group - uint8_t* group_ptr[] = { &pt_only, &cc->pm_240p, &cc->pm_240p, &cc->pm_384p, &cc->pm_480i, &cc->pm_480i, &cc->pm_480p, &cc->pm_480p, &pt_only, &cc->pm_1080i, &pt_only }; + uint8_t* group_ptr[] = { &pt_only, &cc->pm_240p, &cc->pm_240p, &cc->pm_384p, &cc->pm_480i, &cc->pm_480i, &cc->pm_480p, &cc->pm_480p, &pt_only, &cc->pm_1080i, &pt_only, &pt_only }; for (i=0; igroup == GROUP_FIXED_VHZ) && + (abs((int)vm_in->timings.v_hz_x100 - (int)mode_preset->timings.v_hz_x100) > FIXED_VHZ_TOL_X100)) + continue; + + // After the early exit below, only the fixed-refresh presets (appended at the end of the table) may still + // compete, so a preset sharing its line count with a VESA mode can win the equal-line refresh tie-break. + if (settled && (mode_preset->group != GROUP_FIXED_VHZ)) + continue; + switch (mode_preset->group) { case GROUP_384P: //fixed Line2x/3x mode for 240x360p/400p @@ -213,8 +225,8 @@ int get_pure_lm_mode(avconfig_t *cc, mode_data_t *vm_in, mode_data_t *vm_out, vm mindiff_v_hz_x100 = diff_v_hz_x100; mindiff_lm = target_lm; } else if ((mindiff_lines <= 2) && (diff_lines > mindiff_lines)) { - // Break out if suitable mode already found - break; + // Stop considering regular presets once a suitable mode has been found + settled = 1; } } }