-4

I recive 24 bits fixed-point data from a CODEC (ADC) by TDM transmission. Then data is stored into a int buffer (32 bits). I want to convert this to float data.

I tried:

g_analog_input_chL_mean = (((float)(*rx_block_pointer[buffer_cntr] << 8)) * (1.0/2147483648.0)); 

What is the best way to do this conversion?

Thanks, Costi

  • What is `rx_block_pointer`? – πάντα ῥεῖ Jun 28 '17 at 10:58
  • "24 bits fixed-point data" is not some known standard. Everyone is free to implement it as they wish. So you need to tell us exactly what the documentation of your CODEC says about precisely what "24 bits fixed-point data" means to ***them***. – Mike Nakis Jun 28 '17 at 11:00
  • What do you mean "best way"? Fastest? The most exact? As I see, your input is 24-bit 2-complement number. What output do you need? [-1:1]? The only problem I see is that for 0x7fffff, you output a slightly less number than 1. – geza Jun 28 '17 at 11:15
  • rx_block_pointer is a pointer to receive buffer (it`s a ping-pong buffer). – Jerca Costi Jun 28 '17 at 11:42
  • The codec's ADC produces and DAC consumes 24 bit fixed point data that is why I use << 8. – Jerca Costi Jun 28 '17 at 11:45

1 Answers1

1

It depends on the scaling of your fixed point data and also, if the data is signed or unsigned. When you use float to represent 32 bit fixed point data, then you will loose some digits, since some bits are used to store the exponent. I do not really understand, why you do this 32 bit conversion since you could skip this step and write

g_analog_input_chL_mean = (float)(*rx_block_pointer[buffer_cntr])/(float)(0x7FFFFF);

If you insist on this 32 bit conversion, then use

g_analog_input_chL_mean = (float)(*rx_block_pointer[buffer_cntr] << 8)/(float)(0x7FFFFFFF);

Note, that I would always use the hex-scaling which is more typo safe than writing the decimal number. Yours is indeed wrong, since the maximum signed integer number is 2147483647, not 2147483648.

If the ADC value has an unsigned format, than you can use the same expressions, but with the sign-bit included:

g_analog_input_chL_mean = (float)(*rx_block_pointer[buffer_cntr])/(float)(0xFFFFFF);

or

g_analog_input_chL_mean = (float)(*rx_block_pointer[buffer_cntr] << 8)/(float)(0xFFFFFFFF);

Last point: The ADC value might not be scaled to one. So it might be necessary to muliply the whole Expression by your maximum floating point value.

EDIT

I now see the necessity of shifting it to 32 bit. The compiler will then be able to perform the correct sign interpretation when converting to float. Thanks, for the correction.

Loamsiada
  • 444
  • 3
  • 11
  • I think the 32-bit conversion is there because it is a signed number – geza Jun 28 '17 at 11:19
  • You can also have 24-bit signed numbers. It always depends on the number format which must be known. The documentation of the ADC chip describes the format. Usually the highest bit is used as sign bit, where the number is "wrapped" to the negative values. So a 24-Bit "zero" with the highest bit set (0x800000) means the lowest possible number which is -16777216 in this 24 bit example. – Loamsiada Jun 28 '17 at 11:25
  • 1
    exactly. That's why the `<<8` is there. To shift the sign bit from the 23 bit into the 31, so it will be handled a negative number if the 24-bit number has the highest bit set. – geza Jun 28 '17 at 11:31