diff --git a/README.markdown b/README.markdown index 789ad6a..1a4cee4 100644 --- a/README.markdown +++ b/README.markdown @@ -1,13 +1,22 @@ -Open Access Control - Arduino Ethernet +Open Access Control - HTTP Minimal Edition ====================================== -This is a stripped-down version of the 23b hackerspace's Open Access Control system, intended for embedded use with an RFID reader and Ethernet shield for authenticating Wiegand RFID cards with a webservice. +This is a stripped-down version of the 23b hackerspace's Open Access Control system, intended for embedded use with an RFID reader and Ethernet shield for authenticating Wiegand RFID cards with a webservice. Please see http://code.google.com/p/open-access-control/ for the main/full version. -For more info, contact @willbradley on Twitter or will@heatsynclabs.org +For more info, contact @willbradley on Twitter. Structure --------- * This folder * Open Access Control folder - * Open Access Control.pde (Arduino code -- requires the Wiegand26 library to be installed in your IDE.) + * Open Access Control.pde (Arduino code -- open from the Arduino IDE.) + * libraries folder (copy the contents of this folder to your Arduino program's libraries folder.) + * PCATTACH folder + * keywords.txt + * PCATTACH.cpp + * PCATTACH.h + * Wiegand26 folder + * keywords.txt + * WIEGAND26.cpp + * WIEGAND26.h diff --git a/libraries/PCATTACH/PCATTACH.cpp b/libraries/PCATTACH/PCATTACH.cpp new file mode 100644 index 0000000..fa2cb31 --- /dev/null +++ b/libraries/PCATTACH/PCATTACH.cpp @@ -0,0 +1,138 @@ +#include "pins_arduino.h" +#include "PCATTACH.h" + +/* + * an extension to the interrupt support for arduino. + * add pin change interrupts to the external interrupts, giving a way + * for users to have interrupts drive off of any pin. + * Refer to avr-gcc header files, arduino source and atmega datasheet. + */ + +/* + * Theory: all IO pins on Atmega168 are covered by Pin Change Interrupts. + * The PCINT corresponding to the pin must be enabled and masked, and + * an ISR routine provided. Since PCINTs are per port, not per pin, the ISR + * must use some logic to actually implement a per-pin interrupt service. + */ + +PCATTACH::PCATTACH(){ + +} + +PCATTACH::~PCATTACH(){ +} + +PCATTACH pc1; + +/* Pin to interrupt map: + * D0-D7 = PCINT 16-23 = PCIR2 = PD = PCIE2 = pcmsk2 + * D8-D13 = PCINT 0-5 = PCIR0 = PB = PCIE0 = pcmsk0 + * A0-A5 (D14-D19) = PCINT 8-13 = PCIR1 = PC = PCIE1 = pcmsk1 + */ + +volatile uint8_t *port_to_pcmask[] = { + &PCMSK0, + &PCMSK1, + &PCMSK2 +}; + +typedef void (*voidFuncPtr)(void); + +volatile static voidFuncPtr PCintFunc[24] = { + NULL }; + +volatile static uint8_t PCintLast[3]; + +/* + * attach an interrupt to a specific pin using pin change interrupts. + * First version only supports CHANGE mode. + */ + void PCATTACH::PCattachInterrupt(uint8_t pin, void (*userFunc)(void), int mode) { + uint8_t bit = digitalPinToBitMask(pin); + uint8_t port = digitalPinToPort(pin); + uint8_t slot; + volatile uint8_t *pcmask; + + if (mode != CHANGE) { + return; + } + // map pin to PCIR register + if (port == NOT_A_PORT) { + return; + } + else { + port -= 2; + pcmask = port_to_pcmask[port]; + } + slot = port * 8 + (pin % 8); + PCintFunc[slot] = userFunc; + // set the mask + *pcmask |= bit; + // enable the interrupt + PCICR |= 0x01 << port; +} + +void PCATTACH::PCdetachInterrupt(uint8_t pin) { + uint8_t bit = digitalPinToBitMask(pin); + uint8_t port = digitalPinToPort(pin); + volatile uint8_t *pcmask; + + // map pin to PCIR register + if (port == NOT_A_PORT) { + return; + } + else { + port -= 2; + pcmask = port_to_pcmask[port]; + } + + // disable the mask. + *pcmask &= ~bit; + // if that's the last one, disable the interrupt. + if (*pcmask == 0) { + PCICR &= ~(0x01 << port); + } +} + +// common code for isr handler. "port" is the PCINT number. +// there isn't really a good way to back-map ports and masks to pins. + +void PCATTACH::PCint(uint8_t port) { + uint8_t bit; + uint8_t curr; + uint8_t mask; + uint8_t pin; + + // get the pin states for the indicated port. + curr = *portInputRegister(port+2); + mask = curr ^ PCintLast[port]; + PCintLast[port] = curr; + // mask is pins that have changed. screen out non pcint pins. + if ((mask &= *port_to_pcmask[port]) == 0) { + return; + } + // mask is pcint pins that have changed. + for (uint8_t i=0; i < 8; i++) { + bit = 0x01 << i; + if (bit & mask) { + pin = port * 8 + i; + if (PCintFunc[pin] != NULL) { + PCintFunc[pin](); + } + } + } +} + + +SIGNAL (PCINT0_vect) { + pc1.PCint(0); +} +SIGNAL (PCINT1_vect) { + pc1.PCint(1); +} +SIGNAL (PCINT2_vect) { + pc1.PCint(2); +} + + + diff --git a/libraries/PCATTACH/PCATTACH.h b/libraries/PCATTACH/PCATTACH.h new file mode 100644 index 0000000..e2bee0e --- /dev/null +++ b/libraries/PCATTACH/PCATTACH.h @@ -0,0 +1,31 @@ +#ifndef _PCATTACH_H_ +#define _PCATTACH_H_ +#endif + +#include +#define uint_8 byte + +class PCATTACH { + +public: +PCATTACH(); +~PCATTACH(); + + + +void PCattachInterrupt(byte pin, void (*userFunc)(void), int mode); +void PCdetachInterrupt(byte pin); + + +static void PCint(uint8_t); + +/* +volatile uint8_t *port_to_pcmask[]; +typedef void (*voidFuncPtr)(void); +volatile static voidFuncPtr PCintFunc[]; +volatile static uint8_t PCintLast[]; +*/ + + +}; + diff --git a/libraries/PCATTACH/keywords.txt b/libraries/PCATTACH/keywords.txt new file mode 100644 index 0000000..497a9f8 --- /dev/null +++ b/libraries/PCATTACH/keywords.txt @@ -0,0 +1,2 @@ +PCattachInterrupt KEYWORD2 +PCdetachInterrupt KEYWORD2 diff --git a/libraries/Wiegand26/WIEGAND26.cpp b/libraries/Wiegand26/WIEGAND26.cpp new file mode 100644 index 0000000..2eb4ce0 --- /dev/null +++ b/libraries/Wiegand26/WIEGAND26.cpp @@ -0,0 +1,118 @@ +#include + +extern byte reader1Pins[]; // Reader 1 connected to pins 4,5 +extern byte reader2Pins[]; // Reader2 connected to pins 6,7 +extern byte reader3Pins[]; // Reader3 connected to pins X,Y +extern long reader1; +extern int reader1Count; +extern long reader2; +extern int reader2Count; +extern long reader3; +extern int reader3Count; + + +WIEGAND26::WIEGAND26(){ +} + +WIEGAND26::~WIEGAND26(){ +} + + + +/* Wiegand Reader code. Modify as needed or comment out unused readers. + * system supports up to 3 independent readers. + */ + + + +void WIEGAND26::initReaderOne(void) { + for(byte i=0; i<2; i++){ + pinMode(reader1Pins[i], OUTPUT); + digitalWrite(reader1Pins[i], HIGH); // enable internal pull up causing a one + digitalWrite(reader1Pins[i], LOW); // disable internal pull up causing zero and thus an interrupt + pinMode(reader1Pins[i], INPUT); + digitalWrite(reader1Pins[i], HIGH); // enable internal pull up + } + delay(10); + reader1Count=0; + reader1=0; +} + + +void WIEGAND26::initReaderTwo(void) { + for(byte i=0; i<2; i++){ + pinMode(reader2Pins[i], OUTPUT); + digitalWrite(reader2Pins[i], HIGH); // enable internal pull up causing a one + digitalWrite(reader2Pins[i], LOW); // disable internal pull up causing zero and thus an interrupt + pinMode(reader2Pins[i], INPUT); + digitalWrite(reader2Pins[i], HIGH); // enable internal pull up + } + delay(10); + reader2Count=0; + reader2=0; +} + + + +void WIEGAND26::reader1One() { + if(digitalRead(reader1Pins[1]) == LOW){ + reader1Count++; + reader1 = reader1 << 1; + reader1 |= 1; + } +} + +void WIEGAND26::reader1Zero() { + if(digitalRead(reader1Pins[0]) == LOW){ + reader1Count++; + reader1 = reader1 << 1; + + } +} + + +void WIEGAND26::reader2One() { + if(digitalRead(reader2Pins[1]) == LOW){ + reader2Count++; + reader2 = reader2 << 1; + reader2 |= 1; + } +} + +void WIEGAND26::reader2Zero(void) { + if(digitalRead(reader2Pins[0]) == LOW){ + reader2Count++; + reader2 = reader2 << 1; + } +} + + + +void WIEGAND26::initReaderThree(void) { + for(byte i=0; i<2; i++){ + pinMode(reader3Pins[i], OUTPUT); + digitalWrite(reader3Pins[i], HIGH); // enable internal pull up causing a one + digitalWrite(reader3Pins[i], LOW); // disable internal pull up causing zero and thus an interrupt + pinMode(reader3Pins[i], INPUT); + digitalWrite(reader3Pins[i], HIGH); // enable internal pull up + } + delay(10); + reader3Count=0; + reader3=0; + } + + void WIEGAND26::reader3One(void) { + if(digitalRead(reader3Pins[1]) == LOW){ + reader3Count++; + reader3 = reader3 << 1; + reader3 |= 1; + } + } + + void WIEGAND26::reader3Zero(void) { + if(digitalRead(reader3Pins[0]) == LOW){ + reader3Count++; + reader3 = reader3 << 1; + } + } + diff --git a/libraries/Wiegand26/WIEGAND26.h b/libraries/Wiegand26/WIEGAND26.h new file mode 100644 index 0000000..374cfb0 --- /dev/null +++ b/libraries/Wiegand26/WIEGAND26.h @@ -0,0 +1,36 @@ +#ifndef _WIEGAND26_H_ +#define _WIEGAND26_H_ +#endif + +#include + +class WIEGAND26 { +public: +WIEGAND26(); +~WIEGAND26(); + + +//const byte reader1Pins[]; // Reader 1 connected to pins 4,5 +//const byte reader2Pins[]; // Reader2 connected to pins 6,7 +//const byte reader3Pins[]; // Reader3 connected to pins X,Y + +//volatile long reader1; +//volatile int reader1Count; +//volatile long reader2; +//volatile int reader2Count; +//volatile long reader3; +//volatile int reader3Count; + +void initReaderOne(void); +void initReaderTwo(void); +void reader1One(void); +void reader1Zero(void); +void reader2One(void); +void reader2Zero(void); +void initReaderThree(void); +void reader3One(void); +void reader3Zero(void); + +private: + +}; diff --git a/libraries/Wiegand26/keywords.txt b/libraries/Wiegand26/keywords.txt new file mode 100644 index 0000000..8b8118e --- /dev/null +++ b/libraries/Wiegand26/keywords.txt @@ -0,0 +1,9 @@ +initReaderOne KEYWORD2 +initReaderTwo KEYWORD2 +reader1One KEYWORD2 +reader1Zero KEYWORD2 +reader2One KEYWORD2 +reader2Zero KEYWORD2 +initReaderThree KEYWORD2 +reader3One KEYWORD2 +reader3Zero KEYWORD2