kopia lustrzana https://github.com/hoglet67/RGBtoHDMI
rodzic
29d99e7110
commit
cf17594877
113
src/rgb_to_fb.S
113
src/rgb_to_fb.S
|
@ -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
|
|
||||||
|
|
||||||
|
|
|
@ -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);
|
||||||
|
|
Ładowanie…
Reference in New Issue