SubGhz: add GFSK modulation, refactoring subghz_chat (#866)
* SubGhz: add GFSK modulation, refactoring subghz_chat * SubGhz: off echo subghz_chat * SubGhz: subghz_chat add sending and receiving formatted text, translation of the chat to events * SubGhz: add UTF support in subghz_chat_worker_alloc Co-authored-by: あく <alleteam@gmail.com>
This commit is contained in:
		
							parent
							
								
									7170864fe4
								
							
						
					
					
						commit
						f0aed7e583
					
				| @ -18,6 +18,7 @@ typedef enum { | ||||
|     CliSymbolAsciiBell = 0x07, | ||||
|     CliSymbolAsciiBackspace = 0x08, | ||||
|     CliSymbolAsciiTab = 0x09, | ||||
|     CliSymbolAsciiLF = 0x0A, | ||||
|     CliSymbolAsciiCR = 0x0D, | ||||
|     CliSymbolAsciiEsc = 0x1B, | ||||
|     CliSymbolAsciiUS = 0x1F, | ||||
|  | ||||
							
								
								
									
										141
									
								
								applications/subghz/helpers/subghz_chat.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										141
									
								
								applications/subghz/helpers/subghz_chat.c
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,141 @@ | ||||
| #include "subghz_chat.h" | ||||
| #include <lib/subghz/subghz_tx_rx_worker.h> | ||||
| 
 | ||||
| #define TAG "SubGhzChat" | ||||
| #define SUBGHZ_CHAT_WORKER_TIMEOUT_BETWEEN_MESSAGES 500 | ||||
| 
 | ||||
| struct SubGhzChatWorker { | ||||
|     FuriThread* thread; | ||||
|     SubGhzTxRxWorker* subghz_txrx; | ||||
| 
 | ||||
|     volatile bool worker_running; | ||||
|     volatile bool worker_stoping; | ||||
|     osMessageQueueId_t event_queue; | ||||
|     uint32_t last_time_rx_data; | ||||
| }; | ||||
| 
 | ||||
| /** Worker thread
 | ||||
|  *  | ||||
|  * @param context  | ||||
|  * @return exit code  | ||||
|  */ | ||||
| static int32_t subghz_chat_worker_thread(void* context) { | ||||
|     SubGhzChatWorker* instance = context; | ||||
|     FURI_LOG_I(TAG, "Worker start"); | ||||
|     char c; | ||||
|     SubghzChatEvent event; | ||||
|     event.event = SubghzChatEventUserEntrance; | ||||
|     osMessageQueuePut(instance->event_queue, &event, 0, 0); | ||||
|     while(instance->worker_running) { | ||||
|         if(furi_hal_vcp_rx_with_timeout((uint8_t*)&c, 1, osWaitForever) == 1) { | ||||
|             event.event = SubghzChatEventInputData; | ||||
|             event.c = c; | ||||
|             osMessageQueuePut(instance->event_queue, &event, 0, osWaitForever); | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     FURI_LOG_I(TAG, "Worker stop"); | ||||
|     return 0; | ||||
| } | ||||
| 
 | ||||
| static void subghz_chat_worker_update_rx_event_chat(void* context) { | ||||
|     furi_assert(context); | ||||
|     SubGhzChatWorker* instance = context; | ||||
|     SubghzChatEvent event; | ||||
|     if((millis() - instance->last_time_rx_data) > SUBGHZ_CHAT_WORKER_TIMEOUT_BETWEEN_MESSAGES) { | ||||
|         event.event = SubghzChatEventNewMessage; | ||||
|         osMessageQueuePut(instance->event_queue, &event, 0, osWaitForever); | ||||
|     } | ||||
|     instance->last_time_rx_data = millis(); | ||||
|     event.event = SubghzChatEventRXData; | ||||
|     osMessageQueuePut(instance->event_queue, &event, 0, osWaitForever); | ||||
| } | ||||
| 
 | ||||
| SubGhzChatWorker* subghz_chat_worker_alloc() { | ||||
|     SubGhzChatWorker* instance = furi_alloc(sizeof(SubGhzChatWorker)); | ||||
| 
 | ||||
|     instance->thread = furi_thread_alloc(); | ||||
|     furi_thread_set_name(instance->thread, "SubghzChat"); | ||||
|     furi_thread_set_stack_size(instance->thread, 2048); | ||||
|     furi_thread_set_context(instance->thread, instance); | ||||
|     furi_thread_set_callback(instance->thread, subghz_chat_worker_thread); | ||||
|     instance->subghz_txrx = subghz_tx_rx_worker_alloc(); | ||||
|     instance->event_queue = osMessageQueueNew(80, sizeof(SubghzChatEvent), NULL); | ||||
|     return instance; | ||||
| } | ||||
| 
 | ||||
| void subghz_chat_worker_free(SubGhzChatWorker* instance) { | ||||
|     furi_assert(instance); | ||||
|     furi_assert(!instance->worker_running); | ||||
|     osMessageQueueDelete(instance->event_queue); | ||||
|     subghz_tx_rx_worker_free(instance->subghz_txrx); | ||||
|     furi_thread_free(instance->thread); | ||||
| 
 | ||||
|     free(instance); | ||||
| } | ||||
| 
 | ||||
| bool subghz_chat_worker_start(SubGhzChatWorker* instance, uint32_t frequency) { | ||||
|     furi_assert(instance); | ||||
|     furi_assert(!instance->worker_running); | ||||
|     bool res = false; | ||||
| 
 | ||||
|     if(subghz_tx_rx_worker_start(instance->subghz_txrx, frequency)) { | ||||
|         osMessageQueueReset(instance->event_queue); | ||||
|         subghz_tx_rx_worker_set_callback_have_read( | ||||
|             instance->subghz_txrx, subghz_chat_worker_update_rx_event_chat, instance); | ||||
| 
 | ||||
|         instance->worker_running = true; | ||||
|         instance->last_time_rx_data = 0; | ||||
| 
 | ||||
|         res = furi_thread_start(instance->thread); | ||||
|     } | ||||
|     return res; | ||||
| } | ||||
| 
 | ||||
| void subghz_chat_worker_stop(SubGhzChatWorker* instance) { | ||||
|     furi_assert(instance); | ||||
|     furi_assert(instance->worker_running); | ||||
|     if(subghz_tx_rx_worker_is_running(instance->subghz_txrx)) { | ||||
|         subghz_tx_rx_worker_stop(instance->subghz_txrx); | ||||
|     } | ||||
| 
 | ||||
|     instance->worker_running = false; | ||||
| 
 | ||||
|     furi_thread_join(instance->thread); | ||||
| } | ||||
| 
 | ||||
| bool subghz_chat_worker_is_running(SubGhzChatWorker* instance) { | ||||
|     furi_assert(instance); | ||||
|     return instance->worker_running; | ||||
| } | ||||
| 
 | ||||
| SubghzChatEvent subghz_chat_worker_get_event_chat(SubGhzChatWorker* instance) { | ||||
|     furi_assert(instance); | ||||
|     SubghzChatEvent event; | ||||
|     if(osMessageQueueGet(instance->event_queue, &event, NULL, osWaitForever) == osOK) { | ||||
|         return event; | ||||
|     } else { | ||||
|         event.event = SubghzChatEventNoEvent; | ||||
|         return event; | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| void subghz_chat_worker_put_event_chat(SubGhzChatWorker* instance, SubghzChatEvent* event) { | ||||
|     furi_assert(instance); | ||||
|     osMessageQueuePut(instance->event_queue, event, 0, osWaitForever); | ||||
| } | ||||
| 
 | ||||
| size_t subghz_chat_worker_available(SubGhzChatWorker* instance) { | ||||
|     furi_assert(instance); | ||||
|     return subghz_tx_rx_worker_available(instance->subghz_txrx); | ||||
| } | ||||
| 
 | ||||
| size_t subghz_chat_worker_read(SubGhzChatWorker* instance, uint8_t* data, size_t size) { | ||||
|     furi_assert(instance); | ||||
|     return subghz_tx_rx_worker_read(instance->subghz_txrx, data, size); | ||||
| } | ||||
| 
 | ||||
| bool subghz_chat_worker_write(SubGhzChatWorker* instance, uint8_t* data, size_t size) { | ||||
|     furi_assert(instance); | ||||
|     return subghz_tx_rx_worker_write(instance->subghz_txrx, data, size); | ||||
| } | ||||
							
								
								
									
										29
									
								
								applications/subghz/helpers/subghz_chat.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										29
									
								
								applications/subghz/helpers/subghz_chat.h
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,29 @@ | ||||
| #pragma once | ||||
| #include "../subghz_i.h" | ||||
| 
 | ||||
| typedef struct SubGhzChatWorker SubGhzChatWorker; | ||||
| 
 | ||||
| typedef enum { | ||||
|     SubghzChatEventNoEvent, | ||||
|     SubghzChatEventUserEntrance, | ||||
|     SubghzChatEventUserExit, | ||||
|     SubghzChatEventInputData, | ||||
|     SubghzChatEventRXData, | ||||
|     SubghzChatEventNewMessage, | ||||
| } SubghzChatEventType; | ||||
| 
 | ||||
| typedef struct { | ||||
|     SubghzChatEventType event; | ||||
|     char c; | ||||
| } SubghzChatEvent; | ||||
| 
 | ||||
| SubGhzChatWorker* subghz_chat_worker_alloc(); | ||||
| void subghz_chat_worker_free(SubGhzChatWorker* instance); | ||||
| bool subghz_chat_worker_start(SubGhzChatWorker* instance, uint32_t frequency); | ||||
| void subghz_chat_worker_stop(SubGhzChatWorker* instance); | ||||
| bool subghz_chat_worker_is_running(SubGhzChatWorker* instance); | ||||
| SubghzChatEvent subghz_chat_worker_get_event_chat(SubGhzChatWorker* instance); | ||||
| void subghz_chat_worker_put_event_chat(SubGhzChatWorker* instance, SubghzChatEvent* event); | ||||
| size_t subghz_chat_worker_available(SubGhzChatWorker* instance); | ||||
| size_t subghz_chat_worker_read(SubGhzChatWorker* instance, uint8_t* data, size_t size); | ||||
| bool subghz_chat_worker_write(SubGhzChatWorker* instance, uint8_t* data, size_t size); | ||||
| @ -9,7 +9,8 @@ | ||||
| #include <lib/subghz/subghz_keystore.h> | ||||
| #include <lib/subghz/protocols/subghz_protocol_common.h> | ||||
| #include <lib/subghz/protocols/subghz_protocol_princeton.h> | ||||
| #include <lib/subghz/subghz_tx_rx_worker.h> | ||||
| 
 | ||||
| #include "helpers/subghz_chat.h" | ||||
| 
 | ||||
| #include <notification/notification-messages.h> | ||||
| 
 | ||||
| @ -377,23 +378,34 @@ static void subghz_cli_command_chat(Cli* cli, string_t args) { | ||||
|         return; | ||||
|     } | ||||
| 
 | ||||
|     SubGhzTxRxWorker* subghz_txrx = subghz_tx_rx_worker_alloc(); | ||||
|     subghz_tx_rx_worker_start(subghz_txrx, frequency); | ||||
|     SubGhzChatWorker* subghz_chat = subghz_chat_worker_alloc(); | ||||
|     if(!subghz_chat_worker_start(subghz_chat, frequency)) { | ||||
|         printf("Startup error SubGhzChatWorker\r\n"); | ||||
| 
 | ||||
|         if(subghz_chat_worker_is_running(subghz_chat)) { | ||||
|             subghz_chat_worker_stop(subghz_chat); | ||||
|             subghz_chat_worker_free(subghz_chat); | ||||
|         } | ||||
|         return; | ||||
|     } | ||||
| 
 | ||||
|     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); | ||||
|     string_t output; | ||||
|     string_init(output); | ||||
|     string_t sysmsg; | ||||
|     string_init(sysmsg); | ||||
|     char c; | ||||
|     bool exit = false; | ||||
|     SubghzChatEvent chat_event; | ||||
| 
 | ||||
|     NotificationApp* notification = furi_record_open("notification"); | ||||
| 
 | ||||
| @ -402,71 +414,120 @@ static void subghz_cli_command_chat(Cli* cli, string_t args) { | ||||
|     printf("%s", string_get_cstr(input)); | ||||
|     fflush(stdout); | ||||
| 
 | ||||
|     string_printf(sysmsg, "\033[0;34m%s joined chat.\033[0m", furi_hal_version_get_name_ptr()); | ||||
|     subghz_tx_rx_worker_write( | ||||
|         subghz_txrx, (uint8_t*)string_get_cstr(sysmsg), strlen(string_get_cstr(sysmsg))); | ||||
| 
 | ||||
|     while(!exit) { | ||||
|         if(furi_hal_vcp_rx_with_timeout((uint8_t*)&c, 1, 0) == 1) { | ||||
|             if(c == CliSymbolAsciiETX) { | ||||
|         chat_event = subghz_chat_worker_get_event_chat(subghz_chat); | ||||
|         switch(chat_event.event) { | ||||
|         case SubghzChatEventInputData: | ||||
|             if(chat_event.c == CliSymbolAsciiETX) { | ||||
|                 printf("\r\n"); | ||||
|                 exit = true; | ||||
|                 chat_event.event = SubghzChatEventUserExit; | ||||
|                 subghz_chat_worker_put_event_chat(subghz_chat, &chat_event); | ||||
|                 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) || (c == CliSymbolAsciiDel)) { | ||||
|                 size_t len = string_size(input); | ||||
|                 if(len > string_size(name)) { | ||||
|             } else if( | ||||
|                 (chat_event.c == CliSymbolAsciiBackspace) || (chat_event.c == CliSymbolAsciiDel)) { | ||||
|                 size_t len = string_length_u(input); | ||||
|                 if(len > string_length_u(name)) { | ||||
|                     printf("%s", "\e[D\e[1P"); | ||||
|                     fflush(stdout); | ||||
|                     string_set_strn(input, string_get_cstr(input), len - 1); | ||||
|                     //delete 1 char UTF
 | ||||
|                     const char* str = string_get_cstr(input); | ||||
|                     size_t size = 0; | ||||
|                     m_str1ng_utf8_state_e s = M_STRING_UTF8_STARTING; | ||||
|                     string_unicode_t u = 0; | ||||
|                     string_reset(sysmsg); | ||||
|                     while(*str) { | ||||
|                         m_str1ng_utf8_decode(*str, &s, &u); | ||||
|                         if((s == M_STRING_UTF8_ERROR) || s == M_STRING_UTF8_STARTING) { | ||||
|                             string_push_u(sysmsg, u); | ||||
|                             if(++size >= len - 1) break; | ||||
|                             s = M_STRING_UTF8_STARTING; | ||||
|                         } | ||||
|                         str++; | ||||
|                     } | ||||
|                     string_set(input, sysmsg); | ||||
|                 } | ||||
|             } else if(c == CliSymbolAsciiCR) { | ||||
|             } else if(chat_event.c == CliSymbolAsciiCR) { | ||||
|                 printf("\r\n"); | ||||
|                 subghz_tx_rx_worker_write( | ||||
|                     subghz_txrx, (uint8_t*)string_get_cstr(input), strlen(string_get_cstr(input))); | ||||
|                 string_push_back(input, '\r'); | ||||
|                 string_push_back(input, '\n'); | ||||
|                 while(!subghz_chat_worker_write( | ||||
|                     subghz_chat, | ||||
|                     (uint8_t*)string_get_cstr(input), | ||||
|                     strlen(string_get_cstr(input)))) { | ||||
|                     delay(10); | ||||
|                 } | ||||
| 
 | ||||
|                 string_printf(input, "%s", string_get_cstr(name)); | ||||
|                 printf("%s", string_get_cstr(input)); | ||||
|                 fflush(stdout); | ||||
|             } else if(chat_event.c == CliSymbolAsciiLF) { | ||||
|                 //cut out the symbol \n
 | ||||
|             } else { | ||||
|                 putc(chat_event.c, stdout); | ||||
|                 fflush(stdout); | ||||
|                 string_push_back(input, chat_event.c); | ||||
|                 break; | ||||
|             case SubghzChatEventRXData: | ||||
|                 do { | ||||
|                     memset(message, 0x00, message_max_len); | ||||
|                     size_t len = subghz_chat_worker_read(subghz_chat, message, message_max_len); | ||||
|                     for(size_t i = 0; i < len; i++) { | ||||
|                         string_push_back(output, message[i]); | ||||
|                         if(message[i] == '\n') { | ||||
|                             printf("\r"); | ||||
|                             for(uint8_t i = 0; i < 80; i++) { | ||||
|                                 printf(" "); | ||||
|                             } | ||||
|                             printf("\r %s", string_get_cstr(output)); | ||||
|                             printf("%s", string_get_cstr(input)); | ||||
|                             fflush(stdout); | ||||
|                             string_reset(output); | ||||
|                         } | ||||
|                     } | ||||
|                 } while(subghz_chat_worker_available(subghz_chat)); | ||||
|                 break; | ||||
|             case SubghzChatEventNewMessage: | ||||
|                 notification_message(notification, &sequence_single_vibro); | ||||
|                 break; | ||||
|             case SubghzChatEventUserEntrance: | ||||
|                 string_printf( | ||||
|                     sysmsg, | ||||
|                     "\033[0;34m%s joined chat.\033[0m\r\n", | ||||
|                     furi_hal_version_get_name_ptr()); | ||||
|                 subghz_chat_worker_write( | ||||
|                     subghz_chat, | ||||
|                     (uint8_t*)string_get_cstr(sysmsg), | ||||
|                     strlen(string_get_cstr(sysmsg))); | ||||
|                 break; | ||||
|             case SubghzChatEventUserExit: | ||||
|                 string_printf( | ||||
|                     sysmsg, "\033[0;31m%s left chat.\033[0m\r\n", furi_hal_version_get_name_ptr()); | ||||
|                 subghz_chat_worker_write( | ||||
|                     subghz_chat, | ||||
|                     (uint8_t*)string_get_cstr(sysmsg), | ||||
|                     strlen(string_get_cstr(sysmsg))); | ||||
|                 delay(10); | ||||
|                 exit = true; | ||||
|                 break; | ||||
|             default: | ||||
|                 FURI_LOG_W("SubGhzChat", "Error event"); | ||||
|                 break; | ||||
|             } | ||||
|         } | ||||
| 
 | ||||
|         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); | ||||
| 
 | ||||
|             notification_message(notification, &sequence_single_vibro); | ||||
|         } | ||||
|         osDelay(1); | ||||
|     } | ||||
| 
 | ||||
|     string_printf(sysmsg, "\033[0;31m%s left chat.\033[0m", furi_hal_version_get_name_ptr()); | ||||
|     subghz_tx_rx_worker_write( | ||||
|         subghz_txrx, (uint8_t*)string_get_cstr(sysmsg), strlen(string_get_cstr(sysmsg))); | ||||
|     osDelay(10); | ||||
| 
 | ||||
|     printf("\r\nExit chat\r\n"); | ||||
|     string_clear(input); | ||||
|     string_clear(name); | ||||
|     string_clear(output); | ||||
|     string_clear(sysmsg); | ||||
|     furi_hal_power_suppress_charge_exit(); | ||||
|     furi_record_close("notification"); | ||||
| 
 | ||||
|     if(subghz_tx_rx_worker_is_running(subghz_txrx)) { | ||||
|         subghz_tx_rx_worker_stop(subghz_txrx); | ||||
|         subghz_tx_rx_worker_free(subghz_txrx); | ||||
|     if(subghz_chat_worker_is_running(subghz_chat)) { | ||||
|         subghz_chat_worker_stop(subghz_chat); | ||||
|         subghz_chat_worker_free(subghz_chat); | ||||
|     } | ||||
|     printf("\r\nExit chat\r\n"); | ||||
| } | ||||
| 
 | ||||
| static void subghz_cli_command(Cli* cli, string_t args, void* context) { | ||||
|  | ||||
| @ -291,6 +291,45 @@ static const uint8_t furi_hal_subghz_preset_msk_99_97kb_async_regs[][2] = { | ||||
|     /* End  */ | ||||
|     {0, 0}, | ||||
| }; | ||||
| static const uint8_t furi_hal_subghz_preset_gfsk_9_99kb_async_regs[][2] = { | ||||
| 
 | ||||
|     {CC1101_IOCFG0, 0x06}, //GDO0 Output Pin Configuration
 | ||||
|     {CC1101_FIFOTHR, 0x47}, //RX FIFO and TX FIFO Thresholds
 | ||||
| 
 | ||||
|     //1 : CRC calculation in TX and CRC check in RX enabled,
 | ||||
|     //1 : Variable packet length mode. Packet length configured by the first byte after sync word
 | ||||
|     {CC1101_PKTCTRL0, 0x05}, | ||||
| 
 | ||||
|     {CC1101_FSCTRL1, 0x06}, //Frequency Synthesizer Control
 | ||||
| 
 | ||||
|     {CC1101_SYNC1, 0x46}, | ||||
|     {CC1101_SYNC0, 0x4C}, | ||||
|     {CC1101_ADDR, 0x00}, | ||||
|     {CC1101_PKTLEN, 0x00}, | ||||
| 
 | ||||
|     {CC1101_MDMCFG4, 0xC8}, //Modem Configuration 9.99
 | ||||
|     {CC1101_MDMCFG3, 0x93}, //Modem Configuration
 | ||||
|     {CC1101_MDMCFG2, 0x12}, // 2: 16/16 sync word bits detected
 | ||||
| 
 | ||||
|     {CC1101_DEVIATN, 0x34}, //Deviation = 19.042969
 | ||||
|     {CC1101_MCSM0, 0x18}, //Main Radio Control State Machine Configuration
 | ||||
|     {CC1101_FOCCFG, 0x16}, //Frequency Offset Compensation Configuration
 | ||||
| 
 | ||||
|     {CC1101_AGCCTRL2, 0x43}, //AGC Control
 | ||||
|     {CC1101_AGCCTRL1, 0x40}, | ||||
|     {CC1101_AGCCTRL0, 0x91}, | ||||
| 
 | ||||
|     {CC1101_WORCTRL, 0xFB}, //Wake On Radio Control
 | ||||
|     {CC1101_FSCAL3, 0xE9}, //Frequency Synthesizer Calibration
 | ||||
|     {CC1101_FSCAL2, 0x2A}, //Frequency Synthesizer Calibration
 | ||||
|     {CC1101_FSCAL1, 0x00}, //Frequency Synthesizer Calibration
 | ||||
|     {CC1101_FSCAL0, 0x1F}, //Frequency Synthesizer Calibration
 | ||||
|     {CC1101_TEST2, 0x81}, //Various Test Settings
 | ||||
|     {CC1101_TEST1, 0x35}, //Various Test Settings
 | ||||
|     {CC1101_TEST0, 0x09}, //Various Test Settings
 | ||||
|     /* End  */ | ||||
|     {0, 0}, | ||||
| }; | ||||
| 
 | ||||
| static const uint8_t furi_hal_subghz_preset_ook_async_patable[8] = { | ||||
|     0x00, | ||||
| @ -319,6 +358,15 @@ static const uint8_t furi_hal_subghz_preset_msk_async_patable[8] = { | ||||
|     0x00, | ||||
|     0x00, | ||||
|     0x00}; | ||||
| static const uint8_t furi_hal_subghz_preset_gfsk_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() { | ||||
|     furi_assert(furi_hal_subghz_state == SubGhzStateInit); | ||||
| @ -344,7 +392,8 @@ void furi_hal_subghz_init() { | ||||
|         ; | ||||
| 
 | ||||
|     // GD0 high
 | ||||
|     cc1101_write_reg(&furi_hal_spi_bus_handle_subghz, CC1101_IOCFG0, CC1101IocfgHW | CC1101_IOCFG_INV); | ||||
|     cc1101_write_reg( | ||||
|         &furi_hal_spi_bus_handle_subghz, CC1101_IOCFG0, CC1101IocfgHW | CC1101_IOCFG_INV); | ||||
|     while(hal_gpio_read(&gpio_cc1101_g0) != true) | ||||
|         ; | ||||
| 
 | ||||
| @ -402,6 +451,9 @@ void furi_hal_subghz_load_preset(FuriHalSubGhzPreset preset) { | ||||
|     } 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 if(preset == FuriHalSubGhzPresetGFSK9_99KbAsync) { | ||||
|         furi_hal_subghz_load_registers(furi_hal_subghz_preset_gfsk_9_99kb_async_regs); | ||||
|         furi_hal_subghz_load_patable(furi_hal_subghz_preset_gfsk_async_patable); | ||||
|     } else { | ||||
|         furi_crash(NULL); | ||||
|     } | ||||
| @ -438,10 +490,17 @@ void furi_hal_subghz_flush_rx() { | ||||
|     furi_hal_spi_release(&furi_hal_spi_bus_handle_subghz); | ||||
| } | ||||
| 
 | ||||
| void furi_hal_subghz_flush_tx() { | ||||
|     furi_hal_spi_acquire(&furi_hal_spi_bus_handle_subghz); | ||||
|     cc1101_flush_tx(&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); | ||||
|     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) { | ||||
| @ -520,6 +579,14 @@ float furi_hal_subghz_get_rssi() { | ||||
|     return rssi; | ||||
| } | ||||
| 
 | ||||
| uint8_t furi_hal_subghz_get_lqi() { | ||||
|     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); | ||||
|     return data[0] & 0x7F; | ||||
| } | ||||
| 
 | ||||
| bool furi_hal_subghz_is_frequency_valid(uint32_t value) { | ||||
|     if(!(value >= 299999755 && value <= 348000335) && | ||||
|        !(value >= 386999938 && value <= 464000000) && | ||||
| @ -607,13 +674,15 @@ void furi_hal_subghz_set_path(FuriHalSubGhzPath path) { | ||||
|     furi_hal_spi_acquire(&furi_hal_spi_bus_handle_subghz); | ||||
|     if(path == FuriHalSubGhzPath433) { | ||||
|         hal_gpio_write(&gpio_rf_sw_0, 0); | ||||
|         cc1101_write_reg(&furi_hal_spi_bus_handle_subghz, CC1101_IOCFG2, CC1101IocfgHW | CC1101_IOCFG_INV); | ||||
|         cc1101_write_reg( | ||||
|             &furi_hal_spi_bus_handle_subghz, CC1101_IOCFG2, CC1101IocfgHW | CC1101_IOCFG_INV); | ||||
|     } else if(path == FuriHalSubGhzPath315) { | ||||
|         hal_gpio_write(&gpio_rf_sw_0, 1); | ||||
|         cc1101_write_reg(&furi_hal_spi_bus_handle_subghz, CC1101_IOCFG2, CC1101IocfgHW); | ||||
|     } else if(path == FuriHalSubGhzPath868) { | ||||
|         hal_gpio_write(&gpio_rf_sw_0, 1); | ||||
|         cc1101_write_reg(&furi_hal_spi_bus_handle_subghz, CC1101_IOCFG2, CC1101IocfgHW | CC1101_IOCFG_INV); | ||||
|         cc1101_write_reg( | ||||
|             &furi_hal_spi_bus_handle_subghz, CC1101_IOCFG2, CC1101IocfgHW | CC1101_IOCFG_INV); | ||||
|     } else if(path == FuriHalSubGhzPathIsolate) { | ||||
|         hal_gpio_write(&gpio_rf_sw_0, 0); | ||||
|         cc1101_write_reg(&furi_hal_spi_bus_handle_subghz, CC1101_IOCFG2, CC1101IocfgHW); | ||||
|  | ||||
| @ -291,6 +291,45 @@ static const uint8_t furi_hal_subghz_preset_msk_99_97kb_async_regs[][2] = { | ||||
|     /* End  */ | ||||
|     {0, 0}, | ||||
| }; | ||||
| static const uint8_t furi_hal_subghz_preset_gfsk_9_99kb_async_regs[][2] = { | ||||
| 
 | ||||
|     {CC1101_IOCFG0, 0x06}, //GDO0 Output Pin Configuration
 | ||||
|     {CC1101_FIFOTHR, 0x47}, //RX FIFO and TX FIFO Thresholds
 | ||||
| 
 | ||||
|     //1 : CRC calculation in TX and CRC check in RX enabled, 
 | ||||
|     //1 : Variable packet length mode. Packet length configured by the first byte after sync word
 | ||||
|     {CC1101_PKTCTRL0,0x05},  | ||||
| 
 | ||||
|     {CC1101_FSCTRL1, 0x06}, //Frequency Synthesizer Control
 | ||||
| 
 | ||||
|     {CC1101_SYNC1, 0x46}, | ||||
|     {CC1101_SYNC0, 0x4C}, | ||||
|     {CC1101_ADDR, 0x00}, | ||||
|     {CC1101_PKTLEN, 0x00}, | ||||
| 
 | ||||
|     {CC1101_MDMCFG4, 0xC8}, //Modem Configuration 9.99
 | ||||
|     {CC1101_MDMCFG3, 0x93}, //Modem Configuration
 | ||||
|     {CC1101_MDMCFG2, 0x12}, // 2: 16/16 sync word bits detected
 | ||||
| 
 | ||||
|     {CC1101_DEVIATN, 0x34}, //Deviation = 19.042969
 | ||||
|     {CC1101_MCSM0, 0x18}, //Main Radio Control State Machine Configuration
 | ||||
|     {CC1101_FOCCFG, 0x16}, //Frequency Offset Compensation Configuration
 | ||||
|      | ||||
|     {CC1101_AGCCTRL2, 0x43 },   //AGC Control
 | ||||
|     {CC1101_AGCCTRL1, 0x40}, | ||||
|     {CC1101_AGCCTRL0, 0x91}, | ||||
| 
 | ||||
|     {CC1101_WORCTRL, 0xFB}, //Wake On Radio Control
 | ||||
|     {CC1101_FSCAL3, 0xE9}, //Frequency Synthesizer Calibration
 | ||||
|     {CC1101_FSCAL2, 0x2A}, //Frequency Synthesizer Calibration
 | ||||
|     {CC1101_FSCAL1, 0x00}, //Frequency Synthesizer Calibration
 | ||||
|     {CC1101_FSCAL0, 0x1F}, //Frequency Synthesizer Calibration
 | ||||
|     {CC1101_TEST2, 0x81}, //Various Test Settings
 | ||||
|     {CC1101_TEST1, 0x35}, //Various Test Settings
 | ||||
|     {CC1101_TEST0, 0x09}, //Various Test Settings
 | ||||
|     /* End  */ | ||||
|     {0, 0}, | ||||
| }; | ||||
| 
 | ||||
| static const uint8_t furi_hal_subghz_preset_ook_async_patable[8] = { | ||||
|     0x00, | ||||
| @ -319,6 +358,15 @@ static const uint8_t furi_hal_subghz_preset_msk_async_patable[8] = { | ||||
|     0x00, | ||||
|     0x00, | ||||
|     0x00}; | ||||
| static const uint8_t furi_hal_subghz_preset_gfsk_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() { | ||||
|     furi_assert(furi_hal_subghz_state == SubGhzStateInit); | ||||
| @ -402,7 +450,10 @@ void furi_hal_subghz_load_preset(FuriHalSubGhzPreset preset) { | ||||
|     } 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 if(preset == FuriHalSubGhzPresetGFSK9_99KbAsync) { | ||||
|         furi_hal_subghz_load_registers(furi_hal_subghz_preset_gfsk_9_99kb_async_regs); | ||||
|         furi_hal_subghz_load_patable(furi_hal_subghz_preset_gfsk_async_patable); | ||||
|     } else{ | ||||
|         furi_crash(NULL); | ||||
|     } | ||||
| } | ||||
| @ -438,6 +489,12 @@ void furi_hal_subghz_flush_rx() { | ||||
|     furi_hal_spi_release(&furi_hal_spi_bus_handle_subghz); | ||||
| } | ||||
| 
 | ||||
| void furi_hal_subghz_flush_tx() { | ||||
|     furi_hal_spi_acquire(&furi_hal_spi_bus_handle_subghz); | ||||
|     cc1101_flush_tx(&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); | ||||
| @ -520,6 +577,14 @@ float furi_hal_subghz_get_rssi() { | ||||
|     return rssi; | ||||
| } | ||||
| 
 | ||||
| uint8_t furi_hal_subghz_get_lqi() { | ||||
|     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); | ||||
|     return data[0] & 0x7F; | ||||
| } | ||||
| 
 | ||||
| bool furi_hal_subghz_is_frequency_valid(uint32_t value) { | ||||
|     if(!(value >= 299999755 && value <= 348000335) && | ||||
|        !(value >= 386999938 && value <= 464000000) && | ||||
|  | ||||
| @ -21,6 +21,7 @@ typedef enum { | ||||
|     FuriHalSubGhzPreset2FSKDev238Async, /**< FM, deviation 2.380371 kHz, asynchronous */ | ||||
|     FuriHalSubGhzPreset2FSKDev476Async, /**< FM, deviation 4.760742 kHz, asynchronous */ | ||||
|     FuriHalSubGhzPresetMSK99_97KbAsync, /**< MSK, deviation 47.60742 kHz, 99.97Kb/s, asynchronous */ | ||||
|     FuriHalSubGhzPresetGFSK9_99KbAsync  /**< GFSK, deviation 19.042969 kHz, 9.996Kb/s, asynchronous */ | ||||
| } FuriHalSubGhzPreset; | ||||
| 
 | ||||
| /** Switchable Radio Paths */ | ||||
| @ -114,6 +115,10 @@ void furi_hal_subghz_read_packet(uint8_t* data, uint8_t* size); | ||||
|  */ | ||||
| void furi_hal_subghz_flush_rx(); | ||||
| 
 | ||||
| /** Flush tx FIFO buffer
 | ||||
|  */ | ||||
| void furi_hal_subghz_flush_tx(); | ||||
| 
 | ||||
| /** Shutdown Issue spwd command
 | ||||
|  * @warning    registers content will be lost | ||||
|  */ | ||||
| @ -144,6 +149,12 @@ bool furi_hal_subghz_tx(); | ||||
|  */ | ||||
| float furi_hal_subghz_get_rssi(); | ||||
| 
 | ||||
| /** Get LQI
 | ||||
|  * | ||||
|  * @return     LQI value | ||||
|  */ | ||||
| uint8_t furi_hal_subghz_get_lqi(); | ||||
| 
 | ||||
| /** Check if frequency is in valid range
 | ||||
|  * | ||||
|  * @param      value  frequency in Hz | ||||
|  | ||||
| @ -5,11 +5,11 @@ | ||||
| 
 | ||||
| #define TAG "SubGhzTxRxWorker" | ||||
| 
 | ||||
| #define GUBGHZ_TXRX_WORKER_BUF_SIZE 2048 | ||||
| #define SUBGHZ_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 SUBGHZ_TXRX_WORKER_MAX_TXRX_SIZE 60 | ||||
| 
 | ||||
| #define GUBGHZ_TXRX_WORKER_TIMEOUT_READ_WRITE_BUF 40 | ||||
| #define SUBGHZ_TXRX_WORKER_TIMEOUT_READ_WRITE_BUF 40 | ||||
| 
 | ||||
| struct SubGhzTxRxWorker { | ||||
|     FuriThread* thread; | ||||
| @ -19,7 +19,7 @@ struct SubGhzTxRxWorker { | ||||
|     volatile bool worker_running; | ||||
|     volatile bool worker_stoping; | ||||
| 
 | ||||
|     SubGhzTxRxWorkerStatus satus; | ||||
|     SubGhzTxRxWorkerStatus status; | ||||
| 
 | ||||
|     uint32_t frequency; | ||||
| 
 | ||||
| @ -33,7 +33,7 @@ bool subghz_tx_rx_worker_write(SubGhzTxRxWorker* instance, uint8_t* data, size_t | ||||
|     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) == | ||||
|                instance->stream_tx, data, size, SUBGHZ_TXRX_WORKER_TIMEOUT_READ_WRITE_BUF) == | ||||
|            size) { | ||||
|             ret = true; | ||||
|         } | ||||
| @ -48,22 +48,7 @@ size_t subghz_tx_rx_worker_available(SubGhzTxRxWorker* instance) { | ||||
| 
 | ||||
| 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; | ||||
|     return xStreamBufferReceive(instance->stream_rx, data, size, 0); | ||||
| } | ||||
| 
 | ||||
| void subghz_tx_rx_worker_set_callback_have_read( | ||||
| @ -78,11 +63,11 @@ void subghz_tx_rx_worker_set_callback_have_read( | ||||
| } | ||||
| 
 | ||||
| bool subghz_tx_rx_worker_rx(SubGhzTxRxWorker* instance, uint8_t* data, uint8_t* size) { | ||||
|     uint8_t timeout = 20; | ||||
|     uint8_t timeout = 100; | ||||
|     bool ret = false; | ||||
|     if(instance->satus != SubGhzTxRxWorkerStatusRx) { | ||||
|     if(instance->status != SubGhzTxRxWorkerStatusRx) { | ||||
|         furi_hal_subghz_rx(); | ||||
|         instance->satus = SubGhzTxRxWorkerStatusRx; | ||||
|         instance->status = SubGhzTxRxWorkerStatusRx; | ||||
|         osDelay(1); | ||||
|     } | ||||
|     //waiting for reception to complete
 | ||||
| @ -97,6 +82,8 @@ bool subghz_tx_rx_worker_rx(SubGhzTxRxWorker* instance, uint8_t* data, uint8_t* | ||||
|     } | ||||
| 
 | ||||
|     if(furi_hal_subghz_rx_pipe_not_empty()) { | ||||
|         FURI_LOG_I( | ||||
|             TAG, "RSSI: %03.1fdbm LQI: %d", furi_hal_subghz_get_rssi(), furi_hal_subghz_get_lqi()); | ||||
|         if(furi_hal_subghz_is_rx_data_crc_valid()) { | ||||
|             furi_hal_subghz_read_packet(data, size); | ||||
|             ret = true; | ||||
| @ -108,15 +95,13 @@ bool subghz_tx_rx_worker_rx(SubGhzTxRxWorker* instance, uint8_t* data, uint8_t* | ||||
| } | ||||
| 
 | ||||
| void subghz_tx_rx_worker_tx(SubGhzTxRxWorker* instance, uint8_t* data, size_t size) { | ||||
|     uint8_t timeout = 40; | ||||
|     if(instance->satus != SubGhzTxRxWorkerStatusIDLE) { | ||||
|     uint8_t timeout = 200; | ||||
|     if(instance->status != SubGhzTxRxWorkerStatusIDLE) { | ||||
|         furi_hal_subghz_idle(); | ||||
|     } | ||||
|     furi_hal_subghz_write_packet(data, size); | ||||
|     instance->satus = SubGhzTxRxWorkerStatusTx; | ||||
| 
 | ||||
|     furi_hal_subghz_tx(); //start send
 | ||||
| 
 | ||||
|     instance->status = SubGhzTxRxWorkerStatusTx; | ||||
|     while(!hal_gpio_read(&gpio_cc1101_g0)) { // Wait for GDO0 to be set -> sync transmitted
 | ||||
|         osDelay(1); | ||||
|         if(!--timeout) { | ||||
| @ -132,7 +117,7 @@ void subghz_tx_rx_worker_tx(SubGhzTxRxWorker* instance, uint8_t* data, size_t si | ||||
|         } | ||||
|     } | ||||
|     furi_hal_subghz_idle(); | ||||
|     instance->satus = SubGhzTxRxWorkerStatusIDLE; | ||||
|     instance->status = SubGhzTxRxWorkerStatusIDLE; | ||||
| } | ||||
| /** Worker thread
 | ||||
|  *  | ||||
| @ -145,13 +130,14 @@ static int32_t subghz_tx_rx_worker_thread(void* context) { | ||||
| 
 | ||||
|     furi_hal_subghz_reset(); | ||||
|     furi_hal_subghz_idle(); | ||||
|     furi_hal_subghz_load_preset(FuriHalSubGhzPresetMSK99_97KbAsync); | ||||
|     furi_hal_subghz_load_preset(FuriHalSubGhzPresetGFSK9_99KbAsync); | ||||
|     //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}; | ||||
|     uint8_t data[SUBGHZ_TXRX_WORKER_MAX_TXRX_SIZE + 1] = {0}; | ||||
|     size_t size_tx = 0; | ||||
|     uint8_t size_rx[1] = {0}; | ||||
|     uint8_t timeout_tx = 0; | ||||
| @ -161,18 +147,18 @@ static int32_t subghz_tx_rx_worker_thread(void* context) { | ||||
|         //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) { | ||||
|             timeout_tx = 10; //20ms
 | ||||
|             if(size_tx > SUBGHZ_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); | ||||
|                     SUBGHZ_TXRX_WORKER_MAX_TXRX_SIZE, | ||||
|                     SUBGHZ_TXRX_WORKER_TIMEOUT_READ_WRITE_BUF); | ||||
|                 subghz_tx_rx_worker_tx(instance, data, SUBGHZ_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); | ||||
|                     instance->stream_tx, &data, size_tx, SUBGHZ_TXRX_WORKER_TIMEOUT_READ_WRITE_BUF); | ||||
|                 subghz_tx_rx_worker_tx(instance, data, size_tx); | ||||
|             } | ||||
|         } else { | ||||
| @ -188,7 +174,7 @@ static int32_t subghz_tx_rx_worker_thread(void* context) { | ||||
|                         instance->stream_rx, | ||||
|                         &data, | ||||
|                         size_rx[0], | ||||
|                         GUBGHZ_TXRX_WORKER_TIMEOUT_READ_WRITE_BUF); | ||||
|                         SUBGHZ_TXRX_WORKER_TIMEOUT_READ_WRITE_BUF); | ||||
|                     if(callback_rx) { | ||||
|                         instance->callback_have_read(instance->context_have_read); | ||||
|                         callback_rx = false; | ||||
| @ -219,11 +205,11 @@ SubGhzTxRxWorker* subghz_tx_rx_worker_alloc() { | ||||
|     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)); | ||||
|         xStreamBufferCreate(sizeof(uint8_t) * SUBGHZ_TXRX_WORKER_BUF_SIZE, sizeof(uint8_t)); | ||||
|     instance->stream_rx = | ||||
|         xStreamBufferCreate(sizeof(uint8_t) * GUBGHZ_TXRX_WORKER_BUF_SIZE, sizeof(uint8_t)); | ||||
|         xStreamBufferCreate(sizeof(uint8_t) * SUBGHZ_TXRX_WORKER_BUF_SIZE, sizeof(uint8_t)); | ||||
| 
 | ||||
|     instance->satus = SubGhzTxRxWorkerStatusIDLE; | ||||
|     instance->status = SubGhzTxRxWorkerStatusIDLE; | ||||
|     instance->worker_stoping = true; | ||||
| 
 | ||||
|     return instance; | ||||
| @ -231,7 +217,7 @@ SubGhzTxRxWorker* subghz_tx_rx_worker_alloc() { | ||||
| 
 | ||||
| void subghz_tx_rx_worker_free(SubGhzTxRxWorker* instance) { | ||||
|     furi_assert(instance); | ||||
| 
 | ||||
|     furi_assert(!instance->worker_running); | ||||
|     vStreamBufferDelete(instance->stream_tx); | ||||
|     vStreamBufferDelete(instance->stream_rx); | ||||
|     furi_thread_free(instance->thread); | ||||
|  | ||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user
	 Skorpionm
						Skorpionm