Mercurial > ~darius > hgwebdir.cgi > modulator
changeset 3:b10097c3383d
DMA test data repeatedly into PIO FIFO
author | Daniel O'Connor <darius@dons.net.au> |
---|---|
date | Mon, 29 Mar 2021 18:05:05 +1030 |
parents | 0d653f60dec8 |
children | b6416c4aadc8 |
files | CMakeLists.txt modulator.c |
diffstat | 2 files changed, 49 insertions(+), 1 deletions(-) [+] |
line wrap: on
line diff
--- a/CMakeLists.txt Mon Mar 29 17:39:00 2021 +1030 +++ b/CMakeLists.txt Mon Mar 29 18:05:05 2021 +1030 @@ -22,6 +22,8 @@ target_link_libraries(${NAME} pico_stdlib + hardware_dma + hardware_irq hardware_pio )
--- a/modulator.c Mon Mar 29 17:39:00 2021 +1030 +++ b/modulator.c Mon Mar 29 18:05:05 2021 +1030 @@ -19,6 +19,8 @@ #include "pico/stdlib.h" #include "hardware/clocks.h" +#include "hardware/dma.h" +#include "hardware/irq.h" #include "hardware/pio.h" #include "dac.pio.h" @@ -33,9 +35,21 @@ uint8_t shaped_trap_dat_start[] = { 0, 1, 2, 4, 8, 16, 32, 64, 128, 0, 0, 0, 0, 0, 0, 0 }; //uint8_t shaped_trap_dat_start[] = { 0, 1, 2, 3, 1, 2, 0, 3, 1, 1, 2, 3, 0, 1, 2, 3 }; +#define SHAPED_TRAP_DAT_BITS 4 +_Static_assert((1 << SHAPED_TRAP_DAT_BITS) == sizeof(shaped_trap_dat_start)); + +static int dma_chan; + +void +dma_handler(void) { + // Clear the interrupt request. + dma_hw->ints0 = 1u << dma_chan; + // Give the channel a new wave table entry to read from, and re-trigger it + dma_channel_set_read_addr(dma_chan, shaped_trap_dat_start, true); +} int -main() { +main(void) { int i; const uint LED_PIN = PICO_DEFAULT_LED_PIN; @@ -53,10 +67,42 @@ // bits don't seem to work dac_program_init(pio, sm, offset, 14); +// Configure a channel to write the same word (32 bits) repeatedly to PIO0 + // SM0's TX FIFO, paced by the data request signal from that peripheral. + dma_chan = dma_claim_unused_channel(true); + dma_channel_config dmac = dma_channel_get_default_config(dma_chan); + channel_config_set_transfer_data_size(&dmac, DMA_SIZE_32); + channel_config_set_read_increment(&dmac, true); + channel_config_set_ring(&dmac, false, SHAPED_TRAP_DAT_BITS); + channel_config_set_dreq(&dmac, DREQ_PIO0_TX0); + + dma_channel_configure( + dma_chan, + &dmac, + &pio0_hw->txf[0], // Write address (only need to set this once) + NULL, // Don't provide a read address yet + 100, // Write this many times then interrupt + false // Don't start yet + ); + + // Tell the DMA to raise IRQ line 0 when the channel finishes a block + dma_channel_set_irq0_enabled(dma_chan, true); + + // Configure the processor to run dma_handler() when DMA IRQ 0 is asserted + irq_set_exclusive_handler(DMA_IRQ_0, dma_handler); + irq_set_enabled(DMA_IRQ_0, true); + + // Manually call the handler once, to trigger the first transfer + dma_handler(); + + // Everything else from this point is interrupt-driven. The processor has + // time to sit and think about its early retirement -- maybe open a bakery? while (true) { +#if 0 for (int i = 0; i < sizeof(shaped_trap_dat_start) / 4; i++) { pio_sm_put_blocking(pio, sm, ((uint32_t *)shaped_trap_dat_start)[i]); } +#endif #if 0 gpio_put(LED_PIN, 1); sleep_ms(100);