Hi to you all,I've another post on the forum (here's the link Process ADC data, moved by DMA, using CMSIS DSP: what's the right way? ), but since I think I made some small steps forward I felt I could be a little more specific. I hope this won't be a problem.
Actually I'm trying to extract the MAX from a q31_t (Note that: typedef int32_t q31_t) array filled by the ADCHS in my LPC4370 lpc link2 board, using the arm_max_q31 function (here for reference: Maximum). The problem is that the 12bit ADC supplies data in Two's Complement format, but the library is misunderstanding it (ora at least I think so). For instance:
111111111111
Should be
-1
but actually is read by the CMSIS Function as
4095
and therefore is always recognized as the MAX value.
Do I need to manually convert all the samples one-by-one? This seems to be extremely slow, and since I've some real-time requirements I need the fastest way to do this maths.Any help would be highly appreciated since I'm stuck here.
Thanks,Andrea
Hello Abet,
In your example, 4095 would be -1 if you were using a 12 bit data type. However you are using a 32bit data type (q31_t). You need to upshift your data to make sense in the q31_t format. In this case by 20 bits. y = x << 20. You might also use q15_t as your input data is only 12 bits anyways, and the q15_t library is sometimes faster than q31_t due to SIMD. You could use the arm_shift_q15 function to quickly upshift all of your data in one go before calling arm_max_q15.
I would recommend doing some googling to understand how the q31_t, q15_t, int32_t, int16_t data types all work, as your question implies a degree of unfamiliarity.
Cheers,
Dan
Hi Dan,many thanks for your reply. As you said I'm definitely unfamiliar with the fixed point maths, so I spent the last day studying it and try to figure out how it works and that's why I'm late.
Now I think to better understand what's going on here: I followed your advice (even if I'm still using q31'cause I had some issues trying to DEBUGOUT the q15 format) , but I'm stuck with the arm_shift_q31 function.It seems to saturate some of my numbers, and here's why I think so.
Here's my code (all the vectors are in q31_t format):
arm_shift_q31(sample2, 20, sampleTmp, NUM_SAMPLE); arm_max_q31(sampleTmp, NUM_SAMPLE, &maxSample, &sampleIndex); DEBUGOUT("%d\r\n", maxSample);
This are my entries before the left shift, as expected the info is in the first 12Bit and that's fine.
Here you can see the same entries after the left shift:
The CMSIS Doc says
Scaling and Overflow Behavior: The function uses saturating arithmetic. Results outside of the allowable Q31 range [0x80000000 0x7FFFFFFF] will be saturated.
Scaling and Overflow Behavior:
The function uses saturating arithmetic. Results outside of the allowable Q31 range [0x80000000 0x7FFFFFFF] will be saturated.
So this seems to me like an overflow, but why?
Thanks for your time, your previous answer helped me a lot!
Abet
Hi Abet,
That is because arm_shift_q31 appears to be assuming its input is already sign extended. My apologies that I did not notice beforehand. You could sign extend your data and then use the shift function, but it would be faster to make a modified version of the arm_shift_q31 function I think.
In the code below, the input is leftshifted, and stored in a temporary variable. Then it is rightshifted by the same amount and compared to the input. If they differ, an overflow is assumed to have happened. However, in your case no overflow has occurred, but the values differ anyways because in = 4095 (lets say) and out = 4294967295. I would just make a simplified version of this function which does not do this check at all for your case.
Hi Dan,thank you very much for your last reply: that was eyes opening for me.I didn't know that the bit shift operates accordingly with the Two's Complement representation (which is right and reasonable)!So now I commented out the check in the CMSIS's code, build it and the whole thing is working so thanks again.
Using DEBUGOUT to push into the UART the max every 1024 i was able to build some graphs using Matlab, here's the one using your solution:
Which is nice and as expected.
This instead is what I got before today's update:
It's interesting that the fake overflow happened only whit a subset of the (maximized) samples. I'm trying to figure out why, just to have a more complete understanding of what's happening here.Thanks again for your effort, I'm trying to carry on my thesis, but I'm working alone on this right now: your help is really appreciated!
Cheers!Andrea
Hi Andrea,
Although you are now exploring fixed-point fractional data types, I'll reply in your previous post Process ADC data, moved by DMA, using CMSIS DSP: what's the right way?. My reply in that thread is pertaining to floating-point data format. I hope it is still useful, just in case you will again use or refer to floating point data.
Regards,
Goodwin
It's interesting that the fake overflow happened only whit a subset of the (maximized) samples.
It occurred for all the negative values. Those numbers were shifted up to the most significant bit (MSB), and then right shifted by the same amount. When right shifting a signed number, '1's are put in from the left if the MSB is a '1' (or '0s' if it's a '0'). In this way, the numbers you were interpreting as negative, we failing the if statement. The positive numbers shifted left, then right, and were no different than their original number.
A small example. Lets pretend you had 4 bit input numbers, and we're shifting up to 8 bit for whatever reason.
positive input example:00000100 (+4). shift left by 4, 01000000 (+64), now shift right by 4, 00000100 (+4)
negative input example00001100 (-4). shift left by 4, 11000000 (-64), now shift right by 4, 11111100 (-4).
Even though I interpreted 00001100 and 11111100 both as -4, a computer would interpret those as 12 and -4 which are clearly different.
Hope this makes sense
Ok, so now I have the whole thing pretty clear. Unfortunately yesterday I found out that I'm still too slow to process the 40msps stream in continuous mode, but this design provided a huge improve compared to the float-ing approach that i described in my previous post. Now I'm gonna update that post!
Thanks again Dan for your support,Abet