From cf1759487714657f203f1d284791e434d0727cb7 Mon Sep 17 00:00:00 2001 From: David Banks Date: Tue, 25 Apr 2017 11:53:22 +0100 Subject: [PATCH] Implemented vsync Change-Id: I35d7dc7a0184e147faa64fadf038752e7df467b9 --- src/rgb_to_fb.S | 113 ++++++++++++++++++++++++-------------------- vhdl/RGBtoHDMI.vhdl | 34 +++++++++++-- 2 files changed, 94 insertions(+), 53 deletions(-) diff --git a/src/rgb_to_fb.S b/src/rgb_to_fb.S index 3407221c..4cf0bd89 100644 --- a/src/rgb_to_fb.S +++ b/src/rgb_to_fb.S @@ -1,33 +1,68 @@ #include "rpi-base.h" #include "defs.h" - + .text .global rgb_to_fb - + // r0 = pointer to frame buffer // r1 // r2 -// r3 +// r3 = field offset // r4 = GPLEV0 // r5 = line counter // r6 = pixel counter // r8 = value read from GPLEV0 // 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: - 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: - mov r1, r0 - - ldr r4, =GPLEV0 - mov r5, #256 - -loop1: - + +wait_for_hsync_a: + ldr r8, [r4] + tst r8, #HSYNC_MASK + beq wait_for_hsync_a + +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_hsync: ldr r8, [r4] @@ -40,7 +75,7 @@ loop2: // Initialize 8 pixel block mov r10, #0 - + // Wait for 0-1 edge on PSYNC wait_psync_01: ldr r8, [r4] @@ -51,10 +86,10 @@ wait_psync_01: // Pixel 1 in GPIO 7.. 5 -> 3.. 0 // Pixel 2 in GPIO 10.. 8 -> 15..12 // Pixel 3 in GPIO 13..11 -> 11.. 8 - + and r9, r8, #(7 << PIXEL_BASE) orr r10, r10, r9, lsl #2 - + and r9, r8, #(7 << (PIXEL_BASE + 3)) orr r10, r10, r9, lsr #5 @@ -74,10 +109,10 @@ wait_psync_10: // Pixel 5 in GPIO 7.. 5 -> 19..16 // Pixel 6 in GPIO 10.. 8 -> 31..28 // Pixel 7 in GPIO 13..11 -> 27..24 - + and r9, r8, #(7 << PIXEL_BASE) orr r10, r10, r9, lsl #18 - + and r9, r8, #(7 << (PIXEL_BASE + 3)) orr r10, r10, r9, lsl #11 @@ -87,43 +122,21 @@ wait_psync_10: and r9, r8, #(7 << (PIXEL_BASE + 9)) orr r10, r10, r9, lsl #13 - 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 - subs r5, r5, #1 - bne loop1 + subs r5, r5, #1 + bne loop1 + b frame -// Temporary hack - skip inactive lines - ldr r5, =(312-256) - -loop3: - -wait_for_hsync_a: - ldr r8, [r4] - tst r8, #HSYNC_MASK - beq wait_for_hsync_a +// Return -wait_for_hsync_b: - ldr r8, [r4] - tst r8, #HSYNC_MASK - bne wait_for_hsync_b + pop {r4-r12, lr} + mov pc, lr - subs r5, r5, #1 - bne loop3 - - - b loop0 - -// Return - - pop {r4-r12, lr} - mov pc, lr - diff --git a/vhdl/RGBtoHDMI.vhdl b/vhdl/RGBtoHDMI.vhdl index e0e34f6b..6a819777 100644 --- a/vhdl/RGBtoHDMI.vhdl +++ b/vhdl/RGBtoHDMI.vhdl @@ -43,6 +43,7 @@ architecture Behavorial of RGBtoHDMI is signal shift : std_logic_vector(11 downto 0); signal nCSYNC1 : std_logic; + signal nCSYNC2 : std_logic; -- The counter runs at 4x pixel clock -- @@ -80,15 +81,40 @@ begin if rising_edge(clk) then -- synchronize nCSYNC to the sampling clock nCSYNC1 <= nCSYNC; + nCSYNC2 <= nCSYNC1; - if nCSYNC1 = '0' then - -- within horizontal line sync pulse + if nCSYNC1 = '0' and nCSYNC2 = '1' then + -- start of horizontal line sync pulse hsync <= '1'; 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); + + elsif nCSYNC1 = '0' then + -- within the line sync pulse + -- saturate counter at 8us. + if counter < 512 then + counter <= counter + 1; + end if; + else -- within the line - hsync <= '0'; if counter = 31 then counter <= to_unsigned(0, counter'length); else @@ -110,6 +136,8 @@ begin end if; end process; + field <= '1'; + LED1 <= not SW; LED2 <= led_counter(led_counter'left);