From ca049693204ac2598cf78bb92f3af9321baa2759 Mon Sep 17 00:00:00 2001 From: Torsten Stauder Date: Tue, 15 Jun 2021 00:36:14 +0200 Subject: [PATCH] Added interrupt-handling for PCA9555 --- src/Button.cpp | 2 +- src/LogMessages_DE.cpp | 1 + src/LogMessages_EN.cpp | 1 + src/Port.cpp | 53 ++++++++++++++++++++++++++---------- src/logmessages.h | 1 + src/main.cpp | 4 +-- src/settings-complete.h | 6 ++++ src/settings-custom.h | 11 ++++++++ src/settings-espa1s.h | 6 ++++ src/settings-lolin32.h | 6 ++++ src/settings-lolin_d32.h | 6 ++++ src/settings-lolin_d32_pro.h | 6 ++++ src/settings-ttgo_t8.h | 6 ++++ src/settings.h | 1 - 14 files changed, 91 insertions(+), 19 deletions(-) diff --git a/src/Button.cpp b/src/Button.cpp index 90b0e1e..6e5f086 100644 --- a/src/Button.cpp +++ b/src/Button.cpp @@ -129,7 +129,7 @@ void Button_Cyclic() { unsigned long currentTimestamp = millis(); #ifdef PORT_EXPANDER_ENABLE - Port_Cyclic(); // todo: probably change behaviour to read from port-expander via interrupt + Port_Cyclic(); #endif // Buttons can be mixed between GPIO and port-expander. diff --git a/src/LogMessages_DE.cpp b/src/LogMessages_DE.cpp index 7ab2c91..0c69293 100644 --- a/src/LogMessages_DE.cpp +++ b/src/LogMessages_DE.cpp @@ -187,5 +187,6 @@ const char newPlayModeMono[] PROGMEM = "Neuer Modus: mono"; const char portExpanderFound[] PROGMEM = "Port-expander gefunden"; const char portExpanderNotFound[] PROGMEM = "Port-expander nicht gefunden"; + const char portExpanderInterruptEnabled[] PROGMEM = "Interrupt für Port-Expander aktiviert"; #endif diff --git a/src/LogMessages_EN.cpp b/src/LogMessages_EN.cpp index ada7ba5..92afc14 100644 --- a/src/LogMessages_EN.cpp +++ b/src/LogMessages_EN.cpp @@ -187,5 +187,6 @@ const char newPlayModeMono[] PROGMEM = "New mode: mono"; const char portExpanderFound[] PROGMEM = "Port-expander found"; const char portExpanderNotFound[] PROGMEM = "Unable to detect port-expander"; + const char portExpanderInterruptEnabled[] PROGMEM = "Enabled interrupt-handling for port-expander"; #endif diff --git a/src/Port.cpp b/src/Port.cpp index 6a96f91..6dc08ed 100644 --- a/src/Port.cpp +++ b/src/Port.cpp @@ -16,12 +16,19 @@ #ifdef PORT_EXPANDER_ENABLE extern TwoWire i2cBusTwo; - uint8_t Port_ExpanderPortsInputChannelStatus[portsToRead]; + uint8_t Port_ExpanderPortsInputChannelStatus[2]; static uint8_t Port_ExpanderPortsOutputChannelStatus[2] = {255, 255}; // Stores current configuration of output-channels locally - bool Port_ExpanderHandler(void); + void Port_ExpanderHandler(void); uint8_t Port_ChannelToBit(const uint8_t _channel); void Port_WriteInitMaskForOutputChannels(void); void Port_Test(void); + + #if (PE_INTERRUPT_PIN >= 0 && PE_INTERRUPT_PIN <= 39) + #define PE_INTERRUPT_PIN_ENABLE + void IRAM_ATTR PORT_ExpanderISR(void); + bool Port_AllowReadFromPortExpander = false; + bool Port_AllowInitReadFromPortExpander = true; + #endif #endif void Port_Init(void) { @@ -30,6 +37,12 @@ void Port_Init(void) { Port_WriteInitMaskForOutputChannels(); #endif + #ifdef PE_INTERRUPT_PIN_ENABLE + pinMode(PE_INTERRUPT_PIN, INPUT_PULLUP); + attachInterrupt(PE_INTERRUPT_PIN, PORT_ExpanderISR, FALLING); + Log_Println(portExpanderInterruptEnabled, LOGLEVEL_NOTICE); + #endif + // If automatic HP-detection is not used... #ifndef HEADPHONE_ADJUST_ENABLE #ifdef GPIO_PA_EN @@ -59,11 +72,8 @@ bool Port_Read(const uint8_t _channel) { return (Port_ExpanderPortsInputChannelStatus[0] & (1 << (_channel - 100))); // Remove offset 100 (return false if pressed) case 108 ... 115: // Port-expander (port 1) - if (portsToRead == 2) { // Make sure portsToRead != 1 when channel > 107 - return (Port_ExpanderPortsInputChannelStatus[1] & (1 << (_channel - 108))); // Remove offset 100 + 8 (return false if pressed) - } else { - return true; - } + return (Port_ExpanderPortsInputChannelStatus[1] & (1 << (_channel - 108))); // Remove offset 100 + 8 (return false if pressed) + #endif default: // Everything else (doesn't make sense at all) isn't supposed to be pressed @@ -196,7 +206,7 @@ void Port_Write(const uint8_t _channel, const bool _newState) { // So in order to change I/O-direction to output we need to set those bits to 0. OutputBitMaskAsPerPort[0] &= ~(1 << Port_ChannelToBit(GPIO_PA_EN)); //Serial.printf("PA LO: %u\n", OutputBitMaskAsPerPort[0]); - } else if ((GPIO_PA_EN >= 108 && GPIO_PA_EN <= 115) && portsToRead > 1) { + } else if (GPIO_PA_EN >= 108 && GPIO_PA_EN <= 115) { OutputBitMaskAsPerPort[1] &= ~(1 << Port_ChannelToBit(GPIO_PA_EN)); //Serial.printf("PA HI: %u\n", OutputBitMaskAsPerPort[1]); } @@ -206,7 +216,7 @@ void Port_Write(const uint8_t _channel, const bool _newState) { if (GPIO_HP_EN >= 100 && GPIO_HP_EN <= 107) { OutputBitMaskAsPerPort[0] &= ~(1 << Port_ChannelToBit(GPIO_HP_EN)); //Serial.printf("HP LO: %u\n", OutputBitMaskAsPerPort[0]); - } else if ((GPIO_HP_EN >= 108 && GPIO_HP_EN <= 115) && portsToRead > 1) { + } else if (GPIO_HP_EN >= 108 && GPIO_HP_EN <= 115) { OutputBitMaskAsPerPort[1] &= ~(1 << Port_ChannelToBit(GPIO_HP_EN)); //Serial.printf("HP HI: %u\n", OutputBitMaskAsPerPort[1]); } @@ -232,23 +242,30 @@ void Port_Write(const uint8_t _channel, const bool _newState) { // Reads input from port-expander and writes output into global array // Datasheet: https://www.nxp.com/docs/en/data-sheet/PCA9555.pdf - bool Port_ExpanderHandler() { + void Port_ExpanderHandler(void) { + // 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) { + return; + } else { + Port_AllowReadFromPortExpander = false; + Port_AllowInitReadFromPortExpander = false; + } + #endif + i2cBusTwo.beginTransmission(expanderI2cAddress); - for (uint8_t i = 0; i < portsToRead; i++) { + 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(); - } else { - return false; } } - return false; } - // Tests if port-expander can be detected + // Tests if port-expander can be detected at address configured void Port_Test(void) { i2cBusTwo.beginTransmission(expanderI2cAddress); i2cBusTwo.write(0x02); @@ -258,4 +275,10 @@ void Port_Write(const uint8_t _channel, const bool _newState) { Log_Println(portExpanderNotFound, LOGLEVEL_ERROR); } } + + #ifdef PE_INTERRUPT_PIN_ENABLE + void IRAM_ATTR PORT_ExpanderISR(void) { + Port_AllowReadFromPortExpander = true; + } + #endif #endif \ No newline at end of file diff --git a/src/logmessages.h b/src/logmessages.h index ea1008a..7e77a84 100644 --- a/src/logmessages.h +++ b/src/logmessages.h @@ -183,3 +183,4 @@ extern const char newPlayModeStereo[]; extern const char newPlayModeMono[]; extern const char portExpanderFound[]; extern const char portExpanderNotFound[]; +extern const char portExpanderInterruptEnabled[]; diff --git a/src/main.cpp b/src/main.cpp index f265bde..0b5dc8e 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -150,7 +150,7 @@ void setup() Serial.println(F(" | |___ ___) | | __/ | |_| | | | | | | | | (_) |")); Serial.println(F(" |_____| |____/ |_| \\__,_| |_| |_| |_| \\___/ ")); Serial.println(F(" Rfid-controlled musicplayer\n")); - Serial.println(F(" Rev 20210608-1\n")); + Serial.println(F(" Rev 20210615-1\n")); // print wake-up reason printWakeUpReason(); @@ -169,7 +169,7 @@ void setup() } Queues_Init(); - #if defined(GPIO_PA_EN) || defined(GPIO_HP_EN) + #ifdef PORT_EXPANDER_ENABLE Port_Init(); #endif Ftp_Init(); diff --git a/src/settings-complete.h b/src/settings-complete.h index 4962e62..ca62335 100644 --- a/src/settings-complete.h +++ b/src/settings-complete.h @@ -64,6 +64,12 @@ #define BUTTON_4 101 // Button 4: unnamed optional button #define BUTTON_5 104 // Button 5: unnamed optional button +// Channels of port-expander can be read cyclic or interrupt-driven. It's strongly recommended to use the interrupt-way! +// Infos: https://forum.espuino.de/t/einsatz-des-port-expanders-pca9555/306 +#ifdef PORT_EXPANDER_ENABLE + #define PE_INTERRUPT_PIN 4 // GPIO that is used to receive interrupts from port-expander +#endif + // I2C-configuration (necessary for RC522 [only via i2c - not spi!] or port-expander) #if defined(RFID_READER_TYPE_MFRC522_I2C) || defined(PORT_EXPANDER_ENABLE) #define ext_IIC_CLK 33 // i2c-SCL (clock) diff --git a/src/settings-custom.h b/src/settings-custom.h index b88dd40..bb7e653 100644 --- a/src/settings-custom.h +++ b/src/settings-custom.h @@ -52,6 +52,10 @@ #define DREHENCODER_BUTTON 32 // (set to 99 to disable; 0->39 for GPIO; 100->115 for port-expander) #endif + // Amp enable (optional) + //#define GPIO_PA_EN 112 // To enable amp for loudspeaker (GPIO or port-channel) + //#define GPIO_HP_EN 113 // To enable amp for headphones (GPIO or port-channel) + // Control-buttons (set to 99 to DISABLE; 0->39 for GPIO; 100->115 for port-expander) #define NEXT_BUTTON 4 // Button 0: GPIO to detect next #define PREVIOUS_BUTTON 2 // Button 1: GPIO to detect previous (Important: as of 19.11.2020 changed from 33 to 2; make sure to change in SD-MMC-mode) @@ -59,6 +63,12 @@ #define BUTTON_4 99 // Button 4: unnamed optional button #define BUTTON_5 99 // Button 5: unnamed optional button + // Channels of port-expander can be read cyclic or interrupt-driven. It's strongly recommended to use the interrupt-way! + // Infos: https://forum.espuino.de/t/einsatz-des-port-expanders-pca9555/306 + #ifdef PORT_EXPANDER_ENABLE + #define PE_INTERRUPT_PIN 99 // GPIO that is used to receive interrupts from port-expander + #endif + // I2C-configuration (necessary for RC522 [only via i2c - not spi!] or port-expander) #if defined(RFID_READER_TYPE_MFRC522_I2C) || defined(PORT_EXPANDER_ENABLE) #define ext_IIC_CLK 4 // i2c-SCL (clock) @@ -78,6 +88,7 @@ // (optinal) Headphone-detection #ifdef HEADPHONE_ADJUST_ENABLE + //#define DETECT_HP_ON_HIGH // Per default headphones are supposed to be connected if HT_DETECT is LOW. DETECT_HP_ON_HIGH will change this behaviour to HIGH. #define HP_DETECT 22 // GPIO that detects, if there's a plug in the headphone jack or not #endif diff --git a/src/settings-espa1s.h b/src/settings-espa1s.h index 3e947cb..5ad9ccf 100644 --- a/src/settings-espa1s.h +++ b/src/settings-espa1s.h @@ -68,6 +68,12 @@ #define BUTTON_4 99 // Button 4: unnamed optional button #define BUTTON_5 99 // Button 5: unnamed optional button + // Channels of port-expander can be read cyclic or interrupt-driven. It's strongly recommended to use the interrupt-way! + // Infos: https://forum.espuino.de/t/einsatz-des-port-expanders-pca9555/306 + #ifdef PORT_EXPANDER_ENABLE + #define PE_INTERRUPT_PIN 99 // GPIO that is used to receive interrupts from port-expander + #endif + // Wake-up button => this also is the interrupt-pin if port-expander is enabled! // Please note: only RTC-GPIOs (0, 4, 12, 13, 14, 15, 25, 26, 27, 32, 33, 34, 35, 36, 39, 99) can be used! Set to 99 to DISABLE. // Please note #2: this button can be used as interrupt-pin for port-expander. If so, all pins connected to port-expander can wake up ESPuino. diff --git a/src/settings-lolin32.h b/src/settings-lolin32.h index 828b6af..5350c31 100644 --- a/src/settings-lolin32.h +++ b/src/settings-lolin32.h @@ -70,6 +70,12 @@ #define BUTTON_4 99 // Button 4: unnamed optional button #define BUTTON_5 99 // Button 5: unnamed optional button +// Channels of port-expander can be read cyclic or interrupt-driven. It's strongly recommended to use the interrupt-way! +// Infos: https://forum.espuino.de/t/einsatz-des-port-expanders-pca9555/306 +#ifdef PORT_EXPANDER_ENABLE + #define PE_INTERRUPT_PIN 99 // GPIO that is used to receive interrupts from port-expander +#endif + // I2C-configuration (necessary for RC522 [only via i2c - not spi!] or port-expander) #if defined(RFID_READER_TYPE_MFRC522_I2C) || defined(PORT_EXPANDER_ENABLE) #define ext_IIC_CLK 5 // i2c-SCL (clock) diff --git a/src/settings-lolin_d32.h b/src/settings-lolin_d32.h index a838543..e59583c 100644 --- a/src/settings-lolin_d32.h +++ b/src/settings-lolin_d32.h @@ -70,6 +70,12 @@ #define BUTTON_4 99 // Button 4: unnamed optional button #define BUTTON_5 99 // Button 5: unnamed optional button + // Channels of port-expander can be read cyclic or interrupt-driven. It's strongly recommended to use the interrupt-way! + // Infos: https://forum.espuino.de/t/einsatz-des-port-expanders-pca9555/306 + #ifdef PORT_EXPANDER_ENABLE + #define PE_INTERRUPT_PIN 99 // GPIO that is used to receive interrupts from port-expander + #endif + // I2C-configuration (necessary for RC522 [only via i2c - not spi!] or port-expander) #if defined(RFID_READER_TYPE_MFRC522_I2C) || defined(PORT_EXPANDER_ENABLE) #define ext_IIC_CLK 5 // i2c-SCL (clock) diff --git a/src/settings-lolin_d32_pro.h b/src/settings-lolin_d32_pro.h index 8e088c0..7057a05 100644 --- a/src/settings-lolin_d32_pro.h +++ b/src/settings-lolin_d32_pro.h @@ -65,6 +65,12 @@ #define BUTTON_4 99 // Button 4: unnamed optional button #define BUTTON_5 99 // Button 5: unnamed optional button + // Channels of port-expander can be read cyclic or interrupt-driven. It's strongly recommended to use the interrupt-way! + // Infos: https://forum.espuino.de/t/einsatz-des-port-expanders-pca9555/306 + #ifdef PORT_EXPANDER_ENABLE + #define PE_INTERRUPT_PIN 99 // GPIO that is used to receive interrupts from port-expander + #endif + // I2C-configuration (necessary for RC522 [only via i2c - not spi!] or port-expander) #if defined(RFID_READER_TYPE_MFRC522_I2C) || defined(PORT_EXPANDER_ENABLE) #define ext_IIC_CLK 5 // i2c-SCL (clock) diff --git a/src/settings-ttgo_t8.h b/src/settings-ttgo_t8.h index eacb6d3..c7d76ec 100644 --- a/src/settings-ttgo_t8.h +++ b/src/settings-ttgo_t8.h @@ -65,6 +65,12 @@ #define BUTTON_4 99 // Button 4: unnamed optional button #define BUTTON_5 99 // Button 5: unnamed optional button +// Channels of port-expander can be read cyclic or interrupt-driven. It's strongly recommended to use the interrupt-way! +// Infos: https://forum.espuino.de/t/einsatz-des-port-expanders-pca9555/306 +#ifdef PORT_EXPANDER_ENABLE + #define PE_INTERRUPT_PIN 99 // GPIO that is used to receive interrupts from port-expander +#endif + // I2C-configuration (necessary for RC522 [only via i2c - not spi!] or port-expander) #if defined(RFID_READER_TYPE_MFRC522_I2C) || defined(PORT_EXPANDER_ENABLE) #define ext_IIC_CLK 5 // i2c-SCL (clock) diff --git a/src/settings.h b/src/settings.h index 83682e5..e265593 100644 --- a/src/settings.h +++ b/src/settings.h @@ -68,7 +68,6 @@ //############# Port-expander-configuration ###################### #ifdef PORT_EXPANDER_ENABLE - constexpr const uint8_t portsToRead = 2; // PCA9555 has two ports à 8 channels. If 8 channels are sufficient, set to 1 and only use the first port! constexpr uint8_t expanderI2cAddress = 0x20; // I2C-address of PCA9555 #endif