[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:
Skorpionm 2023-06-30 18:03:36 +04:00 committed by GitHub
parent 6d9de25494
commit 8c93695d01
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
67 changed files with 2932 additions and 651 deletions

View file

@ -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)) {

View file

@ -0,0 +1,6 @@
# Placeholder
App(
appid="drivers",
name="Drivers device",
apptype=FlipperAppType.METAPACKAGE,
)

View 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"],
)

View 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;
}

View 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

View 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;
}

View file

@ -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();

View file

@ -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);

View file

@ -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);

View file

@ -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)) {

View file

@ -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);

View file

@ -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);
}

View file

@ -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);

View file

@ -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;

View file

@ -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,

View file

@ -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)

View 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);
}

View file

@ -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);

View file

@ -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(

View file

@ -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 {

View file

@ -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;

View file

@ -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;
} }

View file

@ -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);

View file

@ -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(

View file

@ -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;
} }
} }

View file

@ -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,

View file

@ -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);

View file

@ -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);

View file

@ -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);

View file

@ -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);

View file

@ -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,

View file

@ -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);

View file

@ -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) {

View file

@ -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);

Binary file not shown.

After

Width:  |  Height:  |  Size: 990 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 994 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.4 KiB

View file

@ -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 |

View file

@ -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 entry status name type params
2 Version + 31.3 32.0
3 Header + applications/services/bt/bt_service/bt.h
4 Header + applications/services/cli/cli.h
5 Header + applications/services/cli/cli_vcp.h
283 Function - SystemCoreClockUpdate void
284 Function - SystemInit void
285 Function - _Exit void int
286 Function + __aeabi_uldivmod void* uint64_t, uint64_t
287 Function - __assert void const char*, int, const char*
288 Function + __assert_func void const char*, int, const char*, const char*
289 Function + __clear_cache void void*, void*

View file

@ -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,

