0

I have a byte array containing 0xE1 and 0x04 and I need to manipulate it into producing 0x104 and I'm struggling with it. I've been told to do the following:

  1. 0xE1 AND 0x1F = 0x01
  2. Rotate left 8 bits = 0x100
  3. 0x04 ADD 0x100 = 0x104

The raw instructions from the manufacturer:

  • 0xE1 is greater than 0xE0
  • 0xE1 AND 0x1F = 0x01
  • Rotate left 8 bits = 0x100
  • Read next byte = 0x04
  • 0x04 Add 0x100 = 0x104

I can't get #2 to work. I've tried the extension methods from this SO question, the BitRotator.RotateLeft method, and the BitOperations.RotateLeft method, all without successfully getting 0x100. What am I supposed to do to get to 0x100?

I've never had to do bit-level operations before, so I'm struggling with it.

Update

I'm parsing a GPS report. There's fields in the report that are 1 or 2 bytes in size. If the value of byte 0 is less than 0xE0 then the size of the field is 1 byte. Else, the size is 2 bytes and I'm supposed to use the steps above to get to the real value. To quote the docs:

Any fields designated as 1-byte/2-byte fields are unsigned integers using the following encoding: If the 1st byte is less then 0xE0 (decimal 224) then the field size is 1-byte and the value is the value of the entire byte. If the 1st byte is greater-or-equal to 0xE0 then the field size is 2-bytes and the value is the value of the lsb 13-bits of the 2-byte field (most-significant byte first).

Here's the method I'm using (prototyping in LINQPad):

private static OneTwoField<Type> GetItemType(
    ReadOnlySpan<byte> itemBytes) {
    if (itemBytes[0] < 224) {
        return new OneTwoField<Type>(1, (Type)itemBytes[0]);
    }

    itemBytes[0..2].DumpToTable();

    //  What do I do to get to the real value?
    var type = ???;

    return new OneTwoField<Type>(2, type);
}

The DumpToTable() extension produces the following:

DumpToTable() results

Here's the OneTwoField<T>:

public struct OneTwoField<T> {
    public OneTwoField(
        byte size,
        T value) {
        Offset = size == 1 ? 0 : 1;
        Size = size;
        Value = value;
    }

    public int Offset { get; }
    public byte Size { get; }
    public T Value { get; }
}

And here's the Type:

[Flags]
public enum Type :
    short {
    General = 0x00,
    Versions = 0x104
}
Gup3rSuR4c
  • 9,145
  • 10
  • 68
  • 126
  • The result of `0x100` does not fit in a `byte` so what is the actual type you're using? A left rotate of 8 bits on a byte should just result in the exact same value. Please show the exact code you tried so we can help pinpoint the problem. – juharr Jun 30 '20 at 15:48
  • @juharr, I've updated the question with more information about what I'm dealing with and how I'm dealing with it. – Gup3rSuR4c Jun 30 '20 at 16:14
  • That quote says _lsb 13-bits of the 2-byte field_. I assume that should be "last" and not "lsb"? – juharr Jun 30 '20 at 16:19
  • Also `Type` is a horrible name to use for your enum since that's already the name of a class. And that is clearly not a set of flags (those would have powers of 2 increasing from 0 up). It seems like you really just need constant values instead and `OneTwoField` doesn't need to be generic – juharr Jun 30 '20 at 16:22
  • That's what the docs say, so I can't really answer the question. All I have to go off of is the docs (which have proven wrong in other areas) and the instructions provided by the manufacturer on how to read if its 2 bytes (I've quoted them as well now). Naming is all up in the air right now. I've had to change it a dozen times as I scrape by. It should probably be `ItemType`, but like I said, this is a prototype. – Gup3rSuR4c Jun 30 '20 at 16:27
  • When the first byte is < 0xE0 then the value is just the second byte, otherwise I think you want `((bytes[0] & 0x1F) << 8) | bytes[1]` but your issue seems to be with trying to turn that value into an enum. Just save it as a `short` or `int` or whatever type will hold the 2 byte value. – juharr Jun 30 '20 at 16:29
  • YES! That worked! Please post it as an answer so I can accept it. You're right about the `[Flags]` on `Type`, I've removed the attribute. I made `OneTwoField` generic because it's used in other parts of the report. So far its either a `short` or the `Type` enum which I've constrained to a short, so I guess I could un-genericize it? Thanks for the help, I really appreciate it! – Gup3rSuR4c Jun 30 '20 at 16:40

1 Answers1

1

Bitwise left shift operator <<

byte step1 = 0xE1 & 0x1F; //0x01
short step2 = step1 << 8; //0x100
Klaycon
  • 10,599
  • 18
  • 35