Most efficient way to convert 20b 2's complement to SDword

Started by trastikata, Jun 27, 2021, 03:17 PM

Previous topic - Next topic

trastikata

Hello,

as the title says, what would be the most efficient way of converting a 20 bit 2's complement data, read from a sensor's registers, to SDword? The data is read from three 8bit sensor registers.

Thank you

top204

There are several ways of sign extending, but the method below should work efficiently.

    Dim DwordIn As Dword                                    ' Holds the signed 20-bit value
    Dim Dwordout As SDword                                  ' Holds the sign extended 32-bit value
   
    DwordIn = %00000000000011111111111111111111             ' Load Dwordin with a signed 20-bit value of -1
'   
' Sign extend a 20-bit value to a 32-bit value
'     
    If DwordIn.19 = 1 Then                                  ' Is the sign bit set?
        Dwordout.Byte3 = %11111111                          ' Yes. So set all of byte3
        Dwordout.Byte2 = DwordIn.Byte2 | %11110000          ' Or in set bits of byte2
        Dwordout.Byte1 = DwordIn.Byte1                      ' Transfer byte1 to byte1
        Dwordout.Byte0 = DwordIn.Byte0                      ' Transfer byte0 to byte0
    Else                                                    ' Otherwise... The value is not signed
        Dwordout = DwordIn                                  ' So transfer dwordin to dwordout
    EndIf

trastikata

Quote from: top204 on Jun 27, 2021, 06:11 PMThere are several ways of sign extending, but the method below should work efficiently.

Thank you Les, I know there was a better way than my For-Next loop and bit manipulation :)

top204

Here's a tiny bit more efficient way, because it loads the lower 16-bits first, then alters the higher 16-bits, instead of transfering the lower 16-bits in each comparison.

    Dim DwordIn As Dword                                    ' Holds the signed 20-bit value
    Dim Dwordout As SDword                                  ' Holds the sign extended 32-bit value
   
    DwordIn = %00000000000011111111111111111111             ' Load Dwordin with a signed 20-bit value of -1
'   
' Sign extend a 20-bit value to a signed 32-bit value
'    
    Dwordout.Word0 = DwordIn.Word0                          ' Transfer the lower 16-bits
    If DwordIn.19 = 1 Then                                  ' Is the sign bit set?
        Dwordout.Byte3 = %11111111                          ' Yes. So set all the bits of byte3
        Dwordout.Byte2 = DwordIn.Byte2 | %11110000          ' Or in the permanently set bits of byte2
    Else                                                    ' Otherwise... the value is not signed. So...
        Dwordout.Word1 = DwordIn.Word1                      ' Transfer the high 16-bits   
    EndIf

top204

Here's an even more efficient method using a 24-bit Long variable to hold the 20-bit value. It saves about 6 bytes of code and operates a bit faster.

    Dim LongIn As Long                                      ' Holds the signed 20-bit value
    Dim DwordOut As SDword                                  ' Holds the sign extended 32-bit value
   
    LongIn = %000011111111111111111111                      ' Load LongIn with a signed 20-bit value of -1
'   
' Sign extend a signed 20-bit value to a signed 32-bit value
'    
    DwordOut.Dword = LongIn                                 ' Transfer the 20-bit value to unsigned DwordOut
    If LongIn.19 = 1 Then                                   ' Is the sign bit set?
        DwordOut.Byte3 = %11111111                          ' Yes. So set all the bits of byte3
        DwordOut.Byte2 = LongIn.Byte2 | %11110000           ' Or in the permanently set bits of byte2
    EndIf