Add interlaced video support and improve 12 bit capture / 16BPP frame buffer

pull/154/head
IanSB 2020-07-30 01:59:43 +01:00
rodzic 588dd6b843
commit 33c0a79a84
19 zmienionych plików z 345 dodań i 162 usunięć

Wyświetl plik

@ -92,7 +92,7 @@ preload_capture_line_default_eightbits_8bpp:
b preload_capture_line_default_eightbits_16bpp
capture_line_default_eightbits_16bpp:
push {lr}
SETUP_VSYNC_DEBUG_R11_R12_DOUBLE
SETUP_VSYNC_DEBUG_16BPP_R11_R12
SKIP_PSYNC_NO_OLD_CPLD
push {r14}
SETUP_TWELVE_BITS_MASK_R14
@ -102,12 +102,12 @@ loop_16bpp:
WAIT_FOR_PSYNC_EDGE_FAST // expects GPLEV0 in r4, result in r8
CAPTURE_TWELVE_BITS_16BPP_HI r5 // input in r8
WAIT_FOR_PSYNC_EDGE_FAST // expects GPLEV0 in r4, result in r8
CAPTURE_TWELVE_BITS_16BPP_LO r12 // input in r8
CAPTURE_TWELVE_BITS_16BPP_LO_0 // input in r8
WAIT_FOR_PSYNC_EDGE_FAST // expects GPLEV0 in r4, result in r8
CAPTURE_TWELVE_BITS_16BPP_HI r6 // input in r8
WAIT_FOR_PSYNC_EDGE_FAST // expects GPLEV0 in r4, result in r8
CAPTURE_TWELVE_BITS_16BPP_LO r11 // input in r8
CAPTURE_TWELVE_BITS_16BPP_LO_0 // input in r8
WAIT_FOR_PSYNC_EDGE_FAST // expects GPLEV0 in r4, result in r8
CAPTURE_TWELVE_BITS_16BPP_HI r7 // input in r8
WAIT_FOR_PSYNC_EDGE_FAST // expects GPLEV0 in r4, result in r8
@ -115,7 +115,7 @@ loop_16bpp:
WAIT_FOR_PSYNC_EDGE_FAST // expects GPLEV0 in r4, result in r8
CAPTURE_TWELVE_BITS_16BPP_HI r10 // input in r8
WRITE_R5_R6_R7_R10
WRITE_R5_R6_R7_R10_16BPP
subs r1, r1, #1
bne loop_16bpp

Wyświetl plik

@ -73,7 +73,7 @@ preload_capture_line_default_eightbits_double_8bpp:
b preload_capture_line_default_eightbits_double_16bpp
capture_line_default_eightbits_double_16bpp:
push {lr}
SETUP_VSYNC_DEBUG_R11_R12_DOUBLE
SETUP_VSYNC_DEBUG_16BPP_R11_R12_DOUBLE
SKIP_PSYNC_NO_OLD_CPLD
push {r14}
SETUP_TWELVE_BITS_MASK_R14
@ -81,13 +81,13 @@ loop_16bpp:
WAIT_FOR_PSYNC_EDGE_FAST // expects GPLEV0 in r4, result in r8
CAPTURE_TWELVE_BITS_DOUBLE_16BPP r11 r5 // input in r8
WAIT_FOR_PSYNC_EDGE_FAST // expects GPLEV0 in r4, result in r8
CAPTURE_TWELVE_BITS_DOUBLE_16BPP r12 r6 // input in r8
CAPTURE_TWELVE_BITS_DOUBLE_16BPP_0 r6 // input in r8
WAIT_FOR_PSYNC_EDGE_FAST // expects GPLEV0 in r4, result in r8
CAPTURE_TWELVE_BITS_DOUBLE_16BPP r11 r7 // input in r8
CAPTURE_TWELVE_BITS_DOUBLE_16BPP_0 r7 // input in r8
WAIT_FOR_PSYNC_EDGE_FAST // expects GPLEV0 in r4, result in r8
CAPTURE_TWELVE_BITS_DOUBLE_16BPP r12 r10 // input in r8
WRITE_R5_R6_R7_R10
WRITE_R5_R6_R7_R10_16BPP
subs r1, r1, #1
bne loop_16bpp
@ -98,3 +98,4 @@ loop_16bpp:
preload_capture_line_default_eightbits_double_16bpp:
SETUP_DUMMY_PARAMETERS
b capture_line_default_eightbits_double_16bpp

Wyświetl plik

@ -118,34 +118,34 @@ preload_capture_line_default_sixbits_8bpp:
b preload_capture_line_default_sixbits_16bpp
capture_line_default_sixbits_16bpp:
push {lr}
SETUP_VSYNC_DEBUG_R11_R12
SETUP_VSYNC_DEBUG_16BPP_R11_R12
SKIP_PSYNC_NO_OLD_CPLD
push {r14}
SETUP_TWELVE_BITS_MASK_R14
loop_16bpp:
WAIT_FOR_PSYNC_EDGE_FAST // expects GPLEV0 in r4, result in r8
CAPTURE_TWELVE_BITS_16BPP_LO r11 // input in r8
CAPTURE_TWELVE_BITS_16BPP_LO r11 // input in r8
WAIT_FOR_PSYNC_EDGE_FAST // expects GPLEV0 in r4, result in r8
CAPTURE_TWELVE_BITS_16BPP_HI r5 // input in r8
CAPTURE_TWELVE_BITS_16BPP_HI r5 // input in r8
WAIT_FOR_PSYNC_EDGE_FAST // expects GPLEV0 in r4, result in r8
CAPTURE_TWELVE_BITS_16BPP_LO r12 // input in r8
CAPTURE_TWELVE_BITS_16BPP_LO_0 // input in r8
WAIT_FOR_PSYNC_EDGE_FAST // expects GPLEV0 in r4, result in r8
CAPTURE_TWELVE_BITS_16BPP_HI r6 // input in r8
CAPTURE_TWELVE_BITS_16BPP_HI r6 // input in r8
WRITE_R5_R6_IF_LAST
WRITE_R5_R6_IF_LAST_16BPP
cmp r1, #1
popeq {r0, pc}
WAIT_FOR_PSYNC_EDGE_FAST // expects GPLEV0 in r4, result in r8
CAPTURE_TWELVE_BITS_16BPP_LO r11 // input in r8
CAPTURE_TWELVE_BITS_16BPP_LO_0 // input in r8
WAIT_FOR_PSYNC_EDGE_FAST // expects GPLEV0 in r4, result in r8
CAPTURE_TWELVE_BITS_16BPP_HI r7 // input in r8
CAPTURE_TWELVE_BITS_16BPP_HI r7 // input in r8
WAIT_FOR_PSYNC_EDGE_FAST // expects GPLEV0 in r4, result in r8
CAPTURE_TWELVE_BITS_16BPP_LO r12 // input in r8
CAPTURE_TWELVE_BITS_16BPP_LO r12 // input in r8
WAIT_FOR_PSYNC_EDGE_FAST // expects GPLEV0 in r4, result in r8
CAPTURE_TWELVE_BITS_16BPP_HI r10 // input in r8
CAPTURE_TWELVE_BITS_16BPP_HI r10 // input in r8
WRITE_R5_R6_R7_R10
WRITE_R5_R6_R7_R10_16BPP
subs r1, r1, #2
bne loop_16bpp

Wyświetl plik

