فهرست منبع

[FL-3099] SubGhz: add protocol KingGates Stylo4k (#2368)

* [FL-3099] SubGhz: add protocol KingGates Stylo4k
* SubGhz: add unit test file
* f7: api: reverted symbols

Co-authored-by: hedger <hedger@nanode.su>
Co-authored-by: Aleksandr Kutuzov <alleteam@gmail.com>
Skorpionm 2 سال پیش
والد
کامیت
db1a8f8014

+ 10 - 1
applications/debug/unit_tests/subghz/subghz_test.c

@@ -14,7 +14,7 @@
 #define NICE_FLOR_S_DIR_NAME EXT_PATH("subghz/assets/nice_flor_s")
 #define NICE_FLOR_S_DIR_NAME EXT_PATH("subghz/assets/nice_flor_s")
 #define ALUTECH_AT_4N_DIR_NAME EXT_PATH("subghz/assets/alutech_at_4n")
 #define ALUTECH_AT_4N_DIR_NAME EXT_PATH("subghz/assets/alutech_at_4n")
 #define TEST_RANDOM_DIR_NAME EXT_PATH("unit_tests/subghz/test_random_raw.sub")
 #define TEST_RANDOM_DIR_NAME EXT_PATH("unit_tests/subghz/test_random_raw.sub")
-#define TEST_RANDOM_COUNT_PARSE 317
+#define TEST_RANDOM_COUNT_PARSE 329
 #define TEST_TIMEOUT 10000
 #define TEST_TIMEOUT 10000
 
 
 static SubGhzEnvironment* environment_handler;
 static SubGhzEnvironment* environment_handler;
@@ -637,6 +637,14 @@ MU_TEST(subghz_decoder_nice_one_test) {
         "Test decoder " SUBGHZ_PROTOCOL_NICE_FLOR_S_NAME " error\r\n");
         "Test decoder " SUBGHZ_PROTOCOL_NICE_FLOR_S_NAME " error\r\n");
 }
 }
 
 
