From 8c12424d78d747f208bdc9ee878898e91b37192f Mon Sep 17 00:00:00 2001 From: jziolkowski Date: Sat, 4 Dec 2021 15:39:00 +0100 Subject: [PATCH] WIP --- tasmota/i18n.h | 5 ++ tasmota/language/en_GB.h | 6 ++ tasmota/my_user_config.h | 2 + tasmota/settings.h | 5 +- tasmota/settings.ino | 3 + tasmota/tasmota_template.h | 14 ++++- tasmota/xdrv_60_shift595.ino | 114 +++++++++++++++++++++++++++++++++++ 7 files changed, 146 insertions(+), 3 deletions(-) create mode 100644 tasmota/xdrv_60_shift595.ino diff --git a/tasmota/i18n.h b/tasmota/i18n.h index 462774a53..db93df902 100644 --- a/tasmota/i18n.h +++ b/tasmota/i18n.h @@ -716,6 +716,11 @@ #define D_CMND_BR_RUN "" #define D_BR_NOT_STARTED "Berry not started" +// Commands xdrv_60_shift595.ino - 74x595 family shift register driver +#ifdef USE_SHIFT595 +#define D_CMND_SHIFT595_DEVICE_COUNT "Shift595DeviceCount" +#endif + // Commands xsns_02_analog.ino #define D_CMND_ADCPARAM "AdcParam" diff --git a/tasmota/language/en_GB.h b/tasmota/language/en_GB.h index 79eb011f1..0fed4b222 100644 --- a/tasmota/language/en_GB.h +++ b/tasmota/language/en_GB.h @@ -1083,4 +1083,10 @@ #define D_NEOPOOL_PH_LOW "too low" #define D_NEOPOOL_PUMP_TIME_EXCEEDED "pump time exceeded" +// xdrv_60_shift595.ino +#define D_GPIO_SHIFT595_SRCLK "74HC595 SRCLK" +#define D_GPIO_SHIFT595_RCLK "74HC595 RCLK" +#define D_GPIO_SHIFT595_OE "74HC595 OE" +#define D_GPIO_SHIFT595_SER "74HC595 SER" + #endif // _LANGUAGE_EN_GB_H_ diff --git a/tasmota/my_user_config.h b/tasmota/my_user_config.h index f04b79d93..d34174a56 100644 --- a/tasmota/my_user_config.h +++ b/tasmota/my_user_config.h @@ -350,6 +350,8 @@ #define ZIGBEE_DISTINCT_TOPICS false // [SetOption89] Enable unique device topic based on Zigbee device ShortAddr #define ZIGBEE_RMV_ZBRECEIVED false // [SetOption100] Remove ZbReceived form JSON message #define ZIGBEE_INDEX_EP false // [SetOption101] Add the source endpoint as suffix to attributes, ex `Power3` instead of `Power` if sent from endpoint 3 +#define SHIFT595_INVERT_OUTPUTS false // [SetOption133] Don't invert outputs of 74x595 shift register +#define SHIFT595_DEVICE_COUNT 1 // [Shift595Devices] Set the number of connected 74x595 shift registers /*********************************************************************************************\ * END OF SECTION 1 diff --git a/tasmota/settings.h b/tasmota/settings.h index 3686b1d42..02571350a 100644 --- a/tasmota/settings.h +++ b/tasmota/settings.h @@ -162,7 +162,7 @@ typedef union { // Restricted by MISRA-C Rule 18.4 bu uint32_t show_heap_with_timestamp : 1; // bit 16 (v9.5.0.9) - SetOption130 - (Debug) Show heap with logging timestamp uint32_t tuya_allow_dimmer_0 : 1; // bit 17 (v10.0.0.3) - SetOption131 - (Tuya) Allow save dimmer = 0 receved by MCU uint32_t tls_use_fingerprint : 1; // bit 18 (v10.0.0.4) - SetOption132 - (TLS) use fingerprint validation instead of CA based - uint32_t spare19 : 1; // bit 19 + uint32_t shift595_invert_outputs : 1; // bit 19 (v10.0.0.5) - SetOption133 - (Shift595) invert outputs of 74x595 shift registers uint32_t spare20 : 1; // bit 20 uint32_t spare21 : 1; // bit 21 uint32_t spare22 : 1; // bit 22 @@ -487,7 +487,8 @@ typedef struct { int32_t energy_kWhyesterday_ph[3]; // 320 int32_t energy_kWhtotal_ph[3]; // 32C - uint8_t free_338[7]; // 338 + uint8_t shift595_device_count; // 338 + uint8_t free_339[6]; // 339 uint8_t tuyamcu_topic; // 33F Manage tuyaSend topic. ex_energy_power_delta on 6.6.0.20, replaced on 8.5.0.1 uint16_t domoticz_update_timer; // 340 diff --git a/tasmota/settings.ino b/tasmota/settings.ino index faee15800..b2a58e2ae 100644 --- a/tasmota/settings.ino +++ b/tasmota/settings.ino @@ -1196,6 +1196,9 @@ void SettingsDefaultSet2(void) { flag4.mqtt_tls |= MQTT_TLS_ENABLED; flag4.mqtt_no_retain |= MQTT_NO_RETAIN; + flag5.shift595_invert_outputs |= SHIFT595_INVERT_OUTPUTS; + Settings->shift595_device_count = SHIFT595_DEVICE_COUNT; + Settings->flag = flag; Settings->flag2 = flag2; Settings->flag3 = flag3; diff --git a/tasmota/tasmota_template.h b/tasmota/tasmota_template.h index bbbce4d01..9e08aedb1 100644 --- a/tasmota/tasmota_template.h +++ b/tasmota/tasmota_template.h @@ -176,6 +176,7 @@ enum UserSelectablePins { GPIO_BL0942_RX, // BL0942 Serial interface GPIO_HM330X_SET, // HM330X SET pin (sleep when low) GPIO_HEARTBEAT, GPIO_HEARTBEAT_INV, + GPIO_SHIFT595_SRCLK, GPIO_SHIFT595_RCLK, GPIO_SHIFT595_OE, GPIO_SHIFT595_SER, // 74HC595 Shift register GPIO_SENSOR_END }; enum ProgramSelectablePins { @@ -372,7 +373,11 @@ const char kSensorNames[] PROGMEM = D_SENSOR_BL0942_RX "|" D_SENSOR_HM330X_SET "|" D_SENSOR_HEARTBEAT "|" D_SENSOR_HEARTBEAT "_i|" - ; + +#ifdef USE_SHIFT595 + D_GPIO_SHIFT595_SRCLK "|" D_GPIO_SHIFT595_RCLK "|" D_GPIO_SHIFT595_OE "|" D_GPIO_SHIFT595_SER "|" +#endif +; const char kSensorNamesFixed[] PROGMEM = D_SENSOR_USER; @@ -930,6 +935,13 @@ const uint16_t kGpioNiceList[] PROGMEM = { AGPIO(GPIO_ADC_JOY) + MAX_ADCS, // Joystick AGPIO(GPIO_ADC_PH) + MAX_ADCS, // Analog PH Sensor #endif // ESP32 + +#ifdef USE_SHIFT595 + AGPIO(GPIO_SHIFT595_SRCLK), // 74HC595 shift register + AGPIO(GPIO_SHIFT595_RCLK), + AGPIO(GPIO_SHIFT595_OE), + AGPIO(GPIO_SHIFT595_SER), +#endif }; /*-------------------------------------------------------------------------------------------*\ diff --git a/tasmota/xdrv_60_shift595.ino b/tasmota/xdrv_60_shift595.ino new file mode 100644 index 000000000..6e45194fa --- /dev/null +++ b/tasmota/xdrv_60_shift595.ino @@ -0,0 +1,114 @@ +/* + xdrv_60_shift595.ino - 74x595 shift register family support for Tasmota + + Copyright (C) 2021 Jacek Ziółkowski + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ +#ifdef USE_SHIFT595 + +#define XDRV_60 60 + +const char kShift595Commands[] PROGMEM = "|" D_CMND_SHIFT595_DEVICE_COUNT ; +void (* const Shit595Command[])(void) PROGMEM = { &CmndShift595Devices }; + +struct Shift595 { + int8_t pinSRCLK; + int8_t pinRCLK; + int8_t pinSER; + int8_t pinOE; + bool connected = false; + int8_t outputs; + int8_t first = TasmotaGlobal.devices_present; +} Shift595; + +void Shift595Init(void) +{ + if (PinUsed(GPIO_SHIFT595_SRCLK) && PinUsed(GPIO_SHIFT595_RCLK) && PinUsed(GPIO_SHIFT595_SER)) { + Shift595.pinSRCLK = Pin(GPIO_SHIFT595_SRCLK); + pinMode(Shift595.pinSRCLK, OUTPUT); + digitalWrite(Shift595.pinSRCLK, 0); + + Shift595.pinRCLK = Pin(GPIO_SHIFT595_RCLK); + pinMode(Shift595.pinRCLK, OUTPUT); + digitalWrite(Shift595.pinRCLK, 0); + + Shift595.pinSER = Pin(GPIO_SHIFT595_SER); + pinMode(Shift595.pinSER, OUTPUT); + digitalWrite(Shift595.pinSER, 0); + + if (PinUsed(GPIO_SHIFT595_OE)) { + Shift595.pinOE = Pin(GPIO_SHIFT595_OE); + pinMode(Shift595.pinOE, OUTPUT); + digitalWrite(Shift595.pinOE, 1); + } + Shift595.outputs = Settings->shift595_device_count * 8; + TasmotaGlobal.devices_present += Shift595.outputs; + Shift595.connected = true; + AddLog(LOG_LEVEL_DEBUG, PSTR("595: Controlling relays POWER%d to POWER%d"), Shift595.first + 1, Shift595.outputs); + } +} + +void Shift595LatchPin(uint8 pin) { + digitalWrite(pin, 1); + digitalWrite(pin, 0); +} + +void Shift595SwitchRelay(void) +{ + if (Shift595.connected == true) { + for (uint32_t i = 0; i < Shift595.outputs; i++) { + uint8_t relay_state = bitRead(XdrvMailbox.index, Shift595.first + Shift595.outputs -1 -i); + // digitalWrite(Shift595.pinSER, Settings->flag5.shift595_invert_outputs ? !relay_state : relay_state); + digitalWrite(Shift595.pinSER, relay_state); + Shift595LatchPin(Shift595.pinSRCLK); + } + + Shift595LatchPin(Shift595.pinRCLK); + + if (PinUsed(GPIO_SHIFT595_OE)) { + digitalWrite(Shift595.pinOE, 0); + } + } +} + +void CmndShift595Devices(void) { + if ((XdrvMailbox.payload > 0) && (XdrvMailbox.payload <= 4)) { + Settings->shift595_device_count = (1 == XdrvMailbox.payload) ? SHIFT595_DEVICE_COUNT : XdrvMailbox.payload; + TasmotaGlobal.restart_flag = 2; + } + ResponseCmndNumber(Settings->shift595_device_count); +} + +/*********************************************************************************************\ + * Interface +\*********************************************************************************************/ + +bool Xdrv60(uint8_t function) +{ + bool result = false; + switch (function) { + case FUNC_PRE_INIT: + Shift595Init(); + break; + case FUNC_SET_POWER: + Shift595SwitchRelay(); + break; + case FUNC_COMMAND: + result = DecodeCommand(kShift595Commands, Shift595Command); + break; + return result; +} + +#endif // USE_SHIFT595