Hi,
I'd like to use a quad channel SPI DAC with the Audio library, but can't quite figure out how to make this work. The device in question has a 32 bit wide register, so the basic idea, I guess, would be to interleave the DAC command and audio data bytes with the upper two bytes of SPI0_PUSHR, which contain the chip select stuff. Thus, in the DMA isr, I'm stuffing a/the SPI_tx_buffer like so (in this case I'm using CS = 9, so pcsbits = 0x02 << 16 (as per SPIFIFO.h); CHANNEL_X are the DAC command bytes):
My DMA set-up looks like this (I've tried to adapt the output_i2s_quad object, mainly by making it write to SPI0_PUSHR):
However, this doesn't work. In fact, it doesn't seem to transmit any data and prevents the Audio library from updating. Any DMA experts who can point me to what I'm doing wrong? (config_SPI() basically just invokes SPIFIFO.begin() and sets up the DAC reference and so on, this bit works)
I'd like to use a quad channel SPI DAC with the Audio library, but can't quite figure out how to make this work. The device in question has a 32 bit wide register, so the basic idea, I guess, would be to interleave the DAC command and audio data bytes with the upper two bytes of SPI0_PUSHR, which contain the chip select stuff. Thus, in the DMA isr, I'm stuffing a/the SPI_tx_buffer like so (in this case I'm using CS = 9, so pcsbits = 0x02 << 16 (as per SPIFIFO.h); CHANNEL_X are the DAC command bytes):
Code:
for (int i=0; i < AUDIO_BLOCK_SAMPLES / 2; i++) {
// channel A data:
*dest++ = SPI_PUSHR_CONT | pcsbits | SPI_PUSHR_CTAS(1) | CHANNEL_A;
*dest++ = pcsbits | SPI_PUSHR_CTAS(1) | *src1++;
// channel B data
*dest++ = SPI_PUSHR_CONT | pcsbits | SPI_PUSHR_CTAS(1) | CHANNEL_B;
*dest++ = pcsbits | SPI_PUSHR_CTAS(1) | *src2++;
// channel C data
*dest++ = SPI_PUSHR_CONT | pcsbits | SPI_PUSHR_CTAS(1) | CHANNEL_C;
*dest++ = pcsbits | SPI_PUSHR_CTAS(1) | *src3++;
// channel D data
*dest++ = SPI_PUSHR_CONT | pcsbits | SPI_PUSHR_CTAS(1) | CHANNEL_D;
*dest++ = pcsbits | SPI_PUSHR_CTAS(1) | *src4++;
}
My DMA set-up looks like this (I've tried to adapt the output_i2s_quad object, mainly by making it write to SPI0_PUSHR):
Code:
void AudioOutputSPIQuad::begin(void)
{
#if 1
config_SPI();
dma.begin(true);
block_ch1_1st = NULL;
block_ch2_1st = NULL;
block_ch3_1st = NULL;
block_ch4_1st = NULL;
dma.TCD->SADDR = SPI_tx_buffer;
dma.TCD->SOFF = ELEMENT_SIZE; // source offset per transaction = 4 bytes
dma.TCD->ATTR = DMA_TCD_ATTR_SSIZE(DMA_TCD_ATTR_SIZE_32BIT) | DMA_TCD_ATTR_DSIZE(DMA_TCD_ATTR_SIZE_32BIT);
dma.TCD->NBYTES_MLNO = ELEMENT_SIZE; // bytes/transaction = 4 bytes (~ SPI0_PUSHR)
dma.TCD->SLAST = -sizeof(SPI_tx_buffer);
dma.TCD->DADDR = (volatile uint32_t*)&SPI0_PUSHR;
dma.TCD->DOFF = 0; // destination offset
dma.TCD->CITER_ELINKNO = sizeof(SPI_tx_buffer) / ELEMENT_SIZE; // major loop
dma.TCD->DLASTSGA = 0;
dma.TCD->BITER_ELINKNO = sizeof(SPI_tx_buffer) / ELEMENT_SIZE;
dma.TCD->CSR = DMA_TCD_CSR_INTHALF | DMA_TCD_CSR_INTMAJOR;
dma.triggerAtHardwareEvent(DMAMUX_SOURCE_SPI0_TX);
update_responsibility = update_setup();
dma.enable();
// SPI --
SPI0_SR = 0xFF0F0000;
SPI0_RSER = SPI_RSER_RFDF_RE | SPI_RSER_RFDF_DIRS | SPI_RSER_TFFF_RE | SPI_RSER_TFFF_DIRS;
dma.attachInterrupt(isr);
#endif
}
However, this doesn't work. In fact, it doesn't seem to transmit any data and prevents the Audio library from updating. Any DMA experts who can point me to what I'm doing wrong? (config_SPI() basically just invokes SPIFIFO.begin() and sets up the DAC reference and so on, this bit works)
Last edited: