Merge remote-tracking branch 'ian/dev' into dev

pull/30/head
David Banks 2019-02-25 18:43:26 +00:00
commit 33c91ae80e
8 zmienionych plików z 276 dodań i 24 usunięć

Wyświetl plik

@ -6,6 +6,7 @@
.text
.global capture_line_default_4bpp
.global inBandData
// The capture line function is provided the following:
// r0 = pointer to current line in frame buffer
@ -18,35 +19,130 @@
//
// All registers are available as scratch registers (i.e. nothing needs to be preserved)
inBandData:
.space 1024, 0
capture_line_default_4bpp:
push {lr}
mov r6, #0
mov r7, #0
tst r3, #BIT_VSYNC_MARKER
ldrne r7, =0x11111111
adrl r11, inBandData
mov r12, #0 // pointer to end of "HDMI" string
WAIT_FOR_PSYNC_EDGE // expects GPLEV0 in r4, result in r8
CAPTURE_LOW_BITS // input in r8, result in r10, corrupts r9/r14
WAIT_FOR_PSYNC_EDGE // expects GPLEV0 in r4, result in r8
CAPTURE_HIGH_BITS // input in r8, result in r10, corrupts r9/r14
CONVERT_WORD_MODE0
CONVERT_MODE0_MODE2
WRITE_WORD
sub r1, r1, #1
WAIT_FOR_PSYNC_EDGE // expects GPLEV0 in r4, result in r8
CAPTURE_LOW_BITS // input in r8, result in r10, corrupts r9/r14
WAIT_FOR_PSYNC_EDGE // expects GPLEV0 in r4, result in r8
CAPTURE_HIGH_BITS // input in r8, result in r10, corrupts r9/r14
CONVERT_WORD_MODE0
CONVERT_MODE0_MODE2
WRITE_WORD
sub r1, r1, #1
WAIT_FOR_PSYNC_EDGE // expects GPLEV0 in r4, result in r8
CAPTURE_LOW_BITS // input in r8, result in r10, corrupts r9/r14
WAIT_FOR_PSYNC_EDGE // expects GPLEV0 in r4, result in r8
CAPTURE_HIGH_BITS // input in r8, result in r10, corrupts r9/r14
CONVERT_WORD_MODE0
CONVERT_MODE0_MODE2
WRITE_WORD
sub r1, r1, #1
cmp r9, #'H'
bne loop
WAIT_FOR_PSYNC_EDGE // expects GPLEV0 in r4, result in r8
CAPTURE_LOW_BITS // input in r8, result in r10, corrupts r9/r14
WAIT_FOR_PSYNC_EDGE // expects GPLEV0 in r4, result in r8
CAPTURE_HIGH_BITS // input in r8, result in r10, corrupts r9/r14
CONVERT_WORD_MODE0
CONVERT_MODE0_MODE2
WRITE_WORD
sub r1, r1, #1
cmp r9, #'D'
bne loop
WAIT_FOR_PSYNC_EDGE // expects GPLEV0 in r4, result in r8
CAPTURE_LOW_BITS // input in r8, result in r10, corrupts r9/r14
WAIT_FOR_PSYNC_EDGE // expects GPLEV0 in r4, result in r8
CAPTURE_HIGH_BITS // input in r8, result in r10, corrupts r9/r14
CONVERT_WORD_MODE0
CONVERT_MODE0_MODE2
WRITE_WORD
sub r1, r1, #1
cmp r9, #'M'
bne loop
WAIT_FOR_PSYNC_EDGE // expects GPLEV0 in r4, result in r8
CAPTURE_LOW_BITS // input in r8, result in r10, corrupts r9/r14
WAIT_FOR_PSYNC_EDGE // expects GPLEV0 in r4, result in r8
CAPTURE_HIGH_BITS // input in r8, result in r10, corrupts r9/r14
CONVERT_WORD_MODE0
CONVERT_MODE0_MODE2
WRITE_WORD
sub r1, r1, #1
cmp r9, #'I'
bne loop
mov r12, r0 // save current screen pointer in r12 (points to end of "HDMI")
orr r3, r3, #BIT_IN_BAND_DETECTED
inBandLoop:
WAIT_FOR_PSYNC_EDGE // expects GPLEV0 in r4, result in r8
CAPTURE_LOW_BITS // input in r8, result in r10, corrupts r9/r14
WAIT_FOR_PSYNC_EDGE // expects GPLEV0 in r4, result in r8
CAPTURE_HIGH_BITS // input in r8, result in r10, corrupts r9/r14
CONVERT_WORD_MODE0
mov r10, #0
WRITE_WORD
strb r9, [r11], #1
subs r1, r1, #1
bne inBandLoop
sub r0, r12, #16
mov r10, #0
WRITE_WORD
mov r10, #0
WRITE_WORD
mov r10, #0
WRITE_WORD
mov r10, #0
WRITE_WORD
pop {pc}
loop:
WAIT_FOR_PSYNC_EDGE // expects GPLEV0 in r4, result in r8
CAPTURE_LOW_BITS // input in r8, result in r10, corrupts r9/r14
WAIT_FOR_PSYNC_EDGE // expects GPLEV0 in r4, result in r8
CAPTURE_HIGH_BITS // input in r8, result in r10, corrupts r9/r14
// Orr in the VSync indicator
orr r10, r10, r7
// Line double always in Modes 0-6 regardless of interlace
// On the multi core Pi this introduces stalling artefacts
#ifndef HAS_MULTICORE
tst r3, #BIT_SCANLINES
streq r10, [r0, r2]
strne r6, [r0, r2]
#endif
str r10, [r0], #4
CONVERT_WORD_MODE0
CONVERT_MODE0_MODE2
WRITE_WORD
subs r1, r1, #1
bne loop
pop {pc}

