diff --git a/tasmota/tasmota_xdrv_driver/xdrv_28_pcf8574_v1.ino b/tasmota/tasmota_xdrv_driver/xdrv_28_pcf8574_v1.ino deleted file mode 100644 index 841da4e70..000000000 --- a/tasmota/tasmota_xdrv_driver/xdrv_28_pcf8574_v1.ino +++ /dev/null @@ -1,386 +0,0 @@ -/* - xdrv_28_pcf8574.ino - PCF8574 I2C support for Tasmota - - Copyright (C) 2021 Stefan Bode - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see . -*/ - -#ifdef USE_I2C -#ifdef USE_PCF8574_V1 -/*********************************************************************************************\ - * PCF8574 - I2C IO Expander - * - * I2C Address: PCF8574 = 0x20 .. 0x27 (0x27 is not supported), - * PCF8574A = 0x39 .. 0x3F (0x38 is not supported) -\*********************************************************************************************/ - -#define XDRV_28 28 -#define XI2C_02 2 // See I2CDEVICES.md - -// Start address and count can be overriden in user_config_override.h to allow better -// sharing of the I2C address space. Still the covered range must remains valid. -// A count of 0 can be used totaly disable any of the 2 ranges. -// By default, the following addresses are explicitly excluded (as per the docs) : -// - 0x27 and 0x37 are reserved for USE_DISPLAY_LCD in xdsp_01_lcd.ino -// - 0X38 is reserved for other sensors -// If the respective drivers are not used, overrides allows to recover those addresses -// If defined, USE_MCP230xx_ADDR is also always excluded - -// PCF8574 address range from 0x20 to 0x26 -#ifndef PCF8574_ADDR1 -#define PCF8574_ADDR1 0x20 // PCF8574 -#endif -#ifndef PCF8574_ADDR1_COUNT -#define PCF8574_ADDR1_COUNT 7 -#endif -// PCF8574A address range from 0x39 to 0x3E -#ifndef PCF8574_ADDR2 -#define PCF8574_ADDR2 0x39 // PCF8574A -#endif -#ifndef PCF8574_ADDR2_COUNT -#define PCF8574_ADDR2_COUNT 6 -#endif - -// Consitency tests - Checked across the complete range for the PCF8574/PCF8574A to allow override -#if (PCF8574_ADDR1 < 0x20) || ((PCF8574_ADDR1 + PCF8574_ADDR1_COUNT - 1) > 0x27) -#error PCF8574_ADDR1 and/or PCF8574_ADDR1_COUNT badly overriden. Fix your user_config_override -#endif -#if (PCF8574_ADDR2 < 0x38) || ((PCF8574_ADDR2 + PCF8574_ADDR2_COUNT - 1) > 0x3F) -#error PCF8574_ADDR2 and/or PCF8574_ADDR2_COUNT badly overriden. Fix your user_config_override. -#endif - -struct PCF8574 { - int error; - uint8_t pin[64]; - uint8_t address[MAX_PCF8574]; - uint8_t pin_mask[MAX_PCF8574] = { 0 }; -#ifdef USE_PCF8574_MQTTINPUT - uint8_t last_input[MAX_PCF8574] = { 0 }; -#endif - uint8_t max_connected_ports = 0; // Max numbers of devices comming from PCF8574 modules - uint8_t max_devices = 0; // Max numbers of PCF8574 modules - char stype[9]; - bool type = false; -} Pcf8574; - -uint8_t Pcf8574Read(uint8_t idx) -{ - Wire.requestFrom(Pcf8574.address[idx],(uint8_t)1); - return Wire.read(); -} - -uint8_t Pcf8574Write(uint8_t idx) -{ - Wire.beginTransmission(Pcf8574.address[idx]); - Wire.write(Pcf8574.pin_mask[idx]); - return Wire.endTransmission(); -} - -void Pcf8574SwitchRelay(void) -{ - for (uint32_t i = 0; i < TasmotaGlobal.devices_present; i++) { - uint8_t relay_state = bitRead(XdrvMailbox.index, i); - - if (Pcf8574.max_devices > 0 && Pcf8574.pin[i] < 99) { - uint8_t board = Pcf8574.pin[i]>>3; - uint8_t pin = Pcf8574.pin[i]&0x7; - uint8_t oldpinmask = Pcf8574.pin_mask[board]; - uint8_t _val = bitRead(TasmotaGlobal.rel_inverted, i) ? !relay_state : relay_state; - - //AddLog(LOG_LEVEL_DEBUG, PSTR("PCF: SwitchRelay %d=%d => PCF-%d.D%d=%d"), i, relay_state, board +1, pin, _val); - bitWrite(Pcf8574.pin_mask[board], pin, _val); - if (oldpinmask != Pcf8574.pin_mask[board]) { - Pcf8574.error = Pcf8574Write(board); - } - //else AddLog(LOG_LEVEL_DEBUG, PSTR("PCF: SwitchRelay skipped")); - } - } -} - -void Pcf8574Init(void) -{ - uint8_t pcf8574_address = (PCF8574_ADDR1_COUNT > 0) ? PCF8574_ADDR1 : PCF8574_ADDR2; - while ((Pcf8574.max_devices < MAX_PCF8574) && (pcf8574_address < PCF8574_ADDR2 +PCF8574_ADDR2_COUNT)) { - -#if defined(USE_MCP230xx) && defined(USE_MCP230xx_ADDR) - if (USE_MCP230xx_ADDR == pcf8574_address) { - AddLog(LOG_LEVEL_INFO, PSTR("PCF: Address 0x%02x reserved for MCP320xx skipped"), pcf8574_address); - pcf8574_address++; - if ((PCF8574_ADDR1 +PCF8574_ADDR1_COUNT) == pcf8574_address) { // See comment on allowed addresses and overrides - pcf8574_address = PCF8574_ADDR2; - } - } -#endif - - // AddLog(LOG_LEVEL_DEBUG, PSTR("PCF: Probing addr: 0x%x for PCF8574"), pcf8574_address); - - if (I2cSetDevice(pcf8574_address)) { - Pcf8574.type = true; - - Pcf8574.address[Pcf8574.max_devices] = pcf8574_address; - Pcf8574.max_devices++; - - strcpy(Pcf8574.stype, "PCF8574"); - if (pcf8574_address >= PCF8574_ADDR2) { - strcpy(Pcf8574.stype, "PCF8574A"); - } - I2cSetActiveFound(pcf8574_address, Pcf8574.stype); - } - - pcf8574_address++; - if ((PCF8574_ADDR1 +PCF8574_ADDR1_COUNT) == pcf8574_address) { // Support I2C addresses 0x20 to 0x26 and 0x39 to 0x3F - pcf8574_address = PCF8574_ADDR2; - } - } - if (Pcf8574.type) { - for (uint32_t i = 0; i < sizeof(Pcf8574.pin); i++) { - Pcf8574.pin[i] = 99; - } - UpdateDevicesPresent(-Pcf8574.max_connected_ports); // reset no of devices to avoid duplicate ports on duplicate init. - - Pcf8574.max_connected_ports = 0; // reset no of devices to avoid duplicate ports on duplicate init. - for (uint32_t idx = 0; idx < Pcf8574.max_devices; idx++) { // suport up to 8 boards PCF8574 - uint8_t gpio = Pcf8574Read(idx); - // Insure the input pins are actually writen a 1 for proper input operation - Pcf8574.pin_mask[idx] = gpio | ~Settings->pcf8574_config[idx]; - Pcf8574Write(idx); // Write back to the register -#ifdef USE_PCF8574_MQTTINPUT - Pcf8574.last_input[idx] = gpio & ~Settings->pcf8574_config[idx]; -#endif // #ifdef USE_PCF8574_MQTTINPUT - //AddLog(LOG_LEVEL_DEBUG, PSTR("PCF: PCF-%d config=0x%02x, gpio=0x%02X"), idx +1, Settings->pcf8574_config[idx], gpio); - - for (uint32_t i = 0; i < 8; i++, gpio>>=1) { - uint8_t _result = Settings->pcf8574_config[idx] >> i &1; - //AddLog(LOG_LEVEL_DEBUG, PSTR("PCF: I2C shift i %d: %d. Powerstate: %d, TasmotaGlobal.devices_present: %d"), i,_result, Settings->power>>i&1, TasmotaGlobal.devices_present); - if (_result > 0) { - Pcf8574.pin[TasmotaGlobal.devices_present] = i + 8 * idx; - bitWrite(TasmotaGlobal.rel_inverted, TasmotaGlobal.devices_present, Settings->flag3.pcf8574_ports_inverted); // SetOption81 - Invert all ports on PCF8574 devices - if (!Settings->flag.save_state && !Settings->flag3.no_power_feedback) { // SetOption63 - Don't scan relay power state at restart - #5594 and #5663 - //AddLog(LOG_LEVEL_DEBUG, PSTR("PCF: Set power from from chip state")); - uint8_t power_state = Settings->flag3.pcf8574_ports_inverted ? 1 & ~gpio : 1 & gpio; - bitWrite(TasmotaGlobal.power, TasmotaGlobal.devices_present, power_state); - bitWrite(Settings->power, TasmotaGlobal.devices_present, power_state); - } - //else AddLog(LOG_LEVEL_DEBUG, PSTR("PCF: DON'T set power from chip state")); - UpdateDevicesPresent(1); - Pcf8574.max_connected_ports++; - } - } - } - //AddLog(LOG_LEVEL_DEBUG, PSTR("PCF: Settings->power=0x%08X, TasmotaGlobal.power=0x%08X"), Settings->power, TasmotaGlobal.power); - AddLog(LOG_LEVEL_INFO, PSTR("PCF: Total devices %d, PCF8574 output ports %d"), Pcf8574.max_devices, Pcf8574.max_connected_ports); - } -} - -/*********************************************************************************************\ - * Presentation -\*********************************************************************************************/ - -#ifdef USE_WEBSERVER - -#define WEB_HANDLE_PCF8574 "pcf" - -const char HTTP_BTN_MENU_PCF8574[] PROGMEM = - "

