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 <dolphin/dolphin.h> | ||||||
| #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/protocols/registry.h> | ||||||
| 
 | 
 | ||||||
| #define TAG "SubGhzSetType" | #define TAG "SubGhzSetType" | ||||||
| 
 | 
 | ||||||
| @ -19,13 +20,16 @@ enum SubmenuIndex { | |||||||
|     SubmenuIndexGateTX, |     SubmenuIndexGateTX, | ||||||
|     SubmenuIndexDoorHan_315_00, |     SubmenuIndexDoorHan_315_00, | ||||||
|     SubmenuIndexDoorHan_433_92, |     SubmenuIndexDoorHan_433_92, | ||||||
|  |     SubmenuIndexFirefly_300_00, | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| bool subghz_scene_set_type_submenu_gen_data_protocol( | bool subghz_scene_set_type_submenu_gen_data_protocol( | ||||||
|     void* context, |     void* context, | ||||||
|     const char* protocol_name, |     const char* protocol_name, | ||||||
|     uint64_t key, |     uint64_t key, | ||||||
|     uint32_t bit) { |     uint32_t bit, | ||||||
|  |     uint32_t frequency, | ||||||
|  |     FuriHalSubGhzPreset preset) { | ||||||
|     furi_assert(context); |     furi_assert(context); | ||||||
|     SubGhz* subghz = 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* fff_data_stream = flipper_format_get_raw_stream(subghz->txrx->fff_data); | ||||||
|         stream_clean(fff_data_stream); |         stream_clean(fff_data_stream); | ||||||
|         if(!subghz_protocol_decoder_base_serialize( |         if(!subghz_protocol_decoder_base_serialize( | ||||||
|                subghz->txrx->decoder_result, |                subghz->txrx->decoder_result, subghz->txrx->fff_data, frequency, preset)) { | ||||||
|                subghz->txrx->fff_data, |  | ||||||
|                subghz_setting_get_default_frequency(subghz->setting), |  | ||||||
|                FuriHalSubGhzPresetOok650Async)) { |  | ||||||
|             FURI_LOG_E(TAG, "Unable to serialize"); |             FURI_LOG_E(TAG, "Unable to serialize"); | ||||||
|             break; |             break; | ||||||
|         } |         } | ||||||
| @ -107,6 +108,12 @@ void subghz_scene_set_type_on_enter(void* context) { | |||||||
|         SubmenuIndexCAME24bit, |         SubmenuIndexCAME24bit, | ||||||
|         subghz_scene_set_type_submenu_callback, |         subghz_scene_set_type_submenu_callback, | ||||||
|         subghz); |         subghz); | ||||||
|  |     submenu_add_item( | ||||||
|  |         subghz->submenu, | ||||||
|  |         "Firefly_300", | ||||||
|  |         SubmenuIndexFirefly_300_00, | ||||||
|  |         subghz_scene_set_type_submenu_callback, | ||||||
|  |         subghz); | ||||||
|     submenu_add_item( |     submenu_add_item( | ||||||
|         subghz->submenu, |         subghz->submenu, | ||||||
|         "CAME TWEE", |         "CAME TWEE", | ||||||
| @ -152,7 +159,13 @@ bool subghz_scene_set_type_on_event(void* context, SceneManagerEvent event) { | |||||||
|         switch(event.event) { |         switch(event.event) { | ||||||
|         case SubmenuIndexPricenton: |         case SubmenuIndexPricenton: | ||||||
|             key = (key & 0x00FFFFF0) | 0x4; //btn 0x1, 0x2, 0x4, 0x8
 |             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; |                 uint32_t te = 400; | ||||||
|                 flipper_format_update_uint32(subghz->txrx->fff_data, "TE", (uint32_t*)&te, 1); |                 flipper_format_update_uint32(subghz->txrx->fff_data, "TE", (uint32_t*)&te, 1); | ||||||
|                 generated_protocol = true; |                 generated_protocol = true; | ||||||
| @ -160,32 +173,74 @@ bool subghz_scene_set_type_on_event(void* context, SceneManagerEvent event) { | |||||||
|             break; |             break; | ||||||
|         case SubmenuIndexNiceFlo12bit: |         case SubmenuIndexNiceFlo12bit: | ||||||
|             key = (key & 0x0000FFF0) | 0x1; //btn 0x1, 0x2, 0x4
 |             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; |                 generated_protocol = true; | ||||||
|             } |             } | ||||||
|             break; |             break; | ||||||
|         case SubmenuIndexNiceFlo24bit: |         case SubmenuIndexNiceFlo24bit: | ||||||
|             key = (key & 0x00FFFFF0) | 0x4; //btn 0x1, 0x2, 0x4, 0x8
 |             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; |                 generated_protocol = true; | ||||||
|             } |             } | ||||||
|             break; |             break; | ||||||
|         case SubmenuIndexCAME12bit: |         case SubmenuIndexCAME12bit: | ||||||
|             key = (key & 0x0000FFF0) | 0x1; //btn 0x1, 0x2, 0x4
 |             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; |                 generated_protocol = true; | ||||||
|             } |             } | ||||||
|             break; |             break; | ||||||
|         case SubmenuIndexCAME24bit: |         case SubmenuIndexCAME24bit: | ||||||
|             key = (key & 0x00FFFFF0) | 0x4; //btn 0x1, 0x2, 0x4, 0x8
 |             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; |                 generated_protocol = true; | ||||||
|             } |             } | ||||||
|             break; |             break; | ||||||
|         case SubmenuIndexCAMETwee: |         case SubmenuIndexCAMETwee: | ||||||
|             key = (key & 0x0FFFFFF0); |             key = (key & 0x0FFFFFF0); | ||||||
|             key = 0x003FFF7200000000 | (key ^ 0xE0E0E0EE); |             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; |                 generated_protocol = true; | ||||||
|             } |             } | ||||||
|             break; |             break; | ||||||
| @ -198,13 +253,19 @@ bool subghz_scene_set_type_on_event(void* context, SceneManagerEvent event) { | |||||||
|         case SubmenuIndexGateTX: |         case SubmenuIndexGateTX: | ||||||
|             key = (key & 0x00F0FF00) | 0xF << 16 | 0x40; //btn 0xF, 0xC, 0xA, 0x6 (?)
 |             key = (key & 0x00F0FF00) | 0xF << 16 | 0x40; //btn 0xF, 0xC, 0xA, 0x6 (?)
 | ||||||
|             uint64_t rev_key = subghz_protocol_blocks_reverse_key(key, 24); |             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; |                 generated_protocol = true; | ||||||
|             } |             } | ||||||
|             break; |             break; | ||||||
|         case SubmenuIndexDoorHan_433_92: |         case SubmenuIndexDoorHan_433_92: | ||||||
|             subghz->txrx->transmitter = |             subghz->txrx->transmitter = subghz_transmitter_alloc_init( | ||||||
|                 subghz_transmitter_alloc_init(subghz->txrx->environment, "KeeLoq"); |                 subghz->txrx->environment, SUBGHZ_PROTOCOL_KEELOQ_NAME); | ||||||
|             if(subghz->txrx->transmitter) { |             if(subghz->txrx->transmitter) { | ||||||
|                 subghz_protocol_keeloq_create_data( |                 subghz_protocol_keeloq_create_data( | ||||||
|                     subghz->txrx->transmitter->protocol_instance, |                     subghz->txrx->transmitter->protocol_instance, | ||||||
| @ -227,8 +288,8 @@ bool subghz_scene_set_type_on_event(void* context, SceneManagerEvent event) { | |||||||
|             } |             } | ||||||
|             break; |             break; | ||||||
|         case SubmenuIndexDoorHan_315_00: |         case SubmenuIndexDoorHan_315_00: | ||||||
|             subghz->txrx->transmitter = |             subghz->txrx->transmitter = subghz_transmitter_alloc_init( | ||||||
|                 subghz_transmitter_alloc_init(subghz->txrx->environment, "KeeLoq"); |                 subghz->txrx->environment, SUBGHZ_PROTOCOL_KEELOQ_NAME); | ||||||
|             if(subghz->txrx->transmitter) { |             if(subghz->txrx->transmitter) { | ||||||
|                 subghz_protocol_keeloq_create_data( |                 subghz_protocol_keeloq_create_data( | ||||||
|                     subghz->txrx->transmitter->protocol_instance, |                     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_nero_sketch,  &subghz_protocol_ido,        &subghz_protocol_kia, | ||||||
|     &subghz_protocol_hormann,      &subghz_protocol_nero_radio, &subghz_protocol_somfy_telis, |     &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_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 "scher_khan.h" | ||||||
| #include "gate_tx.h" | #include "gate_tx.h" | ||||||
| #include "raw.h" | #include "raw.h" | ||||||
|  | #include "firefly.h" | ||||||
| 
 | 
 | ||||||
| /**
 | /**
 | ||||||
|  * Registration by name SubGhzProtocol. |  * Registration by name SubGhzProtocol. | ||||||
|  | |||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user
	 Skorpionm
						Skorpionm