Skip to content
12 changes: 4 additions & 8 deletions src/dmd_interface.h
Original file line number Diff line number Diff line change
Expand Up @@ -23,12 +23,8 @@
#include "hardware/gpio.h"
#include "hardware/pio.h"

// Derive divider from current clock so PIO runs at ~125 MHz reference
float dmd_interface_125mhz_clk_divider =
(float)(clock_get_hz(clk_sys)) / 125000000.0f; // scales automatically

// Init the DMD reader (dots) PIO program, common for all DMD types.
void dmd_reader_program_init(PIO pio, uint sm, uint offset, pio_sm_config c,
void dmd_reader_program_init(float dmd_clkdiv, PIO pio, uint sm, uint offset, pio_sm_config c,
uint in_base_pin) {
sm_config_set_in_pins(&c, in_base_pin);

Expand All @@ -48,7 +44,7 @@ void dmd_reader_program_init(PIO pio, uint sm, uint offset, pio_sm_config c,
pio_sm_set_consecutive_pindirs(pio, sm, SDATA_X16_PADDING, 1, false);

// Make sure we run this sm with a 125MHz clk
sm_config_set_clkdiv(&c, dmd_interface_125mhz_clk_divider);
sm_config_set_clkdiv(&c, dmd_clkdiv);
}
// Connect these GPIOs to this PIO block
pio_gpio_init(pio, SDATA);
Expand All @@ -71,7 +67,7 @@ void dmd_reader_program_init(PIO pio, uint sm, uint offset, pio_sm_config c,
}

// Init the framedetect PIO program.
void dmd_framedetect_program_init(PIO pio, uint sm, uint offset,
void dmd_framedetect_program_init(float dmd_clkdiv, PIO pio, uint sm, uint offset,
pio_sm_config c, const uint* input_pins,
uint num_input_pins, uint jump_pin) {
if (jump_pin > 0) {
Expand All @@ -92,7 +88,7 @@ void dmd_framedetect_program_init(PIO pio, uint sm, uint offset,
0);

// Make sure we run this sm with a 125MHz clk
sm_config_set_clkdiv(&c, dmd_interface_125mhz_clk_divider);
sm_config_set_clkdiv(&c, dmd_clkdiv);

// Load our configuration, do not yet start the program
pio_sm_init(pio, sm, offset, &c);
Expand Down
2 changes: 1 addition & 1 deletion src/dmd_interface_capcom_hd.pio
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,6 @@ rclk_loop:
wait 1 gpio RCLK
wait 0 gpio RCLK
jmp x-- rclk_loop
nop [3]
irq PLANE_START_IRQ
wait 1 gpio RDATA
.wrap
4 changes: 2 additions & 2 deletions src/dmd_interface_de_x16_v2.pio
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ dotloop:
jmp y-- start

skip:
mov x, osr ; copy 8192 to x
mov x, osr ; copy 4096 to x
lsb_msb_check:
jmp pin reload_dotloop_y ; if DOTCLK is high, it means we will have a valid LSB + MSB row
jmp x-- lsb_msb_check ; loop for ~65.5 µs (based on 125MHz clkdiv)
Expand Down Expand Up @@ -62,7 +62,7 @@ reload_dotloop_y:

wait_low:
wait 0 gpio DE ; Wait for DE to go low
mov x, osr ; Use x as storage for 3000 iterations
mov x, osr ; Use x as storage for 2500 iterations

delay_loop:
jmp x-- delay_loop ; Decrement x and repeat until zero
Expand Down
4 changes: 2 additions & 2 deletions src/dmd_interface_desega.pio
Original file line number Diff line number Diff line change
Expand Up @@ -41,12 +41,12 @@ dotloop:

wait_low:
wait 0 gpio DE ; Wait for DE to go low
set x, 31 ; Use x as storage for 32 iterations
set x, 20 ; Use x as storage for 20 iterations

delay_loop:
nop [31]
nop [31]
jmp x-- delay_loop [31] ; Decrement x and repeat until zero
jmp x-- delay_loop ; Decrement x and repeat until zero

; After ~10 µs, check if still low
jmp pin, wait_low ; If pin went high early → back to wait_low
Expand Down
24 changes: 15 additions & 9 deletions src/dmdreader.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -650,7 +650,7 @@ void dmd_dma_handler() {
// It seems to be sufficient to check every 8th pixel for these patterns to
// detect sync. So we could avoid bitschifiting of the uint32_t value to
// check every single pixel.
if (dmd_type >= DMD_CAPCOM && !locked_in && !plane0_shifted) {
if (dmd_type == DMD_CAPCOM && !locked_in && !plane0_shifted) {
digitalWrite(LED_BUILTIN, HIGH);
uint8_t value = pixval & 0x0F;
if (value == 2 && (planebuf[px] & 0x0F) != 1 &&
Expand Down Expand Up @@ -724,7 +724,7 @@ void dmd_dma_handler() {
}
}

if (DMD_CAPCOM >= dmd_type && !locked_in && !plane0_shifted &&
if (dmd_type == DMD_CAPCOM && !locked_in && !plane0_shifted &&
detected_0_1_0_1 && detected_1_0_0_0) {
locked_in = true;
}
Expand Down Expand Up @@ -865,20 +865,26 @@ void dmdreader_programs_init(const pio_program_t *dmd_reader_program,
DmdConfigGetter framedetect_get_default_config,
uint *input_pins, uint8_t num_input_pins,
uint8_t jump_pin, uint8_t in_base_pin) {
uint32_t sys_hz = clock_get_hz(clk_sys); // e.g. 125/200/266 MHz
float target_hz = 125000000.0f; // PIO code designed for 125 MHz
float dmd_clkdiv = (float)sys_hz / target_hz; // scales automatically

dmdreader_error_blink(pio_claim_free_sm_and_add_program_for_gpio_range(
dmd_reader_program, &dmd_pio, &dmd_sm, &dmd_offset,
(DE < SDATA_X16) ? DE : SDATA_X16, 8, true));
pio_sm_config dmd_config = reader_get_default_config(dmd_offset);
dmd_reader_program_init(dmd_pio, dmd_sm, dmd_offset, dmd_config, in_base_pin);
dmd_reader_program_init(dmd_clkdiv, dmd_pio, dmd_sm, dmd_offset, dmd_config,
in_base_pin);

// The framedetect program just runs and detects the beginning of a new
// frame
dmdreader_error_blink(pio_claim_free_sm_and_add_program_for_gpio_range(
dmd_framedetect_program, &frame_pio, &frame_sm, &frame_offset,
(DE < SDATA_X16) ? DE : SDATA_X16, 8, true));
pio_sm_config frame_config = framedetect_get_default_config(frame_offset);
dmd_framedetect_program_init(frame_pio, frame_sm, frame_offset, frame_config,
input_pins, num_input_pins, jump_pin);
dmd_framedetect_program_init(dmd_clkdiv, frame_pio, frame_sm, frame_offset,
frame_config, input_pins, num_input_pins,
jump_pin);
pio_sm_set_enabled(frame_pio, frame_sm, true);
}

Expand Down Expand Up @@ -1032,13 +1038,13 @@ bool dmdreader_init(bool return_on_no_detection) {
pio_sm_exec_wait_blocking(dmd_pio, dmd_sm,
pio_encode_mov(pio_y, pio_null));

// load 8192 directly to TX fifo
pio_sm_put(dmd_pio, dmd_sm, 8192);
// load 4096 directly to TX fifo (32uS)
pio_sm_put(dmd_pio, dmd_sm, 4096);
// pull 32 bits from the TX fifo into osr
pio_sm_exec(dmd_pio, dmd_sm, pio_encode_pull(false, false));

// load 3000 directly to TX fifo
pio_sm_put(frame_pio, frame_sm, 3000);
// load 2500 directly to TX fifo (20uS)
pio_sm_put(frame_pio, frame_sm, 2500);
// pull 32 bits from the TX fifo into osr
pio_sm_exec(frame_pio, frame_sm, pio_encode_pull(false, false));

Expand Down
Loading