[FL-2920] WS: add protocol Acurite-606TX, LaCrosse_TX141THBv2 (#1898)
* WS: add protocol Acurite-606TX * WS: history, added display of the channel (if any) in the general list * WS: added display of the button state if it is on the transmitter, and displaying the data that is in the signal * WS: fix batt info * WS: add protocol LaCrosse_TX141THBv2 * WS; fix syntax * Furi: bump api_symbols version Co-authored-by: あく <alleteam@gmail.com>
This commit is contained in:
parent
33892ebfb7
commit
c1bb10a694
@ -3,7 +3,7 @@
|
|||||||
#include <furi.h>
|
#include <furi.h>
|
||||||
#include <furi_hal.h>
|
#include <furi_hal.h>
|
||||||
|
|
||||||
#define WS_VERSION_APP "0.1"
|
#define WS_VERSION_APP "0.2"
|
||||||
#define WS_DEVELOPED "SkorP"
|
#define WS_DEVELOPED "SkorP"
|
||||||
#define WS_GITHUB "https://github.com/flipperdevices/flipperzero-firmware"
|
#define WS_GITHUB "https://github.com/flipperdevices/flipperzero-firmware"
|
||||||
|
|
||||||
|
252
applications/plugins/weather_station/protocols/acurite_606tx.c
Normal file
252
applications/plugins/weather_station/protocols/acurite_606tx.c
Normal file
@ -0,0 +1,252 @@
|
|||||||
|
#include "acurite_606tx.h"
|
||||||
|
|
||||||
|
#define TAG "WSProtocolAcurite_606TX"
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Help
|
||||||
|
* https://github.com/merbanan/rtl_433/blob/5bef4e43133ac4c0e2d18d36f87c52b4f9458453/src/devices/acurite.c#L1644
|
||||||
|
*
|
||||||
|
* 0000 1111 | 0011 0000 | 0101 1100 | 1110 0111
|
||||||
|
* iiii iiii | buuu tttt | tttt tttt | cccc cccc
|
||||||
|
* - i: identification; changes on battery switch
|
||||||
|
* - c: lfsr_digest8;
|
||||||
|
* - u: unknown;
|
||||||
|
* - b: battery low; flag to indicate low battery voltage
|
||||||
|
* - t: Temperature; in °C
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
static const SubGhzBlockConst ws_protocol_acurite_606tx_const = {
|
||||||
|
.te_short = 500,
|
||||||
|
.te_long = 2000,
|
||||||
|
.te_delta = 150,
|
||||||
|
.min_count_bit_for_found = 32,
|
||||||
|
};
|
||||||
|
|
||||||
|
struct WSProtocolDecoderAcurite_606TX {
|
||||||
|
SubGhzProtocolDecoderBase base;
|
||||||
|
|
||||||
|
SubGhzBlockDecoder decoder;
|
||||||
|
WSBlockGeneric generic;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct WSProtocolEncoderAcurite_606TX {
|
||||||
|
SubGhzProtocolEncoderBase base;
|
||||||
|
|
||||||
|
SubGhzProtocolBlockEncoder encoder;
|
||||||
|
WSBlockGeneric generic;
|
||||||
|
};
|
||||||
|
|
||||||
|
typedef enum {
|
||||||
|
Acurite_606TXDecoderStepReset = 0,
|
||||||
|
Acurite_606TXDecoderStepSaveDuration,
|
||||||
|
Acurite_606TXDecoderStepCheckDuration,
|
||||||
|
} Acurite_606TXDecoderStep;
|
||||||
|
|
||||||
|
const SubGhzProtocolDecoder ws_protocol_acurite_606tx_decoder = {
|
||||||
|
.alloc = ws_protocol_decoder_acurite_606tx_alloc,
|
||||||
|
.free = ws_protocol_decoder_acurite_606tx_free,
|
||||||
|
|
||||||
|
.feed = ws_protocol_decoder_acurite_606tx_feed,
|
||||||
|
.reset = ws_protocol_decoder_acurite_606tx_reset,
|
||||||
|
|
||||||
|
.get_hash_data = ws_protocol_decoder_acurite_606tx_get_hash_data,
|
||||||
|
.serialize = ws_protocol_decoder_acurite_606tx_serialize,
|
||||||
|
.deserialize = ws_protocol_decoder_acurite_606tx_deserialize,
|
||||||
|
.get_string = ws_protocol_decoder_acurite_606tx_get_string,
|
||||||
|
};
|
||||||
|
|
||||||
|
const SubGhzProtocolEncoder ws_protocol_acurite_606tx_encoder = {
|
||||||
|
.alloc = NULL,
|
||||||
|
.free = NULL,
|
||||||
|
|
||||||
|
.deserialize = NULL,
|
||||||
|
.stop = NULL,
|
||||||
|
.yield = NULL,
|
||||||
|
};
|
||||||
|
|
||||||
|
const SubGhzProtocol ws_protocol_acurite_606tx = {
|
||||||
|
.name = WS_PROTOCOL_ACURITE_606TX_NAME,
|
||||||
|
.type = SubGhzProtocolWeatherStation,
|
||||||
|
.flag = SubGhzProtocolFlag_433 | SubGhzProtocolFlag_315 | SubGhzProtocolFlag_868 |
|
||||||
|
SubGhzProtocolFlag_AM | SubGhzProtocolFlag_Decodable,
|
||||||
|
|
||||||
|
.decoder = &ws_protocol_acurite_606tx_decoder,
|
||||||
|
.encoder = &ws_protocol_acurite_606tx_encoder,
|
||||||
|
};
|
||||||
|
|
||||||
|
void* ws_protocol_decoder_acurite_606tx_alloc(SubGhzEnvironment* environment) {
|
||||||
|
UNUSED(environment);
|
||||||
|
WSProtocolDecoderAcurite_606TX* instance = malloc(sizeof(WSProtocolDecoderAcurite_606TX));
|
||||||
|
instance->base.protocol = &ws_protocol_acurite_606tx;
|
||||||
|
instance->generic.protocol_name = instance->base.protocol->name;
|
||||||
|
return instance;
|
||||||
|
}
|
||||||
|
|
||||||
|
void ws_protocol_decoder_acurite_606tx_free(void* context) {
|
||||||
|
furi_assert(context);
|
||||||
|
WSProtocolDecoderAcurite_606TX* instance = context;
|
||||||
|
free(instance);
|
||||||
|
}
|
||||||
|
|
||||||
|
void ws_protocol_decoder_acurite_606tx_reset(void* context) {
|
||||||
|
furi_assert(context);
|
||||||
|
WSProtocolDecoderAcurite_606TX* instance = context;
|
||||||
|
instance->decoder.parser_step = Acurite_606TXDecoderStepReset;
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool ws_protocol_acurite_606tx_check(WSProtocolDecoderAcurite_606TX* instance) {
|
||||||
|
if(!instance->decoder.decode_data) return false;
|
||||||
|
uint8_t msg[] = {
|
||||||
|
instance->decoder.decode_data >> 24,
|
||||||
|
instance->decoder.decode_data >> 16,
|
||||||
|
instance->decoder.decode_data >> 8};
|
||||||
|
|
||||||
|
uint8_t crc = subghz_protocol_blocks_lfsr_digest8(msg, 3, 0x98, 0xF1);
|
||||||
|
return (crc == (instance->decoder.decode_data & 0xFF));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Analysis of received data
|
||||||
|
* @param instance Pointer to a WSBlockGeneric* instance
|
||||||
|
*/
|
||||||
|
static void ws_protocol_acurite_606tx_remote_controller(WSBlockGeneric* instance) {
|
||||||
|
instance->id = (instance->data >> 24) & 0xFF;
|
||||||
|
instance->battery_low = (instance->data >> 23) & 1;
|
||||||
|
|
||||||
|
instance->channel = WS_NO_CHANNEL;
|
||||||
|
|
||||||
|
if(!((instance->data >> 19) & 1)) {
|
||||||
|
instance->temp = (float)((instance->data >> 8) & 0x07FF) / 10.0f;
|
||||||
|
} else {
|
||||||
|
instance->temp = (float)((~(instance->data >> 8) & 0x07FF) + 1) / -10.0f;
|
||||||
|
}
|
||||||
|
instance->btn = WS_NO_BTN;
|
||||||
|
instance->humidity = WS_NO_HUMIDITY;
|
||||||
|
}
|
||||||
|
|
||||||
|
void ws_protocol_decoder_acurite_606tx_feed(void* context, bool level, uint32_t duration) {
|
||||||
|
furi_assert(context);
|
||||||
|
WSProtocolDecoderAcurite_606TX* instance = context;
|
||||||
|
|
||||||
|
switch(instance->decoder.parser_step) {
|
||||||
|
case Acurite_606TXDecoderStepReset:
|
||||||
|
if((!level) && (DURATION_DIFF(duration, ws_protocol_acurite_606tx_const.te_short * 17) <
|
||||||
|
ws_protocol_acurite_606tx_const.te_delta * 8)) {
|
||||||
|
//Found syncPrefix
|
||||||
|
instance->decoder.parser_step = Acurite_606TXDecoderStepSaveDuration;
|
||||||
|
instance->decoder.decode_data = 0;
|
||||||
|
instance->decoder.decode_count_bit = 0;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case Acurite_606TXDecoderStepSaveDuration:
|
||||||
|
if(level) {
|
||||||
|
instance->decoder.te_last = duration;
|
||||||
|
instance->decoder.parser_step = Acurite_606TXDecoderStepCheckDuration;
|
||||||
|
} else {
|
||||||
|
instance->decoder.parser_step = Acurite_606TXDecoderStepReset;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case Acurite_606TXDecoderStepCheckDuration:
|
||||||
|
if(!level) {
|
||||||
|
if((DURATION_DIFF(instance->decoder.te_last, ws_protocol_acurite_606tx_const.te_short) <
|
||||||
|
ws_protocol_acurite_606tx_const.te_delta) &&
|
||||||
|
(DURATION_DIFF(duration, ws_protocol_acurite_606tx_const.te_short) <
|
||||||
|
ws_protocol_acurite_606tx_const.te_delta)) {
|
||||||
|
//Found syncPostfix
|
||||||
|
instance->decoder.parser_step = Acurite_606TXDecoderStepReset;
|
||||||
|
if((instance->decoder.decode_count_bit ==
|
||||||
|
ws_protocol_acurite_606tx_const.min_count_bit_for_found) &&
|
||||||
|
ws_protocol_acurite_606tx_check(instance)) {
|
||||||
|
instance->generic.data = instance->decoder.decode_data;
|
||||||
|
instance->generic.data_count_bit = instance->decoder.decode_count_bit;
|
||||||
|
ws_protocol_acurite_606tx_remote_controller(&instance->generic);
|
||||||
|
if(instance->base.callback)
|
||||||
|
instance->base.callback(&instance->base, instance->base.context);
|
||||||
|
}
|
||||||
|
instance->decoder.decode_data = 0;
|
||||||
|
instance->decoder.decode_count_bit = 0;
|
||||||
|
|
||||||
|
break;
|
||||||
|
} else if(
|
||||||
|
(DURATION_DIFF(
|
||||||
|
instance->decoder.te_last, ws_protocol_acurite_606tx_const.te_short) <
|
||||||
|
ws_protocol_acurite_606tx_const.te_delta) &&
|
||||||
|
(DURATION_DIFF(duration, ws_protocol_acurite_606tx_const.te_long) <
|
||||||
|
ws_protocol_acurite_606tx_const.te_delta * 2)) {
|
||||||
|
subghz_protocol_blocks_add_bit(&instance->decoder, 0);
|
||||||
|
instance->decoder.parser_step = Acurite_606TXDecoderStepSaveDuration;
|
||||||
|
} else if(
|
||||||
|
(DURATION_DIFF(
|
||||||
|
instance->decoder.te_last, ws_protocol_acurite_606tx_const.te_short) <
|
||||||
|
ws_protocol_acurite_606tx_const.te_delta) &&
|
||||||
|
(DURATION_DIFF(duration, ws_protocol_acurite_606tx_const.te_long * 2) <
|
||||||
|
ws_protocol_acurite_606tx_const.te_delta * 4)) {
|
||||||
|
subghz_protocol_blocks_add_bit(&instance->decoder, 1);
|
||||||
|
instance->decoder.parser_step = Acurite_606TXDecoderStepSaveDuration;
|
||||||
|
} else {
|
||||||
|
instance->decoder.parser_step = Acurite_606TXDecoderStepReset;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
instance->decoder.parser_step = Acurite_606TXDecoderStepReset;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
uint8_t ws_protocol_decoder_acurite_606tx_get_hash_data(void* context) {
|
||||||
|
furi_assert(context);
|
||||||
|
WSProtocolDecoderAcurite_606TX* instance = context;
|
||||||
|
return subghz_protocol_blocks_get_hash_data(
|
||||||
|
&instance->decoder, (instance->decoder.decode_count_bit / 8) + 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool ws_protocol_decoder_acurite_606tx_serialize(
|
||||||
|
void* context,
|
||||||
|
FlipperFormat* flipper_format,
|
||||||
|
SubGhzRadioPreset* preset) {
|
||||||
|
furi_assert(context);
|
||||||
|
WSProtocolDecoderAcurite_606TX* instance = context;
|
||||||
|
return ws_block_generic_serialize(&instance->generic, flipper_format, preset);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool ws_protocol_decoder_acurite_606tx_deserialize(void* context, FlipperFormat* flipper_format) {
|
||||||
|
furi_assert(context);
|
||||||
|
WSProtocolDecoderAcurite_606TX* instance = context;
|
||||||
|
bool ret = false;
|
||||||
|
do {
|
||||||
|
if(!ws_block_generic_deserialize(&instance->generic, flipper_format)) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if(instance->generic.data_count_bit !=
|
||||||
|
ws_protocol_acurite_606tx_const.min_count_bit_for_found) {
|
||||||
|
FURI_LOG_E(TAG, "Wrong number of bits in key");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
ret = true;
|
||||||
|
} while(false);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
void ws_protocol_decoder_acurite_606tx_get_string(void* context, FuriString* output) {
|
||||||
|
furi_assert(context);
|
||||||
|
WSProtocolDecoderAcurite_606TX* instance = context;
|
||||||
|
furi_string_printf(
|
||||||
|
output,
|
||||||
|
"%s %dbit\r\n"
|
||||||
|
"Key:0x%lX%08lX\r\n"
|
||||||
|
"Sn:0x%lX Ch:%d Bat:%d\r\n"
|
||||||
|
"Temp:%d.%d C Hum:%d%%",
|
||||||
|
instance->generic.protocol_name,
|
||||||
|
instance->generic.data_count_bit,
|
||||||
|
(uint32_t)(instance->generic.data >> 32),
|
||||||
|
(uint32_t)(instance->generic.data),
|
||||||
|
instance->generic.id,
|
||||||
|
instance->generic.channel,
|
||||||
|
instance->generic.battery_low,
|
||||||
|
(int16_t)instance->generic.temp,
|
||||||
|
abs(((int16_t)(instance->generic.temp * 10) - (((int16_t)instance->generic.temp) * 10))),
|
||||||
|
instance->generic.humidity);
|
||||||
|
}
|
@ -0,0 +1,79 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <lib/subghz/protocols/base.h>
|
||||||
|
|
||||||
|
#include <lib/subghz/blocks/const.h>
|
||||||
|
#include <lib/subghz/blocks/decoder.h>
|
||||||
|
#include <lib/subghz/blocks/encoder.h>
|
||||||
|
#include "ws_generic.h"
|
||||||
|
#include <lib/subghz/blocks/math.h>
|
||||||
|
|
||||||
|
#define WS_PROTOCOL_ACURITE_606TX_NAME "Acurite-606TX"
|
||||||
|
|
||||||
|
typedef struct WSProtocolDecoderAcurite_606TX WSProtocolDecoderAcurite_606TX;
|
||||||
|
typedef struct WSProtocolEncoderAcurite_606TX WSProtocolEncoderAcurite_606TX;
|
||||||
|
|
||||||
|
extern const SubGhzProtocolDecoder ws_protocol_acurite_606tx_decoder;
|
||||||
|
extern const SubGhzProtocolEncoder ws_protocol_acurite_606tx_encoder;
|
||||||
|
extern const SubGhzProtocol ws_protocol_acurite_606tx;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Allocate WSProtocolDecoderAcurite_606TX.
|
||||||
|
* @param environment Pointer to a SubGhzEnvironment instance
|
||||||
|
* @return WSProtocolDecoderAcurite_606TX* pointer to a WSProtocolDecoderAcurite_606TX instance
|
||||||
|
*/
|
||||||
|
void* ws_protocol_decoder_acurite_606tx_alloc(SubGhzEnvironment* environment);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Free WSProtocolDecoderAcurite_606TX.
|
||||||
|
* @param context Pointer to a WSProtocolDecoderAcurite_606TX instance
|
||||||
|
*/
|
||||||
|
void ws_protocol_decoder_acurite_606tx_free(void* context);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Reset decoder WSProtocolDecoderAcurite_606TX.
|
||||||
|
* @param context Pointer to a WSProtocolDecoderAcurite_606TX instance
|
||||||
|
*/
|
||||||
|
void ws_protocol_decoder_acurite_606tx_reset(void* context);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Parse a raw sequence of levels and durations received from the air.
|
||||||
|
* @param context Pointer to a WSProtocolDecoderAcurite_606TX instance
|
||||||
|
* @param level Signal level true-high false-low
|
||||||
|
* @param duration Duration of this level in, us
|
||||||
|
*/
|
||||||
|
void ws_protocol_decoder_acurite_606tx_feed(void* context, bool level, uint32_t duration);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Getting the hash sum of the last randomly received parcel.
|
||||||
|
* @param context Pointer to a WSProtocolDecoderAcurite_606TX instance
|
||||||
|
* @return hash Hash sum
|
||||||
|
*/
|
||||||
|
uint8_t ws_protocol_decoder_acurite_606tx_get_hash_data(void* context);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Serialize data WSProtocolDecoderAcurite_606TX.
|
||||||
|
* @param context Pointer to a WSProtocolDecoderAcurite_606TX instance
|
||||||
|
* @param flipper_format Pointer to a FlipperFormat instance
|
||||||
|
* @param preset The modulation on which the signal was received, SubGhzRadioPreset
|
||||||
|
* @return true On success
|
||||||
|
*/
|
||||||
|
bool ws_protocol_decoder_acurite_606tx_serialize(
|
||||||
|
void* context,
|
||||||
|
FlipperFormat* flipper_format,
|
||||||
|
SubGhzRadioPreset* preset);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Deserialize data WSProtocolDecoderAcurite_606TX.
|
||||||
|
* @param context Pointer to a WSProtocolDecoderAcurite_606TX instance
|
||||||
|
* @param flipper_format Pointer to a FlipperFormat instance
|
||||||
|
* @return true On success
|
||||||
|
*/
|
||||||
|
bool ws_protocol_decoder_acurite_606tx_deserialize(void* context, FlipperFormat* flipper_format);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Getting a textual representation of the received data.
|
||||||
|
* @param context Pointer to a WSProtocolDecoderAcurite_606TX instance
|
||||||
|
* @param output Resulting text
|
||||||
|
*/
|
||||||
|
void ws_protocol_decoder_acurite_606tx_get_string(void* context, FuriString* output);
|
@ -142,6 +142,7 @@ static bool ws_protocol_infactory_check_crc(WSProtocolDecoderInfactory* instance
|
|||||||
static void ws_protocol_infactory_remote_controller(WSBlockGeneric* instance) {
|
static void ws_protocol_infactory_remote_controller(WSBlockGeneric* instance) {
|
||||||
instance->id = instance->data >> 32;
|
instance->id = instance->data >> 32;
|
||||||
instance->battery_low = (instance->data >> 26) & 1;
|
instance->battery_low = (instance->data >> 26) & 1;
|
||||||
|
instance->btn = WS_NO_BTN;
|
||||||
instance->temp = ws_block_generic_fahrenheit_to_celsius(
|
instance->temp = ws_block_generic_fahrenheit_to_celsius(
|
||||||
((float)((instance->data >> 12) & 0x0FFF) - 900.0f) / 10.0f);
|
((float)((instance->data >> 12) & 0x0FFF) - 900.0f) / 10.0f);
|
||||||
instance->humidity =
|
instance->humidity =
|
||||||
|
@ -0,0 +1,298 @@
|
|||||||
|
#include "lacrosse_tx141thbv2.h"
|
||||||
|
|
||||||
|
#define TAG "WSProtocolLaCrosse_TX141THBv2"
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Help
|
||||||
|
* https://github.com/merbanan/rtl_433/blob/7e83cfd27d14247b6c3c81732bfe4a4f9a974d30/src/devices/lacrosse_tx141x.c
|
||||||
|
*
|
||||||
|
* iiii iiii | bkcc tttt | tttt tttt | hhhh hhhh | cccc cccc | u
|
||||||
|
* - i: identification; changes on battery switch
|
||||||
|
* - c: lfsr_digest8_reflect;
|
||||||
|
* - u: unknown;
|
||||||
|
* - b: battery low; flag to indicate low battery voltage
|
||||||
|
* - h: Humidity;
|
||||||
|
* - t: Temperature; in °F as binary number with one decimal place + 50 °F offset
|
||||||
|
* - n: Channel; Channel number 1 - 3
|
||||||
|
*/
|
||||||
|
|
||||||
|
static const SubGhzBlockConst ws_protocol_lacrosse_tx141thbv2_const = {
|
||||||
|
.te_short = 250,
|
||||||
|
.te_long = 500,
|
||||||
|
.te_delta = 120,
|
||||||
|
.min_count_bit_for_found = 41,
|
||||||
|
};
|
||||||
|
|
||||||
|
struct WSProtocolDecoderLaCrosse_TX141THBv2 {
|
||||||
|
SubGhzProtocolDecoderBase base;
|
||||||
|
|
||||||
|
SubGhzBlockDecoder decoder;
|
||||||
|
WSBlockGeneric generic;
|
||||||
|
|
||||||
|
uint16_t header_count;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct WSProtocolEncoderLaCrosse_TX141THBv2 {
|
||||||
|
SubGhzProtocolEncoderBase base;
|
||||||
|
|
||||||
|
SubGhzProtocolBlockEncoder encoder;
|
||||||
|
WSBlockGeneric generic;
|
||||||
|
};
|
||||||
|
|
||||||
|
typedef enum {
|
||||||
|
LaCrosse_TX141THBv2DecoderStepReset = 0,
|
||||||
|
LaCrosse_TX141THBv2DecoderStepCheckPreambule,
|
||||||
|
LaCrosse_TX141THBv2DecoderStepSaveDuration,
|
||||||
|
LaCrosse_TX141THBv2DecoderStepCheckDuration,
|
||||||
|
} LaCrosse_TX141THBv2DecoderStep;
|
||||||
|
|
||||||
|
const SubGhzProtocolDecoder ws_protocol_lacrosse_tx141thbv2_decoder = {
|
||||||
|
.alloc = ws_protocol_decoder_lacrosse_tx141thbv2_alloc,
|
||||||
|
.free = ws_protocol_decoder_lacrosse_tx141thbv2_free,
|
||||||
|
|
||||||
|
.feed = ws_protocol_decoder_lacrosse_tx141thbv2_feed,
|
||||||
|
.reset = ws_protocol_decoder_lacrosse_tx141thbv2_reset,
|
||||||
|
|
||||||
|
.get_hash_data = ws_protocol_decoder_lacrosse_tx141thbv2_get_hash_data,
|
||||||
|
.serialize = ws_protocol_decoder_lacrosse_tx141thbv2_serialize,
|
||||||
|
.deserialize = ws_protocol_decoder_lacrosse_tx141thbv2_deserialize,
|
||||||
|
.get_string = ws_protocol_decoder_lacrosse_tx141thbv2_get_string,
|
||||||
|
};
|
||||||
|
|
||||||
|
const SubGhzProtocolEncoder ws_protocol_lacrosse_tx141thbv2_encoder = {
|
||||||
|
.alloc = NULL,
|
||||||
|
.free = NULL,
|
||||||
|
|
||||||
|
.deserialize = NULL,
|
||||||
|
.stop = NULL,
|
||||||
|
.yield = NULL,
|
||||||
|
};
|
||||||
|
|
||||||
|
const SubGhzProtocol ws_protocol_lacrosse_tx141thbv2 = {
|
||||||
|
.name = WS_PROTOCOL_LACROSSE_TX141THBV2_NAME,
|
||||||
|
.type = SubGhzProtocolWeatherStation,
|
||||||
|
.flag = SubGhzProtocolFlag_433 | SubGhzProtocolFlag_315 | SubGhzProtocolFlag_868 |
|
||||||
|
SubGhzProtocolFlag_AM | SubGhzProtocolFlag_Decodable,
|
||||||
|
|
||||||
|
.decoder = &ws_protocol_lacrosse_tx141thbv2_decoder,
|
||||||
|
.encoder = &ws_protocol_lacrosse_tx141thbv2_encoder,
|
||||||
|
};
|
||||||
|
|
||||||
|
void* ws_protocol_decoder_lacrosse_tx141thbv2_alloc(SubGhzEnvironment* environment) {
|
||||||
|
UNUSED(environment);
|
||||||
|
WSProtocolDecoderLaCrosse_TX141THBv2* instance =
|
||||||
|
malloc(sizeof(WSProtocolDecoderLaCrosse_TX141THBv2));
|
||||||
|
instance->base.protocol = &ws_protocol_lacrosse_tx141thbv2;
|
||||||
|
instance->generic.protocol_name = instance->base.protocol->name;
|
||||||
|
return instance;
|
||||||
|
}
|
||||||
|
|
||||||
|
void ws_protocol_decoder_lacrosse_tx141thbv2_free(void* context) {
|
||||||
|
furi_assert(context);
|
||||||
|
WSProtocolDecoderLaCrosse_TX141THBv2* instance = context;
|
||||||
|
free(instance);
|
||||||
|
}
|
||||||
|
|
||||||
|
void ws_protocol_decoder_lacrosse_tx141thbv2_reset(void* context) {
|
||||||
|
furi_assert(context);
|
||||||
|
WSProtocolDecoderLaCrosse_TX141THBv2* instance = context;
|
||||||
|
instance->decoder.parser_step = LaCrosse_TX141THBv2DecoderStepReset;
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool
|
||||||
|
ws_protocol_lacrosse_tx141thbv2_check_crc(WSProtocolDecoderLaCrosse_TX141THBv2* instance) {
|
||||||
|
if(!instance->decoder.decode_data) return false;
|
||||||
|
uint8_t msg[] = {
|
||||||
|
instance->decoder.decode_data >> 33,
|
||||||
|
instance->decoder.decode_data >> 25,
|
||||||
|
instance->decoder.decode_data >> 17,
|
||||||
|
instance->decoder.decode_data >> 9};
|
||||||
|
|
||||||
|
uint8_t crc = subghz_protocol_blocks_lfsr_digest8_reflect(msg, 4, 0x31, 0xF4);
|
||||||
|
return (crc == ((instance->decoder.decode_data >> 1) & 0xFF));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Analysis of received data
|
||||||
|
* @param instance Pointer to a WSBlockGeneric* instance
|
||||||
|
*/
|
||||||
|
static void ws_protocol_lacrosse_tx141thbv2_remote_controller(WSBlockGeneric* instance) {
|
||||||
|
instance->id = instance->data >> 33;
|
||||||
|
instance->battery_low = (instance->data >> 32) & 1;
|
||||||
|
instance->btn = (instance->data >> 31) & 1;
|
||||||
|
instance->channel = ((instance->data >> 29) & 0x03) + 1;
|
||||||
|
instance->temp = ((float)((instance->data >> 17) & 0x0FFF) - 500.0f) / 10.0f;
|
||||||
|
instance->humidity = (instance->data >> 9) & 0xFF;
|
||||||
|
}
|
||||||
|
|
||||||
|
void ws_protocol_decoder_lacrosse_tx141thbv2_feed(void* context, bool level, uint32_t duration) {
|
||||||
|
furi_assert(context);
|
||||||
|
WSProtocolDecoderLaCrosse_TX141THBv2* instance = context;
|
||||||
|
|
||||||
|
switch(instance->decoder.parser_step) {
|
||||||
|
case LaCrosse_TX141THBv2DecoderStepReset:
|
||||||
|
if((level) &&
|
||||||
|
(DURATION_DIFF(duration, ws_protocol_lacrosse_tx141thbv2_const.te_short * 3) <
|
||||||
|
ws_protocol_lacrosse_tx141thbv2_const.te_delta * 2)) {
|
||||||
|
instance->decoder.parser_step = LaCrosse_TX141THBv2DecoderStepCheckPreambule;
|
||||||
|
instance->decoder.te_last = duration;
|
||||||
|
instance->header_count = 0;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case LaCrosse_TX141THBv2DecoderStepCheckPreambule:
|
||||||
|
if(level) {
|
||||||
|
instance->decoder.te_last = duration;
|
||||||
|
} else {
|
||||||
|
if((DURATION_DIFF(
|
||||||
|
instance->decoder.te_last,
|
||||||
|
ws_protocol_lacrosse_tx141thbv2_const.te_short * 3) <
|
||||||
|
ws_protocol_lacrosse_tx141thbv2_const.te_delta * 2) &&
|
||||||
|
(DURATION_DIFF(duration, ws_protocol_lacrosse_tx141thbv2_const.te_short * 3) <
|
||||||
|
ws_protocol_lacrosse_tx141thbv2_const.te_delta * 2)) {
|
||||||
|
//Found preambule
|
||||||
|
instance->header_count++;
|
||||||
|
} else if(instance->header_count == 4) {
|
||||||
|
if((DURATION_DIFF(
|
||||||
|
instance->decoder.te_last,
|
||||||
|
ws_protocol_lacrosse_tx141thbv2_const.te_short) <
|
||||||
|
ws_protocol_lacrosse_tx141thbv2_const.te_delta) &&
|
||||||
|
(DURATION_DIFF(duration, ws_protocol_lacrosse_tx141thbv2_const.te_long) <
|
||||||
|
ws_protocol_lacrosse_tx141thbv2_const.te_delta)) {
|
||||||
|
instance->decoder.decode_data = 0;
|
||||||
|
instance->decoder.decode_count_bit = 0;
|
||||||
|
subghz_protocol_blocks_add_bit(&instance->decoder, 0);
|
||||||
|
instance->decoder.parser_step = LaCrosse_TX141THBv2DecoderStepSaveDuration;
|
||||||
|
} else if(
|
||||||
|
(DURATION_DIFF(
|
||||||
|
instance->decoder.te_last,
|
||||||
|
ws_protocol_lacrosse_tx141thbv2_const.te_long) <
|
||||||
|
ws_protocol_lacrosse_tx141thbv2_const.te_delta) &&
|
||||||
|
(DURATION_DIFF(duration, ws_protocol_lacrosse_tx141thbv2_const.te_short) <
|
||||||
|
ws_protocol_lacrosse_tx141thbv2_const.te_delta)) {
|
||||||
|
instance->decoder.decode_data = 0;
|
||||||
|
instance->decoder.decode_count_bit = 0;
|
||||||
|
subghz_protocol_blocks_add_bit(&instance->decoder, 1);
|
||||||
|
instance->decoder.parser_step = LaCrosse_TX141THBv2DecoderStepSaveDuration;
|
||||||
|
} else {
|
||||||
|
instance->decoder.parser_step = LaCrosse_TX141THBv2DecoderStepReset;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
instance->decoder.parser_step = LaCrosse_TX141THBv2DecoderStepReset;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case LaCrosse_TX141THBv2DecoderStepSaveDuration:
|
||||||
|
if(level) {
|
||||||
|
instance->decoder.te_last = duration;
|
||||||
|
instance->decoder.parser_step = LaCrosse_TX141THBv2DecoderStepCheckDuration;
|
||||||
|
} else {
|
||||||
|
instance->decoder.parser_step = LaCrosse_TX141THBv2DecoderStepReset;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case LaCrosse_TX141THBv2DecoderStepCheckDuration:
|
||||||
|
if(!level) {
|
||||||
|
if(((DURATION_DIFF(
|
||||||
|
instance->decoder.te_last,
|
||||||
|
ws_protocol_lacrosse_tx141thbv2_const.te_short * 3) <
|
||||||
|
ws_protocol_lacrosse_tx141thbv2_const.te_delta * 2) &&
|
||||||
|
(DURATION_DIFF(duration, ws_protocol_lacrosse_tx141thbv2_const.te_short * 3) <
|
||||||
|
ws_protocol_lacrosse_tx141thbv2_const.te_delta * 2))) {
|
||||||
|
if((instance->decoder.decode_count_bit ==
|
||||||
|
ws_protocol_lacrosse_tx141thbv2_const.min_count_bit_for_found) &&
|
||||||
|
ws_protocol_lacrosse_tx141thbv2_check_crc(instance)) {
|
||||||
|
instance->generic.data = instance->decoder.decode_data;
|
||||||
|
instance->generic.data_count_bit = instance->decoder.decode_count_bit;
|
||||||
|
ws_protocol_lacrosse_tx141thbv2_remote_controller(&instance->generic);
|
||||||
|
if(instance->base.callback)
|
||||||
|
instance->base.callback(&instance->base, instance->base.context);
|
||||||
|
}
|
||||||
|
instance->decoder.decode_data = 0;
|
||||||
|
instance->decoder.decode_count_bit = 0;
|
||||||
|
instance->header_count = 1;
|
||||||
|
instance->decoder.parser_step = LaCrosse_TX141THBv2DecoderStepCheckPreambule;
|
||||||
|
break;
|
||||||
|
} else if(
|
||||||
|
(DURATION_DIFF(
|
||||||
|
instance->decoder.te_last, ws_protocol_lacrosse_tx141thbv2_const.te_short) <
|
||||||
|
ws_protocol_lacrosse_tx141thbv2_const.te_delta) &&
|
||||||
|
(DURATION_DIFF(duration, ws_protocol_lacrosse_tx141thbv2_const.te_long) <
|
||||||
|
ws_protocol_lacrosse_tx141thbv2_const.te_delta)) {
|
||||||
|
subghz_protocol_blocks_add_bit(&instance->decoder, 0);
|
||||||
|
instance->decoder.parser_step = LaCrosse_TX141THBv2DecoderStepSaveDuration;
|
||||||
|
} else if(
|
||||||
|
(DURATION_DIFF(
|
||||||
|
instance->decoder.te_last, ws_protocol_lacrosse_tx141thbv2_const.te_long) <
|
||||||
|
ws_protocol_lacrosse_tx141thbv2_const.te_delta) &&
|
||||||
|
(DURATION_DIFF(duration, ws_protocol_lacrosse_tx141thbv2_const.te_short) <
|
||||||
|
ws_protocol_lacrosse_tx141thbv2_const.te_delta)) {
|
||||||
|
subghz_protocol_blocks_add_bit(&instance->decoder, 1);
|
||||||
|
instance->decoder.parser_step = LaCrosse_TX141THBv2DecoderStepSaveDuration;
|
||||||
|
} else {
|
||||||
|
instance->decoder.parser_step = LaCrosse_TX141THBv2DecoderStepReset;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
instance->decoder.parser_step = LaCrosse_TX141THBv2DecoderStepReset;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
uint8_t ws_protocol_decoder_lacrosse_tx141thbv2_get_hash_data(void* context) {
|
||||||
|
furi_assert(context);
|
||||||
|
WSProtocolDecoderLaCrosse_TX141THBv2* instance = context;
|
||||||
|
return subghz_protocol_blocks_get_hash_data(
|
||||||
|
&instance->decoder, (instance->decoder.decode_count_bit / 8) + 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool ws_protocol_decoder_lacrosse_tx141thbv2_serialize(
|
||||||
|
void* context,
|
||||||
|
FlipperFormat* flipper_format,
|
||||||
|
SubGhzRadioPreset* preset) {
|
||||||
|
furi_assert(context);
|
||||||
|
WSProtocolDecoderLaCrosse_TX141THBv2* instance = context;
|
||||||
|
return ws_block_generic_serialize(&instance->generic, flipper_format, preset);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool ws_protocol_decoder_lacrosse_tx141thbv2_deserialize(
|
||||||
|
void* context,
|
||||||
|
FlipperFormat* flipper_format) {
|
||||||
|
furi_assert(context);
|
||||||
|
WSProtocolDecoderLaCrosse_TX141THBv2* instance = context;
|
||||||
|
bool ret = false;
|
||||||
|
do {
|
||||||
|
if(!ws_block_generic_deserialize(&instance->generic, flipper_format)) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if(instance->generic.data_count_bit !=
|
||||||
|
ws_protocol_lacrosse_tx141thbv2_const.min_count_bit_for_found) {
|
||||||
|
FURI_LOG_E(TAG, "Wrong number of bits in key");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
ret = true;
|
||||||
|
} while(false);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
void ws_protocol_decoder_lacrosse_tx141thbv2_get_string(void* context, FuriString* output) {
|
||||||
|
furi_assert(context);
|
||||||
|
WSProtocolDecoderLaCrosse_TX141THBv2* instance = context;
|
||||||
|
furi_string_printf(
|
||||||
|
output,
|
||||||
|
"%s %dbit\r\n"
|
||||||
|
"Key:0x%lX%08lX\r\n"
|
||||||
|
"Sn:0x%lX Ch:%d Bat:%d\r\n"
|
||||||
|
"Temp:%d.%d C Hum:%d%%",
|
||||||
|
instance->generic.protocol_name,
|
||||||
|
instance->generic.data_count_bit,
|
||||||
|
(uint32_t)(instance->generic.data >> 32),
|
||||||
|
(uint32_t)(instance->generic.data),
|
||||||
|
instance->generic.id,
|
||||||
|
instance->generic.channel,
|
||||||
|
instance->generic.battery_low,
|
||||||
|
(int16_t)instance->generic.temp,
|
||||||
|
abs(((int16_t)(instance->generic.temp * 10) - (((int16_t)instance->generic.temp) * 10))),
|
||||||
|
instance->generic.humidity);
|
||||||
|
}
|
@ -0,0 +1,81 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <lib/subghz/protocols/base.h>
|
||||||
|
|
||||||
|
#include <lib/subghz/blocks/const.h>
|
||||||
|
#include <lib/subghz/blocks/decoder.h>
|
||||||
|
#include <lib/subghz/blocks/encoder.h>
|
||||||
|
#include "ws_generic.h"
|
||||||
|
#include <lib/subghz/blocks/math.h>
|
||||||
|
|
||||||
|
#define WS_PROTOCOL_LACROSSE_TX141THBV2_NAME "TX141THBv2"
|
||||||
|
|
||||||
|
typedef struct WSProtocolDecoderLaCrosse_TX141THBv2 WSProtocolDecoderLaCrosse_TX141THBv2;
|
||||||
|
typedef struct WSProtocolEncoderLaCrosse_TX141THBv2 WSProtocolEncoderLaCrosse_TX141THBv2;
|
||||||
|
|
||||||
|
extern const SubGhzProtocolDecoder ws_protocol_lacrosse_tx141thbv2_decoder;
|
||||||
|
extern const SubGhzProtocolEncoder ws_protocol_lacrosse_tx141thbv2_encoder;
|
||||||
|
extern const SubGhzProtocol ws_protocol_lacrosse_tx141thbv2;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Allocate WSProtocolDecoderLaCrosse_TX141THBv2.
|
||||||
|
* @param environment Pointer to a SubGhzEnvironment instance
|
||||||
|
* @return WSProtocolDecoderLaCrosse_TX141THBv2* pointer to a WSProtocolDecoderLaCrosse_TX141THBv2 instance
|
||||||
|
*/
|
||||||
|
void* ws_protocol_decoder_lacrosse_tx141thbv2_alloc(SubGhzEnvironment* environment);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Free WSProtocolDecoderLaCrosse_TX141THBv2.
|
||||||
|
* @param context Pointer to a WSProtocolDecoderLaCrosse_TX141THBv2 instance
|
||||||
|
*/
|
||||||
|
void ws_protocol_decoder_lacrosse_tx141thbv2_free(void* context);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Reset decoder WSProtocolDecoderLaCrosse_TX141THBv2.
|
||||||
|
* @param context Pointer to a WSProtocolDecoderLaCrosse_TX141THBv2 instance
|
||||||
|
*/
|
||||||
|
void ws_protocol_decoder_lacrosse_tx141thbv2_reset(void* context);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Parse a raw sequence of levels and durations received from the air.
|
||||||
|
* @param context Pointer to a WSProtocolDecoderLaCrosse_TX141THBv2 instance
|
||||||
|
* @param level Signal level true-high false-low
|
||||||
|
* @param duration Duration of this level in, us
|
||||||
|
*/
|
||||||
|
void ws_protocol_decoder_lacrosse_tx141thbv2_feed(void* context, bool level, uint32_t duration);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Getting the hash sum of the last randomly received parcel.
|
||||||
|
* @param context Pointer to a WSProtocolDecoderLaCrosse_TX141THBv2 instance
|
||||||
|
* @return hash Hash sum
|
||||||
|
*/
|
||||||
|
uint8_t ws_protocol_decoder_lacrosse_tx141thbv2_get_hash_data(void* context);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Serialize data WSProtocolDecoderLaCrosse_TX141THBv2.
|
||||||
|
* @param context Pointer to a WSProtocolDecoderLaCrosse_TX141THBv2 instance
|
||||||
|
* @param flipper_format Pointer to a FlipperFormat instance
|
||||||
|
* @param preset The modulation on which the signal was received, SubGhzRadioPreset
|
||||||
|
* @return true On success
|
||||||
|
*/
|
||||||
|
bool ws_protocol_decoder_lacrosse_tx141thbv2_serialize(
|
||||||
|
void* context,
|
||||||
|
FlipperFormat* flipper_format,
|
||||||
|
SubGhzRadioPreset* preset);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Deserialize data WSProtocolDecoderLaCrosse_TX141THBv2.
|
||||||
|
* @param context Pointer to a WSProtocolDecoderLaCrosse_TX141THBv2 instance
|
||||||
|
* @param flipper_format Pointer to a FlipperFormat instance
|
||||||
|
* @return true On success
|
||||||
|
*/
|
||||||
|
bool ws_protocol_decoder_lacrosse_tx141thbv2_deserialize(
|
||||||
|
void* context,
|
||||||
|
FlipperFormat* flipper_format);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Getting a textual representation of the received data.
|
||||||
|
* @param context Pointer to a WSProtocolDecoderLaCrosse_TX141THBv2 instance
|
||||||
|
* @param output Resulting text
|
||||||
|
*/
|
||||||
|
void ws_protocol_decoder_lacrosse_tx141thbv2_get_string(void* context, FuriString* output);
|
@ -127,7 +127,7 @@ static void ws_protocol_nexus_th_remote_controller(WSBlockGeneric* instance) {
|
|||||||
instance->id = (instance->data >> 28) & 0xFF;
|
instance->id = (instance->data >> 28) & 0xFF;
|
||||||
instance->battery_low = !((instance->data >> 27) & 1);
|
instance->battery_low = !((instance->data >> 27) & 1);
|
||||||
instance->channel = ((instance->data >> 24) & 0x03) + 1;
|
instance->channel = ((instance->data >> 24) & 0x03) + 1;
|
||||||
|
instance->btn = WS_NO_BTN;
|
||||||
if(!((instance->data >> 23) & 1)) {
|
if(!((instance->data >> 23) & 1)) {
|
||||||
instance->temp = (float)((instance->data >> 12) & 0x07FF) / 10.0f;
|
instance->temp = (float)((instance->data >> 12) & 0x07FF) / 10.0f;
|
||||||
} else {
|
} else {
|
||||||
|
@ -5,6 +5,8 @@ const SubGhzProtocol* weather_station_protocol_registry_items[] = {
|
|||||||
&ws_protocol_thermopro_tx4,
|
&ws_protocol_thermopro_tx4,
|
||||||
&ws_protocol_nexus_th,
|
&ws_protocol_nexus_th,
|
||||||
&ws_protocol_gt_wt_03,
|
&ws_protocol_gt_wt_03,
|
||||||
|
&ws_protocol_acurite_606tx,
|
||||||
|
&ws_protocol_lacrosse_tx141thbv2,
|
||||||
};
|
};
|
||||||
|
|
||||||
const SubGhzProtocolRegistry weather_station_protocol_registry = {
|
const SubGhzProtocolRegistry weather_station_protocol_registry = {
|
||||||
|
@ -5,5 +5,7 @@
|
|||||||
#include "thermopro_tx4.h"
|
#include "thermopro_tx4.h"
|
||||||
#include "nexus_th.h"
|
#include "nexus_th.h"
|
||||||
#include "gt_wt_03.h"
|
#include "gt_wt_03.h"
|
||||||
|
#include "acurite_606tx.h"
|
||||||
|
#include "lacrosse_tx141thbv2.h"
|
||||||
|
|
||||||
extern const SubGhzProtocolRegistry weather_station_protocol_registry;
|
extern const SubGhzProtocolRegistry weather_station_protocol_registry;
|
||||||
|
@ -105,11 +105,11 @@ bool ws_block_generic_serialize(
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
// temp_data = instance->btn;
|
temp_data = instance->btn;
|
||||||
// if(!flipper_format_write_uint32(flipper_format, "Btn", &temp_data, 1)) {
|
if(!flipper_format_write_uint32(flipper_format, "Btn", &temp_data, 1)) {
|
||||||
// FURI_LOG_E(TAG, "Unable to add Btn");
|
FURI_LOG_E(TAG, "Unable to add Btn");
|
||||||
// break;
|
break;
|
||||||
// }
|
}
|
||||||
|
|
||||||
float temp = instance->temp;
|
float temp = instance->temp;
|
||||||
if(!flipper_format_write_float(flipper_format, "Temp", &temp, 1)) {
|
if(!flipper_format_write_float(flipper_format, "Temp", &temp, 1)) {
|
||||||
@ -174,11 +174,11 @@ bool ws_block_generic_deserialize(WSBlockGeneric* instance, FlipperFormat* flipp
|
|||||||
}
|
}
|
||||||
instance->channel = (uint8_t)temp_data;
|
instance->channel = (uint8_t)temp_data;
|
||||||
|
|
||||||
// if(!flipper_format_read_uint32(flipper_format, "Btn", (uint32_t*)&temp_data, 1)) {
|
if(!flipper_format_read_uint32(flipper_format, "Btn", (uint32_t*)&temp_data, 1)) {
|
||||||
// FURI_LOG_E(TAG, "Missing Btn");
|
FURI_LOG_E(TAG, "Missing Btn");
|
||||||
// break;
|
break;
|
||||||
// }
|
}
|
||||||
// instance->btn = (uint8_t)temp_data;
|
instance->btn = (uint8_t)temp_data;
|
||||||
|
|
||||||
float temp;
|
float temp;
|
||||||
if(!flipper_format_read_float(flipper_format, "Temp", (float*)&temp, 1)) {
|
if(!flipper_format_read_float(flipper_format, "Temp", (float*)&temp, 1)) {
|
||||||
|
@ -13,6 +13,13 @@
|
|||||||
extern "C" {
|
extern "C" {
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#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
|
||||||
|
|
||||||
typedef struct WSBlockGeneric WSBlockGeneric;
|
typedef struct WSBlockGeneric WSBlockGeneric;
|
||||||
|
|
||||||
struct WSBlockGeneric {
|
struct WSBlockGeneric {
|
||||||
|
@ -4,7 +4,6 @@
|
|||||||
#include "../protocols/ws_generic.h"
|
#include "../protocols/ws_generic.h"
|
||||||
#include <input/input.h>
|
#include <input/input.h>
|
||||||
#include <gui/elements.h>
|
#include <gui/elements.h>
|
||||||
#include "math.h"
|
|
||||||
|
|
||||||
#define abs(x) ((x) > 0 ? (x) : -(x))
|
#define abs(x) ((x) > 0 ? (x) : -(x))
|
||||||
|
|
||||||
@ -47,14 +46,26 @@ void ws_view_receiver_info_draw(Canvas* canvas, WSReceiverInfoModel* model) {
|
|||||||
model->generic->data_count_bit);
|
model->generic->data_count_bit);
|
||||||
canvas_draw_str(canvas, 5, 8, buffer);
|
canvas_draw_str(canvas, 5, 8, buffer);
|
||||||
|
|
||||||
|
if(model->generic->channel != WS_NO_CHANNEL) {
|
||||||
snprintf(buffer, sizeof(buffer), "Ch: %01d", model->generic->channel);
|
snprintf(buffer, sizeof(buffer), "Ch: %01d", model->generic->channel);
|
||||||
canvas_draw_str(canvas, 105, 8, buffer);
|
canvas_draw_str(canvas, 105, 8, buffer);
|
||||||
|
}
|
||||||
|
|
||||||
|
if(model->generic->id != WS_NO_ID) {
|
||||||
snprintf(buffer, sizeof(buffer), "Sn: 0x%02lX", model->generic->id);
|
snprintf(buffer, sizeof(buffer), "Sn: 0x%02lX", model->generic->id);
|
||||||
canvas_draw_str(canvas, 5, 20, buffer);
|
canvas_draw_str(canvas, 5, 20, buffer);
|
||||||
|
}
|
||||||
|
|
||||||
snprintf(buffer, sizeof(buffer), "Batt: %s", (!model->generic->battery_low ? "ok" : "low"));
|
if(model->generic->btn != WS_NO_BTN) {
|
||||||
canvas_draw_str(canvas, 85, 20, buffer);
|
snprintf(buffer, sizeof(buffer), "Btn: %01d", model->generic->btn);
|
||||||
|
canvas_draw_str(canvas, 62, 20, buffer);
|
||||||
|
}
|
||||||
|
|
||||||
|
if(model->generic->battery_low != WS_NO_BATT) {
|
||||||
|
snprintf(
|
||||||
|
buffer, sizeof(buffer), "Batt: %s", (!model->generic->battery_low ? "ok" : "low"));
|
||||||
|
canvas_draw_str(canvas, 90, 20, buffer);
|
||||||
|
}
|
||||||
|
|
||||||
snprintf(buffer, sizeof(buffer), "Data: 0x%llX", model->generic->data);
|
snprintf(buffer, sizeof(buffer), "Data: 0x%llX", model->generic->data);
|
||||||
canvas_draw_str(canvas, 5, 32, buffer);
|
canvas_draw_str(canvas, 5, 32, buffer);
|
||||||
@ -62,19 +73,23 @@ void ws_view_receiver_info_draw(Canvas* canvas, WSReceiverInfoModel* model) {
|
|||||||
elements_bold_rounded_frame(canvas, 2, 37, 123, 25);
|
elements_bold_rounded_frame(canvas, 2, 37, 123, 25);
|
||||||
canvas_set_font(canvas, FontPrimary);
|
canvas_set_font(canvas, FontPrimary);
|
||||||
|
|
||||||
canvas_draw_icon(canvas, 13 + 5, 42, &I_Therm_7x16);
|
if(model->generic->temp != WS_NO_TEMPERATURE) {
|
||||||
|
canvas_draw_icon(canvas, 18, 42, &I_Therm_7x16);
|
||||||
snprintf(
|
snprintf(
|
||||||
buffer,
|
buffer,
|
||||||
sizeof(buffer),
|
sizeof(buffer),
|
||||||
"%3.2d.%d C",
|
"%3.2d.%d C",
|
||||||
(int16_t)model->generic->temp,
|
(int16_t)model->generic->temp,
|
||||||
abs(((int16_t)(model->generic->temp * 10) - (((int16_t)model->generic->temp) * 10))));
|
abs(((int16_t)(model->generic->temp * 10) - (((int16_t)model->generic->temp) * 10))));
|
||||||
canvas_draw_str_aligned(canvas, 58 + 5, 46, AlignRight, AlignTop, buffer);
|
canvas_draw_str_aligned(canvas, 63, 46, AlignRight, AlignTop, buffer);
|
||||||
canvas_draw_circle(canvas, 50 + 5, 45, 1);
|
canvas_draw_circle(canvas, 55, 45, 1);
|
||||||
|
}
|
||||||
|
|
||||||
canvas_draw_icon(canvas, 70 + 5, 42, &I_Humid_10x15);
|
if(model->generic->humidity != WS_NO_HUMIDITY) {
|
||||||
|
canvas_draw_icon(canvas, 75, 42, &I_Humid_10x15);
|
||||||
snprintf(buffer, sizeof(buffer), "%d%%", model->generic->humidity);
|
snprintf(buffer, sizeof(buffer), "%d%%", model->generic->humidity);
|
||||||
canvas_draw_str(canvas, 86 + 5, 54, buffer);
|
canvas_draw_str(canvas, 91, 54, buffer);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool ws_view_receiver_info_input(InputEvent* event, void* context) {
|
bool ws_view_receiver_info_input(InputEvent* event, void* context) {
|
||||||
|
@ -2,6 +2,7 @@
|
|||||||
#include <flipper_format/flipper_format_i.h>
|
#include <flipper_format/flipper_format_i.h>
|
||||||
#include <lib/toolbox/stream/stream.h>
|
#include <lib/toolbox/stream/stream.h>
|
||||||
#include <lib/subghz/receiver.h>
|
#include <lib/subghz/receiver.h>
|
||||||
|
#include "protocols/ws_generic.h"
|
||||||
|
|
||||||
#include <furi.h>
|
#include <furi.h>
|
||||||
|
|
||||||
@ -224,20 +225,18 @@ WSHistoryStateAddKey
|
|||||||
for(uint8_t i = 0; i < sizeof(uint64_t); i++) {
|
for(uint8_t i = 0; i < sizeof(uint64_t); i++) {
|
||||||
data = (data << 8) | key_data[i];
|
data = (data << 8) | key_data[i];
|
||||||
}
|
}
|
||||||
if(!(uint32_t)(data >> 32)) {
|
uint32_t temp_data = 0;
|
||||||
furi_string_printf(
|
if(!flipper_format_read_uint32(item->flipper_string, "Ch", (uint32_t*)&temp_data, 1)) {
|
||||||
item->item_str,
|
FURI_LOG_E(TAG, "Missing Channel");
|
||||||
"%s %lX",
|
break;
|
||||||
furi_string_get_cstr(instance->tmp_string),
|
|
||||||
(uint32_t)(data & 0xFFFFFFFF));
|
|
||||||
} else {
|
|
||||||
furi_string_printf(
|
|
||||||
item->item_str,
|
|
||||||
"%s %lX%08lX",
|
|
||||||
furi_string_get_cstr(instance->tmp_string),
|
|
||||||
(uint32_t)(data >> 32),
|
|
||||||
(uint32_t)(data & 0xFFFFFFFF));
|
|
||||||
}
|
}
|
||||||
|
if(temp_data != WS_NO_CHANNEL) {
|
||||||
|
furi_string_cat_printf(instance->tmp_string, " Ch:%X", (uint8_t)temp_data);
|
||||||
|
}
|
||||||
|
|
||||||
|
furi_string_printf(
|
||||||
|
item->item_str, "%s %llX", furi_string_get_cstr(instance->tmp_string), data);
|
||||||
|
|
||||||
} while(false);
|
} while(false);
|
||||||
instance->last_index_write++;
|
instance->last_index_write++;
|
||||||
return WSHistoryStateAddKeyNewDada;
|
return WSHistoryStateAddKeyNewDada;
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
entry,status,name,type,params
|
entry,status,name,type,params
|
||||||
Version,+,3.5,,
|
Version,+,3.6,,
|
||||||
Header,+,applications/services/bt/bt_service/bt.h,,
|
Header,+,applications/services/bt/bt_service/bt.h,,
|
||||||
Header,+,applications/services/cli/cli.h,,
|
Header,+,applications/services/cli/cli.h,,
|
||||||
Header,+,applications/services/cli/cli_vcp.h,,
|
Header,+,applications/services/cli/cli_vcp.h,,
|
||||||
@ -2271,13 +2271,19 @@ Function,-,subghz_keystore_raw_encrypted_save,_Bool,"const char*, const char*, u
|
|||||||
Function,-,subghz_keystore_raw_get_data,_Bool,"const char*, size_t, uint8_t*, size_t"
|
Function,-,subghz_keystore_raw_get_data,_Bool,"const char*, size_t, uint8_t*, size_t"
|
||||||
Function,-,subghz_keystore_save,_Bool,"SubGhzKeystore*, const char*, uint8_t*"
|
Function,-,subghz_keystore_save,_Bool,"SubGhzKeystore*, const char*, uint8_t*"
|
||||||
Function,+,subghz_protocol_blocks_add_bit,void,"SubGhzBlockDecoder*, uint8_t"
|
Function,+,subghz_protocol_blocks_add_bit,void,"SubGhzBlockDecoder*, uint8_t"
|
||||||
|
Function,+,subghz_protocol_blocks_crc16,uint16_t,"const uint8_t[], unsigned, uint16_t, uint16_t"
|
||||||
|
Function,+,subghz_protocol_blocks_crc16lsb,uint16_t,"const uint8_t[], unsigned, uint16_t, uint16_t"
|
||||||
Function,+,subghz_protocol_blocks_crc4,uint8_t,"const uint8_t[], unsigned, uint8_t, uint8_t"
|
Function,+,subghz_protocol_blocks_crc4,uint8_t,"const uint8_t[], unsigned, uint8_t, uint8_t"
|
||||||
Function,+,subghz_protocol_blocks_crc7,uint8_t,"const uint8_t[], unsigned, uint8_t, uint8_t"
|
Function,+,subghz_protocol_blocks_crc7,uint8_t,"const uint8_t[], unsigned, uint8_t, uint8_t"
|
||||||
Function,+,subghz_protocol_blocks_crc8,uint8_t,"const uint8_t[], unsigned, uint8_t, uint8_t"
|
Function,+,subghz_protocol_blocks_crc8,uint8_t,"const uint8_t[], unsigned, uint8_t, uint8_t"
|
||||||
|
Function,+,subghz_protocol_blocks_crc8le,uint8_t,"const uint8_t[], unsigned, uint8_t, uint8_t"
|
||||||
Function,+,subghz_protocol_blocks_get_bit_array,_Bool,"uint8_t[], size_t"
|
Function,+,subghz_protocol_blocks_get_bit_array,_Bool,"uint8_t[], size_t"
|
||||||
Function,+,subghz_protocol_blocks_get_hash_data,uint8_t,"SubGhzBlockDecoder*, size_t"
|
Function,+,subghz_protocol_blocks_get_hash_data,uint8_t,"SubGhzBlockDecoder*, size_t"
|
||||||
Function,+,subghz_protocol_blocks_get_parity,uint8_t,"uint64_t, uint8_t"
|
Function,+,subghz_protocol_blocks_get_parity,uint8_t,"uint64_t, uint8_t"
|
||||||
Function,+,subghz_protocol_blocks_get_upload,size_t,"uint8_t[], size_t, LevelDuration*, size_t, uint32_t"
|
Function,+,subghz_protocol_blocks_get_upload,size_t,"uint8_t[], size_t, LevelDuration*, size_t, uint32_t"
|
||||||
|
Function,+,subghz_protocol_blocks_lfsr_digest16,uint16_t,"const uint8_t[], unsigned, uint16_t, uint16_t"
|
||||||
|
Function,+,subghz_protocol_blocks_lfsr_digest8,uint8_t,"const uint8_t[], unsigned, uint8_t, uint8_t"
|
||||||
|
Function,+,subghz_protocol_blocks_lfsr_digest8_reflect,uint8_t,"const uint8_t[], int, uint8_t, uint8_t"
|
||||||
Function,+,subghz_protocol_blocks_reverse_key,uint64_t,"uint64_t, uint8_t"
|
Function,+,subghz_protocol_blocks_reverse_key,uint64_t,"uint64_t, uint8_t"
|
||||||
Function,+,subghz_protocol_blocks_set_bit_array,void,"_Bool, uint8_t[], size_t, size_t"
|
Function,+,subghz_protocol_blocks_set_bit_array,void,"_Bool, uint8_t[], size_t, size_t"
|
||||||
Function,-,subghz_protocol_decoder_base_deserialize,_Bool,"SubGhzProtocolDecoderBase*, FlipperFormat*"
|
Function,-,subghz_protocol_decoder_base_deserialize,_Bool,"SubGhzProtocolDecoderBase*, FlipperFormat*"
|
||||||
|
|
@ -80,3 +80,140 @@ uint8_t subghz_protocol_blocks_crc8(
|
|||||||
}
|
}
|
||||||
return remainder;
|
return remainder;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
uint8_t subghz_protocol_blocks_crc8le(
|
||||||
|
uint8_t const message[],
|
||||||
|
unsigned nBytes,
|
||||||
|
uint8_t polynomial,
|
||||||
|
uint8_t init) {
|
||||||
|
uint8_t remainder = subghz_protocol_blocks_reverse_key(init, 8);
|
||||||
|
unsigned byte, bit;
|
||||||
|
polynomial = subghz_protocol_blocks_reverse_key(polynomial, 8);
|
||||||
|
|
||||||
|
for(byte = 0; byte < nBytes; ++byte) {
|
||||||
|
remainder ^= message[byte];
|
||||||
|
for(bit = 0; bit < 8; ++bit) {
|
||||||
|
if(remainder & 1) {
|
||||||
|
remainder = (remainder >> 1) ^ polynomial;
|
||||||
|
} else {
|
||||||
|
remainder = (remainder >> 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return remainder;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint16_t subghz_protocol_blocks_crc16lsb(
|
||||||
|
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];
|
||||||
|
for(bit = 0; bit < 8; ++bit) {
|
||||||
|
if(remainder & 1) {
|
||||||
|
remainder = (remainder >> 1) ^ polynomial;
|
||||||
|
} else {
|
||||||
|
remainder = (remainder >> 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return remainder;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint16_t subghz_protocol_blocks_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;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint8_t subghz_protocol_blocks_lfsr_digest8(
|
||||||
|
uint8_t const message[],
|
||||||
|
unsigned bytes,
|
||||||
|
uint8_t gen,
|
||||||
|
uint8_t key) {
|
||||||
|
uint8_t sum = 0;
|
||||||
|
for(unsigned k = 0; k < bytes; ++k) {
|
||||||
|
uint8_t data = message[k];
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint8_t subghz_protocol_blocks_lfsr_digest8_reflect(
|
||||||
|
uint8_t const message[],
|
||||||
|
int bytes,
|
||||||
|
uint8_t gen,
|
||||||
|
uint8_t key) {
|
||||||
|
uint8_t sum = 0;
|
||||||
|
// Process message from last byte to first byte (reflected)
|
||||||
|
for(int k = bytes - 1; k >= 0; --k) {
|
||||||
|
uint8_t data = message[k];
|
||||||
|
// Process individual bits of each byte (reflected)
|
||||||
|
for(int 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;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint16_t subghz_protocol_blocks_lfsr_digest16(
|
||||||
|
uint8_t const message[],
|
||||||
|
unsigned bytes,
|
||||||
|
uint16_t gen,
|
||||||
|
uint16_t key) {
|
||||||
|
uint16_t sum = 0;
|
||||||
|
for(unsigned k = 0; k < bytes; ++k) {
|
||||||
|
uint8_t data = message[k];
|
||||||
|
for(int i = 7; i >= 0; --i) {
|
||||||
|
// if data bit is set then xor with key
|
||||||
|
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;
|
||||||
|
}
|
@ -19,7 +19,7 @@ extern "C" {
|
|||||||
* @param key In data
|
* @param key In data
|
||||||
* @param count_bit number of data bits
|
* @param count_bit number of data bits
|
||||||
* @return Reverse data
|
* @return Reverse data
|
||||||
*/
|
**/
|
||||||
uint64_t subghz_protocol_blocks_reverse_key(uint64_t key, uint8_t count_bit);
|
uint64_t subghz_protocol_blocks_reverse_key(uint64_t key, uint8_t count_bit);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -27,7 +27,7 @@ uint64_t subghz_protocol_blocks_reverse_key(uint64_t key, uint8_t count_bit);
|
|||||||
* @param key In data
|
* @param key In data
|
||||||
* @param count_bit number of data bits
|
* @param count_bit number of data bits
|
||||||
* @return parity
|
* @return parity
|
||||||
*/
|
**/
|
||||||
uint8_t subghz_protocol_blocks_get_parity(uint64_t key, uint8_t count_bit);
|
uint8_t subghz_protocol_blocks_get_parity(uint64_t key, uint8_t count_bit);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -37,7 +37,7 @@ uint8_t subghz_protocol_blocks_get_parity(uint64_t key, uint8_t count_bit);
|
|||||||
* @param polynomial CRC polynomial
|
* @param polynomial CRC polynomial
|
||||||
* @param init starting crc value
|
* @param init starting crc value
|
||||||
* @return CRC value
|
* @return CRC value
|
||||||
*/
|
**/
|
||||||
uint8_t subghz_protocol_blocks_crc4(
|
uint8_t subghz_protocol_blocks_crc4(
|
||||||
uint8_t const message[],
|
uint8_t const message[],
|
||||||
unsigned nBytes,
|
unsigned nBytes,
|
||||||
@ -51,7 +51,7 @@ uint8_t subghz_protocol_blocks_crc4(
|
|||||||
* @param polynomial CRC polynomial
|
* @param polynomial CRC polynomial
|
||||||
* @param init starting crc value
|
* @param init starting crc value
|
||||||
* @return CRC value
|
* @return CRC value
|
||||||
*/
|
**/
|
||||||
uint8_t subghz_protocol_blocks_crc7(
|
uint8_t subghz_protocol_blocks_crc7(
|
||||||
uint8_t const message[],
|
uint8_t const message[],
|
||||||
unsigned nBytes,
|
unsigned nBytes,
|
||||||
@ -67,13 +67,100 @@ uint8_t subghz_protocol_blocks_crc7(
|
|||||||
* @param polynomial byte is from x^7 to x^0 (x^8 is implicitly one)
|
* @param polynomial byte is from x^7 to x^0 (x^8 is implicitly one)
|
||||||
* @param init starting crc value
|
* @param init starting crc value
|
||||||
* @return CRC value
|
* @return CRC value
|
||||||
*/
|
**/
|
||||||
uint8_t subghz_protocol_blocks_crc8(
|
uint8_t subghz_protocol_blocks_crc8(
|
||||||
uint8_t const message[],
|
uint8_t const message[],
|
||||||
unsigned nBytes,
|
unsigned nBytes,
|
||||||
uint8_t polynomial,
|
uint8_t polynomial,
|
||||||
uint8_t init);
|
uint8_t init);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* "Little-endian" Cyclic Redundancy Check CRC-8 LE
|
||||||
|
* Input and output are reflected, i.e. least significant bit is shifted in first.
|
||||||
|
* @param message array of bytes to check
|
||||||
|
* @param nBytes number of bytes in message
|
||||||
|
* @param polynomial CRC polynomial
|
||||||
|
* @param init starting crc value
|
||||||
|
* @return CRC value
|
||||||
|
**/
|
||||||
|
uint8_t subghz_protocol_blocks_crc8le(
|
||||||
|
uint8_t const message[],
|
||||||
|
unsigned nBytes,
|
||||||
|
uint8_t polynomial,
|
||||||
|
uint8_t init);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* CRC-16 LSB.
|
||||||
|
* Input and output are reflected, i.e. least significant bit is shifted in first.
|
||||||
|
* Note that poly and init already need to be reflected.
|
||||||
|
* @param message array of bytes to check
|
||||||
|
* @param nBytes number of bytes in message
|
||||||
|
* @param polynomial CRC polynomial
|
||||||
|
* @param init starting crc value
|
||||||
|
* @return CRC value
|
||||||
|
**/
|
||||||
|
uint16_t subghz_protocol_blocks_crc16lsb(
|
||||||
|
uint8_t const message[],
|
||||||
|
unsigned nBytes,
|
||||||
|
uint16_t polynomial,
|
||||||
|
uint16_t init);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* CRC-16.
|
||||||
|
* @param message array of bytes to check
|
||||||
|
* @param nBytes number of bytes in message
|
||||||
|
* @param polynomial CRC polynomial
|
||||||
|
* @param init starting crc value
|
||||||
|
* @return CRC value
|
||||||
|
**/
|
||||||
|
uint16_t subghz_protocol_blocks_crc16(
|
||||||
|
uint8_t const message[],
|
||||||
|
unsigned nBytes,
|
||||||
|
uint16_t polynomial,
|
||||||
|
uint16_t init);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Digest-8 by "LFSR-based Toeplitz hash".
|
||||||
|
* @param message bytes of message data
|
||||||
|
* @param bytes number of bytes to digest
|
||||||
|
* @param gen key stream generator, needs to includes the MSB if the LFSR is rolling
|
||||||
|
* @param key initial key
|
||||||
|
* @return digest value
|
||||||
|
**/
|
||||||
|
uint8_t subghz_protocol_blocks_lfsr_digest8(
|
||||||
|
uint8_t const message[],
|
||||||
|
unsigned bytes,
|
||||||
|
uint8_t gen,
|
||||||
|
uint8_t key);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Digest-8 by "LFSR-based Toeplitz hash", byte reflect, bit reflect.
|
||||||
|
* @param message bytes of message data
|
||||||
|
* @param bytes number of bytes to digest
|
||||||
|
* @param gen key stream generator, needs to includes the MSB if the LFSR is rolling
|
||||||
|
* @param key initial key
|
||||||
|
* @return digest value
|
||||||
|
**/
|
||||||
|
uint8_t subghz_protocol_blocks_lfsr_digest8_reflect(
|
||||||
|
uint8_t const message[],
|
||||||
|
int bytes,
|
||||||
|
uint8_t gen,
|
||||||
|
uint8_t key);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Digest-16 by "LFSR-based Toeplitz hash".
|
||||||
|
* @param message bytes of message data
|
||||||
|
* @param bytes number of bytes to digest
|
||||||
|
* @param gen key stream generator, needs to includes the MSB if the LFSR is rolling
|
||||||
|
* @param key initial key
|
||||||
|
* @return digest value
|
||||||
|
**/
|
||||||
|
uint16_t subghz_protocol_blocks_lfsr_digest16(
|
||||||
|
uint8_t const message[],
|
||||||
|
unsigned bytes,
|
||||||
|
uint16_t gen,
|
||||||
|
uint16_t key);
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
Loading…
x
Reference in New Issue
Block a user