Merge pull request #4547 from andrethomas/mcp230xx

MCP230xx - Add Interrupt Retain
This commit is contained in:
Theo Arends 2018-12-07 09:25:06 +01:00 committed by GitHub
commit cd65888ce7
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 83 additions and 4 deletions

View File

@ -1,6 +1,7 @@
/* 6.3.0.16 20181201
* Add support for iFan02 Fanspeed in Domoticz using a selector (#4517)
* Add Announce Switches to MQTT Discovery (#4531)
* Update MCP230xx driver to support interrupt retention over teleperiod (#4547)
*
* 6.3.0.15 20181201
* Removed command SetOption36 (#4497)

View File

@ -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_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 spare12 : 1;
uint16_t int_retain_flag : 1; // Report if interrupt occured for pin in next teleperiod
uint16_t spare13 : 1;
uint16_t spare14 : 1;
uint16_t spare15 : 1;

View File

@ -47,12 +47,15 @@ uint8_t mcp230xx_pincount = 0;
uint8_t mcp230xx_int_en = 0;
uint8_t mcp230xx_int_prio_counter = 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_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};
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
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) {
#ifdef USE_MCP230xx_OUTPUT
@ -178,6 +195,7 @@ void MCP230xx_ApplySettings(void) {
}
mcp230xx_int_en = int_en;
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)
@ -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
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_defer=0; // Disabled
Settings.mcp230xx_config[pinx].int_count_en=0; // Disabled
Settings.mcp230xx_config[pinx].spare12=0;
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].spare13=0;
Settings.mcp230xx_config[pinx].spare14=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));
if (pin < mcp230xx_pincount) {
@ -703,6 +763,19 @@ void MCP230xx_Interrupt_Counter_Report(void) {
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
@ -724,6 +797,11 @@ boolean Xsns29(byte function)
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
if (tele_period == 0) {
MCP230xx_OutputTelemetry();