From a61b5d4b4cd7f11f4b836ba085860f58689905b8 Mon Sep 17 00:00:00 2001 From: Flipper Zelebro <149575765+flipperzelebro@users.noreply.github.com> Date: Wed, 15 Nov 2023 10:04:45 +0100 Subject: [PATCH] Add Mastercode SubGHz Protocol (#3187) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * 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 Co-authored-by: あく --- .../unit_tests/subghz/mastercode.sub | 7 + .../unit_tests/subghz/mastercode_raw.sub | 6 + .../debug/unit_tests/subghz/subghz_test.c | 15 + lib/subghz/protocols/mastercode.c | 360 ++++++++++++++++++ lib/subghz/protocols/mastercode.h | 109 ++++++ lib/subghz/protocols/protocol_items.c | 1 + lib/subghz/protocols/protocol_items.h | 1 + 7 files changed, 499 insertions(+) create mode 100644 applications/debug/unit_tests/resources/unit_tests/subghz/mastercode.sub create mode 100644 applications/debug/unit_tests/resources/unit_tests/subghz/mastercode_raw.sub create mode 100644 lib/subghz/protocols/mastercode.c create mode 100644 lib/subghz/protocols/mastercode.h diff --git a/applications/debug/unit_tests/resources/unit_tests/subghz/mastercode.sub b/applications/debug/unit_tests/resources/unit_tests/subghz/mastercode.sub new file mode 100644 index 000000000..f50abbfe8 --- /dev/null +++ b/applications/debug/unit_tests/resources/unit_tests/subghz/mastercode.sub @@ -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 diff --git a/applications/debug/unit_tests/resources/unit_tests/subghz/mastercode_raw.sub b/applications/debug/unit_tests/resources/unit_tests/subghz/mastercode_raw.sub new file mode 100644 index 000000000..69d3f396c --- /dev/null +++ b/applications/debug/unit_tests/resources/unit_tests/subghz/mastercode_raw.sub @@ -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 diff --git a/applications/debug/unit_tests/subghz/subghz_test.c b/applications/debug/unit_tests/subghz/subghz_test.c index 64e0591df..2f2b9e981 100644 --- a/applications/debug/unit_tests/subghz/subghz_test.c +++ b/applications/debug/unit_tests/subghz/subghz_test.c @@ -654,6 +654,13 @@ MU_TEST(subghz_decoder_kinggates_stylo4k_test) { "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 MU_TEST(subghz_encoder_princeton_test) { mu_assert( @@ -805,6 +812,12 @@ MU_TEST(subghz_encoder_dooya_test) { "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_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_nice_one_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_came_test); @@ -881,6 +895,7 @@ MU_TEST_SUITE(subghz) { MU_RUN_TEST(subghz_encoder_smc5326_test); MU_RUN_TEST(subghz_encoder_holtek_ht12x_test); MU_RUN_TEST(subghz_encoder_dooya_test); + MU_RUN_TEST(subghz_encoder_mastercode_test); MU_RUN_TEST(subghz_random_test); subghz_test_deinit(); diff --git a/lib/subghz/protocols/mastercode.c b/lib/subghz/protocols/mastercode.c new file mode 100644 index 000000000..54ad5bfaa --- /dev/null +++ b/lib/subghz/protocols/mastercode.c @@ -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)); +} diff --git a/lib/subghz/protocols/mastercode.h b/lib/subghz/protocols/mastercode.h new file mode 100644 index 000000000..c5c73db98 --- /dev/null +++ b/lib/subghz/protocols/mastercode.h @@ -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); diff --git a/lib/subghz/protocols/protocol_items.c b/lib/subghz/protocols/protocol_items.c index 74244c5ff..472a354e3 100644 --- a/lib/subghz/protocols/protocol_items.c +++ b/lib/subghz/protocols/protocol_items.c @@ -43,6 +43,7 @@ const SubGhzProtocol* subghz_protocol_registry_items[] = { &subghz_protocol_alutech_at_4n, &subghz_protocol_kinggates_stylo_4k, &subghz_protocol_bin_raw, + &subghz_protocol_mastercode, }; const SubGhzProtocolRegistry subghz_protocol_registry = { diff --git a/lib/subghz/protocols/protocol_items.h b/lib/subghz/protocols/protocol_items.h index f1a28ac9b..c5a090e99 100644 --- a/lib/subghz/protocols/protocol_items.h +++ b/lib/subghz/protocols/protocol_items.h @@ -44,3 +44,4 @@ #include "alutech_at_4n.h" #include "kinggates_stylo_4k.h" #include "bin_raw.h" +#include "mastercode.h"