Merge pull request #11394 from theOzzieRat/mcp230xx_output_mode_2

Mcp230xx output mode 2
This commit is contained in:
Theo Arends 2021-03-20 11:58:07 +01:00 committed by GitHub
commit b1b64a32b8
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 96 additions and 29 deletions

View File

@ -553,9 +553,9 @@
#define USE_APDS9960_PROXIMITY // Enable APDS9960 Proximity feature (>50 code) #define USE_APDS9960_PROXIMITY // Enable APDS9960 Proximity feature (>50 code)
#define USE_APDS9960_COLOR // Enable APDS9960 Color feature (+0.8k code) #define USE_APDS9960_COLOR // Enable APDS9960 Color feature (+0.8k code)
#define USE_APDS9960_STARTMODE 0 // Default to enable Gesture mode #define USE_APDS9960_STARTMODE 0 // Default to enable Gesture mode
// #define USE_MCP230xx // [I2cDriver22] Enable MCP23008/MCP23017 - Must define I2C Address in #define USE_MCP230xx_ADDR below - range 0x20 - 0x27 (+4k7 code) // #define USE_MCP230xx // [I2cDriver22] Enable MCP23008/MCP23017 - Must define I2C Address in #define USE_MCP230xx_ADDR below - range 0x20 - 0x27 (+5k1 code)
// #define USE_MCP230xx_ADDR 0x20 // Enable MCP23008/MCP23017 I2C Address to use (Must be within range 0x20 through 0x26 - set according to your wired setup) // #define USE_MCP230xx_ADDR 0x20 // Enable MCP23008/MCP23017 I2C Address to use (Must be within range 0x20 through 0x26 - set according to your wired setup)
// #define USE_MCP230xx_OUTPUT // Enable MCP23008/MCP23017 OUTPUT support through sensor29 commands (+1k5 code) // #define USE_MCP230xx_OUTPUT // Enable MCP23008/MCP23017 OUTPUT support through sensor29 commands (+2k2 code)
// #define USE_MCP230xx_DISPLAYOUTPUT // Enable MCP23008/MCP23017 to display state of OUTPUT pins on Web UI (+0k2 code) // #define USE_MCP230xx_DISPLAYOUTPUT // Enable MCP23008/MCP23017 to display state of OUTPUT pins on Web UI (+0k2 code)
// #define USE_PCA9685 // [I2cDriver1] Enable PCA9685 I2C HW PWM Driver - Must define I2C Address in #define USE_PCA9685_ADDR below - range 0x40 - 0x47 (+1k4 code) // #define USE_PCA9685 // [I2cDriver1] Enable PCA9685 I2C HW PWM Driver - Must define I2C Address in #define USE_PCA9685_ADDR below - range 0x40 - 0x47 (+1k4 code)
// #define USE_PCA9685_ADDR 0x40 // Enable PCA9685 I2C Address to use (Must be within range 0x40 through 0x47 - set according to your wired setup) // #define USE_PCA9685_ADDR 0x40 // Enable PCA9685 I2C Address to use (Must be within range 0x40 through 0x47 - set according to your wired setup)

View File

@ -259,7 +259,7 @@ typedef union {
uint16_t int_report_defer : 4; // Number of interrupts to ignore until reporting (default 0, max 15) uint16_t int_report_defer : 4; // Number of interrupts to ignore until reporting (default 0, max 15)
uint16_t int_count_en : 1; // Enable interrupt counter for this pin uint16_t int_count_en : 1; // Enable interrupt counter for this pin
uint16_t int_retain_flag : 1; // Report if interrupt occured for pin in next teleperiod uint16_t int_retain_flag : 1; // Report if interrupt occured for pin in next teleperiod
uint16_t spare13 : 1; uint16_t keep_output : 1; // For output modes, preserve the value currently in the MCP230xx
uint16_t spare14 : 1; uint16_t spare14 : 1;
uint16_t spare15 : 1; uint16_t spare15 : 1;
}; };

View File

