summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSergiusz 'q3k' Bazański <q3k@q3k.org>2015-03-07 02:58:07 +0100
committerSergiusz 'q3k' Bazański <q3k@q3k.org>2015-03-07 02:58:07 +0100
commiteb0a11c7068955c74786ff5475a827c01d3cd64d (patch)
treec68e3667e5a199e0bff0e96f57ff39abc1fbf2c6
parentd15ede7072e694082657560d63dab4d9a905333a (diff)
downloaddoorman-eb0a11c7068955c74786ff5475a827c01d3cd64d.tar.gz
doorman-eb0a11c7068955c74786ff5475a827c01d3cd64d.tar.bz2
doorman-eb0a11c7068955c74786ff5475a827c01d3cd64d.zip
Final new version.
-rw-r--r--.gitignore2
-rwxr-xr-xadmin/doorman_add4
-rw-r--r--admin/lib/.command.py.swpbin12288 -> 0 bytes
-rw-r--r--admin/options.py6
-rw-r--r--arduino/lib/SL018/README7
-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/twoReaders/twoReaders.ino83
-rw-r--r--arduino/lib/SL018/keywords.txt48
-rw-r--r--arduino/lib/SM130/README7
-rw-r--r--arduino/lib/SM130/SM130.cpp (renamed from arduino/lib/SL018/SL018.cpp)392
-rw-r--r--arduino/lib/SM130/SM130.h147
-rw-r--r--arduino/lib/SM130/examples/sm130demo/sm130demo.ino (renamed from arduino/lib/SL018/examples/sl018demo/sl018demo.ino)223
-rw-r--r--arduino/lib/SM130/examples/sm130seek/sm130seek.ino51
-rw-r--r--arduino/lib/SM130/keywords.txt61
-rw-r--r--arduino/src/.pc.cpp.swpbin16384 -> 0 bytes
-rw-r--r--arduino/src/config.h2
-rw-r--r--arduino/src/doorman.ino6
-rw-r--r--arduino/src/keypad.cpp2
-rw-r--r--arduino/src/pc.cpp4
-rw-r--r--arduino/src/rf.cpp109
-rw-r--r--arduino/src/rf.h2
22 files changed, 632 insertions, 739 deletions
diff --git a/.gitignore b/.gitignore
index f3d74a9..403845c 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,2 +1,4 @@
*.pyc
*~
+*.swp
+arduino/eeprom.bin
diff --git a/admin/doorman_add b/admin/doorman_add
index a2301e9..ac9cfbc 100755
--- a/admin/doorman_add
+++ b/admin/doorman_add
@@ -41,7 +41,9 @@ if __name__ == '__main__':
if frame.uid:
print >> stderr, 'E: Token already in use (user %d)' % frame.uid
exit(1)
- status = add(token, frame.hash, proto=proto)
+ else:
+ card = args.card
+ status = add(token, card, proto=proto)
if status.command.upper() != 'C':
print >> stderr, 'Unknown error:', str(status)
exit(1)
diff --git a/admin/lib/.command.py.swp b/admin/lib/.command.py.swp
deleted file mode 100644
index 7498cf8..0000000
--- a/admin/lib/.command.py.swp
+++ /dev/null
Binary files differ
diff --git a/admin/options.py b/admin/options.py
index 629e30e..6f6fc5f 100644
--- a/admin/options.py
+++ b/admin/options.py
@@ -1,4 +1,4 @@
-url = '/dev/ttyACM0'
+url = '/dev/ttyUSB6'
serial = dict(
baudrate = 19200,
timeout = 60,
@@ -9,7 +9,7 @@ csv = './cards.csv'
storage = 'csv'
#whether the storage method should be encrypted
-storage_encrypt = True
+storage_encrypt = False
uid_bytes = 4
cmd_bytes = 1
@@ -19,6 +19,6 @@ empty_mid = 0
hash_bytes = 64
-token_bytes = 8
+mac_bytes = 64
init_sleep = 5
diff --git a/arduino/lib/SL018/README b/arduino/lib/SL018/README
deleted file mode 100644
index 555f43f..0000000
--- a/arduino/lib/SL018/README
+++ /dev/null
@@ -1,7 +0,0 @@
-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.h b/arduino/lib/SL018/SL018.h
deleted file mode 100644
index 4eeedd1..0000000
--- a/arduino/lib/SL018/SL018.h
+++ /dev/null
@@ -1,177 +0,0 @@
-/**
- * @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
deleted file mode 100644
index 163d5e1..0000000
--- a/arduino/lib/SL018/examples/UID/UID.ino
+++ /dev/null
@@ -1,38 +0,0 @@
-/**
- * @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/twoReaders/twoReaders.ino b/arduino/lib/SL018/examples/twoReaders/twoReaders.ino
deleted file mode 100644
index 9ec9371..0000000
--- a/arduino/lib/SL018/examples/twoReaders/twoReaders.ino
+++ /dev/null
@@ -1,83 +0,0 @@
-/**
- * @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
deleted file mode 100644
index 28efac1..0000000
--- a/arduino/lib/SL018/keywords.txt
+++ /dev/null
@@ -1,48 +0,0 @@
-#######################################
-# 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/arduino/lib/SM130/README b/arduino/lib/SM130/README
new file mode 100644
index 0000000..b69de3b
--- /dev/null
+++ b/arduino/lib/SM130/README
@@ -0,0 +1,7 @@
+Arduino library for SonMicro SM130 RFID reader
+
+see:
+http://www.sonmicro.com/en/index.php?option=com_content&view=article&id=57&Itemid=70
+
+June 2011
+marc@marcboon.com \ No newline at end of file
diff --git a/arduino/lib/SL018/SL018.cpp b/arduino/lib/SM130/SM130.cpp
index ef4428b..5ac31db 100644
--- a/arduino/lib/SL018/SL018.cpp
+++ b/arduino/lib/SM130/SM130.cpp
@@ -1,36 +1,45 @@
/**
- * @title StrongLink SL018/SL030 RFID reader library
+ * @file SM130.cpp
+ * @brief SM130 library for Arduino
+ * @author Marc Boon <http://www.marcboon.com>
+ * @date February 2012
*
- * @file SL018.cpp
- * @author marc@marcboon.com
- * @modified fil@rezox.com (Filipe Laborde-Basto) [to make binary safe]
- * @date February 2012
+ * <p>
+ * Controls a SonMicro SM130/mini RFID reader or RFIDuino by I2C
+ * </p>
+ * <p>
+ * Arduino analog input 4 is I2C SDA (SM130/mini pin 10/6)<br>
+ * Arduino analog input 5 is I2C SCL (SM130/mini pin 9/5)<br>
+ * Arduino digital input 4 is DREADY (SM130/mini pin 21/18)<br>
+ * Arduino digital output 3 is RESET (SM130/mini pin 18/14)
+ * </p>
*
- * @see http://www.stronglink.cn/english/sl018.htm
- * @see http://www.stronglink.cn/english/sl030.htm
+ * @see http://www.arduino.cc
+ * @see http://www.sonmicro.com/1356/sm130.php
+ * @see http://rfid.marcboon.com
*/
-
+
#include <Wire.h>
#include <string.h>
-#include "SL018.h"
-// local prototypes
+#include "SM130.h"
+
+// local functions
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
+ * An instance of SM130 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.
+ * The constructor sets data fields to default values for use with RFIDuino.
+ * These may be changed in setup() before SM130::reset() is called.
*/
-SL018::SL018()
+SM130::SM130()
{
- address = 0x50;
- pinRESET = -1;
- pinDREADY = -1;
- cmd = CMD_IDLE;
+ address = 0x42;
+ pinRESET = 3;
+ pinDREADY = 4;
debug = false;
t = millis() + 10;
}
@@ -38,20 +47,20 @@ SL018::SL018()
/* Public member functions ****************************************************/
-/** Reset the SL018 module
+/** Reset the SM130 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.
+ * After reset, a HALT_TAG command is issued 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.
+ * If pinRESET has the value 0xff (-1), software reset over I2C will be used.
+ * If pinDREADY has the value 0xff (-1), the SM130 will be polled over I2C while
+ * in SEEK mode, otherwise the DREADY pin will be polled in SEEK mode.
* For other commands, response polling is always over I2C.
*/
-void SL018::reset()
+void SM130::reset()
{
// Init DREADY pin
if (pinDREADY != 0xff)
@@ -74,6 +83,32 @@ void SL018::reset()
// Allow enough time for reset
delay(200);
+
+ // Set antenna power
+ setAntennaPower(1);
+
+ // To cancel automatic seek mode after reset, we send a HALT_TAG command
+ haltTag();
+}
+
+/** Get the firmware version string.
+ */
+const char* SM130::getFirmwareVersion()
+{
+ // return immediately if version string already retrieved
+ if (*versionString != 0)
+ return versionString;
+
+ // else send VERSION command and retry a few times if no response
+ for (byte n = 0; n < 10; n++)
+ {
+ sendCommand(CMD_VERSION);
+ if (available() && getCommand() == CMD_VERSION)
+ return versionString;
+ delay(100);
+ }
+ // time-out after 1s
+ return 0;
}
/** Checks for availability of a valid response packet.
@@ -83,35 +118,34 @@ void SL018::reset()
*
* @returns true if a valid response packet is available
*/
-boolean SL018::available()
+boolean SM130::available()
{
+ // If in SEEK mode and using DREADY pin, check the status
+ if (cmd == CMD_SEEK_TAG && pinDREADY != 0xff)
+ {
+ if (!digitalRead(pinDREADY))
+ return false;
+ }
+
// 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_ANTENNA_POWER:
+ case CMD_AUTHENTICATE:
case CMD_DEC_VALUE:
case CMD_INC_VALUE:
- case CMD_COPY_VALUE:
- len = 7;
- break;
case CMD_WRITE_KEY:
- len = 9;
+ case CMD_HALT_TAG:
+ case CMD_SLEEP:
+ len = 4;
break;
- case CMD_SEEK:
- case CMD_SELECT:
+ case CMD_WRITE4:
+ case CMD_WRITE_VALUE:
+ case CMD_READ_VALUE:
+ len = 8;
+ case CMD_SEEK_TAG:
+ case CMD_SELECT_TAG:
len = 11;
break;
default:
@@ -119,33 +153,58 @@ boolean SL018::available()
}
// If valid data received, process the response packet
- if (len && receiveData(len) > 0)
+ if (receiveData(len) > 0)
{
// Init response variables
tagType = tagLength = *tagString = 0;
- errorCode = data[2];
+
+ // If packet length is 2, the command failed. Set error code.
+ errorCode = getPacketLength() < 3 ? data[2] : 0;
// Process command response
switch (getCommand())
{
- case CMD_SEEK:
- case CMD_SELECT:
+ case CMD_RESET:
+ case CMD_VERSION:
+ // RESET and VERSION commands produce the firmware version
+ len = min(getPacketLength(), sizeof(versionString)) - 1;
+ memcpy(versionString, data + 2, len);
+ versionString[len] = 0;
+ break;
+
+ case CMD_SEEK_TAG:
+ case CMD_SELECT_TAG:
// If no error, get tag number
- if(errorCode == 0 && getPacketLength() >= 7)
+ if(errorCode == 0 && getPacketLength() >= 6)
{
- tagLength = getPacketLength() - 3;
- tagType = data[getPacketLength()];
+ tagLength = getPacketLength() - 2;
+ tagType = data[2];
memcpy(tagNumber, data + 3, tagLength);
arrayToHex(tagString, tagNumber, tagLength);
}
- else if(cmd == CMD_SEEK)
- {
- // Continue seek
- seekTag();
- return false;
- }
+ break;
+
+ case CMD_AUTHENTICATE:
+ break;
+
+ case CMD_READ16:
+ break;
+
+ case CMD_WRITE16:
+ case CMD_WRITE4:
+ break;
+
+ case CMD_ANTENNA_POWER:
+ errorCode = 0;
+ antennaPower = data[2];
+ break;
+
+ case CMD_SLEEP:
+ // If in SLEEP mode, no data is available
+ return false;
}
- // Data is available
+
+ // Data available
return true;
}
// No data available
@@ -156,63 +215,74 @@ boolean SL018::available()
*
* @return Human-readable error message as a null-terminated string
*/
-const char* SL018::getErrorMessage()
+const char* SM130::getErrorMessage()
{
switch(errorCode)
{
+ case 'L':
+ if(getCommand() == CMD_SEEK_TAG) return "Seek in progress";
case 0:
return "OK";
- case 1:
+ case 'N':
+ if(getCommand() == CMD_WRITE_KEY) return "Write master key failed";
+ if(getCommand() == CMD_SET_BAUD) return "Set baud rate failed";
+ if(getCommand() == CMD_AUTHENTICATE) return "No tag present or login failed";
return "No tag present";
- case 2:
- return "Login OK";
- case 3:
- case 0x10:
- return "Login failed";
- case 4:
- return "Read failed";
- case 5:
+ case 'U':
+ if(getCommand() == CMD_AUTHENTICATE) return "Authentication failed";
+ if(getCommand() == CMD_WRITE16 || getCommand() == CMD_WRITE4) return "Verification failed";
+ return "Antenna off";
+ case 'F':
+ if(getCommand() == CMD_READ16) return "Read failed";
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";
+ case 'I':
+ return "Invalid value block";
+ case 'X':
+ return "Block is read-protected";
+ case 'E':
+ return "Invalid key format in EEPROM";
default:
return "Unknown error";
}
}
+/** Turns on/off the RF field.
+ *
+ * @param level 0 is off, anything else is on
+ */
+void SM130::setAntennaPower(byte level)
+{
+ antennaPower = level;
+ data[0] = 2;
+ data[1] = CMD_ANTENNA_POWER;
+ data[2] = antennaPower;
+ transmitData();
+}
+
/** Authenticate with transport key (0xFFFFFFFFFFFF).
*
- * @param sector Sector number
+ * @param block Block number
*/
-void SL018::authenticate(byte sector)
+void SM130::authenticate(byte block)
{
- data[0] = 9;
- data[1] = CMD_LOGIN;
- data[2] = sector;
- data[3] = 0xAA;
- memset(data + 4, 0xFF, 6);
+ data[0] = 3;
+ data[1] = CMD_AUTHENTICATE;
+ data[2] = block;
+ data[3] = 0xff;
transmitData();
}
/** Authenticate with specified key A or key B.
*
- * @param sector Sector number
+ * @param block Block 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])
+void SM130::authenticate(byte block, byte keyType, byte key[6])
{
data[0] = 9;
- data[1] = CMD_LOGIN;
- data[2] = sector;
+ data[1] = CMD_AUTHENTICATE;
+ data[2] = block;
data[3] = keyType;
memcpy(data + 4, key, 6);
transmitData();
@@ -222,7 +292,7 @@ void SL018::authenticate(byte sector, byte keyType, byte key[6])
*
* @param block Block number
*/
-void SL018::readBlock(byte block)
+void SM130::readBlock(byte block)
{
data[0] = 2;
data[1] = CMD_READ16;
@@ -230,86 +300,46 @@ void SL018::readBlock(byte 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)
+ * @param message Null-terminated string of up to 15 characters
*/
-void SL018::writeBlock(byte block, const char* message)
+void SM130::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 );
+ strncpy((char*)data + 3, message, 15);
data[18] = 0;
transmitData();
}
-/** Write 4-byte page.
+/** Write 4-byte block.
*
- * This command is used for Mifare Ultralight tags which have 4 byte pages.
+ * This command is used for Mifare Ultralight tags which have 4 byte blocks.
*
- * @param page Page number
- * @param message String of 4 characters
+ * @param block Block number
+ * @param message Null-terminated string of up to 3 characters
*/
-void SL018::writePage(byte page, const char* message)
+void SM130::writeFourByteBlock(byte block, 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[2] = block;
+ strncpy((char*)data + 3, message, 3);
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)
+void SM130::sendCommand(byte cmd)
{
data[0] = 1;
data[1] = cmd;
@@ -319,52 +349,56 @@ void SL018::sendCommand(byte cmd)
/* Private member functions ****************************************************/
-/** Transmit a packet to the SL018.
+/** Transmit a packet with checksum to the SM130.
*/
- /*
- data[0] = 18;
- data[1] = CMD_WRITE16;
- data[2] = block;
- strncpy((char*)data + 3, message, 15);
- data[18] = 0;
- */
-void SL018::transmitData()
+void SM130::transmitData()
{
// wait until at least 20ms passed since last I2C transmission
while(t > millis());
t = millis() + 20;
+ // init checksum and packet length
+ byte sum = 0;
+ byte len = data[0] + 1;
+
// remember which command was sent
cmd = data[1];
// transmit packet with checksum
Wire.beginTransmission(address);
-
- for (int i = 0; i <= data[0]; i++)
+ for (int i = 0; i < len; i++)
{
#if defined(ARDUINO) && ARDUINO >= 100
Wire.write(data[i]);
#else
Wire.send(data[i]);
#endif
+ sum += data[i];
}
+#if defined(ARDUINO) && ARDUINO >= 100
+ Wire.write(sum);
+#else
+ Wire.send(sum);
+#endif
Wire.endTransmission();
// show transmitted packet for debugging
if (debug)
{
Serial.print("> ");
- printArrayHex( data, data[0] + 1);
+ printArrayHex(data, len);
+ Serial.print(' ');
+ printHex(sum);
Serial.println();
}
}
-/** Receives a packet from the SL018.
+/** Receives a packet from the SM130 and verifies the checksum.
*
* @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)
+byte SM130::receiveData(byte length)
{
// wait until at least 20ms passed since last I2C transmission
while(t > millis());
@@ -372,22 +406,17 @@ byte SL018::receiveData(byte length)
// read response
Wire.requestFrom(address, length);
- if(Wire.available())
+ byte n = Wire.available();
+
+ // get data if available
+ if(n > 0)
{
- // 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++)
+ for (byte i = 0; i < n;)
{
#if defined(ARDUINO) && ARDUINO >= 100
- data[i] = Wire.read();
+ data[i++] = Wire.read();
#else
- data[i] = Wire.receive();
+ data[i++] = Wire.receive();
#endif
}
@@ -395,12 +424,21 @@ byte SL018::receiveData(byte length)
if (debug && data[0] > 0 )
{
Serial.print("< ");
- printArrayHex(data, data[0] + 1);
+ printArrayHex(data, n);
Serial.println();
}
- // return with length of response
- return data[0];
+ // verify checksum if length > 0 and <= SIZE_PAYLOAD
+ if (data[0] > 0 && data[0] <= SIZE_PAYLOAD)
+ {
+ byte i, sum;
+ for (i = 0, sum = 0; i <= data[0]; i++)
+ {
+ sum += data[i];
+ }
+ // return with length of response, or -1 if invalid checksum
+ return sum == data[i] ? data[0] : -1;
+ }
}
return 0;
}
@@ -410,21 +448,17 @@ byte SL018::receiveData(byte length)
* @param type numeric tag type
* @return Human-readable tag name as null-terminated string
*/
-const char* SL018::tagName(byte type)
+const char* SM130::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 "";
+ case 1: return "Mifare UL";
+ case 2: return "Mifare 1K";
+ case 3: return "Mifare 4K";
+ default: return "Unknown Tag";
}
}
-
// Global helper functions
/** Convert byte array to null-terminated hexadecimal string.
diff --git a/arduino/lib/SM130/SM130.h b/arduino/lib/SM130/SM130.h
new file mode 100644
index 0000000..fee602d
--- /dev/null
+++ b/arduino/lib/SM130/SM130.h
@@ -0,0 +1,147 @@
+/**
+ * @file SM130.h
+ * @brief Header file for SM130 library
+ * @author Marc Boon <http://www.marcboon.com>
+ * @date February 2012
+ */
+
+#ifndef SM130_h
+#define SM130_h
+
+#if defined(ARDUINO) && ARDUINO >= 100
+#include "Arduino.h"
+#else
+#include "WProgram.h"
+#endif
+
+#define SIZE_PAYLOAD 18 // maximum payload size of I2C packet
+#define SIZE_PACKET (SIZE_PAYLOAD + 2) // total I2C packet size, including length byte and checksum
+
+#define halt haltTag // deprecated function halt() renamed to haltTag()
+
+// Global functions
+void printArrayAscii(byte array[], byte len);
+void printArrayHex(byte array[], byte len);
+void printHex(byte val);
+
+/** Class representing a <a href="http://www.sonmicro.com/en/index.php?option=com_content&view=article&id=57&Itemid=70">SonMicro SM130 RFID module</a>.
+ *
+ * Nearly complete implementation of the <a href="http://www.sonmicro.com/en/downloads/Mifare/ds_SM130.pdf">SM130 datasheet</a>.<br>
+ * Functions dealing with value blocks and stored keys are not implemented.
+ */
+class SM130
+{
+ byte data[SIZE_PACKET]; //!< packet data
+ char versionString[8]; //!< version string
+ 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 antennaPower; //!< antenna power level
+ byte cmd; //!< last sent command
+ unsigned long t; //!< timer for sending I2C commands
+
+public:
+ static const int VERSION = 1; //!< version of this library
+
+ static const byte MIFARE_ULTRALIGHT = 1;
+ static const byte MIFARE_1K = 2;
+ static const byte MIFARE_4K = 3;
+
+ static const byte CMD_RESET = 0x80;
+ static const byte CMD_VERSION = 0x81;
+ static const byte CMD_SEEK_TAG = 0x82;
+ static const byte CMD_SELECT_TAG = 0x83;
+ static const byte CMD_AUTHENTICATE = 0x85;
+ static const byte CMD_READ16 = 0x86;
+ static const byte CMD_READ_VALUE = 0x87;
+ static const byte CMD_WRITE16 = 0x89;
+ static const byte CMD_WRITE_VALUE = 0x8a;
+ static const byte CMD_WRITE4 = 0x8b;
+ static const byte CMD_WRITE_KEY = 0x8c;
+ static const byte CMD_INC_VALUE = 0x8d;
+ static const byte CMD_DEC_VALUE = 0x8e;
+ static const byte CMD_ANTENNA_POWER = 0x90;
+ static const byte CMD_READ_PORT = 0x91;
+ static const byte CMD_WRITE_PORT = 0x92;
+ static const byte CMD_HALT_TAG = 0x93;
+ static const byte CMD_SET_BAUD = 0x94;
+ static const byte CMD_SLEEP = 0x96;
+
+ boolean debug; //!< debug mode, prints all I2C communication to Serial port
+ byte address; //!< I2C address (default 0x42)
+ byte pinRESET; //!< RESET pin (default 3)
+ byte pinDREADY; //!< DREADY pin (default 4)
+
+ //! Constructor
+ SM130();
+ //! Hardware or software reset of the SM130 module
+ void reset();
+ //! Returns a null-terminated string with the firmware version of the SM130 module
+ const char* getFirmwareVersion();
+ //! 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 data[1]; };
+ //! Returns the packet length, excluding checksum
+ byte getPacketLength() { return data[0]; };
+ //! Returns the checksum
+ byte getCheckSum() { return data[data[0]+1]; };
+ //! 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 (SM130::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();
+ //! Returns the antenna power level (0 or 1)
+ byte getAntennaPower() { return antennaPower; };
+ //! Sends a SEEK_TAG command
+ void seekTag() { sendCommand(CMD_SEEK_TAG); };
+ //! Sends a SELECT_TAG command
+ void selectTag() { sendCommand(CMD_SELECT_TAG); };
+ //! Sends a HALT_TAG command
+ void haltTag() { sendCommand(CMD_HALT_TAG); };
+ //! Set antenna power (on/off)
+ void setAntennaPower(byte level);
+ //! 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
+ void writeBlock(byte block, const char* message);
+ //! Writes a null-terminated string of maximum 3 characters to a Mifare Ultralight
+ void writeFourByteBlock(byte block, const char* message);
+ //! Sends a AUTHENTICATE command using the transport key
+ void authenticate(byte block);
+ //! Sends a AUTHENTICATE command using the specified key
+ void authenticate(byte block, byte keyType, byte key[6]);
+ //! Reads a 16-byte block
+ void readBlock(byte block);
+
+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 // SM130_h
diff --git a/arduino/lib/SL018/examples/sl018demo/sl018demo.ino b/arduino/lib/SM130/examples/sm130demo/sm130demo.ino
index c0759bf..3690d66 100644
--- a/arduino/lib/SL018/examples/sl018demo/sl018demo.ino
+++ b/arduino/lib/SM130/examples/sm130demo/sm130demo.ino
@@ -1,21 +1,15 @@
-// SL018 demo application
+// SM130 demo application
// Marc Boon <http://www.marcboon.com>
-// April 2010
+// June 2009
-// 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
+// Controls a SonMicro SM130/mini RFID reader or RFIDuino by I2C
+// Arduino analog input 4 is I2C SDA (SM130/mini pin 10/6)
+// Arduino analog input 5 is I2C SCL (SM130/mini pin 9/5)
+// Arduino digital input 4 is DREADY (SM130/mini pin 21/18)
+// Arduino digital output 3 is RESET (SM130/mini pin 18/14)
#include <Wire.h>
-#include <SL018.h>
-
-// TAG pin (low level when tag present)
-#define TAG 17 // A3
+#include <SM130.h> // v1
// Actions
#define NONE 0
@@ -23,13 +17,11 @@
#define READ 2
#define WRITE 3
-// Create SL018 instance
-SL018 rfid;
+// Create SM130 instance for RFIDuino
+SM130 RFIDuino;
// Global vars
byte action = NONE;
-boolean autoRead = false;
-boolean tagPresent = false;
boolean authenticated;
byte block;
byte numBlocks;
@@ -38,39 +30,23 @@ char msg[16];
void setup()
{
- pinMode(TAG, INPUT);
Wire.begin();
- Serial.begin(19200);
- Serial.println("SL018 demo");
+ Serial.begin(115200);
+ Serial.println("RFIDuino");
- // reset rfid module
-// rfid.reset();
+ // reset RFIDuino
+ RFIDuino.reset();
+ // read firmware version
+ Serial.print("Version ");
+ Serial.println(RFIDuino.getFirmwareVersion());
+
// 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)
{
@@ -78,33 +54,42 @@ void loop()
{
case '?':
Serial.println("Commands:");
- Serial.println("A - Auto read on/off");
Serial.println("D - Debug on/off");
+ Serial.println("A - Antenna on/off");
+ Serial.println("H - Halt tag");
Serial.println("S - Seek tag");
Serial.println("R - Read sector");
Serial.println("W - Write string");
+ Serial.println("V - Version");
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;
+ RFIDuino.debug = !RFIDuino.debug;
Serial.print("Debug ");
- Serial.println(rfid.debug ? "on" : "off");
+ Serial.println(RFIDuino.debug ? "on" : "off");
+ break;
+ case 'a':
+ case 'A':
+ // antenna on/off
+ RFIDuino.setAntennaPower(!RFIDuino.getAntennaPower());
+ Serial.print("Antenna ");
+ Serial.println(RFIDuino.getAntennaPower() ? "on" : "off");
+ break;
+ case 'h':
+ case 'H':
+ // halt
+ Serial.println("Halt");
+ RFIDuino.halt();
+ action = NONE;
break;
case 's':
case 'S':
- // seek tag
+ // enter seek mode
Serial.println("Seek");
- rfid.seekTag();
+ RFIDuino.seekTag();
action = SEEK;
break;
case 'r':
@@ -114,9 +99,9 @@ void loop()
action = READ;
// specify what to read
block = 0;
- numBlocks = 16;
+ numBlocks = 4;
// tag has to be selected first
- rfid.selectTag();
+ RFIDuino.selectTag();
break;
case 'w':
case 'W':
@@ -130,146 +115,142 @@ void loop()
action = WRITE;
block = 1;
// tag has to be selected first
- rfid.selectTag();
+ RFIDuino.selectTag();
}
break;
+ case 'v':
+ case 'V':
+ // read firmware version
+ Serial.print("Version ");
+ Serial.println(RFIDuino.getFirmwareVersion());
+ break;
case 'q':
case 'Q':
// enter sleep mode
Serial.println("Sleep");
- rfid.sleep();
+ RFIDuino.sleep();
break;
case 'x':
case 'X':
// reset
Serial.println("Reset");
- rfid.reset();
+ RFIDuino.reset();
action = NONE;
break;
}
}
- // check for response from rfid
- if(rfid.available())
+ // check for response from RFIDuino
+ if(RFIDuino.available())
{
- // check for errors
- if(rfid.getErrorCode() != SL018::OK && rfid.getErrorCode() != SL018::LOGIN_OK)
+ // check for errors, 0 means no error, L means logged in
+ if(RFIDuino.getErrorCode() != 0 && RFIDuino.getErrorCode() != 'L')
{
- if(action != SEEK) // ignore errors while in SEEK mode
- {
- Serial.println(rfid.getErrorMessage());
- rfid.haltTag();
- action = NONE;
- }
+ Serial.println(RFIDuino.getErrorMessage());
+ action = NONE;
}
- else // deal with response if no error
+ else // deal with response
{
- switch(rfid.getCommand())
+ switch(RFIDuino.getCommand())
{
- case SL018::CMD_SEEK:
- case SL018::CMD_SELECT:
+ case SM130::CMD_SEEK_TAG:
+ if(RFIDuino.getErrorCode() == 'L' || action == NONE)
+ {
+ // seek in progress, or auto-seek after reset, which we ignore
+ break;
+ }
+ case SM130::CMD_SELECT_TAG:
// store tag type
- tagType = rfid.getTagType();
+ tagType = RFIDuino.getTagType();
// show tag name and serial number
- Serial.print(rfid.getTagName());
- Serial.print(' ');
- Serial.println(rfid.getTagString());
+ Serial.print(RFIDuino.getTagName());
+ Serial.print(": ");
+ Serial.println(RFIDuino.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)
+ if(tagType == SM130::MIFARE_ULTRALIGHT)
{
authenticated = true;
if(action == READ)
{
- rfid.readPage(block);
+ RFIDuino.readBlock(block);
}
else
{
- // write to last page (because all others are write-protected on tikitags)
- rfid.writePage(15, msg);
+ // write to last 4-byte block (because all others are write-protected on tikitags)
+ RFIDuino.writeFourByteBlock(15, msg);
}
}
else
{
authenticated = false;
- rfid.authenticate(block >> 2);
+ RFIDuino.authenticate(block);
}
}
+ else if(action == SEEK)
+ {
+ // keep seeking
+ RFIDuino.seekTag();
+ }
else
{
// terminate seek
- rfid.haltTag();
action = NONE;
}
break;
- case SL018::CMD_LOGIN:
+ case SM130::CMD_AUTHENTICATE:
authenticated = true;
if(action == READ)
{
- rfid.readBlock(block);
+ RFIDuino.readBlock(block);
}
else if(action == WRITE)
{
- rfid.writeBlock(block, msg);
+ RFIDuino.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();
- }
+ case SM130::CMD_READ16:
+ // print 16-byte block in hex and ascii
+ Serial.print("Block ");
+ printHex(RFIDuino.getBlockNumber());
+ Serial.print(": ");
+ printArrayHex(RFIDuino.getBlock(), 16);
+ Serial.print(" ");
+ printArrayAscii(RFIDuino.getBlock(), 16);
+ Serial.println();
// get next block
- if(++block && --numBlocks)
+ if(++block < numBlocks)
{
- // mifare ultralight does not need authentication, and has 4-byte pages
- if(tagType == SL018::MIFARE_ULTRALIGHT)
+ // mifare ultralight does not need authentication, and has 4-byte blocks
+ if(tagType == SM130::MIFARE_ULTRALIGHT)
{
- rfid.readPage(block);
+ RFIDuino.readBlock(block * 4);
}
else if(authenticated && (block & 0x03) != 0)
{
// blocks from same sector don't need further authentication
- rfid.readBlock(block);
+ RFIDuino.readBlock(block);
}
else
{
- // authenticate next sector (4 blocks per sector)
+ // authenticate next sector
authenticated = false;
- rfid.authenticate(block >> 2);
+ RFIDuino.authenticate(block);
}
}
else // read completed
{
- rfid.haltTag();
+ RFIDuino.haltTag();
action = NONE;
}
break;
- case SL018::CMD_WRITE4:
- case SL018::CMD_WRITE16:
+ case SM130::CMD_WRITE4:
+ case SM130::CMD_WRITE16:
// write completed
Serial.println("OK");
- rfid.haltTag();
+ RFIDuino.haltTag();
action = NONE;
break;
}
diff --git a/arduino/lib/SM130/examples/sm130seek/sm130seek.ino b/arduino/lib/SM130/examples/sm130seek/sm130seek.ino
new file mode 100644
index 0000000..ae36596
--- /dev/null
+++ b/arduino/lib/SM130/examples/sm130seek/sm130seek.ino
@@ -0,0 +1,51 @@
+// SM130 - seek continuosly for tags and print type and id to serial port
+// Marc Boon <http://www.marcboon.com>
+// April 2009
+
+// Controls a SonMicro SM130/mini RFID reader or RFIDuino by I2C
+// Arduino analog input 4 is I2C SDA (SM130/mini pin 10/6)
+// Arduino analog input 5 is I2C SCL (SM130/mini pin 9/5)
+// Arduino digital input 4 is DREADY (SM130/mini pin 21/18)
+// Arduino digital output 3 is RESET (SM130/mini pin 18/14)
+
+// Following two includes are required for SM130
+#include <Wire.h>
+#include <SM130.h>
+
+// Create SM130 instance for RFIDuino
+SM130 RFIDuino;
+
+void setup()
+{
+ // Start I2C bus master (required)
+ Wire.begin();
+
+ // Using the serial port is optional
+ Serial.begin(115200);
+ Serial.println("RFIDuino");
+
+ // Reset RFIDuino, this will also configure IO pins DREADY and RESET
+ RFIDuino.reset();
+
+ // Read firmware version (optional)
+ Serial.print("Version ");
+ Serial.println(RFIDuino.getFirmwareVersion());
+
+ // Start SEEK mode
+ RFIDuino.seekTag();
+}
+
+void loop()
+{
+ // Tag detected?
+ if(RFIDuino.available())
+ {
+ // Print the tag's type and serial number
+ Serial.print(RFIDuino.getTagName());
+ Serial.print(": ");
+ Serial.println(RFIDuino.getTagString());
+
+ // Start new SEEK
+ RFIDuino.seekTag();
+ }
+}
diff --git a/arduino/lib/SM130/keywords.txt b/arduino/lib/SM130/keywords.txt
new file mode 100644
index 0000000..0e6d3a3
--- /dev/null
+++ b/arduino/lib/SM130/keywords.txt
@@ -0,0 +1,61 @@
+#### Class name ####
+SM130 KEYWORD1
+#### Constants ####
+VERSION LITERAL1
+MIFARE_ULTRALIGHT LITERAL1
+MIFARE_1K LITERAL1
+MIFARE_4K LITERAL1
+CMD_RESET LITERAL1
+CMD_VERSION LITERAL1
+CMD_SEEK_TAG LITERAL1
+CMD_SELECT_TAG LITERAL1
+CMD_AUTHENTICATE LITERAL1
+CMD_READ16 LITERAL1
+CMD_READ_VALUE LITERAL1
+CMD_WRITE16 LITERAL1
+CMD_WRITE_VALUE LITERAL1
+CMD_WRITE4 LITERAL1
+CMD_WRITE_KEY LITERAL1
+CMD_INC_VALUE LITERAL1
+CMD_DEC_VALUE LITERAL1
+CMD_RF_POWER LITERAL1
+CMD_READ_PORT LITERAL1
+CMD_WRITE_PORT LITERAL1
+CMD_HALT_TAG LITERAL1
+CMD_SET_BAUD LITERAL1
+CMD_SLEEP LITERAL1
+#### Member functions ####
+debug KEYWORD2
+address KEYWORD2
+pinRESET KEYWORD2
+pinDREADY KEYWORD2
+reset KEYWORD2
+getFirmwareVersion KEYWORD2
+available KEYWORD2
+getRawData KEYWORD2
+getCommand KEYWORD2
+getPacketLength KEYWORD2
+getCheckSum KEYWORD2
+getPayload KEYWORD2
+getTagNumber KEYWORD2
+getTagLength KEYWORD2
+getTagString KEYWORD2
+getTagType KEYWORD2
+getTagName KEYWORD2
+getErrorCode KEYWORD2
+getErrorMessage KEYWORD2
+getAntennaPower KEYWORD2
+getBlock KEYWORD2
+getBlockNumber KEYWORD2
+seekTag KEYWORD2
+selectTag KEYWORD2
+haltTag KEYWORD2
+setAntennaPower KEYWORD2
+sleep KEYWORD2
+writeBlock KEYWORD2
+writeFourByteBlock KEYWORD2
+authenticate KEYWORD2
+readBlock KEYWORD2
+printArrayAscii KEYWORD2
+printArrayHex KEYWORD2
+printHex KEYWORD2
diff --git a/arduino/src/.pc.cpp.swp b/arduino/src/.pc.cpp.swp
deleted file mode 100644
index 2c4fdeb..0000000
--- a/arduino/src/.pc.cpp.swp
+++ /dev/null
Binary files differ
diff --git a/arduino/src/config.h b/arduino/src/config.h
index 83597cf..aa676c7 100644
--- a/arduino/src/config.h
+++ b/arduino/src/config.h
@@ -13,7 +13,7 @@
/** Size of stored hash. */
#define EMEM_HASH_SIZE (32)
/** Flag that indicates (if defined) verbose mode (for diagnostic) */
-#define DEBUG 1
+//#define DEBUG 1
/**
* Flag that indicates (if defined) keyboard simulation mode (for diagnostic).
* In this mode keyboard always return pin.
diff --git a/arduino/src/doorman.ino b/arduino/src/doorman.ino
index 10fba30..e176bd1 100644
--- a/arduino/src/doorman.ino
+++ b/arduino/src/doorman.ino
@@ -25,7 +25,7 @@
/** Used to pass current command hash **/
unsigned char g_Hash[EMEM_HASH_SIZE];
/** Door control pin. */
-#define DOOR_CTRN (4)
+#define DOOR_CTRN (10)
// From pc.cpp
/** Flag set when next scan should send mid. */
@@ -35,8 +35,7 @@ extern boolean pc_send_flag;
void setup() {
Serial.begin(19200);
keypad_init();
- delay(10);
- rf_halt();
+ rf_init();
pinMode(DOOR_CTRN, OUTPUT);
#ifdef DEBUG
Serial.println("Ready");
@@ -161,6 +160,7 @@ void loop(){
pin=0;
rfid=0;
state=STATE_MIFARE;
+ rf_reset();
break;
}
//Communication with PC (optional).
diff --git a/arduino/src/keypad.cpp b/arduino/src/keypad.cpp
index 87b90c4..ea19c60 100644
--- a/arduino/src/keypad.cpp
+++ b/arduino/src/keypad.cpp
@@ -12,7 +12,7 @@
/** Max length of message from keypad. */
#define KEYPAD_RESP_SIZE (5)
/** Software serial port for communication with keypad. */
-SoftwareSerial keypad(2, 3);
+SoftwareSerial keypad(9, 8);
/** Global variable that holds last message from keypad. */
char keypad_bytes[KEYPAD_MAX_BYTES];
/** keypad state variable */
diff --git a/arduino/src/pc.cpp b/arduino/src/pc.cpp
index fb340b4..6d3dc97 100644
--- a/arduino/src/pc.cpp
+++ b/arduino/src/pc.cpp
@@ -167,6 +167,7 @@ void pc_comm(){
else
Serial.print(',');
}
+#endif
// Check MAC
pc_bytes[1+1+1+4+1+EMEM_HASH_SIZE*2] = '\0';
@@ -189,9 +190,8 @@ void pc_comm(){
Serial.print(',');
}
Serial.println("");
-#endif
-
#endif //DEBUG
+
if (mac_result != 0){
#ifdef DEBUG
Serial.println("WRONG TOKEN");
diff --git a/arduino/src/rf.cpp b/arduino/src/rf.cpp
index da8361f..c85e61a 100644
--- a/arduino/src/rf.cpp
+++ b/arduino/src/rf.cpp
@@ -1,88 +1,38 @@
#include <Arduino.h>
+#include <SM130.h>
+#include <Wire.h>
#include "config.h"
-/** Global variable that holds last message from rfid reader. */
-byte rf_bytes[RF_MAX_BYTES];
+/** Global variable that holds RFID reader object. */
+SM130 rfid;
/**
- * Sends hald command to rfid reader.
+ * Init NFC subsystem
*/
-void rf_halt() {
- //Halt tag
- /*rfid.print(255, BYTE);
- rfid.print(0, BYTE);
- rfid.print(1, BYTE);
- rfid.print(147, BYTE);
- rfid.print(148, BYTE);*/
+void rf_init(void) {
+ Wire.begin();
+ rfid.address = 0x30;
+ rfid.reset();
+#ifdef DEBUG
+ Serial.print("SM130 firmware version: ");
+ Serial.println(rfid.getFirmwareVersion());
+#endif //DEBUG
}
/**
- * Sends seek command to rfid reader.
+ * Resets the NFC controller
*/
-void rf_seek() {
- //search for RFID tag
- /*rfid.print(255, BYTE);
- rfid.print(0, BYTE);
- rfid.print(1, BYTE);
- rfid.print(130, BYTE);
- rfid.print(131, BYTE); */
+
+void rf_reset() {
+ rfid.reset();
}
/**
- * Function receives bytes from rfid reader and parses them into message
- * @return Returns true if message was received, false otherwise
+ * Sends seek command to rfid reader.
*/
-boolean rf_parse() {
- /*static int rf_idx = 0;
- while(rfid.available()){
- //Read the incoming byte.
- byte in = rfid.read();
- if (in==255 && rf_idx==0) {
- //Start byte
- rf_bytes[rf_idx]=in;
- rf_idx+=1;
- continue;
- }
- if (rf_idx<RF_MAX_BYTES){
- if (rf_idx>2){
- //Message length was received
- if (rf_idx>(rf_bytes[2]+3)){
- //This should not ever happen.
- rf_idx=0;
- continue;
- } else if (rf_idx==(rf_bytes[2]+3)) {
- //End of message
- rf_bytes[rf_idx]=in;
- int sum=0;
- //Calculate checksum from message
- for (int ii=1;ii<(rf_idx);ii++){
- sum+=rf_bytes[ii];
- }
- if ((sum & 0x0ff)!=rf_bytes[rf_idx]) {
-#ifdef DEBUG
- Serial.println("Wrong checksum");
-#endif //DEBUG
- rf_idx=0;
- return false;
- }
- //Message received!
- rf_idx=0;
- return true;
- }
- }
- rf_bytes[rf_idx]=in;
- rf_idx+=1;
- continue;
- } else{
-#ifdef DEBUG
- Serial.println("Data too long");
-#endif //DEBUG
- rf_idx=0;
- continue;
- }
- }*/
- return false;
+void rf_seek() {
+ rfid.seekTag();
}
/**
@@ -101,14 +51,23 @@ boolean rf_comm(unsigned long * p_rfid) {
rf_seek();
last_millis = new_millis;
}
- if (rf_parse()){
- //Message received
- if(rf_bytes[2] > 2 && rf_bytes[3]==0x82){
+ if (rfid.available()){
+ /*if(rf_bytes[2] > 2 && rf_bytes[3]==0x82){
//Message has id
- unsigned long data=(long(rf_bytes[8])<<24)|(long(rf_bytes[7])<<16)|(long(rf_bytes[6])<<8)|(long(rf_bytes[5]));
+ }*/
+ //Message received
+ uint8_t *rf_bytes = rfid.getTagNumber();
+#ifdef DEBUG
+ Serial.print("RFID Tag: ");
+ for (int i = 0; i < 8; i++) {
+ Serial.print(rf_bytes[i], HEX);
+ Serial.print(",");
+ }
+ Serial.println();
+#endif //DEBUG
+ unsigned long data=(long(rf_bytes[3])<<24)|(long(rf_bytes[2])<<16)|(long(rf_bytes[1])<<8)|(long(rf_bytes[0]));
(*p_rfid) = data;
return true;
- }
}
return false;
}
diff --git a/arduino/src/rf.h b/arduino/src/rf.h
index dfdbea4..ce322dd 100644
--- a/arduino/src/rf.h
+++ b/arduino/src/rf.h
@@ -1,6 +1,8 @@
#ifndef __DOORMAN_RF_H__
#define __DOORMAN_RF_H__
+void rf_reset();
+void rf_init();
void rf_halt();
void rf_seek();
boolean rf_parse();