This commit is contained in:
shylie 2025-04-13 11:16:03 -04:00
parent 9130db7d4f
commit 723dc86a33
6 changed files with 106 additions and 9 deletions

View File

@ -7,6 +7,7 @@ set(CMAKE_EXPORT_COMPILE_COMMANDS ON)
set(CMAKE_C_STANDARD 11)
set(CMAKE_CXX_STANDARD 20)
set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} -O0")
include(lib/pico-ice-sdk/cmake/preinit_pico_ice_sdk.cmake)
set(PICO_SDK_PATH ${CMAKE_SOURCE_DIR}/lib/pico-ice-sdk/lib/pico-sdk)

View File

@ -5,12 +5,15 @@ add_executable(dvi-dynamic
src/framebuffer.cpp
)
pico_generate_pio_header(dvi-dynamic ${CMAKE_CURRENT_SOURCE_DIR}/src/fpga.pio)
FileEmbedAdd(${CMAKE_CURRENT_SOURCE_DIR}/rtl_bin/mandelbrot.bin)
target_include_directories(dvi-dynamic PRIVATE include)
target_link_libraries(dvi-dynamic
pico_ice_sdk
hardware_dma
hardware_pio
file_embed
)
pico_add_extra_outputs(dvi-dynamic)

View File

@ -2,4 +2,13 @@ ldc_set_location -site 35 [get_ports {clk}]
ldc_set_location -site 39 [get_ports {led_g}]
ldc_set_location -site 40 [get_ports {led_b}]
ldc_set_location -site 41 [get_ports {led_r}]
ldc_set_location -site 41 [get_ports {led_r}]
ldc_set_location -site 27 [get_ports {data[0]}]
ldc_set_location -site 25 [get_ports {data[1]}]
ldc_set_location -site 21 [get_ports {data[2]}]
ldc_set_location -site 19 [get_ports {data[3]}]
ldc_set_location -site 26 [get_ports {data[4]}]
ldc_set_location -site 23 [get_ports {data[5]}]
ldc_set_location -site 20 [get_ports {data[6]}]
ldc_set_location -site 18 [get_ports {data[7]}]

View File

@ -3,10 +3,11 @@ module top
input wire clk,
output wire led_r,
output wire led_g,
output wire led_b
output wire led_b,
output wire [7:0] data
);
localparam N = 22;
localparam N = 25;
reg [N:0] counter;
@ -18,4 +19,6 @@ assign led_r = 1'b1;
assign led_g = counter[N];
assign led_b = 1'b1;
assign data = '0;
endmodule

37
dvi-dynamic/src/fpga.pio Normal file
View File

@ -0,0 +1,37 @@
.pio_version 1
.define public CLK_PIN 21
.program fpga
wait 1 gpio CLK_PIN
wait 0 gpio CLK_PIN
in pins, 8
% c-sdk {
static inline void fpga_program_init(PIO pio, uint sm, uint offset, uint pin)
{
pio_sm_config c = fpga_program_get_default_config(offset);
sm_config_set_in_pins(&c, pin);
pio_sm_set_consecutive_pindirs(pio, sm, pin, 8, false);
for (int i = 0; i < 8; i++)
{
pio_gpio_init(pio, pin + i);
}
sm_config_set_in_shift(
&c,
false,
true,
8
);
sm_config_set_fifo_join(&c, PIO_FIFO_JOIN_RX);
pio_sm_init(pio, sm, offset, &c);
pio_sm_set_enabled(pio, sm, true);
}
%}

View File

