cancel
Showing results for 
Search instead for 
Did you mean: 

STM32F4 playing DPCM with simple PWM + DMA

neoirto
Associate II
Posted on February 14, 2013 at 12:37

Hello,

I'd like to know if it is possible to play sound files in DPCM with a reasonnable quality (understanding human voice is enough) with the following configuration :

- with a standard low quality piezo buzzer,

- with PWM (TIMER8 on channel 3) input without a low pass filter (if the frequency of the PWM is enough high perhaps ?)

- by reading low resolution data (8000 Hz / 8 bits data samples) stored in flash memory, with DMA loading at 8000 Hz ?

I presume I have to set a PWM frequency by a multiple of 8000 Hz + repetition counter to inform DMA it have to load a new data in TIM8->CCR3 every 1/8000 sec: but what would be the DMA event I have to configure to do that ?

Is it possible to inform DMA from the number of data samples to load (sound duration) in such a configuration, in order to stop the readings at the end of the data samples ?

Last question : do you know any existing software to format wave files to DPCM, or I'll need to write my own ?

Thanks a lot, in advance ;)
4 REPLIES 4
Posted on February 14, 2013 at 12:52

You should be able to use a TIM/DMA combination to pace the transfer to another timer's CCRx register, which would work in a similar fashion to one outputting to the DAC, etc.

Using non-circular DMA mode you specify the transfer length as a 16-bit transfer count (8/16/32 bit units)
Tips, Buy me a coffee, or three.. PayPal Venmo
Up vote any posts that you find helpful, it shows what's working..
neoirto
Associate II
Posted on February 14, 2013 at 13:28

Thank you for your quick answer Clive,

So the following configuration should work as expected ?

//////// my main clock is at 160 MHz, so for TIM8 : 80Mhz/250 = 320KHz (should be enough without low pass ?)
//////// 320KHz / 8000 Hz data samples = 40 (repetition counter) -> then TIM8_UP DMA event every 1/8000 sec -> new DMA transfer ? is that ok ?
TIM_TimeBaseStructure.TIM_Period = 250;
TIM_TimeBaseStructure.TIM_Prescaler = 0;
TIM_TimeBaseStructure.TIM_ClockDivision = 0;
TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_CenterAligned1;
TIM_TimeBaseStructure.TIM_RepetitionCounter = 40;
TIM_TimeBaseInit(TIM8, &TIM_TimeBaseStructure);
/* PWM Mode configuration: Channel3 */
TIM_OCInitStructure.TIM_Pulse = 0;
TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM2;
TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable;
TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_Low;
TIM_OCInitStructure.TIM_OCIdleState = TIM_OCIdleState_Reset; /// TIM_OCIdleState_Set;
TIM_OC3Init(TIM8, &TIM_OCInitStructure);
TIM_ARRPreloadConfig(TIM8, ENABLE);
DMA_InitStructure.DMA_Channel = DMA_Channel_7; /// TIM8_UP
DMA_InitStructure.DMA_PeripheralBaseAddr = (uint32_t)&(TIM8->CCR3);
DMA_InitStructure.DMA_DIR = DMA_DIR_MemoryToPeripheral;
DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_Byte; /// stored in 8 bits, with maximum value at 249 (need to write my own converter I believe, with ffmepg)
DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_HalfWord;
DMA_InitStructure.DMA_Mode = DMA_Mode_Normal; 
DMA_InitStructure.DMA_BufferSize = Data_samples_Number; /// length of sound file
DMA_Init(DMA2_Stream1, &DMA_InitStructure); /// TIM8_UP
DMA_Cmd(DMA2_Stream1, ENABLE); /// TIM8_UP
TIM_ITConfig(TIM8, TIM_FLAG_Update, DISABLE); // DMA in charge

WithDMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_HalfWord because CCR3 is 16 bits long, is that what you mean ? Tx again
Posted on February 14, 2013 at 18:31

250 - 1 for the period. Repetition might be N-1 too, not played with.

You might need to fill out the TIM and DMA structures more completely.

TIM8 might need PWM Enable.

TIM8_UP, DMA2, Channel 7, Stream 1. Check

DMA needs increment fields, etc.

Tips, Buy me a coffee, or three.. PayPal Venmo
Up vote any posts that you find helpful, it shows what's working..
neoirto
Associate II
Posted on February 14, 2013 at 20:32

Ok, tx for pointing the index error,

It was pseudocode, so there is still code to add, that's true.

I can't test it at the moment, because I have to produce DPCM data first...

But I will do it soon

Tx again Clive