Closed xinshuwei closed 1 year ago
The tx dma channel may be running out of data. For sustained output a double buffered approach using async transfers may be needed.
The following pseudo code outlines the process.
#define TXBUF_LEN 1600
volatile int txdmaDone = 0;
unsigned char txbuf_0[TXBUF_LEN];
unsigned char txbuf_1[TXBUF_LEN];
unsigned char* activeBuf;
void DMA0_IRQHandler(void)
{
MXC_DMA_Handler();
}
void txdmaCallback(int x, int xx)
{
txdmaDone = 1;
}
void workLoop(void)
{
int dmaChannel;
NVIC_EnableIRQ(DMA0_IRQn);
MXC_I2S_RegisterDMACallback(txdmaCallback);
/* read and send initial buffer */
sdhc-read(file, txbuf_0, TXBUF_LEN);
dmaChannel = MXC_I2S_TXDMAConfig(txbuf_0, TXBUF_LEN);
activeBuf = txbuf_0;
/* pre-read next buffer */
sdhc-read(file, txbuf_1, TXBUF_LEN);
while (1) {
if (txdmaDone) {
txdmaDone = 0;
MXC_DMA_ReleaseChannel(dmaChannel);
if (activeBuf == txbuf_0) {
/* send pre-read buffer */
dmaChannel = MXC_I2S_TXDMAConfig(txbuf_1, TXBUF_LEN);
/* read next buffer while active buffer is transmitted */
sdhc-read(file, txbuf_0, TXBUF_LEN);
/* set active buffer */
activeBuf = txbuf_1;
} else {
dmaChannel = MXC_I2S_TXDMAConfig(txbuf_0, TXBUF_LEN);
sdhc-read(file, txbuf_1, TXBUF_LEN);
activeBuf = txbuf_0;
}
}
/*
other work
*/
}
}
i also use double buffered approach.code set like is
1. init
NVIC_EnableIRQ(DMA0_IRQn); MXC_I2S_RegisterDMACallback(i2s_dma_cb); MXC_NVIC_SetVector(DMA0_IRQn, DMA_IRQHandler); void DMA_IRQHandler(void) { MXC_DMA_Handler(); } void i2s_dma_cb(int handle, int error) { i2s_done = 1; }
2. update data
void update_first_data(voidflash_buf,int size) { i2s_buf= flash_buf; //MXC_DMA_ReleaseChannel(0); dmaChannel = MXC_I2S_TXDMAConfig(i2s_buf, size); //MXC_DMA_Start(0); flash_buf = BUF_SEL(flash_buf, buf0, buf1); // Get next set of audio samples } void update_frame_data(void flash_buf,int size) { while(!i2s_done) { } i2s_buf= flash_buf; i2s_done = 0; MXC_DMA_ReleaseChannel(dmaChannel); dmaChannel= MXC_I2S_TXDMAConfig(i2s_buf, size); //MXC_DMA_Start(0); flash_buf = BUF_SEL(flash_buf, buf0, buf1); // Get next set of audio samples }
3.main audio read and playback if((err = f_read(&file,flash_buf,BUF_READ_SIZE,&bytes_read))!= FR_OK) { printf("Error reading file: %s\n", FF_ERRORS[err]); f_mount(NULL, "", 0); return ; } read_size +=BUF_READ_SIZE; update_first_data(flash_buf,BUF_READ_SIZE); while(read_size<file_size) { for(int i= 0;i<file_size;i+=BUF_READ_SIZE) { //LED_Toggle(0); //LED_Toggle(1); if((err = f_read(&file,flash_buf,BUF_READ_SIZE,&bytes_read))!= FR_OK) { printf("Error reading file: %s\n", FF_ERRORS[err]); f_mount(NULL, "", 0); return ; } read_size +=BUF_READ_SIZE; update_frame_data(flash_buf,BUF_READ_SIZE); } }
BUF_READ_SIZE = sizeof(buf1) = sizeof(buf0)=16000
@Jake-Carter @jessexm my code set also have pop, can you help me?
@xinshuwei It's a difficult issue to debug remotely.
As Jesse mentioned a double-buffered approach with DMA is recommended.
I would also recommend using f_stream
instead of f_read
. From the f_read documentation: "If the file needs to be read fast, it should be read in large chunk as possible." f_read
is slow. See f_forward for documentation and out_stream for an example where I implemented the data streaming function to stream to UART.
Additionally, have you verified that the sine lookup table you're sending from is perfectly continuous? I would recommend starting and ending blocks of audio data at the Zero-Crossing for a sine wave.
Desktop.zip @Jake-Carter Thanks your reply. 1.I had upload my file, please check.
i have MAX78000 FTHR_RevA board .I want set up max9867 codec. I learn I2S config with example. Codec is working,i found use
MXC_DMA_ReleaseChannel(0); MXC_I2S_TXDMAConfig() This code once play is ok,but when i send a lot of samples with “SDHC fread“ wav files, release dma ch and TXDMAConfig(), Codec play audio have pop, I have capture this audio wav with audtion(set send bu'ffer size is 1600 ,16bit two ch out,400 samples have pop)
How can i setup is codec with FTHR_RevA I2S ,playback a long file is not have pop? Can help me?