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
1 change: 1 addition & 0 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@ pico_generate_pio_header(${PROJECT_NAME} src/dmd_interface_wpc.pio)
pico_generate_pio_header(${PROJECT_NAME} src/dmd_interface_whitestar.pio)
pico_generate_pio_header(${PROJECT_NAME} src/dmd_interface_spike.pio)
pico_generate_pio_header(${PROJECT_NAME} src/dmd_interface_sam.pio)
pico_generate_pio_header(${PROJECT_NAME} src/dmd_interface_desega.pio)

# Add the standard library to the build
target_link_libraries(${PROJECT_NAME} pico_stdlib)
Expand Down
130 changes: 130 additions & 0 deletions src/dmd_interface_desega.pio
Original file line number Diff line number Diff line change
@@ -0,0 +1,130 @@
.define DE 7
.define RDATA 6
.define RCLK 5
.define COLLAT 4
.define DOTCLK 3
.define SDATA 2


.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

.wrap_target

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

irq clear 4
wait irq 4


; this is the loop for the most significant bit
dotloop1:
wait 0 gpio DOTCLK ; falling edge
wait 1 gpio DOTCLK ; raising edge
in null 2 ; padding
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

remove this line

in pins 1 ; read pin data
in null 1
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

comment "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 3 ; padding
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

in null 1. ; left padding

in pins 1 ; read pin data
jmp x-- dotloop2


.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:
nop [31]
nop [31]
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
irq 4 ; Pin remained low long enough → trigger IRQ

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

.wrap


% c-sdk {
static inline void dmd_reader_desega_program_init(PIO pio, uint sm, uint offset) {
pio_sm_config c = dmd_reader_desega_program_get_default_config(offset);

// Set the IN pin, we don't use any other
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

// Shifting to left matches the customary MSB-first ordering of SPI.
sm_config_set_in_shift(
&c,
false, // Shift-to-right = false
true, // Autopull enabled
32 // Autopull threshold
);

// We only send, so disable the TX FIFO to make the RX FIFO deeper.
sm_config_set_fifo_join(&c, PIO_FIFO_JOIN_RX);

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

% c-sdk {
static inline void dmd_framedetect_desega_program_init(PIO pio, uint sm, uint offset) {
pio_sm_config c = dmd_framedetect_desega_program_get_default_config(offset);

// Set the pin direction at the PIO
pio_sm_set_consecutive_pindirs(pio, sm, 7, 1, false); // DE

// Connect this GPIO to this PIO block
pio_gpio_init(pio, 7); // DE

// Load our configuration, do not yet start the program
pio_sm_init(pio, sm, offset, &c);
}
%}
2 changes: 1 addition & 1 deletion src/dmd_interface_whitestar.pio
Original file line number Diff line number Diff line change
Expand Up @@ -109,4 +109,4 @@ static inline void dmd_framedetect_whitestar_program_init(PIO pio, uint sm, uint
// Load our configuration, do not yet start the program
pio_sm_init(pio, sm, offset, &c);
}
%}
%}
44 changes: 38 additions & 6 deletions src/dmd_reader.c
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
#include "dmd_interface_whitestar.pio.h"
#include "dmd_interface_spike.pio.h"
#include "dmd_interface_sam.pio.h"
#include "dmd_interface_desega.pio.h"

// should CRC32 checksum be caculated and sent with each frame
#define USE_CRC
Expand Down Expand Up @@ -93,6 +94,7 @@ typedef struct __attribute__((__packed__)) block_pix_crc_header_t
#define DMD_WHITESTAR 2
#define DMD_SPIKE1 3
#define DMD_SAM 4
#define DMD_DESEGA 5

// Line oversampling
#define LINEOVERSAMPLING_NONE 1
Expand Down Expand Up @@ -363,30 +365,38 @@ int detect_dmd()

if ((dotclk > 450000) && (dotclk < 550000) &&
(de > 3800) && (de < 4000) &&
(rdata > 115) && (rdata < 130))
{
(rdata > 115) && (rdata < 130)) {
printf("WPC detected\n");
spi_notify_onoff(DMD_WPC);
return DMD_WPC;

} else if ((dotclk > 640000) && (dotclk < 700000) &&
(de > 5000) && (de < 5300) &&
(rdata > 70) && (rdata < 85))
{
(rdata > 70) && (rdata < 85)) {
printf("Stern Whitestar detected\n");
spi_notify_onoff(DMD_WHITESTAR);
return DMD_WHITESTAR;

} else if ((dotclk > 1000000) && (dotclk < 1100000) &&
(de > 8000) && (de < 8400) &&
(rdata > 240) && (rdata < 270)) {
printf("Stern Spike1 detected\n");
spi_notify_onoff(DMD_SPIKE1);
return DMD_SPIKE1;

} else if ((dotclk > 1000000) && (dotclk < 1100000) &&
(de > 8000) && (de < 8400) &&
(rdata > 60) && (rdata < 70)) {
printf("Stern SAM detected\n");
spi_notify_onoff(DMD_SAM);
return DMD_SAM;

} else if ((dotclk > 640000) && (dotclk < 700000) &&
(de > 5000) && (de < 5300) &&
(rdata > 3800) && (rdata < 4000)) {
printf("Data East/Sega detected\n");
spi_notify_onoff(DMD_DESEGA);
return DMD_DESEGA;
}

spi_notify_onoff(1);
Expand Down Expand Up @@ -584,11 +594,11 @@ bool init()

lcd_width = 128;
lcd_height = 32;
lcd_bitsperpixel = 2;
lcd_bitsperpixel = 2; // Whitestar is 2bpp
lcd_pixelsperbyte = 8 / lcd_bitsperpixel;
lcd_planesperframe = 2; // in Whitestar, there's a MSB and a LSB plane
lcd_lineoversampling = LINEOVERSAMPLING_WHITESTAR; // in Whitestar each line is sent twice
lcd_mergeplanes = MERGEPLANES_ADDSHIFT; // required for correct 2bpp merge
//lcd_mergeplanes = MERGEPLANES_ADDSHIFT; // required for correct 2bpp merge
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why is that removed?

} else if (dmd_type == DMD_SPIKE1) {
dmd_pio = pio0;
offset = pio_add_program(dmd_pio, &dmd_reader_spike_program);
Expand Down Expand Up @@ -634,6 +644,28 @@ bool init()
lcd_planesperframe = 1; // in SAM there is one planes
lcd_lineoversampling = LINEOVERSAMPLING_SAM; // with 4x line oversampling
lcd_mergeplanes = MERGEPLANES_ADD;
} else if (dmd_type == DMD_DESEGA) {
dmd_pio = pio0;
offset = pio_add_program(dmd_pio, &dmd_reader_desega_program);
dmd_sm = pio_claim_unused_sm(dmd_pio, true);
dmd_reader_desega_program_init(dmd_pio, dmd_sm, offset);
printf("Data East/Sega DMD reader initialized\n");

// The framedetect program just runs and detects the beginning of a new frame
frame_pio = pio0;
offset = pio_add_program(frame_pio, &dmd_framedetect_desega_program);
frame_sm = pio_claim_unused_sm(frame_pio, true);
dmd_framedetect_desega_program_init(frame_pio, frame_sm, offset);
pio_sm_set_enabled(frame_pio, frame_sm, true);
printf("Data East/Sega frame detection initialized\n");

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