Skip to content
Merged
Show file tree
Hide file tree
Changes from 9 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
Copy Markdown
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
Copy Markdown
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
Copy Markdown
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);
}
%}
6 changes: 3 additions & 3 deletions src/dmd_interface_whitestar.pio
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@
dotloop1:
wait 0 gpio DOTCLK ; falling edge
wait 1 gpio DOTCLK ; raising edge
in null 2 ; padding
;in null 2 ; padding

Copy link
Copy Markdown
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
Copy Markdown
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
Expand All @@ -46,7 +46,7 @@ dotloop1:
dotloop2:
wait 0 gpio DOTCLK ; falling edge
wait 1 gpio DOTCLK ; raising edge
in null 3 ; padding
in null 1 ; padding

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

comment "left padding"

in pins 1 ; read pin data
;in null 1 ; multiply *2
jmp x-- dotloop2
Expand Down Expand Up @@ -111,4 +111,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; // it's only 3, but padding to 4 makes things easier
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
Copy Markdown
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_whitestar_program_init(dmd_pio, dmd_sm, offset);

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

dmd_reader_desega_program_init

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_whitestar_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 = 4; // data east sega is 2bpp

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

must be 2

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