diff --git a/applications/debug/unit_tests/subghz/subghz_test.c b/applications/debug/unit_tests/subghz/subghz_test.c index 8f8acd38b..1fa9302c2 100644 --- a/applications/debug/unit_tests/subghz/subghz_test.c +++ b/applications/debug/unit_tests/subghz/subghz_test.c @@ -13,7 +13,7 @@ #define CAME_ATOMO_DIR_NAME EXT_PATH("subghz/assets/came_atomo") #define NICE_FLOR_S_DIR_NAME EXT_PATH("subghz/assets/nice_flor_s") #define TEST_RANDOM_DIR_NAME EXT_PATH("unit_tests/subghz/test_random_raw.sub") -#define TEST_RANDOM_COUNT_PARSE 248 +#define TEST_RANDOM_COUNT_PARSE 253 #define TEST_TIMEOUT 10000 static SubGhzEnvironment* environment_handler; @@ -593,6 +593,13 @@ MU_TEST(subghz_decoder_pocsag_test) { "Test decoder " SUBGHZ_PROTOCOL_POCSAG_NAME " error\r\n"); } +MU_TEST(subghz_decoder_smc5326_test) { + mu_assert( + subghz_decoder_test( + EXT_PATH("unit_tests/subghz/smc5326_raw.sub"), SUBGHZ_PROTOCOL_SMC5326_NAME), + "Test decoder " SUBGHZ_PROTOCOL_SMC5326_NAME " error\r\n"); +} + //test encoders MU_TEST(subghz_encoder_princeton_test) { mu_assert( @@ -720,6 +727,12 @@ MU_TEST(subghz_encoder_ansonic_test) { "Test encoder " SUBGHZ_PROTOCOL_ANSONIC_NAME " error\r\n"); } +MU_TEST(subghz_encoder_smc5326_test) { + mu_assert( + subghz_encoder_test(EXT_PATH("unit_tests/subghz/smc5326.sub")), + "Test encoder " SUBGHZ_PROTOCOL_SMC5326_NAME " error\r\n"); +} + MU_TEST(subghz_random_test) { mu_assert(subghz_decode_random_test(TEST_RANDOM_DIR_NAME), "Random test error\r\n"); } @@ -764,6 +777,7 @@ MU_TEST_SUITE(subghz) { MU_RUN_TEST(subghz_decoder_clemsa_test); MU_RUN_TEST(subghz_decoder_ansonic_test); MU_RUN_TEST(subghz_decoder_pocsag_test); + MU_RUN_TEST(subghz_decoder_smc5326_test); MU_RUN_TEST(subghz_encoder_princeton_test); MU_RUN_TEST(subghz_encoder_came_test); @@ -786,6 +800,7 @@ MU_TEST_SUITE(subghz) { MU_RUN_TEST(subghz_encoder_intertechno_v3_test); MU_RUN_TEST(subghz_encoder_clemsa_test); MU_RUN_TEST(subghz_encoder_ansonic_test); + MU_RUN_TEST(subghz_encoder_smc5326_test); MU_RUN_TEST(subghz_random_test); subghz_test_deinit(); diff --git a/assets/unit_tests/subghz/smc5326.sub b/assets/unit_tests/subghz/smc5326.sub new file mode 100644 index 000000000..eab7aac99 --- /dev/null +++ b/assets/unit_tests/subghz/smc5326.sub @@ -0,0 +1,8 @@ +Filetype: Flipper SubGhz Key File +Version: 1 +Frequency: 433920000 +Preset: FuriHalSubGhzPresetOok650Async +Protocol: SMC5326 +Bit: 25 +Key: 00 00 00 00 01 7D 55 80 +TE: 210 diff --git a/assets/unit_tests/subghz/smc5326_raw.sub b/assets/unit_tests/subghz/smc5326_raw.sub new file mode 100644 index 000000000..f2e3edbf0 --- /dev/null +++ b/assets/unit_tests/subghz/smc5326_raw.sub @@ -0,0 +1,7 @@ +Filetype: Flipper SubGhz RAW File +Version: 1 +Frequency: 433920000 +Preset: FuriHalSubGhzPresetOok650Async +Protocol: RAW +RAW_Data: 2442 -312 275 -972 949 -310 941 -322 923 -342 921 -352 923 -334 281 -954 945 -350 279 -958 907 -354 289 -980 909 -352 281 -962 907 -330 311 -964 913 -350 317 -930 933 -344 921 -352 893 -330 311 -954 943 -318 315 -958 909 -324 947 -7854 953 -322 289 -948 939 -354 927 -332 911 -324 943 -344 917 -318 317 -964 905 -344 303 -942 947 -312 319 -960 913 -348 281 -958 941 -322 295 -978 905 -350 279 -962 931 -328 947 -324 939 -346 267 -964 935 -348 283 -938 953 -318 931 -7868 935 -346 269 -968 953 -310 941 -322 921 -330 935 -342 931 -318 311 -962 939 -290 337 -950 909 -352 317 -924 943 -324 313 -938 941 -318 317 -932 939 -344 301 -938 933 -350 921 -322 959 -310 301 -942 933 -352 317 -926 957 -314 919 -7868 943 -314 317 -958 909 -322 951 -344 919 -352 921 -324 937 -326 281 -964 941 -318 317 -930 939 -344 301 -938 933 -352 281 -962 953 -314 317 -922 933 -330 315 -954 943 -318 921 -342 943 -320 291 -980 909 -354 281 -962 943 -296 967 -7836 943 -332 309 -950 935 -318 929 -340 943 -320 921 -344 921 -354 283 -960 943 -296 309 -964 945 -318 279 -964 941 -322 333 -944 939 -314 279 -992 903 -342 319 -932 933 -330 931 -340 929 -348 281 -964 935 -334 281 -970 927 -346 921 -7862 951 -314 319 -922 953 -320 923 -346 921 -320 965 -298 943 -324 313 -942 941 -320 317 -930 941 -344 303 -940 945 -312 321 -940 953 -314 303 -960 933 -348 287 -962 911 -352 917 -350 905 -324 333 -918 971 -322 317 -924 945 -324 937 -7872 919 -324 317 -942 941 -318 933 -330 943 -324 943 -310 951 -318 317 -930 939 -344 301 -938 933 -352 317 -926 953 -314 319 -924 939 -324 331 -950 907 -354 315 -926 945 -324 939 -312 953 -318 317 -930 937 -344 301 -940 947 -348 909 -7864 949 -310 319 -956 915 -350 919 -348 905 -322 963 -296 935 -348 317 -922 951 -322 295 -976 939 -314 281 -996 915 -326 307 -940 959 -310 301 -966 935 -346 285 -958 915 -348 921 -348 903 -354 303 -948 911 -350 315 -926 945 -324 941 -7874 943 -290 319 -942 973 -318 929 -314 937 -328 941 -324 939 -310 303 -962 933 -352 285 -962 949 -314 319 -924 951 -320 293 -948 941 -354 283 -962 943 -294 309 -966 943 -320 931 -328 943 -326 311 -940 939 -320 309 -958 933 -338 943 -7840 933 -352 277 -964 941 -322 923 -344 923 -350 931 -310 955 -320 291 -974 907 -350 281 -958 963 -298 313 -956 945 -314 311 -960 937 -312 311 -966 909 -324 319 -944 941 -354 929 -298 945 -324 315 -940 +RAW_Data: 943 -354 281 -964 905 -330 933 -7868 951 -324 315 -938 943 -354 893 -330 943 -324 943 -344 919 -318 317 -962 903 -344 301 -974 903 -350 317 -932 931 -342 269 -972 949 -346 285 -938 955 -310 301 -964 935 -348 921 -320 921 -344 301 -940 935 -350 317 -930 929 -318 937 -7872 939 -344 301 -940 947 -346 917 -322 921 -344 923 -352 927 -334 281 -970 925 -334 277 -982 943 -318 317 -932 931 -344 301 -936 935 -350 281 -960 957 -312 303 -960 935 -346 907 -322 929 -344 301 -942 935 -350 317 -924 955 -312 951 -7858 919 -342 309 -940 949 -348 909 -322 923 -344 923 -352 923 -336 317 -924 945 -312 311 -966 921 -340 317 -924 947 -350 281 -958 941 -322 291 -976 905 -350 279 -960 935 -342 943 -320 919 -330 311 -958 943 -320 315 -932 935 -344 919 -7866 957 -312 303 -964 917 -342 945 -320 923 -344 923 -354 929 -298 315 -956 941 -318 315 -960 911 -324 317 -942 939 -354 281 -964 941 -294 311 -968 943 -318 317 -932 937 -330 931 -350 919 -348 283 -960 917 -350 317 -922 939 -322 965 -7864 921 -324 329 -950 909 -354 923 -336 913 -322 947 -344 919 -354 281 -962 941 -294 311 -960 935 -354 281 -962 939 -294 311 -964 937 -354 281 -964 941 -296 309 -964 939 -318 931 -330 945 -324 315 -940 939 -354 281 -964 909 -344 921 -7862 963 -304 307 -976 933 -320 929 -328 941 -324 939 -348 915 -320 317 -930 939 -344 301 -940 965 -320 319 -926 953 -312 303 -960 933 -312 321 -960 913 -348 319 -924 943 -320 959 -310 921 -354 319 -924 943 -324 311 -938 941 -318 957 -7862 943 -318 317 -932 933 -344 925 -352 897 -332 943 -324 943 -346 267 -966 951 -310 321 -960 911 -350 281 -958 949 -320 291 -978 937 -316 279 -964 949 -326 309 -944 943 -314 959 -318 933 -336 317 -934 933 -344 267 -964 937 -350 905 -7896 943 -318 319 -926 955 -314 919 -350 935 -324 941 -294 967 -312 303 -962 933 -348 285 -960 917 -348 317 -922 941 -322 329 -950 907 -354 315 -926 943 -326 313 -940 941 -352 893 -332 949 -324 315 -938 941 -352 283 -962 943 -310 925 -7890 931 -344 269 -968 949 -310 943 -320 923 -350 937 -310 955 -318 317 -930 935 -344 301 -942 947 -346 285 -958 915 -346 317 -924 951 -322 295 -982 905 -352 317 -924 945 -324 941 -346 917 -318 317 -962 905 -330 311 -956 937 -352 897 -7878 939 -354 283 -960 941 -294 965 -312 953 -318 385 -201512 165 -198 265 -526 229 -298 755 -164 61687 -17310 131 -1056 99 -296 195 -296 65 -66 1617 diff --git a/assets/unit_tests/subghz/test_random_raw.sub b/assets/unit_tests/subghz/test_random_raw.sub index a65761b6b..3ca9e118f 100644 --- a/assets/unit_tests/subghz/test_random_raw.sub +++ b/assets/unit_tests/subghz/test_random_raw.sub @@ -194,3 +194,5 @@ RAW_Data: -728 53 -176 163 -2120 71 -1394 71 -488 107 -1404 221 -422 95 -96 201 RAW_Data: -1490 57 -374 83 -1644 115 -110 71 -478 71 -72 71 -1140 135 -2792 95 -2703 129 -168 85 -1668 133 -1521 53 -914 51 -4717 79 -1724 57 -172 115 -746 127 -394 83 -674 169 -564 71 -2250 119 -1603 51 -464 77 -2220 85 -566 55 -144 143 -116 115 -487 115 -282 129 -1690 111 -706 129 -1429 55 -223 113 -1228 53 -544 57 -114 57 -698 77 -2874 55 -232 113 -254 57 -1523 159 -72 101 -2285 51 -166 85 -315 57 -2125 53 -758 55 -478 107 -1725 53 -5851 83 -1616 101 -339 55 -230 109 -188 77 -652 51 -478 113 -3742 55 -230 57 -144 173 -754 143 -480 71 -2526 179 -4037 57 -1720 75 -432 133 -1464 165 -1268 215 -154 107 -398 87 -3083 85 -144 87 -512 71 -222 113 -487 85 -2428 81 -1648 119 -1226 95 -1213 103 -1275 57 -702 81 -1908 55 -542 55 -1838 109 -148 71 -1286 95 -3248 55 -639 71 -144 71 -598 119 -3930 171 -2344 55 -2623 87 -168 79 -2264 141 -1018 83 -344 115 -426 109 -518 85 -756 55 -2340 55 -1679 85 -200 85 -6170 51 -590 224 -1233 85 -260 107 -6039 57 -2192 113 -1496 109 -1146 55 -174 85 -848 75 -1242 111 -1068 85 -2111 81 -542 95 -1350 75 -144 95 -96 105 -362 105 -340 57 -864 115 -1568 73 -722 71 -2762 249 -382 113 -1979 75 -1233 143 -342 81 -3036 51 -226 87 -572 55 -282 57 -288 103 -3244 83 -242 99 -1748 55 -1206 172 -276 79 -2060 167 -904 123 -770 79 -1816 115 -202 113 -1526 137 -604 85 -2234 73 -300 113 -1504 95 -1114 55 -590 75 -410 103 -1314 83 -590 77 -3440 167 -3132 55 -224 75 -2107 57 -144 123 -842 155 -813 75 -602 71 -3652 141 -2380 57 -224 249 -164 189 -530 75 -493 51 -130 51 -126 95 -670 51 -340 81 -1084 97 -216 115 -1284 57 -1200 85 -310 55 -1002 71 -1455 79 -720 85 -1140 119 -288 95 -944 119 -554 53 -2450 73 -324 79 -836 105 -1087 73 -418 105 -528 139 -468 121 -582 167 -4205 71 -1858 183 -2318 143 -780 101 -98 187 -136 55 -2239 57 -434 103 -1946 113 -86 57 -428 53 -222 57 -86 143 -1036 107 -1232 77 -606 113 -1394 115 -86 57 -2204 75 -456 57 -1623 173 -2832 53 -2464 228 -609 141 -58 95 -847 77 -488 95 -734 51 -882 95 -4004 143 -1242 97 -322 77 -218 109 -2283 85 -116 85 -1281 55 -228 173 -820 77 -2298 71 -2057 115 -116 85 -760 143 -489 57 -2702 139 -1380 143 -583 143 -658 99 -918 141 -1033 55 -262 85 -1408 143 -1979 75 -872 57 -268 219 -594 107 -172 105 -222 71 -448 51 -806 101 -540 51 -108 115 -1558 147 -418 79 -206 71 RAW_Data: -514 107 -1090 125 -928 77 -172 153 -382 71 -742 73 -1060 133 -3547 71 -992 85 -890 119 -72 81 -1154 145 -122 51 -198 57 -1288 173 -2424 83 -260 55 -278 105 -926 55 -274 75 -1555 57 -538 137 -2713 71 -1082 57 -1110 57 -670 83 -494 105 -1504 77 -750 81 -1226 57 -2030 79 -258 57 -140 101 -858 57 -400 55 -2286 55 -3390 55 -542 103 -404 181 -316 57 -174 85 -3657 51 -162 81 -735 105 -518 87 -2452 51 -252 165 -1942 73 -74 73 -1386 113 -3530 181 -1312 57 -1262 115 -314 133 -2418 57 -4028 71 -182 121 -747 83 -2793 167 -686 85 -1814 171 -1984 109 -1592 101 -1250 57 -346 113 -1370 99 -2761 53 -1930 51 -280 57 -1590 71 -1105 79 -702 143 -1216 235 -3208 57 -1998 77 -859 119 -608 51 -1084 143 -709 81 -1286 85 -144 265 -1274 53 -2068 75 -3092 77 -232 55 -144 57 -1836 57 -258 115 -1507 85 -2022 109 -1121 71 -893 93 -696 119 -951 57 -710 75 -844 95 -396 109 -1323 83 -1878 85 -272 51 -1108 179 -584 147 -196 71 -4320 57 -904 81 -776 55 -1857 55 -712 111 -54 81 -1338 121 -510 57 -698 85 -396 55 -1239 57 -892 75 -146 71 -358 71 -278 113 -2876 105 -671 85 -316 269 -1362 81 -342 57 -2932 55 -1391 111 -202 57 -576 55 -910 113 -318 57 -586 55 -719 143 -256 113 -2136 81 -802 71 -1190 95 -144 71 -2156 71 -730 55 -2380 87 -977 83 -172 95 -1322 57 -1160 71 -144 147 -1028 83 -898 53 -878 87 -114 115 -1296 75 -476 171 -1442 53 -1705 103 -2318 57 -3989 73 -414 73 -1012 51 -1492 55 -1992 87 -2711 83 -484 77 -760 105 -1338 53 -56 81 -590 57 -316 169 -4225 105 -1172 109 -744 115 -394 51 -4057 107 -531 87 -734 83 -1522 55 -1895 55 -2121 83 -1574 265 -1181 83 -2434 71 -1888 105 -734 167 -2886 57 -114 135 -2099 79 -854 71 -3982 51 -440 229 -654 57 -2316 57 -266 97 -536 75 -2106 53 -937 149 -2691 85 -838 57 -506 51 -108 57 -1044 85 -760 57 -2398 73 -2428 75 -1016 81 -138 85 -88 57 -1134 235 -1612 113 -2849 71 -1517 77 -434 127 -192 57 -1992 95 -232 107 -3254 53 -1442 57 -86 107 -1024 95 -854 53 -534 85 -2618 81 -2344 115 -2866 111 -998 71 -3113 53 -1341 55 -1216 103 -246 85 -3100 260 -450 85 -3023 55 -372 167 -86 57 -1094 51 -1499 85 -1252 57 -546 51 -2099 191 -172 85 -1829 71 -1259 97 -1506 85 -1928 143 -900 143 -858 115 -942 81 -2027 53 -1292 115 -1010 119 -852 55 -342 51 -80 81 -470 101 -636 55 -1046 85 -576 81 -976 79 -188 95 -947 81 RAW_Data: -1480 55 -1430 55 -596 171 -1583 95 -884 51 -1116 121 -276 143 -2098 51 -1172 73 -1918 111 -112 51 -220 57 -230 163 -740 51 -1074 57 -1608 55 -3299 57 -2876 77 -1268 85 -771 79 -386 77 -1618 71 -1308 55 -863 121 -938 75 -110 83 -1176 187 -1807 57 -2894 55 -344 285 -994 55 -836 51 -963 85 -202 263 -686 55 -853 57 -144 115 -658 127 -955 57 -116 85 -944 111 -1891 57 -460 311 -1531 129 -146 121 -1301 71 -312 75 -600 77 -1760 71 -1264 85 -2345 51 -294 111 -772 51 -78 75 -292 71 -542 113 -690 85 -1164 79 -1368 57 -1284 53 -130 182 -240 53 -114 57 -287 143 -304 75 -754 169 -130 83 -54 85 -527 71 -1657 71 -462 383 -560 115 -638 131 -3943 285 -264 75 -168 85 -3999 83 -996 73 -644 71 -1205 71 -1108 85 -172 87 -1139 139 -518 167 -1278 123 -1125 75 +RAW_Data: 2442 -312 275 -972 949 -310 941 -322 923 -342 921 -352 923 -334 281 -954 945 -350 279 -958 907 -354 289 -980 909 -352 281 -962 907 -330 311 -964 913 -350 317 -930 933 -344 921 -352 893 -330 311 -954 943 -318 315 -958 909 -324 947 -7854 953 -322 289 -948 939 -354 927 -332 911 -324 943 -344 917 -318 317 -964 905 -344 303 -942 947 -312 319 -960 913 -348 281 -958 941 -322 295 -978 905 -350 279 -962 931 -328 947 -324 939 -346 267 -964 935 -348 283 -938 953 -318 931 -7868 935 -346 269 -968 953 -310 941 -322 921 -330 935 -342 931 -318 311 -962 939 -290 337 -950 909 -352 317 -924 943 -324 313 -938 941 -318 317 -932 939 -344 301 -938 933 -350 921 -322 959 -310 301 -942 933 -352 317 -926 957 -314 919 -7868 943 -314 317 -958 909 -322 951 -344 919 -352 921 -324 937 -326 281 -964 941 -318 317 -930 939 -344 301 -938 933 -352 281 -962 953 -314 317 -922 933 -330 315 -954 943 -318 921 -342 943 -320 291 -980 909 -354 281 -962 943 -296 967 -7836 943 -332 309 -950 935 -318 929 -340 943 -320 921 -344 921 -354 283 -960 943 -296 309 -964 945 -318 279 -964 941 -322 333 -944 939 -314 279 -992 903 -342 319 -932 933 -330 931 -340 929 -348 281 -964 935 -334 281 -970 927 -346 921 -7862 951 -314 319 -922 953 -320 923 -346 921 -320 965 -298 943 -324 313 -942 941 -320 317 -930 941 -344 303 -940 945 -312 321 -940 953 -314 303 -960 933 -348 287 -962 911 -352 917 -350 905 -324 333 -918 971 -322 317 -924 945 -324 937 -7872 919 -324 317 -942 941 -318 933 -330 943 -324 943 -310 951 -318 317 -930 939 -344 301 -938 933 -352 317 -926 953 -314 319 -924 939 -324 331 -950 907 -354 315 -926 945 -324 939 -312 953 -318 317 -930 937 -344 301 -940 947 -348 909 -7864 949 -310 319 -956 915 -350 919 -348 905 -322 963 -296 935 -348 317 -922 951 -322 295 -976 939 -314 281 -996 915 -326 307 -940 959 -310 301 -966 935 -346 285 -958 915 -348 921 -348 903 -354 303 -948 911 -350 315 -926 945 -324 941 -7874 943 -290 319 -942 973 -318 929 -314 937 -328 941 -324 939 -310 303 -962 933 -352 285 -962 949 -314 319 -924 951 -320 293 -948 941 -354 283 -962 943 -294 309 -966 943 -320 931 -328 943 -326 311 -940 939 -320 309 -958 933 -338 943 -7840 933 -352 277 -964 941 -322 923 -344 923 -350 931 -310 955 -320 291 -974 907 -350 281 -958 963 -298 313 -956 945 -314 311 -960 937 -312 311 -966 909 -324 319 -944 941 -354 929 -298 945 -324 315 -940 +RAW_Data: 943 -354 281 -964 905 -330 933 -7868 951 -324 315 -938 943 -354 893 -330 943 -324 943 -344 919 -318 317 -962 903 -344 301 -974 903 -350 317 -932 931 -342 269 -972 949 -346 285 -938 955 -310 301 -964 935 -348 921 -320 921 -344 301 -940 935 -350 317 -930 929 -318 937 -7872 939 -344 301 -940 947 -346 917 -322 921 -344 923 -352 927 -334 281 -970 925 -334 277 -982 943 -318 317 -932 931 -344 301 -936 935 -350 281 -960 957 -312 303 -960 935 -346 907 -322 929 -344 301 -942 935 -350 317 -924 955 -312 951 -7858 919 -342 309 -940 949 -348 909 -322 923 -344 923 -352 923 -336 317 -924 945 -312 311 -966 921 -340 317 -924 947 -350 281 -958 941 -322 291 -976 905 -350 279 -960 935 -342 943 -320 919 -330 311 -958 943 -320 315 -932 935 -344 919 -7866 957 -312 303 -964 917 -342 945 -320 923 -344 923 -354 929 -298 315 -956 941 -318 315 -960 911 -324 317 -942 939 -354 281 -964 941 -294 311 -968 943 -318 317 -932 937 -330 931 -350 919 -348 283 -960 917 -350 317 -922 939 -322 965 -7864 921 -324 329 -950 909 -354 923 -336 913 -322 947 -344 919 -354 281 -962 941 -294 311 -960 935 -354 281 -962 939 -294 311 -964 937 -354 281 -964 941 -296 309 -964 939 -318 931 -330 945 -324 315 -940 939 -354 281 -964 909 -344 921 -7862 963 -304 307 -976 933 -320 929 -328 941 -324 939 -348 915 -320 317 -930 939 -344 301 -940 965 -320 319 -926 953 -312 303 -960 933 -312 321 -960 913 -348 319 -924 943 -320 959 -310 921 -354 319 -924 943 -324 311 -938 941 -318 957 -7862 943 -318 317 -932 933 -344 925 -352 897 -332 943 -324 943 -346 267 -966 951 -310 321 -960 911 -350 281 -958 949 -320 291 -978 937 -316 279 -964 949 -326 309 -944 943 -314 959 -318 933 -336 317 -934 933 -344 267 -964 937 -350 905 -7896 943 -318 319 -926 955 -314 919 -350 935 -324 941 -294 967 -312 303 -962 933 -348 285 -960 917 -348 317 -922 941 -322 329 -950 907 -354 315 -926 943 -326 313 -940 941 -352 893 -332 949 -324 315 -938 941 -352 283 -962 943 -310 925 -7890 931 -344 269 -968 949 -310 943 -320 923 -350 937 -310 955 -318 317 -930 935 -344 301 -942 947 -346 285 -958 915 -346 317 -924 951 -322 295 -982 905 -352 317 -924 945 -324 941 -346 917 -318 317 -962 905 -330 311 -956 937 -352 897 -7878 939 -354 283 -960 941 -294 965 -312 953 -318 385 -201512 165 -198 265 -526 229 -298 755 -164 61687 -17310 131 -1056 99 -296 195 -296 65 -66 1617 diff --git a/lib/lfrfid/protocols/lfrfid_protocols.c b/lib/lfrfid/protocols/lfrfid_protocols.c index bd29bd8e0..2c1f0ad97 100644 --- a/lib/lfrfid/protocols/lfrfid_protocols.c +++ b/lib/lfrfid/protocols/lfrfid_protocols.c @@ -1,6 +1,7 @@ #include "lfrfid_protocols.h" #include "protocol_em4100.h" #include "protocol_h10301.h" +#include "protocol_idteck.h" #include "protocol_indala26.h" #include "protocol_io_prox_xsf.h" #include "protocol_awid.h" @@ -19,6 +20,7 @@ const ProtocolBase* lfrfid_protocols[] = { [LFRFIDProtocolEM4100] = &protocol_em4100, [LFRFIDProtocolH10301] = &protocol_h10301, + [LFRFIDProtocolIdteck] = &protocol_idteck, [LFRFIDProtocolIndala26] = &protocol_indala26, [LFRFIDProtocolIOProxXSF] = &protocol_io_prox_xsf, [LFRFIDProtocolAwid] = &protocol_awid, diff --git a/lib/lfrfid/protocols/lfrfid_protocols.h b/lib/lfrfid/protocols/lfrfid_protocols.h index 26065c9aa..848f003a3 100644 --- a/lib/lfrfid/protocols/lfrfid_protocols.h +++ b/lib/lfrfid/protocols/lfrfid_protocols.h @@ -10,6 +10,7 @@ typedef enum { typedef enum { LFRFIDProtocolEM4100, LFRFIDProtocolH10301, + LFRFIDProtocolIdteck, LFRFIDProtocolIndala26, LFRFIDProtocolIOProxXSF, LFRFIDProtocolAwid, diff --git a/lib/lfrfid/protocols/protocol_idteck.c b/lib/lfrfid/protocols/protocol_idteck.c new file mode 100644 index 000000000..033fcd28c --- /dev/null +++ b/lib/lfrfid/protocols/protocol_idteck.c @@ -0,0 +1,269 @@ +#include +#include +#include +#include "lfrfid_protocols.h" + +// Example: 4944544B 351FBE4B +// 01001001 01000100 01010100 01001011 00110101 00011111 10111110 01001011 +// 4 9 4 4 5 4 4 B 3 5 1 F B E 4 B +// 0100 1001 0100 0100 0101 0100 0100 1011 0011 0101 0001 1111 1011 1110 0100 1011 + +#define IDTECK_PREAMBLE_BIT_SIZE (32) +#define IDTECK_PREAMBLE_DATA_SIZE (8) + +#define IDTECK_ENCODED_BIT_SIZE (64) +#define IDTECK_ENCODED_DATA_SIZE (((IDTECK_ENCODED_BIT_SIZE) / 8) + IDTECK_PREAMBLE_DATA_SIZE) +#define IDTECK_ENCODED_DATA_LAST ((IDTECK_ENCODED_BIT_SIZE) / 8) + +#define IDTECK_DECODED_BIT_SIZE (64) +#define IDTECK_DECODED_DATA_SIZE (8) + +#define IDTECK_US_PER_BIT (255) +#define IDTECK_ENCODER_PULSES_PER_BIT (16) + +typedef struct { + uint8_t data_index; + uint8_t bit_clock_index; + bool last_bit; + bool current_polarity; + bool pulse_phase; +} ProtocolIdteckEncoder; + +typedef struct { + uint8_t encoded_data[IDTECK_ENCODED_DATA_SIZE]; + uint8_t negative_encoded_data[IDTECK_ENCODED_DATA_SIZE]; + uint8_t corrupted_encoded_data[IDTECK_ENCODED_DATA_SIZE]; + uint8_t corrupted_negative_encoded_data[IDTECK_ENCODED_DATA_SIZE]; + + uint8_t data[IDTECK_DECODED_DATA_SIZE]; + ProtocolIdteckEncoder encoder; +} ProtocolIdteck; + +ProtocolIdteck* protocol_idteck_alloc(void) { + ProtocolIdteck* protocol = malloc(sizeof(ProtocolIdteck)); + return protocol; +}; + +void protocol_idteck_free(ProtocolIdteck* protocol) { + free(protocol); +}; + +uint8_t* protocol_idteck_get_data(ProtocolIdteck* protocol) { + return protocol->data; +}; + +void protocol_idteck_decoder_start(ProtocolIdteck* protocol) { + memset(protocol->encoded_data, 0, IDTECK_ENCODED_DATA_SIZE); + memset(protocol->negative_encoded_data, 0, IDTECK_ENCODED_DATA_SIZE); + memset(protocol->corrupted_encoded_data, 0, IDTECK_ENCODED_DATA_SIZE); + memset(protocol->corrupted_negative_encoded_data, 0, IDTECK_ENCODED_DATA_SIZE); +}; + +static bool protocol_idteck_check_preamble(uint8_t* data, size_t bit_index) { + // Preamble 01001001 01000100 01010100 01001011 + if(*(uint32_t*)&data[bit_index / 8] != 0b01001011010101000100010001001001) return false; + return true; +} + +static bool protocol_idteck_can_be_decoded(uint8_t* data) { + if(!protocol_idteck_check_preamble(data, 0)) return false; + return true; +} + +static bool protocol_idteck_decoder_feed_internal(bool polarity, uint32_t time, uint8_t* data) { + time += (IDTECK_US_PER_BIT / 2); + + size_t bit_count = (time / IDTECK_US_PER_BIT); + bool result = false; + + if(bit_count < IDTECK_ENCODED_BIT_SIZE) { + for(size_t i = 0; i < bit_count; i++) { + bit_lib_push_bit(data, IDTECK_ENCODED_DATA_SIZE, polarity); + if(protocol_idteck_can_be_decoded(data)) { + result = true; + break; + } + } + } + + return result; +} + +static void protocol_idteck_decoder_save(uint8_t* data_to, const uint8_t* data_from) { + bit_lib_copy_bits(data_to, 0, 64, data_from, 0); +} + +bool protocol_idteck_decoder_feed(ProtocolIdteck* protocol, bool level, uint32_t duration) { + bool result = false; + + if(duration > (IDTECK_US_PER_BIT / 2)) { + if(protocol_idteck_decoder_feed_internal(level, duration, protocol->encoded_data)) { + protocol_idteck_decoder_save(protocol->data, protocol->encoded_data); + FURI_LOG_D("Idteck", "Positive"); + result = true; + return result; + } + + if(protocol_idteck_decoder_feed_internal( + !level, duration, protocol->negative_encoded_data)) { + protocol_idteck_decoder_save(protocol->data, protocol->negative_encoded_data); + FURI_LOG_D("Idteck", "Negative"); + result = true; + return result; + } + } + + if(duration > (IDTECK_US_PER_BIT / 4)) { + // Try to decode wrong phase synced data + if(level) { + duration += 120; + } else { + if(duration > 120) { + duration -= 120; + } + } + + if(protocol_idteck_decoder_feed_internal( + level, duration, protocol->corrupted_encoded_data)) { + protocol_idteck_decoder_save(protocol->data, protocol->corrupted_encoded_data); + FURI_LOG_D("Idteck", "Positive Corrupted"); + + result = true; + return result; + } + + if(protocol_idteck_decoder_feed_internal( + !level, duration, protocol->corrupted_negative_encoded_data)) { + protocol_idteck_decoder_save( + protocol->data, protocol->corrupted_negative_encoded_data); + FURI_LOG_D("Idteck", "Negative Corrupted"); + + result = true; + return result; + } + } + + return result; +}; + +bool protocol_idteck_encoder_start(ProtocolIdteck* protocol) { + memset(protocol->encoded_data, 0, IDTECK_ENCODED_DATA_SIZE); + *(uint32_t*)&protocol->encoded_data[0] = 0b01001011010101000100010001001001; + bit_lib_copy_bits(protocol->encoded_data, 32, 32, protocol->data, 32); + + protocol->encoder.last_bit = + bit_lib_get_bit(protocol->encoded_data, IDTECK_ENCODED_BIT_SIZE - 1); + protocol->encoder.data_index = 0; + protocol->encoder.current_polarity = true; + protocol->encoder.pulse_phase = true; + protocol->encoder.bit_clock_index = 0; + + return true; +}; + +LevelDuration protocol_idteck_encoder_yield(ProtocolIdteck* protocol) { + LevelDuration level_duration; + ProtocolIdteckEncoder* encoder = &protocol->encoder; + + if(encoder->pulse_phase) { + level_duration = level_duration_make(encoder->current_polarity, 1); + encoder->pulse_phase = false; + } else { + level_duration = level_duration_make(!encoder->current_polarity, 1); + encoder->pulse_phase = true; + + encoder->bit_clock_index++; + if(encoder->bit_clock_index >= IDTECK_ENCODER_PULSES_PER_BIT) { + encoder->bit_clock_index = 0; + + bool current_bit = bit_lib_get_bit(protocol->encoded_data, encoder->data_index); + + if(current_bit != encoder->last_bit) { + encoder->current_polarity = !encoder->current_polarity; + } + + encoder->last_bit = current_bit; + + bit_lib_increment_index(encoder->data_index, IDTECK_ENCODED_BIT_SIZE); + } + } + + return level_duration; +}; + +// factory code +static uint32_t get_fc(const uint8_t* data) { + uint32_t fc = 0; + fc = bit_lib_get_bits_32(data, 0, 32); + return fc; +} + +// card number +static uint32_t get_card(const uint8_t* data) { + uint32_t cn = 0; + cn = bit_lib_get_bits_32(data, 32, 32); + return cn; +} + +void protocol_idteck_render_data_internal(ProtocolIdteck* protocol, FuriString* result, bool brief) { + const uint32_t fc = get_fc(protocol->data); + const uint32_t card = get_card(protocol->data); + + if(brief) { + furi_string_printf(result, "FC: %08lX\r\nCard: %08lX", fc, card); + } else { + furi_string_printf( + result, + "FC: %08lX\r\n" + "Card: %08lX\r\n", + fc, + card); + } +} +void protocol_idteck_render_data(ProtocolIdteck* protocol, FuriString* result) { + protocol_idteck_render_data_internal(protocol, result, false); +} +void protocol_idteck_render_brief_data(ProtocolIdteck* protocol, FuriString* result) { + protocol_idteck_render_data_internal(protocol, result, true); +} + +bool protocol_idteck_write_data(ProtocolIdteck* protocol, void* data) { + LFRFIDWriteRequest* request = (LFRFIDWriteRequest*)data; + bool result = false; + + protocol_idteck_encoder_start(protocol); + + if(request->write_type == LFRFIDWriteTypeT5577) { + request->t5577.block[0] = LFRFID_T5577_BITRATE_RF_32 | LFRFID_T5577_MODULATION_PSK1 | + (2 << LFRFID_T5577_MAXBLOCK_SHIFT); + request->t5577.block[1] = bit_lib_get_bits_32(protocol->encoded_data, 0, 32); + request->t5577.block[2] = bit_lib_get_bits_32(protocol->encoded_data, 32, 32); + request->t5577.blocks_to_write = 3; + result = true; + } + return result; +}; + +const ProtocolBase protocol_idteck = { + .name = "Idteck", + .manufacturer = "IDTECK", + .data_size = IDTECK_DECODED_DATA_SIZE, + .features = LFRFIDFeaturePSK, + .validate_count = 6, + .alloc = (ProtocolAlloc)protocol_idteck_alloc, + .free = (ProtocolFree)protocol_idteck_free, + .get_data = (ProtocolGetData)protocol_idteck_get_data, + .decoder = + { + .start = (ProtocolDecoderStart)protocol_idteck_decoder_start, + .feed = (ProtocolDecoderFeed)protocol_idteck_decoder_feed, + }, + .encoder = + { + .start = (ProtocolEncoderStart)protocol_idteck_encoder_start, + .yield = (ProtocolEncoderYield)protocol_idteck_encoder_yield, + }, + .render_data = (ProtocolRenderData)protocol_idteck_render_data, + .render_brief_data = (ProtocolRenderData)protocol_idteck_render_brief_data, + .write_data = (ProtocolWriteData)protocol_idteck_write_data, +}; \ No newline at end of file diff --git a/lib/lfrfid/protocols/protocol_idteck.h b/lib/lfrfid/protocols/protocol_idteck.h new file mode 100644 index 000000000..b7a5ade47 --- /dev/null +++ b/lib/lfrfid/protocols/protocol_idteck.h @@ -0,0 +1,4 @@ +#pragma once +#include + +extern const ProtocolBase protocol_idteck; diff --git a/lib/subghz/protocols/protocol_items.c b/lib/subghz/protocols/protocol_items.c index 82616422b..dd9f40912 100644 --- a/lib/subghz/protocols/protocol_items.c +++ b/lib/subghz/protocols/protocol_items.c @@ -13,6 +13,7 @@ const SubGhzProtocol* subghz_protocol_registry_items[] = { &subghz_protocol_bett, &subghz_protocol_doitrand, &subghz_protocol_phoenix_v2, &subghz_protocol_honeywell_wdb, &subghz_protocol_magellan, &subghz_protocol_intertechno_v3, &subghz_protocol_clemsa, &subghz_protocol_ansonic, &subghz_protocol_pocsag, + &subghz_protocol_smc5326, }; const SubGhzProtocolRegistry subghz_protocol_registry = { diff --git a/lib/subghz/protocols/protocol_items.h b/lib/subghz/protocols/protocol_items.h index f5917e9bd..bfb03a777 100644 --- a/lib/subghz/protocols/protocol_items.h +++ b/lib/subghz/protocols/protocol_items.h @@ -37,6 +37,7 @@ #include "clemsa.h" #include "ansonic.h" #include "pocsag.h" +#include "smc5326.h" #ifdef __cplusplus extern "C" { diff --git a/lib/subghz/protocols/smc5326.c b/lib/subghz/protocols/smc5326.c new file mode 100644 index 000000000..889e39f05 --- /dev/null +++ b/lib/subghz/protocols/smc5326.c @@ -0,0 +1,387 @@ +#include "smc5326.h" + +#include "../blocks/const.h" +#include "../blocks/decoder.h" +#include "../blocks/encoder.h" +#include "../blocks/generic.h" +#include "../blocks/math.h" + +/* + * Help + * https://datasheetspdf.com/pdf-file/532079/Aslic/AX5326-4/1 + * + */ + +#define TAG "SubGhzProtocolSMC5326" + +#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 >> 0xE) & 0x3) == check_dip) ? '*' : '_'), \ + ((((dip >> 0xC) & 0x3) == check_dip) ? '*' : '_'), \ + ((((dip >> 0xA) & 0x3) == check_dip) ? '*' : '_'), \ + ((((dip >> 0x8) & 0x3) == check_dip) ? '*' : '_'), \ + ((((dip >> 0x6) & 0x3) == check_dip) ? '*' : '_'), \ + ((((dip >> 0x4) & 0x3) == check_dip) ? '*' : '_'), \ + ((((dip >> 0x2) & 0x3) == check_dip) ? '*' : '_'), \ + ((((dip >> 0x0) & 0x3) == check_dip) ? '*' : '_') + +static const SubGhzBlockConst subghz_protocol_smc5326_const = { + .te_short = 300, + .te_long = 900, + .te_delta = 200, + .min_count_bit_for_found = 25, +}; + +struct SubGhzProtocolDecoderSMC5326 { + SubGhzProtocolDecoderBase base; + + SubGhzBlockDecoder decoder; + SubGhzBlockGeneric generic; + + uint32_t te; + uint32_t last_data; +}; + +struct SubGhzProtocolEncoderSMC5326 { + SubGhzProtocolEncoderBase base; + + SubGhzProtocolBlockEncoder encoder; + SubGhzBlockGeneric generic; + + uint32_t te; +}; + +typedef enum { + SMC5326DecoderStepReset = 0, + SMC5326DecoderStepSaveDuration, + SMC5326DecoderStepCheckDuration, +} SMC5326DecoderStep; + +const SubGhzProtocolDecoder subghz_protocol_smc5326_decoder = { + .alloc = subghz_protocol_decoder_smc5326_alloc, + .free = subghz_protocol_decoder_smc5326_free, + + .feed = subghz_protocol_decoder_smc5326_feed, + .reset = subghz_protocol_decoder_smc5326_reset, + + .get_hash_data = subghz_protocol_decoder_smc5326_get_hash_data, + .serialize = subghz_protocol_decoder_smc5326_serialize, + .deserialize = subghz_protocol_decoder_smc5326_deserialize, + .get_string = subghz_protocol_decoder_smc5326_get_string, +}; + +const SubGhzProtocolEncoder subghz_protocol_smc5326_encoder = { + .alloc = subghz_protocol_encoder_smc5326_alloc, + .free = subghz_protocol_encoder_smc5326_free, + + .deserialize = subghz_protocol_encoder_smc5326_deserialize, + .stop = subghz_protocol_encoder_smc5326_stop, + .yield = subghz_protocol_encoder_smc5326_yield, +}; + +const SubGhzProtocol subghz_protocol_smc5326 = { + .name = SUBGHZ_PROTOCOL_SMC5326_NAME, + .type = SubGhzProtocolTypeStatic, + .flag = SubGhzProtocolFlag_433 | SubGhzProtocolFlag_868 | SubGhzProtocolFlag_315 | + SubGhzProtocolFlag_AM | SubGhzProtocolFlag_Decodable | SubGhzProtocolFlag_Load | + SubGhzProtocolFlag_Save | SubGhzProtocolFlag_Send, + + .decoder = &subghz_protocol_smc5326_decoder, + .encoder = &subghz_protocol_smc5326_encoder, +}; + +void* subghz_protocol_encoder_smc5326_alloc(SubGhzEnvironment* environment) { + UNUSED(environment); + SubGhzProtocolEncoderSMC5326* instance = malloc(sizeof(SubGhzProtocolEncoderSMC5326)); + + instance->base.protocol = &subghz_protocol_smc5326; + instance->generic.protocol_name = instance->base.protocol->name; + + instance->encoder.repeat = 10; + instance->encoder.size_upload = 128; + instance->encoder.upload = malloc(instance->encoder.size_upload * sizeof(LevelDuration)); + instance->encoder.is_running = false; + return instance; +} + +void subghz_protocol_encoder_smc5326_free(void* context) { + furi_assert(context); + SubGhzProtocolEncoderSMC5326* instance = context; + free(instance->encoder.upload); + free(instance); +} + +/** + * Generating an upload from data. + * @param instance Pointer to a SubGhzProtocolEncoderSMC5326 instance + * @return true On success + */ +static bool subghz_protocol_encoder_smc5326_get_upload(SubGhzProtocolEncoderSMC5326* instance) { + furi_assert(instance); + + size_t index = 0; + size_t size_upload = (instance->generic.data_count_bit * 2) + 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 > 0; i--) { + if(bit_read(instance->generic.data, i - 1)) { + //send bit 1 + instance->encoder.upload[index++] = + level_duration_make(true, (uint32_t)instance->te * 3); + instance->encoder.upload[index++] = level_duration_make(false, (uint32_t)instance->te); + } else { + //send bit 0 + instance->encoder.upload[index++] = level_duration_make(true, (uint32_t)instance->te); + instance->encoder.upload[index++] = + level_duration_make(false, (uint32_t)instance->te * 3); + } + } + + //Send Stop bit + instance->encoder.upload[index++] = level_duration_make(true, (uint32_t)instance->te); + //Send PT_GUARD + instance->encoder.upload[index++] = level_duration_make(false, (uint32_t)instance->te * 25); + + return true; +} + +bool subghz_protocol_encoder_smc5326_deserialize(void* context, FlipperFormat* flipper_format) { + furi_assert(context); + SubGhzProtocolEncoderSMC5326* instance = context; + bool res = false; + do { + if(!subghz_block_generic_deserialize(&instance->generic, flipper_format)) { + FURI_LOG_E(TAG, "Deserialize error"); + break; + } + if(!flipper_format_rewind(flipper_format)) { + FURI_LOG_E(TAG, "Rewind error"); + break; + } + if(!flipper_format_read_uint32(flipper_format, "TE", (uint32_t*)&instance->te, 1)) { + FURI_LOG_E(TAG, "Missing TE"); + break; + } + if(instance->generic.data_count_bit != + subghz_protocol_smc5326_const.min_count_bit_for_found) { + FURI_LOG_E(TAG, "Wrong number of bits in key"); + break; + } + //optional parameter parameter + flipper_format_read_uint32( + flipper_format, "Repeat", (uint32_t*)&instance->encoder.repeat, 1); + + if(!subghz_protocol_encoder_smc5326_get_upload(instance)) break; + instance->encoder.is_running = true; + + res = true; + } while(false); + + return res; +} + +void subghz_protocol_encoder_smc5326_stop(void* context) { + SubGhzProtocolEncoderSMC5326* instance = context; + instance->encoder.is_running = false; +} + +LevelDuration subghz_protocol_encoder_smc5326_yield(void* context) { + SubGhzProtocolEncoderSMC5326* 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_smc5326_alloc(SubGhzEnvironment* environment) { + UNUSED(environment); + SubGhzProtocolDecoderSMC5326* instance = malloc(sizeof(SubGhzProtocolDecoderSMC5326)); + instance->base.protocol = &subghz_protocol_smc5326; + instance->generic.protocol_name = instance->base.protocol->name; + return instance; +} + +void subghz_protocol_decoder_smc5326_free(void* context) { + furi_assert(context); + SubGhzProtocolDecoderSMC5326* instance = context; + free(instance); +} + +void subghz_protocol_decoder_smc5326_reset(void* context) { + furi_assert(context); + SubGhzProtocolDecoderSMC5326* instance = context; + instance->decoder.parser_step = SMC5326DecoderStepReset; + instance->last_data = 0; +} + +void subghz_protocol_decoder_smc5326_feed(void* context, bool level, uint32_t duration) { + furi_assert(context); + SubGhzProtocolDecoderSMC5326* instance = context; + + switch(instance->decoder.parser_step) { + case SMC5326DecoderStepReset: + if((!level) && (DURATION_DIFF(duration, subghz_protocol_smc5326_const.te_short * 24) < + subghz_protocol_smc5326_const.te_delta * 12)) { + //Found Preambula + instance->decoder.parser_step = SMC5326DecoderStepSaveDuration; + instance->decoder.decode_data = 0; + instance->decoder.decode_count_bit = 0; + instance->te = 0; + } + break; + case SMC5326DecoderStepSaveDuration: + //save duration + if(level) { + instance->decoder.te_last = duration; + instance->te += duration; + instance->decoder.parser_step = SMC5326DecoderStepCheckDuration; + } + break; + case SMC5326DecoderStepCheckDuration: + if(!level) { + if(duration >= ((uint32_t)subghz_protocol_smc5326_const.te_long * 2)) { + instance->decoder.parser_step = SMC5326DecoderStepSaveDuration; + if(instance->decoder.decode_count_bit == + subghz_protocol_smc5326_const.min_count_bit_for_found) { + if((instance->last_data == instance->decoder.decode_data) && + instance->last_data) { + instance->te /= (instance->decoder.decode_count_bit * 4 + 1); + + 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->last_data = instance->decoder.decode_data; + } + instance->decoder.decode_data = 0; + instance->decoder.decode_count_bit = 0; + instance->te = 0; + break; + } + + instance->te += duration; + + if((DURATION_DIFF(instance->decoder.te_last, subghz_protocol_smc5326_const.te_short) < + subghz_protocol_smc5326_const.te_delta) && + (DURATION_DIFF(duration, subghz_protocol_smc5326_const.te_long) < + subghz_protocol_smc5326_const.te_delta * 3)) { + subghz_protocol_blocks_add_bit(&instance->decoder, 0); + instance->decoder.parser_step = SMC5326DecoderStepSaveDuration; + } else if( + (DURATION_DIFF(instance->decoder.te_last, subghz_protocol_smc5326_const.te_long) < + subghz_protocol_smc5326_const.te_delta * 3) && + (DURATION_DIFF(duration, subghz_protocol_smc5326_const.te_short) < + subghz_protocol_smc5326_const.te_delta)) { + subghz_protocol_blocks_add_bit(&instance->decoder, 1); + instance->decoder.parser_step = SMC5326DecoderStepSaveDuration; + } else { + instance->decoder.parser_step = SMC5326DecoderStepReset; + } + } else { + instance->decoder.parser_step = SMC5326DecoderStepReset; + } + break; + } +} + +uint8_t subghz_protocol_decoder_smc5326_get_hash_data(void* context) { + furi_assert(context); + SubGhzProtocolDecoderSMC5326* instance = context; + return subghz_protocol_blocks_get_hash_data( + &instance->decoder, (instance->decoder.decode_count_bit / 8) + 1); +} + +bool subghz_protocol_decoder_smc5326_serialize( + void* context, + FlipperFormat* flipper_format, + SubGhzRadioPreset* preset) { + furi_assert(context); + SubGhzProtocolDecoderSMC5326* instance = context; + bool res = subghz_block_generic_serialize(&instance->generic, flipper_format, preset); + if(res && !flipper_format_write_uint32(flipper_format, "TE", &instance->te, 1)) { + FURI_LOG_E(TAG, "Unable to add TE"); + res = false; + } + return res; +} + +bool subghz_protocol_decoder_smc5326_deserialize(void* context, FlipperFormat* flipper_format) { + furi_assert(context); + SubGhzProtocolDecoderSMC5326* instance = context; + bool res = false; + do { + if(!subghz_block_generic_deserialize(&instance->generic, flipper_format)) { + FURI_LOG_E(TAG, "Deserialize error"); + break; + } + if(instance->generic.data_count_bit != + subghz_protocol_smc5326_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; + } + if(!flipper_format_read_uint32(flipper_format, "TE", (uint32_t*)&instance->te, 1)) { + FURI_LOG_E(TAG, "Missing TE"); + break; + } + res = true; + } while(false); + + return res; +} + +static void subghz_protocol_smc5326_get_event_serialize(uint8_t event, FuriString* output) { + furi_string_cat_printf( + output, + "%s%s%s%s\r\n", + (((event >> 6) & 0x3) == 0x3 ? "B1 " : ""), + (((event >> 4) & 0x3) == 0x3 ? "B2 " : ""), + (((event >> 2) & 0x3) == 0x3 ? "B3 " : ""), + (((event >> 0) & 0x3) == 0x3 ? "B4 " : "")); +} + +void subghz_protocol_decoder_smc5326_get_string(void* context, FuriString* output) { + furi_assert(context); + SubGhzProtocolDecoderSMC5326* instance = context; + uint32_t data = (uint32_t)((instance->generic.data >> 9) & 0xFFFF); + + furi_string_cat_printf( + output, + "%s %dbit\r\n" + "Key:%07lX Te:%ldus\r\n" + " +: " DIP_PATTERN "\r\n" + " o: " DIP_PATTERN " ", + instance->generic.protocol_name, + instance->generic.data_count_bit, + (uint32_t)(instance->generic.data & 0x1FFFFFF), + instance->te, + SHOW_DIP_P(data, DIP_P), + SHOW_DIP_P(data, DIP_O)); + subghz_protocol_smc5326_get_event_serialize(instance->generic.data >> 1, output); + furi_string_cat_printf(output, " -: " DIP_PATTERN "\r\n", SHOW_DIP_P(data, DIP_N)); +} diff --git a/lib/subghz/protocols/smc5326.h b/lib/subghz/protocols/smc5326.h new file mode 100644 index 000000000..ddc954bd5 --- /dev/null +++ b/lib/subghz/protocols/smc5326.h @@ -0,0 +1,107 @@ +#pragma once + +#include "base.h" + +#define SUBGHZ_PROTOCOL_SMC5326_NAME "SMC5326" + +typedef struct SubGhzProtocolDecoderSMC5326 SubGhzProtocolDecoderSMC5326; +typedef struct SubGhzProtocolEncoderSMC5326 SubGhzProtocolEncoderSMC5326; + +extern const SubGhzProtocolDecoder subghz_protocol_smc5326_decoder; +extern const SubGhzProtocolEncoder subghz_protocol_smc5326_encoder; +extern const SubGhzProtocol subghz_protocol_smc5326; + +/** + * Allocate SubGhzProtocolEncoderSMC5326. + * @param environment Pointer to a SubGhzEnvironment instance + * @return SubGhzProtocolEncoderSMC5326* pointer to a SubGhzProtocolEncoderSMC5326 instance + */ +void* subghz_protocol_encoder_smc5326_alloc(SubGhzEnvironment* environment); + +/** + * Free SubGhzProtocolEncoderSMC5326. + * @param context Pointer to a SubGhzProtocolEncoderSMC5326 instance + */ +void subghz_protocol_encoder_smc5326_free(void* context); + +/** + * Deserialize and generating an upload to send. + * @param context Pointer to a SubGhzProtocolEncoderSMC5326 instance + * @param flipper_format Pointer to a FlipperFormat instance + * @return true On success + */ +bool subghz_protocol_encoder_smc5326_deserialize(void* context, FlipperFormat* flipper_format); + +/** + * Forced transmission stop. + * @param context Pointer to a SubGhzProtocolEncoderSMC5326 instance + */ +void subghz_protocol_encoder_smc5326_stop(void* context); + +/** + * Getting the level and duration of the upload to be loaded into DMA. + * @param context Pointer to a SubGhzProtocolEncoderSMC5326 instance + * @return LevelDuration + */ +LevelDuration subghz_protocol_encoder_smc5326_yield(void* context); + +/** + * Allocate SubGhzProtocolDecoderSMC5326. + * @param environment Pointer to a SubGhzEnvironment instance + * @return SubGhzProtocolDecoderSMC5326* pointer to a SubGhzProtocolDecoderSMC5326 instance + */ +void* subghz_protocol_decoder_smc5326_alloc(SubGhzEnvironment* environment); + +/** + * Free SubGhzProtocolDecoderSMC5326. + * @param context Pointer to a SubGhzProtocolDecoderSMC5326 instance + */ +void subghz_protocol_decoder_smc5326_free(void* context); + +/** + * Reset decoder SubGhzProtocolDecoderSMC5326. + * @param context Pointer to a SubGhzProtocolDecoderSMC5326 instance + */ +void subghz_protocol_decoder_smc5326_reset(void* context); + +/** + * Parse a raw sequence of levels and durations received from the air. + * @param context Pointer to a SubGhzProtocolDecoderSMC5326 instance + * @param level Signal level true-high false-low + * @param duration Duration of this level in, us + */ +void subghz_protocol_decoder_smc5326_feed(void* context, bool level, uint32_t duration); + +/** + * Getting the hash sum of the last randomly received parcel. + * @param context Pointer to a SubGhzProtocolDecoderSMC5326 instance + * @return hash Hash sum + */ +uint8_t subghz_protocol_decoder_smc5326_get_hash_data(void* context); + +/** + * Serialize data SubGhzProtocolDecoderSMC5326. + * @param context Pointer to a SubGhzProtocolDecoderSMC5326 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_smc5326_serialize( + void* context, + FlipperFormat* flipper_format, + SubGhzRadioPreset* preset); + +/** + * Deserialize data SubGhzProtocolDecoderSMC5326. + * @param context Pointer to a SubGhzProtocolDecoderSMC5326 instance + * @param flipper_format Pointer to a FlipperFormat instance + * @return true On success + */ +bool subghz_protocol_decoder_smc5326_deserialize(void* context, FlipperFormat* flipper_format); + +/** + * Getting a textual representation of the received data. + * @param context Pointer to a SubGhzProtocolDecoderSMC5326 instance + * @param output Resulting text + */ +void subghz_protocol_decoder_smc5326_get_string(void* context, FuriString* output);