@ -42,6 +42,9 @@ uint8_t MCP230xx_GPPU = 0x06;
uint8_t MCP230xx_INTF = 0x07; uint8_t MCP230xx_INTF = 0x07;
uint8_t MCP230xx_INTCAP = 0x08; uint8_t MCP230xx_INTCAP = 0x08;
uint8_t MCP230xx_GPIO = 0x09; uint8_t MCP230xx_GPIO = 0x09;
#ifdef USE_MCP230xx_OUTPUT
uint8_t MCP230xx_OLAT = 0x0A;
#endif // USE_MCP230xx_OUTPUT
uint8_t mcp230xx_type = 0; uint8_t mcp230xx_type = 0;
uint8_t mcp230xx_pincount = 0; uint8_t mcp230xx_pincount = 0;
@ -69,6 +72,7 @@ const char MCP230XX_INTCFG_RESPONSE[] PROGMEM = "{\"MCP230xx_INT%s\":{\"D_%i\":%
#ifdef USE_MCP230xx_OUTPUT #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\"}}";
const char MCP230XX_OUTPUT_RESPONSE[] PROGMEM = "{\"Sensor29_D%i\":{\"MODE\":%i,\"START_UP\":\"%s\",\"STATE\":\"%s\"}}";
#endif // USE_MCP230xx_OUTPUT #endif // USE_MCP230xx_OUTPUT
void MCP230xx_CheckForIntCounter(void) { void MCP230xx_CheckForIntCounter(void) {
@ -102,9 +106,17 @@ void MCP230xx_CheckForIntRetainer(void) {
} }
} }
const char* ConvertNumTxt(uint8_t statu, uint8_t pinmod=0) {
#ifdef USE_MCP230xx_OUTPUT #ifdef USE_MCP230xx_OUTPUT
if ((6 == pinmod) && (statu < 2)) { statu = abs(statu-1); } const char* ConvertNumTxt(uint8_t statu, uint8_t pinmod=0, uint8_t config=0) {
#else // not USE_MCP230xx_OUTPUT
const char* ConvertNumTxt(uint8_t statu, uint8_t pinmod=0) {
#endif // USE_MCP230xx_OUTPUT
#ifdef USE_MCP230xx_OUTPUT
if ((6 == pinmod) && (statu < 2)) { statu = 1-statu; }
AddLog(LOG_LEVEL_DEBUG, PSTR("MCP: ConvertNumTxt config=%d save_state=%d"),config, Settings.flag.save_state);
if ((config) && (Settings.flag.save_state)) {
return "SAVED";
}
#endif // USE_MCP230xx_OUTPUT #endif // USE_MCP230xx_OUTPUT
switch (statu) { switch (statu) {
case 0: case 0:
@ -115,7 +127,15 @@ if ((6 == pinmod) && (statu < 2)) { statu = abs(statu-1); }
break; break;
#ifdef USE_MCP230xx_OUTPUT #ifdef USE_MCP230xx_OUTPUT
case 2: case 2:
return "TOGGLE"; #ifdef USE_MCP230xx_OUTPUT
if (config) {
return "DEVICE";
} else {
#endif // USE_MCP230xx_OUTPUT
return "TOGGLE";
#ifdef USE_MCP230xx_OUTPUT
}
#endif // USE_MCP230xx_OUTPUT
break; break;
#endif // USE_MCP230xx_OUTPUT #endif // USE_MCP230xx_OUTPUT
} }
@ -166,6 +186,7 @@ void MCP230xx_ApplySettings(void)
uint8_t reg_iodir = 0xFF; uint8_t reg_iodir = 0xFF;
#ifdef USE_MCP230xx_OUTPUT #ifdef USE_MCP230xx_OUTPUT
reg_portpins[mcp230xx_port] = 0x00; reg_portpins[mcp230xx_port] = 0x00;
uint8_t reg_readpins = I2cRead8(USE_MCP230xx_ADDR, MCP230xx_OLAT + mcp230xx_port);
#endif // USE_MCP230xx_OUTPUT #endif // USE_MCP230xx_OUTPUT
for (uint32_t idx = 0; idx < 8; idx++) { for (uint32_t idx = 0; idx < 8; idx++) {
switch (Settings.mcp230xx_config[idx+(mcp230xx_port*8)].pinmode) { switch (Settings.mcp230xx_config[idx+(mcp230xx_port*8)].pinmode) {
@ -183,7 +204,11 @@ void MCP230xx_ApplySettings(void)
if (Settings.flag.save_state) { // SetOption0 - Save power state and use after restart - Firmware configuration wants us to use the last pin state if (Settings.flag.save_state) { // SetOption0 - Save power state and use after restart - Firmware configuration wants us to use the last pin state
reg_portpins[mcp230xx_port] |= (Settings.mcp230xx_config[idx+(mcp230xx_port*8)].saved_state << idx); reg_portpins[mcp230xx_port] |= (Settings.mcp230xx_config[idx+(mcp230xx_port*8)].saved_state << idx);
} else { } else {
if (Settings.mcp230xx_config[idx+(mcp230xx_port*8)].pullup) { if (Settings.mcp230xx_config[idx+(mcp230xx_port*8)].keep_output) { // Read the value to use from the MCP230xx
AddLog(LOG_LEVEL_DEBUG, PSTR("MCP: readpins=%d or_val=%d"),reg_readpins, reg_readpins & (1 << idx));
reg_portpins[mcp230xx_port] |= reg_readpins & (1 << idx);
}
else if (Settings.mcp230xx_config[idx+(mcp230xx_port*8)].pullup) {
reg_portpins[mcp230xx_port] |= (1 << idx); reg_portpins[mcp230xx_port] |= (1 << idx);
} }
} }
@ -249,6 +274,9 @@ void MCP230xx_Detect(void)
MCP230xx_INTF = 0x0E; MCP230xx_INTF = 0x0E;
MCP230xx_INTCAP = 0x10; MCP230xx_INTCAP = 0x10;
MCP230xx_GPIO = 0x12; MCP230xx_GPIO = 0x12;
#ifdef USE_MCP230xx_OUTPUT
MCP230xx_OLAT = 0x14;
#endif // USE_MCP230xx_OUTPUT
MCP230xx_ApplySettings(); MCP230xx_ApplySettings();
} }
} }
@ -436,20 +464,30 @@ void MCP230xx_Reset(uint8_t pinmode) {
Settings.mcp230xx_config[pinx].int_report_defer=0; // Disabled Settings.mcp230xx_config[pinx].int_report_defer=0; // Disabled
Settings.mcp230xx_config[pinx].int_count_en=0; // Disabled by default Settings.mcp230xx_config[pinx].int_count_en=0; // Disabled by default
Settings.mcp230xx_config[pinx].int_retain_flag=0; // Disabled by default Settings.mcp230xx_config[pinx].int_retain_flag=0; // Disabled by default
Settings.mcp230xx_config[pinx].spare13=0; Settings.mcp230xx_config[pinx].keep_output=0; // Disabled by default
Settings.mcp230xx_config[pinx].spare14=0; Settings.mcp230xx_config[pinx].spare14=0;
Settings.mcp230xx_config[pinx].spare15=0; Settings.mcp230xx_config[pinx].spare15=0;
} }
Settings.mcp230xx_int_prio = 0; // Once per FUNC_EVERY_50_MSECOND callback Settings.mcp230xx_int_prio = 0; // Once per FUNC_EVERY_50_MSECOND callback
Settings.mcp230xx_int_timer = 0; Settings.mcp230xx_int_timer = 0;
MCP230xx_ApplySettings(); MCP230xx_ApplySettings();
char pulluptxt[7]; #ifdef USE_MCP230xx_OUTPUT
char intmodetxt[9]; if (pinmode > 4) {
sprintf(pulluptxt,ConvertNumTxt(pullup)); char startuptxt[7];
uint8_t intmode = 3; sprintf(startuptxt,ConvertNumTxt(pullup, 0, 1));
if ((pinmode > 1) && (pinmode < 5)) { intmode = 0; } Response_P(MCP230XX_OUTPUT_RESPONSE,99,pinmode,startuptxt,startuptxt);
sprintf(intmodetxt,IntModeTxt(intmode)); } else {
Response_P(MCP230XX_SENSOR_RESPONSE,99,pinmode,pulluptxt,intmodetxt,""); #endif // USE_MCP230xx_OUTPUT
char pulluptxt[7];
char intmodetxt[9];
sprintf(pulluptxt,ConvertNumTxt(pullup));
uint8_t intmode = 3;
if ((pinmode > 1) && (pinmode < 5)) { intmode = 0; }
sprintf(intmodetxt,IntModeTxt(intmode));
Response_P(MCP230XX_SENSOR_RESPONSE,99,pinmode,pulluptxt,intmodetxt,"");
#ifdef USE_MCP230xx_OUTPUT
}
#endif // USE_MCP230xx_OUTPUT
} }
bool MCP230xx_Command(void) bool MCP230xx_Command(void)
@ -643,21 +681,26 @@ bool MCP230xx_Command(void)
if (pin > 7) { port = 1; } if (pin > 7) { port = 1; }
uint8_t portdata = MCP230xx_readGPIO(port); uint8_t portdata = MCP230xx_readGPIO(port);
char pulluptxtr[7],pinstatustxtr[7]; 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; uint8_t pinmod = Settings.mcp230xx_config[pin].pinmode;
sprintf(pinstatustxtr,ConvertNumTxt(portdata>>(pin-(port*8))&1,pinmod)); #ifdef USE_MCP230xx_OUTPUT
Response_P(MCP230XX_SENSOR_RESPONSE,pin,pinmod,pulluptxtr,intmodetxt,pinstatustxtr); if (pinmod > 4) {
#else // not USE_MCP230xx_OUTPUT sprintf(pulluptxtr,ConvertNumTxt(Settings.mcp230xx_config[pin].pullup | (Settings.mcp230xx_config[pin].keep_output << 1), 0, 1));
sprintf(pinstatustxtr,ConvertNumTxt(portdata>>(pin-(port*8))&1)); sprintf(pinstatustxtr,ConvertNumTxt(portdata>>(pin-(port*8))&1,pinmod));
Response_P(MCP230XX_SENSOR_RESPONSE,pin,Settings.mcp230xx_config[pin].pinmode,pulluptxtr,intmodetxt,pinstatustxtr); Response_P(MCP230XX_OUTPUT_RESPONSE,pin,pinmod,pulluptxtr,pinstatustxtr);
} else {
#endif //USE_MCP230xx_OUTPUT
char intmodetxt[9];
sprintf(intmodetxt,IntModeTxt(Settings.mcp230xx_config[pin].int_report_mode));
sprintf(pulluptxtr,ConvertNumTxt(Settings.mcp230xx_config[pin].pullup | (Settings.mcp230xx_config[pin].keep_output << 1)));
sprintf(pinstatustxtr,ConvertNumTxt(portdata>>(pin-(port*8))&1));
Response_P(MCP230XX_SENSOR_RESPONSE,pin,pinmod,pulluptxtr,intmodetxt,pinstatustxtr);
#ifdef USE_MCP230xx_OUTPUT
}
#endif //USE_MCP230xx_OUTPUT #endif //USE_MCP230xx_OUTPUT
return serviced; return serviced;
} }
#ifdef USE_MCP230xx_OUTPUT #ifdef USE_MCP230xx_OUTPUT
if (Settings.mcp230xx_config[pin].pinmode >= 5 && paramcount == 2) { if (Settings.mcp230xx_config[pin].pinmode >= 5 && paramcount == 2) { // Changing output value
uint8_t pincmd = Settings.mcp230xx_config[pin].pinmode - 5; uint8_t pincmd = Settings.mcp230xx_config[pin].pinmode - 5;
uint8_t relay_no = 0; uint8_t relay_no = 0;
for (relay_no = 0; relay_no < mcp230xx_pincount ; relay_no ++) { for (relay_no = 0; relay_no < mcp230xx_pincount ; relay_no ++) {
@ -691,12 +734,13 @@ bool MCP230xx_Command(void)
intmode = atoi(ArgV(argument, 4)); intmode = atoi(ArgV(argument, 4));
} }
#ifdef USE_MCP230xx_OUTPUT #ifdef USE_MCP230xx_OUTPUT
if ((pin < mcp230xx_pincount) && (pinmode > 0) && (pinmode < 7) && (pullup < 2) && (paramcount > 2)) { if ((pin < mcp230xx_pincount) && (((pinmode > 0) && (pinmode < 5) && (pullup < 2)) || ((pinmode > 4) && (pinmode < 7) && (pullup < 3))) && (paramcount > 2)) {
#else // not use OUTPUT #else // not use OUTPUT
if ((pin < mcp230xx_pincount) && (pinmode > 0) && (pinmode < 5) && (pullup < 2) && (paramcount > 2)) { if ((pin < mcp230xx_pincount) && (pinmode > 0) && (pinmode < 5) && (pullup < 2) && (paramcount > 2)) {
#endif // USE_MCP230xx_OUTPUT #endif // USE_MCP230xx_OUTPUT
Settings.mcp230xx_config[pin].pinmode=pinmode; Settings.mcp230xx_config[pin].pinmode=pinmode;
Settings.mcp230xx_config[pin].pullup=pullup; Settings.mcp230xx_config[pin].pullup=pullup & 1;
Settings.mcp230xx_config[pin].keep_output=pullup >> 1;
if ((pinmode > 1) && (pinmode < 5)) { if ((pinmode > 1) && (pinmode < 5)) {
if ((intmode >= 0) && (intmode <= 3)) { if ((intmode >= 0) && (intmode <= 3)) {
Settings.mcp230xx_config[pin].int_report_mode=intmode; Settings.mcp230xx_config[pin].int_report_mode=intmode;
@ -708,7 +752,28 @@ bool MCP230xx_Command(void)
uint8_t port = 0; uint8_t port = 0;
if (pin > 7) { port = 1; } if (pin > 7) { port = 1; }
uint8_t portdata = MCP230xx_readGPIO(port); uint8_t portdata = MCP230xx_readGPIO(port);
char pulluptxtc[7], pinstatustxtc[7]; char pulluptxtr[7],pinstatustxtr[7];
uint8_t pinmod = Settings.mcp230xx_config[pin].pinmode;
#ifdef USE_MCP230xx_OUTPUT
if (pinmod > 4) {
sprintf(pulluptxtr,ConvertNumTxt(Settings.mcp230xx_config[pin].pullup | (Settings.mcp230xx_config[pin].keep_output << 1), 0, 1));
sprintf(pinstatustxtr,ConvertNumTxt(portdata>>(pin-(port*8))&1,pinmod));
Response_P(MCP230XX_OUTPUT_RESPONSE,pin,pinmod,pulluptxtr,pinstatustxtr);
} else {
#endif //USE_MCP230xx_OUTPUT
char intmodetxt[9];
sprintf(intmodetxt,IntModeTxt(Settings.mcp230xx_config[pin].int_report_mode));
sprintf(pulluptxtr,ConvertNumTxt(Settings.mcp230xx_config[pin].pullup | (Settings.mcp230xx_config[pin].keep_output << 1)));
sprintf(pinstatustxtr,ConvertNumTxt(portdata>>(pin-(port*8))&1));
Response_P(MCP230XX_SENSOR_RESPONSE,pin,pinmod,pulluptxtr,intmodetxt,pinstatustxtr);
#ifdef USE_MCP230xx_OUTPUT
}
#endif //USE_MCP230xx_OUTPUT
/* char pulluptxtc[7], pinstatustxtc[7];
char intmodetxt[9]; char intmodetxt[9];
sprintf(pulluptxtc,ConvertNumTxt(pullup)); sprintf(pulluptxtc,ConvertNumTxt(pullup));
sprintf(intmodetxt,IntModeTxt(Settings.mcp230xx_config[pin].int_report_mode)); sprintf(intmodetxt,IntModeTxt(Settings.mcp230xx_config[pin].int_report_mode));
@ -717,7 +782,7 @@ bool MCP230xx_Command(void)
#else // not USE_MCP230xx_OUTPUT #else // not USE_MCP230xx_OUTPUT
sprintf(pinstatustxtc,ConvertNumTxt(portdata>>(pin-(port*8))&1)); sprintf(pinstatustxtc,ConvertNumTxt(portdata>>(pin-(port*8))&1));
#endif // USE_MCP230xx_OUTPUT #endif // USE_MCP230xx_OUTPUT
Response_P(MCP230XX_SENSOR_RESPONSE,pin,pinmode,pulluptxtc,intmodetxt,pinstatustxtc); Response_P(MCP230XX_SENSOR_RESPONSE,pin,pinmode,pulluptxtc,intmodetxt,pinstatustxtc); */
return serviced; return serviced;
} }
} else { } else {
@ -727,6 +792,7 @@ bool MCP230xx_Command(void)
return serviced; return serviced;
} }
#ifdef USE_MCP230xx_OUTPUT
#ifdef USE_MCP230xx_DISPLAYOUTPUT #ifdef USE_MCP230xx_DISPLAYOUTPUT
const char HTTP_SNS_MCP230xx_OUTPUT[] PROGMEM = "{s}MCP230XX D%d{m}%s{e}"; // {s} = <tr><th>, {m} = </th><td>, {e} = </td></tr> const char HTTP_SNS_MCP230xx_OUTPUT[] PROGMEM = "{s}MCP230XX D%d{m}%s{e}"; // {s} = <tr><th>, {m} = </th><td>, {e} = </td></tr>
@ -749,6 +815,7 @@ void MCP230xx_UpdateWebData(void)
} }
#endif // USE_MCP230xx_DISPLAYOUTPUT #endif // USE_MCP230xx_DISPLAYOUTPUT
#endif // USE_MCP230xx_OUTPUT
/* /*
#ifdef USE_MCP230xx_OUTPUT #ifdef USE_MCP230xx_OUTPUT