Android Question 7 to 8 bit decoding

Hermannautomation

Member
Licensed User
Longtime User
Hello,

I get a stream with 8 bytes of 7 bits each.
Is there a way to convert this into 7 bytes of 8 bits each.

0123456, 7012345, 67... --> 01234567, 01234567,...

Thank you very much. I've been looking for a long time.
 

JordiCP

Expert
Licensed User
Longtime User
Should be something like this
B4X:
Dim recodeFrom7To8( src() as Byte, dst() as Byte )
  For k=0 to 6 
    'Dim val as int = Bit.Or( Bit.shiftLeft(src(k),8), src(k+1) )
    'Dim val as int = Bit.Or( Bit.shiftLeft(src(k),8), Bit.And(src(k+1),0xFF) )  '<-- Edited!
     Dim val as int = Bit.Or( Bit.shiftLeft(src(k),7), Bit.And(src(k+1),0x7F) )  '<-- Edited once again!
    dst(k) = Bit.And( Bit.ShiftRight( val, 6-k) , 0xFF )
  Next
End Sub
 
Last edited:
Upvote 0

Hermannautomation

Member
Licensed User
Longtime User
Wow JordiCP, thank you for the effort you have made.
I have to admit that I am not used to this kind and I do not understand the solution sufficiently to apply it.

I would be grateful if you could help me to apply it. Perhaps the original C++ Code helps to understand my issue:

There are x-bytes (x% 8 = 0) to be decoded from 7 to 8 bits. Later there should be y-bytes (y% 7 = 0).

B4X:
   while(start_pointer < end_pointer)   
   {
      *msg_ptr++ = ((start_pointer[0] << 1)&0xFE) | ((start_pointer[1] >> 6)&0x01);
      *msg_ptr++ = ((start_pointer[1] << 2)&0xFC) | ((start_pointer[2] >> 5)&0x03);
      *msg_ptr++ = ((start_pointer[2] << 3)&0xF8) | ((start_pointer[3] >> 4)&0x07);
      *msg_ptr++ = ((start_pointer[3] << 4)&0xF0) | ((start_pointer[4] >> 3)&0x0F);
      *msg_ptr++ = ((start_pointer[4] << 5)&0xE0) | ((start_pointer[5] >> 2)&0x1F);
      *msg_ptr++ = ((start_pointer[5] << 6)&0xC0) | ((start_pointer[6] >> 1)&0x3F);
      *msg_ptr++ = ((start_pointer[6] << 7)&0x80) | ((start_pointer[7] >> 0)&0x7F);
      start_pointer += 8;
   }

Many thanks in advance.
 
Upvote 0

JordiCP

Expert
Licensed User
Longtime User
Hi (just note that there was a mistake :D, now I think it is at last corrected)

Think of all the 7-bit bytes, one after the other, similar as what you wrote at the beginning

Each 8-bit byte in the destination array, will be composed of a certain number of bits from one byte, and a certain number of bits of the next byte
this is what is is done in the first line (Bit.Or is a logical OR of two numbers. We have just shifted the first 7 positions to the left for the first byte, and masked the second also with 7 bits (0x7F), just in case)
B4X:
Dim val as int = Bit.Or( Bit.shiftLeft(src(k),7), Bit.And(src(k+1),0x7F) )
so we have, in val, when k=0, something equivalent to 01234567012345 . Our result is here, but we only want a part of it (the first 01234567) ---> So we shift this result 6 positions to the right (inner operation) and the apply a mask to keep only 8 bits (0xFF) with this line
B4X:
dst(k) = Bit.And( Bit.ShiftRight( val, 6-k) , 0xFF )

The C++ code does the same, but applying a given mask for each index instead of using a for. Except for mistakes on my part, results should be the same.

--- If you have N groups of 8 bytes, then my code should be applied N times, once for each group, since it behaves differently regarding the start pointer
 
Upvote 0

Hermannautomation

Member
Licensed User
Longtime User
Thank you for the extensive explanation.
I´m sorry to ask again, but i spent all over the day without approaching a solution.

The problem is:

Your code recodes the first group of 7-bytes "00 00 21 40 00 14 00" to (8-bytes):
B4X:
your Code_:  "00 01 0C 00 05 00 00 00"
should be:   "00 01 0C 00 05 00 01 00"

The following groups of Septets are completely wrong recoded.
01 00 04 40 01 20 14 is recoded to:
B4X:
 your Code_:  "02 00 24 00 28 0A 00"
should be:   "12 00 14 05 00 00 0C"

Maybe you can look at my code and see the error:
B4X:
Dim septet(8) As Byte
Dim octet(8) As Byte

' - iterate every Septet
' For testing: ONLY the first one, srcOff = 0

byteconv.ArrayCopy(msg, srcOff, septet, 0, 7)
'Copy the first 7 Bytes in septet
'septet : "00 00 21 40 00 14 00

recodeFrom7To8(septet, octet)

And your recodeFrom7To8:
B4X:
Sub recodeFrom7To8( src() As Byte, dst() As Byte )
  For k=0 To 6
     Dim val As Int = Bit.Or( Bit.shiftLeft(src(k),7), Bit.And(src(k+1),0x7F) )  '<-- Edited once again!
    dst(k) = Bit.And( Bit.ShiftRight( val, 6-k) , 0xFF )
  Next
End Sub
 
Upvote 0

JordiCP

Expert
Licensed User
Longtime User
You are doing it wrong (I don't make mistakes :D)

If you are converting a group of 7-bit bytes to another of 8-bit bytes, the input must be composed of 8 bytes and the output of 7 bytes(or multiples), as you said in your first post. In your example you are doing just the opposite: you are getting the input in groups of 7 bytes and get groups of 8 bytes from the output.


Group of 8 7-bit bytes ------> SuperMachineIsWorkingLookLookItsFantastic ---> group of 7 8-bit bytes

You did
"00 00 21 40 00 14 00 [00]" ----> SuperMachineDoesItsWorkButYouForgotToaddTheEightByteSoItAssumesItIsZero --> "00 01 0C 00 05 00 00"

You should have done
"00 00 21 40 00 14 00 01" ----> SuperMachineDoesItsWorkNowWithAllDataCorrect --> "00 01 0C 00 05 00 01"

For the rest of the groups, as you are splitting the origin in groups of 7 instead of groups of 8, then the error is obvious
 
Upvote 0
Top