Implemented vsync

Change-Id: I35d7dc7a0184e147faa64fadf038752e7df467b9
issue_1022
David Banks 2017-04-25 11:53:22 +01:00
rodzic 29d99e7110
commit cf17594877
2 zmienionych plików z 94 dodań i 53 usunięć

Wyświetl plik

@ -1,33 +1,68 @@
#include "rpi-base.h" #include "rpi-base.h"
#include "defs.h" #include "defs.h"
.text .text
.global rgb_to_fb .global rgb_to_fb
// r0 = pointer to frame buffer // r0 = pointer to frame buffer
// r1 // r1
// r2 // r2
// r3 // r3 = field offset
// r4 = GPLEV0 // r4 = GPLEV0
// r5 = line counter // r5 = line counter
// r6 = pixel counter // r6 = pixel counter
// r8 = value read from GPLEV0 // r8 = value read from GPLEV0
// r9 = extracted pixel // r9 = extracted pixel
// r10 = block of 8 pixels, to be written to FB // r10 = block of 8 pixels, to be written to FB
rgb_to_fb: rgb_to_fb:
push {r4-r12, lr} push {r4-r12, lr}
mov r3, #0
ldr r4, =GPLEV0
frame:
// Update field offset to alternate field
eor r3, r3, #320
// Set framebuffer address
add r1, r0, r3
// Wait for start of vsync
wait_for_vsync_a:
ldr r8, [r4]
tst r8, #VSYNC_MASK
beq wait_for_vsync_a
// Wait for end of vsync
wait_for_vsync_b:
ldr r8, [r4]
tst r8, #VSYNC_MASK
bne wait_for_vsync_b
// Skip inactive lines
mov r5, #28
loop0: loop0:
mov r1, r0
wait_for_hsync_a:
ldr r4, =GPLEV0 ldr r8, [r4]
mov r5, #256 tst r8, #HSYNC_MASK
beq wait_for_hsync_a
loop1:
wait_for_hsync_b:
ldr r8, [r4]
tst r8, #HSYNC_MASK
bne wait_for_hsync_b
subs r5, r5, #1
bne loop0
// Process active lines
mov r5, #256
loop1:
// Wait for active high hsync // Wait for active high hsync
wait_for_hsync: wait_for_hsync:
ldr r8, [r4] ldr r8, [r4]
@ -40,7 +75,7 @@ loop2:
// Initialize 8 pixel block // Initialize 8 pixel block
mov r10, #0 mov r10, #0
// Wait for 0-1 edge on PSYNC // Wait for 0-1 edge on PSYNC
wait_psync_01: wait_psync_01:
ldr r8, [r4] ldr r8, [r4]
@ -51,10 +86,10 @@ wait_psync_01:
// Pixel 1 in GPIO 7.. 5 -> 3.. 0 // Pixel 1 in GPIO 7.. 5 -> 3.. 0
// Pixel 2 in GPIO 10.. 8 -> 15..12 // Pixel 2 in GPIO 10.. 8 -> 15..12
// Pixel 3 in GPIO 13..11 -> 11.. 8 // Pixel 3 in GPIO 13..11 -> 11.. 8
and r9, r8, #(7 << PIXEL_BASE) and r9, r8, #(7 << PIXEL_BASE)
orr r10, r10, r9, lsl #2 orr r10, r10, r9, lsl #2
and r9, r8, #(7 << (PIXEL_BASE + 3)) and r9, r8, #(7 << (PIXEL_BASE + 3))
orr r10, r10, r9, lsr #5 orr r10, r10, r9, lsr #5
@ -74,10 +109,10 @@ wait_psync_10:
// Pixel 5 in GPIO 7.. 5 -> 19..16 // Pixel 5 in GPIO 7.. 5 -> 19..16
// Pixel 6 in GPIO 10.. 8 -> 31..28 // Pixel 6 in GPIO 10.. 8 -> 31..28
// Pixel 7 in GPIO 13..11 -> 27..24 // Pixel 7 in GPIO 13..11 -> 27..24
and r9, r8, #(7 << PIXEL_BASE) and r9, r8, #(7 << PIXEL_BASE)
orr r10, r10, r9, lsl #18 orr r10, r10, r9, lsl #18
and r9, r8, #(7 << (PIXEL_BASE + 3)) and r9, r8, #(7 << (PIXEL_BASE + 3))
orr r10, r10, r9, lsl #11 orr r10, r10, r9, lsl #11
@ -87,43 +122,21 @@ wait_psync_10:
and r9, r8, #(7 << (PIXEL_BASE + 9)) and r9, r8, #(7 << (PIXEL_BASE + 9))
orr r10, r10, r9, lsl #13 orr r10, r10, r9, lsl #13
str r10, [r1], #4 str r10, [r1], #4
subs r6, r6, #1
bne loop2
// Skip a whole line subs r6, r6, #1
bne loop2
// Skip a whole line to maintain aspect ratio
add r1, r1, #320 add r1, r1, #320
subs r5, r5, #1 subs r5, r5, #1
bne loop1 bne loop1
b frame
// Temporary hack - skip inactive lines // Return
ldr r5, =(312-256)
loop3:
wait_for_hsync_a:
ldr r8, [r4]
tst r8, #HSYNC_MASK
beq wait_for_hsync_a
wait_for_hsync_b: pop {r4-r12, lr}
ldr r8, [r4] mov pc, lr
tst r8, #HSYNC_MASK
bne wait_for_hsync_b
subs r5, r5, #1
bne loop3
b loop0
// Return
pop {r4-r12, lr}
mov pc, lr

