diff --git a/src/cpld.h b/src/cpld.h index 89f9a22f..3e742646 100644 --- a/src/cpld.h +++ b/src/cpld.h @@ -10,8 +10,8 @@ typedef struct { const char *name; - const int min; - const int max; + int min; + int max; } param_t; // Define a common interface to abstract the calibration code diff --git a/src/defs.h b/src/defs.h index f320d4f1..fff8e036 100644 --- a/src/defs.h +++ b/src/defs.h @@ -21,42 +21,44 @@ #define VSYNCINT 16 -// Field State bits (maintained in r3) -// -// bit 0 indicates mode 7 -// bit 1 is the buffer being written to -// bit 2 is the buffer being displayed -// bit 3 is the field type (0 = odd, 1 = even) of the last field +// Control bits (maintained in r3) -#define BIT_MODE7 0x01 -#define BIT_PROBE 0x02 -#define BIT_CALIBRATE 0x04 -#define BIT_NO_DEINT 0x08 -#define BIT_OSD 0x10 -#define BIT_INITIALIZE 0x20 -#define BIT_ELK 0x40 -#define BIT_SCANLINES 0x80 -#define BIT_FIELD_TYPE 0x100 -#define BIT_CLEAR 0x200 -#define BIT_VSYNC 0x400 -#define BIT_CAL_COUNT 0x800 -#define BIT_DEINT_MODE_0 0x100000 -#define BIT_DEINT_MODE_1 0x200000 -#define BIT_DEBUG 0x400000 - -// Note, due to a hack, bits 16, 19 and 26 are unavailale -// as the are used for switch change detection - -#define OFFSET_LAST_BUFFER 12 -#define OFFSET_CURR_BUFFER 14 -#define OFFSET_NBUFFERS 17 -#define OFFSET_INTERLACE 20 +#define BIT_MODE7 0x01 // bit 0, indicates mode 7 +#define BIT_PROBE 0x02 // bit 1, indicates the mode is being determined +#define BIT_CALIBRATE 0x04 // bit 2, indicates calibration is happening +#define BIT_NO_DEINT 0x08 // bit 3, indicates all deinterlacing should be disabled +#define BIT_OSD 0x10 // bit 4, indicated the OSD is visible +#define BIT_INITIALIZE 0x20 // bit 5, indicates we should sync to an even frame +#define BIT_ELK 0x40 // bit 6, indicated we are an Electron +#define BIT_SCANLINES 0x80 // bit 7, indicates scan lines should be made visible +#define BIT_FIELD_TYPE 0x100 // bit 8, indicates the field type (0 = odd, 1 = even) of the last field +#define BIT_CLEAR 0x200 // bit 9, indicates the frame buffer should be cleared +#define BIT_VSYNC 0x400 // bit 10, indicates the vsync frequency is being probed +#define BIT_CAL_COUNT 0x800 // bit 11, indicates how many fields to capture during calibration (1 or 2) +#define OFFSET_LAST_BUFFER 12 // bit 12-13 LAST_BUFFER #define MASK_LAST_BUFFER (3 << OFFSET_LAST_BUFFER) + +#define OFFSET_CURR_BUFFER 14 // bit 14-15 CURR_BUFFER #define MASK_CURR_BUFFER (3 << OFFSET_CURR_BUFFER) + + // bit 16 unavailable (used for switch detection) + +#define OFFSET_NBUFFERS 17 // bit 17-18 NBUFFERS #define MASK_NBUFFERS (3 << OFFSET_NBUFFERS) + + // bit 19 unavailable (used for switch detection) + +#define OFFSET_INTERLACE 20 // bit 20-21 INTERFACE #define MASK_INTERLACE (3 << OFFSET_INTERLACE) +#define BIT_NEW_DEINT 0x400000 // bit 22, indicates the new deinterlace algorithm should be used +#define BIT_DEBUG 0x800000 // bit 23, indicated the debug grid should be displayed + + // bit 24-25 unused + // bit 26 unavailable (used for switch detection) + // bit 27-31 unused + // R0 return value bits #define RET_SW1 0x02 #define RET_SW2 0x04 diff --git a/src/osd.c b/src/osd.c index 6b96daea..11ad8306 100644 --- a/src/osd.c +++ b/src/osd.c @@ -75,15 +75,6 @@ enum { NUM_INFOS }; -enum { - DEINTERLACE_NONE, - DEINTERLACE_MA1, - DEINTERLACE_MA2, - DEINTERLACE_MA3, - DEINTERLACE_MA4, - NUM_DEINTERLACES -}; - static const char *info_names[] = { "Firmware Version", "Calibration Summary", @@ -107,10 +98,14 @@ static const char *pllh_names[] = { static const char *deinterlace_names[] = { "None", - "Motion Adaptive 1 field", - "Motion Adaptive 2 fields", - "Motion Adaptive 3 fields", - "Motion Adaptive 4 fields", + "Motion Adaptive 1", + "Motion Adaptive 2", + "Motion Adaptive 3", + "Motion Adaptive 4", + "Aligned Motion Adaptive 1", + "Aligned Motion Adaptive 2", + "Aligned Motion Adaptive 3", + "Aligned Motion Adaptive 4" }; #ifdef MULTI_BUFFER @@ -674,6 +669,10 @@ void osd_init() { } } } + // Disable CPLDv2 specific features for CPLDv1 + if (((cpld->get_version() >> VERSION_MAJOR_BIT) & 0x0F) < 2) { + features[F_DEINTERLACE].max = DEINTERLACE_MA4; + } } void osd_update(uint32_t *osd_base, int bytes_per_line) { diff --git a/src/osd.h b/src/osd.h index 53e92fcd..87e36799 100644 --- a/src/osd.h +++ b/src/osd.h @@ -9,6 +9,19 @@ extern int clock_error_ppm; +enum { + DEINTERLACE_NONE, + DEINTERLACE_MA1, + DEINTERLACE_MA2, + DEINTERLACE_MA3, + DEINTERLACE_MA4, + DEINTERLACE_MA1_NEW, + DEINTERLACE_MA2_NEW, + DEINTERLACE_MA3_NEW, + DEINTERLACE_MA4_NEW, + NUM_DEINTERLACES +}; + void osd_init(); void osd_clear(); void osd_set(int line, int attr, char *text); diff --git a/src/rgb_to_fb.S b/src/rgb_to_fb.S index 6e6fdcd9..842804a3 100644 --- a/src/rgb_to_fb.S +++ b/src/rgb_to_fb.S @@ -317,7 +317,27 @@ process_chars_loop_7\@: tst r3, #(BIT_CALIBRATE | BIT_NO_DEINT) bne skip_deinterlace\@ + tst r3, #BIT_NEW_DEINT // use the new deinterlace algorithm? + bne new_deint\@ + // The old deinterlace algorithm only compares odd with odd, and even with even + // It will work with CPLD v1 and CPLD v2, as it requires no character alignment + tst r1, #0x88000000 // test motion flag in last field (R1 finished with after this) + orrne r10, #0x00880000 // set 2nd flag if other field had motion + tst r0, #0x88000000 + orrne r10, #0x00008800 // set 3rd flag as old 1st flag + tst r0, #0x00880000 + orrne r10, #0x00000088 // set 4th flag as old 2nd flag + + eor r0, r0, r10 // compare odd with odd and even with even fields + ands r0, r0, r8 // mask out old flag bits + orrne r10, #0x88000000 // set 1st flag upper and lower half words if different. + + b completed_word\@ + +new_deint\@: + // The new deinterlace algorithm requires mode 7 characters to be word-aligned + // which will only be the case with the CPLD v2 that has the configurable delay tst r1, #0x80000000 // test motion flag in last field orrne r10, #0x00800000 // set 2nd flag if other field had motion upper half word diff --git a/src/rgb_to_hdmi.c b/src/rgb_to_hdmi.c index 9fd14e3f..9bf3ee82 100644 --- a/src/rgb_to_hdmi.c +++ b/src/rgb_to_hdmi.c @@ -998,10 +998,13 @@ void rgb_to_hdmi_main() { if (osd_active()) { flags |= BIT_OSD; } - if (deinterlace == 0) { - flags |= BIT_NO_DEINT; + if (deinterlace >= DEINTERLACE_MA1 && deinterlace <= DEINTERLACE_MA4) { + flags |= (deinterlace - DEINTERLACE_MA1) << OFFSET_INTERLACE; + } else if (deinterlace >= DEINTERLACE_MA1_NEW && deinterlace <= DEINTERLACE_MA4_NEW) { + flags |= (deinterlace - DEINTERLACE_MA1_NEW) << OFFSET_INTERLACE; + flags |= BIT_NEW_DEINT; } else { - flags |= (deinterlace - 1) << OFFSET_INTERLACE; + flags |= BIT_NO_DEINT; } #ifdef MULTI_BUFFER flags |= nbuffers << OFFSET_NBUFFERS;