From 2bef5567f81663f7ce47b6ebc1e524ce217120a3 Mon Sep 17 00:00:00 2001 From: mjmeans Date: Tue, 29 Oct 2024 12:05:40 -0700 Subject: [PATCH 01/32] Add ability to specify disableCollisionAvoidance and activeCommunicationMode options in setRF_on() --- PN5180.cpp | 3 ++- PN5180.h | 2 +- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/PN5180.cpp b/PN5180.cpp index 886167c..ab46a6f 100644 --- a/PN5180.cpp +++ b/PN5180.cpp @@ -579,10 +579,11 @@ bool PN5180::loadRFConfig(uint8_t txConf, uint8_t rxConf) { * This command is used to switch on the internal RF field. If enabled the TX_RFON_IRQ is * set after the field is switched on. */ -bool PN5180::setRF_on() { +bool PN5180::setRF_on(bool disableCollisionAvoidance, bool activeCommunicationMode) { PN5180DEBUG_PRINTLN(F("Set RF ON")); PN5180DEBUG_ENTER; + uint8_t param = ((disableCollisionAvoidance) ? 1:0) & ((activeCommunicationMode) ? 1<<1:0); uint8_t cmd[] = { PN5180_RF_ON, 0x00 }; transceiveCommand(cmd, sizeof(cmd)); diff --git a/PN5180.h b/PN5180.h index c0f5486..2ea75b6 100644 --- a/PN5180.h +++ b/PN5180.h @@ -138,7 +138,7 @@ class PN5180 { bool loadRFConfig(uint8_t txConf, uint8_t rxConf); /* cmd 0x16 */ - bool setRF_on(); + bool setRF_on(bool disableCollisionAvoidance = false, bool activeCommunicationMode = false); /* cmd 0x17 */ bool setRF_off(); From b5e604e7f47d350deca4aa113e4e97971eeeadfe Mon Sep 17 00:00:00 2001 From: mjmeans Date: Tue, 29 Oct 2024 13:13:11 -0700 Subject: [PATCH 02/32] Add missing IRQ_STATUS register defines --- PN5180.h | 33 ++++++++++++++++++++++----------- 1 file changed, 22 insertions(+), 11 deletions(-) diff --git a/PN5180.h b/PN5180.h index 2ea75b6..ba83021 100644 --- a/PN5180.h +++ b/PN5180.h @@ -69,17 +69,28 @@ enum PN5180TransceiveStat { PN5180_TS_RESERVED = 7 }; -// PN5180 IRQ_STATUS -#define RX_IRQ_STAT (1<<0) // End of RF receiption IRQ -#define TX_IRQ_STAT (1<<1) // End of RF transmission IRQ -#define IDLE_IRQ_STAT (1<<2) // IDLE IRQ -#define RFOFF_DET_IRQ_STAT (1<<6) // RF Field OFF detection IRQ -#define RFON_DET_IRQ_STAT (1<<7) // RF Field ON detection IRQ -#define TX_RFOFF_IRQ_STAT (1<<8) // RF Field OFF in PCD IRQ -#define TX_RFON_IRQ_STAT (1<<9) // RF Field ON in PCD IRQ -#define RX_SOF_DET_IRQ_STAT (1<<14) // RF SOF Detection IRQ -#define GENERAL_ERROR_IRQ_STAT (1<<17) // General error IRQ -#define LPCD_IRQ_STAT (1<<19) // LPCD Detection IRQ +// PN5180 IRQ_STATUS register (https://www.nxp.com/docs/en/data-sheet/PN5180A0XX_C3_C4.pdf, pages 83-84) +#define RX_IRQ_STAT (1<<0) // End of RF receiption IRQ +#define TX_IRQ_STAT (1<<1) // End of RF transmission IRQ +#define IDLE_IRQ_STAT (1<<2) // IDLE IRQ +#define MODE_DETECTED_IRQ_STAT (1<<3) // External modulation scheme detection IRQ +#define CARD_ACTIVATED_IRQ_STAT (1<<4) // Activated as a Card IRQ +#define STATE_CHANGE_IRQ_STAT (1<<5) // State Change in the transceive state machine IRQ +#define RFOFF_DET_IRQ_STAT (1<<6) // RF Field OFF detection IRQ +#define RFON_DET_IRQ_STAT (1<<7) // RF Field ON detection IRQ +#define TX_RFOFF_IRQ_STAT (1<<8) // RF Field OFF in PCD IRQ +#define TX_RFON_IRQ_STAT (1<<9) // RF Field ON in PCD IRQ +#define RF_ACTIVE_ERROR_IRQ_STAT (1<<10) // RF active error IRQ +#define TIMER0_IRQ_STAT (1<<11) // Timer0 IRQ +#define TIMER1_IRQ_STAT (1<<12) // Timer1 IRQ +#define TIMER2_IRQ_STAT (1<<13) // Timer2 IRQ +#define RX_SOF_DET_IRQ_STAT (1<<14) // RF SOF Detection IRQ +#define RX_SC_DET_IRQ_STAT (1<<15) // RX Subcarrier Detection IRQ +#define TEMPSENS_ERROR_IRQ_STAT (1<<16) // Temperature Sensor IRQ +#define GENERAL_ERROR_IRQ_STAT (1<<17) // General error IRQ +#define HV_ERROR_IRQ_STAT (1<<18) // EEPROM Failure during Programming IRQ +#define LPCD_IRQ_STAT (1<<19) // LPCD Detection IRQ +// Bits 20-31 RFU (Reserved for Future Use) #define MIFARE_CLASSIC_KEYA 0x60 // Mifare Classic key A #define MIFARE_CLASSIC_KEYB 0x61 // Mifare Classic key B From 93bf5272217933f97f3e95312fed0ac287815bfa Mon Sep 17 00:00:00 2001 From: mjmeans Date: Sat, 9 Nov 2024 09:39:02 -0700 Subject: [PATCH 03/32] Revert "Add ability to specify disableCollisionAvoidance and activeCommunicationMode options in setRF_on()" This reverts commit 2bef5567f81663f7ce47b6ebc1e524ce217120a3. --- PN5180.cpp | 3 +-- PN5180.h | 2 +- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/PN5180.cpp b/PN5180.cpp index ab46a6f..886167c 100644 --- a/PN5180.cpp +++ b/PN5180.cpp @@ -579,11 +579,10 @@ bool PN5180::loadRFConfig(uint8_t txConf, uint8_t rxConf) { * This command is used to switch on the internal RF field. If enabled the TX_RFON_IRQ is * set after the field is switched on. */ -bool PN5180::setRF_on(bool disableCollisionAvoidance, bool activeCommunicationMode) { +bool PN5180::setRF_on() { PN5180DEBUG_PRINTLN(F("Set RF ON")); PN5180DEBUG_ENTER; - uint8_t param = ((disableCollisionAvoidance) ? 1:0) & ((activeCommunicationMode) ? 1<<1:0); uint8_t cmd[] = { PN5180_RF_ON, 0x00 }; transceiveCommand(cmd, sizeof(cmd)); diff --git a/PN5180.h b/PN5180.h index ba83021..ceae6ad 100644 --- a/PN5180.h +++ b/PN5180.h @@ -149,7 +149,7 @@ class PN5180 { bool loadRFConfig(uint8_t txConf, uint8_t rxConf); /* cmd 0x16 */ - bool setRF_on(bool disableCollisionAvoidance = false, bool activeCommunicationMode = false); + bool setRF_on(); /* cmd 0x17 */ bool setRF_off(); From cf0703d6a2f8cc466c2e7f4fef2883733a9cd05d Mon Sep 17 00:00:00 2001 From: mjmeans Date: Sat, 9 Nov 2024 09:48:34 -0700 Subject: [PATCH 04/32] Update Debug.cpp Somewhere along the line the DEBUG define was not in DEBUG, which results in formatHex() not being included. Now it is conspicuously uncommentable. --- Debug.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/Debug.cpp b/Debug.cpp index ea42e42..72de30a 100644 --- a/Debug.cpp +++ b/Debug.cpp @@ -16,6 +16,7 @@ // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU // Lesser General Public License for more details. // +//#define DEBUG 1 #include #include "Debug.h" From c91f0b542e0d0faa6bd78634013b200ad177763e Mon Sep 17 00:00:00 2001 From: mjmeans Date: Sat, 9 Nov 2024 11:50:27 -0700 Subject: [PATCH 05/32] Add missing register defines Expanded defines for all registers for reference and future use --- PN5180.h | 66 ++++++++++++++++++++++++++++++++++++++++---------------- 1 file changed, 47 insertions(+), 19 deletions(-) diff --git a/PN5180.h b/PN5180.h index ceae6ad..5a7322b 100644 --- a/PN5180.h +++ b/PN5180.h @@ -21,25 +21,53 @@ #include -// PN5180 Registers -#define SYSTEM_CONFIG (0x00) -#define IRQ_ENABLE (0x01) -#define IRQ_STATUS (0x02) -#define IRQ_CLEAR (0x03) -#define TRANSCEIVE_CONTROL (0x04) -#define TIMER1_RELOAD (0x0c) -#define TIMER1_CONFIG (0x0f) -#define RX_WAIT_CONFIG (0x11) -#define CRC_RX_CONFIG (0x12) -#define RX_STATUS (0x13) -#define TX_WAIT_CONFIG (0x17) -#define TX_CONFIG (0x18) -#define CRC_TX_CONFIG (0x19) -#define RF_STATUS (0x1d) -#define SYSTEM_STATUS (0x24) -#define TEMP_CONTROL (0x25) -#define AGC_REF_CONFIG (0x26) - +// PN5180 Registers (https://www.nxp.com/docs/en/data-sheet/PN5180A0XX-C1-C2.pdf, pp 87-88) +#define SYSTEM_CONFIG (0x00) +#define IRQ_ENABLE (0x01) +#define IRQ_STATUS (0x02) +#define IRQ_CLEAR (0x03) +#define TRANSCEIVE_CONTROL (0x04) +//#define PADCONFIG (0x05) +//#define RFU (0x06) +//#define PADOUT (0x07) +//#define TIMER0_STATUS (0x08) +//#define TIMER1_STATUS (0x09) +//#define TIMER2_STATUS (0x0a) +//#define TIMER0_RELOAD (0x0b) +#define TIMER1_RELOAD (0x0c) +//#define TIMER2_RELOAD (0x0d) +//#define TIMER0_CONFIG (0x0e) +#define TIMER1_CONFIG (0x0f) +//#define TIMER2_CONFIG (0x10) +#define RX_WAIT_CONFIG (0x11) +#define CRC_RX_CONFIG (0x12) +#define RX_STATUS (0x13) +//#define TX_UNDERSHOOT_CONFIG (0x14) +//#define TX_OVERSHOOT_CONFIG (0x15) +//#define TX_DATA_MOD (0x16) +#define TX_WAIT_CONFIG (0x17) +#define TX_CONFIG (0x18) +#define CRC_TX_CONFIG (0x19) +//#define SIGPRO_CONFIG (0x1a) +//#define SIGPRO_CM_CONFIG (0x1b) +//#define SIGPRO_RM_CONFIG (0x1c) +#define RF_STATUS (0x1d) +//#define AGC_CONFIG (0x1e) +//#define AGC_VALUE (0x1f) +//#define RF_CONTROL_TX (0x20) +//#define RF_CONTROL_TX_CLK (0x21) +//#define RF_CONTROL_RX (0x22) +#define LD_CONTROL (0x23) +#define SYSTEM_STATUS (0x24) +#define TEMP_CONTROL (0x25) +#define AGC_REF_CONFIG (0x26) +//#define DPC_CONFIG (0x27) +//#define EMD_CONTROL (0x28) +//#define ANT_CONTROL (0x29) +//#define SIGPRO_RM_CONFIG_EXTENSION (0x39) // requires FW 3.8 or later +// PN5180 Registers - additional registers(https://www.nxp.com/docs/en/data-sheet/PN5180A0XX_C3_C4.pdf, pp 80-81) +//#define TX_CONTROL (0x36) +//#define FELICA_EMD_CONTROL (0x43) // requires FW 4.1 or later // PN5180 EEPROM Addresses #define DIE_IDENTIFIER (0x00) From 82211286bbdd9fce2dde719a87eaf93755b9723a Mon Sep 17 00:00:00 2001 From: mjmeans Date: Sat, 9 Nov 2024 11:54:21 -0700 Subject: [PATCH 06/32] Add missing Host Interface Command defines Expanded defines for all Host Interface Commands for reference and future use --- PN5180.cpp | 39 +++++++++++++++++++++++++-------------- 1 file changed, 25 insertions(+), 14 deletions(-) diff --git a/PN5180.cpp b/PN5180.cpp index 886167c..12bbf37 100644 --- a/PN5180.cpp +++ b/PN5180.cpp @@ -23,20 +23,31 @@ #include "Debug.h" // PN5180 1-Byte Direct Commands -// see 11.4.3.3 Host Interface Command List -#define PN5180_WRITE_REGISTER (0x00) -#define PN5180_WRITE_REGISTER_OR_MASK (0x01) -#define PN5180_WRITE_REGISTER_AND_MASK (0x02) -#define PN5180_READ_REGISTER (0x04) -#define PN5180_WRITE_EEPROM (0x06) -#define PN5180_READ_EEPROM (0x07) -#define PN5180_SEND_DATA (0x09) -#define PN5180_READ_DATA (0x0A) -#define PN5180_SWITCH_MODE (0x0B) -#define PN5180_MIFARE_AUTHENTICATE (0x0C) -#define PN5180_LOAD_RF_CONFIG (0x11) -#define PN5180_RF_ON (0x16) -#define PN5180_RF_OFF (0x17) +// see 11.4.3.3 Host Interface Command List (https://www.nxp.com/docs/en/data-sheet/PN5180A0XX_C3_C4.pdf, page 20) +#define PN5180_WRITE_REGISTER (0x00) // Write one 32bit register value +#define PN5180_WRITE_REGISTER_OR_MASK (0x01) // Sets one 32bit register value using a 32 bit OR mask +#define PN5180_WRITE_REGISTER_AND_MASK (0x02) // Sets one 32bit register value using a 32 bit AND mask +//#define PN5180_WRITE_REGISTER_MULTIPLE (0x03) // Processes an array of register addresses in random order and performs the defined action on these addresses. +#define PN5180_READ_REGISTER (0x04) // Reads one 32bit register value +//#define PN5180_READ_REGISTER_MULTIPLE (0x05) // Reads from an array of max.18 register addresses in random order +#define PN5180_WRITE_EEPROM (0x06) // Processes an array of EEPROM addresses in random order and writes the value to these addresses +#define PN5180_READ_EEPROM (0x07) // Processes an array of EEPROM addresses from a start address and reads the values from these addresses +//#define PN5180_WRITE_TX_DATA (0x08) // Write data into the transmission buffer +#define PN5180_SEND_DATA (0x09) // Write data into the transmission buffer, the START_SEND bit is automatically set +#define PN5180_READ_DATA (0x0A) // Read data from reception buffer, after successful reception +#define PN5180_SWITCH_MODE (0x0B) // Switch the mode. It is only possible to switch from NormalMode to standby, LPCD or Autocoll +#define PN5180_MIFARE_AUTHENTICATE (0x0C) // Perform a MIFARE Classic Authentication on an activated card +//#define PN5180_EPC_INVENTORY (0x0D) // Perform an inventory of ISO18000-3M3 tags +//#define PN5180_EPC_RESUME_INVENTORY (0x0E) // Resume the inventory algorithm in case it is paused +//#define PN5180_EPC_RETRIEVE_INVENTORY_RESULT_SIZE (0x0F) // Retrieve the size of the inventory result +//#define PN5180_EPC_RETRIEVE_INVENTORY_RESULT (0x10) // Retrieve the result of a preceding EPC_INVENTORY or EPC_RESUME_INVENTORY instruction +#define PN5180_LOAD_RF_CONFIG (0x11) // Load the RF configuration from EEPROM into the configuration registers +//#define UPDATE_RF_CONFIG (0x12) // Update the RF configuration within EEPROM. +//#define RETRIEVE_RF_CONFIG_SIZE (0x13) // Retrieve the number of registers for a selected RF configuration +//#define RETRIEVE_RF_CONFIG (0x14) // Read out an RF configuration. The register address-value-pairs are available in the response +//#define RFU (0x15) // RFU (reserved for future use) +#define PN5180_RF_ON (0x16) // Switch on the RF Field +#define PN5180_RF_OFF (0x17) // Switch off the RF Field uint8_t PN5180::readBufferStatic16[16]; From 43bdde70969a230e22977539288fd5c3a289efce Mon Sep 17 00:00:00 2001 From: mjmeans Date: Thu, 14 Nov 2024 11:59:08 -0700 Subject: [PATCH 07/32] Bugfix: Collision resolution needs to adjust by 4 bits, not 2 --- PN5180ISO15693.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/PN5180ISO15693.cpp b/PN5180ISO15693.cpp index 01ef748..530ca0f 100644 --- a/PN5180ISO15693.cpp +++ b/PN5180ISO15693.cpp @@ -143,8 +143,8 @@ ISO15693ErrorCode PN5180ISO15693::inventoryPoll(uint8_t *uid, uint8_t maxTags, u PN5180DEBUG(F(": ")); uint16_t len = (uint16_t)(rxStatus & 0x000001ff); if((rxStatus >> 18) & 0x01 && *numCol < maxTags){ // 7+ Determine if a collision occurred - if(maskLen > 0) collision[*numCol] = collision[0] | (slot << (maskLen * 2)); - else collision[*numCol] = slot << (maskLen * 2); // Yes, store position of collision + if(maskLen > 0) collision[*numCol] = collision[0] | (slot << (maskLen * 4)); + else collision[*numCol] = slot << (maskLen * 4); // Yes, store position of collision *numCol = *numCol + 1; #ifdef DEBUG PN5180DEBUG_PRINTF("Collision detected for UIDs matching %X starting at LSB", collision[*numCol-1]); From 22fca714b2c2d6272635921547fe3f9a8bcc2fcc Mon Sep 17 00:00:00 2001 From: mjmeans Date: Sat, 16 Nov 2024 23:00:11 -0700 Subject: [PATCH 08/32] Update Debug.h Fix #ifdef nesting --- Debug.h | 37 +++++++++++++++++++++++-------------- 1 file changed, 23 insertions(+), 14 deletions(-) diff --git a/Debug.h b/Debug.h index 475d872..7aafbe1 100644 --- a/Debug.h +++ b/Debug.h @@ -19,16 +19,6 @@ #ifndef DEBUG_H #define DEBUG_H -#ifdef DEBUG -extern uint8_t _pn5180_debugIndent; -extern uint8_t _pn5180_debugIndentN; -extern bool _pn5180_debugNL; -extern uint8_t _pn5180_debugSilent; - -// These macros are helper macros to make the see the debug macros like function calls so they do not alter any current code block structures when the macro contains if/else/break, etc. -#define __DEBUG_BEGIN__ do{if(DEBUG){ -#define __DEBUG_END__ }}while(0) - // DEBUG print with indention macros: // // USAGE: @@ -83,6 +73,19 @@ extern uint8_t _pn5180_debugSilent; // | IRQ-Status=0x00000004 // ---------------------------------- +#if defined(DEBUG) || defined(DEBUG_ERROR) +extern uint8_t _pn5180_debugIndent; +extern uint8_t _pn5180_debugIndentN; +extern bool _pn5180_debugNL; +extern uint8_t _pn5180_debugSilent; + +// These macros are helper macros to make the see the debug macros like function calls so they do not alter any current code block structures when the macro contains if/else/break, etc. +#define __DEBUG_BEGIN__ do{if(DEBUG){ +#define __DEBUG_END__ }}while(0) +#define __ERROR_BEGIN__ do{if(DEBUG_ERROR){ +#define __ERROR_END__ }}while(0) + +#ifdef DEBUG #define PN5180DEBUG_OFF __DEBUG_BEGIN__ ++_pn5180_debugSilent; __DEBUG_END__ #define PN5180DEBUG_ON __DEBUG_BEGIN__ _pn5180_debugSilent-=((_pn5180_debugSilent>0)?1:0); __DEBUG_END__ #define PN5180DEBUG_ENTER __DEBUG_BEGIN__ ++_pn5180_debugIndent; __DEBUG_END__ @@ -92,7 +95,7 @@ extern uint8_t _pn5180_debugSilent; #define PN5180DEBUG_PRINTF(...) __DEBUG_BEGIN__ if (!_pn5180_debugSilent) { if (_pn5180_debugNL) PN5180DEBUG_INDENT; Serial.printf(__VA_ARGS__); }; __DEBUG_END__ #define PN5180DEBUG_PRINT(...) __DEBUG_BEGIN__ if (!_pn5180_debugSilent) { if (_pn5180_debugNL) PN5180DEBUG_INDENT; Serial.print(__VA_ARGS__); }; __DEBUG_END__ #define PN5180DEBUG(msg) PN5180DEBUG_PRINT(msg) -#else +#else #define PN5180DEBUG_OFF #define PN5180DEBUG_ON #define PN5180DEBUG_ENTER @@ -102,12 +105,18 @@ extern uint8_t _pn5180_debugSilent; #define PN5180DEBUG_PRINTF(...) #define PN5180DEBUG_PRINT(...) #define PN5180DEBUG(msg) -#endif +#endif /* DEBUG */ + +#ifdef DEBUG_ERROR +#define PN5180ERROR(...) __ERROR_BEGIN__ if (!_pn5180_debugSilent) { if (!_pn5180_debugNL) Serial.print(F("\n"));; Serial.print(F("*** ERROR: ")); Serial.printf(__VA_ARGS__); Serial.print(F("\n"));}; __ERROR_END__ +#else +#define PN5180ERROR(...) +#endif /* DEBUG_ERROR */ -#ifdef DEBUG extern char * formatHex(const uint8_t val); extern char * formatHex(const uint16_t val); extern char * formatHex(const uint32_t val); -#endif + +#endif /* defined(DEBUG) || defined(DEBUG_ERROR) */ #endif /* DEBUG_H */ From 644bc8182cc2a22992584dbd0e42dd7e6c8c301f Mon Sep 17 00:00:00 2001 From: mjmeans Date: Sat, 16 Nov 2024 23:36:08 -0700 Subject: [PATCH 09/32] Add #defines for ISO18593-3 Improve code readabiility and allow eventual expansion to full ISO18593-3 compatibility. --- PN5180ISO15693.cpp | 62 ++++++++++++++++++++++++++++++++++++++++------ 1 file changed, 54 insertions(+), 8 deletions(-) diff --git a/PN5180ISO15693.cpp b/PN5180ISO15693.cpp index 530ca0f..11f4396 100644 --- a/PN5180ISO15693.cpp +++ b/PN5180ISO15693.cpp @@ -22,6 +22,49 @@ #include "PN5180ISO15693.h" #include "Debug.h" +// ISO15693-3 (1999) Request Flags Table 3 (http://olmicrowaves.com/menucontents/designsupport/rfid/ISO15693-3.pdf, page 9) +#define ISO15693_REQ_FLAG_SUBCARRIER (1<<0) // Subcarrier (0:ASK, 1:FSK) +#define ISO15693_REQ_FLAG_DATARATE (1<<1) // Uplink data rate (0:Low, 1:High) +#define ISO15693_REQ_FLAG_INVENTORY (1<<2) // Inventory (0: Bits 5-8 are table 4 flags, 1: Bits 5-8 are table 5 (inventory) flags) +#define ISO15693_REQ_FLAG_PROTOCOL (1<<3) // Protocol extention (always 0) + +// ISO15693-3 (1999) Request Flags Table 4 (http://olmicrowaves.com/menucontents/designsupport/rfid/ISO15693-3.pdf, page 10) +#define ISO15693_REQ_FLAG_SELECT (1<<4) // Select (0: if Address flag set, use address mode, 1: Use select mode) +#define ISO15693_REQ_FLAG_ADDRESS (1<<5) // Address (0: Don't use address more, 1: Use address mode) +#define ISO15693_REQ_FLAG_OPTION (1<<6) // Option (0: Default value, 1: Must be set for write operations) +#define ISO15693_REQ_FLAG_RFU (1<<7) // RFU (always 0) + +// ISO15693-3 (1999) Request Flags Table 5 (http://olmicrowaves.com/menucontents/designsupport/rfid/ISO15693-3.pdf, page 10) +#define ISO15693_REQ_FLAG_AFI (1<<4) // Inventory AFI (0: Don't use AFI, 1: Use AFI) +#define ISO15693_REQ_FLAG_NBSLOTS (1<<5) // Inventory Slots (0: 16-slots, 1: 1-slot) +#define ISO15693_REQ_FLAG_OPTION (1<<6) // Inventory Option (0: Default value, 1: Must be set for write operations) +#define ISO15693_REQ_FLAG_RFU (1<<7) // Inventory RFU (always 0) + +// ISO15693-3 (1999) Response Flags Table 6 (http://olmicrowaves.com/menucontents/designsupport/rfid/ISO15693-3.pdf, page 11) +#define ISO15693_RESP_FLAG_ERROR (1<<0) // Error: (0: no error, 1: error) +#define ISO15693_RESP_FLAG_EXTENSION (1<<3) // Extension: (0: no protocol format extension, 1: protocol format is extended) + +// ISO15693-3 (1999) Response Error Codes Table 7 (http://olmicrowaves.com/menucontents/designsupport/rfid/ISO15693-3.pdf, page 12) +// (See enum ISO15693ErrorCode in PN5180ISO15693.h) + +// ISO15693-3 (1999) Commands (http://olmicrowaves.com/menucontents/designsupport/rfid/ISO15693-3.pdf, pages 21) +#define ISO15693_CMD_IVENTORY (0x01) +#define ISO15693_CMD_STAYQUIET (0x02) +// 0x03 to 0x1F RFU +#define ISO15693_CMD_READSINGLEBLOCK (0x20) +#define ISO15693_CMD_WRITESINGLEBLOCK (0x21) +#define ISO15693_CMD_LOCKBLOCK (0x22) +#define ISO15693_CMD_READMULTIPLEBLOCKS (0x23) +#define ISO15693_CMD_WRITEMULTIPLEBLOCKS (0x24) +#define ISO15693_CMD_SELECT (0x25) +#define ISO15693_CMD_RESETTOREADY (0x26) +#define ISO15693_CMD_WRITEAFI (0x27) +#define ISO15693_CMD_LOCKAFI (0x28) +#define ISO15693_CMD_WRITEDSFID (0x29) +#define ISO15693_CMD_LOCKDSFID (0x2A) +#define ISO15693_CMD_GETSYSTEMINFORMATION (0x2B) +#define ISO15693_CMD_GETMULTIPLEBLOCKSECURITYSTATUS (0x2C) + PN5180ISO15693::PN5180ISO15693(uint8_t SSpin, uint8_t BUSYpin, uint8_t RSTpin, SPIClass& spi) : PN5180(SSpin, BUSYpin, RSTpin, spi) { } @@ -34,10 +77,11 @@ PN5180ISO15693::PN5180ISO15693(uint8_t SSpin, uint8_t BUSYpin, uint8_t RSTpin, S * */ ISO15693ErrorCode PN5180ISO15693::getInventory(uint8_t *uid) { - // Flags, CMD, maskLen - uint8_t inventory[] = { 0x26, 0x01, 0x00 }; - // |\- inventory flag + high data rate - // \-- 1 slot: only one card, no AFI field present + uint8_t cmd = ISO15693_CMD_IVENTORY; + // flags = 1 slot, only one card, no AFI field present, inventory flag + high data rate + uint8_t flags = ISO15693_REQ_FLAG_NBSLOTS | ISO15693_REQ_FLAG_INVENTORY | ISO15693_REQ_FLAG_DATARATE; + uint8_t maskLen = 0x00; + uint8_t inventory[] = { cmd, flags, maskLen }; PN5180DEBUG(F("Get Inventory...\n")); for (int i=0; i<8; i++) { @@ -80,6 +124,7 @@ ISO15693ErrorCode PN5180ISO15693::getInventoryMultiple(uint8_t *uid, uint8_t max PN5180DEBUG_PRINTF("PN5180ISO15693::getInventoryMultiple(maxTags=%d, numCard=%d)", maxTags, *numCard); PN5180DEBUG_PRINTLN(); PN5180DEBUG_ENTER; + uint16_t collision[maxTags]; *numCard = 0; uint8_t numCol = 0; @@ -108,6 +153,9 @@ ISO15693ErrorCode PN5180ISO15693::inventoryPoll(uint8_t *uid, uint8_t maxTags, u PN5180DEBUG_PRINTLN(); PN5180DEBUG_ENTER; + uint8_t cmd = ISO15693_CMD_IVENTORY; + // flags = 16 slots: upto 16 cards, no AFI field present, inventory flag + high data rate + uint8_t flags = ISO15693_REQ_FLAG_INVENTORY | ISO15693_REQ_FLAG_DATARATE; uint8_t maskLen = 0; if(*numCol > 0){ uint32_t mask = collision[0]; @@ -117,10 +165,8 @@ ISO15693ErrorCode PN5180ISO15693::inventoryPoll(uint8_t *uid, uint8_t maxTags, u }while(mask > 0); } uint8_t *p = (uint8_t*)&(collision[0]); - // Flags, CMD, - const uint8_t inventory[7] = { 0x06, 0x01, uint8_t(maskLen*4), p[0], p[1], p[2], p[3] }; - // |\- inventory flag + high data rate - // \-- 16 slots: upto 16 cards, no AFI field present + + const uint8_t inventory[7] = { flags, cmd, uint8_t(maskLen*4), p[0], p[1], p[2], p[3] }; uint8_t cmdLen = 3 + (maskLen/2) + (maskLen%2); #ifdef DEBUG PN5180DEBUG_PRINTF(F("mask=%d, maskLen=%d, cmdLen=%d"), p[0], maskLen, cmdLen); From 4c564014f1baa52de5af5f9be392e09743ea5c42 Mon Sep 17 00:00:00 2001 From: mjmeans Date: Sat, 16 Nov 2024 23:37:58 -0700 Subject: [PATCH 10/32] Fix typo --- PN5180ISO15693.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/PN5180ISO15693.cpp b/PN5180ISO15693.cpp index 11f4396..24854f7 100644 --- a/PN5180ISO15693.cpp +++ b/PN5180ISO15693.cpp @@ -48,7 +48,7 @@ // (See enum ISO15693ErrorCode in PN5180ISO15693.h) // ISO15693-3 (1999) Commands (http://olmicrowaves.com/menucontents/designsupport/rfid/ISO15693-3.pdf, pages 21) -#define ISO15693_CMD_IVENTORY (0x01) +#define ISO15693_CMD_INVENTORY (0x01) #define ISO15693_CMD_STAYQUIET (0x02) // 0x03 to 0x1F RFU #define ISO15693_CMD_READSINGLEBLOCK (0x20) @@ -77,7 +77,7 @@ PN5180ISO15693::PN5180ISO15693(uint8_t SSpin, uint8_t BUSYpin, uint8_t RSTpin, S * */ ISO15693ErrorCode PN5180ISO15693::getInventory(uint8_t *uid) { - uint8_t cmd = ISO15693_CMD_IVENTORY; + uint8_t cmd = ISO15693_CMD_INVENTORY; // flags = 1 slot, only one card, no AFI field present, inventory flag + high data rate uint8_t flags = ISO15693_REQ_FLAG_NBSLOTS | ISO15693_REQ_FLAG_INVENTORY | ISO15693_REQ_FLAG_DATARATE; uint8_t maskLen = 0x00; @@ -153,7 +153,7 @@ ISO15693ErrorCode PN5180ISO15693::inventoryPoll(uint8_t *uid, uint8_t maxTags, u PN5180DEBUG_PRINTLN(); PN5180DEBUG_ENTER; - uint8_t cmd = ISO15693_CMD_IVENTORY; + uint8_t cmd = ISO15693_CMD_INVENTORY; // flags = 16 slots: upto 16 cards, no AFI field present, inventory flag + high data rate uint8_t flags = ISO15693_REQ_FLAG_INVENTORY | ISO15693_REQ_FLAG_DATARATE; uint8_t maskLen = 0; From 0a620a5f74400329c152727e8c91fe2a9d539947 Mon Sep 17 00:00:00 2001 From: mjmeans Date: Sat, 16 Nov 2024 23:44:07 -0700 Subject: [PATCH 11/32] Debug tracing for getInventory() --- PN5180ISO15693.cpp | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/PN5180ISO15693.cpp b/PN5180ISO15693.cpp index 24854f7..f6281ef 100644 --- a/PN5180ISO15693.cpp +++ b/PN5180ISO15693.cpp @@ -77,6 +77,10 @@ PN5180ISO15693::PN5180ISO15693(uint8_t SSpin, uint8_t BUSYpin, uint8_t RSTpin, S * */ ISO15693ErrorCode PN5180ISO15693::getInventory(uint8_t *uid) { + PN5180DEBUG_PRINTF("PN5180ISO15693::getInventory()"); + PN5180DEBUG_PRINTLN(); + PN5180DEBUG_ENTER; + uint8_t cmd = ISO15693_CMD_INVENTORY; // flags = 1 slot, only one card, no AFI field present, inventory flag + high data rate uint8_t flags = ISO15693_REQ_FLAG_NBSLOTS | ISO15693_REQ_FLAG_INVENTORY | ISO15693_REQ_FLAG_DATARATE; @@ -93,6 +97,9 @@ ISO15693ErrorCode PN5180ISO15693::getInventory(uint8_t *uid) { if (ISO15693_EC_OK != rc) { return rc; } + for (int i=0; i<8; i++) { + uid[i] = readBuffer[2+i]; + } PN5180DEBUG(F("Response flags: ")); PN5180DEBUG(formatHex(readBuffer[0])); @@ -100,16 +107,16 @@ ISO15693ErrorCode PN5180ISO15693::getInventory(uint8_t *uid) { PN5180DEBUG(formatHex(readBuffer[1])); PN5180DEBUG(F(", UID: ")); +#ifdef DEBUG for (int i=0; i<8; i++) { uid[i] = readBuffer[2+i]; -#ifdef DEBUG PN5180DEBUG(formatHex(uid[7-i])); // LSB comes first if (i<2) PN5180DEBUG(":"); -#endif } - PN5180DEBUG_PRINTLN(); +#endif + PN5180DEBUG_EXIT; return ISO15693_EC_OK; } From 174401070a1b190d2182b995b71dca169dff6cea Mon Sep 17 00:00:00 2001 From: mjmeans Date: Sat, 16 Nov 2024 23:45:03 -0700 Subject: [PATCH 12/32] This call too --- PN5180ISO15693.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/PN5180ISO15693.cpp b/PN5180ISO15693.cpp index f6281ef..e02e7e6 100644 --- a/PN5180ISO15693.cpp +++ b/PN5180ISO15693.cpp @@ -95,6 +95,7 @@ ISO15693ErrorCode PN5180ISO15693::getInventory(uint8_t *uid) { uint8_t *readBuffer; ISO15693ErrorCode rc = issueISO15693Command(inventory, sizeof(inventory), &readBuffer); if (ISO15693_EC_OK != rc) { + PN5180DEBUG(F("getInventory() failed at issueISO15693Command()")); return rc; } for (int i=0; i<8; i++) { From b88aea24f923da3069631cf5982a2352bd9fbe36 Mon Sep 17 00:00:00 2001 From: mjmeans Date: Sat, 16 Nov 2024 23:48:57 -0700 Subject: [PATCH 13/32] Show error results of calls without full debug --- PN5180ISO15693.cpp | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/PN5180ISO15693.cpp b/PN5180ISO15693.cpp index e02e7e6..e1db3bb 100644 --- a/PN5180ISO15693.cpp +++ b/PN5180ISO15693.cpp @@ -17,6 +17,7 @@ // Lesser General Public License for more details. // //#define DEBUG 1 +#define DEBUG_ERROR 1 #include #include "PN5180ISO15693.h" @@ -95,7 +96,8 @@ ISO15693ErrorCode PN5180ISO15693::getInventory(uint8_t *uid) { uint8_t *readBuffer; ISO15693ErrorCode rc = issueISO15693Command(inventory, sizeof(inventory), &readBuffer); if (ISO15693_EC_OK != rc) { - PN5180DEBUG(F("getInventory() failed at issueISO15693Command()")); + PN5180ERROR(F("getInventory() failed at issueISO15693Command()")); + PN5180DEBUG_EXIT; return rc; } for (int i=0; i<8; i++) { @@ -136,7 +138,13 @@ ISO15693ErrorCode PN5180ISO15693::getInventoryMultiple(uint8_t *uid, uint8_t max uint16_t collision[maxTags]; *numCard = 0; uint8_t numCol = 0; - inventoryPoll(uid, maxTags, numCard, &numCol, collision); + + if (ISO15693_EC_OK != inventoryPoll(uid, maxTags, numCard, &numCol, collision)) { + PN5180ERROR(F("getInventoryMultiple() failed at first inventoryPoll()")); + PN5180DEBUG_EXIT; + return ISO15693_EC_UNKNOWN_ERROR; + } + PN5180DEBUG_PRINTF("*** Number of collisions=%d", numCol); PN5180DEBUG_PRINTLN(); From 27fb8f38792fb4f07526e3e3d0050e037c638752 Mon Sep 17 00:00:00 2001 From: mjmeans Date: Sun, 17 Nov 2024 01:13:23 -0700 Subject: [PATCH 14/32] Add more error debug messages The bug is: Calling getInventoryMultiple() hangs and times out if there is only one NFC tag and that tag's UID ends in '0'. The library doesn't when calling getInventory() with the same tag. Still unable to see why this is happening. So expand the PN5180ERROR to show deeper calls. --- PN5180ISO15693.cpp | 74 +++++++++++++++++++++++++++++++++++++++------- 1 file changed, 63 insertions(+), 11 deletions(-) diff --git a/PN5180ISO15693.cpp b/PN5180ISO15693.cpp index e1db3bb..3eaaca2 100644 --- a/PN5180ISO15693.cpp +++ b/PN5180ISO15693.cpp @@ -154,12 +154,20 @@ ISO15693ErrorCode PN5180ISO15693::getInventoryMultiple(uint8_t *uid, uint8_t max PN5180DEBUG(formatHex(collision[0])); PN5180DEBUG_PRINTLN(); #endif - inventoryPoll(uid, maxTags, numCard, &numCol, collision); + + // inventoryPoll(uid, maxTags, numCard, &numCol, collision); + if (ISO15693_EC_OK != inventoryPoll(uid, maxTags, numCard, &numCol, collision)) { + PN5180ERROR(F("getInventoryMultiple() failed at collision resolution inventoryPoll()")); + PN5180DEBUG_EXIT; + return ISO15693_EC_UNKNOWN_ERROR; + } + numCol--; for(int i=0; i> 18) & 0x01 && *numCol < maxTags){ // 7+ Determine if a collision occurred if(maskLen > 0) collision[*numCol] = collision[0] | (slot << (maskLen * 4)); @@ -224,8 +251,7 @@ ISO15693ErrorCode PN5180ISO15693::inventoryPoll(uint8_t *uid, uint8_t maxTags, u uint8_t *readBuffer; readBuffer = readData(len+1); // 9. Read reception buffer if(0L == readBuffer){ - PN5180DEBUG(F("ERROR in readData!")); - PN5180DEBUG_PRINTLN(); + PN5180ERROR(F("inventoryPoll() failed at step 9. readBuffer() for slot %d"), slot); PN5180DEBUG_EXIT; return ISO15693_EC_UNKNOWN_ERROR; } @@ -254,13 +280,39 @@ ISO15693ErrorCode PN5180ISO15693::inventoryPoll(uint8_t *uid, uint8_t maxTags, u } if(slot+1 < 16){ // If we have more cards to poll for... - writeRegisterWithAndMask(TX_CONFIG, 0xFFFFFB3F); // 11. Next SEND_DATA will only include EOF - clearIRQStatus(0x000FFFFF); // 14. Clear all IRQ_STATUS flags - sendData(inventory, 0, 0); // 12. 13. 15. Idle/StopCom Command, Transceive Command, Send EOF + // writeRegisterWithAndMask(TX_CONFIG, 0xFFFFFB3F); // 11. Next SEND_DATA will only include EOF + if (!writeRegisterWithAndMask(TX_CONFIG, 0xFFFFFB3F)) { + PN5180ERROR(F("inventoryPoll() failed at step 11. writeRegisterWithAndMask() for slot %d"), slot); + PN5180DEBUG_EXIT; + return ISO15693_EC_UNKNOWN_ERROR; + } + // clearIRQStatus(0x000FFFFF); // 14. Clear all IRQ_STATUS flags + if (!clearIRQStatus(0x000FFFFF)) { + PN5180ERROR(F("inventoryPoll() failed at step 14. clearIRQStatus() for slot %d"), slot); + PN5180DEBUG_EXIT; + return ISO15693_EC_UNKNOWN_ERROR; + } + // sendData(inventory, 0, 0); // 12. 13. 15. Idle/StopCom Command, Transceive Command, Send EOF + if (!sendData(inventory, 0, 0)) { + PN5180ERROR(F("inventoryPoll() failed at step 12.13.15. clearIRQStatus() for slot %d"), slot); + PN5180DEBUG_EXIT; + return ISO15693_EC_UNKNOWN_ERROR; + } } } - setRF_off(); // 16. Switch off RF field - setupRF(); // 1. 2. Load ISO15693 config, RF on + // setRF_off(); // 16. Switch off RF field + if (!setRF_off()) { + PN5180ERROR(F("inventoryPoll() failed at step 16. setRF_off()")); + PN5180DEBUG_EXIT; + return ISO15693_EC_UNKNOWN_ERROR; + } + // setupRF(); // 1. 2. Load ISO15693 config, RF on + if (!setupRF()) { + PN5180ERROR(F("inventoryPoll() failed at step 1.2. setupRF()")); + PN5180DEBUG_EXIT; + return ISO15693_EC_UNKNOWN_ERROR; + } + PN5180DEBUG_EXIT; return ISO15693_EC_OK; } From 3113ec13332e6c3ae767c517c5e0a8406144c537 Mon Sep 17 00:00:00 2001 From: mjmeans Date: Sun, 17 Nov 2024 01:25:16 -0700 Subject: [PATCH 15/32] Add direct commands for SendData, RfOn and RfOff PN5180 Direct Commands These functions are the low level interface to the device: 1. Verify command's parameters 2. Prepare the transmission frame 3. Call transceiveCommand() to send the command 4. No state checking The comments for these direct commands are based on the PN5180A0XX_C3_C4.pdf data sheet. The original setRF_on(), setRF_off() and sendData() calls are the versions that do parameter and state checking before calling the direct commands. This will allow variations of the original calls with different state checking where necessary. --- Debug.cpp | 2 +- PN5180.cpp | 175 ++++++++++++++++++++++++++++++++++++++++++++++++----- PN5180.h | 25 +++++++- 3 files changed, 183 insertions(+), 19 deletions(-) diff --git a/Debug.cpp b/Debug.cpp index 72de30a..b0855bd 100644 --- a/Debug.cpp +++ b/Debug.cpp @@ -16,7 +16,7 @@ // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU // Lesser General Public License for more details. // -//#define DEBUG 1 +#define DEBUG 1 #include #include "Debug.h" diff --git a/PN5180.cpp b/PN5180.cpp index 12bbf37..dee1a2d 100644 --- a/PN5180.cpp +++ b/PN5180.cpp @@ -17,6 +17,7 @@ // Lesser General Public License for more details. // //#define DEBUG 1 +#define DEBUG_ERROR 1 #include #include "PN5180.h" @@ -325,6 +326,7 @@ bool PN5180::sendData(const uint8_t *data, int len, uint8_t validBits) { PN5180DEBUG_PRINTF(F("PN5180::sendData(*data, len=%d, validBits=%d)"), len, validBits); PN5180DEBUG_PRINTLN(); PN5180DEBUG_ENTER; + if (len > 260) { PN5180DEBUG_PRINTLN(F("ERROR: sendData with more than 260 bytes is not supported!")); PN5180DEBUG_EXIT; @@ -342,15 +344,27 @@ bool PN5180::sendData(const uint8_t *data, int len, uint8_t validBits) { PN5180DEBUG_PRINTLN(); #endif - uint8_t buffer[len+2]; - buffer[0] = PN5180_SEND_DATA; - buffer[1] = validBits; // number of valid bits of last byte are transmitted (0 = all bits are transmitted) - for (int i=0; i Date: Sun, 17 Nov 2024 01:30:10 -0700 Subject: [PATCH 16/32] Debug errors using PN5180ERROR instead --- PN5180ISO14443.cpp | 40 ++++++++++++++++++++++++++-------------- 1 file changed, 26 insertions(+), 14 deletions(-) diff --git a/PN5180ISO14443.cpp b/PN5180ISO14443.cpp index 340653b..3c4c4e2 100644 --- a/PN5180ISO14443.cpp +++ b/PN5180ISO14443.cpp @@ -17,6 +17,7 @@ // Lesser General Public License for more details. // //#define DEBUG 1 +#define DEBUG_ERROR 1 #include #include "PN5180ISO14443.h" @@ -95,7 +96,7 @@ int8_t PN5180ISO14443::activateTypeA(uint8_t *buffer, uint8_t kind) { // Load standard TypeA protocol already done in reset() if (!loadRFConfig(0x0, 0x80)) { - PN5180DEBUG_PRINTLN(F("*** ERROR: Load standard TypeA protocol failed!")); + PN5180ERROR(F("Load standard TypeA protocol failed!")); PN5180DEBUG_EXIT; return -1; } @@ -107,33 +108,33 @@ int8_t PN5180ISO14443::activateTypeA(uint8_t *buffer, uint8_t kind) { // OFF Crypto if (!writeRegisterWithAndMask(SYSTEM_CONFIG, 0xFFFFFFBF)) { - PN5180DEBUG_PRINTLN(F("*** ERROR: OFF Crypto failed!")); + PN5180ERROR(F("OFF Crypto failed!")); PN5180DEBUG_EXIT; return -1; } // clear RX CRC if (!writeRegisterWithAndMask(CRC_RX_CONFIG, 0xFFFFFFFE)) { - PN5180DEBUG_PRINTLN(F("*** ERROR: Clear RX CRC failed!")); + PN5180ERROR(F("Clear RX CRC failed!")); PN5180DEBUG_EXIT; return -1; } // clear TX CRC if (!writeRegisterWithAndMask(CRC_TX_CONFIG, 0xFFFFFFFE)) { - PN5180DEBUG_PRINTLN(F("*** ERROR: Clear TX CRC failed!")); + PN5180ERROR(F("Clear TX CRC failed!")); PN5180DEBUG_EXIT; return -1; } // set the PN5180 into IDLE state if (!writeRegisterWithAndMask(SYSTEM_CONFIG, 0xFFFFFFF8)) { - PN5180DEBUG_PRINTLN(F("*** ERROR: set IDLE state failed!")); + PN5180ERROR(F("Set IDLE state failed!")); PN5180DEBUG_EXIT; return -1; } // activate TRANSCEIVE routine if (!writeRegisterWithOrMask(SYSTEM_CONFIG, 0x00000003)) { - PN5180DEBUG_PRINTLN(F("*** ERROR: Activates TRANSCEIVE routine failed!")); + PN5180ERROR(F("Activate TRANSCEIVE routine failed!")); PN5180DEBUG_EXIT; return -1; } @@ -141,7 +142,7 @@ int8_t PN5180ISO14443::activateTypeA(uint8_t *buffer, uint8_t kind) { // wait for wait-transmit state PN5180TransceiveStat transceiveState = getTransceiveState(); if (PN5180_TS_WaitTransmit != transceiveState) { - PN5180DEBUG_PRINTLN(F("*** ERROR: Transceiver not in state WaitTransmit!?")); + PN5180ERROR(F("Transceiver not in state WaitTransmit!?")); PN5180DEBUG_EXIT; return -1; } @@ -158,7 +159,7 @@ int8_t PN5180ISO14443::activateTypeA(uint8_t *buffer, uint8_t kind) { //Send REQA/WUPA, 7 bits in last byte cmd[0] = (kind == 0) ? 0x26 : 0x52; if (!sendData(cmd, 1, 0x07)) { - PN5180DEBUG_PRINTLN(F("*** ERROR: Send REQA/WUPA failed!")); + PN5180ERROR(F("Send REQA/WUPA failed!")); PN5180DEBUG_EXIT; return 0; } @@ -168,7 +169,7 @@ int8_t PN5180ISO14443::activateTypeA(uint8_t *buffer, uint8_t kind) { // READ 2 bytes ATQA into buffer if (!readData(2, buffer)) { - PN5180DEBUG(F("*** ERROR: READ 2 bytes ATQA failed!\n")); + PN5180ERROR(F("READ 2 bytes ATQA failed!\n")); PN5180DEBUG_EXIT; return 0; } @@ -180,10 +181,10 @@ int8_t PN5180ISO14443::activateTypeA(uint8_t *buffer, uint8_t kind) { while (PN5180_TS_WaitTransmit != getTransceiveState()) { if (millis() - startedWaiting > 200) { PN5180DEBUG_ON; - PN5180DEBUG_PRINTLN(F("*** ERROR: timeout in PN5180_TS_WaitTransmit!")); + PN5180ERROR(F("Timeout in PN5180_TS_WaitTransmit!")); PN5180DEBUG_EXIT; return -1; - } + } } PN5180DEBUG_ON; @@ -194,7 +195,7 @@ int8_t PN5180ISO14443::activateTypeA(uint8_t *buffer, uint8_t kind) { cmd[0] = 0x93; cmd[1] = 0x20; if (!sendData(cmd, 2, 0x00)) { - PN5180DEBUG_PRINTLN(F("*** ERROR: Send Anti collision 1 failed!")); + PN5180ERROR(F("Send Anti collision 1 failed!")); PN5180DEBUG_EXIT; return -2; } @@ -204,13 +205,13 @@ int8_t PN5180ISO14443::activateTypeA(uint8_t *buffer, uint8_t kind) { uint8_t numBytes = rxBytesReceived(); if (numBytes != 5) { - PN5180DEBUG_PRINTLN(F("*** ERROR: Read 5 bytes sak failed!")); + PN5180ERROR(F("Read 5 bytes sak failed!")); PN5180DEBUG_EXIT; return -2; }; // read 5 bytes sak, we will store at offset 2 for later usage if (!readData(5, cmd+2)) { - Serial.println("Read 5 bytes failed!"); + PN5180ERROR("Read 5 bytes failed!"); PN5180DEBUG_EXIT; return -2; } @@ -220,11 +221,13 @@ int8_t PN5180ISO14443::activateTypeA(uint8_t *buffer, uint8_t kind) { //Enable RX CRC calculation if (!writeRegisterWithOrMask(CRC_RX_CONFIG, 0x01)) { + PN5180ERROR("Enable RX CRC failed!"); PN5180DEBUG_EXIT; return -2; } //Enable TX CRC calculation if (!writeRegisterWithOrMask(CRC_TX_CONFIG, 0x01)) { + PN5180ERROR("Enable TX CRC failed!"); PN5180DEBUG_EXIT; return -2; } @@ -239,6 +242,7 @@ int8_t PN5180ISO14443::activateTypeA(uint8_t *buffer, uint8_t kind) { } //Read 1 byte SAK into buffer[2] if (!readData(1, buffer+2)) { + PN5180ERROR("Read 1 byte SAK into buffer failed!"); PN5180DEBUG_EXIT; return -2; } @@ -258,11 +262,13 @@ int8_t PN5180ISO14443::activateTypeA(uint8_t *buffer, uint8_t kind) { for (int i = 0; i < 3; i++) buffer[3+i] = cmd[3 + i]; // Clear RX CRC if (!writeRegisterWithAndMask(CRC_RX_CONFIG, 0xFFFFFFFE)) { + PN5180ERROR(F("Clear RX CRC Failed!")); PN5180DEBUG_EXIT; return -2; } // Clear TX CRC if (!writeRegisterWithAndMask(CRC_TX_CONFIG, 0xFFFFFFFE)) { + PN5180ERROR(F("Clear TX CRC Failed!")); PN5180DEBUG_EXIT; return -2; } @@ -270,11 +276,13 @@ int8_t PN5180ISO14443::activateTypeA(uint8_t *buffer, uint8_t kind) { cmd[0] = 0x95; cmd[1] = 0x20; if (!sendData(cmd, 2, 0x00)) { + PN5180ERROR(F("Do anti collision 2 Failed!")); PN5180DEBUG_EXIT; return -2; } //Read 5 bytes. we will store at offset 2 for later use if (!readData(5, cmd+2)) { + PN5180ERROR(F("Read 5 bytes Failed!")); PN5180DEBUG_EXIT; return -2; } @@ -284,11 +292,13 @@ int8_t PN5180ISO14443::activateTypeA(uint8_t *buffer, uint8_t kind) { } //Enable RX CRC calculation if (!writeRegisterWithOrMask(CRC_RX_CONFIG, 0x01)) { + PN5180ERROR(F("Enable RX CRC calculation Failed!")); PN5180DEBUG_EXIT; return -2; } //Enable TX CRC calculation if (!writeRegisterWithOrMask(CRC_TX_CONFIG, 0x01)) { + PN5180ERROR(F("Enable TX CRC calculation Failed!")); PN5180DEBUG_EXIT; return -2; } @@ -296,11 +306,13 @@ int8_t PN5180ISO14443::activateTypeA(uint8_t *buffer, uint8_t kind) { cmd[0] = 0x95; cmd[1] = 0x70; if (!sendData(cmd, 7, 0x00)) { + PN5180ERROR(F("Send Select anti collision 2 Failed!")); PN5180DEBUG_EXIT; return -2; } //Read 1 byte SAK into buffer[2] if (!readData(1, buffer + 2)) { + PN5180ERROR(F("Read 1 byte SAK into buffer[2] Failed!")); PN5180DEBUG_EXIT; return -2; } From b8c5ee5f51948384ac4e3c2ed22e8da4955005d2 Mon Sep 17 00:00:00 2001 From: mjmeans Date: Sun, 17 Nov 2024 02:25:43 -0700 Subject: [PATCH 17/32] Report error returns on most other library calls --- PN5180.cpp | 138 ++++++++++++++++++++++++++++++++++++++++------------- 1 file changed, 106 insertions(+), 32 deletions(-) diff --git a/PN5180.cpp b/PN5180.cpp index dee1a2d..1c4c332 100644 --- a/PN5180.cpp +++ b/PN5180.cpp @@ -152,8 +152,13 @@ bool PN5180::writeRegister(uint8_t reg, uint32_t value) { */ uint8_t cmd[] = { PN5180_WRITE_REGISTER, reg, p[0], p[1], p[2], p[3] }; - transceiveCommand(cmd, sizeof(cmd)); - + // transceiveCommand(cmd, sizeof(cmd)); + if (!transceiveCommand(cmd, sizeof(cmd))) { + PN5180ERROR(F("writeRegister() failed at transceiveCommand()")); + PN5180DEBUG_EXIT; + return false; + } + PN5180DEBUG_EXIT; return true; } @@ -184,7 +189,12 @@ bool PN5180::writeRegisterWithOrMask(uint8_t reg, uint32_t mask) { uint8_t cmd[] = { PN5180_WRITE_REGISTER_OR_MASK, reg, p[0], p[1], p[2], p[3] }; - transceiveCommand(cmd, sizeof(cmd)); + // transceiveCommand(cmd, sizeof(cmd)); + if (!transceiveCommand(cmd, sizeof(cmd))) { + PN5180ERROR(F("writeRegisterWithOrMask() failed at transceiveCommand()")); + PN5180DEBUG_EXIT; + return false; + } PN5180DEBUG_EXIT; return true; @@ -216,7 +226,12 @@ bool PN5180::writeRegisterWithAndMask(uint8_t reg, uint32_t mask) { uint8_t cmd[] = { PN5180_WRITE_REGISTER_AND_MASK, reg, p[0], p[1], p[2], p[3] }; - transceiveCommand(cmd, sizeof(cmd)); + // transceiveCommand(cmd, sizeof(cmd)); + if (!transceiveCommand(cmd, sizeof(cmd))) { + PN5180ERROR(F("writeRegisterWithAndMask() failed at transceiveCommand()")); + PN5180DEBUG_EXIT; + return false; + } PN5180DEBUG_EXIT; return true; @@ -236,7 +251,12 @@ bool PN5180::readRegister(uint8_t reg, uint32_t *value) { uint8_t cmd[] = { PN5180_READ_REGISTER, reg }; - transceiveCommand(cmd, sizeof(cmd), (uint8_t*)value, 4); + // transceiveCommand(cmd, sizeof(cmd), (uint8_t*)value, 4); + if (!transceiveCommand(cmd, sizeof(cmd), (uint8_t*)value, 4)) { + PN5180ERROR(F("readRegister() failed at transceiveCommand()")); + PN5180DEBUG_EXIT; + return false; + } PN5180DEBUG(F("Register value=0x")); PN5180DEBUG(formatHex(*value)); @@ -253,11 +273,19 @@ bool PN5180::writeEEprom(uint8_t addr, const uint8_t *buffer, uint8_t len) { PN5180DEBUG_PRINTF(F("PN5180::writeEEprom(addr=%s, *buffer, len=%d)"), formatHex(addr), len); PN5180DEBUG_PRINTLN(); PN5180DEBUG_ENTER; + uint8_t cmd[len + 2]; cmd[0] = PN5180_WRITE_EEPROM; cmd[1] = addr; for (int i = 0; i < len; i++) cmd[2 + i] = buffer[i]; - transceiveCommand(cmd, len + 2); + + // transceiveCommand(cmd, len + 2); + if (transceiveCommand(cmd, len + 2)) { + PN5180ERROR(F("writeEEprom() failed at transceiveCommand()")); + PN5180DEBUG_EXIT; + return false; + } + PN5180DEBUG_EXIT; return true; } @@ -291,7 +319,12 @@ bool PN5180::readEEprom(uint8_t addr, uint8_t *buffer, int len) { uint8_t cmd[] = { PN5180_READ_EEPROM, addr, uint8_t(len) }; - transceiveCommand(cmd, sizeof(cmd), buffer, len); + // transceiveCommand(cmd, sizeof(cmd), buffer, len); + if (transceiveCommand(cmd, sizeof(cmd), buffer, len)) { + PN5180ERROR(F("readEEprom() failed at transceiveCommand()")); + PN5180DEBUG_EXIT; + return false; + } #ifdef DEBUG PN5180DEBUG(F("EEPROM values: ")); @@ -306,7 +339,6 @@ bool PN5180::readEEprom(uint8_t addr, uint8_t *buffer, int len) { return true; } - /* * SEND_DATA - 0x09 * This command writes data to the RF transmission buffer and starts the RF transmission. @@ -350,7 +382,6 @@ bool PN5180::sendData(const uint8_t *data, int len, uint8_t validBits) { //for (int i=0; i 508) { - Serial.println(F("*** FATAL: Reading more than 508 bytes is not supported!")); + PN5180ERROR(F("readData() failed: Reading more than 508 bytes is not supported!")); PN5180DEBUG_EXIT; return 0L; } @@ -428,14 +459,20 @@ uint8_t * PN5180::readData(int len) { if (!readBufferDynamic508) { readBufferDynamic508 = (uint8_t *) malloc(508); if (!readBufferDynamic508) { - PN5180DEBUG(F("Cannot allocate the read buffer of 508 Bytes!")); + PN5180ERROR(F("readData() failed: Cannot allocate the read buffer of 508 Bytes!")); PN5180DEBUG_EXIT; return 0; } } readBuffer = readBufferDynamic508; } - transceiveCommand(cmd, sizeof(cmd), readBuffer, len); + + // transceiveCommand(cmd, sizeof(cmd), readBuffer, len); + if (transceiveCommand(cmd, sizeof(cmd), readBuffer, len)) { + PN5180ERROR(F("readData() failed at transceiveCommand()")); + PN5180DEBUG_EXIT; + return 0; + } #ifdef DEBUG PN5180DEBUG(F("Data read: ")); @@ -460,9 +497,16 @@ bool PN5180::readData(int len, uint8_t *buffer) { return false; } uint8_t cmd[] = { PN5180_READ_DATA, 0x00 }; - bool ret = transceiveCommand(cmd, sizeof(cmd), buffer, len); + + //bool ret = transceiveCommand(cmd, sizeof(cmd), buffer, len); + if (transceiveCommand(cmd, sizeof(cmd), buffer, len)) { + PN5180ERROR(F("readData() failed at transceiveCommand()")); + PN5180DEBUG_EXIT; + return false; + } + PN5180DEBUG_EXIT; - return ret; + return true; } /* prepare LPCD registers (Low Power Card Detection) */ @@ -544,7 +588,7 @@ bool PN5180::switchToLPCD(uint16_t wakeupCounterInMs) { */ int16_t PN5180::mifareAuthenticate(uint8_t blockNo, const uint8_t *key, uint8_t keyType, const uint8_t *uid) { if (keyType != 0x60 && keyType != 0x61){ - PN5180DEBUG_PRINTLN(F("*** ERROR: invalid key type supplied!")); + PN5180ERROR(F("invalid key type supplied!")); return -2; } @@ -563,7 +607,7 @@ int16_t PN5180::mifareAuthenticate(uint8_t blockNo, const uint8_t *key, uint8_t bool retval = transceiveCommand(cmdBuffer, 13, rcvBuffer, 1); if (!retval){ - PN5180DEBUG_PRINTLN(F("*** ERROR: sending command failed!")); + PN5180ERROR(F("sending command failed!")); return -3; } @@ -599,7 +643,12 @@ bool PN5180::loadRFConfig(uint8_t txConf, uint8_t rxConf) { uint8_t cmd[] = { PN5180_LOAD_RF_CONFIG, txConf, rxConf }; - transceiveCommand(cmd, sizeof(cmd)); + // transceiveCommand(cmd, sizeof(cmd)); + if (transceiveCommand(cmd, sizeof(cmd))) { + PN5180ERROR(F("loadRFConfig() failed at transceiveCommand()")); + PN5180DEBUG_EXIT; + return false; + } PN5180DEBUG_EXIT; return true; @@ -629,14 +678,20 @@ bool PN5180::setRF_on() { while (0 == (TX_RFON_IRQ_STAT & getIRQStatus())) { // wait for RF field to set up (max 500ms) if (millis() - startedWaiting > 500) { PN5180DEBUG_ON; - PN5180DEBUG_PRINTLN(F("*** ERROR: Set RF ON timeout")); + PN5180ERROR(F("setRF_on failed - Set RF ON timeout")); PN5180DEBUG_EXIT; - return false; + return false; } }; PN5180DEBUG_ON; - clearIRQStatus(TX_RFON_IRQ_STAT); + // clearIRQStatus(TX_RFON_IRQ_STAT); + if (clearIRQStatus(TX_RFON_IRQ_STAT)) { + PN5180ERROR(F("setRF_on() failed at clearIRQStatus()")); + PN5180DEBUG_EXIT; + return false; + } + PN5180DEBUG_EXIT; return true; } @@ -664,14 +719,20 @@ bool PN5180::setRF_off() { while (0 == (TX_RFOFF_IRQ_STAT & getIRQStatus())) { // wait for RF field to shut down if (millis() - startedWaiting > 500) { PN5180DEBUG_ON; - PN5180DEBUG_PRINTLN(F("*** ERROR: Set RF OFF timeout")); + PN5180ERROR(F("setRF_off() failed - Set RF OFF timeout")); PN5180DEBUG_EXIT; return false; } }; PN5180DEBUG_ON; - clearIRQStatus(TX_RFOFF_IRQ_STAT); + /// clearIRQStatus(TX_RFOFF_IRQ_STAT); + if (clearIRQStatus(TX_RFOFF_IRQ_STAT)) { + PN5180ERROR(F("setRF_off() failed at clearIRQStatus()")); + PN5180DEBUG_EXIT; + return false; + } + PN5180DEBUG_EXIT; return true; } @@ -718,6 +779,7 @@ bool PN5180::transceiveCommand(uint8_t *sendBuffer, size_t sendBufferLen, uint8_ PN5180DEBUG_PRINTF(F("PN5180::transceiveCommand(*sendBuffer, sendBufferLen=%d, *recvBuffer, recvBufferLen=%d)"), sendBufferLen, recvBufferLen); PN5180DEBUG_PRINTLN(); PN5180DEBUG_ENTER; + PN5180_SPI.beginTransaction(SPI_SETTINGS); #ifdef DEBUG PN5180DEBUG(F("Sending SPI frame: '")); @@ -732,7 +794,7 @@ bool PN5180::transceiveCommand(uint8_t *sendBuffer, size_t sendBufferLen, uint8_ unsigned long startedWaiting = millis(); while (LOW != digitalRead(PN5180_BUSY)) { if (millis() - startedWaiting > commandTimeout) { - PN5180DEBUG("*** ERROR: transceiveCommand timeout (send/0)"); + PN5180ERROR("transceiveCommand timeout (send/0)"); PN5180_SPI.endTransaction(); digitalWrite(PN5180_NSS, HIGH); PN5180DEBUG_EXIT; @@ -747,7 +809,7 @@ bool PN5180::transceiveCommand(uint8_t *sendBuffer, size_t sendBufferLen, uint8_ startedWaiting = millis(); while (HIGH != digitalRead(PN5180_BUSY)) { if (millis() - startedWaiting > commandTimeout) { - PN5180DEBUG("*** ERROR: transceiveCommand timeout (send/3)"); + PN5180ERROR("transceiveCommand timeout (send/3)"); PN5180_SPI.endTransaction(); digitalWrite(PN5180_NSS, HIGH); PN5180DEBUG_EXIT; @@ -760,7 +822,7 @@ bool PN5180::transceiveCommand(uint8_t *sendBuffer, size_t sendBufferLen, uint8_ startedWaiting = millis(); while (LOW != digitalRead(PN5180_BUSY)) { if (millis() - startedWaiting > commandTimeout) { - PN5180DEBUG("*** ERROR: transceiveCommand timeout (send/5)"); + PN5180ERROR("transceiveCommand timeout (send/5)"); PN5180_SPI.endTransaction(); digitalWrite(PN5180_NSS, HIGH); PN5180DEBUG_EXIT; @@ -786,7 +848,7 @@ bool PN5180::transceiveCommand(uint8_t *sendBuffer, size_t sendBufferLen, uint8_ startedWaiting = millis(); //delay(1); while (HIGH != digitalRead(PN5180_BUSY)) { if (millis() - startedWaiting > commandTimeout) { - PN5180DEBUG("*** ERROR: transceiveCommand timeout (receive/3)"); + PN5180ERROR("transceiveCommand timeout (receive/3)"); PN5180_SPI.endTransaction(); digitalWrite(PN5180_NSS, HIGH); PN5180DEBUG_EXIT; @@ -799,7 +861,7 @@ bool PN5180::transceiveCommand(uint8_t *sendBuffer, size_t sendBufferLen, uint8_ startedWaiting = millis(); while (LOW != digitalRead(PN5180_BUSY)) { if (millis() - startedWaiting > commandTimeout) { - PN5180DEBUG("*** ERROR: transceiveCommand timeout (receive/5)"); + PN5180ERROR("PN5180ERRORtransceiveCommand timeout (receive/5)"); PN5180_SPI.endTransaction(); digitalWrite(PN5180_NSS, HIGH); PN5180DEBUG_EXIT; @@ -838,7 +900,7 @@ void PN5180::reset() { while (0 == (IDLE_IRQ_STAT & getIRQStatus())) { // wait for system to start up (with timeout) if (millis() - startedWaiting > commandTimeout) { PN5180DEBUG_ON; - PN5180DEBUG_PRINTLN(F("*** ERROR: reset failed (timeout)!!!")); + PN5180ERROR(F("reset failed (timeout)!!!")); // try again with larger time digitalWrite(PN5180_RST, LOW); delay(10); @@ -862,7 +924,13 @@ uint32_t PN5180::getIRQStatus() { PN5180DEBUG_PRINTLN(F("Read IRQ-Status register...")); uint32_t irqStatus; - readRegister(IRQ_STATUS, &irqStatus); + + // readRegister(IRQ_STATUS, &irqStatus); + if (readRegister(IRQ_STATUS, &irqStatus)) { + PN5180ERROR(F("getIRQStatus() failed at readRegister()")); + PN5180DEBUG_EXIT; + return false; + } PN5180DEBUG(F("IRQ-Status=0x")); PN5180DEBUG(formatHex(irqStatus)); @@ -878,10 +946,16 @@ bool PN5180::clearIRQStatus(uint32_t irqMask) { PN5180DEBUG_ENTER; PN5180DEBUG_PRINTLN(F("Clear IRQ-Status with mask")); - bool ret = writeRegister(IRQ_CLEAR, irqMask); + + //bool ret = writeRegister(IRQ_CLEAR, irqMask); + if (writeRegister(IRQ_CLEAR, irqMask)) { + PN5180ERROR(F("clearIRQStatus() failed at writeRegister()")); + PN5180DEBUG_EXIT; + return false; + } PN5180DEBUG_EXIT; - return ret; + return true; } /* @@ -904,7 +978,7 @@ PN5180TransceiveStat PN5180::getTransceiveState() { #ifdef DEBUG showIRQStatus(getIRQStatus()); #endif - PN5180DEBUG_PRINTLN(F("ERROR reading RF_STATUS register.")); + PN5180ERROR(F("getTransceiveState() failed reading RF_STATUS register.")); ret = PN5180TransceiveStat(0); PN5180DEBUG_EXIT; return ret; From 7b833050e5874e87c88e819497a98edd09a84a2b Mon Sep 17 00:00:00 2001 From: mjmeans Date: Sun, 17 Nov 2024 02:33:13 -0700 Subject: [PATCH 18/32] More comment detail for getInventory* --- PN5180ISO15693.cpp | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/PN5180ISO15693.cpp b/PN5180ISO15693.cpp index 3eaaca2..5b3809f 100644 --- a/PN5180ISO15693.cpp +++ b/PN5180ISO15693.cpp @@ -73,9 +73,13 @@ PN5180ISO15693::PN5180ISO15693(uint8_t SSpin, uint8_t BUSYpin, uint8_t RSTpin, S /* * Inventory, code=01 * + * Inventory with flag for 16 time slots, code=01 + * https://www.nxp.com.cn/docs/en/application-note/AN12650.pdf * Request format: SOF, Req.Flags, Inventory, AFI (opt.), Mask len, Mask value, CRC16, EOF + * | | \_ Mask Length (defined by ISO 15693) + * | \_ 0x01: Inventory command (defined by ISO 15693) + * \_ 0x26: 0x02 high data rate | 0x04 inventory flags | 0x20 1 time slot (defined by ISO 15693) * Response format: SOF, Resp.Flags, DSFID, UID, CRC16, EOF - * */ ISO15693ErrorCode PN5180ISO15693::getInventory(uint8_t *uid) { PN5180DEBUG_PRINTF("PN5180ISO15693::getInventory()"); @@ -127,8 +131,10 @@ ISO15693ErrorCode PN5180ISO15693::getInventory(uint8_t *uid) { * Inventory with flag set for 16 time slots, code=01 * https://www.nxp.com.cn/docs/en/application-note/AN12650.pdf * Request format: SOF, Req.Flags, Inventory, AFI (opt.), Mask len, Mask value, CRC16, EOF + * | | \- ? Mask Length (defined by ISO 15693) + * | \- 0x01: Inventory command (defined by ISO 15693) + * \- 0x26: 0x02 high data rate | 0x04 inventory flags | !(0x20) 16 time slots (defined by ISO 15693) * Response format: SOF, Resp.Flags, DSFID, UID, CRC16, EOF - * */ ISO15693ErrorCode PN5180ISO15693::getInventoryMultiple(uint8_t *uid, uint8_t maxTags, uint8_t *numCard) { PN5180DEBUG_PRINTF("PN5180ISO15693::getInventoryMultiple(maxTags=%d, numCard=%d)", maxTags, *numCard); From b09a07dd0d2305729e4383981dbb660a5f549e84 Mon Sep 17 00:00:00 2001 From: mjmeans Date: Sun, 17 Nov 2024 02:48:55 -0700 Subject: [PATCH 19/32] A few more PN5180ERRORs --- PN5180.cpp | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/PN5180.cpp b/PN5180.cpp index 1c4c332..f31e6f1 100644 --- a/PN5180.cpp +++ b/PN5180.cpp @@ -305,8 +305,9 @@ bool PN5180::readEEprom(uint8_t addr, uint8_t *buffer, int len) { PN5180DEBUG_PRINTF(F("PN5180::readEEprom(addr=%s, *buffer, len=%d)"), formatHex(addr), len); PN5180DEBUG_PRINTLN(); PN5180DEBUG_ENTER; + if ((addr > 254) || ((addr+len) > 254)) { - PN5180DEBUG_PRINTLN(F("ERROR: Reading beyond addr 254!")); + PN5180ERROR(F("ERROR: Reading beyond addr 254!")); PN5180DEBUG_EXIT; return false; } @@ -360,7 +361,7 @@ bool PN5180::sendData(const uint8_t *data, int len, uint8_t validBits) { PN5180DEBUG_ENTER; if (len > 260) { - PN5180DEBUG_PRINTLN(F("ERROR: sendData with more than 260 bytes is not supported!")); + PN5180ERROR(F("sendData with more than 260 bytes is not supported!")); PN5180DEBUG_EXIT; return false; } @@ -861,7 +862,7 @@ bool PN5180::transceiveCommand(uint8_t *sendBuffer, size_t sendBufferLen, uint8_ startedWaiting = millis(); while (LOW != digitalRead(PN5180_BUSY)) { if (millis() - startedWaiting > commandTimeout) { - PN5180ERROR("PN5180ERRORtransceiveCommand timeout (receive/5)"); + PN5180ERROR("transceiveCommand timeout (receive/5)"); PN5180_SPI.endTransaction(); digitalWrite(PN5180_NSS, HIGH); PN5180DEBUG_EXIT; From 65769a6e23cdc72a7d12639eb7e4e7ef7bd365b9 Mon Sep 17 00:00:00 2001 From: mjmeans Date: Sun, 17 Nov 2024 03:12:37 -0700 Subject: [PATCH 20/32] More PN5180ERROR detail --- PN5180.cpp | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/PN5180.cpp b/PN5180.cpp index f31e6f1..262c5c4 100644 --- a/PN5180.cpp +++ b/PN5180.cpp @@ -307,7 +307,7 @@ bool PN5180::readEEprom(uint8_t addr, uint8_t *buffer, int len) { PN5180DEBUG_ENTER; if ((addr > 254) || ((addr+len) > 254)) { - PN5180ERROR(F("ERROR: Reading beyond addr 254!")); + PN5180ERROR(F("readEEprom() failed: Reading beyond addr 254!")); PN5180DEBUG_EXIT; return false; } @@ -361,7 +361,7 @@ bool PN5180::sendData(const uint8_t *data, int len, uint8_t validBits) { PN5180DEBUG_ENTER; if (len > 260) { - PN5180ERROR(F("sendData with more than 260 bytes is not supported!")); + PN5180ERROR(F("sendData() failed: more than 260 bytes is not supported!")); PN5180DEBUG_EXIT; return false; } @@ -408,7 +408,7 @@ bool PN5180::sendData(const uint8_t *data, int len, uint8_t validBits) { PN5180TransceiveStat transceiveState = getTransceiveState(); if (PN5180_TS_WaitTransmit != transceiveState) { - PN5180ERROR(F("sendData() failed - Transceiver not in state WaitTransmit!?")); + PN5180ERROR(F("sendData() failed: Transceiver not in state WaitTransmit!?")); PN5180DEBUG_EXIT; return false; } @@ -679,7 +679,7 @@ bool PN5180::setRF_on() { while (0 == (TX_RFON_IRQ_STAT & getIRQStatus())) { // wait for RF field to set up (max 500ms) if (millis() - startedWaiting > 500) { PN5180DEBUG_ON; - PN5180ERROR(F("setRF_on failed - Set RF ON timeout")); + PN5180ERROR(F("setRF_on() timeout waiting for TX_RFON_IRQ_STAT")); PN5180DEBUG_EXIT; return false; } @@ -720,7 +720,7 @@ bool PN5180::setRF_off() { while (0 == (TX_RFOFF_IRQ_STAT & getIRQStatus())) { // wait for RF field to shut down if (millis() - startedWaiting > 500) { PN5180DEBUG_ON; - PN5180ERROR(F("setRF_off() failed - Set RF OFF timeout")); + PN5180ERROR(F("setRF_off() timeout waiting for TX_RFOFF_IRQ_STAT")); PN5180DEBUG_EXIT; return false; } @@ -795,7 +795,7 @@ bool PN5180::transceiveCommand(uint8_t *sendBuffer, size_t sendBufferLen, uint8_ unsigned long startedWaiting = millis(); while (LOW != digitalRead(PN5180_BUSY)) { if (millis() - startedWaiting > commandTimeout) { - PN5180ERROR("transceiveCommand timeout (send/0)"); + PN5180ERROR("transceiveCommand() timeout waiting for BUSY=LOW (send/0)"); PN5180_SPI.endTransaction(); digitalWrite(PN5180_NSS, HIGH); PN5180DEBUG_EXIT; @@ -810,7 +810,7 @@ bool PN5180::transceiveCommand(uint8_t *sendBuffer, size_t sendBufferLen, uint8_ startedWaiting = millis(); while (HIGH != digitalRead(PN5180_BUSY)) { if (millis() - startedWaiting > commandTimeout) { - PN5180ERROR("transceiveCommand timeout (send/3)"); + PN5180ERROR("transceiveCommand() timeout waiting for BUSY=HIGH (send/3)"); PN5180_SPI.endTransaction(); digitalWrite(PN5180_NSS, HIGH); PN5180DEBUG_EXIT; @@ -823,7 +823,7 @@ bool PN5180::transceiveCommand(uint8_t *sendBuffer, size_t sendBufferLen, uint8_ startedWaiting = millis(); while (LOW != digitalRead(PN5180_BUSY)) { if (millis() - startedWaiting > commandTimeout) { - PN5180ERROR("transceiveCommand timeout (send/5)"); + PN5180ERROR("transceiveCommand() timeout waiting for BUSY=LOW (send/5)"); PN5180_SPI.endTransaction(); digitalWrite(PN5180_NSS, HIGH); PN5180DEBUG_EXIT; @@ -849,7 +849,7 @@ bool PN5180::transceiveCommand(uint8_t *sendBuffer, size_t sendBufferLen, uint8_ startedWaiting = millis(); //delay(1); while (HIGH != digitalRead(PN5180_BUSY)) { if (millis() - startedWaiting > commandTimeout) { - PN5180ERROR("transceiveCommand timeout (receive/3)"); + PN5180ERROR("transceiveCommand() timeout waiting for BUSY=HIGH (receive/3)"); PN5180_SPI.endTransaction(); digitalWrite(PN5180_NSS, HIGH); PN5180DEBUG_EXIT; @@ -862,7 +862,7 @@ bool PN5180::transceiveCommand(uint8_t *sendBuffer, size_t sendBufferLen, uint8_ startedWaiting = millis(); while (LOW != digitalRead(PN5180_BUSY)) { if (millis() - startedWaiting > commandTimeout) { - PN5180ERROR("transceiveCommand timeout (receive/5)"); + PN5180ERROR("transceiveCommand() timeout waiting for BUSY=LOW (receive/5)"); PN5180_SPI.endTransaction(); digitalWrite(PN5180_NSS, HIGH); PN5180DEBUG_EXIT; @@ -901,7 +901,7 @@ void PN5180::reset() { while (0 == (IDLE_IRQ_STAT & getIRQStatus())) { // wait for system to start up (with timeout) if (millis() - startedWaiting > commandTimeout) { PN5180DEBUG_ON; - PN5180ERROR(F("reset failed (timeout)!!!")); + PN5180ERROR(F("reset() timeout waiting for IDLE_IRQ_STAT")); // try again with larger time digitalWrite(PN5180_RST, LOW); delay(10); From 9c9d5312b751ea0119e984ccec7175d54164873f Mon Sep 17 00:00:00 2001 From: mjmeans Date: Sun, 17 Nov 2024 03:35:43 -0700 Subject: [PATCH 21/32] #define for rf on and off timeouts --- PN5180.cpp | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/PN5180.cpp b/PN5180.cpp index 262c5c4..70b075b 100644 --- a/PN5180.cpp +++ b/PN5180.cpp @@ -50,6 +50,9 @@ #define PN5180_RF_ON (0x16) // Switch on the RF Field #define PN5180_RF_OFF (0x17) // Switch off the RF Field +#define SETRF_ON_TIMEOUT (500) +#define SETRF_OFF_TIMEOUT (500) + uint8_t PN5180::readBufferStatic16[16]; PN5180::PN5180(uint8_t SSpin, uint8_t BUSYpin, uint8_t RSTpin, SPIClass& spi) : @@ -674,10 +677,10 @@ bool PN5180::setRF_on() { unsigned long startedWaiting = millis(); - PN5180DEBUG_PRINTLN(F("wait for RF field to set up (max 500ms)")); + PN5180DEBUG_PRINTF(F("wait for RF field to set up (max %d ms)"), SETRF_ON_TIMEOUT); PN5180DEBUG_OFF; while (0 == (TX_RFON_IRQ_STAT & getIRQStatus())) { // wait for RF field to set up (max 500ms) - if (millis() - startedWaiting > 500) { + if (millis() - startedWaiting > SETRF_ON_TIMEOUT) { PN5180DEBUG_ON; PN5180ERROR(F("setRF_on() timeout waiting for TX_RFON_IRQ_STAT")); PN5180DEBUG_EXIT; @@ -715,10 +718,10 @@ bool PN5180::setRF_off() { } unsigned long startedWaiting = millis(); - PN5180DEBUG_PRINTLN(F("wait for RF field to shut down (max 500ms)")); + PN5180DEBUG_PRINTF(F("wait for RF field to shut down (max %d ms)"), SETRF_OFF_TIMEOUT); PN5180DEBUG_OFF; while (0 == (TX_RFOFF_IRQ_STAT & getIRQStatus())) { // wait for RF field to shut down - if (millis() - startedWaiting > 500) { + if (millis() - startedWaiting > SETRF_OFF_TIMEOUT) { PN5180DEBUG_ON; PN5180ERROR(F("setRF_off() timeout waiting for TX_RFOFF_IRQ_STAT")); PN5180DEBUG_EXIT; From 0cf3023b9f675c511fab667b5b9a3e3dcacdc701 Mon Sep 17 00:00:00 2001 From: mjmeans Date: Sun, 17 Nov 2024 04:03:32 -0700 Subject: [PATCH 22/32] More debugging changes --- PN5180.cpp | 39 +++++++++++++++++++++++++++++---------- 1 file changed, 29 insertions(+), 10 deletions(-) diff --git a/PN5180.cpp b/PN5180.cpp index 70b075b..b51d370 100644 --- a/PN5180.cpp +++ b/PN5180.cpp @@ -608,10 +608,10 @@ int16_t PN5180::mifareAuthenticate(uint8_t blockNo, const uint8_t *key, uint8_t cmdBuffer[9+i] = uid[i]; } - bool retval = transceiveCommand(cmdBuffer, 13, rcvBuffer, 1); - - if (!retval){ - PN5180ERROR(F("sending command failed!")); + //bool retval = transceiveCommand(cmdBuffer, 13, rcvBuffer, 1); + if (!transceiveCommand(cmdBuffer, 13, rcvBuffer, 1)) { + PN5180ERROR(F("mifareAuthenticate() failed at transceiveCommand()")); + PN5180DEBUG_EXIT; return -3; } @@ -675,17 +675,36 @@ bool PN5180::setRF_on() { return false; } - unsigned long startedWaiting = millis(); - + //unsigned long startedWaiting = millis(); PN5180DEBUG_PRINTF(F("wait for RF field to set up (max %d ms)"), SETRF_ON_TIMEOUT); PN5180DEBUG_OFF; - while (0 == (TX_RFON_IRQ_STAT & getIRQStatus())) { // wait for RF field to set up (max 500ms) - if (millis() - startedWaiting > SETRF_ON_TIMEOUT) { + //while (0 == (TX_RFON_IRQ_STAT & getIRQStatus())) { // wait for RF field to set up (max 500ms) + // if (millis() - startedWaiting > SETRF_ON_TIMEOUT) { + // PN5180DEBUG_ON; + // PN5180ERROR(F("setRF_on() timeout waiting for TX_RFON_IRQ_STAT")); + // PN5180DEBUG_EXIT; + // return false; + // } + //}; + unsigned long startedWaiting = millis(); + while (1) { // wait for RF field to set up + uint32_t irqStatus; + if (!readRegister(IRQ_STATUS, &irqStatus)) { PN5180DEBUG_ON; - PN5180ERROR(F("setRF_on() timeout waiting for TX_RFON_IRQ_STAT")); + PN5180ERROR(F("setRF_on() failed at readRegister()")); PN5180DEBUG_EXIT; return false; } + if (0 != (TX_RFON_IRQ_STAT & irqStatus)) { + break; + } + if (millis() - startedWaiting > SETRF_ON_TIMEOUT) { + PN5180DEBUG_ON; + PN5180ERROR(F("setRF_on() timeout failed waiting for TX_RFON_IRQ_STAT")); + PN5180DEBUG_EXIT; + return false; + } + delay(1); }; PN5180DEBUG_ON; @@ -952,7 +971,7 @@ bool PN5180::clearIRQStatus(uint32_t irqMask) { PN5180DEBUG_PRINTLN(F("Clear IRQ-Status with mask")); //bool ret = writeRegister(IRQ_CLEAR, irqMask); - if (writeRegister(IRQ_CLEAR, irqMask)) { + if (!writeRegister(IRQ_CLEAR, irqMask)) { PN5180ERROR(F("clearIRQStatus() failed at writeRegister()")); PN5180DEBUG_EXIT; return false; From 96dbd4f40cfa822ec2b1348a4c67ad5d604ee1b4 Mon Sep 17 00:00:00 2001 From: mjmeans Date: Sun, 17 Nov 2024 04:09:34 -0700 Subject: [PATCH 23/32] Remove unneeded declare --- PN5180.h | 1 - 1 file changed, 1 deletion(-) diff --git a/PN5180.h b/PN5180.h index cd04470..e8a9ccb 100644 --- a/PN5180.h +++ b/PN5180.h @@ -212,7 +212,6 @@ class PN5180 { uint32_t getIRQStatus(); bool waitIRQ(uint8_t irq); bool clearIRQStatus(uint32_t irqMask); - bool cycleRF_off_on(); PN5180TransceiveStat getTransceiveState(); From c3d34b196e217564434974175cdca51b21ba4e0d Mon Sep 17 00:00:00 2001 From: mjmeans Date: Sun, 17 Nov 2024 07:13:43 -0700 Subject: [PATCH 24/32] fix typos and debug text --- PN5180.cpp | 67 +++++++++++++++++++++++++++--------------------------- 1 file changed, 33 insertions(+), 34 deletions(-) diff --git a/PN5180.cpp b/PN5180.cpp index b51d370..5e969b1 100644 --- a/PN5180.cpp +++ b/PN5180.cpp @@ -204,7 +204,7 @@ bool PN5180::writeRegisterWithOrMask(uint8_t reg, uint32_t mask) { } /* - * WRITE _REGISTER_AND_MASK - 0x02 + * WRITE_REGISTER_AND_MASK - 0x02 * This command modifies the content of a register using a logical AND operation. The * content of the register is read and a logical AND operation is performed with the provided * mask. The modified content is written back to the register. @@ -282,8 +282,8 @@ bool PN5180::writeEEprom(uint8_t addr, const uint8_t *buffer, uint8_t len) { cmd[1] = addr; for (int i = 0; i < len; i++) cmd[2 + i] = buffer[i]; - // transceiveCommand(cmd, len + 2); - if (transceiveCommand(cmd, len + 2)) { + // transceiveCommand(cmd, len + 2); + if (!transceiveCommand(cmd, len + 2)) { PN5180ERROR(F("writeEEprom() failed at transceiveCommand()")); PN5180DEBUG_EXIT; return false; @@ -323,8 +323,8 @@ bool PN5180::readEEprom(uint8_t addr, uint8_t *buffer, int len) { uint8_t cmd[] = { PN5180_READ_EEPROM, addr, uint8_t(len) }; - // transceiveCommand(cmd, sizeof(cmd), buffer, len); - if (transceiveCommand(cmd, sizeof(cmd), buffer, len)) { + // transceiveCommand(cmd, sizeof(cmd), buffer, len); + if (!transceiveCommand(cmd, sizeof(cmd), buffer, len)) { PN5180ERROR(F("readEEprom() failed at transceiveCommand()")); PN5180DEBUG_EXIT; return false; @@ -388,14 +388,14 @@ bool PN5180::sendData(const uint8_t *data, int len, uint8_t validBits) { //} // writeRegisterWithAndMask(SYSTEM_CONFIG, 0xfffffff8); // Idle/StopCom Command if (!writeRegisterWithAndMask(SYSTEM_CONFIG, 0xfffffff8)) { - PN5180ERROR(F("sendData() failed at writeRegisterWithAndMask()")); + PN5180ERROR(F("sendData() failed at writeRegisterWithAndMask() Idle/StopCom Command")); PN5180DEBUG_EXIT; return false; } // writeRegisterWithOrMask(SYSTEM_CONFIG, 0x00000003); // Transceive Command if (!writeRegisterWithOrMask(SYSTEM_CONFIG, 0x00000003)) { - PN5180ERROR(F("sendData() failed at writeRegisterWithOrMask()")); + PN5180ERROR(F("sendData() failed at writeRegisterWithOrMask() Transceive Command")); PN5180DEBUG_EXIT; return false; } @@ -443,7 +443,7 @@ uint8_t * PN5180::readData(int len) { PN5180DEBUG_ENTER; if (len < 0 || len > 508) { - PN5180ERROR(F("readData() failed: Reading more than 508 bytes is not supported!")); + Serial.println(F("readData() failed: Reading more than 508 bytes is not supported!")); PN5180DEBUG_EXIT; return 0L; } @@ -471,11 +471,11 @@ uint8_t * PN5180::readData(int len) { readBuffer = readBufferDynamic508; } - // transceiveCommand(cmd, sizeof(cmd), readBuffer, len); - if (transceiveCommand(cmd, sizeof(cmd), readBuffer, len)) { + // transceiveCommand(cmd, sizeof(cmd), readBuffer, len); + if (!transceiveCommand(cmd, sizeof(cmd), readBuffer, len)) { PN5180ERROR(F("readData() failed at transceiveCommand()")); PN5180DEBUG_EXIT; - return 0; + return 0L; } #ifdef DEBUG @@ -503,8 +503,8 @@ bool PN5180::readData(int len, uint8_t *buffer) { uint8_t cmd[] = { PN5180_READ_DATA, 0x00 }; //bool ret = transceiveCommand(cmd, sizeof(cmd), buffer, len); - if (transceiveCommand(cmd, sizeof(cmd), buffer, len)) { - PN5180ERROR(F("readData() failed at transceiveCommand()")); + if (!transceiveCommand(cmd, sizeof(cmd), buffer, len)) { + PN5180ERROR(F("sendData() failed at writeRegisterWithAndMask() Idle/StopCom Command")); PN5180DEBUG_EXIT; return false; } @@ -648,7 +648,7 @@ bool PN5180::loadRFConfig(uint8_t txConf, uint8_t rxConf) { uint8_t cmd[] = { PN5180_LOAD_RF_CONFIG, txConf, rxConf }; // transceiveCommand(cmd, sizeof(cmd)); - if (transceiveCommand(cmd, sizeof(cmd))) { + if (!transceiveCommand(cmd, sizeof(cmd))) { PN5180ERROR(F("loadRFConfig() failed at transceiveCommand()")); PN5180DEBUG_EXIT; return false; @@ -664,7 +664,7 @@ bool PN5180::loadRFConfig(uint8_t txConf, uint8_t rxConf) { * set after the field is switched on. */ bool PN5180::setRF_on() { - PN5180DEBUG_PRINTLN(F("Set RF ON")); + PN5180DEBUG_PRINTLN(F("PN5180::setRF_on()")); PN5180DEBUG_ENTER; //uint8_t cmd[] = { PN5180_RF_ON, 0x00 }; @@ -675,8 +675,8 @@ bool PN5180::setRF_on() { return false; } - //unsigned long startedWaiting = millis(); PN5180DEBUG_PRINTF(F("wait for RF field to set up (max %d ms)"), SETRF_ON_TIMEOUT); + PN5180DEBUG_PRINTLN(); PN5180DEBUG_OFF; //while (0 == (TX_RFON_IRQ_STAT & getIRQStatus())) { // wait for RF field to set up (max 500ms) // if (millis() - startedWaiting > SETRF_ON_TIMEOUT) { @@ -708,8 +708,8 @@ bool PN5180::setRF_on() { }; PN5180DEBUG_ON; - // clearIRQStatus(TX_RFON_IRQ_STAT); - if (clearIRQStatus(TX_RFON_IRQ_STAT)) { + // clearIRQStatus(TX_RFON_IRQ_STAT); + if (!clearIRQStatus(TX_RFON_IRQ_STAT)) { PN5180ERROR(F("setRF_on() failed at clearIRQStatus()")); PN5180DEBUG_EXIT; return false; @@ -725,19 +725,17 @@ bool PN5180::setRF_on() { * is set after the field is switched off. */ bool PN5180::setRF_off() { - PN5180DEBUG_PRINTLN(F("Set RF OFF")); + PN5180DEBUG_PRINTLN(F("PN5180::setRF_off()")); PN5180DEBUG_ENTER; - //uint8_t cmd[] { PN5180_RF_OFF, 0x00 }; - //transceiveCommand(cmd, sizeof(cmd)); if (!cmd_RfOff(0)) { PN5180ERROR(F("setRF_off() failed at cmd_RfOff()")); PN5180DEBUG_EXIT; return false; } - unsigned long startedWaiting = millis(); PN5180DEBUG_PRINTF(F("wait for RF field to shut down (max %d ms)"), SETRF_OFF_TIMEOUT); + PN5180DEBUG_PRINTLN(); PN5180DEBUG_OFF; while (0 == (TX_RFOFF_IRQ_STAT & getIRQStatus())) { // wait for RF field to shut down if (millis() - startedWaiting > SETRF_OFF_TIMEOUT) { @@ -747,11 +745,11 @@ bool PN5180::setRF_off() { return false; } }; - PN5180DEBUG_ON; - - /// clearIRQStatus(TX_RFOFF_IRQ_STAT); - if (clearIRQStatus(TX_RFOFF_IRQ_STAT)) { - PN5180ERROR(F("setRF_off() failed at clearIRQStatus()")); + PN5180DEBUG_ON; + + // clearIRQStatus(TX_RFOFF_IRQ_STAT); + if (!clearIRQStatus(TX_RFOFF_IRQ_STAT)) { + PN5180ERROR(F("setRF_on() failed at clearIRQStatus()")); PN5180DEBUG_EXIT; return false; } @@ -948,11 +946,11 @@ uint32_t PN5180::getIRQStatus() { PN5180DEBUG_PRINTLN(F("Read IRQ-Status register...")); uint32_t irqStatus; - // readRegister(IRQ_STATUS, &irqStatus); - if (readRegister(IRQ_STATUS, &irqStatus)) { + // readRegister(IRQ_STATUS, &irqStatus); + if (!readRegister(IRQ_STATUS, &irqStatus)) { PN5180ERROR(F("getIRQStatus() failed at readRegister()")); PN5180DEBUG_EXIT; - return false; + return 0L; } PN5180DEBUG(F("IRQ-Status=0x")); @@ -981,13 +979,14 @@ bool PN5180::clearIRQStatus(uint32_t irqMask) { return true; } -/* - * Get TRANSCEIVE_STATE from RF_STATUS register - */ #ifdef DEBUG extern void showIRQStatus(uint32_t); #endif + +/* + * Get TRANSCEIVE_STATE from RF_STATUS register + */ PN5180TransceiveStat PN5180::getTransceiveState() { PN5180DEBUG_PRINT(F("PN5180::getTransceiveState()")); PN5180DEBUG_PRINTLN(); @@ -1073,7 +1072,7 @@ bool PN5180::cmd_SendData(const uint8_t *data, int len, uint8_t validBits) { } if (!transceiveCommand(buffer, len+2)) { - PN5180ERROR(F("cmd_SendData() failed at transceiveCommand()")); + PN5180ERROR(F("sendData() failed at transceiveCommand()")); PN5180DEBUG_EXIT; return false; } From 3a23febccffc67398b35b264ca02f57de8f5a457 Mon Sep 17 00:00:00 2001 From: mjmeans Date: Sun, 17 Nov 2024 07:22:50 -0700 Subject: [PATCH 25/32] restore accidentally deleted line --- PN5180.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/PN5180.cpp b/PN5180.cpp index 5e969b1..9f6d358 100644 --- a/PN5180.cpp +++ b/PN5180.cpp @@ -737,6 +737,7 @@ bool PN5180::setRF_off() { PN5180DEBUG_PRINTF(F("wait for RF field to shut down (max %d ms)"), SETRF_OFF_TIMEOUT); PN5180DEBUG_PRINTLN(); PN5180DEBUG_OFF; + unsigned long startedWaiting = millis(); while (0 == (TX_RFOFF_IRQ_STAT & getIRQStatus())) { // wait for RF field to shut down if (millis() - startedWaiting > SETRF_OFF_TIMEOUT) { PN5180DEBUG_ON; From 8f18ace880db652e26d6b5b4fd9b197aa824afde Mon Sep 17 00:00:00 2001 From: mjmeans Date: Sun, 17 Nov 2024 08:05:19 -0700 Subject: [PATCH 26/32] typo --- PN5180.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/PN5180.cpp b/PN5180.cpp index 9f6d358..c82d45e 100644 --- a/PN5180.cpp +++ b/PN5180.cpp @@ -741,7 +741,7 @@ bool PN5180::setRF_off() { while (0 == (TX_RFOFF_IRQ_STAT & getIRQStatus())) { // wait for RF field to shut down if (millis() - startedWaiting > SETRF_OFF_TIMEOUT) { PN5180DEBUG_ON; - PN5180ERROR(F("setRF_off() timeout waiting for TX_RFOFF_IRQ_STAT")); + PN5180ERROR(F("setRF_off() timeout failed waiting for TX_RFOFF_IRQ_STAT")); PN5180DEBUG_EXIT; return false; } From aab3eaf279eb7987cec18a3a99b3122d316263cc Mon Sep 17 00:00:00 2001 From: mjmeans Date: Sun, 17 Nov 2024 08:23:14 -0700 Subject: [PATCH 27/32] Watcch for readRegiser return failure checks in wait loops --- PN5180.cpp | 28 ++++++++++++++++------------ 1 file changed, 16 insertions(+), 12 deletions(-) diff --git a/PN5180.cpp b/PN5180.cpp index c82d45e..5fee6c4 100644 --- a/PN5180.cpp +++ b/PN5180.cpp @@ -687,25 +687,22 @@ bool PN5180::setRF_on() { // } //}; unsigned long startedWaiting = millis(); - while (1) { // wait for RF field to set up - uint32_t irqStatus; + uint32_t irqStatus; + while (1) { // wait for RF field to shut down if (!readRegister(IRQ_STATUS, &irqStatus)) { PN5180DEBUG_ON; - PN5180ERROR(F("setRF_on() failed at readRegister()")); + PN5180ERROR(F("setRF_off() failed at readRegister()")); PN5180DEBUG_EXIT; return false; } - if (0 != (TX_RFON_IRQ_STAT & irqStatus)) { - break; - } + if (0 != (TX_RFON_IRQ_STAT & irqStatus)) break; if (millis() - startedWaiting > SETRF_ON_TIMEOUT) { PN5180DEBUG_ON; - PN5180ERROR(F("setRF_on() timeout failed waiting for TX_RFON_IRQ_STAT")); + PN5180ERROR(F("setRF_on() timeout failed waiting for SETRF_ON_TIMEOUT")); PN5180DEBUG_EXIT; return false; } - delay(1); - }; + } PN5180DEBUG_ON; // clearIRQStatus(TX_RFON_IRQ_STAT); @@ -738,15 +735,22 @@ bool PN5180::setRF_off() { PN5180DEBUG_PRINTLN(); PN5180DEBUG_OFF; unsigned long startedWaiting = millis(); - while (0 == (TX_RFOFF_IRQ_STAT & getIRQStatus())) { // wait for RF field to shut down + uint32_t irqStatus; + while (1) { // wait for RF field to shut down + if (!readRegister(IRQ_STATUS, &irqStatus)) { + PN5180DEBUG_ON; + PN5180ERROR(F("setRF_off() failed at readRegister()")); + PN5180DEBUG_EXIT; + return false; + } + if (0 != (TX_RFOFF_IRQ_STAT & irqStatus)) break; if (millis() - startedWaiting > SETRF_OFF_TIMEOUT) { PN5180DEBUG_ON; PN5180ERROR(F("setRF_off() timeout failed waiting for TX_RFOFF_IRQ_STAT")); PN5180DEBUG_EXIT; return false; } - }; - PN5180DEBUG_ON; + } // clearIRQStatus(TX_RFOFF_IRQ_STAT); if (!clearIRQStatus(TX_RFOFF_IRQ_STAT)) { From c31ba61c038e48d90b58331f45fe9726e37f2703 Mon Sep 17 00:00:00 2001 From: mjmeans Date: Sun, 17 Nov 2024 08:26:02 -0700 Subject: [PATCH 28/32] fix typos --- PN5180.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/PN5180.cpp b/PN5180.cpp index 5fee6c4..9d754c5 100644 --- a/PN5180.cpp +++ b/PN5180.cpp @@ -1108,7 +1108,7 @@ bool PN5180::cmd_RfOn(uint8_t parameter) { uint8_t cmd[] = { PN5180_RF_ON, parameter }; if (!transceiveCommand(cmd, sizeof(cmd))) { - PN5180ERROR(F("cmd_RfOn() failed at transceiveCommand() Idle/StopCom Command")); + PN5180ERROR(F("cmd_RfOn() failed at transceiveCommand()")); PN5180DEBUG_EXIT; return false; } @@ -1138,7 +1138,7 @@ bool PN5180::cmd_RfOff(uint8_t parameter) { uint8_t cmd[] = { PN5180_RF_OFF, parameter }; if (!transceiveCommand(cmd, sizeof(cmd))) { - PN5180ERROR(F("cmd_RfOff() failed at transceiveCommand() Idle/StopCom Command")); + PN5180ERROR(F("cmd_RfOff() failed at transceiveCommand()")); PN5180DEBUG_EXIT; return false; } From 63a2416ed3f835615fc29a543afc908ccd1e0bdc Mon Sep 17 00:00:00 2001 From: mjmeans Date: Sun, 17 Nov 2024 09:21:20 -0700 Subject: [PATCH 29/32] add comments and remove unneeded code --- PN5180.cpp | 15 +++++++-------- 1 file changed, 7 insertions(+), 8 deletions(-) diff --git a/PN5180.cpp b/PN5180.cpp index 9d754c5..4c37409 100644 --- a/PN5180.cpp +++ b/PN5180.cpp @@ -344,6 +344,12 @@ bool PN5180::readEEprom(uint8_t addr, uint8_t *buffer, int len) { } /* + * This function: + * 1. checks parameters + * 2. sets SYSTEM_CONFIG Idle/StopCom Command + * 3. sets SYSTEM_CONFIG Transceive Command + * 4. calls cmd_SendData() which in turn calls transceiveCommand() to send the command over SPI to the PN5180 chip + * * SEND_DATA - 0x09 * This command writes data to the RF transmission buffer and starts the RF transmission. * The parameter ‘Number of valid bits in last Byte’ indicates the exact number of bits to be @@ -380,13 +386,7 @@ bool PN5180::sendData(const uint8_t *data, int len, uint8_t validBits) { PN5180DEBUG_PRINTLN(); #endif - //uint8_t buffer[len+2]; - //buffer[0] = PN5180_SEND_DATA; - //buffer[1] = validBits; // number of valid bits of last byte are transmitted (0 = all bits are transmitted) - //for (int i=0; i Date: Sun, 17 Nov 2024 13:55:06 -0700 Subject: [PATCH 30/32] tidy up the code a bit The bug that prevented getInventoryMultiple() from doing collision resolution is fixed. Four cards with UIDs ending in '0' were able to be read at one time. I also had two cards with UIDs ending in 'DD' that were recognized, so the collision avoidance resolution is at least getting to the third round. I do not have any cards with UIDs that all end in the same three or more identical nibbles to see how far it can go, but I think getting to the third round is proves that the algorithm is correct. That alll being said, although my initial problem of the library hanging when reading a stack of cards with at least one ending in '0' has only partially been resolved. In any number of cards within the RF field, if only one of them has a UID ending in '0', getInventoryMultiple() still hangs. Adding a additional tags ending in '0' however does not hang. Even with all the debugging macros I added I still haven't discovered why this occurs only when there is a single tag ending in '0' within the field. And if using the regular single card reading call, getInventory(), cards ending in '0' read just fine. While the latter problem is not yet solved, I have made significant progress on the other two issues arising from errors in collision resolution, so I'd ending this branch here and will send a PR upstream. I will work on the remaining solution in another branch. based on this one. By the way, I have on occasion been able to read 9 NFC Type 5 ICODE SLIX card tags at one time on the PN5180 if the cards are held just above, but not touching, the PN5180 board antenna. But I do find that not all manufacturer's of these cards are able to be read that many at a time. Different manufacturer's use different size or shape or windings of their antennas and possibly use lower quality tag chips inside the cards. I haven't investigated this actual cause of this inconsistency or how to make sure the tags I get are ones that can operate in larger stacks. On another note, I've had communication with NXP regarding the PN5180 and tyriing to get the chip to resolve at a full NFC Type 5 ranges over 10 cm since NFC Type 5 is supposed to be able to be read up to 1.5 m. NXP replied that their PN5180 is NFC compliant, but that their chip is only design to read at ranges up to 10 cm. So word to the wise, if you are looking for the ability to read a single NFC Type 5 tag at ranges longer than 10 cm, you probably don't want the PN5180 unless you are going to design a very complex powerful amplified antenna circuit. NXP offered me no guidance in this respect, other than to suggest contacting another company specializing in long range RFID. Sigh! --- PN5180ISO15693.cpp | 119 +++++++++++++++++++++++++++------------------ 1 file changed, 71 insertions(+), 48 deletions(-) diff --git a/PN5180ISO15693.cpp b/PN5180ISO15693.cpp index 5b3809f..5179af7 100644 --- a/PN5180ISO15693.cpp +++ b/PN5180ISO15693.cpp @@ -91,8 +91,9 @@ ISO15693ErrorCode PN5180ISO15693::getInventory(uint8_t *uid) { uint8_t flags = ISO15693_REQ_FLAG_NBSLOTS | ISO15693_REQ_FLAG_INVENTORY | ISO15693_REQ_FLAG_DATARATE; uint8_t maskLen = 0x00; uint8_t inventory[] = { cmd, flags, maskLen }; - PN5180DEBUG(F("Get Inventory...\n")); + PN5180DEBUG(F("Get Inventory...")); + PN5180DEBUG_PRINTLN(); for (int i=0; i<8; i++) { uid[i] = 0; } @@ -108,18 +109,15 @@ ISO15693ErrorCode PN5180ISO15693::getInventory(uint8_t *uid) { uid[i] = readBuffer[2+i]; } +#ifdef DEBUG PN5180DEBUG(F("Response flags: ")); PN5180DEBUG(formatHex(readBuffer[0])); PN5180DEBUG(F(", Data Storage Format ID: ")); PN5180DEBUG(formatHex(readBuffer[1])); PN5180DEBUG(F(", UID: ")); - -#ifdef DEBUG for (int i=0; i<8; i++) { - uid[i] = readBuffer[2+i]; PN5180DEBUG(formatHex(uid[7-i])); // LSB comes first if (i<2) PN5180DEBUG(":"); - } PN5180DEBUG_PRINTLN(); #endif @@ -151,7 +149,7 @@ ISO15693ErrorCode PN5180ISO15693::getInventoryMultiple(uint8_t *uid, uint8_t max return ISO15693_EC_UNKNOWN_ERROR; } - PN5180DEBUG_PRINTF("*** Number of collisions=%d", numCol); + PN5180DEBUG_PRINTF("Number of collisions=%d", numCol); PN5180DEBUG_PRINTLN(); while(numCol){ // 5+ Continue until no collisions detected @@ -178,14 +176,12 @@ ISO15693ErrorCode PN5180ISO15693::getInventoryMultiple(uint8_t *uid, uint8_t max return ISO15693_EC_OK; } +// 4. Send inventory request with mask length and mask value. ISO15693ErrorCode PN5180ISO15693::inventoryPoll(uint8_t *uid, uint8_t maxTags, uint8_t *numCard, uint8_t *numCol, uint16_t *collision){ PN5180DEBUG_PRINTF("PN5180ISO15693::inventoryPoll(maxTags=%d, numCard=%d, numCol=%d)", maxTags, *numCard, *numCol); PN5180DEBUG_PRINTLN(); PN5180DEBUG_ENTER; - uint8_t cmd = ISO15693_CMD_INVENTORY; - // flags = 16 slots: upto 16 cards, no AFI field present, inventory flag + high data rate - uint8_t flags = ISO15693_REQ_FLAG_INVENTORY | ISO15693_REQ_FLAG_DATARATE; uint8_t maskLen = 0; if(*numCol > 0){ uint32_t mask = collision[0]; @@ -195,29 +191,37 @@ ISO15693ErrorCode PN5180ISO15693::inventoryPoll(uint8_t *uid, uint8_t maxTags, u }while(mask > 0); } uint8_t *p = (uint8_t*)&(collision[0]); - - const uint8_t inventory[7] = { flags, cmd, uint8_t(maskLen*4), p[0], p[1], p[2], p[3] }; + // flags = 16 slots, up to 16 cards, no AFI field present, inventory flag + high data rate + uint8_t flags = ISO15693_REQ_FLAG_DATARATE | ISO15693_REQ_FLAG_INVENTORY; + const uint8_t inventory[7] = { flags, ISO15693_CMD_INVENTORY, uint8_t(maskLen*4), p[0], p[1], p[2], p[3] }; + // TODO: can p[] containing the collision mask bytes be more than 4 bytes long? + // TODO: Why is collision[] initialized to a length of maxTags, but only 4 p[] values in this call? uint8_t cmdLen = 3 + (maskLen/2) + (maskLen%2); #ifdef DEBUG PN5180DEBUG_PRINTF(F("mask=%d, maskLen=%d, cmdLen=%d"), p[0], maskLen, cmdLen); PN5180DEBUG_PRINTLN(); #endif - // clearIRQStatus(0x000FFFFF); // 3. Clear all IRQ_STATUS flags + // 3. Clear all IRQ_STATUS flags + // clearIRQStatus(0x000FFFFF); if (!clearIRQStatus(0x000FFFFF)) { PN5180ERROR(F("inventoryPoll() failed at step 3. clearIRQStatus()")); PN5180DEBUG_EXIT; return ISO15693_EC_UNKNOWN_ERROR; } - // sendData(inventory, cmdLen, 0); // 4. 5. 6. Idle/StopCom Command, Transceive Command, Inventory command + uint8_t *readBuffer; + + // 4. 5. 6. Idle/StopCom Command, Transceive Command, Inventory command + // sendData(inventory, cmdLen, 0); if (!sendData(inventory, cmdLen, 0)) { PN5180ERROR(F("inventoryPoll() failed at step 4.5.6. sendData()")); PN5180DEBUG_EXIT; return ISO15693_EC_UNKNOWN_ERROR; } - for(uint8_t slot=0; slot<16; slot++){ // 7. Loop to check 16 time slots for data + // 7. Loop to check 16 time slots for data + for(uint8_t slot=0; slot<16; slot++){ uint32_t rxStatus; uint32_t irqStatus = getIRQStatus(); @@ -227,6 +231,7 @@ ISO15693ErrorCode PN5180ISO15693::inventoryPoll(uint8_t *uid, uint8_t maxTags, u PN5180DEBUG_EXIT; return ISO15693_EC_UNKNOWN_ERROR; } + PN5180DEBUG(F("slot=")); PN5180DEBUG(formatHex(slot)); PN5180DEBUG(F(": ")); @@ -235,9 +240,10 @@ ISO15693ErrorCode PN5180ISO15693::inventoryPoll(uint8_t *uid, uint8_t maxTags, u PN5180DEBUG(F(", RX_STATUS=")); PN5180DEBUG(formatHex(rxStatus)); PN5180DEBUG(F(": ")); - + + // 7+ Determine if a collision occurred uint16_t len = (uint16_t)(rxStatus & 0x000001ff); - if((rxStatus >> 18) & 0x01 && *numCol < maxTags){ // 7+ Determine if a collision occurred + if((rxStatus >> 18) & 0x01 && *numCol < maxTags){ if(maskLen > 0) collision[*numCol] = collision[0] | (slot << (maskLen * 4)); else collision[*numCol] = slot << (maskLen * 4); // Yes, store position of collision *numCol = *numCol + 1; @@ -246,31 +252,37 @@ ISO15693ErrorCode PN5180ISO15693::inventoryPoll(uint8_t *uid, uint8_t maxTags, u PN5180DEBUG_PRINTLN(); #endif } - else if(!(irqStatus & RX_IRQ_STAT) && !len){ // 8. Check if a card has responded + else + // 8. Check if a card has responded + if(!(irqStatus & RX_IRQ_STAT) && !len){ PN5180DEBUG(F("No card in this time slot.")); PN5180DEBUG_PRINTLN(); } else{ #ifdef DEBUG - PN5180DEBUG_PRINTF("slot=%d, irqStatus: %ld, RX_STATUS: %ld, Response length=%d", slot, irqStatus, rxStatus, len); + PN5180DEBUG_PRINTF("slot=%d, irqStatus: %ld, RX_STATUS: %ld, Response length=%d, ", slot, irqStatus, rxStatus, len); #endif uint8_t *readBuffer; - readBuffer = readData(len+1); // 9. Read reception buffer + + // 9. Read reception buffer + readBuffer = readData(len+1); if(0L == readBuffer){ PN5180ERROR(F("inventoryPoll() failed at step 9. readBuffer() for slot %d"), slot); PN5180DEBUG_EXIT; return ISO15693_EC_UNKNOWN_ERROR; } + #ifdef DEBUG PN5180DEBUG(F("readBuffer=")); for(int i=0; i Date: Sun, 17 Nov 2024 13:57:43 -0700 Subject: [PATCH 31/32] Comment out the DEBUG flags --- Debug.cpp | 3 ++- PN5180.cpp | 2 +- PN5180ISO14443.cpp | 2 +- PN5180ISO15693.cpp | 2 +- 4 files changed, 5 insertions(+), 4 deletions(-) diff --git a/Debug.cpp b/Debug.cpp index b0855bd..13225a1 100644 --- a/Debug.cpp +++ b/Debug.cpp @@ -16,7 +16,8 @@ // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU // Lesser General Public License for more details. // -#define DEBUG 1 +//#define DEBUG 1 + #include #include "Debug.h" diff --git a/PN5180.cpp b/PN5180.cpp index 4c37409..154b06d 100644 --- a/PN5180.cpp +++ b/PN5180.cpp @@ -17,7 +17,7 @@ // Lesser General Public License for more details. // //#define DEBUG 1 -#define DEBUG_ERROR 1 +//#define DEBUG_ERROR 1 #include #include "PN5180.h" diff --git a/PN5180ISO14443.cpp b/PN5180ISO14443.cpp index 3c4c4e2..505c819 100644 --- a/PN5180ISO14443.cpp +++ b/PN5180ISO14443.cpp @@ -17,7 +17,7 @@ // Lesser General Public License for more details. // //#define DEBUG 1 -#define DEBUG_ERROR 1 +//#define DEBUG_ERROR 1 #include #include "PN5180ISO14443.h" diff --git a/PN5180ISO15693.cpp b/PN5180ISO15693.cpp index 5179af7..bcbe2d8 100644 --- a/PN5180ISO15693.cpp +++ b/PN5180ISO15693.cpp @@ -17,7 +17,7 @@ // Lesser General Public License for more details. // //#define DEBUG 1 -#define DEBUG_ERROR 1 +//#define DEBUG_ERROR 1 #include #include "PN5180ISO15693.h" From 8f541a47ef501f1f71b654cb7d190d47981f0706 Mon Sep 17 00:00:00 2001 From: mjmeans Date: Thu, 21 Nov 2024 15:38:32 -0700 Subject: [PATCH 32/32] Fix references when not using any DEBUG defines Well, I didn't test after turning deactivating all the DEBUG defines. This resolves it. --- Debug.h | 39 +++++++++++++++++++++++---------------- 1 file changed, 23 insertions(+), 16 deletions(-) diff --git a/Debug.h b/Debug.h index 7aafbe1..57cbe6c 100644 --- a/Debug.h +++ b/Debug.h @@ -79,13 +79,11 @@ extern uint8_t _pn5180_debugIndentN; extern bool _pn5180_debugNL; extern uint8_t _pn5180_debugSilent; -// These macros are helper macros to make the see the debug macros like function calls so they do not alter any current code block structures when the macro contains if/else/break, etc. +#ifdef DEBUG +// These macros are helper macros to make c compiler treat the debug macros like function calls so they do not alter any current code block structures when the macro contains if/else/break, etc. #define __DEBUG_BEGIN__ do{if(DEBUG){ #define __DEBUG_END__ }}while(0) -#define __ERROR_BEGIN__ do{if(DEBUG_ERROR){ -#define __ERROR_END__ }}while(0) -#ifdef DEBUG #define PN5180DEBUG_OFF __DEBUG_BEGIN__ ++_pn5180_debugSilent; __DEBUG_END__ #define PN5180DEBUG_ON __DEBUG_BEGIN__ _pn5180_debugSilent-=((_pn5180_debugSilent>0)?1:0); __DEBUG_END__ #define PN5180DEBUG_ENTER __DEBUG_BEGIN__ ++_pn5180_debugIndent; __DEBUG_END__ @@ -95,28 +93,37 @@ extern uint8_t _pn5180_debugSilent; #define PN5180DEBUG_PRINTF(...) __DEBUG_BEGIN__ if (!_pn5180_debugSilent) { if (_pn5180_debugNL) PN5180DEBUG_INDENT; Serial.printf(__VA_ARGS__); }; __DEBUG_END__ #define PN5180DEBUG_PRINT(...) __DEBUG_BEGIN__ if (!_pn5180_debugSilent) { if (_pn5180_debugNL) PN5180DEBUG_INDENT; Serial.print(__VA_ARGS__); }; __DEBUG_END__ #define PN5180DEBUG(msg) PN5180DEBUG_PRINT(msg) -#else -#define PN5180DEBUG_OFF -#define PN5180DEBUG_ON -#define PN5180DEBUG_ENTER -#define PN5180DEBUG_EXIT -#define PN5180DEBUG_INDENT -#define PN5180DEBUG_PRINTLN(...) -#define PN5180DEBUG_PRINTF(...) -#define PN5180DEBUG_PRINT(...) -#define PN5180DEBUG(msg) #endif /* DEBUG */ #ifdef DEBUG_ERROR +// These macros are helper macros to make c compiler treat the debug macros like function calls so they do not alter any current code block structures when the macro contains if/else/break, etc. +#define __ERROR_BEGIN__ do{if(DEBUG_ERROR){ +#define __ERROR_END__ }}while(0) + #define PN5180ERROR(...) __ERROR_BEGIN__ if (!_pn5180_debugSilent) { if (!_pn5180_debugNL) Serial.print(F("\n"));; Serial.print(F("*** ERROR: ")); Serial.printf(__VA_ARGS__); Serial.print(F("\n"));}; __ERROR_END__ -#else -#define PN5180ERROR(...) #endif /* DEBUG_ERROR */ extern char * formatHex(const uint8_t val); extern char * formatHex(const uint16_t val); extern char * formatHex(const uint32_t val); +#else /* defined(DEBUG) || defined(DEBUG_ERROR) */ #endif /* defined(DEBUG) || defined(DEBUG_ERROR) */ +#ifndef DEBUG +#define PN5180DEBUG_OFF +#define PN5180DEBUG_ON +#define PN5180DEBUG_ENTER +#define PN5180DEBUG_EXIT +#define PN5180DEBUG_INDENT +#define PN5180DEBUG_PRINTLN(...) +#define PN5180DEBUG_PRINTF(...) +#define PN5180DEBUG_PRINT(...) +#define PN5180DEBUG(msg) +#endif + +#ifndef DEBUG_ERROR +#define PN5180ERROR(...) +#endif + #endif /* DEBUG_H */