cancel
Showing results for 
Search instead for 
Did you mean: 

the gap between DAC DMA stop and start

Mr ZEE
Associate II

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

0693W000007BxjAQAS.png0693W000007Bxj5QAC.png

5 REPLIES 5

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

Never heard of this method before but will give it a try and see what happens. Thanks a lot.

Piranha
Chief II

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:

  1. The software must not be bloatware. Therefore no HAL/Cube or other junk code.
  2. Interrupt has to be of a high priority and almost never disabled.
  3. ISR must do only DMA disable, buffer swap and DMA enable. No intensive processing there.

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.

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.

Tips, Buy me a coffee, or three.. PayPal Venmo
Up vote any posts that you find helpful, it shows what's working..