Read HEX in data stream

Hi i have a problem with reading HEX from a data stream. The data stream comes from a http post request.

The HEX data could look like this. 9f 00 3c 5b 7b 22 62 75 74 74 6f 6e

I need a way to to read e.g. 9f from the stream and store them in a uint8_t.

I've only managed to read them separately, like reading 9, f etc. What i am doing wrong?

Thanks in advance.

Without seeing your code, your guess is as good as anybody else's.

Oh yea ofc.

Here it is.

  uint8_t byte[2];
  uint8_t counter = 0;
  while(client.available())
  {  
    c = client.read();
    byte[counter] = c;
    if (counter == 1)
    {
        uint8_t b1 = byte[0];
        uint8_t b2 = byte[1];
        counter = 0;
        Serial.write((b1 << 8) | b2);
        Serial.write("\n");
    }
    else
    {
        counter++;
    }
  }

It only print half of the hex value.

use Serial.print, not Serial.write

What's this

 Serial.write((b1 << 8) | b2);

Youre shifting b1 out of existence then ORing it with B2 So thats effectively just B2.

You've already got the two bytes in byte[0] and byte[1].
Why don't you just print them instead?

@jremington

How should that help anything?

@kenf

That is how you concat Hexadecimals, i've tried to shift only by 4 bits instead, since it is only a half byte, but i'm still not getting the correct result.

-Because i don't want to want to print them. I want to concat byte[0] with byte[1] so it in total gives me one byte and save that on my SD card.

Rensen:
@kenf

That is how you concat Hexadecimals, i've tried to shift only by 4 bits instead, since it is only a half byte, but i'm still not getting the correct result.

If you shift an 8 bit value held by an 8 bit variable (either direction) you end up with zero. Don't take my word for it, just try it yourself.

-Because i don't want to want to print them. I want to concat byte[0] with byte[1] so it in total gives me one byte and save that on my SD card.

You are not understanding the difference between a character and a hex digit. If you genuinely had two hex digits of data (ie just 0 - 15) then you could shift 4 bits before combining.

But each BYTE that you have is 8 bits because it's the character code of a hex digit. So for instance, the character code for "0" is 48, but that's unimportant, because shifting ANYTHING 8 places within an 8 bit wide variable, reduces it to nothing.

Well I'm on my knees.

What should i do? How can i achieve what i want?

Somrthing like this might work. I can't even check if it compiles as it's not a complete sketch. So obviously you may have some debugging to do.

uint8_t byteValue=0; //just the one byte
bool nibble=0;

while(client.available())
    {  
      c = client.read();
      byteValue *= 16;
      if( (c >= '0') && (c <= '9') )
        byteValue += (c - '0');
      if( (c >= 'a') && (c <= 'f') )
        byteValue += (c - 'a' + 10);
      if( (c >= 'A') && (c <= 'A') )
        byteValue += (c - 'A' + 10);
      nibble=!nibble;
      if(!nibble)
        {
        Serial.print (byteValue,HEX);
        byteValue=0;
        }
    }

Thanks it seems to work just fine. Can i bother you to explain why?

Rensen:
Thanks it seems to work just fine. Can i bother you to explain why?

On each pass the variable c holds the character hex code of a digit. if it's numeric then we have to deduct 48 (the character code of '0') to get the actual value that this character represents.

If it's in the range of a-f we can do the same trick, (just deduct the character code of 'a') but this would give us a value in the range of 0 to 5 (whereas we want a value of 10 - 15) So then we have to add 10;

For the upper case do the same thing except we deduct the character code of 'A' instead.

If this is the second character, we have to multiply the first by 16 (actually shifting 4 bits would work) before adding this one on. Although this multiplication isn't necessary before storing the first character, it does no harm as multiplying 0 x 16 is still 0.

the boolean variable nibble, is just used to keep track of which digit we're dealing with. first time through it will hold 0, gets NOTed to 1. A test for this being zero returns false so it doesn't print yet.

Second time through the loop the 1 gets NOTed to 0, so this time it does the print and zeros the value ready for the next pair of characters.

@jremington
How should that help anything?

Using Serial.write to the monitor results in unreadable garbage. Serial.print is designed to produce human-readable output.

In hexadecimal representation (0-9, A-F), each character represents 4 bits of a byte. KenF provided code to convert between this representation and the binary value.