I'm trying to implement signed unsigned multiplication in C using fixed point arithmetic, but I get a incorrect result. I can't imagine how to solve this problem. I think there is some problem in the bit extension. Here is the piece of code:
int16_t audio_sample=0x1FF; //format signed Q1.8 -> Value represented=-0.00390625
uint8_t gain=0xA; //format unsigned Q5.2 -> Value represented = 2.5
int16_t result= (int16_t)(((int16_t)((int32_t)audio_sample * (int32_t) gain);
printf("%x",result);
The result from printf
is 0x13F6
, which is of course the result from 0x1FF*0xA
, but the fixed-point arithmetics said that the correct results would be 0x3FF6
, considering the proper bit-extension. 0x3FF6
in Q6.10 format represent -0.009765625=-0.00390625*2.5
.
Please help me find my mistake.
Thank in advance.
You should use unsigned types here. The representation is in your head (or the comments), not in the data types in the code.
2's complement means the 1
on the left is theoretically continued forever. e.g. 0x1FF
in Q1.8 is the same as 0xFFFF
in Q8.8 (-1 / 256
).
If you have a 16bit integer, you cannot have Q1.8, it will always be Q8.8, the machine will not ignore the other bits. So, 0x1FF
in Q1.8 should be 0xFFFF
in Q8.8. The 0xA
in Q5.2 do not change in Q6.2
.
0xFFFF * 0xA = 0x9FFF6
, cut away the overflow (therefore use unsigned) and you have 0xFFF6
in Q6.10, which is -10 / 1024
, which is your expected result.