Skip to content

Instantly share code, notes, and snippets.

@ShakataGaNai
Last active January 21, 2024 22:24
Show Gist options
  • Star 9 You must be signed in to star a gist
  • Fork 5 You must be signed in to fork a gist
  • Save ShakataGaNai/4319d3e82a858c9d00c1d80f20da81a3 to your computer and use it in GitHub Desktop.
Save ShakataGaNai/4319d3e82a858c9d00c1d80f20da81a3 to your computer and use it in GitHub Desktop.
/*
* HID RFID Reader Wiegand Interface for Arduino Uno
* Originally by Daniel Smith, 2012.01.30 -- http://www.pagemac.com/projects/rfid/arduino_wiegand
*
* Updated 2016-11-23 by Jon "ShakataGaNai" Davis.
* See https://obviate.io/?p=7470 for more details & instructions
*/
#define MAX_BITS 100 // max number of bits
#define WEIGAND_WAIT_TIME 3000 // time to wait for another weigand pulse.
unsigned char databits[MAX_BITS]; // stores all of the data bits
unsigned char bitCount; // number of bits currently captured
unsigned char flagDone; // goes low when data is currently being captured
unsigned int weigand_counter; // countdown until we assume there are no more bits
unsigned long facilityCode=0; // decoded facility code
unsigned long cardCode=0; // decoded card code
int LED_GREEN = 11;
int LED_RED = 12;
int BEEP_BEEP = 10;
// interrupt that happens when INTO goes low (0 bit)
void ISR_INT0() {
//Serial.print("0"); // uncomment this line to display raw binary
bitCount++;
flagDone = 0;
weigand_counter = WEIGAND_WAIT_TIME;
}
// interrupt that happens when INT1 goes low (1 bit)
void ISR_INT1() {
//Serial.print("1"); // uncomment this line to display raw binary
databits[bitCount] = 1;
bitCount++;
flagDone = 0;
weigand_counter = WEIGAND_WAIT_TIME;
}
void setup() {
pinMode(LED_RED, OUTPUT);
pinMode(LED_GREEN, OUTPUT);
pinMode(BEEP_BEEP, OUTPUT);
digitalWrite(LED_RED, HIGH); // High = Off
digitalWrite(BEEP_BEEP, HIGH); // High = off
digitalWrite(LED_GREEN, LOW); // Low = On
pinMode(2, INPUT); // DATA0 (INT0)
pinMode(3, INPUT); // DATA1 (INT1)
Serial.begin(9600);
Serial.println("RFID Readers");
// binds the ISR functions to the falling edge of INTO and INT1
attachInterrupt(0, ISR_INT0, FALLING);
attachInterrupt(1, ISR_INT1, FALLING);
weigand_counter = WEIGAND_WAIT_TIME;
}
void loop()
{
// This waits to make sure that there have been no more data pulses before processing data
if (!flagDone) {
if (--weigand_counter == 0)
flagDone = 1;
}
// if we have bits and we the weigand counter went out
if (bitCount > 0 && flagDone) {
unsigned char i;
Serial.print("Read ");
Serial.print(bitCount);
Serial.print(" bits. ");
if (bitCount == 35) {
// 35 bit HID Corporate 1000 format
// facility code = bits 2 to 14
for (i=2; i<14; i++) {
facilityCode <<=1;
facilityCode |= databits[i];
}
// card code = bits 15 to 34
for (i=14; i<34; i++) {
cardCode <<=1;
cardCode |= databits[i];
}
printBits();
}
else if (bitCount == 26) {
// standard 26 bit format
// facility code = bits 2 to 9
for (i=1; i<9; i++) {
facilityCode <<=1;
facilityCode |= databits[i];
}
// card code = bits 10 to 23
for (i=9; i<25; i++) {
cardCode <<=1;
cardCode |= databits[i];
}
printBits();
}
else {
// you can add other formats if you want!
// Serial.println("Unable to decode.");
}
// cleanup and get ready for the next card
bitCount = 0;
facilityCode = 0;
cardCode = 0;
for (i=0; i<MAX_BITS; i++)
{
databits[i] = 0;
}
}
}
void printBits() {
Serial.print("FC = ");
Serial.print(facilityCode);
Serial.print(", CC = ");
Serial.println(cardCode);
// Now lets play with some LED's for fun:
digitalWrite(LED_RED, LOW); // Red
if(cardCode == 12345){
// If this one "bad" card, turn off green
// so it's just red. Otherwise you get orange-ish
digitalWrite(LED_GREEN, HIGH);
}
delay(500);
digitalWrite(LED_RED, HIGH); // Red Off
digitalWrite(LED_GREEN, LOW); // Green back on
// Lets be annoying and beep more
digitalWrite(BEEP_BEEP, LOW);
delay(500);
digitalWrite(BEEP_BEEP, HIGH);
delay(500);
digitalWrite(BEEP_BEEP, LOW);
delay(500);
digitalWrite(BEEP_BEEP, HIGH);
}
@akkaman007
Copy link