@ -99,7 +99,7 @@ preload_capture_line_default_sixbits_double_8bpp:
b preload_capture_line_default_sixbits_double_16bpp
capture_line_default_sixbits_double_16bpp:
push {lr}
SETUP_VSYNC_DEBUG_R11_R12_DOUBLE
SETUP_VSYNC_DEBUG_16BPP_R11_R12_DOUBLE
SKIP_PSYNC_NO_OLD_CPLD
push {r14}
SETUP_TWELVE_BITS_MASK_R14
@ -107,25 +107,24 @@ loop_16bpp:
WAIT_FOR_PSYNC_EDGE_FAST // expects GPLEV0 in r4, result in r8
CAPTURE_TWELVE_BITS_DOUBLE_16BPP r11 r5 // input in r8
WAIT_FOR_PSYNC_EDGE_FAST // expects GPLEV0 in r4, result in r8
CAPTURE_TWELVE_BITS_DOUBLE_16BPP r12 r6 // input in r8
CAPTURE_TWELVE_BITS_DOUBLE_16BPP_0 r6 // input in r8
WRITE_R5_R6_IF_LAST
WRITE_R5_R6_IF_LAST_16BPP
cmp r1, #1
popeq {r0, pc}
WAIT_FOR_PSYNC_EDGE_FAST // expects GPLEV0 in r4, result in r8
CAPTURE_TWELVE_BITS_DOUBLE_16BPP r11 r7 // input in r8
CAPTURE_TWELVE_BITS_DOUBLE_16BPP_0 r7 // input in r8
WAIT_FOR_PSYNC_EDGE_FAST // expects GPLEV0 in r4, result in r8
CAPTURE_TWELVE_BITS_DOUBLE_16BPP r12 r10 // input in r8
WRITE_R5_R6_R7_R10
WRITE_R5_R6_R7_R10_16BPP
subs r1, r1, #2
bne loop_16bpp
pop {r0, pc}
preload_capture_line_default_sixbits_double_16bpp:
SETUP_DUMMY_PARAMETERS
b capture_line_default_sixbits_double_16bpp

Wyświetl plik

@ -90,7 +90,7 @@ preload_capture_line_fast_eightbits_8bpp:
b preload_capture_line_fast_eightbits_16bpp
capture_line_fast_eightbits_16bpp:
push {lr}
SETUP_VSYNC_DEBUG_R11_R12
SETUP_VSYNC_DEBUG_16BPP_R11_R12
SKIP_PSYNC_NO_H_SCROLL
push {r14}
SETUP_TWELVE_BITS_MASK_R14
@ -100,12 +100,12 @@ loop_16bpp:
WAIT_FOR_PSYNC_EDGE_FAST // expects GPLEV0 in r4, result in r8
CAPTURE_TWELVE_BITS_16BPP_HI r5 // input in r8
WAIT_FOR_PSYNC_EDGE_FAST // expects GPLEV0 in r4, result in r8
CAPTURE_TWELVE_BITS_16BPP_LO r12 // input in r8
CAPTURE_TWELVE_BITS_16BPP_LO_0 // input in r8
WAIT_FOR_PSYNC_EDGE_FAST // expects GPLEV0 in r4, result in r8
CAPTURE_TWELVE_BITS_16BPP_HI r6 // input in r8
WAIT_FOR_PSYNC_EDGE_FAST // expects GPLEV0 in r4, result in r8
CAPTURE_TWELVE_BITS_16BPP_LO r11 // input in r8
CAPTURE_TWELVE_BITS_16BPP_LO_0 // input in r8
WAIT_FOR_PSYNC_EDGE_FAST // expects GPLEV0 in r4, result in r8
CAPTURE_TWELVE_BITS_16BPP_HI r7 // input in r8
WAIT_FOR_PSYNC_EDGE_FAST // expects GPLEV0 in r4, result in r8

Wyświetl plik

@ -114,7 +114,7 @@ preload_capture_line_fast_sixbits_8bpp:
b preload_capture_line_fast_sixbits_16bpp
capture_line_fast_sixbits_16bpp:
push {lr}
SETUP_VSYNC_DEBUG_R11_R12
SETUP_VSYNC_DEBUG_16BPP_R11_R12
SKIP_PSYNC_NO_H_SCROLL
push {r14}
SETUP_TWELVE_BITS_MASK_R14
@ -124,7 +124,7 @@ loop_16bpp:
WAIT_FOR_PSYNC_EDGE_FAST // expects GPLEV0 in r4, result in r8
CAPTURE_TWELVE_BITS_16BPP_HI r5 // input in r8
WAIT_FOR_PSYNC_EDGE_FAST // expects GPLEV0 in r4, result in r8
CAPTURE_TWELVE_BITS_16BPP_LO r12 // input in r8
CAPTURE_TWELVE_BITS_16BPP_LO_0 // input in r8
WAIT_FOR_PSYNC_EDGE_FAST // expects GPLEV0 in r4, result in r8
CAPTURE_TWELVE_BITS_16BPP_HI r6 // input in r8
@ -133,7 +133,7 @@ loop_16bpp:
popeq {r0, pc}
WAIT_FOR_PSYNC_EDGE_FAST // expects GPLEV0 in r4, result in r8
CAPTURE_TWELVE_BITS_16BPP_LO r11 // input in r8
CAPTURE_TWELVE_BITS_16BPP_LO_0 // input in r8
WAIT_FOR_PSYNC_EDGE_FAST // expects GPLEV0 in r4, result in r8
CAPTURE_TWELVE_BITS_16BPP_HI r7 // input in r8
WAIT_FOR_PSYNC_EDGE_FAST // expects GPLEV0 in r4, result in r8

Wyświetl plik

@ -34,13 +34,13 @@ capture_line_mode7_4bpp:
tst r3, #BIT_CALIBRATE
bne process_chars_7_none
ands r8, r3, #MASK_INTERLACE
beq process_chars_7_none // DEINTERLACE_NONE
beq process_chars_7_none // M7DEINTERLACE_NONE
mov r8, r8, lsr #OFFSET_INTERLACE // put interlace setting in R9 0-6
cmp r8, #1 //DEINTERLACE_BOB
cmp r8, #1 //M7DEINTERLACE_BOB
beq process_chars_7_bob
tst r3, #BIT_FIELD_TYPE // test odd or even field
rsbeq r2, r2,#0 // negate R2 offset if odd field to write to line above (restored to original value on exit)
cmp r8, #6 //DEINTERLACE_ADV
cmp r8, #6 //M7DEINTERLACE_ADV
beq process_chars_7_advanced
// Simple motion adaptive deinterlace
@ -72,7 +72,7 @@ capture_line_mode7_4bpp:
eorne r7, r7, #0x02000000 //green in rightmost
process_chars_loop_7_simple:
#ifdef USE_ALT_DEINTERLACE_CODE
#ifdef USE_ALT_M7DEINTERLACE_CODE
WAIT_FOR_PSYNC_EDGE
ldr r5, [r0] // preload old pixel value from video buffer
CAPTURE_LOW_BITS
@ -115,11 +115,11 @@ process_chars_loop_7_simple:
tst r12, #0x00800000
orrne r10, #0x00000080 // set 4th flag as old 2nd flag
str r10, [r11], #4 // save new value to comparison buffer including flag bit
cmp r9,#4 // if setting =< DEINTERLACE_MA3 then clear 4th motion flag
cmp r9,#4 // if setting =< M7DEINTERLACE_MA3 then clear 4th motion flag
bicle r10, r10, #0x00000080
cmp r9,#3 // if setting =< DEINTERLACE_MA2 then clear 3rd motion flag
cmp r9,#3 // if setting =< M7DEINTERLACE_MA2 then clear 3rd motion flag
bicle r10, r10, #0x00008000
cmp r9,#2 // if setting =< DEINTERLACE_MA1 then clear 2nd motion flag
cmp r9,#2 // if setting =< M7DEINTERLACE_MA1 then clear 2nd motion flag
bicle r10, r10, #0x00800000
bics r9, r10, r8 // extract motion flags
@ -189,7 +189,7 @@ process_chars_7_bob:
ldr r11, =0x77777777 // mask to extract OSD
process_chars_loop_7_bob:
WAIT_FOR_PSYNC_EDGE // expects GPLEV0 in r4, result in r8
#ifdef USE_ALT_DEINTERLACE_CODE
#ifdef USE_ALT_M7DEINTERLACE_CODE
ldr r6, [r0, r2] // preload old pixel value from other field of video buffer
CAPTURE_LOW_BITS // input in r8, result in r10, corrupts r9/r14
WAIT_FOR_PSYNC_EDGE // expects GPLEV0 in r4, result in r8

