2021-01-20 02:03 AM
Hi all
I know the question title sounds weird but here is the actual thing I would like to know about.
So, I have an array of 1000 bytes which I apparently use in the HAL_DAC_START_DMA function, and then start the DAC DMA trigger timer. This works super fine and on the half-complete callback of DAC DMA I read the next 1000 bytes from a file inside the SD-Card and on complete DAC DMA callback, I simply stop the trigger timer, stop the DAC DMA and reload the new 1000 bytes into HAL_DAC_START_DMA function and start the timer again.
// audio out function main bits
memset((void *) DacAudioBuffer.Audio16BitBuffer, 0, sizeof(DacAudioBuffer.Audio16BitBuffer));
memcpy((void *) DacAudioBuffer.Audio16BitBuffer, (void *) DacAudioBuffer.Temp16AudioBuffer, sizeof(DacAudioBuffer.Temp16AudioBuffer));
HAL_DAC_Start_DMA(&hdac, DAC_CHANNEL_1, (uint32_t *) DacAudioBuffer.Audio16BitBuffer, BuffSize, DAC_ALIGN_12B_R);
HAL_TIM_Base_Start_IT(&htim2);
// DAC DMA half out call back
IsDacDataHalfOut = TRUE;
// DAC DMA complete call back
if(HAL_TIM_Base_Stop_IT(&htim2) == HAL_OK) {
if(HAL_DAC_Stop_DMA(hdac, DAC_CHANNEL_1) == HAL_OK) {}
IsDacDataCpltOut = TRUE;
}
The main problem I'm facing is that there is a gap between when I stop the timer and restart it again (a big gap in msec) which I don't like to happen.
The bytes I'm reading from the file are audio bytes of wave file so they need to be stitched together perfectly but as soon as time passes the gap becomes bigger and bigger. Any help would be very appreciated. Thanks
2021-01-20 03:42 AM
The usual way to produce continuous waveform is to use DMA in CIrcular mode (i.e. never stop), and feed the opposite (unused) half of the buffer (i.e. the first half in the HalfComplete interrupt, and the second half in the TransferComplete interrupt), while DMA is playing back from the other half of the buffer.
JW
2021-01-20 04:04 AM
Never heard of this method before but will give it a try and see what happens. Thanks a lot.
2021-01-20 07:04 AM
Overall Jan's advise is the preferred way. But, if for some reason not possible, then it can be done with single shot DMA and interrupts, it just have to be quick:
2021-01-20 07:09 AM
Yeah, I know. No junk code in the interrupt but at the moment I'm letting the DMA run forever and seems like my gap problem is resolved. Now I need to implement the half buffer technique which Jan has recommended me so that the very small amount of humming sound I'm getting can be eliminated.
2021-01-20 07:15 AM
You can't go out to lunch in a callback, it is done under interrupt context.
You need to separate the tasks so you prepare buffers from SD Card in one, and dispatch the half ping-pong output buffer in a continuous/circular DMA operation. ie via a HT/TC interrupt, or double buffer approach.
For SD Card interactions make everything multiples of 512 bytes, and ideally some multiple or sub-multiple of the cluster size.