Add Mastercode SubGHz Protocol (#3187)
* Add Mastercode SubGHz Protocol * Add 2 valid raw files and cleanup code * Add tests to the two Raw Files * Remove extra test & delete comments * Fixes pulse length and shows correct Key Co-authored-by: FlipperZelebro <flipperzelebro [at] gmail.com> Co-authored-by: あく <alleteam@gmail.com>
This commit is contained in:
		
							parent
							
								
									ba074068b0
								
							
						
					
					
						commit
						a61b5d4b4c
					
				| @ -0,0 +1,7 @@ | |||||||
|  | Filetype: Flipper SubGhz Key File | ||||||
|  | Version: 1 | ||||||
|  | Frequency: 433920000 | ||||||
|  | Preset: FuriHalSubGhzPresetOok270Async | ||||||
|  | Protocol: Mastercode | ||||||
|  | Bit: 36 | ||||||
|  | Key: 00 00 00 0B 7E 00 3C 08 | ||||||
| @ -0,0 +1,6 @@ | |||||||
|  | Filetype: Flipper SubGhz RAW File | ||||||
|  | Version: 1 | ||||||
|  | Frequency: 433920000 | ||||||
|  | Preset: FuriHalSubGhzPresetOok270Async | ||||||
|  | Protocol: RAW | ||||||
|  | RAW_Data: 10389 -66 405095 -102 207 -106 1165 -130 963739 -1232 899 -2250 2003 -1190 2017 -1202 911 -2256 2021 -1162 2045 -1134 2047 -1164 2047 -1138 2031 -1180 2039 -1182 949 -2190 995 -2214 961 -2228 963 -2198 963 -2214 977 -2212 975 -2210 975 -2208 971 -2200 963 -2210 993 -2184 2075 -1130 2051 -1142 2055 -1136 2047 -1178 965 -2236 933 -2220 975 -2184 999 -2222 967 -2208 969 -2214 979 -2202 2027 -1156 975 -2242 943 -16080 2023 -1162 967 -2220 2057 -1114 2061 -1124 1007 -2242 2025 -1134 2055 -1168 2017 -1138 2075 -1134 2053 -1136 2075 -1130 979 -2214 979 -2174 999 -2182 1001 -2204 977 -2206 1003 -2188 979 -2176 999 -2182 1009 -2176 1009 -2176 1001 -2212 2029 -1116 2091 -1102 2109 -1092 2095 -1126 1001 -2150 1011 -2180 1011 -2180 1009 -2178 1009 -2172 1009 -2166 1001 -2198 2065 -1136 975 -2220 971 -16018 2097 -1166 951 -2240 2009 -1186 2011 -1160 979 -2208 2035 -1134 2053 -1138 2061 -1158 2045 -1152 2029 -1152 2051 -1166 963 -2188 993 -2222 951 -2214 963 -2220 965 -2212 979 -2212 977 -2180 1003 -2202 965 -2218 975 -2216 967 -2188 2061 -1124 2083 -1126 2071 -1130 2059 -1134 993 -2188 979 -2240 947 -2204 979 -2214 971 -2214 973 -2210 971 -2206 2053 -1130 979 -2216 969 -16056 2053 -1134 1001 -2224 2021 -1150 2051 -1154 953 -2240 2045 -1146 2023 -1168 2033 -1144 2065 -1146 2055 -1130 2071 -1160 961 -2192 973 -2190 1005 -2214 975 -2206 967 -2206 975 -2206 967 -2208 975 -2212 967 -2212 979 -2218 977 -2178 2063 -1156 2035 -1160 2061 -1126 2065 -1130 981 -2186 1003 -2210 977 -2208 973 -2202 977 -2200 965 -2248 943 -2206 2039 -1190 941 -48536 65 -7254 263 -68 363 -102 131 -232 263 -264 751 -230 225 -822 397 -634 231 -268 263 -134 267 -64 867 -132 305 -138 67 -100 331 -98 891 -66 455 -66 531 -100 299 -134 897 -98 693 -132 291 -132 333 -98 337 -68 331 | ||||||
| @ -654,6 +654,13 @@ MU_TEST(subghz_decoder_kinggates_stylo4k_test) { | |||||||
|         "Test decoder " SUBGHZ_PROTOCOL_KINGGATES_STYLO_4K_NAME " error\r\n"); |         "Test decoder " SUBGHZ_PROTOCOL_KINGGATES_STYLO_4K_NAME " error\r\n"); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | MU_TEST(subghz_decoder_mastercode_test) { | ||||||
|  |     mu_assert( | ||||||
|  |         subghz_decoder_test( | ||||||
|  |             EXT_PATH("unit_tests/subghz/mastercode_raw.sub"), SUBGHZ_PROTOCOL_MASTERCODE_NAME), | ||||||
|  |         "Test decoder " SUBGHZ_PROTOCOL_MASTERCODE_NAME " error\r\n"); | ||||||
|  | } | ||||||
|  | 
 | ||||||
