diff --git a/applications/main/subghz/helpers/subghz_txrx.c b/applications/main/subghz/helpers/subghz_txrx.c index 43002437bb33..49b40ca3bfbb 100644 --- a/applications/main/subghz/helpers/subghz_txrx.c +++ b/applications/main/subghz/helpers/subghz_txrx.c @@ -504,11 +504,21 @@ void subghz_txrx_speaker_set_state(SubGhzTxRx* instance, SubGhzSpeakerState stat instance->speaker_state = state; } +void subghz_txrx_repeater_set_state(SubGhzRepeater* instance, SubGhzRepeater state) { + furi_assert(instance); + *instance = state; +} + SubGhzSpeakerState subghz_txrx_speaker_get_state(SubGhzTxRx* instance) { furi_assert(instance); return instance->speaker_state; } +SubGhzRepeater subghz_txrx_repeater_get_state(SubGhzRepeater* instance) { + furi_assert(instance); + return *instance; +} + bool subghz_txrx_load_decoder_by_name_protocol(SubGhzTxRx* instance, const char* name_protocol) { furi_assert(instance); furi_assert(name_protocol); diff --git a/applications/main/subghz/helpers/subghz_txrx.h b/applications/main/subghz/helpers/subghz_txrx.h index a0f9f3055124..a58641a17faa 100644 --- a/applications/main/subghz/helpers/subghz_txrx.h +++ b/applications/main/subghz/helpers/subghz_txrx.h @@ -198,6 +198,22 @@ void subghz_txrx_speaker_set_state(SubGhzTxRx* instance, SubGhzSpeakerState stat */ SubGhzSpeakerState subghz_txrx_speaker_get_state(SubGhzTxRx* instance); +/** + * Set state repeater + * + * @param instance Pointer to a SubGhzTxRx + * @param state State speaker + */ +void subghz_txrx_repeater_set_state(SubGhzRepeater* instance, SubGhzRepeater state); + +/** + * Get state repeater + * + * @param instance Pointer to a SubGhzRepeater + * @return SubGhzRepeater + */ +SubGhzRepeater subghz_txrx_repeater_get_state(SubGhzRepeater* instance); + /** * load decoder by name protocol * diff --git a/applications/main/subghz/helpers/subghz_types.h b/applications/main/subghz/helpers/subghz_types.h index 0d748a80be73..391a3759b925 100644 --- a/applications/main/subghz/helpers/subghz_types.h +++ b/applications/main/subghz/helpers/subghz_types.h @@ -101,4 +101,12 @@ typedef enum { SubGhzDecodeRawStateStart, SubGhzDecodeRawStateLoading, SubGhzDecodeRawStateLoaded, -} SubGhzDecodeRawState; \ No newline at end of file +} SubGhzDecodeRawState; + +/** SubGhz Repeater */ +typedef enum { + SubGhzRepeaterOff, + SubGhzRepeaterOn, + SubGhzRepeaterOnLong, + SubGhzRepeaterOnShort, +} SubGhzRepeater; diff --git a/applications/main/subghz/scenes/subghz_scene_decode_raw.c b/applications/main/subghz/scenes/subghz_scene_decode_raw.c index 85a5241176ea..21fca9354415 100644 --- a/applications/main/subghz/scenes/subghz_scene_decode_raw.c +++ b/applications/main/subghz/scenes/subghz_scene_decode_raw.c @@ -19,7 +19,8 @@ static void subghz_scene_receiver_update_statusbar(void* context) { furi_string_get_cstr(modulation_str), furi_string_get_cstr(history_stat_str), subghz_txrx_hopper_get_state(subghz->txrx) != SubGhzHopperStateOFF, - READ_BIT(subghz->filter, SubGhzProtocolFlag_BinRAW) > 0); + READ_BIT(subghz->filter, SubGhzProtocolFlag_BinRAW) > 0, + (subghz->repeater != SubGhzRepeaterOff)); furi_string_free(frequency_str); furi_string_free(modulation_str); @@ -30,7 +31,8 @@ static void subghz_scene_receiver_update_statusbar(void* context) { "", "", subghz_txrx_hopper_get_state(subghz->txrx) != SubGhzHopperStateOFF, - READ_BIT(subghz->filter, SubGhzProtocolFlag_BinRAW) > 0); + READ_BIT(subghz->filter, SubGhzProtocolFlag_BinRAW) > 0, + (subghz->repeater != SubGhzRepeaterOff)); } furi_string_free(history_stat_str); } diff --git a/applications/main/subghz/scenes/subghz_scene_read_raw.c b/applications/main/subghz/scenes/subghz_scene_read_raw.c index 315eba30f6eb..5ce86e6b612f 100644 --- a/applications/main/subghz/scenes/subghz_scene_read_raw.c +++ b/applications/main/subghz/scenes/subghz_scene_read_raw.c @@ -341,7 +341,7 @@ bool subghz_scene_read_raw_on_event(void* context, SceneManagerEvent event) { subghz_protocol_raw_save_to_file_pause(decoder_raw, !ret_rssi.is_above); break; case SubGhzNotificationStateTx: - notification_message(subghz->notifications, &sequence_blink_magenta_10); + notification_message(subghz->notifications, &sequence_blink_red_10); subghz_read_raw_update_sin(subghz->subghz_read_raw); break; default: diff --git a/applications/main/subghz/scenes/subghz_scene_receiver.c b/applications/main/subghz/scenes/subghz_scene_receiver.c index 79088c67799d..adc6073d6f86 100644 --- a/applications/main/subghz/scenes/subghz_scene_receiver.c +++ b/applications/main/subghz/scenes/subghz_scene_receiver.c @@ -28,6 +28,17 @@ const NotificationSequence subghz_sequence_rx = { NULL, }; +const NotificationSequence subghz_sequence_repeat = { + &message_red_255, + //&message_display_backlight_on, + &message_vibro_on, + &message_note_c6, + &message_delay_50, + &message_sound_off, + &message_vibro_off, + NULL, +}; + const NotificationSequence subghz_sequence_rx_locked = { &message_green_255, @@ -80,7 +91,8 @@ static void subghz_scene_receiver_update_statusbar(void* context) { furi_string_get_cstr(modulation_str), furi_string_get_cstr(history_stat_str), subghz_txrx_hopper_get_state(subghz->txrx) != SubGhzHopperStateOFF, - READ_BIT(subghz->filter, SubGhzProtocolFlag_BinRAW) > 0); + READ_BIT(subghz->filter, SubGhzProtocolFlag_BinRAW) > 0, + (subghz->repeater != SubGhzRepeaterOff)); furi_string_free(frequency_str); furi_string_free(modulation_str); @@ -91,7 +103,8 @@ static void subghz_scene_receiver_update_statusbar(void* context) { "", "", subghz_txrx_hopper_get_state(subghz->txrx) != SubGhzHopperStateOFF, - READ_BIT(subghz->filter, SubGhzProtocolFlag_BinRAW) > 0); + READ_BIT(subghz->filter, SubGhzProtocolFlag_BinRAW) > 0, + (subghz->repeater != SubGhzRepeaterOff)); subghz->state_notifications = SubGhzNotificationStateIDLE; } furi_string_free(history_stat_str); @@ -120,30 +133,75 @@ static void subghz_scene_add_to_history_callback( FuriString* item_time = furi_string_alloc(); uint16_t idx = subghz_history_get_item(history); + //Need the preset for the repeater, move her up here! SubGhzRadioPreset preset = subghz_txrx_get_preset(subghz->txrx); - if(subghz_history_add_to_history(history, decoder_base, &preset)) { - furi_string_reset(item_name); - furi_string_reset(item_time); - subghz->state_notifications = SubGhzNotificationStateRxDone; + /* This is where the repeater logic ended up going! + Instead of adding to the list, Ill beep and send the key on! + Bit of a Hack, but thats the flipper code for you! + */ - subghz_history_get_text_item_menu(history, item_name, idx); - subghz_history_get_time_item_menu(history, item_time, idx); - subghz_view_receiver_add_item_to_menu( - subghz->subghz_receiver, - furi_string_get_cstr(item_name), - furi_string_get_cstr(item_time), - subghz_history_get_type_protocol(history, idx)); + if(subghz->repeater != SubGhzRepeaterOff) { + //Start TX Counter, at the moment I just send the key as fixed length. + //Next version will look at Te time in BinRAW (since its locked to that now!) + //and transmit for the same time as receive was. It works well for my purposes as is though! - subghz_scene_receiver_update_statusbar(subghz); - if(subghz_history_get_text_space_left(subghz->history, NULL)) { - notification_message(subghz->notifications, &sequence_error); + //Stop the Radio from Receiving. + subghz_txrx_hopper_pause(subghz->txrx); + subghz_receiver_reset(receiver); + + //Get the data to send. + subghz_protocol_decoder_base_serialize(decoder_base, subghz->repeater_tx, &preset); + + uint32_t tmpTe = 300; + if(!flipper_format_rewind(subghz->repeater_tx)) { + FURI_LOG_E(TAG, "Rewind error"); + return; + } + if(!flipper_format_read_uint32(subghz->repeater_tx, "TE", (uint32_t*)&tmpTe, 1)) { + FURI_LOG_E(TAG, "Missing TE"); + return; + } else { + subghz->RepeaterTXLength = tmpTe; + subghz->RepeaterStartTime = furi_get_tick(); + FURI_LOG_I(TAG, "Key Received, Transmitting now."); + } + + //CC1101 Stop RX -> Start TX + if(!subghz_tx_start(subghz, subghz->repeater_tx)) { + subghz_txrx_rx_start(subghz->txrx); + subghz_txrx_hopper_unpause(subghz->txrx); + subghz->state_notifications = SubGhzNotificationStateRx; + } else { + subghz->state_notifications = SubGhzNotificationStateTx; + } + notification_message(subghz->notifications, &subghz_sequence_repeat); + } else { + if(subghz_history_add_to_history(history, decoder_base, &preset)) { + furi_string_reset(item_name); + furi_string_reset(item_time); + + subghz->state_notifications = SubGhzNotificationStateRxDone; + + subghz_history_get_text_item_menu(history, item_name, idx); + subghz_history_get_time_item_menu(history, item_time, idx); + subghz_view_receiver_add_item_to_menu( + subghz->subghz_receiver, + furi_string_get_cstr(item_name), + furi_string_get_cstr(item_time), + subghz_history_get_type_protocol(history, idx)); + + subghz_scene_receiver_update_statusbar(subghz); + if(subghz_history_get_text_space_left(subghz->history, NULL)) { + notification_message(subghz->notifications, &sequence_error); + } } + subghz_receiver_reset(receiver); + subghz_rx_key_state_set(subghz, SubGhzRxKeyStateAddKey); } - subghz_receiver_reset(receiver); furi_string_free(item_name); furi_string_free(item_time); - subghz_rx_key_state_set(subghz, SubGhzRxKeyStateAddKey); + } else { FURI_LOG_I(TAG, "%s protocol ignored", decoder_base->protocol->name); } @@ -155,6 +213,8 @@ void subghz_scene_receiver_on_enter(void* context) { FuriString* item_name = furi_string_alloc(); FuriString* item_time = furi_string_alloc(); + subghz->repeater_tx = flipper_format_string_alloc(); + subghz->RepeaterTXLength = 0; if(subghz_rx_key_state_get(subghz) == SubGhzRxKeyStateIDLE) { #if SUBGHZ_LAST_SETTING_SAVE_PRESET @@ -214,6 +274,22 @@ void subghz_scene_receiver_on_enter(void* context) { furi_check( subghz_txrx_load_decoder_by_name_protocol(subghz->txrx, SUBGHZ_PROTOCOL_BIN_RAW_NAME)); + //Remember if the repeater was loaded, need to set protocol back to BinRAW if we are repeating. + //Do this last so that I can override the BinRAW load or not! + if(subghz->last_settings->RepeaterState != SubGhzRepeaterOff) { + subghz->repeater = subghz->last_settings->RepeaterState; + + //User had BinRAW on if the last settings had BinRAW on, if not, repeater is on, and BinRAW goes on, but State CHanged is false! + subghz->BINRawStateChanged = + (subghz->last_settings->filter != + (SubGhzProtocolFlag_Decodable | SubGhzProtocolFlag_BinRAW)); + subghz->filter = SubGhzProtocolFlag_Decodable | SubGhzProtocolFlag_BinRAW; + subghz_txrx_receiver_set_filter(subghz->txrx, subghz->filter); + } else { + subghz->repeater = SubGhzRepeaterOff; + subghz->BINRawStateChanged = false; + } + subghz_scene_receiver_update_statusbar(subghz); view_dispatcher_switch_to_view(subghz->view_dispatcher, SubGhzViewIdReceiver); @@ -317,19 +393,45 @@ bool subghz_scene_receiver_on_event(void* context, SceneManagerEvent event) { break; } } else if(event.type == SceneManagerEventTypeTick) { - if(subghz->state_notifications != SubGhzNotificationStateTx) { - if(subghz_txrx_hopper_get_state(subghz->txrx) != SubGhzHopperStateOFF) { - subghz_txrx_hopper_update(subghz->txrx); - subghz_scene_receiver_update_statusbar(subghz); + if(subghz->RepeaterTXLength > 0) { + uint32_t tmp = furi_get_tick() - subghz->RepeaterStartTime; + uint8_t RepeatMultiplier = (subghz->repeater == SubGhzRepeaterOnShort) ? 1 : //No repeats, 1 key Tx + (subghz->repeater == SubGhzRepeaterOnLong) ? 7 : //Long Repeat + 3; //Normal Repeat + if(tmp > furi_ms_to_ticks(subghz->RepeaterTXLength) * RepeatMultiplier) { + /* AAAAARGH! The FLipper cant tell me how long the receive was happening. + I can find the minimum time to transmit a key though, so Ive just doubled it to get the key + to send OK to a receiver. It works on my car, by who knows how it will work on devices that look at TX time1 + At least the key is guaranteed to be transmitted up to TWICE! Regardless of Te of a Key + + This is the best repeaterv the flipper can do without diving deeper into the firmware for some big changes! + */ + FURI_LOG_I(TAG, "TXLength: %lu TxTime: %lu", subghz->RepeaterTXLength, tmp); + + subghz_txrx_stop(subghz->txrx); + subghz->RepeaterTXLength = 0; + subghz->RepeaterStartTime = 0; + subghz->ignore_filter = 0x00; + subghz_txrx_rx_start(subghz->txrx); + subghz_txrx_hopper_unpause(subghz->txrx); + subghz->state_notifications = SubGhzNotificationStateRx; + //notification_message(subghz->notifications, &subghz_sequence_repeat); } + } else { + if(subghz->state_notifications != SubGhzNotificationStateTx) { + if(subghz_txrx_hopper_get_state(subghz->txrx) != SubGhzHopperStateOFF) { + subghz_txrx_hopper_update(subghz->txrx); + subghz_scene_receiver_update_statusbar(subghz); + } - SubGhzThresholdRssiData ret_rssi = subghz_threshold_get_rssi_data( - subghz->threshold_rssi, subghz_txrx_radio_device_get_rssi(subghz->txrx)); + SubGhzThresholdRssiData ret_rssi = subghz_threshold_get_rssi_data( + subghz->threshold_rssi, subghz_txrx_radio_device_get_rssi(subghz->txrx)); - subghz_receiver_rssi(subghz->subghz_receiver, ret_rssi.rssi); - subghz_protocol_decoder_bin_raw_data_input_rssi( - (SubGhzProtocolDecoderBinRAW*)subghz_txrx_get_decoder(subghz->txrx), - ret_rssi.rssi); + subghz_receiver_rssi(subghz->subghz_receiver, ret_rssi.rssi); + subghz_protocol_decoder_bin_raw_data_input_rssi( + (SubGhzProtocolDecoderBinRAW*)subghz_txrx_get_decoder(subghz->txrx), + ret_rssi.rssi); + } } } @@ -346,7 +448,7 @@ bool subghz_scene_receiver_on_event(void* context, SceneManagerEvent event) { subghz->state_notifications = SubGhzNotificationStateRx; break; case SubGhzNotificationStateTx: - notification_message(subghz->notifications, &sequence_blink_magenta_10); + notification_message(subghz->notifications, &sequence_blink_red_10); break; default: break; @@ -356,5 +458,8 @@ bool subghz_scene_receiver_on_event(void* context, SceneManagerEvent event) { } void subghz_scene_receiver_on_exit(void* context) { - UNUSED(context); + SubGhz* subghz = context; + flipper_format_free(subghz->repeater_tx); + + //UNUSED(context); } diff --git a/applications/main/subghz/scenes/subghz_scene_receiver_config.c b/applications/main/subghz/scenes/subghz_scene_receiver_config.c index 09c3976cc334..c5cdb9558c10 100644 --- a/applications/main/subghz/scenes/subghz_scene_receiver_config.c +++ b/applications/main/subghz/scenes/subghz_scene_receiver_config.c @@ -8,12 +8,13 @@ enum SubGhzSettingIndex { SubGhzSettingIndexHopping, SubGhzSettingIndexModulation, SubGhzSettingIndexBinRAW, + SubGhzSettingIndexRepeater, + SubGhzSettingIndexSound, SubGhzSettingIndexIgnoreStarline, SubGhzSettingIndexIgnoreCars, SubGhzSettingIndexIgnoreMagellan, SubGhzSettingIndexIgnorePrinceton, SubGhzSettingIndexIgnoreNiceFlorS, - SubGhzSettingIndexSound, SubGhzSettingIndexResetToDefault, SubGhzSettingIndexLock, SubGhzSettingIndexRAWThresholdRSSI, @@ -49,6 +50,7 @@ const float raw_threshold_rssi_value[RAW_THRESHOLD_RSSI_COUNT] = { }; #define COMBO_BOX_COUNT 2 +#define REPEATER_BOX_COUNT 4 const uint32_t hopping_value[COMBO_BOX_COUNT] = { SubGhzHopperStateOFF, @@ -65,11 +67,25 @@ const uint32_t bin_raw_value[COMBO_BOX_COUNT] = { SubGhzProtocolFlag_Decodable | SubGhzProtocolFlag_BinRAW, }; +const uint32_t repeater_value[REPEATER_BOX_COUNT] = { + SubGhzRepeaterOff, + SubGhzRepeaterOn, + SubGhzRepeaterOnLong, + SubGhzRepeaterOnShort, +}; + const char* const combobox_text[COMBO_BOX_COUNT] = { "OFF", "ON", }; +const char* const repeater_box_text[REPEATER_BOX_COUNT] = { + "OFF", + "Normal", + "Long", + "Short", +}; + static void subghz_scene_receiver_config_set_ignore_filter(VariableItem* item, SubGhzProtocolFlag filter) { SubGhz* subghz = variable_item_get_context(item); @@ -247,6 +263,44 @@ static void subghz_scene_receiver_config_set_bin_raw(VariableItem* item) { subghz->last_settings->filter = subghz->filter; } +static void subghz_scene_receiver_config_set_repeater(VariableItem* item) { + SubGhz* subghz = variable_item_get_context(item); + uint8_t index = variable_item_get_current_value_index(item); + + variable_item_set_current_value_text(item, repeater_box_text[index]); + subghz_txrx_repeater_set_state(&subghz->repeater, repeater_value[index]); + + //Change BinRAW to ON or OFF as required, and remember whether I changed it! (Put back for the user.) + if(repeater_value[index] != SubGhzRepeaterOff) { + subghz->last_settings->RepeaterState = repeater_value[index]; + + if((bin_raw_value[variable_item_get_current_value_index(subghz->BIN_Raw_menu)] & + SubGhzProtocolFlag_BinRAW) == SubGhzProtocolFlag_BinRAW) { + //BinRAW is on, repeater is on. + } else { + //Repeater is on, Binraw is Off. + subghz->BINRawStateChanged = true; + variable_item_set_current_value_index( + subghz->BIN_Raw_menu, 1 /*Index of ON in BIN_Raw menu!*/); + subghz_scene_receiver_config_set_bin_raw(subghz->BIN_Raw_menu); + } + variable_item_set_locked( + subghz->BIN_Raw_menu, true, "Turn off\n Repeater!\n to do\n that!"); + } else { + subghz->last_settings->RepeaterState = SubGhzRepeaterOff; + + //Put BinRAW back how it was, if we changed it. + if(subghz->BINRawStateChanged) { + subghz->BINRawStateChanged = false; + variable_item_set_current_value_index( + subghz->BIN_Raw_menu, 0 /*Index of OFF in BIN_Raw menu!*/); + subghz_scene_receiver_config_set_bin_raw(subghz->BIN_Raw_menu); + } + variable_item_set_locked( + subghz->BIN_Raw_menu, false, "Turn off\n Repeater!\n to do\n that!"); + } +} + static void subghz_scene_receiver_config_set_raw_threshold_rssi(VariableItem* item) { SubGhz* subghz = variable_item_get_context(item); uint8_t index = variable_item_get_current_value_index(item); @@ -307,7 +361,9 @@ static void subghz_scene_receiver_config_var_list_enter_callback(void* context, subghz->last_settings->frequency = preset.frequency; subghz->last_settings->preset_index = preset_index; - + subghz->last_settings->RepeaterState = SubGhzRepeaterOff; + subghz_txrx_repeater_set_state(&subghz->repeater, SubGhzRepeaterOff); + subghz->BINRawStateChanged = false; subghz_threshold_rssi_set(subghz->threshold_rssi, raw_threshold_rssi_value[default_index]); subghz->filter = bin_raw_value[0]; subghz->ignore_filter = 0x00; @@ -339,6 +395,11 @@ void subghz_scene_receiver_config_on_enter(void* context) { SubGhzSetting* setting = subghz_txrx_get_setting(subghz->txrx); SubGhzRadioPreset preset = subghz_txrx_get_preset(subghz->txrx); + //This gets checked a few times, so lets cache this. + bool IsReadRAWScene = + (scene_manager_get_scene_state(subghz->scene_manager, SubGhzSceneReadRAW) == + SubGhzCustomEventManagerSet); + item = variable_item_list_add( subghz->variable_item_list, "Frequency", @@ -371,8 +432,7 @@ void subghz_scene_receiver_config_on_enter(void* context) { variable_item_set_current_value_text( item, subghz_setting_get_preset_name(setting, value_index)); - if(scene_manager_get_scene_state(subghz->scene_manager, SubGhzSceneReadRAW) != - SubGhzCustomEventManagerSet) { + if(!IsReadRAWScene) { // Hopping item = variable_item_list_add( subghz->variable_item_list, @@ -386,11 +446,10 @@ void subghz_scene_receiver_config_on_enter(void* context) { variable_item_set_current_value_text(item, combobox_text[value_index]); } - if(scene_manager_get_scene_state(subghz->scene_manager, SubGhzSceneReadRAW) != - SubGhzCustomEventManagerSet) { + if(!IsReadRAWScene) { item = variable_item_list_add( subghz->variable_item_list, - "Bin RAW", + "RAW Receive", COMBO_BOX_COUNT, subghz_scene_receiver_config_set_bin_raw, subghz); @@ -398,10 +457,45 @@ void subghz_scene_receiver_config_on_enter(void* context) { value_index = value_index_uint32(subghz->filter, bin_raw_value, COMBO_BOX_COUNT); variable_item_set_current_value_index(item, value_index); variable_item_set_current_value_text(item, combobox_text[value_index]); + subghz->BIN_Raw_menu = item; + } + + /* Repeater Menu. With the Repeater, you can relay a key. + To Use, select the frequency (or hopper) and enable Repeater. + Any keys decoded with BinRAW will be transmitted as soon as they are received. + Ill leave the uses of this one up to your imagination! */ + if(!IsReadRAWScene) { + item = variable_item_list_add( + subghz->variable_item_list, + "Repeater", + REPEATER_BOX_COUNT, + subghz_scene_receiver_config_set_repeater, + subghz); + value_index = value_index_uint32( + subghz_txrx_repeater_get_state(&subghz->repeater), repeater_value, REPEATER_BOX_COUNT); + variable_item_set_current_value_index(item, value_index); + //variable_item_set_current_value_text(item, repeater_box_text[value_index]); + //Instead of setting the text, Im calling the callback. That sets the text, and the bin raw on off and locked! + subghz_scene_receiver_config_set_repeater(item); + //Remember if the user set BinRAW on or if I did with the repeater! + subghz->BINRawStateChanged = + (subghz->last_settings->filter != + (SubGhzProtocolFlag_Decodable | SubGhzProtocolFlag_BinRAW)); } - if(scene_manager_get_scene_state(subghz->scene_manager, SubGhzSceneReadRAW) != - SubGhzCustomEventManagerSet) { + // Enable speaker, will send all incoming noises and signals to speaker so you can listen how your remote sounds like :) + item = variable_item_list_add( + subghz->variable_item_list, + "Sound", + COMBO_BOX_COUNT, + subghz_scene_receiver_config_set_speaker, + subghz); + value_index = value_index_uint32( + subghz_txrx_speaker_get_state(subghz->txrx), speaker_value, COMBO_BOX_COUNT); + variable_item_set_current_value_index(item, value_index); + variable_item_set_current_value_text(item, combobox_text[value_index]); + + if(!IsReadRAWScene) { item = variable_item_list_add( subghz->variable_item_list, "Ignore Starline", @@ -463,20 +557,7 @@ void subghz_scene_receiver_config_on_enter(void* context) { variable_item_set_current_value_text(item, combobox_text[value_index]); } - // Enable speaker, will send all incoming noises and signals to speaker so you can listen how your remote sounds like :) - item = variable_item_list_add( - subghz->variable_item_list, - "Sound", - COMBO_BOX_COUNT, - subghz_scene_receiver_config_set_speaker, - subghz); - value_index = value_index_uint32( - subghz_txrx_speaker_get_state(subghz->txrx), speaker_value, COMBO_BOX_COUNT); - variable_item_set_current_value_index(item, value_index); - variable_item_set_current_value_text(item, combobox_text[value_index]); - - if(scene_manager_get_scene_state(subghz->scene_manager, SubGhzSceneReadRAW) != - SubGhzCustomEventManagerSet) { + if(!IsReadRAWScene) { // Reset to default variable_item_list_add(subghz->variable_item_list, "Reset to default", 1, NULL, NULL); @@ -485,8 +566,7 @@ void subghz_scene_receiver_config_on_enter(void* context) { subghz_scene_receiver_config_var_list_enter_callback, subghz); } - if(scene_manager_get_scene_state(subghz->scene_manager, SubGhzSceneReadRAW) != - SubGhzCustomEventManagerSet) { + if(!IsReadRAWScene) { // Lock keyboard variable_item_list_add(subghz->variable_item_list, "Lock Keyboard", 1, NULL, NULL); variable_item_list_set_enter_callback( @@ -495,8 +575,7 @@ void subghz_scene_receiver_config_on_enter(void* context) { subghz); } - if(scene_manager_get_scene_state(subghz->scene_manager, SubGhzSceneReadRAW) == - SubGhzCustomEventManagerSet) { + if(IsReadRAWScene) { item = variable_item_list_add( subghz->variable_item_list, "RSSI Threshold:", @@ -532,6 +611,15 @@ bool subghz_scene_receiver_config_on_event(void* context, SceneManagerEvent even void subghz_scene_receiver_config_on_exit(void* context) { SubGhz* subghz = context; + + //If the Repeater changed the BinRAW settings, put them back now. That will ensure it loads correctly! + if(subghz->BINRawStateChanged & (subghz->repeater != SubGhzRepeaterOff)) { + //Bit hacky, but works well. + subghz->last_settings->filter = bin_raw_value[0 /*BinRAW Off*/]; + subghz->BINRawStateChanged = false; + } + subghz->BIN_Raw_menu = NULL; + variable_item_list_set_selected_item(subghz->variable_item_list, 0); variable_item_list_reset(subghz->variable_item_list); #ifdef FURI_DEBUG diff --git a/applications/main/subghz/scenes/subghz_scene_receiver_info.c b/applications/main/subghz/scenes/subghz_scene_receiver_info.c index 6bea7e78bfc5..0a639e56cfaa 100644 --- a/applications/main/subghz/scenes/subghz_scene_receiver_info.c +++ b/applications/main/subghz/scenes/subghz_scene_receiver_info.c @@ -199,7 +199,7 @@ bool subghz_scene_receiver_info_on_event(void* context, SceneManagerEvent event) } switch(subghz->state_notifications) { case SubGhzNotificationStateTx: - notification_message(subghz->notifications, &sequence_blink_magenta_10); + notification_message(subghz->notifications, &sequence_blink_red_10); break; case SubGhzNotificationStateRx: notification_message(subghz->notifications, &sequence_blink_cyan_10); diff --git a/applications/main/subghz/scenes/subghz_scene_transmitter.c b/applications/main/subghz/scenes/subghz_scene_transmitter.c index bb51c073dc35..39eac76a5fac 100644 --- a/applications/main/subghz/scenes/subghz_scene_transmitter.c +++ b/applications/main/subghz/scenes/subghz_scene_transmitter.c @@ -100,7 +100,7 @@ bool subghz_scene_transmitter_on_event(void* context, SceneManagerEvent event) { } } else if(event.type == SceneManagerEventTypeTick) { if(subghz->state_notifications == SubGhzNotificationStateTx) { - notification_message(subghz->notifications, &sequence_blink_magenta_10); + notification_message(subghz->notifications, &sequence_blink_red_10); } return true; } diff --git a/applications/main/subghz/subghz_i.c b/applications/main/subghz/subghz_i.c index bf2546062146..f8722ec81093 100644 --- a/applications/main/subghz/subghz_i.c +++ b/applications/main/subghz/subghz_i.c @@ -14,7 +14,7 @@ void subghz_blink_start(SubGhz* subghz) { furi_assert(subghz); notification_message(subghz->notifications, &sequence_blink_stop); - notification_message(subghz->notifications, &sequence_blink_start_magenta); + notification_message(subghz->notifications, &sequence_blink_start_red); } void subghz_blink_stop(SubGhz* subghz) { diff --git a/applications/main/subghz/subghz_i.h b/applications/main/subghz/subghz_i.h index c3daac034837..f86a1135edb4 100644 --- a/applications/main/subghz/subghz_i.h +++ b/applications/main/subghz/subghz_i.h @@ -84,6 +84,12 @@ struct SubGhz { SubGhzProtocolFlag ignore_filter; FuriString* error_str; SubGhzLock lock; + SubGhzRepeater repeater; + FlipperFormat* repeater_tx; + uint32_t RepeaterTXLength; + uint32_t RepeaterStartTime; + VariableItem* BIN_Raw_menu; + bool BINRawStateChanged; SecureData* secure_data; diff --git a/applications/main/subghz/subghz_last_settings.c b/applications/main/subghz/subghz_last_settings.c index fe072a1efe69..d91c36eef2d3 100644 --- a/applications/main/subghz/subghz_last_settings.c +++ b/applications/main/subghz/subghz_last_settings.c @@ -19,6 +19,7 @@ #define SUBGHZ_LAST_SETTING_FIELD_IGNORE_FILTER "IgnoreFilter" #define SUBGHZ_LAST_SETTING_FIELD_FILTER "Filter" #define SUBGHZ_LAST_SETTING_FIELD_RSSI_THRESHOLD "RSSI" +#define SUBGHZ_LAST_SETTING_FIELD_REPEATER "Repeater" SubGhzLastSettings* subghz_last_settings_alloc(void) { SubGhzLastSettings* instance = malloc(sizeof(SubGhzLastSettings)); @@ -44,6 +45,7 @@ void subghz_last_settings_load(SubGhzLastSettings* instance, size_t preset_count bool temp_external_module_power_amp = false; bool temp_timestamp_file_names = false; bool temp_enable_hopping = false; + uint32_t temp_RepeaterState = false; uint32_t temp_ignore_filter = 0; uint32_t temp_filter = 0; float temp_rssi = 0; @@ -106,6 +108,9 @@ void subghz_last_settings_load(SubGhzLastSettings* instance, size_t preset_count 1); filter_was_read = flipper_format_read_uint32( fff_data_file, SUBGHZ_LAST_SETTING_FIELD_FILTER, (uint32_t*)&temp_filter, 1); + flipper_format_read_uint32( + fff_data_file, SUBGHZ_LAST_SETTING_FIELD_REPEATER, (uint32_t*)&temp_RepeaterState, 1); + } else { FURI_LOG_E(TAG, "Error open file %s", SUBGHZ_LAST_SETTINGS_PATH); } @@ -126,6 +131,7 @@ void subghz_last_settings_load(SubGhzLastSettings* instance, size_t preset_count // See bin_raw_value in applications/main/subghz/scenes/subghz_scene_receiver_config.c instance->filter = SubGhzProtocolFlag_Decodable; instance->rssi = SUBGHZ_RAW_THRESHOLD_MIN; + instance->RepeaterState = SubGhzRepeaterOff; } else { instance->frequency = temp_frequency; instance->frequency_analyzer_feedback_level = @@ -161,6 +167,7 @@ void subghz_last_settings_load(SubGhzLastSettings* instance, size_t preset_count instance->rssi = rssi_was_read ? temp_rssi : SUBGHZ_RAW_THRESHOLD_MIN; instance->enable_hopping = temp_enable_hopping; + instance->RepeaterState = temp_RepeaterState; instance->ignore_filter = ignore_filter_was_read ? temp_ignore_filter : 0x00; #if SUBGHZ_LAST_SETTING_SAVE_BIN_RAW instance->filter = filter_was_read ? temp_filter : SubGhzProtocolFlag_Decodable; @@ -270,6 +277,10 @@ bool subghz_last_settings_save(SubGhzLastSettings* instance) { file, SUBGHZ_LAST_SETTING_FIELD_FILTER, &instance->filter, 1)) { break; } + if(!flipper_format_insert_or_update_uint32( + file, SUBGHZ_LAST_SETTING_FIELD_REPEATER, &instance->RepeaterState, 1)) { + break; + } saved = true; } while(0); diff --git a/applications/main/subghz/subghz_last_settings.h b/applications/main/subghz/subghz_last_settings.h index b3742d4bf301..16eef3e69f40 100644 --- a/applications/main/subghz/subghz_last_settings.h +++ b/applications/main/subghz/subghz_last_settings.h @@ -27,6 +27,7 @@ typedef struct { // saved so as not to change the version bool timestamp_file_names; bool enable_hopping; + uint32_t RepeaterState; uint32_t ignore_filter; uint32_t filter; float rssi; diff --git a/applications/main/subghz/views/receiver.c b/applications/main/subghz/views/receiver.c index cdc76c50d379..467939be41d4 100644 --- a/applications/main/subghz/views/receiver.c +++ b/applications/main/subghz/views/receiver.c @@ -64,6 +64,7 @@ typedef struct { FuriString* progress_str; bool hopping_enabled; bool bin_raw_enabled; + bool repeater_enabled; SubGhzReceiverHistory* history; uint16_t idx; uint16_t list_offset; @@ -204,7 +205,8 @@ void subghz_view_receiver_add_data_statusbar( const char* preset_str, const char* history_stat_str, bool hopping_enabled, - bool bin_raw_enabled) { + bool bin_raw_enabled, + bool repeater_enabled) { furi_assert(subghz_receiver); with_view_model( subghz_receiver->view, @@ -215,6 +217,7 @@ void subghz_view_receiver_add_data_statusbar( furi_string_set(model->history_stat_str, history_stat_str); model->hopping_enabled = hopping_enabled; model->bin_raw_enabled = bin_raw_enabled; + model->repeater_enabled = repeater_enabled; }, true); } @@ -325,11 +328,14 @@ void subghz_view_receiver_draw(Canvas* canvas, SubGhzViewReceiverModel* model) { (model->device_type == SubGhzRadioDeviceTypeInternal) ? &I_Scanning_123x52 : &I_Fishing_123x52); canvas_set_font(canvas, FontPrimary); - if(model->hopping_enabled) { + if(model->repeater_enabled) { + canvas_draw_str(canvas, 59, 46, "Repeater..."); + } else if(model->hopping_enabled) { canvas_draw_str(canvas, 59, 46, "Hopper scan..."); } else { canvas_draw_str(canvas, 59, 46, "Fixed scan..."); } + //canvas_draw_line(canvas, 46, 51, 125, 51); canvas_set_font(canvas, FontSecondary); @@ -576,6 +582,7 @@ void subghz_view_receiver_exit(void* context) { model->nodraw = false; model->hopping_enabled = false; model->bin_raw_enabled = false; + model->repeater_enabled = false; }, false); furi_timer_stop(subghz_receiver->timer); @@ -614,6 +621,7 @@ SubGhzViewReceiver* subghz_view_receiver_alloc() { model->history = malloc(sizeof(SubGhzReceiverHistory)); model->hopping_enabled = false; model->bin_raw_enabled = false; + model->repeater_enabled = false; SubGhzReceiverMenuItemArray_init(model->history->data); }, true); diff --git a/applications/main/subghz/views/receiver.h b/applications/main/subghz/views/receiver.h index c280e1de6aaf..53859ec4d16e 100644 --- a/applications/main/subghz/views/receiver.h +++ b/applications/main/subghz/views/receiver.h @@ -33,7 +33,8 @@ void subghz_view_receiver_add_data_statusbar( const char* preset_str, const char* history_stat_str, bool hopping_enabled, - bool bin_raw_enabled); + bool bin_raw_enabled, + bool repeater_enabled); void subghz_view_receiver_set_radio_device_type( SubGhzViewReceiver* subghz_receiver,