Wyświetl plik

@ -43,6 +43,7 @@ architecture Behavorial of RGBtoHDMI is
signal shift : std_logic_vector(11 downto 0); signal shift : std_logic_vector(11 downto 0);
signal nCSYNC1 : std_logic; signal nCSYNC1 : std_logic;
signal nCSYNC2 : std_logic;
-- The counter runs at 4x pixel clock -- The counter runs at 4x pixel clock
-- --
@ -80,15 +81,40 @@ begin
if rising_edge(clk) then if rising_edge(clk) then
-- synchronize nCSYNC to the sampling clock -- synchronize nCSYNC to the sampling clock
nCSYNC1 <= nCSYNC; nCSYNC1 <= nCSYNC;
nCSYNC2 <= nCSYNC1;
if nCSYNC1 = '0' then if nCSYNC1 = '0' and nCSYNC2 = '1' then
-- within horizontal line sync pulse -- start of horizontal line sync pulse
hsync <= '1'; hsync <= '1';
psync <= '0'; psync <= '0';
-- counter is used to measure how long the pulse is
counter <= to_unsigned(0, counter'length);
elsif nCSYNC1 = '1' and nCSYNC2 = '0' then
-- end of horizontal line sync pulse
hsync <= '0';
-- test for vertical sync
-- a normal line sync pulse is 4us
-- a saturated counter (512 == 8us) value can only happen during vsync
if counter = 512 then
vsync <= '1';
else
vsync <= '0';
end if;
-- counter is used to find sampling point for first pixel
counter <= to_unsigned(1311, counter'length); counter <= to_unsigned(1311, counter'length);
elsif nCSYNC1 = '0' then
-- within the line sync pulse
-- saturate counter at 8us.
if counter < 512 then
counter <= counter + 1;
end if;
else else
-- within the line -- within the line
hsync <= '0';
if counter = 31 then if counter = 31 then
counter <= to_unsigned(0, counter'length); counter <= to_unsigned(0, counter'length);
else else
@ -110,6 +136,8 @@ begin
end if; end if;
end process; end process;
field <= '1';
LED1 <= not SW; LED1 <= not SW;
LED2 <= led_counter(led_counter'left); LED2 <= led_counter(led_counter'left);