From b56c3b1592620b73537a9c3c84b5ce4f5f9d6bbe Mon Sep 17 00:00:00 2001 From: Torsten Stauder Date: Thu, 14 Oct 2021 22:54:04 +0200 Subject: [PATCH] Making LPCD compatible with port-expander + removing race-condition --- src/Port.cpp | 21 ++++++++++++++++-- src/Port.h | 3 ++- src/RfidPn5180.cpp | 54 +++++++++++++++++++++++++++++++++++++++++----- src/System.cpp | 1 + src/main.cpp | 1 + src/revision.h | 2 +- 6 files changed, 73 insertions(+), 9 deletions(-) diff --git a/src/Port.cpp b/src/Port.cpp index 6dc08ed..700c42f 100644 --- a/src/Port.cpp +++ b/src/Port.cpp @@ -246,10 +246,13 @@ void Port_Write(const uint8_t _channel, const bool _newState) { // If interrupt-handling is active, only ready port-expander's register if interrupt was fired #ifdef PE_INTERRUPT_PIN_ENABLE if (!Port_AllowReadFromPortExpander && !Port_AllowInitReadFromPortExpander) { + //Serial.println("Interrupt false!"); return; - } else { - Port_AllowReadFromPortExpander = false; + } else if (Port_AllowInitReadFromPortExpander) { Port_AllowInitReadFromPortExpander = false; + } else if (Port_AllowReadFromPortExpander || Port_AllowInitReadFromPortExpander) { + //Serial.println("Interrupt true!"); + Port_AllowReadFromPortExpander = false; } #endif @@ -265,6 +268,20 @@ void Port_Write(const uint8_t _channel, const bool _newState) { } } + // Make sure ports are read finally at shutdown in order to clear any active IRQs that could cause re-wakeup immediately + void Port_Exit(void) { + i2cBusTwo.beginTransmission(expanderI2cAddress); + for (uint8_t i = 0; i < 2; i++) { + i2cBusTwo.write(0x00 + i); // Pointer to input-register... + i2cBusTwo.endTransmission(); + i2cBusTwo.requestFrom(expanderI2cAddress, 1u); // ...and read its byte + + if (i2cBusTwo.available()) { + Port_ExpanderPortsInputChannelStatus[i] = i2cBusTwo.read(); + } + } + } + // Tests if port-expander can be detected at address configured void Port_Test(void) { i2cBusTwo.beginTransmission(expanderI2cAddress); diff --git a/src/Port.h b/src/Port.h index a85e6e2..e4456c7 100644 --- a/src/Port.h +++ b/src/Port.h @@ -5,4 +5,5 @@ void Port_Cyclic(void); bool Port_Read(const uint8_t _channel); void Port_Write(const uint8_t _channel, const bool _newState, const bool _initGpio); void Port_Write(const uint8_t _channel, const bool _newState); -bool Port_Detect_Mode_HP(bool _state); \ No newline at end of file +bool Port_Detect_Mode_HP(bool _state); +void Port_Exit(void); \ No newline at end of file diff --git a/src/RfidPn5180.cpp b/src/RfidPn5180.cpp index af9ebaa..bc43fab 100644 --- a/src/RfidPn5180.cpp +++ b/src/RfidPn5180.cpp @@ -34,6 +34,20 @@ extern unsigned long Rfid_LastRfidCheckTimestamp; #ifdef RFID_READER_TYPE_PN5180 static void Rfid_Task(void *parameter); + static TaskHandle_t rfidTaskHandle; + + #ifdef PN5180_ENABLE_LPCD + void Rfid_EnableLpcd(void); + bool enabledLpcdShutdown = false; // Indicates if LPCD should be activated as part of the shutdown-process + + void Rfid_SetLpcdShutdownStatus(bool lpcdStatus) { + enabledLpcdShutdown = lpcdStatus; + } + + bool Rfid_GetLpcdShutdownStatus(void) { + return enabledLpcdShutdown; + } + #endif void Rfid_Init(void) { #ifdef PN5180_ENABLE_LPCD @@ -41,7 +55,9 @@ extern unsigned long Rfid_LastRfidCheckTimestamp; gpio_deep_sleep_hold_dis(); gpio_hold_dis(gpio_num_t(RFID_CS)); // NSS gpio_hold_dis(gpio_num_t(RFID_RST)); // RST - pinMode(RFID_IRQ, INPUT); + #if (RFID_IRQ >= 0 && RFID_IRQ <= 39) + pinMode(RFID_IRQ, INPUT); // Not necessary for port-expander as for pca9555 all pins are configured as input per default + #endif #endif xTaskCreatePinnedToCore( @@ -50,7 +66,7 @@ extern unsigned long Rfid_LastRfidCheckTimestamp; 1536, /* Stack size in words */ NULL, /* Task input parameter */ 2 | portPRIVILEGE_BIT, /* Priority of the task */ - NULL, /* Task handle. */ + &rfidTaskHandle, /* Task handle. */ 0 /* Core where the task should run */ ); } @@ -75,6 +91,15 @@ extern unsigned long Rfid_LastRfidCheckTimestamp; for (;;) { vTaskDelay(portTICK_RATE_MS * 10u); + #ifdef PN5180_ENABLE_LPCD + if (Rfid_GetLpcdShutdownStatus()) { + Rfid_EnableLpcd(); + Rfid_SetLpcdShutdownStatus(false); // give feedback that execution is complete + while (true) { + vTaskDelay(portTICK_RATE_MS * 100u); // there's no way back if shutdown was initiated + } + } + #endif String cardIdString; bool cardReceived = false; #ifdef PAUSE_WHEN_RFID_REMOVED @@ -245,6 +270,17 @@ extern unsigned long Rfid_LastRfidCheckTimestamp; } void Rfid_Exit(void) { + #ifdef PN5180_ENABLE_LPCD + Rfid_SetLpcdShutdownStatus(true); + while (Rfid_GetLpcdShutdownStatus()) { // Make sure init of LPCD is complete! + vTaskDelay(portTICK_RATE_MS * 10u); + } + #endif + vTaskDelete(rfidTaskHandle); + } + + // Handles activation of LPCD (while shutdown is in progress) + void Rfid_EnableLpcd(void) { // goto low power card detection mode #ifdef PN5180_ENABLE_LPCD static PN5180 nfc(RFID_CS, RFID_BUSY, RFID_RST); @@ -263,8 +299,12 @@ extern unsigned long Rfid_LastRfidCheckTimestamp; return; } Serial.println(F("prepare low power card detection...")); + uint8_t irqConfig = 0b0000010; // Set IRQ active low + clear IRQ-register + nfc.writeEEprom(IRQ_PIN_CONFIG, &irqConfig, 1); + /*nfc.readEEprom(IRQ_PIN_CONFIG, &irqConfig, 1); + Serial.print(F("IRQ_PIN_CONFIG=0x")); + Serial.println(irqConfig, HEX);*/ nfc.prepareLPCD(); - nfc.clearIRQStatus(0xffffffff); Serial.print(F("PN5180 IRQ PIN: ")); Serial.println(Port_Read(RFID_IRQ)); // turn on LPCD @@ -272,7 +312,9 @@ extern unsigned long Rfid_LastRfidCheckTimestamp; 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); + #if (RFID_IRQ >= 0 && RFID_IRQ <= 39) + esp_sleep_enable_ext1_wakeup((1ULL << (RFID_IRQ)), ESP_EXT1_WAKEUP_ANY_HIGH); + #endif // 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 @@ -299,7 +341,9 @@ extern unsigned long Rfid_LastRfidCheckTimestamp; 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); + #if (RFID_IRQ >= 0 && RFID_IRQ <= 39) + esp_sleep_enable_ext1_wakeup((1ULL << (RFID_IRQ)), ESP_EXT1_WAKEUP_ANY_HIGH); + #endif // 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 diff --git a/src/System.cpp b/src/System.cpp index 03082bf..cc5907a 100644 --- a/src/System.cpp +++ b/src/System.cpp @@ -214,6 +214,7 @@ void System_DeepSleepManager(void) { digitalWrite(POWER, LOW); delay(200); Rfid_Exit(); + Port_Exit(); Serial.println(F("deep-sleep, good night.......")); esp_deep_sleep_start(); } diff --git a/src/main.cpp b/src/main.cpp index 103ab47..a74c69e 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -132,6 +132,7 @@ void setup() { Rfid_Init(); #endif // Check if wakeup-reason was card-detection (PN5180 only) + // This only works if RFID.IRQ is connected to a GPIO and not to a port-expander esp_sleep_wakeup_cause_t wakeup_reason = esp_sleep_get_wakeup_cause(); if (wakeup_reason == ESP_SLEEP_WAKEUP_EXT1) { Rfid_WakeupCheck(); diff --git a/src/revision.h b/src/revision.h index f46e5ec..3fec6f4 100644 --- a/src/revision.h +++ b/src/revision.h @@ -1,4 +1,4 @@ #ifndef __REVISION_H__ #define __REVISION_H__ - constexpr const char softwareRevision[] PROGMEM = "Software-revision: 20211007-1"; + constexpr const char softwareRevision[] PROGMEM = "Software-revision: 20211014-1"; #endif \ No newline at end of file