1 entry status name type params
2 Version + 31.3 32.0
3 Header + applications/services/bt/bt_service/bt.h
4 Header + applications/services/cli/cli.h
5 Header + applications/services/cli/cli_vcp.h
56 Header + firmware/targets/f7/furi_hal/furi_hal_spi_config.h
57 Header + firmware/targets/f7/furi_hal/furi_hal_spi_types.h
58 Header + firmware/targets/f7/furi_hal/furi_hal_subghz.h
Header + firmware/targets/f7/furi_hal/furi_hal_subghz_configs.h
59 Header + firmware/targets/f7/furi_hal/furi_hal_target_hw.h
60 Header + firmware/targets/f7/furi_hal/furi_hal_uart.h
61 Header + firmware/targets/f7/furi_hal/furi_hal_usb_cdc.h
185 Header + lib/subghz/blocks/encoder.h
186 Header + lib/subghz/blocks/generic.h
187 Header + lib/subghz/blocks/math.h
188 Header + lib/subghz/devices/cc1101_configs.h
189 Header + lib/subghz/environment.h
190 Header + lib/subghz/protocols/raw.h
191 Header + lib/subghz/receiver.h
317 Function - SystemCoreClockUpdate void
318 Function - SystemInit void
319 Function - _Exit void int
320 Function + __aeabi_uldivmod void* uint64_t, uint64_t
321 Function - __assert void const char*, int, const char*
322 Function + __assert_func void const char*, int, const char*, const char*
323 Function + __clear_cache void void*, void*
658 Function - cbrt double double
659 Function - cbrtf float float
660 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
661 Function - ceil double double
662 Function - ceilf float float
663 Function - ceill long double long double
1364 Function - furi_hal_subghz_dump_state void
1365 Function + furi_hal_subghz_flush_rx void
1366 Function + furi_hal_subghz_flush_tx void
1367 Function + furi_hal_subghz_get_data_gpio const GpioPin*
1368 Function + furi_hal_subghz_get_lqi uint8_t
1369 Function + furi_hal_subghz_get_rssi float
1370 Function + furi_hal_subghz_idle void
1372 Function + furi_hal_subghz_is_async_tx_complete _Bool
1373 Function + furi_hal_subghz_is_frequency_valid _Bool uint32_t
1374 Function + furi_hal_subghz_is_rx_data_crc_valid _Bool
1375 Function + furi_hal_subghz_load_custom_preset void uint8_t* const uint8_t*
1376 Function + furi_hal_subghz_load_patable void const uint8_t[8]
1377 Function + furi_hal_subghz_load_preset furi_hal_subghz_load_registers void FuriHalSubGhzPreset const uint8_t*
Function + furi_hal_subghz_load_registers void uint8_t*
1378 Function + furi_hal_subghz_read_packet void uint8_t*, uint8_t*
1379 Function + furi_hal_subghz_reset void
1380 Function + furi_hal_subghz_rx void
1382 Function + furi_hal_subghz_set_async_mirror_pin void const GpioPin*
1383 Function + furi_hal_subghz_set_frequency uint32_t uint32_t
1384 Function + furi_hal_subghz_set_frequency_and_path uint32_t uint32_t
1385 Function + - furi_hal_subghz_set_path void FuriHalSubGhzPath
1386 Function - furi_hal_subghz_shutdown void
1387 Function + furi_hal_subghz_sleep void
1388 Function + furi_hal_subghz_start_async_rx void FuriHalSubGhzCaptureCallback, void*
2667 Function + subghz_block_generic_deserialize_check_count_bit SubGhzProtocolStatus SubGhzBlockGeneric*, FlipperFormat*, uint16_t
2668 Function + subghz_block_generic_get_preset_name void const char*, FuriString*
2669 Function + subghz_block_generic_serialize SubGhzProtocolStatus SubGhzBlockGeneric*, FlipperFormat*, SubGhzRadioPreset*
2670 Function + subghz_devices_begin _Bool const SubGhzDevice*
2671 Function + subghz_devices_deinit void
2672 Function + subghz_devices_end void const SubGhzDevice*
2673 Function + subghz_devices_flush_rx void const SubGhzDevice*
2674 Function + subghz_devices_flush_tx void const SubGhzDevice*
2675 Function + subghz_devices_get_by_name const SubGhzDevice* const char*
2676 Function + subghz_devices_get_data_gpio const GpioPin* const SubGhzDevice*
2677 Function + subghz_devices_get_lqi uint8_t const SubGhzDevice*
2678 Function + subghz_devices_get_name const char* const SubGhzDevice*
2679 Function + subghz_devices_get_rssi float const SubGhzDevice*
2680 Function + subghz_devices_idle void const SubGhzDevice*
2681 Function + subghz_devices_init void
2682 Function + subghz_devices_is_async_complete_tx _Bool const SubGhzDevice*
2683 Function + subghz_devices_is_connect _Bool const SubGhzDevice*
2684 Function + subghz_devices_is_frequency_valid _Bool const SubGhzDevice*, uint32_t
2685 Function + subghz_devices_is_rx_data_crc_valid _Bool const SubGhzDevice*
2686 Function + subghz_devices_load_preset void const SubGhzDevice*, FuriHalSubGhzPreset, uint8_t*
2687 Function + subghz_devices_read_packet void const SubGhzDevice*, uint8_t*, uint8_t*
2688 Function + subghz_devices_reset void const SubGhzDevice*
2689 Function + subghz_devices_rx_pipe_not_empty _Bool const SubGhzDevice*
2690 Function + subghz_devices_set_async_mirror_pin void const SubGhzDevice*, const GpioPin*
2691 Function + subghz_devices_set_frequency uint32_t const SubGhzDevice*, uint32_t
2692 Function + subghz_devices_set_rx void const SubGhzDevice*
2693 Function + subghz_devices_set_tx _Bool const SubGhzDevice*
2694 Function + subghz_devices_sleep void const SubGhzDevice*
2695 Function + subghz_devices_start_async_rx void const SubGhzDevice*, void*, void*
2696 Function + subghz_devices_start_async_tx _Bool const SubGhzDevice*, void*, void*
2697 Function + subghz_devices_stop_async_rx void const SubGhzDevice*
2698 Function + subghz_devices_stop_async_tx void const SubGhzDevice*
2699 Function + subghz_devices_write_packet void const SubGhzDevice*, const uint8_t*, uint8_t
2700 Function + subghz_environment_alloc SubGhzEnvironment*
2701 Function + subghz_environment_free void SubGhzEnvironment*
2702 Function + subghz_environment_get_alutech_at_4n_rainbow_table_file_name const char* SubGhzEnvironment*
2755 Function + subghz_protocol_encoder_raw_stop void void*
2756 Function + subghz_protocol_encoder_raw_yield LevelDuration void*
2757 Function + subghz_protocol_raw_file_encoder_worker_set_callback_end void SubGhzProtocolEncoderRAW*, SubGhzProtocolEncoderRAWCallbackEnd, void*
2758 Function + subghz_protocol_raw_gen_fff_data void FlipperFormat*, const char* FlipperFormat*, const char*, const char*
2759 Function + subghz_protocol_raw_get_sample_write size_t SubGhzProtocolDecoderRAW*
2760 Function + subghz_protocol_raw_save_to_file_init _Bool SubGhzProtocolDecoderRAW*, const char*, SubGhzRadioPreset*
2761 Function + subghz_protocol_raw_save_to_file_pause void SubGhzProtocolDecoderRAW*, _Bool
2799 Function + subghz_tx_rx_worker_is_running _Bool SubGhzTxRxWorker*
2800 Function + subghz_tx_rx_worker_read size_t SubGhzTxRxWorker*, uint8_t*, size_t
2801 Function + subghz_tx_rx_worker_set_callback_have_read void SubGhzTxRxWorker*, SubGhzTxRxWorkerCallbackHaveRead, void*
2802 Function + subghz_tx_rx_worker_start _Bool SubGhzTxRxWorker*, uint32_t SubGhzTxRxWorker*, const SubGhzDevice*, uint32_t
2803 Function + subghz_tx_rx_worker_stop void SubGhzTxRxWorker*
2804 Function + subghz_tx_rx_worker_write _Bool SubGhzTxRxWorker*, uint8_t*, size_t
2805 Function + subghz_worker_alloc SubGhzWorker*
3400 Variable + sequence_single_vibro const NotificationSequence
3401 Variable + sequence_solid_yellow const NotificationSequence
3402 Variable + sequence_success const NotificationSequence
3403 Variable + subghz_device_cc1101_preset_2fsk_dev2_38khz_async_regs const uint8_t[]
3404 Variable + subghz_device_cc1101_preset_2fsk_dev47_6khz_async_regs const uint8_t[]
3405 Variable + subghz_device_cc1101_preset_gfsk_9_99kb_async_regs const uint8_t[]
3406 Variable + subghz_device_cc1101_preset_msk_99_97kb_async_regs const uint8_t[]
3407 Variable + subghz_device_cc1101_preset_ook_270khz_async_regs const uint8_t[]
3408 Variable + subghz_device_cc1101_preset_ook_650khz_async_regs const uint8_t[]
3409 Variable + subghz_protocol_raw const SubGhzProtocol
3410 Variable + subghz_protocol_raw_decoder const SubGhzProtocolDecoder
3411 Variable + subghz_protocol_raw_encoder const SubGhzProtocolEncoder

View file

@ -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

View file

@ -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;

View file

@ -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
* *

View file

@ -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};

View file

@ -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
} }

View file

@ -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"),
], ],
) )

View 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,
};

View 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

View 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,
};

View 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;

View file

@ -0,0 +1,13 @@
#pragma once
#include "registry.h"
#ifdef __cplusplus
extern "C" {
#endif
extern const SubGhzDeviceRegistry subghz_device_registry;
#ifdef __cplusplus
}
#endif

View 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);
}
}

View 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

View 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;

View 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;
}
}

View 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

View 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;
};

View file

@ -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;

View file

@ -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.

View file

@ -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);

View file

@ -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

View file

@ -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);

View file

@ -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;
} }

View file

@ -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

View file

@ -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;

View file

@ -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),
], ],
), ),