Skip to content
Merged
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ Since not any consumer (especially the Raspberry Pi) can act as an SPI slave thi
* Stern SPIKE 1 -> 128x32
* Capcom -> 128x32
* Gottlieb/Premier -> 128x32
* Alvin G. & Co -> 128x32

## Reading data

Expand Down
1 change: 1 addition & 0 deletions src/dmd_interface.h
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
#include "dmd_interface_sam.pio.h"
#include "dmd_interface_spike.pio.h"
#endif
#include "dmd_interface_alving.pio.h"
#include "dmd_interface_capcom.pio.h"
#include "dmd_interface_capcom_hd.pio.h"
#include "dmd_interface_desega.pio.h"
Expand Down
56 changes: 56 additions & 0 deletions src/dmd_interface_alving.pio
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
.define DE 7
.define RDATA 6
.define RCLK 5
.define COLLAT 4
.define DOTCLK 3
.define SDATA 2
.define FRAME_START_IRQ 5

.program dmd_reader_alving
; initialize y with 16383, number of pixels (128x32x4) - 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, 4 ; shift in 4 bits, isr = 16383
mov y, isr ; y = 16383

.wrap_target
mov x, y ; load number of pixels
mov isr, null ; clear ISR and reset shift counter

irq clear FRAME_START_IRQ
wait irq FRAME_START_IRQ

dotloop:
wait 0 gpio DOTCLK ; falling edge
in null, 3 ; left padding with 3 zeros
wait 1 gpio DOTCLK ; raising edge
in pins 1 ; read pin data
jmp x-- dotloop
.wrap

; Frame detection program runs in parallel to the reader program and signals the start of a new frame using an IRQ.
.program dmd_framedetect_alving
wait 0 gpio RDATA
wait 1 gpio RDATA
; When RDATA turned HIGH, we already missed the start of the first row, so we skip 32 end of rows before sending the first IRQ.
; Alvin G needs to skip 3 COLLAT edges right after for a correct starting point.
.wrap_target
set x, 31 ; 32 rows
set y, 2 ; 3 COLLAT edges

rclk_loop:
wait 0 gpio RCLK
wait 1 gpio RCLK
jmp x-- rclk_loop

collat_loop:
wait 0 gpio COLLAT
wait 1 gpio COLLAT
jmp y-- collat_loop

irq FRAME_START_IRQ
.wrap

62 changes: 51 additions & 11 deletions src/dmdreader.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,7 @@ enum DmdType {
DMD_DESEGA,
DMD_SEGA_HD,
DMD_GOTTLIEB,
DMD_ALVING,
// CAPCOM need to be the last entries:
DMD_CAPCOM,
DMD_CAPCOM_HD,
Expand Down Expand Up @@ -375,6 +376,11 @@ DmdType detect_dmd() {
(de < 13100) && (rdata > 370) && (rdata < 410)) {
return DMD_GOTTLIEB;

// Alvin G -> DOTCLK: 1192000 | DE: 9400 | RDATA: 73
} else if ((dotclk > 1150000) && (dotclk < 1250000) && (de > 9200) &&
(de < 9600) && (rdata > 65) && (rdata < 80)) {
return DMD_ALVING;

// Capcom -> DOTCLK: 4168000 | DE: 16280 | RDATA: 510
} else if ((dotclk > 4000000) && (dotclk < 4300000) && (de > 16000) &&
(de < 16500) && (rdata > 490) && (rdata < 530)) {
Expand Down Expand Up @@ -628,17 +634,32 @@ void dmd_dma_handler() {
src4 = src3 + source_dwordsperline;
uint32_t v;

for (int l = 0; l < source_height; l++) {
for (int w = 0; w < source_dwordsperline; w++) {
// On SAM line order is really messed up :-(
v = src4[w] * 8 + src3[w] * 1 + src2[w] * 4 + src1[w] * 2;
dst[w] = v;
if (dmd_type == DMD_SAM) {
for (int l = 0; l < source_height; l++) {
for (int w = 0; w < source_dwordsperline; w++) {
// On SAM line order is really messed up :-(
v = src4[w] * 8 + src3[w] * 1 + src2[w] * 4 + src1[w] * 2;
dst[w] = v;
}
src1 += source_dwordsperline * 4; // source skips 4 lines forward
src2 += source_dwordsperline * 4;
src3 += source_dwordsperline * 4;
src4 += source_dwordsperline * 4;
dst += source_dwordsperline; // destination skips only one line
}
} else { // Alvin G
for (int l = 0; l < source_height; l++) {
for (int w = 0; w < source_dwordsperline; w++) {
// First row captured counts as intensity level 3 <--
v = src4[w] * 4 + src3[w] * 4 + src2[w] * 4 + src1[w] * 3;
dst[w] = v;
}
src1 += source_dwordsperline * 4; // source skips 4 lines forward
src2 += source_dwordsperline * 4;
src3 += source_dwordsperline * 4;
src4 += source_dwordsperline * 4;
dst += source_dwordsperline; // destination skips only one line
}
src1 += source_dwordsperline * 4; // source skips 4 lines forward
src2 += source_dwordsperline * 4;
src3 += source_dwordsperline * 4;
src4 += source_dwordsperline * 4;
dst += source_dwordsperline; // destination skips only one line
}
}
}
Expand Down Expand Up @@ -849,13 +870,32 @@ void dmdreader_init() {
break;
}

case DMD_ALVING: {
uint input_pins[] = {RDATA, RCLK, COLLAT};
dmdreader_programs_init(
&dmd_reader_alving_program,
dmd_reader_alving_program_get_default_config,
&dmd_framedetect_alving_program,
dmd_framedetect_alving_program_get_default_config, input_pins, 2, 0);

source_width = 128;
source_height = 32;
source_bitsperpixel = 4;
target_bitsperpixel = 4;
source_planesperframe = 1; // in Alvin G there is one plane
// with 4x line oversampling
source_lineoversampling = LINEOVERSAMPLING_4X;
source_mergeplanes = MERGEPLANES_NONE;
break;
}

case DMD_CAPCOM: {
uint input_pins[] = {RDATA, RCLK};
dmdreader_programs_init(&dmd_reader_capcom_program,
dmd_reader_capcom_program_get_default_config,
&dmd_framedetect_capcom_program,
dmd_framedetect_capcom_program_get_default_config,
input_pins, 2, 0);
input_pins, 3, 0);

source_width = 128;
source_height = 32;
Expand Down
Loading