SubGhz add protocol Firefly (#1183)
* SubGhz: add protocol "Firefly" * SubGhz: refactoring "Add Manually" scene * SubGhz: refactoring Firefly protocol Co-authored-by: あく <alleteam@gmail.com>
This commit is contained in:
		
							parent
							
								
									0eac917f91
								
							
						
					
					
						commit
						73477cceed
					
				| @ -4,6 +4,7 @@ | ||||
| #include <dolphin/dolphin.h> | ||||
| #include <flipper_format/flipper_format_i.h> | ||||
| #include <lib/toolbox/stream/stream.h> | ||||
| #include <lib/subghz/protocols/registry.h> | ||||
| 
 | ||||
| #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, | ||||
|  | ||||
							
								
								
									
										343
									
								
								lib/subghz/protocols/firefly.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										343
									
								
								lib/subghz/protocols/firefly.c
									
									
									
									
									
										Normal file
									
								
							| @ -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)); | ||||
| } | ||||
							
								
								
									
										109
									
								
								lib/subghz/protocols/firefly.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										109
									
								
								lib/subghz/protocols/firefly.h
									
									
									
									
									
										Normal file
									
								
							| @ -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); | ||||
| @ -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, | ||||
| 
 | ||||
| }; | ||||
| 
 | ||||
|  | ||||
| @ -21,6 +21,7 @@ | ||||
| #include "scher_khan.h" | ||||
| #include "gate_tx.h" | ||||
| #include "raw.h" | ||||
| #include "firefly.h" | ||||
| 
 | ||||
| /**
 | ||||
|  * Registration by name SubGhzProtocol. | ||||
|  | ||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user
	 Skorpionm
						Skorpionm