Commits

Anonymous committed 9d56482

moved wiegand code into a library, and made it use millis() to know when it has stopped recieving bits. per wiegand spec, there should never be more than 200ms between data signals, so if there is, we know we have all the data.

  • Participants
  • Parent commits 635dd7f

Comments (0)

Files changed (5)

File arduino_rfid_controller.pde

 #include <EEPROM.h>
 
 #include "interrupt_support.h"
+#include "wiegand_rfid.h"
 
 #define BUFFERSIZE 20
 #define MAX_NO_CARDS 200
-#define READER_A_DATA0 4
-#define READER_A_DATA1 3
+#define READER_A_DATA0 3
+#define READER_A_DATA1 4
 #define READER_A_GREEN 2
 #define OPEN_DOOR_PIN1 5
 
 #define successLED 13
 #define failureLED 8
 
+WIEGAND_RFID(reader,READER_A_DATA0,READER_A_DATA1)
+
 int toggleState = 0;    // state of the toggling LED
 long toggleTime = 0;    // delay time of the toggling LED
 byte tag[4];
 char inBytes[BUFFERSIZE]; //Buffer for serial in messages
 
-// has to be a long - ints are 16 bits on this platform!
-volatile long reader1 = 0;
-volatile int reader1Count = 0;
 int serialAvail = 0;
 int serialIndex = 0;
 
-void reader1One(void) {
-  if(reader1Count < 32 && digitalRead(READER_A_DATA1) == LOW){
-    reader1Count++;
-    reader1 = reader1 << 1;
-    reader1 |= 1;
-  }
-}
-
-void reader1Zero(void) {
-  if(reader1Count < 32 && digitalRead(READER_A_DATA0) == LOW){
-    reader1Count++;
-    reader1 = reader1 << 1;
-  }
-}
-
 void setup()
 {
   Serial.begin(9600);
   // Attach pin change interrupt service routines from the Wiegand RFID readers
-  PCattachInterrupt(READER_A_DATA1, reader1One, CHANGE);
-  PCattachInterrupt(READER_A_DATA0, reader1Zero, CHANGE);
+  
+  WIEGAND_RFID_INIT(reader)
 
   delay(10);
-  resetInterruptPin(3);
-  resetInterruptPin(4);
   pinMode(OPEN_DOOR_PIN1, OUTPUT);
   digitalWrite(OPEN_DOOR_PIN1, LOW);
   pinMode(READER_A_GREEN, OUTPUT);
   digitalWrite(READER_A_GREEN, HIGH);
   digitalWrite(13, HIGH);
   delay(10);
-  // put the reader input variables to zero
-  reader1 = 0;
-  reader1Count = 0;
   blink(13,200,3);
   printHelp();
   delay(200);
   Serial.println("o - open door");
 }
 void loop() {
-  readSerialInput();
-  seekKnownTags();
+  //readSerialInput();
+  //seekKnownTags();
+  reader.getTag();
   delay(200);
 } 
 
   return(200);
 }
 
-int getTag(){
-  if(reader1Count >= 20){
-    delay(100);
-    long ret = hash(reader1);
-    reader1 = 0;
-    reader1Count = 0;
-    tag[0] = (byte)(ret >> 24);
-    tag[1] = (byte)(ret >> 16);
-    tag[2] = (byte)(ret >> 8);
-    tag[3] = (byte)ret;
-    return 1;
-  } 
-  else {
-    return 0;
-  }
-}
-
 void cycleDoor() {
     digitalWrite(OPEN_DOOR_PIN1, HIGH);
     delay(500);
 void seekNewTag() {
   Serial.println("Next tag will be added to database");
   Serial.println("Waiting for card");
-  while(getTag() == 0){
+  while(reader.getTag() == 0){
     // wait for tag
     if (millis() - toggleTime > 1000) {
       toggle(waitingLED);
 void seekAndDeleteTag() {
   Serial.println("Deleting the next card");
   Serial.println("Waiting for card");
-  while(getTag() == 0){
+  while(reader.getTag() == 0){
     // do nothing; wait for tag
     // unless you get a byte of serial data,
     if (Serial. available()) {
 
 void seekKnownTags() {
   Serial.println("Waiting for card");
-  while(getTag() == 0){
+  while(reader.getTag() == 0){
     // wait for tag
     if (millis() - toggleTime > 1000) {
       toggle(waitingLED);

File interrupt_support.c

   PCint(2);
 }
 
-void resetInterruptPin(int i)
-{
-  // the interrupt in the Atmel processor mises out the first negitave pulse as the inputs are already high,
-  // so this gives a pulse to each reader input line to get the interrupts working properly.
-  // Then clear out the reader variables.
-  // The readers are open collector sitting normally at a one so this is OK
-  pinMode(i, OUTPUT);
-  digitalWrite(i, HIGH); // enable internal pull up causing a one
-  digitalWrite(i, LOW); // disable internal pull up causing zero and thus an interrupt
-  pinMode(i, INPUT);
-  digitalWrite(i, HIGH); // enable internal pull up
-}
 

File interrupt_support.h

 #endif
 void PCattachInterrupt(uint8_t pin, void (*userFunc)(void), int mode);
 void PCdetachInterrupt(uint8_t pin);
-void resetInterruptPin(int i);
 #ifdef __cplusplus
 }
 #endif

File wiegand_rfid.cpp

+#include <WProgram.h>
+#include "wiegand_rfid.h"
+#include "interrupt_support.h"
+#include "bitarray.h"
+
+WiegandRFID::WiegandRFID(int pinDataZero,int pinDataOne)
+{
+  _pinDataZero = pinDataZero;
+  _pinDataOne = pinDataOne;
+  bits.clear();
+  readerCount = 0;
+}
+
+void WiegandRFID::DataZeroInterrupt()
+{
+  if(digitalRead(_pinDataZero) == LOW){
+    if(readerCount < MAX_BIT_LENGTH) {bits.set(readerCount,0);}
+    readerCount++;
+  }
+  lastDataTime = millis();
+}
+void WiegandRFID::DataOneInterrupt()
+{
+  if(digitalRead(_pinDataOne) == LOW){
+    if(readerCount < MAX_BIT_LENGTH) {bits.set(readerCount,1);}
+    readerCount++;
+  }
+  lastDataTime = millis();
+}
+
+void WiegandRFID::reset() {
+  resetInterruptPin(_pinDataZero);
+  resetInterruptPin(_pinDataOne);
+  bits.clear();
+  readerCount = 0;
+  lastDataTime = 0;
+}
+int WiegandRFID::getTag(){
+  if(readerCount > 0 && (lastDataTime + 200 < millis())){
+    //long ret = hash(reader);
+    char str[MAX_BIT_LENGTH];
+    bits.to_string(str);
+    Serial.println(bits.length());
+    for (int i = 0; i < MAX_BIT_LENGTH; i++) { Serial.print(str[i]);}
+    Serial.println("");
+    Serial.println(readerCount);
+    bits.clear();
+    readerCount = 0;
+    //tag[0] = (byte)(ret >> 24);
+    //tag[1] = (byte)(ret >> 16);
+    //tag[2] = (byte)(ret >> 8);
+    //tag[3] = (byte)ret;
+    return 1;
+  } 
+  else {
+    return 0;
+  }
+}
+
+void WiegandRFID::resetInterruptPin(int i)
+{
+  // the interrupt in the Atmel processor mises out the first negitave pulse as the inputs are already high,
+  // so this gives a pulse to each reader input line to get the interrupts working properly.
+  // Then clear out the reader variables.
+  // The readers are open collector sitting normally at a one so this is OK
+  pinMode(i, OUTPUT);
+  digitalWrite(i, HIGH); // enable internal pull up causing a one
+  digitalWrite(i, LOW); // disable internal pull up causing zero and thus an interrupt
+  pinMode(i, INPUT);
+  digitalWrite(i, HIGH); // enable internal pull up
+}
+

File wiegand_rfid.h

+#ifndef WIEGAND_RFID_H
+#define WIEGAND_RFID_H
+/*
+37 bit format
+EXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXO
+E = even parity bit
+O = odd parity bit
+X = data
+*/
+#include "WProgram.h"
+#include "bitarray.h"
+
+/* This is the max number of bits we accept from a reader */
+#define MAX_BIT_LENGTH 96
+
+
+
+#define WIEGAND_RFID(o,pinDataZero,pinDataOne) WiegandRFID o(pinDataZero,pinDataOne); \
+                            void wiegandRfidDateZeroInterrupt_##o(void) { o.DataZeroInterrupt();} \
+                            void wiegandRfidDateOneInterrupt_##o(void) { o.DataOneInterrupt();} \
+
+#define WIEGAND_RFID_INIT(o) PCattachInterrupt( o._pinDataZero, wiegandRfidDateZeroInterrupt_##o, CHANGE); \
+                             PCattachInterrupt( o._pinDataOne, wiegandRfidDateOneInterrupt_##o, CHANGE); \
+                             o.reset();
+
+typedef unsigned char byte;
+typedef unsigned int uint;
+
+#define BYTES_FOR(nbits) ((nbits / 8)+1)
+
+template <uint NBITS>
+class BitArray {
+	byte data[BYTES_FOR(NBITS)];
+        long highest;
+private:
+        bool _get(uint i) {
+                uint byte = i / 8;
+		uint bit = i % 8;
+		
+		return (data[byte] & (1 << bit)) > 0;
+	}
+
+public:
+	BitArray() {
+		for (uint i = 0; i < BYTES_FOR(NBITS); i++) {
+			data[i] = 0;
+		}
+                highest = 0;
+	}
+	void clear() {
+  		for (uint i = 0; i < BYTES_FOR(NBITS); i++) {
+			data[i] = 0;
+		}
+                highest = 0;
+        }
+	bool get(uint i) {
+                return _get(i);
+	}
+	void set(uint i, bool v) {
+                uint byte = i / 8;
+		uint bit = i % 8;
+		
+		data[byte] &= ~(1 << bit);
+		data[byte] |= (v << bit);
+                if(i > highest) highest = i;
+	}
+	long length()  { return highest+1; }
+	void to_string(char* buffer) {
+                for (int i = 0; i < NBITS; i++) { buffer[i] = '0'; }
+		for (int i = 0; i < length(); i++) {
+			buffer[i+NBITS-highest] = get(i)? '1' : '0';
+		}
+	}
+};
+
+
+class WiegandRFID
+{
+  public:
+    WiegandRFID(int pinDataZero,int pinDataOne);
+    int getTag();
+    void DataZeroInterrupt();
+    void DataOneInterrupt(); 
+    void reset();   
+    int _pinDataZero;
+    int _pinDataOne;
+  private:
+    // has to be a long - ints are 16 bits on this platform!
+    volatile long lastDataTime;
+    volatile int readerCount;
+    //volatile byte reader[MAX_BIT_LENGTH];
+    BitArray<MAX_BIT_LENGTH> bits;
+    void resetInterruptPin(int i);
+};
+
+#endif
+