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, |     CliSymbolAsciiBell = 0x07, | ||||||
|     CliSymbolAsciiBackspace = 0x08, |     CliSymbolAsciiBackspace = 0x08, | ||||||
|     CliSymbolAsciiTab = 0x09, |     CliSymbolAsciiTab = 0x09, | ||||||
|  |     CliSymbolAsciiLF = 0x0A, | ||||||
|     CliSymbolAsciiCR = 0x0D, |     CliSymbolAsciiCR = 0x0D, | ||||||
|     CliSymbolAsciiEsc = 0x1B, |     CliSymbolAsciiEsc = 0x1B, | ||||||
|     CliSymbolAsciiUS = 0x1F, |     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/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> | 
 | ||||||
|  | #include "helpers/subghz_chat.h" | ||||||
| 
 | 
 | ||||||
| #include <notification/notification-messages.h> | #include <notification/notification-messages.h> | ||||||
| 
 | 
 | ||||||
| @ -377,23 +378,34 @@ static void subghz_cli_command_chat(Cli* cli, string_t args) { | |||||||
|         return; |         return; | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     SubGhzTxRxWorker* subghz_txrx = subghz_tx_rx_worker_alloc(); |     SubGhzChatWorker* subghz_chat = subghz_chat_worker_alloc(); | ||||||
|     subghz_tx_rx_worker_start(subghz_txrx, frequency); |     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("Receiving at frequency %lu Hz\r\n", frequency); | ||||||
|     printf("Press CTRL+C to stop\r\n"); |     printf("Press CTRL+C to stop\r\n"); | ||||||
| 
 | 
 | ||||||
|     furi_hal_power_suppress_charge_enter(); |     furi_hal_power_suppress_charge_enter(); | ||||||
|  | 
 | ||||||
|     size_t message_max_len = 64; |     size_t message_max_len = 64; | ||||||
|     uint8_t message[64] = {0}; |     uint8_t message[64] = {0}; | ||||||
|     string_t input; |     string_t input; | ||||||
|     string_init(input); |     string_init(input); | ||||||
|     string_t name; |     string_t name; | ||||||
|     string_init(name); |     string_init(name); | ||||||
|  |     string_t output; | ||||||
|  |     string_init(output); | ||||||
|     string_t sysmsg; |     string_t sysmsg; | ||||||
|     string_init(sysmsg); |     string_init(sysmsg); | ||||||
|     char c; |  | ||||||
|     bool exit = false; |     bool exit = false; | ||||||
|  |     SubghzChatEvent chat_event; | ||||||
| 
 | 
 | ||||||
|     NotificationApp* notification = furi_record_open("notification"); |     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)); |     printf("%s", string_get_cstr(input)); | ||||||
|     fflush(stdout); |     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) { |     while(!exit) { | ||||||
|         if(furi_hal_vcp_rx_with_timeout((uint8_t*)&c, 1, 0) == 1) { |         chat_event = subghz_chat_worker_get_event_chat(subghz_chat); | ||||||
|             if(c == CliSymbolAsciiETX) { |         switch(chat_event.event) { | ||||||
|  |         case SubghzChatEventInputData: | ||||||
|  |             if(chat_event.c == CliSymbolAsciiETX) { | ||||||
|                 printf("\r\n"); |                 printf("\r\n"); | ||||||
|                 exit = true; |                 chat_event.event = SubghzChatEventUserExit; | ||||||
|  |                 subghz_chat_worker_put_event_chat(subghz_chat, &chat_event); | ||||||
|                 break; |                 break; | ||||||
|             } else if((c >= 0x20 && c < 0x7F) || (c >= 0x80 && c < 0xF0)) { |             } else if( | ||||||
|                 putc(c, stdout); |                 (chat_event.c == CliSymbolAsciiBackspace) || (chat_event.c == CliSymbolAsciiDel)) { | ||||||
|                 fflush(stdout); |                 size_t len = string_length_u(input); | ||||||
|                 string_push_back(input, c); |                 if(len > string_length_u(name)) { | ||||||
|             } else if((c == CliSymbolAsciiBackspace) || (c == CliSymbolAsciiDel)) { |  | ||||||
|                 size_t len = string_size(input); |  | ||||||
|                 if(len > string_size(name)) { |  | ||||||
|                     printf("%s", "\e[D\e[1P"); |                     printf("%s", "\e[D\e[1P"); | ||||||
|                     fflush(stdout); |                     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; | ||||||
|                         } |                         } | ||||||
|             } else if(c == CliSymbolAsciiCR) { |                         str++; | ||||||
|  |                     } | ||||||
|  |                     string_set(input, sysmsg); | ||||||
|  |                 } | ||||||
|  |             } else if(chat_event.c == CliSymbolAsciiCR) { | ||||||
|                 printf("\r\n"); |                 printf("\r\n"); | ||||||
|                 subghz_tx_rx_worker_write( |                 string_push_back(input, '\r'); | ||||||
|                     subghz_txrx, (uint8_t*)string_get_cstr(input), strlen(string_get_cstr(input))); |                 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)); |                 string_printf(input, "%s", string_get_cstr(name)); | ||||||
|                 printf("%s", string_get_cstr(input)); |                 printf("%s", string_get_cstr(input)); | ||||||
|                 fflush(stdout); |                 fflush(stdout); | ||||||
|             } |             } else if(chat_event.c == CliSymbolAsciiLF) { | ||||||
|         } |                 //cut out the symbol \n
 | ||||||
