mirror of
https://github.com/eried/portapack-mayhem.git
synced 2025-08-03 12:06:52 -04:00
Subghz decoder (#1646)
* Initial commit - wip
* Half part of the transition of baseband processor.
* More SGD
* WIP, Weather refactor, UI improv
* Rename
* Added 4msps, and fixes
* Fixes
* princeton working
* Renamed proc_weather, bc now multifunctional
* Proto: bett
* FPS_CAME = 4,
FPS_PRASTEL = 5,
FPS_AIRFORCE = 6,
* Came Atomo, fixes
* Separate weather and sgd, bc of baseband size limit
* Fix display
* Save space
* More protos
* Dooya proto added
* More protos
* add protos
* More protos
* Move weather to ext app
* nw
* Revert "Move weather to ext app"
This reverts commit 8a84aac2f5
.
* revert
* Fix merge
* Better naming
* More protos
* More protos
* Add protos
* Fix warning
* Add NeroRadio
* more protos
* more protos
* More protos
* Shrink a bit
* fixes
* More protos
* Nicer code
* Fix naming
* Fix format
* Remove unused
* Fix some protos, that needs a LOOOONG part with the same lo/high
* Modify key calculation
This commit is contained in:
parent
02810bf527
commit
2ccda5aebd
71 changed files with 4952 additions and 248 deletions
200
firmware/baseband/fprotos/fprotogeneral.hpp
Normal file
200
firmware/baseband/fprotos/fprotogeneral.hpp
Normal file
|
@ -0,0 +1,200 @@
|
|||
#ifndef __FPROTO_GENERAL_H__
|
||||
#define __FPROTO_GENERAL_H__
|
||||
|
||||
// useful methods for both weather and subghzd
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stddef.h>
|
||||
|
||||
#define bit_read(value, bit) (((value) >> (bit)) & 0x01)
|
||||
#define bit_set(value, bit) \
|
||||
({ \
|
||||
__typeof__(value) _one = (1); \
|
||||
(value) |= (_one << (bit)); \
|
||||
})
|
||||
#define bit_clear(value, bit) \
|
||||
({ \
|
||||
__typeof__(value) _one = (1); \
|
||||
(value) &= ~(_one << (bit)); \
|
||||
})
|
||||
#define bit_write(value, bit, bitvalue) (bitvalue ? bit_set(value, bit) : bit_clear(value, bit))
|
||||
|
||||
#define DURATION_DIFF(x, y) (((x) < (y)) ? ((y) - (x)) : ((x) - (y)))
|
||||
|
||||
typedef enum {
|
||||
ManchesterStateStart1 = 0,
|
||||
ManchesterStateMid1 = 1,
|
||||
ManchesterStateMid0 = 2,
|
||||
ManchesterStateStart0 = 3
|
||||
} ManchesterState;
|
||||
typedef enum {
|
||||
ManchesterEventShortLow = 0,
|
||||
ManchesterEventShortHigh = 2,
|
||||
ManchesterEventLongLow = 4,
|
||||
ManchesterEventLongHigh = 6,
|
||||
ManchesterEventReset = 8
|
||||
} ManchesterEvent;
|
||||
|
||||
class FProtoGeneral {
|
||||
public:
|
||||
static bool manchester_advance(
|
||||
ManchesterState state,
|
||||
ManchesterEvent event,
|
||||
ManchesterState* next_state,
|
||||
bool* data) {
|
||||
bool result = false;
|
||||
ManchesterState new_state;
|
||||
|
||||
if (event == ManchesterEventReset) {
|
||||
new_state = ManchesterStateMid1;
|
||||
} else {
|
||||
new_state = (ManchesterState)(transitions[state] >> event & 0x3);
|
||||
if (new_state == state) {
|
||||
new_state = ManchesterStateMid1;
|
||||
} else {
|
||||
if (new_state == ManchesterStateMid0) {
|
||||
if (data) *data = false;
|
||||
result = true;
|
||||
} else if (new_state == ManchesterStateMid1) {
|
||||
if (data) *data = true;
|
||||
result = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
*next_state = new_state;
|
||||
return result;
|
||||
}
|
||||
static uint8_t subghz_protocol_blocks_get_parity(uint64_t key, uint8_t bit_count) {
|
||||
uint8_t parity = 0;
|
||||
for (uint8_t i = 0; i < bit_count; i++) {
|
||||
parity += bit_read(key, i);
|
||||
}
|
||||
return parity & 0x01;
|
||||
}
|
||||
|
||||
static uint8_t subghz_protocol_blocks_add_bytes(uint8_t const message[], size_t size) {
|
||||
uint32_t result = 0;
|
||||
for (size_t i = 0; i < size; ++i) {
|
||||
result += message[i];
|
||||
}
|
||||
return (uint8_t)result;
|
||||
}
|
||||
|
||||
static uint8_t subghz_protocol_blocks_parity8(uint8_t byte) {
|
||||
byte ^= byte >> 4;
|
||||
byte &= 0xf;
|
||||
return (0x6996 >> byte) & 1;
|
||||
}
|
||||
|
||||
static uint8_t subghz_protocol_blocks_parity_bytes(uint8_t const message[], size_t size) {
|
||||
uint8_t result = 0;
|
||||
for (size_t i = 0; i < size; ++i) {
|
||||
result ^= subghz_protocol_blocks_parity8(message[i]);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
static uint8_t subghz_protocol_blocks_lfsr_digest8(
|
||||
uint8_t const message[],
|
||||
size_t size,
|
||||
uint8_t gen,
|
||||
uint8_t key) {
|
||||
uint8_t sum = 0;
|
||||
for (size_t byte = 0; byte < size; ++byte) {
|
||||
uint8_t data = message[byte];
|
||||
for (int i = 7; i >= 0; --i) {
|
||||
// XOR key into sum if data bit is set
|
||||
if ((data >> i) & 1) sum ^= key;
|
||||
// roll the key right (actually the LSB is dropped here)
|
||||
// and apply the gen (needs to include the dropped LSB as MSB)
|
||||
if (key & 1)
|
||||
key = (key >> 1) ^ gen;
|
||||
else
|
||||
key = (key >> 1);
|
||||
}
|
||||
}
|
||||
return sum;
|
||||
}
|
||||
static float locale_fahrenheit_to_celsius(float temp_f) {
|
||||
return (temp_f - 32.f) / 1.8f;
|
||||
}
|
||||
|
||||
static uint8_t subghz_protocol_blocks_crc4(
|
||||
uint8_t const message[],
|
||||
size_t size,
|
||||
uint8_t polynomial,
|
||||
uint8_t init) {
|
||||
uint8_t remainder = init << 4; // LSBs are unused
|
||||
uint8_t poly = polynomial << 4;
|
||||
uint8_t bit;
|
||||
|
||||
while (size--) {
|
||||
remainder ^= *message++;
|
||||
for (bit = 0; bit < 8; bit++) {
|
||||
if (remainder & 0x80) {
|
||||
remainder = (remainder << 1) ^ poly;
|
||||
} else {
|
||||
remainder = (remainder << 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
return remainder >> 4 & 0x0f; // discard the LSBs
|
||||
}
|
||||
static uint8_t subghz_protocol_blocks_lfsr_digest8_reflect(
|
||||
uint8_t const message[],
|
||||
size_t size,
|
||||
uint8_t gen,
|
||||
uint8_t key) {
|
||||
uint8_t sum = 0;
|
||||
// Process message from last byte to first byte (reflected)
|
||||
for (int byte = size - 1; byte >= 0; --byte) {
|
||||
uint8_t data = message[byte];
|
||||
// Process individual bits of each byte (reflected)
|
||||
for (uint8_t i = 0; i < 8; ++i) {
|
||||
// XOR key into sum if data bit is set
|
||||
if ((data >> i) & 1) {
|
||||
sum ^= key;
|
||||
}
|
||||
// roll the key left (actually the LSB is dropped here)
|
||||
// and apply the gen (needs to include the dropped lsb as MSB)
|
||||
if (key & 0x80)
|
||||
key = (key << 1) ^ gen;
|
||||
else
|
||||
key = (key << 1);
|
||||
}
|
||||
}
|
||||
return sum;
|
||||
}
|
||||
static uint64_t subghz_protocol_blocks_reverse_key(uint64_t key, uint8_t bit_count) {
|
||||
uint64_t reverse_key = 0;
|
||||
for (uint8_t i = 0; i < bit_count; i++) {
|
||||
reverse_key = reverse_key << 1 | bit_read(key, i);
|
||||
}
|
||||
return reverse_key;
|
||||
}
|
||||
static uint8_t subghz_protocol_blocks_crc8(
|
||||
uint8_t const message[],
|
||||
size_t size,
|
||||
uint8_t polynomial,
|
||||
uint8_t init) {
|
||||
uint8_t remainder = init;
|
||||
|
||||
for (size_t byte = 0; byte < size; ++byte) {
|
||||
remainder ^= message[byte];
|
||||
for (uint8_t bit = 0; bit < 8; ++bit) {
|
||||
if (remainder & 0x80) {
|
||||
remainder = (remainder << 1) ^ polynomial;
|
||||
} else {
|
||||
remainder = (remainder << 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
return remainder;
|
||||
}
|
||||
|
||||
private:
|
||||
static inline const uint8_t transitions[] = {0b00000001, 0b10010001, 0b10011011, 0b11111011};
|
||||
};
|
||||
|
||||
#endif
|
16
firmware/baseband/fprotos/fprotolistgeneral.hpp
Normal file
16
firmware/baseband/fprotos/fprotolistgeneral.hpp
Normal file
|
@ -0,0 +1,16 @@
|
|||
#ifndef __FPROTO_PROTOLISTGENERAL_H__
|
||||
#define __FPROTO_PROTOLISTGENERAL_H__
|
||||
#include <stdint.h>
|
||||
|
||||
class FProtoListGeneral {
|
||||
public:
|
||||
FProtoListGeneral() {}
|
||||
virtual ~FProtoListGeneral() {}
|
||||
virtual void feed(bool level, uint32_t duration) = 0;
|
||||
void setModulation(uint8_t modulation) { modulation_ = modulation; }
|
||||
|
||||
protected:
|
||||
uint8_t modulation_ = 0;
|
||||
};
|
||||
|
||||
#endif
|
83
firmware/baseband/fprotos/s-bett.hpp
Normal file
83
firmware/baseband/fprotos/s-bett.hpp
Normal file
|
@ -0,0 +1,83 @@
|
|||
|
||||
#ifndef __FPROTO_BETT_H__
|
||||
#define __FPROTO_BETT_H__
|
||||
|
||||
#include "subghzdbase.hpp"
|
||||
|
||||
typedef enum : uint8_t {
|
||||
BETTDecoderStepReset = 0,
|
||||
BETTDecoderStepSaveDuration,
|
||||
BETTDecoderStepCheckDuration,
|
||||
} BETTDecoderStep;
|
||||
|
||||
class FProtoSubGhzDBett : public FProtoSubGhzDBase {
|
||||
public:
|
||||
FProtoSubGhzDBett() {
|
||||
sensorType = FPS_BETT;
|
||||
te_short = 340;
|
||||
te_long = 2000;
|
||||
te_delta = 150;
|
||||
min_count_bit_for_found = 18;
|
||||
}
|
||||
|
||||
void feed(bool level, uint32_t duration) {
|
||||
switch (parser_step) {
|
||||
case BETTDecoderStepReset:
|
||||
if ((!level) && (DURATION_DIFF(duration, te_short * 44) <
|
||||
(te_delta * 15))) {
|
||||
decode_data = 0;
|
||||
decode_count_bit = 0;
|
||||
parser_step = BETTDecoderStepCheckDuration;
|
||||
}
|
||||
break;
|
||||
case BETTDecoderStepSaveDuration:
|
||||
if (!level) {
|
||||
if (DURATION_DIFF(duration, te_short * 44) <
|
||||
(te_delta * 15)) {
|
||||
if (decode_count_bit ==
|
||||
min_count_bit_for_found) {
|
||||
data = decode_data;
|
||||
data_count_bit = decode_count_bit;
|
||||
// dip decoder needed
|
||||
if (callback) callback(this);
|
||||
} else {
|
||||
parser_step = BETTDecoderStepReset;
|
||||
}
|
||||
decode_data = 0;
|
||||
decode_count_bit = 0;
|
||||
break;
|
||||
} else {
|
||||
if ((DURATION_DIFF(duration, te_short) <
|
||||
te_delta) ||
|
||||
(DURATION_DIFF(duration, te_long) <
|
||||
te_delta * 3)) {
|
||||
parser_step = BETTDecoderStepCheckDuration;
|
||||
} else {
|
||||
parser_step = BETTDecoderStepReset;
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
case BETTDecoderStepCheckDuration:
|
||||
if (level) {
|
||||
if (DURATION_DIFF(duration, te_long) <
|
||||
te_delta * 3) {
|
||||
subghz_protocol_blocks_add_bit(1);
|
||||
parser_step = BETTDecoderStepSaveDuration;
|
||||
} else if (
|
||||
DURATION_DIFF(duration, te_short) <
|
||||
te_delta) {
|
||||
subghz_protocol_blocks_add_bit(0);
|
||||
parser_step = BETTDecoderStepSaveDuration;
|
||||
} else {
|
||||
parser_step = BETTDecoderStepReset;
|
||||
}
|
||||
} else {
|
||||
parser_step = BETTDecoderStepReset;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
#endif
|
95
firmware/baseband/fprotos/s-came.hpp
Normal file
95
firmware/baseband/fprotos/s-came.hpp
Normal file
|
@ -0,0 +1,95 @@
|
|||
|
||||
#ifndef __FPROTO_CAME_H__
|
||||
#define __FPROTO_CAME_H__
|
||||
|
||||
#include "subghzdbase.hpp"
|
||||
|
||||
#define CAME_12_COUNT_BIT 12
|
||||
#define CAME_24_COUNT_BIT 24
|
||||
#define PRASTEL_COUNT_BIT 25
|
||||
#define AIRFORCE_COUNT_BIT 18
|
||||
|
||||
typedef enum : uint8_t {
|
||||
CameDecoderStepReset = 0,
|
||||
CameDecoderStepFoundStartBit,
|
||||
CameDecoderStepSaveDuration,
|
||||
CameDecoderStepCheckDuration,
|
||||
} CameDecoderStep;
|
||||
|
||||
class FProtoSubGhzDCame : public FProtoSubGhzDBase {
|
||||
public:
|
||||
FProtoSubGhzDCame() {
|
||||
sensorType = FPS_CAME;
|
||||
te_short = 320;
|
||||
te_long = 640;
|
||||
te_delta = 150;
|
||||
min_count_bit_for_found = 12;
|
||||
}
|
||||
|
||||
void feed(bool level, uint32_t duration) {
|
||||
switch (parser_step) {
|
||||
case CameDecoderStepReset:
|
||||
if ((!level) && (DURATION_DIFF(duration, te_short * 56) < te_delta * 47)) {
|
||||
// Found header CAME
|
||||
parser_step = CameDecoderStepFoundStartBit;
|
||||
}
|
||||
break;
|
||||
case CameDecoderStepFoundStartBit:
|
||||
if (!level) {
|
||||
break;
|
||||
} else if (
|
||||
DURATION_DIFF(duration, te_short) < te_delta) {
|
||||
// Found start bit CAME
|
||||
parser_step = CameDecoderStepSaveDuration;
|
||||
decode_data = 0;
|
||||
decode_count_bit = 0;
|
||||
} else {
|
||||
parser_step = CameDecoderStepReset;
|
||||
}
|
||||
break;
|
||||
case CameDecoderStepSaveDuration:
|
||||
if (!level) { // save interval
|
||||
if (duration >= (te_short * 4)) {
|
||||
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
|
||||
sensorType = FPS_CAME;
|
||||
if (decode_count_bit == PRASTEL_COUNT_BIT) sensorType = FPS_PRASTEL;
|
||||
if (decode_count_bit == AIRFORCE_COUNT_BIT) sensorType = FPS_AIRFORCE;
|
||||
if (callback) callback(this);
|
||||
}
|
||||
break;
|
||||
}
|
||||
te_last = duration;
|
||||
parser_step = CameDecoderStepCheckDuration;
|
||||
} else {
|
||||
parser_step = CameDecoderStepReset;
|
||||
}
|
||||
break;
|
||||
case CameDecoderStepCheckDuration:
|
||||
if (level) {
|
||||
if ((DURATION_DIFF(te_last, te_short) < te_delta) &&
|
||||
(DURATION_DIFF(duration, te_long) < te_delta)) {
|
||||
subghz_protocol_blocks_add_bit(0);
|
||||
parser_step = CameDecoderStepSaveDuration;
|
||||
} else if (
|
||||
(DURATION_DIFF(te_last, te_long) < te_delta) &&
|
||||
(DURATION_DIFF(duration, te_short) < te_delta)) {
|
||||
subghz_protocol_blocks_add_bit(1);
|
||||
parser_step = CameDecoderStepSaveDuration;
|
||||
} else
|
||||
parser_step = CameDecoderStepReset;
|
||||
} else {
|
||||
parser_step = CameDecoderStepReset;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
#endif
|
133
firmware/baseband/fprotos/s-came_atomo.hpp
Normal file
133
firmware/baseband/fprotos/s-came_atomo.hpp
Normal file
|
@ -0,0 +1,133 @@
|
|||
|
||||
#ifndef __FPROTO_CAMEATOMO_H__
|
||||
#define __FPROTO_CAMEATOMO_H__
|
||||
|
||||
#include "subghzdbase.hpp"
|
||||
|
||||
typedef enum : uint8_t {
|
||||
CameAtomoDecoderStepReset = 0,
|
||||
CameAtomoDecoderStepDecoderData,
|
||||
} CameAtomoDecoderStep;
|
||||
|
||||
class FProtoSubGhzDCameAtomo : public FProtoSubGhzDBase {
|
||||
public:
|
||||
FProtoSubGhzDCameAtomo() {
|
||||
sensorType = FPS_CAMEATOMO;
|
||||
te_short = 600;
|
||||
te_long = 1200;
|
||||
te_delta = 250;
|
||||
min_count_bit_for_found = 62;
|
||||
}
|
||||
|
||||
void feed(bool level, uint32_t duration) {
|
||||
ManchesterEvent event = ManchesterEventReset;
|
||||
switch (parser_step) {
|
||||
case CameAtomoDecoderStepReset:
|
||||
if ((!level) && (DURATION_DIFF(duration, te_long * 60) < te_delta * 40)) {
|
||||
// Found header CAME
|
||||
parser_step = CameAtomoDecoderStepDecoderData;
|
||||
decode_data = 0;
|
||||
decode_count_bit = 1;
|
||||
FProtoGeneral::manchester_advance(manchester_saved_state, ManchesterEventReset, &manchester_saved_state, NULL);
|
||||
FProtoGeneral::manchester_advance(manchester_saved_state, ManchesterEventShortLow, &manchester_saved_state, NULL);
|
||||
}
|
||||
break;
|
||||
case CameAtomoDecoderStepDecoderData:
|
||||
if (!level) {
|
||||
if (DURATION_DIFF(duration, te_short) < te_delta) {
|
||||
event = ManchesterEventShortLow;
|
||||
} else if (
|
||||
DURATION_DIFF(duration, te_long) < te_delta) {
|
||||
event = ManchesterEventLongLow;
|
||||
} else if (
|
||||
duration >= ((uint32_t)te_long * 2 + te_delta)) {
|
||||
if (decode_count_bit ==
|
||||
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;
|
||||
decode_count_bit = 1;
|
||||
FProtoGeneral::manchester_advance(manchester_saved_state, ManchesterEventReset, &manchester_saved_state, NULL);
|
||||
FProtoGeneral::manchester_advance(manchester_saved_state, ManchesterEventShortLow, &manchester_saved_state, NULL);
|
||||
} else {
|
||||
parser_step = CameAtomoDecoderStepReset;
|
||||
}
|
||||
} else {
|
||||
if (DURATION_DIFF(duration, te_short) < te_delta) {
|
||||
event = ManchesterEventShortHigh;
|
||||
} else if (
|
||||
DURATION_DIFF(duration, te_long) < te_delta) {
|
||||
event = ManchesterEventLongHigh;
|
||||
} else {
|
||||
parser_step = CameAtomoDecoderStepReset;
|
||||
}
|
||||
}
|
||||
if (event != ManchesterEventReset) {
|
||||
bool bit;
|
||||
bool data_ok = FProtoGeneral::manchester_advance(manchester_saved_state, event, &manchester_saved_state, &bit);
|
||||
|
||||
if (data_ok) {
|
||||
decode_data = (decode_data << 1) | !bit;
|
||||
decode_count_bit++;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
protected:
|
||||
ManchesterState manchester_saved_state = ManchesterStateMid1;
|
||||
|
||||
void atomo_decrypt(uint8_t* buff) {
|
||||
buff[0] = (buff[0] ^ 5) & 0x7F;
|
||||
uint8_t tmpB = (-buff[0]) & 0x7F;
|
||||
|
||||
uint8_t bitCnt = 8;
|
||||
while (bitCnt < 59) {
|
||||
if ((tmpB & 0x18) && (((tmpB / 8) & 3) != 3)) {
|
||||
tmpB = ((tmpB << 1) & 0xFF) | 1;
|
||||
} else {
|
||||
tmpB = (tmpB << 1) & 0xFF;
|
||||
}
|
||||
|
||||
if (tmpB & 0x80) {
|
||||
buff[bitCnt / 8] ^= (0x80 >> (bitCnt & 7));
|
||||
}
|
||||
bitCnt++;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
#endif
|
147
firmware/baseband/fprotos/s-came_twee.hpp
Normal file
147
firmware/baseband/fprotos/s-came_twee.hpp
Normal file
|
@ -0,0 +1,147 @@
|
|||
|
||||
#ifndef __FPROTO_CAMETWEE_H__
|
||||
#define __FPROTO_CAMETWEE_H__
|
||||
|
||||
#include "subghzdbase.hpp"
|
||||
|
||||
typedef enum : uint8_t {
|
||||
CameTweeDecoderStepReset = 0,
|
||||
CameTweeDecoderStepDecoderData,
|
||||
} CameTweeDecoderStep;
|
||||
|
||||
class FProtoSubGhzDCameTwee : public FProtoSubGhzDBase {
|
||||
public:
|
||||
FProtoSubGhzDCameTwee() {
|
||||
sensorType = FPS_CAMETWEE;
|
||||
te_short = 500;
|
||||
te_long = 1000;
|
||||
te_delta = 250;
|
||||
min_count_bit_for_found = 54;
|
||||
}
|
||||
|
||||
void feed(bool level, uint32_t duration) {
|
||||
ManchesterEvent event = ManchesterEventReset;
|
||||
switch (parser_step) {
|
||||
case CameTweeDecoderStepReset:
|
||||
if ((!level) && (DURATION_DIFF(duration, te_long * 51) < te_delta * 20)) {
|
||||
// Found header CAME
|
||||
parser_step = CameTweeDecoderStepDecoderData;
|
||||
decode_data = 0;
|
||||
decode_count_bit = 0;
|
||||
FProtoGeneral::manchester_advance(manchester_saved_state, ManchesterEventLongLow, &manchester_saved_state, NULL);
|
||||
FProtoGeneral::manchester_advance(manchester_saved_state, ManchesterEventLongHigh, &manchester_saved_state, NULL);
|
||||
FProtoGeneral::manchester_advance(manchester_saved_state, ManchesterEventShortLow, &manchester_saved_state, NULL);
|
||||
}
|
||||
break;
|
||||
case CameTweeDecoderStepDecoderData:
|
||||
if (!level) {
|
||||
if (DURATION_DIFF(duration, te_short) < te_delta) {
|
||||
event = ManchesterEventShortLow;
|
||||
} else if (
|
||||
DURATION_DIFF(duration, te_long) < te_delta) {
|
||||
event = ManchesterEventLongLow;
|
||||
} else if (
|
||||
duration >= ((uint32_t)te_long * 2 + te_delta)) {
|
||||
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;
|
||||
decode_count_bit = 0;
|
||||
FProtoGeneral::manchester_advance(manchester_saved_state, ManchesterEventLongLow, &manchester_saved_state, NULL);
|
||||
FProtoGeneral::manchester_advance(manchester_saved_state, ManchesterEventLongHigh, &manchester_saved_state, NULL);
|
||||
FProtoGeneral::manchester_advance(manchester_saved_state, ManchesterEventShortLow, &manchester_saved_state, NULL);
|
||||
} else {
|
||||
parser_step = CameTweeDecoderStepReset;
|
||||
}
|
||||
} else {
|
||||
if (DURATION_DIFF(duration, te_short) < te_delta) {
|
||||
event = ManchesterEventShortHigh;
|
||||
} else if (
|
||||
DURATION_DIFF(duration, te_long) < te_delta) {
|
||||
event = ManchesterEventLongHigh;
|
||||
} else {
|
||||
parser_step = CameTweeDecoderStepReset;
|
||||
}
|
||||
}
|
||||
if (event != ManchesterEventReset) {
|
||||
bool bit;
|
||||
if (FProtoGeneral::manchester_advance(manchester_saved_state, event, &manchester_saved_state, &bit)) {
|
||||
decode_data = (decode_data << 1) | !bit;
|
||||
decode_count_bit++;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
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
|
151
firmware/baseband/fprotos/s-chambcode.hpp
Normal file
151
firmware/baseband/fprotos/s-chambcode.hpp
Normal file
|
@ -0,0 +1,151 @@
|
|||
|
||||
#ifndef __FPROTO_CHAMBCODE_H__
|
||||
#define __FPROTO_CHAMBCODE_H__
|
||||
|
||||
#include "subghzdbase.hpp"
|
||||
|
||||
#define CHAMBERLAIN_CODE_BIT_STOP 0b0001
|
||||
#define CHAMBERLAIN_CODE_BIT_1 0b0011
|
||||
#define CHAMBERLAIN_CODE_BIT_0 0b0111
|
||||
|
||||
#define CHAMBERLAIN_7_CODE_MASK 0xF000000FF0F
|
||||
#define CHAMBERLAIN_8_CODE_MASK 0xF00000F00F
|
||||
#define CHAMBERLAIN_9_CODE_MASK 0xF000000000F
|
||||
|
||||
#define CHAMBERLAIN_7_CODE_MASK_CHECK 0x10000001101
|
||||
#define CHAMBERLAIN_8_CODE_MASK_CHECK 0x1000001001
|
||||
#define CHAMBERLAIN_9_CODE_MASK_CHECK 0x10000000001
|
||||
|
||||
typedef enum : uint8_t {
|
||||
Chamb_CodeDecoderStepReset = 0,
|
||||
Chamb_CodeDecoderStepFoundStartBit,
|
||||
Chamb_CodeDecoderStepSaveDuration,
|
||||
Chamb_CodeDecoderStepCheckDuration,
|
||||
} Chamb_CodeDecoderStep;
|
||||
|
||||
class FProtoSubGhzDChambCode : public FProtoSubGhzDBase {
|
||||
public:
|
||||
FProtoSubGhzDChambCode() {
|
||||
sensorType = FPS_CHAMBCODE;
|
||||
te_short = 1000;
|
||||
te_long = 3000;
|
||||
te_delta = 200;
|
||||
min_count_bit_for_found = 10;
|
||||
}
|
||||
|
||||
void feed(bool level, uint32_t duration) {
|
||||
switch (parser_step) {
|
||||
case Chamb_CodeDecoderStepReset:
|
||||
if ((!level) && (DURATION_DIFF(duration, te_short * 39) < te_delta * 20)) {
|
||||
// Found header Chamb_Code
|
||||
parser_step = Chamb_CodeDecoderStepFoundStartBit;
|
||||
}
|
||||
break;
|
||||
case Chamb_CodeDecoderStepFoundStartBit:
|
||||
if ((level) && (DURATION_DIFF(duration, te_short) < te_delta)) {
|
||||
// Found start bit Chamb_Code
|
||||
decode_data = 0;
|
||||
decode_count_bit = 0;
|
||||
decode_data = decode_data << 4 | CHAMBERLAIN_CODE_BIT_STOP;
|
||||
decode_count_bit++;
|
||||
parser_step = Chamb_CodeDecoderStepSaveDuration;
|
||||
} else {
|
||||
parser_step = Chamb_CodeDecoderStepReset;
|
||||
}
|
||||
break;
|
||||
case Chamb_CodeDecoderStepSaveDuration:
|
||||
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;
|
||||
if (callback) callback(this);
|
||||
}
|
||||
}
|
||||
parser_step = Chamb_CodeDecoderStepReset;
|
||||
} else {
|
||||
te_last = duration;
|
||||
parser_step = Chamb_CodeDecoderStepCheckDuration;
|
||||
}
|
||||
} else {
|
||||
parser_step = Chamb_CodeDecoderStepReset;
|
||||
}
|
||||
break;
|
||||
case Chamb_CodeDecoderStepCheckDuration:
|
||||
if (level) { // Found stop bit Chamb_Code
|
||||
if ((DURATION_DIFF(te_last, te_short * 3) <
|
||||
te_delta) &&
|
||||
(DURATION_DIFF(duration, te_short) < te_delta)) {
|
||||
decode_data = decode_data << 4 | CHAMBERLAIN_CODE_BIT_STOP;
|
||||
decode_count_bit++;
|
||||
parser_step = Chamb_CodeDecoderStepSaveDuration;
|
||||
} else if (
|
||||
(DURATION_DIFF(te_last, te_short * 2) < te_delta) &&
|
||||
(DURATION_DIFF(duration, te_short * 2) < te_delta)) {
|
||||
decode_data = decode_data << 4 | CHAMBERLAIN_CODE_BIT_1;
|
||||
decode_count_bit++;
|
||||
parser_step = Chamb_CodeDecoderStepSaveDuration;
|
||||
} else if (
|
||||
(DURATION_DIFF(te_last, te_short) < te_delta) &&
|
||||
(DURATION_DIFF(duration, te_short * 3) < te_delta)) {
|
||||
decode_data = decode_data << 4 | CHAMBERLAIN_CODE_BIT_0;
|
||||
decode_count_bit++;
|
||||
parser_step = Chamb_CodeDecoderStepSaveDuration;
|
||||
} else {
|
||||
parser_step = Chamb_CodeDecoderStepReset;
|
||||
}
|
||||
|
||||
} else {
|
||||
parser_step = Chamb_CodeDecoderStepReset;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
protected:
|
||||
bool subghz_protocol_decoder_chamb_code_check_mask_and_parse() {
|
||||
if (decode_count_bit > min_count_bit_for_found + 1)
|
||||
return false;
|
||||
|
||||
if ((decode_data & CHAMBERLAIN_7_CODE_MASK) == CHAMBERLAIN_7_CODE_MASK_CHECK) {
|
||||
decode_count_bit = 7;
|
||||
decode_data &= ~CHAMBERLAIN_7_CODE_MASK;
|
||||
decode_data = (decode_data >> 12) | ((decode_data >> 4) & 0xF);
|
||||
} else if (
|
||||
(decode_data & CHAMBERLAIN_8_CODE_MASK) == CHAMBERLAIN_8_CODE_MASK_CHECK) {
|
||||
decode_count_bit = 8;
|
||||
decode_data &= ~CHAMBERLAIN_8_CODE_MASK;
|
||||
decode_data = decode_data >> 4 | CHAMBERLAIN_CODE_BIT_0 << 8; // DIP 6 no use
|
||||
} else if (
|
||||
(decode_data & CHAMBERLAIN_9_CODE_MASK) == CHAMBERLAIN_9_CODE_MASK_CHECK) {
|
||||
decode_count_bit = 9;
|
||||
decode_data &= ~CHAMBERLAIN_9_CODE_MASK;
|
||||
decode_data >>= 4;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
return subghz_protocol_chamb_code_to_bit(&decode_data, decode_count_bit);
|
||||
}
|
||||
|
||||
bool subghz_protocol_chamb_code_to_bit(uint64_t* data, uint8_t size) {
|
||||
uint64_t data_tmp = data[0];
|
||||
uint64_t data_res = 0;
|
||||
for (uint8_t i = 0; i < size; i++) {
|
||||
if ((data_tmp & 0xFll) == CHAMBERLAIN_CODE_BIT_0) {
|
||||
bit_write(data_res, i, 0);
|
||||
} else if ((data_tmp & 0xFll) == CHAMBERLAIN_CODE_BIT_1) {
|
||||
bit_write(data_res, i, 1);
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
data_tmp >>= 4;
|
||||
}
|
||||
data[0] = data_res;
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
#endif
|
89
firmware/baseband/fprotos/s-clemsa.hpp
Normal file
89
firmware/baseband/fprotos/s-clemsa.hpp
Normal file
|
@ -0,0 +1,89 @@
|
|||
|
||||
#ifndef __FPROTO_CLEMSA_H__
|
||||
#define __FPROTO_CLEMSA_H__
|
||||
|
||||
#include "subghzdbase.hpp"
|
||||
|
||||
typedef enum : uint8_t {
|
||||
ClemsaDecoderStepReset = 0,
|
||||
ClemsaDecoderStepSaveDuration,
|
||||
ClemsaDecoderStepCheckDuration,
|
||||
} ClemsaDecoderStep;
|
||||
|
||||
class FProtoSubGhzDClemsa : public FProtoSubGhzDBase {
|
||||
public:
|
||||
FProtoSubGhzDClemsa() {
|
||||
sensorType = FPS_CLEMSA;
|
||||
te_short = 385;
|
||||
te_long = 2695;
|
||||
te_delta = 150;
|
||||
min_count_bit_for_found = 18;
|
||||
}
|
||||
|
||||
void feed(bool level, uint32_t duration) {
|
||||
switch (parser_step) {
|
||||
case ClemsaDecoderStepReset:
|
||||
if ((!level) && (DURATION_DIFF(duration, te_short * 51) < te_delta * 25)) {
|
||||
parser_step = ClemsaDecoderStepSaveDuration;
|
||||
decode_data = 0;
|
||||
decode_count_bit = 0;
|
||||
}
|
||||
break;
|
||||
|
||||
case ClemsaDecoderStepSaveDuration:
|
||||
if (level) {
|
||||
te_last = duration;
|
||||
parser_step = ClemsaDecoderStepCheckDuration;
|
||||
} else {
|
||||
parser_step = ClemsaDecoderStepReset;
|
||||
}
|
||||
break;
|
||||
|
||||
case ClemsaDecoderStepCheckDuration:
|
||||
if (!level) {
|
||||
if ((DURATION_DIFF(te_last, te_short) < te_delta) &&
|
||||
(DURATION_DIFF(duration, te_long) < te_delta * 3)) {
|
||||
subghz_protocol_blocks_add_bit(0);
|
||||
parser_step = ClemsaDecoderStepSaveDuration;
|
||||
} else if (
|
||||
(DURATION_DIFF(te_last, te_long) < te_delta * 3) &&
|
||||
(DURATION_DIFF(duration, te_short) < te_delta)) {
|
||||
subghz_protocol_blocks_add_bit(1);
|
||||
parser_step = ClemsaDecoderStepSaveDuration;
|
||||
} else if (
|
||||
DURATION_DIFF(duration, te_short * 51) < te_delta * 25) {
|
||||
if ((DURATION_DIFF(te_last, te_short) < te_delta)) {
|
||||
subghz_protocol_blocks_add_bit(0);
|
||||
} else if ((DURATION_DIFF(te_last, te_long) < te_delta * 3)) {
|
||||
subghz_protocol_blocks_add_bit(1);
|
||||
} else {
|
||||
parser_step = ClemsaDecoderStepReset;
|
||||
}
|
||||
|
||||
if (decode_count_bit ==
|
||||
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;
|
||||
decode_data = 0;
|
||||
decode_count_bit = 0;
|
||||
|
||||
} else {
|
||||
parser_step = ClemsaDecoderStepReset;
|
||||
}
|
||||
} else {
|
||||
parser_step = ClemsaDecoderStepReset;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
#endif
|
86
firmware/baseband/fprotos/s-doitrand.hpp
Normal file
86
firmware/baseband/fprotos/s-doitrand.hpp
Normal file
|
@ -0,0 +1,86 @@
|
|||
|
||||
#ifndef __FPROTO_DOITRAND_H__
|
||||
#define __FPROTO_DOITRAND_H__
|
||||
|
||||
#include "subghzdbase.hpp"
|
||||
|
||||
typedef enum : uint8_t {
|
||||
DoitrandDecoderStepReset = 0,
|
||||
DoitrandDecoderStepFoundStartBit,
|
||||
DoitrandDecoderStepSaveDuration,
|
||||
DoitrandDecoderStepCheckDuration,
|
||||
} DoitrandDecoderStep;
|
||||
|
||||
class FProtoSubGhzDDoitrand : public FProtoSubGhzDBase {
|
||||
public:
|
||||
FProtoSubGhzDDoitrand() {
|
||||
sensorType = FPS_DOITRAND;
|
||||
te_short = 400;
|
||||
te_long = 1100;
|
||||
te_delta = 150;
|
||||
min_count_bit_for_found = 37;
|
||||
}
|
||||
|
||||
void feed(bool level, uint32_t duration) {
|
||||
switch (parser_step) {
|
||||
case DoitrandDecoderStepReset:
|
||||
if ((!level) && (DURATION_DIFF(duration, te_short * 62) < te_delta * 30)) {
|
||||
// Found Preambula
|
||||
parser_step = DoitrandDecoderStepFoundStartBit;
|
||||
}
|
||||
break;
|
||||
case DoitrandDecoderStepFoundStartBit:
|
||||
if (level && ((DURATION_DIFF(duration, (te_short * 2)) < te_delta * 3))) {
|
||||
// Found start bit
|
||||
parser_step = DoitrandDecoderStepSaveDuration;
|
||||
decode_data = 0;
|
||||
decode_count_bit = 0;
|
||||
} else {
|
||||
parser_step = DoitrandDecoderStepReset;
|
||||
}
|
||||
break;
|
||||
case DoitrandDecoderStepSaveDuration:
|
||||
if (!level) {
|
||||
if (duration >= ((uint32_t)te_short * 10 + te_delta)) {
|
||||
parser_step = DoitrandDecoderStepFoundStartBit;
|
||||
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;
|
||||
decode_count_bit = 0;
|
||||
break;
|
||||
} else {
|
||||
te_last = duration;
|
||||
parser_step = DoitrandDecoderStepCheckDuration;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case DoitrandDecoderStepCheckDuration:
|
||||
if (level) {
|
||||
if ((DURATION_DIFF(te_last, te_short) < te_delta) &&
|
||||
(DURATION_DIFF(duration, te_long) < te_delta * 3)) {
|
||||
subghz_protocol_blocks_add_bit(0);
|
||||
parser_step = DoitrandDecoderStepSaveDuration;
|
||||
} else if (
|
||||
(DURATION_DIFF(te_last, te_long) < te_delta * 3) &&
|
||||
(DURATION_DIFF(duration, te_short) < te_delta)) {
|
||||
subghz_protocol_blocks_add_bit(1);
|
||||
parser_step = DoitrandDecoderStepSaveDuration;
|
||||
} else {
|
||||
parser_step = DoitrandDecoderStepReset;
|
||||
}
|
||||
} else {
|
||||
parser_step = DoitrandDecoderStepReset;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
#endif
|
111
firmware/baseband/fprotos/s-dooya.hpp
Normal file
111
firmware/baseband/fprotos/s-dooya.hpp
Normal file
|
@ -0,0 +1,111 @@
|
|||
|
||||
#ifndef __FPROTO_DOOYA_H__
|
||||
#define __FPROTO_DOOYA_H__
|
||||
|
||||
#include "subghzdbase.hpp"
|
||||
|
||||
typedef enum : uint8_t {
|
||||
DooyaDecoderStepReset = 0,
|
||||
DooyaDecoderStepFoundStartBit,
|
||||
DooyaDecoderStepSaveDuration,
|
||||
DooyaDecoderStepCheckDuration,
|
||||
} DooyaDecoderStep;
|
||||
|
||||
class FProtoSubGhzDDooya : public FProtoSubGhzDBase {
|
||||
public:
|
||||
FProtoSubGhzDDooya() {
|
||||
sensorType = FPS_DOOYA;
|
||||
te_short = 366;
|
||||
te_long = 733;
|
||||
te_delta = 120;
|
||||
min_count_bit_for_found = 40;
|
||||
}
|
||||
|
||||
void feed(bool level, uint32_t duration) {
|
||||
switch (parser_step) {
|
||||
case DooyaDecoderStepReset:
|
||||
if ((!level) && (DURATION_DIFF(duration, te_long * 12) < te_delta * 20)) {
|
||||
parser_step = DooyaDecoderStepFoundStartBit;
|
||||
}
|
||||
break;
|
||||
|
||||
case DooyaDecoderStepFoundStartBit:
|
||||
if (!level) {
|
||||
if (DURATION_DIFF(duration, te_long * 2) < te_delta * 3) {
|
||||
parser_step = DooyaDecoderStepSaveDuration;
|
||||
decode_data = 0;
|
||||
decode_count_bit = 0;
|
||||
} else {
|
||||
parser_step = DooyaDecoderStepReset;
|
||||
}
|
||||
} else if (
|
||||
DURATION_DIFF(duration, te_short * 13) < te_delta * 5) {
|
||||
break;
|
||||
} else {
|
||||
parser_step = DooyaDecoderStepReset;
|
||||
}
|
||||
break;
|
||||
|
||||
case DooyaDecoderStepSaveDuration:
|
||||
if (level) {
|
||||
te_last = duration;
|
||||
parser_step = DooyaDecoderStepCheckDuration;
|
||||
} else {
|
||||
parser_step = DooyaDecoderStepReset;
|
||||
}
|
||||
break;
|
||||
|
||||
case DooyaDecoderStepCheckDuration:
|
||||
if (!level) {
|
||||
if (duration >= (te_long * 4)) {
|
||||
// add last bit
|
||||
if (DURATION_DIFF(te_last, te_short) < te_delta) {
|
||||
subghz_protocol_blocks_add_bit(0);
|
||||
} else if (
|
||||
DURATION_DIFF(te_last, te_long) <
|
||||
te_delta * 2) {
|
||||
subghz_protocol_blocks_add_bit(1);
|
||||
} else {
|
||||
parser_step = DooyaDecoderStepReset;
|
||||
break;
|
||||
}
|
||||
parser_step = DooyaDecoderStepFoundStartBit;
|
||||
if (decode_count_bit ==
|
||||
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;
|
||||
} 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 = DooyaDecoderStepSaveDuration;
|
||||
} else 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 = DooyaDecoderStepSaveDuration;
|
||||
} else {
|
||||
parser_step = DooyaDecoderStepReset;
|
||||
}
|
||||
} else {
|
||||
parser_step = DooyaDecoderStepReset;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
#endif
|
85
firmware/baseband/fprotos/s-faac.hpp
Normal file
85
firmware/baseband/fprotos/s-faac.hpp
Normal file
|
@ -0,0 +1,85 @@
|
|||
|
||||
#ifndef __FPROTO_FAAC_H__
|
||||
#define __FPROTO_FAAC_H__
|
||||
|
||||
#include "subghzdbase.hpp"
|
||||
|
||||
typedef enum : uint8_t {
|
||||
FaacSLHDecoderStepReset = 0,
|
||||
FaacSLHDecoderStepFoundPreambula,
|
||||
FaacSLHDecoderStepSaveDuration,
|
||||
FaacSLHDecoderStepCheckDuration,
|
||||
} FaacSLHDecoderStep;
|
||||
|
||||
class FProtoSubGhzDFaac : public FProtoSubGhzDBase {
|
||||
public:
|
||||
FProtoSubGhzDFaac() {
|
||||
sensorType = FPS_FAAC;
|
||||
te_short = 255;
|
||||
te_long = 595;
|
||||
te_delta = 100;
|
||||
min_count_bit_for_found = 64;
|
||||
}
|
||||
|
||||
void feed(bool level, uint32_t duration) {
|
||||
switch (parser_step) {
|
||||
case FaacSLHDecoderStepReset:
|
||||
if ((level) && (DURATION_DIFF(duration, te_long * 2) < te_delta * 3)) {
|
||||
parser_step = FaacSLHDecoderStepFoundPreambula;
|
||||
}
|
||||
break;
|
||||
case FaacSLHDecoderStepFoundPreambula:
|
||||
if ((!level) && (DURATION_DIFF(duration, te_long * 2) < te_delta * 3)) {
|
||||
// Found Preambula
|
||||
parser_step = FaacSLHDecoderStepSaveDuration;
|
||||
decode_data = 0;
|
||||
decode_count_bit = 0;
|
||||
} else {
|
||||
parser_step = FaacSLHDecoderStepReset;
|
||||
}
|
||||
break;
|
||||
case FaacSLHDecoderStepSaveDuration:
|
||||
if (level) {
|
||||
if (duration >= ((uint32_t)te_short * 3 + te_delta)) {
|
||||
parser_step = FaacSLHDecoderStepFoundPreambula;
|
||||
if (decode_count_bit == min_count_bit_for_found) {
|
||||
data = decode_data;
|
||||
data_count_bit = decode_count_bit;
|
||||
// remark controller skipped
|
||||
if (callback) callback(this);
|
||||
}
|
||||
decode_data = 0;
|
||||
decode_count_bit = 0;
|
||||
break;
|
||||
} else {
|
||||
te_last = duration;
|
||||
parser_step = FaacSLHDecoderStepCheckDuration;
|
||||
}
|
||||
|
||||
} else {
|
||||
parser_step = FaacSLHDecoderStepReset;
|
||||
}
|
||||
break;
|
||||
case FaacSLHDecoderStepCheckDuration:
|
||||
if (!level) {
|
||||
if ((DURATION_DIFF(te_last, te_short) < te_delta) &&
|
||||
(DURATION_DIFF(duration, te_long) < te_delta)) {
|
||||
subghz_protocol_blocks_add_bit(0);
|
||||
parser_step = FaacSLHDecoderStepSaveDuration;
|
||||
} else if (
|
||||
(DURATION_DIFF(te_last, te_long) < te_delta) &&
|
||||
(DURATION_DIFF(duration, te_short) < te_delta)) {
|
||||
subghz_protocol_blocks_add_bit(1);
|
||||
parser_step = FaacSLHDecoderStepSaveDuration;
|
||||
} else {
|
||||
parser_step = FaacSLHDecoderStepReset;
|
||||
}
|
||||
} else {
|
||||
parser_step = FaacSLHDecoderStepReset;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
#endif
|
88
firmware/baseband/fprotos/s-gate_tx.hpp
Normal file
88
firmware/baseband/fprotos/s-gate_tx.hpp
Normal file
|
@ -0,0 +1,88 @@
|
|||
|
||||
#ifndef __FPROTO_GATETX_H__
|
||||
#define __FPROTO_GATETX_H__
|
||||
|
||||
#include "subghzdbase.hpp"
|
||||
|
||||
typedef enum : uint8_t {
|
||||
GateTXDecoderStepReset = 0,
|
||||
GateTXDecoderStepFoundStartBit,
|
||||
GateTXDecoderStepSaveDuration,
|
||||
GateTXDecoderStepCheckDuration,
|
||||
} GateTXDecoderStep;
|
||||
|
||||
class FProtoSubGhzDGateTx : public FProtoSubGhzDBase {
|
||||
public:
|
||||
FProtoSubGhzDGateTx() {
|
||||
sensorType = FPS_GATETX;
|
||||
te_short = 350;
|
||||
te_long = 700;
|
||||
te_delta = 100;
|
||||
min_count_bit_for_found = 24;
|
||||
}
|
||||
|
||||
void feed(bool level, uint32_t duration) {
|
||||
switch (parser_step) {
|
||||
case GateTXDecoderStepReset:
|
||||
if ((!level) && (DURATION_DIFF(duration, te_short * 47) < te_delta * 47)) {
|
||||
// Found Preambula
|
||||
parser_step = GateTXDecoderStepFoundStartBit;
|
||||
}
|
||||
break;
|
||||
case GateTXDecoderStepFoundStartBit:
|
||||
if (level && ((DURATION_DIFF(duration, te_long) < te_delta * 3))) {
|
||||
// Found start bit
|
||||
parser_step = GateTXDecoderStepSaveDuration;
|
||||
decode_data = 0;
|
||||
decode_count_bit = 0;
|
||||
} else {
|
||||
parser_step = GateTXDecoderStepReset;
|
||||
}
|
||||
break;
|
||||
case GateTXDecoderStepSaveDuration:
|
||||
if (!level) {
|
||||
if (duration >= ((uint32_t)te_short * 10 + te_delta)) {
|
||||
parser_step = GateTXDecoderStepFoundStartBit;
|
||||
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;
|
||||
decode_count_bit = 0;
|
||||
break;
|
||||
} else {
|
||||
te_last = duration;
|
||||
parser_step = GateTXDecoderStepCheckDuration;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case GateTXDecoderStepCheckDuration:
|
||||
if (level) {
|
||||
if ((DURATION_DIFF(te_last, te_short) < te_delta) &&
|
||||
(DURATION_DIFF(duration, te_long) < te_delta * 3)) {
|
||||
subghz_protocol_blocks_add_bit(0);
|
||||
parser_step = GateTXDecoderStepSaveDuration;
|
||||
} else if (
|
||||
(DURATION_DIFF(te_last, te_long) < te_delta * 3) &&
|
||||
(DURATION_DIFF(duration, te_short) < te_delta)) {
|
||||
subghz_protocol_blocks_add_bit(1);
|
||||
parser_step = GateTXDecoderStepSaveDuration;
|
||||
} else {
|
||||
parser_step = GateTXDecoderStepReset;
|
||||
}
|
||||
} else {
|
||||
parser_step = GateTXDecoderStepReset;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
#endif
|
107
firmware/baseband/fprotos/s-holtek.hpp
Normal file
107
firmware/baseband/fprotos/s-holtek.hpp
Normal file
|
@ -0,0 +1,107 @@
|
|||
|
||||
#ifndef __FPROTO_HOLTEK_H__
|
||||
#define __FPROTO_HOLTEK_H__
|
||||
|
||||
#include "subghzdbase.hpp"
|
||||
|
||||
#define HOLTEK_HEADER_MASK 0xF000000000
|
||||
#define HOLTEK_HEADER 0x5000000000
|
||||
|
||||
typedef enum : uint8_t {
|
||||
HoltekDecoderStepReset = 0,
|
||||
HoltekDecoderStepFoundStartBit,
|
||||
HoltekDecoderStepSaveDuration,
|
||||
HoltekDecoderStepCheckDuration,
|
||||
} HoltekDecoderStep;
|
||||
|
||||
class FProtoSubGhzDHoltek : public FProtoSubGhzDBase {
|
||||
public:
|
||||
FProtoSubGhzDHoltek() {
|
||||
sensorType = FPS_HOLTEK;
|
||||
te_short = 430;
|
||||
te_long = 870;
|
||||
te_delta = 100;
|
||||
min_count_bit_for_found = 40;
|
||||
}
|
||||
|
||||
void feed(bool level, uint32_t duration) {
|
||||
switch (parser_step) {
|
||||
case HoltekDecoderStepReset:
|
||||
if ((!level) && (DURATION_DIFF(duration, te_short * 36) < te_delta * 36)) {
|
||||
// Found Preambula
|
||||
parser_step = HoltekDecoderStepFoundStartBit;
|
||||
}
|
||||
break;
|
||||
case HoltekDecoderStepFoundStartBit:
|
||||
if ((level) && (DURATION_DIFF(duration, te_short) < te_delta)) {
|
||||
// Found StartBit
|
||||
parser_step = HoltekDecoderStepSaveDuration;
|
||||
decode_data = 0;
|
||||
decode_count_bit = 0;
|
||||
} else {
|
||||
parser_step = HoltekDecoderStepReset;
|
||||
}
|
||||
break;
|
||||
case HoltekDecoderStepSaveDuration:
|
||||
// save duration
|
||||
if (!level) {
|
||||
if (duration >= ((uint32_t)te_short * 10 + te_delta)) {
|
||||
if (decode_count_bit ==
|
||||
min_count_bit_for_found) {
|
||||
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);
|
||||
}
|
||||
}
|
||||
decode_data = 0;
|
||||
decode_count_bit = 0;
|
||||
parser_step = HoltekDecoderStepFoundStartBit;
|
||||
break;
|
||||
} else {
|
||||
te_last = duration;
|
||||
parser_step = HoltekDecoderStepCheckDuration;
|
||||
}
|
||||
} else {
|
||||
parser_step = HoltekDecoderStepReset;
|
||||
}
|
||||
break;
|
||||
case HoltekDecoderStepCheckDuration:
|
||||
if (level) {
|
||||
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 = HoltekDecoderStepSaveDuration;
|
||||
} else 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 = HoltekDecoderStepSaveDuration;
|
||||
} else {
|
||||
parser_step = HoltekDecoderStepReset;
|
||||
}
|
||||
} else {
|
||||
parser_step = HoltekDecoderStepReset;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
#endif
|
90
firmware/baseband/fprotos/s-holtek_ht12x.hpp
Normal file
90
firmware/baseband/fprotos/s-holtek_ht12x.hpp
Normal file
|
@ -0,0 +1,90 @@
|
|||
|
||||
#ifndef __FPROTO_HOLTEKTH12X_H__
|
||||
#define __FPROTO_HOLTEKTH12X_H__
|
||||
|
||||
#include "subghzdbase.hpp"
|
||||
|
||||
typedef enum : uint8_t {
|
||||
Holtek_HT12XDecoderStepReset = 0,
|
||||
Holtek_HT12XDecoderStepFoundStartBit,
|
||||
Holtek_HT12XDecoderStepSaveDuration,
|
||||
Holtek_HT12XDecoderStepCheckDuration,
|
||||
} Holtek_HT12XDecoderStep;
|
||||
|
||||
class FProtoSubGhzDHoltekHt12x : public FProtoSubGhzDBase {
|
||||
public:
|
||||
FProtoSubGhzDHoltekHt12x() {
|
||||
sensorType = FPS_HOLTEKHT12X;
|
||||
te_short = 320;
|
||||
te_long = 640;
|
||||
te_delta = 200;
|
||||
min_count_bit_for_found = 12;
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
#endif
|
108
firmware/baseband/fprotos/s-honeywell.hpp
Normal file
108
firmware/baseband/fprotos/s-honeywell.hpp
Normal file
|
@ -0,0 +1,108 @@
|
|||
|
||||
#ifndef __FPROTO_HONEYWELL_H__
|
||||
#define __FPROTO_HONEYWELL_H__
|
||||
|
||||
#include "subghzdbase.hpp"
|
||||
|
||||
class FProtoSubGhzDHoneywell : public FProtoSubGhzDBase {
|
||||
public:
|
||||
FProtoSubGhzDHoneywell() {
|
||||
sensorType = FPS_HONEYWELL;
|
||||
te_short = 280;
|
||||
te_long = 143;
|
||||
te_delta = 51;
|
||||
min_count_bit_for_found = 62;
|
||||
}
|
||||
|
||||
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 bit;
|
||||
bool data_ok = FProtoGeneral::manchester_advance(
|
||||
manchester_saved_state, event, &manchester_saved_state, &bit);
|
||||
if (data_ok) {
|
||||
subghz_protocol_decoder_honeywell_addbit(bit);
|
||||
}
|
||||
} else {
|
||||
decode_data = 0;
|
||||
decode_count_bit = 0;
|
||||
}
|
||||
}
|
||||
|
||||
protected:
|
||||
ManchesterState manchester_saved_state = ManchesterStateMid1;
|
||||
|
||||
void subghz_protocol_decoder_honeywell_addbit(bool bit) {
|
||||
decode_data = (decode_data << 1) | bit;
|
||||
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
|
74
firmware/baseband/fprotos/s-honeywellwdb.hpp
Normal file
74
firmware/baseband/fprotos/s-honeywellwdb.hpp
Normal file
|
@ -0,0 +1,74 @@
|
|||
|
||||
#ifndef __FPROTO_HONEYWELLWDB_H__
|
||||
#define __FPROTO_HONEYWELLWDB_H__
|
||||
|
||||
#include "subghzdbase.hpp"
|
||||
|
||||
typedef enum : uint8_t {
|
||||
Honeywell_WDBDecoderStepReset = 0,
|
||||
Honeywell_WDBDecoderStepFoundStartBit,
|
||||
Honeywell_WDBDecoderStepSaveDuration,
|
||||
Honeywell_WDBDecoderStepCheckDuration,
|
||||
} Honeywell_WDBDecoderStep;
|
||||
|
||||
class FProtoSubGhzDHoneywellWdb : public FProtoSubGhzDBase {
|
||||
public:
|
||||
FProtoSubGhzDHoneywellWdb() {
|
||||
sensorType = FPS_HONEYWELLWDB;
|
||||
te_short = 160;
|
||||
te_long = 320;
|
||||
te_delta = 61;
|
||||
min_count_bit_for_found = 48;
|
||||
}
|
||||
|
||||
void feed(bool level, uint32_t duration) {
|
||||
switch (parser_step) {
|
||||
case Honeywell_WDBDecoderStepReset:
|
||||
if ((!level) && (DURATION_DIFF(duration, te_short * 3) < te_delta)) {
|
||||
// Found header Honeywell_WDB
|
||||
decode_count_bit = 0;
|
||||
decode_data = 0;
|
||||
parser_step = Honeywell_WDBDecoderStepSaveDuration;
|
||||
}
|
||||
break;
|
||||
case Honeywell_WDBDecoderStepSaveDuration:
|
||||
if (level) { // save interval
|
||||
if (DURATION_DIFF(duration, te_short * 3) < te_delta) {
|
||||
if ((decode_count_bit == min_count_bit_for_found) &&
|
||||
((decode_data & 0x01) == FProtoGeneral::subghz_protocol_blocks_get_parity(decode_data >> 1, min_count_bit_for_found - 1))) {
|
||||
data = decode_data;
|
||||
data_count_bit = decode_count_bit;
|
||||
// controller has too much, should be done on ui side
|
||||
if (callback) callback(this);
|
||||
}
|
||||
parser_step = Honeywell_WDBDecoderStepReset;
|
||||
break;
|
||||
}
|
||||
te_last = duration;
|
||||
parser_step = Honeywell_WDBDecoderStepCheckDuration;
|
||||
} else {
|
||||
parser_step = Honeywell_WDBDecoderStepReset;
|
||||
}
|
||||
break;
|
||||
case Honeywell_WDBDecoderStepCheckDuration:
|
||||
if (!level) {
|
||||
if ((DURATION_DIFF(te_last, te_short) < te_delta) &&
|
||||
(DURATION_DIFF(duration, te_long) < te_delta)) {
|
||||
subghz_protocol_blocks_add_bit(0);
|
||||
parser_step = Honeywell_WDBDecoderStepSaveDuration;
|
||||
} else if (
|
||||
(DURATION_DIFF(te_last, te_long) < te_delta) &&
|
||||
(DURATION_DIFF(duration, te_short) < te_delta)) {
|
||||
subghz_protocol_blocks_add_bit(1);
|
||||
parser_step = Honeywell_WDBDecoderStepSaveDuration;
|
||||
} else
|
||||
parser_step = Honeywell_WDBDecoderStepReset;
|
||||
} else {
|
||||
parser_step = Honeywell_WDBDecoderStepReset;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
#endif
|
85
firmware/baseband/fprotos/s-hormann.hpp
Normal file
85
firmware/baseband/fprotos/s-hormann.hpp
Normal file
|
@ -0,0 +1,85 @@
|
|||
|
||||
#ifndef __FPROTO_HORMANN_H__
|
||||
#define __FPROTO_HORMANN_H__
|
||||
|
||||
#include "subghzdbase.hpp"
|
||||
|
||||
typedef enum : uint8_t {
|
||||
HormannDecoderStepReset = 0,
|
||||
HormannDecoderStepFoundStartHeader,
|
||||
HormannDecoderStepFoundHeader,
|
||||
HormannDecoderStepFoundStartBit,
|
||||
HormannDecoderStepSaveDuration,
|
||||
HormannDecoderStepCheckDuration,
|
||||
} HormannDecoderStep;
|
||||
|
||||
#define HORMANN_HSM_PATTERN 0xFF000000003
|
||||
|
||||
class FProtoSubGhzDHormann : public FProtoSubGhzDBase {
|
||||
public:
|
||||
FProtoSubGhzDHormann() {
|
||||
sensorType = FPS_HORMANN;
|
||||
te_short = 500;
|
||||
te_long = 1000;
|
||||
te_delta = 200;
|
||||
min_count_bit_for_found = 44;
|
||||
}
|
||||
|
||||
void feed(bool level, uint32_t duration) {
|
||||
switch (parser_step) {
|
||||
case HormannDecoderStepReset:
|
||||
if ((level) && (DURATION_DIFF(duration, te_short * 24) < te_delta * 24)) {
|
||||
parser_step = HormannDecoderStepFoundStartBit;
|
||||
}
|
||||
break;
|
||||
case HormannDecoderStepFoundStartBit:
|
||||
if ((!level) && (DURATION_DIFF(duration, te_short) < te_delta)) {
|
||||
parser_step = HormannDecoderStepSaveDuration;
|
||||
decode_data = 0;
|
||||
decode_count_bit = 0;
|
||||
} else {
|
||||
parser_step = HormannDecoderStepReset;
|
||||
}
|
||||
break;
|
||||
case HormannDecoderStepSaveDuration:
|
||||
if (level) { // save interval
|
||||
if (duration >= (te_short * 5) && (decode_data & HORMANN_HSM_PATTERN) == HORMANN_HSM_PATTERN) {
|
||||
parser_step = HormannDecoderStepFoundStartBit;
|
||||
if (decode_count_bit >=
|
||||
min_count_bit_for_found) {
|
||||
data = decode_data;
|
||||
data_count_bit = decode_count_bit;
|
||||
// controller
|
||||
btn = (data >> 4) & 0xF;
|
||||
if (callback) callback(this);
|
||||
}
|
||||
break;
|
||||
}
|
||||
te_last = duration;
|
||||
parser_step = HormannDecoderStepCheckDuration;
|
||||
} else {
|
||||
parser_step = HormannDecoderStepReset;
|
||||
}
|
||||
break;
|
||||
case HormannDecoderStepCheckDuration:
|
||||
if (!level) {
|
||||
if ((DURATION_DIFF(te_last, te_short) < te_delta) &&
|
||||
(DURATION_DIFF(duration, te_long) < te_delta)) {
|
||||
subghz_protocol_blocks_add_bit(0);
|
||||
parser_step = HormannDecoderStepSaveDuration;
|
||||
} else if (
|
||||
(DURATION_DIFF(te_last, te_long) < te_delta) &&
|
||||
(DURATION_DIFF(duration, te_short) < te_delta)) {
|
||||
subghz_protocol_blocks_add_bit(1);
|
||||
parser_step = HormannDecoderStepSaveDuration;
|
||||
} else
|
||||
parser_step = HormannDecoderStepReset;
|
||||
} else {
|
||||
parser_step = HormannDecoderStepReset;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
#endif
|
91
firmware/baseband/fprotos/s-ido.hpp
Normal file
91
firmware/baseband/fprotos/s-ido.hpp
Normal file
|
@ -0,0 +1,91 @@
|
|||
|
||||
#ifndef __FPROTO_IDO_H__
|
||||
#define __FPROTO_IDO_H__
|
||||
|
||||
#include "subghzdbase.hpp"
|
||||
|
||||
typedef enum : uint8_t {
|
||||
IDoDecoderStepReset = 0,
|
||||
IDoDecoderStepFoundPreambula,
|
||||
IDoDecoderStepSaveDuration,
|
||||
IDoDecoderStepCheckDuration,
|
||||
} IDoDecoderStep;
|
||||
|
||||
class FProtoSubGhzDIdo : public FProtoSubGhzDBase {
|
||||
public:
|
||||
FProtoSubGhzDIdo() {
|
||||
sensorType = FPS_IDO;
|
||||
te_short = 450;
|
||||
te_long = 1450;
|
||||
te_delta = 150;
|
||||
min_count_bit_for_found = 48;
|
||||
}
|
||||
|
||||
void feed(bool level, uint32_t duration) {
|
||||
switch (parser_step) {
|
||||
case IDoDecoderStepReset:
|
||||
if ((level) && (DURATION_DIFF(duration, te_short * 10) < te_delta * 5)) {
|
||||
parser_step = IDoDecoderStepFoundPreambula;
|
||||
}
|
||||
break;
|
||||
case IDoDecoderStepFoundPreambula:
|
||||
if ((!level) && (DURATION_DIFF(duration, te_short * 10) < te_delta * 5)) {
|
||||
// Found Preambula
|
||||
parser_step = IDoDecoderStepSaveDuration;
|
||||
decode_data = 0;
|
||||
decode_count_bit = 0;
|
||||
} else {
|
||||
parser_step = IDoDecoderStepReset;
|
||||
}
|
||||
break;
|
||||
case IDoDecoderStepSaveDuration:
|
||||
if (level) {
|
||||
if (duration >= ((uint32_t)te_short * 5 + te_delta)) {
|
||||
parser_step = IDoDecoderStepFoundPreambula;
|
||||
if (decode_count_bit >=
|
||||
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;
|
||||
decode_count_bit = 0;
|
||||
break;
|
||||
} else {
|
||||
te_last = duration;
|
||||
parser_step = IDoDecoderStepCheckDuration;
|
||||
}
|
||||
|
||||
} else {
|
||||
parser_step = IDoDecoderStepReset;
|
||||
}
|
||||
break;
|
||||
case IDoDecoderStepCheckDuration:
|
||||
if (!level) {
|
||||
if ((DURATION_DIFF(te_last, te_short) < te_delta) &&
|
||||
(DURATION_DIFF(duration, te_long) < te_delta * 3)) {
|
||||
subghz_protocol_blocks_add_bit(0);
|
||||
parser_step = IDoDecoderStepSaveDuration;
|
||||
} else if (
|
||||
(DURATION_DIFF(te_last, te_short) < te_delta * 3) &&
|
||||
(DURATION_DIFF(duration, te_short) < te_delta)) {
|
||||
subghz_protocol_blocks_add_bit(1);
|
||||
parser_step = IDoDecoderStepSaveDuration;
|
||||
} else {
|
||||
parser_step = IDoDecoderStepReset;
|
||||
}
|
||||
} else {
|
||||
parser_step = IDoDecoderStepReset;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
#endif
|
148
firmware/baseband/fprotos/s-intertechnov3.hpp
Normal file
148
firmware/baseband/fprotos/s-intertechnov3.hpp
Normal file
|
@ -0,0 +1,148 @@
|
|||
|
||||
#ifndef __FPROTO_INTERTECHNOV3_H__
|
||||
#define __FPROTO_INTERTECHNOV3_H__
|
||||
|
||||
#include "subghzdbase.hpp"
|
||||
|
||||
#define INTERTECHNO_V3_DIMMING_COUNT_BIT 36
|
||||
|
||||
typedef enum : uint8_t {
|
||||
IntertechnoV3DecoderStepReset = 0,
|
||||
IntertechnoV3DecoderStepStartSync,
|
||||
IntertechnoV3DecoderStepFoundSync,
|
||||
IntertechnoV3DecoderStepStartDuration,
|
||||
IntertechnoV3DecoderStepSaveDuration,
|
||||
IntertechnoV3DecoderStepCheckDuration,
|
||||
IntertechnoV3DecoderStepEndDuration,
|
||||
} IntertechnoV3DecoderStep;
|
||||
|
||||
class FProtoSubGhzDIntertechnoV3 : public FProtoSubGhzDBase {
|
||||
public:
|
||||
FProtoSubGhzDIntertechnoV3() {
|
||||
sensorType = FPS_INTERTECHNOV3;
|
||||
te_short = 275;
|
||||
te_long = 1375;
|
||||
te_delta = 150;
|
||||
min_count_bit_for_found = 32;
|
||||
}
|
||||
|
||||
void feed(bool level, uint32_t duration) {
|
||||
switch (parser_step) {
|
||||
case IntertechnoV3DecoderStepReset:
|
||||
if ((!level) &&
|
||||
(DURATION_DIFF(duration, te_short * 37) < te_delta * 15)) {
|
||||
parser_step = IntertechnoV3DecoderStepStartSync;
|
||||
}
|
||||
break;
|
||||
case IntertechnoV3DecoderStepStartSync:
|
||||
if (level && (DURATION_DIFF(duration, te_short) < te_delta)) {
|
||||
parser_step = IntertechnoV3DecoderStepFoundSync;
|
||||
} else {
|
||||
parser_step = IntertechnoV3DecoderStepReset;
|
||||
}
|
||||
break;
|
||||
|
||||
case IntertechnoV3DecoderStepFoundSync:
|
||||
if (!level && (DURATION_DIFF(duration, te_short * 10) < te_delta * 3)) {
|
||||
parser_step = IntertechnoV3DecoderStepStartDuration;
|
||||
decode_data = 0;
|
||||
decode_count_bit = 0;
|
||||
} else {
|
||||
parser_step = IntertechnoV3DecoderStepReset;
|
||||
}
|
||||
break;
|
||||
|
||||
case IntertechnoV3DecoderStepStartDuration:
|
||||
if (level && (DURATION_DIFF(duration, te_short) < te_delta)) {
|
||||
parser_step = IntertechnoV3DecoderStepSaveDuration;
|
||||
} else {
|
||||
parser_step = IntertechnoV3DecoderStepReset;
|
||||
}
|
||||
break;
|
||||
|
||||
case IntertechnoV3DecoderStepSaveDuration:
|
||||
if (!level) { // save interval
|
||||
if (duration >= (te_short * 11)) {
|
||||
parser_step = IntertechnoV3DecoderStepStartSync;
|
||||
if ((decode_count_bit == min_count_bit_for_found) ||
|
||||
(decode_count_bit == INTERTECHNO_V3_DIMMING_COUNT_BIT)) {
|
||||
data = decode_data;
|
||||
data_count_bit = decode_count_bit;
|
||||
remote_controller();
|
||||
if (callback) callback(this);
|
||||
}
|
||||
break;
|
||||
}
|
||||
te_last = duration;
|
||||
parser_step = IntertechnoV3DecoderStepCheckDuration;
|
||||
} else {
|
||||
parser_step = IntertechnoV3DecoderStepReset;
|
||||
}
|
||||
break;
|
||||
case IntertechnoV3DecoderStepCheckDuration:
|
||||
if (level) {
|
||||
// Add 0 bit
|
||||
if ((DURATION_DIFF(te_last, te_short) < te_delta) &&
|
||||
(DURATION_DIFF(duration, te_short) < te_delta)) {
|
||||
subghz_protocol_blocks_add_bit(0);
|
||||
parser_step = IntertechnoV3DecoderStepEndDuration;
|
||||
} else if (
|
||||
// Add 1 bit
|
||||
(DURATION_DIFF(te_last, te_long) < te_delta * 2) &&
|
||||
(DURATION_DIFF(duration, te_short) < te_delta)) {
|
||||
subghz_protocol_blocks_add_bit(1);
|
||||
parser_step = IntertechnoV3DecoderStepEndDuration;
|
||||
|
||||
} else if (
|
||||
// Add dimm_state
|
||||
(DURATION_DIFF(te_last, te_short) < te_delta * 2) &&
|
||||
(DURATION_DIFF(duration, te_short) < te_delta) &&
|
||||
(decode_count_bit == 27)) {
|
||||
subghz_protocol_blocks_add_bit(0);
|
||||
parser_step = IntertechnoV3DecoderStepEndDuration;
|
||||
|
||||
} else
|
||||
parser_step = IntertechnoV3DecoderStepReset;
|
||||
} else {
|
||||
parser_step = IntertechnoV3DecoderStepReset;
|
||||
}
|
||||
break;
|
||||
|
||||
case IntertechnoV3DecoderStepEndDuration:
|
||||
if (!level && ((DURATION_DIFF(duration, te_short) < te_delta) ||
|
||||
(DURATION_DIFF(duration, te_long) < te_delta * 2))) {
|
||||
parser_step = IntertechnoV3DecoderStepStartDuration;
|
||||
} else {
|
||||
parser_step = IntertechnoV3DecoderStepReset;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
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
|
107
firmware/baseband/fprotos/s-keeloq.hpp
Normal file
107
firmware/baseband/fprotos/s-keeloq.hpp
Normal file
|
@ -0,0 +1,107 @@
|
|||
|
||||
#ifndef __FPROTO_KEELOQ_H__
|
||||
#define __FPROTO_KEELOQ_H__
|
||||
|
||||
#include "subghzdbase.hpp"
|
||||
|
||||
typedef enum : uint8_t {
|
||||
KeeloqDecoderStepReset = 0,
|
||||
KeeloqDecoderStepCheckPreambula,
|
||||
KeeloqDecoderStepSaveDuration,
|
||||
KeeloqDecoderStepCheckDuration,
|
||||
} KeeloqDecoderStep;
|
||||
|
||||
class FProtoSubGhzDKeeLoq : public FProtoSubGhzDBase {
|
||||
public:
|
||||
FProtoSubGhzDKeeLoq() {
|
||||
sensorType = FPS_KEELOQ;
|
||||
te_short = 400;
|
||||
te_long = 800;
|
||||
te_delta = 140;
|
||||
min_count_bit_for_found = 64;
|
||||
}
|
||||
|
||||
void feed(bool level, uint32_t duration) {
|
||||
switch (parser_step) {
|
||||
case KeeloqDecoderStepReset:
|
||||
if ((level) && DURATION_DIFF(duration, te_short) < te_delta) {
|
||||
parser_step = KeeloqDecoderStepCheckPreambula;
|
||||
header_count++;
|
||||
}
|
||||
break;
|
||||
case KeeloqDecoderStepCheckPreambula:
|
||||
if ((!level) && (DURATION_DIFF(duration, te_short) < te_delta)) {
|
||||
parser_step = KeeloqDecoderStepReset;
|
||||
break;
|
||||
}
|
||||
if ((header_count > 2) && (DURATION_DIFF(duration, te_short * 10) < te_delta * 10)) {
|
||||
// Found header
|
||||
parser_step = KeeloqDecoderStepSaveDuration;
|
||||
decode_data = 0;
|
||||
decode_count_bit = 0;
|
||||
} else {
|
||||
parser_step = KeeloqDecoderStepReset;
|
||||
header_count = 0;
|
||||
}
|
||||
break;
|
||||
case KeeloqDecoderStepSaveDuration:
|
||||
if (level) {
|
||||
te_last = duration;
|
||||
parser_step = KeeloqDecoderStepCheckDuration;
|
||||
}
|
||||
break;
|
||||
case KeeloqDecoderStepCheckDuration:
|
||||
if (!level) {
|
||||
if (duration >= ((uint32_t)te_short * 2 + te_delta)) {
|
||||
// Found end TX
|
||||
parser_step = KeeloqDecoderStepReset;
|
||||
if ((decode_count_bit >= min_count_bit_for_found) &&
|
||||
(decode_count_bit <= min_count_bit_for_found + 2)) {
|
||||
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;
|
||||
decode_count_bit = 0;
|
||||
header_count = 0;
|
||||
}
|
||||
break;
|
||||
} else if (
|
||||
(DURATION_DIFF(te_last, te_short) < te_delta) &&
|
||||
(DURATION_DIFF(duration, te_long) < te_delta * 2)) {
|
||||
if (decode_count_bit < min_count_bit_for_found) {
|
||||
subghz_protocol_blocks_add_bit(1);
|
||||
} else {
|
||||
decode_count_bit++;
|
||||
}
|
||||
parser_step = KeeloqDecoderStepSaveDuration;
|
||||
} else if (
|
||||
(DURATION_DIFF(te_last, te_long) < te_delta * 2) &&
|
||||
(DURATION_DIFF(duration, te_short) < te_delta)) {
|
||||
if (decode_count_bit < min_count_bit_for_found) {
|
||||
subghz_protocol_blocks_add_bit(0);
|
||||
} else {
|
||||
decode_count_bit++;
|
||||
}
|
||||
parser_step = KeeloqDecoderStepSaveDuration;
|
||||
} else {
|
||||
parser_step = KeeloqDecoderStepReset;
|
||||
header_count = 0;
|
||||
}
|
||||
} else {
|
||||
parser_step = KeeloqDecoderStepReset;
|
||||
header_count = 0;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
#endif
|
124
firmware/baseband/fprotos/s-kinggates_stylo_4k.hpp
Normal file
124
firmware/baseband/fprotos/s-kinggates_stylo_4k.hpp
Normal file
|
@ -0,0 +1,124 @@
|
|||
|
||||
#ifndef __FPROTO_KINGGATES_STYLO_4K_H__
|
||||
#define __FPROTO_KINGGATES_STYLO_4K_H__
|
||||
|
||||
#include "subghzdbase.hpp"
|
||||
|
||||
typedef enum : uint8_t {
|
||||
KingGates_stylo_4kDecoderStepReset = 0,
|
||||
KingGates_stylo_4kDecoderStepCheckPreambula,
|
||||
KingGates_stylo_4kDecoderStepCheckStartBit,
|
||||
KingGates_stylo_4kDecoderStepSaveDuration,
|
||||
KingGates_stylo_4kDecoderStepCheckDuration,
|
||||
} KingGates_stylo_4kDecoderStep;
|
||||
|
||||
class FProtoSubGhzDKinggatesStylo4K : public FProtoSubGhzDBase {
|
||||
public:
|
||||
FProtoSubGhzDKinggatesStylo4K() {
|
||||
sensorType = FPS_KINGGATESSTYLO4K;
|
||||
te_short = 400;
|
||||
te_long = 1100;
|
||||
te_delta = 140;
|
||||
min_count_bit_for_found = 89;
|
||||
}
|
||||
|
||||
void feed(bool level, uint32_t duration) {
|
||||
switch (parser_step) {
|
||||
case KingGates_stylo_4kDecoderStepReset:
|
||||
if ((level) && DURATION_DIFF(duration, te_short) < te_delta) {
|
||||
parser_step = KingGates_stylo_4kDecoderStepCheckPreambula;
|
||||
header_count++;
|
||||
}
|
||||
break;
|
||||
case KingGates_stylo_4kDecoderStepCheckPreambula:
|
||||
if ((!level) &&
|
||||
(DURATION_DIFF(duration, te_short) < te_delta)) {
|
||||
parser_step = KingGates_stylo_4kDecoderStepReset;
|
||||
break;
|
||||
}
|
||||
if ((header_count > 2) &&
|
||||
(DURATION_DIFF(duration, te_long * 2) < te_delta * 2)) {
|
||||
// Found header
|
||||
parser_step = KingGates_stylo_4kDecoderStepCheckStartBit;
|
||||
} else {
|
||||
parser_step = KingGates_stylo_4kDecoderStepReset;
|
||||
header_count = 0;
|
||||
}
|
||||
break;
|
||||
case KingGates_stylo_4kDecoderStepCheckStartBit:
|
||||
if ((level) &&
|
||||
DURATION_DIFF(duration, te_short * 2) < te_delta * 2) {
|
||||
parser_step = KingGates_stylo_4kDecoderStepSaveDuration;
|
||||
decode_data = 0;
|
||||
data_2 = 0;
|
||||
decode_count_bit = 0;
|
||||
header_count = 0;
|
||||
}
|
||||
break;
|
||||
case KingGates_stylo_4kDecoderStepSaveDuration:
|
||||
if (!level) {
|
||||
if (duration >= ((uint32_t)te_long * 3)) {
|
||||
if (decode_count_bit ==
|
||||
min_count_bit_for_found) {
|
||||
data = data_2;
|
||||
data_2 = decode_data;
|
||||
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);
|
||||
}
|
||||
|
||||
parser_step = KingGates_stylo_4kDecoderStepReset;
|
||||
decode_data = 0;
|
||||
data_2 = 0;
|
||||
decode_count_bit = 0;
|
||||
header_count = 0;
|
||||
break;
|
||||
} else {
|
||||
te_last = duration;
|
||||
parser_step = KingGates_stylo_4kDecoderStepCheckDuration;
|
||||
}
|
||||
} else {
|
||||
parser_step = KingGates_stylo_4kDecoderStepReset;
|
||||
header_count = 0;
|
||||
}
|
||||
break;
|
||||
case KingGates_stylo_4kDecoderStepCheckDuration:
|
||||
if (level) {
|
||||
if ((DURATION_DIFF(
|
||||
te_last, te_short) < te_delta) &&
|
||||
(DURATION_DIFF(duration, te_long) < te_delta * 2)) {
|
||||
subghz_protocol_blocks_add_bit(1);
|
||||
parser_step = KingGates_stylo_4kDecoderStepSaveDuration;
|
||||
} else if (
|
||||
(DURATION_DIFF(
|
||||
te_last, te_long) <
|
||||
te_delta * 2) &&
|
||||
(DURATION_DIFF(duration, te_short) <
|
||||
te_delta)) {
|
||||
subghz_protocol_blocks_add_bit(0);
|
||||
parser_step = KingGates_stylo_4kDecoderStepSaveDuration;
|
||||
} else {
|
||||
parser_step = KingGates_stylo_4kDecoderStepReset;
|
||||
header_count = 0;
|
||||
}
|
||||
if (decode_count_bit == 53) {
|
||||
data_2 = decode_data;
|
||||
decode_data = 0;
|
||||
}
|
||||
} else {
|
||||
parser_step = KingGates_stylo_4kDecoderStepReset;
|
||||
header_count = 0;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
protected:
|
||||
uint64_t data_2 = 0;
|
||||
};
|
||||
|
||||
#endif
|
88
firmware/baseband/fprotos/s-linear.hpp
Normal file
88
firmware/baseband/fprotos/s-linear.hpp
Normal file
|
@ -0,0 +1,88 @@
|
|||
|
||||
#ifndef __FPROTO_LINEAR_H__
|
||||
#define __FPROTO_LINEAR_H__
|
||||
|
||||
#include "subghzdbase.hpp"
|
||||
|
||||
typedef enum : uint8_t {
|
||||
LinearDecoderStepReset = 0,
|
||||
LinearDecoderStepSaveDuration,
|
||||
LinearDecoderStepCheckDuration,
|
||||
} LinearDecoderStep;
|
||||
|
||||
class FProtoSubGhzDLinear : public FProtoSubGhzDBase {
|
||||
public:
|
||||
FProtoSubGhzDLinear() {
|
||||
sensorType = FPS_LINEAR;
|
||||
te_short = 500;
|
||||
te_long = 1500;
|
||||
te_delta = 150;
|
||||
min_count_bit_for_found = 10;
|
||||
}
|
||||
|
||||
void feed(bool level, uint32_t duration) {
|
||||
switch (parser_step) {
|
||||
case LinearDecoderStepReset:
|
||||
if ((!level) && (DURATION_DIFF(duration, te_short * 42) < te_delta * 20)) {
|
||||
// Found header Linear
|
||||
decode_data = 0;
|
||||
decode_count_bit = 0;
|
||||
parser_step = LinearDecoderStepSaveDuration;
|
||||
}
|
||||
break;
|
||||
case LinearDecoderStepSaveDuration:
|
||||
if (level) {
|
||||
te_last = duration;
|
||||
parser_step = LinearDecoderStepCheckDuration;
|
||||
} else {
|
||||
parser_step = LinearDecoderStepReset;
|
||||
}
|
||||
break;
|
||||
case LinearDecoderStepCheckDuration:
|
||||
if (!level) { // save interval
|
||||
if (duration >= (te_short * 5)) {
|
||||
parser_step = LinearDecoderStepReset;
|
||||
// checking that the duration matches the guardtime
|
||||
if ((DURATION_DIFF(duration, te_short * 42) > te_delta * 20)) {
|
||||
break;
|
||||
}
|
||||
if (DURATION_DIFF(te_last, te_short) < te_delta) {
|
||||
subghz_protocol_blocks_add_bit(0);
|
||||
} else if (
|
||||
DURATION_DIFF(te_last, te_long) <
|
||||
te_delta) {
|
||||
subghz_protocol_blocks_add_bit(1);
|
||||
}
|
||||
if (decode_count_bit == min_count_bit_for_found) {
|
||||
serial = SD_NO_SERIAL;
|
||||
btn = SD_NO_BTN;
|
||||
data = decode_data;
|
||||
data_count_bit = decode_count_bit;
|
||||
|
||||
if (callback) callback(this);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
if ((DURATION_DIFF(te_last, te_short) < te_delta) &&
|
||||
(DURATION_DIFF(duration, te_long) < te_delta)) {
|
||||
subghz_protocol_blocks_add_bit(0);
|
||||
parser_step = LinearDecoderStepSaveDuration;
|
||||
} else if (
|
||||
(DURATION_DIFF(te_last, te_long) < te_delta) &&
|
||||
(DURATION_DIFF(duration, te_short) < te_delta)) {
|
||||
subghz_protocol_blocks_add_bit(1);
|
||||
parser_step = LinearDecoderStepSaveDuration;
|
||||
} else {
|
||||
parser_step = LinearDecoderStepReset;
|
||||
}
|
||||
|
||||
} else {
|
||||
parser_step = LinearDecoderStepReset;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
#endif
|
87
firmware/baseband/fprotos/s-linear_delta3.hpp
Normal file
87
firmware/baseband/fprotos/s-linear_delta3.hpp
Normal file
|
@ -0,0 +1,87 @@
|
|||
|
||||
#ifndef __FPROTO_LINEARDELTA3_H__
|
||||
#define __FPROTO_LINEARDELTA3_H__
|
||||
|
||||
#include "subghzdbase.hpp"
|
||||
|
||||
typedef enum : uint8_t {
|
||||
LinearD3DecoderStepReset = 0,
|
||||
LinearD3DecoderStepSaveDuration,
|
||||
LinearD3DecoderStepCheckDuration,
|
||||
} LinearD3DecoderStep;
|
||||
|
||||
class FProtoSubGhzDLinearDelta3 : public FProtoSubGhzDBase {
|
||||
public:
|
||||
FProtoSubGhzDLinearDelta3() {
|
||||
sensorType = FPS_LINEARDELTA3;
|
||||
te_short = 500;
|
||||
te_long = 2000;
|
||||
te_delta = 150;
|
||||
min_count_bit_for_found = 8;
|
||||
}
|
||||
|
||||
void feed(bool level, uint32_t duration) {
|
||||
switch (parser_step) {
|
||||
case LinearD3DecoderStepReset:
|
||||
if ((!level) && (DURATION_DIFF(duration, te_short * 70) < te_delta * 24)) {
|
||||
// Found header Linear
|
||||
decode_data = 0;
|
||||
decode_count_bit = 0;
|
||||
parser_step = LinearD3DecoderStepSaveDuration;
|
||||
}
|
||||
break;
|
||||
case LinearD3DecoderStepSaveDuration:
|
||||
if (level) {
|
||||
te_last = duration;
|
||||
parser_step = LinearD3DecoderStepCheckDuration;
|
||||
} else {
|
||||
parser_step = LinearD3DecoderStepReset;
|
||||
}
|
||||
break;
|
||||
case LinearD3DecoderStepCheckDuration:
|
||||
if (!level) {
|
||||
if (duration >= (te_short * 10)) {
|
||||
parser_step = LinearD3DecoderStepReset;
|
||||
if (DURATION_DIFF(te_last, te_short) < te_delta) {
|
||||
subghz_protocol_blocks_add_bit(1);
|
||||
} else if (
|
||||
DURATION_DIFF(te_last, te_long) < te_delta) {
|
||||
subghz_protocol_blocks_add_bit(0);
|
||||
}
|
||||
if (decode_count_bit == min_count_bit_for_found) {
|
||||
if ((data == decode_data) && data) {
|
||||
serial = SD_NO_SERIAL;
|
||||
btn = SD_NO_BTN;
|
||||
|
||||
data = decode_data;
|
||||
data_count_bit = decode_count_bit;
|
||||
|
||||
if (callback) callback(this);
|
||||
}
|
||||
parser_step = LinearD3DecoderStepSaveDuration;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
if ((DURATION_DIFF(te_last, te_short) < te_delta) &&
|
||||
(DURATION_DIFF(duration, te_short * 7) < te_delta)) {
|
||||
subghz_protocol_blocks_add_bit(1);
|
||||
parser_step = LinearD3DecoderStepSaveDuration;
|
||||
} else if (
|
||||
(DURATION_DIFF(te_last, te_long) < te_delta) &&
|
||||
(DURATION_DIFF(duration, te_long) < te_delta)) {
|
||||
subghz_protocol_blocks_add_bit(0);
|
||||
parser_step = LinearD3DecoderStepSaveDuration;
|
||||
} else {
|
||||
parser_step = LinearD3DecoderStepReset;
|
||||
}
|
||||
|
||||
} else {
|
||||
parser_step = LinearD3DecoderStepReset;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
#endif
|
139
firmware/baseband/fprotos/s-magellan.hpp
Normal file
139
firmware/baseband/fprotos/s-magellan.hpp
Normal file
|
@ -0,0 +1,139 @@
|
|||
|
||||
#ifndef __FPROTO_MAGELLAN_H__
|
||||
#define __FPROTO_MAGELLAN_H__
|
||||
|
||||
#include "subghzdbase.hpp"
|
||||
|
||||
typedef enum : uint8_t {
|
||||
MagellanDecoderStepReset = 0,
|
||||
MagellanDecoderStepCheckPreambula,
|
||||
MagellanDecoderStepFoundPreambula,
|
||||
MagellanDecoderStepSaveDuration,
|
||||
MagellanDecoderStepCheckDuration,
|
||||
} MagellanDecoderStep;
|
||||
|
||||
class FProtoSubGhzDMagellan : public FProtoSubGhzDBase {
|
||||
public:
|
||||
FProtoSubGhzDMagellan() {
|
||||
sensorType = FPS_MAGELLAN;
|
||||
te_short = 200;
|
||||
te_long = 400;
|
||||
te_delta = 100;
|
||||
min_count_bit_for_found = 32;
|
||||
}
|
||||
|
||||
void feed(bool level, uint32_t duration) {
|
||||
switch (parser_step) {
|
||||
case MagellanDecoderStepReset:
|
||||
if ((level) && (DURATION_DIFF(duration, te_short) < te_delta)) {
|
||||
parser_step = MagellanDecoderStepCheckPreambula;
|
||||
te_last = duration;
|
||||
header_count = 0;
|
||||
}
|
||||
break;
|
||||
|
||||
case MagellanDecoderStepCheckPreambula:
|
||||
if (level) {
|
||||
te_last = duration;
|
||||
} else {
|
||||
if ((DURATION_DIFF(te_last, te_short) < te_delta) &&
|
||||
(DURATION_DIFF(duration, te_short) < te_delta)) {
|
||||
// Found header
|
||||
header_count++;
|
||||
} else if (
|
||||
(DURATION_DIFF(te_last, te_short) < te_delta) &&
|
||||
(DURATION_DIFF(duration, te_long) < te_delta * 2) &&
|
||||
(header_count > 10)) {
|
||||
parser_step = MagellanDecoderStepFoundPreambula;
|
||||
} else {
|
||||
parser_step = MagellanDecoderStepReset;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case MagellanDecoderStepFoundPreambula:
|
||||
if (level) {
|
||||
te_last = duration;
|
||||
} else {
|
||||
if ((DURATION_DIFF(te_last, te_short * 6) < te_delta * 3) &&
|
||||
(DURATION_DIFF(duration, te_long) < te_delta * 2)) {
|
||||
parser_step = MagellanDecoderStepSaveDuration;
|
||||
decode_data = 0;
|
||||
decode_count_bit = 0;
|
||||
} else {
|
||||
parser_step = MagellanDecoderStepReset;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case MagellanDecoderStepSaveDuration:
|
||||
if (level) {
|
||||
te_last = duration;
|
||||
parser_step = MagellanDecoderStepCheckDuration;
|
||||
} else {
|
||||
parser_step = MagellanDecoderStepReset;
|
||||
}
|
||||
break;
|
||||
|
||||
case MagellanDecoderStepCheckDuration:
|
||||
if (!level) {
|
||||
if ((DURATION_DIFF(te_last, te_short) < te_delta) &&
|
||||
(DURATION_DIFF(duration, te_long) < te_delta)) {
|
||||
subghz_protocol_blocks_add_bit(1);
|
||||
parser_step = MagellanDecoderStepSaveDuration;
|
||||
} else if (
|
||||
(DURATION_DIFF(te_last, te_long) < te_delta) &&
|
||||
(DURATION_DIFF(duration, te_short) < te_delta)) {
|
||||
subghz_protocol_blocks_add_bit(0);
|
||||
parser_step = MagellanDecoderStepSaveDuration;
|
||||
} else if (duration >= (te_long * 3)) {
|
||||
// Found stop bit
|
||||
if ((decode_count_bit == min_count_bit_for_found) &&
|
||||
subghz_protocol_magellan_check_crc()) {
|
||||
data = decode_data;
|
||||
data_count_bit = decode_count_bit;
|
||||
|
||||
// controller
|
||||
uint64_t data_rev = FProtoGeneral::subghz_protocol_blocks_reverse_key(data >> 8, 24);
|
||||
serial = data_rev & 0xFFFF;
|
||||
btn = (data_rev >> 16) & 0xFF;
|
||||
if (callback) callback(this);
|
||||
}
|
||||
decode_data = 0;
|
||||
decode_count_bit = 0;
|
||||
parser_step = MagellanDecoderStepReset;
|
||||
} else {
|
||||
parser_step = MagellanDecoderStepReset;
|
||||
}
|
||||
} else {
|
||||
parser_step = MagellanDecoderStepReset;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
protected:
|
||||
bool subghz_protocol_magellan_check_crc() {
|
||||
uint8_t data[3] = {
|
||||
(uint8_t)(decode_data >> 24),
|
||||
(uint8_t)(decode_data >> 16),
|
||||
(uint8_t)(decode_data >> 8)};
|
||||
return (decode_data & 0xFF) == subghz_protocol_magellan_crc8(data, sizeof(data));
|
||||
}
|
||||
uint8_t subghz_protocol_magellan_crc8(uint8_t* data, size_t len) {
|
||||
uint8_t crc = 0x00;
|
||||
uint8_t i, j;
|
||||
for (i = 0; i < len; i++) {
|
||||
crc ^= data[i];
|
||||
for (j = 0; j < 8; j++) {
|
||||
if ((crc & 0x80) != 0)
|
||||
crc = (uint8_t)((crc << 1) ^ 0x31);
|
||||
else
|
||||
crc <<= 1;
|
||||
}
|
||||
}
|
||||
return crc;
|
||||
}
|
||||
};
|
||||
|
||||
#endif
|
86
firmware/baseband/fprotos/s-marantec.hpp
Normal file
86
firmware/baseband/fprotos/s-marantec.hpp
Normal file
|
@ -0,0 +1,86 @@
|
|||
|
||||
#ifndef __FPROTO_MARANTEC_H__
|
||||
#define __FPROTO_MARANTEC_H__
|
||||
|
||||
#include "subghzdbase.hpp"
|
||||
|
||||
typedef enum : uint8_t {
|
||||
MarantecDecoderStepReset = 0,
|
||||
MarantecDecoderFoundHeader,
|
||||
MarantecDecoderStepDecoderData,
|
||||
} MarantecDecoderStep;
|
||||
|
||||
class FProtoSubGhzDMarantec : public FProtoSubGhzDBase {
|
||||
public:
|
||||
FProtoSubGhzDMarantec() {
|
||||
sensorType = FPS_MARANTEC;
|
||||
te_short = 1000;
|
||||
te_long = 2000;
|
||||
te_delta = 200;
|
||||
min_count_bit_for_found = 49;
|
||||
}
|
||||
|
||||
void feed(bool level, uint32_t duration) {
|
||||
ManchesterEvent event = ManchesterEventReset;
|
||||
|
||||
switch (parser_step) {
|
||||
case MarantecDecoderStepReset:
|
||||
if ((!level) && (DURATION_DIFF(duration, te_long * 5) < te_delta * 8)) {
|
||||
// Found header marantec
|
||||
parser_step = MarantecDecoderStepDecoderData;
|
||||
decode_data = 1;
|
||||
decode_count_bit = 1;
|
||||
FProtoGeneral::manchester_advance(manchester_saved_state, ManchesterEventReset, &manchester_saved_state, NULL);
|
||||
}
|
||||
break;
|
||||
case MarantecDecoderStepDecoderData:
|
||||
if (!level) {
|
||||
if (DURATION_DIFF(duration, te_short) < te_delta) {
|
||||
event = ManchesterEventShortLow;
|
||||
} else if (
|
||||
DURATION_DIFF(duration, te_long) < te_delta) {
|
||||
event = ManchesterEventLongLow;
|
||||
} else if (
|
||||
duration >= ((uint32_t)te_long * 2 + te_delta)) {
|
||||
if (decode_count_bit == min_count_bit_for_found) {
|
||||
data = decode_data;
|
||||
data_count_bit = decode_count_bit;
|
||||
// controller
|
||||
btn = (data >> 16) & 0xF;
|
||||
serial = ((data >> 12) & 0xFFFFFF00) | ((data >> 8) & 0xFF);
|
||||
if (callback) callback(this);
|
||||
}
|
||||
decode_data = 1;
|
||||
decode_count_bit = 1;
|
||||
FProtoGeneral::manchester_advance(manchester_saved_state, ManchesterEventReset, &manchester_saved_state, NULL);
|
||||
} else {
|
||||
parser_step = MarantecDecoderStepReset;
|
||||
}
|
||||
} else {
|
||||
if (DURATION_DIFF(duration, te_short) < te_delta) {
|
||||
event = ManchesterEventShortHigh;
|
||||
} else if (
|
||||
DURATION_DIFF(duration, te_long) < te_delta) {
|
||||
event = ManchesterEventLongHigh;
|
||||
} else {
|
||||
parser_step = MarantecDecoderStepReset;
|
||||
}
|
||||
}
|
||||
if (event != ManchesterEventReset) {
|
||||
bool bitstate;
|
||||
bool data_ok = FProtoGeneral::manchester_advance(manchester_saved_state, event, &manchester_saved_state, &bitstate);
|
||||
|
||||
if (data_ok) {
|
||||
decode_data = (decode_data << 1) | bitstate;
|
||||
decode_count_bit++;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
protected:
|
||||
ManchesterState manchester_saved_state = ManchesterStateMid1;
|
||||
};
|
||||
|
||||
#endif
|
86
firmware/baseband/fprotos/s-mastercode.hpp
Normal file
86
firmware/baseband/fprotos/s-mastercode.hpp
Normal file
|
@ -0,0 +1,86 @@
|
|||
|
||||
#ifndef __FPROTO_MASTERCODE_H__
|
||||
#define __FPROTO_MASTERCODE_H__
|
||||
|
||||
#include "subghzdbase.hpp"
|
||||
|
||||
typedef enum : uint8_t {
|
||||
MastercodeDecoderStepReset = 0,
|
||||
MastercodeDecoderStepSaveDuration,
|
||||
MastercodeDecoderStepCheckDuration,
|
||||
} MastercodeDecoderStep;
|
||||
|
||||
class FProtoSubGhzDMastercode : public FProtoSubGhzDBase {
|
||||
public:
|
||||
FProtoSubGhzDMastercode() {
|
||||
sensorType = FPS_MASTERCODE;
|
||||
te_short = 1072;
|
||||
te_long = 2145;
|
||||
te_delta = 150;
|
||||
min_count_bit_for_found = 36;
|
||||
}
|
||||
|
||||
void feed(bool level, uint32_t duration) {
|
||||
switch (parser_step) {
|
||||
case MastercodeDecoderStepReset:
|
||||
if ((!level) && (DURATION_DIFF(duration, te_short * 15) < te_delta * 15)) {
|
||||
parser_step = MastercodeDecoderStepSaveDuration;
|
||||
decode_data = 0;
|
||||
decode_count_bit = 0;
|
||||
}
|
||||
break;
|
||||
|
||||
case MastercodeDecoderStepSaveDuration:
|
||||
if (level) {
|
||||
te_last = duration;
|
||||
parser_step = MastercodeDecoderStepCheckDuration;
|
||||
} else {
|
||||
parser_step = MastercodeDecoderStepReset;
|
||||
}
|
||||
break;
|
||||
|
||||
case MastercodeDecoderStepCheckDuration:
|
||||
if (!level) {
|
||||
if ((DURATION_DIFF(te_last, te_short) < te_delta) &&
|
||||
(DURATION_DIFF(duration, te_long) < te_delta * 8)) {
|
||||
subghz_protocol_blocks_add_bit(0);
|
||||
parser_step = MastercodeDecoderStepSaveDuration;
|
||||
} else if (
|
||||
(DURATION_DIFF(te_last, te_long) < te_delta * 8) &&
|
||||
(DURATION_DIFF(duration, te_short) < te_delta)) {
|
||||
subghz_protocol_blocks_add_bit(1);
|
||||
parser_step = MastercodeDecoderStepSaveDuration;
|
||||
} else if (
|
||||
DURATION_DIFF(duration, te_short * 15) < te_delta * 15) {
|
||||
if ((DURATION_DIFF(te_last, te_short) < te_delta)) {
|
||||
subghz_protocol_blocks_add_bit(0);
|
||||
} else if ((DURATION_DIFF(te_last, te_long) < te_delta * 8)) {
|
||||
subghz_protocol_blocks_add_bit(1);
|
||||
} else {
|
||||
parser_step = MastercodeDecoderStepReset;
|
||||
}
|
||||
|
||||
if (decode_count_bit == min_count_bit_for_found) {
|
||||
data = decode_data;
|
||||
data_count_bit = decode_count_bit;
|
||||
// controller
|
||||
serial = (data >> 4) & 0xFFFF;
|
||||
btn = (data >> 2 & 0x03);
|
||||
if (callback) callback(this);
|
||||
}
|
||||
parser_step = MastercodeDecoderStepSaveDuration;
|
||||
decode_data = 0;
|
||||
decode_count_bit = 0;
|
||||
|
||||
} else {
|
||||
parser_step = MastercodeDecoderStepReset;
|
||||
}
|
||||
} else {
|
||||
parser_step = MastercodeDecoderStepReset;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
#endif
|
104
firmware/baseband/fprotos/s-megacode.hpp
Normal file
104
firmware/baseband/fprotos/s-megacode.hpp
Normal file
|
@ -0,0 +1,104 @@
|
|||
|
||||
#ifndef __FPROTO_MEGACODE_H__
|
||||
#define __FPROTO_MEGACODE_H__
|
||||
|
||||
#include "subghzdbase.hpp"
|
||||
|
||||
typedef enum : uint8_t {
|
||||
MegaCodeDecoderStepReset = 0,
|
||||
MegaCodeDecoderStepFoundStartBit,
|
||||
MegaCodeDecoderStepSaveDuration,
|
||||
MegaCodeDecoderStepCheckDuration,
|
||||
} MegaCodeDecoderStep;
|
||||
|
||||
class FProtoSubGhzDMegacode : public FProtoSubGhzDBase {
|
||||
public:
|
||||
FProtoSubGhzDMegacode() {
|
||||
sensorType = FPS_MEGACODE;
|
||||
te_short = 1000;
|
||||
te_long = 1000;
|
||||
te_delta = 200;
|
||||
min_count_bit_for_found = 24;
|
||||
}
|
||||
|
||||
void feed(bool level, uint32_t duration) {
|
||||
switch (parser_step) {
|
||||
case MegaCodeDecoderStepReset:
|
||||
if ((!level) && (DURATION_DIFF(duration, te_short * 13) < te_delta * 17)) { // 10..16ms
|
||||
// Found header MegaCode
|
||||
parser_step = MegaCodeDecoderStepFoundStartBit;
|
||||
}
|
||||
break;
|
||||
case MegaCodeDecoderStepFoundStartBit:
|
||||
if (level && (DURATION_DIFF(duration, te_short) < te_delta)) {
|
||||
// Found start bit MegaCode
|
||||
parser_step = MegaCodeDecoderStepSaveDuration;
|
||||
decode_data = 0;
|
||||
decode_count_bit = 0;
|
||||
subghz_protocol_blocks_add_bit(1);
|
||||
last_bit = 1;
|
||||
|
||||
} else {
|
||||
parser_step = MegaCodeDecoderStepReset;
|
||||
}
|
||||
break;
|
||||
case MegaCodeDecoderStepSaveDuration:
|
||||
if (!level) { // save interval
|
||||
if (duration >= (te_short * 10)) {
|
||||
parser_step = MegaCodeDecoderStepReset;
|
||||
if (decode_count_bit ==
|
||||
min_count_bit_for_found) {
|
||||
data = decode_data;
|
||||
data_count_bit = decode_count_bit;
|
||||
// controller
|
||||
if ((data >> 23) == 1) {
|
||||
serial = (data >> 3) & 0xFFFF;
|
||||
btn = data & 0b111;
|
||||
cnt = (data >> 19) & 0b1111;
|
||||
} else {
|
||||
serial = 0;
|
||||
btn = 0;
|
||||
cnt = 0;
|
||||
}
|
||||
if (callback) callback(this);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
if (!last_bit) {
|
||||
te_last = duration - te_short * 3;
|
||||
} else {
|
||||
te_last = duration;
|
||||
}
|
||||
parser_step = MegaCodeDecoderStepCheckDuration;
|
||||
} else {
|
||||
parser_step = MegaCodeDecoderStepReset;
|
||||
}
|
||||
break;
|
||||
case MegaCodeDecoderStepCheckDuration:
|
||||
if (level) {
|
||||
if ((DURATION_DIFF(te_last, te_short * 5) < te_delta * 5) &&
|
||||
(DURATION_DIFF(duration, te_short) < te_delta)) {
|
||||
subghz_protocol_blocks_add_bit(1);
|
||||
last_bit = 1;
|
||||
parser_step = MegaCodeDecoderStepSaveDuration;
|
||||
} else if (
|
||||
(DURATION_DIFF(te_last, te_short * 2) < te_delta * 2) &&
|
||||
(DURATION_DIFF(duration, te_short) < te_delta)) {
|
||||
subghz_protocol_blocks_add_bit(0);
|
||||
last_bit = 0;
|
||||
parser_step = MegaCodeDecoderStepSaveDuration;
|
||||
} else
|
||||
parser_step = MegaCodeDecoderStepReset;
|
||||
} else {
|
||||
parser_step = MegaCodeDecoderStepReset;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
protected:
|
||||
uint8_t last_bit = false;
|
||||
};
|
||||
|
||||
#endif
|
108
firmware/baseband/fprotos/s-nero_sketch.hpp
Normal file
108
firmware/baseband/fprotos/s-nero_sketch.hpp
Normal file
|
@ -0,0 +1,108 @@
|
|||
|
||||
#ifndef __FPROTO_NEROSKETCH_H__
|
||||
#define __FPROTO_NEROSKETCH_H__
|
||||
|
||||
#include "subghzdbase.hpp"
|
||||
|
||||
typedef enum : uint8_t {
|
||||
NeroSketchDecoderStepReset = 0,
|
||||
NeroSketchDecoderStepCheckPreambula,
|
||||
NeroSketchDecoderStepSaveDuration,
|
||||
NeroSketchDecoderStepCheckDuration,
|
||||
} NeroSketchDecoderStep;
|
||||
|
||||
class FProtoSubGhzDNeroSketch : public FProtoSubGhzDBase {
|
||||
public:
|
||||
FProtoSubGhzDNeroSketch() {
|
||||
sensorType = FPS_NERO_SKETCH;
|
||||
te_short = 330;
|
||||
te_long = 660;
|
||||
te_delta = 150;
|
||||
min_count_bit_for_found = 40;
|
||||
}
|
||||
|
||||
void feed(bool level, uint32_t duration) {
|
||||
switch (parser_step) {
|
||||
case NeroSketchDecoderStepReset:
|
||||
if ((level) && (DURATION_DIFF(duration, te_short) < te_delta)) {
|
||||
parser_step = NeroSketchDecoderStepCheckPreambula;
|
||||
te_last = duration;
|
||||
header_count = 0;
|
||||
}
|
||||
break;
|
||||
case NeroSketchDecoderStepCheckPreambula:
|
||||
if (level) {
|
||||
if ((DURATION_DIFF(duration, te_short) < te_delta) ||
|
||||
(DURATION_DIFF(duration, te_short * 4) < te_delta)) {
|
||||
te_last = duration;
|
||||
} else {
|
||||
parser_step = NeroSketchDecoderStepReset;
|
||||
}
|
||||
} else if (
|
||||
DURATION_DIFF(duration, te_short) < te_delta) {
|
||||
if (DURATION_DIFF(te_last, te_short) < te_delta) {
|
||||
// Found header
|
||||
header_count++;
|
||||
break;
|
||||
} else if (
|
||||
DURATION_DIFF(te_last, te_short * 4) < te_delta) {
|
||||
// Found start bit
|
||||
if (header_count > 40) {
|
||||
parser_step = NeroSketchDecoderStepSaveDuration;
|
||||
decode_data = 0;
|
||||
decode_count_bit = 0;
|
||||
} else {
|
||||
parser_step = NeroSketchDecoderStepReset;
|
||||
}
|
||||
} else {
|
||||
parser_step = NeroSketchDecoderStepReset;
|
||||
}
|
||||
} else {
|
||||
parser_step = NeroSketchDecoderStepReset;
|
||||
}
|
||||
break;
|
||||
case NeroSketchDecoderStepSaveDuration:
|
||||
if (level) {
|
||||
if (duration >= (te_short * 2 + te_delta * 2)) {
|
||||
// Found stop bit
|
||||
parser_step = NeroSketchDecoderStepReset;
|
||||
if (decode_count_bit == min_count_bit_for_found) {
|
||||
data = decode_data;
|
||||
data_count_bit = decode_count_bit;
|
||||
if (callback) callback(this);
|
||||
}
|
||||
decode_data = 0;
|
||||
decode_count_bit = 0;
|
||||
break;
|
||||
} else {
|
||||
te_last = duration;
|
||||
parser_step = NeroSketchDecoderStepCheckDuration;
|
||||
}
|
||||
|
||||
} else {
|
||||
parser_step = NeroSketchDecoderStepReset;
|
||||
}
|
||||
break;
|
||||
case NeroSketchDecoderStepCheckDuration:
|
||||
if (!level) {
|
||||
if ((DURATION_DIFF(te_last, te_short) < te_delta) &&
|
||||
(DURATION_DIFF(duration, te_long) < te_delta)) {
|
||||
subghz_protocol_blocks_add_bit(0);
|
||||
parser_step = NeroSketchDecoderStepSaveDuration;
|
||||
} else if (
|
||||
(DURATION_DIFF(te_last, te_long) < te_delta) &&
|
||||
(DURATION_DIFF(duration, te_short) < te_delta)) {
|
||||
subghz_protocol_blocks_add_bit(1);
|
||||
parser_step = NeroSketchDecoderStepSaveDuration;
|
||||
} else {
|
||||
parser_step = NeroSketchDecoderStepReset;
|
||||
}
|
||||
} else {
|
||||
parser_step = NeroSketchDecoderStepReset;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
#endif
|
115
firmware/baseband/fprotos/s-neroradio.hpp
Normal file
115
firmware/baseband/fprotos/s-neroradio.hpp
Normal file
|
@ -0,0 +1,115 @@
|
|||
|
||||
#ifndef __FPROTO_NERORADIO_H__
|
||||
#define __FPROTO_NERORADIO_H__
|
||||
|
||||
#include "subghzdbase.hpp"
|
||||
|
||||
typedef enum : uint8_t {
|
||||
NeroRadioDecoderStepReset = 0,
|
||||
NeroRadioDecoderStepCheckPreambula,
|
||||
NeroRadioDecoderStepSaveDuration,
|
||||
NeroRadioDecoderStepCheckDuration,
|
||||
} NeroRadioDecoderStep;
|
||||
|
||||
class FProtoSubGhzDNeroRadio : public FProtoSubGhzDBase {
|
||||
public:
|
||||
FProtoSubGhzDNeroRadio() {
|
||||
sensorType = FPS_NERORADIO;
|
||||
te_short = 200;
|
||||
te_long = 400;
|
||||
te_delta = 80;
|
||||
min_count_bit_for_found = 56;
|
||||
}
|
||||
|
||||
void feed(bool level, uint32_t duration) {
|
||||
switch (parser_step) {
|
||||
case NeroRadioDecoderStepReset:
|
||||
if ((level) && (DURATION_DIFF(duration, te_short) < te_delta)) {
|
||||
parser_step = NeroRadioDecoderStepCheckPreambula;
|
||||
te_last = duration;
|
||||
header_count = 0;
|
||||
}
|
||||
break;
|
||||
case NeroRadioDecoderStepCheckPreambula:
|
||||
if (level) {
|
||||
if ((DURATION_DIFF(duration, te_short) < te_delta) ||
|
||||
(DURATION_DIFF(duration, te_short * 4) < te_delta)) {
|
||||
te_last = duration;
|
||||
} else {
|
||||
parser_step = NeroRadioDecoderStepReset;
|
||||
}
|
||||
} else if (
|
||||
DURATION_DIFF(duration, te_short) < te_delta) {
|
||||
if (DURATION_DIFF(te_last, te_short) < te_delta) {
|
||||
// Found header
|
||||
header_count++;
|
||||
break;
|
||||
} else if (
|
||||
DURATION_DIFF(te_last, te_short * 4) < te_delta) {
|
||||
// Found start bit
|
||||
if (header_count > 40) {
|
||||
parser_step = NeroRadioDecoderStepSaveDuration;
|
||||
decode_data = 0;
|
||||
decode_count_bit = 0;
|
||||
} else {
|
||||
parser_step = NeroRadioDecoderStepReset;
|
||||
}
|
||||
} else {
|
||||
parser_step = NeroRadioDecoderStepReset;
|
||||
}
|
||||
} else {
|
||||
parser_step = NeroRadioDecoderStepReset;
|
||||
}
|
||||
break;
|
||||
case NeroRadioDecoderStepSaveDuration:
|
||||
if (level) {
|
||||
te_last = duration;
|
||||
parser_step = NeroRadioDecoderStepCheckDuration;
|
||||
} else {
|
||||
parser_step = NeroRadioDecoderStepReset;
|
||||
}
|
||||
break;
|
||||
case NeroRadioDecoderStepCheckDuration:
|
||||
if (!level) {
|
||||
if (duration >= ((uint32_t)1250)) {
|
||||
// Found stop bit
|
||||
if (DURATION_DIFF(te_last, te_short) < te_delta) {
|
||||
subghz_protocol_blocks_add_bit(0);
|
||||
} else if (
|
||||
DURATION_DIFF(te_last, te_long) < te_delta) {
|
||||
subghz_protocol_blocks_add_bit(1);
|
||||
}
|
||||
parser_step = NeroRadioDecoderStepReset;
|
||||
if ((decode_count_bit == min_count_bit_for_found) ||
|
||||
(decode_count_bit == min_count_bit_for_found + 1)) {
|
||||
data = decode_data;
|
||||
data_count_bit = decode_count_bit;
|
||||
|
||||
if (callback) callback(this);
|
||||
}
|
||||
decode_data = 0;
|
||||
decode_count_bit = 0;
|
||||
parser_step = NeroRadioDecoderStepReset; //-V1048
|
||||
break;
|
||||
} else if (
|
||||
(DURATION_DIFF(te_last, te_short) < te_delta) &&
|
||||
(DURATION_DIFF(duration, te_long) < te_delta)) {
|
||||
subghz_protocol_blocks_add_bit(0);
|
||||
parser_step = NeroRadioDecoderStepSaveDuration;
|
||||
} else if (
|
||||
(DURATION_DIFF(te_last, te_long) < te_delta) &&
|
||||
(DURATION_DIFF(duration, te_short) < te_delta)) {
|
||||
subghz_protocol_blocks_add_bit(1);
|
||||
parser_step = NeroRadioDecoderStepSaveDuration;
|
||||
} else {
|
||||
parser_step = NeroRadioDecoderStepReset;
|
||||
}
|
||||
} else {
|
||||
parser_step = NeroRadioDecoderStepReset;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
#endif
|
86
firmware/baseband/fprotos/s-nice_flo.hpp
Normal file
86
firmware/baseband/fprotos/s-nice_flo.hpp
Normal file
|
@ -0,0 +1,86 @@
|
|||
|
||||
#ifndef __FPROTO_NICE_FLO_H__
|
||||
#define __FPROTO_NICE_FLO_H__
|
||||
|
||||
#include "subghzdbase.hpp"
|
||||
|
||||
typedef enum : uint8_t {
|
||||
NiceFloDecoderStepReset = 0,
|
||||
NiceFloDecoderStepFoundStartBit,
|
||||
NiceFloDecoderStepSaveDuration,
|
||||
NiceFloDecoderStepCheckDuration,
|
||||
} NiceFloDecoderStep;
|
||||
|
||||
class FProtoSubGhzDNiceflo : public FProtoSubGhzDBase {
|
||||
public:
|
||||
FProtoSubGhzDNiceflo() {
|
||||
sensorType = FPS_NICEFLO;
|
||||
te_short = 700;
|
||||
te_long = 1400;
|
||||
te_delta = 200;
|
||||
min_count_bit_for_found = 12;
|
||||
}
|
||||
|
||||
void feed(bool level, uint32_t duration) {
|
||||
switch (parser_step) {
|
||||
case NiceFloDecoderStepReset:
|
||||
if ((!level) && (DURATION_DIFF(duration, te_short * 36) < te_delta * 36)) {
|
||||
// Found header Nice Flo
|
||||
parser_step = NiceFloDecoderStepFoundStartBit;
|
||||
}
|
||||
break;
|
||||
case NiceFloDecoderStepFoundStartBit:
|
||||
if (!level) {
|
||||
break;
|
||||
} else if (
|
||||
DURATION_DIFF(duration, te_short) < te_delta) {
|
||||
// Found start bit Nice Flo
|
||||
parser_step = NiceFloDecoderStepSaveDuration;
|
||||
decode_data = 0;
|
||||
decode_count_bit = 0;
|
||||
} else {
|
||||
parser_step = NiceFloDecoderStepReset;
|
||||
}
|
||||
break;
|
||||
case NiceFloDecoderStepSaveDuration:
|
||||
if (!level) { // save interval
|
||||
if (duration >= (te_short * 4)) {
|
||||
parser_step = NiceFloDecoderStepFoundStartBit;
|
||||
if (decode_count_bit >= min_count_bit_for_found) {
|
||||
serial = SD_NO_SERIAL;
|
||||
btn = SD_NO_BTN;
|
||||
|
||||
data = decode_data;
|
||||
data_count_bit = decode_count_bit;
|
||||
if (callback) callback(this);
|
||||
}
|
||||
break;
|
||||
}
|
||||
te_last = duration;
|
||||
parser_step = NiceFloDecoderStepCheckDuration;
|
||||
} else {
|
||||
parser_step = NiceFloDecoderStepReset;
|
||||
}
|
||||
break;
|
||||
case NiceFloDecoderStepCheckDuration:
|
||||
if (level) {
|
||||
if ((DURATION_DIFF(te_last, te_short) < te_delta) &&
|
||||
(DURATION_DIFF(duration, te_long) < te_delta)) {
|
||||
subghz_protocol_blocks_add_bit(0);
|
||||
parser_step = NiceFloDecoderStepSaveDuration;
|
||||
} else if (
|
||||
(DURATION_DIFF(te_last, te_long) < te_delta) &&
|
||||
(DURATION_DIFF(duration, te_short) < te_delta)) {
|
||||
subghz_protocol_blocks_add_bit(1);
|
||||
parser_step = NiceFloDecoderStepSaveDuration;
|
||||
} else
|
||||
parser_step = NiceFloDecoderStepReset;
|
||||
} else {
|
||||
parser_step = NiceFloDecoderStepReset;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
#endif
|
100
firmware/baseband/fprotos/s-nice_flors.hpp
Normal file
100
firmware/baseband/fprotos/s-nice_flors.hpp
Normal file
|
@ -0,0 +1,100 @@
|
|||
|
||||
#ifndef __FPROTO_NICE_FLORS_H__
|
||||
#define __FPROTO_NICE_FLORS_H__
|
||||
|
||||
#include "subghzdbase.hpp"
|
||||
|
||||
#define NICE_ONE_COUNT_BIT 72
|
||||
|
||||
typedef enum : uint8_t {
|
||||
NiceFlorSDecoderStepReset = 0,
|
||||
NiceFlorSDecoderStepCheckHeader,
|
||||
NiceFlorSDecoderStepFoundHeader,
|
||||
NiceFlorSDecoderStepSaveDuration,
|
||||
NiceFlorSDecoderStepCheckDuration,
|
||||
} NiceFlorSDecoderStep;
|
||||
|
||||
class FProtoSubGhzDNiceflors : public FProtoSubGhzDBase {
|
||||
public:
|
||||
FProtoSubGhzDNiceflors() {
|
||||
sensorType = FPS_NICEFLORS;
|
||||
te_short = 500;
|
||||
te_long = 1000;
|
||||
te_delta = 300;
|
||||
min_count_bit_for_found = 52;
|
||||
}
|
||||
|
||||
void feed(bool level, uint32_t duration) {
|
||||
switch (parser_step) {
|
||||
case NiceFlorSDecoderStepReset:
|
||||
if ((!level) && (DURATION_DIFF(duration, te_short * 38) < te_delta * 38)) {
|
||||
// Found start header Nice Flor-S
|
||||
parser_step = NiceFlorSDecoderStepCheckHeader;
|
||||
}
|
||||
break;
|
||||
case NiceFlorSDecoderStepCheckHeader:
|
||||
if ((level) && (DURATION_DIFF(duration, te_short * 3) < te_delta * 3)) {
|
||||
// Found next header Nice Flor-S
|
||||
parser_step = NiceFlorSDecoderStepFoundHeader;
|
||||
} else {
|
||||
parser_step = NiceFlorSDecoderStepReset;
|
||||
}
|
||||
break;
|
||||
case NiceFlorSDecoderStepFoundHeader:
|
||||
if ((!level) && (DURATION_DIFF(duration, te_short * 3) < te_delta * 3)) {
|
||||
// Found header Nice Flor-S
|
||||
parser_step = NiceFlorSDecoderStepSaveDuration;
|
||||
decode_data = 0;
|
||||
decode_count_bit = 0;
|
||||
} else {
|
||||
parser_step = NiceFlorSDecoderStepReset;
|
||||
}
|
||||
break;
|
||||
case NiceFlorSDecoderStepSaveDuration:
|
||||
if (level) {
|
||||
if (DURATION_DIFF(duration, te_short * 3) < te_delta) {
|
||||
// Found STOP bit
|
||||
parser_step = NiceFlorSDecoderStepReset;
|
||||
if ((decode_count_bit == min_count_bit_for_found) || (decode_count_bit == NICE_ONE_COUNT_BIT)) {
|
||||
data = decode_data;
|
||||
data_count_bit = decode_count_bit;
|
||||
// controller-
|
||||
cnt = SD_NO_CNT;
|
||||
serial = SD_NO_SERIAL;
|
||||
btn = SD_NO_BTN;
|
||||
if (callback) callback(this);
|
||||
}
|
||||
break;
|
||||
} else {
|
||||
// save interval
|
||||
te_last = duration;
|
||||
parser_step = NiceFlorSDecoderStepCheckDuration;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case NiceFlorSDecoderStepCheckDuration:
|
||||
if (!level) {
|
||||
if ((DURATION_DIFF(te_last, te_short) < te_delta) &&
|
||||
(DURATION_DIFF(duration, te_long) < te_delta)) {
|
||||
subghz_protocol_blocks_add_bit(0);
|
||||
parser_step = NiceFlorSDecoderStepSaveDuration;
|
||||
} else if (
|
||||
(DURATION_DIFF(te_last, te_long) < te_delta) &&
|
||||
(DURATION_DIFF(duration, te_short) < te_delta)) {
|
||||
subghz_protocol_blocks_add_bit(1);
|
||||
parser_step = NiceFlorSDecoderStepSaveDuration;
|
||||
} else
|
||||
parser_step = NiceFlorSDecoderStepReset;
|
||||
} else {
|
||||
parser_step = NiceFlorSDecoderStepReset;
|
||||
}
|
||||
if (decode_count_bit == min_count_bit_for_found) {
|
||||
data = decode_data;
|
||||
decode_data = 0;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
#endif
|
89
firmware/baseband/fprotos/s-phoenix_v2.hpp
Normal file
89
firmware/baseband/fprotos/s-phoenix_v2.hpp
Normal file
|
@ -0,0 +1,89 @@
|
|||
|
||||
#ifndef __FPROTO_PHOENIX_V2_H__
|
||||
#define __FPROTO_PHOENIX_V2_H__
|
||||
|
||||
#include "subghzdbase.hpp"
|
||||
|
||||
typedef enum : uint8_t {
|
||||
Phoenix_V2DecoderStepReset = 0,
|
||||
Phoenix_V2DecoderStepFoundStartBit,
|
||||
Phoenix_V2DecoderStepSaveDuration,
|
||||
Phoenix_V2DecoderStepCheckDuration,
|
||||
} Phoenix_V2DecoderStep;
|
||||
|
||||
class FProtoSubGhzDPhoenixV2 : public FProtoSubGhzDBase {
|
||||
public:
|
||||
FProtoSubGhzDPhoenixV2() {
|
||||
sensorType = FPS_PHOENIXV2;
|
||||
te_short = 427;
|
||||
te_long = 853;
|
||||
te_delta = 100;
|
||||
min_count_bit_for_found = 52;
|
||||
}
|
||||
|
||||
void feed(bool level, uint32_t duration) {
|
||||
switch (parser_step) {
|
||||
case Phoenix_V2DecoderStepReset:
|
||||
if ((!level) && (DURATION_DIFF(duration, te_short * 60) < te_delta * 30)) {
|
||||
// Found Preambula
|
||||
parser_step = Phoenix_V2DecoderStepFoundStartBit;
|
||||
}
|
||||
break;
|
||||
case Phoenix_V2DecoderStepFoundStartBit:
|
||||
if (level && ((DURATION_DIFF(duration, (te_short * 6)) < te_delta * 4))) {
|
||||
// Found start bit
|
||||
parser_step = Phoenix_V2DecoderStepSaveDuration;
|
||||
decode_data = 0;
|
||||
decode_count_bit = 0;
|
||||
} else {
|
||||
parser_step = Phoenix_V2DecoderStepReset;
|
||||
}
|
||||
break;
|
||||
case Phoenix_V2DecoderStepSaveDuration:
|
||||
if (!level) {
|
||||
if (duration >= ((uint32_t)te_short * 10 + te_delta)) {
|
||||
parser_step = Phoenix_V2DecoderStepFoundStartBit;
|
||||
if (decode_count_bit ==
|
||||
min_count_bit_for_found) {
|
||||
data = decode_data;
|
||||
data_count_bit = decode_count_bit;
|
||||
// controller
|
||||
uint64_t data_rev = FProtoGeneral::subghz_protocol_blocks_reverse_key(data, data_count_bit + 4);
|
||||
serial = data_rev & 0xFFFFFFFF;
|
||||
cnt = (data_rev >> 40) & 0xFFFF;
|
||||
btn = (data_rev >> 32) & 0xF;
|
||||
|
||||
if (callback) callback(this);
|
||||
}
|
||||
decode_data = 0;
|
||||
decode_count_bit = 0;
|
||||
break;
|
||||
} else {
|
||||
te_last = duration;
|
||||
parser_step = Phoenix_V2DecoderStepCheckDuration;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case Phoenix_V2DecoderStepCheckDuration:
|
||||
if (level) {
|
||||
if ((DURATION_DIFF(te_last, te_short) < te_delta) &&
|
||||
(DURATION_DIFF(duration, te_long) < te_delta * 3)) {
|
||||
subghz_protocol_blocks_add_bit(1);
|
||||
parser_step = Phoenix_V2DecoderStepSaveDuration;
|
||||
} else if (
|
||||
(DURATION_DIFF(te_last, te_long) < te_delta * 3) &&
|
||||
(DURATION_DIFF(duration, te_short) < te_delta)) {
|
||||
subghz_protocol_blocks_add_bit(0);
|
||||
parser_step = Phoenix_V2DecoderStepSaveDuration;
|
||||
} else {
|
||||
parser_step = Phoenix_V2DecoderStepReset;
|
||||
}
|
||||
} else {
|
||||
parser_step = Phoenix_V2DecoderStepReset;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
#endif
|
84
firmware/baseband/fprotos/s-power_smart.hpp
Normal file
84
firmware/baseband/fprotos/s-power_smart.hpp
Normal file
|
@ -0,0 +1,84 @@
|
|||
|
||||
#ifndef __FPROTO_POWER_SMART_H__
|
||||
#define __FPROTO_POWER_SMART_H__
|
||||
|
||||
#include "subghzdbase.hpp"
|
||||
|
||||
#define POWER_SMART_PACKET_HEADER 0xFD000000AA000000
|
||||
#define POWER_SMART_PACKET_HEADER_MASK 0xFF000000FF000000
|
||||
|
||||
typedef enum : uint8_t {
|
||||
PowerSmartDecoderStepReset = 0,
|
||||
PowerSmartDecoderFoundHeader,
|
||||
PowerSmartDecoderStepDecoderData,
|
||||
} PowerSmartDecoderStep;
|
||||
|
||||
class FProtoSubGhzDPowerSmart : public FProtoSubGhzDBase {
|
||||
public:
|
||||
FProtoSubGhzDPowerSmart() {
|
||||
sensorType = FPS_POWERSMART;
|
||||
te_short = 225;
|
||||
te_long = 450;
|
||||
te_delta = 100;
|
||||
min_count_bit_for_found = 64;
|
||||
}
|
||||
|
||||
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 bit_val;
|
||||
bool data_ok = FProtoGeneral::manchester_advance(manchester_saved_state, event, &manchester_saved_state, &bit_val);
|
||||
|
||||
if (data_ok) {
|
||||
decode_data = (decode_data << 1) | !bit_val;
|
||||
}
|
||||
if ((decode_data & POWER_SMART_PACKET_HEADER_MASK) == POWER_SMART_PACKET_HEADER) {
|
||||
if (subghz_protocol_power_smart_chek_valid(decode_data)) {
|
||||
data = decode_data;
|
||||
data_count_bit = min_count_bit_for_found;
|
||||
|
||||
// controller
|
||||
btn = ((data >> 54) & 0x02) | ((data >> 40) & 0x1);
|
||||
serial = ((data >> 33) & 0x3FFF00) | ((data >> 32) & 0xFF);
|
||||
cnt = ((data >> 49) & 0x3F);
|
||||
|
||||
if (callback) callback(this);
|
||||
decode_data = 0;
|
||||
decode_count_bit = 0;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
decode_data = 0;
|
||||
decode_count_bit = 0;
|
||||
FProtoGeneral::manchester_advance(manchester_saved_state, ManchesterEventReset, &manchester_saved_state, NULL);
|
||||
}
|
||||
}
|
||||
|
||||
protected:
|
||||
ManchesterState manchester_saved_state = ManchesterStateMid1;
|
||||
|
||||
bool subghz_protocol_power_smart_chek_valid(uint64_t packet) {
|
||||
uint32_t data_1 = (uint32_t)((packet >> 40) & 0xFFFF);
|
||||
uint32_t data_2 = (uint32_t)((~packet >> 8) & 0xFFFF);
|
||||
uint8_t data_3 = (uint8_t)(packet >> 32) & 0xFF;
|
||||
uint8_t data_4 = (uint8_t)(((~packet) & 0xFF) - 1);
|
||||
return (data_1 == data_2) && (data_3 == data_4);
|
||||
}
|
||||
};
|
||||
|
||||
#endif
|
77
firmware/baseband/fprotos/s-princeton.hpp
Normal file
77
firmware/baseband/fprotos/s-princeton.hpp
Normal file
|
@ -0,0 +1,77 @@
|
|||
|
||||
#ifndef __FPROTO_PRINCETON_H__
|
||||
#define __FPROTO_PRINCETON_H__
|
||||
|
||||
#include "subghzdbase.hpp"
|
||||
|
||||
typedef enum : uint8_t {
|
||||
PrincetonDecoderStepReset = 0,
|
||||
PrincetonDecoderStepSaveDuration,
|
||||
PrincetonDecoderStepCheckDuration,
|
||||
} PrincetonDecoderStep;
|
||||
|
||||
class FProtoSubGhzDPrinceton : public FProtoSubGhzDBase {
|
||||
public:
|
||||
FProtoSubGhzDPrinceton() {
|
||||
sensorType = FPS_PRINCETON;
|
||||
te_short = 390;
|
||||
te_long = 1170;
|
||||
te_delta = 300;
|
||||
min_count_bit_for_found = 24;
|
||||
}
|
||||
|
||||
void feed(bool level, uint32_t duration) {
|
||||
switch (parser_step) {
|
||||
case PrincetonDecoderStepReset:
|
||||
if ((!level) && (DURATION_DIFF(duration, te_short * 36) < te_delta * 36)) {
|
||||
// Found Preambula
|
||||
parser_step = PrincetonDecoderStepSaveDuration;
|
||||
decode_data = 0;
|
||||
decode_count_bit = 0;
|
||||
}
|
||||
break;
|
||||
case PrincetonDecoderStepSaveDuration:
|
||||
// save duration
|
||||
if (level) {
|
||||
te_last = duration;
|
||||
parser_step = PrincetonDecoderStepCheckDuration;
|
||||
}
|
||||
break;
|
||||
case PrincetonDecoderStepCheckDuration:
|
||||
if (!level) {
|
||||
if (duration >= ((uint32_t)te_long * 2)) {
|
||||
parser_step = PrincetonDecoderStepSaveDuration;
|
||||
if (decode_count_bit == min_count_bit_for_found) {
|
||||
data = decode_data;
|
||||
data_count_bit = decode_count_bit;
|
||||
// controller
|
||||
serial = data >> 4;
|
||||
btn = data & 0xF;
|
||||
if (callback) callback(this);
|
||||
}
|
||||
decode_data = 0;
|
||||
decode_count_bit = 0;
|
||||
break;
|
||||
}
|
||||
|
||||
if ((DURATION_DIFF(te_last, te_short) < te_delta) &&
|
||||
(DURATION_DIFF(duration, te_long) < te_delta * 3)) {
|
||||
subghz_protocol_blocks_add_bit(0);
|
||||
parser_step = PrincetonDecoderStepSaveDuration;
|
||||
} else if (
|
||||
(DURATION_DIFF(te_last, te_long) < te_delta * 3) &&
|
||||
(DURATION_DIFF(duration, te_short) < te_delta)) {
|
||||
subghz_protocol_blocks_add_bit(1);
|
||||
parser_step = PrincetonDecoderStepSaveDuration;
|
||||
} else {
|
||||
parser_step = PrincetonDecoderStepReset;
|
||||
}
|
||||
} else {
|
||||
parser_step = PrincetonDecoderStepReset;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
#endif
|
134
firmware/baseband/fprotos/s-secplus_v1.hpp
Normal file
134
firmware/baseband/fprotos/s-secplus_v1.hpp
Normal file
|
@ -0,0 +1,134 @@
|
|||
|
||||
#ifndef __FPROTO_SECPLUSV1_H__
|
||||
#define __FPROTO_SECPLUSV1_H__
|
||||
|
||||
#include "subghzdbase.hpp"
|
||||
#include <string.h>
|
||||
|
||||
#define SECPLUS_V1_BIT_ERR -1 // 0b0000
|
||||
#define SECPLUS_V1_BIT_0 0 // 0b0001
|
||||
#define SECPLUS_V1_BIT_1 1 // 0b0011
|
||||
#define SECPLUS_V1_BIT_2 2 // 0b0111
|
||||
|
||||
#define SECPLUS_V1_PACKET_1_HEADER 0x00
|
||||
#define SECPLUS_V1_PACKET_2_HEADER 0x02
|
||||
#define SECPLUS_V1_PACKET_1_INDEX_BASE 0
|
||||
#define SECPLUS_V1_PACKET_2_INDEX_BASE 21
|
||||
#define SECPLUS_V1_PACKET_1_ACCEPTED (1 << 0)
|
||||
#define SECPLUS_V1_PACKET_2_ACCEPTED (1 << 1)
|
||||
|
||||
typedef enum : uint8_t {
|
||||
SecPlus_v1DecoderStepReset = 0,
|
||||
SecPlus_v1DecoderStepSearchStartBit,
|
||||
SecPlus_v1DecoderStepSaveDuration,
|
||||
SecPlus_v1DecoderStepDecoderData,
|
||||
} SecPlus_v1DecoderStep;
|
||||
|
||||
class FProtoSubGhzDSecPlusV1 : public FProtoSubGhzDBase {
|
||||
public:
|
||||
FProtoSubGhzDSecPlusV1() {
|
||||
sensorType = FPS_SECPLUSV1;
|
||||
te_short = 500;
|
||||
te_long = 1500;
|
||||
te_delta = 100;
|
||||
min_count_bit_for_found = 21;
|
||||
}
|
||||
|
||||
void feed(bool level, uint32_t duration) {
|
||||
switch (parser_step) {
|
||||
case SecPlus_v1DecoderStepReset:
|
||||
if ((!level) && (DURATION_DIFF(duration, te_short * 120) < te_delta * 120)) {
|
||||
// Found header Security+ 1.0
|
||||
parser_step = SecPlus_v1DecoderStepSearchStartBit;
|
||||
decode_data = 0;
|
||||
decode_count_bit = 0;
|
||||
packet_accepted = 0;
|
||||
memset(data_array, 0, sizeof(data_array));
|
||||
}
|
||||
break;
|
||||
case SecPlus_v1DecoderStepSearchStartBit:
|
||||
if (level) {
|
||||
if (DURATION_DIFF(duration, te_short) < te_delta) {
|
||||
base_packet_index = SECPLUS_V1_PACKET_1_INDEX_BASE;
|
||||
data_array[decode_count_bit + base_packet_index] = SECPLUS_V1_BIT_0;
|
||||
decode_count_bit++;
|
||||
parser_step = SecPlus_v1DecoderStepSaveDuration;
|
||||
} else if (
|
||||
DURATION_DIFF(duration, te_long) < te_delta) {
|
||||
base_packet_index = SECPLUS_V1_PACKET_2_INDEX_BASE;
|
||||
data_array[decode_count_bit + base_packet_index] = SECPLUS_V1_BIT_2;
|
||||
decode_count_bit++;
|
||||
parser_step = SecPlus_v1DecoderStepSaveDuration;
|
||||
} else {
|
||||
parser_step = SecPlus_v1DecoderStepReset;
|
||||
}
|
||||
} else {
|
||||
parser_step = SecPlus_v1DecoderStepReset;
|
||||
}
|
||||
break;
|
||||
case SecPlus_v1DecoderStepSaveDuration:
|
||||
if (!level) { // save interval
|
||||
if (DURATION_DIFF(duration, te_short * 120) < te_delta * 120) {
|
||||
if (decode_count_bit == min_count_bit_for_found) {
|
||||
if (base_packet_index == SECPLUS_V1_PACKET_1_INDEX_BASE)
|
||||
packet_accepted |= SECPLUS_V1_PACKET_1_ACCEPTED;
|
||||
if (base_packet_index == SECPLUS_V1_PACKET_2_INDEX_BASE)
|
||||
packet_accepted |= SECPLUS_V1_PACKET_2_ACCEPTED;
|
||||
|
||||
if (packet_accepted == (SECPLUS_V1_PACKET_1_ACCEPTED | SECPLUS_V1_PACKET_2_ACCEPTED)) {
|
||||
// subghz_protocol_secplus_v1_decode(); // disabled doe to lack of flash
|
||||
// controller
|
||||
// uint32_t fixed = (data >> 32) & 0xFFFFFFFF;
|
||||
// cnt = data & 0xFFFFFFFF;
|
||||
// btn = fixed % 3;
|
||||
if (callback) callback(this);
|
||||
parser_step = SecPlus_v1DecoderStepReset;
|
||||
}
|
||||
}
|
||||
parser_step = SecPlus_v1DecoderStepSearchStartBit;
|
||||
decode_data = 0;
|
||||
decode_count_bit = 0;
|
||||
} else {
|
||||
te_last = duration;
|
||||
parser_step = SecPlus_v1DecoderStepDecoderData;
|
||||
}
|
||||
} else {
|
||||
parser_step = SecPlus_v1DecoderStepReset;
|
||||
}
|
||||
break;
|
||||
case SecPlus_v1DecoderStepDecoderData:
|
||||
if (level && (decode_count_bit <= min_count_bit_for_found)) {
|
||||
if ((DURATION_DIFF(te_last, te_short * 3) < te_delta * 3) &&
|
||||
(DURATION_DIFF(duration, te_short) < te_delta)) {
|
||||
data_array[decode_count_bit + base_packet_index] = SECPLUS_V1_BIT_0;
|
||||
decode_count_bit++;
|
||||
parser_step = SecPlus_v1DecoderStepSaveDuration;
|
||||
} else if (
|
||||
(DURATION_DIFF(te_last, te_short * 2) < te_delta * 2) &&
|
||||
(DURATION_DIFF(duration, te_short * 2) < te_delta * 2)) {
|
||||
data_array[decode_count_bit + base_packet_index] = SECPLUS_V1_BIT_1;
|
||||
decode_count_bit++;
|
||||
parser_step = SecPlus_v1DecoderStepSaveDuration;
|
||||
} else if (
|
||||
(DURATION_DIFF(te_last, te_short) < te_delta) &&
|
||||
(DURATION_DIFF(duration, te_short * 3) < te_delta * 3)) {
|
||||
data_array[decode_count_bit + base_packet_index] = SECPLUS_V1_BIT_2;
|
||||
decode_count_bit++;
|
||||
parser_step = SecPlus_v1DecoderStepSaveDuration;
|
||||
} else {
|
||||
parser_step = SecPlus_v1DecoderStepReset;
|
||||
}
|
||||
} else {
|
||||
parser_step = SecPlus_v1DecoderStepReset;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
protected:
|
||||
uint8_t packet_accepted = 0;
|
||||
uint8_t base_packet_index = 0;
|
||||
uint8_t data_array[44];
|
||||
};
|
||||
|
||||
#endif
|
110
firmware/baseband/fprotos/s-secplus_v2.hpp
Normal file
110
firmware/baseband/fprotos/s-secplus_v2.hpp
Normal file
|
@ -0,0 +1,110 @@
|
|||
|
||||
#ifndef __FPROTO_SECPLUSV2_H__
|
||||
#define __FPROTO_SECPLUSV2_H__
|
||||
|
||||
#include "subghzdbase.hpp"
|
||||
|
||||
#define SECPLUS_V2_HEADER 0x3C0000000000
|
||||
#define SECPLUS_V2_HEADER_MASK 0xFFFF3C0000000000
|
||||
#define SECPLUS_V2_PACKET_1 0x000000000000
|
||||
#define SECPLUS_V2_PACKET_2 0x010000000000
|
||||
#define SECPLUS_V2_PACKET_MASK 0x30000000000
|
||||
|
||||
typedef enum : uint8_t {
|
||||
SecPlus_v2DecoderStepReset = 0,
|
||||
SecPlus_v2DecoderStepDecoderData,
|
||||
} SecPlus_v2DecoderStep;
|
||||
|
||||
class FProtoSubGhzDSecPlusV2 : public FProtoSubGhzDBase {
|
||||
public:
|
||||
FProtoSubGhzDSecPlusV2() {
|
||||
sensorType = FPS_SECPLUSV2;
|
||||
te_short = 250;
|
||||
te_long = 500;
|
||||
te_delta = 110;
|
||||
min_count_bit_for_found = 62;
|
||||
}
|
||||
|
||||
void feed(bool level, uint32_t duration) {
|
||||
ManchesterEvent event = ManchesterEventReset;
|
||||
switch (parser_step) {
|
||||
case SecPlus_v2DecoderStepReset:
|
||||
if ((!level) && (DURATION_DIFF(duration, te_long * 130) < te_delta * 100)) {
|
||||
// Found header Security+ 2.0
|
||||
parser_step = SecPlus_v2DecoderStepDecoderData;
|
||||
decode_data = 0;
|
||||
decode_count_bit = 0;
|
||||
secplus_packet_1 = 0;
|
||||
FProtoGeneral::manchester_advance(manchester_saved_state, ManchesterEventReset, &manchester_saved_state, NULL);
|
||||
FProtoGeneral::manchester_advance(manchester_saved_state, ManchesterEventLongHigh, &manchester_saved_state, NULL);
|
||||
FProtoGeneral::manchester_advance(manchester_saved_state, ManchesterEventShortLow, &manchester_saved_state, NULL);
|
||||
}
|
||||
break;
|
||||
case SecPlus_v2DecoderStepDecoderData:
|
||||
if (!level) {
|
||||
if (DURATION_DIFF(duration, te_short) < te_delta) {
|
||||
event = ManchesterEventShortLow;
|
||||
} else if (
|
||||
DURATION_DIFF(duration, te_long) < te_delta) {
|
||||
event = ManchesterEventLongLow;
|
||||
} else if (
|
||||
duration >= (te_long * 2UL + te_delta)) {
|
||||
if (decode_count_bit == min_count_bit_for_found) {
|
||||
data = decode_data;
|
||||
data_count_bit = decode_count_bit;
|
||||
if (subghz_protocol_secplus_v2_check_packet()) {
|
||||
// controller too big
|
||||
if (callback) callback(this);
|
||||
parser_step = SecPlus_v2DecoderStepReset;
|
||||
}
|
||||
}
|
||||
decode_data = 0;
|
||||
decode_count_bit = 0;
|
||||
FProtoGeneral::manchester_advance(manchester_saved_state, ManchesterEventReset, &manchester_saved_state, NULL);
|
||||
FProtoGeneral::manchester_advance(manchester_saved_state, ManchesterEventLongHigh, &manchester_saved_state, NULL);
|
||||
FProtoGeneral::manchester_advance(manchester_saved_state, ManchesterEventShortLow, &manchester_saved_state, NULL);
|
||||
} else {
|
||||
parser_step = SecPlus_v2DecoderStepReset;
|
||||
}
|
||||
} else {
|
||||
if (DURATION_DIFF(duration, te_short) < te_delta) {
|
||||
event = ManchesterEventShortHigh;
|
||||
} else if (
|
||||
DURATION_DIFF(duration, te_long) < te_delta) {
|
||||
event = ManchesterEventLongHigh;
|
||||
} else {
|
||||
parser_step = SecPlus_v2DecoderStepReset;
|
||||
}
|
||||
}
|
||||
if (event != ManchesterEventReset) {
|
||||
bool bit;
|
||||
bool data_ok = FProtoGeneral::manchester_advance(manchester_saved_state, event, &manchester_saved_state, &bit);
|
||||
|
||||
if (data_ok) {
|
||||
decode_data = (decode_data << 1) | bit;
|
||||
decode_count_bit++;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
protected:
|
||||
uint64_t secplus_packet_1 = 0;
|
||||
ManchesterState manchester_saved_state = ManchesterStateMid0;
|
||||
|
||||
bool subghz_protocol_secplus_v2_check_packet() {
|
||||
if ((decode_data & SECPLUS_V2_HEADER_MASK) == SECPLUS_V2_HEADER) {
|
||||
if ((decode_data & SECPLUS_V2_PACKET_MASK) == SECPLUS_V2_PACKET_1) {
|
||||
secplus_packet_1 = decode_data;
|
||||
} else if (
|
||||
((decode_data & SECPLUS_V2_PACKET_MASK) == SECPLUS_V2_PACKET_2) &&
|
||||
(secplus_packet_1)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
};
|
||||
|
||||
#endif
|
74
firmware/baseband/fprotos/s-smc5326.hpp
Normal file
74
firmware/baseband/fprotos/s-smc5326.hpp
Normal file
|
@ -0,0 +1,74 @@
|
|||
|
||||
#ifndef __FPROTO_SMC5326_H__
|
||||
#define __FPROTO_SMC5326_H__
|
||||
|
||||
#include "subghzdbase.hpp"
|
||||
|
||||
typedef enum {
|
||||
SMC5326DecoderStepReset = 0,
|
||||
SMC5326DecoderStepSaveDuration,
|
||||
SMC5326DecoderStepCheckDuration,
|
||||
} SMC5326DecoderStep;
|
||||
|
||||
class FProtoSubGhzDSmc5326 : public FProtoSubGhzDBase {
|
||||
public:
|
||||
FProtoSubGhzDSmc5326() {
|
||||
sensorType = FPS_SECPLUSV2;
|
||||
te_short = 300;
|
||||
te_long = 900;
|
||||
te_delta = 200;
|
||||
min_count_bit_for_found = 25;
|
||||
}
|
||||
|
||||
void feed(bool level, uint32_t duration) {
|
||||
switch (parser_step) {
|
||||
case SMC5326DecoderStepReset:
|
||||
if ((!level) && (DURATION_DIFF(duration, te_short * 24) < te_delta * 12)) {
|
||||
// Found Preambula
|
||||
parser_step = SMC5326DecoderStepSaveDuration;
|
||||
decode_data = 0;
|
||||
decode_count_bit = 0;
|
||||
}
|
||||
break;
|
||||
case SMC5326DecoderStepSaveDuration:
|
||||
// save duration
|
||||
if (level) {
|
||||
te_last = duration;
|
||||
parser_step = SMC5326DecoderStepCheckDuration;
|
||||
}
|
||||
break;
|
||||
case SMC5326DecoderStepCheckDuration:
|
||||
if (!level) {
|
||||
if (duration >= ((uint32_t)te_long * 2)) {
|
||||
parser_step = SMC5326DecoderStepSaveDuration;
|
||||
if (decode_count_bit == min_count_bit_for_found) {
|
||||
data = decode_data;
|
||||
data_count_bit = decode_count_bit;
|
||||
if (callback) callback(this);
|
||||
}
|
||||
decode_data = 0;
|
||||
decode_count_bit = 0;
|
||||
break;
|
||||
}
|
||||
|
||||
if ((DURATION_DIFF(te_last, te_short) < te_delta) &&
|
||||
(DURATION_DIFF(duration, te_long) < te_delta * 3)) {
|
||||
subghz_protocol_blocks_add_bit(0);
|
||||
parser_step = SMC5326DecoderStepSaveDuration;
|
||||
} else if (
|
||||
(DURATION_DIFF(te_last, te_long) < te_delta * 3) &&
|
||||
(DURATION_DIFF(duration, te_short) < te_delta)) {
|
||||
subghz_protocol_blocks_add_bit(1);
|
||||
parser_step = SMC5326DecoderStepSaveDuration;
|
||||
} else {
|
||||
parser_step = SMC5326DecoderStepReset;
|
||||
}
|
||||
} else {
|
||||
parser_step = SMC5326DecoderStepReset;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
#endif
|
106
firmware/baseband/fprotos/s-star_line.hpp
Normal file
106
firmware/baseband/fprotos/s-star_line.hpp
Normal file
|
@ -0,0 +1,106 @@
|
|||
|
||||
#ifndef __FPROTO_STARLINE_H__
|
||||
#define __FPROTO_STARLINE_H__
|
||||
|
||||
#include "subghzdbase.hpp"
|
||||
|
||||
typedef enum {
|
||||
StarLineDecoderStepReset = 0,
|
||||
StarLineDecoderStepCheckPreambula,
|
||||
StarLineDecoderStepSaveDuration,
|
||||
StarLineDecoderStepCheckDuration,
|
||||
} StarLineDecoderStep;
|
||||
|
||||
class FProtoSubGhzDStarLine : public FProtoSubGhzDBase {
|
||||
public:
|
||||
FProtoSubGhzDStarLine() {
|
||||
sensorType = FPS_STARLINE;
|
||||
te_short = 250;
|
||||
te_long = 500;
|
||||
te_delta = 120;
|
||||
min_count_bit_for_found = 64;
|
||||
}
|
||||
|
||||
void feed(bool level, uint32_t duration) {
|
||||
switch (parser_step) {
|
||||
case StarLineDecoderStepReset:
|
||||
if (level) {
|
||||
if (DURATION_DIFF(duration, te_long * 2) < te_delta * 2) {
|
||||
parser_step = StarLineDecoderStepCheckPreambula;
|
||||
header_count++;
|
||||
} else if (header_count > 4) {
|
||||
decode_data = 0;
|
||||
decode_count_bit = 0;
|
||||
te_last = duration;
|
||||
parser_step = StarLineDecoderStepCheckDuration;
|
||||
}
|
||||
} else {
|
||||
header_count = 0;
|
||||
}
|
||||
break;
|
||||
case StarLineDecoderStepCheckPreambula:
|
||||
if ((!level) && (DURATION_DIFF(duration, te_long * 2) < te_delta * 2)) {
|
||||
// Found Preambula
|
||||
parser_step = StarLineDecoderStepReset;
|
||||
} else {
|
||||
header_count = 0;
|
||||
parser_step = StarLineDecoderStepReset;
|
||||
}
|
||||
break;
|
||||
case StarLineDecoderStepSaveDuration:
|
||||
if (level) {
|
||||
if (duration >= (te_long + te_delta)) {
|
||||
parser_step = StarLineDecoderStepReset;
|
||||
if ((decode_count_bit >= min_count_bit_for_found) &&
|
||||
(decode_count_bit <= min_count_bit_for_found + 2)) {
|
||||
if (data != decode_data) {
|
||||
data = decode_data;
|
||||
data_count_bit = min_count_bit_for_found;
|
||||
if (callback) callback(this);
|
||||
}
|
||||
}
|
||||
decode_data = 0;
|
||||
decode_count_bit = 0;
|
||||
header_count = 0;
|
||||
break;
|
||||
} else {
|
||||
te_last = duration;
|
||||
parser_step = StarLineDecoderStepCheckDuration;
|
||||
}
|
||||
|
||||
} else {
|
||||
parser_step = StarLineDecoderStepReset;
|
||||
}
|
||||
break;
|
||||
case StarLineDecoderStepCheckDuration:
|
||||
if (!level) {
|
||||
if ((DURATION_DIFF(te_last, te_short) < te_delta) &&
|
||||
(DURATION_DIFF(duration, te_short) < te_delta)) {
|
||||
if (decode_count_bit < min_count_bit_for_found) {
|
||||
subghz_protocol_blocks_add_bit(0);
|
||||
} else {
|
||||
decode_count_bit++;
|
||||
}
|
||||
parser_step = StarLineDecoderStepSaveDuration;
|
||||
} else if (
|
||||
(DURATION_DIFF(te_last, te_long) < te_delta) &&
|
||||
(DURATION_DIFF(duration, te_long) < te_delta)) {
|
||||
if (decode_count_bit <
|
||||
min_count_bit_for_found) {
|
||||
subghz_protocol_blocks_add_bit(1);
|
||||
} else {
|
||||
decode_count_bit++;
|
||||
}
|
||||
parser_step = StarLineDecoderStepSaveDuration;
|
||||
} else {
|
||||
parser_step = StarLineDecoderStepReset;
|
||||
}
|
||||
} else {
|
||||
parser_step = StarLineDecoderStepReset;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
#endif
|
99
firmware/baseband/fprotos/s-x10.hpp
Normal file
99
firmware/baseband/fprotos/s-x10.hpp
Normal file
|
@ -0,0 +1,99 @@
|
|||
|
||||
#ifndef __FPROTO_X10_H__
|
||||
#define __FPROTO_X10_H__
|
||||
|
||||
#include "subghzdbase.hpp"
|
||||
|
||||
typedef enum {
|
||||
X10DecoderStepReset = 0,
|
||||
X10DecoderStepFoundPreambula,
|
||||
X10DecoderStepSaveDuration,
|
||||
X10DecoderStepCheckDuration,
|
||||
} X10DecoderStep;
|
||||
|
||||
class FProtoSubGhzDX10 : public FProtoSubGhzDBase {
|
||||
public:
|
||||
FProtoSubGhzDX10() {
|
||||
sensorType = FPS_X10;
|
||||
te_short = 600;
|
||||
te_long = 1800;
|
||||
te_delta = 100;
|
||||
min_count_bit_for_found = 32;
|
||||
}
|
||||
|
||||
void feed(bool level, uint32_t duration) {
|
||||
switch (parser_step) {
|
||||
case X10DecoderStepReset:
|
||||
if ((level) && (DURATION_DIFF(duration, te_short * 16) < te_delta * 7)) {
|
||||
parser_step = X10DecoderStepFoundPreambula;
|
||||
}
|
||||
break;
|
||||
case X10DecoderStepFoundPreambula:
|
||||
if ((!level) && (DURATION_DIFF(duration, te_short * 8) < te_delta * 5)) {
|
||||
parser_step = X10DecoderStepSaveDuration;
|
||||
decode_data = 0;
|
||||
decode_count_bit = 0;
|
||||
} else {
|
||||
decode_data = 0;
|
||||
decode_count_bit = 0;
|
||||
parser_step = X10DecoderStepReset;
|
||||
}
|
||||
break;
|
||||
case X10DecoderStepSaveDuration:
|
||||
if (level) {
|
||||
if (DURATION_DIFF(duration, te_short) < te_delta) {
|
||||
if (decode_count_bit == min_count_bit_for_found) {
|
||||
parser_step = X10DecoderStepReset;
|
||||
if (decode_count_bit >= min_count_bit_for_found &&
|
||||
((((decode_data >> 24) ^ (decode_data >> 16)) & 0xFF) == 0xFF) &&
|
||||
((((decode_data >> 8) ^ (decode_data)) & 0xFF) == 0xFF)) {
|
||||
data = decode_data;
|
||||
data_count_bit = decode_count_bit;
|
||||
|
||||
if (callback) callback(this);
|
||||
}
|
||||
decode_data = 0;
|
||||
decode_count_bit = 0;
|
||||
parser_step = X10DecoderStepReset;
|
||||
} else {
|
||||
te_last = duration;
|
||||
parser_step = X10DecoderStepCheckDuration;
|
||||
}
|
||||
} else {
|
||||
decode_data = 0;
|
||||
decode_count_bit = 0;
|
||||
parser_step = X10DecoderStepReset;
|
||||
}
|
||||
} else {
|
||||
decode_data = 0;
|
||||
decode_count_bit = 0;
|
||||
parser_step = X10DecoderStepReset;
|
||||
}
|
||||
break;
|
||||
case X10DecoderStepCheckDuration:
|
||||
if (!level) {
|
||||
if ((DURATION_DIFF(te_last, te_short) < te_delta) &&
|
||||
(DURATION_DIFF(duration, te_short) < te_delta)) {
|
||||
subghz_protocol_blocks_add_bit(0);
|
||||
parser_step = X10DecoderStepSaveDuration;
|
||||
} else if (
|
||||
(DURATION_DIFF(te_last, te_short) < te_delta) &&
|
||||
(DURATION_DIFF(duration, te_long) < te_delta * 2)) {
|
||||
subghz_protocol_blocks_add_bit(1);
|
||||
parser_step = X10DecoderStepSaveDuration;
|
||||
} else {
|
||||
decode_data = 0;
|
||||
decode_count_bit = 0;
|
||||
parser_step = X10DecoderStepReset;
|
||||
}
|
||||
} else {
|
||||
decode_data = 0;
|
||||
decode_count_bit = 0;
|
||||
parser_step = X10DecoderStepReset;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
#endif
|
56
firmware/baseband/fprotos/subghzdbase.hpp
Normal file
56
firmware/baseband/fprotos/subghzdbase.hpp
Normal file
|
@ -0,0 +1,56 @@
|
|||
/*
|
||||
Base class for all weather protocols.
|
||||
This and most of the weather protocols uses code from Flipper XTreme codebase ( https://github.com/Flipper-XFW/Xtreme-Firmware/tree/dev/lib/subghz ). Thanks for their work!
|
||||
For comments in a protocol implementation check w-nexus-th.hpp
|
||||
*/
|
||||
|
||||
#ifndef __FPROTO_SBASE_H__
|
||||
#define __FPROTO_SBASE_H__
|
||||
|
||||
#include "fprotogeneral.hpp"
|
||||
#include "subghztypes.hpp"
|
||||
|
||||
#include <string>
|
||||
// default values to indicate 'no value'
|
||||
|
||||
class FProtoSubGhzDBase;
|
||||
typedef void (*SubGhzDProtocolDecoderBaseRxCallback)(FProtoSubGhzDBase* instance);
|
||||
|
||||
class FProtoSubGhzDBase {
|
||||
public:
|
||||
FProtoSubGhzDBase() {}
|
||||
virtual ~FProtoSubGhzDBase() {}
|
||||
virtual void feed(bool level, uint32_t duration) = 0; // need to be implemented on each protocol handler.
|
||||
void setCallback(SubGhzDProtocolDecoderBaseRxCallback cb) { callback = cb; } // this is called when there is a hit.
|
||||
|
||||
// General data holder, these will be passed
|
||||
uint8_t sensorType = FPS_Invalid;
|
||||
uint8_t btn = SD_NO_BTN;
|
||||
uint16_t data_count_bit = 0;
|
||||
uint32_t cnt = SD_NO_CNT;
|
||||
uint32_t serial = SD_NO_SERIAL;
|
||||
uint64_t data = 0;
|
||||
|
||||
protected:
|
||||
// Helper functions to keep it as compatible with flipper as we can, so adding new protos will be easy.
|
||||
void subghz_protocol_blocks_add_bit(uint8_t bit) {
|
||||
decode_data = decode_data << 1 | bit;
|
||||
decode_count_bit++;
|
||||
}
|
||||
|
||||
// inner logic stuff, also for flipper compatibility.
|
||||
uint32_t te_short = UINT32_MAX;
|
||||
uint32_t te_long = UINT32_MAX;
|
||||
uint32_t te_delta = UINT32_MAX;
|
||||
uint32_t min_count_bit_for_found = UINT32_MAX;
|
||||
|
||||
SubGhzDProtocolDecoderBaseRxCallback callback = NULL;
|
||||
uint16_t header_count = 0;
|
||||
uint8_t parser_step = 0;
|
||||
uint32_t te_last = 0;
|
||||
uint32_t decode_count_bit = 0;
|
||||
uint64_t decode_data = 0;
|
||||
//
|
||||
};
|
||||
|
||||
#endif
|
132
firmware/baseband/fprotos/subghzdprotos.hpp
Normal file
132
firmware/baseband/fprotos/subghzdprotos.hpp
Normal file
|
@ -0,0 +1,132 @@
|
|||
/*
|
||||
This is the protocol list handler. It holds an instance of all known protocols.
|
||||
So include here the .hpp, and add a new element to the protos vector in the constructor. That's all you need to do here if you wanna add a new proto.
|
||||
@htotoo
|
||||
*/
|
||||
|
||||
#include <vector>
|
||||
#include <memory>
|
||||
#include "portapack_shared_memory.hpp"
|
||||
|
||||
#include "fprotolistgeneral.hpp"
|
||||
#include "subghzdbase.hpp"
|
||||
#include "s-princeton.hpp"
|
||||
#include "s-bett.hpp"
|
||||
#include "s-came.hpp"
|
||||
#include "s-came_atomo.hpp"
|
||||
#include "s-came_twee.hpp"
|
||||
#include "s-chambcode.hpp"
|
||||
#include "s-clemsa.hpp"
|
||||
#include "s-doitrand.hpp"
|
||||
#include "s-dooya.hpp"
|
||||
#include "s-faac.hpp"
|
||||
#include "s-gate_tx.hpp"
|
||||
#include "s-holtek.hpp"
|
||||
#include "s-holtek_ht12x.hpp"
|
||||
#include "s-honeywell.hpp"
|
||||
#include "s-honeywellwdb.hpp"
|
||||
#include "s-hormann.hpp"
|
||||
#include "s-ido.hpp"
|
||||
#include "s-intertechnov3.hpp"
|
||||
#include "s-keeloq.hpp"
|
||||
#include "s-kinggates_stylo_4k.hpp"
|
||||
#include "s-linear.hpp"
|
||||
#include "s-linear_delta3.hpp"
|
||||
#include "s-magellan.hpp"
|
||||
#include "s-marantec.hpp"
|
||||
#include "s-mastercode.hpp"
|
||||
#include "s-megacode.hpp"
|
||||
#include "s-neroradio.hpp"
|
||||
#include "s-nero_sketch.hpp"
|
||||
#include "s-nice_flo.hpp"
|
||||
#include "s-nice_flors.hpp"
|
||||
#include "s-phoenix_v2.hpp"
|
||||
#include "s-power_smart.hpp"
|
||||
#include "s-secplus_v1.hpp"
|
||||
#include "s-secplus_v2.hpp"
|
||||
#include "s-smc5326.hpp"
|
||||
#include "s-star_line.hpp"
|
||||
#include "s-x10.hpp"
|
||||
|
||||
// GENIE FROM PR
|
||||
|
||||
#ifndef __FPROTO_PROTOLISTSGZ_H__
|
||||
#define __FPROTO_PROTOLISTSGZ_H__
|
||||
|
||||
class SubGhzDProtos : public FProtoListGeneral {
|
||||
public:
|
||||
SubGhzDProtos(const SubGhzDProtos&) { SubGhzDProtos(); }; // won't use, but makes compiler happy
|
||||
SubGhzDProtos& operator=(const SubGhzDProtos&) { return *this; } // won't use, but makes compiler happy
|
||||
SubGhzDProtos() {
|
||||
// add protos
|
||||
protos[FPS_PRINCETON] = new FProtoSubGhzDPrinceton();
|
||||
protos[FPS_BETT] = new FProtoSubGhzDBett();
|
||||
protos[FPS_CAME] = new FProtoSubGhzDCame();
|
||||
protos[FPS_CAMEATOMO] = new FProtoSubGhzDCameAtomo();
|
||||
protos[FPS_CAMETWEE] = new FProtoSubGhzDCameTwee();
|
||||
protos[FPS_CHAMBCODE] = new FProtoSubGhzDChambCode();
|
||||
protos[FPS_CLEMSA] = new FProtoSubGhzDClemsa();
|
||||
protos[FPS_DOITRAND] = new FProtoSubGhzDDoitrand();
|
||||
protos[FPS_DOOYA] = new FProtoSubGhzDDooya();
|
||||
protos[FPS_FAAC] = new FProtoSubGhzDFaac();
|
||||
protos[FPS_GATETX] = new FProtoSubGhzDGateTx();
|
||||
protos[FPS_HOLTEK] = new FProtoSubGhzDHoltek();
|
||||
protos[FPS_HOLTEKHT12X] = new FProtoSubGhzDHoltekHt12x();
|
||||
protos[FPS_HONEYWELL] = new FProtoSubGhzDHoneywell();
|
||||
protos[FPS_HONEYWELLWDB] = new FProtoSubGhzDHoneywellWdb();
|
||||
protos[FPS_HORMANN] = new FProtoSubGhzDHormann();
|
||||
protos[FPS_IDO] = new FProtoSubGhzDIdo();
|
||||
protos[FPS_INTERTECHNOV3] = new FProtoSubGhzDIntertechnoV3();
|
||||
protos[FPS_KEELOQ] = new FProtoSubGhzDKeeLoq();
|
||||
protos[FPS_KINGGATESSTYLO4K] = new FProtoSubGhzDKinggatesStylo4K();
|
||||
protos[FPS_LINEAR] = new FProtoSubGhzDLinear();
|
||||
protos[FPS_LINEARDELTA3] = new FProtoSubGhzDLinearDelta3();
|
||||
protos[FPS_MAGELLAN] = new FProtoSubGhzDMagellan();
|
||||
protos[FPS_MARANTEC] = new FProtoSubGhzDMarantec();
|
||||
protos[FPS_MASTERCODE] = new FProtoSubGhzDMastercode();
|
||||
protos[FPS_MEGACODE] = new FProtoSubGhzDMegacode();
|
||||
protos[FPS_NERORADIO] = new FProtoSubGhzDNeroRadio();
|
||||
protos[FPS_NERO_SKETCH] = new FProtoSubGhzDNeroSketch();
|
||||
protos[FPS_NICEFLO] = new FProtoSubGhzDNiceflo();
|
||||
protos[FPS_NICEFLORS] = new FProtoSubGhzDNiceflors();
|
||||
protos[FPS_PHOENIXV2] = new FProtoSubGhzDPhoenixV2();
|
||||
protos[FPS_POWERSMART] = new FProtoSubGhzDPowerSmart();
|
||||
protos[FPS_SECPLUSV1] = new FProtoSubGhzDSecPlusV1();
|
||||
protos[FPS_SECPLUSV2] = new FProtoSubGhzDSecPlusV2();
|
||||
protos[FPS_SMC5326] = new FProtoSubGhzDSmc5326();
|
||||
// somify keytis skipped
|
||||
// somify telis skipped
|
||||
protos[FPS_STARLINE] = new FProtoSubGhzDStarLine();
|
||||
protos[FPS_X10] = new FProtoSubGhzDX10();
|
||||
// genie skipped
|
||||
|
||||
for (uint8_t i = 0; i < FPS_COUNT; ++i) {
|
||||
if (protos[i] != NULL) protos[i]->setCallback(callbackTarget);
|
||||
}
|
||||
}
|
||||
|
||||
~SubGhzDProtos() { // not needed for current operation logic, but a bit more elegant :)
|
||||
for (uint8_t i = 0; i < FPS_COUNT; ++i) {
|
||||
if (protos[i] != NULL) {
|
||||
free(protos[i]);
|
||||
protos[i] = NULL;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
static void callbackTarget(FProtoSubGhzDBase* instance) {
|
||||
SubGhzDDataMessage packet_message{instance->sensorType, instance->btn, instance->data_count_bit, instance->serial, instance->data, instance->cnt};
|
||||
shared_memory.application_queue.push(packet_message);
|
||||
}
|
||||
|
||||
void feed(bool level, uint32_t duration) {
|
||||
for (uint8_t i = 0; i < FPS_COUNT; ++i) {
|
||||
if (protos[i] != NULL) protos[i]->feed(level, duration);
|
||||
}
|
||||
}
|
||||
|
||||
protected:
|
||||
FProtoSubGhzDBase* protos[FPS_COUNT] = {NULL};
|
||||
};
|
||||
|
||||
#endif
|
63
firmware/baseband/fprotos/subghztypes.hpp
Normal file
63
firmware/baseband/fprotos/subghztypes.hpp
Normal file
|
@ -0,0 +1,63 @@
|
|||
|
||||
#ifndef __FPROTO_SUBGHZDTYPES_H__
|
||||
#define __FPROTO_SUBGHZDTYPES_H__
|
||||
|
||||
/*
|
||||
Define known protocols.
|
||||
These values must be present on the protocol's constructor, like FProtoWeatherAcurite592TXR() { sensorType = FPS_ANSONIC; }
|
||||
Also it must have a switch-case element in the getSubGhzDSensorTypeName() function, to display it's name.
|
||||
*/
|
||||
|
||||
#define FPM_AM 0
|
||||
#define FPM_FM 1
|
||||
|
||||
#define SD_NO_SERIAL 0xFFFFFFFF
|
||||
#define SD_NO_BTN 0xFF
|
||||
#define SD_NO_CNT 0xFF
|
||||
|
||||
enum FPROTO_SUBGHZD_SENSOR : uint8_t {
|
||||
FPS_Invalid = 0,
|
||||
FPS_PRINCETON,
|
||||
FPS_BETT,
|
||||
FPS_CAME,
|
||||
FPS_PRASTEL,
|
||||
FPS_AIRFORCE,
|
||||
FPS_CAMEATOMO,
|
||||
FPS_CAMETWEE,
|
||||
FPS_CHAMBCODE,
|
||||
FPS_CLEMSA,
|
||||
FPS_DOITRAND,
|
||||
FPS_DOOYA,
|
||||
FPS_FAAC,
|
||||
FPS_GATETX,
|
||||
FPS_HOLTEK,
|
||||
FPS_HOLTEKHT12X,
|
||||
FPS_HONEYWELL,
|
||||
FPS_HONEYWELLWDB,
|
||||
FPS_HORMANN,
|
||||
FPS_IDO,
|
||||
FPS_INTERTECHNOV3,
|
||||
FPS_KEELOQ,
|
||||
FPS_KINGGATESSTYLO4K,
|
||||
FPS_LINEAR,
|
||||
FPS_LINEARDELTA3,
|
||||
FPS_MAGELLAN,
|
||||
FPS_MARANTEC,
|
||||
FPS_MASTERCODE,
|
||||
FPS_MEGACODE,
|
||||
FPS_NERORADIO,
|
||||
FPS_NERO_SKETCH,
|
||||
FPS_NICEFLO,
|
||||
FPS_NICEFLORS,
|
||||
FPS_PHOENIXV2,
|
||||
FPS_POWERSMART,
|
||||
FPS_SECPLUSV1,
|
||||
FPS_SECPLUSV2,
|
||||
FPS_SMC5326,
|
||||
FPS_STARLINE,
|
||||
FPS_X10,
|
||||
|
||||
FPS_COUNT
|
||||
};
|
||||
|
||||
#endif
|
|
@ -130,9 +130,9 @@ class FProtoWeatherAcurite592TXR : public FProtoWeatherBase {
|
|||
static_cast<uint8_t>(decode_data >> 16),
|
||||
static_cast<uint8_t>(decode_data >> 8)};
|
||||
|
||||
if ((subghz_protocol_blocks_add_bytes(msg, 6) ==
|
||||
if ((FProtoGeneral::subghz_protocol_blocks_add_bytes(msg, 6) ==
|
||||
(uint8_t)(decode_data & 0xFF)) &&
|
||||
(!subghz_protocol_blocks_parity_bytes(&msg[2], 4))) {
|
||||
(!FProtoGeneral::subghz_protocol_blocks_parity_bytes(&msg[2], 4))) {
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
|
|
|
@ -102,7 +102,7 @@ class FProtoWeatherAcurite606TX : public FProtoWeatherBase {
|
|||
static_cast<uint8_t>(decode_data >> 16),
|
||||
static_cast<uint8_t>(decode_data >> 8)};
|
||||
|
||||
uint8_t crc = subghz_protocol_blocks_lfsr_digest8(msg, 3, 0x98, 0xF1);
|
||||
uint8_t crc = FProtoGeneral::subghz_protocol_blocks_lfsr_digest8(msg, 3, 0x98, 0xF1);
|
||||
return (crc == (decode_data & 0xFF));
|
||||
}
|
||||
};
|
||||
|
|
|
@ -108,16 +108,16 @@ class FProtoWeatherAcurite986 : public FProtoWeatherBase {
|
|||
void ws_protocol_acurite_986_remote_controller() {
|
||||
int temp;
|
||||
|
||||
id = subghz_protocol_blocks_reverse_key(data >> 24, 8);
|
||||
id = (id << 8) | subghz_protocol_blocks_reverse_key(data >> 16, 8);
|
||||
id = FProtoGeneral::subghz_protocol_blocks_reverse_key(data >> 24, 8);
|
||||
id = (id << 8) | FProtoGeneral::subghz_protocol_blocks_reverse_key(data >> 16, 8);
|
||||
battery_low = (data >> 14) & 1;
|
||||
channel = ((data >> 15) & 1) + 1;
|
||||
|
||||
temp = subghz_protocol_blocks_reverse_key(data >> 32, 8);
|
||||
temp = FProtoGeneral::subghz_protocol_blocks_reverse_key(data >> 32, 8);
|
||||
if (temp & 0x80) {
|
||||
temp = -(temp & 0x7F);
|
||||
}
|
||||
temp = locale_fahrenheit_to_celsius((float)temp);
|
||||
temp = FProtoGeneral::locale_fahrenheit_to_celsius((float)temp);
|
||||
btn = WS_NO_BTN;
|
||||
humidity = WS_NO_HUMIDITY;
|
||||
}
|
||||
|
@ -130,7 +130,7 @@ class FProtoWeatherAcurite986 : public FProtoWeatherBase {
|
|||
(uint8_t)(decode_data >> 16),
|
||||
(uint8_t)(decode_data >> 8)};
|
||||
|
||||
uint8_t crc = subghz_protocol_blocks_crc8(msg, 4, 0x07, 0x00);
|
||||
uint8_t crc = FProtoGeneral::subghz_protocol_blocks_crc8(msg, 4, 0x07, 0x00);
|
||||
return (crc == (decode_data & 0xFF));
|
||||
}
|
||||
};
|
||||
|
|
|
@ -32,11 +32,11 @@ class FProtoWeatherAmbient : public FProtoWeatherBase {
|
|||
}
|
||||
}
|
||||
if (event != ManchesterEventReset) {
|
||||
bool data;
|
||||
bool data_ok = manchester_advance(manchester_saved_state, event, &manchester_saved_state, &data);
|
||||
bool bit;
|
||||
bool data_ok = FProtoGeneral::manchester_advance(manchester_saved_state, event, &manchester_saved_state, &bit);
|
||||
|
||||
if (data_ok) {
|
||||
decode_data = (decode_data << 1) | !data;
|
||||
decode_data = (decode_data << 1) | !bit;
|
||||
}
|
||||
|
||||
if (((decode_data & AMBIENT_WEATHER_PACKET_HEADER_MASK) == AMBIENT_WEATHER_PACKET_HEADER_1) ||
|
||||
|
@ -53,7 +53,7 @@ class FProtoWeatherAmbient : public FProtoWeatherBase {
|
|||
} else {
|
||||
decode_data = 0;
|
||||
decode_count_bit = 0;
|
||||
manchester_advance(manchester_saved_state, ManchesterEventReset, &manchester_saved_state, NULL);
|
||||
FProtoGeneral::manchester_advance(manchester_saved_state, ManchesterEventReset, &manchester_saved_state, NULL);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -71,7 +71,7 @@ class FProtoWeatherAmbient : public FProtoWeatherBase {
|
|||
static_cast<uint8_t>(decode_data >> 16),
|
||||
static_cast<uint8_t>(decode_data >> 8)};
|
||||
|
||||
uint8_t crc = subghz_protocol_blocks_lfsr_digest8(msg, 5, 0x98, 0x3e) ^ 0x64;
|
||||
uint8_t crc = FProtoGeneral::subghz_protocol_blocks_lfsr_digest8(msg, 5, 0x98, 0x3e) ^ 0x64;
|
||||
return (crc == (uint8_t)(decode_data & 0xFF));
|
||||
}
|
||||
|
||||
|
@ -79,7 +79,7 @@ class FProtoWeatherAmbient : public FProtoWeatherBase {
|
|||
id = (data >> 32) & 0xFF;
|
||||
battery_low = (data >> 31) & 1;
|
||||
channel = ((data >> 28) & 0x07) + 1;
|
||||
temp = locale_fahrenheit_to_celsius(((float)((data >> 16) & 0x0FFF) - 400.0f) / 10.0f);
|
||||
temp = FProtoGeneral::locale_fahrenheit_to_celsius(((float)((data >> 16) & 0x0FFF) - 400.0f) / 10.0f);
|
||||
humidity = (data >> 8) & 0xFF;
|
||||
btn = WS_NO_BTN;
|
||||
}
|
||||
|
|
|
@ -118,19 +118,16 @@ class FProtoWeatherInfactory : public FProtoWeatherBase {
|
|||
static_cast<uint8_t>(decode_data >> 8),
|
||||
static_cast<uint8_t>(decode_data)};
|
||||
|
||||
uint8_t crc =
|
||||
subghz_protocol_blocks_crc4(msg, 4, 0x13, 0); // Koopmann 0x9, CCITT-4; FP-4; ITU-T G.704
|
||||
crc ^= msg[4] >> 4; // last nibble is only XORed
|
||||
uint8_t crc = FProtoGeneral::subghz_protocol_blocks_crc4(msg, 4, 0x13, 0); // Koopmann 0x9, CCITT-4; FP-4; ITU-T G.704
|
||||
crc ^= msg[4] >> 4; // last nibble is only XORed
|
||||
return (crc == ((decode_data >> 28) & 0x0F));
|
||||
}
|
||||
void ws_protocol_infactory_remote_controller() {
|
||||
id = data >> 32;
|
||||
battery_low = (data >> 26) & 1;
|
||||
btn = WS_NO_BTN;
|
||||
temp =
|
||||
locale_fahrenheit_to_celsius(((float)((data >> 12) & 0x0FFF) - 900.0f) / 10.0f);
|
||||
humidity =
|
||||
(((data >> 8) & 0x0F) * 10) + ((data >> 4) & 0x0F); // BCD, 'A0'=100%rH
|
||||
temp = FProtoGeneral::locale_fahrenheit_to_celsius(((float)((data >> 12) & 0x0FFF) - 900.0f) / 10.0f);
|
||||
humidity = (((data >> 8) & 0x0F) * 10) + ((data >> 4) & 0x0F); // BCD, 'A0'=100%rH
|
||||
channel = data & 0x03;
|
||||
}
|
||||
};
|
||||
|
|
|
@ -155,7 +155,7 @@ class FProtoWeatherLaCrosseTx : public FProtoWeatherBase {
|
|||
static_cast<uint8_t>((decode_data >> 8) & 0x0F),
|
||||
static_cast<uint8_t>((decode_data >> 4) & 0x0F)};
|
||||
|
||||
uint8_t crc = subghz_protocol_blocks_add_bytes(msg, 9);
|
||||
uint8_t crc = FProtoGeneral::subghz_protocol_blocks_add_bytes(msg, 9);
|
||||
return ((crc & 0x0F) == (decode_data & 0x0F));
|
||||
}
|
||||
};
|
||||
|
|
|
@ -104,7 +104,7 @@ class FProtoWeatherLaCrosseTx141thbv2 : public FProtoWeatherBase {
|
|||
}
|
||||
uint8_t msg[] = {static_cast<uint8_t>(data >> 32), static_cast<uint8_t>(data >> 24), static_cast<uint8_t>(data >> 16), static_cast<uint8_t>(data >> 8)};
|
||||
|
||||
uint8_t crc = subghz_protocol_blocks_lfsr_digest8_reflect(msg, 4, 0x31, 0xF4);
|
||||
uint8_t crc = FProtoGeneral::subghz_protocol_blocks_lfsr_digest8_reflect(msg, 4, 0x31, 0xF4);
|
||||
return (crc == (data & 0xFF));
|
||||
}
|
||||
void ws_protocol_lacrosse_tx141thbv2_remote_controller() {
|
||||
|
|
|
@ -77,7 +77,7 @@ class FProtoWeatherOregon2 : public FProtoWeatherBase {
|
|||
decode_data = 0UL;
|
||||
decode_count_bit = 0;
|
||||
}
|
||||
if (manchester_advance(manchester_saved_state, event, &manchester_saved_state, &bit_value)) {
|
||||
if (FProtoGeneral::manchester_advance(manchester_saved_state, event, &manchester_saved_state, &bit_value)) {
|
||||
if (have_bit) {
|
||||
if (!prev_bit && bit_value) {
|
||||
subghz_protocol_blocks_add_bit(1);
|
||||
|
@ -165,7 +165,7 @@ class FProtoWeatherOregon2 : public FProtoWeatherBase {
|
|||
parser_step = Oregon2DecoderStepReset;
|
||||
decode_data = 0UL;
|
||||
decode_count_bit = 0;
|
||||
manchester_advance(manchester_saved_state, ManchesterEventReset, &manchester_saved_state, NULL);
|
||||
FProtoGeneral::manchester_advance(manchester_saved_state, ManchesterEventReset, &manchester_saved_state, NULL);
|
||||
have_bit = false;
|
||||
var_data = 0;
|
||||
var_bits = 0;
|
||||
|
|
|
@ -47,7 +47,7 @@ class FProtoWeatherOregon3 : public FProtoWeatherBase {
|
|||
decode_data = 0UL;
|
||||
decode_count_bit = 0;
|
||||
}
|
||||
if (manchester_advance(
|
||||
if (FProtoGeneral::manchester_advance(
|
||||
manchester_saved_state, event, &manchester_saved_state, &prev_bit)) {
|
||||
subghz_protocol_blocks_add_bit(prev_bit);
|
||||
}
|
||||
|
|
|
@ -64,11 +64,7 @@ class FProtoWeatherOregonV1 : public FProtoWeatherBase {
|
|||
// found all the necessary patterns
|
||||
decode_data = 0;
|
||||
decode_count_bit = 1;
|
||||
manchester_advance(
|
||||
manchester_saved_state,
|
||||
ManchesterEventReset,
|
||||
&manchester_saved_state,
|
||||
NULL);
|
||||
FProtoGeneral::manchester_advance(manchester_saved_state, ManchesterEventReset, &manchester_saved_state, NULL);
|
||||
parser_step = Oregon_V1DecoderStepParse;
|
||||
if (duration < te_short * 4) {
|
||||
first_bit = 1;
|
||||
|
@ -114,22 +110,17 @@ class FProtoWeatherOregonV1 : public FProtoWeatherBase {
|
|||
}
|
||||
decode_data = 0;
|
||||
decode_count_bit = 0;
|
||||
manchester_advance(
|
||||
manchester_saved_state,
|
||||
ManchesterEventReset,
|
||||
&manchester_saved_state,
|
||||
NULL);
|
||||
FProtoGeneral::manchester_advance(manchester_saved_state, ManchesterEventReset, &manchester_saved_state, NULL);
|
||||
} else {
|
||||
parser_step = Oregon_V1DecoderStepReset;
|
||||
}
|
||||
}
|
||||
if (event != ManchesterEventReset) {
|
||||
bool data;
|
||||
bool data_ok = manchester_advance(
|
||||
manchester_saved_state, event, &manchester_saved_state, &data);
|
||||
bool bit;
|
||||
bool data_ok = FProtoGeneral::manchester_advance(manchester_saved_state, event, &manchester_saved_state, &bit);
|
||||
|
||||
if (data_ok) {
|
||||
decode_data = (decode_data << 1) | !data;
|
||||
decode_data = (decode_data << 1) | !bit;
|
||||
decode_count_bit++;
|
||||
}
|
||||
}
|
||||
|
@ -149,13 +140,13 @@ class FProtoWeatherOregonV1 : public FProtoWeatherBase {
|
|||
|
||||
bool ws_protocol_oregon_v1_check() {
|
||||
if (!decode_data) return false;
|
||||
uint64_t data = subghz_protocol_blocks_reverse_key(decode_data, 32);
|
||||
uint64_t data = FProtoGeneral::subghz_protocol_blocks_reverse_key(decode_data, 32);
|
||||
uint16_t crc = (data & 0xff) + ((data >> 8) & 0xff) + ((data >> 16) & 0xff);
|
||||
crc = (crc & 0xff) + ((crc >> 8) & 0xff);
|
||||
return (crc == ((data >> 24) & 0xFF));
|
||||
}
|
||||
void ws_protocol_oregon_v1_remote_controller() {
|
||||
uint64_t data2 = subghz_protocol_blocks_reverse_key(data, 32);
|
||||
uint64_t data2 = FProtoGeneral::subghz_protocol_blocks_reverse_key(data, 32);
|
||||
|
||||
id = data2 & 0xFF;
|
||||
channel = ((data2 >> 6) & 0x03) + 1;
|
||||
|
|
|
@ -128,7 +128,7 @@ class FProtoWeatherWendoxW6726 : public FProtoWeatherBase {
|
|||
static_cast<uint8_t>(decode_data >> 12),
|
||||
static_cast<uint8_t>(decode_data >> 4)};
|
||||
|
||||
uint8_t crc = subghz_protocol_blocks_crc4(msg, 4, 0x9, 0xD);
|
||||
uint8_t crc = FProtoGeneral::subghz_protocol_blocks_crc4(msg, 4, 0x9, 0xD);
|
||||
return (crc == (decode_data & 0x0F));
|
||||
}
|
||||
void ws_protocol_wendox_w6726_remote_controller() {
|
||||
|
|
|
@ -7,33 +7,12 @@ For comments in a protocol implementation check w-nexus-th.hpp
|
|||
#ifndef __FPROTO_BASE_H__
|
||||
#define __FPROTO_BASE_H__
|
||||
|
||||
#define bit_read(value, bit) (((value) >> (bit)) & 0x01)
|
||||
|
||||
#include "fprotogeneral.hpp"
|
||||
#include "weathertypes.hpp"
|
||||
|
||||
#include <string>
|
||||
// default walues to indicate 'no value'
|
||||
#define WS_NO_ID 0xFFFFFFFF
|
||||
#define WS_NO_BATT 0xFF
|
||||
#define WS_NO_HUMIDITY 0xFF
|
||||
#define WS_NO_CHANNEL 0xFF
|
||||
#define WS_NO_BTN 0xFF
|
||||
#define WS_NO_TEMPERATURE -273.0f
|
||||
|
||||
#define DURATION_DIFF(x, y) (((x) < (y)) ? ((y) - (x)) : ((x) - (y)))
|
||||
typedef enum {
|
||||
ManchesterStateStart1 = 0,
|
||||
ManchesterStateMid1 = 1,
|
||||
ManchesterStateMid0 = 2,
|
||||
ManchesterStateStart0 = 3
|
||||
} ManchesterState;
|
||||
typedef enum {
|
||||
ManchesterEventShortLow = 0,
|
||||
ManchesterEventShortHigh = 2,
|
||||
ManchesterEventLongLow = 4,
|
||||
ManchesterEventLongHigh = 6,
|
||||
ManchesterEventReset = 8
|
||||
} ManchesterEvent;
|
||||
class FProtoWeatherBase;
|
||||
typedef void (*SubGhzProtocolDecoderBaseRxCallback)(FProtoWeatherBase* instance);
|
||||
|
||||
|
@ -49,7 +28,6 @@ class FProtoWeatherBase {
|
|||
float getTemp() { return temp; }
|
||||
uint8_t getHumidity() { return humidity; }
|
||||
uint8_t getBattLow() { return battery_low; }
|
||||
uint32_t getTimestamp() { return timestamp; }
|
||||
uint8_t getChannel() { return channel; }
|
||||
uint8_t getButton() { return btn; }
|
||||
|
||||
|
@ -59,149 +37,6 @@ class FProtoWeatherBase {
|
|||
decode_data = decode_data << 1 | bit;
|
||||
decode_count_bit++;
|
||||
}
|
||||
uint8_t subghz_protocol_blocks_add_bytes(uint8_t const message[], size_t size) {
|
||||
uint32_t result = 0;
|
||||
for (size_t i = 0; i < size; ++i) {
|
||||
result += message[i];
|
||||
}
|
||||
return (uint8_t)result;
|
||||
}
|
||||
uint8_t subghz_protocol_blocks_parity8(uint8_t byte) {
|
||||
byte ^= byte >> 4;
|
||||
byte &= 0xf;
|
||||
return (0x6996 >> byte) & 1;
|
||||
}
|
||||
uint8_t subghz_protocol_blocks_parity_bytes(uint8_t const message[], size_t size) {
|
||||
uint8_t result = 0;
|
||||
for (size_t i = 0; i < size; ++i) {
|
||||
result ^= subghz_protocol_blocks_parity8(message[i]);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
uint8_t subghz_protocol_blocks_lfsr_digest8(
|
||||
uint8_t const message[],
|
||||
size_t size,
|
||||
uint8_t gen,
|
||||
uint8_t key) {
|
||||
uint8_t sum = 0;
|
||||
for (size_t byte = 0; byte < size; ++byte) {
|
||||
uint8_t data = message[byte];
|
||||
for (int i = 7; i >= 0; --i) {
|
||||
// XOR key into sum if data bit is set
|
||||
if ((data >> i) & 1) sum ^= key;
|
||||
// roll the key right (actually the LSB is dropped here)
|
||||
// and apply the gen (needs to include the dropped LSB as MSB)
|
||||
if (key & 1)
|
||||
key = (key >> 1) ^ gen;
|
||||
else
|
||||
key = (key >> 1);
|
||||
}
|
||||
}
|
||||
return sum;
|
||||
}
|
||||
float locale_fahrenheit_to_celsius(float temp_f) {
|
||||
return (temp_f - 32.f) / 1.8f;
|
||||
}
|
||||
bool manchester_advance(
|
||||
ManchesterState state,
|
||||
ManchesterEvent event,
|
||||
ManchesterState* next_state,
|
||||
bool* data) {
|
||||
bool result = false;
|
||||
ManchesterState new_state;
|
||||
|
||||
if (event == ManchesterEventReset) {
|
||||
new_state = manchester_reset_state;
|
||||
} else {
|
||||
new_state = (ManchesterState)(transitions[state] >> event & 0x3);
|
||||
if (new_state == state) {
|
||||
new_state = manchester_reset_state;
|
||||
} else {
|
||||
if (new_state == ManchesterStateMid0) {
|
||||
if (data) *data = false;
|
||||
result = true;
|
||||
} else if (new_state == ManchesterStateMid1) {
|
||||
if (data) *data = true;
|
||||
result = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
*next_state = new_state;
|
||||
return result;
|
||||
}
|
||||
uint8_t subghz_protocol_blocks_crc4(
|
||||
uint8_t const message[],
|
||||
size_t size,
|
||||
uint8_t polynomial,
|
||||
uint8_t init) {
|
||||
uint8_t remainder = init << 4; // LSBs are unused
|
||||
uint8_t poly = polynomial << 4;
|
||||
uint8_t bit;
|
||||
|
||||
while (size--) {
|
||||
remainder ^= *message++;
|
||||
for (bit = 0; bit < 8; bit++) {
|
||||
if (remainder & 0x80) {
|
||||
remainder = (remainder << 1) ^ poly;
|
||||
} else {
|
||||
remainder = (remainder << 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
return remainder >> 4 & 0x0f; // discard the LSBs
|
||||
}
|
||||
uint8_t subghz_protocol_blocks_lfsr_digest8_reflect(
|
||||
uint8_t const message[],
|
||||
size_t size,
|
||||
uint8_t gen,
|
||||
uint8_t key) {
|
||||
uint8_t sum = 0;
|
||||
// Process message from last byte to first byte (reflected)
|
||||
for (int byte = size - 1; byte >= 0; --byte) {
|
||||
uint8_t data = message[byte];
|
||||
// Process individual bits of each byte (reflected)
|
||||
for (uint8_t i = 0; i < 8; ++i) {
|
||||
// XOR key into sum if data bit is set
|
||||
if ((data >> i) & 1) {
|
||||
sum ^= key;
|
||||
}
|
||||
// roll the key left (actually the LSB is dropped here)
|
||||
// and apply the gen (needs to include the dropped lsb as MSB)
|
||||
if (key & 0x80)
|
||||
key = (key << 1) ^ gen;
|
||||
else
|
||||
key = (key << 1);
|
||||
}
|
||||
}
|
||||
return sum;
|
||||
}
|
||||
uint64_t subghz_protocol_blocks_reverse_key(uint64_t key, uint8_t bit_count) {
|
||||
uint64_t reverse_key = 0;
|
||||
for (uint8_t i = 0; i < bit_count; i++) {
|
||||
reverse_key = reverse_key << 1 | bit_read(key, i);
|
||||
}
|
||||
return reverse_key;
|
||||
}
|
||||
uint8_t subghz_protocol_blocks_crc8(
|
||||
uint8_t const message[],
|
||||
size_t size,
|
||||
uint8_t polynomial,
|
||||
uint8_t init) {
|
||||
uint8_t remainder = init;
|
||||
|
||||
for (size_t byte = 0; byte < size; ++byte) {
|
||||
remainder ^= message[byte];
|
||||
for (uint8_t bit = 0; bit < 8; ++bit) {
|
||||
if (remainder & 0x80) {
|
||||
remainder = (remainder << 1) ^ polynomial;
|
||||
} else {
|
||||
remainder = (remainder << 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
return remainder;
|
||||
}
|
||||
|
||||
// General weather data holder
|
||||
uint8_t sensorType = FPW_Invalid;
|
||||
|
@ -209,11 +44,10 @@ class FProtoWeatherBase {
|
|||
float temp = WS_NO_TEMPERATURE;
|
||||
uint8_t humidity = WS_NO_HUMIDITY;
|
||||
uint8_t battery_low = WS_NO_BATT;
|
||||
uint32_t timestamp = 0;
|
||||
uint8_t channel = WS_NO_CHANNEL;
|
||||
uint8_t btn = WS_NO_BTN;
|
||||
|
||||
// inner logic stuff, also for flipper compatibility. //todo revork a bit, so won't have dupes (decode_data + data, ..), but check if any of the protos uses it in the same time or not. (shouldn't)
|
||||
// inner logic stuff, also for flipper compatibility.
|
||||
SubGhzProtocolDecoderBaseRxCallback callback = NULL;
|
||||
uint16_t header_count = 0;
|
||||
uint8_t parser_step = 0;
|
||||
|
@ -223,8 +57,6 @@ class FProtoWeatherBase {
|
|||
uint64_t decode_data = 0;
|
||||
uint32_t decode_count_bit = 0;
|
||||
ManchesterState manchester_saved_state = ManchesterStateMid1;
|
||||
static const ManchesterState manchester_reset_state = ManchesterStateMid1;
|
||||
static inline const uint8_t transitions[] = {0b00000001, 0b10010001, 0b10011011, 0b11111011};
|
||||
};
|
||||
|
||||
#endif
|
|
@ -3,6 +3,9 @@ This is the protocol list handler. It holds an instance of all known protocols.
|
|||
So include here the .hpp, and add a new element to the protos vector in the constructor. That's all you need to do here if you wanna add a new proto.
|
||||
@htotoo
|
||||
*/
|
||||
|
||||
#include "fprotolistgeneral.hpp"
|
||||
|
||||
#include "w-nexus-th.hpp"
|
||||
#include "w-acurite592txr.hpp"
|
||||
#include "w-acurite606tx.hpp"
|
||||
|
@ -26,10 +29,10 @@ So include here the .hpp, and add a new element to the protos vector in the cons
|
|||
#include <memory>
|
||||
#include "portapack_shared_memory.hpp"
|
||||
|
||||
#ifndef __FPROTO_PROTOLIST_H__
|
||||
#define __FPROTO_PROTOLIST_H__
|
||||
#ifndef __FPROTO_PROTOLISTWTH_H__
|
||||
#define __FPROTO_PROTOLISTWTH_H__
|
||||
|
||||
class WeatherProtos {
|
||||
class WeatherProtos : public FProtoListGeneral {
|
||||
public:
|
||||
WeatherProtos() {
|
||||
// add protos
|
||||
|
|
|
@ -7,6 +7,12 @@ Define known protocols.
|
|||
These values must be present on the protocol's constructor, like FProtoWeatherAcurite592TXR() { sensorType = FPW_Acurite592TXR; }
|
||||
Also it must have a switch-case element in the getWeatherSensorTypeName() function, to display it's name.
|
||||
*/
|
||||
#define WS_NO_ID 0xFFFFFFFF
|
||||
#define WS_NO_BATT 0xFF
|
||||
#define WS_NO_HUMIDITY 0xFF
|
||||
#define WS_NO_CHANNEL 0xFF
|
||||
#define WS_NO_BTN 0xFF
|
||||
#define WS_NO_TEMPERATURE -273.0f
|
||||
|
||||
enum FPROTO_WEATHER_SENSOR {
|
||||
FPW_Invalid = 0,
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue