diff --git a/src/dmd_interface_desega.pio b/src/dmd_interface_desega.pio index f9fb416..0a8d797 100644 --- a/src/dmd_interface_desega.pio +++ b/src/dmd_interface_desega.pio @@ -5,65 +5,51 @@ .define DOTCLK 3 .define SDATA 2 +.define FRAME_START_IRQ 4 -.program dmd_reader_desega +.define PUBLIC desega_DE DE +.define PUBLIC desega_RDATA RDATA +.define PUBLIC desega_DOTCLK DOTCLK +.define PUBLIC desega_SDATA SDATA -; 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 +.program dmd_reader_desega + ; 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 + 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_IRQ + wait irq FRAME_START_IRQ - -; 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: @@ -73,7 +59,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_IRQ ; 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 @@ -86,16 +72,14 @@ 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 + sm_config_set_in_pins(&c, desega_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 + pio_sm_set_consecutive_pindirs(pio, sm, desega_SDATA, 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 + pio_gpio_init(pio, desega_DOTCLK); + pio_gpio_init(pio, desega_SDATA); // Shifting to left matches the customary MSB-first ordering of SPI. sm_config_set_in_shift( @@ -118,10 +102,10 @@ static inline void dmd_framedetect_desega_program_init(PIO pio, uint sm, uint of 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 + pio_sm_set_consecutive_pindirs(pio, sm, desega_DE, 1, false); // Connect this GPIO to this PIO block - pio_gpio_init(pio, 7); // DE + pio_gpio_init(pio, desega_DE); // Load our configuration, do not yet start the program pio_sm_init(pio, sm, offset, &c); diff --git a/src/dmd_interface_sam.pio b/src/dmd_interface_sam.pio index aabd27b..2e820ef 100644 --- a/src/dmd_interface_sam.pio +++ b/src/dmd_interface_sam.pio @@ -5,46 +5,44 @@ .define DOTCLK 3 .define SDATA 2 +.define FRAME_START_IRQ 4 -.program dmd_reader_sam - -; Send using an external clock on the SPI interface -; - IN pin 0 is the DATA pin +.define PUBLIC sam_RCLK RCLK +.define PUBLIC sam_RDATA RDATA +.define PUBLIC sam_DOTCLK DOTCLK +.define PUBLIC sam_SDATA SDATA - ; initialize y with 16348 = number of pixels (128x32x4) - set x, 1 - in x, 1 - in null, 15 - mov y, isr +.program dmd_reader_sam + ; 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 ; reset shift counter - irq clear 4 - wait irq 4 + irq clear FRAME_START_IRQ + wait irq FRAME_START_IRQ dotloop: wait 0 gpio DOTCLK ; falling edge - in null, 3 ; pad with 3 zeros + in null, 3 ; left padding with 3 zeros wait 1 gpio DOTCLK ; raising edge in pins 1 ; read pin data - - jmp x-- dotloop - .wrap -.program dmd_framedetect_sam +.program dmd_framedetect_sam .wrap_target - -; synchronize on the least significant plane wait 0 gpio RDATA wait 1 gpio RDATA - irq 4 - + irq FRAME_START_IRQ .wrap @@ -53,14 +51,14 @@ static inline void dmd_reader_sam_program_init(PIO pio, uint sm, uint offset) { pio_sm_config c = dmd_reader_sam_program_get_default_config(offset); // Set the IN pin, we don't use any other - sm_config_set_in_pins(&c, 2); // SDATA - - // Connect these GPIOs to this PIO block - pio_gpio_init(pio, 3); // DOTCLK - pio_gpio_init(pio, 2); // SDATA + sm_config_set_in_pins(&c, sam_SDATA); // Set the pin direction at the PIO - pio_sm_set_consecutive_pindirs(pio, sm, 2, 2, false); // SDATA, DOTCLK + pio_sm_set_consecutive_pindirs(pio, sm, sam_SDATA, 2, false); // SDATA, DOTCLK + + // Connect these GPIOs to this PIO block + pio_gpio_init(pio, sam_DOTCLK); + pio_gpio_init(pio, sam_SDATA); // Shifting to left matches the customary MSB-first ordering of SPI. sm_config_set_in_shift( @@ -83,10 +81,10 @@ static inline void dmd_framedetect_sam_program_init(PIO pio, uint sm, uint offse pio_sm_config c = dmd_framedetect_sam_program_get_default_config(offset); // Set the pin direction at the PIO - pio_sm_set_consecutive_pindirs(pio, sm, 6, 1, false); // RDATA + pio_sm_set_consecutive_pindirs(pio, sm, sam_RDATA, 1, false); // Connect these GPIOs to this PIO block - pio_gpio_init(pio, 6); // RDATA + pio_gpio_init(pio, sam_RDATA); // Load our configuration, do not yet start the program pio_sm_init(pio, sm, offset, &c); diff --git a/src/dmd_interface_spike.pio b/src/dmd_interface_spike.pio index ed80750..5fc6478 100644 --- a/src/dmd_interface_spike.pio +++ b/src/dmd_interface_spike.pio @@ -5,8 +5,12 @@ .define DOTCLK 3 .define SDATA 2 +.define PLANE_START_IRQ 4 -.define PUBLIC spike_rdata RDATA +.define PUBLIC spike_RCLK RCLK +.define PUBLIC spike_RDATA RDATA +.define PUBLIC spike_DOTCLK DOTCLK +.define PUBLIC spike_SDATA SDATA .program dmd_reader_spike @@ -22,8 +26,8 @@ mov x, y ; load number of pixels mov isr, null ; reset shift counter - irq clear 4 - wait irq 4 + irq clear PLANE_START_IRQ + wait irq PLANE_START_IRQ ; this is the loop for the most significant bit dotloop1: @@ -77,7 +81,7 @@ lineloop: wait 0 gpio RCLK jmp x-- lineloop - irq 4 + irq PLANE_START_IRQ .wrap @@ -86,14 +90,13 @@ static inline void dmd_reader_spike_program_init(PIO pio, uint sm, uint offset) pio_sm_config c = dmd_reader_spike_program_get_default_config(offset); // Set the IN base pin to the provided `pin` parameter. This is the data pin, we don't use any other - sm_config_set_in_pins(&c, 2); // SDATA - + sm_config_set_in_pins(&c, spike_SDATA); // Set the pin direction at the PIO - pio_sm_set_consecutive_pindirs(pio, sm, 2, 2, false); // SDATA, DOTCLK + pio_sm_set_consecutive_pindirs(pio, sm, spike_SDATA, 2, false); // SDATA, DOTCLK // Connect these GPIOs to this PIO block - pio_gpio_init(pio, 3); // DOTCLK - pio_gpio_init(pio, 2); // SDATA + pio_gpio_init(pio, spike_DOTCLK); + pio_gpio_init(pio, spike_SDATA); // Shifting to left matches the customary MSB-first ordering of SPI. sm_config_set_in_shift( @@ -114,8 +117,8 @@ static inline void dmd_reader_spike_program_init(PIO pio, uint sm, uint offset) % c-sdk { static inline void dmd_framedetect_spike_program_init(PIO pio, uint sm, uint offset) { pio_sm_config c = dmd_framedetect_spike_program_get_default_config(offset); - // rdata is used for jump control - sm_config_set_jmp_pin(&c, spike_rdata); + // RDATA is used for jump control + sm_config_set_jmp_pin(&c, spike_RDATA); // Shifting to left matches the customary MSB-first ordering of SPI. sm_config_set_in_shift( @@ -126,11 +129,11 @@ static inline void dmd_framedetect_spike_program_init(PIO pio, uint sm, uint off ); // Set the pin direction at the PIO - pio_sm_set_consecutive_pindirs(pio, sm, 5, 2, false); // RCLK, RDATA + pio_sm_set_consecutive_pindirs(pio, sm, spike_RCLK, 2, false); // RCLK, RDATA // Connect these GPIOs to this PIO block - pio_gpio_init(pio, 6); // RDATA - pio_gpio_init(pio, 5); // RCLK + pio_gpio_init(pio, spike_RDATA); + pio_gpio_init(pio, spike_RCLK); // Load our configuration, do not yet start the program pio_sm_init(pio, sm, offset, &c); diff --git a/src/dmd_interface_whitestar.pio b/src/dmd_interface_whitestar.pio index 6425afd..ff45ba9 100644 --- a/src/dmd_interface_whitestar.pio +++ b/src/dmd_interface_whitestar.pio @@ -5,25 +5,28 @@ .define DOTCLK 3 .define SDATA 2 +.define FRAME_START_IRQ 4 -.program dmd_reader_whitestar - +.define PUBLIC whitestar_RDATA RDATA +.define PUBLIC whitestar_DOTCLK DOTCLK +.define PUBLIC whitestar_SDATA SDATA - ; initialize y with 8192 = number of pixels ((128 x LSB + 128 x MSB) x 32) - set x, 1 - in x, 1 - in null, 13 - mov y, isr +.program dmd_reader_whitestar + ; 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 + 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 - - wait 1 gpio RDATA ; raising edge indicates a new frame + irq clear FRAME_START_IRQ + wait irq FRAME_START_IRQ dotloop: wait 0 gpio DOTCLK ; falling edge @@ -36,15 +39,12 @@ dotloop: ; It is ignored because we already read the specified amount of dots and now wait for a new frame. .wrap -.program dmd_framedetect_whitestar +.program dmd_framedetect_whitestar .wrap_target - -; synchronize on a new frame wait 0 gpio RDATA wait 1 gpio RDATA - irq 4 - + irq FRAME_START_IRQ .wrap @@ -53,16 +53,14 @@ static inline void dmd_reader_whitestar_program_init(PIO pio, uint sm, uint offs pio_sm_config c = dmd_reader_whitestar_program_get_default_config(offset); // Set the IN pin, we don't use any other - sm_config_set_in_pins(&c, 2); // SDATA + sm_config_set_in_pins(&c, whitestar_SDATA); // Set the pin direction at the PIO - pio_sm_set_consecutive_pindirs(pio, sm, 6, 1, false); // RDATA - pio_sm_set_consecutive_pindirs(pio, sm, 2, 2, false); // SDATA, DOTCLK + pio_sm_set_consecutive_pindirs(pio, sm, whitestar_SDATA, 2, false); // SDATA, DOTCLK // Connect these GPIOs to this PIO block - pio_gpio_init(pio, 6); // RDATA - pio_gpio_init(pio, 3); // DOTCLK - pio_gpio_init(pio, 2); // SDATA + pio_gpio_init(pio, whitestar_DOTCLK); + pio_gpio_init(pio, whitestar_SDATA); // Shifting to left matches the customary MSB-first ordering of SPI. sm_config_set_in_shift( @@ -85,12 +83,12 @@ static inline void dmd_framedetect_whitestar_program_init(PIO pio, uint sm, uint pio_sm_config c = dmd_framedetect_whitestar_program_get_default_config(offset); // Set the pin direction at the PIO - pio_sm_set_consecutive_pindirs(pio, sm, 6, 1, false); // RDATA + pio_sm_set_consecutive_pindirs(pio, sm, whitestar_RDATA, 1, false); // Connect these GPIOs to this PIO block - pio_gpio_init(pio, 6); // RDATA + pio_gpio_init(pio, whitestar_RDATA); // Load our configuration, do not yet start the program pio_sm_init(pio, sm, offset, &c); } -%} \ No newline at end of file +%} diff --git a/src/dmd_interface_wpc.pio b/src/dmd_interface_wpc.pio index d229995..e089ebc 100644 --- a/src/dmd_interface_wpc.pio +++ b/src/dmd_interface_wpc.pio @@ -1,12 +1,16 @@ -.define PUBLIC dmd_reader_interrupt 0 .define DE 7 .define RDATA 6 .define RCLK 5 .define COLLAT 4 .define DOTCLK 3 .define SDATA 2 -.define PLANE_START 4 +.define PLANE_START_IRQ 4 + +.define PUBLIC wpc_DE DE +.define PUBLIC wpc_RDATA RDATA +.define PUBLIC wpc_DOTCLK DOTCLK +.define PUBLIC wpc_SDATA SDATA .program dmd_reader_wpc set x, 31 ; load 31, 5 bits is max allowed (0b11111) @@ -21,12 +25,12 @@ mov x, y ; load number of pixels per plane (128x32 - 1) mov isr, null ; reset shift counter - irq clear PLANE_START - wait irq PLANE_START + irq clear PLANE_START_IRQ + wait irq PLANE_START_IRQ plane_loop: wait 0 gpio DOTCLK ; no DOTCLK period or faling edge of the previous - in null 1 ; add a 0 to the output as WPC is 2bit/px + 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-- plane_loop @@ -40,22 +44,23 @@ plane_loop: wait 1 gpio DE wait 0 gpio DOTCLK nop [31] - irq PLANE_START + irq PLANE_START_IRQ .wrap + % c-sdk { static inline void dmd_reader_wpc_program_init(PIO pio, uint sm, uint offset) { pio_sm_config c = dmd_reader_wpc_program_get_default_config(offset); // Set the IN pin, we don't use any other - sm_config_set_in_pins(&c, 2); // SDATA + sm_config_set_in_pins(&c, wpc_SDATA); // Connect these GPIOs to this PIO block - pio_gpio_init(pio, 3); // DOTCLK - pio_gpio_init(pio, 2); // SDATA + pio_gpio_init(pio, wpc_DOTCLK); + pio_gpio_init(pio, wpc_SDATA); // Set the pin direction at the PIO - pio_sm_set_consecutive_pindirs(pio, sm, 2, 2, false); // SDATA, DOTCLK + pio_sm_set_consecutive_pindirs(pio, sm, wpc_SDATA, 2, false); // SDATA, DOTCLK // Shifting to left matches the customary MSB-first ordering of SPI. sm_config_set_in_shift( @@ -78,13 +83,13 @@ static inline void dmd_framedetect_wpc_program_init(PIO pio, uint sm, uint offse pio_sm_config c = dmd_framedetect_wpc_program_get_default_config(offset); // Connect these GPIOs to this PIO block - pio_gpio_init(pio, 7); // DE - pio_gpio_init(pio, 6); // RDATA - pio_gpio_init(pio, 3); // DOTCLK + pio_gpio_init(pio, wpc_DE); + pio_gpio_init(pio, wpc_RDATA); + pio_gpio_init(pio, wpc_DOTCLK); // Set the pin direction at the PIO - pio_sm_set_consecutive_pindirs(pio, sm, 6, 2, false); // RDATA, DE - pio_sm_set_consecutive_pindirs(pio, sm, 3, 1, false); // DOTCLK + pio_sm_set_consecutive_pindirs(pio, sm, wpc_RDATA, 2, false); // RDATA, DE + pio_sm_set_consecutive_pindirs(pio, sm, wpc_DOTCLK, 1, false); // Load our configuration, do not yet start the program pio_sm_init(pio, sm, offset, &c); diff --git a/src/dmd_reader.c b/src/dmd_reader.c index c66b09b..b196506 100644 --- a/src/dmd_reader.c +++ b/src/dmd_reader.c @@ -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; @@ -650,12 +650,13 @@ bool init() { lcd_width = 128; lcd_height = 32; - lcd_bitsperpixel = 2; // Data East/ Sega is 2bpp + lcd_bitsperpixel = 2; // Data East and Sega are 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;