unleashed-firmware/applications/main/subghz/helpers/subghz_txrx.c

702 lines
23 KiB
C
Raw Normal View History

2023-05-09 18:20:35 +00:00
#include "subghz_txrx_i.h"
2023-06-18 17:25:40 +00:00
2023-05-09 14:30:01 +00:00
#include <lib/subghz/protocols/protocol_items.h>
2023-06-18 17:25:40 +00:00
#include <applications/drivers/subghz/cc1101_ext/cc1101_ext_interconnect.h>
#include <lib/subghz/devices/cc1101_int/cc1101_int_interconnect.h>
2023-05-30 19:18:54 +00:00
#include <lib/subghz/blocks/custom_btn.h>
#define TAG "SubGhzTxRx"
2023-06-18 17:25:40 +00:00
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();
}
2023-05-09 14:30:01 +00:00
SubGhzTxRx* subghz_txrx_alloc() {
2023-05-09 16:10:56 +00:00
SubGhzTxRx* instance = malloc(sizeof(SubGhzTxRx));
instance->setting = subghz_setting_alloc();
subghz_setting_load(instance->setting, EXT_PATH("subghz/assets/setting_user"));
2023-05-09 14:30:01 +00:00
2023-05-09 16:10:56 +00:00
instance->preset = malloc(sizeof(SubGhzRadioPreset));
instance->preset->name = furi_string_alloc();
subghz_txrx_set_default_preset(instance, 0);
2023-05-09 14:30:01 +00:00
2023-05-09 16:10:56 +00:00
instance->txrx_state = SubGhzTxRxStateSleep;
2023-05-09 14:30:01 +00:00
2023-05-09 16:10:56 +00:00
subghz_txrx_hopper_set_state(instance, SubGhzHopperStateOFF);
subghz_txrx_speaker_set_state(instance, SubGhzSpeakerStateDisable);
subghz_txrx_set_debug_pin_state(instance, false);
2023-05-09 14:30:01 +00:00
2023-05-09 16:10:56 +00:00
instance->worker = subghz_worker_alloc();
instance->fff_data = flipper_format_string_alloc();
2023-05-09 14:30:01 +00:00
2023-05-09 16:10:56 +00:00
instance->environment = subghz_environment_alloc();
2023-06-18 13:44:45 +00:00
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);
2023-05-09 14:30:01 +00:00
subghz_environment_set_came_atomo_rainbow_table_file_name(
2023-06-18 13:44:45 +00:00
instance->environment, SUBGHZ_CAME_ATOMO_DIR_NAME);
2023-05-09 14:30:01 +00:00
subghz_environment_set_alutech_at_4n_rainbow_table_file_name(
2023-06-18 13:44:45 +00:00
instance->environment, SUBGHZ_ALUTECH_AT_4N_DIR_NAME);
2023-05-09 14:30:01 +00:00
subghz_environment_set_nice_flor_s_rainbow_table_file_name(
2023-06-18 13:44:45 +00:00
instance->environment, SUBGHZ_NICE_FLOR_S_DIR_NAME);
2023-05-09 16:10:56 +00:00
subghz_environment_set_protocol_registry(
instance->environment, (void*)&subghz_protocol_registry);
instance->receiver = subghz_receiver_alloc_init(instance->environment);
2023-05-09 14:30:01 +00:00
subghz_worker_set_overrun_callback(
2023-05-09 16:10:56 +00:00
instance->worker, (SubGhzWorkerOverrunCallback)subghz_receiver_reset);
2023-05-09 14:30:01 +00:00
subghz_worker_set_pair_callback(
2023-05-09 16:10:56 +00:00
instance->worker, (SubGhzWorkerPairCallback)subghz_receiver_decode);
subghz_worker_set_context(instance->worker, instance->receiver);
2023-05-09 14:30:01 +00:00
2023-06-18 17:25:40 +00:00
//set default device External
subghz_devices_init();
instance->radio_device_type = SubGhzRadioDeviceTypeInternal;
2023-06-18 17:25:40 +00:00
instance->radio_device_type =
subghz_txrx_radio_device_set(instance, SubGhzRadioDeviceTypeExternalCC1101);
2023-05-09 16:10:56 +00:00
return instance;
2023-05-09 14:30:01 +00:00
}
2023-05-09 16:10:56 +00:00
void subghz_txrx_free(SubGhzTxRx* instance) {
furi_assert(instance);
2023-05-09 14:30:01 +00:00
2023-06-18 17:25:40 +00:00
if(instance->radio_device_type != SubGhzRadioDeviceTypeInternal) {
subghz_txrx_radio_device_power_off(instance);
subghz_devices_end(instance->radio_device);
}
subghz_devices_deinit();
2023-05-09 16:10:56 +00:00
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);
2023-06-18 13:44:45 +00:00
2023-05-09 16:10:56 +00:00
free(instance->preset);
free(instance);
2023-05-09 14:30:01 +00:00
}
2023-05-09 18:54:56 +00:00
bool subghz_txrx_is_database_loaded(SubGhzTxRx* instance) {
2023-05-09 16:10:56 +00:00
furi_assert(instance);
2023-05-09 18:54:56 +00:00
return instance->is_database_loaded;
2023-05-09 14:30:01 +00:00
}
2023-05-09 16:10:56 +00:00
void subghz_txrx_set_preset(
SubGhzTxRx* instance,
const char* preset_name,
uint32_t frequency,
uint8_t* preset_data,
size_t preset_data_size) {
2023-05-09 16:10:56 +00:00
furi_assert(instance);
furi_string_set(instance->preset->name, preset_name);
2023-05-09 18:20:35 +00:00
SubGhzRadioPreset* preset = instance->preset;
preset->frequency = frequency;
preset->data = preset_data;
preset->data_size = preset_data_size;
}
2023-05-09 18:54:56 +00:00
const char* subghz_txrx_get_preset_name(SubGhzTxRx* instance, const char* preset) {
2023-05-09 16:10:56 +00:00
UNUSED(instance);
2023-05-09 19:16:52 +00:00
const char* preset_name = "";
if(!strcmp(preset, "FuriHalSubGhzPresetOok270Async")) {
2023-05-09 10:34:54 +00:00
preset_name = "AM270";
} else if(!strcmp(preset, "FuriHalSubGhzPresetOok650Async")) {
2023-05-09 10:34:54 +00:00
preset_name = "AM650";
} else if(!strcmp(preset, "FuriHalSubGhzPreset2FSKDev238Async")) {
2023-05-09 10:34:54 +00:00
preset_name = "FM238";
} else if(!strcmp(preset, "FuriHalSubGhzPreset2FSKDev476Async")) {
2023-05-09 10:34:54 +00:00
preset_name = "FM476";
} else if(!strcmp(preset, "FuriHalSubGhzPresetCustom")) {
2023-05-09 10:34:54 +00:00
preset_name = "CUSTOM";
} else {
FURI_LOG_E(TAG, "Unknown preset");
}
2023-05-09 10:34:54 +00:00
return preset_name;
}
2023-05-09 16:10:56 +00:00
SubGhzRadioPreset subghz_txrx_get_preset(SubGhzTxRx* instance) {
furi_assert(instance);
return *instance->preset;
2023-05-09 12:11:54 +00:00
}
2023-05-09 18:54:56 +00:00
void subghz_txrx_get_frequency_and_modulation(
2023-05-09 16:10:56 +00:00
SubGhzTxRx* instance,
FuriString* frequency,
FuriString* modulation,
bool long_name) {
2023-05-09 16:10:56 +00:00
furi_assert(instance);
2023-05-09 18:20:35 +00:00
SubGhzRadioPreset* preset = instance->preset;
if(frequency != NULL) {
furi_string_printf(
frequency,
"%03ld.%02ld",
2023-05-09 18:20:35 +00:00
preset->frequency / 1000000 % 1000,
preset->frequency / 10000 % 100);
}
if(modulation != NULL) {
if(long_name) {
2023-05-09 18:20:35 +00:00
furi_string_printf(modulation, "%s", furi_string_get_cstr(preset->name));
} else {
2023-05-09 18:20:35 +00:00
furi_string_printf(modulation, "%.2s", furi_string_get_cstr(preset->name));
}
}
}
2023-05-09 16:10:56 +00:00
static void subghz_txrx_begin(SubGhzTxRx* instance, uint8_t* preset_data) {
furi_assert(instance);
2023-06-18 17:25:40 +00:00
subghz_devices_reset(instance->radio_device);
subghz_devices_idle(instance->radio_device);
subghz_devices_load_preset(instance->radio_device, FuriHalSubGhzPresetCustom, preset_data);
2023-05-09 16:10:56 +00:00
instance->txrx_state = SubGhzTxRxStateIDLE;
}
2023-05-09 16:10:56 +00:00
static uint32_t subghz_txrx_rx(SubGhzTxRx* instance, uint32_t frequency) {
furi_assert(instance);
furi_assert(
instance->txrx_state != SubGhzTxRxStateRx && instance->txrx_state != SubGhzTxRxStateSleep);
2023-06-18 17:25:40 +00:00
subghz_devices_idle(instance->radio_device);
uint32_t value = subghz_devices_set_frequency(instance->radio_device, frequency);
subghz_devices_flush_rx(instance->radio_device);
2023-05-09 16:10:56 +00:00
subghz_txrx_speaker_on(instance);
2023-06-18 17:25:40 +00:00
subghz_devices_start_async_rx(
instance->radio_device, subghz_worker_rx_callback, instance->worker);
2023-05-09 16:10:56 +00:00
subghz_worker_start(instance->worker);
instance->txrx_state = SubGhzTxRxStateRx;
return value;
}
2023-05-09 16:10:56 +00:00
static void subghz_txrx_idle(SubGhzTxRx* instance) {
furi_assert(instance);
furi_assert(instance->txrx_state != SubGhzTxRxStateSleep);
2023-06-18 17:25:40 +00:00
subghz_devices_idle(instance->radio_device);
2023-05-09 16:10:56 +00:00
subghz_txrx_speaker_off(instance);
instance->txrx_state = SubGhzTxRxStateIDLE;
}
2023-05-09 16:10:56 +00:00
static void subghz_txrx_rx_end(SubGhzTxRx* instance) {
furi_assert(instance);
furi_assert(instance->txrx_state == SubGhzTxRxStateRx);
2023-05-09 16:10:56 +00:00
if(subghz_worker_is_running(instance->worker)) {
subghz_worker_stop(instance->worker);
2023-06-18 17:25:40 +00:00
subghz_devices_stop_async_rx(instance->radio_device);
}
2023-06-18 17:25:40 +00:00
subghz_devices_idle(instance->radio_device);
2023-05-09 16:10:56 +00:00
subghz_txrx_speaker_off(instance);
instance->txrx_state = SubGhzTxRxStateIDLE;
}
2023-05-09 16:10:56 +00:00
void subghz_txrx_sleep(SubGhzTxRx* instance) {
furi_assert(instance);
2023-06-18 17:25:40 +00:00
subghz_devices_sleep(instance->radio_device);
2023-05-09 16:10:56 +00:00
instance->txrx_state = SubGhzTxRxStateSleep;
2023-05-09 12:11:54 +00:00
}
2023-05-09 16:10:56 +00:00
static bool subghz_txrx_tx(SubGhzTxRx* instance, uint32_t frequency) {
furi_assert(instance);
furi_assert(instance->txrx_state != SubGhzTxRxStateSleep);
2023-06-18 17:25:40 +00:00
subghz_devices_idle(instance->radio_device);
subghz_devices_set_frequency(instance->radio_device, frequency);
bool ret = subghz_devices_set_tx(instance->radio_device);
if(ret) {
2023-05-09 16:10:56 +00:00
subghz_txrx_speaker_on(instance);
instance->txrx_state = SubGhzTxRxStateTx;
}
2023-05-09 19:16:52 +00:00
return ret;
}
2023-05-09 16:50:01 +00:00
SubGhzTxRxStartTxState subghz_txrx_tx_start(SubGhzTxRx* instance, FlipperFormat* flipper_format) {
2023-05-09 16:10:56 +00:00
furi_assert(instance);
2023-05-09 12:11:54 +00:00
furi_assert(flipper_format);
2023-05-09 16:10:56 +00:00
subghz_txrx_stop(instance);
2023-05-09 16:50:01 +00:00
SubGhzTxRxStartTxState ret = SubGhzTxRxStartTxStateErrorParserOthers;
FuriString* temp_str = furi_string_alloc();
uint32_t repeat = 200;
do {
if(!flipper_format_rewind(flipper_format)) {
FURI_LOG_E(TAG, "Rewind error");
break;
}
if(!flipper_format_read_string(flipper_format, "Protocol", temp_str)) {
FURI_LOG_E(TAG, "Missing Protocol");
break;
}
if(!flipper_format_insert_or_update_uint32(flipper_format, "Repeat", &repeat, 1)) {
FURI_LOG_E(TAG, "Unable Repeat");
break;
}
2023-05-09 18:20:35 +00:00
ret = SubGhzTxRxStartTxStateOk;
2023-05-09 18:20:35 +00:00
SubGhzRadioPreset* preset = instance->preset;
2023-05-09 16:10:56 +00:00
instance->transmitter =
subghz_transmitter_alloc_init(instance->environment, furi_string_get_cstr(temp_str));
2023-05-09 16:10:56 +00:00
if(instance->transmitter) {
if(subghz_transmitter_deserialize(instance->transmitter, flipper_format) ==
SubGhzProtocolStatusOk) {
2023-05-09 18:20:35 +00:00
if(strcmp(furi_string_get_cstr(preset->name), "") != 0) {
2023-05-09 16:10:56 +00:00
subghz_txrx_begin(
instance,
subghz_setting_get_preset_data_by_name(
2023-05-09 18:20:35 +00:00
instance->setting, furi_string_get_cstr(preset->name)));
if(preset->frequency) {
if(!subghz_txrx_tx(instance, preset->frequency)) {
2023-05-09 16:50:01 +00:00
FURI_LOG_E(TAG, "Only Rx");
ret = SubGhzTxRxStartTxStateErrorOnlyRx;
}
} else {
ret = SubGhzTxRxStartTxStateErrorParserOthers;
}
2023-05-09 19:16:52 +00:00
} else {
FURI_LOG_E(
2023-05-09 18:20:35 +00:00
TAG, "Unknown name preset \" %s \"", furi_string_get_cstr(preset->name));
2023-05-09 16:50:01 +00:00
ret = SubGhzTxRxStartTxStateErrorParserOthers;
}
2023-05-09 19:16:52 +00:00
2023-05-09 16:50:01 +00:00
if(ret == SubGhzTxRxStartTxStateOk) {
//Start TX
2023-06-18 17:25:40 +00:00
subghz_devices_start_async_tx(
instance->radio_device, subghz_transmitter_yield, instance->transmitter);
}
} else {
2023-05-09 16:50:01 +00:00
ret = SubGhzTxRxStartTxStateErrorParserOthers;
}
2023-05-09 19:16:52 +00:00
} else {
ret = SubGhzTxRxStartTxStateErrorParserOthers;
}
2023-05-09 16:50:01 +00:00
if(ret != SubGhzTxRxStartTxStateOk) {
2023-05-09 16:10:56 +00:00
subghz_transmitter_free(instance->transmitter);
if(instance->txrx_state != SubGhzTxRxStateIDLE) {
subghz_txrx_idle(instance);
}
}
} while(false);
furi_string_free(temp_str);
return ret;
}
2023-05-09 16:10:56 +00:00
void subghz_txrx_rx_start(SubGhzTxRx* instance) {
furi_assert(instance);
subghz_txrx_stop(instance);
subghz_txrx_begin(
instance,
2023-05-09 12:11:54 +00:00
subghz_setting_get_preset_data_by_name(
2023-05-09 16:10:56 +00:00
subghz_txrx_get_setting(instance), furi_string_get_cstr(instance->preset->name)));
subghz_txrx_rx(instance, instance->preset->frequency);
2023-05-09 12:11:54 +00:00
}
2023-05-09 18:54:56 +00:00
void subghz_txrx_set_need_save_callback(
2023-05-09 16:10:56 +00:00
SubGhzTxRx* instance,
SubGhzTxRxNeedSaveCallback callback,
void* context) {
2023-05-09 16:10:56 +00:00
furi_assert(instance);
instance->need_save_callback = callback;
instance->need_save_context = context;
}
2023-05-09 16:10:56 +00:00
static void subghz_txrx_tx_stop(SubGhzTxRx* instance) {
furi_assert(instance);
furi_assert(instance->txrx_state == SubGhzTxRxStateTx);
//Stop TX
2023-06-18 17:25:40 +00:00
subghz_devices_stop_async_tx(instance->radio_device);
2023-05-09 16:10:56 +00:00
subghz_transmitter_stop(instance->transmitter);
subghz_transmitter_free(instance->transmitter);
//if protocol dynamic then we save the last upload
2023-05-09 16:10:56 +00:00
if(instance->decoder_result->protocol->type == SubGhzProtocolTypeDynamic) {
if(instance->need_save_callback) {
instance->need_save_callback(instance->need_save_context);
}
}
2023-05-09 16:10:56 +00:00
subghz_txrx_idle(instance);
subghz_txrx_speaker_off(instance);
}
2023-05-09 18:54:56 +00:00
FlipperFormat* subghz_txrx_get_fff_data(SubGhzTxRx* instance) {
2023-05-09 16:10:56 +00:00
furi_assert(instance);
return instance->fff_data;
}
2023-05-09 16:10:56 +00:00
SubGhzSetting* subghz_txrx_get_setting(SubGhzTxRx* instance) {
furi_assert(instance);
return instance->setting;
}
2023-05-09 16:10:56 +00:00
void subghz_txrx_stop(SubGhzTxRx* instance) {
furi_assert(instance);
2023-05-09 16:10:56 +00:00
switch(instance->txrx_state) {
case SubGhzTxRxStateTx:
2023-05-09 16:10:56 +00:00
subghz_txrx_tx_stop(instance);
subghz_txrx_speaker_unmute(instance);
break;
case SubGhzTxRxStateRx:
2023-05-09 16:10:56 +00:00
subghz_txrx_rx_end(instance);
subghz_txrx_speaker_mute(instance);
break;
default:
break;
}
}
2023-05-09 16:10:56 +00:00
void subghz_txrx_hopper_update(SubGhzTxRx* instance) {
furi_assert(instance);
2023-05-09 16:10:56 +00:00
switch(instance->hopper_state) {
case SubGhzHopperStateOFF:
case SubGhzHopperStatePause:
return;
case SubGhzHopperStateRSSITimeOut:
2023-05-09 16:10:56 +00:00
if(instance->hopper_timeout != 0) {
instance->hopper_timeout--;
return;
}
break;
default:
break;
}
// Init value isn't using
// float rssi = -127.0f;
2023-05-09 16:10:56 +00:00
if(instance->hopper_state != SubGhzHopperStateRSSITimeOut) {
// See RSSI Calculation timings in CC1101 17.3 RSSI
float rssi = subghz_devices_get_rssi(instance->radio_device);
// Stay if RSSI is high enough
if(rssi > -90.0f) {
2023-05-09 16:10:56 +00:00
instance->hopper_timeout = 10;
instance->hopper_state = SubGhzHopperStateRSSITimeOut;
return;
}
} else {
2023-05-09 16:10:56 +00:00
instance->hopper_state = SubGhzHopperStateRunning;
}
// Select next frequency
2023-05-09 16:10:56 +00:00
if(instance->hopper_idx_frequency <
subghz_setting_get_hopper_frequency_count(instance->setting) - 1) {
instance->hopper_idx_frequency++;
} else {
2023-05-09 16:10:56 +00:00
instance->hopper_idx_frequency = 0;
}
2023-05-09 16:10:56 +00:00
if(instance->txrx_state == SubGhzTxRxStateRx) {
subghz_txrx_rx_end(instance);
}
2023-05-09 16:10:56 +00:00
if(instance->txrx_state == SubGhzTxRxStateIDLE) {
subghz_receiver_reset(instance->receiver);
instance->preset->frequency =
subghz_setting_get_hopper_frequency(instance->setting, instance->hopper_idx_frequency);
subghz_txrx_rx(instance, instance->preset->frequency);
}
}
2023-05-09 16:10:56 +00:00
SubGhzHopperState subghz_txrx_hopper_get_state(SubGhzTxRx* instance) {
furi_assert(instance);
return instance->hopper_state;
}
2023-05-09 16:10:56 +00:00
void subghz_txrx_hopper_set_state(SubGhzTxRx* instance, SubGhzHopperState state) {
furi_assert(instance);
instance->hopper_state = state;
}
2023-05-09 18:54:56 +00:00
void subghz_txrx_hopper_unpause(SubGhzTxRx* instance) {
2023-05-09 16:10:56 +00:00
furi_assert(instance);
if(instance->hopper_state == SubGhzHopperStatePause) {
instance->hopper_state = SubGhzHopperStateRunning;
}
}
2023-05-09 16:33:45 +00:00
void subghz_txrx_hopper_pause(SubGhzTxRx* instance) {
2023-05-09 16:10:56 +00:00
furi_assert(instance);
if(instance->hopper_state == SubGhzHopperStateRunning) {
instance->hopper_state = SubGhzHopperStatePause;
}
}
2023-05-09 16:10:56 +00:00
void subghz_txrx_speaker_on(SubGhzTxRx* instance) {
furi_assert(instance);
if(instance->debug_pin_state) {
2023-06-18 17:25:40 +00:00
subghz_devices_set_async_mirror_pin(instance->radio_device, &gpio_ibutton);
}
2023-05-09 16:10:56 +00:00
if(instance->speaker_state == SubGhzSpeakerStateEnable) {
if(furi_hal_speaker_acquire(30)) {
2023-05-09 16:10:56 +00:00
if(!instance->debug_pin_state) {
2023-06-18 17:25:40 +00:00
subghz_devices_set_async_mirror_pin(instance->radio_device, &gpio_speaker);
}
} else {
2023-05-09 16:10:56 +00:00
instance->speaker_state = SubGhzSpeakerStateDisable;
}
}
}
2023-05-09 16:10:56 +00:00
void subghz_txrx_speaker_off(SubGhzTxRx* instance) {
furi_assert(instance);
if(instance->debug_pin_state) {
2023-06-18 17:25:40 +00:00
subghz_devices_set_async_mirror_pin(instance->radio_device, NULL);
}
2023-05-09 16:10:56 +00:00
if(instance->speaker_state != SubGhzSpeakerStateDisable) {
if(furi_hal_speaker_is_mine()) {
2023-05-09 16:10:56 +00:00
if(!instance->debug_pin_state) {
2023-06-18 17:25:40 +00:00
subghz_devices_set_async_mirror_pin(instance->radio_device, NULL);
}
furi_hal_speaker_release();
2023-05-09 16:10:56 +00:00
if(instance->speaker_state == SubGhzSpeakerStateShutdown)
instance->speaker_state = SubGhzSpeakerStateDisable;
}
}
}
2023-05-09 16:10:56 +00:00
void subghz_txrx_speaker_mute(SubGhzTxRx* instance) {
furi_assert(instance);
if(instance->debug_pin_state) {
2023-06-18 17:25:40 +00:00
subghz_devices_set_async_mirror_pin(instance->radio_device, NULL);
}
2023-05-09 16:10:56 +00:00
if(instance->speaker_state == SubGhzSpeakerStateEnable) {
if(furi_hal_speaker_is_mine()) {
2023-05-09 16:10:56 +00:00
if(!instance->debug_pin_state) {
2023-06-18 17:25:40 +00:00
subghz_devices_set_async_mirror_pin(instance->radio_device, NULL);
}
}
}
}
2023-05-09 16:10:56 +00:00
void subghz_txrx_speaker_unmute(SubGhzTxRx* instance) {
furi_assert(instance);
if(instance->debug_pin_state) {
2023-06-18 17:25:40 +00:00
subghz_devices_set_async_mirror_pin(instance->radio_device, &gpio_ibutton);
}
2023-05-09 16:10:56 +00:00
if(instance->speaker_state == SubGhzSpeakerStateEnable) {
if(furi_hal_speaker_is_mine()) {
2023-05-09 16:10:56 +00:00
if(!instance->debug_pin_state) {
2023-06-18 17:25:40 +00:00
subghz_devices_set_async_mirror_pin(instance->radio_device, &gpio_speaker);
}
}
}
}
2023-05-09 16:10:56 +00:00
void subghz_txrx_speaker_set_state(SubGhzTxRx* instance, SubGhzSpeakerState state) {
furi_assert(instance);
instance->speaker_state = state;
}
2023-05-09 16:10:56 +00:00
SubGhzSpeakerState subghz_txrx_speaker_get_state(SubGhzTxRx* instance) {
furi_assert(instance);
return instance->speaker_state;
}
2023-05-09 16:10:56 +00:00
bool subghz_txrx_load_decoder_by_name_protocol(SubGhzTxRx* instance, const char* name_protocol) {
furi_assert(instance);
2023-05-09 10:34:54 +00:00
furi_assert(name_protocol);
bool res = false;
2023-05-09 16:10:56 +00:00
instance->decoder_result =
subghz_receiver_search_decoder_base_by_name(instance->receiver, name_protocol);
if(instance->decoder_result) {
2023-05-09 10:34:54 +00:00
res = true;
}
return res;
}
2023-05-09 16:10:56 +00:00
SubGhzProtocolDecoderBase* subghz_txrx_get_decoder(SubGhzTxRx* instance) {
furi_assert(instance);
return instance->decoder_result;
2023-05-09 10:34:54 +00:00
}
2023-05-09 18:54:56 +00:00
bool subghz_txrx_protocol_is_serializable(SubGhzTxRx* instance) {
2023-05-09 16:10:56 +00:00
furi_assert(instance);
2023-05-09 12:22:08 +00:00
return (
2023-05-09 16:10:56 +00:00
(instance->decoder_result->protocol->flag & SubGhzProtocolFlag_Save) ==
2023-05-09 12:22:08 +00:00
SubGhzProtocolFlag_Save);
}
2023-05-09 18:54:56 +00:00
bool subghz_txrx_protocol_is_transmittable(SubGhzTxRx* instance, bool check_type) {
2023-05-09 16:10:56 +00:00
furi_assert(instance);
2023-05-09 18:20:35 +00:00
const SubGhzProtocol* protocol = instance->decoder_result->protocol;
2023-05-09 12:22:08 +00:00
if(check_type) {
return (
2023-05-09 18:20:35 +00:00
((protocol->flag & SubGhzProtocolFlag_Send) == SubGhzProtocolFlag_Send) &&
protocol->encoder->deserialize && protocol->type == SubGhzProtocolTypeStatic);
2023-05-09 12:22:08 +00:00
}
return (
2023-05-09 18:20:35 +00:00
((protocol->flag & SubGhzProtocolFlag_Send) == SubGhzProtocolFlag_Send) &&
protocol->encoder->deserialize);
2023-05-09 12:22:08 +00:00
}
2023-05-09 16:10:56 +00:00
void subghz_txrx_receiver_set_filter(SubGhzTxRx* instance, SubGhzProtocolFlag filter) {
furi_assert(instance);
subghz_receiver_set_filter(instance->receiver, filter);
2023-05-09 12:58:56 +00:00
}
void subghz_txrx_set_rx_callback(
2023-05-09 16:10:56 +00:00
SubGhzTxRx* instance,
SubGhzReceiverCallback callback,
void* context) {
subghz_receiver_set_rx_callback(instance->receiver, callback, context);
2023-05-09 15:24:25 +00:00
}
2023-05-09 18:54:56 +00:00
void subghz_txrx_set_raw_file_encoder_worker_callback_end(
2023-05-09 16:10:56 +00:00
SubGhzTxRx* instance,
2023-05-09 15:24:25 +00:00
SubGhzProtocolEncoderRAWCallbackEnd callback,
void* context) {
subghz_protocol_raw_file_encoder_worker_set_callback_end(
2023-05-09 16:10:56 +00:00
(SubGhzProtocolEncoderRAW*)subghz_transmitter_get_protocol_instance(instance->transmitter),
2023-05-09 15:24:25 +00:00
callback,
context);
}
bool subghz_txrx_radio_device_is_external_connected(SubGhzTxRx* instance, const char* name) {
2023-06-18 17:25:40 +00:00
furi_assert(instance);
bool is_connect = false;
bool is_otg_enabled = furi_hal_power_is_otg_enabled();
if(!is_otg_enabled) {
subghz_txrx_radio_device_power_on(instance);
}
const SubGhzDevice* device = subghz_devices_get_by_name(name);
if(device) {
is_connect = subghz_devices_is_connect(device);
}
2023-06-18 17:25:40 +00:00
if(!is_otg_enabled) {
subghz_txrx_radio_device_power_off(instance);
}
return is_connect;
}
SubGhzRadioDeviceType
subghz_txrx_radio_device_set(SubGhzTxRx* instance, SubGhzRadioDeviceType radio_device_type) {
furi_assert(instance);
if(radio_device_type == SubGhzRadioDeviceTypeExternalCC1101 &&
subghz_txrx_radio_device_is_external_connected(instance, SUBGHZ_DEVICE_CC1101_EXT_NAME)) {
2023-06-18 17:25:40 +00:00
subghz_txrx_radio_device_power_on(instance);
instance->radio_device = subghz_devices_get_by_name(SUBGHZ_DEVICE_CC1101_EXT_NAME);
subghz_devices_begin(instance->radio_device);
instance->radio_device_type = SubGhzRadioDeviceTypeExternalCC1101;
} else {
subghz_txrx_radio_device_power_off(instance);
if(instance->radio_device_type != SubGhzRadioDeviceTypeInternal) {
subghz_devices_end(instance->radio_device);
2023-06-18 17:25:40 +00:00
}
instance->radio_device = subghz_devices_get_by_name(SUBGHZ_DEVICE_CC1101_INT_NAME);
instance->radio_device_type = SubGhzRadioDeviceTypeInternal;
}
return instance->radio_device_type;
}
SubGhzRadioDeviceType subghz_txrx_radio_device_get(SubGhzTxRx* instance) {
furi_assert(instance);
return instance->radio_device_type;
}
float subghz_txrx_radio_device_get_rssi(SubGhzTxRx* instance) {
furi_assert(instance);
return subghz_devices_get_rssi(instance->radio_device);
}
const char* subghz_txrx_radio_device_get_name(SubGhzTxRx* instance) {
furi_assert(instance);
return subghz_devices_get_name(instance->radio_device);
}
bool subghz_txrx_radio_device_is_frequency_valid(SubGhzTxRx* instance, uint32_t frequency) {
2023-06-18 17:25:40 +00:00
furi_assert(instance);
return subghz_devices_is_frequency_valid(instance->radio_device, frequency);
}
bool subghz_txrx_radio_device_is_tx_allowed(SubGhzTxRx* instance, uint32_t frequency) {
// TODO: Remake this function to check if the frequency is allowed on specific module - for modules not based on CC1101
furi_assert(instance);
UNUSED(frequency);
/*
furi_assert(instance->txrx_state != SubGhzTxRxStateSleep);
subghz_devices_idle(instance->radio_device);
subghz_devices_set_frequency(instance->radio_device, frequency);
bool ret = subghz_devices_set_tx(instance->radio_device);
subghz_devices_idle(instance->radio_device);
return ret;
*/
return true;
}
2023-05-09 16:10:56 +00:00
void subghz_txrx_set_debug_pin_state(SubGhzTxRx* instance, bool state) {
furi_assert(instance);
instance->debug_pin_state = state;
}
2023-05-09 16:10:56 +00:00
bool subghz_txrx_get_debug_pin_state(SubGhzTxRx* instance) {
furi_assert(instance);
return instance->debug_pin_state;
}
2023-05-30 19:21:47 +00:00
void subghz_txrx_reset_dynamic_and_custom_btns(SubGhzTxRx* instance) {
2023-05-19 22:15:36 +00:00
furi_assert(instance);
subghz_environment_reset_keeloq(instance->environment);
2023-05-20 13:15:01 +00:00
2023-05-19 22:15:36 +00:00
subghz_custom_btns_reset();
}
2023-05-09 16:10:56 +00:00
SubGhzReceiver* subghz_txrx_get_receiver(SubGhzTxRx* instance) {
furi_assert(instance);
return instance->receiver;
}
void subghz_txrx_set_default_preset(SubGhzTxRx* instance, uint32_t frequency) {
furi_assert(instance);
const char* default_modulation = "AM650";
if(frequency == 0) {
frequency = subghz_setting_get_default_frequency(subghz_txrx_get_setting(instance));
}
subghz_txrx_set_preset(instance, default_modulation, frequency, NULL, 0);
}
const char*
subghz_txrx_set_preset_internal(SubGhzTxRx* instance, uint32_t frequency, uint8_t index) {
furi_assert(instance);
SubGhzSetting* setting = subghz_txrx_get_setting(instance);
const char* preset_name = subghz_setting_get_preset_name(setting, index);
subghz_setting_set_default_frequency(setting, frequency);
subghz_txrx_set_preset(
instance,
preset_name,
frequency,
subghz_setting_get_preset_data(setting, index),
subghz_setting_get_preset_data_size(setting, index));
return preset_name;
}