By Ben Nitkin on
Second post! That's a thing, right? Good.
Last time, I got as far as reading out bits from the card. I noticed a few things about the output bits:
- The first half of the code was always the same.
- The code was around 35 bits long.
With enough cards, I could have reverse-engineered the card code, but Cyborg Mode is easier. A few quick searches turned up a site explaining the HID format. In essence, the card has two pieces of data stored on it: a 12 bit facility code (same of all Lafayette cards), and a 20-bit card code (different on each). A quick aside: 220=1,048,576, so Lafayette's 2,500 students use only a smidge of the possible combinations.
So, I have 35 bits read in, but only the last 20 are relevant for our use case. I have bits coming in one at a time, and I need to check for a match after the stream stops.
I still need to decide how to store and check data. An int only holds 8 or 16 bits (depending), and strings are messy to create. Longs, though, hold 32 bits of data - almost the whole card. I could create a revolving long of the last 32 bits read. It would hold almost an entire card, and flush out the last data read before beginning. The << operator shifts bits left, and the + operator will add. (Shocking, I know.) Writing the new code was incredibly easy. Just add a few lines to the working program from last time.
//The volatile keyword is required for variables modified inside of an interrupt.
volatile long current = 0;
volatile boolean changed = false;
void DATA1() {
current = current << 1; //Shift bits left
current += 1; //Add one to the end.
changed = true;
Serial.print(1);
}
void DATA0() {
//Shift bits left; (add zero)
current = current << 1;
changed = true;
Serial.print(0);
}
void setup() {
Serial.begin(9600);
attachInterrupt(0, DATA0, FALLING); // DATA0 (green) on HID reader, Pin 2 on Arduino
attachInterrupt(1, DATA1, FALLING); // DATA1 (white) on HID reader, Pin 3 on Arduino
delay(10);
}
void loop() {
delay(100);
if(changed) { //Print iff the value has changed.
Serial.println(current);
changed = false;
}
}
This new code tracks the last 32 bits of the card, which is enough to uniquely identify all cards on campus. The ones I scanned all had values of around -881170000, give or take a few hundred thousand. That is, the first bits are all the same, and the ones towards the end aren't.
I added functionality for checking the read key against a list of approved keys, and that's where I stand as of writing. To do:
- Add a servo to actually unlock the door
- Use a button and EEPROM to allow for adding more keys
- Other features? Alarm? Timeout? Awesomesauce?