Hi all,

I'd like to know neat tricks for converting 10-bit offset binary value with 3-bit scaling value to 16-bit signed integer.

Imagine you receive 13 actual bits from a device, of which 10 is the mantissa or value for a 10-bit DAC, and other 3 bits are the controls for a 7-step analog attenuator after the DAC. It means you can have a 16-bit range with 10-bit resolution. 10-bit offset binary means value 0 is most negative -512, 0x1FF is -1, 0x200 is midpoint 0, 0x201 is +1 and 0x3FF is most positive 511, and so to convert that to signed integer you can just XOR the MSB 0x200, after which 0x200=-512, 0x3FF=-1, 0x00=0, 0x01=+1, and 0x1FF=+511.

To convert that into linear 16-bit integer, I now use this code:

int16_t convert(uint16_t indata) { // indata format // 3 MSBs is the shift value 1..7, 0 never encountered // 10 bits DAC value // 3 LSBs unused bits, random even uint16_t shiftval; int16_t value; // first set 10-bit offset binary value to MSB value=(indata<<3)&0xFFC0; // convert offset binary to signed integer, toggle MSB value=value^0x8000; // since shiftval bits originally means 1=minimum range and 7=maximum range, we need to invert it for right shift shiftval=7-(indata>>13); // do the attennuation by 0 to 6 bits value=value>>shiftval; }

Now I'd like to be more efficient, so is there a way to do the sign extension without first copying to MSB and then doing right shifts with negated shift value? Can I just XOR it with some other value based on BIT9 and then do left shifts with (indata>>13)-1 ?

Would this work?

int16_t convert(uint16_t indata) { // indata format // 3 MSBs is the shift value 1..7, 0 never encountered // 10 bits DAC value // 3 LSBs unused bits, random even uint16_t shiftval; int16_t value; // first set 10-bit offset binary value to LSB value=(indata>>3)&0x3FF; // convert offset binary to signed integer if (value&0x200) // positive { value=value^0x200; } else // negative { value=value^0xFE00; } // shiftval bits originally means 1=minimum range and 7=maximum range shiftval=(indata>>13)-1; // do the gain by 0 to 6 bits value=value<<shiftval; }