ino compatibility

serial
q3k 2015-03-04 23:05:19 +01:00
parent b158beac3c
commit 5b0e1cbb36
27 changed files with 1176 additions and 0 deletions

View File

7
arduino/lib/SL018/README Normal file
View File

@ -0,0 +1,7 @@
Arduino library for StrongLink SL018/SL030 RFID readers
http://www.stronglink.cn/english/sl018.htm
http://www.stronglink.cn/english/sl030.htm
June 2011
marc@marcboon.com

507
arduino/lib/SL018/SL018.cpp Normal file
View File

@ -0,0 +1,507 @@
/**
* @title StrongLink SL018/SL030 RFID reader library
*
* @file SL018.cpp
* @author marc@marcboon.com
* @modified fil@rezox.com (Filipe Laborde-Basto) [to make binary safe]
* @date February 2012
*
* @see http://www.stronglink.cn/english/sl018.htm
* @see http://www.stronglink.cn/english/sl030.htm
*/
#include <Wire.h>
#include <string.h>
#include "SL018.h"
// local prototypes
void arrayToHex(char *s, byte array[], byte len);
char toHex(byte b);
/** Constructor.
*
* An instance of SL018 should be created as a global variable, outside of
* any function.
* The constructor sets public data fields to default values.
* These may be changed in setup() before SL018::reset() is called.
*/
SL018::SL018()
{
address = 0x50;
pinRESET = -1;
pinDREADY = -1;
cmd = CMD_IDLE;
debug = false;
t = millis() + 10;
}
/* Public member functions ****************************************************/
/** Reset the SL018 module
*
* This function should be called in setup(). It initializes the IO pins and
* issues a hardware or software reset, depending on the definition of pinRESET.
* After reset, antenna power is switched off to terminate the automatic SEEK mode.
*
* Wire.begin() should also be called in setup(), and Wire.h should be included.
*
* If pinRESET has the value -1 (default), software reset over I2C will be used.
* If pinDREADY has the value -1 (default), the SL018 will be polled over I2C for
* SEEK commands, otherwise the DREADY pin will be polled.
* For other commands, response polling is always over I2C.
*/
void SL018::reset()
{
// Init DREADY pin
if (pinDREADY != 0xff)
{
pinMode(pinDREADY, INPUT);
}
// Init RESET pin
if (pinRESET != 0xff) // hardware reset
{
pinMode(pinRESET, OUTPUT);
digitalWrite(pinRESET, HIGH);
delay(10);
digitalWrite(pinRESET, LOW);
}
else // software reset
{
sendCommand(CMD_RESET);
}
// Allow enough time for reset
delay(200);
}
/** Checks for availability of a valid response packet.
*
* This function should always be called and return true prior to using results
* of a command.
*
* @returns true if a valid response packet is available
*/
boolean SL018::available()
{
// Set the maximum length of the expected response packet
byte len;
switch(cmd)
{
case CMD_IDLE:
case CMD_RESET:
len = 0;
break;
case CMD_LOGIN:
case CMD_SET_LED:
case CMD_SLEEP:
len = 3;
break;
case CMD_READ4:
case CMD_WRITE4:
case CMD_READ_VALUE:
case CMD_WRITE_VALUE:
case CMD_DEC_VALUE:
case CMD_INC_VALUE:
case CMD_COPY_VALUE:
len = 7;
break;
case CMD_WRITE_KEY:
len = 9;
break;
case CMD_SEEK:
case CMD_SELECT:
len = 11;
break;
default:
len = SIZE_PACKET;
}
// If valid data received, process the response packet
if (len && receiveData(len) > 0)
{
// Init response variables
tagType = tagLength = *tagString = 0;
errorCode = data[2];
// Process command response
switch (getCommand())
{
case CMD_SEEK:
case CMD_SELECT:
// If no error, get tag number
if(errorCode == 0 && getPacketLength() >= 7)
{
tagLength = getPacketLength() - 3;
tagType = data[getPacketLength()];
memcpy(tagNumber, data + 3, tagLength);
arrayToHex(tagString, tagNumber, tagLength);
}
else if(cmd == CMD_SEEK)
{
// Continue seek
seekTag();
return false;
}
}
// Data is available
return true;
}
// No data available
return false;
}
/** Get error message for last command.
*
* @return Human-readable error message as a null-terminated string
*/
const char* SL018::getErrorMessage()
{
switch(errorCode)
{
case 0:
return "OK";
case 1:
return "No tag present";
case 2:
return "Login OK";
case 3:
case 0x10:
return "Login failed";
case 4:
return "Read failed";
case 5:
return "Write failed";
case 6:
return "Unable to read after write";
case 0x0A:
return "Collision detected";
case 0x0C:
return "Load key failed";
case 0x0D:
return "Not authenticated";
case 0x0E:
return "Not a value block";
default:
return "Unknown error";
}
}
/** Authenticate with transport key (0xFFFFFFFFFFFF).
*
* @param sector Sector number
*/
void SL018::authenticate(byte sector)
{
data[0] = 9;
data[1] = CMD_LOGIN;
data[2] = sector;
data[3] = 0xAA;
memset(data + 4, 0xFF, 6);
transmitData();
}
/** Authenticate with specified key A or key B.
*
* @param sector Sector number
* @param keyType Which key to use: 0xAA for key A or 0xBB for key B
* @param key Key value (6 bytes)
*/
void SL018::authenticate(byte sector, byte keyType, byte key[6])
{
data[0] = 9;
data[1] = CMD_LOGIN;
data[2] = sector;
data[3] = keyType;
memcpy(data + 4, key, 6);
transmitData();
}
/** Read 16-byte block.
*
* @param block Block number
*/
void SL018::readBlock(byte block)
{
data[0] = 2;
data[1] = CMD_READ16;
data[2] = block;
transmitData();
}
/** Read 4-byte page.
*
* @param page Page number
*/
void SL018::readPage(byte page)
{
data[0] = 2;
data[1] = CMD_READ4;
data[2] = page;
transmitData();
}
/** Write 16-byte block.
*
* The block will be padded with zeroes if the message is shorter
* than 15 characters.
*
* @param block Block number
* @param message string of 16 characters (binary safe)
*/
void SL018::writeBlock(byte block, const char* message)
{
data[0] = 18;
data[1] = CMD_WRITE16;
data[2] = block;
//strncpy((char*)data + 3, message, 15); // not binary safe
memcpy( (char*)data + 3, message, 16 );
data[18] = 0;
transmitData();
}
/** Write 4-byte page.
*
* This command is used for Mifare Ultralight tags which have 4 byte pages.
*
* @param page Page number
* @param message String of 4 characters
*/
void SL018::writePage(byte page, const char* message)
{
data[0] = 6;
data[1] = CMD_WRITE4;
data[2] = page;
//strncpy((char*)data + 3, message, 3); // not binary safe
memcpy( (char*)data + 3, message, 4 );
data[6] = 0;
transmitData();
}
/** Write master key (key A).
*
* @param sector Sector number
* @param key Key value (6 bytes)
*/
void SL018::writeKey(byte sector, byte key[6])
{
data[0] = 8;
data[1] = CMD_WRITE_KEY;
data[2] = sector;
memcpy(data + 3, key, 6);
transmitData();
}
/** Control red LED on SL018 (not implemented on SL030).
*
* @param on true for on, false for off
*/
void SL018::led(boolean on)
{
data[0] = 2;
data[1] = CMD_SET_LED;
data[2] = on;
transmitData();
}
/** Send 1-byte command.
*
* @param cmd Command
*/
void SL018::sendCommand(byte cmd)
{
data[0] = 1;
data[1] = cmd;
transmitData();
}
/* Private member functions ****************************************************/
/** Transmit a packet to the SL018.
*/
/*
data[0] = 18;
data[1] = CMD_WRITE16;
data[2] = block;
strncpy((char*)data + 3, message, 15);
data[18] = 0;
*/
void SL018::transmitData()
{
// wait until at least 20ms passed since last I2C transmission
while(t > millis());
t = millis() + 20;
// remember which command was sent
cmd = data[1];
// transmit packet with checksum
Wire.beginTransmission(address);
for (int i = 0; i <= data[0]; i++)
{
#if defined(ARDUINO) && ARDUINO >= 100
Wire.write(data[i]);
#else
Wire.send(data[i]);
#endif
}
Wire.endTransmission();
// show transmitted packet for debugging
if (debug)
{
Serial.print("> ");
printArrayHex( data, data[0] + 1);
Serial.println();
}
}
/** Receives a packet from the SL018.
*
* @param length the number of bytes to receive
* @return the number of bytes in the payload, or -1 if bad checksum
*/
byte SL018::receiveData(byte length)
{
// wait until at least 20ms passed since last I2C transmission
while(t > millis());
t = millis() + 20;
// read response
Wire.requestFrom(address, length);
if(Wire.available())
{
// get length of packet
#if defined(ARDUINO) && ARDUINO >= 100
data[0] = Wire.read();
#else
data[0] = Wire.receive();
#endif
// get data
for (byte i = 1; i <= data[0]; i++)
{
#if defined(ARDUINO) && ARDUINO >= 100
data[i] = Wire.read();
#else
data[i] = Wire.receive();
#endif
}
// show received packet for debugging
if (debug && data[0] > 0 )
{
Serial.print("< ");
printArrayHex(data, data[0] + 1);
Serial.println();
}
// return with length of response
return data[0];
}
return 0;
}
/** Maps tag types to names.
*
* @param type numeric tag type
* @return Human-readable tag name as null-terminated string
*/
const char* SL018::tagName(byte type)
{
switch(type)
{
case 1: return "Mifare 1K";
case 2: return "Mifare Pro";
case 3: return "Mifare UltraLight";
case 4: return "Mifare 4K";
case 5: return "Mifare ProX";
case 6: return "Mifare DesFire";
default: return "";
}
}
// Global helper functions
/** Convert byte array to null-terminated hexadecimal string.
*
* @param s pointer to destination string
* @param array byte array to convert
* @param len length of byte array to convert
*/
void arrayToHex(char *s, byte array[], byte len)
{
for (byte i = 0; i < len; i++)
{
*s++ = toHex(array[i] >> 4);
*s++ = toHex(array[i]);
}
*s = 0;
}
/** Convert low-nibble of byte to ASCII hex.
*
* @param b byte to convert
* $return uppercase hexadecimal character [0-9A-F]
*/
char toHex(byte b)
{
b = b & 0x0f;
return b < 10 ? b + '0' : b + 'A' - 10;
}
/** Print byte array as ASCII string.
*
* Non-printable characters (<0x20 or >0x7E) are printed as dot.
*
* @param array byte array
* @param len length of byte array
*/
void printArrayAscii(byte array[], byte len)
{
for (byte i = 0; i < len;)
{
char c = array[i++];
if (c < 0x20 || c > 0x7e)
{
Serial.print('.');
}
else
{
Serial.print(char(c));
}
}
}
/** Print byte array as hexadecimal character pairs.
*
* @param array byte array
* @param len length of byte array
*/
void printArrayHex(byte array[], byte len)
{
for (byte i = 0; i < len;)
{
printHex(array[i++]);
if (i < len)
{
Serial.print(' ');
}
}
}
/** Print byte as two hexadecimal characters.
*
* @param val byte value
*/
void printHex(byte val)
{
if (val < 0x10)
{
Serial.print('0');
}
Serial.print(val, HEX);
}

