Browse Source

Added interrupt-handling for PCA9555

master
Torsten Stauder 4 years ago
parent
commit
ca04969320
  1. 2
      src/Button.cpp
  2. 1
      src/LogMessages_DE.cpp
  3. 1
      src/LogMessages_EN.cpp
  4. 51
      src/Port.cpp
  5. 1
      src/logmessages.h
  6. 4
      src/main.cpp
  7. 6
      src/settings-complete.h
  8. 11
      src/settings-custom.h
  9. 6
      src/settings-espa1s.h
  10. 6
      src/settings-lolin32.h
  11. 6
      src/settings-lolin_d32.h
  12. 6
      src/settings-lolin_d32_pro.h
  13. 6
      src/settings-ttgo_t8.h
  14. 1
      src/settings.h

2
src/Button.cpp

@ -129,7 +129,7 @@ void Button_Cyclic() {
unsigned long currentTimestamp = millis(); unsigned long currentTimestamp = millis();
#ifdef PORT_EXPANDER_ENABLE #ifdef PORT_EXPANDER_ENABLE
Port_Cyclic(); // todo: probably change behaviour to read from port-expander via interrupt
Port_Cyclic();
#endif #endif
// Buttons can be mixed between GPIO and port-expander. // Buttons can be mixed between GPIO and port-expander.

1
src/LogMessages_DE.cpp

@ -187,5 +187,6 @@
const char newPlayModeMono[] PROGMEM = "Neuer Modus: mono"; const char newPlayModeMono[] PROGMEM = "Neuer Modus: mono";
const char portExpanderFound[] PROGMEM = "Port-expander gefunden"; const char portExpanderFound[] PROGMEM = "Port-expander gefunden";
const char portExpanderNotFound[] PROGMEM = "Port-expander nicht gefunden"; const char portExpanderNotFound[] PROGMEM = "Port-expander nicht gefunden";
const char portExpanderInterruptEnabled[] PROGMEM = "Interrupt für Port-Expander aktiviert";
#endif #endif

1
src/LogMessages_EN.cpp

@ -187,5 +187,6 @@
const char newPlayModeMono[] PROGMEM = "New mode: mono"; const char newPlayModeMono[] PROGMEM = "New mode: mono";
const char portExpanderFound[] PROGMEM = "Port-expander found"; const char portExpanderFound[] PROGMEM = "Port-expander found";
const char portExpanderNotFound[] PROGMEM = "Unable to detect port-expander"; const char portExpanderNotFound[] PROGMEM = "Unable to detect port-expander";
const char portExpanderInterruptEnabled[] PROGMEM = "Enabled interrupt-handling for port-expander";
#endif #endif

51
src/Port.cpp

@ -16,12 +16,19 @@
#ifdef PORT_EXPANDER_ENABLE #ifdef PORT_EXPANDER_ENABLE
extern TwoWire i2cBusTwo; 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 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); uint8_t Port_ChannelToBit(const uint8_t _channel);
void Port_WriteInitMaskForOutputChannels(void); void Port_WriteInitMaskForOutputChannels(void);
void Port_Test(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 #endif
void Port_Init(void) { void Port_Init(void) {
@ -30,6 +37,12 @@ void Port_Init(void) {
Port_WriteInitMaskForOutputChannels(); Port_WriteInitMaskForOutputChannels();
#endif #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... // If automatic HP-detection is not used...
#ifndef HEADPHONE_ADJUST_ENABLE #ifndef HEADPHONE_ADJUST_ENABLE
#ifdef GPIO_PA_EN #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) return (Port_ExpanderPortsInputChannelStatus[0] & (1 << (_channel - 100))); // Remove offset 100 (return false if pressed)
case 108 ... 115: // Port-expander (port 1) 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) return (Port_ExpanderPortsInputChannelStatus[1] & (1 << (_channel - 108))); // Remove offset 100 + 8 (return false if pressed)
} else {
return true;
}
#endif #endif
default: // Everything else (doesn't make sense at all) isn't supposed to be pressed 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. // 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)); OutputBitMaskAsPerPort[0] &= ~(1 << Port_ChannelToBit(GPIO_PA_EN));
//Serial.printf("PA LO: %u\n", OutputBitMaskAsPerPort[0]); //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)); OutputBitMaskAsPerPort[1] &= ~(1 << Port_ChannelToBit(GPIO_PA_EN));
//Serial.printf("PA HI: %u\n", OutputBitMaskAsPerPort[1]); //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) { if (GPIO_HP_EN >= 100 && GPIO_HP_EN <= 107) {
OutputBitMaskAsPerPort[0] &= ~(1 << Port_ChannelToBit(GPIO_HP_EN)); OutputBitMaskAsPerPort[0] &= ~(1 << Port_ChannelToBit(GPIO_HP_EN));
//Serial.printf("HP LO: %u\n", OutputBitMaskAsPerPort[0]); //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)); OutputBitMaskAsPerPort[1] &= ~(1 << Port_ChannelToBit(GPIO_HP_EN));
//Serial.printf("HP HI: %u\n", OutputBitMaskAsPerPort[1]); //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 // Reads input from port-expander and writes output into global array
// Datasheet: https://www.nxp.com/docs/en/data-sheet/PCA9555.pdf // 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); 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.write(0x00 + i); // Pointer to input-register...
i2cBusTwo.endTransmission(); i2cBusTwo.endTransmission();
i2cBusTwo.requestFrom(expanderI2cAddress, 1u); // ...and read its byte i2cBusTwo.requestFrom(expanderI2cAddress, 1u); // ...and read its byte
if (i2cBusTwo.available()) { if (i2cBusTwo.available()) {
Port_ExpanderPortsInputChannelStatus[i] = i2cBusTwo.read(); 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) { void Port_Test(void) {
i2cBusTwo.beginTransmission(expanderI2cAddress); i2cBusTwo.beginTransmission(expanderI2cAddress);
i2cBusTwo.write(0x02); i2cBusTwo.write(0x02);
@ -258,4 +275,10 @@ void Port_Write(const uint8_t _channel, const bool _newState) {
Log_Println(portExpanderNotFound, LOGLEVEL_ERROR); Log_Println(portExpanderNotFound, LOGLEVEL_ERROR);
} }
} }
#ifdef PE_INTERRUPT_PIN_ENABLE
void IRAM_ATTR PORT_ExpanderISR(void) {
Port_AllowReadFromPortExpander = true;
}
#endif
#endif #endif

1
src/logmessages.h

@ -183,3 +183,4 @@ extern const char newPlayModeStereo[];
extern const char newPlayModeMono[]; extern const char newPlayModeMono[];
extern const char portExpanderFound[]; extern const char portExpanderFound[];
extern const char portExpanderNotFound[]; extern const char portExpanderNotFound[];
extern const char portExpanderInterruptEnabled[];

4
src/main.cpp

@ -150,7 +150,7 @@ void setup()
Serial.println(F(" | |___ ___) | | __/ | |_| | | | | | | | | (_) |")); Serial.println(F(" | |___ ___) | | __/ | |_| | | | | | | | | (_) |"));
Serial.println(F(" |_____| |____/ |_| \\__,_| |_| |_| |_| \\___/ ")); Serial.println(F(" |_____| |____/ |_| \\__,_| |_| |_| |_| \\___/ "));
Serial.println(F(" Rfid-controlled musicplayer\n")); 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 // print wake-up reason
printWakeUpReason(); printWakeUpReason();
@ -169,7 +169,7 @@ void setup()
} }
Queues_Init(); Queues_Init();
#if defined(GPIO_PA_EN) || defined(GPIO_HP_EN)
#ifdef PORT_EXPANDER_ENABLE
Port_Init(); Port_Init();
#endif #endif
Ftp_Init(); Ftp_Init();

6
src/settings-complete.h

@ -64,6 +64,12 @@
#define BUTTON_4 101 // Button 4: unnamed optional button #define BUTTON_4 101 // Button 4: unnamed optional button
#define BUTTON_5 104 // Button 5: 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) // I2C-configuration (necessary for RC522 [only via i2c - not spi!] or port-expander)
#if defined(RFID_READER_TYPE_MFRC522_I2C) || defined(PORT_EXPANDER_ENABLE) #if defined(RFID_READER_TYPE_MFRC522_I2C) || defined(PORT_EXPANDER_ENABLE)
#define ext_IIC_CLK 33 // i2c-SCL (clock) #define ext_IIC_CLK 33 // i2c-SCL (clock)

11
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) #define DREHENCODER_BUTTON 32 // (set to 99 to disable; 0->39 for GPIO; 100->115 for port-expander)
#endif #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) // 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 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) #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_4 99 // Button 4: unnamed optional button
#define BUTTON_5 99 // Button 5: 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) // I2C-configuration (necessary for RC522 [only via i2c - not spi!] or port-expander)
#if defined(RFID_READER_TYPE_MFRC522_I2C) || defined(PORT_EXPANDER_ENABLE) #if defined(RFID_READER_TYPE_MFRC522_I2C) || defined(PORT_EXPANDER_ENABLE)
#define ext_IIC_CLK 4 // i2c-SCL (clock) #define ext_IIC_CLK 4 // i2c-SCL (clock)
@ -78,6 +88,7 @@
// (optinal) Headphone-detection // (optinal) Headphone-detection
#ifdef HEADPHONE_ADJUST_ENABLE #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 #define HP_DETECT 22 // GPIO that detects, if there's a plug in the headphone jack or not
#endif #endif

