This post is older than 2 years and might not be relevant anymore
More Info: Consider searching for newer posts

convert c_float to ieee_11073_16bit_float

Hello,

I need to convert a standard 32 bit floating point number to IEEE-11073 16-bit FLOAT with 12-bit mantissa and 4-bit exponent (source: https://infocenter.nordicsemi.com). Is there already an implementation in the sdk or an example somewhere? I tried it the following way, but the numbers in the nrf connect app where wrong.


#include "ble_bps.h"
ieee_float16_t c_float32_to_ieee_11073_float16(float input)
{
    ieee_float16_t ret;
    uint32_t input_raw = *((uint32_t*)&input);
    ret.mantissa = (input_raw >> 23) & 0xf;
    ret.exponent = (input_raw & 0xfff);
    return ret;
}

Parents Reply
  • the arm_math.h and the post your referenced are using 32 bit floating numbers. I already checked those. I am also confused about the 12 bit mantissa and 4 bit exponent format. The standard half precision floating point number seems to be 5 bit exponent and 11 bit mantissa (source: wikipedia). Could you give me a more detailed description of the IEEE-11073 16-bit FLOAT format? I cant find anything about exponent encoding and INF and NAN definition.

Children
  • I have zero experience with IEEE-11073, I suggest you get a copy of the specification if you intend to use it. 

    What the SDK devs have done is this:

    /**@brief SFLOAT format (IEEE-11073 16-bit FLOAT, 
    defined as a 16-bit vlue with 12-bit mantissa and 4-bit exponent. */
    typedef struct
    {
      int8_t  exponent;                                /**< Base 10 exponent, only 4 bits */
      int16_t mantissa;                                /**< Mantissa, only 12 bits */
    } ieee_float16_t;
    
    
    
    uint16_t encoded_sfloat;
    ieee_float16_t sfloat;
    
    // Taken from the Blood Pressure Service example:
    encoded_sfloat = ((sfloat.exponent << 12) & 0xF000) |
    ((sfloat.mantissa << 0) & 0x0FFF);
    
    //Now you can encode an exponent + mantissa into a uin16_t
    
    



  • I currently have no access to the specification. But I want to use your SDK to transmit bloodpressure measurments. It seems like this is only possible by using the 16 bit float defined in IEEE-11073. Or is there another solution?

  • I managed to get it done.

    Here is the final code:

    ieee_float16_t c_float32_to_ieee_11073_float16(float input)
    {
    	ieee_float16_t ret;	
    	ret.exponent = 0;
    	while(input > (float)0x7ff){
    		input /= 10;
    		ret.exponent += 1;
    	}
    	while(input*10 < (float)0x7ff){
    		input *= 10;
    		ret.exponent -= 1;
    	}
    	ret.mantissa = (int16_t)input;
    	return ret;
    }

    Thanks for your help.

    Alex

  • That's not gonna work, for larger numbers the mantissa gets truncated. 
    You need an algorithm that always returns a float with 12-bit precision. 


  • Your right, thanks. I added an -INF and +INF limitation. For convinience, I set the max values a little bit less than the real limits of the 16 bit float. This should solve the issue.

     

    ieee_float16_t c_float32_to_ieee_11073_float16(float input)
    {
    	ieee_float16_t ret;	
    	if(input != input) //check for NAN
    	{
    		ret.exponent = 0;
    		ret.mantissa = 0x07ff;
    		return ret;
    	}
    	else if(input > (float)2E10) //check for +INF
    	{
    		ret.exponent = 0;
    		ret.mantissa = 0x07FE;
    		return ret;
    	}
    	else if(input < (float)-2E10) //check for -INF
    	{
    		ret.exponent = 0;
    		ret.mantissa = 0x0802;
    		return ret;
    	}
    	else
    	{
    		ret.exponent = 0;
    		while(input > (float)0x7ff){
    			input /= 10;
    			ret.exponent += 1;
    		}
    		while(input*10 < (float)0x7ff){
    			input *= 10;
    			ret.exponent -= 1;
    		}
    		ret.mantissa = ((int16_t)input) & 0xfff;
    		ret.exponent &= 0xf;
    		return ret;
    	}
    }

Related