[FL-3375] SubGhz: add CC1101 module external (#2747)
* SubGhz: add CC1101 Ext driver * SubGhz: move TIM2 -> TIM17 use cc1101_ext * FuriHal: SPI move channel DMA 3,4 -> 6.7 * Documentation: fix font * SubGhz: add work with SubGhz devices by link to device * SubGhz: add support switching external/internal cc1101 "subghz chat" * SubGhz: add support switching external/internal cc1101 "subghz tx" and "subghz rx" * SubGhz: add "Radio Settings" scene * SubGhz: add icon * SubGhz: add supported CC1101 external module in SubGhz app * SubGhz: fix check frequency supported radio device * SubGhz: fix clang-formatted * Sughz: move dirver CC1101_Ext to lib , compile cmd ./fbt launch_app APPSRC=radio_device_cc1101_ext * SubGhz: fix CLI * SubGhz: fix PVS * SubGhz: delete comments * SubGhz: fix unit_test * Format sources * Update api symbols and drivers targets * Drivers: find proper place for target option * SubGhz: external device connected method naming * Format sources * SubGhz: fix module selection menu, when external is not connected * SubGhz: fix furi_assert(device); * SubGhz: fix split h and c * SubGhz: furi_hal_subghz remove preset load function by name * SubGhz: deleted comments * Format Sources * SubGhz: add some consts and fix unit tests * Sync API Symbols Co-authored-by: Aleksandr Kutuzov <alleteam@gmail.com>
This commit is contained in:
		
							parent
							
								
									6d9de25494
								
							
						
					
					
						commit
						8c93695d01
					
				| @ -7,6 +7,8 @@ | |||||||
| #include <lib/subghz/subghz_file_encoder_worker.h> | #include <lib/subghz/subghz_file_encoder_worker.h> | ||||||
| #include <lib/subghz/protocols/protocol_items.h> | #include <lib/subghz/protocols/protocol_items.h> | ||||||
| #include <flipper_format/flipper_format_i.h> | #include <flipper_format/flipper_format_i.h> | ||||||
|  | #include <lib/subghz/devices/devices.h> | ||||||
|  | #include <lib/subghz/devices/cc1101_configs.h> | ||||||
| 
 | 
 | ||||||
| #define TAG "SubGhz TEST" | #define TAG "SubGhz TEST" | ||||||
| #define KEYSTORE_DIR_NAME EXT_PATH("subghz/assets/keeloq_mfcodes") | #define KEYSTORE_DIR_NAME EXT_PATH("subghz/assets/keeloq_mfcodes") | ||||||
| @ -49,12 +51,15 @@ static void subghz_test_init(void) { | |||||||
|     subghz_environment_set_protocol_registry( |     subghz_environment_set_protocol_registry( | ||||||
|         environment_handler, (void*)&subghz_protocol_registry); |         environment_handler, (void*)&subghz_protocol_registry); | ||||||
| 
 | 
 | ||||||
|  |     subghz_devices_init(); | ||||||
|  | 
 | ||||||
|     receiver_handler = subghz_receiver_alloc_init(environment_handler); |     receiver_handler = subghz_receiver_alloc_init(environment_handler); | ||||||
|     subghz_receiver_set_filter(receiver_handler, SubGhzProtocolFlag_Decodable); |     subghz_receiver_set_filter(receiver_handler, SubGhzProtocolFlag_Decodable); | ||||||
|     subghz_receiver_set_rx_callback(receiver_handler, subghz_test_rx_callback, NULL); |     subghz_receiver_set_rx_callback(receiver_handler, subghz_test_rx_callback, NULL); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| static void subghz_test_deinit(void) { | static void subghz_test_deinit(void) { | ||||||
|  |     subghz_devices_deinit(); | ||||||
|     subghz_receiver_free(receiver_handler); |     subghz_receiver_free(receiver_handler); | ||||||
|     subghz_environment_free(environment_handler); |     subghz_environment_free(environment_handler); | ||||||
| } | } | ||||||
| @ -68,7 +73,7 @@ static bool subghz_decoder_test(const char* path, const char* name_decoder) { | |||||||
| 
 | 
 | ||||||
|     if(decoder) { |     if(decoder) { | ||||||
|         file_worker_encoder_handler = subghz_file_encoder_worker_alloc(); |         file_worker_encoder_handler = subghz_file_encoder_worker_alloc(); | ||||||
|         if(subghz_file_encoder_worker_start(file_worker_encoder_handler, path)) { |         if(subghz_file_encoder_worker_start(file_worker_encoder_handler, path, NULL)) { | ||||||
|             // the worker needs a file in order to open and read part of the file
 |             // the worker needs a file in order to open and read part of the file
 | ||||||
|             furi_delay_ms(100); |             furi_delay_ms(100); | ||||||
| 
 | 
 | ||||||
| @ -108,7 +113,7 @@ static bool subghz_decode_random_test(const char* path) { | |||||||
|     uint32_t test_start = furi_get_tick(); |     uint32_t test_start = furi_get_tick(); | ||||||
| 
 | 
 | ||||||
|     file_worker_encoder_handler = subghz_file_encoder_worker_alloc(); |     file_worker_encoder_handler = subghz_file_encoder_worker_alloc(); | ||||||
|     if(subghz_file_encoder_worker_start(file_worker_encoder_handler, path)) { |     if(subghz_file_encoder_worker_start(file_worker_encoder_handler, path, NULL)) { | ||||||
|         // the worker needs a file in order to open and read part of the file
 |         // the worker needs a file in order to open and read part of the file
 | ||||||
|         furi_delay_ms(100); |         furi_delay_ms(100); | ||||||
| 
 | 
 | ||||||
| @ -318,7 +323,7 @@ bool subghz_hal_async_tx_test_run(SubGhzHalAsyncTxTestType type) { | |||||||
|     SubGhzHalAsyncTxTest test = {0}; |     SubGhzHalAsyncTxTest test = {0}; | ||||||
|     test.type = type; |     test.type = type; | ||||||
|     furi_hal_subghz_reset(); |     furi_hal_subghz_reset(); | ||||||
|     furi_hal_subghz_load_preset(FuriHalSubGhzPresetOok650Async); |     furi_hal_subghz_load_custom_preset(subghz_device_cc1101_preset_ook_650khz_async_regs); | ||||||
|     furi_hal_subghz_set_frequency_and_path(433920000); |     furi_hal_subghz_set_frequency_and_path(433920000); | ||||||
| 
 | 
 | ||||||
|     if(!furi_hal_subghz_start_async_tx(subghz_hal_async_tx_test_yield, &test)) { |     if(!furi_hal_subghz_start_async_tx(subghz_hal_async_tx_test_yield, &test)) { | ||||||
|  | |||||||
							
								
								
									
										6
									
								
								applications/drivers/application.fam
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										6
									
								
								applications/drivers/application.fam
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,6 @@ | |||||||
|  | # Placeholder | ||||||
|  | App( | ||||||
|  |     appid="drivers", | ||||||
|  |     name="Drivers device", | ||||||
|  |     apptype=FlipperAppType.METAPACKAGE, | ||||||
|  | ) | ||||||
							
								
								
									
										8
									
								
								applications/drivers/subghz/application.fam
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										8
									
								
								applications/drivers/subghz/application.fam
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,8 @@ | |||||||
|  | App( | ||||||
|  |     appid="radio_device_cc1101_ext", | ||||||
|  |     apptype=FlipperAppType.PLUGIN, | ||||||
|  |     targets=["f7"], | ||||||
|  |     entry_point="subghz_device_cc1101_ext_ep", | ||||||
|  |     requires=["subghz"], | ||||||
|  |     fap_libs=["hwdrivers"], | ||||||
|  | ) | ||||||
							
								
								
									
										765
									
								
								applications/drivers/subghz/cc1101_ext/cc1101_ext.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										765
									
								
								applications/drivers/subghz/cc1101_ext/cc1101_ext.c
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,765 @@ | |||||||
|  | #include "cc1101_ext.h" | ||||||
|  | #include <lib/subghz/devices/cc1101_configs.h> | ||||||
|  | 
 | ||||||
|  | #include <furi_hal_region.h> | ||||||
|  | #include <furi_hal_version.h> | ||||||
|  | #include <furi_hal_rtc.h> | ||||||
|  | #include <furi_hal_spi.h> | ||||||
|  | #include <furi_hal_interrupt.h> | ||||||
|  | #include <furi_hal_resources.h> | ||||||
|  | #include <furi_hal_bus.h> | ||||||
|  | 
 | ||||||
|  | #include <stm32wbxx_ll_dma.h> | ||||||
|  | #include <furi_hal_cortex.h> | ||||||
|  | 
 | ||||||
|  | #include <furi.h> | ||||||
|  | #include <cc1101.h> | ||||||
|  | #include <stdio.h> | ||||||
|  | 
 | ||||||
|  | #define TAG "SubGhz_Device_CC1101_Ext" | ||||||
|  | 
 | ||||||
|  | #define SUBGHZ_DEVICE_CC1101_EXT_TX_GPIO &gpio_ext_pb2 | ||||||
|  | 
 | ||||||
|  | /* DMA Channels definition */ | ||||||
|  | #define SUBGHZ_DEVICE_CC1101_EXT_DMA DMA2 | ||||||
|  | #define SUBGHZ_DEVICE_CC1101_EXT_DMA_CH3_CHANNEL LL_DMA_CHANNEL_3 | ||||||
|  | #define SUBGHZ_DEVICE_CC1101_EXT_DMA_CH4_CHANNEL LL_DMA_CHANNEL_4 | ||||||
|  | #define SUBGHZ_DEVICE_CC1101_EXT_DMA_CH5_CHANNEL LL_DMA_CHANNEL_5 | ||||||
|  | #define SUBGHZ_DEVICE_CC1101_EXT_DMA_CH3_IRQ FuriHalInterruptIdDma2Ch3 | ||||||
|  | #define SUBGHZ_DEVICE_CC1101_EXT_DMA_CH3_DEF \ | ||||||
|  |     SUBGHZ_DEVICE_CC1101_EXT_DMA, SUBGHZ_DEVICE_CC1101_EXT_DMA_CH3_CHANNEL | ||||||
|  | #define SUBGHZ_DEVICE_CC1101_EXT_DMA_CH4_DEF \ | ||||||
|  |     SUBGHZ_DEVICE_CC1101_EXT_DMA, SUBGHZ_DEVICE_CC1101_EXT_DMA_CH4_CHANNEL | ||||||
|  | #define SUBGHZ_DEVICE_CC1101_EXT_DMA_CH5_DEF \ | ||||||
|  |     SUBGHZ_DEVICE_CC1101_EXT_DMA, SUBGHZ_DEVICE_CC1101_EXT_DMA_CH5_CHANNEL | ||||||
|  | 
 | ||||||
|  | /** Low level buffer dimensions and guard times */ | ||||||
|  | #define SUBGHZ_DEVICE_CC1101_EXT_ASYNC_TX_BUFFER_FULL (256) | ||||||
|  | #define SUBGHZ_DEVICE_CC1101_EXT_ASYNC_TX_BUFFER_HALF \ | ||||||
|  |     (SUBGHZ_DEVICE_CC1101_EXT_ASYNC_TX_BUFFER_FULL / 2) | ||||||
|  | #define SUBGHZ_DEVICE_CC1101_EXT_ASYNC_TX_GUARD_TIME 999 | ||||||
|  | 
 | ||||||
|  | /** SubGhz state */ | ||||||
|  | typedef enum { | ||||||
|  |     SubGhzDeviceCC1101ExtStateInit, /**< Init pending */ | ||||||
|  |     SubGhzDeviceCC1101ExtStateIdle, /**< Idle, energy save mode */ | ||||||
|  |     SubGhzDeviceCC1101ExtStateAsyncRx, /**< Async RX started */ | ||||||
|  |     SubGhzDeviceCC1101ExtStateAsyncTx, /**< Async TX started, DMA and timer is on */ | ||||||
|  |     SubGhzDeviceCC1101ExtStateAsyncTxEnd, /**< Async TX complete, cleanup needed */ | ||||||
|  | } SubGhzDeviceCC1101ExtState; | ||||||
|  | 
 | ||||||
|  | /** SubGhz regulation, receive transmission on the current frequency for the
 | ||||||
|  |  * region */ | ||||||
|  | typedef enum { | ||||||
|  |     SubGhzDeviceCC1101ExtRegulationOnlyRx, /**only Rx*/ | ||||||
|  |     SubGhzDeviceCC1101ExtRegulationTxRx, /**TxRx*/ | ||||||
|  | } SubGhzDeviceCC1101ExtRegulation; | ||||||
|  | 
 | ||||||
|  | typedef struct { | ||||||
|  |     uint32_t* buffer; | ||||||
|  |     LevelDuration carry_ld; | ||||||
|  |     SubGhzDeviceCC1101ExtCallback callback; | ||||||
|  |     void* callback_context; | ||||||
|  |     uint32_t gpio_tx_buff[2]; | ||||||
|  |     uint32_t debug_gpio_buff[2]; | ||||||
|  | } SubGhzDeviceCC1101ExtAsyncTx; | ||||||
|  | 
 | ||||||
|  | typedef struct { | ||||||
|  |     uint32_t capture_delta_duration; | ||||||
|  |     SubGhzDeviceCC1101ExtCaptureCallback capture_callback; | ||||||
|  |     void* capture_callback_context; | ||||||
|  | } SubGhzDeviceCC1101ExtAsyncRx; | ||||||
|  | 
 | ||||||
|  | typedef struct { | ||||||
|  |     volatile SubGhzDeviceCC1101ExtState state; | ||||||
|  |     volatile SubGhzDeviceCC1101ExtRegulation regulation; | ||||||
|  |     const GpioPin* async_mirror_pin; | ||||||
|  |     FuriHalSpiBusHandle* spi_bus_handle; | ||||||
|  |     const GpioPin* g0_pin; | ||||||
|  |     SubGhzDeviceCC1101ExtAsyncTx async_tx; | ||||||
|  |     SubGhzDeviceCC1101ExtAsyncRx async_rx; | ||||||
|  | } SubGhzDeviceCC1101Ext; | ||||||
|  | 
 | ||||||
|  | static SubGhzDeviceCC1101Ext* subghz_device_cc1101_ext = NULL; | ||||||
|  | 
 | ||||||
|  | static bool subghz_device_cc1101_ext_check_init() { | ||||||
|  |     furi_assert(subghz_device_cc1101_ext->state == SubGhzDeviceCC1101ExtStateInit); | ||||||
|  |     subghz_device_cc1101_ext->state = SubGhzDeviceCC1101ExtStateIdle; | ||||||
|  | 
 | ||||||
|  |     bool ret = false; | ||||||
|  | 
 | ||||||
|  |     furi_hal_spi_acquire(subghz_device_cc1101_ext->spi_bus_handle); | ||||||
|  |     FuriHalCortexTimer timer = furi_hal_cortex_timer_get(100 * 1000); | ||||||
|  |     do { | ||||||
|  |         // Reset
 | ||||||
|  |         furi_hal_gpio_init( | ||||||
|  |             subghz_device_cc1101_ext->g0_pin, GpioModeAnalog, GpioPullNo, GpioSpeedLow); | ||||||
|  |         cc1101_reset(subghz_device_cc1101_ext->spi_bus_handle); | ||||||
|  |         cc1101_write_reg( | ||||||
|  |             subghz_device_cc1101_ext->spi_bus_handle, CC1101_IOCFG0, CC1101IocfgHighImpedance); | ||||||
|  | 
 | ||||||
|  |         // Prepare GD0 for power on self test
 | ||||||
|  |         furi_hal_gpio_init( | ||||||
|  |             subghz_device_cc1101_ext->g0_pin, GpioModeInput, GpioPullNo, GpioSpeedLow); | ||||||
|  | 
 | ||||||
|  |         // GD0 low
 | ||||||
|  |         cc1101_write_reg(subghz_device_cc1101_ext->spi_bus_handle, CC1101_IOCFG0, CC1101IocfgHW); | ||||||
|  |         while(furi_hal_gpio_read(subghz_device_cc1101_ext->g0_pin) != false) { | ||||||
|  |             if(furi_hal_cortex_timer_is_expired(timer)) { | ||||||
|  |                 //timeout
 | ||||||
|  |                 break; | ||||||
|  |             } | ||||||
|  |         } | ||||||
|  |         if(furi_hal_cortex_timer_is_expired(timer)) { | ||||||
|  |             //timeout
 | ||||||
|  |             break; | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         // GD0 high
 | ||||||
|  |         cc1101_write_reg( | ||||||
|  |             subghz_device_cc1101_ext->spi_bus_handle, | ||||||
|  |             CC1101_IOCFG0, | ||||||
|  |             CC1101IocfgHW | CC1101_IOCFG_INV); | ||||||
|  |         while(furi_hal_gpio_read(subghz_device_cc1101_ext->g0_pin) != true) { | ||||||
|  |             if(furi_hal_cortex_timer_is_expired(timer)) { | ||||||
|  |                 //timeout
 | ||||||
|  |                 break; | ||||||
|  |             } | ||||||
|  |         } | ||||||
|  |         if(furi_hal_cortex_timer_is_expired(timer)) { | ||||||
|  |             //timeout
 | ||||||
|  |             break; | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         // Reset GD0 to floating state
 | ||||||
|  |         cc1101_write_reg( | ||||||
|  |             subghz_device_cc1101_ext->spi_bus_handle, CC1101_IOCFG0, CC1101IocfgHighImpedance); | ||||||
|  |         furi_hal_gpio_init( | ||||||
|  |             subghz_device_cc1101_ext->g0_pin, GpioModeAnalog, GpioPullNo, GpioSpeedLow); | ||||||
|  | 
 | ||||||
|  |         // RF switches
 | ||||||
|  |         furi_hal_gpio_init(&gpio_rf_sw_0, GpioModeOutputPushPull, GpioPullNo, GpioSpeedLow); | ||||||
|  |         cc1101_write_reg(subghz_device_cc1101_ext->spi_bus_handle, CC1101_IOCFG2, CC1101IocfgHW); | ||||||
|  | 
 | ||||||
|  |         // Go to sleep
 | ||||||
|  |         cc1101_shutdown(subghz_device_cc1101_ext->spi_bus_handle); | ||||||
|  |         ret = true; | ||||||
|  |     } while(false); | ||||||
|  | 
 | ||||||
|  |     furi_hal_spi_release(subghz_device_cc1101_ext->spi_bus_handle); | ||||||
|  | 
 | ||||||
|  |     if(ret) { | ||||||
|  |         FURI_LOG_I(TAG, "Init OK"); | ||||||
|  |     } else { | ||||||
|  |         FURI_LOG_E(TAG, "Init failed"); | ||||||
|  |     } | ||||||
|  |     return ret; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | bool subghz_device_cc1101_ext_alloc() { | ||||||
|  |     furi_assert(subghz_device_cc1101_ext == NULL); | ||||||
|  |     subghz_device_cc1101_ext = malloc(sizeof(SubGhzDeviceCC1101Ext)); | ||||||
|  |     subghz_device_cc1101_ext->state = SubGhzDeviceCC1101ExtStateInit; | ||||||
|  |     subghz_device_cc1101_ext->regulation = SubGhzDeviceCC1101ExtRegulationTxRx; | ||||||
|  |     subghz_device_cc1101_ext->async_mirror_pin = NULL; | ||||||
|  |     subghz_device_cc1101_ext->spi_bus_handle = &furi_hal_spi_bus_handle_external; | ||||||
|  |     subghz_device_cc1101_ext->g0_pin = SUBGHZ_DEVICE_CC1101_EXT_TX_GPIO; | ||||||
|  | 
 | ||||||
|  |     subghz_device_cc1101_ext->async_rx.capture_delta_duration = 0; | ||||||
|  | 
 | ||||||
|  |     furi_hal_spi_bus_handle_init(subghz_device_cc1101_ext->spi_bus_handle); | ||||||
|  |     return subghz_device_cc1101_ext_check_init(); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | void subghz_device_cc1101_ext_free() { | ||||||
|  |     furi_assert(subghz_device_cc1101_ext != NULL); | ||||||
|  |     furi_hal_spi_bus_handle_deinit(subghz_device_cc1101_ext->spi_bus_handle); | ||||||
|  |     free(subghz_device_cc1101_ext); | ||||||
|  |     subghz_device_cc1101_ext = NULL; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | void subghz_device_cc1101_ext_set_async_mirror_pin(const GpioPin* pin) { | ||||||
|  |     subghz_device_cc1101_ext->async_mirror_pin = pin; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | const GpioPin* subghz_device_cc1101_ext_get_data_gpio() { | ||||||
|  |     return subghz_device_cc1101_ext->g0_pin; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | bool subghz_device_cc1101_ext_is_connect() { | ||||||
|  |     bool ret = false; | ||||||
|  | 
 | ||||||
|  |     if(subghz_device_cc1101_ext == NULL) { // not initialized
 | ||||||
|  |         ret = subghz_device_cc1101_ext_alloc(); | ||||||
|  |         subghz_device_cc1101_ext_free(); | ||||||
|  |     } else { // initialized
 | ||||||
|  |         furi_hal_spi_acquire(subghz_device_cc1101_ext->spi_bus_handle); | ||||||
|  |         uint8_t partnumber = cc1101_get_partnumber(subghz_device_cc1101_ext->spi_bus_handle); | ||||||
|  |         furi_hal_spi_release(subghz_device_cc1101_ext->spi_bus_handle); | ||||||
|  |         ret = (partnumber != 0) && (partnumber != 0xFF); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     return ret; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | void subghz_device_cc1101_ext_sleep() { | ||||||
|  |     furi_assert(subghz_device_cc1101_ext->state == SubGhzDeviceCC1101ExtStateIdle); | ||||||
|  |     furi_hal_spi_acquire(subghz_device_cc1101_ext->spi_bus_handle); | ||||||
|  | 
 | ||||||
|  |     cc1101_switch_to_idle(subghz_device_cc1101_ext->spi_bus_handle); | ||||||
|  | 
 | ||||||
|  |     cc1101_write_reg( | ||||||
|  |         subghz_device_cc1101_ext->spi_bus_handle, CC1101_IOCFG0, CC1101IocfgHighImpedance); | ||||||
|  |     furi_hal_gpio_init(subghz_device_cc1101_ext->g0_pin, GpioModeAnalog, GpioPullNo, GpioSpeedLow); | ||||||
|  | 
 | ||||||
|  |     cc1101_shutdown(subghz_device_cc1101_ext->spi_bus_handle); | ||||||
|  | 
 | ||||||
|  |     furi_hal_spi_release(subghz_device_cc1101_ext->spi_bus_handle); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | void subghz_device_cc1101_ext_dump_state() { | ||||||
|  |     furi_hal_spi_acquire(subghz_device_cc1101_ext->spi_bus_handle); | ||||||
|  |     printf( | ||||||
|  |         "[subghz_device_cc1101_ext] cc1101 chip %d, version %d\r\n", | ||||||
|  |         cc1101_get_partnumber(subghz_device_cc1101_ext->spi_bus_handle), | ||||||
|  |         cc1101_get_version(subghz_device_cc1101_ext->spi_bus_handle)); | ||||||
|  |     furi_hal_spi_release(subghz_device_cc1101_ext->spi_bus_handle); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | void subghz_device_cc1101_ext_load_custom_preset(const uint8_t* preset_data) { | ||||||
|  |     //load config
 | ||||||
|  |     furi_hal_spi_acquire(subghz_device_cc1101_ext->spi_bus_handle); | ||||||
|  |     cc1101_reset(subghz_device_cc1101_ext->spi_bus_handle); | ||||||
|  |     uint32_t i = 0; | ||||||
|  |     uint8_t pa[8] = {0}; | ||||||
|  |     while(preset_data[i]) { | ||||||
|  |         cc1101_write_reg( | ||||||
|  |             subghz_device_cc1101_ext->spi_bus_handle, preset_data[i], preset_data[i + 1]); | ||||||
|  |         i += 2; | ||||||
|  |     } | ||||||
|  |     furi_hal_spi_release(subghz_device_cc1101_ext->spi_bus_handle); | ||||||
|  | 
 | ||||||
|  |     //load pa table
 | ||||||
|  |     memcpy(&pa[0], &preset_data[i + 2], 8); | ||||||
|  |     subghz_device_cc1101_ext_load_patable(pa); | ||||||
|  | 
 | ||||||
|  |     //show debug
 | ||||||
|  |     if(furi_hal_rtc_is_flag_set(FuriHalRtcFlagDebug)) { | ||||||
|  |         i = 0; | ||||||
|  |         FURI_LOG_D(TAG, "Loading custom preset"); | ||||||
|  |         while(preset_data[i]) { | ||||||
|  |             FURI_LOG_D(TAG, "Reg[%lu]: %02X=%02X", i, preset_data[i], preset_data[i + 1]); | ||||||
|  |             i += 2; | ||||||
|  |         } | ||||||
|  |         for(uint8_t y = i; y < i + 10; y++) { | ||||||
|  |             FURI_LOG_D(TAG, "PA[%u]:  %02X", y, preset_data[y]); | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | void subghz_device_cc1101_ext_load_registers(const uint8_t* data) { | ||||||
|  |     furi_hal_spi_acquire(subghz_device_cc1101_ext->spi_bus_handle); | ||||||
|  |     cc1101_reset(subghz_device_cc1101_ext->spi_bus_handle); | ||||||
|  |     uint32_t i = 0; | ||||||
|  |     while(data[i]) { | ||||||
|  |         cc1101_write_reg(subghz_device_cc1101_ext->spi_bus_handle, data[i], data[i + 1]); | ||||||
|  |         i += 2; | ||||||
|  |     } | ||||||
|  |     furi_hal_spi_release(subghz_device_cc1101_ext->spi_bus_handle); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | void subghz_device_cc1101_ext_load_patable(const uint8_t data[8]) { | ||||||
|  |     furi_hal_spi_acquire(subghz_device_cc1101_ext->spi_bus_handle); | ||||||
|  |     cc1101_set_pa_table(subghz_device_cc1101_ext->spi_bus_handle, data); | ||||||
|  |     furi_hal_spi_release(subghz_device_cc1101_ext->spi_bus_handle); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | void subghz_device_cc1101_ext_write_packet(const uint8_t* data, uint8_t size) { | ||||||
|  |     furi_hal_spi_acquire(subghz_device_cc1101_ext->spi_bus_handle); | ||||||
|  |     cc1101_flush_tx(subghz_device_cc1101_ext->spi_bus_handle); | ||||||
|  |     cc1101_write_reg(subghz_device_cc1101_ext->spi_bus_handle, CC1101_FIFO, size); | ||||||
|  |     cc1101_write_fifo(subghz_device_cc1101_ext->spi_bus_handle, data, size); | ||||||
|  |     furi_hal_spi_release(subghz_device_cc1101_ext->spi_bus_handle); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | void subghz_device_cc1101_ext_flush_rx() { | ||||||
|  |     furi_hal_spi_acquire(subghz_device_cc1101_ext->spi_bus_handle); | ||||||
|  |     cc1101_flush_rx(subghz_device_cc1101_ext->spi_bus_handle); | ||||||
|  |     furi_hal_spi_release(subghz_device_cc1101_ext->spi_bus_handle); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | void subghz_device_cc1101_ext_flush_tx() { | ||||||
|  |     furi_hal_spi_acquire(subghz_device_cc1101_ext->spi_bus_handle); | ||||||
|  |     cc1101_flush_tx(subghz_device_cc1101_ext->spi_bus_handle); | ||||||
|  |     furi_hal_spi_release(subghz_device_cc1101_ext->spi_bus_handle); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | bool subghz_device_cc1101_ext_rx_pipe_not_empty() { | ||||||
|  |     CC1101RxBytes status[1]; | ||||||
|  |     furi_hal_spi_acquire(subghz_device_cc1101_ext->spi_bus_handle); | ||||||
|  |     cc1101_read_reg( | ||||||
|  |         subghz_device_cc1101_ext->spi_bus_handle, | ||||||
|  |         (CC1101_STATUS_RXBYTES) | CC1101_BURST, | ||||||
|  |         (uint8_t*)status); | ||||||
|  |     furi_hal_spi_release(subghz_device_cc1101_ext->spi_bus_handle); | ||||||
|  |     // TODO: you can add a buffer overflow flag if needed
 | ||||||
|  |     if(status->NUM_RXBYTES > 0) { | ||||||
|  |         return true; | ||||||
|  |     } else { | ||||||
|  |         return false; | ||||||
|  |     } | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | bool subghz_device_cc1101_ext_is_rx_data_crc_valid() { | ||||||
|  |     furi_hal_spi_acquire(subghz_device_cc1101_ext->spi_bus_handle); | ||||||
|  |     uint8_t data[1]; | ||||||
|  |     cc1101_read_reg( | ||||||
|  |         subghz_device_cc1101_ext->spi_bus_handle, CC1101_STATUS_LQI | CC1101_BURST, data); | ||||||
|  |     furi_hal_spi_release(subghz_device_cc1101_ext->spi_bus_handle); | ||||||
|  |     if(((data[0] >> 7) & 0x01)) { | ||||||
|  |         return true; | ||||||
|  |     } else { | ||||||
|  |         return false; | ||||||
|  |     } | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | void subghz_device_cc1101_ext_read_packet(uint8_t* data, uint8_t* size) { | ||||||
|  |     furi_hal_spi_acquire(subghz_device_cc1101_ext->spi_bus_handle); | ||||||
|  |     cc1101_read_fifo(subghz_device_cc1101_ext->spi_bus_handle, data, size); | ||||||
|  |     furi_hal_spi_release(subghz_device_cc1101_ext->spi_bus_handle); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | void subghz_device_cc1101_ext_shutdown() { | ||||||
|  |     furi_hal_spi_acquire(subghz_device_cc1101_ext->spi_bus_handle); | ||||||
|  |     // Reset and shutdown
 | ||||||
|  |     cc1101_shutdown(subghz_device_cc1101_ext->spi_bus_handle); | ||||||
|  |     furi_hal_spi_release(subghz_device_cc1101_ext->spi_bus_handle); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | void subghz_device_cc1101_ext_reset() { | ||||||
|  |     furi_hal_spi_acquire(subghz_device_cc1101_ext->spi_bus_handle); | ||||||
|  |     furi_hal_gpio_init(subghz_device_cc1101_ext->g0_pin, GpioModeAnalog, GpioPullNo, GpioSpeedLow); | ||||||
|  |     cc1101_switch_to_idle(subghz_device_cc1101_ext->spi_bus_handle); | ||||||
|  |     cc1101_reset(subghz_device_cc1101_ext->spi_bus_handle); | ||||||
|  |     cc1101_write_reg( | ||||||
|  |         subghz_device_cc1101_ext->spi_bus_handle, CC1101_IOCFG0, CC1101IocfgHighImpedance); | ||||||
|  |     furi_hal_spi_release(subghz_device_cc1101_ext->spi_bus_handle); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | void subghz_device_cc1101_ext_idle() { | ||||||
|  |     furi_hal_spi_acquire(subghz_device_cc1101_ext->spi_bus_handle); | ||||||
|  |     cc1101_switch_to_idle(subghz_device_cc1101_ext->spi_bus_handle); | ||||||
|  |     furi_hal_spi_release(subghz_device_cc1101_ext->spi_bus_handle); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | void subghz_device_cc1101_ext_rx() { | ||||||
|  |     furi_hal_spi_acquire(subghz_device_cc1101_ext->spi_bus_handle); | ||||||
|  |     cc1101_switch_to_rx(subghz_device_cc1101_ext->spi_bus_handle); | ||||||
|  |     furi_hal_spi_release(subghz_device_cc1101_ext->spi_bus_handle); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | bool subghz_device_cc1101_ext_tx() { | ||||||
|  |     if(subghz_device_cc1101_ext->regulation != SubGhzDeviceCC1101ExtRegulationTxRx) return false; | ||||||
|  |     furi_hal_spi_acquire(subghz_device_cc1101_ext->spi_bus_handle); | ||||||
|  |     cc1101_switch_to_tx(subghz_device_cc1101_ext->spi_bus_handle); | ||||||
|  |     furi_hal_spi_release(subghz_device_cc1101_ext->spi_bus_handle); | ||||||
|  |     return true; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | float subghz_device_cc1101_ext_get_rssi() { | ||||||
|  |     furi_hal_spi_acquire(subghz_device_cc1101_ext->spi_bus_handle); | ||||||
|  |     int32_t rssi_dec = cc1101_get_rssi(subghz_device_cc1101_ext->spi_bus_handle); | ||||||
|  |     furi_hal_spi_release(subghz_device_cc1101_ext->spi_bus_handle); | ||||||
|  | 
 | ||||||
|  |     float rssi = rssi_dec; | ||||||
|  |     if(rssi_dec >= 128) { | ||||||
|  |         rssi = ((rssi - 256.0f) / 2.0f) - 74.0f; | ||||||
|  |     } else { | ||||||
|  |         rssi = (rssi / 2.0f) - 74.0f; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     return rssi; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | uint8_t subghz_device_cc1101_ext_get_lqi() { | ||||||
|  |     furi_hal_spi_acquire(subghz_device_cc1101_ext->spi_bus_handle); | ||||||
|  |     uint8_t data[1]; | ||||||
|  |     cc1101_read_reg( | ||||||
|  |         subghz_device_cc1101_ext->spi_bus_handle, CC1101_STATUS_LQI | CC1101_BURST, data); | ||||||
|  |     furi_hal_spi_release(subghz_device_cc1101_ext->spi_bus_handle); | ||||||
|  |     return data[0] & 0x7F; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | bool subghz_device_cc1101_ext_is_frequency_valid(uint32_t value) { | ||||||
|  |     if(!(value >= 299999755 && value <= 348000335) && | ||||||
|  |        !(value >= 386999938 && value <= 464000000) && | ||||||
|  |        !(value >= 778999847 && value <= 928000000)) { | ||||||
|  |         return false; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     return true; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | uint32_t subghz_device_cc1101_ext_set_frequency(uint32_t value) { | ||||||
|  |     if(furi_hal_region_is_frequency_allowed(value)) { | ||||||
|  |         subghz_device_cc1101_ext->regulation = SubGhzDeviceCC1101ExtRegulationTxRx; | ||||||
|  |     } else { | ||||||
|  |         subghz_device_cc1101_ext->regulation = SubGhzDeviceCC1101ExtRegulationOnlyRx; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     furi_hal_spi_acquire(subghz_device_cc1101_ext->spi_bus_handle); | ||||||
|  |     uint32_t real_frequency = | ||||||
|  |         cc1101_set_frequency(subghz_device_cc1101_ext->spi_bus_handle, value); | ||||||
|  |     cc1101_calibrate(subghz_device_cc1101_ext->spi_bus_handle); | ||||||
|  | 
 | ||||||
|  |     while(true) { | ||||||
|  |         CC1101Status status = cc1101_get_status(subghz_device_cc1101_ext->spi_bus_handle); | ||||||
|  |         if(status.STATE == CC1101StateIDLE) break; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     furi_hal_spi_release(subghz_device_cc1101_ext->spi_bus_handle); | ||||||
|  |     return real_frequency; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | static bool subghz_device_cc1101_ext_start_debug() { | ||||||
|  |     bool ret = false; | ||||||
|  |     if(subghz_device_cc1101_ext->async_mirror_pin != NULL) { | ||||||
|  |         furi_hal_gpio_init( | ||||||
|  |             subghz_device_cc1101_ext->async_mirror_pin, | ||||||
|  |             GpioModeOutputPushPull, | ||||||
|  |             GpioPullNo, | ||||||
|  |             GpioSpeedVeryHigh); | ||||||
|  |         ret = true; | ||||||
|  |     } | ||||||
|  |     return ret; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | static bool subghz_device_cc1101_ext_stop_debug() { | ||||||
|  |     bool ret = false; | ||||||
|  |     if(subghz_device_cc1101_ext->async_mirror_pin != NULL) { | ||||||
|  |         furi_hal_gpio_init( | ||||||
|  |             subghz_device_cc1101_ext->async_mirror_pin, GpioModeAnalog, GpioPullNo, GpioSpeedLow); | ||||||
|  |         ret = true; | ||||||
|  |     } | ||||||
|  |     return ret; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | static void subghz_device_cc1101_ext_capture_ISR() { | ||||||
|  |     if(!furi_hal_gpio_read(subghz_device_cc1101_ext->g0_pin)) { | ||||||
|  |         if(subghz_device_cc1101_ext->async_rx.capture_callback) { | ||||||
|  |             if(subghz_device_cc1101_ext->async_mirror_pin != NULL) | ||||||
|  |                 furi_hal_gpio_write(subghz_device_cc1101_ext->async_mirror_pin, false); | ||||||
|  | 
 | ||||||
|  |             subghz_device_cc1101_ext->async_rx.capture_callback( | ||||||
|  |                 true, | ||||||
|  |                 LL_TIM_GetCounter(TIM17), | ||||||
|  |                 (void*)subghz_device_cc1101_ext->async_rx.capture_callback_context); | ||||||
|  |         } | ||||||
|  |     } else { | ||||||
|  |         if(subghz_device_cc1101_ext->async_rx.capture_callback) { | ||||||
|  |             if(subghz_device_cc1101_ext->async_mirror_pin != NULL) | ||||||
|  |                 furi_hal_gpio_write(subghz_device_cc1101_ext->async_mirror_pin, true); | ||||||
|  | 
 | ||||||
|  |             subghz_device_cc1101_ext->async_rx.capture_callback( | ||||||
|  |                 false, | ||||||
|  |                 LL_TIM_GetCounter(TIM17), | ||||||
|  |                 (void*)subghz_device_cc1101_ext->async_rx.capture_callback_context); | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  |     LL_TIM_SetCounter(TIM17, 6); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | void subghz_device_cc1101_ext_start_async_rx( | ||||||
|  |     SubGhzDeviceCC1101ExtCaptureCallback callback, | ||||||
|  |     void* context) { | ||||||
|  |     furi_assert(subghz_device_cc1101_ext->state == SubGhzDeviceCC1101ExtStateIdle); | ||||||
|  |     subghz_device_cc1101_ext->state = SubGhzDeviceCC1101ExtStateAsyncRx; | ||||||
|  | 
 | ||||||
|  |     subghz_device_cc1101_ext->async_rx.capture_callback = callback; | ||||||
|  |     subghz_device_cc1101_ext->async_rx.capture_callback_context = context; | ||||||
|  | 
 | ||||||
|  |     furi_hal_bus_enable(FuriHalBusTIM17); | ||||||
|  | 
 | ||||||
|  |     // Configure TIM
 | ||||||
|  |     LL_TIM_SetPrescaler(TIM17, 64 - 1); | ||||||
|  |     LL_TIM_SetCounterMode(TIM17, LL_TIM_COUNTERMODE_UP); | ||||||
|  |     LL_TIM_SetAutoReload(TIM17, 0xFFFF); | ||||||
|  |     LL_TIM_SetClockDivision(TIM17, LL_TIM_CLOCKDIVISION_DIV1); | ||||||
|  | 
 | ||||||
|  |     // Timer: advanced
 | ||||||
|  |     LL_TIM_SetClockSource(TIM17, LL_TIM_CLOCKSOURCE_INTERNAL); | ||||||
|  |     LL_TIM_DisableARRPreload(TIM17); | ||||||
|  |     LL_TIM_DisableDMAReq_TRIG(TIM17); | ||||||
|  |     LL_TIM_DisableIT_TRIG(TIM17); | ||||||
|  | 
 | ||||||
|  |     furi_hal_gpio_init( | ||||||
|  |         subghz_device_cc1101_ext->g0_pin, GpioModeInterruptRiseFall, GpioPullUp, GpioSpeedVeryHigh); | ||||||
|  |     furi_hal_gpio_remove_int_callback(subghz_device_cc1101_ext->g0_pin); | ||||||
|  |     furi_hal_gpio_add_int_callback( | ||||||
|  |         subghz_device_cc1101_ext->g0_pin, | ||||||
|  |         subghz_device_cc1101_ext_capture_ISR, | ||||||
|  |         subghz_device_cc1101_ext->async_rx.capture_callback); | ||||||
|  | 
 | ||||||
|  |     // Start timer
 | ||||||
|  |     LL_TIM_SetCounter(TIM17, 0); | ||||||
|  |     LL_TIM_EnableCounter(TIM17); | ||||||
|  | 
 | ||||||
|  |     // Start debug
 | ||||||
|  |     subghz_device_cc1101_ext_start_debug(); | ||||||
|  | 
 | ||||||
|  |     // Switch to RX
 | ||||||
|  |     subghz_device_cc1101_ext_rx(); | ||||||
|  | 
 | ||||||
|  |     //Clear the variable after the end of the session
 | ||||||
|  |     subghz_device_cc1101_ext->async_rx.capture_delta_duration = 0; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | void subghz_device_cc1101_ext_stop_async_rx() { | ||||||
|  |     furi_assert(subghz_device_cc1101_ext->state == SubGhzDeviceCC1101ExtStateAsyncRx); | ||||||
|  |     subghz_device_cc1101_ext->state = SubGhzDeviceCC1101ExtStateIdle; | ||||||
|  | 
 | ||||||
|  |     // Shutdown radio
 | ||||||
|  |     subghz_device_cc1101_ext_idle(); | ||||||
|  | 
 | ||||||
|  |     FURI_CRITICAL_ENTER(); | ||||||
|  |     furi_hal_bus_disable(FuriHalBusTIM17); | ||||||
|  | 
 | ||||||
|  |     // Stop debug
 | ||||||
|  |     subghz_device_cc1101_ext_stop_debug(); | ||||||
|  | 
 | ||||||
|  |     FURI_CRITICAL_EXIT(); | ||||||
|  |     furi_hal_gpio_remove_int_callback(subghz_device_cc1101_ext->g0_pin); | ||||||
|  |     furi_hal_gpio_init(subghz_device_cc1101_ext->g0_pin, GpioModeAnalog, GpioPullNo, GpioSpeedLow); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | static void subghz_device_cc1101_ext_async_tx_refill(uint32_t* buffer, size_t samples) { | ||||||
|  |     furi_assert(subghz_device_cc1101_ext->state == SubGhzDeviceCC1101ExtStateAsyncTx); | ||||||
|  |     while(samples > 0) { | ||||||
|  |         bool is_odd = samples % 2; | ||||||
|  |         LevelDuration ld; | ||||||
|  |         if(level_duration_is_reset(subghz_device_cc1101_ext->async_tx.carry_ld)) { | ||||||
|  |             ld = subghz_device_cc1101_ext->async_tx.callback( | ||||||
|  |                 subghz_device_cc1101_ext->async_tx.callback_context); | ||||||
|  |         } else { | ||||||
|  |             ld = subghz_device_cc1101_ext->async_tx.carry_ld; | ||||||
|  |             subghz_device_cc1101_ext->async_tx.carry_ld = level_duration_reset(); | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         if(level_duration_is_wait(ld)) { | ||||||
|  |             *buffer = SUBGHZ_DEVICE_CC1101_EXT_ASYNC_TX_GUARD_TIME; | ||||||
|  |             buffer++; | ||||||
|  |             samples--; | ||||||
|  |         } else if(level_duration_is_reset(ld)) { | ||||||
|  |             *buffer = 0; | ||||||
|  |             buffer++; | ||||||
|  |             samples--; | ||||||
|  |             LL_DMA_DisableIT_HT(SUBGHZ_DEVICE_CC1101_EXT_DMA_CH3_DEF); | ||||||
|  |             LL_DMA_DisableIT_TC(SUBGHZ_DEVICE_CC1101_EXT_DMA_CH3_DEF); | ||||||
|  |             LL_TIM_EnableIT_UPDATE(TIM17); | ||||||
|  |             break; | ||||||
|  |         } else { | ||||||
|  |             bool level = level_duration_get_level(ld); | ||||||
|  | 
 | ||||||
|  |             // Inject guard time if level is incorrect
 | ||||||
|  |             if(is_odd != level) { | ||||||
|  |                 *buffer = SUBGHZ_DEVICE_CC1101_EXT_ASYNC_TX_GUARD_TIME; | ||||||
|  |                 buffer++; | ||||||
|  |                 samples--; | ||||||
|  | 
 | ||||||
|  |                 // Special case: prevent buffer overflow if sample is last
 | ||||||
|  |                 if(samples == 0) { | ||||||
|  |                     subghz_device_cc1101_ext->async_tx.carry_ld = ld; | ||||||
|  |                     break; | ||||||
|  |                 } | ||||||
|  |             } | ||||||
|  | 
 | ||||||
|  |             uint32_t duration = level_duration_get_duration(ld); | ||||||
|  |             furi_assert(duration > 0); | ||||||
|  |             *buffer = duration - 1; | ||||||
|  |             buffer++; | ||||||
|  |             samples--; | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | static void subghz_device_cc1101_ext_async_tx_dma_isr() { | ||||||
|  |     furi_assert(subghz_device_cc1101_ext->state == SubGhzDeviceCC1101ExtStateAsyncTx); | ||||||
|  | 
 | ||||||
|  | #if SUBGHZ_DEVICE_CC1101_EXT_DMA_CH3_CHANNEL == LL_DMA_CHANNEL_3 | ||||||
|  |     if(LL_DMA_IsActiveFlag_HT3(SUBGHZ_DEVICE_CC1101_EXT_DMA)) { | ||||||
|  |         LL_DMA_ClearFlag_HT3(SUBGHZ_DEVICE_CC1101_EXT_DMA); | ||||||
|  |         subghz_device_cc1101_ext_async_tx_refill( | ||||||
|  |             subghz_device_cc1101_ext->async_tx.buffer, | ||||||
|  |             SUBGHZ_DEVICE_CC1101_EXT_ASYNC_TX_BUFFER_HALF); | ||||||
|  |     } | ||||||
|  |     if(LL_DMA_IsActiveFlag_TC3(SUBGHZ_DEVICE_CC1101_EXT_DMA)) { | ||||||
|  |         LL_DMA_ClearFlag_TC3(SUBGHZ_DEVICE_CC1101_EXT_DMA); | ||||||
|  |         subghz_device_cc1101_ext_async_tx_refill( | ||||||
|  |             subghz_device_cc1101_ext->async_tx.buffer + | ||||||
|  |                 SUBGHZ_DEVICE_CC1101_EXT_ASYNC_TX_BUFFER_HALF, | ||||||
|  |             SUBGHZ_DEVICE_CC1101_EXT_ASYNC_TX_BUFFER_HALF); | ||||||
|  |     } | ||||||
|  | #else | ||||||
|  | #error Update this code. Would you kindly? | ||||||
|  | #endif | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | static void subghz_device_cc1101_ext_async_tx_timer_isr() { | ||||||
|  |     if(LL_TIM_IsActiveFlag_UPDATE(TIM17)) { | ||||||
|  |         if(LL_TIM_GetAutoReload(TIM17) == 0) { | ||||||
|  |             LL_DMA_DisableChannel(SUBGHZ_DEVICE_CC1101_EXT_DMA_CH3_DEF); | ||||||
|  |             furi_hal_gpio_write(subghz_device_cc1101_ext->g0_pin, false); | ||||||
|  |             if(subghz_device_cc1101_ext->async_mirror_pin != NULL) | ||||||
|  |                 furi_hal_gpio_write(subghz_device_cc1101_ext->async_mirror_pin, false); | ||||||
|  |             LL_TIM_DisableCounter(TIM17); | ||||||
|  |             subghz_device_cc1101_ext->state = SubGhzDeviceCC1101ExtStateAsyncTxEnd; | ||||||
|  |         } | ||||||
|  |         LL_TIM_ClearFlag_UPDATE(TIM17); | ||||||
|  |     } | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | bool subghz_device_cc1101_ext_start_async_tx(SubGhzDeviceCC1101ExtCallback callback, void* context) { | ||||||
|  |     furi_assert(subghz_device_cc1101_ext->state == SubGhzDeviceCC1101ExtStateIdle); | ||||||
|  |     furi_assert(callback); | ||||||
|  | 
 | ||||||
|  |     //If transmission is prohibited by regional settings
 | ||||||
|  |     if(subghz_device_cc1101_ext->regulation != SubGhzDeviceCC1101ExtRegulationTxRx) return false; | ||||||
|  | 
 | ||||||
|  |     subghz_device_cc1101_ext->async_tx.callback = callback; | ||||||
|  |     subghz_device_cc1101_ext->async_tx.callback_context = context; | ||||||
|  | 
 | ||||||
|  |     subghz_device_cc1101_ext->state = SubGhzDeviceCC1101ExtStateAsyncTx; | ||||||
|  | 
 | ||||||
|  |     subghz_device_cc1101_ext->async_tx.buffer = | ||||||
|  |         malloc(SUBGHZ_DEVICE_CC1101_EXT_ASYNC_TX_BUFFER_FULL * sizeof(uint32_t)); | ||||||
|  | 
 | ||||||
|  |     //Signal generation with mem-to-mem DMA
 | ||||||
|  |     furi_hal_gpio_write(subghz_device_cc1101_ext->g0_pin, false); | ||||||
|  |     furi_hal_gpio_init( | ||||||
|  |         subghz_device_cc1101_ext->g0_pin, GpioModeOutputPushPull, GpioPullNo, GpioSpeedVeryHigh); | ||||||
|  | 
 | ||||||
|  |     // Configure DMA  update timer
 | ||||||
|  |     LL_DMA_SetMemoryAddress( | ||||||
|  |         SUBGHZ_DEVICE_CC1101_EXT_DMA_CH3_DEF, (uint32_t)subghz_device_cc1101_ext->async_tx.buffer); | ||||||
|  |     LL_DMA_SetPeriphAddress(SUBGHZ_DEVICE_CC1101_EXT_DMA_CH3_DEF, (uint32_t) & (TIM17->ARR)); | ||||||
|  |     LL_DMA_ConfigTransfer( | ||||||
|  |         SUBGHZ_DEVICE_CC1101_EXT_DMA_CH3_DEF, | ||||||
|  |         LL_DMA_DIRECTION_MEMORY_TO_PERIPH | LL_DMA_MODE_CIRCULAR | LL_DMA_PERIPH_NOINCREMENT | | ||||||
|  |             LL_DMA_MEMORY_INCREMENT | LL_DMA_PDATAALIGN_WORD | LL_DMA_MDATAALIGN_WORD | | ||||||
|  |             LL_DMA_MODE_NORMAL); | ||||||
|  |     LL_DMA_SetDataLength( | ||||||
|  |         SUBGHZ_DEVICE_CC1101_EXT_DMA_CH3_DEF, SUBGHZ_DEVICE_CC1101_EXT_ASYNC_TX_BUFFER_FULL); | ||||||
|  |     LL_DMA_SetPeriphRequest(SUBGHZ_DEVICE_CC1101_EXT_DMA_CH3_DEF, LL_DMAMUX_REQ_TIM17_UP); | ||||||
|  | 
 | ||||||
|  |     LL_DMA_EnableIT_TC(SUBGHZ_DEVICE_CC1101_EXT_DMA_CH3_DEF); | ||||||
|  |     LL_DMA_EnableIT_HT(SUBGHZ_DEVICE_CC1101_EXT_DMA_CH3_DEF); | ||||||
|  |     LL_DMA_EnableChannel(SUBGHZ_DEVICE_CC1101_EXT_DMA_CH3_DEF); | ||||||
|  | 
 | ||||||
|  |     furi_hal_interrupt_set_isr( | ||||||
|  |         SUBGHZ_DEVICE_CC1101_EXT_DMA_CH3_IRQ, subghz_device_cc1101_ext_async_tx_dma_isr, NULL); | ||||||
|  | 
 | ||||||
|  |     furi_hal_bus_enable(FuriHalBusTIM17); | ||||||
|  | 
 | ||||||
|  |     // Configure TIM
 | ||||||
|  |     LL_TIM_SetPrescaler(TIM17, 64 - 1); | ||||||
|  |     LL_TIM_SetCounterMode(TIM17, LL_TIM_COUNTERMODE_UP); | ||||||
|  |     LL_TIM_SetAutoReload(TIM17, 0xFFFF); | ||||||
|  |     LL_TIM_SetClockDivision(TIM17, LL_TIM_CLOCKDIVISION_DIV1); | ||||||
|  |     LL_TIM_SetClockSource(TIM17, LL_TIM_CLOCKSOURCE_INTERNAL); | ||||||
|  |     LL_TIM_DisableARRPreload(TIM17); | ||||||
|  | 
 | ||||||
|  |     furi_hal_interrupt_set_isr( | ||||||
|  |         FuriHalInterruptIdTim1TrgComTim17, subghz_device_cc1101_ext_async_tx_timer_isr, NULL); | ||||||
|  | 
 | ||||||
|  |     subghz_device_cc1101_ext_async_tx_refill( | ||||||
|  |         subghz_device_cc1101_ext->async_tx.buffer, SUBGHZ_DEVICE_CC1101_EXT_ASYNC_TX_BUFFER_FULL); | ||||||
|  | 
 | ||||||
|  |     // Configure tx gpio dma
 | ||||||
|  |     const GpioPin* gpio = subghz_device_cc1101_ext->g0_pin; | ||||||
|  | 
 | ||||||
|  |     subghz_device_cc1101_ext->async_tx.gpio_tx_buff[0] = (uint32_t)gpio->pin << GPIO_NUMBER; | ||||||
|  |     subghz_device_cc1101_ext->async_tx.gpio_tx_buff[1] = gpio->pin; | ||||||
|  | 
 | ||||||
|  |     LL_DMA_SetMemoryAddress( | ||||||
|  |         SUBGHZ_DEVICE_CC1101_EXT_DMA_CH4_DEF, | ||||||
|  |         (uint32_t)subghz_device_cc1101_ext->async_tx.gpio_tx_buff); | ||||||
|  |     LL_DMA_SetPeriphAddress(SUBGHZ_DEVICE_CC1101_EXT_DMA_CH4_DEF, (uint32_t) & (gpio->port->BSRR)); | ||||||
|  |     LL_DMA_ConfigTransfer( | ||||||
|  |         SUBGHZ_DEVICE_CC1101_EXT_DMA_CH4_DEF, | ||||||
|  |         LL_DMA_DIRECTION_MEMORY_TO_PERIPH | LL_DMA_MODE_CIRCULAR | LL_DMA_PERIPH_NOINCREMENT | | ||||||
|  |             LL_DMA_MEMORY_INCREMENT | LL_DMA_PDATAALIGN_WORD | LL_DMA_MDATAALIGN_WORD | | ||||||
|  |             LL_DMA_PRIORITY_HIGH); | ||||||
|  |     LL_DMA_SetDataLength(SUBGHZ_DEVICE_CC1101_EXT_DMA_CH4_DEF, 2); | ||||||
|  |     LL_DMA_SetPeriphRequest(SUBGHZ_DEVICE_CC1101_EXT_DMA_CH4_DEF, LL_DMAMUX_REQ_TIM17_UP); | ||||||
|  |     LL_DMA_EnableChannel(SUBGHZ_DEVICE_CC1101_EXT_DMA_CH4_DEF); | ||||||
|  | 
 | ||||||
|  |     // Start debug
 | ||||||
|  |     if(subghz_device_cc1101_ext_start_debug()) { | ||||||
|  |         gpio = subghz_device_cc1101_ext->async_mirror_pin; | ||||||
|  |         subghz_device_cc1101_ext->async_tx.debug_gpio_buff[0] = (uint32_t)gpio->pin << GPIO_NUMBER; | ||||||
|  |         subghz_device_cc1101_ext->async_tx.debug_gpio_buff[1] = gpio->pin; | ||||||
|  | 
 | ||||||
|  |         LL_DMA_SetMemoryAddress( | ||||||
|  |             SUBGHZ_DEVICE_CC1101_EXT_DMA_CH5_DEF, | ||||||
|  |             (uint32_t)subghz_device_cc1101_ext->async_tx.debug_gpio_buff); | ||||||
|  |         LL_DMA_SetPeriphAddress( | ||||||
|  |             SUBGHZ_DEVICE_CC1101_EXT_DMA_CH5_DEF, (uint32_t) & (gpio->port->BSRR)); | ||||||
|  |         LL_DMA_ConfigTransfer( | ||||||
|  |             SUBGHZ_DEVICE_CC1101_EXT_DMA_CH5_DEF, | ||||||
|  |             LL_DMA_DIRECTION_MEMORY_TO_PERIPH | LL_DMA_MODE_CIRCULAR | LL_DMA_PERIPH_NOINCREMENT | | ||||||
|  |                 LL_DMA_MEMORY_INCREMENT | LL_DMA_PDATAALIGN_WORD | LL_DMA_MDATAALIGN_WORD | | ||||||
|  |                 LL_DMA_PRIORITY_LOW); | ||||||
|  |         LL_DMA_SetDataLength(SUBGHZ_DEVICE_CC1101_EXT_DMA_CH5_DEF, 2); | ||||||
|  |         LL_DMA_SetPeriphRequest(SUBGHZ_DEVICE_CC1101_EXT_DMA_CH5_DEF, LL_DMAMUX_REQ_TIM17_UP); | ||||||
|  |         LL_DMA_EnableChannel(SUBGHZ_DEVICE_CC1101_EXT_DMA_CH5_DEF); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     // Start counter
 | ||||||
|  |     LL_TIM_EnableDMAReq_UPDATE(TIM17); | ||||||
|  |     LL_TIM_GenerateEvent_UPDATE(TIM17); | ||||||
|  | 
 | ||||||
|  |     subghz_device_cc1101_ext_tx(); | ||||||
|  | 
 | ||||||
|  |     LL_TIM_SetCounter(TIM17, 0); | ||||||
|  |     LL_TIM_EnableCounter(TIM17); | ||||||
|  | 
 | ||||||
|  |     return true; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | bool subghz_device_cc1101_ext_is_async_tx_complete() { | ||||||
|  |     return subghz_device_cc1101_ext->state == SubGhzDeviceCC1101ExtStateAsyncTxEnd; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | void subghz_device_cc1101_ext_stop_async_tx() { | ||||||
|  |     furi_assert( | ||||||
|  |         subghz_device_cc1101_ext->state == SubGhzDeviceCC1101ExtStateAsyncTx || | ||||||
|  |         subghz_device_cc1101_ext->state == SubGhzDeviceCC1101ExtStateAsyncTxEnd); | ||||||
|  | 
 | ||||||
|  |     // Shutdown radio
 | ||||||
|  |     subghz_device_cc1101_ext_idle(); | ||||||
|  | 
 | ||||||
|  |     // Deinitialize Timer
 | ||||||
|  |     FURI_CRITICAL_ENTER(); | ||||||
|  |     furi_hal_bus_disable(FuriHalBusTIM17); | ||||||
|  |     furi_hal_interrupt_set_isr(FuriHalInterruptIdTim1TrgComTim17, NULL, NULL); | ||||||
|  | 
 | ||||||
|  |     // Deinitialize DMA
 | ||||||
|  |     LL_DMA_DeInit(SUBGHZ_DEVICE_CC1101_EXT_DMA_CH3_DEF); | ||||||
|  |     LL_DMA_DisableChannel(SUBGHZ_DEVICE_CC1101_EXT_DMA_CH4_DEF); | ||||||
|  |     furi_hal_interrupt_set_isr(SUBGHZ_DEVICE_CC1101_EXT_DMA_CH3_IRQ, NULL, NULL); | ||||||
|  | 
 | ||||||
|  |     // Deinitialize GPIO
 | ||||||
|  |     furi_hal_gpio_write(subghz_device_cc1101_ext->g0_pin, false); | ||||||
|  |     furi_hal_gpio_init(subghz_device_cc1101_ext->g0_pin, GpioModeAnalog, GpioPullNo, GpioSpeedLow); | ||||||
|  | 
 | ||||||
|  |     // Stop debug
 | ||||||
|  |     if(subghz_device_cc1101_ext_stop_debug()) { | ||||||
|  |         LL_DMA_DisableChannel(SUBGHZ_DEVICE_CC1101_EXT_DMA_CH5_DEF); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     FURI_CRITICAL_EXIT(); | ||||||
|  | 
 | ||||||
|  |     free(subghz_device_cc1101_ext->async_tx.buffer); | ||||||
|  | 
 | ||||||
|  |     subghz_device_cc1101_ext->state = SubGhzDeviceCC1101ExtStateIdle; | ||||||
|  | } | ||||||
							
								
								
									
										206
									
								
								applications/drivers/subghz/cc1101_ext/cc1101_ext.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										206
									
								
								applications/drivers/subghz/cc1101_ext/cc1101_ext.h
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,206 @@ | |||||||
|  | /**
 | ||||||
|  |  * @file furi_hal_subghz.h | ||||||
|  |  * SubGhz HAL API | ||||||
|  |  */ | ||||||
|  | 
 | ||||||
|  | #pragma once | ||||||
|  | #include <lib/subghz/devices/preset.h> | ||||||
|  | #include <stdbool.h> | ||||||
|  | #include <stdint.h> | ||||||
|  | #include <stddef.h> | ||||||
|  | #include <toolbox/level_duration.h> | ||||||
|  | #include <furi_hal_gpio.h> | ||||||
|  | 
 | ||||||
|  | #ifdef __cplusplus | ||||||
|  | extern "C" { | ||||||
|  | #endif | ||||||
|  | 
 | ||||||
|  | /* Mirror RX/TX async modulation signal to specified pin
 | ||||||
|  |  * | ||||||
|  |  * @warning    Configures pin to output mode. Make sure it is not connected | ||||||
|  |  *             directly to power or ground. | ||||||
|  |  * | ||||||
|  |  * @param[in]  pin   pointer to the gpio pin structure or NULL to disable | ||||||
|  |  */ | ||||||
|  | void subghz_device_cc1101_ext_set_async_mirror_pin(const GpioPin* pin); | ||||||
|  | 
 | ||||||
|  | /** Get data GPIO
 | ||||||
|  |  * | ||||||
|  |  * @return     pointer to the gpio pin structure | ||||||
|  |  */ | ||||||
|  | const GpioPin* subghz_device_cc1101_ext_get_data_gpio(); | ||||||
|  | 
 | ||||||
|  | /** Initialize device
 | ||||||
|  |  * | ||||||
|  |  * @return     true if success | ||||||
|  |  */ | ||||||
|  | bool subghz_device_cc1101_ext_alloc(); | ||||||
|  | 
 | ||||||
|  | /** Deinitialize device
 | ||||||
|  |  */ | ||||||
|  | void subghz_device_cc1101_ext_free(); | ||||||
|  | 
 | ||||||
|  | /** Check and switch to power save mode Used by internal API-HAL
 | ||||||
|  |  * initialization routine Can be used to reinitialize device to safe state and | ||||||
|  |  * send it to sleep | ||||||
|  |  */ | ||||||
|  | bool subghz_device_cc1101_ext_is_connect(); | ||||||
|  | 
 | ||||||
|  | /** Send device to sleep mode
 | ||||||
|  |  */ | ||||||
|  | void subghz_device_cc1101_ext_sleep(); | ||||||
|  | 
 | ||||||
|  | /** Dump info to stdout
 | ||||||
|  |  */ | ||||||
|  | void subghz_device_cc1101_ext_dump_state(); | ||||||
|  | 
 | ||||||
|  | /** Load custom registers from preset
 | ||||||
|  |  * | ||||||
|  |  * @param      preset_data   registers to load | ||||||
|  |  */ | ||||||
|  | void subghz_device_cc1101_ext_load_custom_preset(const uint8_t* preset_data); | ||||||
|  | 
 | ||||||
|  | /** Load registers
 | ||||||
|  |  * | ||||||
|  |  * @param      data  Registers data | ||||||
|  |  */ | ||||||
|  | void subghz_device_cc1101_ext_load_registers(const uint8_t* data); | ||||||
|  | 
 | ||||||
|  | /** Load PATABLE
 | ||||||
|  |  * | ||||||
|  |  * @param      data  8 uint8_t values | ||||||
|  |  */ | ||||||
|  | void subghz_device_cc1101_ext_load_patable(const uint8_t data[8]); | ||||||
|  | 
 | ||||||
|  | /** Write packet to FIFO
 | ||||||
|  |  * | ||||||
|  |  * @param      data  bytes array | ||||||
|  |  * @param      size  size | ||||||
|  |  */ | ||||||
|  | void subghz_device_cc1101_ext_write_packet(const uint8_t* data, uint8_t size); | ||||||
|  | 
 | ||||||
|  | /** Check if receive pipe is not empty
 | ||||||
|  |  * | ||||||
|  |  * @return     true if not empty | ||||||
|  |  */ | ||||||
|  | bool subghz_device_cc1101_ext_rx_pipe_not_empty(); | ||||||
|  | 
 | ||||||
|  | /** Check if received data crc is valid
 | ||||||
|  |  * | ||||||
|  |  * @return     true if valid | ||||||
|  |  */ | ||||||
|  | bool subghz_device_cc1101_ext_is_rx_data_crc_valid(); | ||||||
|  | 
 | ||||||
|  | /** Read packet from FIFO
 | ||||||
|  |  * | ||||||
|  |  * @param      data  pointer | ||||||
|  |  * @param      size  size | ||||||
|  |  */ | ||||||
|  | void subghz_device_cc1101_ext_read_packet(uint8_t* data, uint8_t* size); | ||||||
|  | 
 | ||||||
|  | /** Flush rx FIFO buffer
 | ||||||
|  |  */ | ||||||
|  | void subghz_device_cc1101_ext_flush_rx(); | ||||||
|  | 
 | ||||||
|  | /** Flush tx FIFO buffer
 | ||||||
|  |  */ | ||||||
|  | void subghz_device_cc1101_ext_flush_tx(); | ||||||
|  | 
 | ||||||
|  | /** Shutdown Issue SPWD command
 | ||||||
|  |  * @warning    registers content will be lost | ||||||
|  |  */ | ||||||
|  | void subghz_device_cc1101_ext_shutdown(); | ||||||
|  | 
 | ||||||
|  | /** Reset Issue reset command
 | ||||||
|  |  * @warning    registers content will be lost | ||||||
|  |  */ | ||||||
|  | void subghz_device_cc1101_ext_reset(); | ||||||
|  | 
 | ||||||
|  | /** Switch to Idle
 | ||||||
|  |  */ | ||||||
|  | void subghz_device_cc1101_ext_idle(); | ||||||
|  | 
 | ||||||
|  | /** Switch to Receive
 | ||||||
|  |  */ | ||||||
|  | void subghz_device_cc1101_ext_rx(); | ||||||
|  | 
 | ||||||
|  | /** Switch to Transmit
 | ||||||
|  |  * | ||||||
|  |  * @return     true if the transfer is allowed by belonging to the region | ||||||
|  |  */ | ||||||
|  | bool subghz_device_cc1101_ext_tx(); | ||||||
|  | 
 | ||||||
|  | /** Get RSSI value in dBm
 | ||||||
|  |  * | ||||||
|  |  * @return     RSSI value | ||||||
|  |  */ | ||||||
|  | float subghz_device_cc1101_ext_get_rssi(); | ||||||
|  | 
 | ||||||
|  | /** Get LQI
 | ||||||
|  |  * | ||||||
|  |  * @return     LQI value | ||||||
|  |  */ | ||||||
|  | uint8_t subghz_device_cc1101_ext_get_lqi(); | ||||||
|  | 
 | ||||||
|  | /** Check if frequency is in valid range
 | ||||||
|  |  * | ||||||
|  |  * @param      value  frequency in Hz | ||||||
|  |  * | ||||||
|  |  * @return     true if frequency is valid, otherwise false | ||||||
|  |  */ | ||||||
|  | bool subghz_device_cc1101_ext_is_frequency_valid(uint32_t value); | ||||||
|  | 
 | ||||||
|  | /** Set frequency
 | ||||||
|  |  * | ||||||
|  |  * @param      value  frequency in Hz | ||||||
|  |  * | ||||||
|  |  * @return     real frequency in Hz | ||||||
|  |  */ | ||||||
|  | uint32_t subghz_device_cc1101_ext_set_frequency(uint32_t value); | ||||||
|  | 
 | ||||||
|  | /* High Level API */ | ||||||
|  | 
 | ||||||
|  | /** Signal Timings Capture callback */ | ||||||
|  | typedef void (*SubGhzDeviceCC1101ExtCaptureCallback)(bool level, uint32_t duration, void* context); | ||||||
|  | 
 | ||||||
|  | /** Enable signal timings capture Initializes GPIO and TIM2 for timings capture
 | ||||||
|  |  * | ||||||
|  |  * @param      callback  SubGhzDeviceCC1101ExtCaptureCallback | ||||||
|  |  * @param      context   callback context | ||||||
|  |  */ | ||||||
|  | void subghz_device_cc1101_ext_start_async_rx( | ||||||
|  |     SubGhzDeviceCC1101ExtCaptureCallback callback, | ||||||
|  |     void* context); | ||||||
|  | 
 | ||||||
|  | /** Disable signal timings capture Resets GPIO and TIM2
 | ||||||
|  |  */ | ||||||
|  | void subghz_device_cc1101_ext_stop_async_rx(); | ||||||
|  | 
 | ||||||
|  | /** Async TX callback type
 | ||||||
|  |  * @param      context  callback context | ||||||
|  |  * @return     LevelDuration | ||||||
|  |  */ | ||||||
|  | typedef LevelDuration (*SubGhzDeviceCC1101ExtCallback)(void* context); | ||||||
|  | 
 | ||||||
|  | /** Start async TX Initializes GPIO, TIM2 and DMA1 for signal output
 | ||||||
|  |  * | ||||||
|  |  * @param      callback  SubGhzDeviceCC1101ExtCallback | ||||||
|  |  * @param      context   callback context | ||||||
|  |  * | ||||||
|  |  * @return     true if the transfer is allowed by belonging to the region | ||||||
|  |  */ | ||||||
|  | bool subghz_device_cc1101_ext_start_async_tx(SubGhzDeviceCC1101ExtCallback callback, void* context); | ||||||
|  | 
 | ||||||
|  | /** Wait for async transmission to complete
 | ||||||
|  |  * | ||||||
|  |  * @return     true if TX complete | ||||||
|  |  */ | ||||||
|  | bool subghz_device_cc1101_ext_is_async_tx_complete(); | ||||||
|  | 
 | ||||||
|  | /** Stop async transmission and cleanup resources Resets GPIO, TIM2, and DMA1
 | ||||||
|  |  */ | ||||||
|  | void subghz_device_cc1101_ext_stop_async_tx(); | ||||||
|  | 
 | ||||||
|  | #ifdef __cplusplus | ||||||
|  | } | ||||||
|  | #endif | ||||||
							
								
								
									
										110
									
								
								applications/drivers/subghz/cc1101_ext/cc1101_ext_interconnect.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										110
									
								
								applications/drivers/subghz/cc1101_ext/cc1101_ext_interconnect.c
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,110 @@ | |||||||
|  | #include "cc1101_ext_interconnect.h" | ||||||
|  | #include "cc1101_ext.h" | ||||||
|  | #include <lib/subghz/devices/cc1101_configs.h> | ||||||
|  | 
 | ||||||
|  | #define TAG "SubGhzDeviceCC1101Ext" | ||||||
|  | 
 | ||||||
|  | static bool subghz_device_cc1101_ext_interconnect_is_frequency_valid(uint32_t frequency) { | ||||||
|  |     bool ret = subghz_device_cc1101_ext_is_frequency_valid(frequency); | ||||||
|  |     if(!ret) { | ||||||
|  |         furi_crash("SubGhz: Incorrect frequency."); | ||||||
|  |     } | ||||||
|  |     return ret; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | static uint32_t subghz_device_cc1101_ext_interconnect_set_frequency(uint32_t frequency) { | ||||||
|  |     subghz_device_cc1101_ext_interconnect_is_frequency_valid(frequency); | ||||||
|  |     return subghz_device_cc1101_ext_set_frequency(frequency); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | static bool subghz_device_cc1101_ext_interconnect_start_async_tx(void* callback, void* context) { | ||||||
|  |     return subghz_device_cc1101_ext_start_async_tx( | ||||||
|  |         (SubGhzDeviceCC1101ExtCallback)callback, context); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | static void subghz_device_cc1101_ext_interconnect_start_async_rx(void* callback, void* context) { | ||||||
|  |     subghz_device_cc1101_ext_start_async_rx( | ||||||
|  |         (SubGhzDeviceCC1101ExtCaptureCallback)callback, context); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | static void subghz_device_cc1101_ext_interconnect_load_preset( | ||||||
|  |     FuriHalSubGhzPreset preset, | ||||||
|  |     uint8_t* preset_data) { | ||||||
|  |     switch(preset) { | ||||||
|  |     case FuriHalSubGhzPresetOok650Async: | ||||||
|  |         subghz_device_cc1101_ext_load_custom_preset( | ||||||
|  |             subghz_device_cc1101_preset_ook_650khz_async_regs); | ||||||
|  |         break; | ||||||
|  |     case FuriHalSubGhzPresetOok270Async: | ||||||
|  |         subghz_device_cc1101_ext_load_custom_preset( | ||||||
|  |             subghz_device_cc1101_preset_ook_270khz_async_regs); | ||||||
|  |         break; | ||||||
|  |     case FuriHalSubGhzPreset2FSKDev238Async: | ||||||
|  |         subghz_device_cc1101_ext_load_custom_preset( | ||||||
|  |             subghz_device_cc1101_preset_2fsk_dev2_38khz_async_regs); | ||||||
|  |         break; | ||||||
|  |     case FuriHalSubGhzPreset2FSKDev476Async: | ||||||
|  |         subghz_device_cc1101_ext_load_custom_preset( | ||||||
|  |             subghz_device_cc1101_preset_2fsk_dev47_6khz_async_regs); | ||||||
|  |         break; | ||||||
|  |     case FuriHalSubGhzPresetMSK99_97KbAsync: | ||||||
|  |         subghz_device_cc1101_ext_load_custom_preset( | ||||||
|  |             subghz_device_cc1101_preset_msk_99_97kb_async_regs); | ||||||
|  |         break; | ||||||
|  |     case FuriHalSubGhzPresetGFSK9_99KbAsync: | ||||||
|  |         subghz_device_cc1101_ext_load_custom_preset( | ||||||
|  |             subghz_device_cc1101_preset_gfsk_9_99kb_async_regs); | ||||||
|  |         break; | ||||||
|  | 
 | ||||||
|  |     default: | ||||||
|  |         subghz_device_cc1101_ext_load_custom_preset(preset_data); | ||||||
|  |     } | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | const SubGhzDeviceInterconnect subghz_device_cc1101_ext_interconnect = { | ||||||
|  |     .begin = subghz_device_cc1101_ext_alloc, | ||||||
|  |     .end = subghz_device_cc1101_ext_free, | ||||||
|  |     .is_connect = subghz_device_cc1101_ext_is_connect, | ||||||
|  |     .reset = subghz_device_cc1101_ext_reset, | ||||||
|  |     .sleep = subghz_device_cc1101_ext_sleep, | ||||||
|  |     .idle = subghz_device_cc1101_ext_idle, | ||||||
|  |     .load_preset = subghz_device_cc1101_ext_interconnect_load_preset, | ||||||
|  |     .set_frequency = subghz_device_cc1101_ext_interconnect_set_frequency, | ||||||
|  |     .is_frequency_valid = subghz_device_cc1101_ext_is_frequency_valid, | ||||||
|  |     .set_async_mirror_pin = subghz_device_cc1101_ext_set_async_mirror_pin, | ||||||
|  |     .get_data_gpio = subghz_device_cc1101_ext_get_data_gpio, | ||||||
|  | 
 | ||||||
|  |     .set_tx = subghz_device_cc1101_ext_tx, | ||||||
|  |     .flush_tx = subghz_device_cc1101_ext_flush_tx, | ||||||
|  |     .start_async_tx = subghz_device_cc1101_ext_interconnect_start_async_tx, | ||||||
|  |     .is_async_complete_tx = subghz_device_cc1101_ext_is_async_tx_complete, | ||||||
|  |     .stop_async_tx = subghz_device_cc1101_ext_stop_async_tx, | ||||||
|  | 
 | ||||||
|  |     .set_rx = subghz_device_cc1101_ext_rx, | ||||||
|  |     .flush_rx = subghz_device_cc1101_ext_flush_rx, | ||||||
|  |     .start_async_rx = subghz_device_cc1101_ext_interconnect_start_async_rx, | ||||||
|  |     .stop_async_rx = subghz_device_cc1101_ext_stop_async_rx, | ||||||
|  | 
 | ||||||
|  |     .get_rssi = subghz_device_cc1101_ext_get_rssi, | ||||||
|  |     .get_lqi = subghz_device_cc1101_ext_get_lqi, | ||||||
|  | 
 | ||||||
|  |     .rx_pipe_not_empty = subghz_device_cc1101_ext_rx_pipe_not_empty, | ||||||
|  |     .is_rx_data_crc_valid = subghz_device_cc1101_ext_is_rx_data_crc_valid, | ||||||
|  |     .read_packet = subghz_device_cc1101_ext_read_packet, | ||||||
|  |     .write_packet = subghz_device_cc1101_ext_write_packet, | ||||||
|  | }; | ||||||
|  | 
 | ||||||
|  | const SubGhzDevice subghz_device_cc1101_ext = { | ||||||
|  |     .name = SUBGHZ_DEVICE_CC1101_EXT_NAME, | ||||||
|  |     .interconnect = &subghz_device_cc1101_ext_interconnect, | ||||||
|  | }; | ||||||
|  | 
 | ||||||
|  | static const FlipperAppPluginDescriptor subghz_device_cc1101_ext_descriptor = { | ||||||
|  |     .appid = SUBGHZ_RADIO_DEVICE_PLUGIN_APP_ID, | ||||||
|  |     .ep_api_version = SUBGHZ_RADIO_DEVICE_PLUGIN_API_VERSION, | ||||||
|  |     .entry_point = &subghz_device_cc1101_ext, | ||||||
|  | }; | ||||||
|  | 
 | ||||||
|  | const FlipperAppPluginDescriptor* subghz_device_cc1101_ext_ep() { | ||||||
|  |     return &subghz_device_cc1101_ext_descriptor; | ||||||
|  | } | ||||||
| @ -0,0 +1,8 @@ | |||||||
|  | #pragma once | ||||||
|  | #include <lib/subghz/devices/types.h> | ||||||
|  | 
 | ||||||
|  | #define SUBGHZ_DEVICE_CC1101_EXT_NAME "cc1101_ext" | ||||||
|  | 
 | ||||||
|  | typedef struct SubGhzDeviceCC1101Ext SubGhzDeviceCC1101Ext; | ||||||
|  | 
 | ||||||
|  | const FlipperAppPluginDescriptor* subghz_device_cc1101_ext_ep(); | ||||||
| @ -76,12 +76,15 @@ void subghz_chat_worker_free(SubGhzChatWorker* instance) { | |||||||
|     free(instance); |     free(instance); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| bool subghz_chat_worker_start(SubGhzChatWorker* instance, uint32_t frequency) { | bool subghz_chat_worker_start( | ||||||
|  |     SubGhzChatWorker* instance, | ||||||
|  |     const SubGhzDevice* device, | ||||||
|  |     uint32_t frequency) { | ||||||
|     furi_assert(instance); |     furi_assert(instance); | ||||||
|     furi_assert(!instance->worker_running); |     furi_assert(!instance->worker_running); | ||||||
|     bool res = false; |     bool res = false; | ||||||
| 
 | 
 | ||||||
|     if(subghz_tx_rx_worker_start(instance->subghz_txrx, frequency)) { |     if(subghz_tx_rx_worker_start(instance->subghz_txrx, device, frequency)) { | ||||||
|         furi_message_queue_reset(instance->event_queue); |         furi_message_queue_reset(instance->event_queue); | ||||||
|         subghz_tx_rx_worker_set_callback_have_read( |         subghz_tx_rx_worker_set_callback_have_read( | ||||||
|             instance->subghz_txrx, subghz_chat_worker_update_rx_event_chat, instance); |             instance->subghz_txrx, subghz_chat_worker_update_rx_event_chat, instance); | ||||||
|  | |||||||
| @ -1,5 +1,6 @@ | |||||||
| #pragma once | #pragma once | ||||||
| #include "../subghz_i.h" | #include "../subghz_i.h" | ||||||
|  | #include <lib/subghz/devices/devices.h> | ||||||
| #include <cli/cli.h> | #include <cli/cli.h> | ||||||
| 
 | 
 | ||||||
| typedef struct SubGhzChatWorker SubGhzChatWorker; | typedef struct SubGhzChatWorker SubGhzChatWorker; | ||||||
| @ -20,7 +21,10 @@ typedef struct { | |||||||
| 
 | 
 | ||||||
| SubGhzChatWorker* subghz_chat_worker_alloc(Cli* cli); | SubGhzChatWorker* subghz_chat_worker_alloc(Cli* cli); | ||||||
| void subghz_chat_worker_free(SubGhzChatWorker* instance); | void subghz_chat_worker_free(SubGhzChatWorker* instance); | ||||||
| bool subghz_chat_worker_start(SubGhzChatWorker* instance, uint32_t frequency); | bool subghz_chat_worker_start( | ||||||
|  |     SubGhzChatWorker* instance, | ||||||
|  |     const SubGhzDevice* device, | ||||||
|  |     uint32_t frequency); | ||||||
| void subghz_chat_worker_stop(SubGhzChatWorker* instance); | void subghz_chat_worker_stop(SubGhzChatWorker* instance); | ||||||
| bool subghz_chat_worker_is_running(SubGhzChatWorker* instance); | bool subghz_chat_worker_is_running(SubGhzChatWorker* instance); | ||||||
| SubGhzChatEvent subghz_chat_worker_get_event_chat(SubGhzChatWorker* instance); | SubGhzChatEvent subghz_chat_worker_get_event_chat(SubGhzChatWorker* instance); | ||||||
|  | |||||||
| @ -32,9 +32,8 @@ float subghz_threshold_rssi_get(SubGhzThresholdRssi* instance) { | |||||||
|     return instance->threshold_rssi; |     return instance->threshold_rssi; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| SubGhzThresholdRssiData subghz_threshold_get_rssi_data(SubGhzThresholdRssi* instance) { | SubGhzThresholdRssiData subghz_threshold_get_rssi_data(SubGhzThresholdRssi* instance, float rssi) { | ||||||
|     furi_assert(instance); |     furi_assert(instance); | ||||||
|     float rssi = furi_hal_subghz_get_rssi(); |  | ||||||
|     SubGhzThresholdRssiData ret = {.rssi = rssi, .is_above = false}; |     SubGhzThresholdRssiData ret = {.rssi = rssi, .is_above = false}; | ||||||
| 
 | 
 | ||||||
|     if(float_is_equal(instance->threshold_rssi, SUBGHZ_RAW_THRESHOLD_MIN)) { |     if(float_is_equal(instance->threshold_rssi, SUBGHZ_RAW_THRESHOLD_MIN)) { | ||||||
|  | |||||||
| @ -38,6 +38,7 @@ float subghz_threshold_rssi_get(SubGhzThresholdRssi* instance); | |||||||
| /** Check threshold
 | /** Check threshold
 | ||||||
|  *  |  *  | ||||||
|  * @param instance Pointer to a SubGhzThresholdRssi |  * @param instance Pointer to a SubGhzThresholdRssi | ||||||
|  |  * @param rssi Current RSSI | ||||||
|  * @return SubGhzThresholdRssiData  |  * @return SubGhzThresholdRssiData  | ||||||
|  */ |  */ | ||||||
| SubGhzThresholdRssiData subghz_threshold_get_rssi_data(SubGhzThresholdRssi* instance); | SubGhzThresholdRssiData subghz_threshold_get_rssi_data(SubGhzThresholdRssi* instance, float rssi); | ||||||
|  | |||||||
| @ -1,9 +1,26 @@ | |||||||
| #include "subghz_txrx_i.h" | #include "subghz_txrx_i.h" | ||||||
| 
 | 
 | ||||||
| #include <lib/subghz/protocols/protocol_items.h> | #include <lib/subghz/protocols/protocol_items.h> | ||||||
|  | #include <applications/drivers/subghz/cc1101_ext/cc1101_ext_interconnect.h> | ||||||
|  | #include <lib/subghz/devices/cc1101_int/cc1101_int_interconnect.h> | ||||||
| 
 | 
 | ||||||
| #define TAG "SubGhz" | #define TAG "SubGhz" | ||||||
| 
 | 
 | ||||||
|  | static void subghz_txrx_radio_device_power_on(SubGhzTxRx* instance) { | ||||||
|  |     UNUSED(instance); | ||||||
|  |     uint8_t attempts = 0; | ||||||
|  |     while(!furi_hal_power_is_otg_enabled() && attempts++ < 5) { | ||||||
|  |         furi_hal_power_enable_otg(); | ||||||
|  |         //CC1101 power-up time
 | ||||||
|  |         furi_delay_ms(10); | ||||||
|  |     } | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | static void subghz_txrx_radio_device_power_off(SubGhzTxRx* instance) { | ||||||
|  |     UNUSED(instance); | ||||||
|  |     if(furi_hal_power_is_otg_enabled()) furi_hal_power_disable_otg(); | ||||||
|  | } | ||||||
|  | 
 | ||||||
| SubGhzTxRx* subghz_txrx_alloc() { | SubGhzTxRx* subghz_txrx_alloc() { | ||||||
|     SubGhzTxRx* instance = malloc(sizeof(SubGhzTxRx)); |     SubGhzTxRx* instance = malloc(sizeof(SubGhzTxRx)); | ||||||
|     instance->setting = subghz_setting_alloc(); |     instance->setting = subghz_setting_alloc(); | ||||||
| @ -23,16 +40,15 @@ SubGhzTxRx* subghz_txrx_alloc() { | |||||||
|     instance->fff_data = flipper_format_string_alloc(); |     instance->fff_data = flipper_format_string_alloc(); | ||||||
| 
 | 
 | ||||||
|     instance->environment = subghz_environment_alloc(); |     instance->environment = subghz_environment_alloc(); | ||||||
|     instance->is_database_loaded = subghz_environment_load_keystore( |     instance->is_database_loaded = | ||||||
|         instance->environment, EXT_PATH("subghz/assets/keeloq_mfcodes")); |         subghz_environment_load_keystore(instance->environment, SUBGHZ_KEYSTORE_DIR_NAME); | ||||||
|     subghz_environment_load_keystore( |     subghz_environment_load_keystore(instance->environment, SUBGHZ_KEYSTORE_DIR_USER_NAME); | ||||||
|         instance->environment, EXT_PATH("subghz/assets/keeloq_mfcodes_user")); |  | ||||||
|     subghz_environment_set_came_atomo_rainbow_table_file_name( |     subghz_environment_set_came_atomo_rainbow_table_file_name( | ||||||
|         instance->environment, EXT_PATH("subghz/assets/came_atomo")); |         instance->environment, SUBGHZ_CAME_ATOMO_DIR_NAME); | ||||||
|     subghz_environment_set_alutech_at_4n_rainbow_table_file_name( |     subghz_environment_set_alutech_at_4n_rainbow_table_file_name( | ||||||
|         instance->environment, EXT_PATH("subghz/assets/alutech_at_4n")); |         instance->environment, SUBGHZ_ALUTECH_AT_4N_DIR_NAME); | ||||||
|     subghz_environment_set_nice_flor_s_rainbow_table_file_name( |     subghz_environment_set_nice_flor_s_rainbow_table_file_name( | ||||||
|         instance->environment, EXT_PATH("subghz/assets/nice_flor_s")); |         instance->environment, SUBGHZ_NICE_FLOR_S_DIR_NAME); | ||||||
|     subghz_environment_set_protocol_registry( |     subghz_environment_set_protocol_registry( | ||||||
|         instance->environment, (void*)&subghz_protocol_registry); |         instance->environment, (void*)&subghz_protocol_registry); | ||||||
|     instance->receiver = subghz_receiver_alloc_init(instance->environment); |     instance->receiver = subghz_receiver_alloc_init(instance->environment); | ||||||
| @ -43,18 +59,32 @@ SubGhzTxRx* subghz_txrx_alloc() { | |||||||
|         instance->worker, (SubGhzWorkerPairCallback)subghz_receiver_decode); |         instance->worker, (SubGhzWorkerPairCallback)subghz_receiver_decode); | ||||||
|     subghz_worker_set_context(instance->worker, instance->receiver); |     subghz_worker_set_context(instance->worker, instance->receiver); | ||||||
| 
 | 
 | ||||||
|  |     //set default device External
 | ||||||
|  |     subghz_devices_init(); | ||||||
|  |     instance->radio_device_type = SubGhzRadioDeviceTypeInternal; | ||||||
|  |     instance->radio_device_type = | ||||||
|  |         subghz_txrx_radio_device_set(instance, SubGhzRadioDeviceTypeExternalCC1101); | ||||||
|  | 
 | ||||||
|     return instance; |     return instance; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void subghz_txrx_free(SubGhzTxRx* instance) { | void subghz_txrx_free(SubGhzTxRx* instance) { | ||||||
|     furi_assert(instance); |     furi_assert(instance); | ||||||
| 
 | 
 | ||||||
|  |     if(instance->radio_device_type != SubGhzRadioDeviceTypeInternal) { | ||||||
|  |         subghz_txrx_radio_device_power_off(instance); | ||||||
|  |         subghz_devices_end(instance->radio_device); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     subghz_devices_deinit(); | ||||||
|  | 
 | ||||||
|     subghz_worker_free(instance->worker); |     subghz_worker_free(instance->worker); | ||||||
|     subghz_receiver_free(instance->receiver); |     subghz_receiver_free(instance->receiver); | ||||||
|     subghz_environment_free(instance->environment); |     subghz_environment_free(instance->environment); | ||||||
|     flipper_format_free(instance->fff_data); |     flipper_format_free(instance->fff_data); | ||||||
|     furi_string_free(instance->preset->name); |     furi_string_free(instance->preset->name); | ||||||
|     subghz_setting_free(instance->setting); |     subghz_setting_free(instance->setting); | ||||||
|  | 
 | ||||||
|     free(instance->preset); |     free(instance->preset); | ||||||
|     free(instance); |     free(instance); | ||||||
| } | } | ||||||
| @ -122,29 +152,26 @@ void subghz_txrx_get_frequency_and_modulation( | |||||||
| 
 | 
 | ||||||
| static void subghz_txrx_begin(SubGhzTxRx* instance, uint8_t* preset_data) { | static void subghz_txrx_begin(SubGhzTxRx* instance, uint8_t* preset_data) { | ||||||
|     furi_assert(instance); |     furi_assert(instance); | ||||||
|     furi_hal_subghz_reset(); |     subghz_devices_reset(instance->radio_device); | ||||||
|     furi_hal_subghz_idle(); |     subghz_devices_idle(instance->radio_device); | ||||||
|     furi_hal_subghz_load_custom_preset(preset_data); |     subghz_devices_load_preset(instance->radio_device, FuriHalSubGhzPresetCustom, preset_data); | ||||||
|     furi_hal_gpio_init(&gpio_cc1101_g0, GpioModeInput, GpioPullNo, GpioSpeedLow); |  | ||||||
|     instance->txrx_state = SubGhzTxRxStateIDLE; |     instance->txrx_state = SubGhzTxRxStateIDLE; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| static uint32_t subghz_txrx_rx(SubGhzTxRx* instance, uint32_t frequency) { | static uint32_t subghz_txrx_rx(SubGhzTxRx* instance, uint32_t frequency) { | ||||||
|     furi_assert(instance); |     furi_assert(instance); | ||||||
|     if(!furi_hal_subghz_is_frequency_valid(frequency)) { | 
 | ||||||
|         furi_crash("SubGhz: Incorrect RX frequency."); |  | ||||||
|     } |  | ||||||
|     furi_assert( |     furi_assert( | ||||||
|         instance->txrx_state != SubGhzTxRxStateRx && instance->txrx_state != SubGhzTxRxStateSleep); |         instance->txrx_state != SubGhzTxRxStateRx && instance->txrx_state != SubGhzTxRxStateSleep); | ||||||
| 
 | 
 | ||||||
|     furi_hal_subghz_idle(); |     subghz_devices_idle(instance->radio_device); | ||||||
|     uint32_t value = furi_hal_subghz_set_frequency_and_path(frequency); |  | ||||||
|     furi_hal_gpio_init(&gpio_cc1101_g0, GpioModeInput, GpioPullNo, GpioSpeedLow); |  | ||||||
|     furi_hal_subghz_flush_rx(); |  | ||||||
|     subghz_txrx_speaker_on(instance); |  | ||||||
|     furi_hal_subghz_rx(); |  | ||||||
| 
 | 
 | ||||||
|     furi_hal_subghz_start_async_rx(subghz_worker_rx_callback, instance->worker); |     uint32_t value = subghz_devices_set_frequency(instance->radio_device, frequency); | ||||||
|  |     subghz_devices_flush_rx(instance->radio_device); | ||||||
|  |     subghz_txrx_speaker_on(instance); | ||||||
|  | 
 | ||||||
|  |     subghz_devices_start_async_rx( | ||||||
|  |         instance->radio_device, subghz_worker_rx_callback, instance->worker); | ||||||
|     subghz_worker_start(instance->worker); |     subghz_worker_start(instance->worker); | ||||||
|     instance->txrx_state = SubGhzTxRxStateRx; |     instance->txrx_state = SubGhzTxRxStateRx; | ||||||
|     return value; |     return value; | ||||||
| @ -153,7 +180,7 @@ static uint32_t subghz_txrx_rx(SubGhzTxRx* instance, uint32_t frequency) { | |||||||
| static void subghz_txrx_idle(SubGhzTxRx* instance) { | static void subghz_txrx_idle(SubGhzTxRx* instance) { | ||||||
|     furi_assert(instance); |     furi_assert(instance); | ||||||
|     furi_assert(instance->txrx_state != SubGhzTxRxStateSleep); |     furi_assert(instance->txrx_state != SubGhzTxRxStateSleep); | ||||||
|     furi_hal_subghz_idle(); |     subghz_devices_idle(instance->radio_device); | ||||||
|     subghz_txrx_speaker_off(instance); |     subghz_txrx_speaker_off(instance); | ||||||
|     instance->txrx_state = SubGhzTxRxStateIDLE; |     instance->txrx_state = SubGhzTxRxStateIDLE; | ||||||
| } | } | ||||||
| @ -164,30 +191,26 @@ static void subghz_txrx_rx_end(SubGhzTxRx* instance) { | |||||||
| 
 | 
 | ||||||
|     if(subghz_worker_is_running(instance->worker)) { |     if(subghz_worker_is_running(instance->worker)) { | ||||||
|         subghz_worker_stop(instance->worker); |         subghz_worker_stop(instance->worker); | ||||||
|         furi_hal_subghz_stop_async_rx(); |         subghz_devices_stop_async_rx(instance->radio_device); | ||||||
|     } |     } | ||||||
|     furi_hal_subghz_idle(); |     subghz_devices_idle(instance->radio_device); | ||||||
|     subghz_txrx_speaker_off(instance); |     subghz_txrx_speaker_off(instance); | ||||||
|     instance->txrx_state = SubGhzTxRxStateIDLE; |     instance->txrx_state = SubGhzTxRxStateIDLE; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void subghz_txrx_sleep(SubGhzTxRx* instance) { | void subghz_txrx_sleep(SubGhzTxRx* instance) { | ||||||
|     furi_assert(instance); |     furi_assert(instance); | ||||||
|     furi_hal_subghz_sleep(); |     subghz_devices_sleep(instance->radio_device); | ||||||
|     instance->txrx_state = SubGhzTxRxStateSleep; |     instance->txrx_state = SubGhzTxRxStateSleep; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| static bool subghz_txrx_tx(SubGhzTxRx* instance, uint32_t frequency) { | static bool subghz_txrx_tx(SubGhzTxRx* instance, uint32_t frequency) { | ||||||
|     furi_assert(instance); |     furi_assert(instance); | ||||||
|     if(!furi_hal_subghz_is_frequency_valid(frequency)) { |  | ||||||
|         furi_crash("SubGhz: Incorrect TX frequency."); |  | ||||||
|     } |  | ||||||
|     furi_assert(instance->txrx_state != SubGhzTxRxStateSleep); |     furi_assert(instance->txrx_state != SubGhzTxRxStateSleep); | ||||||
|     furi_hal_subghz_idle(); |     subghz_devices_idle(instance->radio_device); | ||||||
|     furi_hal_subghz_set_frequency_and_path(frequency); |     subghz_devices_set_frequency(instance->radio_device, frequency); | ||||||
|     furi_hal_gpio_write(&gpio_cc1101_g0, false); | 
 | ||||||
|     furi_hal_gpio_init(&gpio_cc1101_g0, GpioModeOutputPushPull, GpioPullNo, GpioSpeedLow); |     bool ret = subghz_devices_set_tx(instance->radio_device); | ||||||
|     bool ret = furi_hal_subghz_tx(); |  | ||||||
|     if(ret) { |     if(ret) { | ||||||
|         subghz_txrx_speaker_on(instance); |         subghz_txrx_speaker_on(instance); | ||||||
|         instance->txrx_state = SubGhzTxRxStateTx; |         instance->txrx_state = SubGhzTxRxStateTx; | ||||||
| @ -249,8 +272,8 @@ SubGhzTxRxStartTxState subghz_txrx_tx_start(SubGhzTxRx* instance, FlipperFormat* | |||||||
| 
 | 
 | ||||||
|                 if(ret == SubGhzTxRxStartTxStateOk) { |                 if(ret == SubGhzTxRxStartTxStateOk) { | ||||||
|                     //Start TX
 |                     //Start TX
 | ||||||
|                     furi_hal_subghz_start_async_tx( |                     subghz_devices_start_async_tx( | ||||||
|                         subghz_transmitter_yield, instance->transmitter); |                         instance->radio_device, subghz_transmitter_yield, instance->transmitter); | ||||||
|                 } |                 } | ||||||
|             } else { |             } else { | ||||||
|                 ret = SubGhzTxRxStartTxStateErrorParserOthers; |                 ret = SubGhzTxRxStartTxStateErrorParserOthers; | ||||||
| @ -293,7 +316,7 @@ static void subghz_txrx_tx_stop(SubGhzTxRx* instance) { | |||||||
|     furi_assert(instance); |     furi_assert(instance); | ||||||
|     furi_assert(instance->txrx_state == SubGhzTxRxStateTx); |     furi_assert(instance->txrx_state == SubGhzTxRxStateTx); | ||||||
|     //Stop TX
 |     //Stop TX
 | ||||||
|     furi_hal_subghz_stop_async_tx(); |     subghz_devices_stop_async_tx(instance->radio_device); | ||||||
|     subghz_transmitter_stop(instance->transmitter); |     subghz_transmitter_stop(instance->transmitter); | ||||||
|     subghz_transmitter_free(instance->transmitter); |     subghz_transmitter_free(instance->transmitter); | ||||||
| 
 | 
 | ||||||
| @ -306,7 +329,6 @@ static void subghz_txrx_tx_stop(SubGhzTxRx* instance) { | |||||||
|     subghz_txrx_idle(instance); |     subghz_txrx_idle(instance); | ||||||
|     subghz_txrx_speaker_off(instance); |     subghz_txrx_speaker_off(instance); | ||||||
|     //Todo: Show message
 |     //Todo: Show message
 | ||||||
|     // notification_message(notifications, &sequence_reset_red);
 |  | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| FlipperFormat* subghz_txrx_get_fff_data(SubGhzTxRx* instance) { | FlipperFormat* subghz_txrx_get_fff_data(SubGhzTxRx* instance) { | ||||||
| @ -356,7 +378,7 @@ void subghz_txrx_hopper_update(SubGhzTxRx* instance) { | |||||||
|     float rssi = -127.0f; |     float rssi = -127.0f; | ||||||
|     if(instance->hopper_state != SubGhzHopperStateRSSITimeOut) { |     if(instance->hopper_state != SubGhzHopperStateRSSITimeOut) { | ||||||
|         // See RSSI Calculation timings in CC1101 17.3 RSSI
 |         // See RSSI Calculation timings in CC1101 17.3 RSSI
 | ||||||
|         rssi = furi_hal_subghz_get_rssi(); |         rssi = subghz_devices_get_rssi(instance->radio_device); | ||||||
| 
 | 
 | ||||||
|         // Stay if RSSI is high enough
 |         // Stay if RSSI is high enough
 | ||||||
|         if(rssi > -90.0f) { |         if(rssi > -90.0f) { | ||||||
| @ -414,7 +436,7 @@ void subghz_txrx_speaker_on(SubGhzTxRx* instance) { | |||||||
|     furi_assert(instance); |     furi_assert(instance); | ||||||
|     if(instance->speaker_state == SubGhzSpeakerStateEnable) { |     if(instance->speaker_state == SubGhzSpeakerStateEnable) { | ||||||
|         if(furi_hal_speaker_acquire(30)) { |         if(furi_hal_speaker_acquire(30)) { | ||||||
|             furi_hal_subghz_set_async_mirror_pin(&gpio_speaker); |             subghz_devices_set_async_mirror_pin(instance->radio_device, &gpio_speaker); | ||||||
|         } else { |         } else { | ||||||
|             instance->speaker_state = SubGhzSpeakerStateDisable; |             instance->speaker_state = SubGhzSpeakerStateDisable; | ||||||
|         } |         } | ||||||
| @ -425,7 +447,7 @@ void subghz_txrx_speaker_off(SubGhzTxRx* instance) { | |||||||
|     furi_assert(instance); |     furi_assert(instance); | ||||||
|     if(instance->speaker_state != SubGhzSpeakerStateDisable) { |     if(instance->speaker_state != SubGhzSpeakerStateDisable) { | ||||||
|         if(furi_hal_speaker_is_mine()) { |         if(furi_hal_speaker_is_mine()) { | ||||||
|             furi_hal_subghz_set_async_mirror_pin(NULL); |             subghz_devices_set_async_mirror_pin(instance->radio_device, NULL); | ||||||
|             furi_hal_speaker_release(); |             furi_hal_speaker_release(); | ||||||
|             if(instance->speaker_state == SubGhzSpeakerStateShutdown) |             if(instance->speaker_state == SubGhzSpeakerStateShutdown) | ||||||
|                 instance->speaker_state = SubGhzSpeakerStateDisable; |                 instance->speaker_state = SubGhzSpeakerStateDisable; | ||||||
| @ -437,7 +459,7 @@ void subghz_txrx_speaker_mute(SubGhzTxRx* instance) { | |||||||
|     furi_assert(instance); |     furi_assert(instance); | ||||||
|     if(instance->speaker_state == SubGhzSpeakerStateEnable) { |     if(instance->speaker_state == SubGhzSpeakerStateEnable) { | ||||||
|         if(furi_hal_speaker_is_mine()) { |         if(furi_hal_speaker_is_mine()) { | ||||||
|             furi_hal_subghz_set_async_mirror_pin(NULL); |             subghz_devices_set_async_mirror_pin(instance->radio_device, NULL); | ||||||
|         } |         } | ||||||
|     } |     } | ||||||
| } | } | ||||||
| @ -446,7 +468,7 @@ void subghz_txrx_speaker_unmute(SubGhzTxRx* instance) { | |||||||
|     furi_assert(instance); |     furi_assert(instance); | ||||||
|     if(instance->speaker_state == SubGhzSpeakerStateEnable) { |     if(instance->speaker_state == SubGhzSpeakerStateEnable) { | ||||||
|         if(furi_hal_speaker_is_mine()) { |         if(furi_hal_speaker_is_mine()) { | ||||||
|             furi_hal_subghz_set_async_mirror_pin(&gpio_speaker); |             subghz_devices_set_async_mirror_pin(instance->radio_device, &gpio_speaker); | ||||||
|         } |         } | ||||||
|     } |     } | ||||||
| } | } | ||||||
| @ -519,3 +541,63 @@ void subghz_txrx_set_raw_file_encoder_worker_callback_end( | |||||||
|         callback, |         callback, | ||||||
|         context); |         context); | ||||||
| } | } | ||||||
|  | 
 | ||||||
|  | bool subghz_txrx_radio_device_is_external_connected(SubGhzTxRx* instance, const char* name) { | ||||||
|  |     furi_assert(instance); | ||||||
|  | 
 | ||||||
|  |     bool is_connect = false; | ||||||
|  |     bool is_otg_enabled = furi_hal_power_is_otg_enabled(); | ||||||
|  | 
 | ||||||
|  |     if(!is_otg_enabled) { | ||||||
|  |         subghz_txrx_radio_device_power_on(instance); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     is_connect = subghz_devices_is_connect(subghz_devices_get_by_name(name)); | ||||||
|  | 
 | ||||||
|  |     if(!is_otg_enabled) { | ||||||
|  |         subghz_txrx_radio_device_power_off(instance); | ||||||
|  |     } | ||||||
|  |     return is_connect; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | SubGhzRadioDeviceType | ||||||
|  |     subghz_txrx_radio_device_set(SubGhzTxRx* instance, SubGhzRadioDeviceType radio_device_type) { | ||||||
|  |     furi_assert(instance); | ||||||
|  | 
 | ||||||
|  |     if(radio_device_type == SubGhzRadioDeviceTypeExternalCC1101 && | ||||||
|  |        subghz_txrx_radio_device_is_external_connected(instance, SUBGHZ_DEVICE_CC1101_EXT_NAME)) { | ||||||
|  |         subghz_txrx_radio_device_power_on(instance); | ||||||
|  |         instance->radio_device = subghz_devices_get_by_name(SUBGHZ_DEVICE_CC1101_EXT_NAME); | ||||||
|  |         subghz_devices_begin(instance->radio_device); | ||||||
|  |         instance->radio_device_type = SubGhzRadioDeviceTypeExternalCC1101; | ||||||
|  |     } else { | ||||||
|  |         subghz_txrx_radio_device_power_off(instance); | ||||||
|  |         if(instance->radio_device_type != SubGhzRadioDeviceTypeInternal) { | ||||||
|  |             subghz_devices_end(instance->radio_device); | ||||||
|  |         } | ||||||
|  |         instance->radio_device = subghz_devices_get_by_name(SUBGHZ_DEVICE_CC1101_INT_NAME); | ||||||
|  |         instance->radio_device_type = SubGhzRadioDeviceTypeInternal; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     return instance->radio_device_type; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | SubGhzRadioDeviceType subghz_txrx_radio_device_get(SubGhzTxRx* instance) { | ||||||
|  |     furi_assert(instance); | ||||||
|  |     return instance->radio_device_type; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | float subghz_txrx_radio_device_get_rssi(SubGhzTxRx* instance) { | ||||||
|  |     furi_assert(instance); | ||||||
|  |     return subghz_devices_get_rssi(instance->radio_device); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | const char* subghz_txrx_radio_device_get_name(SubGhzTxRx* instance) { | ||||||
|  |     furi_assert(instance); | ||||||
|  |     return subghz_devices_get_name(instance->radio_device); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | bool subghz_txrx_radio_device_is_frequecy_valid(SubGhzTxRx* instance, uint32_t frequency) { | ||||||
|  |     furi_assert(instance); | ||||||
|  |     return subghz_devices_is_frequency_valid(instance->radio_device, frequency); | ||||||
|  | } | ||||||
| @ -7,6 +7,7 @@ | |||||||
| #include <lib/subghz/receiver.h> | #include <lib/subghz/receiver.h> | ||||||
| #include <lib/subghz/transmitter.h> | #include <lib/subghz/transmitter.h> | ||||||
| #include <lib/subghz/protocols/raw.h> | #include <lib/subghz/protocols/raw.h> | ||||||
|  | #include <lib/subghz/devices/devices.h> | ||||||
| 
 | 
 | ||||||
| typedef struct SubGhzTxRx SubGhzTxRx; | typedef struct SubGhzTxRx SubGhzTxRx; | ||||||
| 
 | 
 | ||||||
| @ -288,3 +289,48 @@ void subghz_txrx_set_raw_file_encoder_worker_callback_end( | |||||||
|     SubGhzTxRx* instance, |     SubGhzTxRx* instance, | ||||||
|     SubGhzProtocolEncoderRAWCallbackEnd callback, |     SubGhzProtocolEncoderRAWCallbackEnd callback, | ||||||
|     void* context); |     void* context); | ||||||
|  | 
 | ||||||
|  | /* Checking if an external radio device is connected
 | ||||||
|  | *  | ||||||
|  | * @param instance Pointer to a SubGhzTxRx | ||||||
|  | * @param name Name of external radio device | ||||||
|  | * @return bool True if is connected to the external radio device | ||||||
|  | */ | ||||||
|  | bool subghz_txrx_radio_device_is_external_connected(SubGhzTxRx* instance, const char* name); | ||||||
|  | 
 | ||||||
|  | /* Set the selected radio device to use
 | ||||||
|  | * | ||||||
|  | * @param instance Pointer to a SubGhzTxRx | ||||||
|  | * @param radio_device_type Radio device type | ||||||
|  | * @return SubGhzRadioDeviceType Type of installed radio device | ||||||
|  | */ | ||||||
|  | SubGhzRadioDeviceType | ||||||
|  |     subghz_txrx_radio_device_set(SubGhzTxRx* instance, SubGhzRadioDeviceType radio_device_type); | ||||||
|  | 
 | ||||||
|  | /* Get the selected radio device to use
 | ||||||
|  | * | ||||||
|  | * @param instance Pointer to a SubGhzTxRx | ||||||
|  | * @return SubGhzRadioDeviceType Type of installed radio device | ||||||
|  | */ | ||||||
|  | SubGhzRadioDeviceType subghz_txrx_radio_device_get(SubGhzTxRx* instance); | ||||||
|  | 
 | ||||||
|  | /* Get RSSI the selected radio device to use
 | ||||||
|  | * | ||||||
|  | * @param instance Pointer to a SubGhzTxRx | ||||||
|  | * @return float RSSI | ||||||
|  | */ | ||||||
|  | float subghz_txrx_radio_device_get_rssi(SubGhzTxRx* instance); | ||||||
|  | 
 | ||||||
|  | /* Get name the selected radio device to use
 | ||||||
|  | * | ||||||
|  | * @param instance Pointer to a SubGhzTxRx | ||||||
|  | * @return const char* Name of installed radio device | ||||||
|  | */ | ||||||
|  | const char* subghz_txrx_radio_device_get_name(SubGhzTxRx* instance); | ||||||
|  | 
 | ||||||
|  | /* Get get intelligence whether frequency the selected radio device to use
 | ||||||
|  | * | ||||||
|  | * @param instance Pointer to a SubGhzTxRx | ||||||
|  | * @return bool True if the frequency is valid | ||||||
|  | */ | ||||||
|  | bool subghz_txrx_radio_device_is_frequecy_valid(SubGhzTxRx* instance, uint32_t frequency); | ||||||
| @ -21,6 +21,8 @@ struct SubGhzTxRx { | |||||||
| 
 | 
 | ||||||
|     SubGhzTxRxState txrx_state; |     SubGhzTxRxState txrx_state; | ||||||
|     SubGhzSpeakerState speaker_state; |     SubGhzSpeakerState speaker_state; | ||||||
|  |     const SubGhzDevice* radio_device; | ||||||
|  |     SubGhzRadioDeviceType radio_device_type; | ||||||
| 
 | 
 | ||||||
|     SubGhzTxRxNeedSaveCallback need_save_callback; |     SubGhzTxRxNeedSaveCallback need_save_callback; | ||||||
|     void* need_save_context; |     void* need_save_context; | ||||||
|  | |||||||
| @ -35,6 +35,13 @@ typedef enum { | |||||||
|     SubGhzSpeakerStateEnable, |     SubGhzSpeakerStateEnable, | ||||||
| } SubGhzSpeakerState; | } SubGhzSpeakerState; | ||||||
| 
 | 
 | ||||||
|  | /** SubGhzRadioDeviceType */ | ||||||
|  | typedef enum { | ||||||
|  |     SubGhzRadioDeviceTypeAuto, | ||||||
|  |     SubGhzRadioDeviceTypeInternal, | ||||||
|  |     SubGhzRadioDeviceTypeExternalCC1101, | ||||||
|  | } SubGhzRadioDeviceType; | ||||||
|  | 
 | ||||||
| /** SubGhzRxKeyState state */ | /** SubGhzRxKeyState state */ | ||||||
| typedef enum { | typedef enum { | ||||||
|     SubGhzRxKeyStateIDLE, |     SubGhzRxKeyStateIDLE, | ||||||
|  | |||||||
| @ -24,3 +24,4 @@ ADD_SCENE(subghz, delete_raw, DeleteRAW) | |||||||
| ADD_SCENE(subghz, need_saving, NeedSaving) | ADD_SCENE(subghz, need_saving, NeedSaving) | ||||||
| ADD_SCENE(subghz, rpc, Rpc) | ADD_SCENE(subghz, rpc, Rpc) | ||||||
| ADD_SCENE(subghz, region_info, RegionInfo) | ADD_SCENE(subghz, region_info, RegionInfo) | ||||||
|  | ADD_SCENE(subghz, radio_settings, RadioSettings) | ||||||
|  | |||||||
							
								
								
									
										70
									
								
								applications/main/subghz/scenes/subghz_scene_radio_setting.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										70
									
								
								applications/main/subghz/scenes/subghz_scene_radio_setting.c
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,70 @@ | |||||||
|  | #include "../subghz_i.h" | ||||||
|  | #include <lib/toolbox/value_index.h> | ||||||
|  | #include <applications/drivers/subghz/cc1101_ext/cc1101_ext_interconnect.h> | ||||||
|  | 
 | ||||||
|  | enum SubGhzRadioSettingIndex { | ||||||
|  |     SubGhzRadioSettingIndexDevice, | ||||||
|  | }; | ||||||
|  | 
 | ||||||
|  | #define RADIO_DEVICE_COUNT 2 | ||||||
|  | const char* const radio_device_text[RADIO_DEVICE_COUNT] = { | ||||||
|  |     "Internal", | ||||||
|  |     "External", | ||||||
|  | }; | ||||||
|  | 
 | ||||||
|  | const uint32_t radio_device_value[RADIO_DEVICE_COUNT] = { | ||||||
|  |     SubGhzRadioDeviceTypeInternal, | ||||||
|  |     SubGhzRadioDeviceTypeExternalCC1101, | ||||||
|  | }; | ||||||
|  | 
 | ||||||
|  | static void subghz_scene_radio_settings_set_device(VariableItem* item) { | ||||||
|  |     SubGhz* subghz = variable_item_get_context(item); | ||||||
|  |     uint8_t index = variable_item_get_current_value_index(item); | ||||||
|  | 
 | ||||||
|  |     if(!subghz_txrx_radio_device_is_external_connected( | ||||||
|  |            subghz->txrx, SUBGHZ_DEVICE_CC1101_EXT_NAME) && | ||||||
|  |        radio_device_value[index] == SubGhzRadioDeviceTypeExternalCC1101) { | ||||||
|  |         //ToDo correct if there is more than 1 module
 | ||||||
|  |         index = 0; | ||||||
|  |     } | ||||||
|  |     variable_item_set_current_value_text(item, radio_device_text[index]); | ||||||
|  |     subghz_txrx_radio_device_set(subghz->txrx, radio_device_value[index]); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | void subghz_scene_radio_settings_on_enter(void* context) { | ||||||
|  |     SubGhz* subghz = context; | ||||||
|  |     VariableItem* item; | ||||||
|  |     uint8_t value_index; | ||||||
|  | 
 | ||||||
|  |     uint8_t value_count_device = RADIO_DEVICE_COUNT; | ||||||
|  |     if(subghz_txrx_radio_device_get(subghz->txrx) == SubGhzRadioDeviceTypeInternal && | ||||||
|  |        !subghz_txrx_radio_device_is_external_connected(subghz->txrx, SUBGHZ_DEVICE_CC1101_EXT_NAME)) | ||||||
|  |         value_count_device = 1; | ||||||
|  |     item = variable_item_list_add( | ||||||
|  |         subghz->variable_item_list, | ||||||
|  |         "Module", | ||||||
|  |         value_count_device, | ||||||
|  |         subghz_scene_radio_settings_set_device, | ||||||
|  |         subghz); | ||||||
|  |     value_index = value_index_uint32( | ||||||
|  |         subghz_txrx_radio_device_get(subghz->txrx), radio_device_value, value_count_device); | ||||||
|  |     variable_item_set_current_value_index(item, value_index); | ||||||
|  |     variable_item_set_current_value_text(item, radio_device_text[value_index]); | ||||||
|  | 
 | ||||||
|  |     view_dispatcher_switch_to_view(subghz->view_dispatcher, SubGhzViewIdVariableItemList); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | bool subghz_scene_radio_settings_on_event(void* context, SceneManagerEvent event) { | ||||||
|  |     SubGhz* subghz = context; | ||||||
|  |     bool consumed = false; | ||||||
|  |     UNUSED(subghz); | ||||||
|  |     UNUSED(event); | ||||||
|  | 
 | ||||||
|  |     return consumed; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | void subghz_scene_radio_settings_on_exit(void* context) { | ||||||
|  |     SubGhz* subghz = context; | ||||||
|  |     variable_item_list_set_selected_item(subghz->variable_item_list, 0); | ||||||
|  |     variable_item_list_reset(subghz->variable_item_list); | ||||||
|  | } | ||||||
| @ -48,6 +48,9 @@ static void subghz_scene_read_raw_update_statusbar(void* context) { | |||||||
| 
 | 
 | ||||||
|     furi_string_free(frequency_str); |     furi_string_free(frequency_str); | ||||||
|     furi_string_free(modulation_str); |     furi_string_free(modulation_str); | ||||||
|  | 
 | ||||||
|  |     subghz_read_raw_set_radio_device_type( | ||||||
|  |         subghz->subghz_read_raw, subghz_txrx_radio_device_get(subghz->txrx)); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void subghz_scene_read_raw_callback(SubGhzCustomEvent event, void* context) { | void subghz_scene_read_raw_callback(SubGhzCustomEvent event, void* context) { | ||||||
| @ -238,7 +241,9 @@ bool subghz_scene_read_raw_on_event(void* context, SceneManagerEvent event) { | |||||||
|             furi_string_printf( |             furi_string_printf( | ||||||
|                 temp_str, "%s/%s%s", SUBGHZ_RAW_FOLDER, RAW_FILE_NAME, SUBGHZ_APP_EXTENSION); |                 temp_str, "%s/%s%s", SUBGHZ_RAW_FOLDER, RAW_FILE_NAME, SUBGHZ_APP_EXTENSION); | ||||||
|             subghz_protocol_raw_gen_fff_data( |             subghz_protocol_raw_gen_fff_data( | ||||||
|                 subghz_txrx_get_fff_data(subghz->txrx), furi_string_get_cstr(temp_str)); |                 subghz_txrx_get_fff_data(subghz->txrx), | ||||||
|  |                 furi_string_get_cstr(temp_str), | ||||||
|  |                 subghz_txrx_radio_device_get_name(subghz->txrx)); | ||||||
|             furi_string_free(temp_str); |             furi_string_free(temp_str); | ||||||
| 
 | 
 | ||||||
|             if(spl_count > 0) { |             if(spl_count > 0) { | ||||||
| @ -298,8 +303,8 @@ bool subghz_scene_read_raw_on_event(void* context, SceneManagerEvent event) { | |||||||
|             subghz_read_raw_update_sample_write( |             subghz_read_raw_update_sample_write( | ||||||
|                 subghz->subghz_read_raw, subghz_protocol_raw_get_sample_write(decoder_raw)); |                 subghz->subghz_read_raw, subghz_protocol_raw_get_sample_write(decoder_raw)); | ||||||
| 
 | 
 | ||||||
|             SubGhzThresholdRssiData ret_rssi = |             SubGhzThresholdRssiData ret_rssi = subghz_threshold_get_rssi_data( | ||||||
|                 subghz_threshold_get_rssi_data(subghz->threshold_rssi); |                 subghz->threshold_rssi, subghz_txrx_radio_device_get_rssi(subghz->txrx)); | ||||||
|             subghz_read_raw_add_data_rssi( |             subghz_read_raw_add_data_rssi( | ||||||
|                 subghz->subghz_read_raw, ret_rssi.rssi, ret_rssi.is_above); |                 subghz->subghz_read_raw, ret_rssi.rssi, ret_rssi.is_above); | ||||||
|             subghz_protocol_raw_save_to_file_pause(decoder_raw, !ret_rssi.is_above); |             subghz_protocol_raw_save_to_file_pause(decoder_raw, !ret_rssi.is_above); | ||||||
|  | |||||||
| @ -56,6 +56,9 @@ static void subghz_scene_receiver_update_statusbar(void* context) { | |||||||
|         subghz->state_notifications = SubGhzNotificationStateIDLE; |         subghz->state_notifications = SubGhzNotificationStateIDLE; | ||||||
|     } |     } | ||||||
|     furi_string_free(history_stat_str); |     furi_string_free(history_stat_str); | ||||||
|  | 
 | ||||||
|  |     subghz_view_receiver_set_radio_device_type( | ||||||
|  |         subghz->subghz_receiver, subghz_txrx_radio_device_get(subghz->txrx)); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void subghz_scene_receiver_callback(SubGhzCustomEvent event, void* context) { | void subghz_scene_receiver_callback(SubGhzCustomEvent event, void* context) { | ||||||
| @ -189,7 +192,8 @@ bool subghz_scene_receiver_on_event(void* context, SceneManagerEvent event) { | |||||||
|             subghz_scene_receiver_update_statusbar(subghz); |             subghz_scene_receiver_update_statusbar(subghz); | ||||||
|         } |         } | ||||||
| 
 | 
 | ||||||
|         SubGhzThresholdRssiData ret_rssi = subghz_threshold_get_rssi_data(subghz->threshold_rssi); |         SubGhzThresholdRssiData ret_rssi = subghz_threshold_get_rssi_data( | ||||||
|  |             subghz->threshold_rssi, subghz_txrx_radio_device_get_rssi(subghz->txrx)); | ||||||
| 
 | 
 | ||||||
|         subghz_receiver_rssi(subghz->subghz_receiver, ret_rssi.rssi); |         subghz_receiver_rssi(subghz->subghz_receiver, ret_rssi.rssi); | ||||||
|         subghz_protocol_decoder_bin_raw_data_input_rssi( |         subghz_protocol_decoder_bin_raw_data_input_rssi( | ||||||
|  | |||||||
| @ -122,7 +122,8 @@ bool subghz_scene_save_name_on_event(void* context, SceneManagerEvent event) { | |||||||
|                    SubGhzCustomEventManagerNoSet) { |                    SubGhzCustomEventManagerNoSet) { | ||||||
|                     subghz_protocol_raw_gen_fff_data( |                     subghz_protocol_raw_gen_fff_data( | ||||||
|                         subghz_txrx_get_fff_data(subghz->txrx), |                         subghz_txrx_get_fff_data(subghz->txrx), | ||||||
|                         furi_string_get_cstr(subghz->file_path)); |                         furi_string_get_cstr(subghz->file_path), | ||||||
|  |                         subghz_txrx_radio_device_get_name(subghz->txrx)); | ||||||
|                     scene_manager_set_scene_state( |                     scene_manager_set_scene_state( | ||||||
|                         subghz->scene_manager, SubGhzSceneReadRAW, SubGhzCustomEventManagerNoSet); |                         subghz->scene_manager, SubGhzSceneReadRAW, SubGhzCustomEventManagerNoSet); | ||||||
|                 } else { |                 } else { | ||||||
|  | |||||||
| @ -8,7 +8,8 @@ enum SubmenuIndex { | |||||||
|     SubmenuIndexAddManually, |     SubmenuIndexAddManually, | ||||||
|     SubmenuIndexFrequencyAnalyzer, |     SubmenuIndexFrequencyAnalyzer, | ||||||
|     SubmenuIndexReadRAW, |     SubmenuIndexReadRAW, | ||||||
|     SubmenuIndexShowRegionInfo |     SubmenuIndexShowRegionInfo, | ||||||
|  |     SubmenuIndexRadioSetting, | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| void subghz_scene_start_submenu_callback(void* context, uint32_t index) { | void subghz_scene_start_submenu_callback(void* context, uint32_t index) { | ||||||
| @ -49,6 +50,12 @@ void subghz_scene_start_on_enter(void* context) { | |||||||
|         SubmenuIndexShowRegionInfo, |         SubmenuIndexShowRegionInfo, | ||||||
|         subghz_scene_start_submenu_callback, |         subghz_scene_start_submenu_callback, | ||||||
|         subghz); |         subghz); | ||||||
|  |     submenu_add_item( | ||||||
|  |         subghz->submenu, | ||||||
|  |         "Radio Settings", | ||||||
|  |         SubmenuIndexRadioSetting, | ||||||
|  |         subghz_scene_start_submenu_callback, | ||||||
|  |         subghz); | ||||||
|     if(furi_hal_rtc_is_flag_set(FuriHalRtcFlagDebug)) { |     if(furi_hal_rtc_is_flag_set(FuriHalRtcFlagDebug)) { | ||||||
|         submenu_add_item( |         submenu_add_item( | ||||||
|             subghz->submenu, "Test", SubmenuIndexTest, subghz_scene_start_submenu_callback, subghz); |             subghz->submenu, "Test", SubmenuIndexTest, subghz_scene_start_submenu_callback, subghz); | ||||||
| @ -104,6 +111,11 @@ bool subghz_scene_start_on_event(void* context, SceneManagerEvent event) { | |||||||
|                 subghz->scene_manager, SubGhzSceneStart, SubmenuIndexShowRegionInfo); |                 subghz->scene_manager, SubGhzSceneStart, SubmenuIndexShowRegionInfo); | ||||||
|             scene_manager_next_scene(subghz->scene_manager, SubGhzSceneRegionInfo); |             scene_manager_next_scene(subghz->scene_manager, SubGhzSceneRegionInfo); | ||||||
|             return true; |             return true; | ||||||
|  |         } else if(event.event == SubmenuIndexRadioSetting) { | ||||||
|  |             scene_manager_set_scene_state( | ||||||
|  |                 subghz->scene_manager, SubGhzSceneStart, SubmenuIndexRadioSetting); | ||||||
|  |             scene_manager_next_scene(subghz->scene_manager, SubGhzSceneRadioSettings); | ||||||
|  |             return true; | ||||||
|         } |         } | ||||||
|     } |     } | ||||||
|     return false; |     return false; | ||||||
|  | |||||||
| @ -35,6 +35,8 @@ bool subghz_scene_transmitter_update_data_show(void* context) { | |||||||
|         furi_string_free(modulation_str); |         furi_string_free(modulation_str); | ||||||
|         furi_string_free(key_str); |         furi_string_free(key_str); | ||||||
|     } |     } | ||||||
|  |     subghz_view_transmitter_set_radio_device_type( | ||||||
|  |         subghz->subghz_transmitter, subghz_txrx_radio_device_get(subghz->txrx)); | ||||||
|     return ret; |     return ret; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | |||||||
| @ -10,6 +10,10 @@ | |||||||
| #include <lib/subghz/transmitter.h> | #include <lib/subghz/transmitter.h> | ||||||
| #include <lib/subghz/subghz_file_encoder_worker.h> | #include <lib/subghz/subghz_file_encoder_worker.h> | ||||||
| #include <lib/subghz/protocols/protocol_items.h> | #include <lib/subghz/protocols/protocol_items.h> | ||||||
|  | #include <applications/drivers/subghz/cc1101_ext/cc1101_ext_interconnect.h> | ||||||
|  | #include <lib/subghz/devices/cc1101_int/cc1101_int_interconnect.h> | ||||||
|  | #include <lib/subghz/devices/devices.h> | ||||||
|  | #include <lib/subghz/devices/cc1101_configs.h> | ||||||
| 
 | 
 | ||||||
| #include "helpers/subghz_chat.h" | #include "helpers/subghz_chat.h" | ||||||
| 
 | 
 | ||||||
| @ -24,6 +28,19 @@ | |||||||
| 
 | 
 | ||||||
| #define SUBGHZ_REGION_FILENAME "/int/.region_data" | #define SUBGHZ_REGION_FILENAME "/int/.region_data" | ||||||
| 
 | 
 | ||||||
|  | static void subghz_cli_radio_device_power_on() { | ||||||
|  |     uint8_t attempts = 0; | ||||||
|  |     while(!furi_hal_power_is_otg_enabled() && attempts++ < 5) { | ||||||
|  |         furi_hal_power_enable_otg(); | ||||||
|  |         //CC1101 power-up time
 | ||||||
|  |         furi_delay_ms(10); | ||||||
|  |     } | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | static void subghz_cli_radio_device_power_off() { | ||||||
|  |     if(furi_hal_power_is_otg_enabled()) furi_hal_power_disable_otg(); | ||||||
|  | } | ||||||
|  | 
 | ||||||
| void subghz_cli_command_tx_carrier(Cli* cli, FuriString* args, void* context) { | void subghz_cli_command_tx_carrier(Cli* cli, FuriString* args, void* context) { | ||||||
|     UNUSED(context); |     UNUSED(context); | ||||||
|     uint32_t frequency = 433920000; |     uint32_t frequency = 433920000; | ||||||
| @ -44,7 +61,7 @@ void subghz_cli_command_tx_carrier(Cli* cli, FuriString* args, void* context) { | |||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     furi_hal_subghz_reset(); |     furi_hal_subghz_reset(); | ||||||
|     furi_hal_subghz_load_preset(FuriHalSubGhzPresetOok650Async); |     furi_hal_subghz_load_custom_preset(subghz_device_cc1101_preset_ook_650khz_async_regs); | ||||||
|     frequency = furi_hal_subghz_set_frequency_and_path(frequency); |     frequency = furi_hal_subghz_set_frequency_and_path(frequency); | ||||||
| 
 | 
 | ||||||
|     furi_hal_gpio_init(&gpio_cc1101_g0, GpioModeOutputPushPull, GpioPullNo, GpioSpeedLow); |     furi_hal_gpio_init(&gpio_cc1101_g0, GpioModeOutputPushPull, GpioPullNo, GpioSpeedLow); | ||||||
| @ -88,7 +105,7 @@ void subghz_cli_command_rx_carrier(Cli* cli, FuriString* args, void* context) { | |||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     furi_hal_subghz_reset(); |     furi_hal_subghz_reset(); | ||||||
|     furi_hal_subghz_load_preset(FuriHalSubGhzPresetOok650Async); |     furi_hal_subghz_load_custom_preset(subghz_device_cc1101_preset_ook_650khz_async_regs); | ||||||
|     frequency = furi_hal_subghz_set_frequency_and_path(frequency); |     frequency = furi_hal_subghz_set_frequency_and_path(frequency); | ||||||
|     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"); | ||||||
| @ -109,44 +126,70 @@ void subghz_cli_command_rx_carrier(Cli* cli, FuriString* args, void* context) { | |||||||
|     furi_hal_subghz_sleep(); |     furi_hal_subghz_sleep(); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | static const SubGhzDevice* subghz_cli_command_get_device(uint32_t device_ind) { | ||||||
|  |     const SubGhzDevice* device = NULL; | ||||||
|  |     switch(device_ind) { | ||||||
|  |     case 1: | ||||||
|  |         subghz_cli_radio_device_power_on(); | ||||||
|  |         device = subghz_devices_get_by_name(SUBGHZ_DEVICE_CC1101_EXT_NAME); | ||||||
|  |         break; | ||||||
|  | 
 | ||||||
|  |     default: | ||||||
|  |         device = subghz_devices_get_by_name(SUBGHZ_DEVICE_CC1101_INT_NAME); | ||||||
|  |         break; | ||||||
|  |     } | ||||||
|  |     return device; | ||||||
|  | } | ||||||
|  | 
 | ||||||
| void subghz_cli_command_tx(Cli* cli, FuriString* args, void* context) { | void subghz_cli_command_tx(Cli* cli, FuriString* args, void* context) { | ||||||
|     UNUSED(context); |     UNUSED(context); | ||||||
|     uint32_t frequency = 433920000; |     uint32_t frequency = 433920000; | ||||||
|     uint32_t key = 0x0074BADE; |     uint32_t key = 0x0074BADE; | ||||||
|     uint32_t repeat = 10; |     uint32_t repeat = 10; | ||||||
|     uint32_t te = 403; |     uint32_t te = 403; | ||||||
|  |     uint32_t device_ind = 0; // 0 - CC1101_INT, 1 - CC1101_EXT
 | ||||||
| 
 | 
 | ||||||
|     if(furi_string_size(args)) { |     if(furi_string_size(args)) { | ||||||
|         int ret = |         int ret = sscanf( | ||||||
|             sscanf(furi_string_get_cstr(args), "%lx %lu %lu %lu", &key, &frequency, &te, &repeat); |             furi_string_get_cstr(args), | ||||||
|         if(ret != 4) { |             "%lx %lu %lu %lu %lu", | ||||||
|  |             &key, | ||||||
|  |             &frequency, | ||||||
|  |             &te, | ||||||
|  |             &repeat, | ||||||
|  |             &device_ind); | ||||||
|  |         if(ret != 5) { | ||||||
|             printf( |             printf( | ||||||
|                 "sscanf returned %d, key: %lx, frequency: %lu, te:%lu, repeat: %lu\r\n", |                 "sscanf returned %d, key: %lx, frequency: %lu, te: %lu, repeat: %lu, device: %lu\r\n ", | ||||||
|                 ret, |                 ret, | ||||||
|                 key, |                 key, | ||||||
|                 frequency, |                 frequency, | ||||||
|                 te, |                 te, | ||||||
|                 repeat); |                 repeat, | ||||||
|  |                 device_ind); | ||||||
|             cli_print_usage( |             cli_print_usage( | ||||||
|                 "subghz tx", |                 "subghz tx", | ||||||
|                 "<3 Byte Key: in hex> <Frequency: in Hz> <Te us> <Repeat count>", |                 "<3 Byte Key: in hex> <Frequency: in Hz> <Te us> <Repeat count> <Device: 0 - CC1101_INT, 1 - CC1101_EXT>", | ||||||
|                 furi_string_get_cstr(args)); |                 furi_string_get_cstr(args)); | ||||||
|             return; |             return; | ||||||
|         } |         } | ||||||
|         if(!furi_hal_subghz_is_frequency_valid(frequency)) { |  | ||||||
|             printf( |  | ||||||
|                 "Frequency must be in " SUBGHZ_FREQUENCY_RANGE_STR " range, not %lu\r\n", |  | ||||||
|                 frequency); |  | ||||||
|             return; |  | ||||||
|         } |  | ||||||
|     } |     } | ||||||
| 
 |     subghz_devices_init(); | ||||||
|  |     const SubGhzDevice* device = subghz_cli_command_get_device(device_ind); | ||||||
|  |     if(!subghz_devices_is_frequency_valid(device, frequency)) { | ||||||
|  |         printf( | ||||||
|  |             "Frequency must be in " SUBGHZ_FREQUENCY_RANGE_STR " range, not %lu\r\n", frequency); | ||||||
|  |         subghz_devices_deinit(); | ||||||
|  |         subghz_cli_radio_device_power_off(); | ||||||
|  |         return; | ||||||
|  |     } | ||||||
|     printf( |     printf( | ||||||
|         "Transmitting at %lu, key %lx, te %lu, repeat %lu. Press CTRL+C to stop\r\n", |         "Transmitting at %lu, key %lx, te %lu, repeat %lu device %lu. Press CTRL+C to stop\r\n", | ||||||
|         frequency, |         frequency, | ||||||
|         key, |         key, | ||||||
|         te, |         te, | ||||||
|         repeat); |         repeat, | ||||||
|  |         device_ind); | ||||||
| 
 | 
 | ||||||
|     FuriString* flipper_format_string = furi_string_alloc_printf( |     FuriString* flipper_format_string = furi_string_alloc_printf( | ||||||
|         "Protocol: Princeton\n" |         "Protocol: Princeton\n" | ||||||
| @ -170,25 +213,29 @@ void subghz_cli_command_tx(Cli* cli, FuriString* args, void* context) { | |||||||
|     SubGhzTransmitter* transmitter = subghz_transmitter_alloc_init(environment, "Princeton"); |     SubGhzTransmitter* transmitter = subghz_transmitter_alloc_init(environment, "Princeton"); | ||||||
|     subghz_transmitter_deserialize(transmitter, flipper_format); |     subghz_transmitter_deserialize(transmitter, flipper_format); | ||||||
| 
 | 
 | ||||||
|     furi_hal_subghz_reset(); |     subghz_devices_begin(device); | ||||||
|     furi_hal_subghz_load_preset(FuriHalSubGhzPresetOok650Async); |     subghz_devices_reset(device); | ||||||
|     frequency = furi_hal_subghz_set_frequency_and_path(frequency); |     subghz_devices_load_preset(device, FuriHalSubGhzPresetOok650Async, NULL); | ||||||
|  |     frequency = subghz_devices_set_frequency(device, frequency); | ||||||
| 
 | 
 | ||||||
|     furi_hal_power_suppress_charge_enter(); |     furi_hal_power_suppress_charge_enter(); | ||||||
| 
 |     if(subghz_devices_start_async_tx(device, subghz_transmitter_yield, transmitter)) { | ||||||
|     if(furi_hal_subghz_start_async_tx(subghz_transmitter_yield, transmitter)) { |         while(!(subghz_devices_is_async_complete_tx(device) || cli_cmd_interrupt_received(cli))) { | ||||||
|         while(!(furi_hal_subghz_is_async_tx_complete() || cli_cmd_interrupt_received(cli))) { |  | ||||||
|             printf("."); |             printf("."); | ||||||
|             fflush(stdout); |             fflush(stdout); | ||||||
|             furi_delay_ms(333); |             furi_delay_ms(333); | ||||||
|         } |         } | ||||||
|         furi_hal_subghz_stop_async_tx(); |         subghz_devices_stop_async_tx(device); | ||||||
| 
 | 
 | ||||||
|     } else { |     } else { | ||||||
|         printf("Transmission on this frequency is restricted in your region\r\n"); |         printf("Transmission on this frequency is restricted in your region\r\n"); | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     furi_hal_subghz_sleep(); |     subghz_devices_sleep(device); | ||||||
|  |     subghz_devices_end(device); | ||||||
|  |     subghz_devices_deinit(); | ||||||
|  |     subghz_cli_radio_device_power_off(); | ||||||
|  | 
 | ||||||
|     furi_hal_power_suppress_charge_exit(); |     furi_hal_power_suppress_charge_exit(); | ||||||
| 
 | 
 | ||||||
|     flipper_format_free(flipper_format); |     flipper_format_free(flipper_format); | ||||||
| @ -233,21 +280,29 @@ static void subghz_cli_command_rx_callback( | |||||||
| void subghz_cli_command_rx(Cli* cli, FuriString* args, void* context) { | void subghz_cli_command_rx(Cli* cli, FuriString* args, void* context) { | ||||||
|     UNUSED(context); |     UNUSED(context); | ||||||
|     uint32_t frequency = 433920000; |     uint32_t frequency = 433920000; | ||||||
|  |     uint32_t device_ind = 0; // 0 - CC1101_INT, 1 - CC1101_EXT
 | ||||||
| 
 | 
 | ||||||
|     if(furi_string_size(args)) { |     if(furi_string_size(args)) { | ||||||
|         int ret = sscanf(furi_string_get_cstr(args), "%lu", &frequency); |         int ret = sscanf(furi_string_get_cstr(args), "%lu %lu", &frequency, &device_ind); | ||||||
|         if(ret != 1) { |         if(ret != 2) { | ||||||
|             printf("sscanf returned %d, frequency: %lu\r\n", ret, frequency); |  | ||||||
|             cli_print_usage("subghz rx", "<Frequency: in Hz>", furi_string_get_cstr(args)); |  | ||||||
|             return; |  | ||||||
|         } |  | ||||||
|         if(!furi_hal_subghz_is_frequency_valid(frequency)) { |  | ||||||
|             printf( |             printf( | ||||||
|                 "Frequency must be in " SUBGHZ_FREQUENCY_RANGE_STR " range, not %lu\r\n", |                 "sscanf returned %d, frequency: %lu device: %lu\r\n", ret, frequency, device_ind); | ||||||
|                 frequency); |             cli_print_usage( | ||||||
|  |                 "subghz rx", | ||||||
|  |                 "<Frequency: in Hz> <Device: 0 - CC1101_INT, 1 - CC1101_EXT>", | ||||||
|  |                 furi_string_get_cstr(args)); | ||||||
|             return; |             return; | ||||||
|         } |         } | ||||||
|     } |     } | ||||||
|  |     subghz_devices_init(); | ||||||
|  |     const SubGhzDevice* device = subghz_cli_command_get_device(device_ind); | ||||||
|  |     if(!subghz_devices_is_frequency_valid(device, frequency)) { | ||||||
|  |         printf( | ||||||
|  |             "Frequency must be in " SUBGHZ_FREQUENCY_RANGE_STR " range, not %lu\r\n", frequency); | ||||||
|  |         subghz_devices_deinit(); | ||||||
|  |         subghz_cli_radio_device_power_off(); | ||||||
|  |         return; | ||||||
|  |     } | ||||||
| 
 | 
 | ||||||
|     // Allocate context and buffers
 |     // Allocate context and buffers
 | ||||||
|     SubGhzCliCommandRx* instance = malloc(sizeof(SubGhzCliCommandRx)); |     SubGhzCliCommandRx* instance = malloc(sizeof(SubGhzCliCommandRx)); | ||||||
| @ -256,14 +311,14 @@ void subghz_cli_command_rx(Cli* cli, FuriString* args, void* context) { | |||||||
|     furi_check(instance->stream); |     furi_check(instance->stream); | ||||||
| 
 | 
 | ||||||
|     SubGhzEnvironment* environment = subghz_environment_alloc(); |     SubGhzEnvironment* environment = subghz_environment_alloc(); | ||||||
|     subghz_environment_load_keystore(environment, EXT_PATH("subghz/assets/keeloq_mfcodes")); |     subghz_environment_load_keystore(environment, SUBGHZ_KEYSTORE_DIR_NAME); | ||||||
|     subghz_environment_load_keystore(environment, EXT_PATH("subghz/assets/keeloq_mfcodes_user")); |     subghz_environment_load_keystore(environment, SUBGHZ_KEYSTORE_DIR_USER_NAME); | ||||||
|     subghz_environment_set_came_atomo_rainbow_table_file_name( |     subghz_environment_set_came_atomo_rainbow_table_file_name( | ||||||
|         environment, EXT_PATH("subghz/assets/came_atomo")); |         environment, SUBGHZ_CAME_ATOMO_DIR_NAME); | ||||||
|     subghz_environment_set_alutech_at_4n_rainbow_table_file_name( |     subghz_environment_set_alutech_at_4n_rainbow_table_file_name( | ||||||
|         environment, EXT_PATH("subghz/assets/alutech_at_4n")); |         environment, SUBGHZ_ALUTECH_AT_4N_DIR_NAME); | ||||||
|     subghz_environment_set_nice_flor_s_rainbow_table_file_name( |     subghz_environment_set_nice_flor_s_rainbow_table_file_name( | ||||||
|         environment, EXT_PATH("subghz/assets/nice_flor_s")); |         environment, SUBGHZ_NICE_FLOR_S_DIR_NAME); | ||||||
|     subghz_environment_set_protocol_registry(environment, (void*)&subghz_protocol_registry); |     subghz_environment_set_protocol_registry(environment, (void*)&subghz_protocol_registry); | ||||||
| 
 | 
 | ||||||
|     SubGhzReceiver* receiver = subghz_receiver_alloc_init(environment); |     SubGhzReceiver* receiver = subghz_receiver_alloc_init(environment); | ||||||
| @ -271,18 +326,21 @@ void subghz_cli_command_rx(Cli* cli, FuriString* args, void* context) { | |||||||
|     subghz_receiver_set_rx_callback(receiver, subghz_cli_command_rx_callback, instance); |     subghz_receiver_set_rx_callback(receiver, subghz_cli_command_rx_callback, instance); | ||||||
| 
 | 
 | ||||||
|     // Configure radio
 |     // Configure radio
 | ||||||
|     furi_hal_subghz_reset(); |     subghz_devices_begin(device); | ||||||
|     furi_hal_subghz_load_preset(FuriHalSubGhzPresetOok650Async); |     subghz_devices_reset(device); | ||||||
|     frequency = furi_hal_subghz_set_frequency_and_path(frequency); |     subghz_devices_load_preset(device, FuriHalSubGhzPresetOok650Async, NULL); | ||||||
|     furi_hal_gpio_init(&gpio_cc1101_g0, GpioModeInput, GpioPullNo, GpioSpeedLow); |     frequency = subghz_devices_set_frequency(device, frequency); | ||||||
| 
 | 
 | ||||||
|     furi_hal_power_suppress_charge_enter(); |     furi_hal_power_suppress_charge_enter(); | ||||||
| 
 | 
 | ||||||
|     // Prepare and start RX
 |     // Prepare and start RX
 | ||||||
|     furi_hal_subghz_start_async_rx(subghz_cli_command_rx_capture_callback, instance); |     subghz_devices_start_async_rx(device, subghz_cli_command_rx_capture_callback, instance); | ||||||
| 
 | 
 | ||||||
|     // Wait for packets to arrive
 |     // Wait for packets to arrive
 | ||||||
|     printf("Listening at %lu. Press CTRL+C to stop\r\n", frequency); |     printf( | ||||||
|  |         "Listening at frequency: %lu device: %lu. Press CTRL+C to stop\r\n", | ||||||
|  |         frequency, | ||||||
|  |         device_ind); | ||||||
|     LevelDuration level_duration; |     LevelDuration level_duration; | ||||||
|     while(!cli_cmd_interrupt_received(cli)) { |     while(!cli_cmd_interrupt_received(cli)) { | ||||||
|         int ret = furi_stream_buffer_receive( |         int ret = furi_stream_buffer_receive( | ||||||
| @ -300,8 +358,11 @@ void subghz_cli_command_rx(Cli* cli, FuriString* args, void* context) { | |||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     // Shutdown radio
 |     // Shutdown radio
 | ||||||
|     furi_hal_subghz_stop_async_rx(); |     subghz_devices_stop_async_rx(device); | ||||||
|     furi_hal_subghz_sleep(); |     subghz_devices_sleep(device); | ||||||
|  |     subghz_devices_end(device); | ||||||
|  |     subghz_devices_deinit(); | ||||||
|  |     subghz_cli_radio_device_power_off(); | ||||||
| 
 | 
 | ||||||
|     furi_hal_power_suppress_charge_exit(); |     furi_hal_power_suppress_charge_exit(); | ||||||
| 
 | 
 | ||||||
| @ -341,7 +402,7 @@ void subghz_cli_command_rx_raw(Cli* cli, FuriString* args, void* context) { | |||||||
| 
 | 
 | ||||||
|     // Configure radio
 |     // Configure radio
 | ||||||
|     furi_hal_subghz_reset(); |     furi_hal_subghz_reset(); | ||||||
|     furi_hal_subghz_load_preset(FuriHalSubGhzPresetOok270Async); |     furi_hal_subghz_load_custom_preset(subghz_device_cc1101_preset_ook_270khz_async_regs); | ||||||
|     frequency = furi_hal_subghz_set_frequency_and_path(frequency); |     frequency = furi_hal_subghz_set_frequency_and_path(frequency); | ||||||
|     furi_hal_gpio_init(&gpio_cc1101_g0, GpioModeInput, GpioPullNo, GpioSpeedLow); |     furi_hal_gpio_init(&gpio_cc1101_g0, GpioModeInput, GpioPullNo, GpioSpeedLow); | ||||||
| 
 | 
 | ||||||
| @ -389,6 +450,7 @@ void subghz_cli_command_rx_raw(Cli* cli, FuriString* args, void* context) { | |||||||
|     furi_stream_buffer_free(instance->stream); |     furi_stream_buffer_free(instance->stream); | ||||||
|     free(instance); |     free(instance); | ||||||
| } | } | ||||||
|  | 
 | ||||||
| void subghz_cli_command_decode_raw(Cli* cli, FuriString* args, void* context) { | void subghz_cli_command_decode_raw(Cli* cli, FuriString* args, void* context) { | ||||||
|     UNUSED(context); |     UNUSED(context); | ||||||
|     FuriString* file_name; |     FuriString* file_name; | ||||||
| @ -442,25 +504,23 @@ void subghz_cli_command_decode_raw(Cli* cli, FuriString* args, void* context) { | |||||||
|         SubGhzCliCommandRx* instance = malloc(sizeof(SubGhzCliCommandRx)); |         SubGhzCliCommandRx* instance = malloc(sizeof(SubGhzCliCommandRx)); | ||||||
| 
 | 
 | ||||||
|         SubGhzEnvironment* environment = subghz_environment_alloc(); |         SubGhzEnvironment* environment = subghz_environment_alloc(); | ||||||
|         if(subghz_environment_load_keystore( |         if(subghz_environment_load_keystore(environment, SUBGHZ_KEYSTORE_DIR_NAME)) { | ||||||
|                environment, EXT_PATH("subghz/assets/keeloq_mfcodes"))) { |  | ||||||
|             printf("SubGhz decode_raw: Load_keystore keeloq_mfcodes \033[0;32mOK\033[0m\r\n"); |             printf("SubGhz decode_raw: Load_keystore keeloq_mfcodes \033[0;32mOK\033[0m\r\n"); | ||||||
|         } else { |         } else { | ||||||
|             printf("SubGhz decode_raw: Load_keystore keeloq_mfcodes \033[0;31mERROR\033[0m\r\n"); |             printf("SubGhz decode_raw: Load_keystore keeloq_mfcodes \033[0;31mERROR\033[0m\r\n"); | ||||||
|         } |         } | ||||||
|         if(subghz_environment_load_keystore( |         if(subghz_environment_load_keystore(environment, SUBGHZ_KEYSTORE_DIR_USER_NAME)) { | ||||||
|                environment, EXT_PATH("subghz/assets/keeloq_mfcodes_user"))) { |  | ||||||
|             printf("SubGhz decode_raw: Load_keystore keeloq_mfcodes_user \033[0;32mOK\033[0m\r\n"); |             printf("SubGhz decode_raw: Load_keystore keeloq_mfcodes_user \033[0;32mOK\033[0m\r\n"); | ||||||
|         } else { |         } else { | ||||||
|             printf( |             printf( | ||||||
|                 "SubGhz decode_raw: Load_keystore keeloq_mfcodes_user \033[0;31mERROR\033[0m\r\n"); |                 "SubGhz decode_raw: Load_keystore keeloq_mfcodes_user \033[0;31mERROR\033[0m\r\n"); | ||||||
|         } |         } | ||||||
|         subghz_environment_set_came_atomo_rainbow_table_file_name( |         subghz_environment_set_came_atomo_rainbow_table_file_name( | ||||||
|             environment, EXT_PATH("subghz/assets/came_atomo")); |             environment, SUBGHZ_CAME_ATOMO_DIR_NAME); | ||||||
|         subghz_environment_set_alutech_at_4n_rainbow_table_file_name( |         subghz_environment_set_alutech_at_4n_rainbow_table_file_name( | ||||||
|             environment, EXT_PATH("subghz/assets/alutech_at_4n")); |             environment, SUBGHZ_ALUTECH_AT_4N_DIR_NAME); | ||||||
|         subghz_environment_set_nice_flor_s_rainbow_table_file_name( |         subghz_environment_set_nice_flor_s_rainbow_table_file_name( | ||||||
|             environment, EXT_PATH("subghz/assets/nice_flor_s")); |             environment, SUBGHZ_NICE_FLOR_S_DIR_NAME); | ||||||
|         subghz_environment_set_protocol_registry(environment, (void*)&subghz_protocol_registry); |         subghz_environment_set_protocol_registry(environment, (void*)&subghz_protocol_registry); | ||||||
| 
 | 
 | ||||||
|         SubGhzReceiver* receiver = subghz_receiver_alloc_init(environment); |         SubGhzReceiver* receiver = subghz_receiver_alloc_init(environment); | ||||||
| @ -468,7 +528,8 @@ void subghz_cli_command_decode_raw(Cli* cli, FuriString* args, void* context) { | |||||||
|         subghz_receiver_set_rx_callback(receiver, subghz_cli_command_rx_callback, instance); |         subghz_receiver_set_rx_callback(receiver, subghz_cli_command_rx_callback, instance); | ||||||
| 
 | 
 | ||||||
|         SubGhzFileEncoderWorker* file_worker_encoder = subghz_file_encoder_worker_alloc(); |         SubGhzFileEncoderWorker* file_worker_encoder = subghz_file_encoder_worker_alloc(); | ||||||
|         if(subghz_file_encoder_worker_start(file_worker_encoder, furi_string_get_cstr(file_name))) { |         if(subghz_file_encoder_worker_start( | ||||||
|  |                file_worker_encoder, furi_string_get_cstr(file_name), NULL)) { | ||||||
|             //the worker needs a file in order to open and read part of the file
 |             //the worker needs a file in order to open and read part of the file
 | ||||||
|             furi_delay_ms(100); |             furi_delay_ms(100); | ||||||
|         } |         } | ||||||
| @ -510,10 +571,11 @@ static void subghz_cli_command_print_usage() { | |||||||
|     printf("subghz <cmd> <args>\r\n"); |     printf("subghz <cmd> <args>\r\n"); | ||||||
|     printf("Cmd list:\r\n"); |     printf("Cmd list:\r\n"); | ||||||
| 
 | 
 | ||||||
|     printf("\tchat <frequency:in Hz>\t - Chat with other Flippers\r\n"); |  | ||||||
|     printf( |     printf( | ||||||
|         "\ttx <3 byte Key: in hex> <frequency: in Hz> <te: us> <repeat: count>\t - Transmitting key\r\n"); |         "\tchat <frequency:in Hz> <device: 0 - CC1101_INT, 1 - CC1101_EXT>\t - Chat with other Flippers\r\n"); | ||||||
|     printf("\trx <frequency:in Hz>\t - Receive\r\n"); |     printf( | ||||||
|  |         "\ttx <3 byte Key: in hex> <frequency: in Hz> <te: us> <repeat: count> <device: 0 - CC1101_INT, 1 - CC1101_EXT>\t - Transmitting key\r\n"); | ||||||
|  |     printf("\trx <frequency:in Hz> <device: 0 - CC1101_INT, 1 - CC1101_EXT>\t - Receive\r\n"); | ||||||
|     printf("\trx_raw <frequency:in Hz>\t - Receive RAW\r\n"); |     printf("\trx_raw <frequency:in Hz>\t - Receive RAW\r\n"); | ||||||
|     printf("\tdecode_raw <file_name: path_RAW_file>\t - Testing\r\n"); |     printf("\tdecode_raw <file_name: path_RAW_file>\t - Testing\r\n"); | ||||||
| 
 | 
 | ||||||
| @ -611,21 +673,29 @@ static void subghz_cli_command_encrypt_raw(Cli* cli, FuriString* args) { | |||||||
| 
 | 
 | ||||||
| static void subghz_cli_command_chat(Cli* cli, FuriString* args) { | static void subghz_cli_command_chat(Cli* cli, FuriString* args) { | ||||||
|     uint32_t frequency = 433920000; |     uint32_t frequency = 433920000; | ||||||
|  |     uint32_t device_ind = 0; // 0 - CC1101_INT, 1 - CC1101_EXT
 | ||||||
| 
 | 
 | ||||||
|     if(furi_string_size(args)) { |     if(furi_string_size(args)) { | ||||||
|         int ret = sscanf(furi_string_get_cstr(args), "%lu", &frequency); |         int ret = sscanf(furi_string_get_cstr(args), "%lu %lu", &frequency, &device_ind); | ||||||
|         if(ret != 1) { |         if(ret != 2) { | ||||||
|             printf("sscanf returned %d, frequency: %lu\r\n", ret, frequency); |             printf("sscanf returned %d, Frequency: %lu\r\n", ret, frequency); | ||||||
|             cli_print_usage("subghz chat", "<Frequency: in Hz>", furi_string_get_cstr(args)); |             printf("sscanf returned %d, Device: %lu\r\n", ret, device_ind); | ||||||
|             return; |             cli_print_usage( | ||||||
|         } |                 "subghz chat", | ||||||
|         if(!furi_hal_subghz_is_frequency_valid(frequency)) { |                 "<Frequency: in Hz> <Device: 0 - CC1101_INT, 1 - CC1101_EXT>", | ||||||
|             printf( |                 furi_string_get_cstr(args)); | ||||||
|                 "Frequency must be in " SUBGHZ_FREQUENCY_RANGE_STR " range, not %lu\r\n", |  | ||||||
|                 frequency); |  | ||||||
|             return; |             return; | ||||||
|         } |         } | ||||||
|     } |     } | ||||||
|  |     subghz_devices_init(); | ||||||
|  |     const SubGhzDevice* device = subghz_cli_command_get_device(device_ind); | ||||||
|  |     if(!subghz_devices_is_frequency_valid(device, frequency)) { | ||||||
|  |         printf( | ||||||
|  |             "Frequency must be in " SUBGHZ_FREQUENCY_RANGE_STR " range, not %lu\r\n", frequency); | ||||||
|  |         subghz_devices_deinit(); | ||||||
|  |         subghz_cli_radio_device_power_off(); | ||||||
|  |         return; | ||||||
|  |     } | ||||||
|     if(!furi_hal_region_is_frequency_allowed(frequency)) { |     if(!furi_hal_region_is_frequency_allowed(frequency)) { | ||||||
|         printf( |         printf( | ||||||
|             "In your region, only reception on this frequency (%lu) is allowed,\r\n" |             "In your region, only reception on this frequency (%lu) is allowed,\r\n" | ||||||
| @ -635,7 +705,8 @@ static void subghz_cli_command_chat(Cli* cli, FuriString* args) { | |||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     SubGhzChatWorker* subghz_chat = subghz_chat_worker_alloc(cli); |     SubGhzChatWorker* subghz_chat = subghz_chat_worker_alloc(cli); | ||||||
|     if(!subghz_chat_worker_start(subghz_chat, frequency)) { | 
 | ||||||
|  |     if(!subghz_chat_worker_start(subghz_chat, device, frequency)) { | ||||||
|         printf("Startup error SubGhzChatWorker\r\n"); |         printf("Startup error SubGhzChatWorker\r\n"); | ||||||
| 
 | 
 | ||||||
|         if(subghz_chat_worker_is_running(subghz_chat)) { |         if(subghz_chat_worker_is_running(subghz_chat)) { | ||||||
| @ -781,6 +852,10 @@ static void subghz_cli_command_chat(Cli* cli, FuriString* args) { | |||||||
|     furi_string_free(name); |     furi_string_free(name); | ||||||
|     furi_string_free(output); |     furi_string_free(output); | ||||||
|     furi_string_free(sysmsg); |     furi_string_free(sysmsg); | ||||||
|  | 
 | ||||||
|  |     subghz_devices_deinit(); | ||||||
|  |     subghz_cli_radio_device_power_off(); | ||||||
|  | 
 | ||||||
|     furi_hal_power_suppress_charge_exit(); |     furi_hal_power_suppress_charge_exit(); | ||||||
|     furi_record_close(RECORD_NOTIFICATION); |     furi_record_close(RECORD_NOTIFICATION); | ||||||
| 
 | 
 | ||||||
|  | |||||||
| @ -115,7 +115,7 @@ bool subghz_key_load(SubGhz* subghz, const char* file_path, bool show_dialog) { | |||||||
|             break; |             break; | ||||||
|         } |         } | ||||||
| 
 | 
 | ||||||
|         if(!furi_hal_subghz_is_frequency_valid(temp_data32)) { |         if(!subghz_txrx_radio_device_is_frequecy_valid(subghz->txrx, temp_data32)) { | ||||||
|             FURI_LOG_E(TAG, "Frequency not supported"); |             FURI_LOG_E(TAG, "Frequency not supported"); | ||||||
|             break; |             break; | ||||||
|         } |         } | ||||||
| @ -163,7 +163,8 @@ bool subghz_key_load(SubGhz* subghz, const char* file_path, bool show_dialog) { | |||||||
|         if(!strcmp(furi_string_get_cstr(temp_str), "RAW")) { |         if(!strcmp(furi_string_get_cstr(temp_str), "RAW")) { | ||||||
|             //if RAW
 |             //if RAW
 | ||||||
|             subghz->load_type_file = SubGhzLoadTypeFileRaw; |             subghz->load_type_file = SubGhzLoadTypeFileRaw; | ||||||
|             subghz_protocol_raw_gen_fff_data(fff_data, file_path); |             subghz_protocol_raw_gen_fff_data( | ||||||
|  |                 fff_data, file_path, subghz_txrx_radio_device_get_name(subghz->txrx)); | ||||||
|         } else { |         } else { | ||||||
|             subghz->load_type_file = SubGhzLoadTypeFileKey; |             subghz->load_type_file = SubGhzLoadTypeFileKey; | ||||||
|             stream_copy_full( |             stream_copy_full( | ||||||
|  | |||||||
| @ -62,6 +62,7 @@ typedef struct { | |||||||
|     uint16_t history_item; |     uint16_t history_item; | ||||||
|     SubGhzViewReceiverBarShow bar_show; |     SubGhzViewReceiverBarShow bar_show; | ||||||
|     uint8_t u_rssi; |     uint8_t u_rssi; | ||||||
|  |     SubGhzRadioDeviceType device_type; | ||||||
| } SubGhzViewReceiverModel; | } SubGhzViewReceiverModel; | ||||||
| 
 | 
 | ||||||
| void subghz_receiver_rssi(SubGhzViewReceiver* instance, float rssi) { | void subghz_receiver_rssi(SubGhzViewReceiver* instance, float rssi) { | ||||||
| @ -173,6 +174,17 @@ void subghz_view_receiver_add_data_statusbar( | |||||||
|         true); |         true); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | void subghz_view_receiver_set_radio_device_type( | ||||||
|  |     SubGhzViewReceiver* subghz_receiver, | ||||||
|  |     SubGhzRadioDeviceType device_type) { | ||||||
|  |     furi_assert(subghz_receiver); | ||||||
|  |     with_view_model( | ||||||
|  |         subghz_receiver->view, | ||||||
|  |         SubGhzViewReceiverModel * model, | ||||||
|  |         { model->device_type = device_type; }, | ||||||
|  |         true); | ||||||
|  | } | ||||||
|  | 
 | ||||||
| static void subghz_view_receiver_draw_frame(Canvas* canvas, uint16_t idx, bool scrollbar) { | static void subghz_view_receiver_draw_frame(Canvas* canvas, uint16_t idx, bool scrollbar) { | ||||||
|     canvas_set_color(canvas, ColorBlack); |     canvas_set_color(canvas, ColorBlack); | ||||||
|     canvas_draw_box(canvas, 0, 0 + idx * FRAME_HEIGHT, scrollbar ? 122 : 127, FRAME_HEIGHT); |     canvas_draw_box(canvas, 0, 0 + idx * FRAME_HEIGHT, scrollbar ? 122 : 127, FRAME_HEIGHT); | ||||||
| @ -190,9 +202,9 @@ static void subghz_view_receiver_draw_frame(Canvas* canvas, uint16_t idx, bool s | |||||||
| static void subghz_view_rssi_draw(Canvas* canvas, SubGhzViewReceiverModel* model) { | static void subghz_view_rssi_draw(Canvas* canvas, SubGhzViewReceiverModel* model) { | ||||||
|     for(uint8_t i = 1; i < model->u_rssi; i++) { |     for(uint8_t i = 1; i < model->u_rssi; i++) { | ||||||
|         if(i % 5) { |         if(i % 5) { | ||||||
|             canvas_draw_dot(canvas, 46 + i, 50); |  | ||||||
|             canvas_draw_dot(canvas, 47 + i, 51); |  | ||||||
|             canvas_draw_dot(canvas, 46 + i, 52); |             canvas_draw_dot(canvas, 46 + i, 52); | ||||||
|  |             canvas_draw_dot(canvas, 47 + i, 53); | ||||||
|  |             canvas_draw_dot(canvas, 46 + i, 54); | ||||||
|         } |         } | ||||||
|     } |     } | ||||||
| } | } | ||||||
| @ -232,22 +244,28 @@ void subghz_view_receiver_draw(Canvas* canvas, SubGhzViewReceiverModel* model) { | |||||||
|     canvas_set_color(canvas, ColorBlack); |     canvas_set_color(canvas, ColorBlack); | ||||||
| 
 | 
 | ||||||
|     if(model->history_item == 0) { |     if(model->history_item == 0) { | ||||||
|         canvas_draw_icon(canvas, 0, 0, &I_Scanning_123x52); |         canvas_draw_icon(canvas, 0, 0, &I_Scanning_short_96x52); | ||||||
|         canvas_set_font(canvas, FontPrimary); |         canvas_set_font(canvas, FontPrimary); | ||||||
|         canvas_draw_str(canvas, 63, 44, "Scanning..."); |         canvas_draw_str(canvas, 63, 44, "Scanning..."); | ||||||
|         canvas_set_font(canvas, FontSecondary); |         canvas_set_font(canvas, FontSecondary); | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|  |     if(model->device_type == SubGhzRadioDeviceTypeInternal) { | ||||||
|  |         canvas_draw_icon(canvas, 108, 0, &I_Internal_antenna_20x12); | ||||||
|  |     } else { | ||||||
|  |         canvas_draw_icon(canvas, 108, 0, &I_External_antenna_20x12); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|     subghz_view_rssi_draw(canvas, model); |     subghz_view_rssi_draw(canvas, model); | ||||||
|     switch(model->bar_show) { |     switch(model->bar_show) { | ||||||
|     case SubGhzViewReceiverBarShowLock: |     case SubGhzViewReceiverBarShowLock: | ||||||
|         canvas_draw_icon(canvas, 64, 55, &I_Lock_7x8); |         canvas_draw_icon(canvas, 64, 56, &I_Lock_7x8); | ||||||
|         canvas_draw_str(canvas, 74, 62, "Locked"); |         canvas_draw_str(canvas, 74, 64, "Locked"); | ||||||
|         break; |         break; | ||||||
|     case SubGhzViewReceiverBarShowToUnlockPress: |     case SubGhzViewReceiverBarShowToUnlockPress: | ||||||
|         canvas_draw_str(canvas, 44, 62, furi_string_get_cstr(model->frequency_str)); |         canvas_draw_str(canvas, 44, 64, furi_string_get_cstr(model->frequency_str)); | ||||||
|         canvas_draw_str(canvas, 79, 62, furi_string_get_cstr(model->preset_str)); |         canvas_draw_str(canvas, 79, 64, furi_string_get_cstr(model->preset_str)); | ||||||
|         canvas_draw_str(canvas, 96, 62, furi_string_get_cstr(model->history_stat_str)); |         canvas_draw_str(canvas, 97, 64, furi_string_get_cstr(model->history_stat_str)); | ||||||
|         canvas_set_font(canvas, FontSecondary); |         canvas_set_font(canvas, FontSecondary); | ||||||
|         elements_bold_rounded_frame(canvas, 14, 8, 99, 48); |         elements_bold_rounded_frame(canvas, 14, 8, 99, 48); | ||||||
|         elements_multiline_text(canvas, 65, 26, "To unlock\npress:"); |         elements_multiline_text(canvas, 65, 26, "To unlock\npress:"); | ||||||
| @ -258,13 +276,13 @@ void subghz_view_receiver_draw(Canvas* canvas, SubGhzViewReceiverModel* model) { | |||||||
|         canvas_draw_dot(canvas, 17, 61); |         canvas_draw_dot(canvas, 17, 61); | ||||||
|         break; |         break; | ||||||
|     case SubGhzViewReceiverBarShowUnlock: |     case SubGhzViewReceiverBarShowUnlock: | ||||||
|         canvas_draw_icon(canvas, 64, 55, &I_Unlock_7x8); |         canvas_draw_icon(canvas, 64, 56, &I_Unlock_7x8); | ||||||
|         canvas_draw_str(canvas, 74, 62, "Unlocked"); |         canvas_draw_str(canvas, 74, 64, "Unlocked"); | ||||||
|         break; |         break; | ||||||
|     default: |     default: | ||||||
|         canvas_draw_str(canvas, 44, 62, furi_string_get_cstr(model->frequency_str)); |         canvas_draw_str(canvas, 44, 64, furi_string_get_cstr(model->frequency_str)); | ||||||
|         canvas_draw_str(canvas, 79, 62, furi_string_get_cstr(model->preset_str)); |         canvas_draw_str(canvas, 79, 64, furi_string_get_cstr(model->preset_str)); | ||||||
|         canvas_draw_str(canvas, 96, 62, furi_string_get_cstr(model->history_stat_str)); |         canvas_draw_str(canvas, 97, 64, furi_string_get_cstr(model->history_stat_str)); | ||||||
|         break; |         break; | ||||||
|     } |     } | ||||||
| } | } | ||||||
|  | |||||||
| @ -29,6 +29,10 @@ void subghz_view_receiver_add_data_statusbar( | |||||||
|     const char* preset_str, |     const char* preset_str, | ||||||
|     const char* history_stat_str); |     const char* history_stat_str); | ||||||
| 
 | 
 | ||||||
|  | void subghz_view_receiver_set_radio_device_type( | ||||||
|  |     SubGhzViewReceiver* subghz_receiver, | ||||||
|  |     SubGhzRadioDeviceType device_type); | ||||||
|  | 
 | ||||||
| void subghz_view_receiver_add_item_to_menu( | void subghz_view_receiver_add_item_to_menu( | ||||||
|     SubGhzViewReceiver* subghz_receiver, |     SubGhzViewReceiver* subghz_receiver, | ||||||
|     const char* name, |     const char* name, | ||||||
|  | |||||||
| @ -177,7 +177,8 @@ void subghz_frequency_analyzer_draw(Canvas* canvas, SubGhzFrequencyAnalyzerModel | |||||||
|         } |         } | ||||||
|         subghz_frequency_analyzer_log_frequency_draw(canvas, model); |         subghz_frequency_analyzer_log_frequency_draw(canvas, model); | ||||||
|     } else { |     } else { | ||||||
|         canvas_draw_str(canvas, 20, 8, "Frequency Analyzer"); |         canvas_draw_str(canvas, 0, 8, "Frequency Analyzer"); | ||||||
|  |         canvas_draw_icon(canvas, 108, 0, &I_Internal_antenna_20x12); | ||||||
|         canvas_draw_str(canvas, 0, 64, "RSSI"); |         canvas_draw_str(canvas, 0, 64, "RSSI"); | ||||||
|         subghz_frequency_analyzer_draw_rssi(canvas, model->rssi, 20, 64); |         subghz_frequency_analyzer_draw_rssi(canvas, model->rssi, 20, 64); | ||||||
| 
 | 
 | ||||||
|  | |||||||
| @ -29,6 +29,7 @@ typedef struct { | |||||||
|     uint8_t ind_sin; |     uint8_t ind_sin; | ||||||
|     SubGhzReadRAWStatus status; |     SubGhzReadRAWStatus status; | ||||||
|     float raw_threshold_rssi; |     float raw_threshold_rssi; | ||||||
|  |     SubGhzRadioDeviceType device_type; | ||||||
| } SubGhzReadRAWModel; | } SubGhzReadRAWModel; | ||||||
| 
 | 
 | ||||||
| void subghz_read_raw_set_callback( | void subghz_read_raw_set_callback( | ||||||
| @ -56,6 +57,14 @@ void subghz_read_raw_add_data_statusbar( | |||||||
|         true); |         true); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | void subghz_read_raw_set_radio_device_type( | ||||||
|  |     SubGhzReadRAW* instance, | ||||||
|  |     SubGhzRadioDeviceType device_type) { | ||||||
|  |     furi_assert(instance); | ||||||
|  |     with_view_model( | ||||||
|  |         instance->view, SubGhzReadRAWModel * model, { model->device_type = device_type; }, true); | ||||||
|  | } | ||||||
|  | 
 | ||||||
| void subghz_read_raw_add_data_rssi(SubGhzReadRAW* instance, float rssi, bool trace) { | void subghz_read_raw_add_data_rssi(SubGhzReadRAW* instance, float rssi, bool trace) { | ||||||
|     furi_assert(instance); |     furi_assert(instance); | ||||||
|     uint8_t u_rssi = 0; |     uint8_t u_rssi = 0; | ||||||
| @ -279,11 +288,16 @@ void subghz_read_raw_draw(Canvas* canvas, SubGhzReadRAWModel* model) { | |||||||
|     uint8_t graphics_mode = 1; |     uint8_t graphics_mode = 1; | ||||||
|     canvas_set_color(canvas, ColorBlack); |     canvas_set_color(canvas, ColorBlack); | ||||||
|     canvas_set_font(canvas, FontSecondary); |     canvas_set_font(canvas, FontSecondary); | ||||||
|     canvas_draw_str(canvas, 5, 7, furi_string_get_cstr(model->frequency_str)); |     canvas_draw_str(canvas, 0, 9, furi_string_get_cstr(model->frequency_str)); | ||||||
|     canvas_draw_str(canvas, 40, 7, furi_string_get_cstr(model->preset_str)); |     canvas_draw_str(canvas, 35, 9, furi_string_get_cstr(model->preset_str)); | ||||||
|     canvas_draw_str_aligned( |     canvas_draw_str_aligned( | ||||||
|         canvas, 126, 0, AlignRight, AlignTop, furi_string_get_cstr(model->sample_write)); |         canvas, 106, 2, AlignRight, AlignTop, furi_string_get_cstr(model->sample_write)); | ||||||
| 
 | 
 | ||||||
|  |     if(model->device_type == SubGhzRadioDeviceTypeInternal) { | ||||||
|  |         canvas_draw_icon(canvas, 108, 0, &I_Internal_antenna_20x12); | ||||||
|  |     } else { | ||||||
|  |         canvas_draw_icon(canvas, 108, 0, &I_External_antenna_20x12); | ||||||
|  |     } | ||||||
|     canvas_draw_line(canvas, 0, 14, 115, 14); |     canvas_draw_line(canvas, 0, 14, 115, 14); | ||||||
|     canvas_draw_line(canvas, 0, 48, 115, 48); |     canvas_draw_line(canvas, 0, 48, 115, 48); | ||||||
|     canvas_draw_line(canvas, 115, 14, 115, 48); |     canvas_draw_line(canvas, 115, 14, 115, 48); | ||||||
|  | |||||||
| @ -1,6 +1,7 @@ | |||||||
| #pragma once | #pragma once | ||||||
| 
 | 
 | ||||||
| #include <gui/view.h> | #include <gui/view.h> | ||||||
|  | #include "../helpers/subghz_types.h" | ||||||
| #include "../helpers/subghz_custom_event.h" | #include "../helpers/subghz_custom_event.h" | ||||||
| 
 | 
 | ||||||
| #define SUBGHZ_RAW_THRESHOLD_MIN -90.0f | #define SUBGHZ_RAW_THRESHOLD_MIN -90.0f | ||||||
| @ -36,6 +37,10 @@ void subghz_read_raw_add_data_statusbar( | |||||||
|     const char* frequency_str, |     const char* frequency_str, | ||||||
|     const char* preset_str); |     const char* preset_str); | ||||||
| 
 | 
 | ||||||
|  | void subghz_read_raw_set_radio_device_type( | ||||||
|  |     SubGhzReadRAW* instance, | ||||||
|  |     SubGhzRadioDeviceType device_type); | ||||||
|  | 
 | ||||||
| void subghz_read_raw_update_sample_write(SubGhzReadRAW* instance, size_t sample); | void subghz_read_raw_update_sample_write(SubGhzReadRAW* instance, size_t sample); | ||||||
| 
 | 
 | ||||||
| void subghz_read_raw_stop_send(SubGhzReadRAW* instance); | void subghz_read_raw_stop_send(SubGhzReadRAW* instance); | ||||||
|  | |||||||
| @ -1,6 +1,7 @@ | |||||||
| #include "subghz_test_carrier.h" | #include "subghz_test_carrier.h" | ||||||
| #include "../subghz_i.h" | #include "../subghz_i.h" | ||||||
| #include "../helpers/subghz_testing.h" | #include "../helpers/subghz_testing.h" | ||||||
|  | #include <lib/subghz/devices/cc1101_configs.h> | ||||||
| 
 | 
 | ||||||
| #include <math.h> | #include <math.h> | ||||||
| #include <furi.h> | #include <furi.h> | ||||||
| @ -138,7 +139,7 @@ void subghz_test_carrier_enter(void* context) { | |||||||
|     SubGhzTestCarrier* subghz_test_carrier = context; |     SubGhzTestCarrier* subghz_test_carrier = context; | ||||||
| 
 | 
 | ||||||
|     furi_hal_subghz_reset(); |     furi_hal_subghz_reset(); | ||||||
|     furi_hal_subghz_load_preset(FuriHalSubGhzPresetOok650Async); |     furi_hal_subghz_load_custom_preset(subghz_device_cc1101_preset_ook_650khz_async_regs); | ||||||
| 
 | 
 | ||||||
|     furi_hal_gpio_init(&gpio_cc1101_g0, GpioModeInput, GpioPullNo, GpioSpeedLow); |     furi_hal_gpio_init(&gpio_cc1101_g0, GpioModeInput, GpioPullNo, GpioSpeedLow); | ||||||
| 
 | 
 | ||||||
|  | |||||||
| @ -1,6 +1,7 @@ | |||||||
| #include "subghz_test_packet.h" | #include "subghz_test_packet.h" | ||||||
| #include "../subghz_i.h" | #include "../subghz_i.h" | ||||||
| #include "../helpers/subghz_testing.h" | #include "../helpers/subghz_testing.h" | ||||||
|  | #include <lib/subghz/devices/cc1101_configs.h> | ||||||
| 
 | 
 | ||||||
| #include <math.h> | #include <math.h> | ||||||
| #include <furi.h> | #include <furi.h> | ||||||
| @ -194,7 +195,7 @@ void subghz_test_packet_enter(void* context) { | |||||||
|     SubGhzTestPacket* instance = context; |     SubGhzTestPacket* instance = context; | ||||||
| 
 | 
 | ||||||
|     furi_hal_subghz_reset(); |     furi_hal_subghz_reset(); | ||||||
|     furi_hal_subghz_load_preset(FuriHalSubGhzPresetOok650Async); |     furi_hal_subghz_load_custom_preset(subghz_device_cc1101_preset_ook_650khz_async_regs); | ||||||
| 
 | 
 | ||||||
|     with_view_model( |     with_view_model( | ||||||
|         instance->view, |         instance->view, | ||||||
|  | |||||||
| @ -1,6 +1,7 @@ | |||||||
| #include "subghz_test_static.h" | #include "subghz_test_static.h" | ||||||
| #include "../subghz_i.h" | #include "../subghz_i.h" | ||||||
| #include "../helpers/subghz_testing.h" | #include "../helpers/subghz_testing.h" | ||||||
|  | #include <lib/subghz/devices/cc1101_configs.h> | ||||||
| 
 | 
 | ||||||
| #include <math.h> | #include <math.h> | ||||||
| #include <furi.h> | #include <furi.h> | ||||||
| @ -141,7 +142,7 @@ void subghz_test_static_enter(void* context) { | |||||||
|     SubGhzTestStatic* instance = context; |     SubGhzTestStatic* instance = context; | ||||||
| 
 | 
 | ||||||
|     furi_hal_subghz_reset(); |     furi_hal_subghz_reset(); | ||||||
|     furi_hal_subghz_load_preset(FuriHalSubGhzPresetOok650Async); |     furi_hal_subghz_load_custom_preset(subghz_device_cc1101_preset_ook_650khz_async_regs); | ||||||
| 
 | 
 | ||||||
|     furi_hal_gpio_init(&gpio_cc1101_g0, GpioModeOutputPushPull, GpioPullNo, GpioSpeedLow); |     furi_hal_gpio_init(&gpio_cc1101_g0, GpioModeOutputPushPull, GpioPullNo, GpioSpeedLow); | ||||||
|     furi_hal_gpio_write(&gpio_cc1101_g0, false); |     furi_hal_gpio_write(&gpio_cc1101_g0, false); | ||||||
|  | |||||||
| @ -15,6 +15,7 @@ typedef struct { | |||||||
|     FuriString* preset_str; |     FuriString* preset_str; | ||||||
|     FuriString* key_str; |     FuriString* key_str; | ||||||
|     bool show_button; |     bool show_button; | ||||||
|  |     SubGhzRadioDeviceType device_type; | ||||||
| } SubGhzViewTransmitterModel; | } SubGhzViewTransmitterModel; | ||||||
| 
 | 
 | ||||||
| void subghz_view_transmitter_set_callback( | void subghz_view_transmitter_set_callback( | ||||||
| @ -46,6 +47,17 @@ void subghz_view_transmitter_add_data_to_show( | |||||||
|         true); |         true); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | void subghz_view_transmitter_set_radio_device_type( | ||||||
|  |     SubGhzViewTransmitter* subghz_transmitter, | ||||||
|  |     SubGhzRadioDeviceType device_type) { | ||||||
|  |     furi_assert(subghz_transmitter); | ||||||
|  |     with_view_model( | ||||||
|  |         subghz_transmitter->view, | ||||||
|  |         SubGhzViewTransmitterModel * model, | ||||||
|  |         { model->device_type = device_type; }, | ||||||
|  |         true); | ||||||
|  | } | ||||||
|  | 
 | ||||||
| static void subghz_view_transmitter_button_right(Canvas* canvas, const char* str) { | static void subghz_view_transmitter_button_right(Canvas* canvas, const char* str) { | ||||||
|     const uint8_t button_height = 12; |     const uint8_t button_height = 12; | ||||||
|     const uint8_t vertical_offset = 3; |     const uint8_t vertical_offset = 3; | ||||||
| @ -56,7 +68,7 @@ static void subghz_view_transmitter_button_right(Canvas* canvas, const char* str | |||||||
|     const uint8_t icon_width_with_offset = icon_get_width(icon) + icon_offset; |     const uint8_t icon_width_with_offset = icon_get_width(icon) + icon_offset; | ||||||
|     const uint8_t button_width = string_width + horizontal_offset * 2 + icon_width_with_offset; |     const uint8_t button_width = string_width + horizontal_offset * 2 + icon_width_with_offset; | ||||||
| 
 | 
 | ||||||
|     const uint8_t x = (canvas_width(canvas) - button_width) / 2 + 40; |     const uint8_t x = (canvas_width(canvas) - button_width) / 2 + 44; | ||||||
|     const uint8_t y = canvas_height(canvas); |     const uint8_t y = canvas_height(canvas); | ||||||
| 
 | 
 | ||||||
|     canvas_draw_box(canvas, x, y - button_height, button_width, button_height); |     canvas_draw_box(canvas, x, y - button_height, button_width, button_height); | ||||||
| @ -88,7 +100,14 @@ void subghz_view_transmitter_draw(Canvas* canvas, SubGhzViewTransmitterModel* mo | |||||||
|         canvas, 0, 0, AlignLeft, AlignTop, furi_string_get_cstr(model->key_str)); |         canvas, 0, 0, AlignLeft, AlignTop, furi_string_get_cstr(model->key_str)); | ||||||
|     canvas_draw_str(canvas, 78, 7, furi_string_get_cstr(model->frequency_str)); |     canvas_draw_str(canvas, 78, 7, furi_string_get_cstr(model->frequency_str)); | ||||||
|     canvas_draw_str(canvas, 113, 7, furi_string_get_cstr(model->preset_str)); |     canvas_draw_str(canvas, 113, 7, furi_string_get_cstr(model->preset_str)); | ||||||
|     if(model->show_button) subghz_view_transmitter_button_right(canvas, "Send"); |     if(model->show_button) { | ||||||
|  |         if(model->device_type == SubGhzRadioDeviceTypeInternal) { | ||||||
|  |             canvas_draw_icon(canvas, 108, 39, &I_Internal_antenna_20x12); | ||||||
|  |         } else { | ||||||
|  |             canvas_draw_icon(canvas, 108, 39, &I_External_antenna_20x12); | ||||||
|  |         } | ||||||
|  |         subghz_view_transmitter_button_right(canvas, "Send"); | ||||||
|  |     } | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| bool subghz_view_transmitter_input(InputEvent* event, void* context) { | bool subghz_view_transmitter_input(InputEvent* event, void* context) { | ||||||
|  | |||||||
| @ -1,6 +1,7 @@ | |||||||
| #pragma once | #pragma once | ||||||
| 
 | 
 | ||||||
| #include <gui/view.h> | #include <gui/view.h> | ||||||
|  | #include "../helpers/subghz_types.h" | ||||||
| #include "../helpers/subghz_custom_event.h" | #include "../helpers/subghz_custom_event.h" | ||||||
| 
 | 
 | ||||||
| typedef struct SubGhzViewTransmitter SubGhzViewTransmitter; | typedef struct SubGhzViewTransmitter SubGhzViewTransmitter; | ||||||
| @ -12,6 +13,10 @@ void subghz_view_transmitter_set_callback( | |||||||
|     SubGhzViewTransmitterCallback callback, |     SubGhzViewTransmitterCallback callback, | ||||||
|     void* context); |     void* context); | ||||||
| 
 | 
 | ||||||
|  | void subghz_view_transmitter_set_radio_device_type( | ||||||
|  |     SubGhzViewTransmitter* subghz_transmitter, | ||||||
|  |     SubGhzRadioDeviceType device_type); | ||||||
|  | 
 | ||||||
| SubGhzViewTransmitter* subghz_view_transmitter_alloc(); | SubGhzViewTransmitter* subghz_view_transmitter_alloc(); | ||||||
| 
 | 
 | ||||||
| void subghz_view_transmitter_free(SubGhzViewTransmitter* subghz_transmitter); | void subghz_view_transmitter_free(SubGhzViewTransmitter* subghz_transmitter); | ||||||
|  | |||||||
							
								
								
									
										
											BIN
										
									
								
								assets/icons/SubGhz/External_antenna_20x12.png
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										
											BIN
										
									
								
								assets/icons/SubGhz/External_antenna_20x12.png
									
									
									
									
									
										Normal file
									
								
							
										
											Binary file not shown.
										
									
								
							| After Width: | Height: | Size: 990 B | 
							
								
								
									
										
											BIN
										
									
								
								assets/icons/SubGhz/Internal_antenna_20x12.png
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										
											BIN
										
									
								
								assets/icons/SubGhz/Internal_antenna_20x12.png
									
									
									
									
									
										Normal file
									
								
							
										
											Binary file not shown.
										
									
								
							| After Width: | Height: | Size: 994 B | 
										
											Binary file not shown.
										
									
								
							| Before Width: | Height: | Size: 1.7 KiB | 
							
								
								
									
										
											BIN
										
									
								
								assets/icons/SubGhz/Scanning_short_96x52.png
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										
											BIN
										
									
								
								assets/icons/SubGhz/Scanning_short_96x52.png
									
									
									
									
									
										Normal file
									
								
							
										
											Binary file not shown.
										
									
								
							| After Width: | Height: | Size: 1.4 KiB | 
| @ -78,9 +78,9 @@ The system will take over any given peripheral only when the respective feature | |||||||
| | ADC           |           |                                       | | | ADC           |           |                                       | | ||||||
| | QUADSPI       |           |                                       | | | QUADSPI       |           |                                       | | ||||||
| | TIM1          | yes       | subghz, lfrfid, nfc, infrared, etc... | | | TIM1          | yes       | subghz, lfrfid, nfc, infrared, etc... | | ||||||
| | TIM2          | yes       | --                                    | | | TIM2          | yes       | subghz, infrared, etc...              | | ||||||
| | TIM16         | yes       | speaker                               | | | TIM16         | yes       | speaker                               | | ||||||
| | TIM17         |           |                                       | | | TIM17         | yes       | cc1101_ext                            | | ||||||
| | LPTIM1        | yes       | tickless idle timer                   | | | LPTIM1        | yes       | tickless idle timer                   | | ||||||
| | LPTIM2        | yes       | pwm                                   | | | LPTIM2        | yes       | pwm                                   | | ||||||
| | SAI1          |           |                                       | | | SAI1          |           |                                       | | ||||||
| @ -104,10 +104,10 @@ Below is the list of DMA channels and their usage by the system. | |||||||
| |  --   | 5         |           |                           | | |  --   | 5         |           |                           | | ||||||
| |  --   | 6         |           |                           | | |  --   | 6         |           |                           | | ||||||
| |  --   | 7         |           |                           | | |  --   | 7         |           |                           | | ||||||
| | DMA2  | 1         | yes       | infrared, lfrfid, subghz  | | | DMA2  | 1         | yes       | infrared, lfrfid, subghz, | | ||||||
| |  --   | 2         | yes       | --                        | | |  --   | 2         | yes       | --                        | | ||||||
| |  --   | 3         | yes       | SPI                       | | |  --   | 3         | yes       | cc1101_ext                | | ||||||
| |  --   | 4         | yes       | SPI                       | | |  --   | 4         | yes       | cc1101_ext                | | ||||||
| |  --   | 5         |           |                           | | |  --   | 5         | yes       | cc1101_ext                | | ||||||
| |  --   | 6         |           |                           | | |  --   | 6         | yes       | SPI                       | | ||||||
| |  --   | 7         |           |                           | | |  --   | 7         | yes       | SPI                       | | ||||||
|  | |||||||
| @ -1,5 +1,5 @@ | |||||||
| entry,status,name,type,params | entry,status,name,type,params | ||||||
| Version,+,31.3,, | Version,+,32.0,, | ||||||
| Header,+,applications/services/bt/bt_service/bt.h,, | Header,+,applications/services/bt/bt_service/bt.h,, | ||||||
| Header,+,applications/services/cli/cli.h,, | Header,+,applications/services/cli/cli.h,, | ||||||
| Header,+,applications/services/cli/cli_vcp.h,, | Header,+,applications/services/cli/cli_vcp.h,, | ||||||
| @ -283,6 +283,7 @@ Function,-,LL_mDelay,void,uint32_t | |||||||
| Function,-,SystemCoreClockUpdate,void, | Function,-,SystemCoreClockUpdate,void, | ||||||
| Function,-,SystemInit,void, | Function,-,SystemInit,void, | ||||||
| Function,-,_Exit,void,int | Function,-,_Exit,void,int | ||||||
|  | Function,+,__aeabi_uldivmod,void*,"uint64_t, uint64_t" | ||||||
| Function,-,__assert,void,"const char*, int, const char*" | Function,-,__assert,void,"const char*, int, const char*" | ||||||
| Function,+,__assert_func,void,"const char*, int, const char*, const char*" | Function,+,__assert_func,void,"const char*, int, const char*, const char*" | ||||||
| Function,+,__clear_cache,void,"void*, void*" | Function,+,__clear_cache,void,"void*, void*" | ||||||
|  | |||||||
| 
 | 
| @ -1,5 +1,5 @@ | |||||||
| entry,status,name,type,params | entry,status,name,type,params | ||||||
| Version,+,31.3,, | Version,+,32.0,, | ||||||
| Header,+,applications/services/bt/bt_service/bt.h,, | Header,+,applications/services/bt/bt_service/bt.h,, | ||||||
| Header,+,applications/services/cli/cli.h,, | Header,+,applications/services/cli/cli.h,, | ||||||
| Header,+,applications/services/cli/cli_vcp.h,, | Header,+,applications/services/cli/cli_vcp.h,, | ||||||
| @ -56,7 +56,6 @@ Header,+,firmware/targets/f7/furi_hal/furi_hal_rfid.h,, | |||||||
| Header,+,firmware/targets/f7/furi_hal/furi_hal_spi_config.h,, | Header,+,firmware/targets/f7/furi_hal/furi_hal_spi_config.h,, | ||||||
| Header,+,firmware/targets/f7/furi_hal/furi_hal_spi_types.h,, | Header,+,firmware/targets/f7/furi_hal/furi_hal_spi_types.h,, | ||||||
| Header,+,firmware/targets/f7/furi_hal/furi_hal_subghz.h,, | Header,+,firmware/targets/f7/furi_hal/furi_hal_subghz.h,, | ||||||
| Header,+,firmware/targets/f7/furi_hal/furi_hal_subghz_configs.h,, |  | ||||||
| Header,+,firmware/targets/f7/furi_hal/furi_hal_target_hw.h,, | Header,+,firmware/targets/f7/furi_hal/furi_hal_target_hw.h,, | ||||||
| Header,+,firmware/targets/f7/furi_hal/furi_hal_uart.h,, | Header,+,firmware/targets/f7/furi_hal/furi_hal_uart.h,, | ||||||
| Header,+,firmware/targets/f7/furi_hal/furi_hal_usb_cdc.h,, | Header,+,firmware/targets/f7/furi_hal/furi_hal_usb_cdc.h,, | ||||||
| @ -186,6 +185,7 @@ Header,+,lib/subghz/blocks/decoder.h,, | |||||||
| Header,+,lib/subghz/blocks/encoder.h,, | Header,+,lib/subghz/blocks/encoder.h,, | ||||||
| Header,+,lib/subghz/blocks/generic.h,, | Header,+,lib/subghz/blocks/generic.h,, | ||||||
| Header,+,lib/subghz/blocks/math.h,, | Header,+,lib/subghz/blocks/math.h,, | ||||||
|  | Header,+,lib/subghz/devices/cc1101_configs.h,, | ||||||
| Header,+,lib/subghz/environment.h,, | Header,+,lib/subghz/environment.h,, | ||||||
| Header,+,lib/subghz/protocols/raw.h,, | Header,+,lib/subghz/protocols/raw.h,, | ||||||
| Header,+,lib/subghz/receiver.h,, | Header,+,lib/subghz/receiver.h,, | ||||||
| @ -317,6 +317,7 @@ Function,-,LL_mDelay,void,uint32_t | |||||||
| Function,-,SystemCoreClockUpdate,void, | Function,-,SystemCoreClockUpdate,void, | ||||||
| Function,-,SystemInit,void, | Function,-,SystemInit,void, | ||||||
| Function,-,_Exit,void,int | Function,-,_Exit,void,int | ||||||
|  | Function,+,__aeabi_uldivmod,void*,"uint64_t, uint64_t" | ||||||
| Function,-,__assert,void,"const char*, int, const char*" | Function,-,__assert,void,"const char*, int, const char*" | ||||||
| Function,+,__assert_func,void,"const char*, int, const char*, const char*" | Function,+,__assert_func,void,"const char*, int, const char*, const char*" | ||||||
| Function,+,__clear_cache,void,"void*, void*" | Function,+,__clear_cache,void,"void*, void*" | ||||||
| @ -657,26 +658,6 @@ Function,+,canvas_width,uint8_t,const Canvas* | |||||||
| Function,-,cbrt,double,double | Function,-,cbrt,double,double | ||||||
| Function,-,cbrtf,float,float | Function,-,cbrtf,float,float | ||||||
| Function,-,cbrtl,long double,long double | Function,-,cbrtl,long double,long double | ||||||
| Function,+,cc1101_calibrate,void,FuriHalSpiBusHandle* |  | ||||||
| Function,+,cc1101_flush_rx,void,FuriHalSpiBusHandle* |  | ||||||
| Function,+,cc1101_flush_tx,void,FuriHalSpiBusHandle* |  | ||||||
| Function,-,cc1101_get_partnumber,uint8_t,FuriHalSpiBusHandle* |  | ||||||
| Function,+,cc1101_get_rssi,uint8_t,FuriHalSpiBusHandle* |  | ||||||
| Function,+,cc1101_get_status,CC1101Status,FuriHalSpiBusHandle* |  | ||||||
| Function,-,cc1101_get_version,uint8_t,FuriHalSpiBusHandle* |  | ||||||
| Function,+,cc1101_read_fifo,uint8_t,"FuriHalSpiBusHandle*, uint8_t*, uint8_t*" |  | ||||||
| Function,+,cc1101_read_reg,CC1101Status,"FuriHalSpiBusHandle*, uint8_t, uint8_t*" |  | ||||||
| Function,+,cc1101_reset,void,FuriHalSpiBusHandle* |  | ||||||
| Function,+,cc1101_set_frequency,uint32_t,"FuriHalSpiBusHandle*, uint32_t" |  | ||||||
| Function,-,cc1101_set_intermediate_frequency,uint32_t,"FuriHalSpiBusHandle*, uint32_t" |  | ||||||
| Function,+,cc1101_set_pa_table,void,"FuriHalSpiBusHandle*, const uint8_t[8]" |  | ||||||
| Function,+,cc1101_shutdown,void,FuriHalSpiBusHandle* |  | ||||||
| Function,+,cc1101_strobe,CC1101Status,"FuriHalSpiBusHandle*, uint8_t" |  | ||||||
| Function,+,cc1101_switch_to_idle,void,FuriHalSpiBusHandle* |  | ||||||
| Function,+,cc1101_switch_to_rx,void,FuriHalSpiBusHandle* |  | ||||||
| Function,+,cc1101_switch_to_tx,void,FuriHalSpiBusHandle* |  | ||||||
| Function,+,cc1101_write_fifo,uint8_t,"FuriHalSpiBusHandle*, const uint8_t*, uint8_t" |  | ||||||
| Function,+,cc1101_write_reg,CC1101Status,"FuriHalSpiBusHandle*, uint8_t, uint8_t" |  | ||||||
| Function,-,ceil,double,double | Function,-,ceil,double,double | ||||||
| Function,-,ceilf,float,float | Function,-,ceilf,float,float | ||||||
| Function,-,ceill,long double,long double | Function,-,ceill,long double,long double | ||||||
| @ -1383,6 +1364,7 @@ Function,+,furi_hal_spi_release,void,FuriHalSpiBusHandle* | |||||||
| Function,-,furi_hal_subghz_dump_state,void, | Function,-,furi_hal_subghz_dump_state,void, | ||||||
| Function,+,furi_hal_subghz_flush_rx,void, | Function,+,furi_hal_subghz_flush_rx,void, | ||||||
| Function,+,furi_hal_subghz_flush_tx,void, | Function,+,furi_hal_subghz_flush_tx,void, | ||||||
|  | Function,+,furi_hal_subghz_get_data_gpio,const GpioPin*, | ||||||
| Function,+,furi_hal_subghz_get_lqi,uint8_t, | Function,+,furi_hal_subghz_get_lqi,uint8_t, | ||||||
| Function,+,furi_hal_subghz_get_rssi,float, | Function,+,furi_hal_subghz_get_rssi,float, | ||||||
| Function,+,furi_hal_subghz_idle,void, | Function,+,furi_hal_subghz_idle,void, | ||||||
| @ -1390,10 +1372,9 @@ Function,-,furi_hal_subghz_init,void, | |||||||
| Function,+,furi_hal_subghz_is_async_tx_complete,_Bool, | Function,+,furi_hal_subghz_is_async_tx_complete,_Bool, | ||||||
| Function,+,furi_hal_subghz_is_frequency_valid,_Bool,uint32_t | Function,+,furi_hal_subghz_is_frequency_valid,_Bool,uint32_t | ||||||
| Function,+,furi_hal_subghz_is_rx_data_crc_valid,_Bool, | Function,+,furi_hal_subghz_is_rx_data_crc_valid,_Bool, | ||||||
| Function,+,furi_hal_subghz_load_custom_preset,void,uint8_t* | Function,+,furi_hal_subghz_load_custom_preset,void,const uint8_t* | ||||||
| Function,+,furi_hal_subghz_load_patable,void,const uint8_t[8] | Function,+,furi_hal_subghz_load_patable,void,const uint8_t[8] | ||||||
| Function,+,furi_hal_subghz_load_preset,void,FuriHalSubGhzPreset | Function,+,furi_hal_subghz_load_registers,void,const uint8_t* | ||||||
| Function,+,furi_hal_subghz_load_registers,void,uint8_t* |  | ||||||
| Function,+,furi_hal_subghz_read_packet,void,"uint8_t*, uint8_t*" | Function,+,furi_hal_subghz_read_packet,void,"uint8_t*, uint8_t*" | ||||||
| Function,+,furi_hal_subghz_reset,void, | Function,+,furi_hal_subghz_reset,void, | ||||||
| Function,+,furi_hal_subghz_rx,void, | Function,+,furi_hal_subghz_rx,void, | ||||||
| @ -1401,7 +1382,7 @@ Function,+,furi_hal_subghz_rx_pipe_not_empty,_Bool, | |||||||
| Function,+,furi_hal_subghz_set_async_mirror_pin,void,const GpioPin* | Function,+,furi_hal_subghz_set_async_mirror_pin,void,const GpioPin* | ||||||
| Function,+,furi_hal_subghz_set_frequency,uint32_t,uint32_t | Function,+,furi_hal_subghz_set_frequency,uint32_t,uint32_t | ||||||
| Function,+,furi_hal_subghz_set_frequency_and_path,uint32_t,uint32_t | Function,+,furi_hal_subghz_set_frequency_and_path,uint32_t,uint32_t | ||||||
| Function,+,furi_hal_subghz_set_path,void,FuriHalSubGhzPath | Function,-,furi_hal_subghz_set_path,void,FuriHalSubGhzPath | ||||||
| Function,-,furi_hal_subghz_shutdown,void, | Function,-,furi_hal_subghz_shutdown,void, | ||||||
| Function,+,furi_hal_subghz_sleep,void, | Function,+,furi_hal_subghz_sleep,void, | ||||||
| Function,+,furi_hal_subghz_start_async_rx,void,"FuriHalSubGhzCaptureCallback, void*" | Function,+,furi_hal_subghz_start_async_rx,void,"FuriHalSubGhzCaptureCallback, void*" | ||||||
| @ -2686,6 +2667,36 @@ Function,+,subghz_block_generic_deserialize,SubGhzProtocolStatus,"SubGhzBlockGen | |||||||
| Function,+,subghz_block_generic_deserialize_check_count_bit,SubGhzProtocolStatus,"SubGhzBlockGeneric*, FlipperFormat*, uint16_t" | Function,+,subghz_block_generic_deserialize_check_count_bit,SubGhzProtocolStatus,"SubGhzBlockGeneric*, FlipperFormat*, uint16_t" | ||||||
| Function,+,subghz_block_generic_get_preset_name,void,"const char*, FuriString*" | Function,+,subghz_block_generic_get_preset_name,void,"const char*, FuriString*" | ||||||
| Function,+,subghz_block_generic_serialize,SubGhzProtocolStatus,"SubGhzBlockGeneric*, FlipperFormat*, SubGhzRadioPreset*" | Function,+,subghz_block_generic_serialize,SubGhzProtocolStatus,"SubGhzBlockGeneric*, FlipperFormat*, SubGhzRadioPreset*" | ||||||
|  | Function,+,subghz_devices_begin,_Bool,const SubGhzDevice* | ||||||
|  | Function,+,subghz_devices_deinit,void, | ||||||
|  | Function,+,subghz_devices_end,void,const SubGhzDevice* | ||||||
|  | Function,+,subghz_devices_flush_rx,void,const SubGhzDevice* | ||||||
|  | Function,+,subghz_devices_flush_tx,void,const SubGhzDevice* | ||||||
|  | Function,+,subghz_devices_get_by_name,const SubGhzDevice*,const char* | ||||||
|  | Function,+,subghz_devices_get_data_gpio,const GpioPin*,const SubGhzDevice* | ||||||
|  | Function,+,subghz_devices_get_lqi,uint8_t,const SubGhzDevice* | ||||||
|  | Function,+,subghz_devices_get_name,const char*,const SubGhzDevice* | ||||||
|  | Function,+,subghz_devices_get_rssi,float,const SubGhzDevice* | ||||||
|  | Function,+,subghz_devices_idle,void,const SubGhzDevice* | ||||||
|  | Function,+,subghz_devices_init,void, | ||||||
|  | Function,+,subghz_devices_is_async_complete_tx,_Bool,const SubGhzDevice* | ||||||
|  | Function,+,subghz_devices_is_connect,_Bool,const SubGhzDevice* | ||||||
|  | Function,+,subghz_devices_is_frequency_valid,_Bool,"const SubGhzDevice*, uint32_t" | ||||||
|  | Function,+,subghz_devices_is_rx_data_crc_valid,_Bool,const SubGhzDevice* | ||||||
|  | Function,+,subghz_devices_load_preset,void,"const SubGhzDevice*, FuriHalSubGhzPreset, uint8_t*" | ||||||
|  | Function,+,subghz_devices_read_packet,void,"const SubGhzDevice*, uint8_t*, uint8_t*" | ||||||
|  | Function,+,subghz_devices_reset,void,const SubGhzDevice* | ||||||
|  | Function,+,subghz_devices_rx_pipe_not_empty,_Bool,const SubGhzDevice* | ||||||
|  | Function,+,subghz_devices_set_async_mirror_pin,void,"const SubGhzDevice*, const GpioPin*" | ||||||
|  | Function,+,subghz_devices_set_frequency,uint32_t,"const SubGhzDevice*, uint32_t" | ||||||
|  | Function,+,subghz_devices_set_rx,void,const SubGhzDevice* | ||||||
|  | Function,+,subghz_devices_set_tx,_Bool,const SubGhzDevice* | ||||||
|  | Function,+,subghz_devices_sleep,void,const SubGhzDevice* | ||||||
|  | Function,+,subghz_devices_start_async_rx,void,"const SubGhzDevice*, void*, void*" | ||||||
|  | Function,+,subghz_devices_start_async_tx,_Bool,"const SubGhzDevice*, void*, void*" | ||||||
|  | Function,+,subghz_devices_stop_async_rx,void,const SubGhzDevice* | ||||||
|  | Function,+,subghz_devices_stop_async_tx,void,const SubGhzDevice* | ||||||
|  | Function,+,subghz_devices_write_packet,void,"const SubGhzDevice*, const uint8_t*, uint8_t" | ||||||
| Function,+,subghz_environment_alloc,SubGhzEnvironment*, | Function,+,subghz_environment_alloc,SubGhzEnvironment*, | ||||||
| Function,+,subghz_environment_free,void,SubGhzEnvironment* | Function,+,subghz_environment_free,void,SubGhzEnvironment* | ||||||
| Function,+,subghz_environment_get_alutech_at_4n_rainbow_table_file_name,const char*,SubGhzEnvironment* | Function,+,subghz_environment_get_alutech_at_4n_rainbow_table_file_name,const char*,SubGhzEnvironment* | ||||||
| @ -2744,7 +2755,7 @@ Function,+,subghz_protocol_encoder_raw_free,void,void* | |||||||
| Function,+,subghz_protocol_encoder_raw_stop,void,void* | Function,+,subghz_protocol_encoder_raw_stop,void,void* | ||||||
| Function,+,subghz_protocol_encoder_raw_yield,LevelDuration,void* | Function,+,subghz_protocol_encoder_raw_yield,LevelDuration,void* | ||||||
| Function,+,subghz_protocol_raw_file_encoder_worker_set_callback_end,void,"SubGhzProtocolEncoderRAW*, SubGhzProtocolEncoderRAWCallbackEnd, void*" | Function,+,subghz_protocol_raw_file_encoder_worker_set_callback_end,void,"SubGhzProtocolEncoderRAW*, SubGhzProtocolEncoderRAWCallbackEnd, void*" | ||||||
| Function,+,subghz_protocol_raw_gen_fff_data,void,"FlipperFormat*, const char*" | Function,+,subghz_protocol_raw_gen_fff_data,void,"FlipperFormat*, const char*, const char*" | ||||||
| Function,+,subghz_protocol_raw_get_sample_write,size_t,SubGhzProtocolDecoderRAW* | Function,+,subghz_protocol_raw_get_sample_write,size_t,SubGhzProtocolDecoderRAW* | ||||||
| Function,+,subghz_protocol_raw_save_to_file_init,_Bool,"SubGhzProtocolDecoderRAW*, const char*, SubGhzRadioPreset*" | Function,+,subghz_protocol_raw_save_to_file_init,_Bool,"SubGhzProtocolDecoderRAW*, const char*, SubGhzRadioPreset*" | ||||||
| Function,+,subghz_protocol_raw_save_to_file_pause,void,"SubGhzProtocolDecoderRAW*, _Bool" | Function,+,subghz_protocol_raw_save_to_file_pause,void,"SubGhzProtocolDecoderRAW*, _Bool" | ||||||
| @ -2788,7 +2799,7 @@ Function,+,subghz_tx_rx_worker_free,void,SubGhzTxRxWorker* | |||||||
| Function,+,subghz_tx_rx_worker_is_running,_Bool,SubGhzTxRxWorker* | Function,+,subghz_tx_rx_worker_is_running,_Bool,SubGhzTxRxWorker* | ||||||
| Function,+,subghz_tx_rx_worker_read,size_t,"SubGhzTxRxWorker*, uint8_t*, size_t" | Function,+,subghz_tx_rx_worker_read,size_t,"SubGhzTxRxWorker*, uint8_t*, size_t" | ||||||
| Function,+,subghz_tx_rx_worker_set_callback_have_read,void,"SubGhzTxRxWorker*, SubGhzTxRxWorkerCallbackHaveRead, void*" | Function,+,subghz_tx_rx_worker_set_callback_have_read,void,"SubGhzTxRxWorker*, SubGhzTxRxWorkerCallbackHaveRead, void*" | ||||||
| Function,+,subghz_tx_rx_worker_start,_Bool,"SubGhzTxRxWorker*, uint32_t" | Function,+,subghz_tx_rx_worker_start,_Bool,"SubGhzTxRxWorker*, const SubGhzDevice*, uint32_t" | ||||||
| Function,+,subghz_tx_rx_worker_stop,void,SubGhzTxRxWorker* | Function,+,subghz_tx_rx_worker_stop,void,SubGhzTxRxWorker* | ||||||
| Function,+,subghz_tx_rx_worker_write,_Bool,"SubGhzTxRxWorker*, uint8_t*, size_t" | Function,+,subghz_tx_rx_worker_write,_Bool,"SubGhzTxRxWorker*, uint8_t*, size_t" | ||||||
| Function,+,subghz_worker_alloc,SubGhzWorker*, | Function,+,subghz_worker_alloc,SubGhzWorker*, | ||||||
| @ -3389,6 +3400,12 @@ Variable,+,sequence_set_vibro_on,const NotificationSequence, | |||||||
| Variable,+,sequence_single_vibro,const NotificationSequence, | Variable,+,sequence_single_vibro,const NotificationSequence, | ||||||
| Variable,+,sequence_solid_yellow,const NotificationSequence, | Variable,+,sequence_solid_yellow,const NotificationSequence, | ||||||
| Variable,+,sequence_success,const NotificationSequence, | Variable,+,sequence_success,const NotificationSequence, | ||||||
|  | Variable,+,subghz_device_cc1101_preset_2fsk_dev2_38khz_async_regs,const uint8_t[], | ||||||
|  | Variable,+,subghz_device_cc1101_preset_2fsk_dev47_6khz_async_regs,const uint8_t[], | ||||||
|  | Variable,+,subghz_device_cc1101_preset_gfsk_9_99kb_async_regs,const uint8_t[], | ||||||
|  | Variable,+,subghz_device_cc1101_preset_msk_99_97kb_async_regs,const uint8_t[], | ||||||
|  | Variable,+,subghz_device_cc1101_preset_ook_270khz_async_regs,const uint8_t[], | ||||||
|  | Variable,+,subghz_device_cc1101_preset_ook_650khz_async_regs,const uint8_t[], | ||||||
| Variable,+,subghz_protocol_raw,const SubGhzProtocol, | Variable,+,subghz_protocol_raw,const SubGhzProtocol, | ||||||
| Variable,+,subghz_protocol_raw_decoder,const SubGhzProtocolDecoder, | Variable,+,subghz_protocol_raw_decoder,const SubGhzProtocolDecoder, | ||||||
| Variable,+,subghz_protocol_raw_encoder,const SubGhzProtocolEncoder, | Variable,+,subghz_protocol_raw_encoder,const SubGhzProtocolEncoder, | ||||||
|  | |||||||
| 
 | 
| @ -12,10 +12,10 @@ | |||||||
| #define TAG "FuriHalSpi" | #define TAG "FuriHalSpi" | ||||||
| 
 | 
 | ||||||
| #define SPI_DMA DMA2 | #define SPI_DMA DMA2 | ||||||
| #define SPI_DMA_RX_CHANNEL LL_DMA_CHANNEL_3 | #define SPI_DMA_RX_CHANNEL LL_DMA_CHANNEL_6 | ||||||
| #define SPI_DMA_TX_CHANNEL LL_DMA_CHANNEL_4 | #define SPI_DMA_TX_CHANNEL LL_DMA_CHANNEL_7 | ||||||
| #define SPI_DMA_RX_IRQ FuriHalInterruptIdDma2Ch3 | #define SPI_DMA_RX_IRQ FuriHalInterruptIdDma2Ch6 | ||||||
| #define SPI_DMA_TX_IRQ FuriHalInterruptIdDma2Ch4 | #define SPI_DMA_TX_IRQ FuriHalInterruptIdDma2Ch7 | ||||||
| #define SPI_DMA_RX_DEF SPI_DMA, SPI_DMA_RX_CHANNEL | #define SPI_DMA_RX_DEF SPI_DMA, SPI_DMA_RX_CHANNEL | ||||||
| #define SPI_DMA_TX_DEF SPI_DMA, SPI_DMA_TX_CHANNEL | #define SPI_DMA_TX_DEF SPI_DMA, SPI_DMA_TX_CHANNEL | ||||||
| 
 | 
 | ||||||
| @ -170,18 +170,18 @@ bool furi_hal_spi_bus_trx( | |||||||
| } | } | ||||||
| 
 | 
 | ||||||
| static void spi_dma_isr() { | static void spi_dma_isr() { | ||||||
| #if SPI_DMA_RX_CHANNEL == LL_DMA_CHANNEL_3 | #if SPI_DMA_RX_CHANNEL == LL_DMA_CHANNEL_6 | ||||||
|     if(LL_DMA_IsActiveFlag_TC3(SPI_DMA) && LL_DMA_IsEnabledIT_TC(SPI_DMA_RX_DEF)) { |     if(LL_DMA_IsActiveFlag_TC6(SPI_DMA) && LL_DMA_IsEnabledIT_TC(SPI_DMA_RX_DEF)) { | ||||||
|         LL_DMA_ClearFlag_TC3(SPI_DMA); |         LL_DMA_ClearFlag_TC6(SPI_DMA); | ||||||
|         furi_check(furi_semaphore_release(spi_dma_completed) == FuriStatusOk); |         furi_check(furi_semaphore_release(spi_dma_completed) == FuriStatusOk); | ||||||
|     } |     } | ||||||
| #else | #else | ||||||
| #error Update this code. Would you kindly? | #error Update this code. Would you kindly? | ||||||
| #endif | #endif | ||||||
| 
 | 
 | ||||||
| #if SPI_DMA_TX_CHANNEL == LL_DMA_CHANNEL_4 | #if SPI_DMA_TX_CHANNEL == LL_DMA_CHANNEL_7 | ||||||
|     if(LL_DMA_IsActiveFlag_TC4(SPI_DMA) && LL_DMA_IsEnabledIT_TC(SPI_DMA_TX_DEF)) { |     if(LL_DMA_IsActiveFlag_TC7(SPI_DMA) && LL_DMA_IsEnabledIT_TC(SPI_DMA_TX_DEF)) { | ||||||
|         LL_DMA_ClearFlag_TC4(SPI_DMA); |         LL_DMA_ClearFlag_TC7(SPI_DMA); | ||||||
|         furi_check(furi_semaphore_release(spi_dma_completed) == FuriStatusOk); |         furi_check(furi_semaphore_release(spi_dma_completed) == FuriStatusOk); | ||||||
|     } |     } | ||||||
| #else | #else | ||||||
| @ -241,8 +241,8 @@ bool furi_hal_spi_bus_trx_dma( | |||||||
|         dma_config.Priority = LL_DMA_PRIORITY_MEDIUM; |         dma_config.Priority = LL_DMA_PRIORITY_MEDIUM; | ||||||
|         LL_DMA_Init(SPI_DMA_TX_DEF, &dma_config); |         LL_DMA_Init(SPI_DMA_TX_DEF, &dma_config); | ||||||
| 
 | 
 | ||||||
| #if SPI_DMA_TX_CHANNEL == LL_DMA_CHANNEL_4 | #if SPI_DMA_TX_CHANNEL == LL_DMA_CHANNEL_7 | ||||||
|         LL_DMA_ClearFlag_TC4(SPI_DMA); |         LL_DMA_ClearFlag_TC7(SPI_DMA); | ||||||
| #else | #else | ||||||
| #error Update this code. Would you kindly? | #error Update this code. Would you kindly? | ||||||
| #endif | #endif | ||||||
| @ -315,8 +315,8 @@ bool furi_hal_spi_bus_trx_dma( | |||||||
|         dma_config.Priority = LL_DMA_PRIORITY_MEDIUM; |         dma_config.Priority = LL_DMA_PRIORITY_MEDIUM; | ||||||
|         LL_DMA_Init(SPI_DMA_RX_DEF, &dma_config); |         LL_DMA_Init(SPI_DMA_RX_DEF, &dma_config); | ||||||
| 
 | 
 | ||||||
| #if SPI_DMA_RX_CHANNEL == LL_DMA_CHANNEL_3 | #if SPI_DMA_RX_CHANNEL == LL_DMA_CHANNEL_6 | ||||||
|         LL_DMA_ClearFlag_TC3(SPI_DMA); |         LL_DMA_ClearFlag_TC6(SPI_DMA); | ||||||
| #else | #else | ||||||
| #error Update this code. Would you kindly? | #error Update this code. Would you kindly? | ||||||
| #endif | #endif | ||||||
|  | |||||||
| @ -1,6 +1,5 @@ | |||||||
| #include <furi_hal_subghz.h> | #include <furi_hal_subghz.h> | ||||||
| #include <furi_hal_subghz_configs.h> | #include <lib/subghz/devices/cc1101_configs.h> | ||||||
| 
 |  | ||||||
| #include <furi_hal_region.h> | #include <furi_hal_region.h> | ||||||
| #include <furi_hal_version.h> | #include <furi_hal_version.h> | ||||||
| #include <furi_hal_rtc.h> | #include <furi_hal_rtc.h> | ||||||
| @ -27,17 +26,36 @@ static uint32_t furi_hal_subghz_debug_gpio_buff[2]; | |||||||
| #define SUBGHZ_DMA_CH1_DEF SUBGHZ_DMA, SUBGHZ_DMA_CH1_CHANNEL | #define SUBGHZ_DMA_CH1_DEF SUBGHZ_DMA, SUBGHZ_DMA_CH1_CHANNEL | ||||||
| #define SUBGHZ_DMA_CH2_DEF SUBGHZ_DMA, SUBGHZ_DMA_CH2_CHANNEL | #define SUBGHZ_DMA_CH2_DEF SUBGHZ_DMA, SUBGHZ_DMA_CH2_CHANNEL | ||||||
| 
 | 
 | ||||||
|  | /** SubGhz state */ | ||||||
|  | typedef enum { | ||||||
|  |     SubGhzStateInit, /**< Init pending */ | ||||||
|  | 
 | ||||||
|  |     SubGhzStateIdle, /**< Idle, energy save mode */ | ||||||
|  | 
 | ||||||
|  |     SubGhzStateAsyncRx, /**< Async RX started */ | ||||||
|  | 
 | ||||||
|  |     SubGhzStateAsyncTx, /**< Async TX started, DMA and timer is on */ | ||||||
|  |     SubGhzStateAsyncTxLast, /**< Async TX continue, DMA completed and timer got last value to go */ | ||||||
|  |     SubGhzStateAsyncTxEnd, /**< Async TX complete, cleanup needed */ | ||||||
|  | 
 | ||||||
|  | } SubGhzState; | ||||||
|  | 
 | ||||||
|  | /** SubGhz regulation, receive transmission on the current frequency for the
 | ||||||
|  |  * region */ | ||||||
|  | typedef enum { | ||||||
|  |     SubGhzRegulationOnlyRx, /**only Rx*/ | ||||||
|  |     SubGhzRegulationTxRx, /**TxRx*/ | ||||||
|  | } SubGhzRegulation; | ||||||
|  | 
 | ||||||
| typedef struct { | typedef struct { | ||||||
|     volatile SubGhzState state; |     volatile SubGhzState state; | ||||||
|     volatile SubGhzRegulation regulation; |     volatile SubGhzRegulation regulation; | ||||||
|     volatile FuriHalSubGhzPreset preset; |  | ||||||
|     const GpioPin* async_mirror_pin; |     const GpioPin* async_mirror_pin; | ||||||
| } FuriHalSubGhz; | } FuriHalSubGhz; | ||||||
| 
 | 
 | ||||||
| volatile FuriHalSubGhz furi_hal_subghz = { | volatile FuriHalSubGhz furi_hal_subghz = { | ||||||
|     .state = SubGhzStateInit, |     .state = SubGhzStateInit, | ||||||
|     .regulation = SubGhzRegulationTxRx, |     .regulation = SubGhzRegulationTxRx, | ||||||
|     .preset = FuriHalSubGhzPresetIDLE, |  | ||||||
|     .async_mirror_pin = NULL, |     .async_mirror_pin = NULL, | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| @ -45,10 +63,13 @@ void furi_hal_subghz_set_async_mirror_pin(const GpioPin* pin) { | |||||||
|     furi_hal_subghz.async_mirror_pin = pin; |     furi_hal_subghz.async_mirror_pin = pin; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | const GpioPin* furi_hal_subghz_get_data_gpio() { | ||||||
|  |     return &gpio_cc1101_g0; | ||||||
|  | } | ||||||
|  | 
 | ||||||
| void furi_hal_subghz_init() { | void furi_hal_subghz_init() { | ||||||
|     furi_assert(furi_hal_subghz.state == SubGhzStateInit); |     furi_assert(furi_hal_subghz.state == SubGhzStateInit); | ||||||
|     furi_hal_subghz.state = SubGhzStateIdle; |     furi_hal_subghz.state = SubGhzStateIdle; | ||||||
|     furi_hal_subghz.preset = FuriHalSubGhzPresetIDLE; |  | ||||||
| 
 | 
 | ||||||
|     furi_hal_spi_acquire(&furi_hal_spi_bus_handle_subghz); |     furi_hal_spi_acquire(&furi_hal_spi_bus_handle_subghz); | ||||||
| 
 | 
 | ||||||
| @ -102,8 +123,6 @@ void furi_hal_subghz_sleep() { | |||||||
|     cc1101_shutdown(&furi_hal_spi_bus_handle_subghz); |     cc1101_shutdown(&furi_hal_spi_bus_handle_subghz); | ||||||
| 
 | 
 | ||||||
|     furi_hal_spi_release(&furi_hal_spi_bus_handle_subghz); |     furi_hal_spi_release(&furi_hal_spi_bus_handle_subghz); | ||||||
| 
 |  | ||||||
|     furi_hal_subghz.preset = FuriHalSubGhzPresetIDLE; |  | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void furi_hal_subghz_dump_state() { | void furi_hal_subghz_dump_state() { | ||||||
| @ -115,34 +134,7 @@ void furi_hal_subghz_dump_state() { | |||||||
|     furi_hal_spi_release(&furi_hal_spi_bus_handle_subghz); |     furi_hal_spi_release(&furi_hal_spi_bus_handle_subghz); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void furi_hal_subghz_load_preset(FuriHalSubGhzPreset preset) { | void furi_hal_subghz_load_custom_preset(const uint8_t* preset_data) { | ||||||
|     if(preset == FuriHalSubGhzPresetOok650Async) { |  | ||||||
|         furi_hal_subghz_load_registers((uint8_t*)furi_hal_subghz_preset_ook_650khz_async_regs); |  | ||||||
|         furi_hal_subghz_load_patable(furi_hal_subghz_preset_ook_async_patable); |  | ||||||
|     } else if(preset == FuriHalSubGhzPresetOok270Async) { |  | ||||||
|         furi_hal_subghz_load_registers((uint8_t*)furi_hal_subghz_preset_ook_270khz_async_regs); |  | ||||||
|         furi_hal_subghz_load_patable(furi_hal_subghz_preset_ook_async_patable); |  | ||||||
|     } else if(preset == FuriHalSubGhzPreset2FSKDev238Async) { |  | ||||||
|         furi_hal_subghz_load_registers( |  | ||||||
|             (uint8_t*)furi_hal_subghz_preset_2fsk_dev2_38khz_async_regs); |  | ||||||
|         furi_hal_subghz_load_patable(furi_hal_subghz_preset_2fsk_async_patable); |  | ||||||
|     } else if(preset == FuriHalSubGhzPreset2FSKDev476Async) { |  | ||||||
|         furi_hal_subghz_load_registers( |  | ||||||
|             (uint8_t*)furi_hal_subghz_preset_2fsk_dev47_6khz_async_regs); |  | ||||||
|         furi_hal_subghz_load_patable(furi_hal_subghz_preset_2fsk_async_patable); |  | ||||||
|     } else if(preset == FuriHalSubGhzPresetMSK99_97KbAsync) { |  | ||||||
|         furi_hal_subghz_load_registers((uint8_t*)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((uint8_t*)furi_hal_subghz_preset_gfsk_9_99kb_async_regs); |  | ||||||
|         furi_hal_subghz_load_patable(furi_hal_subghz_preset_gfsk_async_patable); |  | ||||||
|     } else { |  | ||||||
|         furi_crash("SubGhz: Missing config."); |  | ||||||
|     } |  | ||||||
|     furi_hal_subghz.preset = preset; |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| void furi_hal_subghz_load_custom_preset(uint8_t* preset_data) { |  | ||||||
|     //load config
 |     //load config
 | ||||||
|     furi_hal_spi_acquire(&furi_hal_spi_bus_handle_subghz); |     furi_hal_spi_acquire(&furi_hal_spi_bus_handle_subghz); | ||||||
|     cc1101_reset(&furi_hal_spi_bus_handle_subghz); |     cc1101_reset(&furi_hal_spi_bus_handle_subghz); | ||||||
| @ -157,7 +149,6 @@ void furi_hal_subghz_load_custom_preset(uint8_t* preset_data) { | |||||||
|     //load pa table
 |     //load pa table
 | ||||||
|     memcpy(&pa[0], &preset_data[i + 2], 8); |     memcpy(&pa[0], &preset_data[i + 2], 8); | ||||||
|     furi_hal_subghz_load_patable(pa); |     furi_hal_subghz_load_patable(pa); | ||||||
|     furi_hal_subghz.preset = FuriHalSubGhzPresetCustom; |  | ||||||
| 
 | 
 | ||||||
|     //show debug
 |     //show debug
 | ||||||
|     if(furi_hal_rtc_is_flag_set(FuriHalRtcFlagDebug)) { |     if(furi_hal_rtc_is_flag_set(FuriHalRtcFlagDebug)) { | ||||||
| @ -173,7 +164,7 @@ void furi_hal_subghz_load_custom_preset(uint8_t* preset_data) { | |||||||
|     } |     } | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void furi_hal_subghz_load_registers(uint8_t* data) { | void furi_hal_subghz_load_registers(const uint8_t* data) { | ||||||
|     furi_hal_spi_acquire(&furi_hal_spi_bus_handle_subghz); |     furi_hal_spi_acquire(&furi_hal_spi_bus_handle_subghz); | ||||||
|     cc1101_reset(&furi_hal_spi_bus_handle_subghz); |     cc1101_reset(&furi_hal_spi_bus_handle_subghz); | ||||||
|     uint32_t i = 0; |     uint32_t i = 0; | ||||||
|  | |||||||
| @ -5,6 +5,8 @@ | |||||||
| 
 | 
 | ||||||
| #pragma once | #pragma once | ||||||
| 
 | 
 | ||||||
|  | #include <lib/subghz/devices/preset.h> | ||||||
|  | 
 | ||||||
| #include <stdbool.h> | #include <stdbool.h> | ||||||
| #include <stdint.h> | #include <stdint.h> | ||||||
| #include <stddef.h> | #include <stddef.h> | ||||||
| @ -20,18 +22,6 @@ extern "C" { | |||||||
| #define API_HAL_SUBGHZ_ASYNC_TX_BUFFER_HALF (API_HAL_SUBGHZ_ASYNC_TX_BUFFER_FULL / 2) | #define API_HAL_SUBGHZ_ASYNC_TX_BUFFER_HALF (API_HAL_SUBGHZ_ASYNC_TX_BUFFER_FULL / 2) | ||||||
| #define API_HAL_SUBGHZ_ASYNC_TX_GUARD_TIME 999 | #define API_HAL_SUBGHZ_ASYNC_TX_GUARD_TIME 999 | ||||||
| 
 | 
 | ||||||
| /** Radio Presets */ |  | ||||||
| typedef enum { |  | ||||||
|     FuriHalSubGhzPresetIDLE, /**< default configuration */ |  | ||||||
|     FuriHalSubGhzPresetOok270Async, /**< OOK, bandwidth 270kHz, asynchronous */ |  | ||||||
|     FuriHalSubGhzPresetOok650Async, /**< OOK, bandwidth 650kHz, asynchronous */ |  | ||||||
|     FuriHalSubGhzPreset2FSKDev238Async, /**< FM, deviation 2.380371 kHz, asynchronous */ |  | ||||||
|     FuriHalSubGhzPreset2FSKDev476Async, /**< FM, deviation 47.60742 kHz, asynchronous */ |  | ||||||
|     FuriHalSubGhzPresetMSK99_97KbAsync, /**< MSK, deviation 47.60742 kHz, 99.97Kb/s, asynchronous */ |  | ||||||
|     FuriHalSubGhzPresetGFSK9_99KbAsync, /**< GFSK, deviation 19.042969 kHz, 9.996Kb/s, asynchronous */ |  | ||||||
|     FuriHalSubGhzPresetCustom, /**Custom Preset*/ |  | ||||||
| } FuriHalSubGhzPreset; |  | ||||||
| 
 |  | ||||||
| /** Switchable Radio Paths */ | /** Switchable Radio Paths */ | ||||||
| typedef enum { | typedef enum { | ||||||
|     FuriHalSubGhzPathIsolate, /**< Isolate Radio from antenna */ |     FuriHalSubGhzPathIsolate, /**< Isolate Radio from antenna */ | ||||||
| @ -40,27 +30,6 @@ typedef enum { | |||||||
|     FuriHalSubGhzPath868, /**< Center Frequency: 868MHz. Path 3: SW1RF3-SW2RF3, LCLC */ |     FuriHalSubGhzPath868, /**< Center Frequency: 868MHz. Path 3: SW1RF3-SW2RF3, LCLC */ | ||||||
| } FuriHalSubGhzPath; | } FuriHalSubGhzPath; | ||||||
| 
 | 
 | ||||||
| /** SubGhz state */ |  | ||||||
| typedef enum { |  | ||||||
|     SubGhzStateInit, /**< Init pending */ |  | ||||||
| 
 |  | ||||||
|     SubGhzStateIdle, /**< Idle, energy save mode */ |  | ||||||
| 
 |  | ||||||
|     SubGhzStateAsyncRx, /**< Async RX started */ |  | ||||||
| 
 |  | ||||||
|     SubGhzStateAsyncTx, /**< Async TX started, DMA and timer is on */ |  | ||||||
|     SubGhzStateAsyncTxLast, /**< Async TX continue, DMA completed and timer got last value to go */ |  | ||||||
|     SubGhzStateAsyncTxEnd, /**< Async TX complete, cleanup needed */ |  | ||||||
| 
 |  | ||||||
| } SubGhzState; |  | ||||||
| 
 |  | ||||||
| /** SubGhz regulation, receive transmission on the current frequency for the
 |  | ||||||
|  * region */ |  | ||||||
| typedef enum { |  | ||||||
|     SubGhzRegulationOnlyRx, /**only Rx*/ |  | ||||||
|     SubGhzRegulationTxRx, /**TxRx*/ |  | ||||||
| } SubGhzRegulation; |  | ||||||
| 
 |  | ||||||
| /* Mirror RX/TX async modulation signal to specified pin
 | /* Mirror RX/TX async modulation signal to specified pin
 | ||||||
|  * |  * | ||||||
|  * @warning    Configures pin to output mode. Make sure it is not connected |  * @warning    Configures pin to output mode. Make sure it is not connected | ||||||
| @ -70,6 +39,12 @@ typedef enum { | |||||||
|  */ |  */ | ||||||
| void furi_hal_subghz_set_async_mirror_pin(const GpioPin* pin); | void furi_hal_subghz_set_async_mirror_pin(const GpioPin* pin); | ||||||
| 
 | 
 | ||||||
|  | /** Get data GPIO
 | ||||||
|  |  * | ||||||
|  |  * @return     pointer to the gpio pin structure | ||||||
|  |  */ | ||||||
|  | const GpioPin* furi_hal_subghz_get_data_gpio(); | ||||||
|  | 
 | ||||||
| /** Initialize and switch to power save mode Used by internal API-HAL
 | /** Initialize and switch to power save mode Used by internal API-HAL
 | ||||||
|  * initialization routine Can be used to reinitialize device to safe state and |  * initialization routine Can be used to reinitialize device to safe state and | ||||||
|  * send it to sleep |  * send it to sleep | ||||||
| @ -84,23 +59,17 @@ void furi_hal_subghz_sleep(); | |||||||
|  */ |  */ | ||||||
| void furi_hal_subghz_dump_state(); | void furi_hal_subghz_dump_state(); | ||||||
| 
 | 
 | ||||||
| /** Load registers from preset by preset name
 |  | ||||||
|  * |  | ||||||
|  * @param      preset  to load |  | ||||||
|  */ |  | ||||||
| void furi_hal_subghz_load_preset(FuriHalSubGhzPreset preset); |  | ||||||
| 
 |  | ||||||
| /** Load custom registers from preset
 | /** Load custom registers from preset
 | ||||||
|  * |  * | ||||||
|  * @param      preset_data   registers to load |  * @param      preset_data   registers to load | ||||||
|  */ |  */ | ||||||
| void furi_hal_subghz_load_custom_preset(uint8_t* preset_data); | void furi_hal_subghz_load_custom_preset(const uint8_t* preset_data); | ||||||
| 
 | 
 | ||||||
| /** Load registers
 | /** Load registers
 | ||||||
|  * |  * | ||||||
|  * @param      data  Registers data |  * @param      data  Registers data | ||||||
|  */ |  */ | ||||||
| void furi_hal_subghz_load_registers(uint8_t* data); | void furi_hal_subghz_load_registers(const uint8_t* data); | ||||||
| 
 | 
 | ||||||
| /** Load PATABLE
 | /** Load PATABLE
 | ||||||
|  * |  * | ||||||
|  | |||||||
| @ -1,314 +0,0 @@ | |||||||
| #pragma once |  | ||||||
| 
 |  | ||||||
| #include <cc1101.h> |  | ||||||
| 
 |  | ||||||
| static const uint8_t furi_hal_subghz_preset_ook_270khz_async_regs[][2] = { |  | ||||||
|     // https://e2e.ti.com/support/wireless-connectivity/sub-1-ghz-group/sub-1-ghz/f/sub-1-ghz-forum/382066/cc1101---don-t-know-the-correct-registers-configuration
 |  | ||||||
| 
 |  | ||||||
|     /* GPIO GD0 */ |  | ||||||
|     {CC1101_IOCFG0, 0x0D}, // GD0 as async serial data output/input
 |  | ||||||
| 
 |  | ||||||
|     /* FIFO and internals */ |  | ||||||
|     {CC1101_FIFOTHR, 0x47}, // The only important bit is ADC_RETENTION, FIFO Tx=33 Rx=32
 |  | ||||||
| 
 |  | ||||||
|     /* Packet engine */ |  | ||||||
|     {CC1101_PKTCTRL0, 0x32}, // Async, continious, no whitening
 |  | ||||||
| 
 |  | ||||||
|     /* Frequency Synthesizer Control */ |  | ||||||
|     {CC1101_FSCTRL1, 0x06}, // IF = (26*10^6) / (2^10) * 0x06 = 152343.75Hz
 |  | ||||||
| 
 |  | ||||||
|     // Modem Configuration
 |  | ||||||
|     {CC1101_MDMCFG0, 0x00}, // Channel spacing is 25kHz
 |  | ||||||
|     {CC1101_MDMCFG1, 0x00}, // Channel spacing is 25kHz
 |  | ||||||
|     {CC1101_MDMCFG2, 0x30}, // Format ASK/OOK, No preamble/sync
 |  | ||||||
|     {CC1101_MDMCFG3, 0x32}, // Data rate is 3.79372 kBaud
 |  | ||||||
|     {CC1101_MDMCFG4, 0x67}, // Rx BW filter is 270.833333kHz
 |  | ||||||
| 
 |  | ||||||
|     /* Main Radio Control State Machine */ |  | ||||||
|     {CC1101_MCSM0, 0x18}, // Autocalibrate on idle-to-rx/tx, PO_TIMEOUT is 64 cycles(149-155us)
 |  | ||||||
| 
 |  | ||||||
|     /* Frequency Offset Compensation Configuration */ |  | ||||||
|     {CC1101_FOCCFG, |  | ||||||
|      0x18}, // no frequency offset compensation, POST_K same as PRE_K, PRE_K is 4K, GATE is off
 |  | ||||||
| 
 |  | ||||||
|     /* Automatic Gain Control */ |  | ||||||
|     {CC1101_AGCCTRL0, |  | ||||||
|      0x40}, // 01 - Low hysteresis, small asymmetric dead zone, medium gain; 00 - 8 samples agc; 00 - Normal AGC, 00 - 4dB boundary
 |  | ||||||
|     {CC1101_AGCCTRL1, |  | ||||||
|      0x00}, // 0; 0 - LNA 2 gain is decreased to minimum before decreasing LNA gain; 00 - Relative carrier sense threshold disabled; 0000 - RSSI to MAIN_TARGET
 |  | ||||||
|     {CC1101_AGCCTRL2, 0x03}, // 00 - DVGA all; 000 - MAX LNA+LNA2; 011 - MAIN_TARGET 24 dB
 |  | ||||||
| 
 |  | ||||||
|     /* Wake on radio and timeouts control */ |  | ||||||
|     {CC1101_WORCTRL, 0xFB}, // WOR_RES is 2^15 periods (0.91 - 0.94 s) 16.5 - 17.2 hours
 |  | ||||||
| 
 |  | ||||||
|     /* Frontend configuration */ |  | ||||||
|     {CC1101_FREND0, 0x11}, // Adjusts current TX LO buffer + high is PATABLE[1]
 |  | ||||||
|     {CC1101_FREND1, 0xB6}, //
 |  | ||||||
| 
 |  | ||||||
|     /* End  */ |  | ||||||
|     {0, 0}, |  | ||||||
| }; |  | ||||||
| 
 |  | ||||||
| static const uint8_t furi_hal_subghz_preset_ook_650khz_async_regs[][2] = { |  | ||||||
|     // https://e2e.ti.com/support/wireless-connectivity/sub-1-ghz-group/sub-1-ghz/f/sub-1-ghz-forum/382066/cc1101---don-t-know-the-correct-registers-configuration
 |  | ||||||
| 
 |  | ||||||
|     /* GPIO GD0 */ |  | ||||||
|     {CC1101_IOCFG0, 0x0D}, // GD0 as async serial data output/input
 |  | ||||||
| 
 |  | ||||||
|     /* FIFO and internals */ |  | ||||||
|     {CC1101_FIFOTHR, 0x07}, // The only important bit is ADC_RETENTION
 |  | ||||||
| 
 |  | ||||||
|     /* Packet engine */ |  | ||||||
|     {CC1101_PKTCTRL0, 0x32}, // Async, continious, no whitening
 |  | ||||||
| 
 |  | ||||||
|     /* Frequency Synthesizer Control */ |  | ||||||
|     {CC1101_FSCTRL1, 0x06}, // IF = (26*10^6) / (2^10) * 0x06 = 152343.75Hz
 |  | ||||||
| 
 |  | ||||||
|     // Modem Configuration
 |  | ||||||
|     {CC1101_MDMCFG0, 0x00}, // Channel spacing is 25kHz
 |  | ||||||
|     {CC1101_MDMCFG1, 0x00}, // Channel spacing is 25kHz
 |  | ||||||
|     {CC1101_MDMCFG2, 0x30}, // Format ASK/OOK, No preamble/sync
 |  | ||||||
|     {CC1101_MDMCFG3, 0x32}, // Data rate is 3.79372 kBaud
 |  | ||||||
|     {CC1101_MDMCFG4, 0x17}, // Rx BW filter is 650.000kHz
 |  | ||||||
| 
 |  | ||||||
|     /* Main Radio Control State Machine */ |  | ||||||
|     {CC1101_MCSM0, 0x18}, // Autocalibrate on idle-to-rx/tx, PO_TIMEOUT is 64 cycles(149-155us)
 |  | ||||||
| 
 |  | ||||||
|     /* Frequency Offset Compensation Configuration */ |  | ||||||
|     {CC1101_FOCCFG, |  | ||||||
|      0x18}, // no frequency offset compensation, POST_K same as PRE_K, PRE_K is 4K, GATE is off
 |  | ||||||
| 
 |  | ||||||
|     /* Automatic Gain Control */ |  | ||||||
|     // {CC1101_AGCTRL0,0x40}, // 01 - Low hysteresis, small asymmetric dead zone, medium gain; 00 - 8 samples agc; 00 - Normal AGC, 00 - 4dB boundary
 |  | ||||||
|     // {CC1101_AGCTRL1,0x00}, // 0; 0 - LNA 2 gain is decreased to minimum before decreasing LNA gain; 00 - Relative carrier sense threshold disabled; 0000 - RSSI to MAIN_TARGET
 |  | ||||||
|     // {CC1101_AGCCTRL2, 0x03}, // 00 - DVGA all; 000 - MAX LNA+LNA2; 011 - MAIN_TARGET 24 dB
 |  | ||||||
|     //MAGN_TARGET for RX filter BW =< 100 kHz is 0x3. For higher RX filter BW's MAGN_TARGET is 0x7.
 |  | ||||||
|     {CC1101_AGCCTRL0, |  | ||||||
|      0x91}, // 10 - Medium hysteresis, medium asymmetric dead zone, medium gain ; 01 - 16 samples agc; 00 - Normal AGC, 01 - 8dB boundary
 |  | ||||||
|     {CC1101_AGCCTRL1, |  | ||||||
|      0x0}, // 0; 0 - LNA 2 gain is decreased to minimum before decreasing LNA gain; 00 - Relative carrier sense threshold disabled; 0000 - RSSI to MAIN_TARGET
 |  | ||||||
|     {CC1101_AGCCTRL2, 0x07}, // 00 - DVGA all; 000 - MAX LNA+LNA2; 111 - MAIN_TARGET 42 dB
 |  | ||||||
| 
 |  | ||||||
|     /* Wake on radio and timeouts control */ |  | ||||||
|     {CC1101_WORCTRL, 0xFB}, // WOR_RES is 2^15 periods (0.91 - 0.94 s) 16.5 - 17.2 hours
 |  | ||||||
| 
 |  | ||||||
|     /* Frontend configuration */ |  | ||||||
|     {CC1101_FREND0, 0x11}, // Adjusts current TX LO buffer + high is PATABLE[1]
 |  | ||||||
|     {CC1101_FREND1, 0xB6}, //
 |  | ||||||
| 
 |  | ||||||
|     /* End  */ |  | ||||||
|     {0, 0}, |  | ||||||
| }; |  | ||||||
| 
 |  | ||||||
| static const uint8_t furi_hal_subghz_preset_2fsk_dev2_38khz_async_regs[][2] = { |  | ||||||
| 
 |  | ||||||
|     /* GPIO GD0 */ |  | ||||||
|     {CC1101_IOCFG0, 0x0D}, // GD0 as async serial data output/input
 |  | ||||||
| 
 |  | ||||||
|     /* Frequency Synthesizer Control */ |  | ||||||
|     {CC1101_FSCTRL1, 0x06}, // IF = (26*10^6) / (2^10) * 0x06 = 152343.75Hz
 |  | ||||||
| 
 |  | ||||||
|     /* Packet engine */ |  | ||||||
|     {CC1101_PKTCTRL0, 0x32}, // Async, continious, no whitening
 |  | ||||||
|     {CC1101_PKTCTRL1, 0x04}, |  | ||||||
| 
 |  | ||||||
|     // // Modem Configuration
 |  | ||||||
|     {CC1101_MDMCFG0, 0x00}, |  | ||||||
|     {CC1101_MDMCFG1, 0x02}, |  | ||||||
|     {CC1101_MDMCFG2, 0x04}, // Format 2-FSK/FM, No preamble/sync, Disable (current optimized)
 |  | ||||||
|     {CC1101_MDMCFG3, 0x83}, // Data rate is 4.79794 kBaud
 |  | ||||||
|     {CC1101_MDMCFG4, 0x67}, //Rx BW filter is 270.833333 kHz
 |  | ||||||
|     {CC1101_DEVIATN, 0x04}, //Deviation 2.380371 kHz
 |  | ||||||
| 
 |  | ||||||
|     /* Main Radio Control State Machine */ |  | ||||||
|     {CC1101_MCSM0, 0x18}, // Autocalibrate on idle-to-rx/tx, PO_TIMEOUT is 64 cycles(149-155us)
 |  | ||||||
| 
 |  | ||||||
|     /* Frequency Offset Compensation Configuration */ |  | ||||||
|     {CC1101_FOCCFG, |  | ||||||
|      0x16}, // no frequency offset compensation, POST_K same as PRE_K, PRE_K is 4K, GATE is off
 |  | ||||||
| 
 |  | ||||||
|     /* Automatic Gain Control */ |  | ||||||
|     {CC1101_AGCCTRL0, |  | ||||||
|      0x91}, //10 - Medium hysteresis, medium asymmetric dead zone, medium gain ; 01 - 16 samples agc; 00 - Normal AGC, 01 - 8dB boundary
 |  | ||||||
|     {CC1101_AGCCTRL1, |  | ||||||
|      0x00}, // 0; 0 - LNA 2 gain is decreased to minimum before decreasing LNA gain; 00 - Relative carrier sense threshold disabled; 0000 - RSSI to MAIN_TARGET
 |  | ||||||
|     {CC1101_AGCCTRL2, 0x07}, // 00 - DVGA all; 000 - MAX LNA+LNA2; 111 - MAIN_TARGET 42 dB
 |  | ||||||
| 
 |  | ||||||
|     /* Wake on radio and timeouts control */ |  | ||||||
|     {CC1101_WORCTRL, 0xFB}, // WOR_RES is 2^15 periods (0.91 - 0.94 s) 16.5 - 17.2 hours
 |  | ||||||
| 
 |  | ||||||
|     /* Frontend configuration */ |  | ||||||
|     {CC1101_FREND0, 0x10}, // Adjusts current TX LO buffer
 |  | ||||||
|     {CC1101_FREND1, 0x56}, |  | ||||||
| 
 |  | ||||||
|     /* End  */ |  | ||||||
|     {0, 0}, |  | ||||||
| }; |  | ||||||
| 
 |  | ||||||
| static const uint8_t furi_hal_subghz_preset_2fsk_dev47_6khz_async_regs[][2] = { |  | ||||||
| 
 |  | ||||||
|     /* GPIO GD0 */ |  | ||||||
|     {CC1101_IOCFG0, 0x0D}, // GD0 as async serial data output/input
 |  | ||||||
| 
 |  | ||||||
|     /* Frequency Synthesizer Control */ |  | ||||||
|     {CC1101_FSCTRL1, 0x06}, // IF = (26*10^6) / (2^10) * 0x06 = 152343.75Hz
 |  | ||||||
| 
 |  | ||||||
|     /* Packet engine */ |  | ||||||
|     {CC1101_PKTCTRL0, 0x32}, // Async, continious, no whitening
 |  | ||||||
|     {CC1101_PKTCTRL1, 0x04}, |  | ||||||
| 
 |  | ||||||
|     // // Modem Configuration
 |  | ||||||
|     {CC1101_MDMCFG0, 0x00}, |  | ||||||
|     {CC1101_MDMCFG1, 0x02}, |  | ||||||
|     {CC1101_MDMCFG2, 0x04}, // Format 2-FSK/FM, No preamble/sync, Disable (current optimized)
 |  | ||||||
|     {CC1101_MDMCFG3, 0x83}, // Data rate is 4.79794 kBaud
 |  | ||||||
|     {CC1101_MDMCFG4, 0x67}, //Rx BW filter is 270.833333 kHz
 |  | ||||||
|     {CC1101_DEVIATN, 0x47}, //Deviation 47.60742 kHz
 |  | ||||||
| 
 |  | ||||||
|     /* Main Radio Control State Machine */ |  | ||||||
|     {CC1101_MCSM0, 0x18}, // Autocalibrate on idle-to-rx/tx, PO_TIMEOUT is 64 cycles(149-155us)
 |  | ||||||
| 
 |  | ||||||
|     /* Frequency Offset Compensation Configuration */ |  | ||||||
|     {CC1101_FOCCFG, |  | ||||||
|      0x16}, // no frequency offset compensation, POST_K same as PRE_K, PRE_K is 4K, GATE is off
 |  | ||||||
| 
 |  | ||||||
|     /* Automatic Gain Control */ |  | ||||||
|     {CC1101_AGCCTRL0, |  | ||||||
|      0x91}, //10 - Medium hysteresis, medium asymmetric dead zone, medium gain ; 01 - 16 samples agc; 00 - Normal AGC, 01 - 8dB boundary
 |  | ||||||
|     {CC1101_AGCCTRL1, |  | ||||||
|      0x00}, // 0; 0 - LNA 2 gain is decreased to minimum before decreasing LNA gain; 00 - Relative carrier sense threshold disabled; 0000 - RSSI to MAIN_TARGET
 |  | ||||||
|     {CC1101_AGCCTRL2, 0x07}, // 00 - DVGA all; 000 - MAX LNA+LNA2; 111 - MAIN_TARGET 42 dB
 |  | ||||||
| 
 |  | ||||||
|     /* Wake on radio and timeouts control */ |  | ||||||
|     {CC1101_WORCTRL, 0xFB}, // WOR_RES is 2^15 periods (0.91 - 0.94 s) 16.5 - 17.2 hours
 |  | ||||||
| 
 |  | ||||||
|     /* Frontend configuration */ |  | ||||||
|     {CC1101_FREND0, 0x10}, // Adjusts current TX LO buffer
 |  | ||||||
|     {CC1101_FREND1, 0x56}, |  | ||||||
| 
 |  | ||||||
|     /* End  */ |  | ||||||
|     {0, 0}, |  | ||||||
| }; |  | ||||||
| 
 |  | ||||||
| static const uint8_t furi_hal_subghz_preset_msk_99_97kb_async_regs[][2] = { |  | ||||||
|     /* GPIO GD0 */ |  | ||||||
|     {CC1101_IOCFG0, 0x06}, |  | ||||||
| 
 |  | ||||||
|     {CC1101_FIFOTHR, 0x07}, // The only important bit is ADC_RETENTION
 |  | ||||||
|     {CC1101_SYNC1, 0x46}, |  | ||||||
|     {CC1101_SYNC0, 0x4C}, |  | ||||||
|     {CC1101_ADDR, 0x00}, |  | ||||||
|     {CC1101_PKTLEN, 0x00}, |  | ||||||
|     {CC1101_CHANNR, 0x00}, |  | ||||||
| 
 |  | ||||||
|     {CC1101_PKTCTRL0, 0x05}, |  | ||||||
| 
 |  | ||||||
|     {CC1101_FSCTRL0, 0x23}, |  | ||||||
|     {CC1101_FSCTRL1, 0x06}, |  | ||||||
| 
 |  | ||||||
|     {CC1101_MDMCFG0, 0xF8}, |  | ||||||
|     {CC1101_MDMCFG1, 0x22}, |  | ||||||
|     {CC1101_MDMCFG2, 0x72}, |  | ||||||
|     {CC1101_MDMCFG3, 0xF8}, |  | ||||||
|     {CC1101_MDMCFG4, 0x5B}, |  | ||||||
|     {CC1101_DEVIATN, 0x47}, |  | ||||||
| 
 |  | ||||||
|     {CC1101_MCSM0, 0x18}, |  | ||||||
|     {CC1101_FOCCFG, 0x16}, |  | ||||||
| 
 |  | ||||||
|     {CC1101_AGCCTRL0, 0xB2}, |  | ||||||
|     {CC1101_AGCCTRL1, 0x00}, |  | ||||||
|     {CC1101_AGCCTRL2, 0xC7}, |  | ||||||
| 
 |  | ||||||
|     {CC1101_FREND0, 0x10}, |  | ||||||
|     {CC1101_FREND1, 0x56}, |  | ||||||
| 
 |  | ||||||
|     {CC1101_BSCFG, 0x1C}, |  | ||||||
|     {CC1101_FSTEST, 0x59}, |  | ||||||
| 
 |  | ||||||
|     /* 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
 |  | ||||||
|     /* End  */ |  | ||||||
|     {0, 0}, |  | ||||||
| }; |  | ||||||
| 
 |  | ||||||
| static const uint8_t furi_hal_subghz_preset_ook_async_patable[8] = { |  | ||||||
|     0x00, |  | ||||||
|     0xC0, // 12dBm 0xC0, 10dBm 0xC5, 7dBm 0xCD, 5dBm 0x86, 0dBm 0x50, -6dBm 0x37, -10dBm 0x26, -15dBm 0x1D, -20dBm 0x17, -30dBm 0x03
 |  | ||||||
|     0x00, |  | ||||||
|     0x00, |  | ||||||
|     0x00, |  | ||||||
|     0x00, |  | ||||||
|     0x00, |  | ||||||
|     0x00}; |  | ||||||
| 
 |  | ||||||
| static const uint8_t furi_hal_subghz_preset_ook_async_patable_au[8] = { |  | ||||||
|     0x00, |  | ||||||
|     0x37, // 12dBm 0xC0, 10dBm 0xC5, 7dBm 0xCD, 5dBm 0x86, 0dBm 0x50, -6dBm 0x37, -10dBm 0x26, -15dBm 0x1D, -20dBm 0x17, -30dBm 0x03
 |  | ||||||
|     0x00, |  | ||||||
|     0x00, |  | ||||||
|     0x00, |  | ||||||
|     0x00, |  | ||||||
|     0x00, |  | ||||||
|     0x00}; |  | ||||||
| 
 |  | ||||||
| static const uint8_t furi_hal_subghz_preset_2fsk_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}; |  | ||||||
| 
 |  | ||||||
| static const uint8_t furi_hal_subghz_preset_msk_async_patable[8] = { |  | ||||||
|     0xC0, // 10dBm 0xC0, 7dBm 0xC8, 5dBm 0x84, 0dBm 0x60, -10dBm 0x34, -15dBm 0x1D, -20dBm 0x0E, -30dBm 0x12
 |  | ||||||
|     0x00, |  | ||||||
|     0x00, |  | ||||||
|     0x00, |  | ||||||
|     0x00, |  | ||||||
|     0x00, |  | ||||||
|     0x00, |  | ||||||
|     0x00}; |  | ||||||
| 
 |  | ||||||
| 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}; |  | ||||||
| @ -1,10 +1,12 @@ | |||||||
| #include <errno.h> | #include <errno.h> | ||||||
|  | #include <stdint.h> | ||||||
| 
 | 
 | ||||||
| #ifdef __cplusplus | #ifdef __cplusplus | ||||||
| extern "C" { | extern "C" { | ||||||
| #endif | #endif | ||||||
| 
 | 
 | ||||||
| void __clear_cache(void*, void*); | void __clear_cache(void*, void*); | ||||||
|  | void* __aeabi_uldivmod(uint64_t, uint64_t); | ||||||
| 
 | 
 | ||||||
| #ifdef __cplusplus | #ifdef __cplusplus | ||||||
| } | } | ||||||
|  | |||||||
| @ -19,6 +19,7 @@ env.Append( | |||||||
|         File("blocks/math.h"), |         File("blocks/math.h"), | ||||||
|         File("subghz_setting.h"), |         File("subghz_setting.h"), | ||||||
|         File("subghz_protocol_registry.h"), |         File("subghz_protocol_registry.h"), | ||||||
|  |         File("devices/cc1101_configs.h"), | ||||||
|     ], |     ], | ||||||
| ) | ) | ||||||
| 
 | 
 | ||||||
|  | |||||||
							
								
								
									
										431
									
								
								lib/subghz/devices/cc1101_configs.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										431
									
								
								lib/subghz/devices/cc1101_configs.c
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,431 @@ | |||||||
|  | #include "cc1101_configs.h" | ||||||
|  | #include <cc1101_regs.h> | ||||||
|  | 
 | ||||||
|  | const uint8_t subghz_device_cc1101_preset_ook_270khz_async_regs[] = { | ||||||
|  |     // https://e2e.ti.com/support/wireless-connectivity/sub-1-ghz-group/sub-1-ghz/f/sub-1-ghz-forum/382066/cc1101---don-t-know-the-correct-registers-configuration
 | ||||||
|  | 
 | ||||||
|  |     /* GPIO GD0 */ | ||||||
|  |     CC1101_IOCFG0, | ||||||
|  |     0x0D, // GD0 as async serial data output/input
 | ||||||
|  | 
 | ||||||
|  |     /* FIFO and internals */ | ||||||
|  |     CC1101_FIFOTHR, | ||||||
|  |     0x47, // The only important bit is ADC_RETENTION, FIFO Tx=33 Rx=32
 | ||||||
|  | 
 | ||||||
|  |     /* Packet engine */ | ||||||
|  |     CC1101_PKTCTRL0, | ||||||
|  |     0x32, // Async, continious, no whitening
 | ||||||
|  | 
 | ||||||
|  |     /* Frequency Synthesizer Control */ | ||||||
|  |     CC1101_FSCTRL1, | ||||||
|  |     0x06, // IF = (26*10^6) / (2^10) * 0x06 = 152343.75Hz
 | ||||||
|  | 
 | ||||||
|  |     // Modem Configuration
 | ||||||
|  |     CC1101_MDMCFG0, | ||||||
|  |     0x00, // Channel spacing is 25kHz
 | ||||||
|  |     CC1101_MDMCFG1, | ||||||
|  |     0x00, // Channel spacing is 25kHz
 | ||||||
|  |     CC1101_MDMCFG2, | ||||||
|  |     0x30, // Format ASK/OOK, No preamble/sync
 | ||||||
|  |     CC1101_MDMCFG3, | ||||||
|  |     0x32, // Data rate is 3.79372 kBaud
 | ||||||
|  |     CC1101_MDMCFG4, | ||||||
|  |     0x67, // Rx BW filter is 270.833333kHz
 | ||||||
|  | 
 | ||||||
|  |     /* Main Radio Control State Machine */ | ||||||
|  |     CC1101_MCSM0, | ||||||
|  |     0x18, // Autocalibrate on idle-to-rx/tx, PO_TIMEOUT is 64 cycles(149-155us)
 | ||||||
|  | 
 | ||||||
|  |     /* Frequency Offset Compensation Configuration */ | ||||||
|  |     CC1101_FOCCFG, | ||||||
|  |     0x18, // no frequency offset compensation, POST_K same as PRE_K, PRE_K is 4K, GATE is off
 | ||||||
|  | 
 | ||||||
|  |     /* Automatic Gain Control */ | ||||||
|  |     CC1101_AGCCTRL0, | ||||||
|  |     0x40, // 01 - Low hysteresis, small asymmetric dead zone, medium gain; 00 - 8 samples agc; 00 - Normal AGC, 00 - 4dB boundary
 | ||||||
|  |     CC1101_AGCCTRL1, | ||||||
|  |     0x00, // 0; 0 - LNA 2 gain is decreased to minimum before decreasing LNA gain; 00 - Relative carrier sense threshold disabled; 0000 - RSSI to MAIN_TARGET
 | ||||||
|  |     CC1101_AGCCTRL2, | ||||||
|  |     0x03, // 00 - DVGA all; 000 - MAX LNA+LNA2; 011 - MAIN_TARGET 24 dB
 | ||||||
|  | 
 | ||||||
|  |     /* Wake on radio and timeouts control */ | ||||||
|  |     CC1101_WORCTRL, | ||||||
|  |     0xFB, // WOR_RES is 2^15 periods (0.91 - 0.94 s) 16.5 - 17.2 hours
 | ||||||
|  | 
 | ||||||
|  |     /* Frontend configuration */ | ||||||
|  |     CC1101_FREND0, | ||||||
|  |     0x11, // Adjusts current TX LO buffer + high is PATABLE[1]
 | ||||||
|  |     CC1101_FREND1, | ||||||
|  |     0xB6, //
 | ||||||
|  | 
 | ||||||
|  |     /* End load reg */ | ||||||
|  |     0, | ||||||
|  |     0, | ||||||
|  | 
 | ||||||
|  |     //ook_async_patable[8]
 | ||||||
|  |     0x00, | ||||||
|  |     0xC0, // 12dBm 0xC0, 10dBm 0xC5, 7dBm 0xCD, 5dBm 0x86, 0dBm 0x50, -6dBm 0x37, -10dBm 0x26, -15dBm 0x1D, -20dBm 0x17, -30dBm 0x03
 | ||||||
|  |     0x00, | ||||||
|  |     0x00, | ||||||
|  |     0x00, | ||||||
|  |     0x00, | ||||||
|  |     0x00, | ||||||
|  |     0x00, | ||||||
|  | }; | ||||||
|  | 
 | ||||||
|  | const uint8_t subghz_device_cc1101_preset_ook_650khz_async_regs[] = { | ||||||
|  |     // https://e2e.ti.com/support/wireless-connectivity/sub-1-ghz-group/sub-1-ghz/f/sub-1-ghz-forum/382066/cc1101---don-t-know-the-correct-registers-configuration
 | ||||||
|  | 
 | ||||||
|  |     /* GPIO GD0 */ | ||||||
|  |     CC1101_IOCFG0, | ||||||
|  |     0x0D, // GD0 as async serial data output/input
 | ||||||
|  | 
 | ||||||
|  |     /* FIFO and internals */ | ||||||
|  |     CC1101_FIFOTHR, | ||||||
|  |     0x07, // The only important bit is ADC_RETENTION
 | ||||||
|  | 
 | ||||||
|  |     /* Packet engine */ | ||||||
|  |     CC1101_PKTCTRL0, | ||||||
|  |     0x32, // Async, continious, no whitening
 | ||||||
|  | 
 | ||||||
|  |     /* Frequency Synthesizer Control */ | ||||||
|  |     CC1101_FSCTRL1, | ||||||
|  |     0x06, // IF = (26*10^6) / (2^10) * 0x06 = 152343.75Hz
 | ||||||
|  | 
 | ||||||
|  |     // Modem Configuration
 | ||||||
|  |     CC1101_MDMCFG0, | ||||||
|  |     0x00, // Channel spacing is 25kHz
 | ||||||
|  |     CC1101_MDMCFG1, | ||||||
|  |     0x00, // Channel spacing is 25kHz
 | ||||||
|  |     CC1101_MDMCFG2, | ||||||
|  |     0x30, // Format ASK/OOK, No preamble/sync
 | ||||||
|  |     CC1101_MDMCFG3, | ||||||
|  |     0x32, // Data rate is 3.79372 kBaud
 | ||||||
|  |     CC1101_MDMCFG4, | ||||||
|  |     0x17, // Rx BW filter is 650.000kHz
 | ||||||
|  | 
 | ||||||
|  |     /* Main Radio Control State Machine */ | ||||||
|  |     CC1101_MCSM0, | ||||||
|  |     0x18, // Autocalibrate on idle-to-rx/tx, PO_TIMEOUT is 64 cycles(149-155us)
 | ||||||
|  | 
 | ||||||
|  |     /* Frequency Offset Compensation Configuration */ | ||||||
|  |     CC1101_FOCCFG, | ||||||
|  |     0x18, // no frequency offset compensation, POST_K same as PRE_K, PRE_K is 4K, GATE is off
 | ||||||
|  | 
 | ||||||
|  |     /* Automatic Gain Control */ | ||||||
|  |     // CC1101_AGCTRL0,0x40, // 01 - Low hysteresis, small asymmetric dead zone, medium gain; 00 - 8 samples agc; 00 - Normal AGC, 00 - 4dB boundary
 | ||||||
|  |     // CC1101_AGCTRL1,0x00, // 0; 0 - LNA 2 gain is decreased to minimum before decreasing LNA gain; 00 - Relative carrier sense threshold disabled; 0000 - RSSI to MAIN_TARGET
 | ||||||
|  |     // CC1101_AGCCTRL2, 0x03, // 00 - DVGA all; 000 - MAX LNA+LNA2; 011 - MAIN_TARGET 24 dB
 | ||||||
|  |     //MAGN_TARGET for RX filter BW =< 100 kHz is 0x3. For higher RX filter BW's MAGN_TARGET is 0x7.
 | ||||||
|  |     CC1101_AGCCTRL0, | ||||||
|  |     0x91, // 10 - Medium hysteresis, medium asymmetric dead zone, medium gain ; 01 - 16 samples agc; 00 - Normal AGC, 01 - 8dB boundary
 | ||||||
|  |     CC1101_AGCCTRL1, | ||||||
|  |     0x0, // 0; 0 - LNA 2 gain is decreased to minimum before decreasing LNA gain; 00 - Relative carrier sense threshold disabled; 0000 - RSSI to MAIN_TARGET
 | ||||||
|  |     CC1101_AGCCTRL2, | ||||||
|  |     0x07, // 00 - DVGA all; 000 - MAX LNA+LNA2; 111 - MAIN_TARGET 42 dB
 | ||||||
|  | 
 | ||||||
|  |     /* Wake on radio and timeouts control */ | ||||||
|  |     CC1101_WORCTRL, | ||||||
|  |     0xFB, // WOR_RES is 2^15 periods (0.91 - 0.94 s) 16.5 - 17.2 hours
 | ||||||
|  | 
 | ||||||
|  |     /* Frontend configuration */ | ||||||
|  |     CC1101_FREND0, | ||||||
|  |     0x11, // Adjusts current TX LO buffer + high is PATABLE[1]
 | ||||||
|  |     CC1101_FREND1, | ||||||
|  |     0xB6, //
 | ||||||
|  | 
 | ||||||
|  |     /* End load reg */ | ||||||
|  |     0, | ||||||
|  |     0, | ||||||
|  | 
 | ||||||
|  |     //ook_async_patable[8]
 | ||||||
|  |     0x00, | ||||||
|  |     0xC0, // 12dBm 0xC0, 10dBm 0xC5, 7dBm 0xCD, 5dBm 0x86, 0dBm 0x50, -6dBm 0x37, -10dBm 0x26, -15dBm 0x1D, -20dBm 0x17, -30dBm 0x03
 | ||||||
|  |     0x00, | ||||||
|  |     0x00, | ||||||
|  |     0x00, | ||||||
|  |     0x00, | ||||||
|  |     0x00, | ||||||
|  |     0x00, | ||||||
|  | }; | ||||||
|  | 
 | ||||||
|  | const uint8_t subghz_device_cc1101_preset_2fsk_dev2_38khz_async_regs[] = { | ||||||
|  | 
 | ||||||
|  |     /* GPIO GD0 */ | ||||||
|  |     CC1101_IOCFG0, | ||||||
|  |     0x0D, // GD0 as async serial data output/input
 | ||||||
|  | 
 | ||||||
|  |     /* Frequency Synthesizer Control */ | ||||||
|  |     CC1101_FSCTRL1, | ||||||
|  |     0x06, // IF = (26*10^6) / (2^10) * 0x06 = 152343.75Hz
 | ||||||
|  | 
 | ||||||
|  |     /* Packet engine */ | ||||||
|  |     CC1101_PKTCTRL0, | ||||||
|  |     0x32, // Async, continious, no whitening
 | ||||||
|  |     CC1101_PKTCTRL1, | ||||||
|  |     0x04, | ||||||
|  | 
 | ||||||
|  |     // // Modem Configuration
 | ||||||
|  |     CC1101_MDMCFG0, | ||||||
|  |     0x00, | ||||||
|  |     CC1101_MDMCFG1, | ||||||
|  |     0x02, | ||||||
|  |     CC1101_MDMCFG2, | ||||||
|  |     0x04, // Format 2-FSK/FM, No preamble/sync, Disable (current optimized)
 | ||||||
|  |     CC1101_MDMCFG3, | ||||||
|  |     0x83, // Data rate is 4.79794 kBaud
 | ||||||
|  |     CC1101_MDMCFG4, | ||||||
|  |     0x67, //Rx BW filter is 270.833333 kHz
 | ||||||
|  |     CC1101_DEVIATN, | ||||||
|  |     0x04, //Deviation 2.380371 kHz
 | ||||||
|  | 
 | ||||||
|  |     /* Main Radio Control State Machine */ | ||||||
|  |     CC1101_MCSM0, | ||||||
|  |     0x18, // Autocalibrate on idle-to-rx/tx, PO_TIMEOUT is 64 cycles(149-155us)
 | ||||||
|  | 
 | ||||||
|  |     /* Frequency Offset Compensation Configuration */ | ||||||
|  |     CC1101_FOCCFG, | ||||||
|  |     0x16, // no frequency offset compensation, POST_K same as PRE_K, PRE_K is 4K, GATE is off
 | ||||||
|  | 
 | ||||||
|  |     /* Automatic Gain Control */ | ||||||
|  |     CC1101_AGCCTRL0, | ||||||
|  |     0x91, //10 - Medium hysteresis, medium asymmetric dead zone, medium gain ; 01 - 16 samples agc; 00 - Normal AGC, 01 - 8dB boundary
 | ||||||
|  |     CC1101_AGCCTRL1, | ||||||
|  |     0x00, // 0; 0 - LNA 2 gain is decreased to minimum before decreasing LNA gain; 00 - Relative carrier sense threshold disabled; 0000 - RSSI to MAIN_TARGET
 | ||||||
|  |     CC1101_AGCCTRL2, | ||||||
|  |     0x07, // 00 - DVGA all; 000 - MAX LNA+LNA2; 111 - MAIN_TARGET 42 dB
 | ||||||
|  | 
 | ||||||
|  |     /* Wake on radio and timeouts control */ | ||||||
|  |     CC1101_WORCTRL, | ||||||
|  |     0xFB, // WOR_RES is 2^15 periods (0.91 - 0.94 s) 16.5 - 17.2 hours
 | ||||||
|  | 
 | ||||||
|  |     /* Frontend configuration */ | ||||||
|  |     CC1101_FREND0, | ||||||
|  |     0x10, // Adjusts current TX LO buffer
 | ||||||
|  |     CC1101_FREND1, | ||||||
|  |     0x56, | ||||||
|  | 
 | ||||||
|  |     /* End load reg */ | ||||||
|  |     0, | ||||||
|  |     0, | ||||||
|  | 
 | ||||||
|  |     // 2fsk_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, | ||||||
|  | }; | ||||||
|  | 
 | ||||||
|  | const uint8_t subghz_device_cc1101_preset_2fsk_dev47_6khz_async_regs[] = { | ||||||
|  | 
 | ||||||
|  |     /* GPIO GD0 */ | ||||||
|  |     CC1101_IOCFG0, | ||||||
|  |     0x0D, // GD0 as async serial data output/input
 | ||||||
|  | 
 | ||||||
|  |     /* Frequency Synthesizer Control */ | ||||||
|  |     CC1101_FSCTRL1, | ||||||
|  |     0x06, // IF = (26*10^6) / (2^10) * 0x06 = 152343.75Hz
 | ||||||
|  | 
 | ||||||
|  |     /* Packet engine */ | ||||||
|  |     CC1101_PKTCTRL0, | ||||||
|  |     0x32, // Async, continious, no whitening
 | ||||||
|  |     CC1101_PKTCTRL1, | ||||||
|  |     0x04, | ||||||
|  | 
 | ||||||
|  |     // // Modem Configuration
 | ||||||
|  |     CC1101_MDMCFG0, | ||||||
|  |     0x00, | ||||||
|  |     CC1101_MDMCFG1, | ||||||
|  |     0x02, | ||||||
|  |     CC1101_MDMCFG2, | ||||||
|  |     0x04, // Format 2-FSK/FM, No preamble/sync, Disable (current optimized)
 | ||||||
|  |     CC1101_MDMCFG3, | ||||||
|  |     0x83, // Data rate is 4.79794 kBaud
 | ||||||
|  |     CC1101_MDMCFG4, | ||||||
|  |     0x67, //Rx BW filter is 270.833333 kHz
 | ||||||
|  |     CC1101_DEVIATN, | ||||||
|  |     0x47, //Deviation 47.60742 kHz
 | ||||||
|  | 
 | ||||||
|  |     /* Main Radio Control State Machine */ | ||||||
|  |     CC1101_MCSM0, | ||||||
|  |     0x18, // Autocalibrate on idle-to-rx/tx, PO_TIMEOUT is 64 cycles(149-155us)
 | ||||||
|  | 
 | ||||||
|  |     /* Frequency Offset Compensation Configuration */ | ||||||
|  |     CC1101_FOCCFG, | ||||||
|  |     0x16, // no frequency offset compensation, POST_K same as PRE_K, PRE_K is 4K, GATE is off
 | ||||||
|  | 
 | ||||||
|  |     /* Automatic Gain Control */ | ||||||
|  |     CC1101_AGCCTRL0, | ||||||
|  |     0x91, //10 - Medium hysteresis, medium asymmetric dead zone, medium gain ; 01 - 16 samples agc; 00 - Normal AGC, 01 - 8dB boundary
 | ||||||
|  |     CC1101_AGCCTRL1, | ||||||
|  |     0x00, // 0; 0 - LNA 2 gain is decreased to minimum before decreasing LNA gain; 00 - Relative carrier sense threshold disabled; 0000 - RSSI to MAIN_TARGET
 | ||||||
|  |     CC1101_AGCCTRL2, | ||||||
|  |     0x07, // 00 - DVGA all; 000 - MAX LNA+LNA2; 111 - MAIN_TARGET 42 dB
 | ||||||
|  | 
 | ||||||
|  |     /* Wake on radio and timeouts control */ | ||||||
|  |     CC1101_WORCTRL, | ||||||
|  |     0xFB, // WOR_RES is 2^15 periods (0.91 - 0.94 s) 16.5 - 17.2 hours
 | ||||||
|  | 
 | ||||||
|  |     /* Frontend configuration */ | ||||||
|  |     CC1101_FREND0, | ||||||
|  |     0x10, // Adjusts current TX LO buffer
 | ||||||
|  |     CC1101_FREND1, | ||||||
|  |     0x56, | ||||||
|  | 
 | ||||||
|  |     /* End load reg */ | ||||||
|  |     0, | ||||||
|  |     0, | ||||||
|  | 
 | ||||||
|  |     // 2fsk_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, | ||||||
|  | }; | ||||||
|  | 
 | ||||||
|  | const uint8_t subghz_device_cc1101_preset_msk_99_97kb_async_regs[] = { | ||||||
|  |     /* GPIO GD0 */ | ||||||
|  |     CC1101_IOCFG0, | ||||||
|  |     0x06, | ||||||
|  | 
 | ||||||
|  |     CC1101_FIFOTHR, | ||||||
|  |     0x07, // The only important bit is ADC_RETENTION
 | ||||||
|  |     CC1101_SYNC1, | ||||||
|  |     0x46, | ||||||
|  |     CC1101_SYNC0, | ||||||
|  |     0x4C, | ||||||
|  |     CC1101_ADDR, | ||||||
|  |     0x00, | ||||||
|  |     CC1101_PKTLEN, | ||||||
|  |     0x00, | ||||||
|  |     CC1101_CHANNR, | ||||||
|  |     0x00, | ||||||
|  | 
 | ||||||
|  |     CC1101_PKTCTRL0, | ||||||
|  |     0x05, | ||||||
|  | 
 | ||||||
|  |     CC1101_FSCTRL0, | ||||||
|  |     0x23, | ||||||
|  |     CC1101_FSCTRL1, | ||||||
|  |     0x06, | ||||||
|  | 
 | ||||||
|  |     CC1101_MDMCFG0, | ||||||
|  |     0xF8, | ||||||
|  |     CC1101_MDMCFG1, | ||||||
|  |     0x22, | ||||||
|  |     CC1101_MDMCFG2, | ||||||
|  |     0x72, | ||||||
|  |     CC1101_MDMCFG3, | ||||||
|  |     0xF8, | ||||||
|  |     CC1101_MDMCFG4, | ||||||
|  |     0x5B, | ||||||
|  |     CC1101_DEVIATN, | ||||||
|  |     0x47, | ||||||
|  | 
 | ||||||
|  |     CC1101_MCSM0, | ||||||
|  |     0x18, | ||||||
|  |     CC1101_FOCCFG, | ||||||
|  |     0x16, | ||||||
|  | 
 | ||||||
|  |     CC1101_AGCCTRL0, | ||||||
|  |     0xB2, | ||||||
|  |     CC1101_AGCCTRL1, | ||||||
|  |     0x00, | ||||||
|  |     CC1101_AGCCTRL2, | ||||||
|  |     0xC7, | ||||||
|  | 
 | ||||||
|  |     CC1101_FREND0, | ||||||
|  |     0x10, | ||||||
|  |     CC1101_FREND1, | ||||||
|  |     0x56, | ||||||
|  | 
 | ||||||
|  |     CC1101_BSCFG, | ||||||
|  |     0x1C, | ||||||
|  |     CC1101_FSTEST, | ||||||
|  |     0x59, | ||||||
|  | 
 | ||||||
|  |     /* End load reg */ | ||||||
|  |     0, | ||||||
|  |     0, | ||||||
|  | 
 | ||||||
|  |     // msk_async_patable[8]
 | ||||||
|  |     0xC0, // 10dBm 0xC0, 7dBm 0xC8, 5dBm 0x84, 0dBm 0x60, -10dBm 0x34, -15dBm 0x1D, -20dBm 0x0E, -30dBm 0x12
 | ||||||
|  |     0x00, | ||||||
|  |     0x00, | ||||||
|  |     0x00, | ||||||
|  |     0x00, | ||||||
|  |     0x00, | ||||||
|  |     0x00, | ||||||
|  |     0x00, | ||||||
|  | }; | ||||||
|  | 
 | ||||||
|  | const uint8_t subghz_device_cc1101_preset_gfsk_9_99kb_async_regs[] = { | ||||||
|  | 
 | ||||||
|  |     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
 | ||||||
|  | 
 | ||||||
|  |     /* End load reg */ | ||||||
|  |     0, | ||||||
|  |     0, | ||||||
|  | 
 | ||||||
|  |     // 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, | ||||||
|  | }; | ||||||
							
								
								
									
										18
									
								
								lib/subghz/devices/cc1101_configs.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										18
									
								
								lib/subghz/devices/cc1101_configs.h
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,18 @@ | |||||||
|  | #pragma once | ||||||
|  | #pragma once | ||||||
|  | #include <furi.h> | ||||||
|  | 
 | ||||||
|  | #ifdef __cplusplus | ||||||
|  | extern "C" { | ||||||
|  | #endif | ||||||
|  | 
 | ||||||
|  | extern const uint8_t subghz_device_cc1101_preset_ook_270khz_async_regs[]; | ||||||
|  | extern const uint8_t subghz_device_cc1101_preset_ook_650khz_async_regs[]; | ||||||
|  | extern const uint8_t subghz_device_cc1101_preset_2fsk_dev2_38khz_async_regs[]; | ||||||
|  | extern const uint8_t subghz_device_cc1101_preset_2fsk_dev47_6khz_async_regs[]; | ||||||
|  | extern const uint8_t subghz_device_cc1101_preset_msk_99_97kb_async_regs[]; | ||||||
|  | extern const uint8_t subghz_device_cc1101_preset_gfsk_9_99kb_async_regs[]; | ||||||
|  | 
 | ||||||
|  | #ifdef __cplusplus | ||||||
|  | } | ||||||
|  | #endif | ||||||
							
								
								
									
										96
									
								
								lib/subghz/devices/cc1101_int/cc1101_int_interconnect.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										96
									
								
								lib/subghz/devices/cc1101_int/cc1101_int_interconnect.c
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,96 @@ | |||||||
|  | #include "cc1101_int_interconnect.h" | ||||||
|  | #include <furi_hal.h> | ||||||
|  | #include "../cc1101_configs.h" | ||||||
|  | 
 | ||||||
|  | #define TAG "SubGhzDeviceCC1101Int" | ||||||
|  | 
 | ||||||
|  | static bool subghz_device_cc1101_int_interconnect_is_frequency_valid(uint32_t frequency) { | ||||||
|  |     bool ret = furi_hal_subghz_is_frequency_valid(frequency); | ||||||
|  |     if(!ret) { | ||||||
|  |         furi_crash("SubGhz: Incorrect frequency."); | ||||||
|  |     } | ||||||
|  |     return ret; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | static uint32_t subghz_device_cc1101_int_interconnect_set_frequency(uint32_t frequency) { | ||||||
|  |     subghz_device_cc1101_int_interconnect_is_frequency_valid(frequency); | ||||||
|  |     return furi_hal_subghz_set_frequency_and_path(frequency); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | static bool subghz_device_cc1101_int_interconnect_start_async_tx(void* callback, void* context) { | ||||||
|  |     return furi_hal_subghz_start_async_tx((FuriHalSubGhzAsyncTxCallback)callback, context); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | static void subghz_device_cc1101_int_interconnect_start_async_rx(void* callback, void* context) { | ||||||
|  |     furi_hal_subghz_start_async_rx((FuriHalSubGhzCaptureCallback)callback, context); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | static void subghz_device_cc1101_int_interconnect_load_preset( | ||||||
|  |     FuriHalSubGhzPreset preset, | ||||||
|  |     uint8_t* preset_data) { | ||||||
|  |     switch(preset) { | ||||||
|  |     case FuriHalSubGhzPresetOok650Async: | ||||||
|  |         furi_hal_subghz_load_custom_preset(subghz_device_cc1101_preset_ook_650khz_async_regs); | ||||||
|  |         break; | ||||||
|  |     case FuriHalSubGhzPresetOok270Async: | ||||||
|  |         furi_hal_subghz_load_custom_preset(subghz_device_cc1101_preset_ook_270khz_async_regs); | ||||||
|  |         break; | ||||||
|  |     case FuriHalSubGhzPreset2FSKDev238Async: | ||||||
|  |         furi_hal_subghz_load_custom_preset(subghz_device_cc1101_preset_2fsk_dev2_38khz_async_regs); | ||||||
|  |         break; | ||||||
|  |     case FuriHalSubGhzPreset2FSKDev476Async: | ||||||
|  |         furi_hal_subghz_load_custom_preset(subghz_device_cc1101_preset_2fsk_dev47_6khz_async_regs); | ||||||
|  |         break; | ||||||
|  |     case FuriHalSubGhzPresetMSK99_97KbAsync: | ||||||
|  |         furi_hal_subghz_load_custom_preset(subghz_device_cc1101_preset_msk_99_97kb_async_regs); | ||||||
|  |         break; | ||||||
|  |     case FuriHalSubGhzPresetGFSK9_99KbAsync: | ||||||
|  |         furi_hal_subghz_load_custom_preset(subghz_device_cc1101_preset_gfsk_9_99kb_async_regs); | ||||||
|  |         break; | ||||||
|  | 
 | ||||||
|  |     default: | ||||||
|  |         furi_hal_subghz_load_custom_preset(preset_data); | ||||||
|  |     } | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | static bool subghz_device_cc1101_int_interconnect_is_connect(void) { | ||||||
|  |     return true; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | const SubGhzDeviceInterconnect subghz_device_cc1101_int_interconnect = { | ||||||
|  |     .begin = NULL, | ||||||
|  |     .end = furi_hal_subghz_shutdown, | ||||||
|  |     .is_connect = subghz_device_cc1101_int_interconnect_is_connect, | ||||||
|  |     .reset = furi_hal_subghz_reset, | ||||||
|  |     .sleep = furi_hal_subghz_sleep, | ||||||
|  |     .idle = furi_hal_subghz_idle, | ||||||
|  |     .load_preset = subghz_device_cc1101_int_interconnect_load_preset, | ||||||
|  |     .set_frequency = subghz_device_cc1101_int_interconnect_set_frequency, | ||||||
|  |     .is_frequency_valid = furi_hal_subghz_is_frequency_valid, | ||||||
|  |     .set_async_mirror_pin = furi_hal_subghz_set_async_mirror_pin, | ||||||
|  |     .get_data_gpio = furi_hal_subghz_get_data_gpio, | ||||||
|  | 
 | ||||||
|  |     .set_tx = furi_hal_subghz_tx, | ||||||
|  |     .flush_tx = furi_hal_subghz_flush_tx, | ||||||
|  |     .start_async_tx = subghz_device_cc1101_int_interconnect_start_async_tx, | ||||||
|  |     .is_async_complete_tx = furi_hal_subghz_is_async_tx_complete, | ||||||
|  |     .stop_async_tx = furi_hal_subghz_stop_async_tx, | ||||||
|  | 
 | ||||||
|  |     .set_rx = furi_hal_subghz_rx, | ||||||
|  |     .flush_rx = furi_hal_subghz_flush_rx, | ||||||
|  |     .start_async_rx = subghz_device_cc1101_int_interconnect_start_async_rx, | ||||||
|  |     .stop_async_rx = furi_hal_subghz_stop_async_rx, | ||||||
|  | 
 | ||||||
|  |     .get_rssi = furi_hal_subghz_get_rssi, | ||||||
|  |     .get_lqi = furi_hal_subghz_get_lqi, | ||||||
|  | 
 | ||||||
|  |     .rx_pipe_not_empty = furi_hal_subghz_rx_pipe_not_empty, | ||||||
|  |     .is_rx_data_crc_valid = furi_hal_subghz_is_rx_data_crc_valid, | ||||||
|  |     .read_packet = furi_hal_subghz_read_packet, | ||||||
|  |     .write_packet = furi_hal_subghz_write_packet, | ||||||
|  | }; | ||||||
|  | 
 | ||||||
|  | const SubGhzDevice subghz_device_cc1101_int = { | ||||||
|  |     .name = SUBGHZ_DEVICE_CC1101_INT_NAME, | ||||||
|  |     .interconnect = &subghz_device_cc1101_int_interconnect, | ||||||
|  | }; | ||||||
							
								
								
									
										8
									
								
								lib/subghz/devices/cc1101_int/cc1101_int_interconnect.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										8
									
								
								lib/subghz/devices/cc1101_int/cc1101_int_interconnect.h
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,8 @@ | |||||||
|  | #pragma once | ||||||
|  | #include "../types.h" | ||||||
|  | 
 | ||||||
|  | #define SUBGHZ_DEVICE_CC1101_INT_NAME "cc1101_int" | ||||||
|  | 
 | ||||||
|  | typedef struct SubGhzDeviceCC1101Int SubGhzDeviceCC1101Int; | ||||||
|  | 
 | ||||||
|  | extern const SubGhzDevice subghz_device_cc1101_int; | ||||||
							
								
								
									
										13
									
								
								lib/subghz/devices/device_registry.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										13
									
								
								lib/subghz/devices/device_registry.h
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,13 @@ | |||||||
|  | #pragma once | ||||||
|  | 
 | ||||||
|  | #include "registry.h" | ||||||
|  | 
 | ||||||
|  | #ifdef __cplusplus | ||||||
|  | extern "C" { | ||||||
|  | #endif | ||||||
|  | 
 | ||||||
|  | extern const SubGhzDeviceRegistry subghz_device_registry; | ||||||
|  | 
 | ||||||
|  | #ifdef __cplusplus | ||||||
|  | } | ||||||
|  | #endif | ||||||
							
								
								
									
										236
									
								
								lib/subghz/devices/devices.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										236
									
								
								lib/subghz/devices/devices.c
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,236 @@ | |||||||
|  | #include "devices.h" | ||||||
|  | 
 | ||||||
|  | #include "registry.h" | ||||||
|  | 
 | ||||||
|  | void subghz_devices_init() { | ||||||
|  |     furi_check(!subghz_device_registry_is_valid()); | ||||||
|  |     subghz_device_registry_init(); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | void subghz_devices_deinit(void) { | ||||||
|  |     furi_check(subghz_device_registry_is_valid()); | ||||||
|  |     subghz_device_registry_deinit(); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | const SubGhzDevice* subghz_devices_get_by_name(const char* device_name) { | ||||||
|  |     furi_check(subghz_device_registry_is_valid()); | ||||||
|  |     const SubGhzDevice* device = subghz_device_registry_get_by_name(device_name); | ||||||
|  |     return device; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | const char* subghz_devices_get_name(const SubGhzDevice* device) { | ||||||
|  |     const char* ret = NULL; | ||||||
|  |     if(device) { | ||||||
|  |         ret = device->name; | ||||||
|  |     } | ||||||
|  |     return ret; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | bool subghz_devices_begin(const SubGhzDevice* device) { | ||||||
|  |     bool ret = false; | ||||||
|  |     furi_assert(device); | ||||||
|  |     if(device->interconnect->begin) { | ||||||
|  |         ret = device->interconnect->begin(); | ||||||
|  |     } | ||||||
|  |     return ret; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | void subghz_devices_end(const SubGhzDevice* device) { | ||||||
|  |     furi_assert(device); | ||||||
|  |     if(device->interconnect->end) { | ||||||
|  |         device->interconnect->end(); | ||||||
|  |     } | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | bool subghz_devices_is_connect(const SubGhzDevice* device) { | ||||||
|  |     bool ret = false; | ||||||
|  |     furi_assert(device); | ||||||
|  |     if(device->interconnect->is_connect) { | ||||||
|  |         ret = device->interconnect->is_connect(); | ||||||
|  |     } | ||||||
|  |     return ret; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | void subghz_devices_reset(const SubGhzDevice* device) { | ||||||
|  |     furi_assert(device); | ||||||
|  |     if(device->interconnect->reset) { | ||||||
|  |         device->interconnect->reset(); | ||||||
|  |     } | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | void subghz_devices_sleep(const SubGhzDevice* device) { | ||||||
|  |     furi_assert(device); | ||||||
|  |     if(device->interconnect->sleep) { | ||||||
|  |         device->interconnect->sleep(); | ||||||
|  |     } | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | void subghz_devices_idle(const SubGhzDevice* device) { | ||||||
|  |     furi_assert(device); | ||||||
|  |     if(device->interconnect->idle) { | ||||||
|  |         device->interconnect->idle(); | ||||||
|  |     } | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | void subghz_devices_load_preset( | ||||||
|  |     const SubGhzDevice* device, | ||||||
|  |     FuriHalSubGhzPreset preset, | ||||||
|  |     uint8_t* preset_data) { | ||||||
|  |     furi_assert(device); | ||||||
|  |     if(device->interconnect->load_preset) { | ||||||
|  |         device->interconnect->load_preset(preset, preset_data); | ||||||
|  |     } | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | uint32_t subghz_devices_set_frequency(const SubGhzDevice* device, uint32_t frequency) { | ||||||
|  |     uint32_t ret = 0; | ||||||
|  |     furi_assert(device); | ||||||
|  |     if(device->interconnect->set_frequency) { | ||||||
|  |         ret = device->interconnect->set_frequency(frequency); | ||||||
|  |     } | ||||||
|  |     return ret; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | bool subghz_devices_is_frequency_valid(const SubGhzDevice* device, uint32_t frequency) { | ||||||
|  |     bool ret = false; | ||||||
|  |     furi_assert(device); | ||||||
|  |     if(device->interconnect->is_frequency_valid) { | ||||||
|  |         ret = device->interconnect->is_frequency_valid(frequency); | ||||||
|  |     } | ||||||
|  |     return ret; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | void subghz_devices_set_async_mirror_pin(const SubGhzDevice* device, const GpioPin* gpio) { | ||||||
|  |     furi_assert(device); | ||||||
|  |     if(device->interconnect->set_async_mirror_pin) { | ||||||
|  |         device->interconnect->set_async_mirror_pin(gpio); | ||||||
|  |     } | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | const GpioPin* subghz_devices_get_data_gpio(const SubGhzDevice* device) { | ||||||
|  |     const GpioPin* ret = NULL; | ||||||
|  |     furi_assert(device); | ||||||
|  |     if(device->interconnect->get_data_gpio) { | ||||||
|  |         ret = device->interconnect->get_data_gpio(); | ||||||
|  |     } | ||||||
|  |     return ret; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | bool subghz_devices_set_tx(const SubGhzDevice* device) { | ||||||
|  |     bool ret = 0; | ||||||
|  |     furi_assert(device); | ||||||
|  |     if(device->interconnect->set_tx) { | ||||||
|  |         ret = device->interconnect->set_tx(); | ||||||
|  |     } | ||||||
|  |     return ret; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | void subghz_devices_flush_tx(const SubGhzDevice* device) { | ||||||
|  |     furi_assert(device); | ||||||
|  |     if(device->interconnect->flush_tx) { | ||||||
|  |         device->interconnect->flush_tx(); | ||||||
|  |     } | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | bool subghz_devices_start_async_tx(const SubGhzDevice* device, void* callback, void* context) { | ||||||
|  |     bool ret = false; | ||||||
|  |     furi_assert(device); | ||||||
|  |     if(device->interconnect->start_async_tx) { | ||||||
|  |         ret = device->interconnect->start_async_tx(callback, context); | ||||||
|  |     } | ||||||
|  |     return ret; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | bool subghz_devices_is_async_complete_tx(const SubGhzDevice* device) { | ||||||
|  |     bool ret = false; | ||||||
|  |     furi_assert(device); | ||||||
|  |     if(device->interconnect->is_async_complete_tx) { | ||||||
|  |         ret = device->interconnect->is_async_complete_tx(); | ||||||
|  |     } | ||||||
|  |     return ret; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | void subghz_devices_stop_async_tx(const SubGhzDevice* device) { | ||||||
|  |     furi_assert(device); | ||||||
|  |     if(device->interconnect->stop_async_tx) { | ||||||
|  |         device->interconnect->stop_async_tx(); | ||||||
|  |     } | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | void subghz_devices_set_rx(const SubGhzDevice* device) { | ||||||
|  |     furi_assert(device); | ||||||
|  |     if(device->interconnect->set_rx) { | ||||||
|  |         device->interconnect->set_rx(); | ||||||
|  |     } | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | void subghz_devices_flush_rx(const SubGhzDevice* device) { | ||||||
|  |     furi_assert(device); | ||||||
|  |     if(device->interconnect->flush_rx) { | ||||||
|  |         device->interconnect->flush_rx(); | ||||||
|  |     } | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | void subghz_devices_start_async_rx(const SubGhzDevice* device, void* callback, void* context) { | ||||||
|  |     furi_assert(device); | ||||||
|  |     if(device->interconnect->start_async_rx) { | ||||||
|  |         device->interconnect->start_async_rx(callback, context); | ||||||
|  |     } | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | void subghz_devices_stop_async_rx(const SubGhzDevice* device) { | ||||||
|  |     furi_assert(device); | ||||||
|  |     if(device->interconnect->stop_async_rx) { | ||||||
|  |         device->interconnect->stop_async_rx(); | ||||||
|  |     } | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | float subghz_devices_get_rssi(const SubGhzDevice* device) { | ||||||
|  |     float ret = 0; | ||||||
|  |     furi_assert(device); | ||||||
|  |     if(device->interconnect->get_rssi) { | ||||||
|  |         ret = device->interconnect->get_rssi(); | ||||||
|  |     } | ||||||
|  |     return ret; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | uint8_t subghz_devices_get_lqi(const SubGhzDevice* device) { | ||||||
|  |     uint8_t ret = 0; | ||||||
|  |     furi_assert(device); | ||||||
|  |     if(device->interconnect->get_lqi) { | ||||||
|  |         ret = device->interconnect->get_lqi(); | ||||||
|  |     } | ||||||
|  |     return ret; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | bool subghz_devices_rx_pipe_not_empty(const SubGhzDevice* device) { | ||||||
|  |     bool ret = false; | ||||||
|  |     furi_assert(device); | ||||||
|  |     if(device->interconnect->rx_pipe_not_empty) { | ||||||
|  |         ret = device->interconnect->rx_pipe_not_empty(); | ||||||
|  |     } | ||||||
|  |     return ret; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | bool subghz_devices_is_rx_data_crc_valid(const SubGhzDevice* device) { | ||||||
|  |     bool ret = false; | ||||||
|  |     furi_assert(device); | ||||||
|  |     if(device->interconnect->is_rx_data_crc_valid) { | ||||||
|  |         ret = device->interconnect->is_rx_data_crc_valid(); | ||||||
|  |     } | ||||||
|  |     return ret; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | void subghz_devices_read_packet(const SubGhzDevice* device, uint8_t* data, uint8_t* size) { | ||||||
|  |     furi_assert(device); | ||||||
|  |     if(device->interconnect->read_packet) { | ||||||
|  |         device->interconnect->read_packet(data, size); | ||||||
|  |     } | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | void subghz_devices_write_packet(const SubGhzDevice* device, const uint8_t* data, uint8_t size) { | ||||||
|  |     furi_assert(device); | ||||||
|  |     if(device->interconnect->write_packet) { | ||||||
|  |         device->interconnect->write_packet(data, size); | ||||||
|  |     } | ||||||
|  | } | ||||||
							
								
								
									
										52
									
								
								lib/subghz/devices/devices.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										52
									
								
								lib/subghz/devices/devices.h
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,52 @@ | |||||||
|  | #pragma once | ||||||
|  | 
 | ||||||
|  | #include "types.h" | ||||||
|  | 
 | ||||||
|  | #ifdef __cplusplus | ||||||
|  | extern "C" { | ||||||
|  | #endif | ||||||
|  | 
 | ||||||
|  | typedef struct SubGhzDevice SubGhzDevice; | ||||||
|  | 
 | ||||||
|  | void subghz_devices_init(); | ||||||
|  | void subghz_devices_deinit(void); | ||||||
|  | 
 | ||||||
|  | const SubGhzDevice* subghz_devices_get_by_name(const char* device_name); | ||||||
|  | const char* subghz_devices_get_name(const SubGhzDevice* device); | ||||||
|  | bool subghz_devices_begin(const SubGhzDevice* device); | ||||||
|  | void subghz_devices_end(const SubGhzDevice* device); | ||||||
|  | bool subghz_devices_is_connect(const SubGhzDevice* device); | ||||||
|  | void subghz_devices_reset(const SubGhzDevice* device); | ||||||
|  | void subghz_devices_sleep(const SubGhzDevice* device); | ||||||
|  | void subghz_devices_idle(const SubGhzDevice* device); | ||||||
|  | void subghz_devices_load_preset( | ||||||
|  |     const SubGhzDevice* device, | ||||||
|  |     FuriHalSubGhzPreset preset, | ||||||
|  |     uint8_t* preset_data); | ||||||
|  | uint32_t subghz_devices_set_frequency(const SubGhzDevice* device, uint32_t frequency); | ||||||
|  | bool subghz_devices_is_frequency_valid(const SubGhzDevice* device, uint32_t frequency); | ||||||
|  | void subghz_devices_set_async_mirror_pin(const SubGhzDevice* device, const GpioPin* gpio); | ||||||
|  | const GpioPin* subghz_devices_get_data_gpio(const SubGhzDevice* device); | ||||||
|  | 
 | ||||||
|  | bool subghz_devices_set_tx(const SubGhzDevice* device); | ||||||
|  | void subghz_devices_flush_tx(const SubGhzDevice* device); | ||||||
|  | bool subghz_devices_start_async_tx(const SubGhzDevice* device, void* callback, void* context); | ||||||
|  | bool subghz_devices_is_async_complete_tx(const SubGhzDevice* device); | ||||||
|  | void subghz_devices_stop_async_tx(const SubGhzDevice* device); | ||||||
|  | 
 | ||||||
|  | void subghz_devices_set_rx(const SubGhzDevice* device); | ||||||
|  | void subghz_devices_flush_rx(const SubGhzDevice* device); | ||||||
|  | void subghz_devices_start_async_rx(const SubGhzDevice* device, void* callback, void* context); | ||||||
|  | void subghz_devices_stop_async_rx(const SubGhzDevice* device); | ||||||
|  | 
 | ||||||
|  | float subghz_devices_get_rssi(const SubGhzDevice* device); | ||||||
|  | uint8_t subghz_devices_get_lqi(const SubGhzDevice* device); | ||||||
|  | 
 | ||||||
|  | bool subghz_devices_rx_pipe_not_empty(const SubGhzDevice* device); | ||||||
|  | bool subghz_devices_is_rx_data_crc_valid(const SubGhzDevice* device); | ||||||
|  | void subghz_devices_read_packet(const SubGhzDevice* device, uint8_t* data, uint8_t* size); | ||||||
|  | void subghz_devices_write_packet(const SubGhzDevice* device, const uint8_t* data, uint8_t size); | ||||||
|  | 
 | ||||||
|  | #ifdef __cplusplus | ||||||
|  | } | ||||||
|  | #endif | ||||||
							
								
								
									
										13
									
								
								lib/subghz/devices/preset.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										13
									
								
								lib/subghz/devices/preset.h
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,13 @@ | |||||||
|  | #pragma once | ||||||
|  | 
 | ||||||
|  | /** Radio Presets */ | ||||||
|  | typedef enum { | ||||||
|  |     FuriHalSubGhzPresetIDLE, /**< default configuration */ | ||||||
|  |     FuriHalSubGhzPresetOok270Async, /**< OOK, bandwidth 270kHz, asynchronous */ | ||||||
|  |     FuriHalSubGhzPresetOok650Async, /**< OOK, bandwidth 650kHz, asynchronous */ | ||||||
|  |     FuriHalSubGhzPreset2FSKDev238Async, /**< FM, deviation 2.380371 kHz, asynchronous */ | ||||||
|  |     FuriHalSubGhzPreset2FSKDev476Async, /**< FM, deviation 47.60742 kHz, asynchronous */ | ||||||
|  |     FuriHalSubGhzPresetMSK99_97KbAsync, /**< MSK, deviation 47.60742 kHz, 99.97Kb/s, asynchronous */ | ||||||
|  |     FuriHalSubGhzPresetGFSK9_99KbAsync, /**< GFSK, deviation 19.042969 kHz, 9.996Kb/s, asynchronous */ | ||||||
|  |     FuriHalSubGhzPresetCustom, /**Custom Preset*/ | ||||||
|  | } FuriHalSubGhzPreset; | ||||||
							
								
								
									
										76
									
								
								lib/subghz/devices/registry.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										76
									
								
								lib/subghz/devices/registry.c
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,76 @@ | |||||||
|  | #include "registry.h" | ||||||
|  | 
 | ||||||
|  | #include "cc1101_int/cc1101_int_interconnect.h" | ||||||
|  | #include <flipper_application/plugins/plugin_manager.h> | ||||||
|  | #include <loader/firmware_api/firmware_api.h> | ||||||
|  | 
 | ||||||
|  | #define TAG "SubGhzDeviceRegistry" | ||||||
|  | 
 | ||||||
|  | struct SubGhzDeviceRegistry { | ||||||
|  |     const SubGhzDevice** items; | ||||||
|  |     size_t size; | ||||||
|  |     PluginManager* manager; | ||||||
|  | }; | ||||||
|  | 
 | ||||||
|  | static SubGhzDeviceRegistry* subghz_device_registry = NULL; | ||||||
|  | 
 | ||||||
|  | void subghz_device_registry_init(void) { | ||||||
|  |     SubGhzDeviceRegistry* subghz_device = | ||||||
|  |         (SubGhzDeviceRegistry*)malloc(sizeof(SubGhzDeviceRegistry)); | ||||||
|  |     subghz_device->manager = plugin_manager_alloc( | ||||||
|  |         SUBGHZ_RADIO_DEVICE_PLUGIN_APP_ID, | ||||||
|  |         SUBGHZ_RADIO_DEVICE_PLUGIN_API_VERSION, | ||||||
|  |         firmware_api_interface); | ||||||
|  | 
 | ||||||
|  |     //ToDo: fix path to plugins
 | ||||||
|  |     if(plugin_manager_load_all(subghz_device->manager, "/any/apps_data/subghz/plugins") != | ||||||
|  |        //if(plugin_manager_load_all(subghz_device->manager, APP_DATA_PATH("plugins")) !=
 | ||||||
|  |        PluginManagerErrorNone) { | ||||||
|  |         FURI_LOG_E(TAG, "Failed to load all libs"); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     subghz_device->size = plugin_manager_get_count(subghz_device->manager) + 1; | ||||||
|  |     subghz_device->items = | ||||||
|  |         (const SubGhzDevice**)malloc(sizeof(SubGhzDevice*) * subghz_device->size); | ||||||
|  |     subghz_device->items[0] = &subghz_device_cc1101_int; | ||||||
|  |     for(uint32_t i = 1; i < subghz_device->size; i++) { | ||||||
|  |         const SubGhzDevice* plugin = plugin_manager_get_ep(subghz_device->manager, i - 1); | ||||||
|  |         subghz_device->items[i] = plugin; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     FURI_LOG_I(TAG, "Loaded %zu radio device", subghz_device->size); | ||||||
|  |     subghz_device_registry = subghz_device; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | void subghz_device_registry_deinit(void) { | ||||||
|  |     plugin_manager_free(subghz_device_registry->manager); | ||||||
|  |     free(subghz_device_registry->items); | ||||||
|  |     free(subghz_device_registry); | ||||||
|  |     subghz_device_registry = NULL; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | bool subghz_device_registry_is_valid(void) { | ||||||
|  |     return subghz_device_registry != NULL; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | const SubGhzDevice* subghz_device_registry_get_by_name(const char* name) { | ||||||
|  |     furi_assert(subghz_device_registry); | ||||||
|  | 
 | ||||||
|  |     if(name != NULL) { | ||||||
|  |         for(size_t i = 0; i < subghz_device_registry->size; i++) { | ||||||
|  |             if(strcmp(name, subghz_device_registry->items[i]->name) == 0) { | ||||||
|  |                 return subghz_device_registry->items[i]; | ||||||
|  |             } | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  |     return NULL; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | const SubGhzDevice* subghz_device_registry_get_by_index(size_t index) { | ||||||
|  |     furi_assert(subghz_device_registry); | ||||||
|  |     if(index < subghz_device_registry->size) { | ||||||
|  |         return subghz_device_registry->items[index]; | ||||||
|  |     } else { | ||||||
|  |         return NULL; | ||||||
|  |     } | ||||||
|  | } | ||||||
							
								
								
									
										40
									
								
								lib/subghz/devices/registry.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										40
									
								
								lib/subghz/devices/registry.h
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,40 @@ | |||||||
|  | #pragma once | ||||||
|  | 
 | ||||||
|  | #include "types.h" | ||||||
|  | 
 | ||||||
|  | #ifdef __cplusplus | ||||||
|  | extern "C" { | ||||||
|  | #endif | ||||||
|  | 
 | ||||||
|  | typedef struct SubGhzDevice SubGhzDevice; | ||||||
|  | 
 | ||||||
|  | void subghz_device_registry_init(void); | ||||||
|  | 
 | ||||||
|  | void subghz_device_registry_deinit(void); | ||||||
|  | 
 | ||||||
|  | bool subghz_device_registry_is_valid(void); | ||||||
|  | 
 | ||||||
|  | /**
 | ||||||
|  |  * Registration by name SubGhzDevice. | ||||||
|  |  * @param name SubGhzDevice name | ||||||
|  |  * @return SubGhzDevice* pointer to a SubGhzDevice instance | ||||||
|  |  */ | ||||||
|  | const SubGhzDevice* subghz_device_registry_get_by_name(const char* name); | ||||||
|  | 
 | ||||||
|  | /**
 | ||||||
|  |  * Registration subghzdevice by index in array SubGhzDevice. | ||||||
|  |  * @param index SubGhzDevice by index in array | ||||||
|  |  * @return SubGhzDevice* pointer to a SubGhzDevice instance | ||||||
|  |  */ | ||||||
|  | const SubGhzDevice* subghz_device_registry_get_by_index(size_t index); | ||||||
|  | 
 | ||||||
|  | /**
 | ||||||
|  |  * Getting the number of registered subghzdevices. | ||||||
|  |  * @param subghz_device SubGhzDeviceRegistry | ||||||
|  |  * @return Number of subghzdevices | ||||||
|  |  */ | ||||||
|  | size_t subghz_device_registry_count(void); | ||||||
|  | 
 | ||||||
|  | #ifdef __cplusplus | ||||||
|  | } | ||||||
|  | #endif | ||||||
							
								
								
									
										91
									
								
								lib/subghz/devices/types.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										91
									
								
								lib/subghz/devices/types.h
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,91 @@ | |||||||
|  | #pragma once | ||||||
|  | 
 | ||||||
|  | #include <stdbool.h> | ||||||
|  | #include <stdint.h> | ||||||
|  | #include <stddef.h> | ||||||
|  | 
 | ||||||
|  | #include <furi.h> | ||||||
|  | #include <furi_hal.h> | ||||||
|  | 
 | ||||||
|  | #include "preset.h" | ||||||
|  | 
 | ||||||
|  | #include <flipper_application/flipper_application.h> | ||||||
|  | 
 | ||||||
|  | #define SUBGHZ_RADIO_DEVICE_PLUGIN_APP_ID "subghz_radio_device" | ||||||
|  | #define SUBGHZ_RADIO_DEVICE_PLUGIN_API_VERSION 1 | ||||||
|  | 
 | ||||||
|  | typedef struct SubGhzDeviceRegistry SubGhzDeviceRegistry; | ||||||
|  | typedef struct SubGhzDevice SubGhzDevice; | ||||||
|  | 
 | ||||||
|  | typedef bool (*SubGhzBegin)(void); | ||||||
|  | typedef void (*SubGhzEnd)(void); | ||||||
|  | typedef bool (*SubGhzIsConnect)(void); | ||||||
|  | typedef void (*SubGhzReset)(void); | ||||||
|  | typedef void (*SubGhzSleep)(void); | ||||||
|  | typedef void (*SubGhzIdle)(void); | ||||||
|  | typedef void (*SubGhzLoadPreset)(FuriHalSubGhzPreset preset, uint8_t* preset_data); | ||||||
|  | typedef uint32_t (*SubGhzSetFrequency)(uint32_t frequency); | ||||||
|  | typedef bool (*SubGhzIsFrequencyValid)(uint32_t frequency); | ||||||
|  | 
 | ||||||
|  | typedef void (*SubGhzSetAsyncMirrorPin)(const GpioPin* gpio); | ||||||
|  | typedef const GpioPin* (*SubGhzGetDataGpio)(void); | ||||||
|  | 
 | ||||||
|  | typedef bool (*SubGhzSetTx)(void); | ||||||
|  | typedef void (*SubGhzFlushTx)(void); | ||||||
|  | typedef bool (*SubGhzStartAsyncTx)(void* callback, void* context); | ||||||
|  | typedef bool (*SubGhzIsAsyncCompleteTx)(void); | ||||||
|  | typedef void (*SubGhzStopAsyncTx)(void); | ||||||
|  | 
 | ||||||
|  | typedef void (*SubGhzSetRx)(void); | ||||||
|  | typedef void (*SubGhzFlushRx)(void); | ||||||
|  | typedef void (*SubGhzStartAsyncRx)(void* callback, void* context); | ||||||
|  | typedef void (*SubGhzStopAsyncRx)(void); | ||||||
|  | 
 | ||||||
|  | typedef float (*SubGhzGetRSSI)(void); | ||||||
|  | typedef uint8_t (*SubGhzGetLQI)(void); | ||||||
|  | 
 | ||||||
|  | typedef bool (*SubGhzRxPipeNotEmpty)(void); | ||||||
|  | typedef bool (*SubGhzRxIsDataCrcValid)(void); | ||||||
|  | typedef void (*SubGhzReadPacket)(uint8_t* data, uint8_t* size); | ||||||
|  | typedef void (*SubGhzWritePacket)(const uint8_t* data, uint8_t size); | ||||||
|  | 
 | ||||||
|  | typedef struct { | ||||||
|  |     SubGhzBegin begin; | ||||||
|  |     SubGhzEnd end; | ||||||
|  | 
 | ||||||
|  |     SubGhzIsConnect is_connect; | ||||||
|  |     SubGhzReset reset; | ||||||
|  |     SubGhzSleep sleep; | ||||||
|  |     SubGhzIdle idle; | ||||||
|  | 
 | ||||||
|  |     SubGhzLoadPreset load_preset; | ||||||
|  |     SubGhzSetFrequency set_frequency; | ||||||
|  |     SubGhzIsFrequencyValid is_frequency_valid; | ||||||
|  |     SubGhzSetAsyncMirrorPin set_async_mirror_pin; | ||||||
|  |     SubGhzGetDataGpio get_data_gpio; | ||||||
|  | 
 | ||||||
|  |     SubGhzSetTx set_tx; | ||||||
|  |     SubGhzFlushTx flush_tx; | ||||||
|  |     SubGhzStartAsyncTx start_async_tx; | ||||||
|  |     SubGhzIsAsyncCompleteTx is_async_complete_tx; | ||||||
|  |     SubGhzStopAsyncTx stop_async_tx; | ||||||
|  | 
 | ||||||
|  |     SubGhzSetRx set_rx; | ||||||
|  |     SubGhzFlushRx flush_rx; | ||||||
|  |     SubGhzStartAsyncRx start_async_rx; | ||||||
|  |     SubGhzStopAsyncRx stop_async_rx; | ||||||
|  | 
 | ||||||
|  |     SubGhzGetRSSI get_rssi; | ||||||
|  |     SubGhzGetLQI get_lqi; | ||||||
|  | 
 | ||||||
|  |     SubGhzRxPipeNotEmpty rx_pipe_not_empty; | ||||||
|  |     SubGhzRxIsDataCrcValid is_rx_data_crc_valid; | ||||||
|  |     SubGhzReadPacket read_packet; | ||||||
|  |     SubGhzWritePacket write_packet; | ||||||
|  | 
 | ||||||
|  | } SubGhzDeviceInterconnect; | ||||||
|  | 
 | ||||||
|  | struct SubGhzDevice { | ||||||
|  |     const char* name; | ||||||
|  |     const SubGhzDeviceInterconnect* interconnect; | ||||||
|  | }; | ||||||
| @ -40,6 +40,7 @@ struct SubGhzProtocolEncoderRAW { | |||||||
| 
 | 
 | ||||||
|     bool is_running; |     bool is_running; | ||||||
|     FuriString* file_name; |     FuriString* file_name; | ||||||
|  |     FuriString* radio_device_name; | ||||||
|     SubGhzFileEncoderWorker* file_worker_encoder; |     SubGhzFileEncoderWorker* file_worker_encoder; | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| @ -282,6 +283,7 @@ void* subghz_protocol_encoder_raw_alloc(SubGhzEnvironment* environment) { | |||||||
| 
 | 
 | ||||||
|     instance->base.protocol = &subghz_protocol_raw; |     instance->base.protocol = &subghz_protocol_raw; | ||||||
|     instance->file_name = furi_string_alloc(); |     instance->file_name = furi_string_alloc(); | ||||||
|  |     instance->radio_device_name = furi_string_alloc(); | ||||||
|     instance->is_running = false; |     instance->is_running = false; | ||||||
|     return instance; |     return instance; | ||||||
| } | } | ||||||
| @ -300,6 +302,7 @@ void subghz_protocol_encoder_raw_free(void* context) { | |||||||
|     SubGhzProtocolEncoderRAW* instance = context; |     SubGhzProtocolEncoderRAW* instance = context; | ||||||
|     subghz_protocol_encoder_raw_stop(instance); |     subghz_protocol_encoder_raw_stop(instance); | ||||||
|     furi_string_free(instance->file_name); |     furi_string_free(instance->file_name); | ||||||
|  |     furi_string_free(instance->radio_device_name); | ||||||
|     free(instance); |     free(instance); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| @ -318,7 +321,9 @@ static bool subghz_protocol_encoder_raw_worker_init(SubGhzProtocolEncoderRAW* in | |||||||
| 
 | 
 | ||||||
|     instance->file_worker_encoder = subghz_file_encoder_worker_alloc(); |     instance->file_worker_encoder = subghz_file_encoder_worker_alloc(); | ||||||
|     if(subghz_file_encoder_worker_start( |     if(subghz_file_encoder_worker_start( | ||||||
|            instance->file_worker_encoder, furi_string_get_cstr(instance->file_name))) { |            instance->file_worker_encoder, | ||||||
|  |            furi_string_get_cstr(instance->file_name), | ||||||
|  |            furi_string_get_cstr(instance->radio_device_name))) { | ||||||
|         //the worker needs a file in order to open and read part of the file
 |         //the worker needs a file in order to open and read part of the file
 | ||||||
|         furi_delay_ms(100); |         furi_delay_ms(100); | ||||||
|         instance->is_running = true; |         instance->is_running = true; | ||||||
| @ -328,7 +333,10 @@ static bool subghz_protocol_encoder_raw_worker_init(SubGhzProtocolEncoderRAW* in | |||||||
|     return instance->is_running; |     return instance->is_running; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void subghz_protocol_raw_gen_fff_data(FlipperFormat* flipper_format, const char* file_path) { | void subghz_protocol_raw_gen_fff_data( | ||||||
|  |     FlipperFormat* flipper_format, | ||||||
|  |     const char* file_path, | ||||||
|  |     const char* radio_device_name) { | ||||||
|     do { |     do { | ||||||
|         stream_clean(flipper_format_get_raw_stream(flipper_format)); |         stream_clean(flipper_format_get_raw_stream(flipper_format)); | ||||||
|         if(!flipper_format_write_string_cstr(flipper_format, "Protocol", "RAW")) { |         if(!flipper_format_write_string_cstr(flipper_format, "Protocol", "RAW")) { | ||||||
| @ -340,6 +348,12 @@ void subghz_protocol_raw_gen_fff_data(FlipperFormat* flipper_format, const char* | |||||||
|             FURI_LOG_E(TAG, "Unable to add File_name"); |             FURI_LOG_E(TAG, "Unable to add File_name"); | ||||||
|             break; |             break; | ||||||
|         } |         } | ||||||
|  | 
 | ||||||
|  |         if(!flipper_format_write_string_cstr( | ||||||
|  |                flipper_format, "Radio_device_name", radio_device_name)) { | ||||||
|  |             FURI_LOG_E(TAG, "Unable to add Radio_device_name"); | ||||||
|  |             break; | ||||||
|  |         } | ||||||
|     } while(false); |     } while(false); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| @ -364,6 +378,13 @@ SubGhzProtocolStatus | |||||||
|         } |         } | ||||||
|         furi_string_set(instance->file_name, temp_str); |         furi_string_set(instance->file_name, temp_str); | ||||||
| 
 | 
 | ||||||
|  |         if(!flipper_format_read_string(flipper_format, "Radio_device_name", temp_str)) { | ||||||
|  |             FURI_LOG_E(TAG, "Missing Radio_device_name"); | ||||||
|  |             res = SubGhzProtocolStatusErrorParserOthers; | ||||||
|  |             break; | ||||||
|  |         } | ||||||
|  |         furi_string_set(instance->radio_device_name, temp_str); | ||||||
|  | 
 | ||||||
|         if(!subghz_protocol_encoder_raw_worker_init(instance)) { |         if(!subghz_protocol_encoder_raw_worker_init(instance)) { | ||||||
|             res = SubGhzProtocolStatusErrorEncoderGetUpload; |             res = SubGhzProtocolStatusErrorEncoderGetUpload; | ||||||
|             break; |             break; | ||||||
|  | |||||||
| @ -126,8 +126,12 @@ void subghz_protocol_raw_file_encoder_worker_set_callback_end( | |||||||
|  * File generation for RAW work. |  * File generation for RAW work. | ||||||
|  * @param flipper_format Pointer to a FlipperFormat instance |  * @param flipper_format Pointer to a FlipperFormat instance | ||||||
|  * @param file_path File path |  * @param file_path File path | ||||||
|  |  * @param radio_dev_name Radio device name | ||||||
|  */ |  */ | ||||||
| void subghz_protocol_raw_gen_fff_data(FlipperFormat* flipper_format, const char* file_path); | void subghz_protocol_raw_gen_fff_data( | ||||||
|  |     FlipperFormat* flipper_format, | ||||||
|  |     const char* file_path, | ||||||
|  |     const char* radio_dev_name); | ||||||
| 
 | 
 | ||||||
| /**
 | /**
 | ||||||
|  * Deserialize and generating an upload to send. |  * Deserialize and generating an upload to send. | ||||||
|  | |||||||
| @ -3,6 +3,7 @@ | |||||||
| #include <toolbox/stream/stream.h> | #include <toolbox/stream/stream.h> | ||||||
| #include <flipper_format/flipper_format.h> | #include <flipper_format/flipper_format.h> | ||||||
| #include <flipper_format/flipper_format_i.h> | #include <flipper_format/flipper_format_i.h> | ||||||
|  | #include <lib/subghz/devices/devices.h> | ||||||
| 
 | 
 | ||||||
| #define TAG "SubGhzFileEncoderWorker" | #define TAG "SubGhzFileEncoderWorker" | ||||||
| 
 | 
 | ||||||
| @ -21,6 +22,7 @@ struct SubGhzFileEncoderWorker { | |||||||
|     bool is_storage_slow; |     bool is_storage_slow; | ||||||
|     FuriString* str_data; |     FuriString* str_data; | ||||||
|     FuriString* file_path; |     FuriString* file_path; | ||||||
|  |     const SubGhzDevice* device; | ||||||
| 
 | 
 | ||||||
|     SubGhzFileEncoderWorkerCallbackEnd callback_end; |     SubGhzFileEncoderWorkerCallbackEnd callback_end; | ||||||
|     void* context_end; |     void* context_end; | ||||||
| @ -156,10 +158,13 @@ static int32_t subghz_file_encoder_worker_thread(void* context) { | |||||||
|     if(instance->is_storage_slow) { |     if(instance->is_storage_slow) { | ||||||
|         FURI_LOG_E(TAG, "Storage is slow"); |         FURI_LOG_E(TAG, "Storage is slow"); | ||||||
|     } |     } | ||||||
|  | 
 | ||||||
|     FURI_LOG_I(TAG, "End read file"); |     FURI_LOG_I(TAG, "End read file"); | ||||||
|     while(!furi_hal_subghz_is_async_tx_complete() && instance->worker_running) { |     while(instance->device && !subghz_devices_is_async_complete_tx(instance->device) && | ||||||
|  |           instance->worker_running) { | ||||||
|         furi_delay_ms(5); |         furi_delay_ms(5); | ||||||
|     } |     } | ||||||
|  | 
 | ||||||
|     FURI_LOG_I(TAG, "End transmission"); |     FURI_LOG_I(TAG, "End transmission"); | ||||||
|     while(instance->worker_running) { |     while(instance->worker_running) { | ||||||
|         if(instance->worker_stoping) { |         if(instance->worker_stoping) { | ||||||
| @ -206,12 +211,16 @@ void subghz_file_encoder_worker_free(SubGhzFileEncoderWorker* instance) { | |||||||
|     free(instance); |     free(instance); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| bool subghz_file_encoder_worker_start(SubGhzFileEncoderWorker* instance, const char* file_path) { | bool subghz_file_encoder_worker_start( | ||||||
|  |     SubGhzFileEncoderWorker* instance, | ||||||
|  |     const char* file_path, | ||||||
|  |     const char* radio_device_name) { | ||||||
|     furi_assert(instance); |     furi_assert(instance); | ||||||
|     furi_assert(!instance->worker_running); |     furi_assert(!instance->worker_running); | ||||||
| 
 | 
 | ||||||
|     furi_stream_buffer_reset(instance->stream); |     furi_stream_buffer_reset(instance->stream); | ||||||
|     furi_string_set(instance->file_path, file_path); |     furi_string_set(instance->file_path, file_path); | ||||||
|  |     instance->device = subghz_devices_get_by_name(radio_device_name); | ||||||
|     instance->worker_running = true; |     instance->worker_running = true; | ||||||
|     furi_thread_start(instance->thread); |     furi_thread_start(instance->thread); | ||||||
| 
 | 
 | ||||||
|  | |||||||
| @ -38,9 +38,14 @@ LevelDuration subghz_file_encoder_worker_get_level_duration(void* context); | |||||||
| /** 
 | /** 
 | ||||||
|  * Start SubGhzFileEncoderWorker. |  * Start SubGhzFileEncoderWorker. | ||||||
|  * @param instance Pointer to a SubGhzFileEncoderWorker instance |  * @param instance Pointer to a SubGhzFileEncoderWorker instance | ||||||
|  |  * @param file_path File path | ||||||
|  |  * @param radio_device_name Radio device name | ||||||
|  * @return bool - true if ok |  * @return bool - true if ok | ||||||
|  */ |  */ | ||||||
| bool subghz_file_encoder_worker_start(SubGhzFileEncoderWorker* instance, const char* file_path); | bool subghz_file_encoder_worker_start( | ||||||
|  |     SubGhzFileEncoderWorker* instance, | ||||||
|  |     const char* file_path, | ||||||
|  |     const char* radio_device_name); | ||||||
| 
 | 
 | ||||||
| /** 
 | /** 
 | ||||||
|  * Stop SubGhzFileEncoderWorker |  * Stop SubGhzFileEncoderWorker | ||||||
|  | |||||||
| @ -4,7 +4,7 @@ | |||||||
| 
 | 
 | ||||||
| #include <furi.h> | #include <furi.h> | ||||||
| #include <m-list.h> | #include <m-list.h> | ||||||
| #include <furi_hal_subghz_configs.h> | #include <lib/subghz/devices/cc1101_configs.h> | ||||||
| 
 | 
 | ||||||
| #define TAG "SubGhzSetting" | #define TAG "SubGhzSetting" | ||||||
| 
 | 
 | ||||||
| @ -218,8 +218,7 @@ void subghz_setting_free(SubGhzSetting* instance) { | |||||||
| static void subghz_setting_load_default_preset( | static void subghz_setting_load_default_preset( | ||||||
|     SubGhzSetting* instance, |     SubGhzSetting* instance, | ||||||
|     const char* preset_name, |     const char* preset_name, | ||||||
|     const uint8_t* preset_data, |     const uint8_t* preset_data) { | ||||||
|     const uint8_t preset_pa_table[8]) { |  | ||||||
|     furi_assert(instance); |     furi_assert(instance); | ||||||
|     furi_assert(preset_data); |     furi_assert(preset_data); | ||||||
|     uint32_t preset_data_count = 0; |     uint32_t preset_data_count = 0; | ||||||
| @ -235,10 +234,8 @@ static void subghz_setting_load_default_preset( | |||||||
|     preset_data_count += 2; |     preset_data_count += 2; | ||||||
|     item->custom_preset_data_size = sizeof(uint8_t) * preset_data_count + sizeof(uint8_t) * 8; |     item->custom_preset_data_size = sizeof(uint8_t) * preset_data_count + sizeof(uint8_t) * 8; | ||||||
|     item->custom_preset_data = malloc(item->custom_preset_data_size); |     item->custom_preset_data = malloc(item->custom_preset_data_size); | ||||||
|     //load preset register
 |     //load preset register + pa table
 | ||||||
|     memcpy(&item->custom_preset_data[0], &preset_data[0], preset_data_count); |     memcpy(&item->custom_preset_data[0], &preset_data[0], item->custom_preset_data_size); | ||||||
|     //load pa table
 |  | ||||||
|     memcpy(&item->custom_preset_data[preset_data_count], &preset_pa_table[0], 8); |  | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| static void subghz_setting_load_default_region( | static void subghz_setting_load_default_region( | ||||||
| @ -262,25 +259,13 @@ static void subghz_setting_load_default_region( | |||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     subghz_setting_load_default_preset( |     subghz_setting_load_default_preset( | ||||||
|         instance, |         instance, "AM270", subghz_device_cc1101_preset_ook_270khz_async_regs); | ||||||
|         "AM270", |  | ||||||
|         (uint8_t*)furi_hal_subghz_preset_ook_270khz_async_regs, |  | ||||||
|         furi_hal_subghz_preset_ook_async_patable); |  | ||||||
|     subghz_setting_load_default_preset( |     subghz_setting_load_default_preset( | ||||||
|         instance, |         instance, "AM650", subghz_device_cc1101_preset_ook_650khz_async_regs); | ||||||
|         "AM650", |  | ||||||
|         (uint8_t*)furi_hal_subghz_preset_ook_650khz_async_regs, |  | ||||||
|         furi_hal_subghz_preset_ook_async_patable); |  | ||||||
|     subghz_setting_load_default_preset( |     subghz_setting_load_default_preset( | ||||||
|         instance, |         instance, "FM238", subghz_device_cc1101_preset_2fsk_dev2_38khz_async_regs); | ||||||
|         "FM238", |  | ||||||
|         (uint8_t*)furi_hal_subghz_preset_2fsk_dev2_38khz_async_regs, |  | ||||||
|         furi_hal_subghz_preset_2fsk_async_patable); |  | ||||||
|     subghz_setting_load_default_preset( |     subghz_setting_load_default_preset( | ||||||
|         instance, |         instance, "FM476", subghz_device_cc1101_preset_2fsk_dev47_6khz_async_regs); | ||||||
|         "FM476", |  | ||||||
|         (uint8_t*)furi_hal_subghz_preset_2fsk_dev47_6khz_async_regs, |  | ||||||
|         furi_hal_subghz_preset_2fsk_async_patable); |  | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void subghz_setting_load_default(SubGhzSetting* instance) { | void subghz_setting_load_default(SubGhzSetting* instance) { | ||||||
| @ -359,6 +344,7 @@ void subghz_setting_load(SubGhzSetting* instance, const char* file_path) { | |||||||
|             } |             } | ||||||
|             while(flipper_format_read_uint32( |             while(flipper_format_read_uint32( | ||||||
|                 fff_data_file, "Frequency", (uint32_t*)&temp_data32, 1)) { |                 fff_data_file, "Frequency", (uint32_t*)&temp_data32, 1)) { | ||||||
|  |                 //Todo: add a frequency support check depending on the selected radio device
 | ||||||
|                 if(furi_hal_subghz_is_frequency_valid(temp_data32)) { |                 if(furi_hal_subghz_is_frequency_valid(temp_data32)) { | ||||||
|                     FURI_LOG_I(TAG, "Frequency loaded %lu", temp_data32); |                     FURI_LOG_I(TAG, "Frequency loaded %lu", temp_data32); | ||||||
|                     FrequencyList_push_back(instance->frequencies, temp_data32); |                     FrequencyList_push_back(instance->frequencies, temp_data32); | ||||||
|  | |||||||
| @ -21,6 +21,8 @@ struct SubGhzTxRxWorker { | |||||||
|     SubGhzTxRxWorkerStatus status; |     SubGhzTxRxWorkerStatus status; | ||||||
| 
 | 
 | ||||||
|     uint32_t frequency; |     uint32_t frequency; | ||||||
|  |     const SubGhzDevice* device; | ||||||
|  |     const GpioPin* device_data_gpio; | ||||||
| 
 | 
 | ||||||
|     SubGhzTxRxWorkerCallbackHaveRead callback_have_read; |     SubGhzTxRxWorkerCallbackHaveRead callback_have_read; | ||||||
|     void* context_have_read; |     void* context_have_read; | ||||||
| @ -65,33 +67,33 @@ bool subghz_tx_rx_worker_rx(SubGhzTxRxWorker* instance, uint8_t* data, uint8_t* | |||||||
|     uint8_t timeout = 100; |     uint8_t timeout = 100; | ||||||
|     bool ret = false; |     bool ret = false; | ||||||
|     if(instance->status != SubGhzTxRxWorkerStatusRx) { |     if(instance->status != SubGhzTxRxWorkerStatusRx) { | ||||||
|         furi_hal_subghz_rx(); |         subghz_devices_set_rx(instance->device); | ||||||
|         instance->status = SubGhzTxRxWorkerStatusRx; |         instance->status = SubGhzTxRxWorkerStatusRx; | ||||||
|         furi_delay_tick(1); |         furi_delay_tick(1); | ||||||
|     } |     } | ||||||
|     //waiting for reception to complete
 |     //waiting for reception to complete
 | ||||||
|     while(furi_hal_gpio_read(&gpio_cc1101_g0)) { |     while(furi_hal_gpio_read(instance->device_data_gpio)) { | ||||||
|         furi_delay_tick(1); |         furi_delay_tick(1); | ||||||
|         if(!--timeout) { |         if(!--timeout) { | ||||||
|             FURI_LOG_W(TAG, "RX cc1101_g0 timeout"); |             FURI_LOG_W(TAG, "RX cc1101_g0 timeout"); | ||||||
|             furi_hal_subghz_flush_rx(); |             subghz_devices_flush_rx(instance->device); | ||||||
|             furi_hal_subghz_rx(); |             subghz_devices_set_rx(instance->device); | ||||||
|             break; |             break; | ||||||
|         } |         } | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     if(furi_hal_subghz_rx_pipe_not_empty()) { |     if(subghz_devices_rx_pipe_not_empty(instance->device)) { | ||||||
|         FURI_LOG_I( |         FURI_LOG_I( | ||||||
|             TAG, |             TAG, | ||||||
|             "RSSI: %03.1fdbm LQI: %d", |             "RSSI: %03.1fdbm LQI: %d", | ||||||
|             (double)furi_hal_subghz_get_rssi(), |             (double)subghz_devices_get_rssi(instance->device), | ||||||
|             furi_hal_subghz_get_lqi()); |             subghz_devices_get_lqi(instance->device)); | ||||||
|         if(furi_hal_subghz_is_rx_data_crc_valid()) { |         if(subghz_devices_is_rx_data_crc_valid(instance->device)) { | ||||||
|             furi_hal_subghz_read_packet(data, size); |             subghz_devices_read_packet(instance->device, data, size); | ||||||
|             ret = true; |             ret = true; | ||||||
|         } |         } | ||||||
|         furi_hal_subghz_flush_rx(); |         subghz_devices_flush_rx(instance->device); | ||||||
|         furi_hal_subghz_rx(); |         subghz_devices_set_rx(instance->device); | ||||||
|     } |     } | ||||||
|     return ret; |     return ret; | ||||||
| } | } | ||||||
| @ -99,26 +101,28 @@ 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 = 200; |     uint8_t timeout = 200; | ||||||
|     if(instance->status != SubGhzTxRxWorkerStatusIDLE) { |     if(instance->status != SubGhzTxRxWorkerStatusIDLE) { | ||||||
|         furi_hal_subghz_idle(); |         subghz_devices_idle(instance->device); | ||||||
|     } |     } | ||||||
|     furi_hal_subghz_write_packet(data, size); |     subghz_devices_write_packet(instance->device, data, size); | ||||||
|     furi_hal_subghz_tx(); //start send
 |     subghz_devices_set_tx(instance->device); //start send
 | ||||||
|     instance->status = SubGhzTxRxWorkerStatusTx; |     instance->status = SubGhzTxRxWorkerStatusTx; | ||||||
|     while(!furi_hal_gpio_read(&gpio_cc1101_g0)) { // Wait for GDO0 to be set -> sync transmitted
 |     while(!furi_hal_gpio_read( | ||||||
|  |         instance->device_data_gpio)) { // Wait for GDO0 to be set -> sync transmitted
 | ||||||
|         furi_delay_tick(1); |         furi_delay_tick(1); | ||||||
|         if(!--timeout) { |         if(!--timeout) { | ||||||
|             FURI_LOG_W(TAG, "TX !cc1101_g0 timeout"); |             FURI_LOG_W(TAG, "TX !cc1101_g0 timeout"); | ||||||
|             break; |             break; | ||||||
|         } |         } | ||||||
|     } |     } | ||||||
|     while(furi_hal_gpio_read(&gpio_cc1101_g0)) { // Wait for GDO0 to be cleared -> end of packet
 |     while(furi_hal_gpio_read( | ||||||
|  |         instance->device_data_gpio)) { // Wait for GDO0 to be cleared -> end of packet
 | ||||||
|         furi_delay_tick(1); |         furi_delay_tick(1); | ||||||
|         if(!--timeout) { |         if(!--timeout) { | ||||||
|             FURI_LOG_W(TAG, "TX cc1101_g0 timeout"); |             FURI_LOG_W(TAG, "TX cc1101_g0 timeout"); | ||||||
|             break; |             break; | ||||||
|         } |         } | ||||||
|     } |     } | ||||||
|     furi_hal_subghz_idle(); |     subghz_devices_idle(instance->device); | ||||||
|     instance->status = SubGhzTxRxWorkerStatusIDLE; |     instance->status = SubGhzTxRxWorkerStatusIDLE; | ||||||
| } | } | ||||||
| /** Worker thread
 | /** Worker thread
 | ||||||
| @ -128,16 +132,19 @@ void subghz_tx_rx_worker_tx(SubGhzTxRxWorker* instance, uint8_t* data, size_t si | |||||||
|  */ |  */ | ||||||
| static int32_t subghz_tx_rx_worker_thread(void* context) { | static int32_t subghz_tx_rx_worker_thread(void* context) { | ||||||
|     SubGhzTxRxWorker* instance = context; |     SubGhzTxRxWorker* instance = context; | ||||||
|  |     furi_assert(instance->device); | ||||||
|     FURI_LOG_I(TAG, "Worker start"); |     FURI_LOG_I(TAG, "Worker start"); | ||||||
| 
 | 
 | ||||||
|     furi_hal_subghz_reset(); |     subghz_devices_begin(instance->device); | ||||||
|     furi_hal_subghz_idle(); |     instance->device_data_gpio = subghz_devices_get_data_gpio(instance->device); | ||||||
|     furi_hal_subghz_load_preset(FuriHalSubGhzPresetGFSK9_99KbAsync); |     subghz_devices_reset(instance->device); | ||||||
|     //furi_hal_subghz_load_preset(FuriHalSubGhzPresetMSK99_97KbAsync);
 |     subghz_devices_idle(instance->device); | ||||||
|     furi_hal_gpio_init(&gpio_cc1101_g0, GpioModeInput, GpioPullNo, GpioSpeedLow); |     subghz_devices_load_preset(instance->device, FuriHalSubGhzPresetGFSK9_99KbAsync, NULL); | ||||||
| 
 | 
 | ||||||
|     furi_hal_subghz_set_frequency_and_path(instance->frequency); |     furi_hal_gpio_init(instance->device_data_gpio, GpioModeInput, GpioPullNo, GpioSpeedLow); | ||||||
|     furi_hal_subghz_flush_rx(); | 
 | ||||||
|  |     subghz_devices_set_frequency(instance->device, instance->frequency); | ||||||
|  |     subghz_devices_flush_rx(instance->device); | ||||||
| 
 | 
 | ||||||
|     uint8_t data[SUBGHZ_TXRX_WORKER_MAX_TXRX_SIZE + 1] = {0}; |     uint8_t data[SUBGHZ_TXRX_WORKER_MAX_TXRX_SIZE + 1] = {0}; | ||||||
|     size_t size_tx = 0; |     size_t size_tx = 0; | ||||||
| @ -191,8 +198,8 @@ static int32_t subghz_tx_rx_worker_thread(void* context) { | |||||||
|         furi_delay_tick(1); |         furi_delay_tick(1); | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     furi_hal_subghz_set_path(FuriHalSubGhzPathIsolate); |     subghz_devices_sleep(instance->device); | ||||||
|     furi_hal_subghz_sleep(); |     subghz_devices_end(instance->device); | ||||||
| 
 | 
 | ||||||
|     FURI_LOG_I(TAG, "Worker stop"); |     FURI_LOG_I(TAG, "Worker stop"); | ||||||
|     return 0; |     return 0; | ||||||
| @ -224,7 +231,10 @@ void subghz_tx_rx_worker_free(SubGhzTxRxWorker* instance) { | |||||||
|     free(instance); |     free(instance); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| bool subghz_tx_rx_worker_start(SubGhzTxRxWorker* instance, uint32_t frequency) { | bool subghz_tx_rx_worker_start( | ||||||
|  |     SubGhzTxRxWorker* instance, | ||||||
|  |     const SubGhzDevice* device, | ||||||
|  |     uint32_t frequency) { | ||||||
|     furi_assert(instance); |     furi_assert(instance); | ||||||
|     furi_assert(!instance->worker_running); |     furi_assert(!instance->worker_running); | ||||||
|     bool res = false; |     bool res = false; | ||||||
| @ -235,6 +245,7 @@ bool subghz_tx_rx_worker_start(SubGhzTxRxWorker* instance, uint32_t frequency) { | |||||||
| 
 | 
 | ||||||
|     if(furi_hal_region_is_frequency_allowed(frequency)) { |     if(furi_hal_region_is_frequency_allowed(frequency)) { | ||||||
|         instance->frequency = frequency; |         instance->frequency = frequency; | ||||||
|  |         instance->device = device; | ||||||
|         res = true; |         res = true; | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|  | |||||||
| @ -1,6 +1,7 @@ | |||||||
| #pragma once | #pragma once | ||||||
| 
 | 
 | ||||||
| #include <furi_hal.h> | #include <furi_hal.h> | ||||||
|  | #include <devices/devices.h> | ||||||
| 
 | 
 | ||||||
| #ifdef __cplusplus | #ifdef __cplusplus | ||||||
| extern "C" { | extern "C" { | ||||||
| @ -67,9 +68,13 @@ void subghz_tx_rx_worker_free(SubGhzTxRxWorker* instance); | |||||||
| /** 
 | /** 
 | ||||||
|  * Start SubGhzTxRxWorker |  * Start SubGhzTxRxWorker | ||||||
|  * @param instance Pointer to a SubGhzTxRxWorker instance |  * @param instance Pointer to a SubGhzTxRxWorker instance | ||||||
|  |  * @param device Pointer to a SubGhzDevice instance | ||||||
|  * @return bool - true if ok |  * @return bool - true if ok | ||||||
|  */ |  */ | ||||||
| bool subghz_tx_rx_worker_start(SubGhzTxRxWorker* instance, uint32_t frequency); | bool subghz_tx_rx_worker_start( | ||||||
|  |     SubGhzTxRxWorker* instance, | ||||||
|  |     const SubGhzDevice* device, | ||||||
|  |     uint32_t frequency); | ||||||
| 
 | 
 | ||||||
| /** 
 | /** 
 | ||||||
|  * Stop SubGhzTxRxWorker |  * Stop SubGhzTxRxWorker | ||||||
|  | |||||||
| @ -21,6 +21,12 @@ | |||||||
| #define SUBGHZ_RAW_FILE_VERSION 1 | #define SUBGHZ_RAW_FILE_VERSION 1 | ||||||
| #define SUBGHZ_RAW_FILE_TYPE "Flipper SubGhz RAW File" | #define SUBGHZ_RAW_FILE_TYPE "Flipper SubGhz RAW File" | ||||||
| 
 | 
 | ||||||
|  | #define SUBGHZ_KEYSTORE_DIR_NAME EXT_PATH("subghz/assets/keeloq_mfcodes") | ||||||
|  | #define SUBGHZ_KEYSTORE_DIR_USER_NAME EXT_PATH("subghz/assets/keeloq_mfcodes_user") | ||||||
|  | #define SUBGHZ_CAME_ATOMO_DIR_NAME EXT_PATH("subghz/assets/came_atomo") | ||||||
|  | #define SUBGHZ_NICE_FLOR_S_DIR_NAME EXT_PATH("subghz/assets/nice_flor_s") | ||||||
|  | #define SUBGHZ_ALUTECH_AT_4N_DIR_NAME EXT_PATH("subghz/assets/alutech_at_4n") | ||||||
|  | 
 | ||||||
| typedef struct SubGhzProtocolRegistry SubGhzProtocolRegistry; | typedef struct SubGhzProtocolRegistry SubGhzProtocolRegistry; | ||||||
| typedef struct SubGhzEnvironment SubGhzEnvironment; | typedef struct SubGhzEnvironment SubGhzEnvironment; | ||||||
| 
 | 
 | ||||||
|  | |||||||
| @ -228,6 +228,7 @@ vars.AddVariables( | |||||||
|             ("applications/debug", False), |             ("applications/debug", False), | ||||||
|             ("applications/external", False), |             ("applications/external", False), | ||||||
|             ("applications/examples", False), |             ("applications/examples", False), | ||||||
|  |             ("applications/drivers", False), | ||||||
|             ("applications_user", False), |             ("applications_user", False), | ||||||
|         ], |         ], | ||||||
|     ), |     ), | ||||||
|  | |||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user
	 Skorpionm
						Skorpionm