-
Notifications
You must be signed in to change notification settings - Fork 21
ISO15693 Support added #13
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: master
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,125 @@ | ||
| /* | ||
| 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 <Arduino.h> | ||
| #include <SPI.h> | ||
| #include <mfrc630.h> | ||
|
|
||
| /* | ||
|
|
||
|
|
||
| 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 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. | ||
|
|
||
| */ | ||
|
|
||
|
|
||
| // 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<length; i++){ | ||
| if (block[i] < 16){ | ||
| Serial.print("0"); | ||
| Serial.print(block[i], HEX); | ||
| } else { | ||
| Serial.print(block[i], HEX); | ||
| } | ||
| Serial.print(" "); | ||
| } | ||
| } | ||
|
|
||
|
|
||
| void mfrc630_ISO15693_example_dump_arduino(){ | ||
| uint8_t uid[10]={0}; //variable for 10byte UID | ||
| uint8_t status = mfrc630_ISO15693_readTag(uid); | ||
|
|
||
| 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!"); | ||
| } | ||
| } | ||
|
|
||
|
|
||
|
|
||
|
|
||
| void setup(){ | ||
| // Start serial communication. | ||
| Serial.begin(9600); | ||
|
|
||
| // Set the chip select pin to output. | ||
| pinMode(CHIP_SELECT, OUTPUT); | ||
|
|
||
| // Start the SPI bus. | ||
| SPI.begin(); | ||
|
|
||
| // Set the registers of the MFRC630 into the default. | ||
| mfrc630_AN1102_recommended_registers(MFRC630_PROTO_ISO15693_1_OF_4_SSC); | ||
|
|
||
| } | ||
|
|
||
| void loop(){ | ||
| // call the above function until infinity. | ||
| mfrc630_ISO15693_example_dump_arduino(); | ||
| delay(1000); | ||
| } | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -23,6 +23,7 @@ | |
| */ | ||
|
|
||
| #include "mfrc630.h" | ||
| #include "Arduino.h" | ||
|
Owner
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I don't want this dependency here, it rules out using this driver outside of the arduino ecosystem. |
||
|
|
||
| /** @file */ | ||
|
|
||
|
|
@@ -279,6 +280,24 @@ void mfrc630_AN1102_recommended_registers_skip(uint8_t protocol, uint8_t skip) { | |
| mfrc630_write_regs(MFRC630_REG_DRVMOD+skip, buf+skip, sizeof(buf)-skip); | ||
| } | ||
| break; | ||
| case MFRC630_PROTO_ISO15693_1_OF_4_SSC: | ||
| { | ||
| const uint8_t buf[] = MFRC630_RECOM_15693_ID1_SSC26; | ||
| mfrc630_ISO15693_init(MFRC630_PROTO_ISO15693_1_OF_4_SSC,buf); | ||
| } | ||
| break; | ||
| case MFRC630_PROTO_ISO15693_1_OF_4_DSC: | ||
| { | ||
| const uint8_t buf[] = MFRC630_RECOM_15693_ID1_DSC; | ||
| mfrc630_write_regs(MFRC630_REG_DRVMOD+skip, buf+skip, sizeof(buf)-skip); | ||
| } | ||
| break; | ||
| case MFRC630_PROTO_ISO15693_1_OF_256_SSC: | ||
| { | ||
| const uint8_t buf[] = MFRC630_RECOM_15693_ID1_SSC52; | ||
| mfrc630_write_regs(MFRC630_REG_DRVMOD+skip, buf+skip, sizeof(buf)-skip); | ||
| } | ||
| break; | ||
| } | ||
| } | ||
| void mfrc630_AN1102_recommended_registers(uint8_t protocol) { | ||
|
|
@@ -931,3 +950,149 @@ void mfrc630_MF_example_dump() { | |
| MFRC630_PRINTF("No answer to REQA, no cards?\n"); | ||
| } | ||
| } | ||
|
|
||
| void mfrc630_ISO15693_init(uint8_t protocol, uint8_t buf){ | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. @sgtJohnny I think there's a bug here - |
||
|
|
||
| // Configure Timers | ||
| mfrc630_write_reg(MFRC630_REG_T0CONTROL,0x98); //configure T0 | ||
| mfrc630_write_reg(MFRC630_REG_T1CONTROL,0x92); //configure T1 and cascade it with T0 | ||
| mfrc630_write_reg(MFRC630_REG_T2CONTROL,0x20); //Configure T2 for LFO Autotrimm | ||
| mfrc630_write_reg(MFRC630_REG_T2RELOADHI,0x03); //T2 reload value for LFO AutoTrimm | ||
| mfrc630_write_reg(MFRC630_REG_T2RELOADLO,0xFF); //T2 reload value high | ||
| mfrc630_write_reg(MFRC630_REG_T3CONTROL,0x00); //Configure T3 (for LPCD /Autotrimm) | ||
|
|
||
| //Configure FiFo | ||
| mfrc630_write_reg(MFRC630_REG_FIFOCONTROL,0x90); //Set Fifo-Size and Waterlevel | ||
| mfrc630_write_reg(MFRC630_REG_WATERLEVEL,0xFE); //Set Waterlevel | ||
|
|
||
| //Configure RXBITCTRL | ||
| mfrc630_write_reg(MFRC630_REG_RXBITCTRL,0x80); //Set RXBITCTLR register | ||
|
|
||
| //set the Protocol | ||
| mfrc630_AN1102_recommended_registers(buf); //Write buffered values | ||
|
|
||
| mfrc630_cmd_idle(); //Cancel any commands | ||
| mfrc630_flush_fifo(); //Flush Fifo | ||
| mfrc630_clear_irq0(); //Clear IRQ0 | ||
| mfrc630_clear_irq1(); //Clear IRQ1 | ||
|
|
||
| //Set Timers | ||
| mfrc630_write_reg(MFRC630_REG_T0RELOADHI,0x18); //T0 Reload Hi | ||
| mfrc630_write_reg(MFRC630_REG_T0RELOADLO,0x86); //T0 Reload Lo | ||
| mfrc630_write_reg(MFRC630_REG_T1RELOADHI,0x00); //T1 Reload Hi | ||
| mfrc630_write_reg(MFRC630_REG_T1RELOADLO,0x00); //T1 Reload Lo | ||
|
|
||
| // Write in FIFO "Load protocol" params(TxProtocol=Iso15693(0a), RxProtocol=Iso15693(0a), | ||
| mfrc630_write_reg(MFRC630_REG_FIFODATA,protocol); | ||
| mfrc630_write_reg(MFRC630_REG_FIFODATA,protocol); | ||
|
|
||
| mfrc630_write_reg(MFRC630_REG_IRQ0EN, MFRC630_IRQ0EN_IDLE_IRQEN); // Enable IRQ0 interrupt source | ||
| mfrc630_write_reg(MFRC630_REG_IRQ1EN, MFRC630_IRQ1EN_IRQ_PINEN); // Enable IRQ1 interrupt source | ||
| mfrc630_write_reg(MFRC630_REG_COMMAND,MFRC630_CMD_LOADPROTOCOL); // Execute Rc663 command: "Load protocol" | ||
|
|
||
| mfrc630_write_reg(MFRC630_REG_IRQ0EN, MFRC630_IRQ0EN_CLEAR); //Disable IRQ | ||
| mfrc630_write_reg(MFRC630_REG_IRQ1EN, MFRC630_IRQ1EN_CLEAR); //Disable IRQ | ||
|
|
||
| mfrc630_flush_fifo(); //Flush Fifo | ||
|
|
||
| //> 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 | ||
| } | ||
|
|
||
| uint16_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; | ||
| } | ||
| } | ||
|
Owner
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Any chance you could change this timeout handling to use the internal timer? like how's done in |
||
|
|
||
| //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 0x00; //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 0x00; //return error - invalid uid size! | ||
| } | ||
|
|
||
| //transfer UID to variable | ||
| mfrc630_read_fifo(uid,fifo_len); | ||
| return fifo_len; //return state - valid | ||
| } | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -692,6 +692,38 @@ 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 | ||
iwanders marked this conversation as resolved.
Show resolved
Hide resolved
|
||
|
|
||
| \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 | ||
|
Owner
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Spelling mistakes in |
||
|
|
||
| \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. 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 | ||
| */ | ||
|
Owner
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Can we add some more documentation here? What does the returned value mean?
Owner
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This is much better, please add a space between |
||
| uint16_t mfrc630_ISO15693_readTag(uint8_t *uid); | ||
|
|
||
| //! @} | ||
|
|
||
|
|
||
| #ifdef __cplusplus | ||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nitpick, this function has tabs, not spaces.