Source

arduino_rfid_controller / arduino_rfid_controller.pde

Full commit
/*
 * ©2010 Lokkju Brennr
 * RFID readers outputing 26-XX bit Wiegand code to pins, truncated to 32 bits and hashed :-
 * READER    WIRE COLOR PIN# DESCRIPTION CABLE COLOR
 * --------- ---------- ---- ----------- -----------
 * Reader A  Orange     2    Green LED   BLUE
 * Reader A  White      3    DATA1       GREEN/WHITE
 * Reader A  Green      4    DATA0       GREEN
 * Reader A  Red             +12v        ORANGE
 * Reader A  Black           GND         BROWN
 * Interrupt service routine gathers Wiegand pulses (zero or one) until a minimum of 32 have been recieved
 * Then a sting is sent to processing
 */

#include <EEPROM.h>

#include "interrupt_support.h"
#include "wiegand_rfid.h"

#define BUFFERSIZE 20
#define MAX_NO_CARDS 200
#define READER_A_DATA0 3
#define READER_A_DATA1 4
#define READER_A_GREEN 2
#define OPEN_DOOR_PIN1 5

#define waitingLED 6
#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

int serialAvail = 0;
int serialIndex = 0;

void setup()
{
  Serial.begin(9600);
  // Attach pin change interrupt service routines from the Wiegand RFID readers
  
  WIEGAND_RFID_INIT(reader)

  delay(10);
  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);
  blink(13,200,3);
  printHelp();
  delay(200);
}
void printHelp() {
  Serial.println("ARDUINO SECURITY v0.1");
  Serial.println(" all commands end with ;");
  Serial.println("h - print this help");
  Serial.println("n - add next card to database");
  Serial.println("r - delete next card from database");
  Serial.println("p - print database");
  Serial.println("c - clear entire database");
  Serial.println("d [x] - delete tag at provided index from database");
  Serial.println("o - open door");
}
void loop() {
  //readSerialInput();
  //seekKnownTags();
  reader.getTag();
  delay(200);
} 

// erase the entire EEPROM memory storage:
void eraseEEPROM(){
  for(int i = 0; i < 1024; i++){
    EEPROM.write(i, 0);
  }
}

// writes tag number in a location:
void writeTag(int startingAddress, byte byte0, byte byte1, byte byte2, byte byte3){
  EEPROM.write( startingAddress*5, byte(1));
  EEPROM.write(startingAddress*5+1, byte0);
  EEPROM.write(startingAddress*5+2, byte1);
  EEPROM.write(startingAddress*5+3, byte2);
  EEPROM.write(startingAddress*5+4, byte3);
}
// delete tag from a specified location
void deleteTag(int startingAddress){
  EEPROM.write( startingAddress*5, byte(0));
  EEPROM.write(startingAddress*5+1, byte(0));
  EEPROM.write(startingAddress*5+2, byte(0));
  EEPROM.write(startingAddress*5+3, byte(0));
  EEPROM.write(startingAddress*5+4, byte(0));
}
// find the first empty entry in the database:
int findEmptyTag(){
  for (int startingAddress = 0; startingAddress< MAX_NO_CARDS; startingAddress++){
    byte value = EEPROM.read(startingAddress*5);
    if (value == byte(0)) {
      return(startingAddress);
    }
  }
  return(200);
}

// print the entire database
void printTags(){
  for (int thisTag = 0; thisTag< MAX_NO_CARDS; thisTag++){
    printOneTag(thisTag);
  }
}

// print a single tag given the tag's address:
void printOneTag(int address) {
  Serial.print(address);
  Serial.print(":");
  for (int offset = 1; offset < 5; offset++) {
    int thisByte = int(EEPROM.read(address*5+offset));
    // if the byte is less than 16, i.e. only one hex character
    // add a leading 0:
    if (thisByte < 0x10) {
      Serial.print("0");
    }
    // print the value:
    Serial.print(thisByte,HEX);
  }
  // add a final linefeed and carriage return:
  Serial.println();
}