I tried the same thing, but the system is not able to detect the card. Do, you think that i need to do some configuration of HID midule before running the main arduino code?

@Bjeurn2
Copy link

Bjeurn2 commented Jun 29, 2018

Dear Mr Davis,
Thank you for the code. I am pretty new to RFID and not familiar with C++ programming.
I have tried to make your code work with my HID Proxkey III (a rfid keyfob that works fine with readers at my work). According to the HID website this should be a 125 kHz keyfob. I connected a Wiegand 125 kHz reader (not specifically a HID reader, but that should not be a problem, should it?) to the Arduino board and used your code. At swiping the keyfob close to the reader, nothing happens; no bleep, no LED change, nothing.
Alternatively, I connected a RDM6300 125 kHz antenna tot the Arduino and used several codes for that combination, but once again, the HID Proxkey III does not provoke any reaction to the RDM6300 antenna.
So, either I am doing something wrong, or the HID Proxkey III is a tough nut to crack. Since I have not come across any code for this specific HID keyfob, I suspect that HID changed the easy to read Proxkey II to the very difficult to read Proxkey III.
Scarce information at websites for the Proxmark 3 however say that the HID Proxkey III is just another 125 kHz keyfob that should be no problem to read.
I hope you can give me some clue where to go.

@Bjeurn2
Copy link

Bjeurn2 commented Jul 1, 2018

I guess I already found the problem, after some extensive reading on the internet: the HID proxkey 3 probably (suggested by "Iceman" and "Marshmellow" on the proxmark 3 website) works with the EM4305 or T55X7 microchip, whereas the HID proxkey 2 works with the EM4100. The tag/key/card reader - obviously, with hindsight - must be able to read the backscatter (returned) signal that has been encoded by the microprocessor. Hence, a reader that can read EM4305/T55X7 microchip encoded backscatter should solve the problem. Does this makes sense?

@Bjeurn2
Copy link

Bjeurn2 commented Aug 14, 2018

Dear Mr Davis,

I have got my hands on a HID reader and the sketch now works fine with all HID Keyfobs III and Keyfobs II, so thank you very much for that.

I am now trying to incorporate your HID sketch in the 13.56 mHz RFID MFRC 522 sketch called "Acces Control", which is in the Arduino Library as an example. I have not succeeded yet, but also ran into a few questions:

  1. Why are you using "char" in lines 14 and 15 of your sketch, and not "int"? I 'd think these values can only be integers.
  2. In line 37, under the ISR for the INT 1, you write the " one" value into the "bitcount" position of the "databits" array. But why is there not a similar line to write a "zero" under the ISR for the INT0? ( eg, line 28 databits[bitCount] = 0;). It seems that the the zeros will be missing in the "databits" array and thus creating the wrong facility and cardcodes. However, this is not the case because the sketch works fine. So, what is the magic here?
  3. In line 119 and 120 you set the cardcode and facilitycode back to 0, to be ready for a new card-read. What then is the purpose of the line 84 (and 90 for cardcode), facilityCode <<=1; ?
    Your help much appreciated.

@ojensen5115
Copy link

ojensen5115 commented Apr 30, 2019

@Bjeurn2:

Not the author, but I suspect I can answer your questions:

  1. char just means a 1-byte value, and can be used numerically (think like the ordinal of a value, 'A' == 65, etc). If the author had declared it as an int, it would be 4 bytes long, which was not needed in this case.
  2. the databits structure is initialized to all zeros on line 123, so there's no need to write a zero. Essentially what's going on is you have a buffer and a pointer into it (e.g. [0]00000). If you read a zero, just move the pointer ([0]00000 -> 0[0]0000), while if you read a one you need to overwrite the value and then move the pointer (0[0]0000 -> 0[1]0000 -> 01[0]000)
  3. lines 84 and 90 shift the value one bit to the left, and then or in the new value pulled from databits. Those lines aren't resetting the values, they're completing them, after which printBits() is called on line 94, after which the values are reset on lines 119 and 120.

@SpeedGP
Copy link

SpeedGP commented Sep 24, 2021

Hey, I love the code, it is the only one I could find that I could edit to decode my 36bit badge!

I'm not done troubleshooting yet, but can you think of any reason this code would crash an Arduino if left to run for over a few hours? I know I have the raw option enabled, but none of the data is stored to a cache or ram or anything like that, correct? (Sorry, I'm a noob).

Thanks!!

@ShakataGaNai
Copy link
Author

@SpeedGP

if left to run for over a few hours

I don't see a reason why it would be a problem. The code does very very little beyond exactly what is required to decode the bits. There is a small memory of stuff, but only used to keep track of the bits coming in. If it's been longer than 3 seconds since the bits came in, then that memory is reset.

In short, I can't see any reason why it would be a problem, but I never actually tested this in production.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment