PIO for DMA

This commit is contained in:
Ian Scott committed 2022-08-19 21:45:49 -06:00
1 parent f601c96384
commit 88164720ab
7 files changed
+93 -41

No files matched your search

Binary file not shown.
+1 -1
View File
@@ -76,7 +76,7 @@ pico_enable_stdio_uart(sw-pico 1)
pico_enable_stdio_usb(sw-pico 0)
pico_enable_stdio_semihosting(sw-pico 0)
pico_generate_pio_header(sw-pico ${CMAKE_CURRENT_LIST_DIR}/io.pio)
pico_generate_pio_header(sw-pico ${CMAKE_CURRENT_LIST_DIR}/isa_io.pio)
add_subdirectory(stdio_async_uart)
+6 -6
View File
@@ -2006,12 +2006,12 @@ __force_inline void write_gus(Bitu port,Bitu val,Bitu iolen) {
}
}
#if 0 // TODO implement DMA
static Bitu GUS_Master_Clock = 617400; /* NOTE: This is 1000000Hz / 1.619695497. Seems to be a common base rate within the hardware. */
static Bitu GUS_DMA_Event_transfer = 16; /* DMA words (8 or 16-bit) per interval */
static Bitu GUS_DMA_Events_per_sec = 44100 / 4; /* cheat a little, to improve emulation performance */
static double GUS_DMA_Event_interval = 1000.0 / GUS_DMA_Events_per_sec;
static double GUS_DMA_Event_interval_init = 1000.0 / 44100;
//#if 0 // TODO implement DMA
static constexpr Bitu GUS_Master_Clock = 617400; /* NOTE: This is 1000000Hz / 1.619695497. Seems to be a common base rate within the hardware. */
static constexpr Bitu GUS_DMA_Event_transfer = 16; /* DMA words (8 or 16-bit) per interval */
static constexpr Bitu GUS_DMA_Events_per_sec = 44100 / 4; /* cheat a little, to improve emulation performance */
static constexpr uint32_t GUS_DMA_Event_interval = 1000.0 / GUS_DMA_Events_per_sec;
static constexpr uint32_t GUS_DMA_Event_interval_init = 1 / 44100;
static bool GUS_DMA_Active = false;
void GUS_Update_DMA_Event_transfer() {
+57
View File
@@ -0,0 +1,57 @@
.define public AD0_PIN 6
.define public IRQ_PIN 19
.define public IOW_PIN 4
.define public IOR_PIN 5
.define public IOCHRDY_PIN 26
.define public ADS_PIN 27
.define public BUSOE_PIN 28
.define public DACK_PIN 20
.define public DRQ_PIN 21
.define public TC_PIN 22
.program dma_write
.side_set 2 ; sideset bit 1 is ADS, bit 0 is IOCHRDY
restart:
out null, 32 side 0b01 ; wait to trigger DMA operation
dmaloop:
set pins, 1 side 0b11 ; assert DRQ
wait 0 gpio DACK_PIN side 0b11 ; DACK faling edge
set pins, 0 side 0b11 ; deassert DRQ
wait 0 gpio IOW_PIN side 0b11 ; wait for IOW assert
in pins, 8 side 0b10 ; input data, deassert IOCHRDY if we stall on full FIFO
wait 1 gpio IOW_PIN side 0b11 ; wait for IOW deassert with IOCHRDY back high
jmp pin restart side 0b01 ; if TC high, transfer is over. set ADS back to addr
jmp dmaloop side 0b11 ; else wait for more data and get ADS back to data
% c-sdk {
static inline void dma_write_program_init(PIO pio, uint sm, uint offset) {
pio_sm_config c = dma_write_program_get_default_config(offset);
// Set up AD0 bus as input
sm_config_set_in_pins(&c, AD0_PIN);
// Autopush at 8 bits
sm_config_set_in_shift(&c, false, true, 8);
// Autopull 32 bits (condition variables)
sm_config_set_out_shift(&c, true, true /* autopull */, 32);
// Set the pin direction for IOW and AD0 bus as input at the PIO
pio_sm_set_consecutive_pindirs(pio, sm, IOW_PIN, 1, false);
pio_sm_set_consecutive_pindirs(pio, sm, AD0_PIN, 8, false);
sm_config_set_jmp_pin(&c, TC_PIN);
// set up IOCHRDY and ADS
sm_config_set_set_pins(&c, DRQ_PIN, 1);
pio_gpio_init(pio, IOCHRDY_PIN);
pio_gpio_init(pio, ADS_PIN);
pio_gpio_init(pio, DRQ_PIN);
pio_sm_set_consecutive_pindirs(pio, sm, IOCHRDY_PIN, 2, true);
// Load our configuration, and jump to the start of the program
pio_sm_init(pio, sm, offset, &c);
// Set the state machine running
pio_sm_set_enabled(pio, sm, true);
}
%}
+23 -30
View File
@@ -1,44 +1,36 @@
.define public AD0_PIN 6
.define public IRQ_PIN 19
.define public IOW_PIN 4 ; was 20
.define public IOR_PIN 5 ; was 21
.define public IOW_PIN 4
.define public IOR_PIN 5
.define public IOCHRDY_PIN 26
.define public ADS_PIN 27
.define public BUSOE_PIN 28
.define public DACK_PIN 20
.program iow
restart:
.wrap_target
; muxes to addr, IOCHRDY high
set pins, 0b01
; IOW rising edge (or already high when PIO starts)
wait 1 gpio IOW_PIN
; IOW falling edge:
wait 0 gpio IOW_PIN
; Read address
in pins, 10
; Set muxes to data. Wait 8 cycles for mux to switch
set pins, 0b11 [8]
; Read data
in pins, 8
; irq 0 rel
; Set muxes back to address
set pins, 0b01
; get condition from handle_iow
out X, 32
; if we get a 0 condition from handle_iow, it's not an interesting address
jmp !X restart
; set IOCHRDY low
set pins, 0b00
; stall until handle_iow completes
out null, 32
wait 1 gpio IOW_PIN ; IOW rising edge (or already high when PIO starts)
wait 0 gpio IOW_PIN ; IOW falling edge:
jmp pin read_addr ; if this is not during DMA (~DACK deasserted), go ahead and read address
jmp restart ; otherwise restart
read_addr:
in pins, 10 ; Read address
set pins, 0b11 [8] ; Set muxes to data. Wait 8 cycles for mux to switch
in pins, 8 ; Read data
set pins, 0b01 ; Set muxes back to address
out X, 32 ; get condition from handle_iow
jmp !X restart ; if we get a 0 condition from handle_iow, it's not an interesting address
set pins, 0b00 ; set IOCHRDY low
out null, 32 ; stall until handle_iow completes
set pins, 0b01 ; muxes to addr, IOCHRDY high
.wrap
% c-sdk {
static inline void iow_program_init(PIO pio, uint sm, uint offset) {
pio_sm_config c = iow_program_get_default_config(offset);
// Set up AD0 buus as input
// Set up AD0 pins as input
sm_config_set_in_pins(&c, AD0_PIN);
// Autopush at 18 bits (10 addr + 8 data)
sm_config_set_in_shift(&c, false, true, 18);
@@ -56,6 +48,9 @@ static inline void iow_program_init(PIO pio, uint sm, uint offset) {
pio_gpio_init(pio, ADS_PIN);
pio_sm_set_consecutive_pindirs(pio, sm, IOCHRDY_PIN, 2, true);
// JMP on ~DACK so we can ignore iow during DMA write
sm_config_set_jmp_pin(&c, DACK_PIN);
// Load our configuration, and jump to the start of the program
pio_sm_init(pio, sm, offset, &c);
// Set the state machine running
@@ -65,10 +60,8 @@ static inline void iow_program_init(PIO pio, uint sm, uint offset) {
.program ior
restart:
; muxes to addr, IOCHRDY high
set pins, 0b01
; ensure IOR high when PIO starts
wait 1 gpio IOR_PIN
set pins, 0b01 ; muxes to addr, IOCHRDY high
wait 1 gpio IOR_PIN ; ensure IOR high when PIO starts
.wrap_target
wait 0 gpio IOR_PIN ; IOR falling edge
in pins, 10 ; - Read address
+5 -3
View File
@@ -33,9 +33,11 @@ typedef struct pio_spi_inst {
} pio_spi_inst_t;
static __force_inline void __time_critical_func(pio_spi_write_read_blocking)(pio_spi_inst_t* spi,
const uint8_t* src, const size_t src_len,
uint8_t* dst, const size_t dst_len) {
static __force_inline void __time_critical_func(pio_spi_write_read_blocking)(
pio_spi_inst_t* spi,
const uint8_t* src, const size_t src_len,
uint8_t* dst, const size_t dst_len
) {
size_t tx_remain = src_len, rx_remain = dst_len;
#ifdef USE_SPINLOCK
+1 -1
View File
@@ -24,7 +24,7 @@
#include "psram_spi.h"
pio_spi_inst_t psram_spi;
#endif
#include "io.pio.h"
#include "isa_io.pio.h"
#ifdef SOUND_OPL
#include "opl.h"