kopia lustrzana https://github.com/hoglet67/RGBtoHDMI
Improve multi Pi support, add Video type option in geometry for teletext only modes and hide offsets when not in mode 7
rodzic
d714ba2092
commit
9f54331075
|
@ -132,10 +132,6 @@ _reset_:
|
|||
#endif
|
||||
// BL _enable_l1_cache
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
#ifdef HAS_MULTICORE
|
||||
|
||||
#ifdef KERNEL_OLD
|
||||
|
@ -257,7 +253,7 @@ _reset_continue:
|
|||
// initialise the ro data section (most things that have the const
|
||||
// declaration) and initialise the bss section variables to 0 (generally
|
||||
// known as automatics). It'll then call main
|
||||
|
||||
|
||||
b _cstartup
|
||||
|
||||
|
||||
|
@ -424,7 +420,7 @@ _data_memory_barrier:
|
|||
mov pc, lr
|
||||
|
||||
#ifdef USE_MULTICORE
|
||||
+.section ".text._init_core"
|
||||
.section ".text._init_core"
|
||||
_init_core:
|
||||
// On a Raspberry Pi 2 we enter in HYP mode, and need to force a switch to supervisor mode
|
||||
mrs r0, cpsr
|
||||
|
@ -508,7 +504,7 @@ _spin_core:
|
|||
bl RPI_AuxMiniUartWrite
|
||||
#endif
|
||||
_spin_core1:
|
||||
wfi
|
||||
wfe
|
||||
b _spin_core1
|
||||
|
||||
.section ".text._get_core"
|
||||
|
|
|
@ -20,6 +20,8 @@
|
|||
//
|
||||
// All registers are available as scratch registers (i.e. nothing needs to be preserved)
|
||||
|
||||
.align 6
|
||||
.ltorg
|
||||
b preload_capture_line_mode7_4bpp // entry point for preloading cache
|
||||
capture_line_mode7_4bpp:
|
||||
|
||||
|
@ -27,29 +29,18 @@ capture_line_mode7_4bpp:
|
|||
// by Ian Bradbury (IanB on stardot). Many thanks Ian.
|
||||
//
|
||||
push {lr}
|
||||
mov r5, r8
|
||||
SKIP_PSYNC
|
||||
push {r14}
|
||||
add r11, r0, r8 // offset to second buffer used for comparison not for display
|
||||
mov r12, r0 // pointer to the line in the frame buffer
|
||||
tst r3, #BIT_CALIBRATE
|
||||
bne process_chars_7_none
|
||||
|
||||
ands r8, r3, #MASK_INTERLACE
|
||||
beq process_chars_7_none // DEINTERLACE_NONE
|
||||
|
||||
mov r9, r8, lsr #OFFSET_INTERLACE // put interlace setting in R9 0-6
|
||||
|
||||
cmp r9, #1 //DEINTERLACE_BOB
|
||||
mov r8, r8, lsr #OFFSET_INTERLACE // put interlace setting in R9 0-6
|
||||
cmp r8, #1 //DEINTERLACE_BOB
|
||||
beq process_chars_7_bob
|
||||
|
||||
tst r3, #BIT_FIELD_TYPE // test odd or even field
|
||||
|
||||
add r11, r0, r5 // offset to second buffer used for comparison not for display
|
||||
|
||||
rsbeq r2, r2,#0 // negate R2 offset if odd field to write to line above (restored to original value on exit)
|
||||
|
||||
mov r12, r0 // pointer to the line in the frame buffer
|
||||
|
||||
cmp r9, #6 //DEINTERLACE_ADV
|
||||
cmp r8, #6 //DEINTERLACE_ADV
|
||||
beq process_chars_7_advanced
|
||||
|
||||
// Simple motion adaptive deinterlace
|
||||
|
@ -69,6 +60,8 @@ capture_line_mode7_4bpp:
|
|||
// r11 = pointer into comparison buffer (moves within line)
|
||||
// r12 = pixel value from comparison buffer
|
||||
|
||||
SKIP_PSYNC
|
||||
push {r14}
|
||||
mov r5, #0
|
||||
mov r6, #0
|
||||
mov r7, #0
|
||||
|
@ -79,7 +72,7 @@ capture_line_mode7_4bpp:
|
|||
eorne r7, r7, #0x02000000 //green in rightmost
|
||||
process_chars_loop_7_simple:
|
||||
|
||||
#if defined(RPI2) || defined(RPI3) || defined(RPI4)
|
||||
#ifdef USE_ALT_DEINTERLACE_CODE
|
||||
WAIT_FOR_PSYNC_EDGE
|
||||
ldr r5, [r0] // preload old pixel value from video buffer
|
||||
CAPTURE_LOW_BITS
|
||||
|
@ -145,8 +138,13 @@ process_chars_loop_7_simple:
|
|||
bne process_chars_loop_7_simple
|
||||
pop {r0, pc}
|
||||
|
||||
.align 6
|
||||
.ltorg
|
||||
process_chars_7_none:
|
||||
// No deinterlace
|
||||
|
||||
SKIP_PSYNC
|
||||
push {r14}
|
||||
mov r7, #0
|
||||
tst r3, #BIT_VSYNC_MARKER
|
||||
ldrne r7, =0x11111111 // the VSync indicator
|
||||
|
@ -174,8 +172,12 @@ process_chars_loop_7_none:
|
|||
bne process_chars_loop_7_none
|
||||
pop {r0, pc}
|
||||
|
||||
.align 6
|
||||
.ltorg
|
||||
process_chars_7_bob:
|
||||
// Simple bob deinterlace
|
||||
SKIP_PSYNC
|
||||
push {r14}
|
||||
mov r5, #0
|
||||
mov r6, #0
|
||||
mov r7, #0
|
||||
|
@ -187,19 +189,19 @@ 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
|
||||
#if defined(RPI2) || defined(RPI3) || defined(RPI4)
|
||||
#ifdef USE_ALT_DEINTERLACE_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
|
||||
ldr r5, [r0] // preload old pixel value from video buffer
|
||||
WAIT_FOR_PSYNC_EDGE // expects GPLEV0 in r4, result in r8
|
||||
ldr r5, [r0] // preload old pixel value from video buffer
|
||||
#else
|
||||
tst r3, #BIT_OSD
|
||||
ldrne 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
|
||||
tst r3, #BIT_OSD
|
||||
ldrne r5, [r0] // preload old pixel value from video buffer
|
||||
#endif
|
||||
tst r3, #BIT_OSD
|
||||
ldrne r5, [r0] // preload old pixel value from video buffer
|
||||
#endif
|
||||
CAPTURE_HIGH_BITS // input in r8, result in r10, corrupts r9/r14
|
||||
eor r10, r10, r7 // EOR in the VSync indicator
|
||||
bic r9, r5, r11
|
||||
|
@ -213,6 +215,9 @@ process_chars_loop_7_bob:
|
|||
subs r1, r1, #1
|
||||
bne process_chars_loop_7_bob
|
||||
pop {r0, pc}
|
||||
|
||||
.align 6
|
||||
.ltorg
|
||||
// all 6 osd buffers must be sequential
|
||||
osdbuffer3:
|
||||
.word 0
|
||||
|
@ -224,6 +229,8 @@ osdbufferA3:
|
|||
.word 0
|
||||
charline:
|
||||
.word 0
|
||||
r1save:
|
||||
.word 0
|
||||
|
||||
process_chars_7_advanced:
|
||||
// Advanced deinterlace
|
||||
|
@ -244,22 +251,52 @@ process_chars_7_advanced:
|
|||
// r11 = pointer into comparison buffer (moves within line)
|
||||
// r12 = pointer into frame buffer (moves within line)
|
||||
// r14 = misc
|
||||
|
||||
str r6, charline
|
||||
#ifdef USE_MULTICORE
|
||||
ldr r8, =line_buffer
|
||||
ldr r10, =read_pointer
|
||||
str r8, [r10], #4
|
||||
str r8, [r10], #4 //write_pointer
|
||||
str r3, [r10], #4 //r3copy
|
||||
str r4, [r10], #4 //r4copy
|
||||
str r9, [r10], #4 //r9copy
|
||||
str r1, [r10], #4 //capture_count
|
||||
str r7, [r10] //skip_count
|
||||
dmb // wait until memory written
|
||||
sev // wake up core
|
||||
waitforskip:
|
||||
ldr r7, [r10]
|
||||
cmp r7, #0
|
||||
bne waitforskip
|
||||
READ_CYCLE_COUNTER r14
|
||||
#else
|
||||
SKIP_PSYNC
|
||||
#endif
|
||||
push {r14}
|
||||
|
||||
process_chars_loop_7_advanced:
|
||||
|
||||
WAIT_FOR_PSYNC_EDGE_FAST
|
||||
push {r1}
|
||||
CAPTURE_LOW_BITS
|
||||
#ifdef USE_MULTICORE
|
||||
str r1, r1save
|
||||
CAPTURE_FROM_CORE1
|
||||
tst r3, #BIT_OSD
|
||||
ldmneia r12, {r5, r6, r7} // preload current field old screen values (three words) if OSD on
|
||||
moveq r5,#0
|
||||
moveq r6,#0
|
||||
moveq r7,#0
|
||||
moveq r7,#0
|
||||
ldr r1, =0x77777777 // osd bitmask
|
||||
#else
|
||||
WAIT_FOR_PSYNC_EDGE_FAST
|
||||
str r1, r1save
|
||||
CAPTURE_LOW_BITS
|
||||
tst r3, #BIT_OSD
|
||||
ldmneia r12, {r5, r6, r7} // preload current field old screen values (three words) if OSD on
|
||||
moveq r5,#0
|
||||
moveq r6,#0
|
||||
moveq r7,#0
|
||||
ldr r1, =0x77777777 // osd bitmask
|
||||
WAIT_FOR_PSYNC_EDGE_FAST
|
||||
CAPTURE_HIGH_BITS
|
||||
#endif
|
||||
str r10, [r11] // save new value in comparison buffer
|
||||
|
||||
mov r0, r10 // save left pixel data for later
|
||||
|
@ -286,6 +323,17 @@ process_chars_loop_7_advanced:
|
|||
ldreq r6, [r14, #4] // always load middle word as sometimes half has to be written back to screen during deinterlace
|
||||
moveq r5,#0
|
||||
moveq r7,#0
|
||||
|
||||
#ifdef USE_MULTICORE
|
||||
adr r14, osdbufferA1
|
||||
bic r5, r5, r1 // extract OSD bits
|
||||
bic r7, r7, r1 // extract OSD bits
|
||||
stmia r14, {r5, r6, r7} // save for later in osdbufferA1 but don't extract OSD bits on r6 as might need half old pixel data
|
||||
mov r1, r10
|
||||
CAPTURE_FROM_CORE1
|
||||
add r14, r11, r2 // r14 points to other field
|
||||
ldmia r14, {r5, r6, r7} // preload other field old values from comparison buffer (3 words)
|
||||
#else
|
||||
WAIT_FOR_PSYNC_EDGE_FAST
|
||||
adr r14, osdbufferA1
|
||||
bic r5, r5, r1 // extract OSD bits
|
||||
|
@ -294,10 +342,10 @@ process_chars_loop_7_advanced:
|
|||
mov r1, r10
|
||||
add r14, r11, r2 // r14 points to other field
|
||||
CAPTURE_LOW_BITS
|
||||
ldmia r14, {r5, r6, r7} // preload other field old values from comparison buffer (3 words)
|
||||
ldmia r14, {r5, r6, r7} // preload other field old values from comparison buffer (3 words)
|
||||
WAIT_FOR_PSYNC_EDGE_FAST
|
||||
CAPTURE_HIGH_BITS
|
||||
|
||||
#endif
|
||||
// r0 = left 8 pixels of 1st char
|
||||
// r10 bottom half = right 4 pixels of 1st char
|
||||
// r5 = left 8 pixels of 1st char from other field comparison buffer
|
||||
|
@ -422,12 +470,14 @@ deinterlace1:
|
|||
|
||||
nodeinterlace1:
|
||||
mov r0, r10 // save middle word in r0
|
||||
|
||||
#ifdef USE_MULTICORE
|
||||
CAPTURE_FROM_CORE1
|
||||
#else
|
||||
WAIT_FOR_PSYNC_EDGE_FAST
|
||||
CAPTURE_LOW_BITS
|
||||
WAIT_FOR_PSYNC_EDGE_FAST
|
||||
CAPTURE_HIGH_BITS
|
||||
|
||||
#endif
|
||||
// deinterlace 2nd char here
|
||||
|
||||
// all the above code is repeated for the 2nd character but is slightly different
|
||||
|
@ -557,18 +607,26 @@ deinterlace2:
|
|||
|
||||
nodeinterlace2:
|
||||
|
||||
pop {r1}
|
||||
ldr r1, r1save
|
||||
|
||||
add r11, r11, #12
|
||||
add r12, r12, #12
|
||||
subs r1, r1, #3
|
||||
cmp r1, #0
|
||||
bgt process_chars_loop_7_advanced
|
||||
pop {r0, pc}
|
||||
|
||||
preload_capture_line_mode7_4bpp:
|
||||
adr r0, rounding_lookup
|
||||
ldr r1, =rounding_end
|
||||
preload_loop:
|
||||
ldr r2,[r0], #4
|
||||
cmp r0, r1
|
||||
blt preload_loop
|
||||
SETUP_DUMMY_PARAMETERS
|
||||
b capture_line_mode7_4bpp
|
||||
// Insert the current literal pool, otherwise constants are to far away and you get a build error
|
||||
.align 6
|
||||
.ltorg
|
||||
|
||||
rounding_lookup:
|
||||
|
@ -5216,3 +5274,4 @@ rounding_lookup:
|
|||
.byte 0x00
|
||||
.byte 0x00
|
||||
.byte 0x00
|
||||
rounding_end:
|
||||
|
|
|
@ -261,7 +261,7 @@ static void write_config(config_t *config) {
|
|||
// delay = 1 : use BCDEFA
|
||||
// delay = 2 : use CDEFAB
|
||||
// etc
|
||||
int offset = (supports_delay && mode7) ? (i + config->full_px_delay) % NUM_OFFSETS : i;
|
||||
int offset = (supports_delay && capinfo->video_type == VIDEO_TELETEXT) ? (i + config->full_px_delay) % NUM_OFFSETS : i;
|
||||
sp |= (config->sp_offset[i] & 7) << (offset * 3);
|
||||
}
|
||||
if (config->half_px_delay) {
|
||||
|
@ -553,7 +553,7 @@ static void cpld_calibrate(capture_info_t *capinfo, int elk) {
|
|||
}
|
||||
|
||||
// If the min metric is at the limit, make use of the half pixel delay
|
||||
if (mode7 && min_metric > 0 && (min_i <= 1 || min_i >= 6)) {
|
||||
if (capinfo->video_type == VIDEO_TELETEXT && min_metric > 0 && (min_i <= 1 || min_i >= 6)) {
|
||||
log_info("Enabling half pixel delay");
|
||||
config->half_px_delay = 1;
|
||||
min_i ^= 4;
|
||||
|
@ -575,7 +575,7 @@ static void cpld_calibrate(capture_info_t *capinfo, int elk) {
|
|||
write_config(config);
|
||||
|
||||
// If the metric is non zero, there is scope for further optimization in mode7
|
||||
if (mode7 && min_metric > 0) {
|
||||
if (capinfo->video_type == VIDEO_TELETEXT && min_metric > 0) {
|
||||
log_info("Optimizing calibration");
|
||||
for (int i = 0; i < NUM_OFFSETS; i++) {
|
||||
// Start with current value of the sample point i
|
||||
|
@ -609,7 +609,7 @@ static void cpld_calibrate(capture_info_t *capinfo, int elk) {
|
|||
// Determine mode 7 alignment
|
||||
if (supports_delay) {
|
||||
signed int new_full_px_delay;
|
||||
if (mode7) {
|
||||
if (capinfo->video_type == VIDEO_TELETEXT) {
|
||||
new_full_px_delay = analyze_mode7_alignment(capinfo);
|
||||
} else {
|
||||
new_full_px_delay = analyze_default_alignment(capinfo);
|
||||
|
@ -652,6 +652,8 @@ static void update_param_range() {
|
|||
// Divider = 0 gives 6 clocks per pixel
|
||||
// Divider = 1 gives 8 clocks per pixel
|
||||
RPI_SetGpioValue(MODE7_PIN, config->divider == 8);
|
||||
|
||||
|
||||
}
|
||||
|
||||
static void cpld_set_mode(int mode) {
|
||||
|
@ -711,7 +713,6 @@ static void cpld_update_capture_info(capture_info_t *capinfo) {
|
|||
// Update the sample width
|
||||
capinfo->sample_width = (config->rate == 1); // 1 = 6bpp, everything else 3bpp
|
||||
// Update the line capture function
|
||||
if (!mode7) {
|
||||
if (capinfo->sample_width) {
|
||||
switch (capinfo->px_sampling) {
|
||||
case PS_NORMAL:
|
||||
|
@ -749,13 +750,16 @@ static void cpld_update_capture_info(capture_info_t *capinfo) {
|
|||
break;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
capinfo->capture_line = capture_line_mode7_3bpp_table;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static param_t *cpld_get_params() {
|
||||
params[A_OFFSET].hidden = !mode7;
|
||||
params[B_OFFSET].hidden = !mode7;
|
||||
params[C_OFFSET].hidden = !mode7;
|
||||
params[D_OFFSET].hidden = !mode7;
|
||||
params[E_OFFSET].hidden = !mode7;
|
||||
params[F_OFFSET].hidden = !mode7;
|
||||
return params;
|
||||
}
|
||||
|
||||
|
|
34
src/defs.h
34
src/defs.h
|
@ -71,7 +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
|
||||
// bit 29+ unused
|
||||
#define BIT_TELETEXT 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
|
||||
|
||||
// R0 return value bits
|
||||
#define RET_SW1 0x02
|
||||
|
@ -98,10 +100,14 @@
|
|||
|
||||
// Pi 2/3 Multicore options
|
||||
#if defined(RPI2) || defined(RPI3) || defined(RPI4)
|
||||
|
||||
// Indicate the platform has multiple cores
|
||||
#define HAS_MULTICORE
|
||||
#define HAS_MULTICORE // puts unused cores to sleep
|
||||
#endif
|
||||
|
||||
#if defined(RPI2) || defined(RPI3) // Pi4 may not need these
|
||||
#define USE_MULTICORE // makes Advanced Motion deinterlace use 2nd core
|
||||
#define USE_ALT_DEINTERLACE_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
|
||||
#endif
|
||||
|
||||
#ifdef __ASSEMBLER__
|
||||
|
@ -137,8 +143,9 @@
|
|||
#define O_SYNCTYPE 60
|
||||
#define O_DETSYNCTYPE 64
|
||||
#define O_VSYNCTYPE 68
|
||||
#define O_BORDER 72
|
||||
#define O_CAPTURE_LINE 76
|
||||
#define O_VIDEOTYPE 72
|
||||
#define O_BORDER 76
|
||||
#define O_CAPTURE_LINE 80
|
||||
|
||||
#else
|
||||
|
||||
|
@ -161,6 +168,7 @@ typedef struct {
|
|||
int sync_type; // expected sync type and polarity
|
||||
int detected_sync_type; // detected sync type and polarity
|
||||
int vsync_type; // expected vertical sync type
|
||||
int video_type; // expected video type / progressive / interlaced (teletext)
|
||||
int border; // border logical colour
|
||||
int (*capture_line)(); // the capture line function to use
|
||||
int px_sampling; // whether to sample normally, sub-sample or pixel double
|
||||
|
@ -243,8 +251,20 @@ typedef struct {
|
|||
#define FRAME_MINIMUM 10000000 // 10ms
|
||||
#define FRAME_TIMEOUT 24000000 // 24ms which is over a frame / field @ 50Hz (20ms)
|
||||
#define LINE_MINIMUM 20000 // 20uS
|
||||
//#define LINE_TIMEOUT 74000 // 74uS
|
||||
#define LINE_TIMEOUT 74*1024
|
||||
#define HSYNC_SCROLL_LO (4000 - 250)
|
||||
#define HSYNC_SCROLL_HI (4000 + 250)
|
||||
|
||||
|
||||
#if defined(RPI4)
|
||||
#define LINE_TIMEOUT (100 * 1500/1000 * 1024)
|
||||
#elif defined(RPI3)
|
||||
#define LINE_TIMEOUT (100 * 1200/1000 * 1024)
|
||||
#elif defined(RPI2)
|
||||
#define LINE_TIMEOUT (100 * 1000/1000 * 1024)
|
||||
#else
|
||||
#define LINE_TIMEOUT (100 * 1024)
|
||||
#endif
|
||||
|
||||
|
||||
#if defined(RPI4)
|
||||
#define CRYSTAL 54
|
||||
|
|
|
@ -46,6 +46,12 @@ static const char *fb_sizex2_names[] = {
|
|||
"Double Height+Width",
|
||||
};
|
||||
|
||||
static const char *deint_names[] = {
|
||||
"Progressive",
|
||||
"Interlaced Teletext"
|
||||
};
|
||||
|
||||
|
||||
static param_t params[] = {
|
||||
{ SETUP_MODE, "Setup Mode", "setup_mode", 0,NUM_SETUP-1, 1 },
|
||||
{ H_OFFSET, "H Offset", "h_offset", 0, 512, 4 },
|
||||
|
@ -64,6 +70,7 @@ static param_t params[] = {
|
|||
{ LINES_FRAME, "Lines per Frame", "lines_per_frame", 250, 1200, 1 },
|
||||
{ SYNC_TYPE, "Sync Type", "sync_type", 0, NUM_SYNC-1, 1 },
|
||||
{ VSYNC_TYPE, "V Sync Type", "vsync_type", 0,NUM_VSYNC-1, 1 },
|
||||
{ VIDEO_TYPE, "Video Type", "video_type", 0,NUM_VIDEO-1, 1 },
|
||||
{ PX_SAMPLING, "Pixel Sampling", "pixel_sampling", 0, NUM_PS-1, 1 },
|
||||
{ -1, NULL, NULL, 0, 0, 0 }
|
||||
};
|
||||
|
@ -86,6 +93,7 @@ typedef struct {
|
|||
int lines_per_frame; // number of lines per frame
|
||||
int sync_type; // sync type and polarity
|
||||
int vsync_type; // vsync type auto/interlaced/non-interlaced
|
||||
int video_type; // deinterlace type off/teletext
|
||||
int px_sampling; // pixel sampling mode
|
||||
} geometry_t;
|
||||
|
||||
|
@ -120,6 +128,7 @@ void geometry_init(int version) {
|
|||
mode7_geometry.lines_per_frame = 625;
|
||||
mode7_geometry.sync_type = SYNC_COMP;
|
||||
mode7_geometry.vsync_type = VSYNC_AUTO;
|
||||
mode7_geometry.video_type = VIDEO_TELETEXT;
|
||||
mode7_geometry.px_sampling = PS_NORMAL;
|
||||
|
||||
default_geometry.setup_mode = 0;
|
||||
|
@ -138,6 +147,7 @@ void geometry_init(int version) {
|
|||
default_geometry.lines_per_frame = 625;
|
||||
default_geometry.sync_type = SYNC_COMP;
|
||||
default_geometry.vsync_type = VSYNC_AUTO;
|
||||
default_geometry.video_type = VIDEO_PROG;
|
||||
default_geometry.px_sampling = PS_NORMAL;
|
||||
|
||||
int firmware_support = cpld->old_firmware_support();
|
||||
|
@ -199,8 +209,10 @@ int geometry_get_value(int num) {
|
|||
return geometry->lines_per_frame;
|
||||
case SYNC_TYPE:
|
||||
return geometry->sync_type;
|
||||
case VSYNC_TYPE:
|
||||
case VSYNC_TYPE:
|
||||
return geometry->vsync_type;
|
||||
case VIDEO_TYPE:
|
||||
return geometry->video_type;
|
||||
case PX_SAMPLING:
|
||||
if (use_px_sampling == 0) {
|
||||
geometry->px_sampling = 0;
|
||||
|
@ -226,6 +238,9 @@ const char *geometry_get_value_string(int num) {
|
|||
if (num == FB_SIZEX2) {
|
||||
return fb_sizex2_names[geometry_get_value(num)];
|
||||
}
|
||||
if (num == VIDEO_TYPE) {
|
||||
return deint_names[geometry_get_value(num)];
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
@ -288,6 +303,9 @@ void geometry_set_value(int num, int value) {
|
|||
case VSYNC_TYPE:
|
||||
geometry->vsync_type = value;
|
||||
break;
|
||||
case VIDEO_TYPE:
|
||||
geometry->video_type = value;
|
||||
break;
|
||||
case PX_SAMPLING:
|
||||
if (use_px_sampling == 0) {
|
||||
geometry->px_sampling = 0;
|
||||
|
@ -373,6 +391,21 @@ void geometry_get_fb_params(capture_info_t *capinfo) {
|
|||
geometry_max_v_height = geometry_min_v_height;
|
||||
}
|
||||
|
||||
#if defined(RPI2) || defined(RPI3) //clip capture size to avoid glitches on RPI2 & RPI3 (not needed on RPI4)
|
||||
if (geometry_min_h_width > 704 && geometry_min_v_height > 272 && geometry_min_v_height < 300) {
|
||||
geometry_min_v_height = 272;
|
||||
}
|
||||
if (geometry_min_h_width > 704) {
|
||||
geometry_min_h_width = 704;
|
||||
}
|
||||
if (geometry_max_h_width > 704 && geometry_max_v_height > 272 && geometry_max_v_height < 300) {
|
||||
geometry_max_v_height = 272;
|
||||
}
|
||||
if (geometry_max_h_width > 704) {
|
||||
geometry_max_h_width = 704;
|
||||
}
|
||||
#endif
|
||||
|
||||
if (use_px_sampling != 0) {
|
||||
capinfo->px_sampling = geometry->px_sampling;
|
||||
} else {
|
||||
|
@ -382,6 +415,7 @@ 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;
|
||||
|
||||
if (geometry->setup_mode == SETUP_NORMAL) {
|
||||
capinfo->border = get_border();
|
||||
|
@ -449,10 +483,10 @@ void geometry_get_fb_params(capture_info_t *capinfo) {
|
|||
}
|
||||
|
||||
int h_size43_adj = h_size43;
|
||||
if ((mode7 && m7scaling == M7_UNEVEN)
|
||||
|| (!mode7 && normalscaling == NORMAL_UNEVEN && geometry->h_aspect == 3 && geometry->v_aspect == 2)) {
|
||||
if ((capinfo->video_type == VIDEO_TELETEXT && m7scaling == SCALING_UNEVEN)
|
||||
|| (capinfo->video_type != VIDEO_TELETEXT && normalscaling == SCALING_UNEVEN && geometry->h_aspect == 3 && (geometry->v_aspect == 2 || geometry->v_aspect == 4))) {
|
||||
h_size43_adj = h_size43 * 3 / 4;
|
||||
if (h_aspect !=0 && v_aspect !=0) {
|
||||
if (h_aspect == 3 && (v_aspect == 2 || v_aspect == 4)) {
|
||||
h_aspect--;
|
||||
}
|
||||
}
|
||||
|
@ -559,8 +593,8 @@ void geometry_get_fb_params(capture_info_t *capinfo) {
|
|||
capinfo->width = adjusted_width + hborder;
|
||||
capinfo->height = adjusted_height + vborder;
|
||||
|
||||
if ((mode7 && m7scaling == M7_UNEVEN) // workaround mode 7 width so it looks like other modes
|
||||
||(!mode7 && normalscaling == NORMAL_UNEVEN && geometry->h_aspect == 3 && geometry->v_aspect == 2)) {
|
||||
if ((capinfo->video_type == VIDEO_TELETEXT && m7scaling == SCALING_UNEVEN) // workaround mode 7 width so it looks like other modes
|
||||
||(capinfo->video_type != VIDEO_TELETEXT && normalscaling == SCALING_UNEVEN && geometry->h_aspect == 3 && (geometry->v_aspect == 2 || geometry->v_aspect == 4))) {
|
||||
capinfo->width = capinfo->width * 3 / 4;
|
||||
}
|
||||
|
||||
|
@ -599,7 +633,7 @@ void geometry_get_fb_params(capture_info_t *capinfo) {
|
|||
//log_info("Clipping capture height to %d", capinfo->nlines);
|
||||
}
|
||||
|
||||
if (mode7) {
|
||||
if (capinfo->video_type == VIDEO_TELETEXT) {
|
||||
capvscale >>= 1;
|
||||
} else {
|
||||
if (osd_active()) {
|
||||
|
|
|
@ -32,6 +32,12 @@ enum {
|
|||
NUM_VSYNC
|
||||
};
|
||||
|
||||
enum {
|
||||
VIDEO_PROG,
|
||||
VIDEO_TELETEXT,
|
||||
NUM_VIDEO
|
||||
};
|
||||
|
||||
enum {
|
||||
SETUP_MODE,
|
||||
H_OFFSET,
|
||||
|
@ -50,6 +56,7 @@ enum {
|
|||
LINES_FRAME,
|
||||
SYNC_TYPE,
|
||||
VSYNC_TYPE,
|
||||
VIDEO_TYPE,
|
||||
PX_SAMPLING
|
||||
};
|
||||
|
||||
|
|
81
src/macros.S
81
src/macros.S
|
@ -9,7 +9,7 @@
|
|||
tst r8, #CSYNC_MASK
|
||||
.endm
|
||||
|
||||
.macro LINE_TIMEOUT_TEST_R9
|
||||
.macro LINE_TIMEOUT_TEST_SKIP_HSYNC
|
||||
READ_CYCLE_COUNTER r8
|
||||
subs r8, r8, r14
|
||||
rsbmi r8, r8, #0
|
||||
|
@ -17,7 +17,7 @@
|
|||
// Read the GPLEV0
|
||||
ldr r8, [r4]
|
||||
eorgt r8, r8, #CSYNC_MASK //inverting the value after the timeout will cause the test to pass
|
||||
cmp r9, #0
|
||||
tst r3, #BIT_NO_SKIP_HSYNC
|
||||
tstne r8, #CSYNC_MASK
|
||||
.endm
|
||||
|
||||
|
@ -30,19 +30,19 @@ waitlo\@:
|
|||
bne waitlo\@
|
||||
.endm
|
||||
|
||||
.macro WAIT_FOR_CSYNC_0_R9
|
||||
.macro WAIT_FOR_CSYNC_0_SKIP_HSYNC
|
||||
READ_CYCLE_COUNTER r14
|
||||
waitlo9\@:
|
||||
LINE_TIMEOUT_TEST_R9
|
||||
LINE_TIMEOUT_TEST_SKIP_HSYNC
|
||||
bne waitlo9\@
|
||||
LINE_TIMEOUT_TEST_R9
|
||||
LINE_TIMEOUT_TEST_SKIP_HSYNC
|
||||
bne waitlo9\@
|
||||
.endm
|
||||
|
||||
.macro WAIT_FOR_CSYNC_0_FAST_R9
|
||||
.macro WAIT_FOR_CSYNC_0_FAST_SKIP_HSYNC
|
||||
READ_CYCLE_COUNTER r14
|
||||
waitloF\@:
|
||||
LINE_TIMEOUT_TEST_R9
|
||||
LINE_TIMEOUT_TEST_SKIP_HSYNC
|
||||
bne waitloF\@
|
||||
.endm
|
||||
|
||||
|
@ -113,7 +113,7 @@ waitPF\@:
|
|||
|
||||
.macro SKIP_PSYNC
|
||||
// called if 4 bits per pixel in non-fast mode so has support for old CPLV v1 & v2
|
||||
WAIT_FOR_CSYNC_0_R9
|
||||
WAIT_FOR_CSYNC_0_SKIP_HSYNC
|
||||
READ_CYCLE_COUNTER r10
|
||||
bic r3, r3, #PSYNC_MASK // wait for zero after CSYNC
|
||||
// Wait for the end of hsync
|
||||
|
@ -129,24 +129,32 @@ waitPF\@:
|
|||
// - a "normal" hsync is 4.0us, increment h_offset by 1
|
||||
// - a "long" hsync is 4.5us, increment h_offset by 2
|
||||
// So test against two thresholds inbetween these values
|
||||
bic r3, #BIT_INHIBIT_MODE_DETECT
|
||||
mov r8, r7
|
||||
tst r3, #BIT_OLD_FIRMWARE_SUPPORT
|
||||
beq notoldfirmwarescroll\@
|
||||
|
||||
// old CPLD V1 & V2 code
|
||||
mov r9, r7
|
||||
cmp r10, #(4000 + 224)
|
||||
addgt r9, r9, #1
|
||||
cmp r10, #(4000 - 224)
|
||||
addgt r9, r9, #1
|
||||
|
||||
cmp r10, r9, lsr #16 //HSYNC_SCROLL_HI
|
||||
addgt r8, r8, #1
|
||||
orrgt r3, r3, #BIT_INHIBIT_MODE_DETECT
|
||||
bic r9, r9, #0xff000000
|
||||
bic r9, r9, #0x00ff0000
|
||||
cmp r10, r9 //HSYNC_SCROLL_LO
|
||||
addgt r8, r8, #1
|
||||
orrlt r3, r3, #BIT_INHIBIT_MODE_DETECT
|
||||
b doneoldfirmwarescroll\@
|
||||
notoldfirmwarescroll\@:
|
||||
// new CPLD V3 or later code
|
||||
mov r8, r7
|
||||
cmp r10, #(4000 + 224)
|
||||
cmp r10, r9, lsr #16 //HSYNC_SCROLL_HI
|
||||
addlt r8, r8, #1
|
||||
cmp r10, #(4000 - 224)
|
||||
orrgt r3, r3, #BIT_INHIBIT_MODE_DETECT
|
||||
bic r9, r9, #0xff000000
|
||||
bic r9, r9, #0x00ff0000
|
||||
cmp r10, r9 //HSYNC_SCROLL_LO
|
||||
addlt r8, r8, #1
|
||||
|
||||
tst r3, #BIT_OLD_FIRMWARE_SUPPORT
|
||||
movne r8, r9
|
||||
|
||||
orrlt r3, r3, #BIT_INHIBIT_MODE_DETECT
|
||||
doneoldfirmwarescroll\@:
|
||||
tst r3, #BIT_NO_H_SCROLL
|
||||
moveq r7, r8 // only allow fine sideways scrolling in bbc / electron mode (causes timing issues in ega mode)
|
||||
// Skip the configured number of psync edges (modes 0..6: edges every 250ns, mode 7: edges ever 333ns)
|
||||
|
@ -158,7 +166,7 @@ skip_psync_loop\@:
|
|||
|
||||
.macro SKIP_PSYNC_NO_OLD_CPLD
|
||||
// only called if 6 bits/pixel in non-fast mode (old CPLDs v1 & v2 don't work at 6bpp so no need for test)
|
||||
WAIT_FOR_CSYNC_0_FAST_R9
|
||||
WAIT_FOR_CSYNC_0_FAST_SKIP_HSYNC
|
||||
READ_CYCLE_COUNTER r10
|
||||
bic r3, r3, #PSYNC_MASK // wait for zero after CSYNC
|
||||
// Wait for the end of hsync
|
||||
|
@ -177,11 +185,14 @@ skip_psync_loop\@:
|
|||
|
||||
// new CPLD code only (not called from CPLD v1 & v2)
|
||||
mov r8, r7
|
||||
cmp r10, #(4000 + 224)
|
||||
cmp r10, r9, lsr #16 //HSYNC_SCROLL_HI
|
||||
addlt r8, r8, #1
|
||||
cmp r10, #(4000 - 224)
|
||||
orrgt r3, r3, #BIT_INHIBIT_MODE_DETECT
|
||||
bic r9, r9, #0xff000000
|
||||
bic r9, r9, #0x00ff0000
|
||||
cmp r10, r9 //HSYNC_SCROLL_LO
|
||||
addlt r8, r8, #1
|
||||
|
||||
orrlt r3, r3, #BIT_INHIBIT_MODE_DETECT
|
||||
tst r3, #BIT_NO_H_SCROLL
|
||||
moveq r7, r8 // only allow fine sideways scrolling in bbc / electron mode (causes timing issues in ega mode)
|
||||
// Skip the configured number of psync edges (modes 0..6: edges every 250ns, mode 7: edges ever 333ns)
|
||||
|
@ -193,7 +204,7 @@ skip_psync_loop_no_old\@:
|
|||
|
||||
.macro SKIP_PSYNC_NO_H_SCROLL
|
||||
// only called if in fast mode (both 3 & 6 bpp) - fast mode never called from old CPLDs v1 & v2
|
||||
WAIT_FOR_CSYNC_0_FAST_R9
|
||||
WAIT_FOR_CSYNC_0_FAST_SKIP_HSYNC
|
||||
bic r3, r3, #PSYNC_MASK // wait for zero after CSYNC
|
||||
WAIT_FOR_CSYNC_1_FAST
|
||||
READ_CYCLE_COUNTER r14
|
||||
|
@ -203,6 +214,19 @@ skip_psync_loop_no_h_scroll\@:
|
|||
bne skip_psync_loop_no_h_scroll\@
|
||||
.endm
|
||||
|
||||
#ifdef USE_MULTICORE
|
||||
.macro CAPTURE_FROM_CORE1
|
||||
ldr r9, =read_pointer
|
||||
ldr r8, [r9] //r8 is now read pointer and r9 points to write_pointer
|
||||
wait_wr\@:
|
||||
ldr r10, [r9, #4] //r10 is now write pointer
|
||||
cmp r8, r10
|
||||
bge wait_wr\@
|
||||
ldr r10, [r8], #4 //r10 is now pixel quad
|
||||
str r8, [r9] //save updated read pointer
|
||||
.endm
|
||||
#endif
|
||||
|
||||
.macro CAPTURE_LOW_BITS
|
||||
// Pixel 0 in GPIO 4.. 2 -> 7.. 4
|
||||
// Pixel 1 in GPIO 7.. 5 -> 3.. 0
|
||||
|
@ -755,10 +779,11 @@ skip_psync_loop_no_h_scroll\@:
|
|||
mov r1, #3
|
||||
mov r2, #0
|
||||
orr r3, r3, #BIT_VSYNC_MARKER // ensure that constants are in data cache
|
||||
bic r3, r3, #BIT_NO_SKIP_HSYNC
|
||||
mov r5, #1
|
||||
mov r6, #0
|
||||
mov r7, #2
|
||||
mov r8, #0
|
||||
mov r8, #256
|
||||
mov r9, #0 //force skip of wait for csync 0
|
||||
.endm
|
||||
|
||||
|
@ -816,7 +841,7 @@ novsync\@:
|
|||
#ifdef MULTI_BUFFER
|
||||
.macro FLIP_BUFFER
|
||||
// Skip the multi buffering in mode 7 and probe mode
|
||||
tst r3, #(BIT_MODE7 | BIT_PROBE)
|
||||
tst r3, #(BIT_TELETEXT | BIT_PROBE)
|
||||
bne noflip\@
|
||||
// Flip to the last completed draw buffer
|
||||
// It seems the GPU delays this until the next vsync
|
||||
|
|
34
src/osd.c
34
src/osd.c
|
@ -205,14 +205,9 @@ static const char *fontsize_names[] = {
|
|||
"Auto 12x20 8bpp"
|
||||
};
|
||||
|
||||
static const char *m7scaling_names[] = {
|
||||
"Uneven (3:2 to 4:3)",
|
||||
"Even"
|
||||
};
|
||||
|
||||
static const char *normalscaling_names[] = {
|
||||
static const char *even_scaling_names[] = {
|
||||
"Even",
|
||||
"Uneven (3:2 to 4:3)"
|
||||
"Uneven (3:2>>4:3)"
|
||||
};
|
||||
|
||||
// =============================================================
|
||||
|
@ -260,9 +255,9 @@ static param_t features[] = {
|
|||
{ F_SUBPROFILE, "Sub-Profile", "subprofile", 0, 0, 1 },
|
||||
{ F_PALETTE, "Palette", "palette", 0, 0, 1 },
|
||||
{ F_PALETTECONTROL, "Palette Control", "palette_control", 0, NUM_CONTROLS - 1, 1 },
|
||||
{ F_DEINTERLACE, "Mode7 Deinterlace", "mode7_deinterlace", 0, NUM_DEINTERLACES - 1, 1 },
|
||||
{ F_M7SCALING, "Mode 7 Integer", "mode7_scaling", 0, NUM_M7SCALINGS - 1, 1 },
|
||||
{ F_NORMALSCALING, "Normal Integer", "normal_scaling", 0, NUM_NORMSCALINGS - 1, 1 },
|
||||
{ F_DEINTERLACE,"Teletext Deinterlace", "teletext_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_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 },
|
||||
|
@ -1048,9 +1043,9 @@ static const char *get_param_string(param_menu_item_t *param_item) {
|
|||
case F_DEINTERLACE:
|
||||
return deinterlace_names[value];
|
||||
case F_M7SCALING:
|
||||
return m7scaling_names[value];
|
||||
return even_scaling_names[value];
|
||||
case F_NORMALSCALING:
|
||||
return normalscaling_names[value];
|
||||
return even_scaling_names[value];
|
||||
case F_VLOCKMODE:
|
||||
return vlockmode_names[value];
|
||||
case F_VLOCKSPEED:
|
||||
|
@ -1108,16 +1103,19 @@ static void info_system_summary(int line) {
|
|||
NDIV = (gpioreg[PLLD_CTRL] & 0x3ff) << ANA1_PREDIV;
|
||||
FRAC = gpioreg[PLLD_FRAC] << ANA1_PREDIV;
|
||||
int clockD = (double) (CRYSTAL * ((double)NDIV + ((double)FRAC) / ((double)(1 << 20))) + 0.5);
|
||||
int armclock = clockB / gpioreg[PLLB_ARM];
|
||||
sprintf(message, " CPU Clock: %d Mhz", armclock);
|
||||
sprintf(message, " PLLA: %4d Mhz", clockA);
|
||||
osd_set(line++, 0, message);
|
||||
sprintf(message, " PLLA: %d Mhz", clockA);
|
||||
sprintf(message, " PLLB: %4d Mhz", clockB);
|
||||
osd_set(line++, 0, message);
|
||||
sprintf(message, " PLLB: %d Mhz", clockB);
|
||||
sprintf(message, " PLLC: %4d Mhz", clockC);
|
||||
osd_set(line++, 0, message);
|
||||
sprintf(message, " PLLC: %d Mhz", clockC);
|
||||
sprintf(message, " PLLD: %4d Mhz", clockD);
|
||||
osd_set(line++, 0, message);
|
||||
sprintf(message, " PLLD: %d Mhz", clockD);
|
||||
sprintf(message, " CPU Clock: %4d Mhz", get_clock_rate(ARM_CLK_ID)/1000000);
|
||||
osd_set(line++, 0, message);
|
||||
sprintf(message, " CORE Clock: %4d Mhz", get_clock_rate(CORE_CLK_ID)/1000000);
|
||||
osd_set(line++, 0, message);
|
||||
sprintf(message, " SDRAM Clock: %4d Mhz", get_clock_rate(SDRAM_CLK_ID)/1000000);
|
||||
osd_set(line++, 0, message);
|
||||
sprintf(message, " Core Temp: %6.2f C", get_temp());
|
||||
osd_set(line++, 0, message);
|
||||
|
|
12
src/osd.h
12
src/osd.h
|
@ -143,15 +143,9 @@ enum {
|
|||
};
|
||||
|
||||
enum {
|
||||
M7_UNEVEN,
|
||||
M7_EVEN,
|
||||
NUM_M7SCALINGS
|
||||
};
|
||||
|
||||
enum {
|
||||
NORMAL_EVEN,
|
||||
NORMAL_UNEVEN,
|
||||
NUM_NORMSCALINGS
|
||||
SCALING_EVEN,
|
||||
SCALING_UNEVEN,
|
||||
NUM_ESCALINGS
|
||||
};
|
||||
|
||||
void osd_init();
|
||||
|
|
137
src/rgb_to_fb.S
137
src/rgb_to_fb.S
|
@ -43,10 +43,14 @@
|
|||
.global frame_minimum
|
||||
.global line_minimum
|
||||
.global frame_timeout
|
||||
.global hsync_scroll
|
||||
.global line_timeout
|
||||
|
||||
|
||||
.global capture_line_mode7_3bpp_table
|
||||
#ifdef USE_MULTICORE
|
||||
.global run_core
|
||||
.global read_pointer
|
||||
.global line_buffer
|
||||
#endif
|
||||
|
||||
.global capture_line_normal_3bpp_table
|
||||
.global capture_line_odd_3bpp_table
|
||||
|
@ -103,6 +107,11 @@ rgb_to_fb:
|
|||
str r2, 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
|
||||
ldr r2, [r0, #O_BORDER]
|
||||
str r2, param_border
|
||||
ldr r2, [r0, #O_FB_BASE]
|
||||
|
@ -137,7 +146,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_MODE7 | BIT_PROBE) // options currently in r1!
|
||||
tst r1, #(BIT_TELETEXT | BIT_PROBE) // options currently in r1!
|
||||
beq skip_swap
|
||||
push {r0-r3}
|
||||
mov r0, #0
|
||||
|
@ -167,7 +176,7 @@ skip_swap:
|
|||
// In Mode 7 (or on probe) write to buffer 0, display buffer 0
|
||||
bic r3, r3, #(MASK_LAST_BUFFER | MASK_CURR_BUFFER)
|
||||
#ifdef MULTI_BUFFER
|
||||
tst r3, #(BIT_MODE7 | BIT_PROBE)
|
||||
tst r3, #(BIT_TELETEXT | BIT_PROBE)
|
||||
// In modes 0..6, restore the previous buffer state
|
||||
ldreq r10, buffer_state
|
||||
orreq r3, r3, r10
|
||||
|
@ -212,6 +221,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 r10, param_border
|
||||
tst r10, #0x80
|
||||
ldrne r8, =capture_line_null
|
||||
|
@ -259,7 +271,7 @@ frame:
|
|||
// else draw to the "spare" buffer
|
||||
mov r0, #0
|
||||
#ifdef MULTI_BUFFER
|
||||
tst r3, #(BIT_MODE7 | BIT_PROBE)
|
||||
tst r3, #(BIT_TELETEXT | BIT_PROBE)
|
||||
bne buffer_chosen
|
||||
// Draw to the buffers cyclically, i.e. pick the one
|
||||
// after the last completed buffer, modulo <nbuffers + 1>
|
||||
|
@ -355,7 +367,8 @@ 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_mode_test
|
||||
tst r3, #BIT_MODE7
|
||||
moveq r5, #0 // Modes 0-6
|
||||
movne r5, #1 // Mode 7
|
||||
|
@ -417,7 +430,7 @@ no_sync_loss:
|
|||
// Save a copy of the frame buffer base
|
||||
push {r11}
|
||||
|
||||
#if defined(RPI2) || defined(RPI3) || defined(RPI4)
|
||||
#if defined(USE_CACHED_COMPARISON_BUFFER)
|
||||
ldr r5, =dummyscreen
|
||||
sub r5, r5, r11 // put comparison buffer in cached memory
|
||||
#else
|
||||
|
@ -434,11 +447,12 @@ no_sync_loss:
|
|||
// In Mode 0..6, reduce the number of active lines by one for the even frame
|
||||
// In Mode 7, increment the frame buffer pointer by one line for the even field
|
||||
|
||||
tst r3, #(BIT_NO_LINE_DOUBLE | BIT_MODE7)
|
||||
tst r3, #BIT_NO_LINE_DOUBLE
|
||||
tsteq r3, #BIT_TELETEXT
|
||||
addeq r11, r11, r2
|
||||
tst r3, #BIT_ELK
|
||||
bne is_elk
|
||||
tst r3, #BIT_MODE7
|
||||
tst r3, #BIT_TELETEXT
|
||||
beq fixupmodes
|
||||
tst r3, #BIT_FIELD_TYPE
|
||||
addeq r11, r11, r2
|
||||
|
@ -498,17 +512,19 @@ process_line_loop:
|
|||
// r6 = scan line count modulo 10
|
||||
// r7 = number of psyncs to skip
|
||||
// r8 = frame buffer height (=param_fb_height)
|
||||
// r9 = 1 is normal operation, 0 = skip wait for csync 0 (used during cache preload to avoid waiting for line sync)
|
||||
// r9 = hsync scroll limits
|
||||
// All registers are available as scratch registers (i.e. nothing needs to be preserved)
|
||||
|
||||
// Setup parameters
|
||||
// Load the address of the capture_line function into r12
|
||||
ldr r12, capture_address
|
||||
mov r0, r11
|
||||
orr r3, r3, #BIT_NO_SKIP_HSYNC
|
||||
ldr r6, linecountmod10
|
||||
ldr r7, param_h_offset
|
||||
ldr r8, video_offset
|
||||
mov r9, #1
|
||||
ldr r9, hsync_scroll
|
||||
|
||||
// Call capture line function
|
||||
blx r12 // exits with h sync timestamp in r0
|
||||
|
||||
|
@ -536,7 +552,8 @@ process_line_loop:
|
|||
|
||||
subs r5, r5, #1
|
||||
bne process_line_loop
|
||||
|
||||
tst r3, #BIT_INHIBIT_MODE_DETECT
|
||||
bicne r3, #BIT_MODE7
|
||||
pop {r11}
|
||||
|
||||
skip_all_lines:
|
||||
|
@ -661,7 +678,7 @@ noInBandData:
|
|||
|
||||
tst r3, #BIT_CLEAR
|
||||
bne force_osd_update
|
||||
tst r3, #BIT_MODE7
|
||||
tst r3, #BIT_TELETEXT
|
||||
bne skip_osd_update
|
||||
force_osd_update:
|
||||
push {r1-r5, r11}
|
||||
|
@ -1160,6 +1177,9 @@ param_detected_sync_type:
|
|||
param_vsync_type:
|
||||
.word 0
|
||||
|
||||
param_video_type:
|
||||
.word 0
|
||||
|
||||
param_border:
|
||||
.word 0
|
||||
|
||||
|
@ -1238,10 +1258,76 @@ line_minimum:
|
|||
.word 20000
|
||||
frame_timeout:
|
||||
.word 24000000
|
||||
hsync_scroll:
|
||||
.word (4000 - 224) | ((4000 + 224) << 16)
|
||||
line_timeout:
|
||||
.word 74000000
|
||||
.word 100000000
|
||||
|
||||
|
||||
.align 6
|
||||
.ltorg
|
||||
|
||||
#ifdef USE_MULTICORE
|
||||
|
||||
read_pointer:
|
||||
.word 0
|
||||
write_pointer:
|
||||
.word 0
|
||||
r3copy:
|
||||
.word 0
|
||||
r4copy:
|
||||
.word 0
|
||||
r9copy:
|
||||
.word 0
|
||||
capture_count:
|
||||
.word 0
|
||||
skip_count:
|
||||
.word 0
|
||||
run_core:
|
||||
bl enable_MMU_and_IDCaches
|
||||
bl _enable_unaligned_access
|
||||
bl _init_cycle_counter
|
||||
run_core_loop:
|
||||
wfe // put core to sleep until an event
|
||||
ldr r11, capture_count
|
||||
cmp r11, #0
|
||||
beq run_core_loop // go back to sleep if capture count not valid
|
||||
ldr r7, skip_count
|
||||
cmp r7, #0
|
||||
beq run_core_loop // go back to sleep if skip count not valid
|
||||
ldr r3, r3copy
|
||||
ldr r4, r4copy
|
||||
ldr r9, r9copy
|
||||
SKIP_PSYNC
|
||||
mov r7, #0
|
||||
str r7, skip_count
|
||||
ldr r12, write_pointer
|
||||
core_capture:
|
||||
WAIT_FOR_PSYNC_EDGE
|
||||
CAPTURE_LOW_BITS
|
||||
WAIT_FOR_PSYNC_EDGE
|
||||
CAPTURE_HIGH_BITS
|
||||
mov r6, r10
|
||||
WAIT_FOR_PSYNC_EDGE
|
||||
CAPTURE_LOW_BITS
|
||||
WAIT_FOR_PSYNC_EDGE
|
||||
CAPTURE_HIGH_BITS
|
||||
mov r7, r10
|
||||
WAIT_FOR_PSYNC_EDGE
|
||||
CAPTURE_LOW_BITS
|
||||
WAIT_FOR_PSYNC_EDGE
|
||||
CAPTURE_HIGH_BITS
|
||||
stmia r12!, {r6,r7,r10}
|
||||
str r12, write_pointer
|
||||
sub r11, r11, #3
|
||||
cmp r11, #0
|
||||
bgt core_capture
|
||||
str r12, write_pointer
|
||||
mov r11, #0
|
||||
str r11, capture_count
|
||||
b run_core_loop
|
||||
#endif
|
||||
|
||||
// ======================================================================
|
||||
// CLEAR_SCREEN
|
||||
// ======================================================================
|
||||
|
@ -1484,24 +1570,6 @@ capture_line_normal_6bpp_table:
|
|||
.word capture_line_fast_sixbits_4bpp
|
||||
.word capture_line_fast_sixbits_8bpp
|
||||
|
||||
capture_line_mode7_3bpp_table:
|
||||
.word capture_line_mode7_4bpp
|
||||
.word capture_line_mode7_4bpp
|
||||
.word capture_line_mode7_4bpp
|
||||
.word capture_line_mode7_4bpp
|
||||
.word capture_line_mode7_4bpp
|
||||
.word capture_line_mode7_4bpp
|
||||
|
||||
.word capture_line_mode7_4bpp
|
||||
.word capture_line_mode7_4bpp
|
||||
.word capture_line_mode7_4bpp
|
||||
.word capture_line_mode7_4bpp
|
||||
.word capture_line_mode7_4bpp
|
||||
.word capture_line_mode7_4bpp
|
||||
|
||||
.word capture_line_mode7_4bpp
|
||||
.word capture_line_mode7_4bpp
|
||||
|
||||
|
||||
// tables below are deprecated and will be removed in future
|
||||
|
||||
|
@ -1620,6 +1688,11 @@ sw2counter2:
|
|||
|
||||
sw3counter2:
|
||||
.word 0
|
||||
|
||||
.ltorg
|
||||
.align 6
|
||||
line_buffer:
|
||||
.space 1920, 0
|
||||
.align 6
|
||||
dummyscreen: // used by capture preload
|
||||
.space 1920*1080, 0
|
|
@ -68,6 +68,7 @@ extern int hsync_threshold;
|
|||
extern int frame_minimum;
|
||||
extern int line_minimum;
|
||||
extern int frame_timeout;
|
||||
extern int hsync_scroll;
|
||||
extern int line_timeout;
|
||||
|
||||
extern int dummyscreen;
|
||||
|
|
|
@ -360,8 +360,8 @@ static int last_height = -1;
|
|||
v_overscan = 0;
|
||||
|
||||
if (get_gscaling() == SCALING_INTEGER) {
|
||||
if (!((mode7 && get_m7scaling() == M7_UNEVEN)
|
||||
||(!mode7 && get_normalscaling() == NORMAL_UNEVEN))) {
|
||||
if (!((capinfo->video_type == VIDEO_TELETEXT && get_m7scaling() == SCALING_UNEVEN)
|
||||
||(capinfo->video_type != VIDEO_TELETEXT && get_normalscaling() == SCALING_UNEVEN))) {
|
||||
int width = capinfo->width >> ((capinfo->sizex2 & 2) >> 1);
|
||||
if ((h_size - (h_size / width * width)) != 0) {
|
||||
h_overscan = (h_size - (h_size / capinfo->width * capinfo->width));
|
||||
|
@ -428,7 +428,7 @@ static int last_height = -1;
|
|||
}
|
||||
// On the Pi 2/3 the mailbox returns the address with bits 31..30 set, which is wrong
|
||||
capinfo->fb = (unsigned char *)(((unsigned int) capinfo->fb) & 0x3fffffff);
|
||||
log_info("Framebuffer address masked: %8.8X", (unsigned int)capinfo->fb);
|
||||
//log_info("Framebuffer address masked: %8.8X", (unsigned int)capinfo->fb);
|
||||
// Initialize the palette
|
||||
osd_update_palette();
|
||||
}
|
||||
|
@ -691,7 +691,7 @@ int cpu_adjust(double cycles) {
|
|||
return (int) (cycles * cpuspeed / 1000);
|
||||
}
|
||||
|
||||
static int calibrate_sampling_clock() {
|
||||
static int calibrate_sampling_clock(int profile_changed) {
|
||||
int a = 13;
|
||||
static unsigned int old_pll_freq = 0;
|
||||
static unsigned int old_clock = 0;
|
||||
|
@ -722,7 +722,9 @@ static int calibrate_sampling_clock() {
|
|||
log_info(" Clock error = %d PPM", clock_error_ppm);
|
||||
|
||||
unsigned int new_clock;
|
||||
|
||||
if (profile_changed) {
|
||||
old_clock = clkinfo.clock * cpld->get_divider();
|
||||
}
|
||||
if ((clkinfo.clock_ppm > 0 && abs(clock_error_ppm) > clkinfo.clock_ppm) || (sync_detected == 0)) {
|
||||
if (old_clock > 0 && sub_profiles_available(profile) == 0) {
|
||||
log_warn("PPM error too large, using previous clock");
|
||||
|
@ -1183,11 +1185,7 @@ static void init_hardware() {
|
|||
log_debug("Setting up divisor");
|
||||
init_gpclk(GPCLK_SOURCE, DEFAULT_GPCLK_DIVISOR);
|
||||
log_debug("Done setting up divisor");
|
||||
int ANA1_PREDIV = (gpioreg[PLLB_ANA1] >> 14) & 1;
|
||||
int NDIV = (gpioreg[PLLB_CTRL] & 0x3ff) << ANA1_PREDIV;
|
||||
int FRAC = gpioreg[PLLB_FRAC] << ANA1_PREDIV;
|
||||
int clockB = (double) (CRYSTAL * ((double)NDIV + ((double)FRAC) / ((double)(1 << 20))) + 0.5);
|
||||
cpuspeed = clockB / gpioreg[PLLB_ARM];
|
||||
cpuspeed = get_clock_rate(ARM_CLK_ID)/1000000;
|
||||
log_info("CPU speed detected as: %d Mhz", cpuspeed);
|
||||
|
||||
field_type_threshold = FIELD_TYPE_THRESHOLD * cpuspeed / 1000;
|
||||
|
@ -1199,7 +1197,8 @@ static void init_hardware() {
|
|||
frame_minimum = (int)((double)FRAME_MINIMUM * cpuspeed / 1000);
|
||||
frame_timeout = (int)((double)FRAME_TIMEOUT * cpuspeed / 1000);
|
||||
line_minimum = LINE_MINIMUM * cpuspeed / 1000;
|
||||
line_timeout = LINE_TIMEOUT * cpuspeed / 1000;
|
||||
hsync_scroll = (HSYNC_SCROLL_LO * cpuspeed / 1000) | ((HSYNC_SCROLL_HI * cpuspeed / 1000) << 16);
|
||||
line_timeout = LINE_TIMEOUT * cpuspeed / 1000; //not currently used
|
||||
|
||||
// Initialize the cpld after the gpclk generator has been started
|
||||
cpld_init();
|
||||
|
@ -1272,10 +1271,10 @@ static int extra_flags() {
|
|||
if (autoswitch != AUTOSWITCH_MODE7) {
|
||||
extra |= BIT_NO_H_SCROLL;
|
||||
}
|
||||
if (autoswitch != AUTOSWITCH_PC) {
|
||||
if (autoswitch != AUTOSWITCH_PC || !sub_profiles_available(profile)) {
|
||||
extra |= BIT_NO_AUTOSWITCH;
|
||||
}
|
||||
if (!scanlines || ((capinfo->sizex2 & 1) == 0) || mode7 || osd_active()) {
|
||||
if (!scanlines || ((capinfo->sizex2 & 1) == 0) || (capinfo->video_type == VIDEO_TELETEXT) || osd_active()) {
|
||||
extra |= BIT_NO_SCANLINES;
|
||||
}
|
||||
if (osd_active()) {
|
||||
|
@ -1287,7 +1286,8 @@ return extra;
|
|||
#ifdef HAS_MULTICORE
|
||||
static void start_core(int core, func_ptr func) {
|
||||
printf("starting core %d\r\n", core);
|
||||
*(unsigned int *)(0x4000008C + 0x10 * core) = (unsigned int) func;
|
||||
*(unsigned int *)(0x4000008c + 0x10 * core) = (unsigned int) func;
|
||||
asm ( "sev" );
|
||||
}
|
||||
#endif
|
||||
|
||||
|
@ -1340,7 +1340,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 = mode7 ? 2 : 1;
|
||||
capinfo->ncapture = (capinfo->video_type == VIDEO_TELETEXT) ? 2 : 1;
|
||||
|
||||
#ifdef INSTRUMENT_CAL
|
||||
t = _get_cycle_counter();
|
||||
|
@ -1388,29 +1388,29 @@ int *diff_N_frames_by_sample(capture_info_t *capinfo, int n, int mode7, int elk)
|
|||
if (line >= 0) {
|
||||
if (elk) {
|
||||
// Eliminate cursor lines in 32 row modes (0,1,2,4,5)
|
||||
if (!mode7 && (line % 8) == 5) {
|
||||
if (capinfo->video_type != VIDEO_TELETEXT && (line % 8) == 5) {
|
||||
skip = 1;
|
||||
}
|
||||
// Eliminate cursor lines in 25 row modes (3, 6)
|
||||
if (!mode7 && (line % 10) == 3) {
|
||||
if (capinfo->video_type != VIDEO_TELETEXT && (line % 10) == 3) {
|
||||
skip = 1;
|
||||
}
|
||||
// Eliminate cursor lines in mode 7
|
||||
// (this case is untested as I don't have a Jafa board)
|
||||
if (mode7 && (line % 10) == 7) {
|
||||
if (capinfo->video_type == VIDEO_TELETEXT && (line % 10) == 7) {
|
||||
skip = 1;
|
||||
}
|
||||
} else {
|
||||
// Eliminate cursor lines in 32 row modes (0,1,2,4,5)
|
||||
if (!mode7 && (line % 8) == 7) {
|
||||
if (capinfo->video_type != VIDEO_TELETEXT && (line % 8) == 7) {
|
||||
skip = 1;
|
||||
}
|
||||
// Eliminate cursor lines in 25 row modes (3, 6)
|
||||
if (!mode7 && (line % 10) >= 5 && (line % 10) <= 7) {
|
||||
if (capinfo->video_type != VIDEO_TELETEXT && (line % 10) >= 5 && (line % 10) <= 7) {
|
||||
skip = 1;
|
||||
}
|
||||
// Eliminate cursor lines in mode 7
|
||||
if (mode7 && (line % 10) == 7) {
|
||||
if (capinfo->video_type == VIDEO_TELETEXT && (line % 10) == 7) {
|
||||
skip = 1;
|
||||
}
|
||||
}
|
||||
|
@ -1491,7 +1491,7 @@ int *diff_N_frames_by_sample(capture_info_t *capinfo, int n, int mode7, int elk)
|
|||
#define MODE7_CHAR_WIDTH 12
|
||||
|
||||
signed int analyze_mode7_alignment(capture_info_t *capinfo) {
|
||||
if (autoswitch != AUTOSWITCH_MODE7) {
|
||||
if (capinfo->video_type != VIDEO_TELETEXT) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
@ -1696,7 +1696,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 = mode7 ? 2 : 1;
|
||||
capinfo->ncapture = capinfo->video_type == VIDEO_TELETEXT ? 2 : 1;
|
||||
|
||||
for (int i = 0; i < n; i++) {
|
||||
int total = 0;
|
||||
|
@ -1756,7 +1756,7 @@ void swapBuffer(int buffer) {
|
|||
#endif
|
||||
|
||||
int get_current_display_buffer() {
|
||||
if (mode7) {
|
||||
if (capinfo->video_type == VIDEO_TELETEXT) {
|
||||
return 0;
|
||||
} else {
|
||||
return current_display_buffer;
|
||||
|
@ -2000,7 +2000,12 @@ int get_debug() {
|
|||
return debug;
|
||||
}
|
||||
int get_lines_per_vsync() {
|
||||
if (sync_detected && lines_per_vsync > 220) {
|
||||
return lines_per_vsync;
|
||||
} else {
|
||||
return 1000;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void set_autoswitch(int value) {
|
||||
|
@ -2024,7 +2029,7 @@ void set_autoswitch(int value) {
|
|||
autoswitch = value;
|
||||
}
|
||||
|
||||
hsync_threshold = (autoswitch == AUTOSWITCH_MODE7) ? BBC_HSYNC_THRESHOLD : OTHER_HSYNC_THRESHOLD;
|
||||
hsync_threshold = (autoswitch == AUTOSWITCH_MODE7 || capinfo->video_type == VIDEO_TELETEXT) ? BBC_HSYNC_THRESHOLD : OTHER_HSYNC_THRESHOLD;
|
||||
}
|
||||
|
||||
int get_autoswitch() {
|
||||
|
@ -2033,14 +2038,14 @@ int get_autoswitch() {
|
|||
|
||||
void action_calibrate_clocks() {
|
||||
// re-measure vsync and set the core/sampling clocks
|
||||
calibrate_sampling_clock();
|
||||
calibrate_sampling_clock(0);
|
||||
// set the hdmi clock property to match exactly
|
||||
set_vlockmode(HDMI_EXACT);
|
||||
}
|
||||
|
||||
void action_calibrate_auto() {
|
||||
// re-measure vsync and set the core/sampling clocks
|
||||
calibrate_sampling_clock();
|
||||
calibrate_sampling_clock(0);
|
||||
// During calibration we do our best to auto-delect an Electron
|
||||
log_debug("Elk mode = %d", elk_mode);
|
||||
for (int c = 0; c < NUM_CAL_PASSES; c++) {
|
||||
|
@ -2069,7 +2074,7 @@ void calculate_fb_adjustment() {
|
|||
//log_info("adjust=%d, %d", capinfo->h_adjust, capinfo->v_adjust);
|
||||
}
|
||||
|
||||
void setup_profile() {
|
||||
void setup_profile(int profile_changed) {
|
||||
|
||||
// Switch the the approriate capinfo structure instance
|
||||
capinfo = mode7 ? &mode7_capinfo : &default_capinfo;
|
||||
|
@ -2085,12 +2090,12 @@ void setup_profile() {
|
|||
|
||||
geometry_get_fb_params(capinfo);
|
||||
|
||||
if (autoswitch != AUTOSWITCH_PC) {
|
||||
capinfo->detected_sync_type = cpld->analyse(capinfo->sync_type);
|
||||
log_info("Polarity state set from profile = %s (%s)", sync_names[capinfo->detected_sync_type & SYNC_BIT_MASK], mixed_names[(capinfo->detected_sync_type & SYNC_BIT_MIXED_SYNC) ? 1 : 0]);
|
||||
} else {
|
||||
if (autoswitch == AUTOSWITCH_PC && sub_profiles_available(profile)) {
|
||||
capinfo->detected_sync_type = cpld->analyse(-1);
|
||||
log_info("Detected polarity state = %s (%s)", sync_names[capinfo->detected_sync_type & SYNC_BIT_MASK], mixed_names[(capinfo->detected_sync_type & SYNC_BIT_MIXED_SYNC) ? 1 : 0]);
|
||||
} else {
|
||||
capinfo->detected_sync_type = cpld->analyse(capinfo->sync_type);
|
||||
log_info("Polarity state set from profile = %s (%s)", 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);
|
||||
|
@ -2098,13 +2103,13 @@ void setup_profile() {
|
|||
|
||||
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();
|
||||
// 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);
|
||||
|
||||
if (autoswitch == AUTOSWITCH_PC) { // set window around expected time from sub-profile
|
||||
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;
|
||||
int window = (int) ((double) clkinfo.clock_ppm * line_time / 1000000);
|
||||
hsync_comparison_lo = (line_time - window) * cpuspeed / 1000;
|
||||
|
@ -2121,6 +2126,8 @@ void setup_profile() {
|
|||
}
|
||||
|
||||
log_info("Window: H = %d to %d, V = %d to %d, S = %s", hsync_comparison_lo * 1000 / cpuspeed, hsync_comparison_hi * 1000 / cpuspeed, (int)((double)vsync_comparison_lo * 1000 / cpuspeed), (int)((double)vsync_comparison_hi * 1000 / cpuspeed), sync_names[capinfo->sync_type]);
|
||||
|
||||
hsync_threshold = (autoswitch == AUTOSWITCH_MODE7 || capinfo->video_type == VIDEO_TELETEXT) ? BBC_HSYNC_THRESHOLD : OTHER_HSYNC_THRESHOLD;
|
||||
}
|
||||
void set_status_message(char *msg) {
|
||||
strcpy(status, msg);
|
||||
|
@ -2148,7 +2155,7 @@ void rgb_to_hdmi_main() {
|
|||
|
||||
// Setup defaults (these may be overridden by the CPLD)
|
||||
default_capinfo.capture_line = capture_line_normal_3bpp_table;
|
||||
mode7_capinfo.capture_line = capture_line_mode7_3bpp_table;
|
||||
mode7_capinfo.capture_line = capture_line_normal_3bpp_table;
|
||||
capinfo = &default_capinfo;
|
||||
capinfo->v_adjust = 0;
|
||||
capinfo->h_adjust = 0;
|
||||
|
@ -2201,15 +2208,17 @@ void rgb_to_hdmi_main() {
|
|||
while (1) {
|
||||
log_info("-----------------------LOOP------------------------");
|
||||
|
||||
setup_profile();
|
||||
setup_profile(profile != last_profile || last_subprofile != subprofile);
|
||||
|
||||
if ((autoswitch == AUTOSWITCH_PC) && ((result & RET_SYNC_TIMING_CHANGED) || profile != last_profile || last_subprofile != subprofile)) {
|
||||
if ((autoswitch == AUTOSWITCH_PC) && sub_profiles_available(profile) && ((result & RET_SYNC_TIMING_CHANGED) || profile != last_profile || last_subprofile != subprofile)) {
|
||||
int new_sub_profile = autoswitch_detect(one_line_time_ns, lines_per_frame, capinfo->detected_sync_type & SYNC_BIT_MASK);
|
||||
if (new_sub_profile >= 0) {
|
||||
set_subprofile(new_sub_profile);
|
||||
process_sub_profile(get_profile(), new_sub_profile);
|
||||
setup_profile();
|
||||
setup_profile(1);
|
||||
set_status_message("");
|
||||
} else {
|
||||
set_status_message("Auto Switch: No profile matched");
|
||||
log_info("Autoswitch: No profile matched");
|
||||
}
|
||||
}
|
||||
|
@ -2219,6 +2228,7 @@ void rgb_to_hdmi_main() {
|
|||
log_debug("Setting up frame buffer");
|
||||
init_framebuffer(capinfo);
|
||||
log_debug("Done setting up frame buffer");
|
||||
//log_info("Peripheral base = %08X", PERIPHERAL_BASE);
|
||||
log_info("RAM benchmark: Main memory = %d nS, Screen memory = %d nS", (int) ((double) benchmarkRAM(dummyscreen) * 1000 / cpuspeed), (int) ((double) benchmarkRAM((int) capinfo->fb) * 1000 / cpuspeed));
|
||||
|
||||
osd_refresh();
|
||||
|
@ -2286,7 +2296,7 @@ void rgb_to_hdmi_main() {
|
|||
|
||||
flags |= deinterlace << OFFSET_INTERLACE;
|
||||
#ifdef MULTI_BUFFER
|
||||
if (!mode7 && osd_active() && (nbuffers == 0)) {
|
||||
if (capinfo->video_type != VIDEO_TELETEXT && osd_active() && (nbuffers == 0)) {
|
||||
flags |= 2 << OFFSET_NBUFFERS;
|
||||
} else {
|
||||
flags |= nbuffers << OFFSET_NBUFFERS;
|
||||
|
@ -2318,6 +2328,10 @@ 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;
|
||||
|
||||
// Possibly the size or offset has been adjusted, so update current capinfo
|
||||
|
@ -2345,8 +2359,13 @@ void rgb_to_hdmi_main() {
|
|||
last_mode7 = mode7;
|
||||
|
||||
mode7 = result & BIT_MODE7 & (autoswitch == AUTOSWITCH_MODE7);
|
||||
|
||||
if (mode7 != last_mode7) {
|
||||
log_info("Mode changed %d", mode7);
|
||||
}
|
||||
|
||||
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->px_sampling != last_capinfo.px_sampling || paletteControl != last_paletteControl
|
||||
|| capinfo->video_type != last_capinfo.video_type|| capinfo->px_sampling != last_capinfo.px_sampling || paletteControl != last_paletteControl
|
||||
|| profile != last_profile || last_subprofile != subprofile || (result & RET_SYNC_TIMING_CHANGED);
|
||||
|
||||
if (active_size_changed) {
|
||||
|
@ -2357,7 +2376,7 @@ void rgb_to_hdmi_main() {
|
|||
target_difference = 0;
|
||||
resync_count = 0;
|
||||
// Measure the frame time and set the sampling clock
|
||||
calibrate_sampling_clock();
|
||||
calibrate_sampling_clock(0);
|
||||
// Force recalculation of the HDMI clock (if the vlockmode property requires this)
|
||||
recalculate_hdmi_clock_line_locked_update(GENLOCK_FORCE);
|
||||
}
|
||||
|
@ -2446,11 +2465,13 @@ void kernel_main(unsigned int r0, unsigned int r1, unsigned int atags)
|
|||
|
||||
#ifdef HAS_MULTICORE
|
||||
int i;
|
||||
|
||||
printf("main running on core %u\r\n", _get_core());
|
||||
|
||||
for (i = 0; i < 10000000; i++);
|
||||
#ifdef USE_MULTICORE
|
||||
start_core(1, _init_core);
|
||||
#else
|
||||
start_core(1, _spin_core);
|
||||
#endif
|
||||
for (i = 0; i < 10000000; i++);
|
||||
start_core(2, _spin_core);
|
||||
for (i = 0; i < 10000000; i++);
|
||||
|
|
Ładowanie…
Reference in New Issue