"; - -const char HTTP_FORM_I2C_PCF8574_1[] PROGMEM = - "
 " D_PCF8574_PARAMETERS " " - "
" - "


"; - -const char HTTP_FORM_I2C_PCF8574_2[] PROGMEM = - "" D_DEVICE " %d " D_PORT " %d"; - -const char HTTP_SNS_PCF8574_GPIO[] PROGMEM = "{s}PCF8574%c%d D%d{m}%d{e}"; // {s} = , {m} = , {e} = - - -void HandlePcf8574(void) -{ - if (!HttpCheckPriviledgedAccess()) { return; } - - AddLog(LOG_LEVEL_DEBUG, PSTR(D_LOG_HTTP D_CONFIGURE_PCF8574)); - - if (Webserver->hasArg("save")) { - Pcf8574SaveSettings(); - WebRestart(1); - return; - } - - WSContentStart_P(D_CONFIGURE_PCF8574); - WSContentSendStyle(); - WSContentSend_P(HTTP_FORM_I2C_PCF8574_1, (Settings->flag3.pcf8574_ports_inverted) ? PSTR(" checked") : ""); // SetOption81 - Invert all ports on PCF8574 devices - WSContentSend_P(HTTP_TABLE100); - for (uint32_t idx = 0; idx < Pcf8574.max_devices; idx++) { - for (uint32_t idx2 = 0; idx2 < 8; idx2++) { // 8 ports on PCF8574 - uint8_t helper = 1 << idx2; - WSContentSend_P(HTTP_FORM_I2C_PCF8574_2, - idx +1, idx2, - idx2 + 8*idx, - idx2 + 8*idx, - ((helper & Settings->pcf8574_config[idx]) >> idx2 == 0) ? PSTR(" selected ") : " ", - ((helper & Settings->pcf8574_config[idx]) >> idx2 == 1) ? PSTR(" selected ") : " " - ); - } - } - WSContentSend_P(PSTR("")); - WSContentSend_P(HTTP_FORM_END); - WSContentSpaceButton(BUTTON_CONFIGURATION); - WSContentStop(); -} - -#if defined(USE_PCF8574_SENSOR) || defined(USE_PCF8574_DISPLAYINPUT) -void Pcf8574Show(bool json) -{ -#ifdef USE_PCF8574_SENSOR - if (json) { - for (int idx = 0 ; idx < Pcf8574.max_devices ; idx++) - { - uint8_t gpio = Pcf8574Read(idx); - ResponseAppend_P(PSTR(",\"PCF8574%c%d\":{\"D0\":%i,\"D1\":%i,\"D2\":%i,\"D3\":%i,\"D4\":%i,\"D5\":%i,\"D6\":%i,\"D7\":%i}"), - IndexSeparator(), idx +1, - (gpio>>0)&1,(gpio>>1)&1,(gpio>>2)&1,(gpio>>3)&1,(gpio>>4)&1,(gpio>>5)&1,(gpio>>6)&1,(gpio>>7)&1); - } - } -#endif // #ifdef USE_PCF8574_SENSOR -#if defined(USE_WEBSERVER) && defined(USE_PCF8574_DISPLAYINPUT) - if(!json) { - for (int idx = 0 ; idx < Pcf8574.max_devices ; idx++) - { - uint8_t input_mask = ~Settings->pcf8574_config[idx]; //invert to 1 = input - uint8_t gpio = Pcf8574Read(idx); - for (int pin = 0 ; pin < 8 ; ++pin, input_mask>>=1, gpio>>=1) - { - if (input_mask & 1) - WSContentSend_P(HTTP_SNS_PCF8574_GPIO, IndexSeparator(), idx +1, pin, gpio & 1); - } - } - } -#endif // defined(USE_WEBSERVER) && defined(USE_PCF8574_DISPLAYINPUT) -} -#endif // #if defined(USE_PCF8574_SENSOR) || defined(USE_PCF8574_DISPLAYINPUT) - - -#ifdef USE_PCF8574_MQTTINPUT -void Pcf8574CheckForInputChange(void) -{ - for (int idx = 0 ; idx < Pcf8574.max_devices ; idx++) - { - uint8_t input_mask = ~Settings->pcf8574_config[idx]; //invert to 1 = input - uint8_t input = Pcf8574Read(idx) & input_mask; - uint8_t last_input = Pcf8574.last_input[idx]; - if (input != last_input) { // don't scan bits if no change (EVERY_50_MS !) - for (uint8_t pin = 0 ; pin < 8 ; ++pin) { - if (bitRead(input_mask,pin) && bitRead(input,pin) != bitRead(last_input,pin)) { - ResponseTime_P(PSTR(",\"PCF8574%c%d_INP\":{\"D%i\":%i}}"), IndexSeparator(), idx +1, pin, bitRead(input,pin)); - MqttPublishPrefixTopicRulesProcess_P(RESULT_OR_STAT, PSTR("PCF8574_INP")); - if (Settings->flag3.hass_tele_on_power) { // SetOption59 - Send tele/%topic%/SENSOR in addition to stat/%topic%/RESULT - MqttPublishSensor(); - } - } - Pcf8574.last_input[idx] = input; - } - } - } -} -#endif //#ifdef USE_PCF8574_MQTTINPUT - -void Pcf8574SaveSettings(void) -{ - char stemp[7]; - char tmp[100]; - - //AddLog(LOG_LEVEL_DEBUG, PSTR("PCF: Start working on Save arguements: inverted:%d")), Webserver->hasArg("b1"); - - Settings->flag3.pcf8574_ports_inverted = Webserver->hasArg("b1"); // SetOption81 - Invert all ports on PCF8574 devices - for (byte idx = 0; idx < Pcf8574.max_devices; idx++) { - byte count=0; - byte n = Settings->pcf8574_config[idx]; - while(n!=0) { - n = n&(n-1); - count++; - } - if (count <= TasmotaGlobal.devices_present) { - UpdateDevicesPresent(-count); - } - for (byte i = 0; i < 8; i++) { - snprintf_P(stemp, sizeof(stemp), PSTR("i2cs%d"), i+8*idx); - WebGetArg(stemp, tmp, sizeof(tmp)); - byte _value = (!strlen(tmp)) ? 0 : atoi(tmp); - if (_value) { - Settings->pcf8574_config[idx] = Settings->pcf8574_config[idx] | 1 << i; - UpdateDevicesPresent(1); - Pcf8574.max_connected_ports++; - } else { - Settings->pcf8574_config[idx] = Settings->pcf8574_config[idx] & ~(1 << i ); - } - } - //Settings->pcf8574_config[0] = (!strlen(webServer->arg("i2cs0").c_str())) ? 0 : atoi(webServer->arg("i2cs0").c_str()); - //AddLog(LOG_LEVEL_INFO, PSTR("PCF: I2C Board: %d, Config: %2x")), idx, Settings->pcf8574_config[idx]; - - } -} -#endif // USE_WEBSERVER - -/*********************************************************************************************\ - * Interface -\*********************************************************************************************/ - -bool Xdrv28(uint32_t function) -{ - if (!I2cEnabled(XI2C_02)) { return false; } - - bool result = false; - - if (FUNC_PRE_INIT == function) { - Pcf8574Init(); - } - else if (Pcf8574.type) { - switch (function) { - case FUNC_SET_POWER: - Pcf8574SwitchRelay(); - break; -#ifdef USE_PCF8574_MQTTINPUT - case FUNC_EVERY_50_MSECOND: - Pcf8574CheckForInputChange(); - break; -#endif // #ifdef USE_PCF8574_MQTTINPUT -#ifdef USE_PCF8574_SENSOR - case FUNC_JSON_APPEND: - Pcf8574Show(1); - break; -#endif // #ifdef USE_PCF8574_SENSOR -#ifdef USE_WEBSERVER - case FUNC_WEB_ADD_BUTTON: - WSContentSend_P(HTTP_BTN_MENU_PCF8574); - break; - case FUNC_WEB_ADD_HANDLER: - WebServer_on(PSTR("/" WEB_HANDLE_PCF8574), HandlePcf8574); - break; -#ifdef USE_PCF8574_DISPLAYINPUT - case FUNC_WEB_SENSOR: - Pcf8574Show(0); - break; -#endif // #ifdef USE_PCF8574_DISPLAYINPUT -#endif // USE_WEBSERVER - } - } - return result; -} - -#endif // USE_PCF8574 -#endif // USE_I2C diff --git a/tasmota/tasmota_xdrv_driver/xdrv_28_pcf8574.ino b/tasmota/tasmota_xdrv_driver/xdrv_28_pcf8574_v2.ino similarity index 91% rename from tasmota/tasmota_xdrv_driver/xdrv_28_pcf8574.ino rename to tasmota/tasmota_xdrv_driver/xdrv_28_pcf8574_v2.ino index f07355b1b..0ccaef4ab 100644 --- a/tasmota/tasmota_xdrv_driver/xdrv_28_pcf8574.ino +++ b/tasmota/tasmota_xdrv_driver/xdrv_28_pcf8574_v2.ino @@ -71,8 +71,6 @@ * {"NAME":"PCF8574 A=Ri8-1, B=B1-8","GPIO":[263,262,261,260,259,258,257,256,32,33,34,35,36,37,38,39]} * B1 B2 B3 B4 Ri4 Ri3 Ri2 Ri1 B5 B6 B7 B8 Ri8 Ri7 Ri6 Ri5 * {"NAME":"PCF8574 A=B1-4,Ri4-1, B=B5-8,Ri8-5","GPIO":[32,33,34,35,259,258,257,256,36,37,38,39,263,262,261,260]} - * B1 B2 B3 B4 Ri4 Ri3 Ri2 Ri1 B5 B6 B7 B8 Ri8 Ri7 Ri6 Ri5 - * {"NAME":"PCF8574 A=Bi1-4,Ri4-1, B=Bi5-8,Ri8-5","GPIO":[64,65,66,67,259,258,257,256,68,69,70,71,263,262,261,260]} \*********************************************************************************************/ #define XDRV_28 28 @@ -108,7 +106,6 @@ #endif struct PCF8574 { - int error; uint32_t relay_inverted; uint32_t button_inverted; uint16_t pin[PCF8574_MAX_PINS]; @@ -120,7 +117,6 @@ struct PCF8574 { uint8_t max_connected_ports = 0; // Max numbers of devices comming from PCF8574 modules uint8_t max_devices = 0; // Max numbers of PCF8574 modules uint8_t mode; - uint8_t chip; uint8_t relay_max; uint8_t relay_offset; uint8_t button_max; @@ -135,34 +131,21 @@ struct PCF8574 { \*********************************************************************************************/ uint8_t Pcf8574Read(uint8_t idx) { - Wire.requestFrom(Pcf8574.address[idx],(uint8_t)1); + Wire.requestFrom(Pcf8574.address[idx], (uint8_t)1); return Wire.read(); } -uint8_t Pcf8574Write(uint8_t idx) { +void Pcf8574Write(uint8_t idx) { Wire.beginTransmission(Pcf8574.address[idx]); Wire.write(Pcf8574.pin_mask[idx]); - return Wire.endTransmission(); -} - -/*********************************************************************************************/ - -uint8_t Pcf8574ReadByte(void) { - Wire.requestFrom(Pcf8574.address[Pcf8574.chip], (uint8_t)1); - return Wire.read(); -} - -uint8_t Pcf8574WriteByte(uint8_t value) { - Wire.beginTransmission(Pcf8574.address[Pcf8574.chip]); - Wire.write(value); - return Wire.endTransmission(); + Wire.endTransmission(); } bool Pcf8574DigitalRead(uint8_t pin) { // pin 0 - 63 - Pcf8574.chip = pin / 8; - uint8_t bit = pin % 8; - uint8_t value = Pcf8574ReadByte(); + uint32_t chip = pin / 8; + uint32_t bit = pin % 8; + uint32_t value = Pcf8574Read(chip); return value & (1 << bit); } @@ -170,15 +153,17 @@ void Pcf8574DigitalWrite(uint8_t pin, bool pin_value) { // pin 0 - 63 // INPUT or INPUT_PULLUP = Pcf8574DigitalWrite(pin, 1); // OUTPUT = Pcf8574DigitalWrite(pin, 0); or Pcf8574DigitalWrite(pin, 1); - Pcf8574.chip = pin / 8; - uint8_t bit = pin % 8; - uint8_t reg_value = Pcf8574ReadByte(); + uint32_t chip = pin / 8; + uint32_t bit = pin % 8; + uint32_t value = Pcf8574Read(chip); if (pin_value) { - reg_value |= 1 << bit; + value |= 1 << bit; } else { - reg_value &= ~(1 << bit); + value &= ~(1 << bit); } - Pcf8574WriteByte(reg_value); + Wire.beginTransmission(Pcf8574.address[chip]); + Wire.write(value); + Wire.endTransmission(); } /*********************************************************************************************\ @@ -244,7 +229,6 @@ bool Pcf8574LoadTemplate(void) { if (!root) { return false; } // rule3 on file#pcf8574.dat do {"NAME":"PCF8574 A=B1-4,Ri4-1, B=B5-8,Ri8-5","GPIO":[32,33,34,35,259,258,257,256,36,37,38,39,263,262,261,260]} endon - // rule3 on file#pcf8574.dat do {"NAME":"PCF8574 A=Bi1-4,Ri4-1, B=Bi5-8,Ri8-5","GPIO":[64,65,66,67,259,258,257,256,68,69,70,71,263,262,261,260]} endon JsonParserToken val = root[PSTR(D_JSON_NAME)]; if (val) { AddLog(LOG_LEVEL_DEBUG, PSTR("PCF: Template %s"), val.getStr()); @@ -289,13 +273,13 @@ bool Pcf8574LoadTemplate(void) { } else if ((mpin >= AGPIO(GPIO_REL1)) && (mpin < (AGPIO(GPIO_REL1) + MAX_RELAYS_SET))) { Pcf8574.relay_max++; - Pcf8574DigitalWrite(pin, 1); // OUTPUT +// Pcf8574DigitalWrite(pin, 1); // OUTPUT - Leave unchanged to fix restart and power on spikes (default is 1) } else if ((mpin >= AGPIO(GPIO_REL1_INV)) && (mpin < (AGPIO(GPIO_REL1_INV) + MAX_RELAYS_SET))) { bitSet(Pcf8574.relay_inverted, mpin - AGPIO(GPIO_REL1_INV)); mpin -= (AGPIO(GPIO_REL1_INV) - AGPIO(GPIO_REL1)); Pcf8574.relay_max++; - Pcf8574DigitalWrite(pin, 0); // OUTPUT +// Pcf8574DigitalWrite(pin, 1); // OUTPUT - Leave unchanged to fix restart and power on spikes (default is 1) } else if (mpin == AGPIO(GPIO_OUTPUT_HI)) { Pcf8574DigitalWrite(pin, 1); // OUTPUT @@ -315,38 +299,15 @@ bool Pcf8574LoadTemplate(void) { } Pcf8574.max_connected_ports = pin; // Max number of configured pins } - -// AddLog(LOG_LEVEL_DEBUG, PSTR("PCF: Pins %d, pin %*_V"), Pcf8574.max_connected_ports, Pcf8574.max_connected_ports, (uint8_t*)Pcf8574.pin); - return true; } -uint32_t Pcf8574TemplateGpio(void) { - String pcftmplt = Pcf8574TemplateLoadFile(); - uint32_t len = pcftmplt.length() +1; - if (len < 7) { return 0; } // No PcfTmplt found - - JsonParser parser((char*)pcftmplt.c_str()); - JsonParserObject root = parser.getRootObject(); - if (!root) { return 0; } - - JsonParserArray arr = root[PSTR(D_JSON_GPIO)]; - if (arr.isArray()) { - return arr.size(); // Number of requested pins - } - return 0; -} - void Pcf8574ServiceInput(void) { Pcf8574.interrupt = false; - // This works with no interrupt + // This works with no interrupt too uint32_t pin_offset = 0; - uint32_t gpio; - for (Pcf8574.chip = 0; Pcf8574.chip < Pcf8574.max_devices; Pcf8574.chip++) { - gpio = Pcf8574ReadByte(); - -// AddLog(LOG_LEVEL_DEBUG_MORE, PSTR("PCF: Chip %d, State %02X"), Pcf8574.chip, gpio); - + for (uint32_t chip = 0; chip < Pcf8574.max_devices; chip++) { + uint32_t gpio = Pcf8574Read(chip); uint32_t mask = 1; for (uint32_t pin = 0; pin < 8; pin++) { uint32_t state = ((gpio & mask) != 0); @@ -367,7 +328,7 @@ void Pcf8574ServiceInput(void) { } } -void IRAM_ATTR Pcf8574InputIsr(void) { +static void IRAM_ATTR Pcf8574InputIsr(void) { Pcf8574.interrupt = true; } @@ -381,14 +342,12 @@ void Pcf8574Init(void) { } void Pcf8574Power(void) { + // XdrvMailbox.index = 32-bit rpower bit mask power_t rpower = XdrvMailbox.index >> Pcf8574.relay_offset; for (uint32_t index = 0; index < Pcf8574.relay_max; index++) { power_t state = rpower &1; if (Pcf8574PinUsed(GPIO_REL1, index)) { uint32_t pin = Pcf8574Pin(GPIO_REL1, index) & 0x3F; // Fix possible overflow over 63 gpios - -// AddLog(LOG_LEVEL_DEBUG, PSTR("PCF: Power pin %d, state %d(%d)"), pin, state, bitRead(Pcf8574.relay_inverted, index)); - Pcf8574DigitalWrite(pin, bitRead(Pcf8574.relay_inverted, index) ? !state : state); } rpower >>= 1; // Select next power @@ -401,9 +360,6 @@ bool Pcf8574AddButton(void) { uint32_t index = XdrvMailbox.index - Pcf8574.button_offset; if (index >= Pcf8574.button_max) { return false; } XdrvMailbox.index = (Pcf8574DigitalRead(Pcf8574Pin(GPIO_KEY1, index)) != bitRead(Pcf8574.button_inverted, index)); - -// AddLog(LOG_LEVEL_DEBUG, PSTR("PCF: AddButton index %d, state %d"), index, XdrvMailbox.index); - return true; } @@ -433,7 +389,7 @@ void Pcf8574SwitchRelay(void) { //AddLog(LOG_LEVEL_DEBUG, PSTR("PCF: SwitchRelay %d=%d => PCF-%d.D%d=%d"), i, relay_state, board +1, pin, _val); bitWrite(Pcf8574.pin_mask[board], pin, _val); if (oldpinmask != Pcf8574.pin_mask[board]) { - Pcf8574.error = Pcf8574Write(board); + Pcf8574Write(board); } //else AddLog(LOG_LEVEL_DEBUG, PSTR("PCF: SwitchRelay skipped")); } @@ -459,8 +415,8 @@ void Pcf8574ModuleInit(void) { if (I2cSetDevice(pcf8574_address)) { Pcf8574.mode = 1; - Pcf8574.address[Pcf8574.max_devices] = pcf8574_address; Pcf8574.max_connected_ports += 8; + Pcf8574.address[Pcf8574.max_devices] = pcf8574_address; Pcf8574.max_devices++; char stype[9]; @@ -469,6 +425,7 @@ void Pcf8574ModuleInit(void) { strcpy(stype, "PCF8574A"); } I2cSetActiveFound(pcf8574_address, stype); + if (Pcf8574.max_connected_ports > PCF8574_MAX_PINS -8) { break; } } pcf8574_address++; diff --git a/tasmota/tasmota_xdrv_driver/xdrv_67_mcp23xxx.ino b/tasmota/tasmota_xdrv_driver/xdrv_67_mcp23xxx.ino index 6b67e0b46..0f0bf34b3 100644 --- a/tasmota/tasmota_xdrv_driver/xdrv_67_mcp23xxx.ino +++ b/tasmota/tasmota_xdrv_driver/xdrv_67_mcp23xxx.ino @@ -709,7 +709,7 @@ void MCP23xServiceInput(void) { } } -void IRAM_ATTR MCP23xInputIsr(void) { +static void IRAM_ATTR MCP23xInputIsr(void) { Mcp23x.interrupt = true; }