diff options
author | Sergiusz 'q3k' Bazański <q3k@q3k.org> | 2015-03-07 02:58:07 +0100 |
---|---|---|
committer | Sergiusz 'q3k' Bazański <q3k@q3k.org> | 2015-03-07 02:58:07 +0100 |
commit | eb0a11c7068955c74786ff5475a827c01d3cd64d (patch) | |
tree | c68e3667e5a199e0bff0e96f57ff39abc1fbf2c6 | |
parent | d15ede7072e694082657560d63dab4d9a905333a (diff) | |
download | doorman-eb0a11c7068955c74786ff5475a827c01d3cd64d.tar.gz doorman-eb0a11c7068955c74786ff5475a827c01d3cd64d.tar.bz2 doorman-eb0a11c7068955c74786ff5475a827c01d3cd64d.tar.xz doorman-eb0a11c7068955c74786ff5475a827c01d3cd64d.zip |
Final new version.
22 files changed, 632 insertions, 739 deletions
@@ -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 Binary files differdeleted file mode 100644 index 7498cf8..0000000 --- a/admin/lib/.command.py.swp +++ /dev/null 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 Binary files differdeleted file mode 100644 index 2c4fdeb..0000000 --- a/arduino/src/.pc.cpp.swp +++ /dev/null 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(); |