From 746980c49775d18eceb598d9d3ab8d5c494e4e5d Mon Sep 17 00:00:00 2001 From: Jan Vos Date: Thu, 12 Mar 2026 16:52:15 +0100 Subject: [PATCH 01/13] remove algorithm for HD and romstar --- src/dmdreader.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/dmdreader.cpp b/src/dmdreader.cpp index a144ab0..a8d4a9a 100644 --- a/src/dmdreader.cpp +++ b/src/dmdreader.cpp @@ -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 && @@ -724,7 +724,7 @@ void dmd_dma_handler() { } } - if (DMD_CAPCOM >= dmd_type && !locked_in && !plane0_shifted && + if (DMD_CAPCOM == dmd_type && !locked_in && !plane0_shifted && detected_0_1_0_1 && detected_1_0_0_0) { locked_in = true; } From b00b5c800803dc10227ba4923ad7895a733737d9 Mon Sep 17 00:00:00 2001 From: Jan Vos Date: Thu, 12 Mar 2026 19:38:03 +0100 Subject: [PATCH 02/13] fix ribbon cable pull for capcom HD --- src/dmd_interface_capcom_hd.pio | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/dmd_interface_capcom_hd.pio b/src/dmd_interface_capcom_hd.pio index 33d8bc3..433d10d 100644 --- a/src/dmd_interface_capcom_hd.pio +++ b/src/dmd_interface_capcom_hd.pio @@ -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 \ No newline at end of file From 525857a95ad310e78a0e5310729af75a385eab03 Mon Sep 17 00:00:00 2001 From: Jan Vos Date: Thu, 12 Mar 2026 19:38:15 +0100 Subject: [PATCH 03/13] more forgiving algorithm --- src/dmdreader.cpp | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/dmdreader.cpp b/src/dmdreader.cpp index a8d4a9a..31b09a7 100644 --- a/src/dmdreader.cpp +++ b/src/dmdreader.cpp @@ -650,7 +650,8 @@ 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 && + px & 1 == 0) { digitalWrite(LED_BUILTIN, HIGH); uint8_t value = pixval & 0x0F; if (value == 2 && (planebuf[px] & 0x0F) != 1 && @@ -724,7 +725,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; } From 5df0ffdc24eb0976eef1f32f705d33aa00b4598d Mon Sep 17 00:00:00 2001 From: Jan Vos Date: Thu, 12 Mar 2026 20:16:31 +0100 Subject: [PATCH 04/13] add some brackets --- src/dmdreader.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/dmdreader.cpp b/src/dmdreader.cpp index 31b09a7..5fd573a 100644 --- a/src/dmdreader.cpp +++ b/src/dmdreader.cpp @@ -651,7 +651,7 @@ void dmd_dma_handler() { // 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 && - px & 1 == 0) { + (px & 1) == 0) { digitalWrite(LED_BUILTIN, HIGH); uint8_t value = pixval & 0x0F; if (value == 2 && (planebuf[px] & 0x0F) != 1 && From f7958846bc711f3502c260855803515d37559f44 Mon Sep 17 00:00:00 2001 From: Jan Vos Date: Thu, 12 Mar 2026 20:26:04 +0100 Subject: [PATCH 05/13] every third pixel --- src/dmdreader.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/dmdreader.cpp b/src/dmdreader.cpp index 5fd573a..276b249 100644 --- a/src/dmdreader.cpp +++ b/src/dmdreader.cpp @@ -651,7 +651,7 @@ void dmd_dma_handler() { // 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 && - (px & 1) == 0) { + (px & 2) == 0) { digitalWrite(LED_BUILTIN, HIGH); uint8_t value = pixval & 0x0F; if (value == 2 && (planebuf[px] & 0x0F) != 1 && From 33876f0f840f1e61694f11291e88eeddd539b2f9 Mon Sep 17 00:00:00 2001 From: Jan Vos Date: Thu, 12 Mar 2026 20:33:41 +0100 Subject: [PATCH 06/13] skip more pixels --- src/dmdreader.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/dmdreader.cpp b/src/dmdreader.cpp index 276b249..fa557fa 100644 --- a/src/dmdreader.cpp +++ b/src/dmdreader.cpp @@ -651,7 +651,7 @@ void dmd_dma_handler() { // 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 && - (px & 2) == 0) { + (px & 3) == 0) { digitalWrite(LED_BUILTIN, HIGH); uint8_t value = pixval & 0x0F; if (value == 2 && (planebuf[px] & 0x0F) != 1 && From 8b200b3b7486d4596cfc583a58810a10ca5ea621 Mon Sep 17 00:00:00 2001 From: Jan Vos Date: Thu, 12 Mar 2026 20:48:58 +0100 Subject: [PATCH 07/13] The algorithm is too heavy for Capcom HD. --- src/dmdreader.cpp | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/src/dmdreader.cpp b/src/dmdreader.cpp index fa557fa..6e4a5ed 100644 --- a/src/dmdreader.cpp +++ b/src/dmdreader.cpp @@ -650,8 +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 && - (px & 3) == 0) { + 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 && @@ -725,7 +724,7 @@ void dmd_dma_handler() { } } - if (dmd_type >= DMD_CAPCOM && !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; } From 916d329e470cc4c7263eaccf0066497904b0a0a6 Mon Sep 17 00:00:00 2001 From: Jan Vos Date: Thu, 12 Mar 2026 21:02:21 +0100 Subject: [PATCH 08/13] spike check --- src/dmd_interface.h | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/src/dmd_interface.h b/src/dmd_interface.h index ef35eef..5fd7904 100644 --- a/src/dmd_interface.h +++ b/src/dmd_interface.h @@ -91,8 +91,13 @@ void dmd_framedetect_program_init(PIO pio, uint sm, uint offset, false, // no autopush 0); + // Derive divider from current clock so PIO runs at ~125 MHz reference + 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 divider = (float)sys_hz / target_hz; // scales automatically + sm_config_set_clkdiv(&c, divider); // 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_interface_125mhz_clk_divider); // Load our configuration, do not yet start the program pio_sm_init(pio, sm, offset, &c); From 2f39cb8869fbe4d815f16f5bd12695459e7c5c00 Mon Sep 17 00:00:00 2001 From: Jan Vos Date: Thu, 12 Mar 2026 21:30:06 +0100 Subject: [PATCH 09/13] correctly set and parse dmd_clkdiv --- src/dmd_interface.h | 17 ++++------------- src/dmdreader.cpp | 12 +++++++++--- 2 files changed, 13 insertions(+), 16 deletions(-) diff --git a/src/dmd_interface.h b/src/dmd_interface.h index 5fd7904..67ce0bb 100644 --- a/src/dmd_interface.h +++ b/src/dmd_interface.h @@ -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); @@ -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); @@ -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) { @@ -91,13 +87,8 @@ void dmd_framedetect_program_init(PIO pio, uint sm, uint offset, false, // no autopush 0); - // Derive divider from current clock so PIO runs at ~125 MHz reference - 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 divider = (float)sys_hz / target_hz; // scales automatically - sm_config_set_clkdiv(&c, divider); // 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); diff --git a/src/dmdreader.cpp b/src/dmdreader.cpp index 6e4a5ed..2874bc8 100644 --- a/src/dmdreader.cpp +++ b/src/dmdreader.cpp @@ -865,11 +865,16 @@ 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 @@ -877,8 +882,9 @@ void dmdreader_programs_init(const pio_program_t *dmd_reader_program, 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); } From fbe6697fca3f3bdc274a388e83e62535d68a3962 Mon Sep 17 00:00:00 2001 From: Jan Vos Date: Thu, 12 Mar 2026 21:40:07 +0100 Subject: [PATCH 10/13] revert sega to previous values because 125MHz clkdiv was set incorrectly --- src/dmd_interface_desega.pio | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/dmd_interface_desega.pio b/src/dmd_interface_desega.pio index 062ff81..f35b5de 100644 --- a/src/dmd_interface_desega.pio +++ b/src/dmd_interface_desega.pio @@ -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 From a1de57bb21ae3804e7b420e8c2eb9481a9560ffb Mon Sep 17 00:00:00 2001 From: Jan Vos Date: Thu, 12 Mar 2026 22:25:10 +0100 Subject: [PATCH 11/13] hook good now? --- src/dmdreader.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/dmdreader.cpp b/src/dmdreader.cpp index 2874bc8..351622a 100644 --- a/src/dmdreader.cpp +++ b/src/dmdreader.cpp @@ -1038,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 3096 directly to TX fifo + 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 2000 directly to TX fifo + pio_sm_put(frame_pio, frame_sm, 2000); // pull 32 bits from the TX fifo into osr pio_sm_exec(frame_pio, frame_sm, pio_encode_pull(false, false)); From 1a63e5bfbddd088094a196373c9507065c125cd3 Mon Sep 17 00:00:00 2001 From: Jan Vos Date: Thu, 12 Mar 2026 23:04:54 +0100 Subject: [PATCH 12/13] typo --- src/dmdreader.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/dmdreader.cpp b/src/dmdreader.cpp index 351622a..55ce287 100644 --- a/src/dmdreader.cpp +++ b/src/dmdreader.cpp @@ -1038,7 +1038,7 @@ 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 3096 directly to TX fifo + // load 4096 directly to TX fifo 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)); From 046c68d09be704c5ab3e772f0bdcee89828250cc Mon Sep 17 00:00:00 2001 From: Jan Vos Date: Fri, 13 Mar 2026 16:06:08 +0100 Subject: [PATCH 13/13] hook specific change, faster detection? --- src/dmd_interface_de_x16_v2.pio | 4 ++-- src/dmdreader.cpp | 6 +++--- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/src/dmd_interface_de_x16_v2.pio b/src/dmd_interface_de_x16_v2.pio index 86f80cc..6a7e394 100644 --- a/src/dmd_interface_de_x16_v2.pio +++ b/src/dmd_interface_de_x16_v2.pio @@ -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) @@ -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 diff --git a/src/dmdreader.cpp b/src/dmdreader.cpp index 55ce287..3399380 100644 --- a/src/dmdreader.cpp +++ b/src/dmdreader.cpp @@ -1038,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 4096 directly to TX fifo + // 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 2000 directly to TX fifo - pio_sm_put(frame_pio, frame_sm, 2000); + // 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));