6
src/settings-espa1s.h

@ -68,6 +68,12 @@
#define BUTTON_4 99 // Button 4: unnamed optional button #define BUTTON_4 99 // Button 4: unnamed optional button
#define BUTTON_5 99 // Button 5: 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! // 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: 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. // 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.

6
src/settings-lolin32.h

@ -70,6 +70,12 @@
#define BUTTON_4 99 // Button 4: unnamed optional button #define BUTTON_4 99 // Button 4: unnamed optional button
#define BUTTON_5 99 // Button 5: 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) // I2C-configuration (necessary for RC522 [only via i2c - not spi!] or port-expander)
#if defined(RFID_READER_TYPE_MFRC522_I2C) || defined(PORT_EXPANDER_ENABLE) #if defined(RFID_READER_TYPE_MFRC522_I2C) || defined(PORT_EXPANDER_ENABLE)
#define ext_IIC_CLK 5 // i2c-SCL (clock) #define ext_IIC_CLK 5 // i2c-SCL (clock)

6
src/settings-lolin_d32.h

@ -70,6 +70,12 @@
#define BUTTON_4 99 // Button 4: unnamed optional button #define BUTTON_4 99 // Button 4: unnamed optional button
#define BUTTON_5 99 // Button 5: 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) // I2C-configuration (necessary for RC522 [only via i2c - not spi!] or port-expander)
#if defined(RFID_READER_TYPE_MFRC522_I2C) || defined(PORT_EXPANDER_ENABLE) #if defined(RFID_READER_TYPE_MFRC522_I2C) || defined(PORT_EXPANDER_ENABLE)
#define ext_IIC_CLK 5 // i2c-SCL (clock) #define ext_IIC_CLK 5 // i2c-SCL (clock)

