diff --git a/applications/drivers/application.fam b/applications/drivers/application.fam new file mode 100644 index 000000000..dc70e630c --- /dev/null +++ b/applications/drivers/application.fam @@ -0,0 +1,6 @@ +# Placeholder +App( + appid="drivers", + name="Drivers device", + apptype=FlipperAppType.METAPACKAGE, +) diff --git a/applications/drivers/subghz/application.fam b/applications/drivers/subghz/application.fam new file mode 100644 index 000000000..aaf0e1bd9 --- /dev/null +++ b/applications/drivers/subghz/application.fam @@ -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"], +) diff --git a/applications/drivers/subghz/cc1101_ext/cc1101_ext.h b/applications/drivers/subghz/cc1101_ext/cc1101_ext.h new file mode 100644 index 000000000..d972fcb66 --- /dev/null +++ b/applications/drivers/subghz/cc1101_ext/cc1101_ext.h @@ -0,0 +1,206 @@ +/** + * @file furi_hal_subghz.h + * SubGhz HAL API + */ + +#pragma once +#include +#include +#include +#include +#include +#include + +#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 diff --git a/applications/drivers/subghz/cc1101_ext/cc1101_ext_interconnect.c b/applications/drivers/subghz/cc1101_ext/cc1101_ext_interconnect.c new file mode 100644 index 000000000..51f5a0d1d --- /dev/null +++ b/applications/drivers/subghz/cc1101_ext/cc1101_ext_interconnect.c @@ -0,0 +1,110 @@ +#include "cc1101_ext_interconnect.h" +#include "cc1101_ext.h" +#include + +#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; +} \ No newline at end of file diff --git a/applications/drivers/subghz/cc1101_ext/cc1101_ext_interconnect.h b/applications/drivers/subghz/cc1101_ext/cc1101_ext_interconnect.h new file mode 100644 index 000000000..cf1ff3ee0 --- /dev/null +++ b/applications/drivers/subghz/cc1101_ext/cc1101_ext_interconnect.h @@ -0,0 +1,8 @@ +#pragma once +#include + +#define SUBGHZ_DEVICE_CC1101_EXT_NAME "cc1101_ext" + +typedef struct SubGhzDeviceCC1101Ext SubGhzDeviceCC1101Ext; + +const FlipperAppPluginDescriptor* subghz_device_cc1101_ext_ep(); diff --git a/applications/external/subghz_playlist/radio_device_loader.c b/applications/external/subghz_playlist/helpers/radio_device_loader.c similarity index 100% rename from applications/external/subghz_playlist/radio_device_loader.c rename to applications/external/subghz_playlist/helpers/radio_device_loader.c diff --git a/applications/external/subghz_playlist/radio_device_loader.h b/applications/external/subghz_playlist/helpers/radio_device_loader.h similarity index 100% rename from applications/external/subghz_playlist/radio_device_loader.h rename to applications/external/subghz_playlist/helpers/radio_device_loader.h diff --git a/applications/external/subghz_playlist/playlist.c b/applications/external/subghz_playlist/playlist.c index dc7b7a45b..5ed896780 100644 --- a/applications/external/subghz_playlist/playlist.c +++ b/applications/external/subghz_playlist/playlist.c @@ -720,7 +720,7 @@ void playlist_free(Playlist* app) { free(app); } -int32_t playlist_app(char* p) { +int32_t playlist_app(void* p) { UNUSED(p); dolphin_deed(DolphinDeedPluginStart); diff --git a/applications/external/subghz_remote/application.fam b/applications/external/subghz_remote/application.fam index 4af6a1275..030ed030f 100644 --- a/applications/external/subghz_remote/application.fam +++ b/applications/external/subghz_remote/application.fam @@ -1,29 +1,10 @@ App( appid="subghz_remote", name="Sub-GHz Remote", -<<<<<<< HEAD:applications/external/subghz_remote/application.fam apptype=FlipperAppType.EXTERNAL, entry_point="subghz_remote_app", - cdefines=[ - "APP_SUBGHZREMOTE", - "SUBREM_LIGHT", - ], - requires=[ - "gui", - "dialogs", - ], stack_size=2 * 1024, order=11, fap_icon="subrem_10px.png", fap_category="Sub-GHz", -======= - apptype=FlipperAppType.MENUEXTERNAL, - entry_point="subghz_remote_app", - icon="A_SubGHzRemote_14", - stack_size=2 * 1024, - order=11, - fap_libs=["assets",], - fap_icon="icon.png", - fap_category="Sub-Ghz", ->>>>>>> ea357b8eafe91c3a07cb89c3b90d03b78e2633ff:applications/main/subghz_remote/application.fam ) diff --git a/applications/external/subghz_remote/helpers/txrx/subghz_txrx.h b/applications/external/subghz_remote/helpers/txrx/subghz_txrx.h new file mode 100644 index 000000000..8bb7f2aee --- /dev/null +++ b/applications/external/subghz_remote/helpers/txrx/subghz_txrx.h @@ -0,0 +1,375 @@ +#pragma once + +#include +#include +#include +#include +#include +#include + +typedef struct SubGhzTxRx SubGhzTxRx; + +typedef void (*SubGhzTxRxNeedSaveCallback)(void* context); + +typedef enum { + SubGhzTxRxStartTxStateOk, + SubGhzTxRxStartTxStateErrorOnlyRx, + SubGhzTxRxStartTxStateErrorParserOthers, +} SubGhzTxRxStartTxState; + +// Type from subghz_types.h need for txrx working +/** SubGhzTxRx state */ +typedef enum { + SubGhzTxRxStateIDLE, + SubGhzTxRxStateRx, + SubGhzTxRxStateTx, + SubGhzTxRxStateSleep, +} SubGhzTxRxState; + +/** SubGhzHopperState state */ +typedef enum { + SubGhzHopperStateOFF, + SubGhzHopperStateRunning, + SubGhzHopperStatePause, + SubGhzHopperStateRSSITimeOut, +} SubGhzHopperState; + +/** SubGhzSpeakerState state */ +typedef enum { + SubGhzSpeakerStateDisable, + SubGhzSpeakerStateShutdown, + SubGhzSpeakerStateEnable, +} SubGhzSpeakerState; + +/** SubGhzRadioDeviceType */ +typedef enum { + SubGhzRadioDeviceTypeAuto, + SubGhzRadioDeviceTypeInternal, + SubGhzRadioDeviceTypeExternalCC1101, +} SubGhzRadioDeviceType; + +/** + * Allocate SubGhzTxRx + * + * @return SubGhzTxRx* pointer to SubGhzTxRx + */ +SubGhzTxRx* subghz_txrx_alloc(); + +/** + * Free SubGhzTxRx + * + * @param instance Pointer to a SubGhzTxRx + */ +void subghz_txrx_free(SubGhzTxRx* instance); + +/** + * Check if the database is loaded + * + * @param instance Pointer to a SubGhzTxRx + * @return bool True if the database is loaded + */ +bool subghz_txrx_is_database_loaded(SubGhzTxRx* instance); + +/** + * Set preset + * + * @param instance Pointer to a SubGhzTxRx + * @param preset_name Name of preset + * @param frequency Frequency in Hz + * @param preset_data Data of preset + * @param preset_data_size Size of preset data + */ +void subghz_txrx_set_preset( + SubGhzTxRx* instance, + const char* preset_name, + uint32_t frequency, + uint8_t* preset_data, + size_t preset_data_size); + +/** + * Get name of preset + * + * @param instance Pointer to a SubGhzTxRx + * @param preset String of preset + * @return const char* Name of preset + */ +const char* subghz_txrx_get_preset_name(SubGhzTxRx* instance, const char* preset); + +/** + * Get of preset + * + * @param instance Pointer to a SubGhzTxRx + * @return SubGhzRadioPreset Preset + */ +SubGhzRadioPreset subghz_txrx_get_preset(SubGhzTxRx* instance); + +/** + * Get string frequency and modulation + * + * @param instance Pointer to a SubGhzTxRx + * @param frequency Pointer to a string frequency + * @param modulation Pointer to a string modulation + */ +void subghz_txrx_get_frequency_and_modulation( + SubGhzTxRx* instance, + FuriString* frequency, + FuriString* modulation, + bool long_name); + +/** + * Start TX CC1101 + * + * @param instance Pointer to a SubGhzTxRx + * @param flipper_format Pointer to a FlipperFormat + * @return SubGhzTxRxStartTxState + */ +SubGhzTxRxStartTxState subghz_txrx_tx_start(SubGhzTxRx* instance, FlipperFormat* flipper_format); + +/** + * Start RX CC1101 + * + * @param instance Pointer to a SubGhzTxRx + */ +void subghz_txrx_rx_start(SubGhzTxRx* instance); + +/** + * Stop TX/RX CC1101 + * + * @param instance Pointer to a SubGhzTxRx + */ +void subghz_txrx_stop(SubGhzTxRx* instance); + +/** + * Set sleep mode CC1101 + * + * @param instance Pointer to a SubGhzTxRx + */ +void subghz_txrx_sleep(SubGhzTxRx* instance); + +/** + * Update frequency CC1101 in automatic mode (hopper) + * + * @param instance Pointer to a SubGhzTxRx + */ +void subghz_txrx_hopper_update(SubGhzTxRx* instance); + +/** + * Get state hopper + * + * @param instance Pointer to a SubGhzTxRx + * @return SubGhzHopperState + */ +SubGhzHopperState subghz_txrx_hopper_get_state(SubGhzTxRx* instance); + +/** + * Set state hopper + * + * @param instance Pointer to a SubGhzTxRx + * @param state State hopper + */ +void subghz_txrx_hopper_set_state(SubGhzTxRx* instance, SubGhzHopperState state); + +/** + * Unpause hopper + * + * @param instance Pointer to a SubGhzTxRx + */ +void subghz_txrx_hopper_unpause(SubGhzTxRx* instance); + +/** + * Set pause hopper + * + * @param instance Pointer to a SubGhzTxRx + */ +void subghz_txrx_hopper_pause(SubGhzTxRx* instance); + +/** + * Speaker on + * + * @param instance Pointer to a SubGhzTxRx + */ +void subghz_txrx_speaker_on(SubGhzTxRx* instance); + +/** + * Speaker off + * + * @param instance Pointer to a SubGhzTxRx + */ +void subghz_txrx_speaker_off(SubGhzTxRx* instance); + +/** + * Speaker mute + * + * @param instance Pointer to a SubGhzTxRx + */ +void subghz_txrx_speaker_mute(SubGhzTxRx* instance); + +/** + * Speaker unmute + * + * @param instance Pointer to a SubGhzTxRx + */ +void subghz_txrx_speaker_unmute(SubGhzTxRx* instance); + +/** + * Set state speaker + * + * @param instance Pointer to a SubGhzTxRx + * @param state State speaker + */ +void subghz_txrx_speaker_set_state(SubGhzTxRx* instance, SubGhzSpeakerState state); + +/** + * Get state speaker + * + * @param instance Pointer to a SubGhzTxRx + * @return SubGhzSpeakerState + */ +SubGhzSpeakerState subghz_txrx_speaker_get_state(SubGhzTxRx* instance); + +/** + * load decoder by name protocol + * + * @param instance Pointer to a SubGhzTxRx + * @param name_protocol Name protocol + * @return bool True if the decoder is loaded + */ +bool subghz_txrx_load_decoder_by_name_protocol(SubGhzTxRx* instance, const char* name_protocol); + +/** + * Get decoder + * + * @param instance Pointer to a SubGhzTxRx + * @return SubGhzProtocolDecoderBase* Pointer to a SubGhzProtocolDecoderBase + */ +SubGhzProtocolDecoderBase* subghz_txrx_get_decoder(SubGhzTxRx* instance); + +/** + * Set callback for save data + * + * @param instance Pointer to a SubGhzTxRx + * @param callback Callback for save data + * @param context Context for callback + */ +void subghz_txrx_set_need_save_callback( + SubGhzTxRx* instance, + SubGhzTxRxNeedSaveCallback callback, + void* context); + +/** + * Get pointer to a load data key + * + * @param instance Pointer to a SubGhzTxRx + * @return FlipperFormat* + */ +FlipperFormat* subghz_txrx_get_fff_data(SubGhzTxRx* instance); + +/** + * Get pointer to a SugGhzSetting + * + * @param instance Pointer to a SubGhzTxRx + * @return SubGhzSetting* + */ +SubGhzSetting* subghz_txrx_get_setting(SubGhzTxRx* instance); + +/** + * Is it possible to save this protocol + * + * @param instance Pointer to a SubGhzTxRx + * @return bool True if it is possible to save this protocol + */ +bool subghz_txrx_protocol_is_serializable(SubGhzTxRx* instance); + +/** + * Is it possible to send this protocol + * + * @param instance Pointer to a SubGhzTxRx + * @return bool True if it is possible to send this protocol + */ +bool subghz_txrx_protocol_is_transmittable(SubGhzTxRx* instance, bool check_type); + +/** + * Set filter, what types of decoder to use + * + * @param instance Pointer to a SubGhzTxRx + * @param filter Filter + */ +void subghz_txrx_receiver_set_filter(SubGhzTxRx* instance, SubGhzProtocolFlag filter); + +/** + * Set callback for receive data + * + * @param instance Pointer to a SubGhzTxRx + * @param callback Callback for receive data + * @param context Context for callback + */ +void subghz_txrx_set_rx_calback( + SubGhzTxRx* instance, + SubGhzReceiverCallback callback, + void* context); + +/** + * Set callback for Raw decoder, end of data transfer + * + * @param instance Pointer to a SubGhzTxRx + * @param callback Callback for Raw decoder, end of data transfer + * @param context Context for callback + */ +void subghz_txrx_set_raw_file_encoder_worker_callback_end( + SubGhzTxRx* instance, + SubGhzProtocolEncoderRAWCallbackEnd callback, + 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); + +bool subghz_txrx_radio_device_is_tx_alowed(SubGhzTxRx* instance, uint32_t frequency); + +void subghz_txrx_set_debug_pin_state(SubGhzTxRx* instance, bool state); +bool subghz_txrx_get_debug_pin_state(SubGhzTxRx* instance); + +void subghz_txrx_reset_dynamic_and_custom_btns(SubGhzTxRx* instance); + +SubGhzReceiver* subghz_txrx_get_receiver(SubGhzTxRx* instance); // TODO use only in DecodeRaw diff --git a/applications/external/subghz_remote_configurator/application.fam b/applications/external/subghz_remote_configurator/application.fam index 4604a509b..29b7ed082 100644 --- a/applications/external/subghz_remote_configurator/application.fam +++ b/applications/external/subghz_remote_configurator/application.fam @@ -10,6 +10,6 @@ App( stack_size=2 * 1024, order=50, fap_description="File Editor for the SubGhz Remote app", - fap_category="Sub-Ghz", + fap_category="Sub-GHz", fap_icon="subrem_10px.png", ) diff --git a/applications/main/subghz/application.fam b/applications/main/subghz/application.fam index 7da1b9081..37e131cc4 100644 --- a/applications/main/subghz/application.fam +++ b/applications/main/subghz/application.fam @@ -11,10 +11,7 @@ App( ], provides=[ "subghz_start", - "subghz_load_extended_settings", - ], - sdk_headers=[ - "helpers/subghz_txrx.h", + "subghz_load_dangerous_settings", ], icon="A_Sub1ghz_14", stack_size=3 * 1024, @@ -32,9 +29,9 @@ App( ) App( - appid="subghz_load_extended_settings", + appid="subghz_load_dangerous_settings", apptype=FlipperAppType.STARTUP, - entry_point="subghz_extended_freq", + entry_point="subghz_dangerous_freq", requires=["storage", "subghz"], order=650, ) diff --git a/applications/main/subghz/helpers/subghz_chat.c b/applications/main/subghz/helpers/subghz_chat.c index b589ba5d5..6e2ac7388 100644 --- a/applications/main/subghz/helpers/subghz_chat.c +++ b/applications/main/subghz/helpers/subghz_chat.c @@ -76,12 +76,15 @@ void subghz_chat_worker_free(SubGhzChatWorker* 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->worker_running); 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); subghz_tx_rx_worker_set_callback_have_read( instance->subghz_txrx, subghz_chat_worker_update_rx_event_chat, instance); diff --git a/applications/main/subghz/helpers/subghz_chat.h b/applications/main/subghz/helpers/subghz_chat.h index b418bbdbf..2c454b75d 100644 --- a/applications/main/subghz/helpers/subghz_chat.h +++ b/applications/main/subghz/helpers/subghz_chat.h @@ -1,5 +1,6 @@ #pragma once #include "../subghz_i.h" +#include #include typedef struct SubGhzChatWorker SubGhzChatWorker; @@ -20,7 +21,10 @@ typedef struct { SubGhzChatWorker* subghz_chat_worker_alloc(Cli* cli); 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); bool subghz_chat_worker_is_running(SubGhzChatWorker* instance); SubGhzChatEvent subghz_chat_worker_get_event_chat(SubGhzChatWorker* instance); diff --git a/applications/main/subghz/helpers/subghz_threshold_rssi.c b/applications/main/subghz/helpers/subghz_threshold_rssi.c index 04a06bc17..07d7bccf9 100644 --- a/applications/main/subghz/helpers/subghz_threshold_rssi.c +++ b/applications/main/subghz/helpers/subghz_threshold_rssi.c @@ -32,9 +32,8 @@ float subghz_threshold_rssi_get(SubGhzThresholdRssi* instance) { 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); - float rssi = furi_hal_subghz_get_rssi(); SubGhzThresholdRssiData ret = {.rssi = rssi, .is_above = false}; if(float_is_equal(instance->threshold_rssi, SUBGHZ_RAW_THRESHOLD_MIN)) { diff --git a/applications/main/subghz/helpers/subghz_threshold_rssi.h b/applications/main/subghz/helpers/subghz_threshold_rssi.h index e28092acb..1d588e271 100644 --- a/applications/main/subghz/helpers/subghz_threshold_rssi.h +++ b/applications/main/subghz/helpers/subghz_threshold_rssi.h @@ -38,6 +38,7 @@ float subghz_threshold_rssi_get(SubGhzThresholdRssi* instance); /** Check threshold * * @param instance Pointer to a SubGhzThresholdRssi + * @param rssi Current RSSI * @return SubGhzThresholdRssiData */ -SubGhzThresholdRssiData subghz_threshold_get_rssi_data(SubGhzThresholdRssi* instance); +SubGhzThresholdRssiData subghz_threshold_get_rssi_data(SubGhzThresholdRssi* instance, float rssi); diff --git a/applications/main/subghz/helpers/subghz_txrx.c b/applications/main/subghz/helpers/subghz_txrx.c index db833d272..d878c0e04 100644 --- a/applications/main/subghz/helpers/subghz_txrx.c +++ b/applications/main/subghz/helpers/subghz_txrx.c @@ -8,6 +8,21 @@ #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* instance = malloc(sizeof(SubGhzTxRx)); instance->setting = subghz_setting_alloc(); @@ -28,16 +43,15 @@ SubGhzTxRx* subghz_txrx_alloc() { instance->fff_data = flipper_format_string_alloc(); instance->environment = subghz_environment_alloc(); - instance->is_database_loaded = subghz_environment_load_keystore( - instance->environment, EXT_PATH("subghz/assets/keeloq_mfcodes")); - subghz_environment_load_keystore( - instance->environment, EXT_PATH("subghz/assets/keeloq_mfcodes_user")); + instance->is_database_loaded = + subghz_environment_load_keystore(instance->environment, SUBGHZ_KEYSTORE_DIR_NAME); + subghz_environment_load_keystore(instance->environment, SUBGHZ_KEYSTORE_DIR_USER_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( - 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( - instance->environment, EXT_PATH("subghz/assets/nice_flor_s")); + instance->environment, SUBGHZ_NICE_FLOR_S_DIR_NAME); subghz_environment_set_protocol_registry( instance->environment, (void*)&subghz_protocol_registry); instance->receiver = subghz_receiver_alloc_init(instance->environment); @@ -48,18 +62,32 @@ SubGhzTxRx* subghz_txrx_alloc() { instance->worker, (SubGhzWorkerPairCallback)subghz_receiver_decode); 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; } void subghz_txrx_free(SubGhzTxRx* 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_receiver_free(instance->receiver); subghz_environment_free(instance->environment); flipper_format_free(instance->fff_data); furi_string_free(instance->preset->name); subghz_setting_free(instance->setting); + free(instance->preset); free(instance); } @@ -145,7 +173,12 @@ static uint32_t subghz_txrx_rx(SubGhzTxRx* instance, uint32_t frequency) { subghz_devices_idle(instance->radio_device); - 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); instance->txrx_state = SubGhzTxRxStateRx; return value; @@ -154,7 +187,7 @@ static uint32_t subghz_txrx_rx(SubGhzTxRx* instance, uint32_t frequency) { static void subghz_txrx_idle(SubGhzTxRx* instance) { furi_assert(instance); furi_assert(instance->txrx_state != SubGhzTxRxStateSleep); - furi_hal_subghz_idle(); + subghz_devices_idle(instance->radio_device); subghz_txrx_speaker_off(instance); instance->txrx_state = SubGhzTxRxStateIDLE; } @@ -165,24 +198,21 @@ static void subghz_txrx_rx_end(SubGhzTxRx* instance) { if(subghz_worker_is_running(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); instance->txrx_state = SubGhzTxRxStateIDLE; } void subghz_txrx_sleep(SubGhzTxRx* instance) { furi_assert(instance); - furi_hal_subghz_sleep(); + subghz_devices_sleep(instance->radio_device); instance->txrx_state = SubGhzTxRxStateSleep; } static bool subghz_txrx_tx(SubGhzTxRx* instance, uint32_t frequency) { furi_assert(instance); - if(!furi_hal_subghz_is_frequency_valid(frequency)) { - furi_crash("SubGhz: Incorrect TX frequency."); - } furi_assert(instance->txrx_state != SubGhzTxRxStateSleep); subghz_devices_idle(instance->radio_device); @@ -250,8 +280,8 @@ SubGhzTxRxStartTxState subghz_txrx_tx_start(SubGhzTxRx* instance, FlipperFormat* if(ret == SubGhzTxRxStartTxStateOk) { //Start TX - furi_hal_subghz_start_async_tx( - subghz_transmitter_yield, instance->transmitter); + subghz_devices_start_async_tx( + instance->radio_device, subghz_transmitter_yield, instance->transmitter); } } else { ret = SubGhzTxRxStartTxStateErrorParserOthers; @@ -294,7 +324,7 @@ static void subghz_txrx_tx_stop(SubGhzTxRx* instance) { furi_assert(instance); furi_assert(instance->txrx_state == SubGhzTxRxStateTx); //Stop TX - furi_hal_subghz_stop_async_tx(); + subghz_devices_stop_async_tx(instance->radio_device); subghz_transmitter_stop(instance->transmitter); subghz_transmitter_free(instance->transmitter); @@ -307,7 +337,6 @@ static void subghz_txrx_tx_stop(SubGhzTxRx* instance) { subghz_txrx_idle(instance); subghz_txrx_speaker_off(instance); //Todo: Show message - // notification_message(notifications, &sequence_reset_red); } FlipperFormat* subghz_txrx_get_fff_data(SubGhzTxRx* instance) { @@ -357,7 +386,7 @@ void subghz_txrx_hopper_update(SubGhzTxRx* instance) { float rssi = -127.0f; if(instance->hopper_state != SubGhzHopperStateRSSITimeOut) { // 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 if(rssi > -90.0f) { @@ -638,4 +667,4 @@ void subghz_txrx_reset_dynamic_and_custom_btns(SubGhzTxRx* instance) { SubGhzReceiver* subghz_txrx_get_receiver(SubGhzTxRx* instance) { furi_assert(instance); return instance->receiver; -} +} \ No newline at end of file diff --git a/applications/main/subghz/helpers/subghz_txrx.h b/applications/main/subghz/helpers/subghz_txrx.h index d6d420352..76c7c8ead 100644 --- a/applications/main/subghz/helpers/subghz_txrx.h +++ b/applications/main/subghz/helpers/subghz_txrx.h @@ -7,10 +7,7 @@ #include #include #include - -#ifdef __cplusplus -extern "C" { -#endif +#include typedef struct SubGhzTxRx SubGhzTxRx; diff --git a/applications/main/subghz/helpers/subghz_txrx_i.h b/applications/main/subghz/helpers/subghz_txrx_i.h index 5240884ff..f058c2282 100644 --- a/applications/main/subghz/helpers/subghz_txrx_i.h +++ b/applications/main/subghz/helpers/subghz_txrx_i.h @@ -21,6 +21,8 @@ struct SubGhzTxRx { SubGhzTxRxState txrx_state; SubGhzSpeakerState speaker_state; + const SubGhzDevice* radio_device; + SubGhzRadioDeviceType radio_device_type; SubGhzTxRxNeedSaveCallback need_save_callback; void* need_save_context; diff --git a/applications/main/subghz/helpers/subghz_types.h b/applications/main/subghz/helpers/subghz_types.h index 2e7ca468d..0d748a80b 100644 --- a/applications/main/subghz/helpers/subghz_types.h +++ b/applications/main/subghz/helpers/subghz_types.h @@ -35,6 +35,13 @@ typedef enum { SubGhzSpeakerStateEnable, } SubGhzSpeakerState; +/** SubGhzRadioDeviceType */ +typedef enum { + SubGhzRadioDeviceTypeAuto, + SubGhzRadioDeviceTypeInternal, + SubGhzRadioDeviceTypeExternalCC1101, +} SubGhzRadioDeviceType; + /** SubGhzRxKeyState state */ typedef enum { SubGhzRxKeyStateIDLE, diff --git a/applications/main/subghz/scenes/subghz_scene_read_raw.c b/applications/main/subghz/scenes/subghz_scene_read_raw.c index 7394ace90..0be51244d 100644 --- a/applications/main/subghz/scenes/subghz_scene_read_raw.c +++ b/applications/main/subghz/scenes/subghz_scene_read_raw.c @@ -52,6 +52,9 @@ static void subghz_scene_read_raw_update_statusbar(void* context) { furi_string_free(frequency_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) { @@ -116,15 +119,17 @@ void subghz_scene_read_raw_on_enter(void* context) { // Start sending immediately with favorites if(subghz->fav_timeout) { - with_view_model( - subghz->subghz_read_raw->view, - SubGhzReadRAWModel * model, - { - scene_manager_handle_custom_event( - subghz->scene_manager, SubGhzCustomEventViewReadRAWSendStart); - model->status = SubGhzReadRAWStatusTXRepeat; - }, - true); + scene_manager_handle_custom_event( + subghz->scene_manager, SubGhzCustomEventViewReadRAWSendStart); + // with_view_model( + // subghz->subghz_read_raw->view, + // SubGhzReadRAWModel * model, + // { + // scene_manager_handle_custom_event( + // subghz->scene_manager, SubGhzCustomEventViewReadRAWSendStart); + // model->status = SubGhzReadRAWStatusTXRepeat; + // }, + // true); } } @@ -267,7 +272,9 @@ bool subghz_scene_read_raw_on_event(void* context, SceneManagerEvent event) { furi_string_printf( temp_str, "%s/%s%s", SUBGHZ_RAW_FOLDER, RAW_FILE_NAME, SUBGHZ_APP_EXTENSION); 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); if(spl_count > 0) { @@ -327,8 +334,8 @@ bool subghz_scene_read_raw_on_event(void* context, SceneManagerEvent event) { subghz_read_raw_update_sample_write( subghz->subghz_read_raw, subghz_protocol_raw_get_sample_write(decoder_raw)); - 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_read_raw_add_data_rssi( subghz->subghz_read_raw, ret_rssi.rssi, ret_rssi.is_above); subghz_protocol_raw_save_to_file_pause(decoder_raw, !ret_rssi.is_above); diff --git a/applications/main/subghz/scenes/subghz_scene_receiver.c b/applications/main/subghz/scenes/subghz_scene_receiver.c index 427e5e3de..ac09ebcea 100644 --- a/applications/main/subghz/scenes/subghz_scene_receiver.c +++ b/applications/main/subghz/scenes/subghz_scene_receiver.c @@ -80,6 +80,9 @@ static void subghz_scene_receiver_update_statusbar(void* context) { subghz->state_notifications = SubGhzNotificationStateIDLE; } 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) { diff --git a/applications/main/subghz/scenes/subghz_scene_rpc.c b/applications/main/subghz/scenes/subghz_scene_rpc.c index b07ad4a98..724abaf3e 100644 --- a/applications/main/subghz/scenes/subghz_scene_rpc.c +++ b/applications/main/subghz/scenes/subghz_scene_rpc.c @@ -14,6 +14,7 @@ void subghz_scene_rpc_on_enter(void* context) { popup_set_header(popup, "Sub-GHz", 89, 42, AlignCenter, AlignBottom); popup_set_text(popup, "RPC mode", 89, 44, AlignCenter, AlignTop); + popup_set_icon(popup, 0, 12, &I_RFIDDolphinSend_97x61); view_dispatcher_switch_to_view(subghz->view_dispatcher, SubGhzViewIdPopup); diff --git a/applications/main/subghz/scenes/subghz_scene_save_name.c b/applications/main/subghz/scenes/subghz_scene_save_name.c index 845b40f41..07618d7ae 100644 --- a/applications/main/subghz/scenes/subghz_scene_save_name.c +++ b/applications/main/subghz/scenes/subghz_scene_save_name.c @@ -163,7 +163,8 @@ bool subghz_scene_save_name_on_event(void* context, SceneManagerEvent event) { SubGhzCustomEventManagerNoSet) { subghz_protocol_raw_gen_fff_data( 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( subghz->scene_manager, SubGhzSceneReadRAW, SubGhzCustomEventManagerNoSet); } else { diff --git a/applications/main/subghz/scenes/subghz_scene_transmitter.c b/applications/main/subghz/scenes/subghz_scene_transmitter.c index c7c95f457..48dc69ea0 100644 --- a/applications/main/subghz/scenes/subghz_scene_transmitter.c +++ b/applications/main/subghz/scenes/subghz_scene_transmitter.c @@ -39,6 +39,8 @@ bool subghz_scene_transmitter_update_data_show(void* context) { furi_string_free(modulation_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; } @@ -66,19 +68,19 @@ void subghz_scene_transmitter_on_enter(void* context) { // Auto send and exit with favorites if(subghz->fav_timeout) { - subghz_custom_btn_set(0); + // subghz_custom_btn_set(0); scene_manager_handle_custom_event( subghz->scene_manager, SubGhzCustomEventViewTransmitterSendStart); - with_view_model( - subghz->subghz_transmitter->view, - SubGhzViewTransmitterModel * model, - { model->show_button = false; }, - true); + // with_view_model( + // subghz->subghz_transmitter->view, + // SubGhzViewTransmitterModel * model, + // { model->show_button = false; }, + // true); subghz->fav_timer = furi_timer_alloc(fav_timer_callback, FuriTimerTypeOnce, subghz); furi_timer_start( subghz->fav_timer, XTREME_SETTINGS()->favorite_timeout * furi_kernel_get_tick_frequency()); - subghz->state_notifications = SubGhzNotificationStateTx; + // subghz->state_notifications = SubGhzNotificationStateTx; } } diff --git a/applications/main/subghz/subghz_cli.c b/applications/main/subghz/subghz_cli.c index 1d49038eb..d58c66917 100644 --- a/applications/main/subghz/subghz_cli.c +++ b/applications/main/subghz/subghz_cli.c @@ -10,6 +10,10 @@ #include #include #include +#include +#include +#include +#include #include "helpers/subghz_chat.h" @@ -65,7 +69,7 @@ void subghz_cli_command_tx_carrier(Cli* cli, FuriString* args, void* context) { } 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); furi_hal_gpio_init(&gpio_cc1101_g0, GpioModeOutputPushPull, GpioPullNo, GpioSpeedLow); @@ -109,7 +113,7 @@ void subghz_cli_command_rx_carrier(Cli* cli, FuriString* args, void* context) { } 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); printf("Receiving at frequency %lu Hz\r\n", frequency); printf("Press CTRL+C to stop\r\n"); @@ -157,21 +161,29 @@ void subghz_cli_command_tx(Cli* cli, FuriString* args, void* context) { uint32_t key = 0x0074BADE; uint32_t repeat = 10; uint32_t te = 403; + uint32_t device_ind = 0; // 0 - CC1101_INT, 1 - CC1101_EXT if(furi_string_size(args)) { - int ret = - sscanf(furi_string_get_cstr(args), "%lx %lu %lu %lu", &key, &frequency, &te, &repeat); - if(ret != 4) { + int ret = sscanf( + furi_string_get_cstr(args), + "%lx %lu %lu %lu %lu", + &key, + &frequency, + &te, + &repeat, + &device_ind); + if(ret != 5) { 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, key, frequency, te, - repeat); + repeat, + device_ind); cli_print_usage( "subghz tx", - "<3 Byte Key: in hex> ", + "<3 Byte Key: in hex> ", furi_string_get_cstr(args)); return; } @@ -186,11 +198,12 @@ void subghz_cli_command_tx(Cli* cli, FuriString* args, void* context) { return; } 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, key, te, - repeat); + repeat, + device_ind); FuriString* flipper_format_string = furi_string_alloc_printf( "Protocol: Princeton\n" @@ -214,25 +227,29 @@ void subghz_cli_command_tx(Cli* cli, FuriString* args, void* context) { SubGhzTransmitter* transmitter = subghz_transmitter_alloc_init(environment, "Princeton"); subghz_transmitter_deserialize(transmitter, flipper_format); - furi_hal_subghz_reset(); - furi_hal_subghz_load_preset(FuriHalSubGhzPresetOok650Async); - frequency = furi_hal_subghz_set_frequency_and_path(frequency); + subghz_devices_begin(device); + subghz_devices_reset(device); + subghz_devices_load_preset(device, FuriHalSubGhzPresetOok650Async, NULL); + frequency = subghz_devices_set_frequency(device, frequency); furi_hal_power_suppress_charge_enter(); - - if(furi_hal_subghz_start_async_tx(subghz_transmitter_yield, transmitter)) { - while(!(furi_hal_subghz_is_async_tx_complete() || cli_cmd_interrupt_received(cli))) { + if(subghz_devices_start_async_tx(device, subghz_transmitter_yield, transmitter)) { + while(!(subghz_devices_is_async_complete_tx(device) || cli_cmd_interrupt_received(cli))) { printf("."); fflush(stdout); furi_delay_ms(333); } - furi_hal_subghz_stop_async_tx(); + subghz_devices_stop_async_tx(device); } else { printf("Frequency is outside of default range. Check docs.\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(); flipper_format_free(flipper_format); @@ -276,12 +293,17 @@ static void subghz_cli_command_rx_callback( void subghz_cli_command_rx(Cli* cli, FuriString* args, void* context) { UNUSED(context); uint32_t frequency = 433920000; + uint32_t device_ind = 0; // 0 - CC1101_INT, 1 - CC1101_EXT if(furi_string_size(args)) { - int ret = sscanf(furi_string_get_cstr(args), "%lu", &frequency); - if(ret != 1) { - printf("sscanf returned %d, frequency: %lu\r\n", ret, frequency); - cli_print_usage("subghz rx", "", furi_string_get_cstr(args)); + int ret = sscanf(furi_string_get_cstr(args), "%lu %lu", &frequency, &device_ind); + if(ret != 2) { + printf( + "sscanf returned %d, frequency: %lu device: %lu\r\n", ret, frequency, device_ind); + cli_print_usage( + "subghz rx", + " ", + furi_string_get_cstr(args)); return; } } @@ -302,14 +324,14 @@ void subghz_cli_command_rx(Cli* cli, FuriString* args, void* context) { furi_check(instance->stream); SubGhzEnvironment* environment = subghz_environment_alloc(); - subghz_environment_load_keystore(environment, EXT_PATH("subghz/assets/keeloq_mfcodes")); - subghz_environment_load_keystore(environment, EXT_PATH("subghz/assets/keeloq_mfcodes_user")); + subghz_environment_load_keystore(environment, SUBGHZ_KEYSTORE_DIR_NAME); + subghz_environment_load_keystore(environment, SUBGHZ_KEYSTORE_DIR_USER_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( - 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( - 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); SubGhzReceiver* receiver = subghz_receiver_alloc_init(environment); @@ -325,10 +347,13 @@ void subghz_cli_command_rx(Cli* cli, FuriString* args, void* context) { furi_hal_power_suppress_charge_enter(); // 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 - 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; while(!cli_cmd_interrupt_received(cli)) { int ret = furi_stream_buffer_receive( @@ -346,8 +371,11 @@ void subghz_cli_command_rx(Cli* cli, FuriString* args, void* context) { } // Shutdown radio - furi_hal_subghz_stop_async_rx(); - furi_hal_subghz_sleep(); + subghz_devices_stop_async_rx(device); + subghz_devices_sleep(device); + subghz_devices_end(device); + subghz_devices_deinit(); + subghz_cli_radio_device_power_off(); furi_hal_power_suppress_charge_exit(); @@ -435,6 +463,7 @@ void subghz_cli_command_rx_raw(Cli* cli, FuriString* args, void* context) { furi_stream_buffer_free(instance->stream); free(instance); } + void subghz_cli_command_decode_raw(Cli* cli, FuriString* args, void* context) { UNUSED(context); FuriString* file_name = furi_string_alloc(); @@ -486,25 +515,23 @@ void subghz_cli_command_decode_raw(Cli* cli, FuriString* args, void* context) { SubGhzCliCommandRx* instance = malloc(sizeof(SubGhzCliCommandRx)); SubGhzEnvironment* environment = subghz_environment_alloc(); - if(subghz_environment_load_keystore( - environment, EXT_PATH("subghz/assets/keeloq_mfcodes"))) { + if(subghz_environment_load_keystore(environment, SUBGHZ_KEYSTORE_DIR_NAME)) { printf("SubGhz decode_raw: Load_keystore keeloq_mfcodes \033[0;32mOK\033[0m\r\n"); } else { printf("SubGhz decode_raw: Load_keystore keeloq_mfcodes \033[0;31mERROR\033[0m\r\n"); } - if(subghz_environment_load_keystore( - environment, EXT_PATH("subghz/assets/keeloq_mfcodes_user"))) { + if(subghz_environment_load_keystore(environment, SUBGHZ_KEYSTORE_DIR_USER_NAME)) { printf("SubGhz decode_raw: Load_keystore keeloq_mfcodes_user \033[0;32mOK\033[0m\r\n"); } else { printf( "SubGhz decode_raw: Load_keystore keeloq_mfcodes_user \033[0;31mERROR\033[0m\r\n"); } 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( - 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( - 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); SubGhzReceiver* receiver = subghz_receiver_alloc_init(environment); @@ -512,7 +539,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); 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 furi_delay_ms(100); } @@ -554,10 +582,11 @@ static void subghz_cli_command_print_usage() { printf("subghz \r\n"); printf("Cmd list:\r\n"); - printf("\tchat \t - Chat with other Flippers\r\n"); printf( - "\ttx <3 byte Key: in hex> \t - Transmitting key\r\n"); - printf("\trx \t - Receive\r\n"); + "\tchat \t - Chat with other Flippers\r\n"); + printf( + "\ttx <3 byte Key: in hex> \t - Transmitting key\r\n"); + printf("\trx \t - Receive\r\n"); printf("\trx_raw \t - Receive RAW\r\n"); printf("\tdecode_raw \t - Testing\r\n"); @@ -652,12 +681,17 @@ static void subghz_cli_command_encrypt_raw(Cli* cli, FuriString* args) { static void subghz_cli_command_chat(Cli* cli, FuriString* args, void* context) { UNUSED(context); uint32_t frequency = 433920000; + uint32_t device_ind = 0; // 0 - CC1101_INT, 1 - CC1101_EXT if(furi_string_size(args)) { - int ret = sscanf(furi_string_get_cstr(args), "%lu", &frequency); - if(ret != 1) { - printf("sscanf returned %d, frequency: %lu\r\n", ret, frequency); - cli_print_usage("subghz chat", "", furi_string_get_cstr(args)); + int ret = sscanf(furi_string_get_cstr(args), "%lu %lu", &frequency, &device_ind); + if(ret != 2) { + printf("sscanf returned %d, Frequency: %lu\r\n", ret, frequency); + printf("sscanf returned %d, Device: %lu\r\n", ret, device_ind); + cli_print_usage( + "subghz chat", + " ", + furi_string_get_cstr(args)); return; } } @@ -681,7 +715,8 @@ static void subghz_cli_command_chat(Cli* cli, FuriString* args, void* context) { } 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"); if(subghz_chat_worker_is_running(subghz_chat)) { @@ -823,6 +858,10 @@ static void subghz_cli_command_chat(Cli* cli, FuriString* args, void* context) { furi_string_free(name); furi_string_free(output); furi_string_free(sysmsg); + + subghz_devices_deinit(); + subghz_cli_radio_device_power_off(); + furi_hal_power_suppress_charge_exit(); furi_record_close(RECORD_NOTIFICATION); diff --git a/applications/main/subghz/subghz_dangerous_freq.c b/applications/main/subghz/subghz_dangerous_freq.c new file mode 100644 index 000000000..69a54f04b --- /dev/null +++ b/applications/main/subghz/subghz_dangerous_freq.c @@ -0,0 +1,23 @@ +#include +#include + +#include + +#include + +void subghz_dangerous_freq() { + bool is_extended_i = false; + + Storage* storage = furi_record_open(RECORD_STORAGE); + FlipperFormat* fff_data_file = flipper_format_file_alloc(storage); + + if(flipper_format_file_open_existing(fff_data_file, "/ext/subghz/assets/dangerous_settings")) { + flipper_format_read_bool( + fff_data_file, "yes_i_want_to_destroy_my_flipper", &is_extended_i, 1); + } + + furi_hal_subghz_set_dangerous_frequency(is_extended_i); + + flipper_format_free(fff_data_file); + furi_record_close(RECORD_STORAGE); +} diff --git a/applications/main/subghz/subghz_extended_freq.c b/applications/main/subghz/subghz_extended_freq.c deleted file mode 100644 index bbd44f639..000000000 --- a/applications/main/subghz/subghz_extended_freq.c +++ /dev/null @@ -1,19 +0,0 @@ -#include -#include -#include -#include - -void subghz_extended_freq() { - bool is_extended_i = false; - Storage* storage = furi_record_open(RECORD_STORAGE); - FlipperFormat* file = flipper_format_file_alloc(storage); - - if(flipper_format_file_open_existing(file, "/ext/subghz/assets/extend_range.txt")) { - flipper_format_read_bool(file, "use_ext_range_at_own_risk", &is_extended_i, 1); - } - - furi_hal_subghz_set_extended_frequency(is_extended_i); - - flipper_format_free(file); - furi_record_close(RECORD_STORAGE); -} diff --git a/applications/main/subghz/subghz_i.c b/applications/main/subghz/subghz_i.c index b16900177..f91f128cf 100644 --- a/applications/main/subghz/subghz_i.c +++ b/applications/main/subghz/subghz_i.c @@ -170,7 +170,8 @@ bool subghz_key_load(SubGhz* subghz, const char* file_path, bool show_dialog) { if(!strcmp(furi_string_get_cstr(temp_str), "RAW")) { //if RAW 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 { subghz->load_type_file = SubGhzLoadTypeFileKey; stream_copy_full( diff --git a/applications/main/subghz/views/subghz_read_raw.c b/applications/main/subghz/views/subghz_read_raw.c index 2a10e9d2e..45668a6fc 100644 --- a/applications/main/subghz/views/subghz_read_raw.c +++ b/applications/main/subghz/views/subghz_read_raw.c @@ -59,6 +59,14 @@ void subghz_read_raw_add_data_statusbar( 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) { furi_assert(instance); uint8_t u_rssi = 0; diff --git a/applications/main/subghz/views/subghz_read_raw.h b/applications/main/subghz/views/subghz_read_raw.h index f9a56ca04..c7d87f2d5 100644 --- a/applications/main/subghz/views/subghz_read_raw.h +++ b/applications/main/subghz/views/subghz_read_raw.h @@ -1,17 +1,14 @@ #pragma once #include +#include "../helpers/subghz_types.h" #include "../helpers/subghz_custom_event.h" #define SUBGHZ_RAW_THRESHOLD_MIN -90.0f -typedef void (*SubGhzReadRAWCallback)(SubGhzCustomEvent event, void* context); +typedef struct SubGhzReadRAW SubGhzReadRAW; -typedef struct { - View* view; - SubGhzReadRAWCallback callback; - void* context; -} SubGhzReadRAW; +typedef void (*SubGhzReadRAWCallback)(SubGhzCustomEvent event, void* context); typedef enum { SubGhzReadRAWStatusStart, @@ -26,22 +23,6 @@ typedef enum { SubGhzReadRAWStatusSaveKey, } SubGhzReadRAWStatus; -typedef struct { - FuriString* frequency_str; - FuriString* preset_str; - FuriString* sample_write; - FuriString* file_name; - uint8_t* rssi_history; - uint8_t rssi_current; - bool rssi_history_end; - uint8_t ind_write; - uint8_t ind_sin; - SubGhzReadRAWStatus status; - bool raw_send_only; - float raw_threshold_rssi; - bool not_showing_samples; -} SubGhzReadRAWModel; - void subghz_read_raw_set_callback( SubGhzReadRAW* subghz_read_raw, SubGhzReadRAWCallback callback, @@ -56,6 +37,10 @@ void subghz_read_raw_add_data_statusbar( const char* frequency_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_stop_send(SubGhzReadRAW* instance); diff --git a/applications/main/subghz/views/transmitter.c b/applications/main/subghz/views/transmitter.c index d555b2244..16a2ea110 100644 --- a/applications/main/subghz/views/transmitter.c +++ b/applications/main/subghz/views/transmitter.c @@ -51,6 +51,17 @@ void subghz_view_transmitter_add_data_to_show( 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) { const uint8_t button_height = 12; const uint8_t vertical_offset = 3; diff --git a/applications/main/subghz/views/transmitter.h b/applications/main/subghz/views/transmitter.h index e121c8746..19da3145c 100644 --- a/applications/main/subghz/views/transmitter.h +++ b/applications/main/subghz/views/transmitter.h @@ -1,30 +1,22 @@ #pragma once #include +#include "../helpers/subghz_types.h" #include "../helpers/subghz_custom_event.h" -typedef struct { - FuriString* frequency_str; - FuriString* preset_str; - FuriString* key_str; - bool show_button; - FuriString* temp_button_id; - bool draw_temp_button; -} SubGhzViewTransmitterModel; +typedef struct SubGhzViewTransmitter SubGhzViewTransmitter; typedef void (*SubGhzViewTransmitterCallback)(SubGhzCustomEvent event, void* context); -typedef struct { - View* view; - SubGhzViewTransmitterCallback callback; - void* context; -} SubGhzViewTransmitter; - void subghz_view_transmitter_set_callback( SubGhzViewTransmitter* subghz_transmitter, SubGhzViewTransmitterCallback callback, void* context); +void subghz_view_transmitter_set_radio_device_type( + SubGhzViewTransmitter* subghz_transmitter, + SubGhzRadioDeviceType device_type); + SubGhzViewTransmitter* subghz_view_transmitter_alloc(); void subghz_view_transmitter_free(SubGhzViewTransmitter* subghz_transmitter); diff --git a/firmware/targets/f7/api_symbols.csv b/firmware/targets/f7/api_symbols.csv index 2e372506f..535afe8c7 100644 --- a/firmware/targets/f7/api_symbols.csv +++ b/firmware/targets/f7/api_symbols.csv @@ -1,7 +1,6 @@ entry,status,name,type,params Version,+,34.1,, Header,+,applications/main/archive/helpers/favorite_timeout.h,, -Header,+,applications/main/subghz/helpers/subghz_txrx.h,, Header,+,applications/services/bt/bt_service/bt.h,, Header,+,applications/services/cli/cli.h,, Header,+,applications/services/cli/cli_vcp.h,, @@ -2983,42 +2982,6 @@ Function,+,subghz_tx_rx_worker_set_callback_have_read,void,"SubGhzTxRxWorker*, S Function,+,subghz_tx_rx_worker_start,_Bool,"SubGhzTxRxWorker*, uint32_t" Function,+,subghz_tx_rx_worker_stop,void,SubGhzTxRxWorker* Function,+,subghz_tx_rx_worker_write,_Bool,"SubGhzTxRxWorker*, uint8_t*, size_t" -Function,+,subghz_txrx_alloc,SubGhzTxRx*, -Function,+,subghz_txrx_free,void,SubGhzTxRx* -Function,-,subghz_txrx_get_debug_pin_state,_Bool,SubGhzTxRx* -Function,+,subghz_txrx_get_decoder,SubGhzProtocolDecoderBase*,SubGhzTxRx* -Function,-,subghz_txrx_get_fff_data,FlipperFormat*,SubGhzTxRx* -Function,-,subghz_txrx_get_frequency_and_modulation,void,"SubGhzTxRx*, FuriString*, FuriString*, _Bool" -Function,-,subghz_txrx_get_preset,SubGhzRadioPreset,SubGhzTxRx* -Function,+,subghz_txrx_get_preset_name,const char*,"SubGhzTxRx*, const char*" -Function,-,subghz_txrx_get_receiver,SubGhzReceiver*,SubGhzTxRx* -Function,+,subghz_txrx_get_setting,SubGhzSetting*,SubGhzTxRx* -Function,-,subghz_txrx_hopper_get_state,SubGhzHopperState,SubGhzTxRx* -Function,-,subghz_txrx_hopper_pause,void,SubGhzTxRx* -Function,-,subghz_txrx_hopper_set_state,void,"SubGhzTxRx*, SubGhzHopperState" -Function,-,subghz_txrx_hopper_unpause,void,SubGhzTxRx* -Function,-,subghz_txrx_hopper_update,void,SubGhzTxRx* -Function,-,subghz_txrx_is_database_loaded,_Bool,SubGhzTxRx* -Function,+,subghz_txrx_load_decoder_by_name_protocol,_Bool,"SubGhzTxRx*, const char*" -Function,-,subghz_txrx_protocol_is_serializable,_Bool,SubGhzTxRx* -Function,-,subghz_txrx_protocol_is_transmittable,_Bool,"SubGhzTxRx*, _Bool" -Function,-,subghz_txrx_receiver_set_filter,void,"SubGhzTxRx*, SubGhzProtocolFlag" -Function,+,subghz_txrx_reset_dynamic_and_custom_btns,void,SubGhzTxRx* -Function,-,subghz_txrx_rx_start,void,SubGhzTxRx* -Function,-,subghz_txrx_set_debug_pin_state,void,"SubGhzTxRx*, _Bool" -Function,+,subghz_txrx_set_need_save_callback,void,"SubGhzTxRx*, SubGhzTxRxNeedSaveCallback, void*" -Function,+,subghz_txrx_set_preset,void,"SubGhzTxRx*, const char*, uint32_t, uint8_t*, size_t" -Function,+,subghz_txrx_set_raw_file_encoder_worker_callback_end,void,"SubGhzTxRx*, SubGhzProtocolEncoderRAWCallbackEnd, void*" -Function,-,subghz_txrx_set_rx_calback,void,"SubGhzTxRx*, SubGhzReceiverCallback, void*" -Function,-,subghz_txrx_sleep,void,SubGhzTxRx* -Function,-,subghz_txrx_speaker_get_state,SubGhzSpeakerState,SubGhzTxRx* -Function,-,subghz_txrx_speaker_mute,void,SubGhzTxRx* -Function,-,subghz_txrx_speaker_off,void,SubGhzTxRx* -Function,-,subghz_txrx_speaker_on,void,SubGhzTxRx* -Function,-,subghz_txrx_speaker_set_state,void,"SubGhzTxRx*, SubGhzSpeakerState" -Function,-,subghz_txrx_speaker_unmute,void,SubGhzTxRx* -Function,+,subghz_txrx_stop,void,SubGhzTxRx* -Function,+,subghz_txrx_tx_start,SubGhzTxRxStartTxState,"SubGhzTxRx*, FlipperFormat*" Function,+,subghz_worker_alloc,SubGhzWorker*, Function,+,subghz_worker_free,void,SubGhzWorker* Function,+,subghz_worker_is_running,_Bool,SubGhzWorker* diff --git a/lib/subghz/SConscript b/lib/subghz/SConscript index ae0816582..575d27b2a 100644 --- a/lib/subghz/SConscript +++ b/lib/subghz/SConscript @@ -14,7 +14,6 @@ env.Append( File("transmitter.h"), File("protocols/raw.h"), File("blocks/const.h"), - File("blocks/custom_btn.h"), File("blocks/decoder.h"), File("blocks/encoder.h"), File("blocks/generic.h"), @@ -22,6 +21,7 @@ env.Append( File("blocks/custom_btn.h"), File("subghz_setting.h"), File("subghz_protocol_registry.h"), + File("devices/cc1101_configs.h"), ], ) diff --git a/lib/subghz/devices/cc1101_int/cc1101_int_interconnect.c b/lib/subghz/devices/cc1101_int/cc1101_int_interconnect.c new file mode 100644 index 000000000..41a0609df --- /dev/null +++ b/lib/subghz/devices/cc1101_int/cc1101_int_interconnect.c @@ -0,0 +1,96 @@ +#include "cc1101_int_interconnect.h" +#include +#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, +}; diff --git a/lib/subghz/devices/cc1101_int/cc1101_int_interconnect.h b/lib/subghz/devices/cc1101_int/cc1101_int_interconnect.h new file mode 100644 index 000000000..629d1264c --- /dev/null +++ b/lib/subghz/devices/cc1101_int/cc1101_int_interconnect.h @@ -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; diff --git a/lib/subghz/devices/device_registry.h b/lib/subghz/devices/device_registry.h new file mode 100644 index 000000000..70a0db4b2 --- /dev/null +++ b/lib/subghz/devices/device_registry.h @@ -0,0 +1,13 @@ +#pragma once + +#include "registry.h" + +#ifdef __cplusplus +extern "C" { +#endif + +extern const SubGhzDeviceRegistry subghz_device_registry; + +#ifdef __cplusplus +} +#endif diff --git a/lib/subghz/devices/devices.h b/lib/subghz/devices/devices.h new file mode 100644 index 000000000..dad3c9aeb --- /dev/null +++ b/lib/subghz/devices/devices.h @@ -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 diff --git a/lib/subghz/devices/preset.h b/lib/subghz/devices/preset.h new file mode 100644 index 000000000..8716f2e23 --- /dev/null +++ b/lib/subghz/devices/preset.h @@ -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; diff --git a/lib/subghz/devices/registry.c b/lib/subghz/devices/registry.c new file mode 100644 index 000000000..c0d5bb292 --- /dev/null +++ b/lib/subghz/devices/registry.c @@ -0,0 +1,76 @@ +#include "registry.h" + +#include "cc1101_int/cc1101_int_interconnect.h" +#include +#include + +#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; + } +} diff --git a/lib/subghz/devices/registry.h b/lib/subghz/devices/registry.h new file mode 100644 index 000000000..520058920 --- /dev/null +++ b/lib/subghz/devices/registry.h @@ -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 diff --git a/lib/subghz/devices/types.h b/lib/subghz/devices/types.h new file mode 100644 index 000000000..8a4198426 --- /dev/null +++ b/lib/subghz/devices/types.h @@ -0,0 +1,91 @@ +#pragma once + +#include +#include +#include + +#include +#include + +#include "preset.h" + +#include + +#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; +}; diff --git a/lib/subghz/protocols/alutech_at_4n.h b/lib/subghz/protocols/alutech_at_4n.h index 68d6580ea..b7b5b9ede 100644 --- a/lib/subghz/protocols/alutech_at_4n.h +++ b/lib/subghz/protocols/alutech_at_4n.h @@ -1,10 +1,6 @@ #pragma once #include "base.h" -#ifdef __cplusplus -extern "C" { -#endif - #define SUBGHZ_PROTOCOL_ALUTECH_AT_4N_NAME "Alutech AT-4N" typedef struct SubGhzProtocolDecoderAlutech_at_4n SubGhzProtocolDecoderAlutech_at_4n; @@ -128,7 +124,3 @@ SubGhzProtocolStatus * @param output Resulting text */ void subghz_protocol_decoder_alutech_at_4n_get_string(void* context, FuriString* output); - -#ifdef __cplusplus -} -#endif diff --git a/lib/subghz/protocols/keeloq.h b/lib/subghz/protocols/keeloq.h index 988b37c24..a757e82d5 100644 --- a/lib/subghz/protocols/keeloq.h +++ b/lib/subghz/protocols/keeloq.h @@ -2,10 +2,6 @@ #include "base.h" -#ifdef __cplusplus -extern "C" { -#endif - #define SUBGHZ_PROTOCOL_KEELOQ_NAME "KeeLoq" typedef struct SubGhzProtocolDecoderKeeloq SubGhzProtocolDecoderKeeloq; @@ -153,7 +149,3 @@ SubGhzProtocolStatus * @param output Resulting text */ void subghz_protocol_decoder_keeloq_get_string(void* context, FuriString* output); - -#ifdef __cplusplus -} -#endif diff --git a/lib/subghz/protocols/nice_flor_s.h b/lib/subghz/protocols/nice_flor_s.h index 56ef15aa3..5f8b30644 100644 --- a/lib/subghz/protocols/nice_flor_s.h +++ b/lib/subghz/protocols/nice_flor_s.h @@ -2,10 +2,6 @@ #include "base.h" -#ifdef __cplusplus -extern "C" { -#endif - #define SUBGHZ_PROTOCOL_NICE_FLOR_S_NAME "Nice FloR-S" typedef struct SubGhzProtocolDecoderNiceFlorS SubGhzProtocolDecoderNiceFlorS; @@ -133,7 +129,3 @@ SubGhzProtocolStatus * @param output Resulting text */ void subghz_protocol_decoder_nice_flor_s_get_string(void* context, FuriString* output); - -#ifdef __cplusplus -} -#endif diff --git a/lib/subghz/protocols/raw.c b/lib/subghz/protocols/raw.c index a82c9cf83..d945d19a1 100644 --- a/lib/subghz/protocols/raw.c +++ b/lib/subghz/protocols/raw.c @@ -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; diff --git a/lib/subghz/protocols/raw.h b/lib/subghz/protocols/raw.h index 4f67a4e2f..6d791bb36 100644 --- a/lib/subghz/protocols/raw.h +++ b/lib/subghz/protocols/raw.h @@ -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. diff --git a/lib/subghz/protocols/secplus_v2.h b/lib/subghz/protocols/secplus_v2.h index c71038bcb..0eea732af 100644 --- a/lib/subghz/protocols/secplus_v2.h +++ b/lib/subghz/protocols/secplus_v2.h @@ -1,10 +1,6 @@ #pragma once #include "base.h" -#ifdef __cplusplus -extern "C" { -#endif - #define SUBGHZ_PROTOCOL_SECPLUS_V2_NAME "Security+ 2.0" typedef struct SubGhzProtocolDecoderSecPlus_v2 SubGhzProtocolDecoderSecPlus_v2; @@ -129,7 +125,3 @@ SubGhzProtocolStatus * @param output Resulting text */ void subghz_protocol_decoder_secplus_v2_get_string(void* context, FuriString* output); - -#ifdef __cplusplus -} -#endif diff --git a/lib/subghz/protocols/somfy_telis.h b/lib/subghz/protocols/somfy_telis.h index 053940304..cb5cf8e96 100644 --- a/lib/subghz/protocols/somfy_telis.h +++ b/lib/subghz/protocols/somfy_telis.h @@ -2,10 +2,6 @@ #include "base.h" -#ifdef __cplusplus -extern "C" { -#endif - #define SUBGHZ_PROTOCOL_SOMFY_TELIS_NAME "Somfy Telis" typedef struct SubGhzProtocolDecoderSomfyTelis SubGhzProtocolDecoderSomfyTelis; @@ -129,7 +125,3 @@ SubGhzProtocolStatus * @param output Resulting text */ void subghz_protocol_decoder_somfy_telis_get_string(void* context, FuriString* output); - -#ifdef __cplusplus -} -#endif diff --git a/lib/subghz/protocols/star_line.h b/lib/subghz/protocols/star_line.h index 7400e1e01..851819ec7 100644 --- a/lib/subghz/protocols/star_line.h +++ b/lib/subghz/protocols/star_line.h @@ -2,10 +2,6 @@ #include "base.h" -#ifdef __cplusplus -extern "C" { -#endif - #define SUBGHZ_PROTOCOL_STAR_LINE_NAME "Star Line" typedef struct SubGhzProtocolDecoderStarLine SubGhzProtocolDecoderStarLine; @@ -131,7 +127,3 @@ SubGhzProtocolStatus * @param output Resulting text */ void subghz_protocol_decoder_star_line_get_string(void* context, FuriString* output); - -#ifdef __cplusplus -} -#endif diff --git a/lib/subghz/subghz_file_encoder_worker.c b/lib/subghz/subghz_file_encoder_worker.c index fce4e8592..3534745b7 100644 --- a/lib/subghz/subghz_file_encoder_worker.c +++ b/lib/subghz/subghz_file_encoder_worker.c @@ -3,6 +3,7 @@ #include #include #include +#include #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; @@ -180,10 +182,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_stopping) { @@ -230,12 +235,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); diff --git a/lib/subghz/subghz_file_encoder_worker.h b/lib/subghz/subghz_file_encoder_worker.h index f90875c98..eace03348 100644 --- a/lib/subghz/subghz_file_encoder_worker.h +++ b/lib/subghz/subghz_file_encoder_worker.h @@ -51,9 +51,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 diff --git a/lib/subghz/subghz_setting.c b/lib/subghz/subghz_setting.c index 5e936b33b..8efe85f7b 100644 --- a/lib/subghz/subghz_setting.c +++ b/lib/subghz/subghz_setting.c @@ -3,7 +3,7 @@ //#include "subghz_i.h" #include -#include +#include #define TAG "SubGhzSetting" @@ -141,8 +141,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; @@ -158,10 +157,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( @@ -185,25 +182,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); } // Region check removed @@ -262,6 +247,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); diff --git a/lib/subghz/subghz_tx_rx_worker.c b/lib/subghz/subghz_tx_rx_worker.c index b9d2f3c61..4eca17419 100644 --- a/lib/subghz/subghz_tx_rx_worker.c +++ b/lib/subghz/subghz_tx_rx_worker.c @@ -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,7 +67,7 @@ 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); } @@ -74,24 +76,24 @@ bool subghz_tx_rx_worker_rx(SubGhzTxRxWorker* instance, uint8_t* data, uint8_t* 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,10 +101,10 @@ 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( instance->device_data_gpio)) { // Wait for GDO0 to be set -> sync transmitted @@ -120,7 +122,7 @@ void subghz_tx_rx_worker_tx(SubGhzTxRxWorker* instance, uint8_t* data, size_t si break; } } - furi_hal_subghz_idle(); + subghz_devices_idle(instance->device); instance->status = SubGhzTxRxWorkerStatusIDLE; } /** Worker thread @@ -130,6 +132,7 @@ 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"); subghz_devices_begin(instance->device); @@ -138,8 +141,10 @@ static int32_t subghz_tx_rx_worker_thread(void* context) { 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; @@ -193,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; @@ -226,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; @@ -237,6 +245,7 @@ bool subghz_tx_rx_worker_start(SubGhzTxRxWorker* instance, uint32_t frequency) { if(furi_hal_subghz_is_tx_allowed(frequency)) { instance->frequency = frequency; + instance->device = device; res = true; } diff --git a/lib/subghz/subghz_tx_rx_worker.h b/lib/subghz/subghz_tx_rx_worker.h index ddc02e749..56bdb0a1f 100644 --- a/lib/subghz/subghz_tx_rx_worker.h +++ b/lib/subghz/subghz_tx_rx_worker.h @@ -1,6 +1,7 @@ #pragma once #include +#include #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 diff --git a/lib/subghz/types.h b/lib/subghz/types.h index 70a57d3f9..d0b500a85 100644 --- a/lib/subghz/types.h +++ b/lib/subghz/types.h @@ -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;