| 
 |             } else { | ||||||
|         if(subghz_tx_rx_worker_available(subghz_txrx)) { |                 putc(chat_event.c, stdout); | ||||||
|  |                 fflush(stdout); | ||||||
|  |                 string_push_back(input, chat_event.c); | ||||||
|  |                 break; | ||||||
|  |             case SubghzChatEventRXData: | ||||||
|  |                 do { | ||||||
|                     memset(message, 0x00, message_max_len); |                     memset(message, 0x00, message_max_len); | ||||||
|             subghz_tx_rx_worker_read(subghz_txrx, message, 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"); |                             printf("\r"); | ||||||
|                             for(uint8_t i = 0; i < 80; i++) { |                             for(uint8_t i = 0; i < 80; i++) { | ||||||
|                                 printf(" "); |                                 printf(" "); | ||||||
|                             } |                             } | ||||||
| 
 |                             printf("\r %s", string_get_cstr(output)); | ||||||
|             printf("\r %s\r\n", message); |  | ||||||
| 
 |  | ||||||
|                             printf("%s", string_get_cstr(input)); |                             printf("%s", string_get_cstr(input)); | ||||||
|                             fflush(stdout); |                             fflush(stdout); | ||||||
| 
 |                             string_reset(output); | ||||||
|  |                         } | ||||||
|  |                     } | ||||||
|  |                 } while(subghz_chat_worker_available(subghz_chat)); | ||||||
|  |                 break; | ||||||
|  |             case SubghzChatEventNewMessage: | ||||||
|                 notification_message(notification, &sequence_single_vibro); |                 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; | ||||||
|  |             } | ||||||
|         } |         } | ||||||
|         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(input); | ||||||
|     string_clear(name); |     string_clear(name); | ||||||
|  |     string_clear(output); | ||||||
|     string_clear(sysmsg); |     string_clear(sysmsg); | ||||||
|     furi_hal_power_suppress_charge_exit(); |     furi_hal_power_suppress_charge_exit(); | ||||||
|     furi_record_close("notification"); |     furi_record_close("notification"); | ||||||
| 
 | 
 | ||||||
