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] 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 -