#include #include #include #include "settings.h" #include "Rfid.h" #include "Log.h" #include "MemX.h" #include "Queues.h" #include "System.h" #include "Port.h" #ifdef RFID_READER_TYPE_PN5180 #include #include #include #endif #define RFID_PN5180_STATE_INIT 0u #define RFID_PN5180_NFC14443_STATE_RESET 1u #define RFID_PN5180_NFC14443_STATE_SETUPRF 2u #define RFID_PN5180_NFC14443_STATE_READCARD 3u #define RFID_PN5180_NFC14443_STATE_ACTIVE 99u #define RFID_PN5180_NFC15693_STATE_RESET 4u #define RFID_PN5180_NFC15693_STATE_SETUPRF 5u #define RFID_PN5180_NFC15693_STATE_DISABLEPRIVACYMODE 6u #define RFID_PN5180_NFC15693_STATE_GETINVENTORY 7u #define RFID_PN5180_NFC15693_STATE_ACTIVE 100u extern unsigned long Rfid_LastRfidCheckTimestamp; #ifdef RFID_READER_TYPE_PN5180 static void Rfid_Read(void); void Rfid_Init(void) { #ifdef PN5180_ENABLE_LPCD // disable pin hold from deep sleep gpio_deep_sleep_hold_dis(); gpio_hold_dis(gpio_num_t(RFID_CS)); // NSS gpio_hold_dis(gpio_num_t(RFID_RST)); // RST #endif } void Rfid_Cyclic(void) { Rfid_Read(); vTaskDelay(5u); } void Rfid_Read(void) { static PN5180ISO14443 nfc14443(RFID_CS, RFID_BUSY, RFID_RST); static PN5180ISO15693 nfc15693(RFID_CS, RFID_BUSY, RFID_RST); static uint32_t lastTimeDetected14443 = 0; static uint32_t lastTimeDetected15693 = 0; static uint8_t stateMachine = RFID_PN5180_STATE_INIT; static byte cardId[cardIdSize], lastCardId[cardIdSize]; uint8_t uid[10]; String cardIdString; bool cardReceived = false; if (RFID_PN5180_STATE_INIT == stateMachine) { nfc14443.begin(); nfc14443.reset(); // show PN5180 reader version uint8_t firmwareVersion[2]; nfc14443.readEEprom(FIRMWARE_VERSION, firmwareVersion, sizeof(firmwareVersion)); Serial.print(F("Firmware version=")); Serial.print(firmwareVersion[1]); Serial.print("."); Serial.println(firmwareVersion[0]); // activate RF field delay(4u); Log_Println((char *) FPSTR(rfidScannerReady), LOGLEVEL_DEBUG); // 1. check for an ISO-14443 card } else if (RFID_PN5180_NFC14443_STATE_RESET == stateMachine) { nfc14443.reset(); } else if (RFID_PN5180_NFC14443_STATE_SETUPRF == stateMachine) { nfc14443.setupRF(); } else if (RFID_PN5180_NFC14443_STATE_READCARD == stateMachine) { if (nfc14443.readCardSerial(uid) >= 4u) { cardReceived = true; stateMachine = RFID_PN5180_NFC14443_STATE_ACTIVE; lastTimeDetected14443 = millis(); } else { // Reset to dummy-value if no card is there // Necessary to differentiate between "card is still applied" and "card is re-applied again after removal" // lastTimeDetected14443 is used to prevent "new card detection with old card" with single events where no card was detected if (!lastTimeDetected14443 || (millis() - lastTimeDetected14443 >= 400)) { lastTimeDetected14443 = 0; for (uint8_t i=0; i= 400)) { lastTimeDetected15693 = 0; for (uint8_t i=0; i RFID_PN5180_NFC15693_STATE_GETINVENTORY) { stateMachine = RFID_PN5180_NFC14443_STATE_RESET; } } } void Rfid_Exit(void) { // goto low power card detection mode #ifdef PN5180_ENABLE_LPCD static PN5180 nfc(RFID_CS, RFID_BUSY, RFID_RST); nfc.begin(); // show PN5180 reader version uint8_t firmwareVersion[2]; nfc.readEEprom(FIRMWARE_VERSION, firmwareVersion, sizeof(firmwareVersion)); Serial.print(F("Firmware version=")); Serial.print(firmwareVersion[1]); Serial.print("."); Serial.println(firmwareVersion[0]); // check firmware version: PN5180 firmware < 4.0 has several bugs preventing the LPCD mode // you can flash latest firmware with this project: https://github.com/abidxraihan/PN5180_Updater_ESP32 if (firmwareVersion[1] < 4) { Serial.println(F("This PN5180 firmware does not work with LPCD! use firmware >= 4.0")); return; } Serial.println(F("prepare low power card detection...")); nfc.prepareLPCD(); nfc.clearIRQStatus(0xffffffff); Serial.print(F("PN5180 IRQ PIN: ")); Serial.println(Port_Read(RFID_IRQ)); // turn on LPCD uint16_t wakeupCounterInMs = 0x3FF; // must be in the range of 0x0 - 0xA82. max wake-up time is 2960 ms. if (nfc.switchToLPCD(wakeupCounterInMs)) { Serial.println(F("switch to low power card detection: success")); // configure wakeup pin for deep-sleep wake-up, use ext1 esp_sleep_enable_ext1_wakeup((1ULL << (RFID_IRQ)), ESP_EXT1_WAKEUP_ANY_HIGH); // freeze pin states in deep sleep gpio_hold_en(gpio_num_t(RFID_CS)); // CS/NSS gpio_hold_en(gpio_num_t(RFID_RST)); // RST gpio_deep_sleep_hold_en(); } else { Serial.println(F("switchToLPCD failed")); } #endif } // wake up from LPCD, check card is present. This works only for ISO-14443 compatible cards void Rfid_WakeupCheck(void) { #ifdef PN5180_ENABLE_LPCD static PN5180ISO14443 nfc14443(RFID_CS, RFID_BUSY, RFID_RST); nfc14443.begin(); nfc14443.reset(); nfc14443.setupRF(); if (!nfc14443.isCardPresent()) { nfc14443.clearIRQStatus(0xffffffff); Serial.print(F("Logic-level at PN5180's IRQ-PIN: ")); Serial.println(Port_Read(RFID_IRQ)); // turn on LPCD uint16_t wakeupCounterInMs = 0x3FF; // needs to be in the range of 0x0 - 0xA82. max wake-up time is 2960 ms. if (nfc14443.switchToLPCD(wakeupCounterInMs)) { Log_Println((char *) FPSTR(lowPowerCardSuccess), LOGLEVEL_INFO); // configure wakeup pin for deep-sleep wake-up, use ext1 esp_sleep_enable_ext1_wakeup((1ULL << (RFID_IRQ)), ESP_EXT1_WAKEUP_ANY_HIGH); // freeze pin states in deep sleep gpio_hold_en(gpio_num_t(RFID_CS)); // CS/NSS gpio_hold_en(gpio_num_t(RFID_RST)); // RST gpio_deep_sleep_hold_en(); Log_Println((char *) FPSTR(wakeUpRfidNoIso14443), LOGLEVEL_ERROR); esp_deep_sleep_start(); } else { Serial.println(F("switchToLPCD failed")); } } #endif } #endif