|     if(subghz_tx_rx_worker_is_running(subghz_txrx)) { |     if(subghz_chat_worker_is_running(subghz_chat)) { | ||||||
|         subghz_tx_rx_worker_stop(subghz_txrx); |         subghz_chat_worker_stop(subghz_chat); | ||||||
|         subghz_tx_rx_worker_free(subghz_txrx); |         subghz_chat_worker_free(subghz_chat); | ||||||
|     } |     } | ||||||
|  |     printf("\r\nExit chat\r\n"); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| static void subghz_cli_command(Cli* cli, string_t args, void* context) { | 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  */ |     /* End  */ | ||||||
|     {0, 0}, |     {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] = { | static const uint8_t furi_hal_subghz_preset_ook_async_patable[8] = { | ||||||
|     0x00, |     0x00, | ||||||
| @ -319,6 +358,15 @@ static const uint8_t furi_hal_subghz_preset_msk_async_patable[8] = { | |||||||
|     0x00, |     0x00, | ||||||
|     0x00, |     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() { | void furi_hal_subghz_init() { | ||||||
|     furi_assert(furi_hal_subghz_state == SubGhzStateInit); |     furi_assert(furi_hal_subghz_state == SubGhzStateInit); | ||||||
| @ -344,7 +392,8 @@ void furi_hal_subghz_init() { | |||||||
|         ; |         ; | ||||||
| 
 | 
 | ||||||
|     // GD0 high
 |     // 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) |     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) { |     } else if(preset == FuriHalSubGhzPresetMSK99_97KbAsync) { | ||||||
|         furi_hal_subghz_load_registers(furi_hal_subghz_preset_msk_99_97kb_async_regs); |         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); |         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 { |     } else { | ||||||
|         furi_crash(NULL); |         furi_crash(NULL); | ||||||
|     } |     } | ||||||
| @ -438,10 +490,17 @@ 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); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | 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() { | bool furi_hal_subghz_rx_pipe_not_empty() { | ||||||
|     CC1101RxBytes status[1]; |     CC1101RxBytes status[1]; | ||||||
|     furi_hal_spi_acquire(&furi_hal_spi_bus_handle_subghz); |     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); |     furi_hal_spi_release(&furi_hal_spi_bus_handle_subghz); | ||||||
|     // TODO: you can add a buffer overflow flag if needed
 |     // TODO: you can add a buffer overflow flag if needed
 | ||||||
|     if(status->NUM_RXBYTES > 0) { |     if(status->NUM_RXBYTES > 0) { | ||||||
| @ -520,6 +579,14 @@ float furi_hal_subghz_get_rssi() { | |||||||
|     return 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) { | bool furi_hal_subghz_is_frequency_valid(uint32_t value) { | ||||||
|     if(!(value >= 299999755 && value <= 348000335) && |     if(!(value >= 299999755 && value <= 348000335) && | ||||||
|        !(value >= 386999938 && value <= 464000000) && |        !(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); |     furi_hal_spi_acquire(&furi_hal_spi_bus_handle_subghz); | ||||||
|     if(path == FuriHalSubGhzPath433) { |     if(path == FuriHalSubGhzPath433) { | ||||||
|         hal_gpio_write(&gpio_rf_sw_0, 0); |         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) { |     } else if(path == FuriHalSubGhzPath315) { | ||||||
|         hal_gpio_write(&gpio_rf_sw_0, 1); |         hal_gpio_write(&gpio_rf_sw_0, 1); | ||||||
|         cc1101_write_reg(&furi_hal_spi_bus_handle_subghz, CC1101_IOCFG2, CC1101IocfgHW); |         cc1101_write_reg(&furi_hal_spi_bus_handle_subghz, CC1101_IOCFG2, CC1101IocfgHW); | ||||||
|     } else if(path == FuriHalSubGhzPath868) { |     } else if(path == FuriHalSubGhzPath868) { | ||||||
|         hal_gpio_write(&gpio_rf_sw_0, 1); |         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) { |     } else if(path == FuriHalSubGhzPathIsolate) { | ||||||
|         hal_gpio_write(&gpio_rf_sw_0, 0); |         hal_gpio_write(&gpio_rf_sw_0, 0); | ||||||
|         cc1101_write_reg(&furi_hal_spi_bus_handle_subghz, CC1101_IOCFG2, CC1101IocfgHW); |         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  */ |     /* End  */ | ||||||
|     {0, 0}, |     {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] = { | static const uint8_t furi_hal_subghz_preset_ook_async_patable[8] = { | ||||||
|     0x00, |     0x00, | ||||||
| @ -319,6 +358,15 @@ static const uint8_t furi_hal_subghz_preset_msk_async_patable[8] = { | |||||||
|     0x00, |     0x00, | ||||||
|     0x00, |     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() { | void furi_hal_subghz_init() { | ||||||
|     furi_assert(furi_hal_subghz_state == SubGhzStateInit); |     furi_assert(furi_hal_subghz_state == SubGhzStateInit); | ||||||
| @ -402,7 +450,10 @@ void furi_hal_subghz_load_preset(FuriHalSubGhzPreset preset) { | |||||||
|     } else if(preset == FuriHalSubGhzPresetMSK99_97KbAsync) { |     } else if(preset == FuriHalSubGhzPresetMSK99_97KbAsync) { | ||||||
|         furi_hal_subghz_load_registers(furi_hal_subghz_preset_msk_99_97kb_async_regs); |         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); |         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); |         furi_crash(NULL); | ||||||
|     } |     } | ||||||
| } | } | ||||||
| @ -438,6 +489,12 @@ 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); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | 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() { | bool furi_hal_subghz_rx_pipe_not_empty() { | ||||||
|     CC1101RxBytes status[1]; |     CC1101RxBytes status[1]; | ||||||
|     furi_hal_spi_acquire(&furi_hal_spi_bus_handle_subghz); |     furi_hal_spi_acquire(&furi_hal_spi_bus_handle_subghz); | ||||||
| @ -520,6 +577,14 @@ float furi_hal_subghz_get_rssi() { | |||||||
|     return 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) { | bool furi_hal_subghz_is_frequency_valid(uint32_t value) { | ||||||
|     if(!(value >= 299999755 && value <= 348000335) && |     if(!(value >= 299999755 && value <= 348000335) && | ||||||
|        !(value >= 386999938 && value <= 464000000) && |        !(value >= 386999938 && value <= 464000000) && | ||||||
|  | |||||||
| @ -21,6 +21,7 @@ typedef enum { | |||||||
|     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 */ |     FuriHalSubGhzPresetMSK99_97KbAsync, /**< MSK, deviation 47.60742 kHz, 99.97Kb/s, asynchronous */ | ||||||
|  |     FuriHalSubGhzPresetGFSK9_99KbAsync  /**< GFSK, deviation 19.042969 kHz, 9.996Kb/s, asynchronous */ | ||||||
| } FuriHalSubGhzPreset; | } FuriHalSubGhzPreset; | ||||||
| 
 | 
 | ||||||
| /** Switchable Radio Paths */ | /** 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(); | void furi_hal_subghz_flush_rx(); | ||||||
| 
 | 
 | ||||||
|  | /** Flush tx FIFO buffer
 | ||||||
|  |  */ | ||||||
|  | void furi_hal_subghz_flush_tx(); | ||||||
|  | 
 | ||||||
| /** Shutdown Issue spwd command
 | /** Shutdown Issue spwd command
 | ||||||
|  * @warning    registers content will be lost |  * @warning    registers content will be lost | ||||||
|  */ |  */ | ||||||
| @ -144,6 +149,12 @@ bool furi_hal_subghz_tx(); | |||||||
|  */ |  */ | ||||||
| float furi_hal_subghz_get_rssi(); | 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
 | /** Check if frequency is in valid range
 | ||||||
|  * |  * | ||||||
|  * @param      value  frequency in Hz |  * @param      value  frequency in Hz | ||||||
|  | |||||||
| @ -5,11 +5,11 @@ | |||||||
| 
 | 
 | ||||||
| #define TAG "SubGhzTxRxWorker" | #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
 | //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 { | struct SubGhzTxRxWorker { | ||||||
|     FuriThread* thread; |     FuriThread* thread; | ||||||
| @ -19,7 +19,7 @@ struct SubGhzTxRxWorker { | |||||||
|     volatile bool worker_running; |     volatile bool worker_running; | ||||||
|     volatile bool worker_stoping; |     volatile bool worker_stoping; | ||||||
| 
 | 
 | ||||||
|     SubGhzTxRxWorkerStatus satus; |     SubGhzTxRxWorkerStatus status; | ||||||
| 
 | 
 | ||||||
|     uint32_t frequency; |     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); |     size_t stream_tx_free_byte = xStreamBufferSpacesAvailable(instance->stream_tx); | ||||||
|     if(size && (stream_tx_free_byte >= size)) { |     if(size && (stream_tx_free_byte >= size)) { | ||||||
|         if(xStreamBufferSend( |         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) { |            size) { | ||||||
|             ret = true; |             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) { | size_t subghz_tx_rx_worker_read(SubGhzTxRxWorker* instance, uint8_t* data, size_t size) { | ||||||
|     furi_assert(instance); |     furi_assert(instance); | ||||||
|     size_t len = 0; |     return xStreamBufferReceive(instance->stream_rx, data, size, 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( | 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) { | 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; |     bool ret = false; | ||||||
|     if(instance->satus != SubGhzTxRxWorkerStatusRx) { |     if(instance->status != SubGhzTxRxWorkerStatusRx) { | ||||||
|         furi_hal_subghz_rx(); |         furi_hal_subghz_rx(); | ||||||
|         instance->satus = SubGhzTxRxWorkerStatusRx; |         instance->status = SubGhzTxRxWorkerStatusRx; | ||||||
|         osDelay(1); |         osDelay(1); | ||||||
|     } |     } | ||||||
|     //waiting for reception to complete
 |     //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()) { |     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()) { |         if(furi_hal_subghz_is_rx_data_crc_valid()) { | ||||||
|             furi_hal_subghz_read_packet(data, size); |             furi_hal_subghz_read_packet(data, size); | ||||||
|             ret = true; |             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) { | void subghz_tx_rx_worker_tx(SubGhzTxRxWorker* instance, uint8_t* data, size_t size) { | ||||||
|     uint8_t timeout = 40; |     uint8_t timeout = 200; | ||||||
|     if(instance->satus != SubGhzTxRxWorkerStatusIDLE) { |     if(instance->status != SubGhzTxRxWorkerStatusIDLE) { | ||||||
|         furi_hal_subghz_idle(); |         furi_hal_subghz_idle(); | ||||||
|     } |     } | ||||||
|     furi_hal_subghz_write_packet(data, size); |     furi_hal_subghz_write_packet(data, size); | ||||||
|     instance->satus = SubGhzTxRxWorkerStatusTx; |  | ||||||
| 
 |  | ||||||
|     furi_hal_subghz_tx(); //start send
 |     furi_hal_subghz_tx(); //start send
 | ||||||
| 
 |     instance->status = SubGhzTxRxWorkerStatusTx; | ||||||
|     while(!hal_gpio_read(&gpio_cc1101_g0)) { // Wait for GDO0 to be set -> sync transmitted
 |     while(!hal_gpio_read(&gpio_cc1101_g0)) { // Wait for GDO0 to be set -> sync transmitted
 | ||||||
|         osDelay(1); |         osDelay(1); | ||||||
|         if(!--timeout) { |         if(!--timeout) { | ||||||
| @ -132,7 +117,7 @@ void subghz_tx_rx_worker_tx(SubGhzTxRxWorker* instance, uint8_t* data, size_t si | |||||||
|         } |         } | ||||||
|     } |     } | ||||||
|     furi_hal_subghz_idle(); |     furi_hal_subghz_idle(); | ||||||
|     instance->satus = SubGhzTxRxWorkerStatusIDLE; |     instance->status = SubGhzTxRxWorkerStatusIDLE; | ||||||
| } | } | ||||||
| /** Worker thread
 | /** Worker thread
 | ||||||
|  *  |  *  | ||||||
| @ -145,13 +130,14 @@ static int32_t subghz_tx_rx_worker_thread(void* context) { | |||||||
| 
 | 
 | ||||||
|     furi_hal_subghz_reset(); |     furi_hal_subghz_reset(); | ||||||
|     furi_hal_subghz_idle(); |     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); |     hal_gpio_init(&gpio_cc1101_g0, GpioModeInput, GpioPullNo, GpioSpeedLow); | ||||||
| 
 | 
 | ||||||
|     furi_hal_subghz_set_frequency_and_path(instance->frequency); |     furi_hal_subghz_set_frequency_and_path(instance->frequency); | ||||||
|     furi_hal_subghz_flush_rx(); |     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; |     size_t size_tx = 0; | ||||||
|     uint8_t size_rx[1] = {0}; |     uint8_t size_rx[1] = {0}; | ||||||
|     uint8_t timeout_tx = 0; |     uint8_t timeout_tx = 0; | ||||||
| @ -161,18 +147,18 @@ static int32_t subghz_tx_rx_worker_thread(void* context) { | |||||||
|         //transmit
 |         //transmit
 | ||||||
|         size_tx = xStreamBufferBytesAvailable(instance->stream_tx); |         size_tx = xStreamBufferBytesAvailable(instance->stream_tx); | ||||||
|         if(size_tx > 0 && !timeout_tx) { |         if(size_tx > 0 && !timeout_tx) { | ||||||
|             timeout_tx = 20; //20ms
 |             timeout_tx = 10; //20ms
 | ||||||
|             if(size_tx > GUBGHZ_TXRX_WORKER_MAX_TXRX_SIZE) { |             if(size_tx > SUBGHZ_TXRX_WORKER_MAX_TXRX_SIZE) { | ||||||
|                 xStreamBufferReceive( |                 xStreamBufferReceive( | ||||||
|                     instance->stream_tx, |                     instance->stream_tx, | ||||||
|                     &data, |                     &data, | ||||||
|                     GUBGHZ_TXRX_WORKER_MAX_TXRX_SIZE, |                     SUBGHZ_TXRX_WORKER_MAX_TXRX_SIZE, | ||||||
|                     GUBGHZ_TXRX_WORKER_TIMEOUT_READ_WRITE_BUF); |                     SUBGHZ_TXRX_WORKER_TIMEOUT_READ_WRITE_BUF); | ||||||
|                 subghz_tx_rx_worker_tx(instance, data, GUBGHZ_TXRX_WORKER_MAX_TXRX_SIZE); |                 subghz_tx_rx_worker_tx(instance, data, SUBGHZ_TXRX_WORKER_MAX_TXRX_SIZE); | ||||||
|             } else { |             } else { | ||||||
|                 //todo checking that he managed to write all the data to the TX buffer
 |                 //todo checking that he managed to write all the data to the TX buffer
 | ||||||
|                 xStreamBufferReceive( |                 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); |                 subghz_tx_rx_worker_tx(instance, data, size_tx); | ||||||
|             } |             } | ||||||
|         } else { |         } else { | ||||||
| @ -188,7 +174,7 @@ static int32_t subghz_tx_rx_worker_thread(void* context) { | |||||||
|                         instance->stream_rx, |                         instance->stream_rx, | ||||||
|                         &data, |                         &data, | ||||||
|                         size_rx[0], |                         size_rx[0], | ||||||
|                         GUBGHZ_TXRX_WORKER_TIMEOUT_READ_WRITE_BUF); |                         SUBGHZ_TXRX_WORKER_TIMEOUT_READ_WRITE_BUF); | ||||||
|                     if(callback_rx) { |                     if(callback_rx) { | ||||||
|                         instance->callback_have_read(instance->context_have_read); |                         instance->callback_have_read(instance->context_have_read); | ||||||
|                         callback_rx = false; |                         callback_rx = false; | ||||||
| @ -219,11 +205,11 @@ SubGhzTxRxWorker* subghz_tx_rx_worker_alloc() { | |||||||
|     furi_thread_set_context(instance->thread, instance); |     furi_thread_set_context(instance->thread, instance); | ||||||
|     furi_thread_set_callback(instance->thread, subghz_tx_rx_worker_thread); |     furi_thread_set_callback(instance->thread, subghz_tx_rx_worker_thread); | ||||||
|     instance->stream_tx = |     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 = |     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; |     instance->worker_stoping = true; | ||||||
| 
 | 
 | ||||||
|     return instance; |     return instance; | ||||||
| @ -231,7 +217,7 @@ SubGhzTxRxWorker* subghz_tx_rx_worker_alloc() { | |||||||
| 
 | 
 | ||||||
| void subghz_tx_rx_worker_free(SubGhzTxRxWorker* instance) { | void subghz_tx_rx_worker_free(SubGhzTxRxWorker* instance) { | ||||||
|     furi_assert(instance); |     furi_assert(instance); | ||||||
| 
 |     furi_assert(!instance->worker_running); | ||||||
|     vStreamBufferDelete(instance->stream_tx); |     vStreamBufferDelete(instance->stream_tx); | ||||||
|     vStreamBufferDelete(instance->stream_rx); |     vStreamBufferDelete(instance->stream_rx); | ||||||
|     furi_thread_free(instance->thread); |     furi_thread_free(instance->thread); | ||||||
|  | |||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user
	 Skorpionm
						Skorpionm