From 73477cceed7c02785d477f704c355067aaa80f2b Mon Sep 17 00:00:00 2001 From: Skorpionm <85568270+Skorpionm@users.noreply.github.com> Date: Fri, 29 Apr 2022 16:17:42 +0400 Subject: [PATCH] SubGhz add protocol Firefly (#1183) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * SubGhz: add protocol "Firefly" * SubGhz: refactoring "Add Manually" scene * SubGhz: refactoring Firefly protocol Co-authored-by: あく --- .../subghz/scenes/subghz_scene_set_type.c | 93 ++++- lib/subghz/protocols/firefly.c | 343 ++++++++++++++++++ lib/subghz/protocols/firefly.h | 109 ++++++ lib/subghz/protocols/registry.c | 2 +- lib/subghz/protocols/registry.h | 1 + 5 files changed, 531 insertions(+), 17 deletions(-) create mode 100644 lib/subghz/protocols/firefly.c create mode 100644 lib/subghz/protocols/firefly.h diff --git a/applications/subghz/scenes/subghz_scene_set_type.c b/applications/subghz/scenes/subghz_scene_set_type.c index 22a15143..964b85b2 100644 --- a/applications/subghz/scenes/subghz_scene_set_type.c +++ b/applications/subghz/scenes/subghz_scene_set_type.c @@ -4,6 +4,7 @@ #include #include #include +#include #define TAG "SubGhzSetType" @@ -19,13 +20,16 @@ enum SubmenuIndex { SubmenuIndexGateTX, SubmenuIndexDoorHan_315_00, SubmenuIndexDoorHan_433_92, + SubmenuIndexFirefly_300_00, }; bool subghz_scene_set_type_submenu_gen_data_protocol( void* context, const char* protocol_name, uint64_t key, - uint32_t bit) { + uint32_t bit, + uint32_t frequency, + FuriHalSubGhzPreset preset) { furi_assert(context); SubGhz* subghz = context; @@ -44,10 +48,7 @@ bool subghz_scene_set_type_submenu_gen_data_protocol( Stream* fff_data_stream = flipper_format_get_raw_stream(subghz->txrx->fff_data); stream_clean(fff_data_stream); if(!subghz_protocol_decoder_base_serialize( - subghz->txrx->decoder_result, - subghz->txrx->fff_data, - subghz_setting_get_default_frequency(subghz->setting), - FuriHalSubGhzPresetOok650Async)) { + subghz->txrx->decoder_result, subghz->txrx->fff_data, frequency, preset)) { FURI_LOG_E(TAG, "Unable to serialize"); break; } @@ -107,6 +108,12 @@ void subghz_scene_set_type_on_enter(void* context) { SubmenuIndexCAME24bit, subghz_scene_set_type_submenu_callback, subghz); + submenu_add_item( + subghz->submenu, + "Firefly_300", + SubmenuIndexFirefly_300_00, + subghz_scene_set_type_submenu_callback, + subghz); submenu_add_item( subghz->submenu, "CAME TWEE", @@ -152,7 +159,13 @@ bool subghz_scene_set_type_on_event(void* context, SceneManagerEvent event) { switch(event.event) { case SubmenuIndexPricenton: key = (key & 0x00FFFFF0) | 0x4; //btn 0x1, 0x2, 0x4, 0x8 - if(subghz_scene_set_type_submenu_gen_data_protocol(subghz, "Princeton", key, 24)) { + if(subghz_scene_set_type_submenu_gen_data_protocol( + subghz, + SUBGHZ_PROTOCOL_PRINCETON_NAME, + key, + 24, + 433920000, + FuriHalSubGhzPresetOok650Async)) { uint32_t te = 400; flipper_format_update_uint32(subghz->txrx->fff_data, "TE", (uint32_t*)&te, 1); generated_protocol = true; @@ -160,32 +173,74 @@ bool subghz_scene_set_type_on_event(void* context, SceneManagerEvent event) { break; case SubmenuIndexNiceFlo12bit: key = (key & 0x0000FFF0) | 0x1; //btn 0x1, 0x2, 0x4 - if(subghz_scene_set_type_submenu_gen_data_protocol(subghz, "Nice FLO", key, 12)) { + if(subghz_scene_set_type_submenu_gen_data_protocol( + subghz, + SUBGHZ_PROTOCOL_NICE_FLO_NAME, + key, + 12, + 433920000, + FuriHalSubGhzPresetOok650Async)) { generated_protocol = true; } break; case SubmenuIndexNiceFlo24bit: key = (key & 0x00FFFFF0) | 0x4; //btn 0x1, 0x2, 0x4, 0x8 - if(subghz_scene_set_type_submenu_gen_data_protocol(subghz, "Nice FLO", key, 24)) { + if(subghz_scene_set_type_submenu_gen_data_protocol( + subghz, + SUBGHZ_PROTOCOL_NICE_FLO_NAME, + key, + 24, + 433920000, + FuriHalSubGhzPresetOok650Async)) { generated_protocol = true; } break; case SubmenuIndexCAME12bit: key = (key & 0x0000FFF0) | 0x1; //btn 0x1, 0x2, 0x4 - if(subghz_scene_set_type_submenu_gen_data_protocol(subghz, "CAME", key, 12)) { + if(subghz_scene_set_type_submenu_gen_data_protocol( + subghz, + SUBGHZ_PROTOCOL_CAME_NAME, + key, + 12, + 433920000, + FuriHalSubGhzPresetOok650Async)) { generated_protocol = true; } break; case SubmenuIndexCAME24bit: key = (key & 0x00FFFFF0) | 0x4; //btn 0x1, 0x2, 0x4, 0x8 - if(subghz_scene_set_type_submenu_gen_data_protocol(subghz, "CAME", key, 24)) { + if(subghz_scene_set_type_submenu_gen_data_protocol( + subghz, + SUBGHZ_PROTOCOL_CAME_NAME, + key, + 24, + 433920000, + FuriHalSubGhzPresetOok650Async)) { + generated_protocol = true; + } + break; + case SubmenuIndexFirefly_300_00: + key = (key & 0x3FF); + if(subghz_scene_set_type_submenu_gen_data_protocol( + subghz, + SUBGHZ_PROTOCOL_FIREFLY_NAME, + key, + 10, + 300000000, + FuriHalSubGhzPresetOok650Async)) { generated_protocol = true; } break; case SubmenuIndexCAMETwee: key = (key & 0x0FFFFFF0); key = 0x003FFF7200000000 | (key ^ 0xE0E0E0EE); - if(subghz_scene_set_type_submenu_gen_data_protocol(subghz, "CAME TWEE", key, 54)) { + if(subghz_scene_set_type_submenu_gen_data_protocol( + subghz, + SUBGHZ_PROTOCOL_CAME_TWEE_NAME, + key, + 54, + 433920000, + FuriHalSubGhzPresetOok650Async)) { generated_protocol = true; } break; @@ -198,13 +253,19 @@ bool subghz_scene_set_type_on_event(void* context, SceneManagerEvent event) { case SubmenuIndexGateTX: key = (key & 0x00F0FF00) | 0xF << 16 | 0x40; //btn 0xF, 0xC, 0xA, 0x6 (?) uint64_t rev_key = subghz_protocol_blocks_reverse_key(key, 24); - if(subghz_scene_set_type_submenu_gen_data_protocol(subghz, "GateTX", rev_key, 24)) { + if(subghz_scene_set_type_submenu_gen_data_protocol( + subghz, + SUBGHZ_PROTOCOL_GATE_TX_NAME, + rev_key, + 24, + 433920000, + FuriHalSubGhzPresetOok650Async)) { generated_protocol = true; } break; case SubmenuIndexDoorHan_433_92: - subghz->txrx->transmitter = - subghz_transmitter_alloc_init(subghz->txrx->environment, "KeeLoq"); + subghz->txrx->transmitter = subghz_transmitter_alloc_init( + subghz->txrx->environment, SUBGHZ_PROTOCOL_KEELOQ_NAME); if(subghz->txrx->transmitter) { subghz_protocol_keeloq_create_data( subghz->txrx->transmitter->protocol_instance, @@ -227,8 +288,8 @@ bool subghz_scene_set_type_on_event(void* context, SceneManagerEvent event) { } break; case SubmenuIndexDoorHan_315_00: - subghz->txrx->transmitter = - subghz_transmitter_alloc_init(subghz->txrx->environment, "KeeLoq"); + subghz->txrx->transmitter = subghz_transmitter_alloc_init( + subghz->txrx->environment, SUBGHZ_PROTOCOL_KEELOQ_NAME); if(subghz->txrx->transmitter) { subghz_protocol_keeloq_create_data( subghz->txrx->transmitter->protocol_instance, diff --git a/lib/subghz/protocols/firefly.c b/lib/subghz/protocols/firefly.c new file mode 100644 index 00000000..e872d558 --- /dev/null +++ b/lib/subghz/protocols/firefly.c @@ -0,0 +1,343 @@ +#include "firefly.h" + +#include "../blocks/const.h" +#include "../blocks/decoder.h" +#include "../blocks/encoder.h" +#include "../blocks/generic.h" +#include "../blocks/math.h" + +/* + * Help + * https://phreakerclub.com/447 + * + */ + +#define TAG "SubGhzProtocolFirefly" + +#define DIP_PATTERN "%c%c%c%c%c%c%c%c%c%c" +#define DATA_TO_DIP(dip) \ + (dip & 0x0200 ? '1' : '0'), (dip & 0x0100 ? '1' : '0'), (dip & 0x0080 ? '1' : '0'), \ + (dip & 0x0040 ? '1' : '0'), (dip & 0x0020 ? '1' : '0'), (dip & 0x0010 ? '1' : '0'), \ + (dip & 0x0008 ? '1' : '0'), (dip & 0x0004 ? '1' : '0'), (dip & 0x0002 ? '1' : '0'), \ + (dip & 0x0001 ? '1' : '0') + +static const SubGhzBlockConst subghz_protocol_firefly_const = { + .te_short = 500, + .te_long = 1500, + .te_delta = 150, + .min_count_bit_for_found = 10, +}; + +struct SubGhzProtocolDecoderFirefly { + SubGhzProtocolDecoderBase base; + + SubGhzBlockDecoder decoder; + SubGhzBlockGeneric generic; +}; + +struct SubGhzProtocolEncoderFirefly { + SubGhzProtocolEncoderBase base; + + SubGhzProtocolBlockEncoder encoder; + SubGhzBlockGeneric generic; +}; + +typedef enum { + FireflyDecoderStepReset = 0, + FireflyDecoderStepSaveDuration, + FireflyDecoderStepCheckDuration, +} FireflyDecoderStep; + +const SubGhzProtocolDecoder subghz_protocol_firefly_decoder = { + .alloc = subghz_protocol_decoder_firefly_alloc, + .free = subghz_protocol_decoder_firefly_free, + + .feed = subghz_protocol_decoder_firefly_feed, + .reset = subghz_protocol_decoder_firefly_reset, + + .get_hash_data = subghz_protocol_decoder_firefly_get_hash_data, + .serialize = subghz_protocol_decoder_firefly_serialize, + .deserialize = subghz_protocol_decoder_firefly_deserialize, + .get_string = subghz_protocol_decoder_firefly_get_string, +}; + +const SubGhzProtocolEncoder subghz_protocol_firefly_encoder = { + .alloc = subghz_protocol_encoder_firefly_alloc, + .free = subghz_protocol_encoder_firefly_free, + + .deserialize = subghz_protocol_encoder_firefly_deserialize, + .stop = subghz_protocol_encoder_firefly_stop, + .yield = subghz_protocol_encoder_firefly_yield, +}; + +const SubGhzProtocol subghz_protocol_firefly = { + .name = SUBGHZ_PROTOCOL_FIREFLY_NAME, + .type = SubGhzProtocolTypeStatic, + .flag = SubGhzProtocolFlag_315 | SubGhzProtocolFlag_AM | SubGhzProtocolFlag_Decodable | + SubGhzProtocolFlag_Load | SubGhzProtocolFlag_Save | SubGhzProtocolFlag_Send, + + .decoder = &subghz_protocol_firefly_decoder, + .encoder = &subghz_protocol_firefly_encoder, +}; + +void* subghz_protocol_encoder_firefly_alloc(SubGhzEnvironment* environment) { + SubGhzProtocolEncoderFirefly* instance = malloc(sizeof(SubGhzProtocolEncoderFirefly)); + + instance->base.protocol = &subghz_protocol_firefly; + instance->generic.protocol_name = instance->base.protocol->name; + + instance->encoder.repeat = 10; + instance->encoder.size_upload = 28; //max 10bit*2 + 2 (start, stop) + instance->encoder.upload = malloc(instance->encoder.size_upload * sizeof(LevelDuration)); + instance->encoder.is_runing = false; + return instance; +} + +void subghz_protocol_encoder_firefly_free(void* context) { + furi_assert(context); + SubGhzProtocolEncoderFirefly* instance = context; + free(instance->encoder.upload); + free(instance); +} + +/** + * Generating an upload from data. + * @param instance Pointer to a SubGhzProtocolEncoderFirefly instance + * @return true On success + */ +static bool subghz_protocol_encoder_firefly_get_upload(SubGhzProtocolEncoderFirefly* instance) { + furi_assert(instance); + size_t index = 0; + size_t size_upload = (instance->generic.data_count_bit * 2); + if(size_upload > instance->encoder.size_upload) { + FURI_LOG_E(TAG, "Size upload exceeds allocated encoder buffer."); + return false; + } else { + instance->encoder.size_upload = size_upload; + } + + //Send key data + for(uint8_t i = instance->generic.data_count_bit; i > 1; i--) { + if(bit_read(instance->generic.data, i - 1)) { + //send bit 1 + instance->encoder.upload[index++] = + level_duration_make(true, (uint32_t)subghz_protocol_firefly_const.te_short * 3); + instance->encoder.upload[index++] = + level_duration_make(false, (uint32_t)subghz_protocol_firefly_const.te_short); + } else { + //send bit 0 + instance->encoder.upload[index++] = + level_duration_make(true, (uint32_t)subghz_protocol_firefly_const.te_short); + instance->encoder.upload[index++] = + level_duration_make(false, (uint32_t)subghz_protocol_firefly_const.te_short * 3); + } + } + //Send end bit + if(bit_read(instance->generic.data, 0)) { + //send bit 1 + instance->encoder.upload[index++] = + level_duration_make(true, (uint32_t)subghz_protocol_firefly_const.te_short * 3); + //Send PT_GUARD + instance->encoder.upload[index++] = + level_duration_make(false, (uint32_t)subghz_protocol_firefly_const.te_short * 42); + } else { + //send bit 0 + instance->encoder.upload[index++] = + level_duration_make(true, (uint32_t)subghz_protocol_firefly_const.te_short); + //Send PT_GUARD + instance->encoder.upload[index++] = + level_duration_make(false, (uint32_t)subghz_protocol_firefly_const.te_short * 44); + } + + return true; +} + +bool subghz_protocol_encoder_firefly_deserialize(void* context, FlipperFormat* flipper_format) { + furi_assert(context); + SubGhzProtocolEncoderFirefly* instance = context; + bool res = false; + do { + if(!subghz_block_generic_deserialize(&instance->generic, flipper_format)) { + FURI_LOG_E(TAG, "Deserialize error"); + break; + } + + //optional parameter parameter + flipper_format_read_uint32( + flipper_format, "Repeat", (uint32_t*)&instance->encoder.repeat, 1); + + subghz_protocol_encoder_firefly_get_upload(instance); + instance->encoder.is_runing = true; + + res = true; + } while(false); + + return res; +} + +void subghz_protocol_encoder_firefly_stop(void* context) { + SubGhzProtocolEncoderFirefly* instance = context; + instance->encoder.is_runing = false; +} + +LevelDuration subghz_protocol_encoder_firefly_yield(void* context) { + SubGhzProtocolEncoderFirefly* instance = context; + + if(instance->encoder.repeat == 0 || !instance->encoder.is_runing) { + instance->encoder.is_runing = false; + return level_duration_reset(); + } + + LevelDuration ret = instance->encoder.upload[instance->encoder.front]; + + if(++instance->encoder.front == instance->encoder.size_upload) { + instance->encoder.repeat--; + instance->encoder.front = 0; + } + + return ret; +} + +void* subghz_protocol_decoder_firefly_alloc(SubGhzEnvironment* environment) { + SubGhzProtocolDecoderFirefly* instance = malloc(sizeof(SubGhzProtocolDecoderFirefly)); + instance->base.protocol = &subghz_protocol_firefly; + instance->generic.protocol_name = instance->base.protocol->name; + return instance; +} + +void subghz_protocol_decoder_firefly_free(void* context) { + furi_assert(context); + SubGhzProtocolDecoderFirefly* instance = context; + free(instance); +} + +void subghz_protocol_decoder_firefly_reset(void* context) { + furi_assert(context); + SubGhzProtocolDecoderFirefly* instance = context; + instance->decoder.parser_step = FireflyDecoderStepReset; +} + +void subghz_protocol_decoder_firefly_feed(void* context, bool level, uint32_t duration) { + furi_assert(context); + SubGhzProtocolDecoderFirefly* instance = context; + switch(instance->decoder.parser_step) { + case FireflyDecoderStepReset: + if((!level) && (DURATION_DIFF(duration, subghz_protocol_firefly_const.te_short * 42) < + subghz_protocol_firefly_const.te_delta * 20)) { + //Found header Firefly + instance->decoder.decode_data = 0; + instance->decoder.decode_count_bit = 0; + instance->decoder.parser_step = FireflyDecoderStepSaveDuration; + } + break; + case FireflyDecoderStepSaveDuration: + if(level) { + instance->decoder.te_last = duration; + instance->decoder.parser_step = FireflyDecoderStepCheckDuration; + } else { + instance->decoder.parser_step = FireflyDecoderStepReset; + } + break; + case FireflyDecoderStepCheckDuration: + if(!level) { //save interval + if(duration >= (subghz_protocol_firefly_const.te_short * 5)) { + instance->decoder.parser_step = FireflyDecoderStepReset; + //checking that the duration matches the guardtime + if((DURATION_DIFF(duration, subghz_protocol_firefly_const.te_short * 42) > + subghz_protocol_firefly_const.te_delta * 20)) { + break; + } + if(DURATION_DIFF( + instance->decoder.te_last, subghz_protocol_firefly_const.te_short) < + subghz_protocol_firefly_const.te_delta) { + subghz_protocol_blocks_add_bit(&instance->decoder, 0); + } else if( + DURATION_DIFF( + instance->decoder.te_last, subghz_protocol_firefly_const.te_long) < + subghz_protocol_firefly_const.te_delta) { + subghz_protocol_blocks_add_bit(&instance->decoder, 1); + } + if(instance->decoder.decode_count_bit == + subghz_protocol_firefly_const.min_count_bit_for_found) { + instance->generic.serial = 0x0; + instance->generic.btn = 0x0; + + instance->generic.data = instance->decoder.decode_data; + instance->generic.data_count_bit = instance->decoder.decode_count_bit; + + if(instance->base.callback) + instance->base.callback(&instance->base, instance->base.context); + } + break; + } + + if((DURATION_DIFF(instance->decoder.te_last, subghz_protocol_firefly_const.te_short) < + subghz_protocol_firefly_const.te_delta) && + (DURATION_DIFF(duration, subghz_protocol_firefly_const.te_long) < + subghz_protocol_firefly_const.te_delta)) { + subghz_protocol_blocks_add_bit(&instance->decoder, 0); + instance->decoder.parser_step = FireflyDecoderStepSaveDuration; + } else if( + (DURATION_DIFF(instance->decoder.te_last, subghz_protocol_firefly_const.te_long) < + subghz_protocol_firefly_const.te_delta) && + (DURATION_DIFF(duration, subghz_protocol_firefly_const.te_short) < + subghz_protocol_firefly_const.te_delta)) { + subghz_protocol_blocks_add_bit(&instance->decoder, 1); + instance->decoder.parser_step = FireflyDecoderStepSaveDuration; + } else { + instance->decoder.parser_step = FireflyDecoderStepReset; + } + + } else { + instance->decoder.parser_step = FireflyDecoderStepReset; + } + break; + } +} + +uint8_t subghz_protocol_decoder_firefly_get_hash_data(void* context) { + furi_assert(context); + SubGhzProtocolDecoderFirefly* instance = context; + return subghz_protocol_blocks_get_hash_data( + &instance->decoder, (instance->decoder.decode_count_bit / 8) + 1); +} + +bool subghz_protocol_decoder_firefly_serialize( + void* context, + FlipperFormat* flipper_format, + uint32_t frequency, + FuriHalSubGhzPreset preset) { + furi_assert(context); + SubGhzProtocolDecoderFirefly* instance = context; + return subghz_block_generic_serialize(&instance->generic, flipper_format, frequency, preset); +} + +bool subghz_protocol_decoder_firefly_deserialize(void* context, FlipperFormat* flipper_format) { + furi_assert(context); + SubGhzProtocolDecoderFirefly* instance = context; + return subghz_block_generic_deserialize(&instance->generic, flipper_format); +} + +void subghz_protocol_decoder_firefly_get_string(void* context, string_t output) { + furi_assert(context); + SubGhzProtocolDecoderFirefly* instance = context; + + uint32_t code_found_lo = instance->generic.data & 0x00000000ffffffff; + + uint64_t code_found_reverse = subghz_protocol_blocks_reverse_key( + instance->generic.data, instance->generic.data_count_bit); + + uint32_t code_found_reverse_lo = code_found_reverse & 0x00000000ffffffff; + + string_cat_printf( + output, + "%s %dbit\r\n" + "Key:0x%08lX\r\n" + "Yek:0x%08lX\r\n" + "DIP:" DIP_PATTERN "\r\n", + instance->generic.protocol_name, + instance->generic.data_count_bit, + code_found_lo, + code_found_reverse_lo, + DATA_TO_DIP(code_found_lo)); +} diff --git a/lib/subghz/protocols/firefly.h b/lib/subghz/protocols/firefly.h new file mode 100644 index 00000000..abb4537c --- /dev/null +++ b/lib/subghz/protocols/firefly.h @@ -0,0 +1,109 @@ +#pragma once + +#include "base.h" + +#define SUBGHZ_PROTOCOL_FIREFLY_NAME "Firefly" + +typedef struct SubGhzProtocolDecoderFirefly SubGhzProtocolDecoderFirefly; +typedef struct SubGhzProtocolEncoderFirefly SubGhzProtocolEncoderFirefly; + +extern const SubGhzProtocolDecoder subghz_protocol_firefly_decoder; +extern const SubGhzProtocolEncoder subghz_protocol_firefly_encoder; +extern const SubGhzProtocol subghz_protocol_firefly; + +/** + * Allocate SubGhzProtocolEncoderFirefly. + * @param environment Pointer to a SubGhzEnvironment instance + * @return SubGhzProtocolEncoderFirefly* pointer to a SubGhzProtocolEncoderFirefly instance + */ +void* subghz_protocol_encoder_firefly_alloc(SubGhzEnvironment* environment); + +/** + * Free SubGhzProtocolEncoderFirefly. + * @param context Pointer to a SubGhzProtocolEncoderFirefly instance + */ +void subghz_protocol_encoder_firefly_free(void* context); + +/** + * Deserialize and generating an upload to send. + * @param context Pointer to a SubGhzProtocolEncoderFirefly instance + * @param flipper_format Pointer to a FlipperFormat instance + * @return true On success + */ +bool subghz_protocol_encoder_firefly_deserialize(void* context, FlipperFormat* flipper_format); + +/** + * Forced transmission stop. + * @param context Pointer to a SubGhzProtocolEncoderFirefly instance + */ +void subghz_protocol_encoder_firefly_stop(void* context); + +/** + * Getting the level and duration of the upload to be loaded into DMA. + * @param context Pointer to a SubGhzProtocolEncoderFirefly instance + * @return LevelDuration + */ +LevelDuration subghz_protocol_encoder_firefly_yield(void* context); + +/** + * Allocate SubGhzProtocolDecoderFirefly. + * @param environment Pointer to a SubGhzEnvironment instance + * @return SubGhzProtocolDecoderFirefly* pointer to a SubGhzProtocolDecoderFirefly instance + */ +void* subghz_protocol_decoder_firefly_alloc(SubGhzEnvironment* environment); + +/** + * Free SubGhzProtocolDecoderFirefly. + * @param context Pointer to a SubGhzProtocolDecoderFirefly instance + */ +void subghz_protocol_decoder_firefly_free(void* context); + +/** + * Reset decoder SubGhzProtocolDecoderFirefly. + * @param context Pointer to a SubGhzProtocolDecoderFirefly instance + */ +void subghz_protocol_decoder_firefly_reset(void* context); + +/** + * Parse a raw sequence of levels and durations received from the air. + * @param context Pointer to a SubGhzProtocolDecoderFirefly instance + * @param level Signal level true-high false-low + * @param duration Duration of this level in, us + */ +void subghz_protocol_decoder_firefly_feed(void* context, bool level, uint32_t duration); + +/** + * Getting the hash sum of the last randomly received parcel. + * @param context Pointer to a SubGhzProtocolDecoderFirefly instance + * @return hash Hash sum + */ +uint8_t subghz_protocol_decoder_firefly_get_hash_data(void* context); + +/** + * Serialize data SubGhzProtocolDecoderFirefly. + * @param context Pointer to a SubGhzProtocolDecoderFirefly instance + * @param flipper_format Pointer to a FlipperFormat instance + * @param frequency The frequency at which the signal was received, Hz + * @param preset The modulation on which the signal was received, FuriHalSubGhzPreset + * @return true On success + */ +bool subghz_protocol_decoder_firefly_serialize( + void* context, + FlipperFormat* flipper_format, + uint32_t frequency, + FuriHalSubGhzPreset preset); + +/** + * Deserialize data SubGhzProtocolDecoderFirefly. + * @param context Pointer to a SubGhzProtocolDecoderFirefly instance + * @param flipper_format Pointer to a FlipperFormat instance + * @return true On success + */ +bool subghz_protocol_decoder_firefly_deserialize(void* context, FlipperFormat* flipper_format); + +/** + * Getting a textual representation of the received data. + * @param context Pointer to a SubGhzProtocolDecoderFirefly instance + * @param output Resulting text + */ +void subghz_protocol_decoder_firefly_get_string(void* context, string_t output); diff --git a/lib/subghz/protocols/registry.c b/lib/subghz/protocols/registry.c index 6d15af56..c384eda1 100644 --- a/lib/subghz/protocols/registry.c +++ b/lib/subghz/protocols/registry.c @@ -7,7 +7,7 @@ const SubGhzProtocol* subghz_protocol_registry[] = { &subghz_protocol_nero_sketch, &subghz_protocol_ido, &subghz_protocol_kia, &subghz_protocol_hormann, &subghz_protocol_nero_radio, &subghz_protocol_somfy_telis, &subghz_protocol_somfy_keytis, &subghz_protocol_scher_khan, &subghz_protocol_gate_tx, - &subghz_protocol_raw, + &subghz_protocol_raw, &subghz_protocol_firefly, }; diff --git a/lib/subghz/protocols/registry.h b/lib/subghz/protocols/registry.h index cce48e02..531caee2 100644 --- a/lib/subghz/protocols/registry.h +++ b/lib/subghz/protocols/registry.h @@ -21,6 +21,7 @@ #include "scher_khan.h" #include "gate_tx.h" #include "raw.h" +#include "firefly.h" /** * Registration by name SubGhzProtocol.