//lookup tag in the database:
int lookupTag(byte byte0, byte byte1, byte byte2, byte byte3){
  for (int thisCard = 0; thisCard< MAX_NO_CARDS; thisCard++){
    byte value = EEPROM.read(thisCard*5);
    if (value != byte(0)){                    //it is a valid tag
      //see if all four bytes are the same as the ones we're looking for
      if(byte0 == byte(0) && byte1 == byte(0) && byte2 == byte(0) && byte1 == byte(0)){
        return 200;
      }
      if(byte0 == byte(255) && byte1 == byte(255) && byte2 == byte(255) && byte1 == byte(255)){
        return 200;
      }
      if(byte0 == EEPROM.read(thisCard*5+1) && byte1 == EEPROM.read(thisCard*5+2) && byte2 == EEPROM.read(thisCard*5+3) && byte3 == EEPROM.read(thisCard*5+4)) {
        return(thisCard);
      }
    }
  }
  // if you don't find the tag, return 200;
  return(200);
}

void cycleDoor() {
    digitalWrite(OPEN_DOOR_PIN1, HIGH);
    delay(500);
    digitalWrite(OPEN_DOOR_PIN1, LOW);  
}
void seekNewTag() {
  Serial.println("Next tag will be added to database");
  Serial.println("Waiting for card");
  while(reader.getTag() == 0){
    // wait for tag
    if (millis() - toggleTime > 1000) {
      toggle(waitingLED);
      toggleTime  = millis();
    }
    // unless you get a byte of serial data,
    if (Serial. available()) {
      // break out of the while loop
      // and out of the seekNewTag() method:
      return;
    }
  }

  // look it up in the database:
  int tagToCheck = lookupTag(tag[0], tag[1], tag[2], tag[3]);      

  if (tagToCheck != 200){
    Serial.println("That tag is already stored");
    printOneTag(tagToCheck);
  }
  else {
    int emptyTagLocation = findEmptyTag();
    if (emptyTagLocation != 200){
      writeTag(emptyTagLocation, tag[0], tag[1], tag[2], tag[3]);
      Serial.println("That tag is new, saving...");
      printOneTag(emptyTagLocation);
      blink(successLED, 100, 1);
    }
    else {
      Serial.println("Maximum number of cards stored");
      blink(failureLED, 50, 10);
    }
  }
}


void seekAndDeleteTag() {
  Serial.println("Deleting the next card");
  Serial.println("Waiting for card");
  while(reader.getTag() == 0){
    // do nothing; wait for tag
    // unless you get a byte of serial data,
    if (Serial. available()) {
      // break out of the while loop
      // and out of the method:
      return;
    }
  }
  int tagToDelete = lookupTag(tag[0], tag[1], tag[2], tag[3]);
  if (tagToDelete == 200){
    Serial.print("That tag is not stored");
  }
  else {
    deleteTag(tagToDelete);
  }
}

void toggle(int thisLED) {
  toggleState = !toggleState;
  digitalWrite(thisLED, toggleState);
}

void blink(int thisLED, int interval, int count) {
  for (int i = 0; i < count; i++) {
    digitalWrite(thisLED, LOW);
    delay(interval/2);
    digitalWrite(thisLED, HIGH);
    delay(interval/2);
  }
}

