summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSergiusz 'q3k' Bazański <q3k@q3k.org>2015-03-04 23:05:19 +0100
committerSergiusz 'q3k' Bazański <q3k@q3k.org>2015-03-04 23:05:19 +0100
commit5b0e1cbb36cdac5a0e421b7a6a22b3313d005ebe (patch)
treee6eea75a8006d0e2592ee1b7269e2e7c1d59d084
parentb158beac3cf75974ba46e4ae5f9671d910ee4b8c (diff)
downloaddoorman-5b0e1cbb36cdac5a0e421b7a6a22b3313d005ebe.tar.gz
doorman-5b0e1cbb36cdac5a0e421b7a6a22b3313d005ebe.tar.bz2
doorman-5b0e1cbb36cdac5a0e421b7a6a22b3313d005ebe.tar.xz
doorman-5b0e1cbb36cdac5a0e421b7a6a22b3313d005ebe.zip
ino compatibility
-rw-r--r--admin/cards.csv0
-rw-r--r--arduino/lib/SL018/README7
-rw-r--r--arduino/lib/SL018/SL018.cpp507
-rw-r--r--arduino/lib/SL018/SL018.h177
-rw-r--r--arduino/lib/SL018/examples/UID/UID.ino38
-rw-r--r--arduino/lib/SL018/examples/sl018demo/sl018demo.ino316
-rw-r--r--arduino/lib/SL018/examples/twoReaders/twoReaders.ino83
-rw-r--r--arduino/lib/SL018/keywords.txt48
-rw-r--r--arduino/lib/Sha/examples/hmacsha256test/hmacsha256test.pde (renamed from libraries/Sha/examples/hmacsha256test/hmacsha256test.pde)0
-rw-r--r--arduino/lib/Sha/examples/sha1test/sha1test.pde (renamed from libraries/Sha/examples/sha1test/sha1test.pde)0
-rw-r--r--arduino/lib/Sha/examples/sha256test/sha256test.pde (renamed from libraries/Sha/examples/sha256test/sha256test.pde)0
-rw-r--r--arduino/lib/Sha/keywords.txt (renamed from libraries/Sha/keywords.txt)0
-rw-r--r--arduino/lib/Sha/readme.txt (renamed from libraries/Sha/readme.txt)0
-rw-r--r--arduino/lib/Sha/sha1.cpp (renamed from libraries/Sha/sha1.cpp)0
-rw-r--r--arduino/lib/Sha/sha1.h (renamed from libraries/Sha/sha1.h)0
-rw-r--r--arduino/lib/Sha/sha256.cpp (renamed from libraries/Sha/sha256.cpp)0
-rw-r--r--arduino/lib/Sha/sha256.h (renamed from libraries/Sha/sha256.h)0
-rw-r--r--arduino/src/config.h (renamed from arduino/doorman/config.h)0
-rw-r--r--arduino/src/doorman.ino (renamed from arduino/doorman/doorman.ino)0
-rw-r--r--arduino/src/emem.cpp (renamed from arduino/doorman/emem.cpp)0
-rw-r--r--arduino/src/emem.h (renamed from arduino/doorman/emem.h)0
-rw-r--r--arduino/src/keypad.cpp (renamed from arduino/doorman/keypad.cpp)0
-rw-r--r--arduino/src/keypad.h (renamed from arduino/doorman/keypad.h)0
-rw-r--r--arduino/src/pc.cpp (renamed from arduino/doorman/pc.cpp)0
-rw-r--r--arduino/src/pc.h (renamed from arduino/doorman/pc.h)0
-rw-r--r--arduino/src/rf.cpp (renamed from arduino/doorman/rf.cpp)0
-rw-r--r--arduino/src/rf.h (renamed from arduino/doorman/rf.h)0
27 files changed, 1176 insertions, 0 deletions
diff --git a/admin/cards.csv b/admin/cards.csv
deleted file mode 100644
index e69de29..0000000
--- a/admin/cards.csv
+++ /dev/null
diff --git a/arduino/lib/SL018/README b/arduino/lib/SL018/README
new file mode 100644
index 0000000..555f43f
--- /dev/null
+++ b/arduino/lib/SL018/README
@@ -0,0 +1,7 @@
+Arduino library for StrongLink SL018/SL030 RFID readers
+
+http://www.stronglink.cn/english/sl018.htm
+http://www.stronglink.cn/english/sl030.htm
+
+June 2011
+marc@marcboon.com \ No newline at end of file
diff --git a/arduino/lib/SL018/SL018.cpp b/arduino/lib/SL018/SL018.cpp
new file mode 100644
index 0000000..ef4428b
--- /dev/null
+++ b/arduino/lib/SL018/SL018.cpp
@@ -0,0 +1,507 @@
+/**
+ * @title StrongLink SL018/SL030 RFID reader library
+ *
+ * @file SL018.cpp
+ * @author marc@marcboon.com
+ * @modified fil@rezox.com (Filipe Laborde-Basto) [to make binary safe]
+ * @date February 2012
+ *
+ * @see http://www.stronglink.cn/english/sl018.htm
+ * @see http://www.stronglink.cn/english/sl030.htm
+ */
+
+#include <Wire.h>
+#include <string.h>
+#include "SL018.h"
+
+// local prototypes
+void arrayToHex(char *s, byte array[], byte len);
+char toHex(byte b);
+
+/** Constructor.
+ *
+ * An instance of SL018 should be created as a global variable, outside of
+ * any function.
+ * The constructor sets public data fields to default values.
+ * These may be changed in setup() before SL018::reset() is called.
+ */
+SL018::SL018()
+{
+ address = 0x50;
+ pinRESET = -1;
+ pinDREADY = -1;
+ cmd = CMD_IDLE;
+ debug = false;
+ t = millis() + 10;
+}
+
+/* Public member functions ****************************************************/
+
+
+/** Reset the SL018 module
+ *
+ * This function should be called in setup(). It initializes the IO pins and
+ * issues a hardware or software reset, depending on the definition of pinRESET.
+ * After reset, antenna power is switched off to terminate the automatic SEEK mode.
+ *
+ * Wire.begin() should also be called in setup(), and Wire.h should be included.
+ *
+ * If pinRESET has the value -1 (default), software reset over I2C will be used.
+ * If pinDREADY has the value -1 (default), the SL018 will be polled over I2C for
+ * SEEK commands, otherwise the DREADY pin will be polled.
+ * For other commands, response polling is always over I2C.
+ */
+void SL018::reset()
+{
+ // Init DREADY pin
+ if (pinDREADY != 0xff)
+ {
+ pinMode(pinDREADY, INPUT);
+ }
+
+ // Init RESET pin
+ if (pinRESET != 0xff) // hardware reset
+ {
+ pinMode(pinRESET, OUTPUT);
+ digitalWrite(pinRESET, HIGH);
+ delay(10);
+ digitalWrite(pinRESET, LOW);
+ }
+ else // software reset
+ {
+ sendCommand(CMD_RESET);
+ }
+
+ // Allow enough time for reset
+ delay(200);
+}
+
+/** Checks for availability of a valid response packet.
+ *
+ * This function should always be called and return true prior to using results
+ * of a command.
+ *
+ * @returns true if a valid response packet is available
+ */
+boolean SL018::available()
+{
+ // Set the maximum length of the expected response packet
+ byte len;
+ switch(cmd)
+ {
+ case CMD_IDLE:
+ case CMD_RESET:
+ len = 0;
+ break;
+ case CMD_LOGIN:
+ case CMD_SET_LED:
+ case CMD_SLEEP:
+ len = 3;
+ break;
+ case CMD_READ4:
+ case CMD_WRITE4:
+ case CMD_READ_VALUE:
+ case CMD_WRITE_VALUE:
+ case CMD_DEC_VALUE:
+ case CMD_INC_VALUE:
+ case CMD_COPY_VALUE:
+ len = 7;
+ break;
+ case CMD_WRITE_KEY:
+ len = 9;
+ break;
+ case CMD_SEEK:
+ case CMD_SELECT:
+ len = 11;
+ break;
+ default:
+ len = SIZE_PACKET;
+ }
+
+ // If valid data received, process the response packet
+ if (len && receiveData(len) > 0)
+ {
+ // Init response variables
+ tagType = tagLength = *tagString = 0;
+ errorCode = data[2];
+
+ // Process command response
+ switch (getCommand())
+ {
+ case CMD_SEEK:
+ case CMD_SELECT:
+ // If no error, get tag number
+ if(errorCode == 0 && getPacketLength() >= 7)
+ {
+ tagLength = getPacketLength() - 3;
+ tagType = data[getPacketLength()];
+ memcpy(tagNumber, data + 3, tagLength);
+ arrayToHex(tagString, tagNumber, tagLength);
+ }
+ else if(cmd == CMD_SEEK)
+ {
+ // Continue seek
+ seekTag();
+ return false;
+ }
+ }
+ // Data is available
+ return true;
+ }
+ // No data available
+ return false;
+}
+
+/** Get error message for last command.
+ *
+ * @return Human-readable error message as a null-terminated string
+ */
+const char* SL018::getErrorMessage()
+{
+ switch(errorCode)
+ {
+ case 0:
+ return "OK";
+ case 1:
+ return "No tag present";
+ case 2:
+ return "Login OK";
+ case 3:
+ case 0x10:
+ return "Login failed";
+ case 4:
+ return "Read failed";
+ case 5:
+ return "Write failed";
+ case 6:
+ return "Unable to read after write";
+ case 0x0A:
+ return "Collision detected";
+ case 0x0C:
+ return "Load key failed";
+ case 0x0D:
+ return "Not authenticated";
+ case 0x0E:
+ return "Not a value block";
+ default:
+ return "Unknown error";
+ }
+}
+
+/** Authenticate with transport key (0xFFFFFFFFFFFF).
+ *
+ * @param sector Sector number
+ */
+void SL018::authenticate(byte sector)
+{
+ data[0] = 9;
+ data[1] = CMD_LOGIN;
+ data[2] = sector;
+ data[3] = 0xAA;
+ memset(data + 4, 0xFF, 6);
+ transmitData();
+}
+
+/** Authenticate with specified key A or key B.
+ *
+ * @param sector Sector number
+ * @param keyType Which key to use: 0xAA for key A or 0xBB for key B
+ * @param key Key value (6 bytes)
+ */
+void SL018::authenticate(byte sector, byte keyType, byte key[6])
+{
+ data[0] = 9;
+ data[1] = CMD_LOGIN;
+ data[2] = sector;
+ data[3] = keyType;
+ memcpy(data + 4, key, 6);
+ transmitData();
+}
+
+/** Read 16-byte block.
+ *
+ * @param block Block number
+ */
+void SL018::readBlock(byte block)
+{
+ data[0] = 2;
+ data[1] = CMD_READ16;
+ data[2] = block;
+ transmitData();
+}
+
+/** Read 4-byte page.
+ *
+ * @param page Page number
+ */
+void SL018::readPage(byte page)
+{
+ data[0] = 2;
+ data[1] = CMD_READ4;
+ data[2] = page;
+ transmitData();
+}
+
+/** Write 16-byte block.
+ *
+ * The block will be padded with zeroes if the message is shorter
+ * than 15 characters.
+ *
+ * @param block Block number
+ * @param message string of 16 characters (binary safe)
+ */
+void SL018::writeBlock(byte block, const char* message)
+{
+ data[0] = 18;
+ data[1] = CMD_WRITE16;
+ data[2] = block;
+ //strncpy((char*)data + 3, message, 15); // not binary safe
+ memcpy( (char*)data + 3, message, 16 );
+ data[18] = 0;
+ transmitData();
+}
+
+/** Write 4-byte page.
+ *
+ * This command is used for Mifare Ultralight tags which have 4 byte pages.
+ *
+ * @param page Page number
+ * @param message String of 4 characters
+ */
+void SL018::writePage(byte page, const char* message)
+{
+ data[0] = 6;
+ data[1] = CMD_WRITE4;
+ data[2] = page;
+ //strncpy((char*)data + 3, message, 3); // not binary safe
+ memcpy( (char*)data + 3, message, 4 );
+ data[6] = 0;
+ transmitData();
+}
+
+/** Write master key (key A).
+ *
+ * @param sector Sector number
+ * @param key Key value (6 bytes)
+ */
+void SL018::writeKey(byte sector, byte key[6])
+{
+ data[0] = 8;
+ data[1] = CMD_WRITE_KEY;
+ data[2] = sector;
+ memcpy(data + 3, key, 6);
+ transmitData();
+}
+
+/** Control red LED on SL018 (not implemented on SL030).
+ *
+ * @param on true for on, false for off
+ */
+void SL018::led(boolean on)
+{
+ data[0] = 2;
+ data[1] = CMD_SET_LED;
+ data[2] = on;
+ transmitData();
+}
+
+/** Send 1-byte command.
+ *
+ * @param cmd Command
+ */
+void SL018::sendCommand(byte cmd)
+{
+ data[0] = 1;
+ data[1] = cmd;
+ transmitData();
+}
+
+/* Private member functions ****************************************************/
+
+
+/** Transmit a packet to the SL018.
+ */
+ /*
+ data[0] = 18;
+ data[1] = CMD_WRITE16;
+ data[2] = block;
+ strncpy((char*)data + 3, message, 15);
+ data[18] = 0;
+ */
+void SL018::transmitData()
+{
+ // wait until at least 20ms passed since last I2C transmission
+ while(t > millis());
+ t = millis() + 20;
+
+ // remember which command was sent
+ cmd = data[1];
+
+ // transmit packet with checksum
+ Wire.beginTransmission(address);
+
+ for (int i = 0; i <= data[0]; i++)
+ {
+#if defined(ARDUINO) && ARDUINO >= 100
+ Wire.write(data[i]);
+#else
+ Wire.send(data[i]);
+#endif
+ }
+ Wire.endTransmission();
+
+ // show transmitted packet for debugging
+ if (debug)
+ {
+ Serial.print("> ");
+ printArrayHex( data, data[0] + 1);
+ Serial.println();
+ }
+}
+
+/** Receives a packet from the SL018.
+ *
+ * @param length the number of bytes to receive
+ * @return the number of bytes in the payload, or -1 if bad checksum
+ */
+byte SL018::receiveData(byte length)
+{
+ // wait until at least 20ms passed since last I2C transmission
+ while(t > millis());
+ t = millis() + 20;
+
+ // read response
+ Wire.requestFrom(address, length);
+ if(Wire.available())
+ {
+ // get length of packet
+#if defined(ARDUINO) && ARDUINO >= 100
+ data[0] = Wire.read();
+#else
+ data[0] = Wire.receive();
+#endif
+
+ // get data
+ for (byte i = 1; i <= data[0]; i++)
+ {
+#if defined(ARDUINO) && ARDUINO >= 100
+ data[i] = Wire.read();
+#else
+ data[i] = Wire.receive();
+#endif
+ }
+
+ // show received packet for debugging
+ if (debug && data[0] > 0 )
+ {
+ Serial.print("< ");
+ printArrayHex(data, data[0] + 1);
+ Serial.println();
+ }
+
+ // return with length of response
+ return data[0];
+ }
+ return 0;
+}
+
+/** Maps tag types to names.
+ *
+ * @param type numeric tag type
+ * @return Human-readable tag name as null-terminated string
+ */
+const char* SL018::tagName(byte type)
+{
+ switch(type)
+ {
+ case 1: return "Mifare 1K";
+ case 2: return "Mifare Pro";
+ case 3: return "Mifare UltraLight";
+ case 4: return "Mifare 4K";
+ case 5: return "Mifare ProX";
+ case 6: return "Mifare DesFire";
+ default: return "";
+ }
+}
+
+
+// Global helper functions
+
+/** Convert byte array to null-terminated hexadecimal string.
+ *
+ * @param s pointer to destination string
+ * @param array byte array to convert
+ * @param len length of byte array to convert
+ */
+void arrayToHex(char *s, byte array[], byte len)
+{
+ for (byte i = 0; i < len; i++)
+ {
+ *s++ = toHex(array[i] >> 4);
+ *s++ = toHex(array[i]);
+ }
+ *s = 0;
+}
+
+/** Convert low-nibble of byte to ASCII hex.
+ *
+ * @param b byte to convert
+ * $return uppercase hexadecimal character [0-9A-F]
+ */
+char toHex(byte b)
+{
+ b = b & 0x0f;
+ return b < 10 ? b + '0' : b + 'A' - 10;
+}
+
+/** Print byte array as ASCII string.
+ *
+ * Non-printable characters (<0x20 or >0x7E) are printed as dot.
+ *
+ * @param array byte array
+ * @param len length of byte array
+ */
+void printArrayAscii(byte array[], byte len)
+{
+ for (byte i = 0; i < len;)
+ {
+ char c = array[i++];
+ if (c < 0x20 || c > 0x7e)
+ {
+ Serial.print('.');
+ }
+ else
+ {
+ Serial.print(char(c));
+ }
+ }
+}
+
+/** Print byte array as hexadecimal character pairs.
+ *
+ * @param array byte array
+ * @param len length of byte array
+ */
+void printArrayHex(byte array[], byte len)
+{
+ for (byte i = 0; i < len;)
+ {
+ printHex(array[i++]);
+ if (i < len)
+ {
+ Serial.print(' ');
+ }
+ }
+}
+/** Print byte as two hexadecimal characters.
+ *
+ * @param val byte value
+ */
+void printHex(byte val)
+{
+ if (val < 0x10)
+ {
+ Serial.print('0');
+ }
+ Serial.print(val, HEX);
+}
diff --git a/arduino/lib/SL018/SL018.h b/arduino/lib/SL018/SL018.h
new file mode 100644
index 0000000..4eeedd1
--- /dev/null
+++ b/arduino/lib/SL018/SL018.h
@@ -0,0 +1,177 @@
+/**
+ * @file SL018.h
+ * @brief Header file for SL018 library
+ * @author Marc Boon <http://www.marcboon.com>
+ * @date February 2012
+ */
+
+#ifndef SL018_h
+#define SL018_h
+
+#if defined(ARDUINO) && ARDUINO >= 100
+#include "Arduino.h"
+#else
+#include "WProgram.h"
+#endif
+
+#define SIZE_PACKET 19
+
+// Global functions
+void printArrayAscii(byte array[], byte len);
+void printArrayHex(byte array[], byte len);
+void printHex(byte val);
+
+class SL018
+{
+ public:
+ static const int VERSION = 1; //!< version of this library
+
+ static const byte MIFARE_1K = 1;
+ static const byte MIFARE_PRO = 2;
+ static const byte MIFARE_ULTRALIGHT = 3;
+ static const byte MIFARE_4K = 4;
+ static const byte MIFARE_PROX = 5;
+ static const byte MIFARE_DESFIRE = 6;
+
+ static const byte CMD_IDLE = 0x00;
+ static const byte CMD_SELECT = 0x01;
+ static const byte CMD_LOGIN = 0x02;
+ static const byte CMD_READ16 = 0x03;
+ static const byte CMD_WRITE16 = 0x04;
+ static const byte CMD_READ_VALUE = 0x05;
+ static const byte CMD_WRITE_VALUE = 0x06;
+ static const byte CMD_WRITE_KEY = 0x07;
+ static const byte CMD_INC_VALUE = 0x08;
+ static const byte CMD_DEC_VALUE = 0x09;
+ static const byte CMD_COPY_VALUE = 0x0A;
+ static const byte CMD_READ4 = 0x10;
+ static const byte CMD_WRITE4 = 0x11;
+ static const byte CMD_SEEK = 0x20;
+ static const byte CMD_SET_LED = 0x40;
+ static const byte CMD_SLEEP = 0x50;
+ static const byte CMD_RESET = 0xFF;
+
+ static const byte OK = 0x00;
+ static const byte NO_TAG = 0x01;
+ static const byte LOGIN_OK = 0x02;
+ static const byte LOGIN_FAIL = 0x03;
+ static const byte READ_FAIL = 0x04;
+ static const byte WRITE_FAIL = 0x05;
+ static const byte CANT_VERIFY = 0x06;
+ static const byte COLLISION = 0x0A;
+ static const byte KEY_FAIL = 0x0C;
+ static const byte NO_LOGIN = 0x0D;
+ static const byte NO_VALUE = 0x0E;
+
+ boolean debug; //!< debug mode, prints all I2C communication to Serial port
+ byte address; //!< I2C address (default 0x50)
+ byte pinRESET; //!< RESET pin (default -1)
+ byte pinDREADY; //!< DREADY pin (default -1)
+
+ private:
+ byte data[SIZE_PACKET]; //!< packet data
+ byte tagNumber[7]; //!< tag number as byte array
+ byte tagLength; //!< length of tag number in bytes (4 or 7)
+ char tagString[15]; //!< tag number as hex string
+ byte tagType; //!< type of tag
+ char errorCode; //!< error code from some commands
+ byte cmd; //!< last sent command
+ unsigned long t; //!< timer for sending I2C commands
+
+ public:
+ //! Constructor
+ SL018();
+
+ //! Hardware or software reset of the SL018 module
+ void reset();
+
+ //! Returns true if a response packet is available
+ boolean available();
+
+ //! Returns a pointer to the response packet
+ byte* getRawData() { return data; };
+
+ //! Returns the last executed command
+ byte getCommand() { return cmd; };
+
+ //! Returns the packet length, excluding checksum
+ byte getPacketLength() { return data[0]; };
+
+ //! Returns a pointer to the packet payload
+ byte* getPayload() { return data+2; };
+
+ //! Returns the block number for read/write commands
+ byte getBlockNumber() { return data[2]; };
+
+ //! Returns a pointer to the read block (with a length of 16 bytes)
+ byte* getBlock() { return data+3; };
+
+ //! Returns the tag's serial number as a byte array
+ byte* getTagNumber() { return tagNumber; };
+
+ //! Returns the length of the tag's serial number obtained by getTagNumer()
+ byte getTagLength() { return tagLength; };
+
+ //! Returns the tag's serial number as a hexadecimal null-terminated string
+ const char* getTagString() { return tagString; };
+
+ //! Returns the tag type (SL018::MIFARE_XX)
+ byte getTagType() { return tagType; };
+
+ //! Returns the tag type as a null-terminated string
+ const char* getTagName() { return tagName(tagType); };
+
+ //! Returns the error code of the last executed command
+ char getErrorCode() { return errorCode; };
+
+ //! Returns a human-readable error message corresponding to the error code
+ const char* getErrorMessage();
+
+ //! Starts SEEK mode
+ void seekTag() { selectTag(); cmd = CMD_SEEK; };
+
+ //! Sends a SELECT_TAG command
+ void selectTag() { sendCommand(CMD_SELECT); };
+
+ //! Sends a HALT_TAG command
+ void haltTag() { cmd = CMD_IDLE; };
+
+ //! Sends a SLEEP command (can only wake-up with hardware reset!)
+ void sleep() { sendCommand(CMD_SLEEP); };
+
+ //! Writes a null-terminated string of maximum 15 characters to a block
+ void writeBlock(byte block, const char* message);
+
+ //! Writes a null-terminated string of maximum 3 characters to a Mifare Ultralight page
+ void writePage(byte page, const char* message);
+
+ //! Authenticate a sector using the transport key
+ void authenticate(byte sector);
+
+ //! Authenticate a sector using the specified key
+ void authenticate(byte sector, byte keyType, byte key[6]);
+
+ //! Reads a 16-byte block
+ void readBlock(byte block);
+
+ //! Reads a 4-byte page
+ void readPage(byte page);
+
+ //! Write master key (key A)
+ void writeKey(byte sector, byte key[6]);
+
+ //! LED control (SL018 only)
+ void led(boolean on);
+
+ private:
+ //! Send single-byte command
+ void sendCommand(byte cmd);
+ //! Transmit command packet over I2C
+ void transmitData();
+ //! Receive response packet over I2C
+ byte receiveData(byte length);
+ //! Returns human-readable tag name corresponding to tag type
+ const char* tagName(byte type);
+};
+
+#endif
diff --git a/arduino/lib/SL018/examples/UID/UID.ino b/arduino/lib/SL018/examples/UID/UID.ino
new file mode 100644
index 0000000..163d5e1
--- /dev/null
+++ b/arduino/lib/SL018/examples/UID/UID.ino
@@ -0,0 +1,38 @@
+/**
+ * @title: StrongLink SL018/SL030 RFID reader demo
+ * @author: marc@marcboon.com
+ * @see: http://www.stronglink.cn/english/sl018.htm
+ * @see: http://www.stronglink.cn/english/sl030.htm
+ *
+ * Arduino to SL018/SL030 wiring:
+ * A4/SDA 2 3
+ * A5/SCL 3 4
+ * 5V 4 -
+ * GND 5 6
+ * 3V3 - 1
+ */
+
+#include <Wire.h>
+#include <SL018.h>
+
+SL018 rfid;
+
+void setup()
+{
+ Wire.begin();
+ Serial.begin(19200);
+
+ // prompt for tag
+ Serial.println("Show me your tag");
+}
+
+void loop()
+{
+ // start seek mode
+ rfid.seekTag();
+ // wait until tag detected
+ while(!rfid.available());
+ // print tag id
+ Serial.println(rfid.getTagString());
+}
+
diff --git a/arduino/lib/SL018/examples/sl018demo/sl018demo.ino b/arduino/lib/SL018/examples/sl018demo/sl018demo.ino
new file mode 100644
index 0000000..c0759bf
--- /dev/null
+++ b/arduino/lib/SL018/examples/sl018demo/sl018demo.ino
@@ -0,0 +1,316 @@
+// SL018 demo application
+// Marc Boon <http://www.marcboon.com>
+// April 2010
+
+// Controls a StrongLink SL018 or SL030 RFID reader by I2C
+// Arduino to SL018/SL030 wiring:
+// A3/TAG 1 5
+// A4/SDA 2 3
+// A5/SCL 3 4
+// 5V 4 -
+// GND 5 6
+// 3V3 - 1
+
+#include <Wire.h>
+#include <SL018.h>
+
+// TAG pin (low level when tag present)
+#define TAG 17 // A3
+
+// Actions
+#define NONE 0
+#define SEEK 1
+#define READ 2
+#define WRITE 3
+
+// Create SL018 instance
+SL018 rfid;
+
+// Global vars
+byte action = NONE;
+boolean autoRead = false;
+boolean tagPresent = false;
+boolean authenticated;
+byte block;
+byte numBlocks;
+byte tagType;
+char msg[16];
+
+void setup()
+{
+ pinMode(TAG, INPUT);
+ Wire.begin();
+ Serial.begin(19200);
+ Serial.println("SL018 demo");
+
+ // reset rfid module
+// rfid.reset();
+
+ // help
+ Serial.println("Type ? for help");
+}
+
+void loop()
+{
+ // check for tag presence when auto read is enabled
+ if(autoRead && !tagPresent && !digitalRead(TAG) && action == NONE)
+ {
+ tagPresent = true;
+ // read tag
+ action = READ;
+ // specify what to read
+ block = 0;
+ numBlocks = 16;
+ // tag has to be selected first
+ rfid.selectTag();
+ }
+
+ // check if tag has gone
+ if(tagPresent && digitalRead(TAG))
+ {
+ tagPresent = false;
+ }
+
+ // check for command from serial port
+ if(Serial.available() > 0)
+ {
+ switch(Serial.read())
+ {
+ case '?':
+ Serial.println("Commands:");
+ Serial.println("A - Auto read on/off");
+ Serial.println("D - Debug on/off");
+ Serial.println("S - Seek tag");
+ Serial.println("R - Read sector");
+ Serial.println("W - Write string");
+ Serial.println("Q - Sleep");
+ Serial.println("X - Reset");
+ break;
+ case 'a':
+ case 'A':
+ // auto read on/off
+ autoRead = !autoRead;
+ Serial.print("Auto read ");
+ Serial.println(autoRead ? "on" : "off");
+ break;
+ case 'd':
+ case 'D':
+ // debug on/off
+ rfid.debug = !rfid.debug;
+ Serial.print("Debug ");
+ Serial.println(rfid.debug ? "on" : "off");
+ break;
+ case 's':
+ case 'S':
+ // seek tag
+ Serial.println("Seek");
+ rfid.seekTag();
+ action = SEEK;
+ break;
+ case 'r':
+ case 'R':
+ // read tag
+ Serial.println("Read");
+ action = READ;
+ // specify what to read
+ block = 0;
+ numBlocks = 16;
+ // tag has to be selected first
+ rfid.selectTag();
+ break;
+ case 'w':
+ case 'W':
+ // collect up to 15 characters from input, and terminate with zero
+ if(readQuotedString(msg, sizeof(msg)) > 0)
+ {
+ // write string to tag
+ Serial.print("Write '");
+ Serial.print(msg);
+ Serial.println("'");
+ action = WRITE;
+ block = 1;
+ // tag has to be selected first
+ rfid.selectTag();
+ }
+ break;
+ case 'q':
+ case 'Q':
+ // enter sleep mode
+ Serial.println("Sleep");
+ rfid.sleep();
+ break;
+ case 'x':
+ case 'X':
+ // reset
+ Serial.println("Reset");
+ rfid.reset();
+ action = NONE;
+ break;
+ }
+ }
+
+ // check for response from rfid
+ if(rfid.available())
+ {
+ // check for errors
+ if(rfid.getErrorCode() != SL018::OK && rfid.getErrorCode() != SL018::LOGIN_OK)
+ {
+ if(action != SEEK) // ignore errors while in SEEK mode
+ {
+ Serial.println(rfid.getErrorMessage());
+ rfid.haltTag();
+ action = NONE;
+ }
+ }
+ else // deal with response if no error
+ {
+ switch(rfid.getCommand())
+ {
+ case SL018::CMD_SEEK:
+ case SL018::CMD_SELECT:
+ // store tag type
+ tagType = rfid.getTagType();
+ // show tag name and serial number
+ Serial.print(rfid.getTagName());
+ Serial.print(' ');
+ Serial.println(rfid.getTagString());
+ // in case of read or write action, authenticate first
+ if(action == READ || action == WRITE)
+ {
+ // mifare ultralight does not need authentication, and has 4-byte blocks
+ if(tagType == SL018::MIFARE_ULTRALIGHT)
+ {
+ authenticated = true;
+ if(action == READ)
+ {
+ rfid.readPage(block);
+ }
+ else
+ {
+ // write to last page (because all others are write-protected on tikitags)
+ rfid.writePage(15, msg);
+ }
+ }
+ else
+ {
+ authenticated = false;
+ rfid.authenticate(block >> 2);
+ }
+ }
+ else
+ {
+ // terminate seek
+ rfid.haltTag();
+ action = NONE;
+ }
+ break;
+ case SL018::CMD_LOGIN:
+ authenticated = true;
+ if(action == READ)
+ {
+ rfid.readBlock(block);
+ }
+ else if(action == WRITE)
+ {
+ rfid.writeBlock(block, msg);
+ }
+ break;
+ case SL018::CMD_READ4:
+ case SL018::CMD_READ16:
+ if(rfid.getCommand() == SL018::CMD_READ4)
+ {
+ // print 4-byte page in hex and ascii
+ Serial.print("Page ");
+ printHex(block);
+ Serial.print(": ");
+ printArrayHex(rfid.getBlock(), 4);
+ Serial.print(" ");
+ printArrayAscii(rfid.getBlock(), 4);
+ Serial.println();
+ }
+ else
+ {
+ // print 16-byte block in hex and ascii
+ Serial.print("Block ");
+ printHex(block);
+ Serial.print(": ");
+ printArrayHex(rfid.getBlock(), 16);
+ Serial.print(" ");
+ printArrayAscii(rfid.getBlock(), 16);
+ Serial.println();
+ }
+ // get next block
+ if(++block && --numBlocks)
+ {
+ // mifare ultralight does not need authentication, and has 4-byte pages
+ if(tagType == SL018::MIFARE_ULTRALIGHT)
+ {
+ rfid.readPage(block);
+ }
+ else if(authenticated && (block & 0x03) != 0)
+ {
+ // blocks from same sector don't need further authentication
+ rfid.readBlock(block);
+ }
+ else
+ {
+ // authenticate next sector (4 blocks per sector)
+ authenticated = false;
+ rfid.authenticate(block >> 2);
+ }
+ }
+ else // read completed
+ {
+ rfid.haltTag();
+ action = NONE;
+ }
+ break;
+ case SL018::CMD_WRITE4:
+ case SL018::CMD_WRITE16:
+ // write completed
+ Serial.println("OK");
+ rfid.haltTag();
+ action = NONE;
+ break;
+ }
+ }
+ }
+}
+
+int readQuotedString(char *s, int len)
+{
+ int i = 0;
+ char quote = 0;
+ while(i < len)
+ {
+ delay(5);
+ if(Serial.available() == 0)
+ {
+ break;
+ }
+ *s = Serial.read();
+ if(quote == 0)
+ {
+ if(*s == '"' || *s == '\'')
+ {
+ quote = *s;
+ }
+ else if(*s != ' ')
+ {
+ ++s;
+ ++i;
+ }
+ }
+ else if(*s == quote)
+ {
+ break;
+ }
+ else
+ {
+ ++s;
+ ++i;
+ }
+ }
+ *s = 0;
+ return i;
+}
diff --git a/arduino/lib/SL018/examples/twoReaders/twoReaders.ino b/arduino/lib/SL018/examples/twoReaders/twoReaders.ino
new file mode 100644
index 0000000..9ec9371
--- /dev/null
+++ b/arduino/lib/SL018/examples/twoReaders/twoReaders.ino
@@ -0,0 +1,83 @@
+/**
+ * @title: StrongLink SL018/SL030 RFID 2-reader demo
+ * @author: lukasz.szostek@gmail.com based on code of:
+ * @author: marc@marcboon.com
+ * @see: http://www.stronglink.cn/english/sl018.htm
+ * @see: http://www.stronglink.cn/english/sl030.htm
+ *
+ * Arduino to SL018/SL030 wiring:
+ * A4/SDA 2 3
+ * A5/SCL 3 4
+ * 5V 4 -
+ * GND 5 6
+ * 3V3 - 1
+ * 5 1 5 // first reader
+ * 4 1 5 // second reader
+ */
+
+#include <Wire.h>
+#include <SL018.h>
+
+//pins to listen for the RFID board signalling that it has detected a tag
+int reader1OutPin = 5;
+int reader2OutPin = 4;
+const char* tagString;
+
+SL018 rfid1;
+SL018 rfid2;
+
+void setup()
+{
+ //make sure these two addresses match your reader configuration
+ rfid1.address = 0x50;
+ rfid2.address = 0x52;
+ pinMode(reader1OutPin, INPUT);
+ pinMode(reader2OutPin, INPUT);
+ Wire.begin();
+ Serial.begin(57600);
+
+ // prompt for tag
+ Serial.println("Show me your tag");
+}
+
+void loop()
+{
+ //if the board has signalled that it found a tag
+ if(!digitalRead(reader1OutPin))
+ {
+ //query tag data
+ rfid1.seekTag();
+
+ /* for some reason the loop defined as:
+ while(!digitalRead(reader1OutPin) || !rfid1.available());
+ does not work so we need a workaround:*/
+
+ //while we are waiting for data
+ while(!rfid1.available()) {
+ //break if the tag has been removed
+ if (digitalRead(reader1OutPin)) {
+ break;
+ };
+ };
+ tagString = rfid1.getTagString();
+ Serial.print("Reader 1 found: ");
+ Serial.println(tagString);
+ //wait a while before querying the tag again
+ delay(1500);
+ };
+
+ //"in parallel" we wait for the other reader
+ if(!digitalRead(reader2OutPin))
+ {
+ rfid2.seekTag();
+ while(!rfid2.available()) {
+ if (digitalRead(reader2OutPin)) {
+ break;
+ };
+ };
+ tagString = rfid2.getTagString();
+ Serial.print("Reader 2 found: ");
+ Serial.println(tagString);
+ delay(1500);
+ };
+} \ No newline at end of file
diff --git a/arduino/lib/SL018/keywords.txt b/arduino/lib/SL018/keywords.txt
new file mode 100644
index 0000000..28efac1
--- /dev/null
+++ b/arduino/lib/SL018/keywords.txt
@@ -0,0 +1,48 @@
+#######################################
+# Syntax Coloring Map For SL018
+#######################################
+
+#######################################
+# Datatypes (KEYWORD1)
+#######################################
+
+SL018 KEYWORD1
+
+#######################################
+# Methods and Functions (KEYWORD2)
+#######################################
+
+seekTag KEYWORD2
+selectTag KEYWORD2
+authenticate KEYWORD2
+readBlock KEYWORD2
+readPage KEYWORD2
+writeBlock KEYWORD2
+writePage KEYWORD2
+reset KEYWORD2
+led KEYWORD2
+
+#######################################
+# Constants (LITERAL1)
+#######################################
+
+MIFARE_1K LITERAL1
+MIFARE_PRO LITERAL1
+MIFARE_ULTRALIGHT LITERAL1
+MIFARE_4K LITERAL1
+MIFARE_PROX LITERAL1
+MIFARE_DESFIRE LITERAL1
+
+OK LITERAL1
+NO_TAG LITERAL1
+LOGIN_OK LITERAL1
+LOGIN_FAIL LITERAL1
+READ_FAIL LITERAL1
+WRITE_FAIL LITERAL1
+CANT_VERIFY LITERAL1
+COLLISION LITERAL1
+KEY_FAIL LITERAL1
+NO_LOGIN LITERAL1
+NO_VALUE LITERAL1
+
+ \ No newline at end of file
diff --git a/libraries/Sha/examples/hmacsha256test/hmacsha256test.pde b/arduino/lib/Sha/examples/hmacsha256test/hmacsha256test.pde
index e7b925e..e7b925e 100644
--- a/libraries/Sha/examples/hmacsha256test/hmacsha256test.pde
+++ b/arduino/lib/Sha/examples/hmacsha256test/hmacsha256test.pde
diff --git a/libraries/Sha/examples/sha1test/sha1test.pde b/arduino/lib/Sha/examples/sha1test/sha1test.pde
index 9fd205b..9fd205b 100644
--- a/libraries/Sha/examples/sha1test/sha1test.pde
+++ b/arduino/lib/Sha/examples/sha1test/sha1test.pde
diff --git a/libraries/Sha/examples/sha256test/sha256test.pde b/arduino/lib/Sha/examples/sha256test/sha256test.pde
index 2f9b932..2f9b932 100644
--- a/libraries/Sha/examples/sha256test/sha256test.pde
+++ b/arduino/lib/Sha/examples/sha256test/sha256test.pde
diff --git a/libraries/Sha/keywords.txt b/arduino/lib/Sha/keywords.txt
index a48af9b..a48af9b 100644
--- a/libraries/Sha/keywords.txt
+++ b/arduino/lib/Sha/keywords.txt
diff --git a/libraries/Sha/readme.txt b/arduino/lib/Sha/readme.txt
index bf1dbd8..bf1dbd8 100644
--- a/libraries/Sha/readme.txt
+++ b/arduino/lib/Sha/readme.txt
diff --git a/libraries/Sha/sha1.cpp b/arduino/lib/Sha/sha1.cpp
index 003093d..003093d 100644
--- a/libraries/Sha/sha1.cpp
+++ b/arduino/lib/Sha/sha1.cpp
diff --git a/libraries/Sha/sha1.h b/arduino/lib/Sha/sha1.h
index 9eef9fe..9eef9fe 100644
--- a/libraries/Sha/sha1.h
+++ b/arduino/lib/Sha/sha1.h
diff --git a/libraries/Sha/sha256.cpp b/arduino/lib/Sha/sha256.cpp
index ee23113..ee23113 100644
--- a/libraries/Sha/sha256.cpp
+++ b/arduino/lib/Sha/sha256.cpp
diff --git a/libraries/Sha/sha256.h b/arduino/lib/Sha/sha256.h
index 7f9eed2..7f9eed2 100644
--- a/libraries/Sha/sha256.h
+++ b/arduino/lib/Sha/sha256.h
diff --git a/arduino/doorman/config.h b/arduino/src/config.h
index 126e51f..126e51f 100644
--- a/arduino/doorman/config.h
+++ b/arduino/src/config.h
diff --git a/arduino/doorman/doorman.ino b/arduino/src/doorman.ino
index 384e936..384e936 100644
--- a/arduino/doorman/doorman.ino
+++ b/arduino/src/doorman.ino
diff --git a/arduino/doorman/emem.cpp b/arduino/src/emem.cpp
index 50fa99d..50fa99d 100644
--- a/arduino/doorman/emem.cpp
+++ b/arduino/src/emem.cpp
diff --git a/arduino/doorman/emem.h b/arduino/src/emem.h
index 72d0e0e..72d0e0e 100644
--- a/arduino/doorman/emem.h
+++ b/arduino/src/emem.h
diff --git a/arduino/doorman/keypad.cpp b/arduino/src/keypad.cpp
index 87b90c4..87b90c4 100644
--- a/arduino/doorman/keypad.cpp
+++ b/arduino/src/keypad.cpp
diff --git a/arduino/doorman/keypad.h b/arduino/src/keypad.h
index f703207..f703207 100644
--- a/arduino/doorman/keypad.h
+++ b/arduino/src/keypad.h
diff --git a/arduino/doorman/pc.cpp b/arduino/src/pc.cpp
index 5c5841c..5c5841c 100644
--- a/arduino/doorman/pc.cpp
+++ b/arduino/src/pc.cpp
diff --git a/arduino/doorman/pc.h b/arduino/src/pc.h
index 30a3992..30a3992 100644
--- a/arduino/doorman/pc.h
+++ b/arduino/src/pc.h
diff --git a/arduino/doorman/rf.cpp b/arduino/src/rf.cpp
index da8361f..da8361f 100644
--- a/arduino/doorman/rf.cpp
+++ b/arduino/src/rf.cpp
diff --git a/arduino/doorman/rf.h b/arduino/src/rf.h
index dfdbea4..dfdbea4 100644
--- a/arduino/doorman/rf.h
+++ b/arduino/src/rf.h