mirror of
https://github.com/Next-Flip/Momentum-Firmware.git
synced 2026-07-26 01:48:10 -07:00
Merge remote-tracking branch 'mntm/dev' into ofw-3822-nestednonces
This commit is contained in:
@@ -646,6 +646,33 @@ NfcError nfc_iso15693_listener_tx_sof(Nfc* instance) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
NfcError nfc_iso15693_detect_mode(Nfc* instance) {
|
||||
furi_check(instance);
|
||||
|
||||
FuriHalNfcError error = furi_hal_nfc_iso15693_detect_mode();
|
||||
NfcError ret = nfc_process_hal_error(error);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
NfcError nfc_iso15693_force_1outof4(Nfc* instance) {
|
||||
furi_check(instance);
|
||||
|
||||
FuriHalNfcError error = furi_hal_nfc_iso15693_force_1outof4();
|
||||
NfcError ret = nfc_process_hal_error(error);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
NfcError nfc_iso15693_force_1outof256(Nfc* instance) {
|
||||
furi_check(instance);
|
||||
|
||||
FuriHalNfcError error = furi_hal_nfc_iso15693_force_1outof256();
|
||||
NfcError ret = nfc_process_hal_error(error);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
NfcError nfc_felica_listener_set_sensf_res_data(
|
||||
Nfc* instance,
|
||||
const uint8_t* idm,
|
||||
|
||||
@@ -380,6 +380,30 @@ NfcError nfc_felica_listener_set_sensf_res_data(
|
||||
*/
|
||||
NfcError nfc_iso15693_listener_tx_sof(Nfc* instance);
|
||||
|
||||
/**
|
||||
* @brief Set ISO15693 parser mode to autodetect
|
||||
*
|
||||
* @param[in,out] instance pointer to the instance to be configured.
|
||||
* @returns NfcErrorNone on success, any other error code on failure.
|
||||
*/
|
||||
NfcError nfc_iso15693_detect_mode(Nfc* instance);
|
||||
|
||||
/**
|
||||
* @brief Set ISO15693 parser mode to 1OutOf4, disables autodetection
|
||||
*
|
||||
* @param[in,out] instance pointer to the instance to be configured.
|
||||
* @return NfcErrorNone on success, any other error code on failure.
|
||||
*/
|
||||
NfcError nfc_iso15693_force_1outof4(Nfc* instance);
|
||||
|
||||
/**
|
||||
* @brief Set ISO15693 parser mode to 1OutOf256, disables autodetection
|
||||
*
|
||||
* @param[in,out] instance pointer to the instance to be configured.
|
||||
* @return NfcErrorNone on success, any other error code on failure.
|
||||
*/
|
||||
NfcError nfc_iso15693_force_1outof256(Nfc* instance);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -26,6 +26,7 @@ typedef enum {
|
||||
struct Iso15693Parser {
|
||||
Iso15693ParserState state;
|
||||
Iso15693ParserMode mode;
|
||||
bool detect_mode;
|
||||
|
||||
SignalReader* signal_reader;
|
||||
|
||||
@@ -62,6 +63,7 @@ typedef Iso15693ParserCommand (*Iso15693ParserStateHandler)(Iso15693Parser* inst
|
||||
|
||||
Iso15693Parser* iso15693_parser_alloc(const GpioPin* pin, size_t max_frame_size) {
|
||||
Iso15693Parser* instance = malloc(sizeof(Iso15693Parser));
|
||||
instance->detect_mode = true;
|
||||
instance->parsed_frame = bit_buffer_alloc(max_frame_size);
|
||||
|
||||
instance->signal_reader = signal_reader_alloc(pin, ISO15693_PARSER_SIGNAL_READER_BUFF_SIZE);
|
||||
@@ -86,7 +88,7 @@ void iso15693_parser_reset(Iso15693Parser* instance) {
|
||||
furi_assert(instance);
|
||||
|
||||
instance->state = Iso15693ParserStateParseSoF;
|
||||
instance->mode = Iso15693ParserMode1OutOf4;
|
||||
if(instance->detect_mode) instance->mode = Iso15693ParserMode1OutOf4;
|
||||
memset(instance->bitstream_buff, 0x00, sizeof(instance->bitstream_buff));
|
||||
instance->bitstream_idx = 0;
|
||||
|
||||
@@ -122,10 +124,10 @@ static void signal_reader_callback(SignalReaderEvent event, void* context) {
|
||||
|
||||
if(instance->state == Iso15693ParserStateParseSoF) {
|
||||
if(event.data->data[0] == sof_1_out_of_4) {
|
||||
instance->mode = Iso15693ParserMode1OutOf4;
|
||||
if(instance->detect_mode) instance->mode = Iso15693ParserMode1OutOf4;
|
||||
instance->state = Iso15693ParserStateParseFrame;
|
||||
} else if(event.data->data[0] == sof_1_out_of_256) {
|
||||
instance->mode = Iso15693ParserMode1OutOf256;
|
||||
if(instance->detect_mode) instance->mode = Iso15693ParserMode1OutOf256;
|
||||
instance->state = Iso15693ParserStateParseFrame;
|
||||
} else if(event.data->data[0] == eof_single) {
|
||||
instance->eof_received = true;
|
||||
@@ -298,3 +300,23 @@ void iso15693_parser_get_data(
|
||||
bit_buffer_write_bytes(instance->parsed_frame, buff, buff_size);
|
||||
*data_bits = bit_buffer_get_size(instance->parsed_frame);
|
||||
}
|
||||
|
||||
void iso15693_parser_detect_mode(Iso15693Parser* instance) {
|
||||
furi_assert(instance);
|
||||
|
||||
instance->detect_mode = true;
|
||||
}
|
||||
|
||||
void iso15693_parser_force_1outof4(Iso15693Parser* instance) {
|
||||
furi_assert(instance);
|
||||
|
||||
instance->detect_mode = false;
|
||||
instance->mode = Iso15693ParserMode1OutOf4;
|
||||
}
|
||||
|
||||
void iso15693_parser_force_1outof256(Iso15693Parser* instance) {
|
||||
furi_assert(instance);
|
||||
|
||||
instance->detect_mode = false;
|
||||
instance->mode = Iso15693ParserMode1OutOf256;
|
||||
}
|
||||
|
||||
@@ -37,6 +37,10 @@ void iso15693_parser_get_data(
|
||||
size_t buff_size,
|
||||
size_t* data_bits);
|
||||
|
||||
void iso15693_parser_detect_mode(Iso15693Parser* instance);
|
||||
void iso15693_parser_force_1outof4(Iso15693Parser* instance);
|
||||
void iso15693_parser_force_1outof256(Iso15693Parser* instance);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -0,0 +1,264 @@
|
||||
#include "bresser_3ch.h"
|
||||
#include "furi/core/log.h"
|
||||
#define TAG "WSProtocolBresser3ch"
|
||||
|
||||
/*
|
||||
* Help:
|
||||
* https://github.com/merbanan/rtl_433/blob/master/src/devices/bresser_3ch.c
|
||||
*
|
||||
* Bresser sensor protocol.
|
||||
*
|
||||
* The protocol is for the wireless Temperature/Humidity sensor
|
||||
* - Bresser Thermo-/Hygro-Sensor 3CH
|
||||
* - also works for Renkforce DM-7511
|
||||
*
|
||||
* The sensor sends 15 identical packages of 40 bits each ~60s.
|
||||
* The bits are PWM modulated with On Off Keying.
|
||||
*
|
||||
* A short pulse of 250 us followed by a 500 us gap is a 0 bit,
|
||||
* a long pulse of 500 us followed by a 250 us gap is a 1 bit,
|
||||
* there is a sync preamble of pulse, gap, 750 us each, repeated 4 times.
|
||||
* Actual received and demodulated timings might be 2% shorter.
|
||||
*
|
||||
* The data is grouped in 5 bytes / 10 nibbles
|
||||
*
|
||||
* [id] [id] [flags] [temp] [temp] [temp] [humi] [humi] [chk] [chk]
|
||||
*
|
||||
* - id is an 8 bit random id that is generated when the sensor starts
|
||||
* - flags are 4 bits battery low indicator, test button press and channel
|
||||
* - temp is 12 bit unsigned fahrenheit offset by 90 and scaled by 10
|
||||
* - humi is 8 bit relative humidity percentage
|
||||
* - chk is the sum of the four data bytes
|
||||
*
|
||||
* @m7i-org - because there's more stuff screaming in the ether than you might think
|
||||
*
|
||||
*/
|
||||
|
||||
static const SubGhzBlockConst ws_protocol_bresser_3ch_const = {
|
||||
.te_short = 250,
|
||||
.te_long = 500,
|
||||
.te_delta = 150,
|
||||
.min_count_bit_for_found = 40,
|
||||
};
|
||||
|
||||
struct WSProtocolDecoderBresser3ch {
|
||||
SubGhzProtocolDecoderBase base;
|
||||
|
||||
SubGhzBlockDecoder decoder;
|
||||
WSBlockGeneric generic;
|
||||
};
|
||||
|
||||
struct WSProtocolEncoderBresser3ch {
|
||||
SubGhzProtocolEncoderBase base;
|
||||
|
||||
SubGhzProtocolBlockEncoder encoder;
|
||||
WSBlockGeneric generic;
|
||||
};
|
||||
|
||||
const SubGhzProtocolDecoder ws_protocol_bresser_3ch_decoder = {
|
||||
.alloc = ws_protocol_decoder_bresser_3ch_alloc,
|
||||
.free = ws_protocol_decoder_bresser_3ch_free,
|
||||
|
||||
.feed = ws_protocol_decoder_bresser_3ch_feed,
|
||||
.reset = ws_protocol_decoder_bresser_3ch_reset,
|
||||
|
||||
.get_hash_data = NULL,
|
||||
.get_hash_data_long = ws_protocol_decoder_bresser_3ch_get_hash_data,
|
||||
.serialize = ws_protocol_decoder_bresser_3ch_serialize,
|
||||
.deserialize = ws_protocol_decoder_bresser_3ch_deserialize,
|
||||
.get_string = ws_protocol_decoder_bresser_3ch_get_string,
|
||||
.get_string_brief = NULL,
|
||||
};
|
||||
|
||||
const SubGhzProtocolEncoder ws_protocol_bresser_3ch_encoder = {
|
||||
.alloc = NULL,
|
||||
.free = NULL,
|
||||
|
||||
.deserialize = NULL,
|
||||
.stop = NULL,
|
||||
.yield = NULL,
|
||||
};
|
||||
|
||||
const SubGhzProtocol ws_protocol_bresser_3ch = {
|
||||
.name = WS_PROTOCOL_BRESSER_3CH_NAME,
|
||||
.type = SubGhzProtocolTypeStatic,
|
||||
.flag = SubGhzProtocolFlag_433 | SubGhzProtocolFlag_315 | SubGhzProtocolFlag_868 |
|
||||
SubGhzProtocolFlag_AM | SubGhzProtocolFlag_Decodable | SubGhzProtocolFlag_Load |
|
||||
SubGhzProtocolFlag_Save,
|
||||
.filter = SubGhzProtocolFilter_Weather,
|
||||
.decoder = &ws_protocol_bresser_3ch_decoder,
|
||||
.encoder = &ws_protocol_bresser_3ch_encoder,
|
||||
};
|
||||
|
||||
typedef enum {
|
||||
Bresser3chDecoderStepReset = 0,
|
||||
Bresser3chDecoderStepPreambleDn,
|
||||
Bresser3chDecoderStepPreambleUp,
|
||||
Bresser3chDecoderStepSaveDuration,
|
||||
Bresser3chDecoderStepCheckDuration,
|
||||
} Bresser3chDecoderStep;
|
||||
|
||||
void* ws_protocol_decoder_bresser_3ch_alloc(SubGhzEnvironment* environment) {
|
||||
UNUSED(environment);
|
||||
WSProtocolDecoderBresser3ch* instance = malloc(sizeof(WSProtocolDecoderBresser3ch));
|
||||
instance->base.protocol = &ws_protocol_bresser_3ch;
|
||||
instance->generic.protocol_name = instance->base.protocol->name;
|
||||
return instance;
|
||||
}
|
||||
|
||||
void ws_protocol_decoder_bresser_3ch_free(void* context) {
|
||||
furi_assert(context);
|
||||
WSProtocolDecoderBresser3ch* instance = context;
|
||||
free(instance);
|
||||
}
|
||||
|
||||
void ws_protocol_decoder_bresser_3ch_reset(void* context) {
|
||||
furi_assert(context);
|
||||
WSProtocolDecoderBresser3ch* instance = context;
|
||||
instance->decoder.parser_step = Bresser3chDecoderStepReset;
|
||||
}
|
||||
|
||||
static bool ws_protocol_bresser_3ch_check(WSProtocolDecoderBresser3ch* instance) {
|
||||
if(!instance->decoder.decode_data) return false;
|
||||
|
||||
uint8_t sum = (((instance->decoder.decode_data >> 32) & 0xff) +
|
||||
((instance->decoder.decode_data >> 24) & 0xff) +
|
||||
((instance->decoder.decode_data >> 16) & 0xff) +
|
||||
((instance->decoder.decode_data >> 8) & 0xff)) &
|
||||
0xff;
|
||||
|
||||
return (instance->decoder.decode_data & 0xff) == sum;
|
||||
}
|
||||
|
||||
/**
|
||||
* Analysis of received data
|
||||
* @param instance Pointer to a WSBlockGeneric* instance
|
||||
*/
|
||||
static void ws_protocol_bresser_3ch_extract_data(WSBlockGeneric* instance) {
|
||||
instance->id = (instance->data >> 32) & 0xff;
|
||||
instance->battery_low = ((instance->data >> 31) & 0x1);
|
||||
instance->btn = (instance->data >> 30) & 0x1;
|
||||
instance->channel = (instance->data >> 28) & 0x3;
|
||||
|
||||
int16_t temp = (instance->data >> 16) & 0xfff;
|
||||
instance->temp = locale_fahrenheit_to_celsius((float)(temp - 900) / 10.0);
|
||||
|
||||
instance->humidity = (instance->data >> 8) & 0xff;
|
||||
}
|
||||
|
||||
void ws_protocol_decoder_bresser_3ch_feed(void* context, bool level, uint32_t duration) {
|
||||
furi_assert(context);
|
||||
WSProtocolDecoderBresser3ch* instance = context;
|
||||
|
||||
switch(instance->decoder.parser_step) {
|
||||
case Bresser3chDecoderStepReset:
|
||||
if(level && DURATION_DIFF(duration, ws_protocol_bresser_3ch_const.te_short * 3) <
|
||||
ws_protocol_bresser_3ch_const.te_delta) {
|
||||
instance->decoder.te_last = duration;
|
||||
instance->decoder.parser_step = Bresser3chDecoderStepPreambleDn;
|
||||
instance->decoder.decode_data = 0;
|
||||
instance->decoder.decode_count_bit = 0;
|
||||
}
|
||||
break;
|
||||
|
||||
case Bresser3chDecoderStepPreambleDn:
|
||||
if((!level) && DURATION_DIFF(duration, ws_protocol_bresser_3ch_const.te_short * 3) <
|
||||
ws_protocol_bresser_3ch_const.te_delta) {
|
||||
if(DURATION_DIFF(
|
||||
instance->decoder.te_last, ws_protocol_bresser_3ch_const.te_short * 12) <
|
||||
ws_protocol_bresser_3ch_const.te_delta * 2) {
|
||||
// End of sync after 4*750 (12*250) high values, start reading the message
|
||||
instance->decoder.parser_step = Bresser3chDecoderStepSaveDuration;
|
||||
} else {
|
||||
instance->decoder.parser_step = Bresser3chDecoderStepPreambleUp;
|
||||
}
|
||||
} else {
|
||||
instance->decoder.parser_step = Bresser3chDecoderStepReset;
|
||||
}
|
||||
break;
|
||||
|
||||
case Bresser3chDecoderStepPreambleUp:
|
||||
if(level && DURATION_DIFF(duration, ws_protocol_bresser_3ch_const.te_short * 3) <
|
||||
ws_protocol_bresser_3ch_const.te_delta) {
|
||||
instance->decoder.te_last = instance->decoder.te_last + duration;
|
||||
instance->decoder.parser_step = Bresser3chDecoderStepPreambleDn;
|
||||
} else {
|
||||
instance->decoder.parser_step = Bresser3chDecoderStepReset;
|
||||
}
|
||||
break;
|
||||
|
||||
case Bresser3chDecoderStepSaveDuration:
|
||||
if(instance->decoder.decode_count_bit ==
|
||||
ws_protocol_bresser_3ch_const.min_count_bit_for_found) {
|
||||
if(ws_protocol_bresser_3ch_check(instance)) {
|
||||
instance->generic.data = instance->decoder.decode_data;
|
||||
instance->generic.data_count_bit = instance->decoder.decode_count_bit;
|
||||
ws_protocol_bresser_3ch_extract_data(&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->decoder.parser_step = Bresser3chDecoderStepReset;
|
||||
} else if(level) {
|
||||
instance->decoder.te_last = duration;
|
||||
instance->decoder.parser_step = Bresser3chDecoderStepCheckDuration;
|
||||
} else {
|
||||
instance->decoder.parser_step = Bresser3chDecoderStepReset;
|
||||
}
|
||||
break;
|
||||
|
||||
case Bresser3chDecoderStepCheckDuration:
|
||||
if(!level) {
|
||||
if(DURATION_DIFF(instance->decoder.te_last, ws_protocol_bresser_3ch_const.te_short) <
|
||||
ws_protocol_bresser_3ch_const.te_delta &&
|
||||
DURATION_DIFF(duration, ws_protocol_bresser_3ch_const.te_long) <
|
||||
ws_protocol_bresser_3ch_const.te_delta) {
|
||||
subghz_protocol_blocks_add_bit(&instance->decoder, 0);
|
||||
instance->decoder.parser_step = Bresser3chDecoderStepSaveDuration;
|
||||
} else if(
|
||||
DURATION_DIFF(instance->decoder.te_last, ws_protocol_bresser_3ch_const.te_long) <
|
||||
ws_protocol_bresser_3ch_const.te_delta &&
|
||||
DURATION_DIFF(duration, ws_protocol_bresser_3ch_const.te_short) <
|
||||
ws_protocol_bresser_3ch_const.te_delta) {
|
||||
subghz_protocol_blocks_add_bit(&instance->decoder, 1);
|
||||
instance->decoder.parser_step = Bresser3chDecoderStepSaveDuration;
|
||||
} else
|
||||
instance->decoder.parser_step = Bresser3chDecoderStepReset;
|
||||
} else
|
||||
instance->decoder.parser_step = Bresser3chDecoderStepReset;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
uint32_t ws_protocol_decoder_bresser_3ch_get_hash_data(void* context) {
|
||||
furi_assert(context);
|
||||
WSProtocolDecoderBresser3ch* instance = context;
|
||||
return subghz_protocol_blocks_get_hash_data_long(
|
||||
&instance->decoder, (instance->decoder.decode_count_bit / 8) + 1);
|
||||
}
|
||||
|
||||
SubGhzProtocolStatus ws_protocol_decoder_bresser_3ch_serialize(
|
||||
void* context,
|
||||
FlipperFormat* flipper_format,
|
||||
SubGhzRadioPreset* preset) {
|
||||
furi_assert(context);
|
||||
WSProtocolDecoderBresser3ch* instance = context;
|
||||
return ws_block_generic_serialize(&instance->generic, flipper_format, preset);
|
||||
}
|
||||
|
||||
SubGhzProtocolStatus
|
||||
ws_protocol_decoder_bresser_3ch_deserialize(void* context, FlipperFormat* flipper_format) {
|
||||
furi_assert(context);
|
||||
WSProtocolDecoderBresser3ch* instance = context;
|
||||
return ws_block_generic_deserialize_check_count_bit(
|
||||
&instance->generic, flipper_format, ws_protocol_bresser_3ch_const.min_count_bit_for_found);
|
||||
}
|
||||
|
||||
void ws_protocol_decoder_bresser_3ch_get_string(void* context, FuriString* output) {
|
||||
furi_assert(context);
|
||||
WSProtocolDecoderBresser3ch* instance = context;
|
||||
ws_block_generic_get_string(&instance->generic, output);
|
||||
}
|
||||
@@ -0,0 +1,80 @@
|
||||
#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_BRESSER_3CH_NAME "Bresser-3CH"
|
||||
|
||||
typedef struct WSProtocolDecoderBresser3ch WSProtocolDecoderBresser3ch;
|
||||
typedef struct WSProtocolEncoderBresser3ch WSProtocolEncoderBresser3ch;
|
||||
|
||||
extern const SubGhzProtocolDecoder ws_protocol_bresser_3ch_decoder;
|
||||
extern const SubGhzProtocolEncoder ws_protocol_bresser_3ch_encoder;
|
||||
extern const SubGhzProtocol ws_protocol_bresser_3ch;
|
||||
|
||||
/**
|
||||
* Allocate WSProtocolDecoderBresser3ch.
|
||||
* @param environment Pointer to a SubGhzEnvironment instance
|
||||
* @return WSProtocolDecoderBresser3ch* pointer to a WSProtocolDecoderBresser3ch instance
|
||||
*/
|
||||
void* ws_protocol_decoder_bresser_3ch_alloc(SubGhzEnvironment* environment);
|
||||
|
||||
/**
|
||||
* Free WSProtocolDecoderBresser3ch.
|
||||
* @param context Pointer to a WSProtocolDecoderBresser3ch instance
|
||||
*/
|
||||
void ws_protocol_decoder_bresser_3ch_free(void* context);
|
||||
|
||||
/**
|
||||
* Reset decoder WSProtocolDecoderBresser3ch.
|
||||
* @param context Pointer to a WSProtocolDecoderBresser3ch instance
|
||||
*/
|
||||
void ws_protocol_decoder_bresser_3ch_reset(void* context);
|
||||
|
||||
/**
|
||||
* Parse a raw sequence of levels and durations received from the air.
|
||||
* @param context Pointer to a WSProtocolDecoderBresser3ch instance
|
||||
* @param level Signal level true-high false-low
|
||||
* @param duration Duration of this level in, us
|
||||
*/
|
||||
void ws_protocol_decoder_bresser_3ch_feed(void* context, bool level, uint32_t duration);
|
||||
|
||||
/**
|
||||
* Getting the hash sum of the last randomly received parcel.
|
||||
* @param context Pointer to a WSProtocolDecoderBresser3ch instance
|
||||
* @return hash Hash sum
|
||||
*/
|
||||
uint32_t ws_protocol_decoder_bresser_3ch_get_hash_data(void* context);
|
||||
|
||||
/**
|
||||
* Serialize data WSProtocolDecoderBresser3ch.
|
||||
* @param context Pointer to a WSProtocolDecoderBresser3ch instance
|
||||
* @param flipper_format Pointer to a FlipperFormat instance
|
||||
* @param preset The modulation on which the signal was received, SubGhzRadioPreset
|
||||
* @return status
|
||||
*/
|
||||
SubGhzProtocolStatus ws_protocol_decoder_bresser_3ch_serialize(
|
||||
void* context,
|
||||
FlipperFormat* flipper_format,
|
||||
SubGhzRadioPreset* preset);
|
||||
|
||||
/**
|
||||
* Deserialize data WSProtocolDecoderBresser3ch.
|
||||
* @param context Pointer to a WSProtocolDecoderBresser3ch instance
|
||||
* @param flipper_format Pointer to a FlipperFormat instance
|
||||
* @return status
|
||||
*/
|
||||
SubGhzProtocolStatus
|
||||
ws_protocol_decoder_bresser_3ch_deserialize(void* context, FlipperFormat* flipper_format);
|
||||
|
||||
/**
|
||||
* Getting a textual representation of the received data.
|
||||
* @param context Pointer to a WSProtocolDecoderBresser3ch instance
|
||||
* @param output Resulting text
|
||||
*/
|
||||
void ws_protocol_decoder_bresser_3ch_get_string(void* context, FuriString* output);
|
||||
@@ -498,8 +498,7 @@ void subghz_protocol_decoder_gangqi_get_string(void* context, FuriString* output
|
||||
bool serial_is_valid =
|
||||
(((!(sum_3bytes_serial & 0x3)) &&
|
||||
((0xB < sum_3bytes_serial) && (sum_3bytes_serial < 0x141))) &&
|
||||
((((instance->generic.serial >> 16) & 0xFF) == 0x2) ||
|
||||
(((instance->generic.serial >> 16) & 0xFF) == 0x3)));
|
||||
(((instance->generic.serial >> 16) & 0xFF) <= 0x3));
|
||||
|
||||
furi_string_cat_printf(
|
||||
output,
|
||||
|
||||
@@ -404,16 +404,16 @@ static const char* subghz_protocol_hollarm_get_button_name(uint8_t btn) {
|
||||
"Disarm", // B (2)
|
||||
"Arm", // A (1)
|
||||
"0x3",
|
||||
"Alarm", // C (3)
|
||||
"Ringtone/Alarm", // C (3)
|
||||
"0x5",
|
||||
"0x6",
|
||||
"0x7",
|
||||
"Ring", // D (4)
|
||||
"0x9",
|
||||
"0xA",
|
||||
"0xB",
|
||||
"0xC",
|
||||
"0xD",
|
||||
"Settings mode",
|
||||
"Exit settings",
|
||||
"Vibro sens. setting",
|
||||
"Not used\n(in settings)",
|
||||
"Volume setting",
|
||||
"0xE",
|
||||
"0xF"};
|
||||
return btn <= 0xf ? name_btn[btn] : name_btn[0];
|
||||
|
||||
@@ -6,6 +6,8 @@
|
||||
#include "../blocks/generic.h"
|
||||
#include "../blocks/math.h"
|
||||
|
||||
#include "../blocks/custom_btn_i.h"
|
||||
|
||||
/*
|
||||
* Help
|
||||
* https://phreakerclub.com/447
|
||||
@@ -109,6 +111,109 @@ void subghz_protocol_encoder_princeton_free(void* context) {
|
||||
free(instance);
|
||||
}
|
||||
|
||||
// Get custom button code
|
||||
static uint8_t subghz_protocol_princeton_get_btn_code(void) {
|
||||
uint8_t custom_btn_id = subghz_custom_btn_get();
|
||||
uint8_t original_btn_code = subghz_custom_btn_get_original();
|
||||
uint8_t btn = original_btn_code;
|
||||
|
||||
// Set custom button
|
||||
if((custom_btn_id == SUBGHZ_CUSTOM_BTN_OK) && (original_btn_code != 0)) {
|
||||
// Restore original button code
|
||||
btn = original_btn_code;
|
||||
} else if(custom_btn_id == SUBGHZ_CUSTOM_BTN_UP) {
|
||||
switch(original_btn_code) {
|
||||
case 0x1:
|
||||
btn = 0x2;
|
||||
break;
|
||||
case 0x2:
|
||||
btn = 0x1;
|
||||
break;
|
||||
case 0x4:
|
||||
btn = 0x2;
|
||||
break;
|
||||
case 0x8:
|
||||
btn = 0x2;
|
||||
break;
|
||||
case 0xF:
|
||||
btn = 0x2;
|
||||
break;
|
||||
|
||||
default:
|
||||
btn = 0x2;
|
||||
break;
|
||||
}
|
||||
} else if(custom_btn_id == SUBGHZ_CUSTOM_BTN_DOWN) {
|
||||
switch(original_btn_code) {
|
||||
case 0x1:
|
||||
btn = 0x4;
|
||||
break;
|
||||
case 0x2:
|
||||
btn = 0x4;
|
||||
break;
|
||||
case 0x4:
|
||||
btn = 0x1;
|
||||
break;
|
||||
case 0x8:
|
||||
btn = 0x1;
|
||||
break;
|
||||
case 0xF:
|
||||
btn = 0x1;
|
||||
break;
|
||||
|
||||
default:
|
||||
btn = 0x1;
|
||||
break;
|
||||
}
|
||||
} else if(custom_btn_id == SUBGHZ_CUSTOM_BTN_LEFT) {
|
||||
switch(original_btn_code) {
|
||||
case 0x1:
|
||||
btn = 0x8;
|
||||
break;
|
||||
case 0x2:
|
||||
btn = 0x8;
|
||||
break;
|
||||
case 0x4:
|
||||
btn = 0x8;
|
||||
break;
|
||||
case 0x8:
|
||||
btn = 0x4;
|
||||
break;
|
||||
case 0xF:
|
||||
btn = 0x4;
|
||||
break;
|
||||
|
||||
default:
|
||||
btn = 0x4;
|
||||
break;
|
||||
}
|
||||
} else if(custom_btn_id == SUBGHZ_CUSTOM_BTN_RIGHT) {
|
||||
switch(original_btn_code) {
|
||||
case 0x1:
|
||||
btn = 0xF;
|
||||
break;
|
||||
case 0x2:
|
||||
btn = 0xF;
|
||||
break;
|
||||
case 0x4:
|
||||
btn = 0xF;
|
||||
break;
|
||||
case 0x8:
|
||||
btn = 0xF;
|
||||
break;
|
||||
case 0xF:
|
||||
btn = 0x8;
|
||||
break;
|
||||
|
||||
default:
|
||||
btn = 0x8;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return btn;
|
||||
}
|
||||
|
||||
/**
|
||||
* Generating an upload from data.
|
||||
* @param instance Pointer to a SubGhzProtocolEncoderPrinceton instance
|
||||
@@ -118,6 +223,13 @@ static bool
|
||||
subghz_protocol_encoder_princeton_get_upload(SubGhzProtocolEncoderPrinceton* instance) {
|
||||
furi_assert(instance);
|
||||
|
||||
// Generate new key using custom or default button
|
||||
instance->generic.btn = subghz_protocol_princeton_get_btn_code();
|
||||
|
||||
// Reconstruction of the data
|
||||
instance->generic.data =
|
||||
((uint64_t)instance->generic.serial << 4 | (uint64_t)instance->generic.btn);
|
||||
|
||||
size_t index = 0;
|
||||
size_t size_upload = (instance->generic.data_count_bit * 2) + 2;
|
||||
if(size_upload > instance->encoder.size_upload) {
|
||||
@@ -151,6 +263,21 @@ static bool
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Analysis of received data
|
||||
* @param instance Pointer to a SubGhzBlockGeneric* instance
|
||||
*/
|
||||
static void subghz_protocol_princeton_check_remote_controller(SubGhzBlockGeneric* instance) {
|
||||
instance->serial = instance->data >> 4;
|
||||
instance->btn = instance->data & 0xF;
|
||||
|
||||
// Save original button for later use
|
||||
if(subghz_custom_btn_get_original() == 0) {
|
||||
subghz_custom_btn_set_original(instance->btn);
|
||||
}
|
||||
subghz_custom_btn_set_max(4);
|
||||
}
|
||||
|
||||
SubGhzProtocolStatus
|
||||
subghz_protocol_encoder_princeton_deserialize(void* context, FlipperFormat* flipper_format) {
|
||||
furi_assert(context);
|
||||
@@ -188,10 +315,26 @@ SubGhzProtocolStatus
|
||||
flipper_format_read_uint32(
|
||||
flipper_format, "Repeat", (uint32_t*)&instance->encoder.repeat, 1);
|
||||
|
||||
// Get button and serial before calling get_upload
|
||||
subghz_protocol_princeton_check_remote_controller(&instance->generic);
|
||||
|
||||
if(!subghz_protocol_encoder_princeton_get_upload(instance)) {
|
||||
ret = SubGhzProtocolStatusErrorEncoderGetUpload;
|
||||
break;
|
||||
}
|
||||
|
||||
if(!flipper_format_rewind(flipper_format)) {
|
||||
FURI_LOG_E(TAG, "Rewind error");
|
||||
break;
|
||||
}
|
||||
uint8_t key_data[sizeof(uint64_t)] = {0};
|
||||
for(size_t i = 0; i < sizeof(uint64_t); i++) {
|
||||
key_data[sizeof(uint64_t) - i - 1] = (instance->generic.data >> i * 8) & 0xFF;
|
||||
}
|
||||
if(!flipper_format_update_hex(flipper_format, "Key", key_data, sizeof(uint64_t))) {
|
||||
FURI_LOG_E(TAG, "Unable to add Key");
|
||||
break;
|
||||
}
|
||||
instance->encoder.is_running = true;
|
||||
} while(false);
|
||||
|
||||
@@ -320,15 +463,6 @@ void subghz_protocol_decoder_princeton_feed(void* context, bool level, uint32_t
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Analysis of received data
|
||||
* @param instance Pointer to a SubGhzBlockGeneric* instance
|
||||
*/
|
||||
static void subghz_protocol_princeton_check_remote_controller(SubGhzBlockGeneric* instance) {
|
||||
instance->serial = instance->data >> 4;
|
||||
instance->btn = instance->data & 0xF;
|
||||
}
|
||||
|
||||
uint32_t subghz_protocol_decoder_princeton_get_hash_data(void* context) {
|
||||
furi_assert(context);
|
||||
SubGhzProtocolDecoderPrinceton* instance = context;
|
||||
|
||||
@@ -51,6 +51,7 @@ const SubGhzProtocol* subghz_protocol_registry_items[] = {
|
||||
&ws_protocol_acurite_606tx,
|
||||
&ws_protocol_acurite_609txc,
|
||||
&ws_protocol_acurite_986,
|
||||
&ws_protocol_bresser_3ch, // Should be before lacrosse
|
||||
&ws_protocol_lacrosse_tx,
|
||||
&ws_protocol_lacrosse_tx141thbv2,
|
||||
&ws_protocol_oregon2,
|
||||
|
||||
@@ -67,6 +67,7 @@
|
||||
#include "emos_e601x.h"
|
||||
#include "acurite_5n1.h"
|
||||
#include "solight_te44.h"
|
||||
#include "bresser_3ch.h"
|
||||
#include "pocsag.h"
|
||||
#include "schrader_gg4.h"
|
||||
#include "bin_raw.h"
|
||||
|
||||
Reference in New Issue
Block a user