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...
This commit is contained in:
MadDoct 2018-08-13 23:54:27 +01:00 committed by GitHub
parent 8a61c25218
commit 41b594ae53
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
1 changed files with 83 additions and 48 deletions

View File

@ -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);
}
@ -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);
@ -107,7 +130,7 @@ void MCP230xx_ApplySettings(void) {
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
@ -128,12 +151,12 @@ 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];
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,7 +256,7 @@ 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) {
@ -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) {
@ -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") {
@ -326,7 +351,7 @@ 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)) {
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
@ -336,7 +361,14 @@ 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,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} = <tr><th>, {m} = </th><td>, {e} = </td></tr>
const char HTTP_SNS_MCP230xx_OUTPUT[] PROGMEM = "%s{s}MCP230XX D%d{m}%s{e}"; // {s} = <tr><th>, {m} = </th><td>, {e} = </td></tr>
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);
@ -449,4 +485,3 @@ boolean Xsns29(byte function)
#endif // USE_MCP230xx
#endif // USE_I2C