Bitshift problem - Endian issue?

Status
Not open for further replies.

thomas7

Member
Hello,

i have a problem and i do not understand why this happen.

I want to write a function where i can extract X-Bits from a Byte Array of 8 Bytes.

What i need are i.e. 12 Bit, started from Byte 0 Bit 4 to Byte 1 Bit 7.
This may differ, that's why i want to have this function which i just call and say start-bit and length.

This is what i have:

Code:
unsigned char byte1[8] = { 0x12, 0x34, 0x56, 0x78, 0x9A, 0xBC, 0xDE, 0xFF };

unsigned long result = 0;
unsigned long realResult = 0;

unsigned long ByteToLong( byte const *pData, byte BitOffset, byte BitSize)
{
  unsigned long bytetolongvalue = 0;
  
  byte c = ( BitOffset + BitSize ) / 8;
  c * 8 == BitOffset + BitSize ? 0 : c++;
  
  memcpy ( &bytetolongvalue, pData, c );
  
  bytetolongvalue <<= ( sizeof ( bytetolongvalue ) - c ) * 8 + BitOffset;
  bytetolongvalue >>= 8 * sizeof ( bytetolongvalue ) - BitSize;
  
  return bytetolongvalue;
}

void setup()
{
  Serial.begin(9600);


  Serial.println("--12 Bit 4...16--");
  result = ByteToLong(byte1, 4, 12);
  Serial.print("Byte To Long result: ");
  Serial.println(result, HEX);

  // CORRECT RESULT IS:
  realResult = ((byte1[1] & 0xFF) << 4);
  realResult |= (((byte1[0]) >> 4) & 0x0F);
  Serial.print("realResult: ");
  Serial.println(realResult ,HEX);

}

void loop()
{
	
  
}

The result of the function is Hex: 412
But i expect 341.

I also played around with byteswap, endians and so on, but i could not find the right way.

Can someone help me to find a solution what the problem is?
It must be something with the memory storage of the bytes, that this is swapped.

But how is it swapped and what should i do? If the memory / processor is using the bytes in a different way, do i have to bring the byte array in a form that the processor is using it like i want and then swap it back?

Thanks a lot.

Thomas
 
What you have done is equivalent to this:

Code:
union {
    uint8_t byte1[8] = { 0xff, 0xde, 0xbc, 0x9a, 0x78, 0x56, 0x34, 0x12 };
    uint64_t val;
} x;
 
(x.val >> 3) & 0xfff) = 412
 
I suspect there is something wrong in the shifters. Looking at your data
( damn proportional fonts )
Code:
   result   412
   expect  341

So it looks like you shifted up too far and lost the 3 off the top of the long.
And did not shift down far enough and retained the 2 in the nibble on the least significant end. Or this shift was ok and this result was due to the previous shift up being incorrect.
 
This should do the trick:
Code:
unsigned char byte1[8] = { 0x12, 0x34, 0x56, 0x78, 0x9A, 0xBC, 0xDE, 0xFF };

unsigned long result = 0;
unsigned long realResult = 0;

unsigned long ByteToLong( byte const *pData, byte BitOffset, byte BitSize)
{
  uint64_t bytetolongvalue;
  
  memcpy ( &bytetolongvalue, pData, 8 );

  // Shift to the left removes unwanted bits on the left.
  bytetolongvalue <<= 64 - BitSize - BitOffset;
  // Shift to the right removes unwanted bits on the right
  bytetolongvalue >>= 64 - BitSize;
  
  return bytetolongvalue;
}

void setup(void)
{
  Serial.begin(9600);


  Serial.println("--12 Bit 4...16--");
  result = ByteToLong(byte1, 4, 12);
  Serial.print("Byte To Long result: ");
  Serial.println(result, HEX);

  // CORRECT RESULT IS:
  realResult = ((byte1[1] & 0xFF) << 4);
  realResult |= (((byte1[0]) >> 4) & 0x0F);
  Serial.print("realResult: ");
  Serial.println(realResult ,HEX);

}

void loop(void)
{
}

Output:
Code:
--12 Bit 4...16--
Byte To Long result: 341
realResult: 341

The Teensy processor is little-endian, so in this declaration:
Code:
unsigned char byte1[8] = { 0x12, 0x34, 0x56, 0x78, 0x9A, 0xBC, 0xDE, 0xFF };
the low order byte is 0x12 and when interpreted as a 64-bit integer the whole thing is:
Code:
0xFFDEBC9A78563412

Pete
 
Pete, that is fantastic.

Thanks so much.
So, as soon as i copy just x Bytes it throws the bytes in little endians, and i could not do it as easy as i want.

Your solution is perfect, easy, small and working :)
It looks that i was thinking too complicated.

Cheers,
Thomas
 
Status
Not open for further replies.
Back
Top