From c803670137ad3c7fca4ae075dab164b6001b7057 Mon Sep 17 00:00:00 2001 From: Vic Date: Thu, 7 Jan 2021 16:39:41 +0100 Subject: [PATCH] BS814A-2 Touch Driver xdrv_52 flavor --- tasmota/language/bg_BG.h | 2 + tasmota/language/cs_CZ.h | 2 + tasmota/language/de_DE.h | 2 + tasmota/language/el_GR.h | 2 + tasmota/language/en_GB.h | 2 + tasmota/language/es_ES.h | 2 + tasmota/language/fr_FR.h | 2 + tasmota/language/he_HE.h | 2 + tasmota/language/hu_HU.h | 2 + tasmota/language/it_IT.h | 2 + tasmota/language/ko_KO.h | 2 + tasmota/language/nl_NL.h | 2 + tasmota/language/pl_PL.h | 2 + tasmota/language/pt_BR.h | 2 + tasmota/language/pt_PT.h | 2 + tasmota/language/ro_RO.h | 2 + tasmota/language/ru_RU.h | 2 + tasmota/language/sk_SK.h | 2 + tasmota/language/sv_SE.h | 2 + tasmota/language/tr_TR.h | 2 + tasmota/language/uk_UA.h | 2 + tasmota/language/vi_VN.h | 2 + tasmota/language/zh_CN.h | 2 + tasmota/language/zh_TW.h | 2 + tasmota/support_features.ino | 5 +- tasmota/tasmota_template.h | 6 ++ tasmota/xdrv_51_bs814a2.ino | 194 +++++++++++++++++++++++++++++++++++ 27 files changed, 251 insertions(+), 2 deletions(-) create mode 100644 tasmota/xdrv_51_bs814a2.ino diff --git a/tasmota/language/bg_BG.h b/tasmota/language/bg_BG.h index 7e2d2f7de..f00b30d2c 100644 --- a/tasmota/language/bg_BG.h +++ b/tasmota/language/bg_BG.h @@ -640,6 +640,8 @@ #define D_SENSOR_HX711_SCK "HX711 SCK" #define D_SENSOR_HX711_DAT "HX711 DAT" #define D_SENSOR_FTC532 "FTC532" +#define D_SENSOR_BS814_CLK "BS814 CLK" +#define D_SENSOR_BS814_DAT "BS814 DAT" #define D_SENSOR_TX2X_TX "TX2x" #define D_SENSOR_RFSEND "RFSend" #define D_SENSOR_RFRECV "RFrecv" diff --git a/tasmota/language/cs_CZ.h b/tasmota/language/cs_CZ.h index eabd83f6d..d529a4e16 100644 --- a/tasmota/language/cs_CZ.h +++ b/tasmota/language/cs_CZ.h @@ -641,6 +641,8 @@ #define D_SENSOR_HX711_SCK "HX711 SCK" #define D_SENSOR_HX711_DAT "HX711 DAT" #define D_SENSOR_FTC532 "FTC532" +#define D_SENSOR_BS814_CLK "BS814 CLK" +#define D_SENSOR_BS814_DAT "BS814 DAT" #define D_SENSOR_TX2X_TX "TX2x" #define D_SENSOR_RFSEND "RFSend" #define D_SENSOR_RFRECV "RFrecv" diff --git a/tasmota/language/de_DE.h b/tasmota/language/de_DE.h index e397d4bad..3ae7a842d 100644 --- a/tasmota/language/de_DE.h +++ b/tasmota/language/de_DE.h @@ -641,6 +641,8 @@ #define D_SENSOR_HX711_SCK "HX711 SCK" #define D_SENSOR_HX711_DAT "HX711 DAT" #define D_SENSOR_FTC532 "FTC532" +#define D_SENSOR_BS814_CLK "BS814 CLK" +#define D_SENSOR_BS814_DAT "BS814 DAT" #define D_SENSOR_TX2X_TX "TX2x" #define D_SENSOR_RFSEND "RFSend" #define D_SENSOR_RFRECV "RFrecv" diff --git a/tasmota/language/el_GR.h b/tasmota/language/el_GR.h index ac63555ca..9f1342b0b 100644 --- a/tasmota/language/el_GR.h +++ b/tasmota/language/el_GR.h @@ -641,6 +641,8 @@ #define D_SENSOR_HX711_SCK "HX711 SCK" #define D_SENSOR_HX711_DAT "HX711 DAT" #define D_SENSOR_FTC532 "FTC532" +#define D_SENSOR_BS814_CLK "BS814 CLK" +#define D_SENSOR_BS814_DAT "BS814 DAT" #define D_SENSOR_TX2X_TX "TX2x" #define D_SENSOR_RFSEND "RFSend" #define D_SENSOR_RFRECV "RFrecv" diff --git a/tasmota/language/en_GB.h b/tasmota/language/en_GB.h index 8f53e456c..11acc25fb 100644 --- a/tasmota/language/en_GB.h +++ b/tasmota/language/en_GB.h @@ -641,6 +641,8 @@ #define D_SENSOR_HX711_SCK "HX711 SCK" #define D_SENSOR_HX711_DAT "HX711 DAT" #define D_SENSOR_FTC532 "FTC532" +#define D_SENSOR_BS814_CLK "BS814 CLK" +#define D_SENSOR_BS814_DAT "BS814 DAT" #define D_SENSOR_TX2X_TX "TX2x" #define D_SENSOR_RFSEND "RFSend" #define D_SENSOR_RFRECV "RFrecv" diff --git a/tasmota/language/es_ES.h b/tasmota/language/es_ES.h index 01b323d94..bb9bdd4d0 100644 --- a/tasmota/language/es_ES.h +++ b/tasmota/language/es_ES.h @@ -641,6 +641,8 @@ #define D_SENSOR_HX711_SCK "HX711 SCK" #define D_SENSOR_HX711_DAT "HX711 DAT" #define D_SENSOR_FTC532 "FTC532" +#define D_SENSOR_BS814_CLK "BS814 CLK" +#define D_SENSOR_BS814_DAT "BS814 DAT" #define D_SENSOR_TX2X_TX "TX2x" #define D_SENSOR_RFSEND "RFSend" #define D_SENSOR_RFRECV "RFrecv" diff --git a/tasmota/language/fr_FR.h b/tasmota/language/fr_FR.h index b0ffb3378..4deb4afdf 100644 --- a/tasmota/language/fr_FR.h +++ b/tasmota/language/fr_FR.h @@ -637,6 +637,8 @@ #define D_SENSOR_HX711_SCK "HX711 SCK" #define D_SENSOR_HX711_DAT "HX711 DAT" #define D_SENSOR_FTC532 "FTC532" +#define D_SENSOR_BS814_CLK "BS814 CLK" +#define D_SENSOR_BS814_DAT "BS814 DAT" #define D_SENSOR_TX2X_TX "TX2x" #define D_SENSOR_RFSEND "RF TX" #define D_SENSOR_RFRECV "RF RX" diff --git a/tasmota/language/he_HE.h b/tasmota/language/he_HE.h index de4df185d..1ed935184 100644 --- a/tasmota/language/he_HE.h +++ b/tasmota/language/he_HE.h @@ -641,6 +641,8 @@ #define D_SENSOR_HX711_SCK "HX711 SCK" #define D_SENSOR_HX711_DAT "HX711 DAT" #define D_SENSOR_FTC532 "FTC532" +#define D_SENSOR_BS814_CLK "BS814 CLK" +#define D_SENSOR_BS814_DAT "BS814 DAT" #define D_SENSOR_TX2X_TX "TX2x" #define D_SENSOR_RFSEND "RFSend" #define D_SENSOR_RFRECV "RFrecv" diff --git a/tasmota/language/hu_HU.h b/tasmota/language/hu_HU.h index 70ebac047..b8d4d5347 100644 --- a/tasmota/language/hu_HU.h +++ b/tasmota/language/hu_HU.h @@ -641,6 +641,8 @@ #define D_SENSOR_HX711_SCK "HX711 SCK" #define D_SENSOR_HX711_DAT "HX711 DAT" #define D_SENSOR_FTC532 "FTC532" +#define D_SENSOR_BS814_CLK "BS814 CLK" +#define D_SENSOR_BS814_DAT "BS814 DAT" #define D_SENSOR_TX2X_TX "TX2x" #define D_SENSOR_RFSEND "RFSend" #define D_SENSOR_RFRECV "RFrecv" diff --git a/tasmota/language/it_IT.h b/tasmota/language/it_IT.h index 6d8842e8e..00bbc7721 100644 --- a/tasmota/language/it_IT.h +++ b/tasmota/language/it_IT.h @@ -641,6 +641,8 @@ #define D_SENSOR_HX711_SCK "HX711 - SCK" #define D_SENSOR_HX711_DAT "HX711 - DAT" #define D_SENSOR_FTC532 "FTC532" +#define D_SENSOR_BS814_CLK "BS814 CLK" +#define D_SENSOR_BS814_DAT "BS814 DAT" #define D_SENSOR_TX2X_TX "TX2x" #define D_SENSOR_RFSEND "RF - TX" #define D_SENSOR_RFRECV "RF - RX" diff --git a/tasmota/language/ko_KO.h b/tasmota/language/ko_KO.h index aba3bfb77..a51333856 100644 --- a/tasmota/language/ko_KO.h +++ b/tasmota/language/ko_KO.h @@ -641,6 +641,8 @@ #define D_SENSOR_HX711_SCK "HX711 SCK" #define D_SENSOR_HX711_DAT "HX711 DAT" #define D_SENSOR_FTC532 "FTC532" +#define D_SENSOR_BS814_CLK "BS814 CLK" +#define D_SENSOR_BS814_DAT "BS814 DAT" #define D_SENSOR_TX2X_TX "TX2x" #define D_SENSOR_RFSEND "RFSend" #define D_SENSOR_RFRECV "RFrecv" diff --git a/tasmota/language/nl_NL.h b/tasmota/language/nl_NL.h index 28475c5d2..185e3a0c0 100644 --- a/tasmota/language/nl_NL.h +++ b/tasmota/language/nl_NL.h @@ -641,6 +641,8 @@ #define D_SENSOR_HX711_SCK "HX711 SCK" #define D_SENSOR_HX711_DAT "HX711 DAT" #define D_SENSOR_FTC532 "FTC532" +#define D_SENSOR_BS814_CLK "BS814 CLK" +#define D_SENSOR_BS814_DAT "BS814 DAT" #define D_SENSOR_TX2X_TX "TX2x" #define D_SENSOR_RFSEND "RFSend" #define D_SENSOR_RFRECV "RFrecv" diff --git a/tasmota/language/pl_PL.h b/tasmota/language/pl_PL.h index 38b59817e..3c1bb5922 100644 --- a/tasmota/language/pl_PL.h +++ b/tasmota/language/pl_PL.h @@ -641,6 +641,8 @@ #define D_SENSOR_HX711_SCK "HX711 SCK" #define D_SENSOR_HX711_DAT "HX711 DAT" #define D_SENSOR_FTC532 "FTC532" +#define D_SENSOR_BS814_CLK "BS814 CLK" +#define D_SENSOR_BS814_DAT "BS814 DAT" #define D_SENSOR_TX2X_TX "TX2x" #define D_SENSOR_RFSEND "RFSend" #define D_SENSOR_RFRECV "RFrecv" diff --git a/tasmota/language/pt_BR.h b/tasmota/language/pt_BR.h index 5cbf9dff6..f48328e4c 100644 --- a/tasmota/language/pt_BR.h +++ b/tasmota/language/pt_BR.h @@ -641,6 +641,8 @@ #define D_SENSOR_HX711_SCK "HX711 SCK" #define D_SENSOR_HX711_DAT "HX711 DAT" #define D_SENSOR_FTC532 "FTC532" +#define D_SENSOR_BS814_CLK "BS814 CLK" +#define D_SENSOR_BS814_DAT "BS814 DAT" #define D_SENSOR_TX2X_TX "TX2x" #define D_SENSOR_RFSEND "RFSend" #define D_SENSOR_RFRECV "RFrecv" diff --git a/tasmota/language/pt_PT.h b/tasmota/language/pt_PT.h index 23a28466f..f7893127c 100644 --- a/tasmota/language/pt_PT.h +++ b/tasmota/language/pt_PT.h @@ -641,6 +641,8 @@ #define D_SENSOR_HX711_SCK "HX711 SCK" #define D_SENSOR_HX711_DAT "HX711 DAT" #define D_SENSOR_FTC532 "FTC532" +#define D_SENSOR_BS814_CLK "BS814 CLK" +#define D_SENSOR_BS814_DAT "BS814 DAT" #define D_SENSOR_TX2X_TX "TX2x" #define D_SENSOR_RFSEND "RFSend" #define D_SENSOR_RFRECV "RFrecv" diff --git a/tasmota/language/ro_RO.h b/tasmota/language/ro_RO.h index 6c1fc214d..b4641fca8 100644 --- a/tasmota/language/ro_RO.h +++ b/tasmota/language/ro_RO.h @@ -641,6 +641,8 @@ #define D_SENSOR_HX711_SCK "HX711 SCK" #define D_SENSOR_HX711_DAT "HX711 DAT" #define D_SENSOR_FTC532 "FTC532" +#define D_SENSOR_BS814_CLK "BS814 CLK" +#define D_SENSOR_BS814_DAT "BS814 DAT" #define D_SENSOR_TX2X_TX "TX2x" #define D_SENSOR_RFSEND "RFSend" #define D_SENSOR_RFRECV "RFrecv" diff --git a/tasmota/language/ru_RU.h b/tasmota/language/ru_RU.h index bf13e2976..9d19762a4 100644 --- a/tasmota/language/ru_RU.h +++ b/tasmota/language/ru_RU.h @@ -641,6 +641,8 @@ #define D_SENSOR_HX711_SCK "HX711 SCK" #define D_SENSOR_HX711_DAT "HX711 DAT" #define D_SENSOR_FTC532 "FTC532" +#define D_SENSOR_BS814_CLK "BS814 CLK" +#define D_SENSOR_BS814_DAT "BS814 DAT" #define D_SENSOR_TX2X_TX "TX2x" #define D_SENSOR_RFSEND "RFSend" #define D_SENSOR_RFRECV "RFrecv" diff --git a/tasmota/language/sk_SK.h b/tasmota/language/sk_SK.h index c37af4db1..5c46b4b89 100644 --- a/tasmota/language/sk_SK.h +++ b/tasmota/language/sk_SK.h @@ -641,6 +641,8 @@ #define D_SENSOR_HX711_SCK "HX711 SCK" #define D_SENSOR_HX711_DAT "HX711 DAT" #define D_SENSOR_FTC532 "FTC532" +#define D_SENSOR_BS814_CLK "BS814 CLK" +#define D_SENSOR_BS814_DAT "BS814 DAT" #define D_SENSOR_TX2X_TX "TX2x" #define D_SENSOR_RFSEND "RFSend" #define D_SENSOR_RFRECV "RFrecv" diff --git a/tasmota/language/sv_SE.h b/tasmota/language/sv_SE.h index 78926b602..a6e6aa1f6 100644 --- a/tasmota/language/sv_SE.h +++ b/tasmota/language/sv_SE.h @@ -641,6 +641,8 @@ #define D_SENSOR_HX711_SCK "HX711 SCK" #define D_SENSOR_HX711_DAT "HX711 DAT" #define D_SENSOR_FTC532 "FTC532" +#define D_SENSOR_BS814_CLK "BS814 CLK" +#define D_SENSOR_BS814_DAT "BS814 DAT" #define D_SENSOR_TX2X_TX "TX2x" #define D_SENSOR_RFSEND "RFSend" #define D_SENSOR_RFRECV "RFrecv" diff --git a/tasmota/language/tr_TR.h b/tasmota/language/tr_TR.h index df30519b8..21ac79065 100644 --- a/tasmota/language/tr_TR.h +++ b/tasmota/language/tr_TR.h @@ -641,6 +641,8 @@ #define D_SENSOR_HX711_SCK "HX711 SCK" #define D_SENSOR_HX711_DAT "HX711 DAT" #define D_SENSOR_FTC532 "FTC532" +#define D_SENSOR_BS814_CLK "BS814 CLK" +#define D_SENSOR_BS814_DAT "BS814 DAT" #define D_SENSOR_TX2X_TX "TX2x" #define D_SENSOR_RFSEND "RFSend" #define D_SENSOR_RFRECV "RFrecv" diff --git a/tasmota/language/uk_UA.h b/tasmota/language/uk_UA.h index 5787cf47c..b32761e2e 100644 --- a/tasmota/language/uk_UA.h +++ b/tasmota/language/uk_UA.h @@ -641,6 +641,8 @@ #define D_SENSOR_HX711_SCK "HX711 SCK" #define D_SENSOR_HX711_DAT "HX711 DAT" #define D_SENSOR_FTC532 "FTC532" +#define D_SENSOR_BS814_CLK "BS814 CLK" +#define D_SENSOR_BS814_DAT "BS814 DAT" #define D_SENSOR_TX2X_TX "TX2x" #define D_SENSOR_RFSEND "RFSend" #define D_SENSOR_RFRECV "RFRecv" diff --git a/tasmota/language/vi_VN.h b/tasmota/language/vi_VN.h index c3c465fb8..e5d7d6c35 100644 --- a/tasmota/language/vi_VN.h +++ b/tasmota/language/vi_VN.h @@ -641,6 +641,8 @@ #define D_SENSOR_HX711_SCK "HX711 SCK" #define D_SENSOR_HX711_DAT "HX711 DAT" #define D_SENSOR_FTC532 "FTC532" +#define D_SENSOR_BS814_CLK "BS814 CLK" +#define D_SENSOR_BS814_DAT "BS814 DAT" #define D_SENSOR_TX2X_TX "TX2x" #define D_SENSOR_RFSEND "RFSend" #define D_SENSOR_RFRECV "RFrecv" diff --git a/tasmota/language/zh_CN.h b/tasmota/language/zh_CN.h index aba3ede8a..2041c1483 100644 --- a/tasmota/language/zh_CN.h +++ b/tasmota/language/zh_CN.h @@ -641,6 +641,8 @@ #define D_SENSOR_HX711_SCK "HX711 SCK" #define D_SENSOR_HX711_DAT "HX711 DAT" #define D_SENSOR_FTC532 "FTC532" +#define D_SENSOR_BS814_CLK "BS814 CLK" +#define D_SENSOR_BS814_DAT "BS814 DAT" #define D_SENSOR_TX2X_TX "TX2x" #define D_SENSOR_RFSEND "RFSend" #define D_SENSOR_RFRECV "RFrecv" diff --git a/tasmota/language/zh_TW.h b/tasmota/language/zh_TW.h index 13bc7829b..46814ce24 100644 --- a/tasmota/language/zh_TW.h +++ b/tasmota/language/zh_TW.h @@ -641,6 +641,8 @@ #define D_SENSOR_HX711_SCK "HX711 SCK" #define D_SENSOR_HX711_DAT "HX711 DAT" #define D_SENSOR_FTC532 "FTC532" +#define D_SENSOR_BS814_CLK "BS814 CLK" +#define D_SENSOR_BS814_DAT "BS814 DAT" #define D_SENSOR_TX2X_TX "TX2x" #define D_SENSOR_RFSEND "RFSend" #define D_SENSOR_RFRECV "RFrecv" diff --git a/tasmota/support_features.ino b/tasmota/support_features.ino index 6000b4b09..d114b1b65 100644 --- a/tasmota/support_features.ino +++ b/tasmota/support_features.ino @@ -698,8 +698,9 @@ void ResponseAppendFeatures(void) #ifdef USE_PID feature7 |= 0x00800000; // xdrv_49_pid.ino #endif - -// feature7 |= 0x01000000; +#ifdef USE_BS814A2 + feature7 |= 0x01000000; // xdrv_51_bs814a2.ino +#endif // feature7 |= 0x02000000; // feature7 |= 0x04000000; // feature7 |= 0x08000000; diff --git a/tasmota/tasmota_template.h b/tasmota/tasmota_template.h index 0a48c3a66..512a22fec 100644 --- a/tasmota/tasmota_template.h +++ b/tasmota/tasmota_template.h @@ -145,6 +145,7 @@ enum UserSelectablePins { GPIO_SDCARD_CS, GPIO_ROT1A_NP, GPIO_ROT1B_NP, // Rotary switch GPIO_ADC_PH, // Analog PH Sensor + GPIO_BS814_CLK, GPIO_BS814_DAT, // Holtek BS814A2 touch ctrlr GPIO_SENSOR_END }; enum ProgramSelectablePins { @@ -310,6 +311,7 @@ const char kSensorNames[] PROGMEM = D_SENSOR_SDCARD_CS "|" D_SENSOR_ROTARY " A_n|" D_SENSOR_ROTARY " B_n|" D_SENSOR_ADC_PH "|" + D_SENSOR_BS814_CLK "|" D_SENSOR_BS814_DAT "|" ; const char kSensorNamesFixed[] PROGMEM = @@ -358,6 +360,10 @@ const uint16_t kGpioNiceList[] PROGMEM = { #ifdef USE_FTC532 AGPIO(GPIO_FTC532), // FTC532 touch input #endif +#ifdef USE_BS814A2 + AGPIO(GPIO_BS814_CLK), // Holtek BS814A2 touch ctrlr + AGPIO(GPIO_BS814_DAT), +#endif /*-------------------------------------------------------------------------------------------*\ * Protocol specifics diff --git a/tasmota/xdrv_51_bs814a2.ino b/tasmota/xdrv_51_bs814a2.ino new file mode 100644 index 000000000..17403e130 --- /dev/null +++ b/tasmota/xdrv_51_bs814a2.ino @@ -0,0 +1,194 @@ +/* + xdrv_51_bs814a2.ino - BS814A-2 touch buttons support for Tasmota + + Copyright (C) 2021 Peter Franck and Theo Arends + + 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_BS814A2 +/*********************************************************************************************\ + THE PLAN [tm]: OUTCOME: + ============== ======== + appear in a dropdown (BS814 CLK, BS814 DAT) + select 2 pins (clk, data) DONE + poll data pin for low state UNRELIABLE + generate high-speed clock (25kHz) DONE + poll data bits on clock plateau RISING EDGE + update data & report every 50 ms DONE + error & retry logic (if reqired) BASIC + MQTT message & rules hook DONE + test on actual Hardware DONE + + THE PROTOCOL [tm]: + ================== + see Holtek-Semicon BS814A-2 datasheet for details + + ********************* + * About this driver * + ********************* + + This driver implements the documented protocol of the Holtek BS814A-2 touch controller. + The protocol encodes the bitmap of touched keys in a syncronous serial data stream and + adds a 3-bit checksum to it. The Chip is supposed to alert the MCU of new key input by + pulling the data line low. This mechanism would have been nice but it didn't function + reliablly in my hardware sample. So I decided to poll the touch keys every 50 ms regard- + less of a change signal. The rest of the driver logic follows pretty much my previous + touch driver FTC532. + + Usage: + ------ + This driver does not actually switch anything. It is a pure "rules" driver that solely emits + {"BS814":{"KEYS":"XX"}} JSON messages to be used in a rule or by an MQTT broker. "XX" stands + for the hexadecimal (big endian) representation of a bitmap of keys currently touched, where + e.g. "00" means "no key touched" while "03" means "keys 1 and 2 touched simultaneously". + Selecting "BS814 CLK" on one GPIO and "BS814 DAT" on another GPIO will awake the driver. + This driver can only be selected once. + + NOTE: Key hex output is sent in 2 digits although it would fit in one. + The reason is a provision for BS818A-2 8-key controllers. +\*********************************************************************************************/ + +#define XDRV_51 51 + +#define BS814_KEYS_MAX 4 // no. of keys supported + +// Timing in microseconds +#define BS814_BIT 40 // serial bit time +#define BS814_PULSE 20 // clock pulse width +#define BS814_ERR_WAIT 6000 // minimum time before retry +#define BS814_FREQ 25000 // max bitrate + +struct BS814 { + uint8_t keys = 0; // bitmap of active & old keys: [ooookkkk] + bool present = false; // driver initialized +#ifdef DEBUG_BS814_DRIVER + uint16_t e_level = 0; // level disagree error + uint16_t e_cksum = 0; // checksum errror + uint16_t e_stp = 0; // stop bit error + bool valid = false; // did we ever receive valid data? +#endif // DEBUG_BS814_DRIVER +} Bs814; + +const char Bs814_json[] PROGMEM = "\"BS814\":{\"KEYS\":\""; + +extern "C" { + void os_delay_us(uint32_t); +} + +void bs814_init(void) { // Initialize + if (!PinUsed(GPIO_BS814_CLK) || !PinUsed(GPIO_BS814_DAT)) { return; } + pinMode(Pin(GPIO_BS814_DAT), INPUT_PULLUP); + pinMode(Pin(GPIO_BS814_CLK), OUTPUT); + Bs814.present = true; + bs814_read(); +} + +void bs814_read(void) { // Poll touch keys + uint8_t frame = 0; + uint8_t checksum = 0; + uint8_t bitp; + bool bitval; + + // generate clock signal & sample frame + for (bitp = 0; bitp < 2 * BS814_KEYS_MAX - 1; ++bitp) { + digitalWrite(Pin(GPIO_BS814_CLK), LOW); + os_delay_us(BS814_PULSE); + digitalWrite(Pin(GPIO_BS814_CLK), HIGH); + bitval = digitalRead(Pin(GPIO_BS814_DAT)); +#ifdef DEBUG_BS814_DRIVER + if (bitval != digitalRead(Pin(GPIO_BS814_DAT))) { // value consistent? + ++Bs814.e_level; + } +#endif // DEBUG_BS814_DRIVER + frame |= (bitval << bitp); + if (bitp < BS814_KEYS_MAX) { + checksum += bitval; + } + os_delay_us(BS814_PULSE); + } + digitalWrite(Pin(GPIO_BS814_CLK), LOW); + os_delay_us(BS814_PULSE); + digitalWrite(Pin(GPIO_BS814_CLK), HIGH); + bitval = digitalRead(Pin(GPIO_BS814_DAT)); + frame |= (bitval << bitp); + // validate frame + if (BS814_KEYS_MAX - checksum != ((frame >> 4) & 0x7)) { // checksum error +#ifdef DEBUG_BS814_DRIVER + ++Bs814.e_cksum; + AddLog_P(LOG_LEVEL_DEBUG, PSTR("CKS=%02X CFR=%02X"), checksum, (frame >> 4) & 0x7); +#endif // DEBUG_BS814_DRIVER + return; + } + if ((frame & 0x80) == 0) { // stop bit error +#ifdef DEBUG_BS814_DRIVER + ++Bs814.e_stp; +#endif // DEBUG_BS814_DRIVER + return; + } + Bs814.keys = (Bs814.keys & 0xF0) | (~frame & 0xF); // frame logic inverted +#ifdef DEBUG_BS814_DRIVER + Bs814.valid = true; +#endif // DEBUG_BS814_DRIVER +} + +void bs814_update(void) { // Usually called every 50 ms + bs814_read(); + if ((Bs814.keys & 0xF) != (Bs814.keys >> 4)) { +#ifdef DEBUG_BS814_DRIVER + AddLog_P(LOG_LEVEL_DEBUG, PSTR("BS814: KEY=%0X OLD=%0X LVL=%u CKS=%u STP=%u OK=%u CLK=%u DAT=%u"), + Bs814.keys & 0xF, Bs814.keys >> 4, Bs814.e_level, Bs814.e_cksum, Bs814.e_stp, + Bs814.valid, Pin(GPIO_BS814_CLK), Pin(GPIO_BS814_DAT)); +#endif // DEBUG_BS814_DRIVER + bs814_publish(); + Bs814.keys = (Bs814.keys << 4) | (Bs814.keys & 0xF); + } +} + +void bs814_show() { + ResponseAppend_P(PSTR(",%s%02X\"}"), Bs814_json, Bs814.keys & 0xF); // tele json +} + +void bs814_publish(void) { + Response_P(PSTR("{%s%02X\"}}"), Bs814_json, Bs814.keys & 0xF); // mqtt & rules + MqttPublishTeleSensor(); +} + +/*********************************************************************************************\ + * Interface +\*********************************************************************************************/ + +bool Xdrv51(uint8_t function) { + bool result = false; + + if (FUNC_INIT == function) { + // Initialize driver + bs814_init(); + } else if (Bs814.present) { + switch (function) { + // timed callback functions + case FUNC_EVERY_50_MSECOND: + bs814_update(); + break; + // Generate JSON telemetry string + case FUNC_JSON_APPEND: + bs814_show(); + break; + } + } + // Return bool result + return result; +} + +#endif // USE_BS814A2