AnsweredAssumed Answered

Implementing audio delay using SSI and DMA

Question asked by Ruben Valls Blasco on Mar 11, 2016
Latest reply on Mar 15, 2016 by Ruben Valls Blasco


Hello everybody!

I need to implement an audio delay for 8 audio channels. The audio format is TDM, meaning 8 slots per frame, using only one RX pin and one TX pin.

Right now, I am already receiving and transmitting the 8 channels, by using two eDMA channels, one for the reception and one for the transmission of the data.

The eDMA channels are configured to work automatically, without intervention of the uC.

The implementation just consists in having a buffer of N audio frames (each one consisting in the 8 audio channel slots). The receiver DMA channel stores continuously into this buffer, and the transmitter DMA channel reads continuously from this buffer.

 

The problem is that, for implementing a different delay per audio channel, I need that the receiver DMA channel stores each audio sample in a different frame, thus when the transmitter DMA channel reads the frames continuously, each one of the slots will be effectively delayed.

 

So, I think it can be done by having the receiving DMA channel to use the scatter feature, and configuring 8 different TCDs, forming a circular linked list, each one containing the offset to apply to each slot.

 

In order to make this work, I have to set up the DMA channel to have only one minor loop iteration, and only one major loop iteration, so each transaction will trigger a TCD change.

 

In order to take one step at a time, I have managed to make the basic RX-DMA-Memory and Memory-DMA-TX work. Now, the next step would be to make the RX-DMA-Memory work with only one iteration, and the last step would be to make it work with the scatter feature.

 

Here comes the problem. When I set the RX-DMA to have only one major loop iteration, the system stops working. If it has any other iteration count (two, four, eight...) everything works fine.

 

My RX-DMA configuration is as follows:

 

#define DMA_CHANNEL_RX 1
#define DMA_CHANNEL_TX 2
#define TDM_SAMPLE_SIZE 4
#define alignment 128
tcd=(edma_tcd_t*)&DMA0->TCD[DMA_CHANNEL_RX];
tcd->SADDR=(uint32_t)&I2S0->RDR[0];
tcd->SOFF=0;
tcd->ATTR=DMA_ATTR_SMOD(0) | DMA_ATTR_SSIZE(kEDMA_TransferSize4Bytes)
  | DMA_ATTR_DMOD(alignment) | DMA_ATTR_DSIZE(kEDMA_TransferSize4Bytes);
tcd->NBYTES= TDM_SAMPLE_SIZE;
tcd->SLAST=0;
tcd->DADDR=(uint32_t)&tdm->frames[tdm->rx+tdm->delay[0]][0];
tcd->DOFF=TDM_SAMPLE_SIZE;
tcd->CITER=2; //If set to 1 iteration, it stops working
tcd->BITER=2; //If set to 1 iteration, it stops working
tcd->DLAST_SGA=0;
tcd->CSR= 0
  | DMA_CSR_MAJORLINKCH(DMA_CHANNEL_RX)
  | DMA_CSR_MAJORELINK_MASK
  ;

 

Does somebody faced a similar problem?

 

I am using the KSDK v2.0, and a Kinetis K64 uC.

 

Thank you very much for your help, it is really appreciated,

Best regards,

Ruben

Outcomes