From 41b594ae53c9968ffb50d8c9fdb7e8ed5f78c93b Mon Sep 17 00:00:00 2001 From: MadDoct <32080323+MadDoct@users.noreply.github.com> Date: Mon, 13 Aug 2018 23:54:27 +0100 Subject: [PATCH 01/15] update mcp230xx to allow inverted output Created pinmode 6 to allow setting inverted output, so it can easily be used with active low relay boards... Also changerd some of the output to make it more readable... --- sonoff/xsns_29_mcp230xx.ino | 131 +++++++++++++++++++++++------------- 1 file changed, 83 insertions(+), 48 deletions(-) diff --git a/sonoff/xsns_29_mcp230xx.ino b/sonoff/xsns_29_mcp230xx.ino index 79e95f03a..04b06457f 100644 --- a/sonoff/xsns_29_mcp230xx.ino +++ b/sonoff/xsns_29_mcp230xx.ino @@ -1,5 +1,5 @@ /* - xsns_29_mcp230xx.ino - Support for I2C MCP23008/MCP23017 GPIO Expander (INPUT ONLY!) + xsns_29_mcp230xx.ino - Support for I2C MCP23008/MCP23017 GPIO Expander (INPUT AND OUTPUT) Copyright (C) 2018 Andre Thomas and Theo Arends @@ -62,12 +62,35 @@ uint8_t mcp230xx_int_en = 0; uint16_t mcp230xx_tele_count = 0; #endif -const char MCP230XX_SENSOR_RESPONSE[] PROGMEM = "{\"Sensor29-D%i\":{\"MODE\":%i,\"PULL-UP\":%i,\"STATE\":%i}}"; +const char MCP230XX_SENSOR_RESPONSE[] PROGMEM = "{\"Sensor29-D%i\":{\"MODE\":%i,\"PULL-UP\":\"%s\",\"STATE\":\"%s\"}}"; #ifdef USE_MCP230xx_OUTPUT -const char MCP230XX_CMND_RESPONSE[] PROGMEM = "{\"S29cmnd-D%i\":{\"C\":\"%s\",\"R\":%i}}"; +const char MCP230XX_CMND_RESPONSE[] PROGMEM = "{\"S29cmnd-D%i\":{\"COMMAND\":\"%s\",\"STATE\":\"%s\"}}"; #endif // USE_MCP230xx_OUTPUT +const char* ConvertNumTxt(uint8_t statu, uint8_t pinmod=0) { +#ifdef USE_MCP230xx_OUTPUT +if (pinmod==6) { + if (statu < 2) statu = abs(statu-1); +} +#endif // USE_MCP230xx_OUTPUT + switch (statu) { + case 0: + return "OFF"; + break; + case 1: + return "ON"; + break; +#ifdef USE_MCP230xx_OUTPUT + case 2: + return "TOGGLE"; + break; +#endif // USE_MCP230xx_OUTPUT + default: + break; + } +} + uint8_t MCP230xx_readGPIO(uint8_t port) { return I2cRead8(mcp230xx_address, MCP230xx_GPIO + port); } @@ -78,9 +101,9 @@ void MCP230xx_ApplySettings(void) { uint8_t reg_gppu = 0; uint8_t reg_gpinten = 0; uint8_t reg_iodir = 0xFF; -#ifdef USE_MCP230xx_OUTPUT +#ifdef USE_MCP230xx_OUTPUT uint8_t reg_portpins = 0x00; -#endif +#endif for (uint8_t idx = 0; idx < 8; idx++) { switch (Settings.mcp230xx_config[idx+(mcp230xx_port*8)].pinmode) { case 0 ... 1: @@ -92,7 +115,7 @@ void MCP230xx_ApplySettings(void) { int_en=1; break; #ifdef USE_MCP230xx_OUTPUT - case 5: + case 5 ... 6: reg_iodir &= ~(1 << idx); if (Settings.flag.save_state) { // Firmware configuration wants us to use the last pin state reg_portpins |= (Settings.mcp230xx_config[idx+(mcp230xx_port*8)].saved_state << idx); @@ -102,12 +125,12 @@ void MCP230xx_ApplySettings(void) { } } break; -#endif // USE_MCP230xx_OUTPUT +#endif // USE_MCP230xx_OUTPUT default: break; } #ifdef USE_MCP230xx_OUTPUT - if (Settings.mcp230xx_config[idx+(mcp230xx_port*8)].pullup && (Settings.mcp230xx_config[idx+(mcp230xx_port*8)].pinmode != 5)) { + if (Settings.mcp230xx_config[idx+(mcp230xx_port*8)].pullup && (Settings.mcp230xx_config[idx+(mcp230xx_port*8)].pinmode < 5)) { reg_gppu |= (1 << idx); } #else @@ -119,21 +142,21 @@ void MCP230xx_ApplySettings(void) { I2cWrite8(mcp230xx_address, MCP230xx_GPPU+mcp230xx_port, reg_gppu); I2cWrite8(mcp230xx_address, MCP230xx_GPINTEN+mcp230xx_port, reg_gpinten); I2cWrite8(mcp230xx_address, MCP230xx_IODIR+mcp230xx_port, reg_iodir); -#ifdef USE_MCP230xx_OUTPUT +#ifdef USE_MCP230xx_OUTPUT I2cWrite8(mcp230xx_address, MCP230xx_GPIO+mcp230xx_port, reg_portpins); -#endif +#endif } mcp230xx_int_en=int_en; } void MCP230xx_Detect() { + uint8_t buffer; + if (mcp230xx_type) { return; } - uint8_t buffer; - for (byte i = 0; i < sizeof(mcp230xx_addresses); i++) { mcp230xx_address = mcp230xx_addresses[i]; I2cWrite8(mcp230xx_address, MCP230xx_IOCON, 0x80); // attempt to set bank mode - this will only work on MCP23017, so its the best way to detect the different chips 23008 vs 23017 @@ -233,11 +256,11 @@ void MCP230xx_Show(boolean json) void MCP230xx_SetOutPin(uint8_t pin,uint8_t pinstate) { uint8_t portpins; uint8_t port = 0; - char cmnd[7]; + char cmnd[7], stt[4]; if (pin > 7) port=1; portpins = MCP230xx_readGPIO(port); if (pinstate < 2) { - if (pinstate) portpins |= (1 << pin-(port*8)); else portpins &= ~(1 << pin-(port*8)); + if (pinstate) portpins |= (1 << pin-(port*8)); else portpins &= ~(1 << pin-(port*8)); } else { portpins ^= (1 << pin-(port*8)); } @@ -245,20 +268,10 @@ void MCP230xx_SetOutPin(uint8_t pin,uint8_t pinstate) { if (Settings.flag.save_state) { // Firmware configured to save last known state in settings Settings.mcp230xx_config[pin].saved_state=portpins>>(pin-(port*8))&1; } - switch (pinstate) { - case 0: - sprintf(cmnd,"OFF"); - break; - case 1: - sprintf(cmnd,"ON"); - break; - case 2: - sprintf(cmnd,"TOGGLE"); - break; - default: - break; - } - snprintf_P(mqtt_data, sizeof(mqtt_data), MCP230XX_CMND_RESPONSE, pin, cmnd,(portpins >> (pin-(port*8)))&1); + uint8_t pinmo = Settings.mcp230xx_config[pin].pinmode; + sprintf(cmnd,ConvertNumTxt(pinstate, pinmo)); + sprintf(stt,ConvertNumTxt((portpins >> (pin-(port*8))&1), pinmo)); + snprintf_P(mqtt_data, sizeof(mqtt_data), MCP230XX_CMND_RESPONSE, pin, cmnd, stt); } #endif // USE_MCP230xx_OUTPUT @@ -275,7 +288,9 @@ void MCP230xx_Reset(uint8_t pinmode) { Settings.mcp230xx_config[pinx].b7=0; } MCP230xx_ApplySettings(); - snprintf_P(mqtt_data, sizeof(mqtt_data), MCP230XX_SENSOR_RESPONSE,99,pinmode,pullup,99); + char pulluptxt[4]; + sprintf(pulluptxt,ConvertNumTxt(pullup)); + snprintf_P(mqtt_data, sizeof(mqtt_data), MCP230XX_SENSOR_RESPONSE,99,pinmode,pulluptxt,""); } bool MCP230xx_Command(void) { @@ -291,7 +306,7 @@ bool MCP230xx_Command(void) { if (data == "RESET4") { MCP230xx_Reset(4); return serviced; } #ifdef USE_MCP230xx_OUTPUT if (data == "RESET5") { MCP230xx_Reset(5); return serviced; } -#endif +#endif _a = data.indexOf(","); pin = data.substring(0, _a).toInt(); if (pin < mcp230xx_pincount) { @@ -300,17 +315,27 @@ bool MCP230xx_Command(void) { uint8_t port = 0; if (pin > 7) port = 1; uint8_t portdata = MCP230xx_readGPIO(port); - snprintf_P(mqtt_data, sizeof(mqtt_data), MCP230XX_SENSOR_RESPONSE,pin,Settings.mcp230xx_config[pin].pinmode,Settings.mcp230xx_config[pin].pullup,portdata>>(pin-(port*8))&1); + char pulluptxtr[4],pinstatustxtr[4]; + sprintf(pulluptxtr,ConvertNumTxt(Settings.mcp230xx_config[pin].pullup)); +#ifdef USE_MCP230xx_OUTPUT + uint8_t pinmod = Settings.mcp230xx_config[pin].pinmode; + sprintf(pinstatustxtr,ConvertNumTxt(portdata>>(pin-(port*8))&1,pinmod)); + snprintf_P(mqtt_data, sizeof(mqtt_data), MCP230XX_SENSOR_RESPONSE,pin,pinmod,pulluptxtr,pinstatustxtr); +#else + sprintf(pinstatustxtr,ConvertNumTxt(portdata>>(pin-(port*8))&1)); + snprintf_P(mqtt_data, sizeof(mqtt_data), MCP230XX_SENSOR_RESPONSE,pin,Settings.mcp230xx_config[pin].pinmode,pulluptxtr,pinstatustxtr); +#endif //USE_MCP230xx_OUTPUT return serviced; } #ifdef USE_MCP230xx_OUTPUT - if (Settings.mcp230xx_config[pin].pinmode == 5) { + if (Settings.mcp230xx_config[pin].pinmode >= 5) { + uint8_t pincmd = Settings.mcp230xx_config[pin].pinmode - 5; if (cmnd == "ON") { - MCP230xx_SetOutPin(pin,1); + MCP230xx_SetOutPin(pin,abs(pincmd-1)); return serviced; } if (cmnd == "OFF") { - MCP230xx_SetOutPin(pin,0); + MCP230xx_SetOutPin(pin,pincmd); return serviced; } if (cmnd == "T") { @@ -318,7 +343,7 @@ bool MCP230xx_Command(void) { return serviced; } } -#endif // USE_MCP230xx_OUTPUT +#endif // USE_MCP230xx_OUTPUT } _b = data.indexOf(",", _a + 1); if (_a < XdrvMailbox.data_len) { @@ -326,17 +351,24 @@ bool MCP230xx_Command(void) { pinmode = data.substring(_a+1, _b).toInt(); pullup = data.substring(_b+1, XdrvMailbox.data_len).toInt(); #ifdef USE_MCP230xx_OUTPUT - if ((pin < mcp230xx_pincount) && (pinmode < 6) && (pullup < 2)) { -#else // not USE_MCP230xx_OUTPUT + if ((pin < mcp230xx_pincount) && (pinmode < 7) && (pullup < 2)) { +#else // not USE_MCP230xx_OUTPUT if ((pin < mcp230xx_pincount) && (pinmode < 5) && (pullup < 2)) { -#endif // USE_MCP230xx_OUTPUT +#endif // USE_MCP230xx_OUTPUT Settings.mcp230xx_config[pin].pinmode=pinmode; Settings.mcp230xx_config[pin].pullup=pullup; MCP230xx_ApplySettings(); uint8_t port = 0; if (pin > 7) port = 1; uint8_t portdata = MCP230xx_readGPIO(port); - snprintf_P(mqtt_data, sizeof(mqtt_data), MCP230XX_SENSOR_RESPONSE,pin,pinmode,pullup,portdata>>(pin-(port*8))&1); + char pulluptxtc[4], pinstatustxtc[4]; + sprintf(pulluptxtc,ConvertNumTxt(pullup)); +#ifdef USE_MCP230xx_OUTPUT + sprintf(pinstatustxtc,ConvertNumTxt(portdata>>(pin-(port*8))&1,Settings.mcp230xx_config[pin].pinmode)); +#else // not USE_MCP230xx_OUTPUT + sprintf(pinstatustxtc,ConvertNumTxt(portdata>>(pin-(port*8))&1)); +#endif // USE_MCP230xx_OUTPUT + snprintf_P(mqtt_data, sizeof(mqtt_data), MCP230XX_SENSOR_RESPONSE,pin,pinmode,pulluptxtc,pinstatustxtc); } else { serviced = false; } @@ -351,7 +383,7 @@ bool MCP230xx_Command(void) { #ifdef USE_MCP230xx_DISPLAYOUTPUT -const char HTTP_SNS_MCP230xx_OUTPUT[] PROGMEM = "%s{s}MCP230XX D%d{m}%d{e}"; // {s} = , {m} = , {e} = +const char HTTP_SNS_MCP230xx_OUTPUT[] PROGMEM = "%s{s}MCP230XX D%d{m}%s{e}"; // {s} = , {m} = , {e} = void MCP230xx_UpdateWebData(void) { uint8_t gpio1 = MCP230xx_readGPIO(0); @@ -361,8 +393,10 @@ void MCP230xx_UpdateWebData(void) { } uint16_t gpio = (gpio2 << 8) + gpio1; for (uint8_t pin = 0; pin < mcp230xx_pincount; pin++) { - if (Settings.mcp230xx_config[pin].pinmode == 5) { - snprintf_P(mqtt_data, sizeof(mqtt_data), HTTP_SNS_MCP230xx_OUTPUT, mqtt_data, pin, (gpio>>pin)&1); + if (Settings.mcp230xx_config[pin].pinmode >= 5) { + char stt[4]; + sprintf(stt,ConvertNumTxt((gpio>>pin)&1,Settings.mcp230xx_config[pin].pinmode)); + snprintf_P(mqtt_data, sizeof(mqtt_data), HTTP_SNS_MCP230xx_OUTPUT, mqtt_data, pin, stt); } } } @@ -381,13 +415,15 @@ void MCP230xx_OutputTelemetry(void) { if (mcp230xx_type == 2) gpiob=MCP230xx_readGPIO(1); gpiototal=((uint16_t)gpiob<<8) | gpioa; for (uint8_t pinx = 0;pinx < mcp230xx_pincount;pinx++) { - if (Settings.mcp230xx_config[pinx].pinmode == 5) outputcount++; + if (Settings.mcp230xx_config[pinx].pinmode >= 5) outputcount++; } if (outputcount) { + char stt[4]; snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("{\"" D_JSON_TIME "\":\"%s\",\"MCP230_OUT\": {"), GetDateAndTime(DT_LOCAL).c_str()); for (uint8_t pinx = 0;pinx < mcp230xx_pincount;pinx++) { - if (Settings.mcp230xx_config[pinx].pinmode == 5) { - snprintf_P(mqtt_data,sizeof(mqtt_data), PSTR("%s\"OUTD%i\":%i,"),mqtt_data,pinx,(gpiototal>>pinx)&1); + if (Settings.mcp230xx_config[pinx].pinmode >= 5) { + sprintf(stt,ConvertNumTxt(((gpiototal>>pinx)&1),Settings.mcp230xx_config[pinx].pinmode)); + snprintf_P(mqtt_data,sizeof(mqtt_data), PSTR("%s\"OUTD%i\":%s,"),mqtt_data,pinx,stt); } } snprintf_P(mqtt_data,sizeof(mqtt_data),PSTR("%s\"END\":1}}"),mqtt_data); @@ -400,7 +436,7 @@ void MCP230xx_OutputTelemetry(void) { /*********************************************************************************************\ Interface - \*********************************************************************************************/ +\*********************************************************************************************/ boolean Xsns29(byte function) { @@ -416,7 +452,7 @@ boolean Xsns29(byte function) mcp230xx_tele_count=0; MCP230xx_OutputTelemetry(); } -#endif +#endif break; case FUNC_EVERY_50_MSECOND: if (mcp230xx_int_en) { // Only check for interrupts if its enabled on one of the pins @@ -449,4 +485,3 @@ boolean Xsns29(byte function) #endif // USE_MCP230xx #endif // USE_I2C - From 48b6ee20ed8d2229d30db22e42941156ffb152f0 Mon Sep 17 00:00:00 2001 From: MadDoct <32080323+MadDoct@users.noreply.github.com> Date: Tue, 14 Aug 2018 00:13:56 +0100 Subject: [PATCH 02/15] add pinmode 6 for inverted output and changed some data output --- sonoff/xsns_29_mcp230xx.ino | 131 +++++++++++++++++++++++------------- 1 file changed, 83 insertions(+), 48 deletions(-) diff --git a/sonoff/xsns_29_mcp230xx.ino b/sonoff/xsns_29_mcp230xx.ino index 79e95f03a..04b06457f 100644 --- a/sonoff/xsns_29_mcp230xx.ino +++ b/sonoff/xsns_29_mcp230xx.ino @@ -1,5 +1,5 @@ /* - xsns_29_mcp230xx.ino - Support for I2C MCP23008/MCP23017 GPIO Expander (INPUT ONLY!) + xsns_29_mcp230xx.ino - Support for I2C MCP23008/MCP23017 GPIO Expander (INPUT AND OUTPUT) Copyright (C) 2018 Andre Thomas and Theo Arends @@ -62,12 +62,35 @@ uint8_t mcp230xx_int_en = 0; uint16_t mcp230xx_tele_count = 0; #endif -const char MCP230XX_SENSOR_RESPONSE[] PROGMEM = "{\"Sensor29-D%i\":{\"MODE\":%i,\"PULL-UP\":%i,\"STATE\":%i}}"; +const char MCP230XX_SENSOR_RESPONSE[] PROGMEM = "{\"Sensor29-D%i\":{\"MODE\":%i,\"PULL-UP\":\"%s\",\"STATE\":\"%s\"}}"; #ifdef USE_MCP230xx_OUTPUT -const char MCP230XX_CMND_RESPONSE[] PROGMEM = "{\"S29cmnd-D%i\":{\"C\":\"%s\",\"R\":%i}}"; +const char MCP230XX_CMND_RESPONSE[] PROGMEM = "{\"S29cmnd-D%i\":{\"COMMAND\":\"%s\",\"STATE\":\"%s\"}}"; #endif // USE_MCP230xx_OUTPUT +const char* ConvertNumTxt(uint8_t statu, uint8_t pinmod=0) { +#ifdef USE_MCP230xx_OUTPUT +if (pinmod==6) { + if (statu < 2) statu = abs(statu-1); +} +#endif // USE_MCP230xx_OUTPUT + switch (statu) { + case 0: + return "OFF"; + break; + case 1: + return "ON"; + break; +#ifdef USE_MCP230xx_OUTPUT + case 2: + return "TOGGLE"; + break; +#endif // USE_MCP230xx_OUTPUT + default: + break; + } +} + uint8_t MCP230xx_readGPIO(uint8_t port) { return I2cRead8(mcp230xx_address, MCP230xx_GPIO + port); } @@ -78,9 +101,9 @@ void MCP230xx_ApplySettings(void) { uint8_t reg_gppu = 0; uint8_t reg_gpinten = 0; uint8_t reg_iodir = 0xFF; -#ifdef USE_MCP230xx_OUTPUT +#ifdef USE_MCP230xx_OUTPUT uint8_t reg_portpins = 0x00; -#endif +#endif for (uint8_t idx = 0; idx < 8; idx++) { switch (Settings.mcp230xx_config[idx+(mcp230xx_port*8)].pinmode) { case 0 ... 1: @@ -92,7 +115,7 @@ void MCP230xx_ApplySettings(void) { int_en=1; break; #ifdef USE_MCP230xx_OUTPUT - case 5: + case 5 ... 6: reg_iodir &= ~(1 << idx); if (Settings.flag.save_state) { // Firmware configuration wants us to use the last pin state reg_portpins |= (Settings.mcp230xx_config[idx+(mcp230xx_port*8)].saved_state << idx); @@ -102,12 +125,12 @@ void MCP230xx_ApplySettings(void) { } } break; -#endif // USE_MCP230xx_OUTPUT +#endif // USE_MCP230xx_OUTPUT default: break; } #ifdef USE_MCP230xx_OUTPUT - if (Settings.mcp230xx_config[idx+(mcp230xx_port*8)].pullup && (Settings.mcp230xx_config[idx+(mcp230xx_port*8)].pinmode != 5)) { + if (Settings.mcp230xx_config[idx+(mcp230xx_port*8)].pullup && (Settings.mcp230xx_config[idx+(mcp230xx_port*8)].pinmode < 5)) { reg_gppu |= (1 << idx); } #else @@ -119,21 +142,21 @@ void MCP230xx_ApplySettings(void) { I2cWrite8(mcp230xx_address, MCP230xx_GPPU+mcp230xx_port, reg_gppu); I2cWrite8(mcp230xx_address, MCP230xx_GPINTEN+mcp230xx_port, reg_gpinten); I2cWrite8(mcp230xx_address, MCP230xx_IODIR+mcp230xx_port, reg_iodir); -#ifdef USE_MCP230xx_OUTPUT +#ifdef USE_MCP230xx_OUTPUT I2cWrite8(mcp230xx_address, MCP230xx_GPIO+mcp230xx_port, reg_portpins); -#endif +#endif } mcp230xx_int_en=int_en; } void MCP230xx_Detect() { + uint8_t buffer; + if (mcp230xx_type) { return; } - uint8_t buffer; - for (byte i = 0; i < sizeof(mcp230xx_addresses); i++) { mcp230xx_address = mcp230xx_addresses[i]; I2cWrite8(mcp230xx_address, MCP230xx_IOCON, 0x80); // attempt to set bank mode - this will only work on MCP23017, so its the best way to detect the different chips 23008 vs 23017 @@ -233,11 +256,11 @@ void MCP230xx_Show(boolean json) void MCP230xx_SetOutPin(uint8_t pin,uint8_t pinstate) { uint8_t portpins; uint8_t port = 0; - char cmnd[7]; + char cmnd[7], stt[4]; if (pin > 7) port=1; portpins = MCP230xx_readGPIO(port); if (pinstate < 2) { - if (pinstate) portpins |= (1 << pin-(port*8)); else portpins &= ~(1 << pin-(port*8)); + if (pinstate) portpins |= (1 << pin-(port*8)); else portpins &= ~(1 << pin-(port*8)); } else { portpins ^= (1 << pin-(port*8)); } @@ -245,20 +268,10 @@ void MCP230xx_SetOutPin(uint8_t pin,uint8_t pinstate) { if (Settings.flag.save_state) { // Firmware configured to save last known state in settings Settings.mcp230xx_config[pin].saved_state=portpins>>(pin-(port*8))&1; } - switch (pinstate) { - case 0: - sprintf(cmnd,"OFF"); - break; - case 1: - sprintf(cmnd,"ON"); - break; - case 2: - sprintf(cmnd,"TOGGLE"); - break; - default: - break; - } - snprintf_P(mqtt_data, sizeof(mqtt_data), MCP230XX_CMND_RESPONSE, pin, cmnd,(portpins >> (pin-(port*8)))&1); + uint8_t pinmo = Settings.mcp230xx_config[pin].pinmode; + sprintf(cmnd,ConvertNumTxt(pinstate, pinmo)); + sprintf(stt,ConvertNumTxt((portpins >> (pin-(port*8))&1), pinmo)); + snprintf_P(mqtt_data, sizeof(mqtt_data), MCP230XX_CMND_RESPONSE, pin, cmnd, stt); } #endif // USE_MCP230xx_OUTPUT @@ -275,7 +288,9 @@ void MCP230xx_Reset(uint8_t pinmode) { Settings.mcp230xx_config[pinx].b7=0; } MCP230xx_ApplySettings(); - snprintf_P(mqtt_data, sizeof(mqtt_data), MCP230XX_SENSOR_RESPONSE,99,pinmode,pullup,99); + char pulluptxt[4]; + sprintf(pulluptxt,ConvertNumTxt(pullup)); + snprintf_P(mqtt_data, sizeof(mqtt_data), MCP230XX_SENSOR_RESPONSE,99,pinmode,pulluptxt,""); } bool MCP230xx_Command(void) { @@ -291,7 +306,7 @@ bool MCP230xx_Command(void) { if (data == "RESET4") { MCP230xx_Reset(4); return serviced; } #ifdef USE_MCP230xx_OUTPUT if (data == "RESET5") { MCP230xx_Reset(5); return serviced; } -#endif +#endif _a = data.indexOf(","); pin = data.substring(0, _a).toInt(); if (pin < mcp230xx_pincount) { @@ -300,17 +315,27 @@ bool MCP230xx_Command(void) { uint8_t port = 0; if (pin > 7) port = 1; uint8_t portdata = MCP230xx_readGPIO(port); - snprintf_P(mqtt_data, sizeof(mqtt_data), MCP230XX_SENSOR_RESPONSE,pin,Settings.mcp230xx_config[pin].pinmode,Settings.mcp230xx_config[pin].pullup,portdata>>(pin-(port*8))&1); + char pulluptxtr[4],pinstatustxtr[4]; + sprintf(pulluptxtr,ConvertNumTxt(Settings.mcp230xx_config[pin].pullup)); +#ifdef USE_MCP230xx_OUTPUT + uint8_t pinmod = Settings.mcp230xx_config[pin].pinmode; + sprintf(pinstatustxtr,ConvertNumTxt(portdata>>(pin-(port*8))&1,pinmod)); + snprintf_P(mqtt_data, sizeof(mqtt_data), MCP230XX_SENSOR_RESPONSE,pin,pinmod,pulluptxtr,pinstatustxtr); +#else + sprintf(pinstatustxtr,ConvertNumTxt(portdata>>(pin-(port*8))&1)); + snprintf_P(mqtt_data, sizeof(mqtt_data), MCP230XX_SENSOR_RESPONSE,pin,Settings.mcp230xx_config[pin].pinmode,pulluptxtr,pinstatustxtr); +#endif //USE_MCP230xx_OUTPUT return serviced; } #ifdef USE_MCP230xx_OUTPUT - if (Settings.mcp230xx_config[pin].pinmode == 5) { + if (Settings.mcp230xx_config[pin].pinmode >= 5) { + uint8_t pincmd = Settings.mcp230xx_config[pin].pinmode - 5; if (cmnd == "ON") { - MCP230xx_SetOutPin(pin,1); + MCP230xx_SetOutPin(pin,abs(pincmd-1)); return serviced; } if (cmnd == "OFF") { - MCP230xx_SetOutPin(pin,0); + MCP230xx_SetOutPin(pin,pincmd); return serviced; } if (cmnd == "T") { @@ -318,7 +343,7 @@ bool MCP230xx_Command(void) { return serviced; } } -#endif // USE_MCP230xx_OUTPUT +#endif // USE_MCP230xx_OUTPUT } _b = data.indexOf(",", _a + 1); if (_a < XdrvMailbox.data_len) { @@ -326,17 +351,24 @@ bool MCP230xx_Command(void) { pinmode = data.substring(_a+1, _b).toInt(); pullup = data.substring(_b+1, XdrvMailbox.data_len).toInt(); #ifdef USE_MCP230xx_OUTPUT - if ((pin < mcp230xx_pincount) && (pinmode < 6) && (pullup < 2)) { -#else // not USE_MCP230xx_OUTPUT + if ((pin < mcp230xx_pincount) && (pinmode < 7) && (pullup < 2)) { +#else // not USE_MCP230xx_OUTPUT if ((pin < mcp230xx_pincount) && (pinmode < 5) && (pullup < 2)) { -#endif // USE_MCP230xx_OUTPUT +#endif // USE_MCP230xx_OUTPUT Settings.mcp230xx_config[pin].pinmode=pinmode; Settings.mcp230xx_config[pin].pullup=pullup; MCP230xx_ApplySettings(); uint8_t port = 0; if (pin > 7) port = 1; uint8_t portdata = MCP230xx_readGPIO(port); - snprintf_P(mqtt_data, sizeof(mqtt_data), MCP230XX_SENSOR_RESPONSE,pin,pinmode,pullup,portdata>>(pin-(port*8))&1); + char pulluptxtc[4], pinstatustxtc[4]; + sprintf(pulluptxtc,ConvertNumTxt(pullup)); +#ifdef USE_MCP230xx_OUTPUT + sprintf(pinstatustxtc,ConvertNumTxt(portdata>>(pin-(port*8))&1,Settings.mcp230xx_config[pin].pinmode)); +#else // not USE_MCP230xx_OUTPUT + sprintf(pinstatustxtc,ConvertNumTxt(portdata>>(pin-(port*8))&1)); +#endif // USE_MCP230xx_OUTPUT + snprintf_P(mqtt_data, sizeof(mqtt_data), MCP230XX_SENSOR_RESPONSE,pin,pinmode,pulluptxtc,pinstatustxtc); } else { serviced = false; } @@ -351,7 +383,7 @@ bool MCP230xx_Command(void) { #ifdef USE_MCP230xx_DISPLAYOUTPUT -const char HTTP_SNS_MCP230xx_OUTPUT[] PROGMEM = "%s{s}MCP230XX D%d{m}%d{e}"; // {s} = , {m} = , {e} = +const char HTTP_SNS_MCP230xx_OUTPUT[] PROGMEM = "%s{s}MCP230XX D%d{m}%s{e}"; // {s} = , {m} = , {e} = void MCP230xx_UpdateWebData(void) { uint8_t gpio1 = MCP230xx_readGPIO(0); @@ -361,8 +393,10 @@ void MCP230xx_UpdateWebData(void) { } uint16_t gpio = (gpio2 << 8) + gpio1; for (uint8_t pin = 0; pin < mcp230xx_pincount; pin++) { - if (Settings.mcp230xx_config[pin].pinmode == 5) { - snprintf_P(mqtt_data, sizeof(mqtt_data), HTTP_SNS_MCP230xx_OUTPUT, mqtt_data, pin, (gpio>>pin)&1); + if (Settings.mcp230xx_config[pin].pinmode >= 5) { + char stt[4]; + sprintf(stt,ConvertNumTxt((gpio>>pin)&1,Settings.mcp230xx_config[pin].pinmode)); + snprintf_P(mqtt_data, sizeof(mqtt_data), HTTP_SNS_MCP230xx_OUTPUT, mqtt_data, pin, stt); } } } @@ -381,13 +415,15 @@ void MCP230xx_OutputTelemetry(void) { if (mcp230xx_type == 2) gpiob=MCP230xx_readGPIO(1); gpiototal=((uint16_t)gpiob<<8) | gpioa; for (uint8_t pinx = 0;pinx < mcp230xx_pincount;pinx++) { - if (Settings.mcp230xx_config[pinx].pinmode == 5) outputcount++; + if (Settings.mcp230xx_config[pinx].pinmode >= 5) outputcount++; } if (outputcount) { + char stt[4]; snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("{\"" D_JSON_TIME "\":\"%s\",\"MCP230_OUT\": {"), GetDateAndTime(DT_LOCAL).c_str()); for (uint8_t pinx = 0;pinx < mcp230xx_pincount;pinx++) { - if (Settings.mcp230xx_config[pinx].pinmode == 5) { - snprintf_P(mqtt_data,sizeof(mqtt_data), PSTR("%s\"OUTD%i\":%i,"),mqtt_data,pinx,(gpiototal>>pinx)&1); + if (Settings.mcp230xx_config[pinx].pinmode >= 5) { + sprintf(stt,ConvertNumTxt(((gpiototal>>pinx)&1),Settings.mcp230xx_config[pinx].pinmode)); + snprintf_P(mqtt_data,sizeof(mqtt_data), PSTR("%s\"OUTD%i\":%s,"),mqtt_data,pinx,stt); } } snprintf_P(mqtt_data,sizeof(mqtt_data),PSTR("%s\"END\":1}}"),mqtt_data); @@ -400,7 +436,7 @@ void MCP230xx_OutputTelemetry(void) { /*********************************************************************************************\ Interface - \*********************************************************************************************/ +\*********************************************************************************************/ boolean Xsns29(byte function) { @@ -416,7 +452,7 @@ boolean Xsns29(byte function) mcp230xx_tele_count=0; MCP230xx_OutputTelemetry(); } -#endif +#endif break; case FUNC_EVERY_50_MSECOND: if (mcp230xx_int_en) { // Only check for interrupts if its enabled on one of the pins @@ -449,4 +485,3 @@ boolean Xsns29(byte function) #endif // USE_MCP230xx #endif // USE_I2C - From 4d9a034663224efc1444e39cdf2804f669a85120 Mon Sep 17 00:00:00 2001 From: MadDoct <32080323+MadDoct@users.noreply.github.com> Date: Tue, 14 Aug 2018 16:45:06 +0100 Subject: [PATCH 03/15] Change output data some more... --- sonoff/xsns_29_mcp230xx.ino | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/sonoff/xsns_29_mcp230xx.ino b/sonoff/xsns_29_mcp230xx.ino index 04b06457f..9d22ff2a4 100644 --- a/sonoff/xsns_29_mcp230xx.ino +++ b/sonoff/xsns_29_mcp230xx.ino @@ -62,10 +62,10 @@ uint8_t mcp230xx_int_en = 0; uint16_t mcp230xx_tele_count = 0; #endif -const char MCP230XX_SENSOR_RESPONSE[] PROGMEM = "{\"Sensor29-D%i\":{\"MODE\":%i,\"PULL-UP\":\"%s\",\"STATE\":\"%s\"}}"; +const char MCP230XX_SENSOR_RESPONSE[] PROGMEM = "{\"Sensor29_D%i\":{\"MODE\":%i,\"PULL-UP\":\"%s\",\"STATE\":\"%s\"}}"; #ifdef USE_MCP230xx_OUTPUT -const char MCP230XX_CMND_RESPONSE[] PROGMEM = "{\"S29cmnd-D%i\":{\"COMMAND\":\"%s\",\"STATE\":\"%s\"}}"; +const char MCP230XX_CMND_RESPONSE[] PROGMEM = "{\"S29cmnd_D%i\":{\"COMMAND\":\"%s\",\"STATE\":\"%s\"}}"; #endif // USE_MCP230xx_OUTPUT const char* ConvertNumTxt(uint8_t statu, uint8_t pinmod=0) { @@ -220,7 +220,7 @@ bool MCP230xx_CheckForInterrupt(void) { snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s}"), mqtt_data); MqttPublishPrefixTopic_P(RESULT_OR_STAT, mqtt_data); char command[18]; - sprintf(command,"event MCPINTD%i=%i",intp+(mcp230xx_port*8),((mcp230xx_intcap >> intp) & 0x01)); + sprintf(command,"event MCPINT_D%i=%i",intp+(mcp230xx_port*8),((mcp230xx_intcap >> intp) & 0x01)); ExecuteCommand(command, SRC_RULE); } } @@ -423,7 +423,7 @@ void MCP230xx_OutputTelemetry(void) { for (uint8_t pinx = 0;pinx < mcp230xx_pincount;pinx++) { if (Settings.mcp230xx_config[pinx].pinmode >= 5) { sprintf(stt,ConvertNumTxt(((gpiototal>>pinx)&1),Settings.mcp230xx_config[pinx].pinmode)); - snprintf_P(mqtt_data,sizeof(mqtt_data), PSTR("%s\"OUTD%i\":%s,"),mqtt_data,pinx,stt); + snprintf_P(mqtt_data,sizeof(mqtt_data), PSTR("%s\"OUT_D%i\":%s,"),mqtt_data,pinx,stt); } } snprintf_P(mqtt_data,sizeof(mqtt_data),PSTR("%s\"END\":1}}"),mqtt_data); From b946d9e233f51b20b04df12e5b6fabfa3d9ee9a8 Mon Sep 17 00:00:00 2001 From: MadDoct <32080323+MadDoct@users.noreply.github.com> Date: Tue, 14 Aug 2018 18:35:18 +0100 Subject: [PATCH 04/15] Update xsns_29_mcp230xx.ino --- sonoff/xsns_29_mcp230xx.ino | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sonoff/xsns_29_mcp230xx.ino b/sonoff/xsns_29_mcp230xx.ino index 9d22ff2a4..5de0febb0 100644 --- a/sonoff/xsns_29_mcp230xx.ino +++ b/sonoff/xsns_29_mcp230xx.ino @@ -423,7 +423,7 @@ void MCP230xx_OutputTelemetry(void) { for (uint8_t pinx = 0;pinx < mcp230xx_pincount;pinx++) { if (Settings.mcp230xx_config[pinx].pinmode >= 5) { sprintf(stt,ConvertNumTxt(((gpiototal>>pinx)&1),Settings.mcp230xx_config[pinx].pinmode)); - snprintf_P(mqtt_data,sizeof(mqtt_data), PSTR("%s\"OUT_D%i\":%s,"),mqtt_data,pinx,stt); + snprintf_P(mqtt_data,sizeof(mqtt_data), PSTR("%s\"OUT_D%i\":\"%s\","),mqtt_data,pinx,stt); } } snprintf_P(mqtt_data,sizeof(mqtt_data),PSTR("%s\"END\":1}}"),mqtt_data); From 18f47be237cc7cb9fc48b8c35b65c5bdd0f9aa90 Mon Sep 17 00:00:00 2001 From: andrethomas Date: Tue, 14 Aug 2018 21:36:10 +0200 Subject: [PATCH 05/15] Cleanup #else and #endif statements with // USE_MCP230xx_OUTPUT comments --- sonoff/xsns_29_mcp230xx.ino | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/sonoff/xsns_29_mcp230xx.ino b/sonoff/xsns_29_mcp230xx.ino index 5de0febb0..9d4ab89fc 100644 --- a/sonoff/xsns_29_mcp230xx.ino +++ b/sonoff/xsns_29_mcp230xx.ino @@ -60,7 +60,7 @@ uint8_t mcp230xx_int_en = 0; #ifdef USE_MCP230xx_OUTPUT uint16_t mcp230xx_tele_count = 0; -#endif +#endif // USE_MCP230xx_OUTPUT const char MCP230XX_SENSOR_RESPONSE[] PROGMEM = "{\"Sensor29_D%i\":{\"MODE\":%i,\"PULL-UP\":\"%s\",\"STATE\":\"%s\"}}"; @@ -103,7 +103,7 @@ void MCP230xx_ApplySettings(void) { uint8_t reg_iodir = 0xFF; #ifdef USE_MCP230xx_OUTPUT uint8_t reg_portpins = 0x00; -#endif +#endif USE_MCP230xx_OUTPUT for (uint8_t idx = 0; idx < 8; idx++) { switch (Settings.mcp230xx_config[idx+(mcp230xx_port*8)].pinmode) { case 0 ... 1: @@ -133,18 +133,18 @@ void MCP230xx_ApplySettings(void) { if (Settings.mcp230xx_config[idx+(mcp230xx_port*8)].pullup && (Settings.mcp230xx_config[idx+(mcp230xx_port*8)].pinmode < 5)) { reg_gppu |= (1 << idx); } -#else +#else // not USE_MCP230xx_OUTPUT if (Settings.mcp230xx_config[idx+(mcp230xx_port*8)].pullup) { reg_gppu |= (1 << idx); } -#endif +#endif // USE_MCP230xx_OUTPUT } I2cWrite8(mcp230xx_address, MCP230xx_GPPU+mcp230xx_port, reg_gppu); I2cWrite8(mcp230xx_address, MCP230xx_GPINTEN+mcp230xx_port, reg_gpinten); I2cWrite8(mcp230xx_address, MCP230xx_IODIR+mcp230xx_port, reg_iodir); #ifdef USE_MCP230xx_OUTPUT I2cWrite8(mcp230xx_address, MCP230xx_GPIO+mcp230xx_port, reg_portpins); -#endif +#endif // USE_MCP230xx_OUTPUT } mcp230xx_int_en=int_en; } @@ -306,7 +306,7 @@ bool MCP230xx_Command(void) { if (data == "RESET4") { MCP230xx_Reset(4); return serviced; } #ifdef USE_MCP230xx_OUTPUT if (data == "RESET5") { MCP230xx_Reset(5); return serviced; } -#endif +#endif // USE_MCP230xx_OUTPUT _a = data.indexOf(","); pin = data.substring(0, _a).toInt(); if (pin < mcp230xx_pincount) { @@ -321,7 +321,7 @@ bool MCP230xx_Command(void) { uint8_t pinmod = Settings.mcp230xx_config[pin].pinmode; sprintf(pinstatustxtr,ConvertNumTxt(portdata>>(pin-(port*8))&1,pinmod)); snprintf_P(mqtt_data, sizeof(mqtt_data), MCP230XX_SENSOR_RESPONSE,pin,pinmod,pulluptxtr,pinstatustxtr); -#else +#else // not USE_MCP230xx_OUTPUT sprintf(pinstatustxtr,ConvertNumTxt(portdata>>(pin-(port*8))&1)); snprintf_P(mqtt_data, sizeof(mqtt_data), MCP230XX_SENSOR_RESPONSE,pin,Settings.mcp230xx_config[pin].pinmode,pulluptxtr,pinstatustxtr); #endif //USE_MCP230xx_OUTPUT @@ -431,7 +431,7 @@ void MCP230xx_OutputTelemetry(void) { } } -#endif +#endif // USE_MCP230xx_OUTPUT /*********************************************************************************************\ @@ -452,7 +452,7 @@ boolean Xsns29(byte function) mcp230xx_tele_count=0; MCP230xx_OutputTelemetry(); } -#endif +#endif // USE_MCP230xx_OUTPUT break; case FUNC_EVERY_50_MSECOND: if (mcp230xx_int_en) { // Only check for interrupts if its enabled on one of the pins From db223b9d10a9802a3575d79e88edd220754a0753 Mon Sep 17 00:00:00 2001 From: andrethomas Date: Tue, 14 Aug 2018 21:41:17 +0200 Subject: [PATCH 06/15] Update xsns_29_mcp230xx.ino --- sonoff/xsns_29_mcp230xx.ino | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sonoff/xsns_29_mcp230xx.ino b/sonoff/xsns_29_mcp230xx.ino index 9d4ab89fc..6ef5a3835 100644 --- a/sonoff/xsns_29_mcp230xx.ino +++ b/sonoff/xsns_29_mcp230xx.ino @@ -70,7 +70,7 @@ const char MCP230XX_CMND_RESPONSE[] PROGMEM = "{\"S29cmnd_D%i\":{\"COMMAND\":\"% const char* ConvertNumTxt(uint8_t statu, uint8_t pinmod=0) { #ifdef USE_MCP230xx_OUTPUT -if (pinmod==6) { +if (pinmod == 6) { if (statu < 2) statu = abs(statu-1); } #endif // USE_MCP230xx_OUTPUT From 50f2eb38118dd0718071dd592ae38cff0df08b86 Mon Sep 17 00:00:00 2001 From: andrethomas Date: Tue, 14 Aug 2018 21:44:33 +0200 Subject: [PATCH 07/15] Update xsns_29_mcp230xx.ino --- sonoff/xsns_29_mcp230xx.ino | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sonoff/xsns_29_mcp230xx.ino b/sonoff/xsns_29_mcp230xx.ino index 6ef5a3835..b530b8a76 100644 --- a/sonoff/xsns_29_mcp230xx.ino +++ b/sonoff/xsns_29_mcp230xx.ino @@ -1,5 +1,5 @@ /* - xsns_29_mcp230xx.ino - Support for I2C MCP23008/MCP23017 GPIO Expander (INPUT AND OUTPUT) + xsns_29_mcp230xx.ino - Support for I2C MCP23008/MCP23017 GPIO Expander Copyright (C) 2018 Andre Thomas and Theo Arends From 1b714b0320062bca1efa0348b5443e2bdfdb6401 Mon Sep 17 00:00:00 2001 From: andrethomas Date: Tue, 14 Aug 2018 21:45:56 +0200 Subject: [PATCH 08/15] Update xsns_29_mcp230xx.ino --- sonoff/xsns_29_mcp230xx.ino | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/sonoff/xsns_29_mcp230xx.ino b/sonoff/xsns_29_mcp230xx.ino index b530b8a76..73608372d 100644 --- a/sonoff/xsns_29_mcp230xx.ino +++ b/sonoff/xsns_29_mcp230xx.ino @@ -27,7 +27,7 @@ https://www.microchip.com/wwwproducts/en/MCP23017 I2C Address: 0x20 - 0x27 - \*********************************************************************************************/ +\*********************************************************************************************/ #define XSNS_29 29 @@ -151,11 +151,11 @@ void MCP230xx_ApplySettings(void) { void MCP230xx_Detect() { - uint8_t buffer; - if (mcp230xx_type) { return; } + + uint8_t buffer; for (byte i = 0; i < sizeof(mcp230xx_addresses); i++) { mcp230xx_address = mcp230xx_addresses[i]; From 2d36f2e447ba8bacba1d70d11c5050c052acb990 Mon Sep 17 00:00:00 2001 From: MadDoct <32080323+MadDoct@users.noreply.github.com> Date: Tue, 14 Aug 2018 23:49:34 +0100 Subject: [PATCH 09/15] Added interlocking output in pairs If Setoption14 is set The output pins will have paired interlocking (D0 with D1, D2 with D3, etc...) as long as: They have the same mode (both have pinmode 5 or both have 6) --- sonoff/xsns_29_mcp230xx.ino | 25 ++++++++++++++++++++----- 1 file changed, 20 insertions(+), 5 deletions(-) diff --git a/sonoff/xsns_29_mcp230xx.ino b/sonoff/xsns_29_mcp230xx.ino index 5de0febb0..2e9045b77 100644 --- a/sonoff/xsns_29_mcp230xx.ino +++ b/sonoff/xsns_29_mcp230xx.ino @@ -256,19 +256,33 @@ void MCP230xx_Show(boolean json) void MCP230xx_SetOutPin(uint8_t pin,uint8_t pinstate) { uint8_t portpins; uint8_t port = 0; + uint8_t pinmo = Settings.mcp230xx_config[pin].pinmode; + uint8_t interlock = Settings.flag.interlock; + int pinadd = (pin % 2)+1-(3*(pin % 2)); //check if pin is odd or even and convert to 1 (if even) or -1 (if odd) char cmnd[7], stt[4]; if (pin > 7) port=1; portpins = MCP230xx_readGPIO(port); - if (pinstate < 2) { - if (pinstate) portpins |= (1 << pin-(port*8)); else portpins &= ~(1 << pin-(port*8)); - } else { - portpins ^= (1 << pin-(port*8)); + if (interlock && pinmo == Settings.mcp230xx_config[pin+pinadd].pinmode) { + if (pinstate < 2) { + if (pinmo == 6) { + if (pinstate) portpins |= (1 << pin-(port*8)); else portpins |= (1 << pin+pinadd-(port*8)),portpins &= ~(1 << pin-(port*8)); + } else { + if (pinstate) portpins &= ~(1 << pin+pinadd-(port*8)),portpins |= (1 << pin-(port*8)); else portpins &= ~(1 << pin-(port*8)); + } + } else { + portpins &= ~(1 << pin+pinadd-(port*8)),portpins ^= (1 << pin-(port*8)); } +} else { + if (pinstate < 2) { + if (pinstate) portpins |= (1 << pin-(port*8)); else portpins &= ~(1 << pin-(port*8)); + } else { + portpins ^= (1 << pin-(port*8)); +} +} I2cWrite8(mcp230xx_address, MCP230xx_GPIO + port, portpins); if (Settings.flag.save_state) { // Firmware configured to save last known state in settings Settings.mcp230xx_config[pin].saved_state=portpins>>(pin-(port*8))&1; } - uint8_t pinmo = Settings.mcp230xx_config[pin].pinmode; sprintf(cmnd,ConvertNumTxt(pinstate, pinmo)); sprintf(stt,ConvertNumTxt((portpins >> (pin-(port*8))&1), pinmo)); snprintf_P(mqtt_data, sizeof(mqtt_data), MCP230XX_CMND_RESPONSE, pin, cmnd, stt); @@ -306,6 +320,7 @@ bool MCP230xx_Command(void) { if (data == "RESET4") { MCP230xx_Reset(4); return serviced; } #ifdef USE_MCP230xx_OUTPUT if (data == "RESET5") { MCP230xx_Reset(5); return serviced; } + if (data == "RESET6") { MCP230xx_Reset(6); return serviced; } #endif _a = data.indexOf(","); pin = data.substring(0, _a).toInt(); From 6818f8d92aa83481014ac22f6e40dc889c297e9f Mon Sep 17 00:00:00 2001 From: andrethomas Date: Wed, 15 Aug 2018 10:23:02 +0200 Subject: [PATCH 10/15] Change mcp230xx_config bits and do some housekeeping on formatting --- sonoff/settings.h | 6 +++--- sonoff/xsns_29_mcp230xx.ino | 18 +++++++++--------- 2 files changed, 12 insertions(+), 12 deletions(-) diff --git a/sonoff/settings.h b/sonoff/settings.h index c2def2466..835710c63 100644 --- a/sonoff/settings.h +++ b/sonoff/settings.h @@ -154,11 +154,11 @@ typedef union { typedef union { uint8_t data; struct { - uint8_t pinmode : 3; // Pin mode (1 through 5) + uint8_t pinmode : 3; // Pin mode (1 through 6) uint8_t pullup : 1; // Enable internal weak pull-up resistor uint8_t saved_state : 1; // Save output state, if used. - uint8_t b5 : 1; - uint8_t b6 : 1; + uint8_t int_event_enable : 1; // Enable interrupt to cause immediate event transmit + uint8_t int_tele_enable : 1; // Enable interrupt to cause immediate telemetry transmit uint8_t b7 : 1; }; } Mcp230xxCfg; diff --git a/sonoff/xsns_29_mcp230xx.ino b/sonoff/xsns_29_mcp230xx.ino index 04e61ff58..c6c96f2fe 100644 --- a/sonoff/xsns_29_mcp230xx.ino +++ b/sonoff/xsns_29_mcp230xx.ino @@ -271,14 +271,14 @@ void MCP230xx_SetOutPin(uint8_t pin,uint8_t pinstate) { } } else { portpins &= ~(1 << pin+pinadd-(port*8)),portpins ^= (1 << pin-(port*8)); - } -} else { - if (pinstate < 2) { - if (pinstate) portpins |= (1 << pin-(port*8)); else portpins &= ~(1 << pin-(port*8)); + } + } else { + if (pinstate < 2) { + if (pinstate) portpins |= (1 << pin-(port*8)); else portpins &= ~(1 << pin-(port*8)); } else { - portpins ^= (1 << pin-(port*8)); -} -} + portpins ^= (1 << pin-(port*8)); + } + } I2cWrite8(mcp230xx_address, MCP230xx_GPIO + port, portpins); if (Settings.flag.save_state) { // Firmware configured to save last known state in settings Settings.mcp230xx_config[pin].saved_state=portpins>>(pin-(port*8))&1; @@ -297,8 +297,8 @@ void MCP230xx_Reset(uint8_t pinmode) { Settings.mcp230xx_config[pinx].pinmode=pinmode; Settings.mcp230xx_config[pinx].pullup=pullup; Settings.mcp230xx_config[pinx].saved_state=0; - Settings.mcp230xx_config[pinx].b5=0; - Settings.mcp230xx_config[pinx].b6=0; + Settings.mcp230xx_config[pinx].int_event_enable=0; + Settings.mcp230xx_config[pinx].int_tele_enable=0; Settings.mcp230xx_config[pinx].b7=0; } MCP230xx_ApplySettings(); From fd0e759f4205e6461bb144e95d27eb64fa1837a2 Mon Sep 17 00:00:00 2001 From: andrethomas Date: Wed, 15 Aug 2018 13:16:12 +0200 Subject: [PATCH 11/15] Update output telemetry timing --- sonoff/xsns_29_mcp230xx.ino | 45 ++++++++++++++++++++++++------------- 1 file changed, 29 insertions(+), 16 deletions(-) diff --git a/sonoff/xsns_29_mcp230xx.ino b/sonoff/xsns_29_mcp230xx.ino index c6c96f2fe..90c379b1b 100644 --- a/sonoff/xsns_29_mcp230xx.ino +++ b/sonoff/xsns_29_mcp230xx.ino @@ -58,10 +58,6 @@ uint8_t mcp230xx_addresses[] = { MCP230xx_ADDRESS1, MCP230xx_ADDRESS2, MCP230xx_ uint8_t mcp230xx_pincount = 0; uint8_t mcp230xx_int_en = 0; -#ifdef USE_MCP230xx_OUTPUT -uint16_t mcp230xx_tele_count = 0; -#endif // USE_MCP230xx_OUTPUT - const char MCP230XX_SENSOR_RESPONSE[] PROGMEM = "{\"Sensor29_D%i\":{\"MODE\":%i,\"PULL-UP\":\"%s\",\"STATE\":\"%s\"}}"; #ifdef USE_MCP230xx_OUTPUT @@ -215,13 +211,31 @@ bool MCP230xx_CheckForInterrupt(void) { break; } if (report_int) { - snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("{\"" D_JSON_TIME "\":\"%s\""), GetDateAndTime(DT_LOCAL).c_str()); - snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s,\"MCP230XX_INT\":{\"D%i\":%i}"), mqtt_data, intp+(mcp230xx_port*8), ((mcp230xx_intcap >> intp) & 0x01)); - snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s}"), mqtt_data); - MqttPublishPrefixTopic_P(RESULT_OR_STAT, mqtt_data); - char command[18]; - sprintf(command,"event MCPINT_D%i=%i",intp+(mcp230xx_port*8),((mcp230xx_intcap >> intp) & 0x01)); - ExecuteCommand(command, SRC_RULE); + bool int_tele = false; + bool int_event = false; + switch (Settings.mcp230xx_config[intp+(mcp230xx_port*8)].int_report_mode) { + case 0: + int_tele=true; + int_event=true; + break; + case 1: + int_event=true; + break; + case 2: + int_tele=true; + break; + } + if (int_tele) { + snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("{\"" D_JSON_TIME "\":\"%s\""), GetDateAndTime(DT_LOCAL).c_str()); + snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s,\"MCP230XX_INT\":{\"D%i\":%i}"), mqtt_data, intp+(mcp230xx_port*8), ((mcp230xx_intcap >> intp) & 0x01)); + snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s}"), mqtt_data); + MqttPublishPrefixTopic_P(RESULT_OR_STAT, mqtt_data); + } + if (int_event) { + char command[18]; + sprintf(command,"event MCPINT_D%i=%i",intp+(mcp230xx_port*8),((mcp230xx_intcap >> intp) & 0x01)); + ExecuteCommand(command, SRC_RULE); + } } } } @@ -297,8 +311,7 @@ void MCP230xx_Reset(uint8_t pinmode) { Settings.mcp230xx_config[pinx].pinmode=pinmode; Settings.mcp230xx_config[pinx].pullup=pullup; Settings.mcp230xx_config[pinx].saved_state=0; - Settings.mcp230xx_config[pinx].int_event_enable=0; - Settings.mcp230xx_config[pinx].int_tele_enable=0; + Settings.mcp230xx_config[pinx].int_report_mode=0; Settings.mcp230xx_config[pinx].b7=0; } MCP230xx_ApplySettings(); @@ -460,12 +473,12 @@ boolean Xsns29(byte function) if (i2c_flg) { switch (function) { + case FUNC_MQTT_DATA: + break; case FUNC_EVERY_SECOND: MCP230xx_Detect(); #ifdef USE_MCP230xx_OUTPUT - mcp230xx_tele_count++; - if (mcp230xx_tele_count >= Settings.tele_period) { - mcp230xx_tele_count=0; + if (tele_period == 0) { MCP230xx_OutputTelemetry(); } #endif // USE_MCP230xx_OUTPUT From 084f3d486cb7577d045a4e52a6886bcedbc525a9 Mon Sep 17 00:00:00 2001 From: andrethomas Date: Wed, 15 Aug 2018 22:07:25 +0200 Subject: [PATCH 12/15] Fix settings.h and compiler warning in xsns_29_mcp230xx.ino --- sonoff/settings.h | 3 +-- sonoff/xsns_29_mcp230xx.ino | 2 +- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/sonoff/settings.h b/sonoff/settings.h index 835710c63..c400e803d 100644 --- a/sonoff/settings.h +++ b/sonoff/settings.h @@ -157,8 +157,7 @@ typedef union { uint8_t pinmode : 3; // Pin mode (1 through 6) uint8_t pullup : 1; // Enable internal weak pull-up resistor uint8_t saved_state : 1; // Save output state, if used. - uint8_t int_event_enable : 1; // Enable interrupt to cause immediate event transmit - uint8_t int_tele_enable : 1; // Enable interrupt to cause immediate telemetry transmit + uint8_t int_report_mode : 2; // Interrupt reporting mode 0 = immediate telemetry & event, 1 = immediate event only, 2 = immediate telemetry only uint8_t b7 : 1; }; } Mcp230xxCfg; diff --git a/sonoff/xsns_29_mcp230xx.ino b/sonoff/xsns_29_mcp230xx.ino index 90c379b1b..39da4bcf7 100644 --- a/sonoff/xsns_29_mcp230xx.ino +++ b/sonoff/xsns_29_mcp230xx.ino @@ -99,7 +99,7 @@ void MCP230xx_ApplySettings(void) { uint8_t reg_iodir = 0xFF; #ifdef USE_MCP230xx_OUTPUT uint8_t reg_portpins = 0x00; -#endif USE_MCP230xx_OUTPUT +#endif // USE_MCP230xx_OUTPUT for (uint8_t idx = 0; idx < 8; idx++) { switch (Settings.mcp230xx_config[idx+(mcp230xx_port*8)].pinmode) { case 0 ... 1: From 3346660419f3b5063824cccc35a78328ab136dec Mon Sep 17 00:00:00 2001 From: andrethomas Date: Fri, 17 Aug 2018 00:18:45 +0200 Subject: [PATCH 13/15] Add intmode for pinmode 2 to 4 with sensor29 pin,pinmode,pullup,intmode - 0 = ALL, 1 = EVENT only, 2 = TELE only --- sonoff/xsns_29_mcp230xx.ino | 63 ++++++++++++++++++++++++++++++------- 1 file changed, 51 insertions(+), 12 deletions(-) diff --git a/sonoff/xsns_29_mcp230xx.ino b/sonoff/xsns_29_mcp230xx.ino index 39da4bcf7..3e1ce5269 100644 --- a/sonoff/xsns_29_mcp230xx.ino +++ b/sonoff/xsns_29_mcp230xx.ino @@ -58,7 +58,7 @@ uint8_t mcp230xx_addresses[] = { MCP230xx_ADDRESS1, MCP230xx_ADDRESS2, MCP230xx_ uint8_t mcp230xx_pincount = 0; uint8_t mcp230xx_int_en = 0; -const char MCP230XX_SENSOR_RESPONSE[] PROGMEM = "{\"Sensor29_D%i\":{\"MODE\":%i,\"PULL-UP\":\"%s\",\"STATE\":\"%s\"}}"; +const char MCP230XX_SENSOR_RESPONSE[] PROGMEM = "{\"Sensor29_D%i\":{\"MODE\":%i,\"PULL-UP\":\"%s\",\"INT_MODE\":\"%s\",\"STATE\":\"%s\"}}"; #ifdef USE_MCP230xx_OUTPUT const char MCP230XX_CMND_RESPONSE[] PROGMEM = "{\"S29cmnd_D%i\":{\"COMMAND\":\"%s\",\"STATE\":\"%s\"}}"; @@ -87,6 +87,26 @@ if (pinmod == 6) { } } +const char* IntModeTxt(uint8_t intmo) { + switch (intmo) { + case 0: + return "ALL"; + break; + case 1: + return "EVENT"; + break; + case 2: + return "TELE"; + break; + case 3: + return "DISABLED"; + break; + default: + return "UNKNOWN"; + break; + } +} + uint8_t MCP230xx_readGPIO(uint8_t port) { return I2cRead8(mcp230xx_address, MCP230xx_GPIO + port); } @@ -273,7 +293,7 @@ void MCP230xx_SetOutPin(uint8_t pin,uint8_t pinstate) { uint8_t pinmo = Settings.mcp230xx_config[pin].pinmode; uint8_t interlock = Settings.flag.interlock; int pinadd = (pin % 2)+1-(3*(pin % 2)); //check if pin is odd or even and convert to 1 (if even) or -1 (if odd) - char cmnd[7], stt[4]; + char cmnd[7], stt[7]; if (pin > 7) port=1; portpins = MCP230xx_readGPIO(port); if (interlock && pinmo == Settings.mcp230xx_config[pin+pinadd].pinmode) { @@ -315,9 +335,13 @@ void MCP230xx_Reset(uint8_t pinmode) { Settings.mcp230xx_config[pinx].b7=0; } MCP230xx_ApplySettings(); - char pulluptxt[4]; + char pulluptxt[7]; + char intmodetxt[9]; sprintf(pulluptxt,ConvertNumTxt(pullup)); - snprintf_P(mqtt_data, sizeof(mqtt_data), MCP230XX_SENSOR_RESPONSE,99,pinmode,pulluptxt,""); + uint8_t intmode = 3; + if (pinmode > 1 && pinmode < 5) intmode=0; + sprintf(intmodetxt,IntModeTxt(intmode)); + snprintf_P(mqtt_data, sizeof(mqtt_data), MCP230XX_SENSOR_RESPONSE,99,pinmode,pulluptxt,intmodetxt,""); } bool MCP230xx_Command(void) { @@ -344,15 +368,17 @@ bool MCP230xx_Command(void) { uint8_t port = 0; if (pin > 7) port = 1; uint8_t portdata = MCP230xx_readGPIO(port); - char pulluptxtr[4],pinstatustxtr[4]; + char pulluptxtr[7],pinstatustxtr[7]; + char intmodetxt[9]; + sprintf(intmodetxt,IntModeTxt(Settings.mcp230xx_config[pin].int_report_mode)); sprintf(pulluptxtr,ConvertNumTxt(Settings.mcp230xx_config[pin].pullup)); #ifdef USE_MCP230xx_OUTPUT uint8_t pinmod = Settings.mcp230xx_config[pin].pinmode; sprintf(pinstatustxtr,ConvertNumTxt(portdata>>(pin-(port*8))&1,pinmod)); - snprintf_P(mqtt_data, sizeof(mqtt_data), MCP230XX_SENSOR_RESPONSE,pin,pinmod,pulluptxtr,pinstatustxtr); + snprintf_P(mqtt_data, sizeof(mqtt_data), MCP230XX_SENSOR_RESPONSE,pin,pinmod,pulluptxtr,intmodetxt,pinstatustxtr); #else // not USE_MCP230xx_OUTPUT sprintf(pinstatustxtr,ConvertNumTxt(portdata>>(pin-(port*8))&1)); - snprintf_P(mqtt_data, sizeof(mqtt_data), MCP230XX_SENSOR_RESPONSE,pin,Settings.mcp230xx_config[pin].pinmode,pulluptxtr,pinstatustxtr); + snprintf_P(mqtt_data, sizeof(mqtt_data), MCP230XX_SENSOR_RESPONSE,pin,Settings.mcp230xx_config[pin].pinmode,pulluptxtr,intmodetxt,pinstatustxtr); #endif //USE_MCP230xx_OUTPUT return serviced; } @@ -377,8 +403,12 @@ bool MCP230xx_Command(void) { _b = data.indexOf(",", _a + 1); if (_a < XdrvMailbox.data_len) { if (_b < XdrvMailbox.data_len) { + // Lets see if we have a 4th parameter for interrupt mode + uint8_t _c = data.indexOf(",", _b + 1); + if (_c > XdrvMailbox.data_len) _c=XdrvMailbox.data_len; pinmode = data.substring(_a+1, _b).toInt(); - pullup = data.substring(_b+1, XdrvMailbox.data_len).toInt(); + pullup = data.substring(_b+1, _c).toInt(); + uint8_t intmode = data.substring(_c+1, XdrvMailbox.data_len).toInt(); #ifdef USE_MCP230xx_OUTPUT if ((pin < mcp230xx_pincount) && (pinmode < 7) && (pullup < 2)) { #else // not USE_MCP230xx_OUTPUT @@ -386,18 +416,27 @@ bool MCP230xx_Command(void) { #endif // USE_MCP230xx_OUTPUT Settings.mcp230xx_config[pin].pinmode=pinmode; Settings.mcp230xx_config[pin].pullup=pullup; + if (pinmode > 1 && pinmode < 5) { + if (intmode >= 0 && intmode <= 2) { + Settings.mcp230xx_config[pin].int_report_mode=intmode; + } + } else { + Settings.mcp230xx_config[pin].int_report_mode=3; // Int mode not valid for pinmodes other than 2 through 4 + } MCP230xx_ApplySettings(); uint8_t port = 0; if (pin > 7) port = 1; uint8_t portdata = MCP230xx_readGPIO(port); - char pulluptxtc[4], pinstatustxtc[4]; + char pulluptxtc[7], pinstatustxtc[7]; + char intmodetxt[9]; sprintf(pulluptxtc,ConvertNumTxt(pullup)); + sprintf(intmodetxt,IntModeTxt(Settings.mcp230xx_config[pin].int_report_mode)); #ifdef USE_MCP230xx_OUTPUT sprintf(pinstatustxtc,ConvertNumTxt(portdata>>(pin-(port*8))&1,Settings.mcp230xx_config[pin].pinmode)); #else // not USE_MCP230xx_OUTPUT sprintf(pinstatustxtc,ConvertNumTxt(portdata>>(pin-(port*8))&1)); #endif // USE_MCP230xx_OUTPUT - snprintf_P(mqtt_data, sizeof(mqtt_data), MCP230XX_SENSOR_RESPONSE,pin,pinmode,pulluptxtc,pinstatustxtc); + snprintf_P(mqtt_data, sizeof(mqtt_data), MCP230XX_SENSOR_RESPONSE,pin,pinmode,pulluptxtc,intmodetxt,pinstatustxtc); } else { serviced = false; } @@ -423,7 +462,7 @@ void MCP230xx_UpdateWebData(void) { uint16_t gpio = (gpio2 << 8) + gpio1; for (uint8_t pin = 0; pin < mcp230xx_pincount; pin++) { if (Settings.mcp230xx_config[pin].pinmode >= 5) { - char stt[4]; + char stt[7]; sprintf(stt,ConvertNumTxt((gpio>>pin)&1,Settings.mcp230xx_config[pin].pinmode)); snprintf_P(mqtt_data, sizeof(mqtt_data), HTTP_SNS_MCP230xx_OUTPUT, mqtt_data, pin, stt); } @@ -447,7 +486,7 @@ void MCP230xx_OutputTelemetry(void) { if (Settings.mcp230xx_config[pinx].pinmode >= 5) outputcount++; } if (outputcount) { - char stt[4]; + char stt[7]; snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("{\"" D_JSON_TIME "\":\"%s\",\"MCP230_OUT\": {"), GetDateAndTime(DT_LOCAL).c_str()); for (uint8_t pinx = 0;pinx < mcp230xx_pincount;pinx++) { if (Settings.mcp230xx_config[pinx].pinmode >= 5) { From e3f2deaccee1d0f96f0d679f694dd73cae265f57 Mon Sep 17 00:00:00 2001 From: andrethomas Date: Fri, 17 Aug 2018 00:23:20 +0200 Subject: [PATCH 14/15] Allow intmode=3 (Disabled) --- sonoff/xsns_29_mcp230xx.ino | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sonoff/xsns_29_mcp230xx.ino b/sonoff/xsns_29_mcp230xx.ino index 3e1ce5269..3ab47559d 100644 --- a/sonoff/xsns_29_mcp230xx.ino +++ b/sonoff/xsns_29_mcp230xx.ino @@ -417,7 +417,7 @@ bool MCP230xx_Command(void) { Settings.mcp230xx_config[pin].pinmode=pinmode; Settings.mcp230xx_config[pin].pullup=pullup; if (pinmode > 1 && pinmode < 5) { - if (intmode >= 0 && intmode <= 2) { + if (intmode >= 0 && intmode <= 3) { Settings.mcp230xx_config[pin].int_report_mode=intmode; } } else { From 93bd6b135c2a52971a74219489024a91e4e95354 Mon Sep 17 00:00:00 2001 From: andrethomas Date: Fri, 17 Aug 2018 23:19:14 +0200 Subject: [PATCH 15/15] Update xsns_29_mcp230xx.ino --- sonoff/xsns_29_mcp230xx.ino | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sonoff/xsns_29_mcp230xx.ino b/sonoff/xsns_29_mcp230xx.ino index 3ab47559d..0e4a74e97 100644 --- a/sonoff/xsns_29_mcp230xx.ino +++ b/sonoff/xsns_29_mcp230xx.ino @@ -58,7 +58,7 @@ uint8_t mcp230xx_addresses[] = { MCP230xx_ADDRESS1, MCP230xx_ADDRESS2, MCP230xx_ uint8_t mcp230xx_pincount = 0; uint8_t mcp230xx_int_en = 0; -const char MCP230XX_SENSOR_RESPONSE[] PROGMEM = "{\"Sensor29_D%i\":{\"MODE\":%i,\"PULL-UP\":\"%s\",\"INT_MODE\":\"%s\",\"STATE\":\"%s\"}}"; +const char MCP230XX_SENSOR_RESPONSE[] PROGMEM = "{\"Sensor29_D%i\":{\"MODE\":%i,\"PULL_UP\":\"%s\",\"INT_MODE\":\"%s\",\"STATE\":\"%s\"}}"; #ifdef USE_MCP230xx_OUTPUT const char MCP230XX_CMND_RESPONSE[] PROGMEM = "{\"S29cmnd_D%i\":{\"COMMAND\":\"%s\",\"STATE\":\"%s\"}}";