+MU_TEST(subghz_decoder_kinggates_stylo4k_test) {
+    mu_assert(
+        subghz_decoder_test(
+            EXT_PATH("unit_tests/subghz/kinggates_stylo4k_raw.sub"),
+            SUBGHZ_PROTOCOL_KINGGATES_STYLO_4K_NAME),
+        "Test decoder " SUBGHZ_PROTOCOL_KINGGATES_STYLO_4K_NAME " error\r\n");
+}
+
 //test encoders
 //test encoders
 MU_TEST(subghz_encoder_princeton_test) {
 MU_TEST(subghz_encoder_princeton_test) {
     mu_assert(
     mu_assert(
@@ -837,6 +845,7 @@ MU_TEST_SUITE(subghz) {
     MU_RUN_TEST(subghz_decoder_dooya_test);
     MU_RUN_TEST(subghz_decoder_dooya_test);
     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_encoder_princeton_test);
     MU_RUN_TEST(subghz_encoder_princeton_test);
     MU_RUN_TEST(subghz_encoder_came_test);
     MU_RUN_TEST(subghz_encoder_came_test);

+ 53 - 52
assets/resources/subghz/assets/keeloq_mfcodes

@@ -1,55 +1,56 @@
 Filetype: Flipper SubGhz Keystore File
 Filetype: Flipper SubGhz Keystore File
 Version: 0
 Version: 0
 Encryption: 1
 Encryption: 1
-IV: AA FF DE 54 A1 BB F1 21 83 46 FE 2A 1E B7 3D 33
-95B8CD65BBAC95EACE67CA94F679B82877A921396D461ECB479722F8A369454A
-61065C41297B9FF8F8168814F49A03D1FE7B4CB79DFFCBBF0402AAA6A2211E84
-A1557AC139188FF105D1081A4B688C5CA440FB5DA7F40901B541120AD08A544F
-AF0A6056D7F0D97DAD6C16C4E63204E4B3B1C5A20AC82B983B516F4F718EE29F
-6861BFAE46A1AADB1DB2D6DFAA7E39D21D5B3E46A41BD50F4F2828879EB328EF0A406F2B9C79A031AB361257E6D69756
-0DDB3DAC53678541981CC46C22CED245CBA314C9BBE1BA9383B8505B75AC5E40
-99AB5D9404934F2D257ED04D9F8CCEE06D00F38157B121AFD63101E4E5C08268
-5114A6C42B342C7D933A76F9052FF963C2047E85EA524497C21B4C35C38EF6E7
-88CA2A1907D94B972FF93DBB9B88CB576F3E1BB0FE8F85A5B2CCA7D44B00374D
-349C4153FE7CA8AE044E9F75F77D9694304474CE3F127CF968662B5F78A7F421
-62AA02E20CA7E691EFC0B55CA41C9BDF889FB23868289284241CD31AA1A0E499AE2A770B6B5AB3170CDCCDB8A246D36C
-97901B5EB76228ADF8E5073F1BAB1502878DEFF1C4EBF12A43D105556CB7E80F947A8BD7831666BD838C57CDF64A6F3F
-B05959D210B500943A93BDFAF783D9DB215FC84503B152EAFBCFB5B6237E3888
-B393DE4489BCAFD5DB80592A12E329E18913E185D2042580048029A8C4C3A257
-B4B30492A5F0C3C763E2F43C02D1451A5B9CFB468CFE62BE85B1F56FF49DAB9A
-CE5D57C0EE3D717FC717EB725970A9F25D211546EE7AC5C237950CEA323D85D4
-4E9028944813FD40A17AF6DF5A97E76179B48EE79265BBD38B07E3A270587A813DADB51B3367479AC5644F754B5613F8
-3B3C3000B9D1361711ECE3DB77C90A059576F738CB167679DA36DD3D128B27A1
-997023148148DE7B9CBA47D3FD48DEF73AA1715FF4BC1E7A1DBA6D52A0DCB2C0
-C8428D18E69FB92486434FCE470F1FF37D40507F27D824679C132A70D516530367277F02DDB5C464D03450FF6B425A24
-3701200DF5DA7235971FD95844056E74C7D61A8EB12A8772E04F52037C63D50B6229A7F905F3E6F84C565FCC7632870C
-BB392A464CDC0D5D923AA9EF8ECC3C6F020D0AD82165462DF0DE7C5025AAAAAC
-999C82209B30638506E5D708471676D2CBB4A432E5AF86ABD61179111EDAE636
-FDE2A452A6B47261338117EC20FC57731DA492562ECD21BBC61F098A5442CF20
-D923BABB5C4DFB48E3F763898B2796C7830D3EE9A91DF904AC2223A0F4736507
-0987DDAC695DD5E4607048DF1D4EF96599E17ED52F41785E676AA048AB7213FE
-26CB3E6CFA10338A8DDD99BFF6957C53DEF435CB0FF977B71B5164ADFE11292A
-097908FD07A0A093CA80E6FF59524707C1A11169D0CB6F8E4967D8DAA725FE7A
-8C629E70A5CC6FCB039DFA1A6AC58CB7B7E92C85BDA66266AB49E6B1285FC7A6
-39A2052350CD446EDC1B9AD0C2DD51C78B2E5F3A76AAD0EC200F74B40ACD4AC5
-A1685CF8C4A5401F2CA0C8172CB5B4B5726C61CE68A72AE834B0A472CEB2F3DE
-1F5ED5793DB381D1B501BA8A4DF3E74FB11FC1A922DDC8AE62E5BA8934C37EA8
-D80EF661BF36E2F6C179E253CE5BC3732684ACBC7C65E526A628442A2EBF8FAA
-7785BF721F21E19A8CFBFBBB56BD76B96A4E8EF9F8A2344009B14AB385909598F834A5533B648DA7D62BD6D4314A43A5
-C8F6F943DE615B5827569B283577344C0455B3279C73634FC4E0E9A8088DF633
-FB4F4C786FC51BBDA679A212B4A05EF120AC62F7EBFFE8263BD50A4D9BC9C6E0
-16EEC35CF69BA86DB3BE999CDF9B39F5736F3727B2AA2C5AB9141A48F176D831
-AD1AD6DE813E7710DA3AF546D4F9EA085831E6B3FA17B64F1B8765F48134EA54
-345D743BC35B4A8614632ADD11E809C0D1E6C78F9469256B9A738DA0B648B2B8
-7C876CECAC839EBB4609C3996966C3EC454F51C8ABCC51097E405370C4B6F086
-0F857C031FD3047607647148C534F969567F207FF1691D8D06DCDF4C2514695D
-EC0630EDC82241C1952F49B6B1B0C1A954A7DDD6BDB1326ACC54AD449D1BF985
-286EF9F7FD0D09F2604CCE867C52144CD0C4773A3D8183066C61B8BF9860AE7C
-EA55424097A08722A66966E3177E09DE91AC65175E5C68CB47B6153E6585DF85
-D54FCDF9EA4BD1FE4F316DB6D5CE4A2675F2D0144772865EDC781FBA7DFD23E4
-7A2F5C5CA9F97FE9527BAA760E64B930C407A27DE036476737E6BDD9422F4056A5F1F414F12F0982109FD7C30E8CC1CB
-06BAD9B4EEEEB1BCF8C97672D271534FE84D772282EE9642698788D3842D7641
-101C1B2DBD963E23777294C22E553D145D5B40838F91355CA86D571A0CEFF68F
-1B148C2B502B3E0A5BD40858E019C513DD4CCAF2A114CBB29C59BFB018079285
-8DF4D07EC20FF873EA989ACEF4AF96E9787FE6E0F71965858B4186C3AF302A31
-2317DC8C098CD60F3467B3644A19CCE887339708820CD37F6F5277D6648F837512F70CE90E23D7339CDDE002BD8D83DB
+IV: 41 84 34 43 84 1D 43 04 45 44 34 38 41 24 3E 74
+8C5AEF725F0620DB3952B40BB8E76A815BCEE1D1B92F7E8E8E63D1894F1C7FD0
+1DFF1D6A322D6B3D8AD7C594A02462AADE723D417B9233585526982F08187DAA
+0A9184F15D4A5589DDDA6422063BACD58580661CFE60EE600D87F73F0CB5013E
+6E56802DAA049C3DFDEDC90432A0E694A172C369EBECD136F4C911B979AA098D
+A659716B51053604059F7FC3651D6A153F5EAB1852F95B20C44C41A7889A0DE91A078B63E3C311280C4315F0A3C8BA1F
+A315170EDC51627157725D9A96490DB75EBF8232957FBA313C03B2BA2884EA85
+DEAB3C2C2E2DC76FE45AEBAC7EBFB478CECCD970A63B8DE2024FBFDCCBD1B26E
+7BBFC36CBA77468B4624C6B685610877D53985C985DAD8EFE47527EB7C7260CD
+879EE18B314ED4F3F548B41176099176FB97F4F1A062481C935B2DDFBCE2FE4D
+493372D7D47A96A66305DFDC8A915EB651620881AE1D603B7E9605E004C04CA9
+F80AAA4C447F8E8C0B039DDAECF9126119C32FF164118780BE268E326A8CBF8010DE2EBF94033CEAC39815D6A8958CF4
+41C1393A039E665F6A53A5E5D1C105008BD14D9755751545A667860C39B2E39AA47306E76E2BA7DDDAA2A286FDB58D23
+34853A4CDE42CB80045E641AB4800C86C1CF6907EAAFA399156CCC727A008584
+D0783A34BD6A36D31BFF5F70FA1116CAE48EF02716D80481AE406DABB3C3400E
+0BB3582605434CF2A5D74A27773B88DA331B6033C444837E9F7A155897258B03
+E4E71F3EB290B9436FFF0FDADA468BE37D964E89BE8D9971A14776F821822769
+744AA59D129C892120B5DAB81C8A3D573B0AD80EF0708C1B9ECF13DA60CECA07DC0591A08611DB4D3A8B7C70994D5DEF
+716F9F8D5D2C697BC4183EFCC97E52D08ECA07B613A0F389C801F65803DFF4A4
+560262DA8489D2C18C8D97E314DC663403AFE4DE9DCB6D453087D2BFBD36532D
+9E31F7152C50B6940EE3E3894C98F75702C7897F702B48E5C9B54B6E25083641AD2E521267505066C7E5BAB7F6CF1433
+6630EDA18A6E58BD395792CCC656DD10CD9C5DD2B1949FE677122FA39A53C724E79C0D0752A3A39A03407BBA2282185E
+00D15A06F5DD82A4B926B78809CC4D129AAFA9A92B0A81568F255D15697FE0FD
+29FF9A4F5346ABEE8FEDE034988F87FCD29EA747735898F1E7207EF74FAB71A8
+C0E8EB6AE6F77EE38DF2AB1B7742E34ED5236F3D8E964845E66762A4675AA21F
+00FC4C459DC4CE92B62D0AC2546F9FBBE0893F84D2AF0A20ED462A5EAE63DE3B
+E92EF482A40CEEFC8339BBB713BBC452A266A09B2645EDEB12716544B2DB9B09
+D7D9C5C757831BCE2FF1DB25A080D77769FB36A1F3F48F4361418A0A45609280
+C19246F52AE1EE5CE968CED52F642D9CD78B020029632FE83C49C657D23ED075
+FEE3C05432FB3860D5D28562323F5D1B053B8F3ADCD416BD0C4645F6F4D43DCF
+D780A4AADD0205E0BACDCC9AF46ED259E0946C5DA888C341BFE96E09A87CCCFA
+CE3C13CFA08E532B637FDB707E29548D57EE92EAEF6516C3D67E9D36FCD59CF9
+5E88CE71258CB0D91631FEB41C9A2F47AE0FF4810A9A1EDF3F308BBDE6944D5E
+1531F4107FC64810BA5DB5E46C7B9AD61531AF5430E137B7688109FBC06B6221
+68050A39C0B302E0B713FAAC5F829C79AB30E18B1D982A94005DBAC7CCFB95379A619C0B9F7409C44D19FF2C5E8E4546
+3F73E8BA22C602280496EF8E88E2CAA9EC442E3B3083B684942DBF9CB5121241
+FA1FCD7C9182FAE8FFF4E88433AE68F66076B3BDFF8AD0BF5CEA43870082E9BE
+DFF7DD2678C03401656B093BF7AC7E033F15FD0F30188E48A62045740B423699
+371BCFF653E7811D99C048A1A39921AAA563E06AC86CB3D2F392C2C955A1ABD0
+F4F1766DEAEDE934478208B9EB3050326D9FFCC001C73EEE93407D8B12CD49E4
+A241C9FC62DDF67D645936245FAFFE2A42C86151F484B7BCE5410E8F36FC87901D3AC4E40334E08FFFC2AD676E490D94
+3566A94A9C0479E0C4387D9137375ADF2C921504364F3903F198D6757CDFD21B
+7274E1B5A6445FDC29C355D550E981C17F349BC4A14251B3B51BC96FC334FBCA
+04EEA5EDD9B3BC3E0638E53A5561DC8BF761D615A64D435BD31A94AF2650159E
+B84818CC1695FE8B731CD653D0679D1AAA0578C0B06AD1E3510785B2DE20841C
+4121343D6B79E38C06DD038D770D76D10336AFF47ED0D0DCDDD6B0FEA4DAE67C
+75E49C839CCD7019D9CE90AC364F488468B2AB01E387A8BEF8815915925166A6
+CFAA9F4717568C1EC7B96E0D71D260B828A70484E1D9CA7C99A50D10704F8BBBAE62EE98C9FBDFF06F357F1C1E2F2677
+41E4D250B92BC57442B91DE2015C41226531CF9A8D77B83AFC8E4F3183DB11DE
+45EA8BD854D7F044FB249C16F08A0C24FF117D54BC20A4CC667B3DAD09EAC4F9
+F455CA0BB8B496C301406DE4FB52C9B0F64645776803BC2935A2F38675318BE2
+22FF72A5D2E1A2EBFB6C55FFD0A3CEA0474CCBD13462D63229C9708276E87D3F
+8470F9A300170F226C0216C07AA829591CBD4CE34AA918EAE49363BDE86CC77EEEBEEA84A097488D35B92F773F5DBB4C

تفاوت فایلی نمایش داده نمی شود زیرا این فایل بسیار بزرگ است
+ 5 - 0
assets/unit_tests/subghz/kinggates_stylo4k_raw.sub


تفاوت فایلی نمایش داده نمی شود زیرا این فایل بسیار بزرگ است
+ 0 - 0
assets/unit_tests/subghz/test_random_raw.sub


+ 336 - 0
lib/subghz/protocols/kinggates_stylo_4k.c

@@ -0,0 +1,336 @@
+#include "kinggates_stylo_4k.h"
+#include "keeloq_common.h"
+
+#include "../subghz_keystore.h"
+#include "../blocks/const.h"
+#include "../blocks/decoder.h"
+#include "../blocks/encoder.h"
+#include "../blocks/generic.h"
+#include "../blocks/math.h"
+
+#define TAG "SubGhzProtocoKingGates_stylo_4k"
+
+static const SubGhzBlockConst subghz_protocol_kinggates_stylo_4k_const = {
+    .te_short = 400,
+    .te_long = 1100,
+    .te_delta = 140,
+    .min_count_bit_for_found = 89,
+};
+
+struct SubGhzProtocolDecoderKingGates_stylo_4k {
+    SubGhzProtocolDecoderBase base;
+
+    SubGhzBlockDecoder decoder;
+    SubGhzBlockGeneric generic;
+
+    uint64_t data;
+    uint16_t header_count;
+    SubGhzKeystore* keystore;
+};
+
+struct SubGhzProtocolEncoderKingGates_stylo_4k {
+    SubGhzProtocolEncoderBase base;
+
+    SubGhzProtocolBlockEncoder encoder;
+    SubGhzBlockGeneric generic;
+};
+
+typedef enum {
+    KingGates_stylo_4kDecoderStepReset = 0,
+    KingGates_stylo_4kDecoderStepCheckPreambula,
+    KingGates_stylo_4kDecoderStepCheckStartBit,
+    KingGates_stylo_4kDecoderStepSaveDuration,
+    KingGates_stylo_4kDecoderStepCheckDuration,
+} KingGates_stylo_4kDecoderStep;
+
+const SubGhzProtocolDecoder subghz_protocol_kinggates_stylo_4k_decoder = {
+    .alloc = subghz_protocol_decoder_kinggates_stylo_4k_alloc,
+    .free = subghz_protocol_decoder_kinggates_stylo_4k_free,
+
+    .feed = subghz_protocol_decoder_kinggates_stylo_4k_feed,
+    .reset = subghz_protocol_decoder_kinggates_stylo_4k_reset,
+
+    .get_hash_data = subghz_protocol_decoder_kinggates_stylo_4k_get_hash_data,
+    .serialize = subghz_protocol_decoder_kinggates_stylo_4k_serialize,
+    .deserialize = subghz_protocol_decoder_kinggates_stylo_4k_deserialize,
+    .get_string = subghz_protocol_decoder_kinggates_stylo_4k_get_string,
+};
+
+const SubGhzProtocolEncoder subghz_protocol_kinggates_stylo_4k_encoder = {
+    .alloc = NULL,
+    .free = NULL,
+
+    .deserialize = NULL,
+    .stop = NULL,
+    .yield = NULL,
+};
+
+const SubGhzProtocol subghz_protocol_kinggates_stylo_4k = {
+    .name = SUBGHZ_PROTOCOL_KINGGATES_STYLO_4K_NAME,
+    .type = SubGhzProtocolTypeDynamic,
+    .flag = SubGhzProtocolFlag_433 | SubGhzProtocolFlag_AM | SubGhzProtocolFlag_Decodable,
+
+    .decoder = &subghz_protocol_kinggates_stylo_4k_decoder,
+    .encoder = &subghz_protocol_kinggates_stylo_4k_encoder,
+};
+
+void* subghz_protocol_decoder_kinggates_stylo_4k_alloc(SubGhzEnvironment* environment) {
+    SubGhzProtocolDecoderKingGates_stylo_4k* instance =
+        malloc(sizeof(SubGhzProtocolDecoderKingGates_stylo_4k));
+    instance->base.protocol = &subghz_protocol_kinggates_stylo_4k;
+    instance->generic.protocol_name = instance->base.protocol->name;
+    instance->keystore = subghz_environment_get_keystore(environment);
+    return instance;
+}
+
+void subghz_protocol_decoder_kinggates_stylo_4k_free(void* context) {
+    furi_assert(context);
+    SubGhzProtocolDecoderKingGates_stylo_4k* instance = context;
+    free(instance);
+}
+
+void subghz_protocol_decoder_kinggates_stylo_4k_reset(void* context) {
+    furi_assert(context);
+    SubGhzProtocolDecoderKingGates_stylo_4k* instance = context;
+    instance->decoder.parser_step = KingGates_stylo_4kDecoderStepReset;
+}
+
+void subghz_protocol_decoder_kinggates_stylo_4k_feed(void* context, bool level, uint32_t duration) {
+    furi_assert(context);
+    SubGhzProtocolDecoderKingGates_stylo_4k* instance = context;
+
+    switch(instance->decoder.parser_step) {
+    case KingGates_stylo_4kDecoderStepReset:
+        if((level) && DURATION_DIFF(duration, subghz_protocol_kinggates_stylo_4k_const.te_short) <
+                          subghz_protocol_kinggates_stylo_4k_const.te_delta) {
+            instance->decoder.parser_step = KingGates_stylo_4kDecoderStepCheckPreambula;
+            instance->header_count++;
+        }
+        break;
+    case KingGates_stylo_4kDecoderStepCheckPreambula:
+        if((!level) &&
+           (DURATION_DIFF(duration, subghz_protocol_kinggates_stylo_4k_const.te_short) <
+            subghz_protocol_kinggates_stylo_4k_const.te_delta)) {
+            instance->decoder.parser_step = KingGates_stylo_4kDecoderStepReset;
+            break;
+        }
+        if((instance->header_count > 2) &&
+           (DURATION_DIFF(duration, subghz_protocol_kinggates_stylo_4k_const.te_long * 2) <
+            subghz_protocol_kinggates_stylo_4k_const.te_delta * 2)) {
+            // Found header
+            instance->decoder.parser_step = KingGates_stylo_4kDecoderStepCheckStartBit;
+        } else {
+            instance->decoder.parser_step = KingGates_stylo_4kDecoderStepReset;
+            instance->header_count = 0;
+        }
+        break;
+    case KingGates_stylo_4kDecoderStepCheckStartBit:
+        if((level) &&
+           DURATION_DIFF(duration, subghz_protocol_kinggates_stylo_4k_const.te_short * 2) <
+               subghz_protocol_kinggates_stylo_4k_const.te_delta * 2) {
+            instance->decoder.parser_step = KingGates_stylo_4kDecoderStepSaveDuration;
+            instance->decoder.decode_data = 0;
+            instance->data = 0;
+            instance->decoder.decode_count_bit = 0;
+            instance->header_count = 0;
+        }
+        break;
+    case KingGates_stylo_4kDecoderStepSaveDuration:
+        if(!level) {
+            if(duration >= ((uint32_t)subghz_protocol_kinggates_stylo_4k_const.te_long * 3)) {
+                if(instance->decoder.decode_count_bit ==
+                   subghz_protocol_kinggates_stylo_4k_const.min_count_bit_for_found) {
+                    instance->generic.data = instance->data;
+                    instance->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 = KingGates_stylo_4kDecoderStepReset;
+                instance->decoder.decode_data = 0;
+                instance->data = 0;
+                instance->decoder.decode_count_bit = 0;
+                instance->header_count = 0;
+                break;
+            } else {
+                instance->decoder.te_last = duration;
+                instance->decoder.parser_step = KingGates_stylo_4kDecoderStepCheckDuration;
+            }
+        } else {
+            instance->decoder.parser_step = KingGates_stylo_4kDecoderStepReset;
+            instance->header_count = 0;
+        }
+        break;
+    case KingGates_stylo_4kDecoderStepCheckDuration:
+        if(level) {
+            if((DURATION_DIFF(
+                    instance->decoder.te_last, subghz_protocol_kinggates_stylo_4k_const.te_short) <
+                subghz_protocol_kinggates_stylo_4k_const.te_delta) &&
+               (DURATION_DIFF(duration, subghz_protocol_kinggates_stylo_4k_const.te_long) <
+                subghz_protocol_kinggates_stylo_4k_const.te_delta * 2)) {
+                subghz_protocol_blocks_add_bit(&instance->decoder, 1);
+                instance->decoder.parser_step = KingGates_stylo_4kDecoderStepSaveDuration;
+            } else if(
+                (DURATION_DIFF(
+                     instance->decoder.te_last, subghz_protocol_kinggates_stylo_4k_const.te_long) <
+                 subghz_protocol_kinggates_stylo_4k_const.te_delta * 2) &&
+                (DURATION_DIFF(duration, subghz_protocol_kinggates_stylo_4k_const.te_short) <
+                 subghz_protocol_kinggates_stylo_4k_const.te_delta)) {
+                subghz_protocol_blocks_add_bit(&instance->decoder, 0);
+                instance->decoder.parser_step = KingGates_stylo_4kDecoderStepSaveDuration;
+            } else {
+                instance->decoder.parser_step = KingGates_stylo_4kDecoderStepReset;
+                instance->header_count = 0;
+            }
+            if(instance->decoder.decode_count_bit == 53) {
+                instance->data = instance->decoder.decode_data;
+                instance->decoder.decode_data = 0;
+            }
+        } else {
+            instance->decoder.parser_step = KingGates_stylo_4kDecoderStepReset;
+            instance->header_count = 0;
+        }
+        break;
+    }
+}
+
+/** 
+ * Analysis of received data
+ * @param instance Pointer to a SubGhzBlockGeneric* instance
+ * @param file_name Full path to rainbow table the file
+ */
+static void subghz_protocol_kinggates_stylo_4k_remote_controller(
+    SubGhzBlockGeneric* instance,
+    uint64_t data,
+    SubGhzKeystore* keystore) {
+    /**
+ *  9500us   12*(400/400)  2200/800|1-bit|0-bit|
+ *           _   _       _       __   ___     _ 
+ *  ________| |_| |_..._| |_____|  |_|   |___| |.....
+ * 
+ *  1-bit 400/1100 us
+ *  0-bit 1100/400 us
+ *  
+ *  The package consists of 89 bits of data, LSB first  
+ *  Data        - 1C9037F0C80000 CE280BA00
+ *    S[3]     S[2]   1 key    S[1]     S[0]    2 byte always 0   Hop[3]   Hop[2]  Hop[1]   Hop[0]    0
+ *  11100100 10000001 1 0111 11110000 11001000 00000000 00000000 11001110 00101000 00001011 10100000 0000
+ * 
+ *  Encryption  - keeloq Simple Learning
+ *                                         key C  S[3]  CNT 
+ *  Decrypt     - 0xEC270B9C        =>  0x  E  C   27   0B9C
+ * 
+ * 
+ * 
+*/
+
+    uint32_t hop = subghz_protocol_blocks_reverse_key(data >> 4, 32);
+    uint64_t fix = subghz_protocol_blocks_reverse_key(instance->data, 53);
+    bool ret = false;
+    uint32_t decrypt = 0;
+    instance->btn = (fix >> 17) & 0x0F;
+    instance->serial = ((fix >> 5) & 0xFFFF0000) | (fix & 0xFFFF);
+
+    for
+        M_EACH(manufacture_code, *subghz_keystore_get_data(keystore), SubGhzKeyArray_t) {
+            if(manufacture_code->type == KEELOQ_LEARNING_SIMPLE) {
+                decrypt = subghz_protocol_keeloq_common_decrypt(hop, manufacture_code->key);
+                if(((decrypt >> 28) == instance->btn) && (((decrypt >> 24) & 0x0F) == 0x0C) &&
+                   (((decrypt >> 16) & 0xFF) == (instance->serial & 0xFF))) {
+                    ret = true;
+                    break;
+                }
+            }
+        }
+    if(ret) {
+        instance->cnt = decrypt & 0xFFFF;
+    } else {
+        instance->btn = 0;
+        instance->serial = 0;
+        instance->cnt = 0;
+    }
+}
+
+uint8_t subghz_protocol_decoder_kinggates_stylo_4k_get_hash_data(void* context) {
+    furi_assert(context);
+    SubGhzProtocolDecoderKingGates_stylo_4k* instance = context;
+    return subghz_protocol_blocks_get_hash_data(
+        &instance->decoder, (instance->decoder.decode_count_bit / 8) + 1);
+}
+
+bool subghz_protocol_decoder_kinggates_stylo_4k_serialize(
+    void* context,
+    FlipperFormat* flipper_format,
+    SubGhzRadioPreset* preset) {
+    furi_assert(context);
+    SubGhzProtocolDecoderKingGates_stylo_4k* instance = context;
+    bool res = subghz_block_generic_serialize(&instance->generic, flipper_format, preset);
+
+    uint8_t key_data[sizeof(uint64_t)] = {0};
+    for(size_t i = 0; i < sizeof(uint64_t); i++) {
+        key_data[sizeof(uint64_t) - i - 1] = (instance->data >> (i * 8)) & 0xFF;
+    }
+
+    if(res && !flipper_format_write_hex(flipper_format, "Data", key_data, sizeof(uint64_t))) {
+        FURI_LOG_E(TAG, "Unable to add Data");
+        res = false;
+    }
+    return res;
+
+    return subghz_block_generic_serialize(&instance->generic, flipper_format, preset);
+}
+
+bool subghz_protocol_decoder_kinggates_stylo_4k_deserialize(
+    void* context,
+    FlipperFormat* flipper_format) {
+    furi_assert(context);
+    SubGhzProtocolDecoderKingGates_stylo_4k* instance = context;
+    bool ret = false;
+    do {
+        if(!subghz_block_generic_deserialize(&instance->generic, flipper_format)) {
+            break;
+        }
+        if(instance->generic.data_count_bit !=
+           subghz_protocol_kinggates_stylo_4k_const.min_count_bit_for_found) {
+            FURI_LOG_E(TAG, "Wrong number of bits in key");
+            break;
+        }
+        if(!flipper_format_rewind(flipper_format)) {
+            FURI_LOG_E(TAG, "Rewind error");
+            break;
+        }
+        uint8_t key_data[sizeof(uint64_t)] = {0};
+        if(!flipper_format_read_hex(flipper_format, "Data", key_data, sizeof(uint64_t))) {
+            FURI_LOG_E(TAG, "Missing Data");
+            break;
+        }
+        for(uint8_t i = 0; i < sizeof(uint64_t); i++) {
+            instance->data = instance->data << 8 | key_data[i];
+        }
+        ret = true;
+    } while(false);
+    return ret;
+}
+
+void subghz_protocol_decoder_kinggates_stylo_4k_get_string(void* context, FuriString* output) {
+    furi_assert(context);
+    SubGhzProtocolDecoderKingGates_stylo_4k* instance = context;
+    subghz_protocol_kinggates_stylo_4k_remote_controller(
+        &instance->generic, instance->data, instance->keystore);
+
+    furi_string_cat_printf(
+        output,
+        "%s\r\n"
+        "Key:0x%llX%07llX  %dbit\r\n"
+        "Sn:0x%08lX  Btn:0x%01X\r\n"
+        "Cnt:0x%04lX\r\n",
+        instance->generic.protocol_name,
+        instance->generic.data,
+        instance->data,
+        instance->generic.data_count_bit,
+        instance->generic.serial,
+        instance->generic.btn,
+        instance->generic.cnt);
+}

+ 74 - 0
lib/subghz/protocols/kinggates_stylo_4k.h

@@ -0,0 +1,74 @@
+#pragma once
+#include "base.h"
+
+#define SUBGHZ_PROTOCOL_KINGGATES_STYLO_4K_NAME "KingGates Stylo4k"
+
+typedef struct SubGhzProtocolDecoderKingGates_stylo_4k SubGhzProtocolDecoderKingGates_stylo_4k;
+typedef struct SubGhzProtocolEncoderKingGates_stylo_4k SubGhzProtocolEncoderKingGates_stylo_4k;
+
+extern const SubGhzProtocolDecoder subghz_protocol_kinggates_stylo_4k_decoder;
+extern const SubGhzProtocolEncoder subghz_protocol_kinggates_stylo_4k_encoder;
+extern const SubGhzProtocol subghz_protocol_kinggates_stylo_4k;
+
+/**
+ * Allocate SubGhzProtocolDecoderKingGates_stylo_4k.
+ * @param environment Pointer to a SubGhzEnvironment instance
+ * @return SubGhzProtocolDecoderKingGates_stylo_4k* pointer to a SubGhzProtocolDecoderKingGates_stylo_4k instance
+ */
+void* subghz_protocol_decoder_kinggates_stylo_4k_alloc(SubGhzEnvironment* environment);
+
+/**
+ * Free SubGhzProtocolDecoderKingGates_stylo_4k.
+ * @param context Pointer to a SubGhzProtocolDecoderKingGates_stylo_4k instance
+ */
+void subghz_protocol_decoder_kinggates_stylo_4k_free(void* context);
+
+/**
+ * Reset decoder SubGhzProtocolDecoderKingGates_stylo_4k.
+ * @param context Pointer to a SubGhzProtocolDecoderKingGates_stylo_4k instance
+ */
+void subghz_protocol_decoder_kinggates_stylo_4k_reset(void* context);
+
+/**
+ * Parse a raw sequence of levels and durations received from the air.
+ * @param context Pointer to a SubGhzProtocolDecoderKingGates_stylo_4k instance
+ * @param level Signal level true-high false-low
+ * @param duration Duration of this level in, us
+ */
+void subghz_protocol_decoder_kinggates_stylo_4k_feed(void* context, bool level, uint32_t duration);
+
+/**
+ * Getting the hash sum of the last randomly received parcel.
+ * @param context Pointer to a SubGhzProtocolDecoderKingGates_stylo_4k instance
+ * @return hash Hash sum
+ */
+uint8_t subghz_protocol_decoder_kinggates_stylo_4k_get_hash_data(void* context);
+
+/**
+ * Serialize data SubGhzProtocolDecoderKingGates_stylo_4k.
+ * @param context Pointer to a SubGhzProtocolDecoderKingGates_stylo_4k instance
+ * @param flipper_format Pointer to a FlipperFormat instance
+ * @param preset The modulation on which the signal was received, SubGhzRadioPreset
+ * @return true On success
+ */
+bool subghz_protocol_decoder_kinggates_stylo_4k_serialize(
+    void* context,
+    FlipperFormat* flipper_format,
+    SubGhzRadioPreset* preset);
+
+/**
+ * Deserialize data SubGhzProtocolDecoderKingGates_stylo_4k.
+ * @param context Pointer to a SubGhzProtocolDecoderKingGates_stylo_4k instance
+ * @param flipper_format Pointer to a FlipperFormat instance
+ * @return true On success
+ */
+bool subghz_protocol_decoder_kinggates_stylo_4k_deserialize(
+    void* context,
+    FlipperFormat* flipper_format);
+
+/**
+ * Getting a textual representation of the received data.
+ * @param context Pointer to a SubGhzProtocolDecoderKingGates_stylo_4k instance
+ * @param output Resulting text
+ */
+void subghz_protocol_decoder_kinggates_stylo_4k_get_string(void* context, FuriString* output);

+ 1 - 0
lib/subghz/protocols/protocol_items.c

@@ -41,6 +41,7 @@ const SubGhzProtocol* subghz_protocol_registry_items[] = {
     &subghz_protocol_linear_delta3,
     &subghz_protocol_linear_delta3,
     &subghz_protocol_dooya,
     &subghz_protocol_dooya,
     &subghz_protocol_alutech_at_4n,
     &subghz_protocol_alutech_at_4n,
+    &subghz_protocol_kinggates_stylo_4k,
 };
 };
 
 
 const SubGhzProtocolRegistry subghz_protocol_registry = {
 const SubGhzProtocolRegistry subghz_protocol_registry = {

+ 1 - 0
lib/subghz/protocols/protocol_items.h

@@ -41,5 +41,6 @@
 #include "holtek_ht12x.h"
 #include "holtek_ht12x.h"
 #include "dooya.h"
 #include "dooya.h"
 #include "alutech_at_4n.h"
 #include "alutech_at_4n.h"
+#include "kinggates_stylo_4k.h"
 
 
 extern const SubGhzProtocolRegistry subghz_protocol_registry;
 extern const SubGhzProtocolRegistry subghz_protocol_registry;

برخی فایل ها در این مقایسه diff نمایش داده نمی شوند زیرا تعداد فایل ها بسیار زیاد است