SubGhz: sending / receiving messages via subghz (#851)
* SubGhz: add worker subghz_txrx * SubGhz: added support for transferring Russian characters and support for backspace in CLI subghz_txrx * SubGhz: refactoring subghz_txrx_worker, added a callback for accepting data in an empty one RX buffer * SubGhz: fix conflict * SubGhz: fix syntax errors * Cli: document string_move usage and its behavior * FuriHal: update subghz api and documentation. Subghz: move chat to subghz cli subcommand. * Subghz: update text in chat cli Co-authored-by: Aleksandr Kutuzov <alleteam@gmail.com>
This commit is contained in:
		
							parent
							
								
									54c41e4189
								
							
						
					
					
						commit
						b912cc7991
					
				| @ -113,7 +113,9 @@ void cli_prompt(Cli* cli) { | |||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void cli_reset(Cli* cli) { | void cli_reset(Cli* cli) { | ||||||
|  |     // cli->last_line is cleared and cli->line's buffer moved to cli->last_line
 | ||||||
|     string_move(cli->last_line, cli->line); |     string_move(cli->last_line, cli->line); | ||||||
|  |     // Reiniting cli->line
 | ||||||
|     string_init(cli->line); |     string_init(cli->line); | ||||||
|     cli->cursor_position = 0; |     cli->cursor_position = 0; | ||||||
| } | } | ||||||
| @ -129,7 +131,11 @@ static void cli_handle_backspace(Cli* cli) { | |||||||
|         string_reserve(temp, string_size(cli->line) - 1); |         string_reserve(temp, string_size(cli->line) - 1); | ||||||
|         string_set_strn(temp, string_get_cstr(cli->line), cli->cursor_position - 1); |         string_set_strn(temp, string_get_cstr(cli->line), cli->cursor_position - 1); | ||||||
|         string_cat_str(temp, string_get_cstr(cli->line) + cli->cursor_position); |         string_cat_str(temp, string_get_cstr(cli->line) + cli->cursor_position); | ||||||
|  | 
 | ||||||
|  |         // cli->line is cleared and temp's buffer moved to cli->line
 | ||||||
|         string_move(cli->line, temp); |         string_move(cli->line, temp); | ||||||
|  |         // NO MEMORY LEAK, STOP REPORTING IT
 | ||||||
|  | 
 | ||||||
|         cli->cursor_position--; |         cli->cursor_position--; | ||||||
|     } else { |     } else { | ||||||
|         cli_putc(CliSymbolAsciiBell); |         cli_putc(CliSymbolAsciiBell); | ||||||
| @ -332,7 +338,11 @@ void cli_process_input(Cli* cli) { | |||||||
|             string_set_strn(temp, string_get_cstr(cli->line), cli->cursor_position); |             string_set_strn(temp, string_get_cstr(cli->line), cli->cursor_position); | ||||||
|             string_push_back(temp, c); |             string_push_back(temp, c); | ||||||
|             string_cat_str(temp, string_get_cstr(cli->line) + cli->cursor_position); |             string_cat_str(temp, string_get_cstr(cli->line) + cli->cursor_position); | ||||||
|  | 
 | ||||||
|  |             // cli->line is cleared and temp's buffer moved to cli->line
 | ||||||
|             string_move(cli->line, temp); |             string_move(cli->line, temp); | ||||||
|  |             // NO MEMORY LEAK, STOP REPORTING IT
 | ||||||
|  | 
 | ||||||
|             // Print character in replace mode
 |             // Print character in replace mode
 | ||||||
|             printf("\e[4h%c\e[4l", c); |             printf("\e[4h%c\e[4l", c); | ||||||
|             fflush(stdout); |             fflush(stdout); | ||||||
|  | |||||||
| @ -9,11 +9,12 @@ | |||||||
| #include <lib/subghz/subghz_keystore.h> | #include <lib/subghz/subghz_keystore.h> | ||||||
| #include <lib/subghz/protocols/subghz_protocol_common.h> | #include <lib/subghz/protocols/subghz_protocol_common.h> | ||||||
| #include <lib/subghz/protocols/subghz_protocol_princeton.h> | #include <lib/subghz/protocols/subghz_protocol_princeton.h> | ||||||
|  | #include <lib/subghz/subghz_tx_rx_worker.h> | ||||||
| 
 | 
 | ||||||
| #define SUBGHZ_FREQUENCY_RANGE_STR \ | #define SUBGHZ_FREQUENCY_RANGE_STR \ | ||||||
|     "299999755...348000000 or 386999938...464000000 or 778999847...928000000" |     "299999755...348000000 or 386999938...464000000 or 778999847...928000000" | ||||||
| 
 | 
 | ||||||
| void subghz_cli_command_tx_carrier(Cli* cli, string_t args, void* context) { | static void subghz_cli_command_tx_carrier(Cli* cli, string_t args, void* context) { | ||||||
|     uint32_t frequency = 433920000; |     uint32_t frequency = 433920000; | ||||||
| 
 | 
 | ||||||
|     if(string_size(args)) { |     if(string_size(args)) { | ||||||
| @ -56,7 +57,7 @@ void subghz_cli_command_tx_carrier(Cli* cli, string_t args, void* context) { | |||||||
|     furi_hal_power_suppress_charge_exit(); |     furi_hal_power_suppress_charge_exit(); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void subghz_cli_command_rx_carrier(Cli* cli, string_t args, void* context) { | static void subghz_cli_command_rx_carrier(Cli* cli, string_t args, void* context) { | ||||||
|     uint32_t frequency = 433920000; |     uint32_t frequency = 433920000; | ||||||
| 
 | 
 | ||||||
|     if(string_size(args)) { |     if(string_size(args)) { | ||||||
| @ -96,7 +97,7 @@ void subghz_cli_command_rx_carrier(Cli* cli, string_t args, void* context) { | |||||||
|     furi_hal_subghz_sleep(); |     furi_hal_subghz_sleep(); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void subghz_cli_command_tx(Cli* cli, string_t args, void* context) { | static void subghz_cli_command_tx(Cli* cli, string_t args, void* context) { | ||||||
|     uint32_t frequency = 433920000; |     uint32_t frequency = 433920000; | ||||||
|     uint32_t key = 0x0074BADE; |     uint32_t key = 0x0074BADE; | ||||||
|     size_t repeat = 10; |     size_t repeat = 10; | ||||||
| @ -187,7 +188,7 @@ static void subghz_cli_command_rx_text_callback(string_t text, void* context) { | |||||||
|     printf("%s", string_get_cstr(text)); |     printf("%s", string_get_cstr(text)); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void subghz_cli_command_rx(Cli* cli, string_t args, void* context) { | static void subghz_cli_command_rx(Cli* cli, string_t args, void* context) { | ||||||
|     uint32_t frequency = 433920000; |     uint32_t frequency = 433920000; | ||||||
| 
 | 
 | ||||||
|     if(string_size(args)) { |     if(string_size(args)) { | ||||||
| @ -260,7 +261,7 @@ void subghz_cli_command_rx(Cli* cli, string_t args, void* context) { | |||||||
|     free(instance); |     free(instance); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void subghz_cli_command_print_usage() { | static void subghz_cli_command_print_usage() { | ||||||
|     printf("Usage:\r\n"); |     printf("Usage:\r\n"); | ||||||
|     printf("subghz <cmd> <args>\r\n"); |     printf("subghz <cmd> <args>\r\n"); | ||||||
|     printf("Cmd list:\r\n"); |     printf("Cmd list:\r\n"); | ||||||
| @ -268,9 +269,10 @@ void subghz_cli_command_print_usage() { | |||||||
|         "\tencrypt_keeloq <path_decrypted_file> <path_encrypted_file> <IV:16 bytes in hex>\t - Encrypt keeloq manufacture keys\r\n"); |         "\tencrypt_keeloq <path_decrypted_file> <path_encrypted_file> <IV:16 bytes in hex>\t - Encrypt keeloq manufacture keys\r\n"); | ||||||
|     printf( |     printf( | ||||||
|         "\tencrypt_raw <path_decrypted_file> <path_encrypted_file> <IV:16 bytes in hex>\t - Encrypt RAW data\r\n"); |         "\tencrypt_raw <path_decrypted_file> <path_encrypted_file> <IV:16 bytes in hex>\t - Encrypt RAW data\r\n"); | ||||||
|  |     printf("\tchat <frequency:in Herz>\t - Chat with other Flippers\r\n"); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void subghz_cli_command_encrypt_keeloq(Cli* cli, string_t args) { | static void subghz_cli_command_encrypt_keeloq(Cli* cli, string_t args) { | ||||||
|     uint8_t iv[16]; |     uint8_t iv[16]; | ||||||
| 
 | 
 | ||||||
|     string_t source; |     string_t source; | ||||||
| @ -312,7 +314,7 @@ void subghz_cli_command_encrypt_keeloq(Cli* cli, string_t args) { | |||||||
|     string_clear(source); |     string_clear(source); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void subghz_cli_command_encrypt_raw(Cli* cli, string_t args) { | static void subghz_cli_command_encrypt_raw(Cli* cli, string_t args) { | ||||||
|     uint8_t iv[16]; |     uint8_t iv[16]; | ||||||
| 
 | 
 | ||||||
|     string_t source; |     string_t source; | ||||||
| @ -348,7 +350,110 @@ void subghz_cli_command_encrypt_raw(Cli* cli, string_t args) { | |||||||
|     string_clear(source); |     string_clear(source); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void subghz_cli_command(Cli* cli, string_t args, void* context) { | static void subghz_cli_command_chat(Cli* cli, string_t args) { | ||||||
|  |     uint32_t frequency = 433920000; | ||||||
|  | 
 | ||||||
|  |     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_txrx", "<Frequency in HZ>", string_get_cstr(args)); | ||||||
|  |             return; | ||||||
|  |         } | ||||||
|  |         if(!furi_hal_subghz_is_frequency_valid(frequency)) { | ||||||
|  |             printf( | ||||||
|  |                 "Frequency must be in " SUBGHZ_FREQUENCY_RANGE_STR " range, not %lu\r\n", | ||||||
|  |                 frequency); | ||||||
|  |             return; | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  |     if(!furi_hal_subghz_is_tx_allowed(frequency)) { | ||||||
|  |         printf( | ||||||
|  |             "In your region, only reception on this frequency (%lu) is allowed,\r\n" | ||||||
|  |             "the actual operation of the application is not possible\r\n ", | ||||||
|  |             frequency); | ||||||
|  |         return; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     SubGhzTxRxWorker* subghz_txrx = subghz_tx_rx_worker_alloc(); | ||||||
|  |     subghz_tx_rx_worker_start(subghz_txrx, frequency); | ||||||
|  | 
 | ||||||
|  |     printf("Receiving at frequency %lu Hz\r\n", frequency); | ||||||
|  |     printf("Press CTRL+C to stop\r\n"); | ||||||
|  | 
 | ||||||
|  |     furi_hal_power_suppress_charge_enter(); | ||||||
|  |     size_t message_max_len = 64; | ||||||
|  |     uint8_t message[64] = {0}; | ||||||
|  |     string_t input; | ||||||
|  |     string_init(input); | ||||||
|  |     string_t name; | ||||||
|  |     string_init(name); | ||||||
|  |     char c; | ||||||
|  |     bool exit = false; | ||||||
|  | 
 | ||||||
|  |     string_printf(name, "\033[0;33m%s\033[0m: ", furi_hal_version_get_name_ptr()); | ||||||
|  |     string_set(input, name); | ||||||
|  |     printf("%s", string_get_cstr(input)); | ||||||
|  |     fflush(stdout); | ||||||
|  | 
 | ||||||
|  |     while(!exit) { | ||||||
|  |         if(furi_hal_vcp_rx_with_timeout((uint8_t*)&c, 1, 0) == 1) { | ||||||
|  |             if(c == CliSymbolAsciiETX) { | ||||||
|  |                 printf("\r\n"); | ||||||
|  |                 exit = true; | ||||||
|  |                 break; | ||||||
|  |             } else if((c >= 0x20 && c < 0x7F) || (c >= 0x80 && c < 0xF0)) { | ||||||
|  |                 putc(c, stdout); | ||||||
|  |                 fflush(stdout); | ||||||
|  |                 string_push_back(input, c); | ||||||
|  |             } else if(c == CliSymbolAsciiBackspace) { | ||||||
|  |                 size_t len = string_size(input); | ||||||
|  |                 if(len > string_size(name)) { | ||||||
|  |                     string_set_strn(input, string_get_cstr(input), len - 1); | ||||||
|  |                     printf("\r"); | ||||||
|  |                     for(uint8_t i = 0; i < len; i++) { | ||||||
|  |                         printf(" "); | ||||||
|  |                     } | ||||||
|  |                     printf("\r%s", string_get_cstr(input)); | ||||||
|  |                     fflush(stdout); | ||||||
|  |                 } | ||||||
|  |             } else if(c == CliSymbolAsciiCR) { | ||||||
|  |                 printf("\r\n"); | ||||||
|  |                 subghz_tx_rx_worker_write( | ||||||
|  |                     subghz_txrx, (uint8_t*)string_get_cstr(input), strlen(string_get_cstr(input))); | ||||||
|  |                 string_printf(input, "%s", string_get_cstr(name)); | ||||||
|  |                 printf("%s", string_get_cstr(input)); | ||||||
|  |                 fflush(stdout); | ||||||
|  |             } | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         if(subghz_tx_rx_worker_available(subghz_txrx)) { | ||||||
|  |             memset(message, 0x00, message_max_len); | ||||||
|  |             subghz_tx_rx_worker_read(subghz_txrx, message, message_max_len); | ||||||
|  |             printf("\r"); | ||||||
|  |             for(uint8_t i = 0; i < 80; i++) { | ||||||
|  |                 printf(" "); | ||||||
|  |             } | ||||||
|  | 
 | ||||||
|  |             printf("\r %s\r\n", message); | ||||||
|  | 
 | ||||||
|  |             printf("%s", string_get_cstr(input)); | ||||||
|  |             fflush(stdout); | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     printf("\r\nExit chat\r\n"); | ||||||
|  |     string_clear(input); | ||||||
|  |     string_clear(name); | ||||||
|  |     furi_hal_power_suppress_charge_exit(); | ||||||
|  | 
 | ||||||
|  |     if(subghz_tx_rx_worker_is_running(subghz_txrx)) { | ||||||
|  |         subghz_tx_rx_worker_stop(subghz_txrx); | ||||||
|  |         subghz_tx_rx_worker_free(subghz_txrx); | ||||||
|  |     } | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | static void subghz_cli_command(Cli* cli, string_t args, void* context) { | ||||||
|     string_t cmd; |     string_t cmd; | ||||||
|     string_init(cmd); |     string_init(cmd); | ||||||
| 
 | 
 | ||||||
| @ -368,6 +473,11 @@ void subghz_cli_command(Cli* cli, string_t args, void* context) { | |||||||
|             break; |             break; | ||||||
|         } |         } | ||||||
| 
 | 
 | ||||||
|  |         if(string_cmp_str(cmd, "chat") == 0) { | ||||||
|  |             subghz_cli_command_chat(cli, args); | ||||||
|  |             break; | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|         subghz_cli_command_print_usage(); |         subghz_cli_command_print_usage(); | ||||||
|     } while(false); |     } while(false); | ||||||
| 
 | 
 | ||||||
|  | |||||||
| @ -244,6 +244,54 @@ static const uint8_t furi_hal_subghz_preset_2fsk_dev4_76khz_async_regs[][2] = { | |||||||
|     /* End  */ |     /* End  */ | ||||||
|     {0, 0}, |     {0, 0}, | ||||||
| }; | }; | ||||||
|  | static const uint8_t furi_hal_subghz_preset_msk_99_97kb_async_regs[][2] = { | ||||||
|  |     /* GPIO GD0 */ | ||||||
|  |     {CC1101_IOCFG0, 0x06}, | ||||||
|  | 
 | ||||||
|  |     {CC1101_FIFOTHR, 0x07}, // The only important bit is ADC_RETENTION
 | ||||||
|  |     {CC1101_SYNC1, 0x46}, | ||||||
|  |     {CC1101_SYNC0, 0x4C}, | ||||||
|  |     {CC1101_ADDR, 0x00}, | ||||||
|  |     {CC1101_PKTLEN, 0x00}, | ||||||
|  |     {CC1101_CHANNR, 0x00}, | ||||||
|  | 
 | ||||||
|  |     {CC1101_PKTCTRL0, 0x05}, | ||||||
|  | 
 | ||||||
|  |     {CC1101_FSCTRL0, 0x23}, | ||||||
|  |     {CC1101_FSCTRL1, 0x06}, | ||||||
|  | 
 | ||||||
|  |     {CC1101_MDMCFG0, 0xF8}, | ||||||
|  |     {CC1101_MDMCFG1, 0x22}, | ||||||
|  |     {CC1101_MDMCFG2, 0x72}, | ||||||
|  |     {CC1101_MDMCFG3, 0xF8}, | ||||||
|  |     {CC1101_MDMCFG4, 0x5B}, | ||||||
|  |     {CC1101_DEVIATN, 0x47}, | ||||||
|  | 
 | ||||||
|  |     {CC1101_MCSM0, 0x18}, | ||||||
|  |     {CC1101_FOCCFG, 0x16}, | ||||||
|  | 
 | ||||||
|  |     {CC1101_AGCCTRL0, 0xB2}, | ||||||
|  |     {CC1101_AGCCTRL1, 0x00}, | ||||||
|  |     {CC1101_AGCCTRL2, 0xC7}, | ||||||
|  | 
 | ||||||
|  |     {CC1101_FREND0, 0x10}, | ||||||
|  |     {CC1101_FREND1, 0x56}, | ||||||
|  | 
 | ||||||
|  |     {CC1101_FSCAL3, 0xE9}, | ||||||
|  |     {CC1101_FSCAL2, 0x2A}, | ||||||
|  |     {CC1101_FSCAL1, 0x00}, | ||||||
|  |     {CC1101_FSCAL0, 0x1F}, | ||||||
|  | 
 | ||||||
|  |     {CC1101_BSCFG, 0x1C}, | ||||||
|  |     {CC1101_FSTEST, 0x59}, | ||||||
|  | 
 | ||||||
|  |     {CC1101_TEST2, 0x81}, | ||||||
|  |     {CC1101_TEST1, 0x35}, | ||||||
|  |     {CC1101_TEST0, 0x09}, | ||||||
|  |     /* End  */ | ||||||
|  |     {0, 0}, | ||||||
|  | }; | ||||||
|  | 
 | ||||||
| static const uint8_t furi_hal_subghz_preset_ook_async_patable[8] = { | static const uint8_t furi_hal_subghz_preset_ook_async_patable[8] = { | ||||||
|     0x00, |     0x00, | ||||||
|     0xC0, // 10dBm 0xC0, 7dBm 0xC8, 5dBm 0x84, 0dBm 0x60, -10dBm 0x34, -15dBm 0x1D, -20dBm 0x0E, -30dBm 0x12
 |     0xC0, // 10dBm 0xC0, 7dBm 0xC8, 5dBm 0x84, 0dBm 0x60, -10dBm 0x34, -15dBm 0x1D, -20dBm 0x0E, -30dBm 0x12
 | ||||||
| @ -261,9 +309,16 @@ static const uint8_t furi_hal_subghz_preset_2fsk_async_patable[8] = { | |||||||
|     0x00, |     0x00, | ||||||
|     0x00, |     0x00, | ||||||
|     0x00, |     0x00, | ||||||
|     0x00 |     0x00}; | ||||||
| 
 | static const uint8_t furi_hal_subghz_preset_msk_async_patable[8] = { | ||||||
| }; |     0xC0, // 10dBm 0xC0, 7dBm 0xC8, 5dBm 0x84, 0dBm 0x60, -10dBm 0x34, -15dBm 0x1D, -20dBm 0x0E, -30dBm 0x12
 | ||||||
|  |     0x00, | ||||||
|  |     0x00, | ||||||
|  |     0x00, | ||||||
|  |     0x00, | ||||||
|  |     0x00, | ||||||
|  |     0x00, | ||||||
|  |     0x00}; | ||||||
| 
 | 
 | ||||||
| void furi_hal_subghz_init() { | void furi_hal_subghz_init() { | ||||||
|     furi_assert(furi_hal_subghz_state == SubGhzStateInit); |     furi_assert(furi_hal_subghz_state == SubGhzStateInit); | ||||||
| @ -344,6 +399,9 @@ void furi_hal_subghz_load_preset(FuriHalSubGhzPreset preset) { | |||||||
|     } else if(preset == FuriHalSubGhzPreset2FSKDev476Async) { |     } 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_dev4_76khz_async_regs); | ||||||
|         furi_hal_subghz_load_patable(furi_hal_subghz_preset_2fsk_async_patable); |         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); | ||||||
|  |         furi_hal_subghz_load_patable(furi_hal_subghz_preset_msk_async_patable); | ||||||
|     } else { |     } else { | ||||||
|         furi_crash(NULL); |         furi_crash(NULL); | ||||||
|     } |     } | ||||||
| @ -369,6 +427,7 @@ void furi_hal_subghz_load_patable(const uint8_t data[8]) { | |||||||
| void furi_hal_subghz_write_packet(const uint8_t* data, uint8_t size) { | void furi_hal_subghz_write_packet(const uint8_t* data, uint8_t size) { | ||||||
|     furi_hal_spi_acquire(&furi_hal_spi_bus_handle_subghz); |     furi_hal_spi_acquire(&furi_hal_spi_bus_handle_subghz); | ||||||
|     cc1101_flush_tx(&furi_hal_spi_bus_handle_subghz); |     cc1101_flush_tx(&furi_hal_spi_bus_handle_subghz); | ||||||
|  |     cc1101_write_reg(&furi_hal_spi_bus_handle_subghz, CC1101_FIFO, size); | ||||||
|     cc1101_write_fifo(&furi_hal_spi_bus_handle_subghz, data, size); |     cc1101_write_fifo(&furi_hal_spi_bus_handle_subghz, data, size); | ||||||
|     furi_hal_spi_release(&furi_hal_spi_bus_handle_subghz); |     furi_hal_spi_release(&furi_hal_spi_bus_handle_subghz); | ||||||
| } | } | ||||||
| @ -379,6 +438,31 @@ void furi_hal_subghz_flush_rx() { | |||||||
|     furi_hal_spi_release(&furi_hal_spi_bus_handle_subghz); |     furi_hal_spi_release(&furi_hal_spi_bus_handle_subghz); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | bool furi_hal_subghz_rx_pipe_not_empty() { | ||||||
|  |     CC1101RxBytes status[1]; | ||||||
|  |     furi_hal_spi_acquire(&furi_hal_spi_bus_handle_subghz); | ||||||
|  |     cc1101_read_reg(&furi_hal_spi_bus_handle_subghz, (CC1101_STATUS_RXBYTES) | CC1101_BURST, (uint8_t*)status); | ||||||
|  |     furi_hal_spi_release(&furi_hal_spi_bus_handle_subghz); | ||||||
|  |     // TODO: you can add a buffer overflow flag if needed
 | ||||||
|  |     if(status->NUM_RXBYTES > 0) { | ||||||
|  |         return true; | ||||||
|  |     } else { | ||||||
|  |         return false; | ||||||
|  |     } | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | bool furi_hal_subghz_is_rx_data_crc_valid() { | ||||||
|  |     furi_hal_spi_acquire(&furi_hal_spi_bus_handle_subghz); | ||||||
|  |     uint8_t data[1]; | ||||||
|  |     cc1101_read_reg(&furi_hal_spi_bus_handle_subghz, CC1101_STATUS_LQI | CC1101_BURST, data); | ||||||
|  |     furi_hal_spi_release(&furi_hal_spi_bus_handle_subghz); | ||||||
|  |     if(((data[0] >> 7) & 0x01)) { | ||||||
|  |         return true; | ||||||
|  |     } else { | ||||||
|  |         return false; | ||||||
|  |     } | ||||||
|  | } | ||||||
|  | 
 | ||||||
| void furi_hal_subghz_read_packet(uint8_t* data, uint8_t* size) { | void furi_hal_subghz_read_packet(uint8_t* data, uint8_t* size) { | ||||||
|     furi_hal_spi_acquire(&furi_hal_spi_bus_handle_subghz); |     furi_hal_spi_acquire(&furi_hal_spi_bus_handle_subghz); | ||||||
|     cc1101_read_fifo(&furi_hal_spi_bus_handle_subghz, data, size); |     cc1101_read_fifo(&furi_hal_spi_bus_handle_subghz, data, size); | ||||||
| @ -460,18 +544,16 @@ uint32_t furi_hal_subghz_set_frequency_and_path(uint32_t value) { | |||||||
|     return value; |     return value; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| uint32_t furi_hal_subghz_set_frequency(uint32_t value) { | bool furi_hal_subghz_is_tx_allowed(uint32_t value) { | ||||||
|     furi_hal_spi_acquire(&furi_hal_spi_bus_handle_subghz); |  | ||||||
| 
 |  | ||||||
|     //checking regional settings
 |     //checking regional settings
 | ||||||
|     bool txrx = false; |     bool is_allowed = false; | ||||||
|     switch(furi_hal_version_get_hw_region()) { |     switch(furi_hal_version_get_hw_region()) { | ||||||
|     case FuriHalVersionRegionEuRu: |     case FuriHalVersionRegionEuRu: | ||||||
|         //433,05..434,79; 868,15..868,55
 |         //433,05..434,79; 868,15..868,55
 | ||||||
|         if(!(value >= 433050000 && value <= 434790000) && |         if(!(value >= 433050000 && value <= 434790000) && | ||||||
|            !(value >= 868150000 && value <= 868550000)) { |            !(value >= 868150000 && value <= 868550000)) { | ||||||
|         } else { |         } else { | ||||||
|             txrx = true; |             is_allowed = true; | ||||||
|         } |         } | ||||||
|         break; |         break; | ||||||
|     case FuriHalVersionRegionUsCaAu: |     case FuriHalVersionRegionUsCaAu: | ||||||
| @ -480,7 +562,7 @@ uint32_t furi_hal_subghz_set_frequency(uint32_t value) { | |||||||
|            !(value >= 433050000 && value <= 434790000) && |            !(value >= 433050000 && value <= 434790000) && | ||||||
|            !(value >= 915000000 && value <= 928000000)) { |            !(value >= 915000000 && value <= 928000000)) { | ||||||
|         } else { |         } else { | ||||||
|             txrx = true; |             is_allowed = true; | ||||||
|         } |         } | ||||||
|         break; |         break; | ||||||
|     case FuriHalVersionRegionJp: |     case FuriHalVersionRegionJp: | ||||||
| @ -488,16 +570,21 @@ uint32_t furi_hal_subghz_set_frequency(uint32_t value) { | |||||||
|         if(!(value >= 312000000 && value <= 315250000) && |         if(!(value >= 312000000 && value <= 315250000) && | ||||||
|            !(value >= 920500000 && value <= 923500000)) { |            !(value >= 920500000 && value <= 923500000)) { | ||||||
|         } else { |         } else { | ||||||
|             txrx = true; |             is_allowed = true; | ||||||
|         } |         } | ||||||
|         break; |         break; | ||||||
| 
 | 
 | ||||||
|     default: |     default: | ||||||
|         txrx = true; |         is_allowed = true; | ||||||
|         break; |         break; | ||||||
|     } |     } | ||||||
|  |     return is_allowed; | ||||||
|  | } | ||||||
| 
 | 
 | ||||||
|     if(txrx) { | uint32_t furi_hal_subghz_set_frequency(uint32_t value) { | ||||||
|  |     furi_hal_spi_acquire(&furi_hal_spi_bus_handle_subghz); | ||||||
|  | 
 | ||||||
|  |     if(furi_hal_subghz_is_tx_allowed(value)) { | ||||||
|         furi_hal_subghz_regulation = SubGhzRegulationTxRx; |         furi_hal_subghz_regulation = SubGhzRegulationTxRx; | ||||||
|     } else { |     } else { | ||||||
|         furi_hal_subghz_regulation = SubGhzRegulationOnlyRx; |         furi_hal_subghz_regulation = SubGhzRegulationOnlyRx; | ||||||
|  | |||||||
| @ -244,6 +244,54 @@ static const uint8_t furi_hal_subghz_preset_2fsk_dev4_76khz_async_regs[][2] = { | |||||||
|     /* End  */ |     /* End  */ | ||||||
|     {0, 0}, |     {0, 0}, | ||||||
| }; | }; | ||||||
|  | static const uint8_t furi_hal_subghz_preset_msk_99_97kb_async_regs[][2] = { | ||||||
|  |     /* GPIO GD0 */ | ||||||
|  |     {CC1101_IOCFG0, 0x06}, | ||||||
|  | 
 | ||||||
|  |     {CC1101_FIFOTHR, 0x07}, // The only important bit is ADC_RETENTION
 | ||||||
|  |     {CC1101_SYNC1, 0x46}, | ||||||
|  |     {CC1101_SYNC0, 0x4C}, | ||||||
|  |     {CC1101_ADDR, 0x00}, | ||||||
|  |     {CC1101_PKTLEN, 0x00}, | ||||||
|  |     {CC1101_CHANNR, 0x00}, | ||||||
|  | 
 | ||||||
|  |     {CC1101_PKTCTRL0, 0x05}, | ||||||
|  | 
 | ||||||
|  |     {CC1101_FSCTRL0, 0x23}, | ||||||
|  |     {CC1101_FSCTRL1, 0x06}, | ||||||
|  | 
 | ||||||
|  |     {CC1101_MDMCFG0, 0xF8}, | ||||||
|  |     {CC1101_MDMCFG1, 0x22}, | ||||||
|  |     {CC1101_MDMCFG2, 0x72}, | ||||||
|  |     {CC1101_MDMCFG3, 0xF8}, | ||||||
|  |     {CC1101_MDMCFG4, 0x5B}, | ||||||
|  |     {CC1101_DEVIATN, 0x47}, | ||||||
|  | 
 | ||||||
|  |     {CC1101_MCSM0, 0x18}, | ||||||
|  |     {CC1101_FOCCFG, 0x16}, | ||||||
|  | 
 | ||||||
|  |     {CC1101_AGCCTRL0, 0xB2}, | ||||||
|  |     {CC1101_AGCCTRL1, 0x00}, | ||||||
|  |     {CC1101_AGCCTRL2, 0xC7}, | ||||||
|  | 
 | ||||||
|  |     {CC1101_FREND0, 0x10}, | ||||||
|  |     {CC1101_FREND1, 0x56}, | ||||||
|  | 
 | ||||||
|  |     {CC1101_FSCAL3, 0xE9}, | ||||||
|  |     {CC1101_FSCAL2, 0x2A}, | ||||||
|  |     {CC1101_FSCAL1, 0x00}, | ||||||
|  |     {CC1101_FSCAL0, 0x1F}, | ||||||
|  | 
 | ||||||
|  |     {CC1101_BSCFG, 0x1C}, | ||||||
|  |     {CC1101_FSTEST, 0x59}, | ||||||
|  | 
 | ||||||
|  |     {CC1101_TEST2, 0x81}, | ||||||
|  |     {CC1101_TEST1, 0x35}, | ||||||
|  |     {CC1101_TEST0, 0x09}, | ||||||
|  |     /* End  */ | ||||||
|  |     {0, 0}, | ||||||
|  | }; | ||||||
|  | 
 | ||||||
| static const uint8_t furi_hal_subghz_preset_ook_async_patable[8] = { | static const uint8_t furi_hal_subghz_preset_ook_async_patable[8] = { | ||||||
|     0x00, |     0x00, | ||||||
|     0xC0, // 10dBm 0xC0, 7dBm 0xC8, 5dBm 0x84, 0dBm 0x60, -10dBm 0x34, -15dBm 0x1D, -20dBm 0x0E, -30dBm 0x12
 |     0xC0, // 10dBm 0xC0, 7dBm 0xC8, 5dBm 0x84, 0dBm 0x60, -10dBm 0x34, -15dBm 0x1D, -20dBm 0x0E, -30dBm 0x12
 | ||||||
| @ -261,9 +309,16 @@ static const uint8_t furi_hal_subghz_preset_2fsk_async_patable[8] = { | |||||||
|     0x00, |     0x00, | ||||||
|     0x00, |     0x00, | ||||||
|     0x00, |     0x00, | ||||||
|     0x00 |     0x00}; | ||||||
| 
 | static const uint8_t furi_hal_subghz_preset_msk_async_patable[8] = { | ||||||
| }; |     0xC0, // 10dBm 0xC0, 7dBm 0xC8, 5dBm 0x84, 0dBm 0x60, -10dBm 0x34, -15dBm 0x1D, -20dBm 0x0E, -30dBm 0x12
 | ||||||
|  |     0x00, | ||||||
|  |     0x00, | ||||||
|  |     0x00, | ||||||
|  |     0x00, | ||||||
|  |     0x00, | ||||||
|  |     0x00, | ||||||
|  |     0x00}; | ||||||
| 
 | 
 | ||||||
| void furi_hal_subghz_init() { | void furi_hal_subghz_init() { | ||||||
|     furi_assert(furi_hal_subghz_state == SubGhzStateInit); |     furi_assert(furi_hal_subghz_state == SubGhzStateInit); | ||||||
| @ -344,6 +399,9 @@ void furi_hal_subghz_load_preset(FuriHalSubGhzPreset preset) { | |||||||
|     } else if(preset == FuriHalSubGhzPreset2FSKDev476Async) { |     } 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_dev4_76khz_async_regs); | ||||||
|         furi_hal_subghz_load_patable(furi_hal_subghz_preset_2fsk_async_patable); |         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); | ||||||
|  |         furi_hal_subghz_load_patable(furi_hal_subghz_preset_msk_async_patable); | ||||||
|     } else { |     } else { | ||||||
|         furi_crash(NULL); |         furi_crash(NULL); | ||||||
|     } |     } | ||||||
| @ -369,6 +427,7 @@ void furi_hal_subghz_load_patable(const uint8_t data[8]) { | |||||||
| void furi_hal_subghz_write_packet(const uint8_t* data, uint8_t size) { | void furi_hal_subghz_write_packet(const uint8_t* data, uint8_t size) { | ||||||
|     furi_hal_spi_acquire(&furi_hal_spi_bus_handle_subghz); |     furi_hal_spi_acquire(&furi_hal_spi_bus_handle_subghz); | ||||||
|     cc1101_flush_tx(&furi_hal_spi_bus_handle_subghz); |     cc1101_flush_tx(&furi_hal_spi_bus_handle_subghz); | ||||||
|  |     cc1101_write_reg(&furi_hal_spi_bus_handle_subghz, CC1101_FIFO, size); | ||||||
|     cc1101_write_fifo(&furi_hal_spi_bus_handle_subghz, data, size); |     cc1101_write_fifo(&furi_hal_spi_bus_handle_subghz, data, size); | ||||||
|     furi_hal_spi_release(&furi_hal_spi_bus_handle_subghz); |     furi_hal_spi_release(&furi_hal_spi_bus_handle_subghz); | ||||||
| } | } | ||||||
| @ -379,6 +438,31 @@ void furi_hal_subghz_flush_rx() { | |||||||
|     furi_hal_spi_release(&furi_hal_spi_bus_handle_subghz); |     furi_hal_spi_release(&furi_hal_spi_bus_handle_subghz); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | bool furi_hal_subghz_rx_pipe_not_empty() { | ||||||
|  |     CC1101RxBytes status[1]; | ||||||
|  |     furi_hal_spi_acquire(&furi_hal_spi_bus_handle_subghz); | ||||||
|  |     cc1101_read_reg(&furi_hal_spi_bus_handle_subghz, (CC1101_STATUS_RXBYTES) | CC1101_BURST, (uint8_t*)status); | ||||||
|  |     furi_hal_spi_release(&furi_hal_spi_bus_handle_subghz); | ||||||
|  |     // TODO: you can add a buffer overflow flag if needed
 | ||||||
|  |     if(status->NUM_RXBYTES > 0) { | ||||||
|  |         return true; | ||||||
|  |     } else { | ||||||
|  |         return false; | ||||||
|  |     } | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | bool furi_hal_subghz_is_rx_data_crc_valid() { | ||||||
|  |     furi_hal_spi_acquire(&furi_hal_spi_bus_handle_subghz); | ||||||
|  |     uint8_t data[1]; | ||||||
|  |     cc1101_read_reg(&furi_hal_spi_bus_handle_subghz, CC1101_STATUS_LQI | CC1101_BURST, data); | ||||||
|  |     furi_hal_spi_release(&furi_hal_spi_bus_handle_subghz); | ||||||
|  |     if(((data[0] >> 7) & 0x01)) { | ||||||
|  |         return true; | ||||||
|  |     } else { | ||||||
|  |         return false; | ||||||
|  |     } | ||||||
|  | } | ||||||
|  | 
 | ||||||
| void furi_hal_subghz_read_packet(uint8_t* data, uint8_t* size) { | void furi_hal_subghz_read_packet(uint8_t* data, uint8_t* size) { | ||||||
|     furi_hal_spi_acquire(&furi_hal_spi_bus_handle_subghz); |     furi_hal_spi_acquire(&furi_hal_spi_bus_handle_subghz); | ||||||
|     cc1101_read_fifo(&furi_hal_spi_bus_handle_subghz, data, size); |     cc1101_read_fifo(&furi_hal_spi_bus_handle_subghz, data, size); | ||||||
| @ -460,18 +544,16 @@ uint32_t furi_hal_subghz_set_frequency_and_path(uint32_t value) { | |||||||
|     return value; |     return value; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| uint32_t furi_hal_subghz_set_frequency(uint32_t value) { | bool furi_hal_subghz_is_tx_allowed(uint32_t value) { | ||||||
|     furi_hal_spi_acquire(&furi_hal_spi_bus_handle_subghz); |  | ||||||
| 
 |  | ||||||
|     //checking regional settings
 |     //checking regional settings
 | ||||||
|     bool txrx = false; |     bool is_allowed = false; | ||||||
|     switch(furi_hal_version_get_hw_region()) { |     switch(furi_hal_version_get_hw_region()) { | ||||||
|     case FuriHalVersionRegionEuRu: |     case FuriHalVersionRegionEuRu: | ||||||
|         //433,05..434,79; 868,15..868,55
 |         //433,05..434,79; 868,15..868,55
 | ||||||
|         if(!(value >= 433050000 && value <= 434790000) && |         if(!(value >= 433050000 && value <= 434790000) && | ||||||
|            !(value >= 868150000 && value <= 868550000)) { |            !(value >= 868150000 && value <= 868550000)) { | ||||||
|         } else { |         } else { | ||||||
|             txrx = true; |             is_allowed = true; | ||||||
|         } |         } | ||||||
|         break; |         break; | ||||||
|     case FuriHalVersionRegionUsCaAu: |     case FuriHalVersionRegionUsCaAu: | ||||||
| @ -480,7 +562,7 @@ uint32_t furi_hal_subghz_set_frequency(uint32_t value) { | |||||||
|            !(value >= 433050000 && value <= 434790000) && |            !(value >= 433050000 && value <= 434790000) && | ||||||
|            !(value >= 915000000 && value <= 928000000)) { |            !(value >= 915000000 && value <= 928000000)) { | ||||||
|         } else { |         } else { | ||||||
|             txrx = true; |             is_allowed = true; | ||||||
|         } |         } | ||||||
|         break; |         break; | ||||||
|     case FuriHalVersionRegionJp: |     case FuriHalVersionRegionJp: | ||||||
| @ -488,16 +570,21 @@ uint32_t furi_hal_subghz_set_frequency(uint32_t value) { | |||||||
|         if(!(value >= 312000000 && value <= 315250000) && |         if(!(value >= 312000000 && value <= 315250000) && | ||||||
|            !(value >= 920500000 && value <= 923500000)) { |            !(value >= 920500000 && value <= 923500000)) { | ||||||
|         } else { |         } else { | ||||||
|             txrx = true; |             is_allowed = true; | ||||||
|         } |         } | ||||||
|         break; |         break; | ||||||
| 
 | 
 | ||||||
|     default: |     default: | ||||||
|         txrx = true; |         is_allowed = true; | ||||||
|         break; |         break; | ||||||
|     } |     } | ||||||
|  |     return is_allowed; | ||||||
|  | } | ||||||
| 
 | 
 | ||||||
|     if(txrx) { | uint32_t furi_hal_subghz_set_frequency(uint32_t value) { | ||||||
|  |     furi_hal_spi_acquire(&furi_hal_spi_bus_handle_subghz); | ||||||
|  | 
 | ||||||
|  |     if(furi_hal_subghz_is_tx_allowed(value)) { | ||||||
|         furi_hal_subghz_regulation = SubGhzRegulationTxRx; |         furi_hal_subghz_regulation = SubGhzRegulationTxRx; | ||||||
|     } else { |     } else { | ||||||
|         furi_hal_subghz_regulation = SubGhzRegulationOnlyRx; |         furi_hal_subghz_regulation = SubGhzRegulationOnlyRx; | ||||||
|  | |||||||
| @ -20,6 +20,7 @@ typedef enum { | |||||||
|     FuriHalSubGhzPresetOok650Async,     /**< OOK, bandwidth 650kHz, asynchronous */ |     FuriHalSubGhzPresetOok650Async,     /**< OOK, bandwidth 650kHz, asynchronous */ | ||||||
|     FuriHalSubGhzPreset2FSKDev238Async, /**< FM, deviation 2.380371 kHz, asynchronous */ |     FuriHalSubGhzPreset2FSKDev238Async, /**< FM, deviation 2.380371 kHz, asynchronous */ | ||||||
|     FuriHalSubGhzPreset2FSKDev476Async, /**< FM, deviation 4.760742 kHz, asynchronous */ |     FuriHalSubGhzPreset2FSKDev476Async, /**< FM, deviation 4.760742 kHz, asynchronous */ | ||||||
|  |     FuriHalSubGhzPresetMSK99_97KbAsync, /**< MSK, deviation 47.60742 kHz, 99.97Kb/s, asynchronous */ | ||||||
| } FuriHalSubGhzPreset; | } FuriHalSubGhzPreset; | ||||||
| 
 | 
 | ||||||
| /** Switchable Radio Paths */ | /** Switchable Radio Paths */ | ||||||
| @ -90,6 +91,18 @@ void furi_hal_subghz_load_patable(const uint8_t data[8]); | |||||||
|  */ |  */ | ||||||
| void furi_hal_subghz_write_packet(const uint8_t* data, uint8_t size); | void furi_hal_subghz_write_packet(const uint8_t* data, uint8_t size); | ||||||
| 
 | 
 | ||||||
|  | /** Check if recieve pipe is not empty
 | ||||||
|  |  * | ||||||
|  |  * @return     true if not empty | ||||||
|  |  */ | ||||||
|  | bool furi_hal_subghz_rx_pipe_not_empty(); | ||||||
|  | 
 | ||||||
|  | /** Check if recieved data crc is valid
 | ||||||
|  |  * | ||||||
|  |  * @return     true if valid | ||||||
|  |  */ | ||||||
|  | bool furi_hal_subghz_is_rx_data_crc_valid(); | ||||||
|  | 
 | ||||||
| /** Read packet from FIFO
 | /** Read packet from FIFO
 | ||||||
|  * |  * | ||||||
|  * @param      data  pointer |  * @param      data  pointer | ||||||
| @ -148,6 +161,14 @@ bool furi_hal_subghz_is_frequency_valid(uint32_t value); | |||||||
|  */ |  */ | ||||||
| uint32_t furi_hal_subghz_set_frequency_and_path(uint32_t value); | uint32_t furi_hal_subghz_set_frequency_and_path(uint32_t value); | ||||||
| 
 | 
 | ||||||
|  | /** Сheck if transmission is allowed on this frequency for your flipper region
 | ||||||
|  |  * | ||||||
|  |  * @param      value  frequency in Hz | ||||||
|  |  * | ||||||
|  |  * @return     true if allowed | ||||||
|  |  */ | ||||||
|  | bool furi_hal_subghz_is_tx_allowed(uint32_t value); | ||||||
|  | 
 | ||||||
| /** Set frequency
 | /** Set frequency
 | ||||||
|  * |  * | ||||||
|  * @param      value  frequency in Hz |  * @param      value  frequency in Hz | ||||||
|  | |||||||
| @ -22,14 +22,14 @@ CC1101Status cc1101_write_reg(FuriHalSpiBusHandle* handle, uint8_t reg, uint8_t | |||||||
|     while(hal_gpio_read(handle->miso)); |     while(hal_gpio_read(handle->miso)); | ||||||
|     furi_hal_spi_bus_trx(handle, tx, (uint8_t*)rx, 2, CC1101_TIMEOUT); |     furi_hal_spi_bus_trx(handle, tx, (uint8_t*)rx, 2, CC1101_TIMEOUT); | ||||||
| 
 | 
 | ||||||
|     assert((rx[0].CHIP_RDYn|rx[1].CHIP_RDYn) == 0); |     assert((rx[0].CHIP_RDYn | rx[1].CHIP_RDYn) == 0); | ||||||
|     return rx[1]; |     return rx[1]; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| CC1101Status cc1101_read_reg(FuriHalSpiBusHandle* handle, uint8_t reg, uint8_t* data) { | CC1101Status cc1101_read_reg(FuriHalSpiBusHandle* handle, uint8_t reg, uint8_t* data) { | ||||||
|     assert(sizeof(CC1101Status) == 1); |     assert(sizeof(CC1101Status) == 1); | ||||||
|     uint8_t tx[2] = { reg|CC1101_READ, 0}; |     uint8_t tx[2] = {reg | CC1101_READ, 0}; | ||||||
|     CC1101Status rx[2] = { 0 }; |     CC1101Status rx[2] = {0}; | ||||||
| 
 | 
 | ||||||
|     while(hal_gpio_read(handle->miso)); |     while(hal_gpio_read(handle->miso)); | ||||||
|     furi_hal_spi_bus_trx(handle, tx, (uint8_t*)rx, 2, CC1101_TIMEOUT); |     furi_hal_spi_bus_trx(handle, tx, (uint8_t*)rx, 2, CC1101_TIMEOUT); | ||||||
| @ -58,8 +58,6 @@ uint8_t cc1101_get_rssi(FuriHalSpiBusHandle* handle) { | |||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void cc1101_reset(FuriHalSpiBusHandle* handle) { | void cc1101_reset(FuriHalSpiBusHandle* handle) { | ||||||
|     delay_us(1000); |  | ||||||
|     delay_us(1000); |  | ||||||
|     cc1101_strobe(handle, CC1101_STROBE_SRES); |     cc1101_strobe(handle, CC1101_STROBE_SRES); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| @ -130,7 +128,7 @@ void cc1101_set_pa_table(FuriHalSpiBusHandle* handle, const uint8_t value[8]) { | |||||||
|     while(hal_gpio_read(handle->miso)); |     while(hal_gpio_read(handle->miso)); | ||||||
|     furi_hal_spi_bus_trx(handle, tx, (uint8_t*)rx, sizeof(rx), CC1101_TIMEOUT); |     furi_hal_spi_bus_trx(handle, tx, (uint8_t*)rx, sizeof(rx), CC1101_TIMEOUT); | ||||||
| 
 | 
 | ||||||
|     assert((rx[0].CHIP_RDYn|rx[8].CHIP_RDYn) == 0); |     assert((rx[0].CHIP_RDYn | rx[8].CHIP_RDYn) == 0); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| uint8_t cc1101_write_fifo(FuriHalSpiBusHandle* handle, const uint8_t* data, uint8_t size) { | uint8_t cc1101_write_fifo(FuriHalSpiBusHandle* handle, const uint8_t* data, uint8_t size) { | ||||||
| @ -159,9 +157,14 @@ uint8_t cc1101_read_fifo(FuriHalSpiBusHandle* handle, uint8_t* data, uint8_t* si | |||||||
| 
 | 
 | ||||||
|     // First byte - packet length
 |     // First byte - packet length
 | ||||||
|     furi_hal_spi_bus_trx(handle, buff_tx, buff_rx, 2, CC1101_TIMEOUT); |     furi_hal_spi_bus_trx(handle, buff_tx, buff_rx, 2, CC1101_TIMEOUT); | ||||||
|  | 
 | ||||||
|  |     // Check that the packet is placed in the receive buffer
 | ||||||
|  |     if(buff_rx[1] > 64) { | ||||||
|  |         *size = 64; | ||||||
|  |     } else { | ||||||
|         *size = buff_rx[1]; |         *size = buff_rx[1]; | ||||||
|  |     } | ||||||
|     furi_hal_spi_bus_trx(handle, &buff_tx[1], data, *size, CC1101_TIMEOUT); |     furi_hal_spi_bus_trx(handle, &buff_tx[1], data, *size, CC1101_TIMEOUT); | ||||||
|     cc1101_flush_rx(handle); |  | ||||||
| 
 | 
 | ||||||
|     return *size; |     return *size; | ||||||
| } | } | ||||||
|  | |||||||
| @ -89,22 +89,21 @@ extern "C" { | |||||||
| #define CC1101_STATUS_PARTNUM           0x30    /** Chip ID Part Number */ | #define CC1101_STATUS_PARTNUM           0x30    /** Chip ID Part Number */ | ||||||
| #define CC1101_STATUS_VERSION           0x31    /** Chip ID Version */ | #define CC1101_STATUS_VERSION           0x31    /** Chip ID Version */ | ||||||
| #define CC1101_STATUS_FREQEST           0x32    /** Frequency Offset Estimate from Demodulator */ | #define CC1101_STATUS_FREQEST           0x32    /** Frequency Offset Estimate from Demodulator */ | ||||||
| #define CC1101_STATUS_LQI               0x33    /** Demodulator Estimate for Link Quality */ | #define CC1101_STATUS_LQI               0x33    /** Demodulator Estimate for Link Quality, 7bit-CRC, 6..0-LQI*/ | ||||||
| #define CC1101_STATUS_RSSI              0x34    /** Received Signal Strength Indication */ | #define CC1101_STATUS_RSSI              0x34    /** Received Signal Strength Indication */ | ||||||
| #define CC1101_STATUS_MARCSTATE         0x35    /** Main Radio Control State Machine State */ | #define CC1101_STATUS_MARCSTATE         0x35    /** Main Radio Control State Machine State */ | ||||||
| #define CC1101_STATUS_WORTIME1          0x36    /** High Byte of WOR Time */ | #define CC1101_STATUS_WORTIME1          0x36    /** High Byte of WOR Time */ | ||||||
| #define CC1101_STATUS_WORTIME0          0x37    /** Low Byte of WOR Time */ | #define CC1101_STATUS_WORTIME0          0x37    /** Low Byte of WOR Time */ | ||||||
| #define CC1101_STATUS_PKTSTATUS         0x38    /** Current GDOx Status and Packet Status */ | #define CC1101_STATUS_PKTSTATUS         0x38    /** Current GDOx Status and Packet Status */ | ||||||
| #define CC1101_STATUS_VCO_VC_DAC        0x39    /** Current Setting from PLL Calibration Module */ | #define CC1101_STATUS_VCO_VC_DAC        0x39    /** Current Setting from PLL Calibration Module */ | ||||||
| #define CC1101_STATUS_TXBYTES           0x3A    /** Underflow and Number of Bytes */ | #define CC1101_STATUS_TXBYTES           0x3A    /** Underflow and Number of Bytes, 7bit-Underflow, 6..0-Number of Bytes*/ | ||||||
| #define CC1101_STATUS_RXBYTES           0x3B    /** Overflow and Number of Bytes */ | #define CC1101_STATUS_RXBYTES           0x3B    /** Overflow and Number of Bytes, 7bit-Overflow*, 6..0-Number of Bytes*/ | ||||||
| #define CC1101_STATUS_RCCTRL1_STATUS    0x3C    /** Last RC Oscillator Calibration Result */ | #define CC1101_STATUS_RCCTRL1_STATUS    0x3C    /** Last RC Oscillator Calibration Result */ | ||||||
| #define CC1101_STATUS_RCCTRL0_STATUS    0x3D    /** Last RC Oscillator Calibration Result */ | #define CC1101_STATUS_RCCTRL0_STATUS    0x3D    /** Last RC Oscillator Calibration Result */ | ||||||
| 
 | 
 | ||||||
| /* Some special registers, use CC1101_BURST to read/write data */ | /* Some special registers, use CC1101_BURST to read/write data */ | ||||||
| #define CC1101_PATABLE                  0x3E    /** PATABLE register number, an 8-byte table that defines the PA control settings */ | #define CC1101_PATABLE                  0x3E    /** PATABLE register number, an 8-byte table that defines the PA control settings */ | ||||||
| #define CC1101_FIFO                     0x3F    /** FIFO register nunmber, can be combined with CC1101_WRITE and/or CC1101_BURST */ | #define CC1101_FIFO                     0x3F    /** FIFO register nunmber, can be combined with CC1101_WRITE and/or CC1101_BURST */ | ||||||
| 
 |  | ||||||
| #define CC1101_IOCFG_INV                (1<<6)  /** IOCFG inversion */ | #define CC1101_IOCFG_INV                (1<<6)  /** IOCFG inversion */ | ||||||
| 
 | 
 | ||||||
| typedef enum { | typedef enum { | ||||||
|  | |||||||
							
								
								
									
										273
									
								
								lib/subghz/subghz_tx_rx_worker.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										273
									
								
								lib/subghz/subghz_tx_rx_worker.c
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,273 @@ | |||||||
|  | #include "subghz_tx_rx_worker.h" | ||||||
|  | 
 | ||||||
|  | #include <stream_buffer.h> | ||||||
|  | #include <furi.h> | ||||||
|  | 
 | ||||||
|  | #define TAG "SubGhzTxRxWorker" | ||||||
|  | 
 | ||||||
|  | #define GUBGHZ_TXRX_WORKER_BUF_SIZE 2048 | ||||||
|  | //you can not set more than 62 because it will not fit into the FIFO CC1101
 | ||||||
|  | #define GUBGHZ_TXRX_WORKER_MAX_TXRX_SIZE 60 | ||||||
|  | 
 | ||||||
|  | #define GUBGHZ_TXRX_WORKER_TIMEOUT_READ_WRITE_BUF 40 | ||||||
|  | 
 | ||||||
|  | struct SubGhzTxRxWorker { | ||||||
|  |     FuriThread* thread; | ||||||
|  |     StreamBufferHandle_t stream_tx; | ||||||
|  |     StreamBufferHandle_t stream_rx; | ||||||
|  | 
 | ||||||
|  |     volatile bool worker_running; | ||||||
|  |     volatile bool worker_stoping; | ||||||
|  | 
 | ||||||
|  |     SubGhzTxRxWorkerStatus satus; | ||||||
|  | 
 | ||||||
|  |     uint32_t frequency; | ||||||
|  | 
 | ||||||
|  |     SubGhzTxRxWorkerCallbackHaveRead callback_have_read; | ||||||
|  |     void* context_have_read; | ||||||
|  | }; | ||||||
|  | 
 | ||||||
|  | bool subghz_tx_rx_worker_write(SubGhzTxRxWorker* instance, uint8_t* data, size_t size) { | ||||||
|  |     furi_assert(instance); | ||||||
|  |     bool ret = false; | ||||||
|  |     size_t stream_tx_free_byte = xStreamBufferSpacesAvailable(instance->stream_tx); | ||||||
|  |     if(size && (stream_tx_free_byte >= size)) { | ||||||
|  |         if(xStreamBufferSend( | ||||||
|  |                instance->stream_tx, data, size, GUBGHZ_TXRX_WORKER_TIMEOUT_READ_WRITE_BUF) == | ||||||
|  |            size) { | ||||||
|  |             ret = true; | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  |     return ret; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | size_t subghz_tx_rx_worker_available(SubGhzTxRxWorker* instance) { | ||||||
|  |     furi_assert(instance); | ||||||
|  |     return xStreamBufferBytesAvailable(instance->stream_rx); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | size_t subghz_tx_rx_worker_read(SubGhzTxRxWorker* instance, uint8_t* data, size_t size) { | ||||||
|  |     furi_assert(instance); | ||||||
|  |     size_t len = 0; | ||||||
|  |     size_t stream_rx_byte = xStreamBufferBytesAvailable(instance->stream_rx); | ||||||
|  | 
 | ||||||
|  |     if(stream_rx_byte > 0) { | ||||||
|  |         if(stream_rx_byte <= size) { | ||||||
|  |             len = xStreamBufferReceive( | ||||||
|  |                 instance->stream_rx, | ||||||
|  |                 data, | ||||||
|  |                 stream_rx_byte, | ||||||
|  |                 GUBGHZ_TXRX_WORKER_TIMEOUT_READ_WRITE_BUF); | ||||||
|  |         } else { | ||||||
|  |             len = xStreamBufferReceive( | ||||||
|  |                 instance->stream_rx, data, size, GUBGHZ_TXRX_WORKER_TIMEOUT_READ_WRITE_BUF); | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  |     return len; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | void subghz_tx_rx_worker_set_callback_have_read( | ||||||
|  |     SubGhzTxRxWorker* instance, | ||||||
|  |     SubGhzTxRxWorkerCallbackHaveRead callback, | ||||||
|  |     void* context) { | ||||||
|  |     furi_assert(instance); | ||||||
|  |     furi_assert(callback); | ||||||
|  |     furi_assert(context); | ||||||
|  |     instance->callback_have_read = callback; | ||||||
|  |     instance->context_have_read = context; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | bool subghz_tx_rx_worker_rx(SubGhzTxRxWorker* instance, uint8_t* data, uint8_t* size) { | ||||||
|  |     uint8_t timeout = 20; | ||||||
|  |     bool ret = false; | ||||||
|  |     if(instance->satus != SubGhzTxRxWorkerStatusRx) { | ||||||
|  |         furi_hal_subghz_rx(); | ||||||
|  |         instance->satus = SubGhzTxRxWorkerStatusRx; | ||||||
|  |         osDelay(1); | ||||||
|  |     } | ||||||
|  |     //waiting for reception to complete
 | ||||||
|  |     while(hal_gpio_read(&gpio_cc1101_g0)) { | ||||||
|  |         osDelay(1); | ||||||
|  |         if(!--timeout) { | ||||||
|  |             FURI_LOG_W(TAG, "RX cc1101_g0 timeout"); | ||||||
|  |             furi_hal_subghz_flush_rx(); | ||||||
|  |             furi_hal_subghz_rx(); | ||||||
|  |             break; | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     if(furi_hal_subghz_rx_pipe_not_empty()) { | ||||||
|  |         if(furi_hal_subghz_is_rx_data_crc_valid()) { | ||||||
|  |             furi_hal_subghz_read_packet(data, size); | ||||||
|  |             ret = true; | ||||||
|  |         } | ||||||
|  |         furi_hal_subghz_flush_rx(); | ||||||
|  |         furi_hal_subghz_rx(); | ||||||
|  |     } | ||||||
|  |     return ret; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | void subghz_tx_rx_worker_tx(SubGhzTxRxWorker* instance, uint8_t* data, size_t size) { | ||||||
|  |     uint8_t timeout = 40; | ||||||
|  |     if(instance->satus != SubGhzTxRxWorkerStatusIDLE) { | ||||||
|  |         furi_hal_subghz_idle(); | ||||||
|  |     } | ||||||
|  |     furi_hal_subghz_write_packet(data, size); | ||||||
|  |     instance->satus = SubGhzTxRxWorkerStatusTx; | ||||||
|  | 
 | ||||||
|  |     furi_hal_subghz_tx(); //start send
 | ||||||
|  | 
 | ||||||
|  |     while(!hal_gpio_read(&gpio_cc1101_g0)) { // Wait for GDO0 to be set -> sync transmitted
 | ||||||
|  |         osDelay(1); | ||||||
|  |         if(!--timeout) { | ||||||
|  |             FURI_LOG_W(TAG, "TX !cc1101_g0 timeout"); | ||||||
|  |             break; | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  |     while(hal_gpio_read(&gpio_cc1101_g0)) { // Wait for GDO0 to be cleared -> end of packet
 | ||||||
|  |         osDelay(1); | ||||||
|  |         if(!--timeout) { | ||||||
|  |             FURI_LOG_W(TAG, "TX cc1101_g0 timeout"); | ||||||
|  |             break; | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  |     furi_hal_subghz_idle(); | ||||||
|  |     instance->satus = SubGhzTxRxWorkerStatusIDLE; | ||||||
|  | } | ||||||
|  | /** Worker thread
 | ||||||
|  |  *  | ||||||
|  |  * @param context  | ||||||
|  |  * @return exit code  | ||||||
|  |  */ | ||||||
|  | static int32_t subghz_tx_rx_worker_thread(void* context) { | ||||||
|  |     SubGhzTxRxWorker* instance = context; | ||||||
|  |     FURI_LOG_I(TAG, "Worker start"); | ||||||
|  | 
 | ||||||
|  |     furi_hal_subghz_reset(); | ||||||
|  |     furi_hal_subghz_idle(); | ||||||
|  |     furi_hal_subghz_load_preset(FuriHalSubGhzPresetMSK99_97KbAsync); | ||||||
|  |     hal_gpio_init(&gpio_cc1101_g0, GpioModeInput, GpioPullNo, GpioSpeedLow); | ||||||
|  | 
 | ||||||
|  |     furi_hal_subghz_set_frequency_and_path(instance->frequency); | ||||||
|  |     furi_hal_subghz_flush_rx(); | ||||||
|  | 
 | ||||||
|  |     uint8_t data[GUBGHZ_TXRX_WORKER_MAX_TXRX_SIZE] = {0}; | ||||||
|  |     size_t size_tx = 0; | ||||||
|  |     uint8_t size_rx[1] = {0}; | ||||||
|  |     uint8_t timeout_tx = 0; | ||||||
|  |     bool callback_rx = false; | ||||||
|  | 
 | ||||||
|  |     while(instance->worker_running) { | ||||||
|  |         //transmit
 | ||||||
|  |         size_tx = xStreamBufferBytesAvailable(instance->stream_tx); | ||||||
|  |         if(size_tx > 0 && !timeout_tx) { | ||||||
|  |             timeout_tx = 20; //20ms
 | ||||||
|  |             if(size_tx > GUBGHZ_TXRX_WORKER_MAX_TXRX_SIZE) { | ||||||
|  |                 xStreamBufferReceive( | ||||||
|  |                     instance->stream_tx, | ||||||
|  |                     &data, | ||||||
|  |                     GUBGHZ_TXRX_WORKER_MAX_TXRX_SIZE, | ||||||
|  |                     GUBGHZ_TXRX_WORKER_TIMEOUT_READ_WRITE_BUF); | ||||||
|  |                 subghz_tx_rx_worker_tx(instance, data, GUBGHZ_TXRX_WORKER_MAX_TXRX_SIZE); | ||||||
|  |             } else { | ||||||
|  |                 //todo checking that he managed to write all the data to the TX buffer
 | ||||||
|  |                 xStreamBufferReceive( | ||||||
|  |                     instance->stream_tx, &data, size_tx, GUBGHZ_TXRX_WORKER_TIMEOUT_READ_WRITE_BUF); | ||||||
|  |                 subghz_tx_rx_worker_tx(instance, data, size_tx); | ||||||
|  |             } | ||||||
|  |         } else { | ||||||
|  |             //recive
 | ||||||
|  |             if(subghz_tx_rx_worker_rx(instance, data, size_rx)) { | ||||||
|  |                 if(xStreamBufferSpacesAvailable(instance->stream_rx) >= size_rx[0]) { | ||||||
|  |                     if(instance->callback_have_read && | ||||||
|  |                        xStreamBufferBytesAvailable(instance->stream_rx) == 0) { | ||||||
|  |                         callback_rx = true; | ||||||
|  |                     } | ||||||
|  |                     //todo checking that he managed to write all the data to the RX buffer
 | ||||||
|  |                     xStreamBufferSend( | ||||||
|  |                         instance->stream_rx, | ||||||
|  |                         &data, | ||||||
|  |                         size_rx[0], | ||||||
|  |                         GUBGHZ_TXRX_WORKER_TIMEOUT_READ_WRITE_BUF); | ||||||
|  |                     if(callback_rx) { | ||||||
|  |                         instance->callback_have_read(instance->context_have_read); | ||||||
|  |                         callback_rx = false; | ||||||
|  |                     } | ||||||
|  |                 } else { | ||||||
|  |                     //todo RX buffer overflow
 | ||||||
|  |                 } | ||||||
|  |             } | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         if(timeout_tx) timeout_tx--; | ||||||
|  |         osDelay(1); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     furi_hal_subghz_set_path(FuriHalSubGhzPathIsolate); | ||||||
|  |     furi_hal_subghz_sleep(); | ||||||
|  | 
 | ||||||
|  |     FURI_LOG_I(TAG, "Worker stop"); | ||||||
|  |     return 0; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | SubGhzTxRxWorker* subghz_tx_rx_worker_alloc() { | ||||||
|  |     SubGhzTxRxWorker* instance = furi_alloc(sizeof(SubGhzTxRxWorker)); | ||||||
|  | 
 | ||||||
|  |     instance->thread = furi_thread_alloc(); | ||||||
|  |     furi_thread_set_name(instance->thread, "SubghzTxRxWorker"); | ||||||
|  |     furi_thread_set_stack_size(instance->thread, 2048); | ||||||
|  |     furi_thread_set_context(instance->thread, instance); | ||||||
|  |     furi_thread_set_callback(instance->thread, subghz_tx_rx_worker_thread); | ||||||
|  |     instance->stream_tx = | ||||||
|  |         xStreamBufferCreate(sizeof(uint8_t) * GUBGHZ_TXRX_WORKER_BUF_SIZE, sizeof(uint8_t)); | ||||||
|  |     instance->stream_rx = | ||||||
|  |         xStreamBufferCreate(sizeof(uint8_t) * GUBGHZ_TXRX_WORKER_BUF_SIZE, sizeof(uint8_t)); | ||||||
|  | 
 | ||||||
|  |     instance->satus = SubGhzTxRxWorkerStatusIDLE; | ||||||
|  |     instance->worker_stoping = true; | ||||||
|  | 
 | ||||||
|  |     return instance; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | void subghz_tx_rx_worker_free(SubGhzTxRxWorker* instance) { | ||||||
|  |     furi_assert(instance); | ||||||
|  | 
 | ||||||
|  |     vStreamBufferDelete(instance->stream_tx); | ||||||
|  |     vStreamBufferDelete(instance->stream_rx); | ||||||
|  |     furi_thread_free(instance->thread); | ||||||
|  | 
 | ||||||
|  |     free(instance); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | bool subghz_tx_rx_worker_start(SubGhzTxRxWorker* instance, uint32_t frequency) { | ||||||
|  |     furi_assert(instance); | ||||||
|  |     furi_assert(!instance->worker_running); | ||||||
|  |     bool res = false; | ||||||
|  |     xStreamBufferReset(instance->stream_tx); | ||||||
|  |     xStreamBufferReset(instance->stream_rx); | ||||||
|  | 
 | ||||||
|  |     instance->worker_running = true; | ||||||
|  | 
 | ||||||
|  |     furi_thread_start(instance->thread); | ||||||
|  | 
 | ||||||
|  |     if(furi_hal_subghz_is_tx_allowed(frequency)) { | ||||||
|  |         instance->frequency = frequency; | ||||||
|  |         res = true; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     return res; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | void subghz_tx_rx_worker_stop(SubGhzTxRxWorker* instance) { | ||||||
|  |     furi_assert(instance); | ||||||
|  |     furi_assert(instance->worker_running); | ||||||
|  | 
 | ||||||
|  |     instance->worker_running = false; | ||||||
|  | 
 | ||||||
|  |     furi_thread_join(instance->thread); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | bool subghz_tx_rx_worker_is_running(SubGhzTxRxWorker* instance) { | ||||||
|  |     furi_assert(instance); | ||||||
|  |     return instance->worker_running; | ||||||
|  | } | ||||||
							
								
								
									
										81
									
								
								lib/subghz/subghz_tx_rx_worker.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										81
									
								
								lib/subghz/subghz_tx_rx_worker.h
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,81 @@ | |||||||
|  | #pragma once | ||||||
|  | 
 | ||||||
|  | #include <furi-hal.h> | ||||||
|  | 
 | ||||||
|  | typedef void (*SubGhzTxRxWorkerCallbackHaveRead)(void* context); | ||||||
|  | 
 | ||||||
|  | typedef struct SubGhzTxRxWorker SubGhzTxRxWorker; | ||||||
|  | 
 | ||||||
|  | typedef enum { | ||||||
|  |     SubGhzTxRxWorkerStatusIDLE, | ||||||
|  |     SubGhzTxRxWorkerStatusTx, | ||||||
|  |     SubGhzTxRxWorkerStatusRx, | ||||||
|  | } SubGhzTxRxWorkerStatus; | ||||||
|  | 
 | ||||||
|  | /** SubGhzTxRxWorker, add data to transfer
 | ||||||
|  |  *  | ||||||
|  |  * @param instance  SubGhzTxRxWorker instance | ||||||
|  |  * @param data      *data | ||||||
|  |  * @param size      data size | ||||||
|  |  * @return bool     true if ok | ||||||
|  |  */ | ||||||
|  | bool subghz_tx_rx_worker_write(SubGhzTxRxWorker* instance, uint8_t* data, size_t size); | ||||||
|  | 
 | ||||||
|  | /** SubGhzTxRxWorker, get available data
 | ||||||
|  |  *  | ||||||
|  |  * @param instance   SubGhzTxRxWorker instance | ||||||
|  |  * @return size_t    data size | ||||||
|  |  */ | ||||||
|  | size_t subghz_tx_rx_worker_available(SubGhzTxRxWorker* instance); | ||||||
|  | 
 | ||||||
|  | /** SubGhzTxRxWorker, read data
 | ||||||
|  |  *  | ||||||
|  |  * @param instance   SubGhzTxRxWorker instance | ||||||
|  |  * @param data       *data | ||||||
|  |  * @param size       max data size, which can be read | ||||||
|  |  * @return size_t    data size, how much is actually read | ||||||
|  |  */ | ||||||
|  | size_t subghz_tx_rx_worker_read(SubGhzTxRxWorker* instance, uint8_t* data, size_t size); | ||||||
|  | 
 | ||||||
|  | /** Сallback SubGhzTxRxWorker when there is data to read in an empty buffer
 | ||||||
|  |  *  | ||||||
|  |  * @param instance SubGhzTxRxWorker instance | ||||||
|  |  * @param callback SubGhzTxRxWorkerCallbackHaveRead callback | ||||||
|  |  * @param context | ||||||
|  |  */ | ||||||
|  | void subghz_tx_rx_worker_set_callback_have_read( | ||||||
|  |     SubGhzTxRxWorker* instance, | ||||||
|  |     SubGhzTxRxWorkerCallbackHaveRead callback, | ||||||
|  |     void* context); | ||||||
|  | 
 | ||||||
|  | /** Allocate SubGhzTxRxWorker
 | ||||||
|  |  *  | ||||||
|  |  * @return SubGhzTxRxWorker*  | ||||||
|  |  */ | ||||||
|  | SubGhzTxRxWorker* subghz_tx_rx_worker_alloc(); | ||||||
|  | 
 | ||||||
|  | /** Free SubGhzTxRxWorker
 | ||||||
|  |  *  | ||||||
|  |  * @param instance SubGhzTxRxWorker instance | ||||||
|  |  */ | ||||||
|  | void subghz_tx_rx_worker_free(SubGhzTxRxWorker* instance); | ||||||
|  | 
 | ||||||
|  | /** Start SubGhzTxRxWorker
 | ||||||
|  |  *  | ||||||
|  |  * @param instance SubGhzTxRxWorker instance | ||||||
|  |  * @return bool - true if ok | ||||||
|  |  */ | ||||||
|  | bool subghz_tx_rx_worker_start(SubGhzTxRxWorker* instance, uint32_t frequency); | ||||||
|  | 
 | ||||||
|  | /** Stop SubGhzTxRxWorker
 | ||||||
|  |  *  | ||||||
|  |  * @param instance SubGhzTxRxWorker instance | ||||||
|  |  */ | ||||||
|  | void subghz_tx_rx_worker_stop(SubGhzTxRxWorker* instance); | ||||||
|  | 
 | ||||||
|  | /** Check if worker is running
 | ||||||
|  |  *  | ||||||
|  |  * @param instance SubGhzTxRxWorker instance | ||||||
|  |  * @return bool - true if running | ||||||
|  |  */ | ||||||
|  | bool subghz_tx_rx_worker_is_running(SubGhzTxRxWorker* instance); | ||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user
	 Skorpionm
						Skorpionm