From 952e6ae6b175403793a3e3b4fe74c3b646b5beb2 Mon Sep 17 00:00:00 2001 From: Jonathan Frech Date: Tue, 7 Apr 2020 16:40:16 +0200 Subject: [PATCH 1/2] ISO15693 Support added Basic ISO15693 Tag reading and dump to Serial. Also Example File for Arduino added --- .../arduino_example/arduino_example_15693.ino | 130 ++++++++++++++ mfrc630.c | 165 ++++++++++++++++++ mfrc630.h | 23 +++ mfrc630_def.h | 62 ++++++- 4 files changed, 376 insertions(+), 4 deletions(-) create mode 100644 examples/arduino_example/arduino_example_15693.ino diff --git a/examples/arduino_example/arduino_example_15693.ino b/examples/arduino_example/arduino_example_15693.ino new file mode 100644 index 0000000..ba39c15 --- /dev/null +++ b/examples/arduino_example/arduino_example_15693.ino @@ -0,0 +1,130 @@ +/* + The MIT License (MIT) + + Copyright (c) 2016 Ivor Wanders + + Permission is hereby granted, free of charge, to any person obtaining a copy + of this software and associated documentation files (the "Software"), to deal + in the Software without restriction, including without limitation the rights + to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + copies of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in all + copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + SOFTWARE. +*/ + +#include +#include +#include + +/* + + + This example shows how to use the library on Arduino platform, it was tested with Arduino Nano + + + In the setup() function, there are some custom register settings which are you probably have to uncomment or change + such that they are in the correct configuration for your hardware. + The hardware I used had three switchable antenna's, so modification of there parameters is likely to get it to work. + + If all goes well, a ISO15693 Tag/Card will print something like: + + Tag was found! UID:00 02 F4 CF 31 1E 66 24 16 E0 ..waiting 1s for next read + + + Onto the serial port. + +*/ + + +// Pin to select the hardware, the NSS pin. +#define CHIP_SELECT 10 + +// Pins MOSI, MISO and SCK are connected to the default pins, and are manipulated through the SPI object. +// By default that means MOSI=11, MISO=12, SCK=13. + + +// Implement the HAL functions on an Arduino compatible system. +void mfrc630_SPI_transfer(const uint8_t* tx, uint8_t* rx, uint16_t len) { + for (uint16_t i=0; i < len; i++){ + rx[i] = SPI.transfer(tx[i]); + } +} + +// Select the chip and start an SPI transaction. +void mfrc630_SPI_select() { + SPI.beginTransaction(SPISettings(10000000, MSBFIRST, SPI_MODE0)); // gain control of SPI bus + digitalWrite(CHIP_SELECT, LOW); +} + +// Unselect the chip and end the transaction. +void mfrc630_SPI_unselect() { + digitalWrite(CHIP_SELECT, HIGH); + SPI.endTransaction(); // release the SPI bus +} + +// Hex print for blocks without printf. +void print_block(uint8_t * block,uint8_t length){ + for (uint8_t i=0; i Apply RegisterSet + mfrc630_write_reg(MFRC630_REG_TXCRCPRESET,0x7B); + mfrc630_write_reg(MFRC630_REG_RXCRCCON,0x7B); + mfrc630_write_reg(MFRC630_REG_TXDATANUM,0x08); + mfrc630_write_reg(MFRC630_REG_TXMODWIDTH,0x00); + mfrc630_write_reg(MFRC630_REG_TXSYM10BURSTLEN,0x00); + mfrc630_write_reg(MFRC630_REG_TXWAITCTRL,0x00); + mfrc630_write_reg(MFRC630_REG_FRAMECON,0x0F); + mfrc630_write_reg(MFRC630_REG_RXCTRL,0x02); + mfrc630_write_reg(MFRC630_REG_RXTHRESHOLD,0x4E); + mfrc630_write_reg(MFRC630_REG_RXANA,0x04); + mfrc630_write_reg(MFRC630_REG_RXWAIT,0x8C); // Set the RxWait register + mfrc630_write_reg(MFRC630_REG_TXWAITCTRL,0xC0); + mfrc630_write_reg(MFRC630_REG_TXWAITLO,0x00); + + // Write Timer-0, Timer-1 reload values(high,low) + mfrc630_write_reg(MFRC630_REG_T0RELOADHI,0x18); + mfrc630_write_reg(MFRC630_REG_T0RELOADLO,0x86); + mfrc630_write_reg(MFRC630_REG_T1RELOADHI,0x00); + mfrc630_write_reg(MFRC630_REG_T1RELOADLO,0x00); + mfrc630_write_reg(MFRC630_REG_TXAMP,0x0A); + mfrc630_write_reg(MFRC630_REG_DRVMOD,0x81); + mfrc630_write_reg(MFRC630_REG_STATUS,0x00); // Disable MIFARE Crypto1 + //Set Driver +} + +uint8_t mfrc630_ISO15693_readTag(uint8_t* uid){ + + //Set timeout for Timer0/Timer1, set reload values + mfrc630_write_reg(MFRC630_REG_T0RELOADHI,0x24); + mfrc630_write_reg(MFRC630_REG_T0RELOADLO,0xEB); + mfrc630_write_reg(MFRC630_REG_T1RELOADHI,0x00); + mfrc630_write_reg(MFRC630_REG_T1RELOADLO,0x00); + + mfrc630_cmd_idle(); //cancel any commands + mfrc630_flush_fifo(); //clear the fifo + mfrc630_clear_irq0(); //clear irq0 + mfrc630_clear_irq1(); //clear irq1 + + //Prepare instruction to send to fifo + uint8_t instruction[4] ={ + MFRC630_ISO15693_FLAGS, //set the flags, + MFRC630_ISO15693_INVENTORY, //set "Inventory Command" + MFRC630_ISO15693_BlANK, //set blank + MFRC630_ISO15693_BlANK //set blank + }; + + //Send instruction to reader + mfrc630_write_reg(MFRC630_REG_DRVMOD,0x89); //Field on + mfrc630_cmd_transceive(instruction,4); + + // clear interrupts + mfrc630_clear_irq0(); //clear irq0 + mfrc630_clear_irq1(); //clear irq1 + + // Enable IRQ0,IRQ1 interrupt sources + mfrc630_write_reg(MFRC630_REG_IRQ0EN, MFRC630_IRQ0EN_IDLE_IRQEN | MFRC630_IRQ0EN_TX_IRQEN); + mfrc630_write_reg(MFRC630_REG_IRQ1EN, MFRC630_IRQ1EN_IRQ_PINEN | MFRC630_IRQ1EN_TIMER1_IRQEN ); + + // block until transmission ending + uint8_t irq0_value = 0; + uint8_t irq1_value = 0; + uint32_t timeout= millis() ; + while (!((irq0_value & 0x08)== 0x08)) { + irq0_value = mfrc630_irq0(); + if(millis()>(timeout+50)){ + break; + } + } + + //Wait for timer1 underflow (irq1(0x02) or RxIrQ irq0(0x04; + irq0_value =0; + timeout= millis(); + while ( ((irq1_value & 0x02) !=0x02) && ((irq0_value & 0x04) !=0x04)){ + irq1_value = mfrc630_irq1(); + irq0_value = mfrc630_irq0(); + if(millis()>(timeout+50)){ + break; + } + } + + //Check for error + if((irq1_value & 0x02)){ + return 0x01; //return error! + }; + + //disable IRQ0,IRQ1 + mfrc630_write_reg(MFRC630_REG_IRQ0EN,MFRC630_IRQ0EN_CLEAR); + mfrc630_write_reg(MFRC630_REG_IRQ1EN,MFRC630_IRQ1EN_CLEAR); + + //see if a uid was found: + uint16_t fifo_len = mfrc630_fifo_length(); + if(fifo_len != MFRC630_ISO15693_UID_LENGTH){ + return 0x02; //return error - invalid uid size! + } + + //transfer UID to variable + mfrc630_read_fifo(uid,fifo_len); + return 0; //return state - valid +} + diff --git a/mfrc630.h b/mfrc630.h index 36b60cf..7167708 100644 --- a/mfrc630.h +++ b/mfrc630.h @@ -692,6 +692,29 @@ uint8_t mfrc630_MF_write_block(uint8_t block_address, const uint8_t* source); void mfrc630_MF_example_dump(); //! @} +// --------------------------------------------------------------------------- +// ISO15693 +// --------------------------------------------------------------------------- +/*! \defgroup iso15693 ISO15693 + \brief Functions to interact with ISO15693 RFID tags / cards. + + + Basic functionallity to read uid + @{ +*/ +/*! \Initializes the reader for iso15693 + + Set all registers to the desired value for ISO15693 reading +*/ +void mfrc630_ISO15693_init(uint8_t protocol, uint8_t buf); + +/*! \Reads ISO15693 tag + + Try to Read ISO15693 tag +*/ +uint8_t mfrc630_ISO15693_readTag(uint8_t *uid); + +//! @} #ifdef __cplusplus diff --git a/mfrc630_def.h b/mfrc630_def.h index eaac4f5..b24bbf7 100644 --- a/mfrc630_def.h +++ b/mfrc630_def.h @@ -160,6 +160,11 @@ #define MFRC630_CMD_SOFTRESET 0x1F /*!< (no arguments) ; resets the MFRC630. */ +#define MFRC630_CMD_SLEEP 0xC /*!< (no arguments) ; sends the reader in low power mode */ + +#define MFRC630_CMD_WAKE 0x00 /*!< (no arguments) ; wakes up the reader from sleep mode */ + + //! @} @@ -303,6 +308,8 @@ #define MFRC630_IRQ0EN_ERR_IRQEN (1<<1) //! If set allow rx SOF irq to propagate to the global IRQ. #define MFRC630_IRQ0EN_RXSOF_IRQEN (1<<0) +//! If set allow no irq +#define MFRC630_IRQ0EN_CLEAR 0x00 //! @} @@ -334,6 +341,8 @@ #define MFRC630_IRQ1EN_TIMER1_IRQEN (1<<1) //! If set allow Timer 0 irq to propagate to the global IRQ. #define MFRC630_IRQ1EN_TIMER0_IRQEN (1<<0) +//! If set allow no irq +#define MFRC630_IRQ1EN_CLEAR 0x00 //! @} @@ -442,18 +451,18 @@ #define MFRC630_PROTO_FELICA_212_MANCHESTER_MANCHESTER 8 //! Transmitter at 424 kbit/s using Manchester modulation, Receive at 424 kbit/s using Manchester modulation. #define MFRC630_PROTO_FELICA_424_MANCHESTER_MANCHESTER 9 -//! ISO15693 1/4 SSC +//! ISO15693 1/4 SSC (ID2) #define MFRC630_PROTO_ISO15693_1_OF_4_SSC 10 -//! ISO15693 1/4 DSC +//! ISO15693 1/4 DSC (ID2) #define MFRC630_PROTO_ISO15693_1_OF_4_DSC 11 -//! ISO15693 1/256 SSC +//! ISO15693 1/256 SSC (ID2) #define MFRC630_PROTO_ISO15693_1_OF_256_SSC 12 //! EPC/UID Unitray SSC #define MFRC630_PROTO_EPC_UID_UNITRAY_SSC 13 //! ISO18000-3 Mode 3, Tari, ASK, PIE, 2/424 #define MFRC630_PROTO_ISO18000_MODE_3 14 - //! @} +//! @} // recommended register values from register 0x28 down. // From AN11022: CLRC663 Quickstart Guide @@ -472,8 +481,40 @@ //! Recommended register values for ISO1443A at 848 kbit/s with Miller / BPSK modulation. #define MFRC630_RECOM_14443A_ID1_848 {0x8F, 0xDB, 0x11, 0x06, 0x18, 0x18, 0x0F, 0x02, 0x00, 0xC0, 0x12, 0xCF, 0x00, \ 0x07, 0x90, 0x3F, 0x12, 0x02} +//registers for ISO15693 - ID1 - SSC26 - SLI 1/4 +#define MFRC630_RECOM_15693_ID1_SSC26 {0x8F, 0x4F, 0x01, 0x0A, 0x7B, 0x7B, 0x08, 0x00, 0x00, 0x88, 0xA9, 0x0F, 0x00, \ + 0x02,0x10,0x44,0x12,0x06} +//Recommended register value for ISO15693 - ID1 - SSC52 - SLI 1/4 +#define MFRC630_RECOM_15693_ID1_SSC52 {0x8F, 0x4F, 0x01, 0x0A, 0x7B, 0x7B, 0x08, 0x00, 0x00, 0x88, 0xA9, 0x0F, 0x00, \ + 0x03,0x10,0x44,0x12,0x06} +//Recommended register value for ISO15693 -ID1 - DSC - SLI 1/256 +#define MFRC630_RECOM_15693_ID1_DSC {0x8E, 0x4F, 0x01, 0x0A, 0x7B, 0x7B, 0x08, 0x00, 0x00, 0x88, 0xA9, 0x0F, 0x00, \ + 0x02,0x10,0x44,0x12,0x06} +//Recommended register value for ISO15693 - ID2 - SSC26 - SLI 1/4 +#define MFRC630_RECOM_15693_ID2_SSC26 {0x8F, 0x10, 0x01, 0x06, 0x7B, 0x7B, 0x08, 0x00, 0x00, 0x88, 0xA9, 0x0F, 0x00, \ + 0x02,0x10,0x44,0x12,0x06} +//Recommended register value for ISO15693 - ID2 - SSC52 - SLI 1/4 +#define MFRC630_RECOM_15693_ID2_SSC52 {0x8F, 0x10, 0x01, 0x06, 0x7B, 0x7B, 0x08, 0x00, 0x00, 0x88, 0xA9, 0x0F, 0x00, \ + 0x03,0x10,0x44,0x12,0x06} +//Recommended register value for ISO15693 -ID2 - DSC - SLI 1/256 +#define MFRC630_RECOM_15693_ID2_DSC {0x8E, 0x10, 0x01, 0x06, 0x7B, 0x7B, 0x08, 0x00, 0x00, 0x88, 0xA9, 0x0F, 0x00, \ + 0x02,0x10,0x44,0x12,0x06} +///Recommended register value for ISO15693 - ID3 - SSC26 - SLI 1/4 +#define MFRC630_RECOM_15693_ID3_SSC26 {0x8F, 0x17, 0x01, 0x0A, 0x7B, 0x7B, 0x08, 0x00, 0x00, 0x88, 0xA9, 0x0F, 0x00, \ + 0x02,0x10,0x44,0x12,0x06} +///Recommended register value for ISO15693 - ID3 - SSC52 - SLI 1/4 +#define MFRC630_RECOM_15693_ID3_SSC52 {0x8F, 0x17, 0x01, 0x0A, 0x7B, 0x7B, 0x08, 0x00, 0x00, 0x88, 0xA9, 0x0F, 0x00, \ + 0x03,0x10,0x44,0x12,0x06} +///Recommended register value for ISO15693 -ID3 - DSC - SLI 1/256 +#define MFRC630_RECOM_15693_ID3_DSC {0x8E, 0x17, 0x01, 0x0A, 0x7B, 0x7B, 0x08, 0x00, 0x00, 0x88, 0xA9, 0x0F, 0x00, \ + 0x02,0x10,0x44,0x12,0x06} + + + //! @} + + /*! \addtogroup iso14443a @{ */ @@ -498,4 +539,17 @@ //! @} +/*! \addtogroup iso15693 + @{ +*/ +// Defines for ISO15693 +#define MFRC630_ISO15693_INVENTORY 0x01 //!< Inventory Command of ISO15693 (like REQA for 14443) +#define MFRC630_ISO15693_FLAGS 0x36 //!< Flags for the Tag. B00110110. Check page 20 - http://www.ti.com/lit/an/sloa141/sloa141.pdf +#define MFRC630_ISO15693_BlANK 0x00 //!< Value to fill 4 byte +#define MFRC630_ISO15693_QUIET 0x02 //!< Makes a tag stay quiet + + +#define MFRC630_ISO15693_UID_LENGTH 0x0A //!< Size of UID (10 btye) +//! @} + #endif // MFRC630_DEF_H_ From d6fcd11c56d420726751bef2c255105759815026 Mon Sep 17 00:00:00 2001 From: Jonathan Frech Date: Tue, 14 Apr 2020 21:20:52 +0200 Subject: [PATCH 2/2] Various corrections -Return uid lenght as status and zero as error - adding comments - changed arduino example --- .../arduino_example/arduino_example_15693.ino | 23 ++++++++----------- mfrc630.c | 8 +++---- mfrc630.h | 13 +++++++++-- 3 files changed, 24 insertions(+), 20 deletions(-) diff --git a/examples/arduino_example/arduino_example_15693.ino b/examples/arduino_example/arduino_example_15693.ino index ba39c15..3a78071 100644 --- a/examples/arduino_example/arduino_example_15693.ino +++ b/examples/arduino_example/arduino_example_15693.ino @@ -38,7 +38,7 @@ If all goes well, a ISO15693 Tag/Card will print something like: - Tag was found! UID:00 02 F4 CF 31 1E 66 24 16 E0 ..waiting 1s for next read + Tag with valid UID was found! UID: UID:00 02 F4 CF 31 1E 66 24 16 E0 ..waiting 1s for next read Onto the serial port. @@ -90,18 +90,13 @@ void mfrc630_ISO15693_example_dump_arduino(){ uint8_t uid[10]={0}; //variable for 10byte UID uint8_t status = mfrc630_ISO15693_readTag(uid); - switch (status){ - case 0: - Serial.print("Tag was found! UID: "); - print_block(uid,10); - Serial.println(" ..waiting 1s for next read"); - break; - case 1: - Serial.println("Failure, No Tag found or Reader Problem!"); - break; - case 2: - Serial.println("Failure, No Tag found or Reader Problem!"); - break; + if(status==10){ + Serial.print("Tag with valid UID was found! UID: "); + print_block(uid,10); + Serial.println(" ..waiting 1s for next read"); + } + else{ + Serial.println("Failure, No Tag found or Reader Problem!"); } } @@ -119,7 +114,7 @@ void setup(){ SPI.begin(); // Set the registers of the MFRC630 into the default. - mfrc630_AN1102_recommended_registers(MFRC630_PROTO_ISO15693_1_OF_4_SSC); + mfrc630_AN1102_recommended_registers(MFRC630_PROTO_ISO15693_1_OF_4_SSC); } diff --git a/mfrc630.c b/mfrc630.c index ad55a9c..d9be1f1 100644 --- a/mfrc630.c +++ b/mfrc630.c @@ -1021,7 +1021,7 @@ void mfrc630_ISO15693_init(uint8_t protocol, uint8_t buf){ //Set Driver } -uint8_t mfrc630_ISO15693_readTag(uint8_t* uid){ +uint16_t mfrc630_ISO15693_readTag(uint8_t* uid){ //Set timeout for Timer0/Timer1, set reload values mfrc630_write_reg(MFRC630_REG_T0RELOADHI,0x24); @@ -1078,7 +1078,7 @@ uint8_t mfrc630_ISO15693_readTag(uint8_t* uid){ //Check for error if((irq1_value & 0x02)){ - return 0x01; //return error! + return 0x00; //return error! }; //disable IRQ0,IRQ1 @@ -1088,11 +1088,11 @@ uint8_t mfrc630_ISO15693_readTag(uint8_t* uid){ //see if a uid was found: uint16_t fifo_len = mfrc630_fifo_length(); if(fifo_len != MFRC630_ISO15693_UID_LENGTH){ - return 0x02; //return error - invalid uid size! + return 0x00; //return error - invalid uid size! } //transfer UID to variable mfrc630_read_fifo(uid,fifo_len); - return 0; //return state - valid + return fifo_len; //return state - valid } diff --git a/mfrc630.h b/mfrc630.h index 7167708..32064ff 100644 --- a/mfrc630.h +++ b/mfrc630.h @@ -705,14 +705,23 @@ void mfrc630_MF_example_dump(); /*! \Initializes the reader for iso15693 Set all registers to the desired value for ISO15693 reading + + \param [in] the specified protocol number for ISO15693, there are differnt values for 1/4 SSC or DSC or 1/256 SSC. + The right protocol for the desired card standart must be used + + \param [in] the buffer with register values according to the selected protocol, see mfrc630_AN1102_recommended_registers_skip for more information + */ void mfrc630_ISO15693_init(uint8_t protocol, uint8_t buf); /*! \Reads ISO15693 tag - Try to Read ISO15693 tag + Try to Read ISO15693 tag. The device will send the command flags and the inventory command and tries to get a response + + \param [out] uid: The UID of the card will be stored into this array. + \return length of uid in bytes, returns zero in case of failure. ISO15693 should normally return 10 for 10bytes of uid in Fifo */ -uint8_t mfrc630_ISO15693_readTag(uint8_t *uid); +uint16_t mfrc630_ISO15693_readTag(uint8_t *uid); //! @}