Wyświetl plik

@ -61,7 +61,9 @@
#define BIT_FIELD_TYPE1 0x00800000 // bit 23, indicates the field type of the previous field
#define BIT_FIELD_TYPE1_VALID 0x01000000 // bit 24, indicates FIELD_TYPE1 is valid
// bits 25-31 unused
#define BIT_MODE2_16COLOUR 0x02000000 // bit 25, if set then 16 colour mode 2 is emulated by decoding mode 0
#define BIT_IN_BAND_DETECTED 0x04000000 // bit 26, if set if in band data is detected
// bits 27-31 unused
// R0 return value bits
#define RET_SW1 0x02
#define RET_SW2 0x04

Wyświetl plik

@ -51,3 +51,68 @@ wait\@:
orr r10, r10, r9, lsl #(22 - PIXEL_BASE)
orr r10, r10, r8, lsl #(15 - PIXEL_BASE)
.endm
.macro CONVERT_WORD_MODE0
// Any non-zero pixel gets converted sets a bit
mov r9, #0
tst r10, #0x00000070
orrne r9, r9, #0x80
tst r10, #0x00000007
orrne r9, r9, #0x40
tst r10, #0x00007000
orrne r9, r9, #0x20
tst r10, #0x00000700
orrne r9, r9, #0x10
tst r10, #0x00700000
orrne r9, r9, #0x08
tst r10, #0x00070000
orrne r9, r9, #0x04
tst r10, #0x70000000
orrne r9, r9, #0x02
tst r10, #0x07000000
orrne r9, r9, #0x01
.endm
.macro CONVERT_MODE0_MODE2
tst r3, #BIT_MODE2_16COLOUR
beq standardPalette\@
// reinterpret mode 0 bits as 16 colour mode 2
mov r10,#0
tst r9, #0x01
orrne r10, r10, #0x010000
tst r9, #0x04
orrne r10, r10, #0x020000
tst r9, #0x10
orrne r10, r10, #0x040000
tst r9, #0x40
orrne r10, r10, #0x080000
tst r9, #0x02
orrne r10, r10, #0x01
tst r9, #0x08
orrne r10, r10, #0x02
tst r9, #0x20
orrne r10, r10, #0x04
tst r9, #0x80
orrne r10, r10, #0x08
orr r10, r10, r10, lsl #4
orr r10, r10, r10, lsl #8
standardPalette\@:
.endm
.macro WRITE_WORD
// eor in the VSync indicator (orr doesn't work on zx80/81 due to white screen)
eor r10, r10, r7
tst r3, #BIT_DEBUG
orrne r10, r10, #0x10 //red in leftmost
orrne r10, r10, #0x02000000 //green in rightmost
// Line double always in Modes 0-6 regardless of interlace
// On the multi core Pi this introduces stalling artefacts
#ifndef HAS_MULTICORE
tst r3, #BIT_SCANLINES
streq r10, [r0, r2]
strne r6, [r0, r2]
#endif
str r10, [r0], #4
.endm

Wyświetl plik

