diff --git a/applications/main/subghz_remote/helpers/txrx/subghz_txrx.c b/applications/main/subghz_remote/helpers/txrx/subghz_txrx.c index 3275b7288..db485a2aa 100644 --- a/applications/main/subghz_remote/helpers/txrx/subghz_txrx.c +++ b/applications/main/subghz_remote/helpers/txrx/subghz_txrx.c @@ -1,9 +1,28 @@ #include "subghz_txrx_i.h" + #include +#include +#include + #include #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(); @@ -24,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); @@ -44,18 +62,32 @@ SubGhzTxRx* subghz_txrx_alloc() { instance->worker, (SubGhzWorkerPairCallback)subghz_receiver_decode); subghz_worker_set_context(instance->worker, instance->receiver); + //set default device Internal + subghz_devices_init(); + instance->radio_device_type = SubGhzRadioDeviceTypeInternal; + instance->radio_device_type = + subghz_txrx_radio_device_set(instance, SubGhzRadioDeviceTypeInternal); + 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); } @@ -128,29 +160,25 @@ void subghz_txrx_get_frequency_and_modulation( static void subghz_txrx_begin(SubGhzTxRx* instance, uint8_t* preset_data) { furi_assert(instance); - furi_hal_subghz_reset(); - furi_hal_subghz_idle(); - furi_hal_subghz_load_custom_preset(preset_data); - furi_hal_gpio_init(furi_hal_subghz.cc1101_g0_pin, GpioModeInput, GpioPullNo, GpioSpeedLow); + subghz_devices_reset(instance->radio_device); + subghz_devices_idle(instance->radio_device); + subghz_devices_load_preset(instance->radio_device, FuriHalSubGhzPresetCustom, preset_data); instance->txrx_state = SubGhzTxRxStateIDLE; } static uint32_t subghz_txrx_rx(SubGhzTxRx* instance, uint32_t frequency) { furi_assert(instance); - if(!furi_hal_subghz_is_frequency_valid(frequency)) { - furi_crash("SubGhz: Incorrect RX frequency."); - } furi_assert( instance->txrx_state != SubGhzTxRxStateRx && instance->txrx_state != SubGhzTxRxStateSleep); - furi_hal_subghz_idle(); - uint32_t value = furi_hal_subghz_set_frequency_and_path(frequency); - furi_hal_gpio_init(furi_hal_subghz.cc1101_g0_pin, GpioModeInput, GpioPullNo, GpioSpeedLow); - furi_hal_subghz_flush_rx(); - subghz_txrx_speaker_on(instance); - furi_hal_subghz_rx(); + 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; @@ -159,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; } @@ -170,31 +198,27 @@ 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); - furi_hal_subghz_idle(); - furi_hal_subghz_set_frequency_and_path(frequency); - furi_hal_gpio_write(furi_hal_subghz.cc1101_g0_pin, false); - furi_hal_gpio_init( - furi_hal_subghz.cc1101_g0_pin, GpioModeOutputPushPull, GpioPullNo, GpioSpeedLow); - bool ret = furi_hal_subghz_tx(); + + 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) { subghz_txrx_speaker_on(instance); instance->txrx_state = SubGhzTxRxStateTx; @@ -256,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; @@ -300,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); @@ -313,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) { @@ -363,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) { @@ -420,13 +443,13 @@ void subghz_txrx_hopper_pause(SubGhzTxRx* instance) { void subghz_txrx_speaker_on(SubGhzTxRx* instance) { furi_assert(instance); if(instance->debug_pin_state) { - furi_hal_subghz_set_async_mirror_pin(&gpio_ibutton); + subghz_devices_set_async_mirror_pin(instance->radio_device, &gpio_ibutton); } if(instance->speaker_state == SubGhzSpeakerStateEnable) { if(furi_hal_speaker_acquire(30)) { if(!instance->debug_pin_state) { - furi_hal_subghz_set_async_mirror_pin(&gpio_speaker); + subghz_devices_set_async_mirror_pin(instance->radio_device, &gpio_speaker); } } else { instance->speaker_state = SubGhzSpeakerStateDisable; @@ -437,12 +460,12 @@ void subghz_txrx_speaker_on(SubGhzTxRx* instance) { void subghz_txrx_speaker_off(SubGhzTxRx* instance) { furi_assert(instance); if(instance->debug_pin_state) { - furi_hal_subghz_set_async_mirror_pin(NULL); + subghz_devices_set_async_mirror_pin(instance->radio_device, NULL); } if(instance->speaker_state != SubGhzSpeakerStateDisable) { if(furi_hal_speaker_is_mine()) { if(!instance->debug_pin_state) { - furi_hal_subghz_set_async_mirror_pin(NULL); + subghz_devices_set_async_mirror_pin(instance->radio_device, NULL); } furi_hal_speaker_release(); if(instance->speaker_state == SubGhzSpeakerStateShutdown) @@ -454,12 +477,12 @@ void subghz_txrx_speaker_off(SubGhzTxRx* instance) { void subghz_txrx_speaker_mute(SubGhzTxRx* instance) { furi_assert(instance); if(instance->debug_pin_state) { - furi_hal_subghz_set_async_mirror_pin(NULL); + subghz_devices_set_async_mirror_pin(instance->radio_device, NULL); } if(instance->speaker_state == SubGhzSpeakerStateEnable) { if(furi_hal_speaker_is_mine()) { if(!instance->debug_pin_state) { - furi_hal_subghz_set_async_mirror_pin(NULL); + subghz_devices_set_async_mirror_pin(instance->radio_device, NULL); } } } @@ -468,12 +491,12 @@ void subghz_txrx_speaker_mute(SubGhzTxRx* instance) { void subghz_txrx_speaker_unmute(SubGhzTxRx* instance) { furi_assert(instance); if(instance->debug_pin_state) { - furi_hal_subghz_set_async_mirror_pin(&gpio_ibutton); + subghz_devices_set_async_mirror_pin(instance->radio_device, &gpio_ibutton); } if(instance->speaker_state == SubGhzSpeakerStateEnable) { if(furi_hal_speaker_is_mine()) { if(!instance->debug_pin_state) { - furi_hal_subghz_set_async_mirror_pin(&gpio_speaker); + subghz_devices_set_async_mirror_pin(instance->radio_device, &gpio_speaker); } } } @@ -548,6 +571,82 @@ void subghz_txrx_set_raw_file_encoder_worker_callback_end( context); } +bool subghz_txrx_radio_device_is_external_connected(SubGhzTxRx* instance, const char* name) { + furi_assert(instance); + + bool is_connect = false; + bool is_otg_enabled = furi_hal_power_is_otg_enabled(); + + if(!is_otg_enabled) { + subghz_txrx_radio_device_power_on(instance); + } + + const SubGhzDevice* device = subghz_devices_get_by_name(name); + if(device) { + is_connect = subghz_devices_is_connect(device); + } + + if(!is_otg_enabled) { + subghz_txrx_radio_device_power_off(instance); + } + return is_connect; +} + +SubGhzRadioDeviceType + subghz_txrx_radio_device_set(SubGhzTxRx* instance, SubGhzRadioDeviceType radio_device_type) { + furi_assert(instance); + + if(radio_device_type == SubGhzRadioDeviceTypeExternalCC1101 && + subghz_txrx_radio_device_is_external_connected(instance, SUBGHZ_DEVICE_CC1101_EXT_NAME)) { + subghz_txrx_radio_device_power_on(instance); + instance->radio_device = subghz_devices_get_by_name(SUBGHZ_DEVICE_CC1101_EXT_NAME); + subghz_devices_begin(instance->radio_device); + instance->radio_device_type = SubGhzRadioDeviceTypeExternalCC1101; + } else { + subghz_txrx_radio_device_power_off(instance); + if(instance->radio_device_type != SubGhzRadioDeviceTypeInternal) { + subghz_devices_end(instance->radio_device); + } + instance->radio_device = subghz_devices_get_by_name(SUBGHZ_DEVICE_CC1101_INT_NAME); + instance->radio_device_type = SubGhzRadioDeviceTypeInternal; + } + + return instance->radio_device_type; +} + +SubGhzRadioDeviceType subghz_txrx_radio_device_get(SubGhzTxRx* instance) { + furi_assert(instance); + return instance->radio_device_type; +} + +float subghz_txrx_radio_device_get_rssi(SubGhzTxRx* instance) { + furi_assert(instance); + return subghz_devices_get_rssi(instance->radio_device); +} + +const char* subghz_txrx_radio_device_get_name(SubGhzTxRx* instance) { + furi_assert(instance); + return subghz_devices_get_name(instance->radio_device); +} + +bool subghz_txrx_radio_device_is_frequecy_valid(SubGhzTxRx* instance, uint32_t frequency) { + furi_assert(instance); + return subghz_devices_is_frequency_valid(instance->radio_device, frequency); +} + +bool subghz_txrx_radio_device_is_tx_alowed(SubGhzTxRx* instance, uint32_t frequency) { + furi_assert(instance); + 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; +} + void subghz_txrx_set_debug_pin_state(SubGhzTxRx* instance, bool state) { furi_assert(instance); instance->debug_pin_state = state; diff --git a/applications/main/subghz_remote/helpers/txrx/subghz_txrx.h b/applications/main/subghz_remote/helpers/txrx/subghz_txrx.h index 6e7641734..8bb7f2aee 100644 --- a/applications/main/subghz_remote/helpers/txrx/subghz_txrx.h +++ b/applications/main/subghz_remote/helpers/txrx/subghz_txrx.h @@ -5,6 +5,7 @@ #include #include #include +#include typedef struct SubGhzTxRx SubGhzTxRx; @@ -40,6 +41,13 @@ typedef enum { SubGhzSpeakerStateEnable, } SubGhzSpeakerState; +/** SubGhzRadioDeviceType */ +typedef enum { + SubGhzRadioDeviceTypeAuto, + SubGhzRadioDeviceTypeInternal, + SubGhzRadioDeviceTypeExternalCC1101, +} SubGhzRadioDeviceType; + /** * Allocate SubGhzTxRx * @@ -312,6 +320,53 @@ void subghz_txrx_set_raw_file_encoder_worker_callback_end( 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); diff --git a/applications/main/subghz_remote/helpers/txrx/subghz_txrx_i.h b/applications/main/subghz_remote/helpers/txrx/subghz_txrx_i.h index 680d27158..f058c2282 100644 --- a/applications/main/subghz_remote/helpers/txrx/subghz_txrx_i.h +++ b/applications/main/subghz_remote/helpers/txrx/subghz_txrx_i.h @@ -1,5 +1,5 @@ - #pragma once + #include "subghz_txrx.h" struct SubGhzTxRx { @@ -21,9 +21,11 @@ struct SubGhzTxRx { SubGhzTxRxState txrx_state; SubGhzSpeakerState speaker_state; + const SubGhzDevice* radio_device; + SubGhzRadioDeviceType radio_device_type; SubGhzTxRxNeedSaveCallback need_save_callback; void* need_save_context; bool debug_pin_state; -}; \ No newline at end of file +};