177
arduino/lib/SL018/SL018.h Normal file
View File

@ -0,0 +1,177 @@
/**
* @file SL018.h
* @brief Header file for SL018 library
* @author Marc Boon <http://www.marcboon.com>
* @date February 2012
*/
#ifndef SL018_h
#define SL018_h
#if defined(ARDUINO) && ARDUINO >= 100
#include "Arduino.h"
#else
#include "WProgram.h"
#endif
#define SIZE_PACKET 19
// Global functions
void printArrayAscii(byte array[], byte len);
void printArrayHex(byte array[], byte len);
void printHex(byte val);
class SL018
{
public:
static const int VERSION = 1; //!< version of this library
static const byte MIFARE_1K = 1;
static const byte MIFARE_PRO = 2;
static const byte MIFARE_ULTRALIGHT = 3;
static const byte MIFARE_4K = 4;
static const byte MIFARE_PROX = 5;
static const byte MIFARE_DESFIRE = 6;
static const byte CMD_IDLE = 0x00;
static const byte CMD_SELECT = 0x01;
static const byte CMD_LOGIN = 0x02;
static const byte CMD_READ16 = 0x03;
static const byte CMD_WRITE16 = 0x04;
static const byte CMD_READ_VALUE = 0x05;
static const byte CMD_WRITE_VALUE = 0x06;
static const byte CMD_WRITE_KEY = 0x07;
static const byte CMD_INC_VALUE = 0x08;
static const byte CMD_DEC_VALUE = 0x09;
static const byte CMD_COPY_VALUE = 0x0A;
static const byte CMD_READ4 = 0x10;
static const byte CMD_WRITE4 = 0x11;
static const byte CMD_SEEK = 0x20;
static const byte CMD_SET_LED = 0x40;
static const byte CMD_SLEEP = 0x50;
static const byte CMD_RESET = 0xFF;
static const byte OK = 0x00;
static const byte NO_TAG = 0x01;
static const byte LOGIN_OK = 0x02;
static const byte LOGIN_FAIL = 0x03;
static const byte READ_FAIL = 0x04;
static const byte WRITE_FAIL = 0x05;
static const byte CANT_VERIFY = 0x06;
static const byte COLLISION = 0x0A;
static const byte KEY_FAIL = 0x0C;
static const byte NO_LOGIN = 0x0D;
static const byte NO_VALUE = 0x0E;
boolean debug; //!< debug mode, prints all I2C communication to Serial port
byte address; //!< I2C address (default 0x50)
byte pinRESET; //!< RESET pin (default -1)
byte pinDREADY; //!< DREADY pin (default -1)
private:
byte data[SIZE_PACKET]; //!< packet data
byte tagNumber[7]; //!< tag number as byte array
byte tagLength; //!< length of tag number in bytes (4 or 7)
char tagString[15]; //!< tag number as hex string
byte tagType; //!< type of tag
char errorCode; //!< error code from some commands
byte cmd; //!< last sent command
unsigned long t; //!< timer for sending I2C commands
public:
//! Constructor
SL018();
//! Hardware or software reset of the SL018 module
void reset();
//! Returns true if a response packet is available
boolean available();
//! Returns a pointer to the response packet
byte* getRawData() { return data; };
//! Returns the last executed command
byte getCommand() { return cmd; };
//! Returns the packet length, excluding checksum
byte getPacketLength() { return data[0]; };
//! Returns a pointer to the packet payload
byte* getPayload() { return data+2; };
//! Returns the block number for read/write commands
byte getBlockNumber() { return data[2]; };
//! Returns a pointer to the read block (with a length of 16 bytes)
byte* getBlock() { return data+3; };
//! Returns the tag's serial number as a byte array
byte* getTagNumber() { return tagNumber; };
//! Returns the length of the tag's serial number obtained by getTagNumer()
byte getTagLength() { return tagLength; };
//! Returns the tag's serial number as a hexadecimal null-terminated string
const char* getTagString() { return tagString; };
//! Returns the tag type (SL018::MIFARE_XX)
byte getTagType() { return tagType; };
//! Returns the tag type as a null-terminated string
const char* getTagName() { return tagName(tagType); };
//! Returns the error code of the last executed command
char getErrorCode() { return errorCode; };
//! Returns a human-readable error message corresponding to the error code
const char* getErrorMessage();
//! Starts SEEK mode
void seekTag() { selectTag(); cmd = CMD_SEEK; };
//! Sends a SELECT_TAG command
void selectTag() { sendCommand(CMD_SELECT); };
//! Sends a HALT_TAG command
void haltTag() { cmd = CMD_IDLE; };
//! Sends a SLEEP command (can only wake-up with hardware reset!)
void sleep() { sendCommand(CMD_SLEEP); };
//! Writes a null-terminated string of maximum 15 characters to a block
void writeBlock(byte block, const char* message);
//! Writes a null-terminated string of maximum 3 characters to a Mifare Ultralight page
void writePage(byte page, const char* message);
//! Authenticate a sector using the transport key
void authenticate(byte sector);
//! Authenticate a sector using the specified key
void authenticate(byte sector, byte keyType, byte key[6]);
//! Reads a 16-byte block
void readBlock(byte block);
//! Reads a 4-byte page
void readPage(byte page);
//! Write master key (key A)
void writeKey(byte sector, byte key[6]);
//! LED control (SL018 only)
void led(boolean on);
private:
//! Send single-byte command
void sendCommand(byte cmd);
//! Transmit command packet over I2C
void transmitData();
//! Receive response packet over I2C
byte receiveData(byte length);
//! Returns human-readable tag name corresponding to tag type
const char* tagName(byte type);
};
#endif