@ -731,11 +731,21 @@ void osd_update_palette() {
int m;
int num_colours = (capinfo->bpp == 8) ? 256 : 16;
for (int i = 0; i < num_colours; i++) {
int r = (i & 1) ? 255 : 0;
int g = (i & 2) ? 255 : 0;
int b = (i & 4) ? 255 : 0;
int r = (i & 1) ? 255 : 0;
int g = (i & 2) ? 255 : 0;
int b = (i & 4) ? 255 : 0;
if (paletteFlags & 1) {
r = customPalette[i] & 0xff;
g = (customPalette[i]>>8) & 0xff;
b = (customPalette[i]>>16) & 0xff;
} else {
switch (palette) {
case PALETTE_INVERSE:
case PALETTE_INVERSE:
r = 255 - r;
g = 255 - g;
b = 255 - b;
@ -855,6 +865,7 @@ void osd_update_palette() {
r = g = b = m;
break;
}
}
if (active) {
if (i >= (num_colours >> 1)) {
palette_data[i] = 0xFFFFFFFF;
@ -868,6 +879,7 @@ void osd_update_palette() {
if (get_debug()) {
palette_data[i] |= 0x00101010;
}
}
// Flush the previous swapBuffer() response from the GPU->ARM mailbox

Wyświetl plik

@ -9,6 +9,9 @@
#define ATTR_DOUBLE_SIZE (1 << 0)
extern int clock_error_ppm;
extern int customPalette[];
extern int paletteFlags;
enum {
HDMI_ORIGINAL,

Wyświetl plik

@ -15,6 +15,8 @@
.global vsync_line
.global default_vsync_line
.global lock_fail
.global paletteFlags
.global customPalette
// ======================================================================
// Macros
@ -229,6 +231,13 @@ frame:
bl wait_for_vsync
ldr r0, default_vsync_line
str r0, vsync_line // default for vsync line if vsync in blanking area
bic r3, r3, #BIT_IN_BAND_DETECTED
ldr r0, paletteFlags
tst r0, #1
orrne r3, r3, #BIT_MODE2_16COLOUR
biceq r3, r3, #BIT_MODE2_16COLOUR
// Working registers while frame is being captured
//
@ -456,7 +465,10 @@ skip_psync_loop_exit:
blx r10
// Restore the state used by the outer code
tst r3, #BIT_IN_BAND_DETECTED
pop {r1-r5, r11}
orrne r3, r3, #BIT_IN_BAND_DETECTED
// Skip a whole line to maintain aspect ratio
ldr r0, linecountmod10
@ -468,7 +480,53 @@ skip_psync_loop_exit:
subs r5, r5, #1
bne process_line_loop
push {r0-r12, lr}
mov r9, #0 // palette changed flag
mov r8, #0 // mode 2 emulation flag
tst r3, #BIT_OSD
bne noInBandData
tst r3, #BIT_IN_BAND_DETECTED
beq noInBandData
adr r10, customPalette
ldr r12, =inBandData
ldrb r11, [r12], #1 //read 1 byte of command data
cmp r11, #0
beq noInBandData
mov r11, r11, lsr #1
mov r8, #1 // mode 2 emulation enabled
commandloop:
ldrb r1, [r12], #1 //read 1 byte of command data
and r0, r1, #0x0f
ldrb r1, [r12], #1 //read 1 byte of command data
and r3, r1, #0xf0
orr r0, r0, r3, lsl #4
and r3, r1, #0x0f
orr r0, r0, r3, lsl #16
orr r0, r0, r0, lsl #4
ldr r2, [r10]
str r0, [r10], #4
cmp r0, r2
movne r9, #1
subs r11, r11, #1
bne commandloop
noInBandData:
ldr r7, paletteFlags
str r8, paletteFlags
cmp r9, #0
cmpeq r7, r8
blne osd_update_palette
pop {r0-r12, lr}
// Update the OSD in Mode 0..6
pop {r11}
tst r3, #BIT_MODE7
@ -480,6 +538,7 @@ skip_psync_loop_exit:
pop {r0-r12, lr}
skip_osd_update:
#ifdef MULTI_BUFFER
// Update the last drawn buffer
mov r0, r3, lsr #OFFSET_CURR_BUFFER
@ -491,6 +550,8 @@ skip_osd_update:
#endif
push {r0-r12, lr}
bl recalculate_hdmi_clock_line_locked_update
// Returns:
@ -775,3 +836,10 @@ vsync_line:
lock_fail:
.word 0
paletteFlags:
.word 0
customPalette:
.space 1024, 0

Wyświetl plik

@ -41,4 +41,6 @@ extern int lock_fail;
int recalculate_hdmi_clock_line_locked_update();
void osd_update_palette();
#endif

Wyświetl plik

@ -459,7 +459,11 @@ static void recalculate_hdmi_clock(int vlockmode) { // use local vsyncmode, not
double f2 = pllh_clock;
if (vlockmode > 0) {
f2 /= error;
f2 /= 1.0 + ((double) (HDMI_EXACT - vlockmode)) / 1000.0;
double divisor = 1000.0;
if (vlockmode == HDMI_SLOW_1000PPM || vlockmode == HDMI_FAST_1000PPM) {
divisor = 2000.0; //workaround 1000PPM actually now 500PPM
}
f2 /= 1.0 + ((double) (HDMI_EXACT - vlockmode)) / divisor;
}
// Sanity check HDMI pixel clock
@ -573,13 +577,13 @@ int recalculate_hdmi_clock_line_locked_update() {
log_info("Locked");
} else {
if (difference >= target_difference) {
if (difference < (20 + target_difference)) {
if (difference <= 3) {
recalculate_hdmi_clock_once(HDMI_SLOW_1000PPM);
} else {
recalculate_hdmi_clock_once(HDMI_SLOW_2000PPM);
}
} else {
if (difference > (-20 + target_difference)) {
if (difference >= 3) {
recalculate_hdmi_clock_once(HDMI_FAST_1000PPM);
} else {
recalculate_hdmi_clock_once(HDMI_FAST_2000PPM);