Skip to content

Commit 5016518

Browse files
authored
Frame sync x16 v2 & final changes (#41)
1 parent a820699 commit 5016518

6 files changed

Lines changed: 41 additions & 27 deletions

File tree

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ The Pi Pico is directly connected to the 6 DMD data lines. Communication between
88
On this IRQ line, the Pico signals that new data is available and consumer must start the data transfer.
99
Since not any consumer (especially the Raspberry Pi) can act as an SPI slave this method is used.
1010

11-
## Currently supported hardware systems
11+
## Officially Supported hardware systems
1212

1313
* WPC95 & WPC -> 128x32
1414
* Data East -> 128x32 & 128x16

src/dmd_interface.h

Lines changed: 4 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -23,12 +23,8 @@
2323
#include "hardware/gpio.h"
2424
#include "hardware/pio.h"
2525

26-
// Derive divider from current clock so PIO runs at ~125 MHz reference
27-
float dmd_interface_125mhz_clk_divider =
28-
(float)(clock_get_hz(clk_sys)) / 125000000.0f; // scales automatically
29-
3026
// Init the DMD reader (dots) PIO program, common for all DMD types.
31-
void dmd_reader_program_init(PIO pio, uint sm, uint offset, pio_sm_config c,
27+
void dmd_reader_program_init(float dmd_clkdiv, PIO pio, uint sm, uint offset, pio_sm_config c,
3228
uint in_base_pin) {
3329
sm_config_set_in_pins(&c, in_base_pin);
3430

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

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

7369
// Init the framedetect PIO program.
74-
void dmd_framedetect_program_init(PIO pio, uint sm, uint offset,
70+
void dmd_framedetect_program_init(float dmd_clkdiv, PIO pio, uint sm, uint offset,
7571
pio_sm_config c, const uint* input_pins,
7672
uint num_input_pins, uint jump_pin) {
7773
if (jump_pin > 0) {
@@ -92,7 +88,7 @@ void dmd_framedetect_program_init(PIO pio, uint sm, uint offset,
9288
0);
9389

9490
// Make sure we run this sm with a 125MHz clk
95-
sm_config_set_clkdiv(&c, dmd_interface_125mhz_clk_divider);
91+
sm_config_set_clkdiv(&c, dmd_clkdiv);
9692

9793
// Load our configuration, do not yet start the program
9894
pio_sm_init(pio, sm, offset, &c);

src/dmd_interface_capcom_hd.pio

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,6 @@ rclk_loop:
4848
wait 1 gpio RCLK
4949
wait 0 gpio RCLK
5050
jmp x-- rclk_loop
51-
nop [3]
5251
irq PLANE_START_IRQ
52+
wait 1 gpio RDATA
5353
.wrap

src/dmd_interface_de_x16_v2.pio

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111
.program dmd_reader_de_x16_v2
1212

1313
wait irq FRAME_START_IRQ ; we only check for an IRQ once because of limitations
14+
mov isr, null ; clean the isr before starting a new frame
1415

1516
.wrap_target
1617

@@ -32,7 +33,7 @@ dotloop:
3233
jmp y-- start
3334

3435
skip:
35-
mov x, osr ; copy 8192 to x
36+
mov x, osr ; copy 4096 to x
3637
lsb_msb_check:
3738
jmp pin reload_dotloop_y ; if DOTCLK is high, it means we will have a valid LSB + MSB row
3839
jmp x-- lsb_msb_check ; loop for ~65.5 µs (based on 125MHz clkdiv)
@@ -62,15 +63,15 @@ reload_dotloop_y:
6263

6364
wait_low:
6465
wait 0 gpio DE ; Wait for DE to go low
65-
mov x, osr ; Use x as storage for 3000 iterations
66+
mov x, osr ; Use x as storage for 2500 iterations
6667

6768
delay_loop:
68-
jmp x-- delay_loop ; Decrement x and repeat until zero
69+
jmp x-- delay_loop ; Decrement x and repeat until zero
6970

7071
; After ~16 µs, check if still low
71-
jmp pin, frame_start ; If DE went high early → we found the start
72+
jmp pin, frame_start ; If DE went high early → we found the start
7273
wait 1 gpio DE
73-
jmp wait_low ; DE didn't go high early → restart
74+
jmp wait_low ; DE didn't go high early → restart
7475

7576
frame_start:
7677
irq FRAME_START_IRQ

src/dmd_interface_desega.pio

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -41,12 +41,12 @@ dotloop:
4141

4242
wait_low:
4343
wait 0 gpio DE ; Wait for DE to go low
44-
set x, 31 ; Use x as storage for 32 iterations
44+
set x, 20 ; Use x as storage for 20 iterations
4545

4646
delay_loop:
4747
nop [31]
4848
nop [31]
49-
jmp x-- delay_loop [31] ; Decrement x and repeat until zero
49+
jmp x-- delay_loop ; Decrement x and repeat until zero
5050

5151
; After ~10 µs, check if still low
5252
jmp pin, wait_low ; If pin went high early → back to wait_low

src/dmdreader.cpp

Lines changed: 27 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -592,6 +592,18 @@ void dmd_dma_reset() {
592592
void dmd_dma_handler() {
593593
dmd_set_and_enable_new_dma_target();
594594

595+
if (dmd_type == DMD_DE_X16_V2) {
596+
// Due to the complexity of x16 v2, we use this way to re-sync
597+
// if the signals are noisy, or whatever else could happen.
598+
pio_sm_set_enabled(dmd_pio, dmd_sm, false);
599+
// clear the interrupt for FRAME_START_IRQ 5 in the pio
600+
dmd_pio->irq = (1u << 5);
601+
pio_sm_exec_wait_blocking(dmd_pio, dmd_sm, pio_encode_mov(pio_y, pio_null));
602+
dmd_dma_reset();
603+
pio_sm_exec(dmd_pio, dmd_sm, pio_encode_jmp(dmd_offset));
604+
pio_sm_set_enabled(dmd_pio, dmd_sm, true);
605+
}
606+
595607
// Required as long as CAPCOM is not locked-in:
596608
plane0_shifted = false;
597609
detected_0_1_0_1 = false;
@@ -650,7 +662,7 @@ void dmd_dma_handler() {
650662
// It seems to be sufficient to check every 8th pixel for these patterns to
651663
// detect sync. So we could avoid bitschifiting of the uint32_t value to
652664
// check every single pixel.
653-
if (dmd_type >= DMD_CAPCOM && !locked_in && !plane0_shifted) {
665+
if (dmd_type == DMD_CAPCOM && !locked_in && !plane0_shifted) {
654666
digitalWrite(LED_BUILTIN, HIGH);
655667
uint8_t value = pixval & 0x0F;
656668
if (value == 2 && (planebuf[px] & 0x0F) != 1 &&
@@ -724,7 +736,7 @@ void dmd_dma_handler() {
724736
}
725737
}
726738

727-
if (DMD_CAPCOM >= dmd_type && !locked_in && !plane0_shifted &&
739+
if (dmd_type == DMD_CAPCOM && !locked_in && !plane0_shifted &&
728740
detected_0_1_0_1 && detected_1_0_0_0) {
729741
locked_in = true;
730742
}
@@ -865,20 +877,26 @@ void dmdreader_programs_init(const pio_program_t *dmd_reader_program,
865877
DmdConfigGetter framedetect_get_default_config,
866878
uint *input_pins, uint8_t num_input_pins,
867879
uint8_t jump_pin, uint8_t in_base_pin) {
880+
uint32_t sys_hz = clock_get_hz(clk_sys); // e.g. 125/200/266 MHz
881+
float target_hz = 125000000.0f; // PIO code designed for 125 MHz
882+
float dmd_clkdiv = (float)sys_hz / target_hz; // scales automatically
883+
868884
dmdreader_error_blink(pio_claim_free_sm_and_add_program_for_gpio_range(
869885
dmd_reader_program, &dmd_pio, &dmd_sm, &dmd_offset,
870886
(DE < SDATA_X16) ? DE : SDATA_X16, 8, true));
871887
pio_sm_config dmd_config = reader_get_default_config(dmd_offset);
872-
dmd_reader_program_init(dmd_pio, dmd_sm, dmd_offset, dmd_config, in_base_pin);
888+
dmd_reader_program_init(dmd_clkdiv, dmd_pio, dmd_sm, dmd_offset, dmd_config,
889+
in_base_pin);
873890

874891
// The framedetect program just runs and detects the beginning of a new
875892
// frame
876893
dmdreader_error_blink(pio_claim_free_sm_and_add_program_for_gpio_range(
877894
dmd_framedetect_program, &frame_pio, &frame_sm, &frame_offset,
878895
(DE < SDATA_X16) ? DE : SDATA_X16, 8, true));
879896
pio_sm_config frame_config = framedetect_get_default_config(frame_offset);
880-
dmd_framedetect_program_init(frame_pio, frame_sm, frame_offset, frame_config,
881-
input_pins, num_input_pins, jump_pin);
897+
dmd_framedetect_program_init(dmd_clkdiv, frame_pio, frame_sm, frame_offset,
898+
frame_config, input_pins, num_input_pins,
899+
jump_pin);
882900
pio_sm_set_enabled(frame_pio, frame_sm, true);
883901
}
884902

@@ -1032,13 +1050,13 @@ bool dmdreader_init(bool return_on_no_detection) {
10321050
pio_sm_exec_wait_blocking(dmd_pio, dmd_sm,
10331051
pio_encode_mov(pio_y, pio_null));
10341052

1035-
// load 8192 directly to TX fifo
1036-
pio_sm_put(dmd_pio, dmd_sm, 8192);
1053+
// load 4096 directly to TX fifo (32uS)
1054+
pio_sm_put(dmd_pio, dmd_sm, 4096);
10371055
// pull 32 bits from the TX fifo into osr
10381056
pio_sm_exec(dmd_pio, dmd_sm, pio_encode_pull(false, false));
10391057

1040-
// load 3000 directly to TX fifo
1041-
pio_sm_put(frame_pio, frame_sm, 3000);
1058+
// load 2500 directly to TX fifo (20uS)
1059+
pio_sm_put(frame_pio, frame_sm, 2500);
10421060
// pull 32 bits from the TX fifo into osr
10431061
pio_sm_exec(frame_pio, frame_sm, pio_encode_pull(false, false));
10441062

@@ -1311,7 +1329,6 @@ bool dmdreader_init(bool return_on_no_detection) {
13111329
irq_set_exclusive_handler(DMA_IRQ_0, dmd_dma_handler);
13121330
irq_set_enabled(DMA_IRQ_0, true);
13131331
#endif
1314-
13151332
// Finally start DMD reader PIO program and DMA
13161333
dmd_set_and_enable_new_dma_target();
13171334
pio_sm_set_enabled(dmd_pio, dmd_sm, true);

0 commit comments

Comments
 (0)