Wyświetl plik

@ -50,7 +50,7 @@
#define OFFSETDUP_PALETTE_HIGH_NIBBLE 12 // bit 12-15
#define MASKDUP_PALETTE_HIGH_NIBBLE (15 << OFFSETDUP_PALETTE_HIGH_NIBBLE)
#define BIT_INTERLACED 0x10000 // bit 16, indicates the frame is expected to be interlaced
#define BIT_INHIBIT_MODE_DETECT 0x10000 // bit 16 inhibit mode detection if sideways scrolling
#define BIT_PSYNC_POL 0x20000 // bit 17, indicates psync inversion (NEEDS TO MATCH PSYNC_PIN below)
#define OFFSET_NBUFFERS 18 // bit 18-19 NBUFFERS
@ -71,9 +71,9 @@
#define BIT_NO_H_SCROLL 0x04000000 // bit 26, if set then smooth H scrolling disabled
#define BIT_ELK 0x08000000 // bit 27, indicates we are an Electron
#define BIT_NO_AUTOSWITCH 0x10000000 // bit 28, if set then autoselect enabled
#define BIT_TELETEXT 0x20000000 // bit 29, if set then teletext enabled
#define BIT_INTERLACED_VIDEO 0x20000000 // bit 29, if set then teletext enabled
#define BIT_NO_SKIP_HSYNC 0x40000000 // bit 30 clear if hsync is ignored (used by cache preload)
#define BIT_INHIBIT_MODE_DETECT 0x80000000 // bit 31 inhibit mode detection if sideways scrolling
// bit 31 0x80000000 unused
// R0 return value bits
#define RET_SW1 0x02
@ -107,7 +107,7 @@
#define USE_MULTICORE // makes Advanced Motion deinterlace use 2nd core
#endif
#if defined(RPI2) || defined(RPI3) // Pi4 may not need these
#define USE_ALT_DEINTERLACE_CODE // uses re-ordered code for bob and simple motion deinterlace
#define USE_ALT_M7DEINTERLACE_CODE // uses re-ordered code for bob and simple motion deinterlace
#define USE_CACHED_COMPARISON_BUFFER // uses cached memory for the comparison buffer with simple & advanced motion deinterlace
#define INHIBIT_DOUBLE_HEIGHT // inhibit line doubling as it causes memory stalls with Pi2 & Pi3
#endif
@ -227,6 +227,7 @@ typedef struct {
#define SYNC_BIT_VSYNC_INVERTED 0x02 // bit 1, indicates vsync is inverted
#define SYNC_BIT_COMPOSITE_SYNC 0x04 // bit 2, indicates composite sync
#define SYNC_BIT_MIXED_SYNC 0x08 // bit 3, indicates H and V syncs eored in CPLD
#define SYNC_BIT_INTERLACED 0x10 // bit 4, indicates interlaced sync detected
#define SYNC_BIT_MASK 0x07 // masks out bit 3
#define VSYNC_RETRY_MAX 100

Wyświetl plik

@ -50,6 +50,7 @@ static const char *fb_sizex2_names[] = {
static const char *deint_names[] = {
"Progressive",
"Interlaced",
"Interlaced Teletext"
};
@ -406,10 +407,15 @@ void geometry_get_fb_params(capture_info_t *capinfo) {
}
#ifdef INHIBIT_DOUBLE_HEIGHT
if (capinfo->video_type != VIDEO_TELETEXT) {
if (capinfo->video_type == VIDEO_PROGRESSIVE) {
capinfo->sizex2 &= 2;
}
#endif
if ((capinfo->detected_sync_type & SYNC_BIT_INTERLACED) && capinfo->video_type != VIDEO_PROGRESSIVE) {
capinfo->sizex2 |= 1;
}
int geometry_h_offset = geometry->h_offset;
int geometry_v_offset = geometry->v_offset;
int geometry_min_h_width = geometry->min_h_width;
@ -481,12 +487,11 @@ void geometry_get_fb_params(capture_info_t *capinfo) {
int double_width = (capinfo->sizex2 & 2) >> 1;
int double_height = capinfo->sizex2 & 1;
if (capinfo->sample_width == SAMPLE_WIDTH_6 && capinfo->bpp == 16) { //special double rate 6 bpp mode
if (((geometry_min_h_width >> 1) << double_width) > h_size43) {
double_width = 0;
}
} else {
} else {
if ((geometry_min_h_width << double_width) > h_size43) {
double_width = 0;
}
@ -494,7 +499,6 @@ void geometry_get_fb_params(capture_info_t *capinfo) {
if ((geometry_min_v_height << double_height) > v_size43) {
double_height = 0;
}
capinfo->sizex2 = double_height | (double_width << 1);
//log_info("unadjusted integer = %d, %d, %d, %d, %d, %d", geometry_h_offset, geometry_v_offset, geometry_min_h_width, geometry_min_v_height, geometry_max_h_width, geometry_max_v_height);
@ -735,7 +739,7 @@ void geometry_get_fb_params(capture_info_t *capinfo) {
//log_info("Clipping capture height to %d", capinfo->nlines);
}
if (capinfo->video_type == VIDEO_TELETEXT) {
if (capinfo->video_type != VIDEO_PROGRESSIVE) {
capvscale >>= 1;
} else {
if (osd_active() || get_scanlines()) {

Wyświetl plik

@ -35,6 +35,7 @@ enum {
enum {
VIDEO_PROGRESSIVE,
VIDEO_INTERLACED,
VIDEO_TELETEXT,
NUM_VIDEO
};

Wyświetl plik

@ -1137,13 +1137,13 @@ int xsvfDoXSIR( SXsvfInfo* pXsvfInfo )
}
if (instr == 0xFE) {
osd_set(1, 0, "Identifying");
osd_set_clear(1, 0, "Identifying");
} else if (instr == 0xED) {
osd_set(1, 0, "Erasing");
osd_set_clear(1, 0, "Erasing");
} else if (instr == 0xEA) {
osd_set(1, 0, "Programming");
osd_set_clear(1, 0, "Programming");
} else if (instr == 0xEE) {
osd_set(1, 0, "Verifying");
osd_set_clear(1, 0, "Verifying");
}
/* Shift the data */

Wyświetl plik

@ -66,12 +66,12 @@ int update_cpld(char *path) {
if (xsvf_ret != XSVF_ERROR_NONE) {
sprintf(message, "Failed, error = %d", xsvf_ret);
log_info(message);
osd_set(1, 0, message);
osd_set_clear(1, 0, message);
} else {
for (int i = 5; i > 0; i--) {
sprintf(message, "Successful, rebooting in %d secs ", i);
log_info(message);
osd_set(1, 0, message);
osd_set_clear(1, 0, message);
delay_in_arm_cycles_cpu_adjust(1000000000);
}
reboot();

Wyświetl plik

@ -571,12 +571,11 @@ wait_wr\@:
.macro SETUP_TWELVE_BITS_MASK_R14
mov r14, #(0x0e << PIXEL_BASE)
orr r14, r14, #(0x0e << (PIXEL_BASE + 4))
orr r14, r14, #(0x0e << (PIXEL_BASE + 8))
mov r14, #0x00000610 //2 high order bits of green (0x0600) + 1 high order bit of blue (0x0010)
orr r14, r14, #0x00008000 //1 high order bit of red (0x8000)
orr r14, r14, r14, lsl #16 //put in both pixels
.endm
.macro CAPTURE_TWELVE_BITS_16BPP_LO reg
// Pixel in GPIO 13.. 2 -> 15.. 0
@ -586,6 +585,20 @@ wait_wr\@:
eor r10, r10, r9, lsl #(3 - PIXEL_BASE)
and r9, r8, #0x0f << (PIXEL_BASE + 8)
eor r10, r10, r9, lsl #(4 - PIXEL_BASE)
.endm
.macro CAPTURE_TWELVE_BITS_16BPP_LO_0
// Pixel in GPIO 13.. 2 -> 15.. 0
and r9, r8, #0x0f << PIXEL_BASE
mov r10, r9, lsr #(PIXEL_BASE - 1)
tst r3, #BIT_VSYNC_MARKER
eorne r10, r10, #0x0000e000
eorne r10, r10, #0xe0000000
and r9, r8, #0x0f << (PIXEL_BASE + 4)
eor r10, r10, r9, lsl #(3 - PIXEL_BASE)
and r9, r8, #0x0f << (PIXEL_BASE + 8)
eor r10, r10, r9, lsl #(4 - PIXEL_BASE)
.endm
.macro CAPTURE_TWELVE_BITS_16BPP_HI reg
@ -596,10 +609,11 @@ wait_wr\@:
and r9, r8, #0x0f << (PIXEL_BASE + 4)
eor r10, r10, r9, lsl #(16 + (3 - PIXEL_BASE))
and r9, r8, #0x0f << (PIXEL_BASE + 8)
eor \reg, r10, r9, lsl #(16 + (4 - PIXEL_BASE))
eor r10, r10, r9, lsl #(16 + (4 - PIXEL_BASE))
and r9, r10, r14 // extract high order bits
tst r3, #BIT_OSD
movne \reg, \reg, lsr #1
orreq \reg, r10, r9, lsr #4 // put high order bits in unused low order bits to ensure full range 5r 6g 5b
movne \reg, r10, lsr #1 // half intensity for menu (low order bits already 0
.endm
.macro CAPTURE_TWELVE_BITS_DOUBLE_16BPP reg reg2
@ -611,9 +625,31 @@ wait_wr\@:
and r9, r8, #0x0f << (PIXEL_BASE + 8)
eor r10, r10, r9, lsl #(4 - PIXEL_BASE)
// Pixel double
orr \reg2, r10, r10, lsl #16
orr r10, r10, r10, lsl #16
and r9, r10, r14 // extract high order bits
tst r3, #BIT_OSD
movne \reg2, \reg2, lsr #1
orreq \reg2, r10, r9, lsr #4 // put high order bits in unused low order bits to ensure full range 5r 6g 5b
movne \reg2, r10, lsr #1 // half intensity for menu (low order bits already 0
.endm
.macro CAPTURE_TWELVE_BITS_DOUBLE_16BPP_0 reg
// Pixel in GPIO 13.. 2 -> 15.. 0
and r9, r8, #0x0f << PIXEL_BASE
mov r10, r9, lsr #(PIXEL_BASE - 1)
tst r3, #BIT_VSYNC_MARKER
eorne r10, r10, #0x0000e000
eorne r10, r10, #0xe0000000
and r9, r8, #0x0f << (PIXEL_BASE + 4)
eor r10, r10, r9, lsl #(3 - PIXEL_BASE)
and r9, r8, #0x0f << (PIXEL_BASE + 8)
eor r10, r10, r9, lsl #(4 - PIXEL_BASE)
// Pixel double
orr r10, r10, r10, lsl #16
and r9, r10, r14 // extract high order bits
tst r3, #BIT_OSD
orreq \reg, r10, r9, lsr #4 // put high order bits in unused low order bits to ensure full range 5r 6g 5b
movne \reg, r10, lsr #1 // half intensity for menu (low order bits already 0
.endm
@ -827,6 +863,57 @@ wait_wr\@:
eorne r12, r12, #0x00020000 //green in rightmost >> 8
.endm
.macro SETUP_VSYNC_DEBUG_16BPP_R11_R12
tst r3, #BIT_VSYNC_MARKER
ldrne r11, =0xe000e000
moveq r11, #0
movne r12, r11
moveq r12, #0
tst r3, #BIT_DEBUG
eorne r11, r11, #0x001c //magenta in leftmost
eorne r11, r11, #0xe000 //magenta in leftmost
eorne r12, r12, #0x07c00000 //green in rightmost
.endm
.macro SETUP_VSYNC_DEBUG_16BPP_R11_R12_DOUBLE
tst r3, #BIT_VSYNC_MARKER
ldrne r11, =0xe000e000
moveq r11, #0
movne r12, r11
moveq r12, #0
tst r3, #BIT_DEBUG
eorne r11, r11, #0x001c //magenta in leftmost
eorne r11, r11, #0xe000 //magenta in leftmost
eorne r12, r12, #0x000007c0 //green in rightmost >> 16
.endm
.macro WRITE_R5_R6_IF_LAST_16BPP
cmp r1, #1
stmeqia r0, {r5, r6}
tsteq r3, #BIT_NO_SCANLINES
moveq r5, #0
moveq r6, #0
cmp r1, #1
tsteq r3, #BIT_NO_LINE_DOUBLE
subeq r0, r0, r2
stmeqia r0, {r5, r6}
.endm
.macro WRITE_R5_R6_R7_R10_16BPP
stmia r0, {r5, r6, r7, r10}
tst r3, #BIT_NO_SCANLINES
moveq r5, #0
moveq r6, #0
moveq r7, #0
moveq r10, #0
tst r3, #BIT_NO_LINE_DOUBLE
subeq r0, r0, r2
stmeqia r0, {r5, r6, r7, r10}
addeq r0, r0, r2
add r0, r0, #16
.endm
.macro WRITE_R5_R6_IF_LAST
cmp r1, #1
stmeqia r0, {r5, r6}
@ -993,7 +1080,7 @@ novsync\@:
#ifdef MULTI_BUFFER
.macro FLIP_BUFFER
// Skip the multi buffering in mode 7 and probe mode
tst r3, #(BIT_TELETEXT | BIT_PROBE)
tst r3, #(BIT_INTERLACED_VIDEO | BIT_PROBE)
bne noflip\@
// Flip to the last completed draw buffer
// It seems the GPU delays this until the next vsync

Wyświetl plik

@ -135,7 +135,7 @@ static const char *vlockmode_names[] = {
};
static const char *deinterlace_names[] = {
"None",
"None (Weave)",
"Simple Bob",
"Simple Motion 1",
"Simple Motion 2",
@ -271,6 +271,7 @@ enum {
F_CONT,
F_BRIGHT,
F_GAMMA,
F_M7DEINTERLACE,
F_DEINTERLACE,
F_M7SCALING,
F_NORMALSCALING,
@ -310,9 +311,10 @@ static param_t features[] = {
{ F_CONT, "Contrast", "contrast", 0, 200, 1 },
{ F_BRIGHT, "Brightness", "brightness", 0, 200, 1 },
{ F_GAMMA, "Gamma", "gamma", 10, 300, 1 },
{ F_DEINTERLACE,"Teletext Deinterlace", "teletext_deinterlace", 0, NUM_DEINTERLACES - 1, 1 },
{ F_M7DEINTERLACE,"Teletext Deinterlace","teletext_deinterlace", 0, NUM_M7DEINTERLACES - 1, 1 },
{ F_DEINTERLACE, "Normal Deinterlace", "normal_deinterlace", 0, NUM_DEINTERLACES - 1, 1 },
{ F_M7SCALING, "Teletext Scaling", "teletext_scaling", 0, NUM_ESCALINGS - 1, 1 },
{ F_NORMALSCALING,"Progressive Scaling", "progressive_scaling", 0, NUM_ESCALINGS - 1, 1 },
{ F_NORMALSCALING, "Normal Scaling", "normal_scaling", 0, NUM_ESCALINGS - 1, 1 },
{ F_COLOUR, "Output Colour", "output_colour", 0, NUM_COLOURS - 1, 1 },
{ F_INVERT, "Output Invert", "output_invert", 0, NUM_INVERT - 1, 1 },
{ F_SCANLINES, "Scanlines", "scanlines", 0, 1, 1 },
@ -489,6 +491,7 @@ static param_menu_item_t cont_ref = { I_FEATURE, &features[F_CONT]
static param_menu_item_t bright_ref = { I_FEATURE, &features[F_BRIGHT] };
static param_menu_item_t gamma_ref = { I_FEATURE, &features[F_GAMMA] };
static param_menu_item_t palette_ref = { I_FEATURE, &features[F_PALETTE] };
static param_menu_item_t m7deinterlace_ref = { I_FEATURE, &features[F_M7DEINTERLACE] };
static param_menu_item_t deinterlace_ref = { I_FEATURE, &features[F_DEINTERLACE] };
static param_menu_item_t m7scaling_ref = { I_FEATURE, &features[F_M7SCALING] };
static param_menu_item_t normalscaling_ref = { I_FEATURE, &features[F_NORMALSCALING] };
@ -536,6 +539,7 @@ static menu_t preferences_menu = {
(base_menu_item_t *) &back_ref,
(base_menu_item_t *) &scanlines_ref,
(base_menu_item_t *) &scanlinesint_ref,
(base_menu_item_t *) &m7deinterlace_ref,
(base_menu_item_t *) &deinterlace_ref,
(base_menu_item_t *) &m7scaling_ref,
(base_menu_item_t *) &normalscaling_ref,
@ -898,10 +902,12 @@ static int get_feature(int num) {
return get_border();
case F_FONTSIZE:
return get_fontsize();
case F_DEINTERLACE:
return get_deinterlace();
case F_M7DEINTERLACE:
return get_m7deinterlace();
case F_M7SCALING:
return get_m7scaling();
case F_DEINTERLACE:
return get_deinterlace();
case F_NORMALSCALING:
return get_normalscaling();
case F_PALETTE:
@ -981,12 +987,15 @@ static void set_feature(int num, int value) {
case F_FRONTEND:
set_frontend(value, 1);
break;
case F_DEINTERLACE:
set_deinterlace(value);
case F_M7DEINTERLACE:
set_m7deinterlace(value);
break;
case F_M7SCALING:
set_m7scaling(value);
break;
case F_DEINTERLACE:
set_deinterlace(value);
break;
case F_NORMALSCALING:
set_normalscaling(value);
break;
@ -1196,6 +1205,7 @@ static const char *get_param_string(param_menu_item_t *param_item) {
return palette_control_names[value];
case F_AUTOSWITCH:
return autoswitch_names[value];
case F_M7DEINTERLACE:
case F_DEINTERLACE:
return deinterlace_names[value];
case F_M7SCALING:
@ -1447,8 +1457,8 @@ static void redraw_menu() {
i++;
}
}
if ((capinfo->bpp) != 16) {
osd_update((uint32_t *) (capinfo->fb + capinfo->pitch * capinfo->height * get_current_display_buffer() + capinfo->pitch * capinfo->v_adjust + capinfo->h_adjust), capinfo->pitch);
if (capinfo->bpp != 16) {
osd_update((uint32_t *) (capinfo->fb + capinfo->pitch * capinfo->height * get_current_display_buffer() + capinfo->pitch * capinfo->v_adjust + capinfo->h_adjust), capinfo->pitch);
}
}
@ -3233,9 +3243,9 @@ void process_single_profile(char *buffer) {
// Disable CPLDv2 specific features for CPLDv1
if (cpld->old_firmware_support() & BIT_NORMAL_FIRMWARE_V1) {
features[F_DEINTERLACE].max = DEINTERLACE_MA4;
if (get_feature(F_DEINTERLACE) > features[F_DEINTERLACE].max) {
set_feature(F_DEINTERLACE, DEINTERLACE_MA1); // TODO: Decide whether this is the right fallback
features[F_M7DEINTERLACE].max = M7DEINTERLACE_MA4;
if (get_feature(F_M7DEINTERLACE) > features[F_M7DEINTERLACE].max) {
set_feature(F_M7DEINTERLACE, M7DEINTERLACE_MA1); // TODO: Decide whether this is the right fallback
}
}
}
@ -3382,6 +3392,14 @@ void osd_set(int line, int attr, char *text) {
osd_update((uint32_t *) (capinfo->fb + capinfo->pitch * capinfo->height * get_current_display_buffer() + capinfo->pitch * capinfo->v_adjust + capinfo->h_adjust), capinfo->pitch);
}
void osd_set_clear(int line, int attr, char *text) {
osd_set_noupdate(line, attr, text);
if (capinfo->bpp >= 16) {
clear_screen();
}
osd_update((uint32_t *) (capinfo->fb + capinfo->pitch * capinfo->height * get_current_display_buffer() + capinfo->pitch * capinfo->v_adjust + capinfo->h_adjust), capinfo->pitch);
}
int osd_active() {
return active;
}
@ -4314,9 +4332,15 @@ void osd_init() {
}
void osd_update(uint32_t *osd_base, int bytes_per_line) {
if (!active) { //osd is written every other field in progressive mode so no real need to write here as well
if (!active) {
return;
}
if (capinfo->bpp == 16) {
if (capinfo->video_type == VIDEO_INTERLACED && (capinfo->sync_type & SYNC_BIT_INTERLACED) && get_deinterlace() == DEINTERLACE_NONE) {
clear_full_screen();
}
}
// SAA5050 character data is 12x20
int bufferCharWidth = (capinfo->chars_per_line << 3) / 12; // SAA5050 character data is 12x20
if (capinfo->sample_width == SAMPLE_WIDTH_6 && capinfo->bpp == 16) { //special double rate 6 bpp mode
@ -4554,6 +4578,9 @@ void osd_update_fast(uint32_t *osd_base, int bytes_per_line) {
if (!active) {
return;
}
if (capinfo->bpp == 16 && capinfo->video_type == VIDEO_INTERLACED && (capinfo->detected_sync_type & SYNC_BIT_INTERLACED) && get_deinterlace() == DEINTERLACE_NONE) {
clear_screen();
}
// SAA5050 character data is 12x20
int bufferCharWidth = (capinfo->chars_per_line << 3) / 12; // SAA5050 character data is 12x20
if (capinfo->sample_width == SAMPLE_WIDTH_6 && capinfo->bpp == 16) { //special double rate 6 bpp mode

Wyświetl plik

@ -118,14 +118,20 @@ enum {
NUM_SCALING
};
enum {
M7DEINTERLACE_NONE,
M7DEINTERLACE_BOB,
M7DEINTERLACE_MA1,
M7DEINTERLACE_MA2,
M7DEINTERLACE_MA3,
M7DEINTERLACE_MA4,
M7DEINTERLACE_ADV,
NUM_M7DEINTERLACES
};
enum {
DEINTERLACE_NONE,
DEINTERLACE_BOB,
DEINTERLACE_MA1,
DEINTERLACE_MA2,
DEINTERLACE_MA3,
DEINTERLACE_MA4,
DEINTERLACE_ADV,
NUM_DEINTERLACES
};
@ -180,6 +186,7 @@ void osd_init();
void osd_clear();
void osd_set(int line, int attr, char *text);
void osd_set_noupdate(int line, int attr, char *text);
void osd_set_clear(int line, int attr, char *text);
void osd_show_cpld_recovery_menu();
void osd_refresh();
void osd_update(uint32_t *osd_base, int bytes_per_line);

Wyświetl plik

@ -11,6 +11,7 @@
.global analyse_sync
.global clear_full_screen
.global clear_menu_bits
.global clear_screen
.global measure_n_lines
.global sw1counter
.global sw2counter
@ -104,15 +105,16 @@ rgb_to_fb:
str r2, param_v_adjust
ldr r2, [r0, #O_SYNCTYPE]
str r2, param_sync_type
ldr r2, [r0, #O_DETSYNCTYPE]
str r2, param_detected_sync_type
ldr r3, [r0, #O_DETSYNCTYPE]
str r3, param_detected_sync_type
ldr r2, [r0, #O_VSYNCTYPE]
str r2, param_vsync_type
ldr r2, [r0, #O_VIDEOTYPE]
str r2, param_video_type
cmp r2, #0
biceq r1, r1, #BIT_TELETEXT
orrne r1, r1, #BIT_TELETEXT
bic r1, r1, #BIT_INTERLACED_VIDEO
cmp r2, #0 //VIDEO_PROGRESSIVE;
tstne r3, #SYNC_BIT_INTERLACED
orrne r1, r1, #BIT_INTERLACED_VIDEO
ldr r2, [r0, #O_NTSCPHASE]
str r2, param_ntscphase
ldr r2, [r0, #O_BORDER]
@ -158,7 +160,7 @@ rgb_to_fb:
add r2, r10
str r2, param_framebuffer3
// Default to displaying buffer 0 in Mode 7 (or on probe)
tst r1, #(BIT_TELETEXT | BIT_PROBE) // options currently in r1!
tst r1, #(BIT_INTERLACED_VIDEO | BIT_PROBE) // options currently in r1!
beq skip_swap
push {r0-r3}
mov r0, #0
@ -194,7 +196,7 @@ skip_swap:
//add r8, r8, #1
str r8, buffer_total
tst r3, #(BIT_TELETEXT | BIT_PROBE)
tst r3, #(BIT_INTERLACED_VIDEO | BIT_PROBE)
// In modes 0..6, restore the previous buffer state
ldreq r10, buffer_state
orreq r3, r3, r10
@ -206,11 +208,21 @@ skip_swap:
add r8, r8, #1 // first psync test is wait for a zero after csync
str r8, param_h_offset
ldr r9, param_fb_sizex2
tst r9, #1
bicne r3, r3, #BIT_NO_LINE_DOUBLE
orreq r3, r3, #BIT_NO_LINE_DOUBLE
ldr r8, param_video_type
cmp r8, #1 //VIDEO_INTERLACED
bne skip_double_check
tst r3, #BIT_INTERLACED_VIDEO
beq skip_double_check
ands r8, r3, #MASK_INTERLACE
orreq r3, r3, #BIT_NO_LINE_DOUBLE
biceq r9, #1
skip_double_check:
ldr r8, param_palette_control
ldr r7, param_fb_bpp
cmp r7, #8
@ -238,8 +250,9 @@ skip_swap:
ldr r9, param_capture_line
ldr r8, [r9, r7, lsl #2]
tst r3, #BIT_TELETEXT
ldrne r8, =capture_line_mode7_4bpp
ldr r9, param_video_type
cmp r9, #2 //VIDEO_TELETEXT
ldreq r8, =capture_line_mode7_4bpp
ldr r10, param_border
tst r10, #0x80
@ -251,7 +264,7 @@ skip_swap:
ldr r9, =0x48444d49 // "HDMI" sentinel
str r9, [r8]
mov r8, #4 // number of frames before h and v sync timing is analysed
mov r8, #4 // number of frames before h and v sync timing is analysed
str r8, frame_countdown
// mov r8, #0
@ -259,7 +272,6 @@ skip_swap:
bl restore_menu_bits
frame:
ldr r8, =inBandPointer
ldr r9, =inBandData
@ -292,7 +304,7 @@ frame:
// else draw to the "spare" buffer
mov r0, #0
#ifdef MULTI_BUFFER
tst r3, #(BIT_TELETEXT | BIT_PROBE)
tst r3, #(BIT_INTERLACED_VIDEO | BIT_PROBE)
bne buffer_chosen
// Draw to the buffers cyclically, i.e. pick the one
// after the last completed buffer, modulo <nbuffers + 1>
@ -304,6 +316,7 @@ frame:
cmp r8, r9
beq buffer_chosen
add r0, r8, #1
and r0, r0, #3
buffer_chosen:
#endif
ldr r8, =param_framebuffer0
@ -395,15 +408,26 @@ normal_mode_test:
bne exit
skip_switch_test:
tst r3, #BIT_MODE_DETECT // Have we been told to exit on mode change
beq skip_mode_test
tst r3, #BIT_INHIBIT_MODE_DETECT
bne skip_interlace_test
ldr r9, sync_detected
cmp r9, #0
beq skip_interlace_test
ldr r9, frame_countdown
cmp r9, #0
bne skip_interlace_test
tst r3, #BIT_MODE_DETECT // Have we been told to exit on mode change
bne force_mode_test
ldr r9, param_video_type
cmp r9, #1 //VIDEO_INTERLACE
bne skip_interlace_test
force_mode_test:
tst r3, #BIT_INHIBIT_MODE_DETECT
bne detect_interlace
tst r3, #BIT_MODE7
moveq r5, #0 // Modes 0-6
movne r5, #1 // Mode 7
@ -411,7 +435,7 @@ skip_switch_test:
bne exit // If so, then bail, as the frame buffer needs to be resized
tst r3, #BIT_FIELD_TYPE1_VALID
beq skip_interlace_test // we haven't yet seen two fields, so skip the test
beq detect_interlace // we haven't yet seen two fields, so skip the test
// XOR BIT_FIELD_TYPE and BIT_FIELD_TYPE1 to determine if the current frame is interlacd
// FT1 FT
@ -422,21 +446,21 @@ skip_switch_test:
// then XOR BIT_INTERLACED and if the result is 1 then the interlace mode has changed
tst r3, #BIT_FIELD_TYPE
eorne r3, #BIT_FIELD_TYPE1
tst r3, #BIT_INTERLACED
ldr r8, param_detected_sync_type
tst r8, #SYNC_BIT_INTERLACED
eorne r3, #BIT_FIELD_TYPE1
tst r3, #BIT_FIELD_TYPE1
orrne r0, #RET_INTERLACE_CHANGED
bne exit
skip_interlace_test:
detect_interlace:
// copy BIT_FIELD_TYPE to BIT_FIELD_TYPE1
tst r3, #BIT_FIELD_TYPE
biceq r3, #BIT_FIELD_TYPE1
orrne r3, #BIT_FIELD_TYPE1
orr r3, #BIT_FIELD_TYPE1_VALID // set the valid bit
skip_mode_test:
skip_interlace_test:
ldr r8, param_fb_pitch
ldr r9, param_v_adjust
mul r9, r9, r8
@ -523,7 +547,6 @@ subsloop:
subs r8, r8, r10
subpl r0, r0, #1
bpl subsloop
// add r8, r8, r10, lsr #1 // remove rounding leaving remainder
b continue
negative:
sub r8, r8, r10, lsr #1 // half line rounding
@ -531,11 +554,7 @@ addsloop:
adds r8, r8, r10
addmi r0, r0, #1
bmi addsloop
// sub r8, r8, r10, lsr #1 // remove rounding leaving remainder
continue:
// add r9, r9, r8 // adjust timestamp by remainder to compensate for rounding
cmp r0, r7
streq r6, required_vsync_period // update vertical period timing if no jitter detected.
@ -557,11 +576,11 @@ skip_fix_vsync_jitter:
// In Mode 7, increment the frame buffer pointer by one line for the even field
tst r3, #BIT_NO_LINE_DOUBLE
tsteq r3, #BIT_TELETEXT
tsteq r3, #BIT_INTERLACED_VIDEO
addeq r11, r11, r2
tst r3, #BIT_ELK
bne is_elk
tst r3, #BIT_TELETEXT
tst r3, #BIT_INTERLACED_VIDEO
beq fixupmodes
tst r3, #BIT_FIELD_TYPE
addeq r11, r11, r2
@ -673,6 +692,14 @@ process_line_loop:
pop {r11}
skip_all_lines:
ldr r8, frame_countdown
subs r8, r8, #1
strpl r8, frame_countdown
bpl skip_sync_time_test
ldr r8, sync_detected
cmp r8, #0
beq skip_sync_time_test // if no sync then timing comparison is meaningless
tst r3, #BIT_OSD | BIT_CALIBRATE | BIT_PROBE
bne skip_sync_time_test
@ -682,15 +709,6 @@ skip_all_lines:
cmp r7,r8
beq skip_sync_time_test //no sensible window
ldr r8, sync_detected
cmp r8, #0
beq skip_sync_time_test // if no sync then timing comparison is meaningless
ldr r8, frame_countdown
subs r8, r8, #1
strpl r8, frame_countdown
bpl skip_sync_time_test
and r0, r3, #BIT_MODE7
orr r0, #RET_SYNC_TIMING_CHANGED
@ -792,8 +810,9 @@ noInBandData:
tst r3, #BIT_CLEAR
bne force_osd_update
tst r3, #BIT_TELETEXT
bne skip_osd_update
ldr r0, param_video_type
cmp r0, #2 //VIDEO_TELETEXT
beq skip_osd_update
tst r3, #BIT_OSD
beq skip_osd_update
@ -802,14 +821,18 @@ noInBandData:
bl recalculate_hdmi_clock_line_locked_update
bl wait_for_vsync //wait for field sync as sometimes the update will be on the ragged edge of finishing during field sync causing glitches
pop {r1-r5, r11}
subs r6, r6, r7
rsbmi r6, r6, #0
ldr r7, field_type_threshold
cmp r6, r7
biclt r3, r3, #BIT_FIELD_TYPE1 // Odd, clear bit
orrge r3, r3, #BIT_FIELD_TYPE1 // Even, set bit
force_osd_update:
push {r1-r5, r11}
mov r0, r11
mov r1, r2 // bytes per line
bl osd_update_fast
pop {r1-r5, r11}
bic r3, #BIT_FIELD_TYPE1_VALID //Workaround to stop interlace change detection when OSD on in case it takes longer than frame
skip_osd_update:
bic r3, r3, #BIT_CLEAR
@ -1600,6 +1623,9 @@ clearfull:
// ======================================================================
clear_menu_bits:
ldr r0, param_fb_bpp
cmp r0, #2 //16 BPP
movge pc, lr
ldr r3, last_scanlines_state
tst r3, #BIT_NO_SCANLINES | BIT_PROBE
movne pc, lr
@ -1627,6 +1653,9 @@ clear_menu:
pop {r4-r12, pc}
restore_menu_bits:
ldr r0, param_fb_bpp
cmp r0, #2 //16 BPP
movge pc, lr
str r3, last_scanlines_state
tst r3, #BIT_NO_SCANLINES | BIT_PROBE
movne pc, lr

Wyświetl plik

@ -16,7 +16,7 @@ extern int measure_vsync();
extern int analyse_sync();
extern int clear_full_screen();
extern int clear_screen();
extern int clear_menu_bits();
extern int measure_n_lines(int n);

Wyświetl plik

@ -215,7 +215,8 @@ static int scanlines_intensity = 0;
static int colour = 0;
static int invert = 0;
static int fontsize = 0;
static int deinterlace = 6;
static int m7deinterlace = 6;
static int deinterlace = 0;
static int ntsccolour = 0;
static int vsync = 0;
static int vlockmode = 1;
@ -381,7 +382,8 @@ static int last_height = -1;
if (capinfo->sample_width == SAMPLE_WIDTH_6 && capinfo->bpp == 16) { //special double rate 6 bpp mode
adjusted_width >>= 1;
}
//last_width = capinfo->width;
//last_height = capinfo->height;
/* work out if overscan needed */
int h_size = get_hdisplay();
@ -429,9 +431,6 @@ static int last_height = -1;
RPI_PropertyAddTag(TAG_SET_VIRTUAL_SIZE, adjusted_width, capinfo->height);
#endif
RPI_PropertyAddTag(TAG_SET_DEPTH, capinfo->bpp);
//if (capinfo->bpp >= 16) {
// RPI_PropertyAddTag( TAG_SET_PIXEL_ORDER, 1);
//}
RPI_PropertyAddTag(TAG_SET_OVERSCAN, top_overscan, bottom_overscan, left_overscan, right_overscan);
RPI_PropertyAddTag(TAG_GET_PITCH);
RPI_PropertyAddTag(TAG_GET_PHYSICAL_SIZE);
@ -861,7 +860,9 @@ static int calibrate_sampling_clock(int profile_changed) {
lines_per_vsync = ((int) (lines_per_frame_double + 0.5) >> 1);
// Log it
capinfo->detected_sync_type &= ~SYNC_BIT_INTERLACED;
if (interlaced) {
capinfo->detected_sync_type |= SYNC_BIT_INTERLACED;
lines_per_frame = (int) (lines_per_frame_double + 0.5);
log_info(" Lines per frame = %d, (%g)", lines_per_frame, lines_per_frame_double);
log_info("Actual frame time = %d ns (interlaced), line time = %d ns", vsync_time_ns, one_line_time_ns);
@ -1001,6 +1002,7 @@ int recalculate_hdmi_clock_line_locked_update(int force) {
static double vsync_total = 0;
static int last = 0x80000000;
if (last != jitter_offset) {
log_info("Jit%d", jitter_offset);
last = jitter_offset;
@ -1013,6 +1015,21 @@ int recalculate_hdmi_clock_line_locked_update(int force) {
return 1 + genlocked;
}
}
/*
static int last_debug = -1;
if (last_debug != debug_value) {
log_info("%08X", debug_value);
last_debug = debug_value;
if (vlockmode != HDMI_EXACT) {
// Return 0 if genlock disabled
return 0;
} else {
// Return 1 if genlock enabled but not yet locked
// Return 2 if genlock enabled and locked
return 1 + genlocked;
}
}
*/
if (!force) {
int recalc_nlines_time_ns = (int)((double)total_hsync_period * 1000 * MEASURE_NLINES / (capinfo->nlines - 1) / cpuspeed); //adjust to MEASURE_NLINES in ns
int ppm_lo = (int)(((double) nlines_time_ns * PLL_PPM_LO / 1000000) + 0.5);
@ -1041,7 +1058,7 @@ int recalculate_hdmi_clock_line_locked_update(int force) {
nlines_time_ns = recalc_nlines_time_ns;
old_clock = new_clock;
old_pll_freq = pll_freq;
log_info("***PLL");
log_info("*PLL");
drifted_count = 0;
line_total = 0;
// return without doing any genlock processing to avoid two log messages in one field.
@ -1545,7 +1562,7 @@ int *diff_N_frames_by_sample(capture_info_t *capinfo, int n, int mode7, int elk)
geometry_get_fb_params(capinfo); // required as calibration sets delay to 0 and the 2 high bits of that adjust the h offset
// In mode 0..6, capture one field
// In mode 7, capture two fields
capinfo->ncapture = (capinfo->video_type == VIDEO_TELETEXT) ? 2 : 1;
capinfo->ncapture = (capinfo->video_type != VIDEO_PROGRESSIVE) ? 2 : 1;
#ifdef INSTRUMENT_CAL
t = _get_cycle_counter();
@ -1899,7 +1916,7 @@ int total_N_frames(capture_info_t *capinfo, int n, int mode7, int elk) {
// In mode 0..6, capture one field
// In mode 7, capture two fields
capinfo->ncapture = capinfo->video_type == VIDEO_TELETEXT ? 2 : 1;
capinfo->ncapture = capinfo->video_type != VIDEO_PROGRESSIVE ? 2 : 1;
for (int i = 0; i < n; i++) {
int total = 0;
@ -1959,10 +1976,10 @@ void swapBuffer(int buffer) {
#endif
int get_current_display_buffer() {
if (capinfo->video_type == VIDEO_TELETEXT) {
return 0;
} else {
if ((capinfo->video_type == VIDEO_PROGRESSIVE || (capinfo->video_type == VIDEO_INTERLACED && !interlaced))) {
return current_display_buffer;
} else {
return 0;
}
}
@ -2161,6 +2178,14 @@ int get_ntsccolour() {
return ntsccolour;
}
void set_m7deinterlace(int mode) {
m7deinterlace = mode;
}
int get_m7deinterlace() {
return m7deinterlace;
}
void set_deinterlace(int mode) {
deinterlace = mode;
}
@ -2168,7 +2193,6 @@ void set_deinterlace(int mode) {
int get_deinterlace() {
return deinterlace;
}
void set_scanlines(int on) {
scanlines = on;
clear = BIT_CLEAR;
@ -2375,7 +2399,8 @@ void calculate_fb_adjustment() {
}
break;
}
//log_info("adjust=%d, %d", capinfo->h_adjust, capinfo->v_adjust);
//log_info("adjust=%d, %d", capinfo->h_adjust, capinfo->v_adjust);
}
void setup_profile(int profile_changed) {
@ -2396,8 +2421,6 @@ 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) {
capinfo->detected_sync_type = cpld->analyse(capinfo->sync_type, 0); // skips sync test if BBC and assumes non-inverted composite (saves time during mode changes)
@ -2406,15 +2429,14 @@ 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]);
calculate_fb_adjustment();
cpld->update_capture_info(capinfo);
geometry_get_fb_params(capinfo);
rgb_to_fb(capinfo, extra_flags() | BIT_PROBE); // dummy mode7 probe to setup sync type from capinfo
// Measure the frame time and set the sampling clock
calibrate_sampling_clock(profile_changed);
// force recalculation of the HDMI clock (if the vlockmode property requires this)
recalculate_hdmi_clock_line_locked_update(GENLOCK_FORCE);
geometry_get_fb_params(capinfo);
if (autoswitch == AUTOSWITCH_PC && sub_profiles_available(profile)) { // set window around expected time from sub-profile
double line_time = (double) clkinfo.line_len * 1000000000 / (double) clkinfo.clock;
@ -2584,16 +2606,16 @@ void rgb_to_hdmi_main() {
} else {
switch (cpld_fail_state) {
case CPLD_BLANK:
osd_set(1, 0, "CPLD is unprogrammed: Select correct CPLD");
osd_set_clear(1, 0, "CPLD is unprogrammed: Select correct CPLD");
break;
case CPLD_UNKNOWN:
osd_set(1, 0, "CPLD is unknown: Select correct CPLD");
osd_set_clear(1, 0, "CPLD is unknown: Select correct CPLD");
break;
case CPLD_WRONG:
osd_set(1, 0, "Wrong CPLD (6bit CPLD on 3bit board)");
osd_set_clear(1, 0, "Wrong CPLD (6bit CPLD on 3bit board)");
break;
case CPLD_MANUAL:
osd_set(1, 0, "Manual CPLD recovery: Select correct CPLD");
osd_set_clear(1, 0, "Manual CPLD recovery: Select correct CPLD");
break;
}
}
@ -2624,9 +2646,6 @@ void rgb_to_hdmi_main() {
flags |= BIT_MODE_DETECT;
}
if (interlaced) {
flags |= BIT_INTERLACED;
}
if (vsync) {
flags |= BIT_VSYNC;
}
@ -2635,29 +2654,32 @@ void rgb_to_hdmi_main() {
}
//paletteFlags |= BIT_MULTI_PALETTE; // test multi palette
flags |= deinterlace << OFFSET_INTERLACE;
if (capinfo->video_type == VIDEO_TELETEXT) {
flags |= m7deinterlace << OFFSET_INTERLACE;
} else {
flags |= deinterlace << OFFSET_INTERLACE;
}
#ifdef MULTI_BUFFER
if (capinfo->video_type != VIDEO_TELETEXT && osd_active() && (nbuffers == 0)) {
if ((capinfo->video_type == VIDEO_PROGRESSIVE || (capinfo->video_type == VIDEO_INTERLACED && !interlaced)) && osd_active() && (nbuffers == 0)) {
flags |= 2 << OFFSET_NBUFFERS;
} else {
flags |= nbuffers << OFFSET_NBUFFERS;
}
//log_info("Buffers = %d", (flags & MASK_NBUFFERS) >> OFFSET_NBUFFERS);
#endif
if (!osd_active() && reboot_required) {
file_save_config(resolution_name, scaling, filtering, frontend);
// Wait a while to allow UART time to empty
delay_in_arm_cycles_cpu_adjust(100000000);
if (resolution_warning != 0) {
osd_set(0, 0, "Hold menu during reset to recover");
osd_set_clear(0, 0, "Hold menu during reset to recover");
osd_set(1, 0, "if no display at new resolution.");
for (int i = 5; i > 0; i--) {
sprintf(osdline, "Rebooting in %d secs ", i);
log_info(osdline);
osd_set(3, 0, osdline);
osd_set_clear(3, 0, osdline);
delay_in_arm_cycles_cpu_adjust(1000000000);
}
}
@ -2699,9 +2721,6 @@ void rgb_to_hdmi_main() {
if (result & RET_SYNC_TIMING_CHANGED) {
log_info("Timing exceeds window: H = %d, V = %d, Lines = %d, VSync = %d", hsync_period * 1000 / cpuspeed, (int)((double)vsync_period * 1000 / cpuspeed), (int) (((double)vsync_period/hsync_period) + 0.5), (result & RET_VSYNC_POLARITY_CHANGED) ? 1 : 0);
}
if (result & RET_INTERLACE_CHANGED) {
log_info("Interlaced changed");
}
clear = 0;
@ -2727,6 +2746,12 @@ void rgb_to_hdmi_main() {
}
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);
if ((result & RET_INTERLACE_CHANGED) && capinfo->video_type == VIDEO_INTERLACED) {
fb_size_changed |= 1;
log_info("Interlaced changed");
}
active_size_changed = (capinfo->chars_per_line != last_capinfo.chars_per_line) || (capinfo->nlines != last_capinfo.nlines);
geometry_get_clk_params(&clkinfo);
@ -2748,7 +2773,7 @@ void rgb_to_hdmi_main() {
clear = BIT_CLEAR;
}
if (clk_changed || (result & RET_INTERLACE_CHANGED)) { // || lock_fail != 0) {
if ((clk_changed || (result & RET_INTERLACE_CHANGED)) && !fb_size_changed) { // || lock_fail != 0) {
target_difference = 0;
resync_count = 0;
// Measure the frame time and set the sampling clock

Wyświetl plik

@ -14,6 +14,8 @@ void set_scaling(int mode, int reboot);
int get_scaling();
void set_frontend(int value, int save);
int get_frontend();
void set_m7deinterlace(int value);
int get_m7deinterlace();
void set_deinterlace(int value);
int get_deinterlace();
void set_scanlines(int on);