From f21ca11c6b57f6f87b1449079d7fec15d03061ec Mon Sep 17 00:00:00 2001 From: HTotoo Date: Sun, 10 Dec 2023 15:23:45 +0100 Subject: [PATCH] add protos --- firmware/application/apps/ui_subghzd.cpp | 6 ++ firmware/baseband/fprotos/s-holtek_ht12x.hpp | 92 ++++++++++++++++ firmware/baseband/fprotos/s-honeywell.hpp | 107 +++++++++++++++++++ firmware/baseband/fprotos/subghzdprotos.hpp | 28 ++--- firmware/baseband/fprotos/subghztypes.hpp | 2 + 5 files changed, 223 insertions(+), 12 deletions(-) create mode 100644 firmware/baseband/fprotos/s-holtek_ht12x.hpp create mode 100644 firmware/baseband/fprotos/s-honeywell.hpp diff --git a/firmware/application/apps/ui_subghzd.cpp b/firmware/application/apps/ui_subghzd.cpp index 598d092a7..94f779eab 100644 --- a/firmware/application/apps/ui_subghzd.cpp +++ b/firmware/application/apps/ui_subghzd.cpp @@ -154,6 +154,12 @@ const char* SubGhzDView::getSensorTypeName(FPROTO_SUBGHZD_SENSOR type) { return "Faac"; case FPS_GATETX: return "Gate TX"; + case FPS_HOLTEK: + return "Holtek"; + case FPS_HOLTEKHT12X: + return "Holtek HT12X"; + case FPS_HONEYWELL: + return "Honeywell"; case FPS_Invalid: default: return "Unknown"; diff --git a/firmware/baseband/fprotos/s-holtek_ht12x.hpp b/firmware/baseband/fprotos/s-holtek_ht12x.hpp new file mode 100644 index 000000000..45ea773b2 --- /dev/null +++ b/firmware/baseband/fprotos/s-holtek_ht12x.hpp @@ -0,0 +1,92 @@ + +#ifndef __FPROTO_HOLTEKTH12X_H__ +#define __FPROTO_HOLTEKTH12X_H__ + +#include "subghzdbase.hpp" + +typedef enum { + Holtek_HT12XDecoderStepReset = 0, + Holtek_HT12XDecoderStepFoundStartBit, + Holtek_HT12XDecoderStepSaveDuration, + Holtek_HT12XDecoderStepCheckDuration, +} Holtek_HT12XDecoderStep; + +class FProtoSubGhzDCHoltekHt12x : public FProtoSubGhzDBase { + public: + FProtoSubGhzDCHoltekHt12x() { + sensorType = FPS_HOLTEKHT12X; + } + + void feed(bool level, uint32_t duration) { + switch (parser_step) { + case Holtek_HT12XDecoderStepReset: + if ((!level) && (DURATION_DIFF(duration, te_short * 36) < te_delta * 36)) { + // Found Preambula + parser_step = Holtek_HT12XDecoderStepFoundStartBit; + } + break; + case Holtek_HT12XDecoderStepFoundStartBit: + if ((level) && (DURATION_DIFF(duration, te_short) < te_delta)) { + // Found StartBit + parser_step = Holtek_HT12XDecoderStepSaveDuration; + decode_data = 0; + decode_count_bit = 0; + } else { + parser_step = Holtek_HT12XDecoderStepReset; + } + break; + case Holtek_HT12XDecoderStepSaveDuration: + // save duration + if (!level) { + if (duration >= ((uint32_t)te_short * 10 + te_delta)) { + if (decode_count_bit == min_count_bit_for_found) { + if (data != decode_data) { + data = decode_data; + data_count_bit = decode_count_bit; + // controller + btn = data & 0x0F; + cnt = (data >> 4) & 0xFF; + if (callback) callback(this); + } + } + decode_data = 0; + decode_count_bit = 0; + parser_step = Holtek_HT12XDecoderStepFoundStartBit; + break; + } else { + te_last = duration; + parser_step = Holtek_HT12XDecoderStepCheckDuration; + } + } else { + parser_step = Holtek_HT12XDecoderStepReset; + } + break; + case Holtek_HT12XDecoderStepCheckDuration: + if (level) { + if ((DURATION_DIFF(te_last, te_long) < te_delta * 2) && + (DURATION_DIFF(duration, te_short) < te_delta)) { + subghz_protocol_blocks_add_bit(1); + parser_step = Holtek_HT12XDecoderStepSaveDuration; + } else if ( + (DURATION_DIFF(te_last, te_short) < te_delta) && + (DURATION_DIFF(duration, te_long) < te_delta * 2)) { + subghz_protocol_blocks_add_bit(0); + parser_step = Holtek_HT12XDecoderStepSaveDuration; + } else { + parser_step = Holtek_HT12XDecoderStepReset; + } + } else { + parser_step = Holtek_HT12XDecoderStepReset; + } + break; + } + } + + protected: + uint32_t te_short = 320; + uint32_t te_long = 640; + uint32_t te_delta = 200; + uint32_t min_count_bit_for_found = 12; +}; + +#endif diff --git a/firmware/baseband/fprotos/s-honeywell.hpp b/firmware/baseband/fprotos/s-honeywell.hpp new file mode 100644 index 000000000..63eb2d723 --- /dev/null +++ b/firmware/baseband/fprotos/s-honeywell.hpp @@ -0,0 +1,107 @@ + +#ifndef __FPROTO_HONEYWELL_H__ +#define __FPROTO_HONEYWELL_H__ + +#include "subghzdbase.hpp" + +class FProtoSubGhzDCHoneywell : public FProtoSubGhzDBase { + public: + FProtoSubGhzDCHoneywell() { + sensorType = FPS_HONEYWELL; + } + + void feed(bool level, uint32_t duration) { + ManchesterEvent event = ManchesterEventReset; + if (!level) { + if (DURATION_DIFF(duration, te_short) < te_delta) { + event = ManchesterEventShortLow; + } else if ( + DURATION_DIFF(duration, te_long) < te_delta * 2) { + event = ManchesterEventLongLow; + } + } else { + if (DURATION_DIFF(duration, te_short) < te_delta) { + event = ManchesterEventShortHigh; + } else if ( + DURATION_DIFF(duration, te_long) < te_delta * 2) { + event = ManchesterEventLongHigh; + } + } + if (event != ManchesterEventReset) { + bool data; + bool data_ok = FProtoGeneral::manchester_advance( + manchester_saved_state, event, &manchester_saved_state, &data); + if (data_ok) { + subghz_protocol_decoder_honeywell_addbit(data); + } + } else { + decode_data = 0; + decode_count_bit = 0; + } + } + + protected: + uint32_t te_short = 280; + uint32_t te_long = 143; + uint32_t te_delta = 51; + uint32_t min_count_bit_for_found = 62; + + void subghz_protocol_decoder_honeywell_addbit(bool data) { + decode_data = (decode_data << 1) | data; + decode_count_bit++; + + uint16_t preamble = (decode_data >> 48) & 0xFFFF; + // can be multiple, since flipper can't read it well.. + if (preamble == 0b0011111111111110 || preamble == 0b0111111111111110 || + preamble == 0b1111111111111110) { + uint8_t datatocrc[4]; + datatocrc[0] = (decode_data >> 40) & 0xFFFF; + datatocrc[1] = (decode_data >> 32) & 0xFFFF; + datatocrc[2] = (decode_data >> 24) & 0xFFFF; + datatocrc[3] = (decode_data >> 16) & 0xFFFF; + uint8_t channel = (decode_data >> 44) & 0xF; + uint16_t crc_calc = 0; + if (channel == 0x2 || channel == 0x4 || channel == 0xA) { + // 2GIG brand + crc_calc = subghz_protocol_honeywell_crc16(datatocrc, 4, 0x8050, 0); + } else { // channel == 0x8 + crc_calc = subghz_protocol_honeywell_crc16(datatocrc, 4, 0x8005, 0); + } + uint16_t crc = decode_data & 0xFFFF; + if (crc == crc_calc) { + // the data is good. process it. + data = decode_data; + data_count_bit = decode_count_bit; // maybe set it to 64, and hack the first 2 bits to 1! will see if replay needs it + serial = (decode_data >> 24) & 0xFFFFF; + btn = (decode_data >> 16) & 0xFF; // not exactly button, but can contain btn data too. + if (callback) callback(this); + decode_data = 0; + decode_count_bit = 0; + } else { + return; + } + } + } + uint16_t subghz_protocol_honeywell_crc16( + uint8_t const message[], + unsigned nBytes, + uint16_t polynomial, + uint16_t init) { + uint16_t remainder = init; + unsigned byte, bit; + + for (byte = 0; byte < nBytes; ++byte) { + remainder ^= message[byte] << 8; + for (bit = 0; bit < 8; ++bit) { + if (remainder & 0x8000) { + remainder = (remainder << 1) ^ polynomial; + } else { + remainder = (remainder << 1); + } + } + } + return remainder; + } +}; + +#endif diff --git a/firmware/baseband/fprotos/subghzdprotos.hpp b/firmware/baseband/fprotos/subghzdprotos.hpp index 9b2505ae8..618e5155c 100644 --- a/firmware/baseband/fprotos/subghzdprotos.hpp +++ b/firmware/baseband/fprotos/subghzdprotos.hpp @@ -23,6 +23,8 @@ So include here the .hpp, and add a new element to the protos vector in the cons #include "s-faac.hpp" #include "s-gate_tx.hpp" #include "s-holtek.hpp" +#include "s-holtek_ht12x.hpp" +#include "s-honeywell.hpp" #ifndef __FPROTO_PROTOLISTSGZ_H__ #define __FPROTO_PROTOLISTSGZ_H__ @@ -32,18 +34,20 @@ class SubGhzDProtos : public FProtoListGeneral { SubGhzDProtos() { // add protos // protos.push_back(std::make_unique()); // 1 //skip since fm - protos.push_back(std::make_unique()); // 2 - protos.push_back(std::make_unique()); // 3 - protos.push_back(std::make_unique()); // 4, 5, 6 - protos.push_back(std::make_unique()); // 7 - protos.push_back(std::make_unique()); // 8 - protos.push_back(std::make_unique()); // 9 - protos.push_back(std::make_unique()); // 10 - protos.push_back(std::make_unique()); // 11 - protos.push_back(std::make_unique()); // 12 - protos.push_back(std::make_unique()); // 13 - protos.push_back(std::make_unique()); // 14 - protos.push_back(std::make_unique()); // 15 + protos.push_back(std::make_unique()); // 2 + protos.push_back(std::make_unique()); // 3 + protos.push_back(std::make_unique()); // 4, 5, 6 + protos.push_back(std::make_unique()); // 7 + protos.push_back(std::make_unique()); // 8 + protos.push_back(std::make_unique()); // 9 + protos.push_back(std::make_unique()); // 10 + protos.push_back(std::make_unique()); // 11 + protos.push_back(std::make_unique()); // 12 + protos.push_back(std::make_unique()); // 13 + protos.push_back(std::make_unique()); // 14 + protos.push_back(std::make_unique()); // 15 + protos.push_back(std::make_unique()); // 16 + protos.push_back(std::make_unique()); // 17 // set callback for them for (const auto& obj : protos) { diff --git a/firmware/baseband/fprotos/subghztypes.hpp b/firmware/baseband/fprotos/subghztypes.hpp index 180b459b1..19c10e01c 100644 --- a/firmware/baseband/fprotos/subghztypes.hpp +++ b/firmware/baseband/fprotos/subghztypes.hpp @@ -34,6 +34,8 @@ enum FPROTO_SUBGHZD_SENSOR { FPS_FAAC = 13, FPS_GATETX = 14, FPS_HOLTEK = 15, + FPS_HOLTEKHT12X = 16, + FPS_HONEYWELL = 17, }; #endif