Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
55 changes: 17 additions & 38 deletions src/dmd_interface_desega.pio
Original file line number Diff line number Diff line change
Expand Up @@ -4,66 +4,47 @@
.define COLLAT 4
.define DOTCLK 3
.define SDATA 2
.define FRAME_START 4


.program dmd_reader_desega

; Send using an external clock on the SPI interface

; initialize y with 4096 = number of pixels (128x32)
set x, 1
in x, 1
in null, 13
mov y, isr
; initialize y with 8191, number of pixels ((128 x LSB + 128 x MSB) x 32) - 1 because counting starts at 0.
set x, 31 ; x = 31 (max 5-bit value)
in x, 5 ; shift in 5 bits, isr = 31
set x, 31 ; x = 31
in x, 5 ; shift in 5 bits, isr = 1023
set x, 15 ; x = 15
in x, 3 ; shift in 3 bits, isr = 8191
in null, 3 ; pad with 3 zeros
mov y, isr ; y = 8191

.wrap_target

mov x, y ; load number of pixels
mov isr, null ; reset shift counter

irq clear 4
wait irq 4
irq clear FRAME_START
wait irq FRAME_START


; this is the loop for the most significant bit
dotloop1:
dotloop:
wait 0 gpio DOTCLK ; falling edge
wait 1 gpio DOTCLK ; raising edge
in pins 1 ; read pin data
in null 1 ; right padding
jmp x-- dotloop1

mov x, y ; load number of pixels
mov isr, null ; reset shift counter

; There's an empty line between LSB and HSB plane
wait 0 gpio RCLK
wait 1 gpio RCLK

; this is the loop for the least significant bit
; in this loop, the bit value is multipled by 2 by shifting it one bit
dotloop2:
wait 0 gpio DOTCLK ; falling edge
wait 1 gpio DOTCLK ; raising edge
in null 1 ; left padding
wait 1 gpio DOTCLK ; raising edge
in pins 1 ; read pin data
jmp x-- dotloop2

jmp x-- dotloop

.wrap


.program dmd_framedetect_desega

.wrap_target

; Data East/Sega frame start detection
; ~7.86µs is the longest state in which DE can be low without it being a new frame
; Each nop [31] = 32 cycles = 256 ns @125 MHz
; We go with 10 µs to be safe and confirm the start of a new frame, which is 256ns * 39 = 9.98 µs

wait_low:
wait 0 gpio DE ; Wait for DE to go low

set x, 20 ; Use x as storage for 20 iterations

delay_loop:
Expand All @@ -73,7 +54,7 @@ delay_loop:

; After ~10 µs, check if still low
jmp pin, wait_low ; If pin went high early → back to wait_low
irq 4 ; Pin remained low long enough → trigger IRQ
irq FRAME_START ; Pin remained low long enough → frame started

wait 1 gpio DE ; Wait again for it to go high before restarting cycle
jmp wait_low ; went high, time to go back to wait_low
Expand All @@ -89,11 +70,9 @@ static inline void dmd_reader_desega_program_init(PIO pio, uint sm, uint offset)
sm_config_set_in_pins(&c, 2); // SDATA

// Set the pin direction at the PIO
pio_sm_set_consecutive_pindirs(pio, sm, 5, 1, false); // RCLK
pio_sm_set_consecutive_pindirs(pio, sm, 2, 2, false); // SDATA, DOTCLK

// Connect these GPIOs to this PIO block
pio_gpio_init(pio, 5); // RCLK
pio_gpio_init(pio, 3); // DOTCLK
pio_gpio_init(pio, 2); // SDATA

Expand Down
13 changes: 7 additions & 6 deletions src/dmd_reader.c
Original file line number Diff line number Diff line change
Expand Up @@ -376,8 +376,8 @@ int detect_dmd() {
spi_notify_onoff(DMD_SAM);
return DMD_SAM;

} else if ((dotclk > 640000) && (dotclk < 700000) && (de > 5000) &&
(de < 5300) && (rdata > 3800) && (rdata < 4000)) {
} else if ((dotclk > 600000) && (dotclk < 680000) && (de > 4800) &&
(de < 5200) && (rdata > 2500) && (rdata < 2650)) {
printf("Data East/Sega detected\n");
spi_notify_onoff(DMD_DESEGA);
return DMD_DESEGA;
Expand Down Expand Up @@ -650,12 +650,13 @@ bool init() {

lcd_width = 128;
lcd_height = 32;
lcd_bitsperpixel = 2; // Data East/ Sega is 2bpp
lcd_bitsperpixel = 2; // DE-Sega is 2bpp
lcd_pixelsperbyte = 8 / lcd_bitsperpixel;
lcd_planesperframe = 2; // in DE/Sega, there's a MSB and a LSB plane
lcd_planesperframe = 1; // in DE-Sega, there's only one plane, containg
// one LSB row followed by one MSB row and so on
lcd_lineoversampling =
LINEOVERSAMPLING_2X; // in DE/Sega each line is sent twice
lcd_mergeplanes = MERGEPLANES_ADDSHIFT; // required for correct 2bpp merge
LINEOVERSAMPLING_2X; // in DE-Sega each line is sent twice
lcd_mergeplanes = MERGEPLANES_NONE; // required for correct 2bpp merge
} else {
printf("Unknown DMD type, aborting\n");
return false;
Expand Down