1

An implementation function from the nice little Wiegand library YetAnotherArduinoWiegandLibrary prints a hexadecimal representation of a facility # & card # (8-bit facility #, 16-bit card #) — 24 bits of a 26-bit stream that comes across the wire.

Example encoded 24-bit number: 7111097 (decimal). Hex equivalent: 6C81B9. The 6C portion is the facility # (decimal: 108). 81B9 is card # (decimal 33209).

This function from the library's example usage serial prints the hexadecimal format of the number:

void receivedData(uint8_t* data, uint8_t bits, const char* message) {
 Serial.print(message);
 Serial.print(bits);
 Serial.print("bits / ");
 //Print value in HEX
 uint8_t bytes = (bits+7)/8;
 for (int i=0; i<bytes; i++) {
 Serial.print(data[i] >> 4, 16); //1st, 3rd, 5th hex digit
 Serial.print(data[i] & 0xF, 16); //2nd, 4th, 6th hex digit
 }
 Serial.println();
}

What I've tried to do unsuccessfully so far is to loop over the bits to also serial print the two decimal formatted numbers (facility:card) in the final output form: 108:33209

asked Mar 3, 2020 at 18:33
4
  • why do you need to loop over bits? ... the for loop already manipulates bytes of data Commented Mar 3, 2020 at 18:49
  • @jsotola With or without a for loop how do you output the two separate logical numbers in decimal format? Commented Mar 3, 2020 at 18:57
  • how do you convert 3 bytes to a single number? .... think about this ... what mathematical process do you follow to convert 4 hundreds , 6 tens and 8 units to 468? Commented Mar 3, 2020 at 19:05
  • I wonder why that sample code prints each nibble of a byte separately? Doesn't Serial.print(255, 16); output FF? So couldn't the inside of the for loop just read Serial.print(data[i], 16); Commented Mar 4, 2020 at 1:39

1 Answer 1

2

Your code loops from the high order byte to the low order byte, printing each byte as 2 hex digits.

If you want instead to print the first byte as a decimal value, and then the remaining bytes as another decimal value, then do this:

Print byte 0 in base 10:

 Serial.print(data[0]); //first byte
 Serial.print(":");

Then loop through the remaining bytes, building a result as a decimal value, and print that:

unsigned long total = 0;
for (int i=1; i<bytes; i++) //Skip the first byte
{
 total = total << 8; //Shift the previous total by 8 bits. 
 //(The same as multiplying by 256, but faster)
 total += data[i]; //Add in the new value
}
Serial.println(total);

The sample code you posted is written to handle a variable number of bytes. The code above does the same thing with decimal results. It's much simpler if you know you will always have 3 bytes or 4 bytes:

For 3 bytes:

 Serial.print(data[0]); //first byte
 Serial.print(":");
 long total = long(data[1])*256 + data[2]);
 Serial.println(long(total); 
answered Mar 4, 2020 at 1:26
2
  • I wrote the second version of the code using long ints, since I started out with printing an 8-bit value followed by a 24 bit value. If the second value is only 2 bytes (16 bits) you could change the data type to unsigned int Commented Mar 4, 2020 at 1:43
  • This is great and makes sense of it for me, thank you. Commented Mar 4, 2020 at 5:12

Your Answer

Draft saved
Draft discarded

Sign up or log in

Sign up using Google
Sign up using Email and Password

Post as a guest

Required, but never shown

Post as a guest

Required, but never shown

By clicking "Post Your Answer", you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.