@ -13,6 +13,7 @@
#include <hardware/dma.h>
#include <hardware/gpio.h>
#include <hardware/irq.h>
#include <hardware/pio.h>
#include <hardware/structs/bus_ctrl.h>
#include <hardware/structs/hstx_ctrl.h>
#include <hardware/structs/hstx_fifo.h>
@ -24,6 +25,7 @@
#include "framebuffer.h"
#include "mandelbrot_bin.h"
#include "fpga.pio.h"
// ----------------------------------------------------------------------------
// DVI constants
@ -108,9 +110,12 @@ static uint32_t vactive_line[] = {
#define DMACH_PING 0
#define DMACH_PONG 1
#define DMACH_FBPI 2
#define DMACH_FBPO 3
// First we ping. Then we pong. Then... we ping again.
static bool dma_pong = false;
static bool dma_fb_pong = false;
// A ping and a pong are cued up initially, so the first time we enter this
// handler it is to cue up the second ping after the first ping has completed.
@ -121,11 +126,12 @@ static uint v_scanline = 2;
// post the command list, and another to post the pixels.
static bool vactive_cmdlist_posted = false;
void __scratch_x("") dma_irq_handler() {
void __scratch_x("") dma_irq0_handler()
{
// dma_pong indicates the channel that just finished, which is the one
// we're about to reload.
uint ch_num = dma_pong ? DMACH_PONG : DMACH_PING;
dma_channel_hw_t *ch = &dma_hw->ch[ch_num];
dma_channel_hw_t* ch = &dma_hw->ch[ch_num];
dma_hw->intr = 1u << ch_num;
dma_pong = !dma_pong;
@ -150,21 +156,59 @@ void __scratch_x("") dma_irq_handler() {
}
}
void dma_irq1_handler()
{
uint ch_num = dma_fb_pong ? DMACH_FBPI : DMACH_FBPO;
dma_channel_hw_t* ch = &dma_hw->ch[ch_num];
dma_hw->intr = 1u << ch_num;
dma_fb_pong = !dma_fb_pong;
ch->write_addr = (uintptr_t)FRAMEBUFFER;
}
// ----------------------------------------------------------------------------
// Main program
int main(void) {
int main(void)
{
ice_led_init();
ice_fpga_init(FPGA_DATA, 48);
sleep_ms(1000);
ice_cram_open(FPGA_DATA);
ice_cram_write(mandelbrot_bin_data, mandelbrot_bin_size);
ice_cram_close();
ice_fpga_init(FPGA_DATA, 16);
for (int i = 0; i < FRAMEBUFFER_SIZE; i++)
{
FRAMEBUFFER[i] = 0xFF;
FRAMEBUFFER[i] = rand();
}
const PIO pio = pio0;
const uint offset = pio_add_program(pio, &fpga_program);
const uint sm = pio_claim_unused_sm(pio, true);
fpga_program_init(pio, sm, offset, 0);
{
dma_channel_config c = dma_channel_get_default_config(DMACH_FBPI);
channel_config_set_read_increment(&c, false);
channel_config_set_write_increment(&c, true);
channel_config_set_transfer_data_size(&c, DMA_SIZE_8);
channel_config_set_dreq(&c, pio_get_dreq(pio, sm, false));
channel_config_set_chain_to(&c, DMACH_FBPO);
dma_channel_configure(DMACH_FBPI, &c, FRAMEBUFFER, &pio->rxf[sm], FRAMEBUFFER_SIZE, false);
channel_config_set_chain_to(&c, DMACH_FBPI);
dma_channel_configure(DMACH_FBPO, &c, FRAMEBUFFER, &pio->rxf[sm], FRAMEBUFFER_SIZE, false);
dma_hw->ints1 = (1u << DMACH_FBPI) | (1u << DMACH_FBPO);
dma_hw->inte1 = (1u << DMACH_FBPI) | (1u << DMACH_FBPO);
irq_set_exclusive_handler(DMA_IRQ_1, dma_irq1_handler);
irq_set_enabled(DMA_IRQ_1, true);
dma_channel_start(DMACH_FBPI);
}
// Configure HSTX's TMDS encoder for RGB332
@ -259,7 +303,7 @@ int main(void) {
dma_hw->ints0 = (1u << DMACH_PING) | (1u << DMACH_PONG);
dma_hw->inte0 = (1u << DMACH_PING) | (1u << DMACH_PONG);
irq_set_exclusive_handler(DMA_IRQ_0, dma_irq_handler);
irq_set_exclusive_handler(DMA_IRQ_0, dma_irq0_handler);
irq_set_enabled(DMA_IRQ_0, true);
bus_ctrl_hw->priority = BUSCTRL_BUS_PRIORITY_DMA_W_BITS | BUSCTRL_BUS_PRIORITY_DMA_R_BITS;