mirror of https://github.com/arendst/Tasmota.git
Merge pull request #4547 from andrethomas/mcp230xx
MCP230xx - Add Interrupt Retain
This commit is contained in:
commit
cd65888ce7
|
@ -1,6 +1,7 @@
|
||||||
/* 6.3.0.16 20181201
|
/* 6.3.0.16 20181201
|
||||||
* Add support for iFan02 Fanspeed in Domoticz using a selector (#4517)
|
* Add support for iFan02 Fanspeed in Domoticz using a selector (#4517)
|
||||||
* Add Announce Switches to MQTT Discovery (#4531)
|
* Add Announce Switches to MQTT Discovery (#4531)
|
||||||
|
* Update MCP230xx driver to support interrupt retention over teleperiod (#4547)
|
||||||
*
|
*
|
||||||
* 6.3.0.15 20181201
|
* 6.3.0.15 20181201
|
||||||
* Removed command SetOption36 (#4497)
|
* Removed command SetOption36 (#4497)
|
||||||
|
|
|
@ -156,7 +156,7 @@ typedef union {
|
||||||
uint16_t int_report_mode : 2; // Interrupt reporting mode 0 = immediate telemetry & event, 1 = immediate event only, 2 = immediate telemetry only
|
uint16_t int_report_mode : 2; // Interrupt reporting mode 0 = immediate telemetry & event, 1 = immediate event only, 2 = immediate telemetry only
|
||||||
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 spare12 : 1;
|
uint16_t int_retain_flag : 1; // Report if interrupt occured for pin in next teleperiod
|
||||||
uint16_t spare13 : 1;
|
uint16_t spare13 : 1;
|
||||||
uint16_t spare14 : 1;
|
uint16_t spare14 : 1;
|
||||||
uint16_t spare15 : 1;
|
uint16_t spare15 : 1;
|
||||||
|
|
|
@ -47,12 +47,15 @@ uint8_t mcp230xx_pincount = 0;
|
||||||
uint8_t mcp230xx_int_en = 0;
|
uint8_t mcp230xx_int_en = 0;
|
||||||
uint8_t mcp230xx_int_prio_counter = 0;
|
uint8_t mcp230xx_int_prio_counter = 0;
|
||||||
uint8_t mcp230xx_int_counter_en = 0;
|
uint8_t mcp230xx_int_counter_en = 0;
|
||||||
|
uint8_t mcp230xx_int_retainer_en = 0;
|
||||||
uint8_t mcp230xx_int_sec_counter = 0;
|
uint8_t mcp230xx_int_sec_counter = 0;
|
||||||
|
|
||||||
uint8_t mcp230xx_int_report_defer_counter[16] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
|
uint8_t mcp230xx_int_report_defer_counter[16] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
|
||||||
|
|
||||||
uint16_t mcp230xx_int_counter[16] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
|
uint16_t mcp230xx_int_counter[16] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
|
||||||
|
|
||||||
|
uint8_t mcp230xx_int_retainer[16] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}; // Used to store if an interrupt occured that needs to be retained until teleperiod
|
||||||
|
|
||||||
unsigned long int_millis[16]; // To keep track of millis() since last interrupt
|
unsigned long int_millis[16]; // To keep track of millis() since last interrupt
|
||||||
|
|
||||||
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\"}}";
|
||||||
|
@ -79,6 +82,20 @@ void MCP230xx_CheckForIntCounter(void) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void MCP230xx_CheckForIntRetainer(void) {
|
||||||
|
uint8_t en = 0;
|
||||||
|
for (uint8_t ca=0;ca<16;ca++) {
|
||||||
|
if (Settings.mcp230xx_config[ca].int_retain_flag) {
|
||||||
|
en=1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
mcp230xx_int_retainer_en=en;
|
||||||
|
if (!mcp230xx_int_retainer_en) { // Interrupt counters are disabled, so we clear all the counters
|
||||||
|
for (uint8_t ca=0;ca<16;ca++) {
|
||||||
|
mcp230xx_int_retainer[ca] = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
const char* ConvertNumTxt(uint8_t statu, uint8_t pinmod=0) {
|
const char* ConvertNumTxt(uint8_t statu, uint8_t pinmod=0) {
|
||||||
#ifdef USE_MCP230xx_OUTPUT
|
#ifdef USE_MCP230xx_OUTPUT
|
||||||
|
@ -177,7 +194,8 @@ void MCP230xx_ApplySettings(void) {
|
||||||
int_millis[idx]=millis();
|
int_millis[idx]=millis();
|
||||||
}
|
}
|
||||||
mcp230xx_int_en = int_en;
|
mcp230xx_int_en = int_en;
|
||||||
MCP230xx_CheckForIntCounter(); // update register on whether or not we should be counting interrupts
|
MCP230xx_CheckForIntCounter(); // update register on whether or not we should be counting interrupts
|
||||||
|
MCP230xx_CheckForIntRetainer(); // update register on whether or not we should be retaining interrupt events for teleperiod
|
||||||
}
|
}
|
||||||
|
|
||||||
void MCP230xx_Detect(void)
|
void MCP230xx_Detect(void)
|
||||||
|
@ -258,6 +276,13 @@ void MCP230xx_CheckForInterrupt(void) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
// check if interrupt retain is used, if it is for this pin then we do not report immediately as it will be reported in teleperiod
|
||||||
|
if (report_int) {
|
||||||
|
if (Settings.mcp230xx_config[intp+(mcp230xx_port*8)].int_retain_flag) {
|
||||||
|
mcp230xx_int_retainer[intp+(mcp230xx_port*8)] = 1;
|
||||||
|
report_int = 0; // do not report for now
|
||||||
|
}
|
||||||
|
}
|
||||||
if (Settings.mcp230xx_config[intp+(mcp230xx_port*8)].int_count_en) { // We do not want to report via tele or event if counting is enabled
|
if (Settings.mcp230xx_config[intp+(mcp230xx_port*8)].int_count_en) { // We do not want to report via tele or event if counting is enabled
|
||||||
report_int = 0;
|
report_int = 0;
|
||||||
}
|
}
|
||||||
|
@ -382,8 +407,8 @@ void MCP230xx_Reset(uint8_t pinmode) {
|
||||||
Settings.mcp230xx_config[pinx].int_report_mode=3; // Disabled for pinmode 1, 5 and 6 (No interrupts there)
|
Settings.mcp230xx_config[pinx].int_report_mode=3; // Disabled for pinmode 1, 5 and 6 (No interrupts there)
|
||||||
}
|
}
|
||||||
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
|
Settings.mcp230xx_config[pinx].int_count_en=0; // Disabled by default
|
||||||
Settings.mcp230xx_config[pinx].spare12=0;
|
Settings.mcp230xx_config[pinx].int_retain_flag=0; // Disabled by default
|
||||||
Settings.mcp230xx_config[pinx].spare13=0;
|
Settings.mcp230xx_config[pinx].spare13=0;
|
||||||
Settings.mcp230xx_config[pinx].spare14=0;
|
Settings.mcp230xx_config[pinx].spare14=0;
|
||||||
Settings.mcp230xx_config[pinx].spare15=0;
|
Settings.mcp230xx_config[pinx].spare15=0;
|
||||||
|
@ -544,6 +569,41 @@ bool MCP230xx_Command(void) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!strcmp(subStr(sub_string, XdrvMailbox.data, ",", 1),"INTRETAIN")) {
|
||||||
|
if (paramcount > 1) {
|
||||||
|
uint8_t pin = atoi(subStr(sub_string, XdrvMailbox.data, ",", 2));
|
||||||
|
if (pin < mcp230xx_pincount) {
|
||||||
|
if (pin == 0) {
|
||||||
|
if (!strcmp(subStr(sub_string, XdrvMailbox.data, ",", 2), "0")) validpin=true;
|
||||||
|
} else {
|
||||||
|
validpin = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (validpin) {
|
||||||
|
if (paramcount > 2) {
|
||||||
|
uint8_t int_retain = atoi(subStr(sub_string, XdrvMailbox.data, ",", 3));
|
||||||
|
if ((int_retain >= 0) && (int_retain <= 1)) {
|
||||||
|
Settings.mcp230xx_config[pin].int_retain_flag=int_retain;
|
||||||
|
snprintf_P(mqtt_data, sizeof(mqtt_data), MCP230XX_INTCFG_RESPONSE,"INT_RETAIN",pin,Settings.mcp230xx_config[pin].int_retain_flag);
|
||||||
|
MCP230xx_CheckForIntRetainer();
|
||||||
|
return serviced;
|
||||||
|
} else {
|
||||||
|
serviced=false;
|
||||||
|
return serviced;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
snprintf_P(mqtt_data, sizeof(mqtt_data), MCP230XX_INTCFG_RESPONSE,"INT_RETAIN",pin,Settings.mcp230xx_config[pin].int_retain_flag);
|
||||||
|
return serviced;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
serviced = false;
|
||||||
|
return serviced;
|
||||||
|
} else {
|
||||||
|
serviced = false;
|
||||||
|
return serviced;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
uint8_t pin = atoi(subStr(sub_string, XdrvMailbox.data, ",", 1));
|
uint8_t pin = atoi(subStr(sub_string, XdrvMailbox.data, ",", 1));
|
||||||
|
|
||||||
if (pin < mcp230xx_pincount) {
|
if (pin < mcp230xx_pincount) {
|
||||||
|
@ -703,6 +763,19 @@ void MCP230xx_Interrupt_Counter_Report(void) {
|
||||||
mcp230xx_int_sec_counter = 0;
|
mcp230xx_int_sec_counter = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void MCP230xx_Interrupt_Retain_Report(void) {
|
||||||
|
uint16_t retainresult = 0;
|
||||||
|
snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("{\"" D_JSON_TIME "\":\"%s\",\"MCP_INTRETAIN\": {"), GetDateAndTime(DT_LOCAL).c_str());
|
||||||
|
for (uint8_t pinx = 0;pinx < mcp230xx_pincount;pinx++) {
|
||||||
|
if (Settings.mcp230xx_config[pinx].int_retain_flag) {
|
||||||
|
snprintf_P(mqtt_data,sizeof(mqtt_data), PSTR("%s\"D%i\":%i,"),mqtt_data,pinx,mcp230xx_int_retainer[pinx]);
|
||||||
|
retainresult |= (((mcp230xx_int_retainer[pinx])&1) << pinx);
|
||||||
|
mcp230xx_int_retainer[pinx]=0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
snprintf_P(mqtt_data,sizeof(mqtt_data),PSTR("%s\"Value\":%u}}"),mqtt_data,retainresult);
|
||||||
|
MqttPublishPrefixTopic_P(TELE, PSTR(D_RSLT_SENSOR), Settings.flag.mqtt_sensor_retain);
|
||||||
|
}
|
||||||
|
|
||||||
/*********************************************************************************************\
|
/*********************************************************************************************\
|
||||||
Interface
|
Interface
|
||||||
|
@ -724,6 +797,11 @@ boolean Xsns29(byte function)
|
||||||
MCP230xx_Interrupt_Counter_Report();
|
MCP230xx_Interrupt_Counter_Report();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if (tele_period == 0) {
|
||||||
|
if (mcp230xx_int_retainer_en) { // We have pins configured for interrupt retain reporting
|
||||||
|
MCP230xx_Interrupt_Retain_Report();
|
||||||
|
}
|
||||||
|
}
|
||||||
#ifdef USE_MCP230xx_OUTPUT
|
#ifdef USE_MCP230xx_OUTPUT
|
||||||
if (tele_period == 0) {
|
if (tele_period == 0) {
|
||||||
MCP230xx_OutputTelemetry();
|
MCP230xx_OutputTelemetry();
|
||||||
|
|
Loading…
Reference in New Issue