diff --git a/tasmota/my_user_config.h b/tasmota/my_user_config.h index 7d6a3c18e..ffef8ccbe 100644 --- a/tasmota/my_user_config.h +++ b/tasmota/my_user_config.h @@ -978,6 +978,11 @@ //#define USE_HX711 // Add support for HX711 load cell (+1k5 code) // #define USE_HX711_GUI // Add optional web GUI to HX711 as scale (+1k8 code) +//#define USE_DINGTIAN_RELAY // Add support for the Dingian board using 74'595 et 74'165 shift registers +// #define DINGTIAN_INPUTS_INVERTED // Invert input states (Hi => OFF, Low => ON) +// #define DINGTIAN_USE_AS_BUTTON // Inputs as Tasmota's virtual Buttons +// #define DINGTIAN_USE_AS_SWITCH // Inputs as Tasmota's virtual Switches + // Select none or only one of the below defines //#define USE_TX20_WIND_SENSOR // Add support for La Crosse TX20 anemometer (+2k6/0k8 code) //#define USE_TX23_WIND_SENSOR // Add support for La Crosse TX23 anemometer (+2k7/1k code) diff --git a/tasmota/tasmota_xdrv_driver/xdrv_90_esp32_dingtian_relay.ino b/tasmota/tasmota_xdrv_driver/xdrv_90_esp32_dingtian_relay.ino index 6e4e9005f..93bfd2a34 100644 --- a/tasmota/tasmota_xdrv_driver/xdrv_90_esp32_dingtian_relay.ino +++ b/tasmota/tasmota_xdrv_driver/xdrv_90_esp32_dingtian_relay.ino @@ -22,6 +22,14 @@ #define XDRV_90 90 +/******************************************************************************************************** + * Check defines + */ + +#if defined(DINGTIAN_USE_AS_BUTTON) && defined(DINGTIAN_USE_AS_SWITCH) +#error DINGTIAN - Only one of DINGTIAN_USE_AS_BUTTON or DINGTIAN_USE_AS_SWITCH should be defined +#endif + /******************************************************************************************************** * Global private data */ @@ -31,6 +39,7 @@ struct DINGTIAN_DATA { uint32_t last_inputs; // previous inputs state uint8_t count; // number of relay and input (8 * numver of shift registers) uint8_t first; // index of 1st Tasmota relay assigned to 1st Dingtian relays + int8_t key_offset; // index of virtual key // pins uint8_t pin_clk, pin_sdi, pin_q7, pin_pl, pin_rck; } *Dingtian = nullptr; @@ -63,7 +72,11 @@ uint32_t DingtianReadWrite(uint32_t outputs) digitalWrite(Dingtian->pin_rck, 1); // rclk pulse to load '595 into output registers digitalWrite(Dingtian->pin_pl, 0); // re-enable '595 ouputs +#ifdef DINGTIAN_INPUTS_INVERTED + return ~inputs; +#else return inputs; +#endif } /******************************************************************************************************** @@ -98,16 +111,51 @@ void DingtianInit(void) { DINGTIAN_SET_OUTPUT(Dingtian->pin_rck, 0); Dingtian->first = TasmotaGlobal.devices_present; + Dingtian->key_offset = -1; UpdateDevicesPresent(Dingtian->count); AddLog(LOG_LEVEL_DEBUG, PSTR("DNGT: Dingtian relays: POWER%d to POWER%d"), Dingtian->first + 1, TasmotaGlobal.devices_present); } } } +#if defined(DINGTIAN_USE_AS_BUTTON) || defined(DINGTIAN_USE_AS_SWITCH) +bool DingtianAddKey(void) { + if (Dingtian->key_offset < 0) { + Dingtian->key_offset = XdrvMailbox.index; + #ifdef DINGTIAN_USE_AS_BUTTON + AddLog(LOG_LEVEL_DEBUG, PSTR("DNGT: Dingtian inputs: Button%d to Button%d"), Dingtian->key_offset + 1, Dingtian->key_offset + Dingtian->count); + #else + AddLog(LOG_LEVEL_DEBUG, PSTR("DNGT: Dingtian inputs: Switch%d to Switch%d"), Dingtian->key_offset + 1, Dingtian->key_offset + Dingtian->count); + #endif + } + uint32_t index = XdrvMailbox.index - Dingtian->key_offset; + if (index >= Dingtian->count) { + return false; + } + XdrvMailbox.index = 0; // Default is 0 - Button will also set invert + return true; +} +#endif + /******************************************************************************************************** * Driver operations */ +#if defined(DINGTIAN_USE_AS_BUTTON) || defined(DINGTIAN_USE_AS_SWITCH) +void DingtianLoop() +{ + uint32_t inputs = DingtianReadWrite(Dingtian->outputs); + Dingtian->last_inputs = inputs; + + for (int i = 0 ; i < Dingtian->count ; i++, inputs>>=1) { +#ifdef DINGTIAN_USE_AS_BUTTON + ButtonSetVirtualPinState(Dingtian->key_offset +i, inputs &1); +#else + SwitchSetVirtualPinState(Dingtian->key_offset +i, inputs &1); +#endif + } +} +#else void DingtianLoop() { uint32_t inputs = DingtianReadWrite(Dingtian->outputs); @@ -131,6 +179,7 @@ void DingtianLoop() } } } +#endif void DingtianSetPower(void) { @@ -146,30 +195,32 @@ void DingtianSetPower(void) const char HTTP_DINGTIAN_INPUTS[] PROGMEM = "{s}DINGTIAN " D_SENSOR_INPUT "%d.." D_SENSOR_INPUT "%d{m}%s{e}"; -void DingtianShow(bool json) +#if !defined(DINGTIAN_USE_AS_BUTTON) && !defined(DINGTIAN_USE_AS_SWITCH) +void DingtianJsonAppend(void) { - if (json) { - bool first_done = false; - ResponseAppend_P(PSTR(",\"DINGTIAN\":{")); - for (int i = 0 ; i < Dingtian->count ; i++) { - if (first_done) ResponseAppend_P(PSTR(",")); - ResponseAppend_P(PSTR("\"IN%d\":%d"), i +1, bitRead(Dingtian->last_inputs, i)); - first_done = true; - } - ResponseAppend_P(PSTR("}")); + bool first_done = false; + ResponseAppend_P(PSTR(",\"DINGTIAN\":{")); + for (int i = 0 ; i < Dingtian->count ; i++) { + if (first_done) ResponseAppend_P(PSTR(",")); + ResponseAppend_P(PSTR("\"IN%d\":%d"), i +1, bitRead(Dingtian->last_inputs, i)); + first_done = true; } -#ifdef USE_WEBSERVER - else { - char input_str[9]; - for (int block_input = 0 ; block_input < Dingtian->count ; block_input += 8 ) { - for (int i = 0 ; i < 8 ; i++ ) - input_str[i] = '0' + bitRead(Dingtian->last_inputs, block_input +i); - input_str[8] = '\0'; - WSContentSend_P(HTTP_DINGTIAN_INPUTS, block_input, block_input +7, input_str); - } - } -#endif + ResponseAppend_P(PSTR("}")); } +#endif + +#ifdef USE_WEBSERVER +void DingtianWebSensor(void) +{ + char input_str[9]; + for (int block_input = 0 ; block_input < Dingtian->count ; block_input += 8 ) { + for (int i = 0 ; i < 8 ; i++ ) + input_str[i] = '0' + bitRead(Dingtian->last_inputs, block_input +i); + input_str[8] = '\0'; + WSContentSend_P(HTTP_DINGTIAN_INPUTS, block_input, block_input +7, input_str); + } +} +#endif /*********************************************************************************************\ @@ -179,7 +230,7 @@ void DingtianShow(bool json) bool Xdrv90(uint32_t function) { bool result = false; - if (FUNC_PRE_INIT == function) { + if (FUNC_SETUP_RING2 == function) { DingtianInit(); } else if (Dingtian) { switch (function) { @@ -190,14 +241,26 @@ bool Xdrv90(uint32_t function) { //case FUNC_EVERY_250_MSECOND: DingtianLoop(); break; +#if !defined(DINGTIAN_USE_AS_BUTTON) && !defined(DINGTIAN_USE_AS_SWITCH) case FUNC_JSON_APPEND: - DingtianShow(1); + DingtianJsonAppend(); break; +#endif #ifdef USE_WEBSERVER case FUNC_WEB_SENSOR: - DingtianShow(0); + DingtianWebSensor(); break; #endif // USE_WEBSERVER +#ifdef DINGTIAN_USE_AS_BUTTON + case FUNC_ADD_BUTTON: + result = DingtianAddKey(); + break; +#endif +#ifdef DINGTIAN_USE_AS_SWITCH + case FUNC_ADD_SWITCH: + result = DingtianAddKey(); + break; +#endif } } return result;