View File

@ -0,0 +1,38 @@
/**
* @title: StrongLink SL018/SL030 RFID reader demo
* @author: marc@marcboon.com
* @see: http://www.stronglink.cn/english/sl018.htm
* @see: http://www.stronglink.cn/english/sl030.htm
*
* Arduino to SL018/SL030 wiring:
* A4/SDA 2 3
* A5/SCL 3 4
* 5V 4 -
* GND 5 6
* 3V3 - 1
*/
#include <Wire.h>
#include <SL018.h>
SL018 rfid;
void setup()
{
Wire.begin();
Serial.begin(19200);
// prompt for tag
Serial.println("Show me your tag");
}
void loop()
{
// start seek mode
rfid.seekTag();
// wait until tag detected
while(!rfid.available());
// print tag id
Serial.println(rfid.getTagString());
}

View File

@ -0,0 +1,316 @@
// SL018 demo application
// Marc Boon <http://www.marcboon.com>
// April 2010
// Controls a StrongLink SL018 or SL030 RFID reader by I2C
// Arduino to SL018/SL030 wiring:
// A3/TAG 1 5
// A4/SDA 2 3
// A5/SCL 3 4
// 5V 4 -
// GND 5 6
// 3V3 - 1
#include <Wire.h>
#include <SL018.h>
// TAG pin (low level when tag present)
#define TAG 17 // A3
// Actions
#define NONE 0
#define SEEK 1
#define READ 2
#define WRITE 3
// Create SL018 instance
SL018 rfid;
// Global vars
byte action = NONE;
boolean autoRead = false;
boolean tagPresent = false;
boolean authenticated;
byte block;
byte numBlocks;
byte tagType;
char msg[16];
void setup()
{
pinMode(TAG, INPUT);
Wire.begin();
Serial.begin(19200);
Serial.println("SL018 demo");
// reset rfid module
// rfid.reset();
// help
Serial.println("Type ? for help");
}
void loop()
{
// check for tag presence when auto read is enabled
if(autoRead && !tagPresent && !digitalRead(TAG) && action == NONE)
{
tagPresent = true;
// read tag
action = READ;
// specify what to read
block = 0;
numBlocks = 16;
// tag has to be selected first
rfid.selectTag();
}
// check if tag has gone
if(tagPresent && digitalRead(TAG))
{
tagPresent = false;
}
// check for command from serial port
if(Serial.available() > 0)
{
switch(Serial.read())
{
case '?':
Serial.println("Commands:");
Serial.println("A - Auto read on/off");
Serial.println("D - Debug on/off");
Serial.println("S - Seek tag");
Serial.println("R - Read sector");
Serial.println("W - Write string");
Serial.println("Q - Sleep");
Serial.println("X - Reset");
break;
case 'a':
case 'A':
// auto read on/off
autoRead = !autoRead;
Serial.print("Auto read ");
Serial.println(autoRead ? "on" : "off");
break;
case 'd':
case 'D':
// debug on/off
rfid.debug = !rfid.debug;
Serial.print("Debug ");
Serial.println(rfid.debug ? "on" : "off");
break;
case 's':
case 'S':
// seek tag
Serial.println("Seek");
rfid.seekTag();
action = SEEK;
break;
case 'r':
case 'R':
// read tag
Serial.println("Read");
action = READ;
// specify what to read
block = 0;
numBlocks = 16;
// tag has to be selected first
rfid.selectTag();
break;
case 'w':
case 'W':
// collect up to 15 characters from input, and terminate with zero
if(readQuotedString(msg, sizeof(msg)) > 0)
{
// write string to tag
Serial.print("Write '");
Serial.print(msg);
Serial.println("'");
action = WRITE;
block = 1;
// tag has to be selected first
rfid.selectTag();
}
break;
case 'q':
case 'Q':
// enter sleep mode
Serial.println("Sleep");
rfid.sleep();
break;
case 'x':
case 'X':
// reset
Serial.println("Reset");
rfid.reset();
action = NONE;
break;
}
}
// check for response from rfid
if(rfid.available())
{
// check for errors
if(rfid.getErrorCode() != SL018::OK && rfid.getErrorCode() != SL018::LOGIN_OK)
{
if(action != SEEK) // ignore errors while in SEEK mode
{
Serial.println(rfid.getErrorMessage());
rfid.haltTag();
action = NONE;
}
}
else // deal with response if no error
{
switch(rfid.getCommand())
{
case SL018::CMD_SEEK:
case SL018::CMD_SELECT:
// store tag type
tagType = rfid.getTagType();
// show tag name and serial number
Serial.print(rfid.getTagName());
Serial.print(' ');
Serial.println(rfid.getTagString());
// in case of read or write action, authenticate first
if(action == READ || action == WRITE)
{
// mifare ultralight does not need authentication, and has 4-byte blocks
if(tagType == SL018::MIFARE_ULTRALIGHT)
{
authenticated = true;
if(action == READ)
{
rfid.readPage(block);
}
else
{
// write to last page (because all others are write-protected on tikitags)
rfid.writePage(15, msg);
}
}
else
{
authenticated = false;
rfid.authenticate(block >> 2);
}
}
else
{
// terminate seek
rfid.haltTag();
action = NONE;
}
break;
case SL018::CMD_LOGIN:
authenticated = true;
if(action == READ)
{
rfid.readBlock(block);
}
else if(action == WRITE)
{
rfid.writeBlock(block, msg);
}
break;
case SL018::CMD_READ4:
case SL018::CMD_READ16:
if(rfid.getCommand() == SL018::CMD_READ4)
{
// print 4-byte page in hex and ascii
Serial.print("Page ");
printHex(block);
Serial.print(": ");
printArrayHex(rfid.getBlock(), 4);
Serial.print(" ");
printArrayAscii(rfid.getBlock(), 4);
Serial.println();
}
else
{
// print 16-byte block in hex and ascii
Serial.print("Block ");
printHex(block);
Serial.print(": ");
printArrayHex(rfid.getBlock(), 16);
Serial.print(" ");
printArrayAscii(rfid.getBlock(), 16);
Serial.println();
}
// get next block
if(++block && --numBlocks)
{
// mifare ultralight does not need authentication, and has 4-byte pages
if(tagType == SL018::MIFARE_ULTRALIGHT)
{
rfid.readPage(block);
}
else if(authenticated && (block & 0x03) != 0)
{
// blocks from same sector don't need further authentication
rfid.readBlock(block);
}
else
{
// authenticate next sector (4 blocks per sector)
authenticated = false;
rfid.authenticate(block >> 2);
}
}
else // read completed
{
rfid.haltTag();
action = NONE;
}
break;
case SL018::CMD_WRITE4:
case SL018::CMD_WRITE16:
// write completed
Serial.println("OK");
rfid.haltTag();
action = NONE;
break;
}
}
}
}
int readQuotedString(char *s, int len)
{
int i = 0;
char quote = 0;
while(i < len)
{
delay(5);
if(Serial.available() == 0)
{
break;
}
*s = Serial.read();
if(quote == 0)
{
if(*s == '"' || *s == '\'')
{
quote = *s;
}
else if(*s != ' ')
{
++s;
++i;
}
}
else if(*s == quote)
{
break;
}
else
{
++s;
++i;
}
}
*s = 0;
return i;
}

