mirror of
https://github.com/RfidResearchGroup/mayhem-firmware.git
synced 2026-05-12 11:27:21 -07:00
SubghzD rework (#2210)
* Removed controller code * Add Legrand * Added Somify Keytis * Somify * better display
This commit is contained in:
File diff suppressed because it is too large
Load Diff
@@ -23,6 +23,10 @@
|
||||
#ifndef __UI_SUBGHZD_H__
|
||||
#define __UI_SUBGHZD_H__
|
||||
|
||||
#define SD_NO_SERIAL 0xFFFFFFFF
|
||||
#define SD_NO_BTN 0xFF
|
||||
#define SD_NO_CNT 0xFF
|
||||
|
||||
#include "ui.hpp"
|
||||
#include "ui_navigation.hpp"
|
||||
#include "ui_receiver.hpp"
|
||||
@@ -33,6 +37,7 @@
|
||||
#include "recent_entries.hpp"
|
||||
|
||||
#include "../baseband/fprotos/subghztypes.hpp"
|
||||
#include "../baseband/fprotos/fprotogeneral.hpp"
|
||||
|
||||
using namespace ui;
|
||||
|
||||
@@ -42,29 +47,20 @@ struct SubGhzDRecentEntry {
|
||||
using Key = uint64_t;
|
||||
static constexpr Key invalid_key = 0x0fffffff;
|
||||
uint8_t sensorType = FPS_Invalid;
|
||||
uint8_t btn = SD_NO_BTN;
|
||||
uint32_t serial = SD_NO_SERIAL;
|
||||
uint16_t bits = 0;
|
||||
uint16_t age = 0; // updated on each seconds, show how long the signal was last seen
|
||||
uint32_t cnt = SD_NO_CNT;
|
||||
uint64_t data = 0;
|
||||
SubGhzDRecentEntry() {}
|
||||
SubGhzDRecentEntry(
|
||||
uint8_t sensorType,
|
||||
uint32_t serial,
|
||||
uint16_t bits = 0,
|
||||
uint64_t data = 0,
|
||||
uint8_t btn = SD_NO_BTN,
|
||||
uint32_t cnt = SD_NO_CNT)
|
||||
uint16_t bits = 0)
|
||||
: sensorType{sensorType},
|
||||
btn{btn},
|
||||
serial{serial},
|
||||
bits{bits},
|
||||
cnt{cnt},
|
||||
data{data} {
|
||||
}
|
||||
Key key() const {
|
||||
return (data ^ ((static_cast<uint64_t>(serial) << 32) | (static_cast<uint64_t>(sensorType) & 0xFF) << 0));
|
||||
return (data ^ ((static_cast<uint64_t>(sensorType) & 0xFF) << 0));
|
||||
}
|
||||
void inc_age(int delta) {
|
||||
if (UINT16_MAX - delta > age) age += delta;
|
||||
@@ -149,6 +145,12 @@ class SubGhzDRecentEntryDetailView : public View {
|
||||
private:
|
||||
NavigationView& nav_;
|
||||
SubGhzDRecentEntry entry_{};
|
||||
|
||||
uint32_t serial = 0;
|
||||
uint8_t btn = SD_NO_BTN;
|
||||
uint32_t cnt = SD_NO_CNT;
|
||||
uint32_t seed = 0;
|
||||
|
||||
Text text_type{{0 * 8, 1 * 16, 15 * 8, 16}, "?"};
|
||||
Text text_id{{6 * 8, 2 * 16, 10 * 8, 16}, "?"};
|
||||
|
||||
@@ -164,6 +166,8 @@ class SubGhzDRecentEntryDetailView : public View {
|
||||
Button button_done{
|
||||
{screen_width - 96 - 4, screen_height - 32 - 12, 96, 32},
|
||||
"Done"};
|
||||
|
||||
void parseProtocol();
|
||||
};
|
||||
|
||||
} // namespace ui
|
||||
|
||||
@@ -53,8 +53,6 @@ class FProtoSubGhzDCame : public FProtoSubGhzDBase {
|
||||
parser_step = CameDecoderStepFoundStartBit;
|
||||
if ((decode_count_bit == min_count_bit_for_found) || (decode_count_bit == AIRFORCE_COUNT_BIT) ||
|
||||
(decode_count_bit == PRASTEL_COUNT_BIT) || (decode_count_bit == CAME_24_COUNT_BIT)) {
|
||||
serial = SD_NO_SERIAL;
|
||||
btn = SD_NO_BTN;
|
||||
data = decode_data;
|
||||
data_count_bit = decode_count_bit;
|
||||
// if flippa hacky, i hacky
|
||||
|
||||
@@ -45,36 +45,6 @@ class FProtoSubGhzDCameAtomo : public FProtoSubGhzDBase {
|
||||
min_count_bit_for_found) {
|
||||
data = decode_data;
|
||||
data_count_bit = decode_count_bit;
|
||||
// controller
|
||||
data ^= 0xFFFFFFFFFFFFFFFF;
|
||||
data <<= 4;
|
||||
|
||||
uint8_t pack[8] = {};
|
||||
pack[0] = (data >> 56);
|
||||
pack[1] = ((data >> 48) & 0xFF);
|
||||
pack[2] = ((data >> 40) & 0xFF);
|
||||
pack[3] = ((data >> 32) & 0xFF);
|
||||
pack[4] = ((data >> 24) & 0xFF);
|
||||
pack[5] = ((data >> 16) & 0xFF);
|
||||
pack[6] = ((data >> 8) & 0xFF);
|
||||
pack[7] = (data & 0xFF);
|
||||
|
||||
atomo_decrypt(pack);
|
||||
|
||||
cnt = (uint16_t)pack[1] << 8 | pack[2];
|
||||
serial = (uint32_t)(pack[3]) << 24 | pack[4] << 16 | pack[5] << 8 | pack[6];
|
||||
|
||||
uint8_t btn_decode = (pack[7] >> 4);
|
||||
if (btn_decode == 0x0) {
|
||||
btn = 0x1;
|
||||
} else if (btn_decode == 0x2) {
|
||||
btn = 0x2;
|
||||
} else if (btn_decode == 0x4) {
|
||||
btn = 0x3;
|
||||
} else if (btn_decode == 0x6) {
|
||||
btn = 0x4;
|
||||
}
|
||||
|
||||
if (callback) callback(this);
|
||||
}
|
||||
decode_data = 0;
|
||||
|
||||
@@ -45,7 +45,6 @@ class FProtoSubGhzDCameTwee : public FProtoSubGhzDBase {
|
||||
if (decode_count_bit == min_count_bit_for_found) {
|
||||
data = decode_data;
|
||||
data_count_bit = decode_count_bit;
|
||||
subghz_protocol_came_twee_remote_controller();
|
||||
if (callback) callback(this);
|
||||
}
|
||||
decode_data = 0;
|
||||
@@ -79,69 +78,6 @@ class FProtoSubGhzDCameTwee : public FProtoSubGhzDBase {
|
||||
|
||||
protected:
|
||||
ManchesterState manchester_saved_state = ManchesterStateMid1;
|
||||
|
||||
void subghz_protocol_came_twee_remote_controller() {
|
||||
/* Came Twee 54 bit, rolling code 15 parcels with
|
||||
* a decreasing counter from 0xE to 0x0
|
||||
* with originally coded dip switches on the console 10 bit code
|
||||
*
|
||||
* 0x003FFF72E04A6FEE
|
||||
* 0x003FFF72D17B5EDD
|
||||
* 0x003FFF72C2684DCC
|
||||
* 0x003FFF72B3193CBB
|
||||
* 0x003FFF72A40E2BAA
|
||||
* 0x003FFF72953F1A99
|
||||
* 0x003FFF72862C0988
|
||||
* 0x003FFF7277DDF877
|
||||
* 0x003FFF7268C2E766
|
||||
* 0x003FFF7259F3D655
|
||||
* 0x003FFF724AE0C544
|
||||
* 0x003FFF723B91B433
|
||||
* 0x003FFF722C86A322
|
||||
* 0x003FFF721DB79211
|
||||
* 0x003FFF720EA48100
|
||||
*
|
||||
* decryption
|
||||
* the last 32 bits, do XOR by the desired number, divide the result by 4,
|
||||
* convert the first 16 bits of the resulting 32-bit number to bin and do
|
||||
* bit-by-bit mirroring, adding up to 10 bits
|
||||
*
|
||||
* Example
|
||||
* Step 1. 0x003FFF721DB79211 => 0x1DB79211
|
||||
* Step 4. 0x1DB79211 xor 0x1D1D1D11 => 0x00AA8F00
|
||||
* Step 4. 0x00AA8F00 / 4 => 0x002AA3C0
|
||||
* Step 5. 0x002AA3C0 => 0x002A
|
||||
* Step 6. 0x002A bin => b101010
|
||||
* Step 7. b101010 => b0101010000
|
||||
* Step 8. b0101010000 => (Dip) Off ON Off ON Off ON Off Off Off Off
|
||||
*/
|
||||
|
||||
uint8_t cnt_parcel = (uint8_t)(data & 0xF);
|
||||
serial = (uint32_t)(data & 0x0FFFFFFFF);
|
||||
data = (data ^ came_twee_magic_numbers_xor[cnt_parcel]);
|
||||
data /= 4;
|
||||
btn = (data >> 4) & 0x0F;
|
||||
data >>= 16;
|
||||
data = (uint16_t)FProtoGeneral::subghz_protocol_blocks_reverse_key(data, 16);
|
||||
cnt = data >> 6;
|
||||
}
|
||||
inline static const uint32_t came_twee_magic_numbers_xor[15] = {
|
||||
0x0E0E0E00,
|
||||
0x1D1D1D11,
|
||||
0x2C2C2C22,
|
||||
0x3B3B3B33,
|
||||
0x4A4A4A44,
|
||||
0x59595955,
|
||||
0x68686866,
|
||||
0x77777777,
|
||||
0x86868688,
|
||||
0x95959599,
|
||||
0xA4A4A4AA,
|
||||
0xB3B3B3BB,
|
||||
0xC2C2C2CC,
|
||||
0xD1D1D1DD,
|
||||
0xE0E0E0EE,
|
||||
};
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
@@ -57,8 +57,6 @@ class FProtoSubGhzDChambCode : public FProtoSubGhzDBase {
|
||||
if (!level) { // save interval
|
||||
if (duration > te_short * 5) {
|
||||
if (decode_count_bit >= min_count_bit_for_found) {
|
||||
serial = SD_NO_SERIAL;
|
||||
btn = SD_NO_BTN;
|
||||
if (subghz_protocol_decoder_chamb_code_check_mask_and_parse()) {
|
||||
data = decode_data;
|
||||
data_count_bit = decode_count_bit;
|
||||
|
||||
@@ -64,11 +64,6 @@ class FProtoSubGhzDClemsa : public FProtoSubGhzDBase {
|
||||
min_count_bit_for_found) {
|
||||
data = decode_data;
|
||||
data_count_bit = decode_count_bit;
|
||||
|
||||
// controller
|
||||
serial = (data >> 2) & 0xFFFF;
|
||||
btn = (data & 0x03);
|
||||
|
||||
if (callback) callback(this);
|
||||
}
|
||||
parser_step = ClemsaDecoderStepSaveDuration;
|
||||
|
||||
@@ -46,10 +46,6 @@ class FProtoSubGhzDDoitrand : public FProtoSubGhzDBase {
|
||||
if (decode_count_bit == min_count_bit_for_found) {
|
||||
data = decode_data;
|
||||
data_count_bit = decode_count_bit;
|
||||
|
||||
// controller
|
||||
cnt = (data >> 24) | ((data >> 15) & 0x1);
|
||||
btn = ((data >> 18) & 0x3);
|
||||
if (callback) callback(this);
|
||||
}
|
||||
decode_data = 0;
|
||||
|
||||
@@ -74,16 +74,6 @@ class FProtoSubGhzDDooya : public FProtoSubGhzDBase {
|
||||
min_count_bit_for_found) {
|
||||
data = decode_data;
|
||||
data_count_bit = decode_count_bit;
|
||||
|
||||
// controller:
|
||||
serial = (data >> 16);
|
||||
if ((data >> 12) & 0x0F) {
|
||||
cnt = (data >> 8) & 0x0F;
|
||||
} else {
|
||||
cnt = 0xFF;
|
||||
}
|
||||
btn = data & 0xFF;
|
||||
|
||||
if (callback) callback(this);
|
||||
}
|
||||
break;
|
||||
|
||||
@@ -46,12 +46,6 @@ class FProtoSubGhzDGateTx : public FProtoSubGhzDBase {
|
||||
if (decode_count_bit == min_count_bit_for_found) {
|
||||
data = decode_data;
|
||||
data_count_bit = decode_count_bit;
|
||||
|
||||
// controller
|
||||
uint32_t code_found_reverse = FProtoGeneral::subghz_protocol_blocks_reverse_key(data, data_count_bit);
|
||||
serial = (code_found_reverse & 0xFF) << 12 | ((code_found_reverse >> 8) & 0xFF) << 4 | ((code_found_reverse >> 20) & 0x0F);
|
||||
btn = ((code_found_reverse >> 16) & 0x0F);
|
||||
|
||||
if (callback) callback(this);
|
||||
}
|
||||
decode_data = 0;
|
||||
|
||||
@@ -51,22 +51,6 @@ class FProtoSubGhzDHoltek : public FProtoSubGhzDBase {
|
||||
if ((decode_data & HOLTEK_HEADER_MASK) == HOLTEK_HEADER) {
|
||||
data = decode_data;
|
||||
data_count_bit = decode_count_bit;
|
||||
|
||||
// controller
|
||||
serial = FProtoGeneral::subghz_protocol_blocks_reverse_key((data >> 16) & 0xFFFFF, 20);
|
||||
uint16_t btn = data & 0xFFFF;
|
||||
if ((btn & 0xf) != 0xA) {
|
||||
btn = 0x1 << 4 | (btn & 0xF);
|
||||
} else if (((btn >> 4) & 0xF) != 0xA) {
|
||||
btn = 0x2 << 4 | ((btn >> 4) & 0xF);
|
||||
} else if (((btn >> 8) & 0xF) != 0xA) {
|
||||
btn = 0x3 << 4 | ((btn >> 8) & 0xF);
|
||||
} else if (((btn >> 12) & 0xF) != 0xA) {
|
||||
btn = 0x4 << 4 | ((btn >> 12) & 0xF);
|
||||
} else {
|
||||
btn = 0;
|
||||
}
|
||||
|
||||
if (callback) callback(this);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -47,9 +47,6 @@ class FProtoSubGhzDHoltekHt12x : public FProtoSubGhzDBase {
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -73,8 +73,6 @@ class FProtoSubGhzDHoneywell : public FProtoSubGhzDBase {
|
||||
// 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;
|
||||
|
||||
@@ -49,8 +49,6 @@ class FProtoSubGhzDHormann : public FProtoSubGhzDBase {
|
||||
min_count_bit_for_found) {
|
||||
data = decode_data;
|
||||
data_count_bit = decode_count_bit;
|
||||
// controller
|
||||
btn = (data >> 4) & 0xF;
|
||||
if (callback) callback(this);
|
||||
}
|
||||
break;
|
||||
|
||||
@@ -0,0 +1,130 @@
|
||||
|
||||
#ifndef __FPROTO_HORMANNBISECURE_H__
|
||||
#define __FPROTO_HORMANNBISECURE_H__
|
||||
|
||||
#include "subghzdbase.hpp"
|
||||
|
||||
typedef enum {
|
||||
HormannBiSecurDecoderStepReset = 0,
|
||||
HormannBiSecurDecoderStepFoundPreambleAlternatingShort,
|
||||
HormannBiSecurDecoderStepFoundPreambleHighVeryLong,
|
||||
HormannBiSecurDecoderStepFoundPreambleAlternatingLong,
|
||||
HormannBiSecurDecoderStepFoundData,
|
||||
} HormannBiSecurDecoderStep;
|
||||
|
||||
class FProtoSubGhzDHormannBiSecure : public FProtoSubGhzDBase {
|
||||
public:
|
||||
FProtoSubGhzDHormannBiSecure() {
|
||||
sensorType = FPS_HORMANN;
|
||||
te_short = 208;
|
||||
te_long = 416;
|
||||
te_delta = 104;
|
||||
min_count_bit_for_found = 176;
|
||||
}
|
||||
|
||||
void subghz_protocol_decoder_hormann_bisecur_reset() {
|
||||
parser_step = HormannBiSecurDecoderStepReset;
|
||||
data = 0;
|
||||
for (uint8_t i = 0; i < 22; ++i) dataa[i] = 0;
|
||||
data_count_bit = 0;
|
||||
manchester_saved_state = ManchesterStateStart1;
|
||||
}
|
||||
|
||||
void feed(bool level, uint32_t duration) {
|
||||
ManchesterEvent event = ManchesterEventReset;
|
||||
|
||||
switch (parser_step) {
|
||||
case HormannBiSecurDecoderStepReset:
|
||||
if (!level && DURATION_DIFF(duration, duration_short + duration_half_short) < te_delta) {
|
||||
parser_step = HormannBiSecurDecoderStepFoundPreambleAlternatingShort;
|
||||
}
|
||||
break;
|
||||
case HormannBiSecurDecoderStepFoundPreambleAlternatingShort:
|
||||
if (DURATION_DIFF(duration, duration_short) < te_delta) {
|
||||
// stay on the same step, the pattern repeats around 21 times
|
||||
break;
|
||||
}
|
||||
|
||||
if (level && DURATION_DIFF(duration, duration_long * 4) < te_delta) {
|
||||
parser_step = HormannBiSecurDecoderStepFoundPreambleHighVeryLong;
|
||||
break;
|
||||
}
|
||||
|
||||
parser_step = HormannBiSecurDecoderStepReset;
|
||||
break;
|
||||
case HormannBiSecurDecoderStepFoundPreambleHighVeryLong:
|
||||
if (!level && DURATION_DIFF(duration, duration_long) < te_delta) {
|
||||
sync_cnt = 3;
|
||||
parser_step = HormannBiSecurDecoderStepFoundPreambleAlternatingLong;
|
||||
break;
|
||||
}
|
||||
|
||||
parser_step = HormannBiSecurDecoderStepReset;
|
||||
break;
|
||||
case HormannBiSecurDecoderStepFoundPreambleAlternatingLong:
|
||||
if (level == (sync_cnt-- & 1) &&
|
||||
DURATION_DIFF(duration, duration_long) < te_delta) {
|
||||
if (!sync_cnt) {
|
||||
FProtoGeneral::manchester_advance_alt(manchester_saved_state, event, &manchester_saved_state, NULL);
|
||||
parser_step = HormannBiSecurDecoderStepFoundData;
|
||||
}
|
||||
|
||||
// stay on the same step, or advance to the next if enough transitions are found
|
||||
break;
|
||||
}
|
||||
|
||||
parser_step = HormannBiSecurDecoderStepReset;
|
||||
break;
|
||||
case HormannBiSecurDecoderStepFoundData:
|
||||
if (DURATION_DIFF(duration, duration_short) < te_delta ||
|
||||
(
|
||||
// the last bit can be arbitrary long, but it is parsed as a short
|
||||
data_count_bit == min_count_bit_for_found - 1 &&
|
||||
duration > duration_short)) {
|
||||
event = !level ? ManchesterEventShortHigh : ManchesterEventShortLow;
|
||||
}
|
||||
|
||||
if (DURATION_DIFF(duration, duration_long) < te_delta) {
|
||||
event = !level ? ManchesterEventLongHigh : ManchesterEventLongLow;
|
||||
}
|
||||
|
||||
if (event == ManchesterEventReset) {
|
||||
subghz_protocol_decoder_hormann_bisecur_reset();
|
||||
} else {
|
||||
bool new_level;
|
||||
|
||||
if (manchester_advance_alt(instance->manchester_saved_state, event, &instance->manchester_saved_state, &new_level)) {
|
||||
subghz_protocol_decoder_hormann_bisecur_add_bit(instance, new_level);
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void subghz_protocol_decoder_hormann_bisecur_add_bit(bool level) {
|
||||
if (data_count_bit >= min_count_bit_for_found) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (level) {
|
||||
uint8_t byte_index = data_count_bit / 8;
|
||||
uint8_t bit_index = data_count_bit % 8;
|
||||
dataa[byte_index] |= 1 << (7 - bit_index);
|
||||
}
|
||||
data_count_bit++;
|
||||
if (data_count_bit >= min_count_bit_for_found) {
|
||||
if (callback) {
|
||||
callback(this);
|
||||
} else {
|
||||
subghz_protocol_decoder_hormann_bisecur_reset();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protected:
|
||||
ManchesterState manchester_saved_state = ManchesterStateMid1;
|
||||
uint8_t dataa[22] = {0};
|
||||
uint8_t sync_cnt = 0;
|
||||
};
|
||||
|
||||
#endif
|
||||
@@ -46,12 +46,6 @@ class FProtoSubGhzDIdo : public FProtoSubGhzDBase {
|
||||
min_count_bit_for_found) {
|
||||
data = decode_data;
|
||||
data_count_bit = decode_count_bit;
|
||||
// controller
|
||||
uint64_t code_found_reverse = FProtoGeneral::subghz_protocol_blocks_reverse_key(data, data_count_bit);
|
||||
uint32_t code_fix = code_found_reverse & 0xFFFFFF;
|
||||
|
||||
serial = code_fix & 0xFFFFF;
|
||||
btn = (code_fix >> 20) & 0x0F;
|
||||
if (callback) callback(this);
|
||||
}
|
||||
decode_data = 0;
|
||||
|
||||
@@ -68,7 +68,6 @@ class FProtoSubGhzDIntertechnoV3 : public FProtoSubGhzDBase {
|
||||
(decode_count_bit == INTERTECHNO_V3_DIMMING_COUNT_BIT)) {
|
||||
data = decode_data;
|
||||
data_count_bit = decode_count_bit;
|
||||
remote_controller();
|
||||
if (callback) callback(this);
|
||||
}
|
||||
break;
|
||||
@@ -120,29 +119,6 @@ class FProtoSubGhzDIntertechnoV3 : public FProtoSubGhzDBase {
|
||||
}
|
||||
|
||||
protected:
|
||||
void remote_controller() {
|
||||
if (data_count_bit == min_count_bit_for_found) {
|
||||
serial = (data >> 6) & 0x3FFFFFF;
|
||||
if ((data >> 5) & 0x1) {
|
||||
cnt = 1 << 5;
|
||||
} else {
|
||||
cnt = (~data & 0xF);
|
||||
}
|
||||
btn = (data >> 4) & 0x1;
|
||||
} else if (data_count_bit == INTERTECHNO_V3_DIMMING_COUNT_BIT) {
|
||||
serial = (data >> 10) & 0x3FFFFFF;
|
||||
if ((data >> 9) & 0x1) {
|
||||
cnt = 1 << 5;
|
||||
} else {
|
||||
cnt = (~(data >> 4) & 0xF);
|
||||
}
|
||||
btn = data & 0xF;
|
||||
} else {
|
||||
serial = 0;
|
||||
cnt = 0;
|
||||
btn = 0;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
@@ -60,12 +60,6 @@ class FProtoSubGhzDKeeLoq : public FProtoSubGhzDBase {
|
||||
if (data != decode_data) {
|
||||
data = decode_data;
|
||||
data_count_bit = min_count_bit_for_found;
|
||||
// controller
|
||||
uint64_t key = FProtoGeneral::subghz_protocol_blocks_reverse_key(data, data_count_bit);
|
||||
uint32_t key_fix = key >> 32;
|
||||
// uint32_t key_hop = key & 0x00000000ffffffff; //unused
|
||||
serial = key_fix & 0x0FFFFFFF;
|
||||
btn = key_fix >> 28;
|
||||
if (callback) callback(this);
|
||||
}
|
||||
decode_data = 0;
|
||||
|
||||
@@ -61,13 +61,8 @@ class FProtoSubGhzDKinggatesStylo4K : public FProtoSubGhzDBase {
|
||||
if (decode_count_bit ==
|
||||
min_count_bit_for_found) {
|
||||
data = data_2;
|
||||
data_2 = decode_data;
|
||||
data_2 = decode_data; // TODO DATA2
|
||||
data_count_bit = decode_count_bit;
|
||||
// controller
|
||||
uint64_t fix = FProtoGeneral::subghz_protocol_blocks_reverse_key(data, 53);
|
||||
|
||||
btn = (fix >> 17) & 0x0F;
|
||||
serial = ((fix >> 5) & 0xFFFF0000) | (fix & 0xFFFF);
|
||||
if (callback) callback(this);
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,113 @@
|
||||
|
||||
#ifndef __FPROTO_LEGRAND_H__
|
||||
#define __FPROTO_LEGRAND_H__
|
||||
|
||||
#include "subghzdbase.hpp"
|
||||
|
||||
typedef enum {
|
||||
LegrandDecoderStepReset = 0,
|
||||
LegrandDecoderStepFirstBit,
|
||||
LegrandDecoderStepSaveDuration,
|
||||
LegrandDecoderStepCheckDuration,
|
||||
} LegrandDecoderStep;
|
||||
|
||||
class FProtoSubGhzDLegrand : public FProtoSubGhzDBase {
|
||||
public:
|
||||
FProtoSubGhzDLegrand() {
|
||||
sensorType = FPS_LEGRAND;
|
||||
te_short = 375;
|
||||
te_long = 1125;
|
||||
te_delta = 150;
|
||||
min_count_bit_for_found = 18;
|
||||
}
|
||||
|
||||
void feed(bool level, uint32_t duration) {
|
||||
switch (parser_step) {
|
||||
case LegrandDecoderStepReset:
|
||||
if (!level && DURATION_DIFF(duration, te_short * 16) < te_delta * 8) {
|
||||
parser_step = LegrandDecoderStepFirstBit;
|
||||
decode_data = 0;
|
||||
decode_count_bit = 0;
|
||||
te = 0;
|
||||
}
|
||||
break;
|
||||
case LegrandDecoderStepFirstBit:
|
||||
if (level) {
|
||||
if (DURATION_DIFF(duration, te_short) < te_delta) {
|
||||
subghz_protocol_blocks_add_bit(0);
|
||||
te += duration * 4; // long low that is part of sync, then short high
|
||||
}
|
||||
|
||||
if (DURATION_DIFF(duration, te_long) < te_delta * 3) {
|
||||
subghz_protocol_blocks_add_bit(1);
|
||||
te += duration / 3 * 4; // short low that is part of sync, then long high
|
||||
}
|
||||
|
||||
if (decode_count_bit > 0) {
|
||||
// advance to the next step if either short or long is found
|
||||
parser_step = LegrandDecoderStepSaveDuration;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
parser_step = LegrandDecoderStepReset;
|
||||
break;
|
||||
case LegrandDecoderStepSaveDuration:
|
||||
if (!level) {
|
||||
te_last = duration;
|
||||
te += duration;
|
||||
parser_step = LegrandDecoderStepCheckDuration;
|
||||
break;
|
||||
}
|
||||
|
||||
parser_step = LegrandDecoderStepReset;
|
||||
break;
|
||||
case LegrandDecoderStepCheckDuration:
|
||||
if (level) {
|
||||
uint8_t found = 0;
|
||||
|
||||
if (DURATION_DIFF(te_last, te_long) < te_delta * 3 && DURATION_DIFF(duration, te_short) < te_delta) {
|
||||
found = 1;
|
||||
subghz_protocol_blocks_add_bit(0);
|
||||
}
|
||||
|
||||
if (DURATION_DIFF(te_last, te_short) < te_delta && DURATION_DIFF(duration, te_long) < te_delta * 3) {
|
||||
found = 1;
|
||||
subghz_protocol_blocks_add_bit(1);
|
||||
}
|
||||
|
||||
if (found) {
|
||||
te += duration;
|
||||
|
||||
if (decode_count_bit <
|
||||
min_count_bit_for_found) {
|
||||
parser_step = LegrandDecoderStepSaveDuration;
|
||||
break;
|
||||
}
|
||||
|
||||
// enough bits for a packet found, save it only if there was a previous packet
|
||||
// with the same data
|
||||
if (data && (data != decode_data)) {
|
||||
te /= decode_count_bit * 4;
|
||||
|
||||
data = decode_data;
|
||||
data_count_bit = decode_count_bit;
|
||||
|
||||
if (callback) {
|
||||
callback(this);
|
||||
}
|
||||
}
|
||||
// fallthrough to reset, the next bit is expected to be a sync
|
||||
// it also takes care of resetting the decoder state
|
||||
}
|
||||
}
|
||||
parser_step = LegrandDecoderStepReset;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
protected:
|
||||
uint32_t te = 0;
|
||||
};
|
||||
|
||||
#endif
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user