void seekKnownTags() {
  Serial.println("Waiting for card");
  while(reader.getTag() == 0){
    // wait for tag
    if (millis() - toggleTime > 1000) {
      toggle(waitingLED);
      toggleTime  = millis();
    }
    // unless you get a byte of serial data,
    if (Serial.available()) {
      // break out of the while loop
      // and out of the seekKnownTag() method:
      return;
    }
  }

  // look it up in the database:
  int tagToCheck = lookupTag(tag[0], tag[1], tag[2], tag[3]);      

  if (tagToCheck != 200){
    digitalWrite(READER_A_GREEN,LOW);
    cycleDoor();
    printOneTag(tagToCheck);
    Serial.println("OPEN SESAME!!!");
    blink(successLED,500,2);
    digitalWrite(READER_A_GREEN,HIGH);
  }
  else {
    blink(READER_A_GREEN, 50, 10);
    Serial.print("INVALID CARD!!!");
    printOneTag(tagToCheck);
    blink(successLED, 50, 10);
  }
}
long hash( long a)
{
  a = (a+0x7ed55d16) + (a<<12);
  a = (a^0xc761c23c) ^ (a>>19);
  a = (a+0x165667b1) + (a<<5);
  a = (a+0xd3a2646c) ^ (a<<9);
  a = (a+0xfd7046c5) + (a<<3);
  a = (a^0xb55a4f09) ^ (a>>16);
  return a;
}

// Reads serial input if available and parses command when full command has been sent. 
void readSerialInput() {
  int si = serialIndex;
  serialAvail = Serial.available();  
  for (int i = 0; i < serialAvail; i++) {
    char c = Serial.read();
    if(si + i >= BUFFERSIZE) {
      // don't want to overflow the buffer!
      serialIndex = 0;
      for (int i= 0; i < BUFFERSIZE; i++) { 
        inBytes[i] = '\0';
      }
      Serial.flush();
      return;
    }
    //Store into buffer.
    inBytes[i + si] = c;
    //Check for command end. 
    if (inBytes[i + si] == ';') {
      // print the buffer  
      inBytes[i + si] = '\0'; //end of string char
      parseCommand(inBytes); 
      Serial.flush();
      serialIndex = 0;
      for (int i= 0; i < BUFFERSIZE; i++) { 
        inBytes[i] = '\0';
      }
    } 
    else {
      //expecting more of the command to come later.
      serialIndex += 1;
    }
  }  
}

// Cleans and parses the command
void parseCommand(char* com) {
  if (com[0] == '\0') { 
    return; 
  } //bit of error checking
  int start = 0;
  //get start of command
  while (com[start] != '<'){
    start++; 
    if (com[start] == '\0') {
      //its not there. Must be old version
      start = -1;
      break;
    }
  }
  start++;
  //Shift to beginning
  int i = 0;
  while (com[i + start - 1] != '\0') {
    com[i] = com[start + i];
    i++; 
  } 
  performCommand(com);
}

void serialReply(char* sensorname, char* tmpmsg) {
  Serial.print(sensorname);
  Serial.print(":");
  Serial.println(tmpmsg); // Send the message back out the serial line
  //Wait for the serial debugger to shut up
  delay(200); //this is a magic number
  Serial.flush(); //clears all incoming data
}

void performCommand(char* com) {
  if (strcmp(com, "n") == 0) { // store the next tag number
    seekNewTag();
  } 
  else if (strcmp(com,"c") == 0) { // erase entire database 
    Serial.println("i Deleting entire database");
    eraseEEPROM();    // if user enters 'c' then 
    serialReply("i","Database deleted");
  } 
  else if (com[0] == 'd' && com[1] == ' ') { // delete the specified tag number "d 20"
    serialReply("i","Deleting indicated tag from database");
    int value;
    Serial.println(com);
    sscanf(com,"d %d",&value); // Parse the input into multiple values
    Serial.println(value);
    deleteTag(value);
  } 
  else if (strcmp(com,"r") == 0) { // delete the next tag
    seekAndDeleteTag();
  } 
  else if (strcmp(com,"p") == 0) { // print the database
    printTags();
  } 
  else if (strcmp(com,"h") == 0) { // print help
    printHelp();
  }
  else if (strcmp(com,"o") == 0) { //cycle door
    cycleDoor();
  }
  else { 
    Serial.print("e ");
    Serial.println(com); // Echo unknown command back
  }
}