View File

@ -0,0 +1,83 @@
/**
* @title: StrongLink SL018/SL030 RFID 2-reader demo
* @author: lukasz.szostek@gmail.com based on code of:
* @author: marc@marcboon.com
* @see: http://www.stronglink.cn/english/sl018.htm
* @see: http://www.stronglink.cn/english/sl030.htm
*
* Arduino to SL018/SL030 wiring:
* A4/SDA 2 3
* A5/SCL 3 4
* 5V 4 -
* GND 5 6
* 3V3 - 1
* 5 1 5 // first reader
* 4 1 5 // second reader
*/
#include <Wire.h>
#include <SL018.h>
//pins to listen for the RFID board signalling that it has detected a tag
int reader1OutPin = 5;
int reader2OutPin = 4;
const char* tagString;
SL018 rfid1;
SL018 rfid2;
void setup()
{
//make sure these two addresses match your reader configuration
rfid1.address = 0x50;
rfid2.address = 0x52;
pinMode(reader1OutPin, INPUT);
pinMode(reader2OutPin, INPUT);
Wire.begin();
Serial.begin(57600);
// prompt for tag
Serial.println("Show me your tag");
}
void loop()
{
//if the board has signalled that it found a tag
if(!digitalRead(reader1OutPin))
{
//query tag data
rfid1.seekTag();
/* for some reason the loop defined as:
while(!digitalRead(reader1OutPin) || !rfid1.available());
does not work so we need a workaround:*/
//while we are waiting for data
while(!rfid1.available()) {
//break if the tag has been removed
if (digitalRead(reader1OutPin)) {
break;
};
};
tagString = rfid1.getTagString();
Serial.print("Reader 1 found: ");
Serial.println(tagString);
//wait a while before querying the tag again
delay(1500);
};
//"in parallel" we wait for the other reader
if(!digitalRead(reader2OutPin))
{
rfid2.seekTag();
while(!rfid2.available()) {
if (digitalRead(reader2OutPin)) {
break;
};
};
tagString = rfid2.getTagString();
Serial.print("Reader 2 found: ");
Serial.println(tagString);
delay(1500);
};
}

View File

@ -0,0 +1,48 @@
#######################################
# Syntax Coloring Map For SL018
#######################################
#######################################
# Datatypes (KEYWORD1)
#######################################
SL018 KEYWORD1
#######################################
# Methods and Functions (KEYWORD2)
#######################################
seekTag KEYWORD2
selectTag KEYWORD2
authenticate KEYWORD2
readBlock KEYWORD2
readPage KEYWORD2
writeBlock KEYWORD2
writePage KEYWORD2
reset KEYWORD2
led KEYWORD2
#######################################
# Constants (LITERAL1)
#######################################
MIFARE_1K LITERAL1
MIFARE_PRO LITERAL1
MIFARE_ULTRALIGHT LITERAL1
MIFARE_4K LITERAL1
MIFARE_PROX LITERAL1
MIFARE_DESFIRE LITERAL1
OK LITERAL1
NO_TAG LITERAL1
LOGIN_OK LITERAL1
LOGIN_FAIL LITERAL1
READ_FAIL LITERAL1
WRITE_FAIL LITERAL1
CANT_VERIFY LITERAL1
COLLISION LITERAL1
KEY_FAIL LITERAL1
NO_LOGIN LITERAL1
NO_VALUE LITERAL1