I am trying to decimate my ADC values which are stored in a DMA buffer.
The functions I am using are:1. HAL_ADC_Start_DMA();2. arm_fir_decimate_init_f32();3. arm_fir_decimate_f32();
I understand that the information from the 12 bit ADC are stored in a uin32_t type buffer in the DMA. However, to decimate these values, which are in the range of 0-4096, it requires me to convert the uint32_t DMA values to a float32_t data type. I have tried casting the uint32_t values to a q31_t format and convert them to float32_t via the CMSIS lib: arm_q31_float, but to no avail. The output array of the decimation is always 0. May I have some help pertaining to either the conversion from uint32_t to q31_t format, or an alternative way to decimate uint32_t values.
Thank you.
Hello,
Uint32_t is going to store your 12 bit data in the LSBs, but for q31_t to make any sense, you should shift the data up to the MSBs before converting to float. Let me know if that improves anything for you or not.
Hi, thanks for replying. I have tried it and it works. But why does it work? Why does q31_t takes in values from the MSB instead of the LSB?
Regards,
Selwyn
uint32_t is a fully integer type. q31_t has 1 integer bit, and 31 fractional bits. the integer bit is the MSB. By storing your data in the LSBs, you represented a very small number in q31_t. Storing those numbers in the MSBs means you get numbers near +- 1. arm_q31_float takes all that into account when converting by multiply by a different scale factor for q31->float than uint32->float
I see. I have implemented something like this; Please help me verify if I am getting the right picture.
uint32_t ArrayU32;
f32_t BufferF32;
/* Perform shifting from LSB to MSB */
q31_t BufferQ31 = ((q31_t)ArrayU32)<<20;
/* Convert q31 to f32 */
arm_q31_to_float(BufferQ31, BufferF32, 100);
looks good! you could also use a q15_t instead of q31_t if you'd like it to go a little faster. CMSIS takes advantage of SIMD for q15_t when it's available on specific targets. For targets without SIMD, it probably won't make a difference though. For q15_t just shift up 4 bits instead of 20.
Hi selwyn123,
The ADC data can be directly converted from integer to floating-point without going to Q fractional data format. You are taking unnecessary steps with uint32_t to q31_t then q31_t to float32_t.
You are in control of the ADC, what is your reason for decimating the ADC values? Do you want to process your ADC data through various sampling rates? If you just want to downsample, you should try first if you can arrive at the required sampling rate by altering the sampling clock of the ADC. If that is possible you don't have to perform the decimation and avoid the computations involved.
Goodwin