view modulator.c @ 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 2db42eaba3c8
line wrap: on
line source

/******************************************************************
*******************************************************************
**
** This is proprietary unpublished source code, property
** of Genesis Software.  Use or disclosure without prior
** agreement is expressly prohibited.
**
** Copyright (c) 2021 Genesis Software, all rights reserved.
**
*******************************************************************
 ******************************************************************/

/*
** MODULATOR.C
**
** Create modulation shape
**
*/

#include "pico/stdlib.h"
#include "hardware/clocks.h"
#include "hardware/dma.h"
#include "hardware/irq.h"
#include "hardware/pio.h"

#include "dac.pio.h"

#if 0
extern void* shaped_trap_dat_size;
extern void* shaped_trap_dat_start;

extern void* sgauss_dat_size;
extern void* sgauss_dat_start;
#endif

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(void) {
    int i;
    const uint LED_PIN = PICO_DEFAULT_LED_PIN;

    stdio_init_all();

    gpio_init(LED_PIN);
    gpio_set_dir(LED_PIN, GPIO_OUT);

    // Load the clocked_input program, and configure a free state machine
    // to run the program.
    PIO pio = pio0;
    uint offset = pio_add_program(pio, &dac_program);
    uint sm = pio_claim_unused_sm(pio, true);
    // XXX: I would prefer starting at GPIO16 but in that case the top 2
    // 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);
	gpio_put(LED_PIN, 0);
#endif
    }
}