diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 7c001ab2..2ff5a506 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -65,10 +65,13 @@ file( GLOB core_files capture_line_mode7_4bpp.S capture_line_default_4bpp_8bpp.S capture_line_default_sixbits_4bpp_8bpp.S + capture_line_default_eightbits_8bpp.S capture_line_default_double_4bpp_8bpp.S capture_line_default_sixbits_double_4bpp_8bpp.S + capture_line_default_eightbits_double_8bpp.S capture_line_fast_4bpp_8bpp.S capture_line_fast_sixbits_4bpp_8bpp.S + capture_line_fast_eightbits_8bpp.S capture_line_ntsc_sixbits_8bpp.S capture_line_inband_4bpp_8bpp.S capture_line_oddeven_4bpp_8bpp.S diff --git a/src/capture_line_default_eightbits_8bpp.S b/src/capture_line_default_eightbits_8bpp.S new file mode 100644 index 00000000..e879dcbd --- /dev/null +++ b/src/capture_line_default_eightbits_8bpp.S @@ -0,0 +1,85 @@ +#include "rpi-base.h" +#include "defs.h" + +#include "macros.S" + +.text + +.global capture_line_default_eightbits_8bpp + +// The capture line function is provided the following: +// r0 = pointer to current line in frame buffer +// r1 = number of complete psync cycles to capture (=param_chars_per_line) +// r2 = frame buffer line pitch in bytes (=param_fb_pitch) +// r3 = flags register +// r4 = GPLEV0 constant +// r5 = line number count down to 0 (initial value =param_nlines) +// r6 = scan line count modulo 10 +// r7 = number of psyncs to skip +// r8 = frame buffer height (=param_fb_height) +// +// All registers are available as scratch registers (i.e. nothing needs to be preserved) + + .ltorg + + // *** 8 bit *** + + b preload_capture_line_default_eightbits_8bpp +capture_line_default_eightbits_8bpp: + push {lr} + SETUP_VSYNC_DEBUG_R11_R12 + SKIP_PSYNC_NO_OLD_CPLD + push {r14} + SETUP_MASK_R14 +loop_8bpp: + WAIT_FOR_PSYNC_EDGE_FAST // expects GPLEV0 in r4, result in r8 + CAPTURE_EIGHT_BITS_8BPP_0 r11 // input in r8 + WAIT_FOR_PSYNC_EDGE_FAST // expects GPLEV0 in r4, result in r8 + CAPTURE_EIGHT_BITS_8BPP_1 // input in r8 + WAIT_FOR_PSYNC_EDGE_FAST // expects GPLEV0 in r4, result in r8 + CAPTURE_EIGHT_BITS_8BPP_2 // input in r8 + WAIT_FOR_PSYNC_EDGE_FAST // expects GPLEV0 in r4, result in r8 + CAPTURE_EIGHT_BITS_8BPP_3 r5 // input in r8 + + WAIT_FOR_PSYNC_EDGE_FAST // expects GPLEV0 in r4, result in r8 + CAPTURE_EIGHT_BITS_8BPP_0 r12 // input in r8 + WAIT_FOR_PSYNC_EDGE_FAST // expects GPLEV0 in r4, result in r8 + CAPTURE_EIGHT_BITS_8BPP_1 // input in r8 + WAIT_FOR_PSYNC_EDGE_FAST // expects GPLEV0 in r4, result in r8 + CAPTURE_EIGHT_BITS_8BPP_2 // input in r8 + WAIT_FOR_PSYNC_EDGE_FAST // expects GPLEV0 in r4, result in r8 + CAPTURE_EIGHT_BITS_8BPP_3 r6 // input in r8 + + WRITE_R5_R6_IF_LAST + cmp r1, #1 + popeq {r0, pc} + + WAIT_FOR_PSYNC_EDGE_FAST // expects GPLEV0 in r4, result in r8 + CAPTURE_EIGHT_BITS_8BPP_0 r11 // input in r8 + WAIT_FOR_PSYNC_EDGE_FAST // expects GPLEV0 in r4, result in r8 + CAPTURE_EIGHT_BITS_8BPP_1 // input in r8 + WAIT_FOR_PSYNC_EDGE_FAST // expects GPLEV0 in r4, result in r8 + CAPTURE_EIGHT_BITS_8BPP_2 // input in r8 + WAIT_FOR_PSYNC_EDGE_FAST // expects GPLEV0 in r4, result in r8 + CAPTURE_EIGHT_BITS_8BPP_3 r7 // input in r8 + + WAIT_FOR_PSYNC_EDGE_FAST // expects GPLEV0 in r4, result in r8 + CAPTURE_EIGHT_BITS_8BPP_0 r12 // input in r8 + WAIT_FOR_PSYNC_EDGE_FAST // expects GPLEV0 in r4, result in r8 + CAPTURE_EIGHT_BITS_8BPP_1 // input in r8 + WAIT_FOR_PSYNC_EDGE_FAST // expects GPLEV0 in r4, result in r8 + CAPTURE_EIGHT_BITS_8BPP_2 // input in r8 + WAIT_FOR_PSYNC_EDGE_FAST // expects GPLEV0 in r4, result in r8 + CAPTURE_EIGHT_BITS_8BPP_3 r10 // input in r8 + + WRITE_R5_R6_R7_R10 + + subs r1, r1, #2 + bne loop_8bpp + + pop {r0, pc} + + +preload_capture_line_default_eightbits_8bpp: + SETUP_DUMMY_PARAMETERS + b capture_line_default_eightbits_8bpp diff --git a/src/capture_line_default_eightbits_double_8bpp.S b/src/capture_line_default_eightbits_double_8bpp.S new file mode 100644 index 00000000..fc447b9d --- /dev/null +++ b/src/capture_line_default_eightbits_double_8bpp.S @@ -0,0 +1,67 @@ +#include "rpi-base.h" +#include "defs.h" + +#include "macros.S" + +.text + +.global capture_line_default_eightbits_double_8bpp + +// The capture line function is provided the following: +// r0 = pointer to current line in frame buffer +// r1 = number of complete psync cycles to capture (=param_chars_per_line) +// r2 = frame buffer line pitch in bytes (=param_fb_pitch) +// r3 = flags register +// r4 = GPLEV0 constant +// r5 = line number count down to 0 (initial value =param_nlines) +// r6 = scan line count modulo 10 +// r7 = number of psyncs to skip +// r8 = frame buffer height (=param_fb_height) +// +// All registers are available as scratch registers (i.e. nothing needs to be preserved) + + .ltorg + + // *** 8 bit *** + + b preload_capture_line_default_eightbits_double_8bpp +capture_line_default_eightbits_double_8bpp: + push {lr} + SETUP_VSYNC_DEBUG_R11_R12_DOUBLE + SKIP_PSYNC_NO_OLD_CPLD + push {r14} + SETUP_MASK_R14 +loop_8bpp: + WAIT_FOR_PSYNC_EDGE_FAST // expects GPLEV0 in r4, result in r8 + CAPTURE_EIGHT_BITS_DOUBLE_8BPP_LO r11 // input in r8 + WAIT_FOR_PSYNC_EDGE_FAST // expects GPLEV0 in r4, result in r8 + CAPTURE_EIGHT_BITS_DOUBLE_8BPP_HI r5 // input in r8 + WAIT_FOR_PSYNC_EDGE_FAST // expects GPLEV0 in r4, result in r8 + CAPTURE_EIGHT_BITS_DOUBLE_8BPP_LO r12 // input in r8 + WAIT_FOR_PSYNC_EDGE_FAST // expects GPLEV0 in r4, result in r8 + CAPTURE_EIGHT_BITS_DOUBLE_8BPP_HI r6 // input in r8 + + WRITE_R5_R6_IF_LAST + cmp r1, #1 + popeq {r0, pc} + + WAIT_FOR_PSYNC_EDGE_FAST // expects GPLEV0 in r4, result in r8 + CAPTURE_EIGHT_BITS_DOUBLE_8BPP_LO r11 // input in r8 + WAIT_FOR_PSYNC_EDGE_FAST // expects GPLEV0 in r4, result in r8 + CAPTURE_EIGHT_BITS_DOUBLE_8BPP_HI r7 // input in r8 + WAIT_FOR_PSYNC_EDGE_FAST // expects GPLEV0 in r4, result in r8 + CAPTURE_EIGHT_BITS_DOUBLE_8BPP_LO r12 // input in r8 + WAIT_FOR_PSYNC_EDGE_FAST // expects GPLEV0 in r4, result in r8 + CAPTURE_EIGHT_BITS_DOUBLE_8BPP_HI r10 // input in r8 + + WRITE_R5_R6_R7_R10 + + subs r1, r1, #2 + bne loop_8bpp + + pop {r0, pc} + + +preload_capture_line_default_eightbits_double_8bpp: + SETUP_DUMMY_PARAMETERS + b capture_line_default_eightbits_double_8bpp diff --git a/src/capture_line_fast_eightbits_8bpp.S b/src/capture_line_fast_eightbits_8bpp.S new file mode 100644 index 00000000..ce4b7bbf --- /dev/null +++ b/src/capture_line_fast_eightbits_8bpp.S @@ -0,0 +1,84 @@ +#include "rpi-base.h" +#include "defs.h" + +#include "macros.S" + +.text + +.global capture_line_fast_eightbits_8bpp + +// The capture line function is provided the following: +// r0 = pointer to current line in frame buffer +// r1 = number of complete psync cycles to capture (=param_chars_per_line) +// r2 = frame buffer line pitch in bytes (=param_fb_pitch) +// r3 = flags register +// r4 = GPLEV0 constant +// r5 = line number count down to 0 (initial value =param_nlines) +// r6 = scan line count modulo 10 +// r7 = number of psyncs to skip +// r8 = frame buffer height (=param_fb_height) +// +// All registers are available as scratch registers (i.e. nothing needs to be preserved) + + + .ltorg + + // *** 8 bit *** + + b preload_capture_line_fast_eightbits_8bpp +capture_line_fast_eightbits_8bpp: + push {lr} + SETUP_VSYNC_DEBUG_R11_R12 + SKIP_PSYNC_NO_H_SCROLL + push {r14} + SETUP_MASK_R14 +loop_8bpp: + WAIT_FOR_PSYNC_EDGE_FAST // expects GPLEV0 in r4, result in r8 + CAPTURE_EIGHT_BITS_8BPP_0 r11 // input in r8 + WAIT_FOR_PSYNC_EDGE_FAST // expects GPLEV0 in r4, result in r8 + CAPTURE_EIGHT_BITS_8BPP_1 // input in r8 + WAIT_FOR_PSYNC_EDGE_FAST // expects GPLEV0 in r4, result in r8 + CAPTURE_EIGHT_BITS_8BPP_2 // input in r8 + WAIT_FOR_PSYNC_EDGE_FAST // expects GPLEV0 in r4, result in r8 + CAPTURE_EIGHT_BITS_8BPP_3 r5 // input in r8 + + WAIT_FOR_PSYNC_EDGE_FAST // expects GPLEV0 in r4, result in r8 + CAPTURE_EIGHT_BITS_8BPP_0 r12 // input in r8 + WAIT_FOR_PSYNC_EDGE_FAST // expects GPLEV0 in r4, result in r8 + CAPTURE_EIGHT_BITS_8BPP_1 // input in r8 + WAIT_FOR_PSYNC_EDGE_FAST // expects GPLEV0 in r4, result in r8 + CAPTURE_EIGHT_BITS_8BPP_2 // input in r8 + WAIT_FOR_PSYNC_EDGE_FAST // expects GPLEV0 in r4, result in r8 + CAPTURE_EIGHT_BITS_8BPP_3 r6 // input in r8 + + cmp r1, #1 + stmeqia r0, {r5, r6} + popeq {r0, pc} + + WAIT_FOR_PSYNC_EDGE_FAST // expects GPLEV0 in r4, result in r8 + CAPTURE_EIGHT_BITS_8BPP_0 r11 // input in r8 + WAIT_FOR_PSYNC_EDGE_FAST // expects GPLEV0 in r4, result in r8 + CAPTURE_EIGHT_BITS_8BPP_1 // input in r8 + WAIT_FOR_PSYNC_EDGE_FAST // expects GPLEV0 in r4, result in r8 + CAPTURE_EIGHT_BITS_8BPP_2 // input in r8 + WAIT_FOR_PSYNC_EDGE_FAST // expects GPLEV0 in r4, result in r8 + CAPTURE_EIGHT_BITS_8BPP_3 r7 // input in r8 + + WAIT_FOR_PSYNC_EDGE_FAST // expects GPLEV0 in r4, result in r8 + CAPTURE_EIGHT_BITS_8BPP_0 r12 // input in r8 + WAIT_FOR_PSYNC_EDGE_FAST // expects GPLEV0 in r4, result in r8 + CAPTURE_EIGHT_BITS_8BPP_1 // input in r8 + WAIT_FOR_PSYNC_EDGE_FAST // expects GPLEV0 in r4, result in r8 + CAPTURE_EIGHT_BITS_8BPP_2 // input in r8 + WAIT_FOR_PSYNC_EDGE_FAST // expects GPLEV0 in r4, result in r8 + CAPTURE_EIGHT_BITS_8BPP_3 r10 // input in r8 + + stmia r0!, {r5, r6, r7, r10} + subs r1, r1, #2 + bne loop_8bpp + + pop {r0, pc} + +preload_capture_line_fast_eightbits_8bpp: + SETUP_DUMMY_PARAMETERS + b capture_line_fast_eightbits_8bpp diff --git a/src/cpld.h b/src/cpld.h index 674fcd1d..15ec5844 100644 --- a/src/cpld.h +++ b/src/cpld.h @@ -59,4 +59,9 @@ signed int analyze_mode7_alignment(capture_info_t *capinfo); extern cpld_t *cpld; extern capture_info_t *capinfo; +enum { + WIDTH_3, + WIDTH_6, + WIDTH_8 +}; #endif diff --git a/src/cpld_atom.c b/src/cpld_atom.c index ba52b363..ca58274d 100644 --- a/src/cpld_atom.c +++ b/src/cpld_atom.c @@ -189,7 +189,7 @@ static void cpld_update_capture_info(capture_info_t *capinfo) { // Update the capture info stucture, if one was passed in if (capinfo) { // Update the sample width - capinfo->sample_width = 1; // 1 = 6 bits + capinfo->sample_width = WIDTH_6; // Update the line capture function capinfo->capture_line = capture_line_normal_6bpp_table; } diff --git a/src/cpld_rgb.c b/src/cpld_rgb.c index 3fb3f531..cb9fa2fc 100644 --- a/src/cpld_rgb.c +++ b/src/cpld_rgb.c @@ -89,7 +89,7 @@ static int supports_separate; static int supports_analog; // Indicates the Analog frontent interface supports 4 level RGB -static int supports_four_level; +static int supports_8bit; // invert state (not part of config) static int invert = 0; @@ -124,6 +124,13 @@ enum { DAC_H }; +enum { + RGB_RATE_3, + RGB_RATE_6, + RGB_RATE_6_LEVEL_4, + RGB_RATE_8 +}; + static const char *rate_names[] = { "3 Bits Per Pixel", "6 Bits Per Pixel", @@ -131,10 +138,12 @@ static const char *rate_names[] = { "Half-Even (3BPP)" }; -static const char *four_level_rate_names[] = { +static const char *eight_bit_rate_names[] = { "3 Bits Per Pixel", "6 Bits Per Pixel", "6 Bits (4 Level)", + "8 Bits Per Pixel" + }; @@ -181,7 +190,7 @@ static param_t params[] = { { MUX, "Sync on G/V", "input_mux", 0, 1, 1 }, { RATE, "Sample Mode", "sample_mode", 0, 3, 1 }, { TERMINATE, "75R Termination", "termination", 0, NUM_RGB_TERM-1, 1 }, - { COUPLING, "G Input Coupling", "coupling", 0, NUM_RGB_COUPLING-1, 1 }, + { COUPLING, "G Coupling", "coupling", 0, NUM_RGB_COUPLING-1, 1 }, { DAC_A, "DAC-A: G Hi", "dac_a", 0, 255, 1 }, { DAC_B, "DAC-B: G Lo", "dac_b", 0, 255, 1 }, { DAC_C, "DAC-C: RB Hi", "dac_c", 0, 255, 1 }, @@ -363,12 +372,7 @@ static void write_config(config_t *config) { scan_len += supports_delay; // 2 or 4 depending on the CPLD version } if (supports_rate) { - if (supports_four_level && config->rate >= 2) { - sp |= (3 << scan_len); - } else { - sp |= (config->rate << scan_len); - } - + sp |= (config->rate << scan_len); scan_len += supports_rate; // 1 or 2 depending on the CPLD version } if (supports_invert) { @@ -409,7 +413,7 @@ static void write_config(config_t *config) { int dac_g = config->dac_g; if (dac_g == 255) { - if (supports_four_level && config->rate >= 2) { + if (supports_8bit && config->rate == RGB_RATE_6_LEVEL_4) { dac_g = dac_c; } else { dac_g = 0; @@ -444,7 +448,7 @@ static void write_config(config_t *config) { RPI_SetGpioValue(SP_DATA_PIN, 0); //ac-dc break; case RGB_INPUT_AC: - RPI_SetGpioValue(SP_DATA_PIN, (config->rate < 2) || !supports_four_level); // only allow clamping in 3 level mode or old cpld or 6 bit board + RPI_SetGpioValue(SP_DATA_PIN, (config->rate != RGB_RATE_6_LEVEL_4) || !supports_8bit); // only allow clamping in 3 level mode or old cpld or 6 bit board break; } @@ -581,15 +585,14 @@ static void cpld_init(int version) { if (major >= 8) { if (eight_bit_detected()) { - supports_four_level = 1; - params[RATE].max = 2; + supports_8bit = 1; } else { - supports_four_level = 0; - params[RATE].max = 1; // running on a 6 bit board so hide the 4 level option + supports_8bit = 0; + params[RATE].max = 1; // running on a 6 bit board so hide the 8 bit options params[DAC_H].hidden = 1; } } else { - supports_four_level = 0; + supports_8bit = 0; params[DAC_H].hidden = 1; // hide spare DAC as will only be useful with new 8 bit CPLDs with new drivers (hiding maintains compatible save format) } @@ -865,52 +868,46 @@ static int cpld_analyse(int selected_sync_state, int analyse) { static void cpld_update_capture_info(capture_info_t *capinfo) { // Update the capture info stucture, if one was passed in - if (capinfo) { + if (capinfo) { // Update the sample width - if (supports_four_level) { - capinfo->sample_width = (config->rate >= 1); + if (supports_8bit) { + capinfo->sample_width = config->rate; + if (capinfo->sample_width >= RGB_RATE_6_LEVEL_4) { + capinfo->sample_width--; //4 level analog option is actually 6bpp + } } else { - capinfo->sample_width = (config->rate == 1); // 1 = 6bpp, everything else 3bpp + capinfo->sample_width = (config->rate == RGB_RATE_6); // 1 = 6bpp, everything else 3bpp } + // Update the line capture function - if (capinfo->sample_width) { - switch (capinfo->px_sampling) { - case PS_NORMAL: + switch (capinfo->sample_width) { + case 0: + switch (capinfo->px_sampling) { + case PS_NORMAL: + capinfo->capture_line = capture_line_normal_3bpp_table; + break; + case PS_NORMAL_O: + capinfo->capture_line = capture_line_odd_3bpp_table; + break; + case PS_NORMAL_E: + capinfo->capture_line = capture_line_even_3bpp_table; + break; + case PS_HALF_O: + capinfo->capture_line = capture_line_half_odd_3bpp_table; + break; + case PS_HALF_E: + capinfo->capture_line = capture_line_half_even_3bpp_table; + break; + } + break; + case 1 : capinfo->capture_line = capture_line_normal_6bpp_table; - break; - case PS_NORMAL_O: - capinfo->capture_line = capture_line_odd_6bpp_table; - break; - case PS_NORMAL_E: - capinfo->capture_line = capture_line_even_6bpp_table; - break; - case PS_HALF_O: - capinfo->capture_line = capture_line_half_odd_6bpp_table; - break; - case PS_HALF_E: - capinfo->capture_line = capture_line_half_even_6bpp_table; - break; - } - } else { - switch (capinfo->px_sampling) { - case PS_NORMAL: - capinfo->capture_line = capture_line_normal_3bpp_table; - break; - case PS_NORMAL_O: - capinfo->capture_line = capture_line_odd_3bpp_table; - break; - case PS_NORMAL_E: - capinfo->capture_line = capture_line_even_3bpp_table; - break; - case PS_HALF_O: - capinfo->capture_line = capture_line_half_odd_3bpp_table; - break; - case PS_HALF_E: - capinfo->capture_line = capture_line_half_even_3bpp_table; - break; - } - } - } + break; + case 2 : + capinfo->capture_line = capture_line_normal_8bpp_table; + break; + } + } } static param_t *cpld_get_params() { @@ -978,8 +975,8 @@ static int cpld_get_value(int num) { static const char *cpld_get_value_string(int num) { if (num == RATE) { - if (supports_four_level) { - return four_level_rate_names[config->rate]; + if (supports_8bit) { + return eight_bit_rate_names[config->rate]; } else { return rate_names[config->rate]; } @@ -1043,21 +1040,22 @@ static void cpld_set_value(int num, int value) { break; case RATE: config->rate = value; - if (supports_four_level) { - if (config->rate >= 2) { - // params[DAC_H].hidden = 0; - // params[COUPLING].hidden = 0; + if (supports_8bit) { + if (config->rate == RGB_RATE_6_LEVEL_4) { + params[DAC_H].hidden = 0; + params[COUPLING].hidden = 1; params[DAC_F].label = "DAC-F: G Mid"; params[DAC_G].label = "DAC-G: R Mid"; params[DAC_H].label = "DAC-H: B Mid"; } else { - // params[DAC_H].hidden = 1; - // params[COUPLING].hidden = 1; + params[DAC_H].hidden = 1; + params[COUPLING].hidden = 0; params[DAC_F].label = "DAC-F: G V Sync"; params[DAC_G].label = "DAC-G: G Clamp"; params[DAC_H].label = "DAC-H: Unused"; } } + osd_refresh(); break; case MUX: config->mux = value; diff --git a/src/cpld_yuv.c b/src/cpld_yuv.c index 71c3698f..44dd7430 100644 --- a/src/cpld_yuv.c +++ b/src/cpld_yuv.c @@ -43,7 +43,10 @@ typedef struct { int dac_h; } config_t; - +enum { + YUV_RATE_6, + YUV_RATE_6_LEVEL_4, +}; // Current calibration state for mode 0..6 static config_t default_config; @@ -124,12 +127,19 @@ static const char *clamptype_names[] = { "Back Porch Auto" }; +static const char *level_names[] = { + "3 Level YUV", + "3 Lvl Y, 4 Lvl UV", + "4 Lvl Y, 3 Lvl UV", + "4 Level YUV", + "Auto 4 Level YUV" +}; + static const char *rate_names[] = { "6 Bits Per Pixel", "6 Bits (4 Level)", }; - static const char *coupling_names[] = { "DC", "AC With Clamp" @@ -330,12 +340,16 @@ static void write_config(config_t *config) { if (supports_clamptype) { int clamptype = config->clamptype; if (clamptype == CLAMPTYPE_AUTO) { - clamptype = CLAMPTYPE_SHORT; - if (geometry_get_value(CLOCK) >= 6750000) { - clamptype = CLAMPTYPE_MEDIUM; - } - if (geometry_get_value(CLOCK) >= 9750000) { - clamptype = CLAMPTYPE_LONG; + if (config->rate == YUV_RATE_6) { + clamptype = CLAMPTYPE_SHORT; + if (geometry_get_value(CLOCK) >= 6750000) { + clamptype = CLAMPTYPE_MEDIUM; + } + if (geometry_get_value(CLOCK) >= 9750000) { + clamptype = CLAMPTYPE_LONG; + } + } else { + clamptype = CLAMPTYPE_LONG; // force 4 level YUV in four level mode } } sp |= clamptype << scan_len; @@ -374,7 +388,7 @@ static void write_config(config_t *config) { int dac_g = config->dac_g; if (dac_g == 255) { - if (supports_four_level && config->rate >= 2) { + if (supports_four_level && config->rate >= YUV_RATE_6_LEVEL_4) { dac_g = dac_c; } else { dac_g = 0; @@ -384,6 +398,13 @@ static void write_config(config_t *config) { int dac_h = config->dac_h; if (dac_h == 255) dac_h = dac_c; + if (params[DAC_G].hidden == 1) { + dac_g = dac_c; + } + if (params[DAC_H].hidden == 1) { + dac_h = dac_c; + } + sendDAC(0, dac_a); sendDAC(1, dac_b); sendDAC(2, dac_c); @@ -409,7 +430,7 @@ static void write_config(config_t *config) { RPI_SetGpioValue(SP_DATA_PIN, 0); //ac-dc break; case YUV_INPUT_AC: - RPI_SetGpioValue(SP_DATA_PIN, (config->rate < 2) || !supports_four_level); // only allow clamping in 3 level mode or old cpld or 6 bit board + RPI_SetGpioValue(SP_DATA_PIN, (config->rate < YUV_RATE_6_LEVEL_4) || !supports_four_level); // only allow clamping in 3 level mode or old cpld or 6 bit board break; } @@ -441,7 +462,7 @@ static void log_sp(config_t *config) { static void cpld_init(int version) { cpld_version = version; config->sp_offset = 0; - config->rate = 0; + config->rate = YUV_RATE_6; config->filter_l = 1; for (int i = 0; i < RANGE_MAX; i++) { sum_metrics[i] = -1; @@ -608,7 +629,7 @@ static void cpld_update_capture_info(capture_info_t *capinfo) { // Update the capture info stucture, if one was passed in if (capinfo) { // Update the sample width - capinfo->sample_width = 1; // 1 = 6 bits + capinfo->sample_width = WIDTH_6; // Update the line capture function capinfo->capture_line = capture_line_normal_6bpp_table; } @@ -669,10 +690,16 @@ static const char *cpld_get_value_string(int num) { return edge_names[config->edge]; } if (num == RATE) { - return rate_names[config->rate]; + if ((cpld_version & 0xff) >= 0x82) { + return rate_names[config->rate]; + } } if (num == CLAMPTYPE) { - return clamptype_names[config->clamptype]; + if ((cpld_version & 0xff) >= 0x82 && config->rate == YUV_RATE_6_LEVEL_4) { + return level_names[config->clamptype]; + } else { + return clamptype_names[config->clamptype]; + } } if (num == CPLD_SETUP_MODE) { return cpld_setup_names[config->cpld_setup_mode]; @@ -704,22 +731,36 @@ static void cpld_set_value(int num, int value) { case RATE: config->rate = value; if (supports_four_level) { - if (config->rate == 0) { + params[DAC_B].label = "DAC-B: Y Lo"; + params[DAC_D].label = "DAC-D: UV Lo"; + params[DAC_F].label = "DAC-F: Y V Sync"; + params[DAC_G].label = "DAC-G: Y Clamp"; + params[DAC_H].label = "DAC-H: Unused"; + params[DAC_G].hidden = 0; + params[DAC_H].hidden = 1; + if (config->rate == YUV_RATE_6) { + params[CLAMPTYPE].label = "Clamp Type"; params[DAC_H].hidden = 1; params[COUPLING].hidden = 0; - params[DAC_B].label = "DAC-B: Y Lo"; - params[DAC_D].label = "DAC-D: UV Lo"; - params[DAC_F].label = "DAC-F: Y V Sync"; - params[DAC_G].label = "DAC-G: Y Clamp"; - params[DAC_H].label = "DAC-H: Unused"; } else { - params[DAC_H].hidden = 0; + params[CLAMPTYPE].label = "Level Type"; params[COUPLING].hidden = 1; - params[DAC_B].label = "DAC-B: Y Mid"; - params[DAC_D].label = "DAC-D: UV Mid"; - params[DAC_F].label = "DAC-F: Y Lo"; - params[DAC_G].label = "DAC-G: V Lo"; - params[DAC_H].label = "DAC-H: U Lo"; + int levels = config->clamptype; + if (levels > 3) { + levels = 3; + } + params[DAC_G].hidden = 1; + if (levels & 2) { + params[DAC_B].label = "DAC-B: Y Mid"; + params[DAC_F].label = "DAC-F: Y Lo"; + } + if (levels & 1) { + params[DAC_G].hidden = 0; + params[DAC_H].hidden = 0; + params[DAC_D].label = "DAC-D: UV Mid"; + params[DAC_G].label = "DAC-G: V Lo"; + params[DAC_H].label = "DAC-H: U Lo"; + } } osd_refresh(); } @@ -770,6 +811,7 @@ static void cpld_set_value(int num, int value) { break; case CLAMPTYPE: config->clamptype = value; + cpld_set_value(RATE, config->rate); break; case TERMINATE: config->terminate = value; diff --git a/src/geometry.c b/src/geometry.c index f0f7be25..4c477121 100644 --- a/src/geometry.c +++ b/src/geometry.c @@ -373,11 +373,19 @@ void set_setup_mode(int mode) { } void geometry_get_fb_params(capture_info_t *capinfo) { - capinfo->bpp = geometry->fb_bpp; capinfo->sync_type = geometry->sync_type; capinfo->vsync_type = geometry->vsync_type; capinfo->video_type = geometry->video_type; capinfo->sizex2 = geometry->fb_sizex2; + capinfo->bpp = geometry->fb_bpp; + if (capinfo->video_type == VIDEO_TELETEXT) { + capinfo->bpp = 4; //force 4bpp for teletext + } else { + if (capinfo->sample_width >= WIDTH_8) { + capinfo->bpp = 8; //force 8bpp in 8 bit modes + } + } + #ifdef INHIBIT_DOUBLE_HEIGHT if (capinfo->video_type != VIDEO_TELETEXT) { capinfo->sizex2 &= 2; diff --git a/src/macros.S b/src/macros.S index 9802610c..9443e504 100644 --- a/src/macros.S +++ b/src/macros.S @@ -486,6 +486,56 @@ wait_wr\@: orr \reg2, r10, r10, lsl #8 .endm +.macro SETUP_MASK_R14 + tst r3, #BIT_OSD + movne r14, #(0x7f << PIXEL_BASE) + moveq r14, #(0xff << PIXEL_BASE) +.endm + +.macro CAPTURE_EIGHT_BITS_8BPP_0 reg + // Pixel 0 in GPIO 9.. 2 -> 7.. 0 + + and r9, r8, r14 + eor r10, \reg, r9, lsr #PIXEL_BASE +.endm + +.macro CAPTURE_EIGHT_BITS_8BPP_1 + // Pixel 0 in GPIO 9.. 2 -> 15.. 8 + + and r9, r8, r14 + eor r10, r10, r9, lsl #(8 - PIXEL_BASE) +.endm + +.macro CAPTURE_EIGHT_BITS_8BPP_2 + // Pixel 0 in GPIO 9.. 2 -> 23.. 16 + + and r9, r8, r14 + eor r10, r10, r9, lsl #(16 - PIXEL_BASE) +.endm + +.macro CAPTURE_EIGHT_BITS_8BPP_3 reg + // Pixel 0 in GPIO 9.. 2 -> 31.. 24 + + and r9, r8, r14 + eor \reg, r10, r9, lsl #(24 - PIXEL_BASE) +.endm + +.macro CAPTURE_EIGHT_BITS_DOUBLE_8BPP_LO reg + // Pixel 0 in GPIO 9.. 2 -> 7.. 0 + + and r9, r8, r14 + eor r10, \reg, r9, lsr #PIXEL_BASE +.endm + +.macro CAPTURE_EIGHT_BITS_DOUBLE_8BPP_HI reg + // Pixel 0 in GPIO 9.. 2 -> 7.. 0 + + and r9, r8, r14 + eor r10, r10, r9, lsl #(16 - PIXEL_BASE) + // Pixel double + orr \reg, r10, r10, lsl #8 +.endm + .macro CAPTURE_LOW_BITS_8BPP_WIDE reg // Pixel 0 in GPIO 7.. 2 -> 7.. 0 // Pixel 1 in GPIO 13.. 8 -> 15.. 8 diff --git a/src/rgb_to_fb.S b/src/rgb_to_fb.S index d3117c9d..e75e4d2c 100644 --- a/src/rgb_to_fb.S +++ b/src/rgb_to_fb.S @@ -65,11 +65,7 @@ .global capture_line_half_even_3bpp_table .global capture_line_normal_6bpp_table -.global capture_line_odd_6bpp_table -.global capture_line_even_6bpp_table -.global capture_line_double_6bpp_table -.global capture_line_half_odd_6bpp_table -.global capture_line_half_even_6bpp_table +.global capture_line_normal_8bpp_table rgb_to_fb: @@ -206,8 +202,7 @@ skip_swap: ldr r8, param_h_offset ldr r7, param_sample_width - ands r7, r7, #1 - movne r8, r8, lsl #1 + mov r8, r8, lsl r7 add r8, r8, #1 // first psync test is wait for a zero after csync str r8, param_h_offset @@ -486,6 +481,7 @@ no_sync_loss: cmp r9, #4 //flywheel vsync bne skip_fix_vsync_jitter + SHOW_VSYNC WAIT_FOR_CSYNC_0_LONG WAIT_FOR_CSYNC_1_LONG @@ -494,10 +490,18 @@ no_sync_loss: movmi r5, #0 READ_CYCLE_COUNTER r9 + + tst r3, #BIT_OSD | BIT_CALIBRATE | BIT_PROBE + bne skip_fix_vsync_jitter_saving_timestamp + + ldr r10, sync_detected + ldr r8, last_sync_detected + ands r8, r8, r10 + beq skip_fix_vsync_jitter_saving_timestamp + ldr r10, first_hsync_timestamp subs r6, r9, r10 rsbmi r6, r6, #0 - ldr r0, required_vsync_period add r10, r0, r0, lsr #1 fixvloop: @@ -530,7 +534,7 @@ addsloop: // sub r8, r8, r10, lsr #1 // remove rounding leaving remainder continue: // add r9, r9, r8 // adjust timestamp by remainder to compensate for rounding - str r9, first_hsync_timestamp + cmp r0, r7 streq r6, required_vsync_period // update vertical period timing if no jitter detected. @@ -543,6 +547,9 @@ continue: movmi r5, #0 str r0, jitter_offset +skip_fix_vsync_jitter_saving_timestamp: + str r9, first_hsync_timestamp + skip_fix_vsync_jitter: // Correct the relative positions of the odd and even frames @@ -1802,6 +1809,36 @@ capture_line_normal_6bpp_table: .word capture_line_fast_sixbits_8bpp +capture_line_normal_8bpp_table: + .word capture_line_default_4bpp //never called + .word capture_line_default_eightbits_8bpp + .word capture_line_default_4bpp //never called + .word capture_line_default_eightbits_8bpp + .word capture_line_default_4bpp //never called + .word capture_line_default_eightbits_8bpp + .word capture_line_default_4bpp //never called + .word capture_line_default_eightbits_8bpp + .word capture_line_default_4bpp //never called + .word capture_line_default_eightbits_8bpp + + .word capture_line_default_4bpp //never called + .word capture_line_default_eightbits_double_8bpp + .word capture_line_default_4bpp //never called + .word capture_line_default_eightbits_double_8bpp + .word capture_line_default_4bpp //never called + .word capture_line_default_eightbits_double_8bpp + .word capture_line_default_4bpp //never called + .word capture_line_default_eightbits_double_8bpp + .word capture_line_default_4bpp //never called + .word capture_line_default_eightbits_double_8bpp + + .word capture_line_default_4bpp //never called + .word capture_line_fast_eightbits_8bpp + + + + + // tables below are deprecated and will be removed in future capture_line_odd_3bpp_table: @@ -1860,7 +1897,6 @@ capture_line_even_6bpp_table: //no six bit versions .word capture_line_even_8bpp capture_line_half_odd_3bpp_table: -capture_line_half_odd_6bpp_table: //no six bit versions .word capture_line_half_odd_4bpp .word capture_line_half_odd_8bpp .word capture_line_half_odd_4bpp @@ -1887,7 +1923,6 @@ capture_line_half_odd_6bpp_table: //no six bit versions .word capture_line_half_odd_8bpp capture_line_half_even_3bpp_table: -capture_line_half_even_6bpp_table: //no six bit versions .word capture_line_half_even_4bpp .word capture_line_half_even_8bpp .word capture_line_half_even_4bpp diff --git a/src/rgb_to_fb.h b/src/rgb_to_fb.h index 2f4e6401..9baf9bdf 100644 --- a/src/rgb_to_fb.h +++ b/src/rgb_to_fb.h @@ -37,11 +37,7 @@ extern int capture_line_half_odd_3bpp_table(); extern int capture_line_half_even_3bpp_table(); extern int capture_line_normal_6bpp_table(); -extern int capture_line_odd_6bpp_table(); -extern int capture_line_even_6bpp_table(); -extern int capture_line_double_6bpp_table(); -extern int capture_line_half_odd_6bpp_table(); -extern int capture_line_half_even_6bpp_table(); +extern int capture_line_normal_8bpp_table(); extern int vsync_line; extern int total_lines; diff --git a/src/rgb_to_hdmi.c b/src/rgb_to_hdmi.c index 465dbe9b..86feb4b1 100644 --- a/src/rgb_to_hdmi.c +++ b/src/rgb_to_hdmi.c @@ -2371,6 +2371,7 @@ void setup_profile(int profile_changed) { log_info("Detected screen size = %dx%d",get_hdisplay(), get_vdisplay()); set_scaling(scaling, 1); + cpld->update_capture_info(capinfo); geometry_get_fb_params(capinfo); if (autoswitch == AUTOSWITCH_MODE7) { @@ -2380,7 +2381,6 @@ void setup_profile(int profile_changed) { } log_info("Detected polarity state = %X, %s (%s)", capinfo->detected_sync_type, sync_names[capinfo->detected_sync_type & SYNC_BIT_MASK], mixed_names[(capinfo->detected_sync_type & SYNC_BIT_MIXED_SYNC) ? 1 : 0]); - cpld->update_capture_info(capinfo); calculate_fb_adjustment(); rgb_to_fb(capinfo, extra_flags() | BIT_PROBE); // dummy mode7 probe to setup sync type from capinfo @@ -2698,7 +2698,7 @@ void rgb_to_hdmi_main() { capinfo->palette_control = PALETTECONTROL_OFF; } - fb_size_changed = (capinfo->width != last_capinfo.width) || (capinfo->height != last_capinfo.height) || (capinfo->bpp != last_capinfo.bpp); + fb_size_changed = (capinfo->width != last_capinfo.width) || (capinfo->height != last_capinfo.height) || (capinfo->bpp != last_capinfo.bpp) || (capinfo->sample_width != last_capinfo.sample_width); active_size_changed = (capinfo->chars_per_line != last_capinfo.chars_per_line) || (capinfo->nlines != last_capinfo.nlines); geometry_get_clk_params(&clkinfo); @@ -2713,7 +2713,7 @@ void rgb_to_hdmi_main() { } mode_changed = mode7 != last_mode7 || capinfo->vsync_type != last_capinfo.vsync_type || capinfo->sync_type != last_capinfo.sync_type || capinfo->border != last_capinfo.border - || capinfo->video_type != last_capinfo.video_type|| capinfo->px_sampling != last_capinfo.px_sampling + || capinfo->video_type != last_capinfo.video_type || capinfo->px_sampling != last_capinfo.px_sampling || profile != last_profile || last_subprofile != subprofile || (result & RET_SYNC_TIMING_CHANGED); if (active_size_changed) {