Procházet zdrojové kódy

SubGhz: Unit_test and bugfixes (#1104)

* SubGhz: CLI add "subghz decode_raw"
* SubGhz: unit_test
* SubGhz: add Hormann_hsm_raw unit_test
* SubGhz: fix duration raw
* Unit_test: fix total test timer
* SubGHz: fix name display scher_khan
* SubGhz: fix deviation protocol kia
* SubGhz: return max name length to previous value
* FuriHal: correctly handle mute in speaker
* UnitTests: fix grammar in subghz

Co-authored-by: Aleksandr Kutuzov <alleteam@gmail.com>
Skorpionm před 3 roky
rodič
revize
8cc3fd579c
57 změnil soubory, kde provedl 698 přidání a 39 odebrání
  1. 112 0
      applications/subghz/subghz_cli.c
  2. 1 1
      applications/subghz/subghz_i.h
  3. 0 0
      applications/unit_tests/flipper_format/flipper_format_string_test.c
  4. 0 0
      applications/unit_tests/flipper_format/flipper_format_test.c
  5. 0 0
      applications/unit_tests/furi_memmgr_test.c
  6. 0 0
      applications/unit_tests/furi_pubsub_test.c
  7. 0 0
      applications/unit_tests/furi_record_test.c
  8. 0 0
      applications/unit_tests/furi_valuemutex_test.c
  9. 0 0
      applications/unit_tests/infrared_decoder_encoder/infrared_decoder_encoder_test.c
  10. 0 0
      applications/unit_tests/infrared_decoder_encoder/test_data/infrared_nec_test_data.srcdata
  11. 0 0
      applications/unit_tests/infrared_decoder_encoder/test_data/infrared_necext_test_data.srcdata
  12. 0 0
      applications/unit_tests/infrared_decoder_encoder/test_data/infrared_rc5_test_data.srcdata
  13. 0 0
      applications/unit_tests/infrared_decoder_encoder/test_data/infrared_rc6_test_data.srcdata
  14. 0 0
      applications/unit_tests/infrared_decoder_encoder/test_data/infrared_samsung_test_data.srcdata
  15. 0 0
      applications/unit_tests/infrared_decoder_encoder/test_data/infrared_sirc_test_data.srcdata
  16. 0 0
      applications/unit_tests/minunit.h
  17. 0 0
      applications/unit_tests/minunit_test.c
  18. 0 0
      applications/unit_tests/minunit_vars.h
  19. 0 0
      applications/unit_tests/minunit_vars_ex.h
  20. 0 0
      applications/unit_tests/rpc/rpc_test.c
  21. 0 0
      applications/unit_tests/storage/storage_test.c
  22. 0 0
      applications/unit_tests/stream/stream_test.c
  23. 404 0
      applications/unit_tests/subghz/subghz_test.c
  24. 6 3
      applications/unit_tests/test_index.c
  25. 7 0
      assets/unit_tests/subghz/came.sub
  26. 5 0
      assets/unit_tests/subghz/came_atomo_raw.sub
  27. 5 0
      assets/unit_tests/subghz/came_raw.sub
  28. 7 0
      assets/unit_tests/subghz/came_twee.sub
  29. 5 0
      assets/unit_tests/subghz/came_twee_raw.sub
  30. 5 0
      assets/unit_tests/subghz/cenmax_raw.sub
  31. 7 0
      assets/unit_tests/subghz/doorhan.sub
  32. 5 0
      assets/unit_tests/subghz/doorhan_raw.sub
  33. 5 0
      assets/unit_tests/subghz/faac_slh_raw.sub
  34. 7 0
      assets/unit_tests/subghz/gate_tx.sub
  35. 5 0
      assets/unit_tests/subghz/gate_tx_raw.sub
  36. 5 0
      assets/unit_tests/subghz/hormann_hsm_raw.sub
  37. 5 0
      assets/unit_tests/subghz/ido_117_111_raw.sub
  38. 5 0
      assets/unit_tests/subghz/kia_seed_raw.sub
  39. 5 0
      assets/unit_tests/subghz/nero_radio_raw.sub
  40. 5 0
      assets/unit_tests/subghz/nero_sketch_raw.sub
  41. 7 0
      assets/unit_tests/subghz/nice_flo.sub
  42. 5 0
      assets/unit_tests/subghz/nice_flo_raw.sub
  43. 5 0
      assets/unit_tests/subghz/nice_flor_s_raw.sub
  44. 8 0
      assets/unit_tests/subghz/princeton.sub
  45. 5 0
      assets/unit_tests/subghz/princeton_raw.sub
  46. 5 0
      assets/unit_tests/subghz/scher_khan_magic_code.sub
  47. 5 0
      assets/unit_tests/subghz/somfy_keytis_raw.sub
  48. 5 0
      assets/unit_tests/subghz/somfy_telis_raw.sub
  49. 5 0
      assets/unit_tests/subghz/test_random_raw.sub
  50. 4 0
      firmware/targets/f7/furi_hal/furi_hal_speaker.c
  51. 3 3
      firmware/targets/f7/furi_hal/furi_hal_subghz.c
  52. 1 1
      firmware/targets/furi_hal_include/furi_hal_subghz.h
  53. 5 5
      lib/subghz/protocols/kia.c
  54. 1 3
      lib/subghz/protocols/raw.c
  55. 0 20
      lib/subghz/protocols/registry.c
  56. 20 0
      lib/subghz/protocols/registry.h
  57. 3 3
      lib/subghz/protocols/scher_khan.c

+ 112 - 0
applications/subghz/subghz_cli.c

@@ -9,6 +9,7 @@
 
 #include <lib/subghz/receiver.h>
 #include <lib/subghz/transmitter.h>
+#include <lib/subghz/subghz_file_encoder_worker.h>
 
 #include "helpers/subghz_chat.h"
 
@@ -294,6 +295,110 @@ void subghz_cli_command_rx(Cli* cli, string_t args, void* context) {
     free(instance);
 }
 
+void subghz_cli_command_decode_raw(Cli* cli, string_t args, void* context) {
+    string_t file_name;
+    string_init(file_name);
+    string_set(file_name, "/any/subghz/test.sub");
+
+    Storage* storage = furi_record_open("storage");
+    FlipperFormat* fff_data_file = flipper_format_file_alloc(storage);
+    string_t temp_str;
+    string_init(temp_str);
+    uint32_t temp_data32;
+    bool check_file = false;
+
+    do {
+        if(string_size(args)) {
+            if(!args_read_string_and_trim(args, file_name)) {
+                cli_print_usage(
+                    "subghz decode_raw", "<file_name: path_RAW_file>", string_get_cstr(args));
+                break;
+            }
+        }
+
+        if(!flipper_format_file_open_existing(fff_data_file, string_get_cstr(file_name))) {
+            printf(
+                "subghz decode_raw \033[0;31mError open file\033[0m %s\r\n",
+                string_get_cstr(file_name));
+            break;
+        }
+
+        if(!flipper_format_read_header(fff_data_file, temp_str, &temp_data32)) {
+            printf("subghz decode_raw \033[0;31mMissing or incorrect header\033[0m\r\n");
+            break;
+        }
+
+        if(!strcmp(string_get_cstr(temp_str), SUBGHZ_RAW_FILE_TYPE) &&
+           temp_data32 == SUBGHZ_KEY_FILE_VERSION) {
+        } else {
+            printf("subghz decode_raw \033[0;31mType or version mismatch\033[0m\r\n");
+            break;
+        }
+
+        check_file = true;
+    } while(false);
+
+    string_clear(temp_str);
+    flipper_format_free(fff_data_file);
+    furi_record_close("storage");
+
+    if(check_file) {
+        // Allocate context
+        SubGhzCliCommandRx* instance = malloc(sizeof(SubGhzCliCommandRx));
+
+        SubGhzEnvironment* environment = subghz_environment_alloc();
+        if(subghz_environment_load_keystore(environment, "/ext/subghz/assets/keeloq_mfcodes")) {
+            printf("SubGhz test: Load_keystore \033[0;32mOK\033[0m\r\n");
+        } else {
+            printf("SubGhz test: Load_keystore \033[0;31mERROR\033[0m\r\n");
+        }
+        subghz_environment_set_came_atomo_rainbow_table_file_name(
+            environment, "/ext/subghz/assets/came_atomo");
+        subghz_environment_set_nice_flor_s_rainbow_table_file_name(
+            environment, "/ext/subghz/assets/nice_flor_s");
+
+        SubGhzReceiver* receiver = subghz_receiver_alloc_init(environment);
+        subghz_receiver_set_filter(receiver, SubGhzProtocolFlag_Decodable);
+        subghz_receiver_set_rx_callback(receiver, subghz_cli_command_rx_callback, instance);
+
+        SubGhzFileEncoderWorker* file_worker_encoder = subghz_file_encoder_worker_alloc();
+        if(subghz_file_encoder_worker_start(file_worker_encoder, string_get_cstr(file_name))) {
+            //the worker needs a file in order to open and read part of the file
+            osDelay(100);
+        }
+
+        printf(
+            "Listening at \033[0;33m%s\033[0m.\r\n\r\nPress CTRL+C to stop\r\n\r\n",
+            string_get_cstr(file_name));
+
+        LevelDuration level_duration;
+        while(!cli_cmd_interrupt_received(cli)) {
+            furi_hal_delay_us(500); //you need to have time to read from the file from the SD card
+            level_duration = subghz_file_encoder_worker_get_level_duration(file_worker_encoder);
+            if(!level_duration_is_reset(level_duration)) {
+                bool level = level_duration_get_level(level_duration);
+                uint32_t duration = level_duration_get_duration(level_duration);
+                subghz_receiver_decode(receiver, level, duration);
+            } else {
+                break;
+            }
+        }
+
+        printf("\r\nPackets recieved \033[0;32m%u\033[0m\r\n", instance->packet_count);
+
+        // Cleanup
+        subghz_receiver_free(receiver);
+        subghz_environment_free(environment);
+
+        if(subghz_file_encoder_worker_is_running(file_worker_encoder)) {
+            subghz_file_encoder_worker_stop(file_worker_encoder);
+        }
+        subghz_file_encoder_worker_free(file_worker_encoder);
+        free(instance);
+    }
+    string_clear(file_name);
+}
+
 static void subghz_cli_command_print_usage() {
     printf("Usage:\r\n");
     printf("subghz <cmd> <args>\r\n");
@@ -303,6 +408,7 @@ static void subghz_cli_command_print_usage() {
     printf(
         "\ttx <3 byte Key: in hex> <frequency: in Hz> <repeat: count>\t - Transmitting key\r\n");
     printf("\trx <frequency:in Hz>\t - Reception key\r\n");
+    printf("\tdecode_raw <file_name: path_RAW_file>\t - Testing\r\n");
 
     if(furi_hal_rtc_is_flag_set(FuriHalRtcFlagDebug)) {
         printf("\r\n");
@@ -595,6 +701,12 @@ static void subghz_cli_command(Cli* cli, string_t args, void* context) {
             subghz_cli_command_rx(cli, args, context);
             break;
         }
+
+        if(string_cmp_str(cmd, "decode_raw") == 0) {
+            subghz_cli_command_decode_raw(cli, args, context);
+            break;
+        }
+
         if(furi_hal_rtc_is_flag_set(FuriHalRtcFlagDebug)) {
             if(string_cmp_str(cmd, "encrypt_keeloq") == 0) {
                 subghz_cli_command_encrypt_keeloq(cli, args);

+ 1 - 1
applications/subghz/subghz_i.h

@@ -33,7 +33,7 @@
 
 #include <gui/modules/variable_item_list.h>
 
-#define SUBGHZ_MAX_LEN_NAME 21
+#define SUBGHZ_MAX_LEN_NAME 40
 
 extern const char* const subghz_frequencies_text[];
 extern const uint32_t subghz_frequencies[];

+ 0 - 0
applications/tests/flipper_format/flipper_format_string_test.c → applications/unit_tests/flipper_format/flipper_format_string_test.c


+ 0 - 0
applications/tests/flipper_format/flipper_format_test.c → applications/unit_tests/flipper_format/flipper_format_test.c


+ 0 - 0
applications/tests/furi_memmgr_test.c → applications/unit_tests/furi_memmgr_test.c


+ 0 - 0
applications/tests/furi_pubsub_test.c → applications/unit_tests/furi_pubsub_test.c


+ 0 - 0
applications/tests/furi_record_test.c → applications/unit_tests/furi_record_test.c


+ 0 - 0
applications/tests/furi_valuemutex_test.c → applications/unit_tests/furi_valuemutex_test.c


+ 0 - 0
applications/tests/infrared_decoder_encoder/infrared_decoder_encoder_test.c → applications/unit_tests/infrared_decoder_encoder/infrared_decoder_encoder_test.c


+ 0 - 0
applications/tests/infrared_decoder_encoder/test_data/infrared_nec_test_data.srcdata → applications/unit_tests/infrared_decoder_encoder/test_data/infrared_nec_test_data.srcdata


+ 0 - 0
applications/tests/infrared_decoder_encoder/test_data/infrared_necext_test_data.srcdata → applications/unit_tests/infrared_decoder_encoder/test_data/infrared_necext_test_data.srcdata


+ 0 - 0
applications/tests/infrared_decoder_encoder/test_data/infrared_rc5_test_data.srcdata → applications/unit_tests/infrared_decoder_encoder/test_data/infrared_rc5_test_data.srcdata


+ 0 - 0
applications/tests/infrared_decoder_encoder/test_data/infrared_rc6_test_data.srcdata → applications/unit_tests/infrared_decoder_encoder/test_data/infrared_rc6_test_data.srcdata


+ 0 - 0
applications/tests/infrared_decoder_encoder/test_data/infrared_samsung_test_data.srcdata → applications/unit_tests/infrared_decoder_encoder/test_data/infrared_samsung_test_data.srcdata


+ 0 - 0
applications/tests/infrared_decoder_encoder/test_data/infrared_sirc_test_data.srcdata → applications/unit_tests/infrared_decoder_encoder/test_data/infrared_sirc_test_data.srcdata


+ 0 - 0
applications/tests/minunit.h → applications/unit_tests/minunit.h


+ 0 - 0
applications/tests/minunit_test.c → applications/unit_tests/minunit_test.c


+ 0 - 0
applications/tests/minunit_vars.h → applications/unit_tests/minunit_vars.h


+ 0 - 0
applications/tests/minunit_vars_ex.h → applications/unit_tests/minunit_vars_ex.h


+ 0 - 0
applications/tests/rpc/rpc_test.c → applications/unit_tests/rpc/rpc_test.c


+ 0 - 0
applications/tests/storage/storage_test.c → applications/unit_tests/storage/storage_test.c


+ 0 - 0
applications/tests/stream/stream_test.c → applications/unit_tests/stream/stream_test.c


+ 404 - 0
applications/unit_tests/subghz/subghz_test.c

@@ -0,0 +1,404 @@
+#include <furi.h>
+#include <furi_hal.h>
+#include "../minunit.h"
+#include <lib/subghz/receiver.h>
+#include <lib/subghz/transmitter.h>
+#include <lib/subghz/subghz_keystore.h>
+#include <lib/subghz/subghz_file_encoder_worker.h>
+#include <lib/subghz/protocols/registry.h>
+#include <flipper_format/flipper_format_i.h>
+
+#define TAG "SubGhz TEST"
+#define KEYSTORE_DIR_NAME "/ext/subghz/assets/keeloq_mfcodes"
+#define CAME_ATOMO_DIR_NAME "/ext/subghz/assets/came_atomo"
+#define NICE_FLOR_S_DIR_NAME "/ext/subghz/assets/nice_flor_s"
+#define TEST_RANDOM_DIR_NAME "/ext/unit_tests/subghz/test_random_raw.sub"
+#define TEST_RANDOM_COUNT_PARSE 101
+#define TEST_TIMEOUT 10000
+
+static SubGhzEnvironment* environment_handler;
+static SubGhzReceiver* receiver_handler;
+//static SubGhzTransmitter* transmitter_handler;
+static SubGhzFileEncoderWorker* file_worker_encoder_handler;
+static uint16_t subghz_test_decoder_count = 0;
+
+static void subghz_test_rx_callback(
+    SubGhzReceiver* receiver,
+    SubGhzProtocolDecoderBase* decoder_base,
+    void* context) {
+    string_t text;
+    string_init(text);
+    subghz_protocol_decoder_base_get_string(decoder_base, text);
+    FURI_LOG_I(TAG, "\r\n%s", string_get_cstr(text));
+    string_clear(text);
+    subghz_test_decoder_count++;
+}
+
+static void subghz_test_init(void) {
+    environment_handler = subghz_environment_alloc();
+    subghz_environment_set_came_atomo_rainbow_table_file_name(
+        environment_handler, CAME_ATOMO_DIR_NAME);
+    subghz_environment_set_nice_flor_s_rainbow_table_file_name(
+        environment_handler, NICE_FLOR_S_DIR_NAME);
+
+    receiver_handler = subghz_receiver_alloc_init(environment_handler);
+    subghz_receiver_set_filter(receiver_handler, SubGhzProtocolFlag_Decodable);
+    subghz_receiver_set_rx_callback(receiver_handler, subghz_test_rx_callback, NULL);
+}
+
+static void subghz_test_deinit(void) {
+    subghz_receiver_free(receiver_handler);
+    subghz_environment_free(environment_handler);
+}
+
+static bool subghz_decode_test(const char* path, const char* name_decoder) {
+    subghz_test_decoder_count = 0;
+    uint32_t test_start = furi_hal_get_tick();
+
+    SubGhzProtocolDecoderBase* decoder =
+        subghz_receiver_search_decoder_base_by_name(receiver_handler, name_decoder);
+
+    if(decoder) {
+        file_worker_encoder_handler = subghz_file_encoder_worker_alloc();
+        if(subghz_file_encoder_worker_start(file_worker_encoder_handler, path)) {
+            //the worker needs a file in order to open and read part of the file
+            osDelay(100);
+
+            LevelDuration level_duration;
+            while(furi_hal_get_tick() - test_start < TEST_TIMEOUT) {
+                furi_hal_delay_us(
+                    500); //you need to have time to read from the file from the SD card
+                level_duration =
+                    subghz_file_encoder_worker_get_level_duration(file_worker_encoder_handler);
+                if(!level_duration_is_reset(level_duration)) {
+                    bool level = level_duration_get_level(level_duration);
+                    uint32_t duration = level_duration_get_duration(level_duration);
+                    decoder->protocol->decoder->feed(decoder, level, duration);
+                } else {
+                    break;
+                }
+            }
+            furi_hal_delay_ms(10);
+        }
+        if(subghz_file_encoder_worker_is_running(file_worker_encoder_handler)) {
+            subghz_file_encoder_worker_stop(file_worker_encoder_handler);
+        }
+        subghz_file_encoder_worker_free(file_worker_encoder_handler);
+    }
+    FURI_LOG_I(TAG, "\r\n Decoder count parse \033[0;33m%d\033[0m ", subghz_test_decoder_count);
+    if(furi_hal_get_tick() - test_start > TEST_TIMEOUT) {
+        printf("\033[0;31mTest decoder %s ERROR TimeOut\033[0m\r\n", name_decoder);
+        return false;
+    } else {
+        return subghz_test_decoder_count ? true : false;
+    }
+}
+
+static bool subghz_decode_ramdom_test(const char* path) {
+    subghz_test_decoder_count = 0;
+    subghz_receiver_reset(receiver_handler);
+    uint32_t test_start = furi_hal_get_tick();
+
+    file_worker_encoder_handler = subghz_file_encoder_worker_alloc();
+    if(subghz_file_encoder_worker_start(file_worker_encoder_handler, path)) {
+        //the worker needs a file in order to open and read part of the file
+        osDelay(100);
+
+        LevelDuration level_duration;
+        while(furi_hal_get_tick() - test_start < TEST_TIMEOUT * 10) {
+            furi_hal_delay_us(500); //you need to have time to read from the file from the SD card
+            level_duration =
+                subghz_file_encoder_worker_get_level_duration(file_worker_encoder_handler);
+            if(!level_duration_is_reset(level_duration)) {
+                bool level = level_duration_get_level(level_duration);
+                uint32_t duration = level_duration_get_duration(level_duration);
+                subghz_receiver_decode(receiver_handler, level, duration);
+            } else {
+                break;
+            }
+        }
+        furi_hal_delay_ms(10);
+        if(subghz_file_encoder_worker_is_running(file_worker_encoder_handler)) {
+            subghz_file_encoder_worker_stop(file_worker_encoder_handler);
+        }
+        subghz_file_encoder_worker_free(file_worker_encoder_handler);
+    }
+    FURI_LOG_I(TAG, "\r\n Decoder count parse \033[0;33m%d\033[0m ", subghz_test_decoder_count);
+    if(furi_hal_get_tick() - test_start > TEST_TIMEOUT * 10) {
+        printf("\033[0;31mRandom test ERROR TimeOut\033[0m\r\n");
+        return false;
+    } else if(subghz_test_decoder_count == TEST_RANDOM_COUNT_PARSE) {
+        return true;
+    } else {
+        return false;
+    }
+}
+
+static bool subghz_ecode_test(const char* path) {
+    subghz_test_decoder_count = 0;
+    uint32_t test_start = furi_hal_get_tick();
+    string_t temp_str;
+    string_init(temp_str);
+    bool file_load = false;
+
+    Storage* storage = furi_record_open("storage");
+    FlipperFormat* fff_data_file = flipper_format_file_alloc(storage);
+
+    do {
+        if(!flipper_format_file_open_existing(fff_data_file, path)) {
+            FURI_LOG_E(TAG, "Error open file %s", path);
+            break;
+        }
+
+        if(!flipper_format_read_string(fff_data_file, "Preset", temp_str)) {
+            FURI_LOG_E(TAG, "Missing Preset");
+            break;
+        }
+
+        if(!flipper_format_read_string(fff_data_file, "Protocol", temp_str)) {
+            FURI_LOG_E(TAG, "Missing Protocol");
+            break;
+        }
+        file_load = true;
+    } while(false);
+    if(file_load) {
+        SubGhzTransmitter* transmitter =
+            subghz_transmitter_alloc_init(environment_handler, string_get_cstr(temp_str));
+        subghz_transmitter_deserialize(transmitter, fff_data_file);
+
+        SubGhzProtocolDecoderBase* decoder = subghz_receiver_search_decoder_base_by_name(
+            receiver_handler, string_get_cstr(temp_str));
+
+        if(decoder) {
+            LevelDuration level_duration;
+            while(furi_hal_get_tick() - test_start < TEST_TIMEOUT) {
+                level_duration = subghz_transmitter_yield(transmitter);
+                if(!level_duration_is_reset(level_duration)) {
+                    bool level = level_duration_get_level(level_duration);
+                    uint32_t duration = level_duration_get_duration(level_duration);
+                    decoder->protocol->decoder->feed(decoder, level, duration);
+                } else {
+                    break;
+                }
+            }
+            furi_hal_delay_ms(10);
+        }
+        subghz_transmitter_free(transmitter);
+    }
+    flipper_format_free(fff_data_file);
+    FURI_LOG_I(TAG, "\r\n Decoder count parse \033[0;33m%d\033[0m ", subghz_test_decoder_count);
+    if(furi_hal_get_tick() - test_start > TEST_TIMEOUT) {
+        printf("\033[0;31mTest encoder %s ERROR TimeOut\033[0m\r\n", string_get_cstr(temp_str));
+        subghz_test_decoder_count = 0;
+    }
+    string_clear(temp_str);
+
+    return subghz_test_decoder_count ? true : false;
+}
+
+MU_TEST(subghz_keystore_test) {
+    mu_assert(
+        subghz_environment_load_keystore(environment_handler, KEYSTORE_DIR_NAME),
+        "Test keystore error");
+}
+
+MU_TEST(subghz_decoder_came_atomo_test) {
+    mu_assert(
+        subghz_decode_test(
+            "/ext/unit_tests/subghz/came_atomo_raw.sub", SUBGHZ_PROTOCOL_CAME_ATOMO_NAME),
+        "Test decoder " SUBGHZ_PROTOCOL_CAME_ATOMO_NAME " error\r\n");
+}
+
+MU_TEST(subghz_decoder_came_test) {
+    mu_assert(
+        subghz_decode_test("/ext/unit_tests/subghz/came_raw.sub", SUBGHZ_PROTOCOL_CAME_NAME),
+        "Test decoder " SUBGHZ_PROTOCOL_CAME_NAME " error\r\n");
+}
+
+MU_TEST(subghz_decoder_came_twee_test) {
+    mu_assert(
+        subghz_decode_test(
+            "/ext/unit_tests/subghz/came_twee_raw.sub", SUBGHZ_PROTOCOL_CAME_TWEE_NAME),
+        "Test decoder " SUBGHZ_PROTOCOL_CAME_TWEE_NAME " error\r\n");
+}
+
+MU_TEST(subghz_decoder_faac_slh_test) {
+    mu_assert(
+        subghz_decode_test(
+            "/ext/unit_tests/subghz/faac_slh_raw.sub", SUBGHZ_PROTOCOL_FAAC_SLH_NAME),
+        "Test decoder " SUBGHZ_PROTOCOL_FAAC_SLH_NAME " error\r\n");
+}
+
+MU_TEST(subghz_decoder_gate_tx_test) {
+    mu_assert(
+        subghz_decode_test("/ext/unit_tests/subghz/gate_tx_raw.sub", SUBGHZ_PROTOCOL_GATE_TX_NAME),
+        "Test decoder " SUBGHZ_PROTOCOL_GATE_TX_NAME " error\r\n");
+}
+
+MU_TEST(subghz_decoder_hormann_hsm_test) {
+    mu_assert(
+        subghz_decode_test(
+            "/ext/unit_tests/subghz/hormann_hsm_raw.sub", SUBGHZ_PROTOCOL_HORMANN_HSM_NAME),
+        "Test decoder " SUBGHZ_PROTOCOL_HORMANN_HSM_NAME " error\r\n");
+}
+
+MU_TEST(subghz_decoder_ido_test) {
+    mu_assert(
+        subghz_decode_test("/ext/unit_tests/subghz/ido_117_111_raw.sub", SUBGHZ_PROTOCOL_IDO_NAME),
+        "Test decoder " SUBGHZ_PROTOCOL_IDO_NAME " error\r\n");
+}
+
+MU_TEST(subghz_decoder_keelog_test) {
+    mu_assert(
+        subghz_decode_test("/ext/unit_tests/subghz/doorhan_raw.sub", SUBGHZ_PROTOCOL_KEELOQ_NAME),
+        "Test decoder " SUBGHZ_PROTOCOL_KEELOQ_NAME " error\r\n");
+}
+
+MU_TEST(subghz_decoder_kia_seed_test) {
+    mu_assert(
+        subghz_decode_test("/ext/unit_tests/subghz/kia_seed_raw.sub", SUBGHZ_PROTOCOL_KIA_NAME),
+        "Test decoder " SUBGHZ_PROTOCOL_KIA_NAME " error\r\n");
+}
+
+MU_TEST(subghz_decoder_nero_radio_test) {
+    mu_assert(
+        subghz_decode_test(
+            "/ext/unit_tests/subghz/nero_radio_raw.sub", SUBGHZ_PROTOCOL_NERO_RADIO_NAME),
+        "Test decoder " SUBGHZ_PROTOCOL_NERO_RADIO_NAME " error\r\n");
+}
+
+MU_TEST(subghz_decoder_nero_sketch_test) {
+    mu_assert(
+        subghz_decode_test(
+            "/ext/unit_tests/subghz/nero_sketch_raw.sub", SUBGHZ_PROTOCOL_NERO_SKETCH_NAME),
+        "Test decoder " SUBGHZ_PROTOCOL_NERO_SKETCH_NAME " error\r\n");
+}
+
+MU_TEST(subghz_decoder_nice_flo_test) {
+    mu_assert(
+        subghz_decode_test(
+            "/ext/unit_tests/subghz/nice_flo_raw.sub", SUBGHZ_PROTOCOL_NICE_FLO_NAME),
+        "Test decoder " SUBGHZ_PROTOCOL_NICE_FLO_NAME " error\r\n");
+}
+
+MU_TEST(subghz_decoder_nice_flor_s_test) {
+    mu_assert(
+        subghz_decode_test(
+            "/ext/unit_tests/subghz/nice_flor_s_raw.sub", SUBGHZ_PROTOCOL_NICE_FLOR_S_NAME),
+        "Test decoder " SUBGHZ_PROTOCOL_NICE_FLOR_S_NAME " error\r\n");
+}
+
+MU_TEST(subghz_decoder_princeton_test) {
+    mu_assert(
+        subghz_decode_test(
+            "/ext/unit_tests/subghz/Princeton_raw.sub", SUBGHZ_PROTOCOL_PRINCETON_NAME),
+        "Test decoder " SUBGHZ_PROTOCOL_PRINCETON_NAME " error\r\n");
+}
+
+MU_TEST(subghz_decoder_scher_khan_magic_code_test) {
+    mu_assert(
+        subghz_decode_test(
+            "/ext/unit_tests/subghz/scher_khan_magic_code.sub", SUBGHZ_PROTOCOL_SCHER_KHAN_NAME),
+        "Test decoder " SUBGHZ_PROTOCOL_SCHER_KHAN_NAME " error\r\n");
+}
+
+MU_TEST(subghz_decoder_somfy_keytis_test) {
+    mu_assert(
+        subghz_decode_test(
+            "/ext/unit_tests/subghz/Somfy_keytis_raw.sub", SUBGHZ_PROTOCOL_SOMFY_KEYTIS_NAME),
+        "Test decoder " SUBGHZ_PROTOCOL_SOMFY_KEYTIS_NAME " error\r\n");
+}
+
+MU_TEST(subghz_decoder_somfy_telis_test) {
+    mu_assert(
+        subghz_decode_test(
+            "/ext/unit_tests/subghz/somfy_telis_raw.sub", SUBGHZ_PROTOCOL_SOMFY_TELIS_NAME),
+        "Test decoder " SUBGHZ_PROTOCOL_SOMFY_TELIS_NAME " error\r\n");
+}
+
+MU_TEST(subghz_decoder_star_line_test) {
+    mu_assert(
+        subghz_decode_test("/ext/unit_tests/subghz/cenmax_raw.sub", SUBGHZ_PROTOCOL_STAR_LINE_NAME),
+        "Test decoder " SUBGHZ_PROTOCOL_STAR_LINE_NAME " error\r\n");
+}
+
+MU_TEST(subghz_ecoder_princeton_test) {
+    mu_assert(
+        subghz_ecode_test("/ext/unit_tests/subghz/princeton.sub"),
+        "Test encoder " SUBGHZ_PROTOCOL_PRINCETON_NAME " error\r\n");
+}
+
+MU_TEST(subghz_ecoder_came_test) {
+    mu_assert(
+        subghz_ecode_test("/ext/unit_tests/subghz/came.sub"),
+        "Test encoder " SUBGHZ_PROTOCOL_CAME_NAME " error\r\n");
+}
+
+MU_TEST(subghz_ecoder_came_twee_test) {
+    mu_assert(
+        subghz_ecode_test("/ext/unit_tests/subghz/came_twee.sub"),
+        "Test encoder " SUBGHZ_PROTOCOL_CAME_TWEE_NAME " error\r\n");
+}
+
+MU_TEST(subghz_ecoder_gate_tx_test) {
+    mu_assert(
+        subghz_ecode_test("/ext/unit_tests/subghz/gate_tx.sub"),
+        "Test encoder " SUBGHZ_PROTOCOL_GATE_TX_NAME " error\r\n");
+}
+
+MU_TEST(subghz_ecoder_nice_flo_test) {
+    mu_assert(
+        subghz_ecode_test("/ext/unit_tests/subghz/nice_flo.sub"),
+        "Test encoder " SUBGHZ_PROTOCOL_NICE_FLO_NAME " error\r\n");
+}
+
+MU_TEST(subghz_ecoder_keelog_test) {
+    mu_assert(
+        subghz_ecode_test("/ext/unit_tests/subghz/doorhan.sub"),
+        "Test encoder " SUBGHZ_PROTOCOL_KEELOQ_NAME " error\r\n");
+}
+
+MU_TEST(subghz_random_test) {
+    mu_assert(subghz_decode_ramdom_test(TEST_RANDOM_DIR_NAME), "Random test error\r\n");
+}
+
+MU_TEST_SUITE(subghz) {
+    //MU_SUITE_CONFIGURE(&subghz_test_init, &subghz_test_deinit);
+
+    subghz_test_init();
+    MU_RUN_TEST(subghz_keystore_test);
+
+    MU_RUN_TEST(subghz_decoder_came_atomo_test);
+    MU_RUN_TEST(subghz_decoder_came_test);
+    MU_RUN_TEST(subghz_decoder_came_twee_test);
+    MU_RUN_TEST(subghz_decoder_faac_slh_test);
+    MU_RUN_TEST(subghz_decoder_gate_tx_test);
+    MU_RUN_TEST(subghz_decoder_hormann_hsm_test);
+    MU_RUN_TEST(subghz_decoder_ido_test);
+    MU_RUN_TEST(subghz_decoder_keelog_test);
+    MU_RUN_TEST(subghz_decoder_kia_seed_test);
+    MU_RUN_TEST(subghz_decoder_nero_radio_test);
+    MU_RUN_TEST(subghz_decoder_nero_sketch_test);
+    MU_RUN_TEST(subghz_decoder_nice_flo_test);
+    MU_RUN_TEST(subghz_decoder_nice_flor_s_test);
+    MU_RUN_TEST(subghz_decoder_princeton_test);
+    MU_RUN_TEST(subghz_decoder_scher_khan_magic_code_test);
+    MU_RUN_TEST(subghz_decoder_somfy_keytis_test);
+    MU_RUN_TEST(subghz_decoder_somfy_telis_test);
+    MU_RUN_TEST(subghz_decoder_star_line_test);
+
+    MU_RUN_TEST(subghz_ecoder_princeton_test);
+    MU_RUN_TEST(subghz_ecoder_came_test);
+    MU_RUN_TEST(subghz_ecoder_came_twee_test);
+    MU_RUN_TEST(subghz_ecoder_gate_tx_test);
+    MU_RUN_TEST(subghz_ecoder_nice_flo_test);
+    MU_RUN_TEST(subghz_ecoder_keelog_test);
+
+    MU_RUN_TEST(subghz_random_test);
+    subghz_test_deinit();
+}
+
+int run_minunit_test_subghz() {
+    MU_RUN_SUITE(subghz);
+    return MU_EXIT_CODE;
+}

+ 6 - 3
applications/tests/test_index.c → applications/unit_tests/test_index.c

@@ -17,6 +17,7 @@ int run_minunit_test_flipper_format();
 int run_minunit_test_flipper_format_string();
 int run_minunit_test_stream();
 int run_minunit_test_storage();
+int run_minunit_test_subghz();
 
 void minunit_print_progress(void) {
     static char progress[] = {'\\', '|', '/', '-'};
@@ -51,7 +52,7 @@ void unit_tests_cli(Cli* cli, string_t args, void* context) {
         notification_message_block(notification, &sequence_set_only_blue_255);
 
         uint32_t heap_before = memmgr_get_free_heap();
-        uint32_t cycle_counter = DWT->CYCCNT;
+        uint32_t cycle_counter = furi_hal_get_tick();
 
         test_result |= run_minunit();
         test_result |= run_minunit_test_storage();
@@ -60,9 +61,11 @@ void unit_tests_cli(Cli* cli, string_t args, void* context) {
         test_result |= run_minunit_test_flipper_format_string();
         test_result |= run_minunit_test_infrared_decoder_encoder();
         test_result |= run_minunit_test_rpc();
-        cycle_counter = (DWT->CYCCNT - cycle_counter);
+        test_result |= run_minunit_test_subghz();
 
-        FURI_LOG_I(TAG, "Consumed: %0.2fs", (float)cycle_counter / (SystemCoreClock));
+        cycle_counter = (furi_hal_get_tick() - cycle_counter);
+
+        FURI_LOG_I(TAG, "Consumed: %0.2fs", (float)cycle_counter / 1000);
 
         if(test_result == 0) {
             furi_hal_delay_ms(200); /* wait for tested services and apps to deallocate */

+ 7 - 0
assets/unit_tests/subghz/came.sub

@@ -0,0 +1,7 @@
+Filetype: Flipper SubGhz Key File
+Version: 1
+Frequency: 433920000
+Preset: FuriHalSubGhzPresetOok650Async
+Protocol: CAME
+Bit: 24
+Key: 00 00 00 00 00 6A B2 34

Rozdílová data souboru nebyla zobrazena, protože soubor je příliš velký
+ 5 - 0
assets/unit_tests/subghz/came_atomo_raw.sub


Rozdílová data souboru nebyla zobrazena, protože soubor je příliš velký
+ 5 - 0
assets/unit_tests/subghz/came_raw.sub


+ 7 - 0
assets/unit_tests/subghz/came_twee.sub

@@ -0,0 +1,7 @@
+Filetype: Flipper SubGhz Key File
+Version: 1
+Frequency: 433920000
+Preset: FuriHalSubGhzPresetOok650Async
+Protocol: CAME TWEE
+Bit: 54
+Key: 00 00 00 00 E7 1E 05 2E

Rozdílová data souboru nebyla zobrazena, protože soubor je příliš velký
+ 5 - 0
assets/unit_tests/subghz/came_twee_raw.sub


Rozdílová data souboru nebyla zobrazena, protože soubor je příliš velký
+ 5 - 0
assets/unit_tests/subghz/cenmax_raw.sub


+ 7 - 0
assets/unit_tests/subghz/doorhan.sub

@@ -0,0 +1,7 @@
+Filetype: Flipper SubGhz Key File
+Version: 1
+Frequency: 433920000
+Preset: FuriHalSubGhzPresetOok650Async
+Protocol: KeeLoq
+Bit: 64
+Key: 48 50 F0 72 33 78 95 14

Rozdílová data souboru nebyla zobrazena, protože soubor je příliš velký
+ 5 - 0
assets/unit_tests/subghz/doorhan_raw.sub


Rozdílová data souboru nebyla zobrazena, protože soubor je příliš velký
+ 5 - 0
assets/unit_tests/subghz/faac_slh_raw.sub


+ 7 - 0
assets/unit_tests/subghz/gate_tx.sub

@@ -0,0 +1,7 @@
+Filetype: Flipper SubGhz Key File
+Version: 1
+Frequency: 433920000
+Preset: FuriHalSubGhzPresetOok650Async
+Protocol: GateTX
+Bit: 24
+Key: 00 00 00 00 00 02 8F F3

Rozdílová data souboru nebyla zobrazena, protože soubor je příliš velký
+ 5 - 0
assets/unit_tests/subghz/gate_tx_raw.sub


Rozdílová data souboru nebyla zobrazena, protože soubor je příliš velký
+ 5 - 0
assets/unit_tests/subghz/hormann_hsm_raw.sub


Rozdílová data souboru nebyla zobrazena, protože soubor je příliš velký
+ 5 - 0
assets/unit_tests/subghz/ido_117_111_raw.sub


Rozdílová data souboru nebyla zobrazena, protože soubor je příliš velký
+ 5 - 0
assets/unit_tests/subghz/kia_seed_raw.sub


Rozdílová data souboru nebyla zobrazena, protože soubor je příliš velký
+ 5 - 0
assets/unit_tests/subghz/nero_radio_raw.sub


Rozdílová data souboru nebyla zobrazena, protože soubor je příliš velký
+ 5 - 0
assets/unit_tests/subghz/nero_sketch_raw.sub


+ 7 - 0
assets/unit_tests/subghz/nice_flo.sub

@@ -0,0 +1,7 @@
+Filetype: Flipper SubGhz Key File
+Version: 1
+Frequency: 433920000
+Preset: FuriHalSubGhzPresetOok650Async
+Protocol: Nice FLO
+Bit: 24
+Key: 00 00 00 00 00 02 FE C4

Rozdílová data souboru nebyla zobrazena, protože soubor je příliš velký
+ 5 - 0
assets/unit_tests/subghz/nice_flo_raw.sub


Rozdílová data souboru nebyla zobrazena, protože soubor je příliš velký
+ 5 - 0
assets/unit_tests/subghz/nice_flor_s_raw.sub


+ 8 - 0
assets/unit_tests/subghz/princeton.sub

@@ -0,0 +1,8 @@
+Filetype: Flipper SubGhz Key File
+Version: 1
+Frequency: 433920000
+Preset: FuriHalSubGhzPresetOok650Async
+Protocol: Princeton
+Bit: 24
+Key: 00 00 00 00 00 95 D5 D4
+TE: 400

Rozdílová data souboru nebyla zobrazena, protože soubor je příliš velký
+ 5 - 0
assets/unit_tests/subghz/princeton_raw.sub


Rozdílová data souboru nebyla zobrazena, protože soubor je příliš velký
+ 5 - 0
assets/unit_tests/subghz/scher_khan_magic_code.sub


Rozdílová data souboru nebyla zobrazena, protože soubor je příliš velký
+ 5 - 0
assets/unit_tests/subghz/somfy_keytis_raw.sub


Rozdílová data souboru nebyla zobrazena, protože soubor je příliš velký
+ 5 - 0
assets/unit_tests/subghz/somfy_telis_raw.sub


Rozdílová data souboru nebyla zobrazena, protože soubor je příliš velký
+ 5 - 0
assets/unit_tests/subghz/test_random_raw.sub


+ 4 - 0
firmware/targets/f7/furi_hal/furi_hal_speaker.c

@@ -21,6 +21,10 @@ void furi_hal_speaker_init() {
 }
 
 void furi_hal_speaker_start(float frequency, float volume) {
+    if(volume == 0) {
+        return;
+    }
+
     if(volume < 0) volume = 0;
     if(volume > 1) volume = 1;
     volume = volume * volume * volume;

+ 3 - 3
firmware/targets/f7/furi_hal/furi_hal_subghz.c

@@ -160,7 +160,7 @@ static const uint8_t furi_hal_subghz_preset_2fsk_dev2_38khz_async_regs[][2] = {
     /* End  */
     {0, 0},
 };
-static const uint8_t furi_hal_subghz_preset_2fsk_dev4_76khz_async_regs[][2] = {
+static const uint8_t furi_hal_subghz_preset_2fsk_dev47_6khz_async_regs[][2] = {
 
     /* GPIO GD0 */
     {CC1101_IOCFG0, 0x0D}, // GD0 as async serial data output/input
@@ -178,7 +178,7 @@ static const uint8_t furi_hal_subghz_preset_2fsk_dev4_76khz_async_regs[][2] = {
     {CC1101_MDMCFG2, 0x04}, // Format 2-FSK/FM, No preamble/sync, Disable (current optimized)
     {CC1101_MDMCFG3, 0x83}, // Data rate is 4.79794 kBaud
     {CC1101_MDMCFG4, 0x67}, //Rx BW filter is 270.833333 kHz
-    {CC1101_DEVIATN, 0x14}, //Deviation 4.760742 kHz
+    {CC1101_DEVIATN, 0x47}, //Deviation 47.60742 kHz
 
     /* Main Radio Control State Machine */
     {CC1101_MCSM0, 0x18}, // Autocalibrate on idle-to-rx/tx, PO_TIMEOUT is 64 cycles(149-155us)
@@ -403,7 +403,7 @@ void furi_hal_subghz_load_preset(FuriHalSubGhzPreset preset) {
         furi_hal_subghz_load_registers(furi_hal_subghz_preset_2fsk_dev2_38khz_async_regs);
         furi_hal_subghz_load_patable(furi_hal_subghz_preset_2fsk_async_patable);
     } else if(preset == FuriHalSubGhzPreset2FSKDev476Async) {
-        furi_hal_subghz_load_registers(furi_hal_subghz_preset_2fsk_dev4_76khz_async_regs);
+        furi_hal_subghz_load_registers(furi_hal_subghz_preset_2fsk_dev47_6khz_async_regs);
         furi_hal_subghz_load_patable(furi_hal_subghz_preset_2fsk_async_patable);
     } else if(preset == FuriHalSubGhzPresetMSK99_97KbAsync) {
         furi_hal_subghz_load_registers(furi_hal_subghz_preset_msk_99_97kb_async_regs);

+ 1 - 1
firmware/targets/furi_hal_include/furi_hal_subghz.h

@@ -20,7 +20,7 @@ typedef enum {
     FuriHalSubGhzPresetOok270Async, /**< OOK, bandwidth 270kHz, asynchronous */
     FuriHalSubGhzPresetOok650Async, /**< OOK, bandwidth 650kHz, asynchronous */
     FuriHalSubGhzPreset2FSKDev238Async, /**< FM, deviation 2.380371 kHz, asynchronous */
-    FuriHalSubGhzPreset2FSKDev476Async, /**< FM, deviation 4.760742 kHz, asynchronous */
+    FuriHalSubGhzPreset2FSKDev476Async, /**< FM, deviation 47.60742 kHz, asynchronous */
     FuriHalSubGhzPresetMSK99_97KbAsync, /**< MSK, deviation 47.60742 kHz, 99.97Kb/s, asynchronous */
     FuriHalSubGhzPresetGFSK9_99KbAsync /**< GFSK, deviation 19.042969 kHz, 9.996Kb/s, asynchronous */
 } FuriHalSubGhzPreset;

+ 5 - 5
lib/subghz/protocols/kia.c

@@ -95,15 +95,15 @@ void subghz_protocol_decoder_kia_feed(void* context, bool level, uint32_t durati
 
     switch(instance->decoder.parser_step) {
     case KIADecoderStepReset:
-        if((!level) && (DURATION_DIFF(duration, subghz_protocol_kia_const.te_short) <
-                        subghz_protocol_kia_const.te_delta)) {
+        if((level) && (DURATION_DIFF(duration, subghz_protocol_kia_const.te_short) <
+                       subghz_protocol_kia_const.te_delta)) {
             instance->decoder.parser_step = KIADecoderStepCheckPreambula;
             instance->decoder.te_last = duration;
             instance->header_count = 0;
         }
         break;
     case KIADecoderStepCheckPreambula:
-        if(!level) {
+        if(level) {
             if((DURATION_DIFF(duration, subghz_protocol_kia_const.te_short) <
                 subghz_protocol_kia_const.te_delta) ||
                (DURATION_DIFF(duration, subghz_protocol_kia_const.te_long) <
@@ -139,7 +139,7 @@ void subghz_protocol_decoder_kia_feed(void* context, bool level, uint32_t durati
         }
         break;
     case KIADecoderStepSaveDuration:
-        if(!level) {
+        if(level) {
             if(duration >=
                (subghz_protocol_kia_const.te_long + subghz_protocol_kia_const.te_delta * 2)) {
                 //Found stop bit
@@ -164,7 +164,7 @@ void subghz_protocol_decoder_kia_feed(void* context, bool level, uint32_t durati
         }
         break;
     case KIADecoderStepCheckDuration:
-        if(level) {
+        if(!level) {
             if((DURATION_DIFF(instance->decoder.te_last, subghz_protocol_kia_const.te_short) <
                 subghz_protocol_kia_const.te_delta) &&
                (DURATION_DIFF(duration, subghz_protocol_kia_const.te_short) <

+ 1 - 3
lib/subghz/protocols/raw.c

@@ -15,7 +15,7 @@
 #define SUBGHZ_DOWNLOAD_MAX_SIZE 512
 
 static const SubGhzBlockConst subghz_protocol_raw_const = {
-    .te_short = 80,
+    .te_short = 50,
     .te_long = 32700,
     .te_delta = 0,
     .min_count_bit_for_found = 0,
@@ -223,8 +223,6 @@ void subghz_protocol_decoder_raw_feed(void* context, bool level, uint32_t durati
 
     if(instance->upload_raw != NULL) {
         if(duration > subghz_protocol_raw_const.te_short) {
-            if(duration > subghz_protocol_raw_const.te_long)
-                duration = subghz_protocol_raw_const.te_long;
             if(instance->last_level != level) {
                 instance->last_level = (level ? true : false);
                 instance->upload_raw[instance->ind_write++] = (level ? duration : -duration);

+ 0 - 20
lib/subghz/protocols/registry.c

@@ -1,25 +1,5 @@
 #include "registry.h"
 
-#include "princeton.h"
-#include "keeloq.h"
-#include "star_line.h"
-#include "nice_flo.h"
-#include "came.h"
-#include "faac_slh.h"
-#include "nice_flor_s.h"
-#include "came_twee.h"
-#include "came_atomo.h"
-#include "nero_sketch.h"
-#include "ido.h"
-#include "kia.h"
-#include "hormann.h"
-#include "nero_radio.h"
-#include "somfy_telis.h"
-#include "somfy_keytis.h"
-#include "scher_khan.h"
-#include "gate_tx.h"
-#include "raw.h"
-
 const SubGhzProtocol* subghz_protocol_registry[] = {
     &subghz_protocol_princeton,    &subghz_protocol_keeloq,     &subghz_protocol_star_line,
     &subghz_protocol_nice_flo,     &subghz_protocol_came,       &subghz_protocol_faac_slh,

+ 20 - 0
lib/subghz/protocols/registry.h

@@ -2,6 +2,26 @@
 
 #include "../types.h"
 
+#include "princeton.h"
+#include "keeloq.h"
+#include "star_line.h"
+#include "nice_flo.h"
+#include "came.h"
+#include "faac_slh.h"
+#include "nice_flor_s.h"
+#include "came_twee.h"
+#include "came_atomo.h"
+#include "nero_sketch.h"
+#include "ido.h"
+#include "kia.h"
+#include "hormann.h"
+#include "nero_radio.h"
+#include "somfy_telis.h"
+#include "somfy_keytis.h"
+#include "scher_khan.h"
+#include "gate_tx.h"
+#include "raw.h"
+
 /**
  * Registration by name SubGhzProtocol.
  * @param name Protocol name

+ 3 - 3
lib/subghz/protocols/scher_khan.c

@@ -207,7 +207,7 @@ void subghz_protocol_decoder_scher_khan_feed(void* context, bool level, uint32_t
  */
 static void subghz_protocol_scher_khan_check_remote_controller(
     SubGhzBlockGeneric* instance,
-    const char* protocol_name) {
+    const char** protocol_name) {
     /* 
     * MAGICAR 51 bit 00000001A99121DE83C3 MAGIC CODE, Dinamic
     * 0E8C1619E830C -> 000011101000110000010110 0001 1001 1110 1000001100001100
@@ -222,7 +222,7 @@ static void subghz_protocol_scher_khan_check_remote_controller(
     //     instance->protocol_name = "MAGIC CODE, Static";
     //     break;
     case 51: //MAGIC CODE, Dinamic
-        protocol_name = "MAGIC CODE, Dinamic";
+        *protocol_name = "MAGIC CODE, Dinamic";
         instance->serial = ((instance->data >> 24) & 0xFFFFFF0) | ((instance->data >> 20) & 0x0F);
         instance->btn = (instance->data >> 24) & 0x0F;
         instance->cnt = instance->data & 0xFFFF;
@@ -268,7 +268,7 @@ void subghz_protocol_decoder_scher_khan_get_string(void* context, string_t outpu
     SubGhzProtocolDecoderScherKhan* instance = context;
 
     subghz_protocol_scher_khan_check_remote_controller(
-        &instance->generic, instance->protocol_name);
+        &instance->generic, &instance->protocol_name);
 
     string_cat_printf(
         output,

Některé soubory nejsou zobrazeny, neboť je v těchto rozdílových datech změněno mnoho souborů