[FL-1546, FL-1534, FL-1550] Drop F5, Certification preparation, Global application start lock (#585)
* Firmware: drop F5 target * Rename app-loader to loader * Update code owners file * Loader: global application start lock API, minor refactoring * Archive: update loader usage * Cli: Command flags, global application start lock * Apps: update cli API usage * Bootloader: minor refactoring * Firmware: minor build refactoring * SubGhz: GUI packet test * SubGhz: drop packet transmission and unused presets * Github: drop F5 from build * Archive: favorites * Archive: a little bit more of Favorites
This commit is contained in:
		| @@ -3,17 +3,11 @@ | ||||
| #include <furi.h> | ||||
| #include <api-hal.h> | ||||
| #include <stream_buffer.h> | ||||
| #include <lib/subghz/protocols/subghz_protocol.h> | ||||
|  | ||||
| #define CC1101_FREQUENCY_RANGE_STR \ | ||||
|     "300000000...348000000 or 387000000...464000000 or 779000000...928000000" | ||||
|  | ||||
| static const uint8_t subghz_test_packet_data[] = { | ||||
|     0x30, // 48bytes to transmit | ||||
|     0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, | ||||
|     0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, | ||||
|     0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, | ||||
| }; | ||||
|  | ||||
| bool subghz_check_frequency_range(uint32_t frequency) { | ||||
|     if(!(frequency >= 300000000 && frequency <= 348000000) && | ||||
|        !(frequency >= 387000000 && frequency <= 464000000) && | ||||
| @@ -26,42 +20,45 @@ bool subghz_check_frequency_range(uint32_t frequency) { | ||||
| void subghz_cli_init() { | ||||
|     Cli* cli = furi_record_open("cli"); | ||||
|  | ||||
|     cli_add_command(cli, "subghz_tx_carrier", subghz_cli_command_tx_carrier, NULL); | ||||
|     cli_add_command(cli, "subghz_rx_carrier", subghz_cli_command_rx_carrier, NULL); | ||||
|     cli_add_command(cli, "subghz_tx_pt", subghz_cli_command_tx_pt, NULL); | ||||
|     cli_add_command(cli, "subghz_rx_pt", subghz_cli_command_rx_pt, NULL); | ||||
|     cli_add_command(cli, "subghz_tx", subghz_cli_command_tx, NULL); | ||||
|     cli_add_command(cli, "subghz_rx", subghz_cli_command_rx, NULL); | ||||
|     cli_add_command( | ||||
|         cli, "subghz_tx_carrier", CliCommandFlagDefault, subghz_cli_command_tx_carrier, NULL); | ||||
|     cli_add_command( | ||||
|         cli, "subghz_rx_carrier", CliCommandFlagDefault, subghz_cli_command_rx_carrier, NULL); | ||||
|     cli_add_command(cli, "subghz_tx", CliCommandFlagDefault, subghz_cli_command_tx, NULL); | ||||
|     cli_add_command(cli, "subghz_rx", CliCommandFlagDefault, subghz_cli_command_rx, NULL); | ||||
|  | ||||
|     furi_record_close("cli"); | ||||
| } | ||||
|  | ||||
| void subghz_cli_command_tx_carrier(Cli* cli, string_t args, void* context) { | ||||
|     uint32_t frequency = 0; | ||||
|     int ret = sscanf(string_get_cstr(args), "%lu", &frequency); | ||||
|     if(ret != 1) { | ||||
|         printf("sscanf returned %d, frequency: %lu\r\n", ret, frequency); | ||||
|         cli_print_usage("subghz_tx_carrier", "<Frequency in HZ>", string_get_cstr(args)); | ||||
|         return; | ||||
|     } | ||||
|     uint32_t frequency = 433920000; | ||||
|  | ||||
|     if(!subghz_check_frequency_range(frequency)) { | ||||
|         printf( | ||||
|             "Frequency must be in " CC1101_FREQUENCY_RANGE_STR " range, not %lu\r\n", frequency); | ||||
|         return; | ||||
|     if(string_size(args)) { | ||||
|         int ret = sscanf(string_get_cstr(args), "%lu", &frequency); | ||||
|         if(ret != 1) { | ||||
|             printf("sscanf returned %d, frequency: %lu\r\n", ret, frequency); | ||||
|             cli_print_usage("subghz_tx_carrier", "<Frequency in HZ>", string_get_cstr(args)); | ||||
|             return; | ||||
|         } | ||||
|         if(!subghz_check_frequency_range(frequency)) { | ||||
|             printf( | ||||
|                 "Frequency must be in " CC1101_FREQUENCY_RANGE_STR " range, not %lu\r\n", | ||||
|                 frequency); | ||||
|             return; | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     api_hal_subghz_reset(); | ||||
|     api_hal_subghz_load_preset(ApiHalSubGhzPresetOokAsync); | ||||
|     frequency = api_hal_subghz_set_frequency_and_path(frequency); | ||||
|     printf("Transmitting at frequency %lu Hz\r\n", frequency); | ||||
|     printf("Press CTRL+C to stop\r\n"); | ||||
|  | ||||
|     hal_gpio_init(&gpio_cc1101_g0, GpioModeOutputPushPull, GpioPullNo, GpioSpeedLow); | ||||
|     hal_gpio_write(&gpio_cc1101_g0, false); | ||||
|     hal_gpio_write(&gpio_cc1101_g0, true); | ||||
|  | ||||
|     api_hal_subghz_tx(); | ||||
|  | ||||
|     printf("Transmitting at frequency %lu Hz\r\n", frequency); | ||||
|     printf("Press CTRL+C to stop\r\n"); | ||||
|     while(!cli_cmd_interrupt_received(cli)) { | ||||
|         osDelay(250); | ||||
|     } | ||||
| @@ -71,18 +68,21 @@ void subghz_cli_command_tx_carrier(Cli* cli, string_t args, void* context) { | ||||
| } | ||||
|  | ||||
| void subghz_cli_command_rx_carrier(Cli* cli, string_t args, void* context) { | ||||
|     uint32_t frequency = 0; | ||||
|     int ret = sscanf(string_get_cstr(args), "%lu", &frequency); | ||||
|     if(ret != 1) { | ||||
|         printf("sscanf returned %d, frequency: %lu\r\n", ret, frequency); | ||||
|         cli_print_usage("subghz_tx_carrier", "<Frequency in HZ>", string_get_cstr(args)); | ||||
|         return; | ||||
|     } | ||||
|     uint32_t frequency = 433920000; | ||||
|  | ||||
|     if(!subghz_check_frequency_range(frequency)) { | ||||
|         printf( | ||||
|             "Frequency must be in " CC1101_FREQUENCY_RANGE_STR " range, not %lu\r\n", frequency); | ||||
|         return; | ||||
|     if(string_size(args)) { | ||||
|         int ret = sscanf(string_get_cstr(args), "%lu", &frequency); | ||||
|         if(ret != 1) { | ||||
|             printf("sscanf returned %d, frequency: %lu\r\n", ret, frequency); | ||||
|             cli_print_usage("subghz_tx_carrier", "<Frequency in HZ>", string_get_cstr(args)); | ||||
|             return; | ||||
|         } | ||||
|         if(!subghz_check_frequency_range(frequency)) { | ||||
|             printf( | ||||
|                 "Frequency must be in " CC1101_FREQUENCY_RANGE_STR " range, not %lu\r\n", | ||||
|                 frequency); | ||||
|             return; | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     api_hal_subghz_reset(); | ||||
| @@ -103,109 +103,9 @@ void subghz_cli_command_rx_carrier(Cli* cli, string_t args, void* context) { | ||||
|     api_hal_subghz_sleep(); | ||||
| } | ||||
|  | ||||
| void subghz_cli_command_tx_pt(Cli* cli, string_t args, void* context) { | ||||
|     uint32_t frequency = 0; | ||||
|     uint32_t pattern; | ||||
|     uint32_t count; | ||||
|  | ||||
|     int ret = sscanf(string_get_cstr(args), "%lu %lu %lu", &frequency, &pattern, &count); | ||||
|     if(ret != 3) { | ||||
|         printf( | ||||
|             "sscanf returned %d, frequency: %lu; pattern: %lu; count: %lu\r\n", | ||||
|             ret, | ||||
|             frequency, | ||||
|             pattern, | ||||
|             count); | ||||
|         cli_print_usage( | ||||
|             "subghz_tx_pt", "<Frequency in HZ> <Pattern> <Count>", string_get_cstr(args)); | ||||
|         return; | ||||
|     } | ||||
|  | ||||
|     if(!subghz_check_frequency_range(frequency)) { | ||||
|         printf( | ||||
|             "Frequency must be in " CC1101_FREQUENCY_RANGE_STR " range, not %lu\r\n", frequency); | ||||
|         return; | ||||
|     } | ||||
|     if(pattern > 1) { | ||||
|         printf("Pattern must be 1, not %lu\r\n", pattern); | ||||
|     } | ||||
|  | ||||
|     api_hal_subghz_reset(); | ||||
|     api_hal_subghz_idle(); | ||||
|  | ||||
|     api_hal_subghz_load_preset(ApiHalSubGhzPreset2FskPacket); | ||||
|  | ||||
|     frequency = api_hal_subghz_set_frequency_and_path(frequency); | ||||
|     hal_gpio_init(&gpio_cc1101_g0, GpioModeInput, GpioPullNo, GpioSpeedLow); | ||||
|  | ||||
|     uint8_t status = api_hal_subghz_get_status(); | ||||
|     FURI_LOG_D("SUBGHZ CLI", "Status: %02X", status); | ||||
|  | ||||
|     while(!cli_cmd_interrupt_received(cli) && count) { | ||||
|         api_hal_subghz_idle(); | ||||
|         api_hal_subghz_write_packet(subghz_test_packet_data, sizeof(subghz_test_packet_data)); | ||||
|         api_hal_subghz_tx(); | ||||
|         while(!hal_gpio_read(&gpio_cc1101_g0)) osDelay(1); // Wait for sync | ||||
|         while(hal_gpio_read(&gpio_cc1101_g0)) osDelay(1); // Wait end of transaction | ||||
|         count--; | ||||
|     } | ||||
|  | ||||
|     api_hal_subghz_sleep(); | ||||
|     api_hal_subghz_set_path(ApiHalSubGhzPathIsolate); | ||||
| } | ||||
|  | ||||
| void subghz_cli_command_rx_pt(Cli* cli, string_t args, void* context) { | ||||
|     uint32_t frequency = 0; | ||||
|  | ||||
|     int ret = sscanf(string_get_cstr(args), "%lu", &frequency); | ||||
|     if(ret != 1) { | ||||
|         printf("sscanf returned %d, frequency: %lu\r\n", ret, frequency); | ||||
|         cli_print_usage("subghz_rx_pt", "<Frequency in HZ>", string_get_cstr(args)); | ||||
|         return; | ||||
|     } | ||||
|  | ||||
|     if(!subghz_check_frequency_range(frequency)) { | ||||
|         printf( | ||||
|             "Frequency must be in " CC1101_FREQUENCY_RANGE_STR " range, not %lu\r\n", frequency); | ||||
|         return; | ||||
|     } | ||||
|  | ||||
|     api_hal_subghz_reset(); | ||||
|     api_hal_subghz_idle(); | ||||
|     api_hal_subghz_load_preset(ApiHalSubGhzPreset2FskPacket); | ||||
|  | ||||
|     frequency = api_hal_subghz_set_frequency_and_path(frequency); | ||||
|     hal_gpio_init(&gpio_cc1101_g0, GpioModeInput, GpioPullNo, GpioSpeedLow); | ||||
|  | ||||
|     uint8_t status = api_hal_subghz_get_status(); | ||||
|     FURI_LOG_D("SUBGHZ CLI", "Status: %02X", status); | ||||
|     printf("Start receiving packets. Press CTRL+C to stop\r\n"); | ||||
|  | ||||
|     api_hal_subghz_flush_rx(); | ||||
|     api_hal_subghz_rx(); | ||||
|     uint32_t packet_cnt = 0; | ||||
|  | ||||
|     while(!cli_cmd_interrupt_received(cli)) { | ||||
|         if(hal_gpio_read(&gpio_cc1101_g0)) { | ||||
|             while(hal_gpio_read(&gpio_cc1101_g0)) | ||||
|                 ; // Wait reception | ||||
|             packet_cnt++; | ||||
|             api_hal_subghz_idle(); | ||||
|             api_hal_subghz_flush_rx(); | ||||
|             api_hal_subghz_rx(); | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     printf("Received %lu packets", packet_cnt); | ||||
|  | ||||
|     api_hal_subghz_sleep(); | ||||
|     api_hal_subghz_set_path(ApiHalSubGhzPathIsolate); | ||||
|     hal_gpio_init(&gpio_cc1101_g0, GpioModeAnalog, GpioPullNo, GpioSpeedLow); | ||||
| } | ||||
|  | ||||
| #define SUBGHZ_PT_SHORT 260 | ||||
| #define SUBGHZ_PT_SHORT 376 | ||||
| #define SUBGHZ_PT_LONG (SUBGHZ_PT_SHORT * 3) | ||||
| #define SUBGHZ_PT_GUARD 8060 | ||||
| #define SUBGHZ_PT_GUARD 10600 | ||||
|  | ||||
| void subghz_cli_command_tx(Cli* cli, string_t args, void* context) { | ||||
|     uint32_t frequency = 433920000; | ||||
| @@ -227,7 +127,6 @@ void subghz_cli_command_tx(Cli* cli, string_t args, void* context) { | ||||
|                 string_get_cstr(args)); | ||||
|             return; | ||||
|         } | ||||
|  | ||||
|         if(!subghz_check_frequency_range(frequency)) { | ||||
|             printf( | ||||
|                 "Frequency must be in " CC1101_FREQUENCY_RANGE_STR " range, not %lu\r\n", | ||||
| @@ -255,8 +154,14 @@ void subghz_cli_command_tx(Cli* cli, string_t args, void* context) { | ||||
|     subghz_test_data[pos++] = SUBGHZ_PT_SHORT; | ||||
|     subghz_test_data[pos++] = SUBGHZ_PT_SHORT + SUBGHZ_PT_GUARD; | ||||
|  | ||||
|     printf( | ||||
|         "Transmitting at %lu, key %lx, repeat %u. Press CTRL+C to stop\r\n", | ||||
|         frequency, | ||||
|         key, | ||||
|         repeat); | ||||
|  | ||||
|     api_hal_subghz_reset(); | ||||
|     api_hal_subghz_load_preset(ApiHalSubGhzPresetMP); | ||||
|     api_hal_subghz_load_preset(ApiHalSubGhzPresetOokAsync); | ||||
|     frequency = api_hal_subghz_set_frequency_and_path(frequency); | ||||
|  | ||||
|     api_hal_subghz_start_async_tx(subghz_test_data, subghz_test_data_size, repeat); | ||||
| @@ -267,25 +172,36 @@ void subghz_cli_command_tx(Cli* cli, string_t args, void* context) { | ||||
|     api_hal_subghz_sleep(); | ||||
| } | ||||
|  | ||||
| #include <fl_subghz/protocols/subghz_protocol.h> | ||||
| typedef struct { | ||||
|     volatile bool overrun; | ||||
|     StreamBufferHandle_t stream; | ||||
|     size_t packet_count; | ||||
| } SubGhzCliCommandRx; | ||||
|  | ||||
| volatile bool subghz_cli_overrun = false; | ||||
| static void subghz_cli_command_rx_callback(bool level, uint32_t duration, void* context) { | ||||
|     SubGhzCliCommandRx* instance = context; | ||||
|  | ||||
| void subghz_cli_command_rx_callback(bool level, uint32_t duration, void* context) { | ||||
|     BaseType_t xHigherPriorityTaskWoken = pdFALSE; | ||||
|     LevelDuration level_duration = level_duration_make(level, duration); | ||||
|     if(subghz_cli_overrun) { | ||||
|         subghz_cli_overrun = false; | ||||
|     if(instance->overrun) { | ||||
|         instance->overrun = false; | ||||
|         level_duration = level_duration_reset(); | ||||
|     } | ||||
|     size_t ret = xStreamBufferSendFromISR( | ||||
|         context, &level_duration, sizeof(LevelDuration), &xHigherPriorityTaskWoken); | ||||
|     if(sizeof(LevelDuration) != ret) subghz_cli_overrun = true; | ||||
|         instance->stream, &level_duration, sizeof(LevelDuration), &xHigherPriorityTaskWoken); | ||||
|     if(sizeof(LevelDuration) != ret) instance->overrun = true; | ||||
|     portYIELD_FROM_ISR(xHigherPriorityTaskWoken); | ||||
| } | ||||
|  | ||||
| static void subghz_cli_command_rx_text_callback(string_t text, void* context) { | ||||
|     SubGhzCliCommandRx* instance = context; | ||||
|     instance->packet_count++; | ||||
|     printf(string_get_cstr(text)); | ||||
| } | ||||
|  | ||||
| void subghz_cli_command_rx(Cli* cli, string_t args, void* context) { | ||||
|     uint32_t frequency = 433920000; | ||||
|  | ||||
|     if(string_size(args)) { | ||||
|         int ret = sscanf(string_get_cstr(args), "%lu", &frequency); | ||||
|         if(ret != 1) { | ||||
| @@ -293,7 +209,6 @@ void subghz_cli_command_rx(Cli* cli, string_t args, void* context) { | ||||
|             cli_print_usage("subghz_rx", "<Frequency in HZ>", string_get_cstr(args)); | ||||
|             return; | ||||
|         } | ||||
|  | ||||
|         if(!subghz_check_frequency_range(frequency)) { | ||||
|             printf( | ||||
|                 "Frequency must be in " CC1101_FREQUENCY_RANGE_STR " range, not %lu\r\n", | ||||
| @@ -302,26 +217,32 @@ void subghz_cli_command_rx(Cli* cli, string_t args, void* context) { | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     api_hal_subghz_reset(); | ||||
|     api_hal_subghz_load_preset(ApiHalSubGhzPresetMP); | ||||
|     frequency = api_hal_subghz_set_frequency_and_path(frequency); | ||||
|     hal_gpio_init(&gpio_cc1101_g0, GpioModeInput, GpioPullNo, GpioSpeedLow); | ||||
|     // Allocate context and buffers | ||||
|     SubGhzCliCommandRx* instance = furi_alloc(sizeof(SubGhzCliCommandRx)); | ||||
|     instance->stream = xStreamBufferCreate(sizeof(LevelDuration) * 1024, sizeof(LevelDuration)); | ||||
|     furi_check(instance->stream); | ||||
|  | ||||
|     SubGhzProtocol* protocol = subghz_protocol_alloc(); | ||||
|     subghz_protocol_load_keeloq_file(protocol, "/assets/subghz/keeloq_mfcodes"); | ||||
|     subghz_protocol_load_nice_flor_s_file(protocol, "/assets/subghz/nice_floor_s_rx"); | ||||
|     subghz_protocol_enable_dump_text(protocol, NULL, NULL); | ||||
|     subghz_protocol_enable_dump_text(protocol, subghz_cli_command_rx_text_callback, instance); | ||||
|  | ||||
|     StreamBufferHandle_t rx_stream = | ||||
|         xStreamBufferCreate(sizeof(LevelDuration) * 1024, sizeof(LevelDuration)); | ||||
|     // Configure radio | ||||
|     api_hal_subghz_reset(); | ||||
|     api_hal_subghz_load_preset(ApiHalSubGhzPresetOokAsync); | ||||
|     frequency = api_hal_subghz_set_frequency_and_path(frequency); | ||||
|     hal_gpio_init(&gpio_cc1101_g0, GpioModeInput, GpioPullNo, GpioSpeedLow); | ||||
|  | ||||
|     api_hal_subghz_set_async_rx_callback(subghz_cli_command_rx_callback, rx_stream); | ||||
|     // Prepare and start RX | ||||
|     api_hal_subghz_set_async_rx_callback(subghz_cli_command_rx_callback, instance); | ||||
|     api_hal_subghz_start_async_rx(); | ||||
|  | ||||
|     // Wait for packets to arrive | ||||
|     printf("Listening at %lu. Press CTRL+C to stop\r\n", frequency); | ||||
|     LevelDuration level_duration; | ||||
|     while(!cli_cmd_interrupt_received(cli)) { | ||||
|         int ret = xStreamBufferReceive(rx_stream, &level_duration, sizeof(LevelDuration), 10); | ||||
|         int ret = | ||||
|             xStreamBufferReceive(instance->stream, &level_duration, sizeof(LevelDuration), 10); | ||||
|         if(ret == sizeof(LevelDuration)) { | ||||
|             if(level_duration_is_reset(level_duration)) { | ||||
|                 printf("."); | ||||
| @@ -334,8 +255,14 @@ void subghz_cli_command_rx(Cli* cli, string_t args, void* context) { | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     // Shutdown radio | ||||
|     api_hal_subghz_stop_async_rx(); | ||||
|     api_hal_subghz_sleep(); | ||||
|  | ||||
|     printf("\r\nPackets recieved %u\r\n", instance->packet_count); | ||||
|  | ||||
|     // Cleanup | ||||
|     subghz_protocol_free(protocol); | ||||
|     vStreamBufferDelete(rx_stream); | ||||
|     vStreamBufferDelete(instance->stream); | ||||
|     free(instance); | ||||
| } | ||||
|   | ||||
| @@ -8,8 +8,8 @@ | ||||
| #include <gui/elements.h> | ||||
| #include <notification/notification-messages.h> | ||||
|  | ||||
| #include <fl_subghz/subghz_worker.h> | ||||
| #include <fl_subghz/protocols/subghz_protocol.h> | ||||
| #include <lib/subghz/subghz_worker.h> | ||||
| #include <lib/subghz/protocols/subghz_protocol.h> | ||||
|  | ||||
| #include <assets_icons.h> | ||||
|  | ||||
| @@ -143,7 +143,7 @@ void subghz_capture_enter(void* context) { | ||||
|  | ||||
|     api_hal_subghz_reset(); | ||||
|     api_hal_subghz_idle(); | ||||
|     api_hal_subghz_load_preset(ApiHalSubGhzPresetMP); | ||||
|     api_hal_subghz_load_preset(ApiHalSubGhzPresetOokAsync); | ||||
|  | ||||
|     with_view_model( | ||||
|         subghz_capture->view, (SubghzCaptureModel * model) { | ||||
|   | ||||
| @@ -14,8 +14,8 @@ static const uint8_t subghz_static_keys[][4] = { | ||||
|     {0xE3, 0x4A, 0x4E}, | ||||
| }; | ||||
|  | ||||
| #define SUBGHZ_PT_ONE 376 | ||||
| #define SUBGHZ_PT_ZERO (SUBGHZ_PT_ONE * 3) | ||||
| #define SUBGHZ_PT_SHORT 376 | ||||
| #define SUBGHZ_PT_LONG (SUBGHZ_PT_SHORT * 3) | ||||
| #define SUBGHZ_PT_GUARD 10600 | ||||
|  | ||||
| struct SubghzStatic { | ||||
| @@ -101,13 +101,13 @@ bool subghz_static_input(InputEvent* event, void* context) { | ||||
|                             bool value = (key[byte] >> (7 - bit)) & 1; | ||||
|                             // Payload send | ||||
|                             hal_gpio_write(&gpio_cc1101_g0, true); | ||||
|                             delay_us(value ? SUBGHZ_PT_ONE : SUBGHZ_PT_ZERO); | ||||
|                             delay_us(value ? SUBGHZ_PT_SHORT : SUBGHZ_PT_LONG); | ||||
|                             hal_gpio_write(&gpio_cc1101_g0, false); | ||||
|                             delay_us(value ? SUBGHZ_PT_ZERO : SUBGHZ_PT_ONE); | ||||
|                             delay_us(value ? SUBGHZ_PT_LONG : SUBGHZ_PT_SHORT); | ||||
|                         } | ||||
|                         // Last bit | ||||
|                         hal_gpio_write(&gpio_cc1101_g0, true); | ||||
|                         delay_us(SUBGHZ_PT_ONE); | ||||
|                         delay_us(SUBGHZ_PT_SHORT); | ||||
|                         hal_gpio_write(&gpio_cc1101_g0, false); | ||||
|                         // Guard time | ||||
|                         delay_us(10600); | ||||
|   | ||||
| @@ -5,18 +5,23 @@ | ||||
| #include <furi.h> | ||||
| #include <api-hal.h> | ||||
| #include <input/input.h> | ||||
| #include <toolbox/level_duration.h> | ||||
| #include <lib/subghz/protocols/subghz_protocol_princeton.h> | ||||
|  | ||||
| static const uint8_t subghz_test_packet_data[] = { | ||||
|     0x30, // 48bytes to transmit | ||||
|     'F',  'L', 'I', 'P', 'P', 'E', 'R', ' ', 'T', 'E', 'S', 'T', ' ', 'P', 'A', 'C', | ||||
|     'K',  'E', 'T', ' ', 'D', 'A', 'T', 'A', ' ', 'A', 'N', 'D', ' ', 'P', 'A', 'D', | ||||
|     'F',  'L', 'I', 'P', 'P', 'E', 'R', ' ', 'T', 'E', 'S', 'T', ' ', 'P', 'A', 'C', | ||||
| #define SUBGHZ_TEST_PACKET_COUNT 1000 | ||||
|  | ||||
| }; | ||||
| #define SUBGHZ_PT_SHORT 376 | ||||
| #define SUBGHZ_PT_LONG (SUBGHZ_PT_SHORT * 3) | ||||
| #define SUBGHZ_PT_GUARD 10600 | ||||
|  | ||||
| struct SubghzTestPacket { | ||||
|     View* view; | ||||
|     osTimerId timer; | ||||
|     size_t tx_buffer_size; | ||||
|     uint32_t* tx_buffer; | ||||
|     SubGhzProtocolPrinceton* princeton; | ||||
|  | ||||
|     volatile size_t packet_rx; | ||||
| }; | ||||
|  | ||||
| typedef enum { | ||||
| @@ -29,10 +34,42 @@ typedef struct { | ||||
|     uint32_t real_frequency; | ||||
|     ApiHalSubGhzPath path; | ||||
|     float rssi; | ||||
|     size_t packets; | ||||
|     SubghzTestPacketModelStatus status; | ||||
| } SubghzTestPacketModel; | ||||
|  | ||||
| void subghz_test_packet_draw(Canvas* canvas, SubghzTestPacketModel* model) { | ||||
| volatile bool subghz_test_packet_overrun = false; | ||||
|  | ||||
| static void subghz_test_packet_rx_callback(bool level, uint32_t duration, void* context) { | ||||
|     furi_assert(context); | ||||
|     SubghzTestPacket* instance = context; | ||||
|     subghz_protocol_princeton_parse(instance->princeton, level, duration); | ||||
| } | ||||
|  | ||||
| static void subghz_test_packet_rx_pt_callback(SubGhzProtocolCommon* parser, void* context) { | ||||
|     furi_assert(context); | ||||
|     SubghzTestPacket* instance = context; | ||||
|     instance->packet_rx++; | ||||
| } | ||||
|  | ||||
| static void subghz_test_packet_rssi_timer_callback(void* context) { | ||||
|     furi_assert(context); | ||||
|     SubghzTestPacket* instance = context; | ||||
|  | ||||
|     with_view_model( | ||||
|         instance->view, (SubghzTestPacketModel * model) { | ||||
|             if(model->status == SubghzTestPacketModelStatusRx) { | ||||
|                 model->rssi = api_hal_subghz_get_rssi(); | ||||
|                 model->packets = instance->packet_rx; | ||||
|             } else { | ||||
|                 model->packets = | ||||
|                     SUBGHZ_TEST_PACKET_COUNT - api_hal_subghz_get_async_tx_repeat_left(); | ||||
|             } | ||||
|             return true; | ||||
|         }); | ||||
| } | ||||
|  | ||||
| static void subghz_test_packet_draw(Canvas* canvas, SubghzTestPacketModel* model) { | ||||
|     char buffer[64]; | ||||
|  | ||||
|     canvas_set_color(canvas, ColorBlack); | ||||
| @@ -62,6 +99,10 @@ void subghz_test_packet_draw(Canvas* canvas, SubghzTestPacketModel* model) { | ||||
|     } | ||||
|     snprintf(buffer, sizeof(buffer), "Path: %d - %s", model->path, path_name); | ||||
|     canvas_draw_str(canvas, 0, 31, buffer); | ||||
|  | ||||
|     snprintf(buffer, sizeof(buffer), "Packets: %d", model->packets); | ||||
|     canvas_draw_str(canvas, 0, 42, buffer); | ||||
|  | ||||
|     if(model->status == SubghzTestPacketModelStatusRx) { | ||||
|         snprintf( | ||||
|             buffer, | ||||
| @@ -69,24 +110,27 @@ void subghz_test_packet_draw(Canvas* canvas, SubghzTestPacketModel* model) { | ||||
|             "RSSI: %ld.%ld dBm", | ||||
|             (int32_t)(model->rssi), | ||||
|             (int32_t)fabs(model->rssi * 10) % 10); | ||||
|         canvas_draw_str(canvas, 0, 42, buffer); | ||||
|         canvas_draw_str(canvas, 0, 53, buffer); | ||||
|     } else { | ||||
|         canvas_draw_str(canvas, 0, 42, "TX"); | ||||
|         canvas_draw_str(canvas, 0, 53, "TX"); | ||||
|     } | ||||
| } | ||||
|  | ||||
| bool subghz_test_packet_input(InputEvent* event, void* context) { | ||||
| static bool subghz_test_packet_input(InputEvent* event, void* context) { | ||||
|     furi_assert(context); | ||||
|     SubghzTestPacket* subghz_test_packet = context; | ||||
|     SubghzTestPacket* instance = context; | ||||
|  | ||||
|     if(event->key == InputKeyBack) { | ||||
|         return false; | ||||
|     } | ||||
|  | ||||
|     with_view_model( | ||||
|         subghz_test_packet->view, (SubghzTestPacketModel * model) { | ||||
|             osTimerStop(subghz_test_packet->timer); | ||||
|             api_hal_subghz_idle(); | ||||
|         instance->view, (SubghzTestPacketModel * model) { | ||||
|             if(model->status == SubghzTestPacketModelStatusRx) { | ||||
|                 api_hal_subghz_stop_async_rx(); | ||||
|             } else { | ||||
|                 api_hal_subghz_stop_async_tx(); | ||||
|             } | ||||
|  | ||||
|             if(event->type == InputTypeShort) { | ||||
|                 if(event->key == InputKeyLeft) { | ||||
| @@ -111,12 +155,10 @@ bool subghz_test_packet_input(InputEvent* event, void* context) { | ||||
|             } | ||||
|  | ||||
|             if(model->status == SubghzTestPacketModelStatusRx) { | ||||
|                 api_hal_subghz_rx(); | ||||
|                 osTimerStart(subghz_test_packet->timer, 1024 / 4); | ||||
|                 api_hal_subghz_start_async_rx(); | ||||
|             } else { | ||||
|                 api_hal_subghz_write_packet( | ||||
|                     subghz_test_packet_data, sizeof(subghz_test_packet_data)); | ||||
|                 api_hal_subghz_tx(); | ||||
|                 api_hal_subghz_start_async_tx( | ||||
|                     instance->tx_buffer, instance->tx_buffer_size, SUBGHZ_TEST_PACKET_COUNT); | ||||
|             } | ||||
|  | ||||
|             return true; | ||||
| @@ -127,15 +169,35 @@ bool subghz_test_packet_input(InputEvent* event, void* context) { | ||||
|  | ||||
| void subghz_test_packet_enter(void* context) { | ||||
|     furi_assert(context); | ||||
|     SubghzTestPacket* subghz_test_packet = context; | ||||
|     SubghzTestPacket* instance = context; | ||||
|  | ||||
|     instance->tx_buffer_size = 25 * 2 * sizeof(uint32_t); | ||||
|     instance->tx_buffer = furi_alloc(instance->tx_buffer_size); | ||||
|  | ||||
|     const uint32_t key = 0x00ABCDEF; | ||||
|  | ||||
|     size_t pos = 0; | ||||
|     for(uint8_t i = 0; i < 24; i++) { | ||||
|         uint8_t byte = i / 8; | ||||
|         uint8_t bit = i % 8; | ||||
|         bool value = (((uint8_t*)&key)[2 - byte] >> (7 - bit)) & 1; | ||||
|         if(value) { | ||||
|             instance->tx_buffer[pos++] = SUBGHZ_PT_SHORT; | ||||
|             instance->tx_buffer[pos++] = SUBGHZ_PT_LONG; | ||||
|         } else { | ||||
|             instance->tx_buffer[pos++] = SUBGHZ_PT_LONG; | ||||
|             instance->tx_buffer[pos++] = SUBGHZ_PT_SHORT; | ||||
|         } | ||||
|     } | ||||
|     instance->tx_buffer[pos++] = SUBGHZ_PT_SHORT; | ||||
|     instance->tx_buffer[pos++] = SUBGHZ_PT_SHORT + SUBGHZ_PT_GUARD; | ||||
|  | ||||
|     api_hal_subghz_reset(); | ||||
|     api_hal_subghz_load_preset(ApiHalSubGhzPreset2FskPacket); | ||||
|  | ||||
|     hal_gpio_init(&gpio_cc1101_g0, GpioModeInput, GpioPullNo, GpioSpeedLow); | ||||
|     api_hal_subghz_load_preset(ApiHalSubGhzPresetOokAsync); | ||||
|     api_hal_subghz_set_async_rx_callback(subghz_test_packet_rx_callback, instance); | ||||
|  | ||||
|     with_view_model( | ||||
|         subghz_test_packet->view, (SubghzTestPacketModel * model) { | ||||
|         instance->view, (SubghzTestPacketModel * model) { | ||||
|             model->frequency = subghz_frequencies_433_92; | ||||
|             model->real_frequency = | ||||
|                 api_hal_subghz_set_frequency(subghz_frequencies[model->frequency]); | ||||
| @@ -145,30 +207,29 @@ void subghz_test_packet_enter(void* context) { | ||||
|             return true; | ||||
|         }); | ||||
|  | ||||
|     api_hal_subghz_rx(); | ||||
|     api_hal_subghz_start_async_rx(); | ||||
|  | ||||
|     osTimerStart(subghz_test_packet->timer, 1024 / 4); | ||||
|     osTimerStart(instance->timer, 1024 / 4); | ||||
| } | ||||
|  | ||||
| void subghz_test_packet_exit(void* context) { | ||||
|     furi_assert(context); | ||||
|     SubghzTestPacket* subghz_test_packet = context; | ||||
|     SubghzTestPacket* instance = context; | ||||
|  | ||||
|     osTimerStop(subghz_test_packet->timer); | ||||
|     osTimerStop(instance->timer); | ||||
|  | ||||
|     // Reinitialize IC to default state | ||||
|     api_hal_subghz_sleep(); | ||||
| } | ||||
|  | ||||
| void subghz_test_packet_rssi_timer_callback(void* context) { | ||||
|     furi_assert(context); | ||||
|     SubghzTestPacket* subghz_test_packet = context; | ||||
|  | ||||
|     with_view_model( | ||||
|         subghz_test_packet->view, (SubghzTestPacketModel * model) { | ||||
|             model->rssi = api_hal_subghz_get_rssi(); | ||||
|         instance->view, (SubghzTestPacketModel * model) { | ||||
|             if(model->status == SubghzTestPacketModelStatusRx) { | ||||
|                 api_hal_subghz_stop_async_rx(); | ||||
|             } else { | ||||
|                 api_hal_subghz_stop_async_tx(); | ||||
|             } | ||||
|             return true; | ||||
|         }); | ||||
|     api_hal_subghz_set_async_rx_callback(NULL, NULL); | ||||
|     api_hal_subghz_sleep(); | ||||
| } | ||||
|  | ||||
| uint32_t subghz_test_packet_back(void* context) { | ||||
| @@ -176,33 +237,38 @@ uint32_t subghz_test_packet_back(void* context) { | ||||
| } | ||||
|  | ||||
| SubghzTestPacket* subghz_test_packet_alloc() { | ||||
|     SubghzTestPacket* subghz_test_packet = furi_alloc(sizeof(SubghzTestPacket)); | ||||
|     SubghzTestPacket* instance = furi_alloc(sizeof(SubghzTestPacket)); | ||||
|  | ||||
|     // View allocation and configuration | ||||
|     subghz_test_packet->view = view_alloc(); | ||||
|     view_allocate_model( | ||||
|         subghz_test_packet->view, ViewModelTypeLockFree, sizeof(SubghzTestPacketModel)); | ||||
|     view_set_context(subghz_test_packet->view, subghz_test_packet); | ||||
|     view_set_draw_callback(subghz_test_packet->view, (ViewDrawCallback)subghz_test_packet_draw); | ||||
|     view_set_input_callback(subghz_test_packet->view, subghz_test_packet_input); | ||||
|     view_set_enter_callback(subghz_test_packet->view, subghz_test_packet_enter); | ||||
|     view_set_exit_callback(subghz_test_packet->view, subghz_test_packet_exit); | ||||
|     view_set_previous_callback(subghz_test_packet->view, subghz_test_packet_back); | ||||
|     instance->view = view_alloc(); | ||||
|     view_allocate_model(instance->view, ViewModelTypeLockFree, sizeof(SubghzTestPacketModel)); | ||||
|     view_set_context(instance->view, instance); | ||||
|     view_set_draw_callback(instance->view, (ViewDrawCallback)subghz_test_packet_draw); | ||||
|     view_set_input_callback(instance->view, subghz_test_packet_input); | ||||
|     view_set_enter_callback(instance->view, subghz_test_packet_enter); | ||||
|     view_set_exit_callback(instance->view, subghz_test_packet_exit); | ||||
|     view_set_previous_callback(instance->view, subghz_test_packet_back); | ||||
|  | ||||
|     subghz_test_packet->timer = osTimerNew( | ||||
|         subghz_test_packet_rssi_timer_callback, osTimerPeriodic, subghz_test_packet, NULL); | ||||
|     instance->timer = | ||||
|         osTimerNew(subghz_test_packet_rssi_timer_callback, osTimerPeriodic, instance, NULL); | ||||
|  | ||||
|     return subghz_test_packet; | ||||
|     instance->princeton = subghz_protocol_princeton_alloc(); | ||||
|     subghz_protocol_common_set_callback( | ||||
|         (SubGhzProtocolCommon*)instance->princeton, subghz_test_packet_rx_pt_callback, instance); | ||||
|  | ||||
|     return instance; | ||||
| } | ||||
|  | ||||
| void subghz_test_packet_free(SubghzTestPacket* subghz_test_packet) { | ||||
|     furi_assert(subghz_test_packet); | ||||
|     osTimerDelete(subghz_test_packet->timer); | ||||
|     view_free(subghz_test_packet->view); | ||||
|     free(subghz_test_packet); | ||||
| void subghz_test_packet_free(SubghzTestPacket* instance) { | ||||
|     furi_assert(instance); | ||||
|  | ||||
|     subghz_protocol_princeton_free(instance->princeton); | ||||
|     osTimerDelete(instance->timer); | ||||
|     view_free(instance->view); | ||||
|     free(instance); | ||||
| } | ||||
|  | ||||
| View* subghz_test_packet_get_view(SubghzTestPacket* subghz_test_packet) { | ||||
|     furi_assert(subghz_test_packet); | ||||
|     return subghz_test_packet->view; | ||||
| View* subghz_test_packet_get_view(SubghzTestPacket* instance) { | ||||
|     furi_assert(instance); | ||||
|     return instance->view; | ||||
| } | ||||
|   | ||||
		Reference in New Issue
	
	Block a user