6
src/settings-lolin_d32_pro.h

@ -65,6 +65,12 @@
#define BUTTON_4 99 // Button 4: unnamed optional button #define BUTTON_4 99 // Button 4: unnamed optional button
#define BUTTON_5 99 // Button 5: 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) // I2C-configuration (necessary for RC522 [only via i2c - not spi!] or port-expander)
#if defined(RFID_READER_TYPE_MFRC522_I2C) || defined(PORT_EXPANDER_ENABLE) #if defined(RFID_READER_TYPE_MFRC522_I2C) || defined(PORT_EXPANDER_ENABLE)
#define ext_IIC_CLK 5 // i2c-SCL (clock) #define ext_IIC_CLK 5 // i2c-SCL (clock)

6
src/settings-ttgo_t8.h

@ -65,6 +65,12 @@
#define BUTTON_4 99 // Button 4: unnamed optional button #define BUTTON_4 99 // Button 4: unnamed optional button
#define BUTTON_5 99 // Button 5: 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) // I2C-configuration (necessary for RC522 [only via i2c - not spi!] or port-expander)
#if defined(RFID_READER_TYPE_MFRC522_I2C) || defined(PORT_EXPANDER_ENABLE) #if defined(RFID_READER_TYPE_MFRC522_I2C) || defined(PORT_EXPANDER_ENABLE)
#define ext_IIC_CLK 5 // i2c-SCL (clock) #define ext_IIC_CLK 5 // i2c-SCL (clock)

1
src/settings.h

@ -68,7 +68,6 @@
//############# Port-expander-configuration ###################### //############# Port-expander-configuration ######################
#ifdef PORT_EXPANDER_ENABLE #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 constexpr uint8_t expanderI2cAddress = 0x20; // I2C-address of PCA9555
#endif #endif

Loading…
Cancel
Save