[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
67 changed files with 2932 additions and 651 deletions
+1
View File
@@ -19,6 +19,7 @@ env.Append(
File("blocks/math.h"),
File("subghz_setting.h"),
File("subghz_protocol_registry.h"),
File("devices/cc1101_configs.h"),
],
)
+431
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,
};
+18
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
@@ -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,
};
@@ -0,0 +1,8 @@
#pragma once
#include "../types.h"
#define SUBGHZ_DEVICE_CC1101_INT_NAME "cc1101_int"
typedef struct SubGhzDeviceCC1101Int SubGhzDeviceCC1101Int;
extern const SubGhzDevice subghz_device_cc1101_int;
+13
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
+236
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);
}
}
+52
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
+13
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;
+76
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;
}
}
+40
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
+91
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;
};
+23 -2
View File
@@ -40,6 +40,7 @@ struct SubGhzProtocolEncoderRAW {
bool is_running;
FuriString* file_name;
FuriString* radio_device_name;
SubGhzFileEncoderWorker* file_worker_encoder;
};
@@ -282,6 +283,7 @@ void* subghz_protocol_encoder_raw_alloc(SubGhzEnvironment* environment) {
instance->base.protocol = &subghz_protocol_raw;
instance->file_name = furi_string_alloc();
instance->radio_device_name = furi_string_alloc();
instance->is_running = false;
return instance;
}
@@ -300,6 +302,7 @@ void subghz_protocol_encoder_raw_free(void* context) {
SubGhzProtocolEncoderRAW* instance = context;
subghz_protocol_encoder_raw_stop(instance);
furi_string_free(instance->file_name);
furi_string_free(instance->radio_device_name);
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();
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
furi_delay_ms(100);
instance->is_running = true;
@@ -328,7 +333,10 @@ static bool subghz_protocol_encoder_raw_worker_init(SubGhzProtocolEncoderRAW* in
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 {
stream_clean(flipper_format_get_raw_stream(flipper_format));
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");
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);
}
@@ -364,6 +378,13 @@ SubGhzProtocolStatus
}
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)) {
res = SubGhzProtocolStatusErrorEncoderGetUpload;
break;
+5 -1
View File
@@ -126,8 +126,12 @@ void subghz_protocol_raw_file_encoder_worker_set_callback_end(
* File generation for RAW work.
* @param flipper_format Pointer to a FlipperFormat instance
* @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.
+11 -2
View File
@@ -3,6 +3,7 @@
#include <toolbox/stream/stream.h>
#include <flipper_format/flipper_format.h>
#include <flipper_format/flipper_format_i.h>
#include <lib/subghz/devices/devices.h>
#define TAG "SubGhzFileEncoderWorker"
@@ -21,6 +22,7 @@ struct SubGhzFileEncoderWorker {
bool is_storage_slow;
FuriString* str_data;
FuriString* file_path;
const SubGhzDevice* device;
SubGhzFileEncoderWorkerCallbackEnd callback_end;
void* context_end;
@@ -156,10 +158,13 @@ static int32_t subghz_file_encoder_worker_thread(void* context) {
if(instance->is_storage_slow) {
FURI_LOG_E(TAG, "Storage is slow");
}
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_LOG_I(TAG, "End transmission");
while(instance->worker_running) {
if(instance->worker_stoping) {
@@ -206,12 +211,16 @@ void subghz_file_encoder_worker_free(SubGhzFileEncoderWorker* 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->worker_running);
furi_stream_buffer_reset(instance->stream);
furi_string_set(instance->file_path, file_path);
instance->device = subghz_devices_get_by_name(radio_device_name);
instance->worker_running = true;
furi_thread_start(instance->thread);
+6 -1
View File
@@ -38,9 +38,14 @@ LevelDuration subghz_file_encoder_worker_get_level_duration(void* context);
/**
* Start SubGhzFileEncoderWorker.
* @param instance Pointer to a SubGhzFileEncoderWorker instance
* @param file_path File path
* @param radio_device_name Radio device name
* @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
+9 -23
View File
@@ -4,7 +4,7 @@
#include <furi.h>
#include <m-list.h>
#include <furi_hal_subghz_configs.h>
#include <lib/subghz/devices/cc1101_configs.h>
#define TAG "SubGhzSetting"
@@ -218,8 +218,7 @@ void subghz_setting_free(SubGhzSetting* instance) {
static void subghz_setting_load_default_preset(
SubGhzSetting* instance,
const char* preset_name,
const uint8_t* preset_data,
const uint8_t preset_pa_table[8]) {
const uint8_t* preset_data) {
furi_assert(instance);
furi_assert(preset_data);
uint32_t preset_data_count = 0;
@@ -235,10 +234,8 @@ static void subghz_setting_load_default_preset(
preset_data_count += 2;
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);
//load preset register
memcpy(&item->custom_preset_data[0], &preset_data[0], preset_data_count);
//load pa table
memcpy(&item->custom_preset_data[preset_data_count], &preset_pa_table[0], 8);
//load preset register + pa table
memcpy(&item->custom_preset_data[0], &preset_data[0], item->custom_preset_data_size);
}
static void subghz_setting_load_default_region(
@@ -262,25 +259,13 @@ static void subghz_setting_load_default_region(
}
subghz_setting_load_default_preset(
instance,
"AM270",
(uint8_t*)furi_hal_subghz_preset_ook_270khz_async_regs,
furi_hal_subghz_preset_ook_async_patable);
instance, "AM270", subghz_device_cc1101_preset_ook_270khz_async_regs);
subghz_setting_load_default_preset(
instance,
"AM650",
(uint8_t*)furi_hal_subghz_preset_ook_650khz_async_regs,
furi_hal_subghz_preset_ook_async_patable);
instance, "AM650", subghz_device_cc1101_preset_ook_650khz_async_regs);
subghz_setting_load_default_preset(
instance,
"FM238",
(uint8_t*)furi_hal_subghz_preset_2fsk_dev2_38khz_async_regs,
furi_hal_subghz_preset_2fsk_async_patable);
instance, "FM238", subghz_device_cc1101_preset_2fsk_dev2_38khz_async_regs);
subghz_setting_load_default_preset(
instance,
"FM476",
(uint8_t*)furi_hal_subghz_preset_2fsk_dev47_6khz_async_regs,
furi_hal_subghz_preset_2fsk_async_patable);
instance, "FM476", subghz_device_cc1101_preset_2fsk_dev47_6khz_async_regs);
}
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(
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)) {
FURI_LOG_I(TAG, "Frequency loaded %lu", temp_data32);
FrequencyList_push_back(instance->frequencies, temp_data32);
+38 -27
View File
@@ -21,6 +21,8 @@ struct SubGhzTxRxWorker {
SubGhzTxRxWorkerStatus status;
uint32_t frequency;
const SubGhzDevice* device;
const GpioPin* device_data_gpio;
SubGhzTxRxWorkerCallbackHaveRead callback_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;
bool ret = false;
if(instance->status != SubGhzTxRxWorkerStatusRx) {
furi_hal_subghz_rx();
subghz_devices_set_rx(instance->device);
instance->status = SubGhzTxRxWorkerStatusRx;
furi_delay_tick(1);
}
//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);
if(!--timeout) {
FURI_LOG_W(TAG, "RX cc1101_g0 timeout");
furi_hal_subghz_flush_rx();
furi_hal_subghz_rx();
subghz_devices_flush_rx(instance->device);
subghz_devices_set_rx(instance->device);
break;
}
}
if(furi_hal_subghz_rx_pipe_not_empty()) {
if(subghz_devices_rx_pipe_not_empty(instance->device)) {
FURI_LOG_I(
TAG,
"RSSI: %03.1fdbm LQI: %d",
(double)furi_hal_subghz_get_rssi(),
furi_hal_subghz_get_lqi());
if(furi_hal_subghz_is_rx_data_crc_valid()) {
furi_hal_subghz_read_packet(data, size);
(double)subghz_devices_get_rssi(instance->device),
subghz_devices_get_lqi(instance->device));
if(subghz_devices_is_rx_data_crc_valid(instance->device)) {
subghz_devices_read_packet(instance->device, data, size);
ret = true;
}
furi_hal_subghz_flush_rx();
furi_hal_subghz_rx();
subghz_devices_flush_rx(instance->device);
subghz_devices_set_rx(instance->device);
}
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) {
uint8_t timeout = 200;
if(instance->status != SubGhzTxRxWorkerStatusIDLE) {
furi_hal_subghz_idle();
subghz_devices_idle(instance->device);
}
furi_hal_subghz_write_packet(data, size);
furi_hal_subghz_tx(); //start send
subghz_devices_write_packet(instance->device, data, size);
subghz_devices_set_tx(instance->device); //start send
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);
if(!--timeout) {
FURI_LOG_W(TAG, "TX !cc1101_g0 timeout");
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);
if(!--timeout) {
FURI_LOG_W(TAG, "TX cc1101_g0 timeout");
break;
}
}
furi_hal_subghz_idle();
subghz_devices_idle(instance->device);
instance->status = SubGhzTxRxWorkerStatusIDLE;
}
/** 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) {
SubGhzTxRxWorker* instance = context;
furi_assert(instance->device);
FURI_LOG_I(TAG, "Worker start");
furi_hal_subghz_reset();
furi_hal_subghz_idle();
furi_hal_subghz_load_preset(FuriHalSubGhzPresetGFSK9_99KbAsync);
//furi_hal_subghz_load_preset(FuriHalSubGhzPresetMSK99_97KbAsync);
furi_hal_gpio_init(&gpio_cc1101_g0, GpioModeInput, GpioPullNo, GpioSpeedLow);
subghz_devices_begin(instance->device);
instance->device_data_gpio = subghz_devices_get_data_gpio(instance->device);
subghz_devices_reset(instance->device);
subghz_devices_idle(instance->device);
subghz_devices_load_preset(instance->device, FuriHalSubGhzPresetGFSK9_99KbAsync, NULL);
furi_hal_subghz_set_frequency_and_path(instance->frequency);
furi_hal_subghz_flush_rx();
furi_hal_gpio_init(instance->device_data_gpio, GpioModeInput, GpioPullNo, GpioSpeedLow);
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};
size_t size_tx = 0;
@@ -191,8 +198,8 @@ static int32_t subghz_tx_rx_worker_thread(void* context) {
furi_delay_tick(1);
}
furi_hal_subghz_set_path(FuriHalSubGhzPathIsolate);
furi_hal_subghz_sleep();
subghz_devices_sleep(instance->device);
subghz_devices_end(instance->device);
FURI_LOG_I(TAG, "Worker stop");
return 0;
@@ -224,7 +231,10 @@ void subghz_tx_rx_worker_free(SubGhzTxRxWorker* 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->worker_running);
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)) {
instance->frequency = frequency;
instance->device = device;
res = true;
}
+6 -1
View File
@@ -1,6 +1,7 @@
#pragma once
#include <furi_hal.h>
#include <devices/devices.h>
#ifdef __cplusplus
extern "C" {
@@ -67,9 +68,13 @@ void subghz_tx_rx_worker_free(SubGhzTxRxWorker* instance);
/**
* Start SubGhzTxRxWorker
* @param instance Pointer to a SubGhzTxRxWorker instance
* @param device Pointer to a SubGhzDevice instance
* @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
+6
View File
@@ -21,6 +21,12 @@
#define SUBGHZ_RAW_FILE_VERSION 1
#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 SubGhzEnvironment SubGhzEnvironment;