| //test encoders
 | //test encoders
 | ||||||
| MU_TEST(subghz_encoder_princeton_test) { | MU_TEST(subghz_encoder_princeton_test) { | ||||||
|     mu_assert( |     mu_assert( | ||||||
| @ -805,6 +812,12 @@ MU_TEST(subghz_encoder_dooya_test) { | |||||||
|         "Test encoder " SUBGHZ_PROTOCOL_DOOYA_NAME " error\r\n"); |         "Test encoder " SUBGHZ_PROTOCOL_DOOYA_NAME " error\r\n"); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | MU_TEST(subghz_encoder_mastercode_test) { | ||||||
|  |     mu_assert( | ||||||
|  |         subghz_encoder_test(EXT_PATH("unit_tests/subghz/mastercode.sub")), | ||||||
|  |         "Test encoder " SUBGHZ_PROTOCOL_MASTERCODE_NAME " error\r\n"); | ||||||
|  | } | ||||||
|  | 
 | ||||||
| MU_TEST(subghz_random_test) { | MU_TEST(subghz_random_test) { | ||||||
|     mu_assert(subghz_decode_random_test(TEST_RANDOM_DIR_NAME), "Random test error\r\n"); |     mu_assert(subghz_decode_random_test(TEST_RANDOM_DIR_NAME), "Random test error\r\n"); | ||||||
| } | } | ||||||
| @ -855,6 +868,7 @@ MU_TEST_SUITE(subghz) { | |||||||
|     MU_RUN_TEST(subghz_decoder_alutech_at_4n_test); |     MU_RUN_TEST(subghz_decoder_alutech_at_4n_test); | ||||||
|     MU_RUN_TEST(subghz_decoder_nice_one_test); |     MU_RUN_TEST(subghz_decoder_nice_one_test); | ||||||
|     MU_RUN_TEST(subghz_decoder_kinggates_stylo4k_test); |     MU_RUN_TEST(subghz_decoder_kinggates_stylo4k_test); | ||||||
|  |     MU_RUN_TEST(subghz_decoder_mastercode_test); | ||||||
| 
 | 
 | ||||||
|     MU_RUN_TEST(subghz_encoder_princeton_test); |     MU_RUN_TEST(subghz_encoder_princeton_test); | ||||||
|     MU_RUN_TEST(subghz_encoder_came_test); |     MU_RUN_TEST(subghz_encoder_came_test); | ||||||
| @ -881,6 +895,7 @@ MU_TEST_SUITE(subghz) { | |||||||
|     MU_RUN_TEST(subghz_encoder_smc5326_test); |     MU_RUN_TEST(subghz_encoder_smc5326_test); | ||||||
|     MU_RUN_TEST(subghz_encoder_holtek_ht12x_test); |     MU_RUN_TEST(subghz_encoder_holtek_ht12x_test); | ||||||
|     MU_RUN_TEST(subghz_encoder_dooya_test); |     MU_RUN_TEST(subghz_encoder_dooya_test); | ||||||
|  |     MU_RUN_TEST(subghz_encoder_mastercode_test); | ||||||
| 
 | 
 | ||||||
|     MU_RUN_TEST(subghz_random_test); |     MU_RUN_TEST(subghz_random_test); | ||||||
|     subghz_test_deinit(); |     subghz_test_deinit(); | ||||||
|  | |||||||
							
								
								
									
										360
									
								
								lib/subghz/protocols/mastercode.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										360
									
								
								lib/subghz/protocols/mastercode.c
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,360 @@ | |||||||
|  | #include "mastercode.h" | ||||||
|  | 
 | ||||||
|  | #include "../blocks/const.h" | ||||||
|  | #include "../blocks/decoder.h" | ||||||
|  | #include "../blocks/encoder.h" | ||||||
|  | #include "../blocks/generic.h" | ||||||
|  | #include "../blocks/math.h" | ||||||
|  | 
 | ||||||
|  | // protocol MASTERCODE Clemsa MV1/MV12
 | ||||||
|  | #define TAG "SubGhzProtocolMastercode" | ||||||
|  | 
 | ||||||
|  | #define DIP_P 0b11 //(+)
 | ||||||
|  | #define DIP_O 0b10 //(0)
 | ||||||
|  | #define DIP_N 0b00 //(-)
 | ||||||
|  | 
 | ||||||
|  | #define DIP_PATTERN "%c%c%c%c%c%c%c%c" | ||||||
|  | 
 | ||||||
|  | #define SHOW_DIP_P(dip, check_dip)                         \ | ||||||
|  |     ((((dip >> 0x0) & 0x3) == check_dip) ? '*' : '_'),     \ | ||||||
|  |         ((((dip >> 0x2) & 0x3) == check_dip) ? '*' : '_'), \ | ||||||
|  |         ((((dip >> 0x4) & 0x3) == check_dip) ? '*' : '_'), \ | ||||||
|  |         ((((dip >> 0x6) & 0x3) == check_dip) ? '*' : '_'), \ | ||||||
|  |         ((((dip >> 0x8) & 0x3) == check_dip) ? '*' : '_'), \ | ||||||
|  |         ((((dip >> 0xA) & 0x3) == check_dip) ? '*' : '_'), \ | ||||||
|  |         ((((dip >> 0xC) & 0x3) == check_dip) ? '*' : '_'), \ | ||||||
|  |         ((((dip >> 0xE) & 0x3) == check_dip) ? '*' : '_') | ||||||
|  | 
 | ||||||
|  | static const SubGhzBlockConst subghz_protocol_mastercode_const = { | ||||||
|  |     .te_short = 1072, | ||||||
|  |     .te_long = 2145, | ||||||
|  |     .te_delta = 150, | ||||||
|  |     .min_count_bit_for_found = 36, | ||||||
|  | }; | ||||||
|  | 
 | ||||||
|  | struct SubGhzProtocolDecoderMastercode { | ||||||
|  |     SubGhzProtocolDecoderBase base; | ||||||
|  |     SubGhzBlockDecoder decoder; | ||||||
|  |     SubGhzBlockGeneric generic; | ||||||
|  | }; | ||||||
|  | 
 | ||||||
|  | struct SubGhzProtocolEncoderMastercode { | ||||||
|  |     SubGhzProtocolEncoderBase base; | ||||||
|  |     SubGhzProtocolBlockEncoder encoder; | ||||||
|  |     SubGhzBlockGeneric generic; | ||||||
|  | }; | ||||||
|  | 
 | ||||||
|  | typedef enum { | ||||||
|  |     MastercodeDecoderStepReset = 0, | ||||||
|  |     MastercodeDecoderStepSaveDuration, | ||||||
|  |     MastercodeDecoderStepCheckDuration, | ||||||
|  | } MastercodeDecoderStep; | ||||||
|  | 
 | ||||||
|  | const SubGhzProtocolDecoder subghz_protocol_mastercode_decoder = { | ||||||
|  |     .alloc = subghz_protocol_decoder_mastercode_alloc, | ||||||
|  |     .free = subghz_protocol_decoder_mastercode_free, | ||||||
|  | 
 | ||||||
|  |     .feed = subghz_protocol_decoder_mastercode_feed, | ||||||
|  |     .reset = subghz_protocol_decoder_mastercode_reset, | ||||||
|  | 
 | ||||||
|  |     .get_hash_data = subghz_protocol_decoder_mastercode_get_hash_data, | ||||||
|  |     .serialize = subghz_protocol_decoder_mastercode_serialize, | ||||||
|  |     .deserialize = subghz_protocol_decoder_mastercode_deserialize, | ||||||
|  |     .get_string = subghz_protocol_decoder_mastercode_get_string, | ||||||
|  | }; | ||||||
|  | 
 | ||||||
|  | const SubGhzProtocolEncoder subghz_protocol_mastercode_encoder = { | ||||||
|  |     .alloc = subghz_protocol_encoder_mastercode_alloc, | ||||||
|  |     .free = subghz_protocol_encoder_mastercode_free, | ||||||
|  | 
 | ||||||
|  |     .deserialize = subghz_protocol_encoder_mastercode_deserialize, | ||||||
|  |     .stop = subghz_protocol_encoder_mastercode_stop, | ||||||
|  |     .yield = subghz_protocol_encoder_mastercode_yield, | ||||||
|  | }; | ||||||
|  | 
 | ||||||
|  | const SubGhzProtocol subghz_protocol_mastercode = { | ||||||
|  |     .name = SUBGHZ_PROTOCOL_MASTERCODE_NAME, | ||||||
|  |     .type = SubGhzProtocolTypeStatic, | ||||||
|  |     .flag = SubGhzProtocolFlag_433 | SubGhzProtocolFlag_AM | SubGhzProtocolFlag_Decodable | | ||||||
|  |             SubGhzProtocolFlag_Load | SubGhzProtocolFlag_Save | SubGhzProtocolFlag_Send, | ||||||
|  | 
 | ||||||
|  |     .decoder = &subghz_protocol_mastercode_decoder, | ||||||
|  |     .encoder = &subghz_protocol_mastercode_encoder, | ||||||
|  | }; | ||||||
|  | 
 | ||||||
|  | void* subghz_protocol_encoder_mastercode_alloc(SubGhzEnvironment* environment) { | ||||||
|  |     UNUSED(environment); | ||||||
|  |     SubGhzProtocolEncoderMastercode* instance = malloc(sizeof(SubGhzProtocolEncoderMastercode)); | ||||||
|  | 
 | ||||||
|  |     instance->base.protocol = &subghz_protocol_mastercode; | ||||||
|  |     instance->generic.protocol_name = instance->base.protocol->name; | ||||||
|  | 
 | ||||||
|  |     instance->encoder.repeat = 10; | ||||||
|  |     instance->encoder.size_upload = 72; | ||||||
|  |     instance->encoder.upload = malloc(instance->encoder.size_upload * sizeof(LevelDuration)); | ||||||
|  |     instance->encoder.is_running = false; | ||||||
|  |     return instance; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | void subghz_protocol_encoder_mastercode_free(void* context) { | ||||||
|  |     furi_assert(context); | ||||||
|  |     SubGhzProtocolEncoderMastercode* instance = context; | ||||||
|  |     free(instance->encoder.upload); | ||||||
|  |     free(instance); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | /**
 | ||||||
|  |  * Generating an upload from data. | ||||||
|  |  * @param instance Pointer to a SubGhzProtocolEncoderMastercode instance | ||||||
|  |  * @return true On success | ||||||
|  |  */ | ||||||
|  | static bool | ||||||
|  |     subghz_protocol_encoder_mastercode_get_upload(SubGhzProtocolEncoderMastercode* 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; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     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_mastercode_const.te_long); | ||||||
|  |             instance->encoder.upload[index++] = | ||||||
|  |                 level_duration_make(false, (uint32_t)subghz_protocol_mastercode_const.te_short); | ||||||
|  |         } else { | ||||||
|  |             //send bit 0
 | ||||||
|  |             instance->encoder.upload[index++] = | ||||||
|  |                 level_duration_make(true, (uint32_t)subghz_protocol_mastercode_const.te_short); | ||||||
|  |             instance->encoder.upload[index++] = | ||||||
|  |                 level_duration_make(false, (uint32_t)subghz_protocol_mastercode_const.te_long); | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  |     if(bit_read(instance->generic.data, 0)) { | ||||||
|  |         //send bit 1
 | ||||||
|  |         instance->encoder.upload[index++] = | ||||||
|  |             level_duration_make(true, (uint32_t)subghz_protocol_mastercode_const.te_long); | ||||||
|  |         instance->encoder.upload[index++] = level_duration_make( | ||||||
|  |             false, | ||||||
|  |             (uint32_t)subghz_protocol_mastercode_const.te_short + | ||||||
|  |                 subghz_protocol_mastercode_const.te_short * 13); | ||||||
|  |     } else { | ||||||
|  |         //send bit 0
 | ||||||
|  |         instance->encoder.upload[index++] = | ||||||
|  |             level_duration_make(true, (uint32_t)subghz_protocol_mastercode_const.te_short); | ||||||
|  |         instance->encoder.upload[index++] = level_duration_make( | ||||||
|  |             false, | ||||||
|  |             (uint32_t)subghz_protocol_mastercode_const.te_long + | ||||||
|  |                 subghz_protocol_mastercode_const.te_short * 13); | ||||||
|  |     } | ||||||
|  |     return true; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | SubGhzProtocolStatus | ||||||
|  |     subghz_protocol_encoder_mastercode_deserialize(void* context, FlipperFormat* flipper_format) { | ||||||
|  |     furi_assert(context); | ||||||
|  |     SubGhzProtocolEncoderMastercode* instance = context; | ||||||
|  |     SubGhzProtocolStatus ret = SubGhzProtocolStatusError; | ||||||
|  |     do { | ||||||
|  |         ret = subghz_block_generic_deserialize_check_count_bit( | ||||||
|  |             &instance->generic, | ||||||
|  |             flipper_format, | ||||||
|  |             subghz_protocol_mastercode_const.min_count_bit_for_found); | ||||||
|  |         if(ret != SubGhzProtocolStatusOk) { | ||||||
|  |             break; | ||||||
|  |         } | ||||||
|  |         //optional parameter parameter
 | ||||||
|  |         flipper_format_read_uint32( | ||||||
|  |             flipper_format, "Repeat", (uint32_t*)&instance->encoder.repeat, 1); | ||||||
|  | 
 | ||||||
|  |         if(!subghz_protocol_encoder_mastercode_get_upload(instance)) { | ||||||
|  |             ret = SubGhzProtocolStatusErrorEncoderGetUpload; | ||||||
|  |             break; | ||||||
|  |         } | ||||||
|  |         instance->encoder.is_running = true; | ||||||
|  | 
 | ||||||
|  |     } while(false); | ||||||
|  | 
 | ||||||
|  |     return ret; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | void subghz_protocol_encoder_mastercode_stop(void* context) { | ||||||
|  |     SubGhzProtocolEncoderMastercode* instance = context; | ||||||
|  |     instance->encoder.is_running = false; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | LevelDuration subghz_protocol_encoder_mastercode_yield(void* context) { | ||||||
|  |     SubGhzProtocolEncoderMastercode* instance = context; | ||||||
|  | 
 | ||||||
|  |     if(instance->encoder.repeat == 0 || !instance->encoder.is_running) { | ||||||
|  |         instance->encoder.is_running = 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_mastercode_alloc(SubGhzEnvironment* environment) { | ||||||
|  |     UNUSED(environment); | ||||||
|  |     SubGhzProtocolDecoderMastercode* instance = malloc(sizeof(SubGhzProtocolDecoderMastercode)); | ||||||
|  |     instance->base.protocol = &subghz_protocol_mastercode; | ||||||
|  |     instance->generic.protocol_name = instance->base.protocol->name; | ||||||
|  |     return instance; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | void subghz_protocol_decoder_mastercode_free(void* context) { | ||||||
|  |     furi_assert(context); | ||||||
|  |     SubGhzProtocolDecoderMastercode* instance = context; | ||||||
|  |     free(instance); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | void subghz_protocol_decoder_mastercode_reset(void* context) { | ||||||
|  |     furi_assert(context); | ||||||
|  |     SubGhzProtocolDecoderMastercode* instance = context; | ||||||
|  |     instance->decoder.parser_step = MastercodeDecoderStepReset; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | void subghz_protocol_decoder_mastercode_feed(void* context, bool level, uint32_t duration) { | ||||||
|  |     furi_assert(context); | ||||||
|  |     SubGhzProtocolDecoderMastercode* instance = context; | ||||||
|  | 
 | ||||||
|  |     switch(instance->decoder.parser_step) { | ||||||
|  |     case MastercodeDecoderStepReset: | ||||||
|  |         if((!level) && (DURATION_DIFF(duration, subghz_protocol_mastercode_const.te_short * 15) < | ||||||
|  |                         subghz_protocol_mastercode_const.te_delta * 15)) { | ||||||
|  |             instance->decoder.parser_step = MastercodeDecoderStepSaveDuration; | ||||||
|  |             instance->decoder.decode_data = 0; | ||||||
|  |             instance->decoder.decode_count_bit = 0; | ||||||
|  |         } | ||||||
|  |         break; | ||||||
|  | 
 | ||||||
|  |     case MastercodeDecoderStepSaveDuration: | ||||||
|  |         if(level) { | ||||||
|  |             instance->decoder.te_last = duration; | ||||||
|  |             instance->decoder.parser_step = MastercodeDecoderStepCheckDuration; | ||||||
|  |         } else { | ||||||
|  |             instance->decoder.parser_step = MastercodeDecoderStepReset; | ||||||
|  |         } | ||||||
|  |         break; | ||||||
|  | 
 | ||||||
|  |     case MastercodeDecoderStepCheckDuration: | ||||||
|  |         if(!level) { | ||||||
|  |             if((DURATION_DIFF( | ||||||
|  |                     instance->decoder.te_last, subghz_protocol_mastercode_const.te_short) < | ||||||
|  |                 subghz_protocol_mastercode_const.te_delta) && | ||||||
|  |                (DURATION_DIFF(duration, subghz_protocol_mastercode_const.te_long) < | ||||||
|  |                 subghz_protocol_mastercode_const.te_delta * 8)) { | ||||||
|  |                 subghz_protocol_blocks_add_bit(&instance->decoder, 0); | ||||||
|  |                 instance->decoder.parser_step = MastercodeDecoderStepSaveDuration; | ||||||
|  |             } else if( | ||||||
|  |                 (DURATION_DIFF( | ||||||
|  |                      instance->decoder.te_last, subghz_protocol_mastercode_const.te_long) < | ||||||
|  |                  subghz_protocol_mastercode_const.te_delta * 8) && | ||||||
|  |                 (DURATION_DIFF(duration, subghz_protocol_mastercode_const.te_short) < | ||||||
|  |                  subghz_protocol_mastercode_const.te_delta)) { | ||||||
|  |                 subghz_protocol_blocks_add_bit(&instance->decoder, 1); | ||||||
|  |                 instance->decoder.parser_step = MastercodeDecoderStepSaveDuration; | ||||||
|  |             } else if( | ||||||
|  |                 DURATION_DIFF(duration, subghz_protocol_mastercode_const.te_short * 15) < | ||||||
|  |                 subghz_protocol_mastercode_const.te_delta * 15) { | ||||||
|  |                 if((DURATION_DIFF( | ||||||
|  |                         instance->decoder.te_last, subghz_protocol_mastercode_const.te_short) < | ||||||
|  |                     subghz_protocol_mastercode_const.te_delta)) { | ||||||
|  |                     subghz_protocol_blocks_add_bit(&instance->decoder, 0); | ||||||
|  |                 } else if((DURATION_DIFF( | ||||||
|  |                                instance->decoder.te_last, | ||||||
|  |                                subghz_protocol_mastercode_const.te_long) < | ||||||
|  |                            subghz_protocol_mastercode_const.te_delta * 8)) { | ||||||
|  |                     subghz_protocol_blocks_add_bit(&instance->decoder, 1); | ||||||
|  |                 } else { | ||||||
|  |                     instance->decoder.parser_step = MastercodeDecoderStepReset; | ||||||
|  |                 } | ||||||
|  | 
 | ||||||
|  |                 if(instance->decoder.decode_count_bit == | ||||||
|  |                    subghz_protocol_mastercode_const.min_count_bit_for_found) { | ||||||
|  |                     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); | ||||||
|  |                 } | ||||||
|  |                 instance->decoder.parser_step = MastercodeDecoderStepSaveDuration; | ||||||
|  |                 instance->decoder.decode_data = 0; | ||||||
|  |                 instance->decoder.decode_count_bit = 0; | ||||||
|  | 
 | ||||||
|  |             } else { | ||||||
|  |                 instance->decoder.parser_step = MastercodeDecoderStepReset; | ||||||
|  |             } | ||||||
|  |         } else { | ||||||
|  |             instance->decoder.parser_step = MastercodeDecoderStepReset; | ||||||
|  |         } | ||||||
|  |         break; | ||||||
|  |     } | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | /** 
 | ||||||
|  |  * Analysis of received data | ||||||
|  |  * @param instance Pointer to a SubGhzBlockGeneric* instance | ||||||
|  |  */ | ||||||
|  | static void subghz_protocol_mastercode_check_remote_controller(SubGhzBlockGeneric* instance) { | ||||||
|  |     instance->serial = (instance->data >> 4) & 0xFFFF; | ||||||
|  |     instance->btn = (instance->data >> 2 & 0x03); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | uint8_t subghz_protocol_decoder_mastercode_get_hash_data(void* context) { | ||||||
|  |     furi_assert(context); | ||||||
|  |     SubGhzProtocolDecoderMastercode* instance = context; | ||||||
|  |     return subghz_protocol_blocks_get_hash_data( | ||||||
|  |         &instance->decoder, (instance->decoder.decode_count_bit / 8) + 1); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | SubGhzProtocolStatus subghz_protocol_decoder_mastercode_serialize( | ||||||
|  |     void* context, | ||||||
|  |     FlipperFormat* flipper_format, | ||||||
|  |     SubGhzRadioPreset* preset) { | ||||||
|  |     furi_assert(context); | ||||||
|  |     SubGhzProtocolDecoderMastercode* instance = context; | ||||||
|  |     return subghz_block_generic_serialize(&instance->generic, flipper_format, preset); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | SubGhzProtocolStatus | ||||||
|  |     subghz_protocol_decoder_mastercode_deserialize(void* context, FlipperFormat* flipper_format) { | ||||||
|  |     furi_assert(context); | ||||||
|  |     SubGhzProtocolDecoderMastercode* instance = context; | ||||||
|  |     return subghz_block_generic_deserialize_check_count_bit( | ||||||
|  |         &instance->generic, | ||||||
|  |         flipper_format, | ||||||
|  |         subghz_protocol_mastercode_const.min_count_bit_for_found); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | void subghz_protocol_decoder_mastercode_get_string(void* context, FuriString* output) { | ||||||
|  |     furi_assert(context); | ||||||
|  |     SubGhzProtocolDecoderMastercode* instance = context; | ||||||
|  |     subghz_protocol_mastercode_check_remote_controller(&instance->generic); | ||||||
|  |     furi_string_cat_printf( | ||||||
|  |         output, | ||||||
|  |         "%s %dbit\r\n" | ||||||
|  |         "Key:%llX   Btn %X\r\n" | ||||||
|  |         "  +:   " DIP_PATTERN "\r\n" | ||||||
|  |         "  o:   " DIP_PATTERN "\r\n" | ||||||
|  |         "  -:   " DIP_PATTERN "\r\n", | ||||||
|  |         instance->generic.protocol_name, | ||||||
|  |         instance->generic.data_count_bit, | ||||||
|  |         (uint64_t)(instance->generic.data), | ||||||
|  |         instance->generic.btn, | ||||||
|  |         SHOW_DIP_P(instance->generic.serial, DIP_P), | ||||||
|  |         SHOW_DIP_P(instance->generic.serial, DIP_O), | ||||||
|  |         SHOW_DIP_P(instance->generic.serial, DIP_N)); | ||||||
|  | } | ||||||
							
								
								
									
										109
									
								
								lib/subghz/protocols/mastercode.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										109
									
								
								lib/subghz/protocols/mastercode.h
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,109 @@ | |||||||
|  | #pragma once | ||||||
|  | 
 | ||||||
|  | #include "base.h" | ||||||
|  | 
 | ||||||
|  | #define SUBGHZ_PROTOCOL_MASTERCODE_NAME "Mastercode" | ||||||
|  | 
 | ||||||
|  | typedef struct SubGhzProtocolDecoderMastercode SubGhzProtocolDecoderMastercode; | ||||||
|  | typedef struct SubGhzProtocolEncoderMastercode SubGhzProtocolEncoderMastercode; | ||||||
|  | 
 | ||||||
|  | extern const SubGhzProtocolDecoder subghz_protocol_mastercode_decoder; | ||||||
|  | extern const SubGhzProtocolEncoder subghz_protocol_mastercode_encoder; | ||||||
|  | extern const SubGhzProtocol subghz_protocol_mastercode; | ||||||
|  | 
 | ||||||
|  | /**
 | ||||||
|  |  * Allocate SubGhzProtocolEncoderMastercode. | ||||||
|  |  * @param environment Pointer to a SubGhzEnvironment instance | ||||||
|  |  * @return SubGhzProtocolEncoderMastercode* pointer to a SubGhzProtocolEncoderMastercode instance | ||||||
|  |  */ | ||||||
|  | void* subghz_protocol_encoder_mastercode_alloc(SubGhzEnvironment* environment); | ||||||
|  | 
 | ||||||
|  | /**
 | ||||||
|  |  * Free SubGhzProtocolEncoderMastercode. | ||||||
|  |  * @param context Pointer to a SubGhzProtocolEncoderMastercode instance | ||||||
|  |  */ | ||||||
|  | void subghz_protocol_encoder_mastercode_free(void* context); | ||||||
|  | 
 | ||||||
|  | /**
 | ||||||
|  |  * Deserialize and generating an upload to send. | ||||||
|  |  * @param context Pointer to a SubGhzProtocolEncoderMastercode instance | ||||||
|  |  * @param flipper_format Pointer to a FlipperFormat instance | ||||||
|  |  * @return status | ||||||
|  |  */ | ||||||
|  | SubGhzProtocolStatus | ||||||
|  |     subghz_protocol_encoder_mastercode_deserialize(void* context, FlipperFormat* flipper_format); | ||||||
|  | 
 | ||||||
|  | /**
 | ||||||
|  |  * Forced transmission stop. | ||||||
|  |  * @param context Pointer to a SubGhzProtocolEncoderMastercode instance | ||||||
|  |  */ | ||||||
|  | void subghz_protocol_encoder_mastercode_stop(void* context); | ||||||
|  | 
 | ||||||
|  | /**
 | ||||||
|  |  * Getting the level and duration of the upload to be loaded into DMA. | ||||||
|  |  * @param context Pointer to a SubGhzProtocolEncoderMastercode instance | ||||||
|  |  * @return LevelDuration  | ||||||
|  |  */ | ||||||
|  | LevelDuration subghz_protocol_encoder_mastercode_yield(void* context); | ||||||
|  | 
 | ||||||
|  | /**
 | ||||||
|  |  * Allocate SubGhzProtocolDecoderMastercode. | ||||||
|  |  * @param environment Pointer to a SubGhzEnvironment instance | ||||||
|  |  * @return SubGhzProtocolDecoderMastercode* pointer to a SubGhzProtocolDecoderMastercode instance | ||||||
|  |  */ | ||||||
|  | void* subghz_protocol_decoder_mastercode_alloc(SubGhzEnvironment* environment); | ||||||
|  | 
 | ||||||
|  | /**
 | ||||||
|  |  * Free SubGhzProtocolDecoderMastercode. | ||||||
|  |  * @param context Pointer to a SubGhzProtocolDecoderMastercode instance | ||||||
|  |  */ | ||||||
|  | void subghz_protocol_decoder_mastercode_free(void* context); | ||||||
|  | 
 | ||||||
|  | /**
 | ||||||
|  |  * Reset decoder SubGhzProtocolDecoderMastercode. | ||||||
|  |  * @param context Pointer to a SubGhzProtocolDecoderMastercode instance | ||||||
|  |  */ | ||||||
|  | void subghz_protocol_decoder_mastercode_reset(void* context); | ||||||
|  | 
 | ||||||
|  | /**
 | ||||||
|  |  * Parse a raw sequence of levels and durations received from the air. | ||||||
|  |  * @param context Pointer to a SubGhzProtocolDecoderMastercode instance | ||||||
|  |  * @param level Signal level true-high false-low | ||||||
|  |  * @param duration Duration of this level in, us | ||||||
|  |  */ | ||||||
|  | void subghz_protocol_decoder_mastercode_feed(void* context, bool level, uint32_t duration); | ||||||
|  | 
 | ||||||
|  | /**
 | ||||||
|  |  * Getting the hash sum of the last randomly received parcel. | ||||||
|  |  * @param context Pointer to a SubGhzProtocolDecoderMastercode instance | ||||||
|  |  * @return hash Hash sum | ||||||
|  |  */ | ||||||
|  | uint8_t subghz_protocol_decoder_mastercode_get_hash_data(void* context); | ||||||
|  | 
 | ||||||
|  | /**
 | ||||||
|  |  * Serialize data SubGhzProtocolDecoderMastercode. | ||||||
|  |  * @param context Pointer to a SubGhzProtocolDecoderMastercode instance | ||||||
|  |  * @param flipper_format Pointer to a FlipperFormat instance | ||||||
|  |  * @param preset The modulation on which the signal was received, SubGhzRadioPreset | ||||||
|  |  * @return status | ||||||
|  |  */ | ||||||
|  | SubGhzProtocolStatus subghz_protocol_decoder_mastercode_serialize( | ||||||
|  |     void* context, | ||||||
|  |     FlipperFormat* flipper_format, | ||||||
|  |     SubGhzRadioPreset* preset); | ||||||
|  | 
 | ||||||
|  | /**
 | ||||||
|  |  * Deserialize data SubGhzProtocolDecoderMastercode. | ||||||
|  |  * @param context Pointer to a SubGhzProtocolDecoderMastercode instance | ||||||
|  |  * @param flipper_format Pointer to a FlipperFormat instance | ||||||
|  |  * @return status | ||||||
|  |  */ | ||||||
|  | SubGhzProtocolStatus | ||||||
|  |     subghz_protocol_decoder_mastercode_deserialize(void* context, FlipperFormat* flipper_format); | ||||||
|  | 
 | ||||||
|  | /**
 | ||||||
|  |  * Getting a textual representation of the received data. | ||||||
|  |  * @param context Pointer to a SubGhzProtocolDecoderMastercode instance | ||||||
|  |  * @param output Resulting text | ||||||
|  |  */ | ||||||
|  | void subghz_protocol_decoder_mastercode_get_string(void* context, FuriString* output); | ||||||
| @ -43,6 +43,7 @@ const SubGhzProtocol* subghz_protocol_registry_items[] = { | |||||||
|     &subghz_protocol_alutech_at_4n, |     &subghz_protocol_alutech_at_4n, | ||||||
|     &subghz_protocol_kinggates_stylo_4k, |     &subghz_protocol_kinggates_stylo_4k, | ||||||
|     &subghz_protocol_bin_raw, |     &subghz_protocol_bin_raw, | ||||||
|  |     &subghz_protocol_mastercode, | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| const SubGhzProtocolRegistry subghz_protocol_registry = { | const SubGhzProtocolRegistry subghz_protocol_registry = { | ||||||
|  | |||||||
| @ -44,3 +44,4 @@ | |||||||
| #include "alutech_at_4n.h" | #include "alutech_at_4n.h" | ||||||
| #include "kinggates_stylo_4k.h" | #include "kinggates_stylo_4k.h" | ||||||
| #include "bin_raw.h" | #include "bin_raw.h" | ||||||
|  | #include "mastercode.h" | ||||||
|  | |||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user
	 Flipper Zelebro
						Flipper Zelebro