diff --git a/src/dmd_interface.h b/src/dmd_interface.h index cbd18cb..5d22633 100644 --- a/src/dmd_interface.h +++ b/src/dmd_interface.h @@ -11,6 +11,7 @@ #include "dmd_interface_desega.pio.h" #include "dmd_interface_whitestar.pio.h" #include "dmd_interface_wpc.pio.h" +#include "dmd_interface_capcom.pio.h" #include "dmdreader_pins.h" #include "hardware/gpio.h" #include "hardware/pio.h" diff --git a/src/dmd_interface_capcom.pio b/src/dmd_interface_capcom.pio new file mode 100644 index 0000000..71a1a9d --- /dev/null +++ b/src/dmd_interface_capcom.pio @@ -0,0 +1,47 @@ +.define DE 7 +.define RDATA 6 +.define RCLK 5 +.define COLLAT 4 +.define DOTCLK 3 +.define SDATA 2 +.define PLANE_START_IRQ 4 + +.program dmd_reader_capcom + set x, 31 ; load 31, 5 bits is max allowed (0b11111) + in x, 5 ; shift in 5 bits, isr is 31 now + set x, 3 ; load 3 + in x, 2 ; shift in 2 bits, isr is 127 now + mov osr, isr ; copy 127 to OSR + mov isr, null ; reset shift counter + +.wrap_target + set y, 31 ; number of rows + + irq clear PLANE_START_IRQ + wait irq PLANE_START_IRQ + +row_loop: + mov x, osr ; load number of dots to skip (128) +dot_skip_loop: + wait 0 gpio DOTCLK ; no DOTCLK period or faling edge of the previous + wait 1 gpio DOTCLK + jmp x-- dot_skip_loop ; skip 128 dots + + mov x, osr ; load number of pixels to read (128) +dot_read_loop: + wait 0 gpio DOTCLK ; no DOTCLK period or faling edge of the previous + in null 1 ; left padding a 0 to the output as WPC is 2bit/px + wait 1 gpio DOTCLK ; raising edge + in pins 1 ; read 1 bit pin data + jmp x-- dot_read_loop + jmp y-- row_loop +.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_capcom +.wrap_target + wait 1 gpio RDATA + wait 0 gpio RCLK + irq PLANE_START_IRQ + wait 0 gpio RDATA +.wrap \ No newline at end of file diff --git a/src/dmdreader.cpp b/src/dmdreader.cpp index 840bb27..f868453 100644 --- a/src/dmdreader.cpp +++ b/src/dmdreader.cpp @@ -70,6 +70,7 @@ typedef struct __attribute__((__packed__)) block_pix_crc_header_t { #define DMD_SPIKE1 3 #define DMD_SAM 4 #define DMD_DESEGA 5 +#define DMD_CAPCOM 6 // Line oversampling #define LINEOVERSAMPLING_NONE 1 @@ -327,6 +328,11 @@ int detect_dmd() { } else if ((dotclk > 645000) && (dotclk < 669000) && (de > 5075) && (de < 5200) && (rdata > 75) && (rdata < 85)) { return DMD_WHITESTAR; + + // Capcom -> DOTCLK: 4168000 | DE: 16280 | RDATA: 510 + } else if ((dotclk > 4000000) && (dotclk < 4300000) && (de > 16000) && + (de < 16500) && (rdata > 490) && (rdata < 530)) { + return DMD_CAPCOM; } #endif @@ -649,6 +655,36 @@ void dmdreader_init() { source_mergeplanes = MERGEPLANES_NONE; break; } + + case DMD_CAPCOM: { + dmd_pio = pio0; + offset = pio_add_program(dmd_pio, &dmd_reader_capcom_program); + dmd_sm = pio_claim_unused_sm(dmd_pio, true); + pio_sm_config dmd_config = + dmd_reader_capcom_program_get_default_config(offset); + dmd_reader_program_init(dmd_pio, dmd_sm, offset, dmd_config); + + // The framedetect program just runs and detects the beginning of a new + // frame + uint input_pins[] = {RDATA, RCLK}; + frame_pio = pio0; + offset = pio_add_program(frame_pio, &dmd_framedetect_capcom_program); + frame_sm = pio_claim_unused_sm(frame_pio, true); + pio_sm_config frame_config = + dmd_framedetect_capcom_program_get_default_config(offset); + dmd_framedetect_program_init(frame_pio, frame_sm, offset, frame_config, + input_pins, 2, 0); + pio_sm_set_enabled(frame_pio, frame_sm, true); + + source_width = 128; + source_height = 32; + source_bitsperpixel = 2; + source_pixelsperbyte = 8 / source_bitsperpixel; + source_planesperframe = 4; + source_lineoversampling = LINEOVERSAMPLING_NONE; + source_mergeplanes = MERGEPLANES_ADD; + break; + } } // Calculate display parameters