From 326c3a13de9cf4d8731ffcc354f23073d61d5678 Mon Sep 17 00:00:00 2001 From: WillyJL <49810075+WillyJL@users.noreply.github.com> Date: Sat, 7 Jun 2025 15:58:04 +0100 Subject: [PATCH] IR: "Decode only" mode, more intuitive learn scene buttons --- CHANGELOG.md | 1 + applications/main/infrared/infrared_app.c | 1 + applications/main/infrared/infrared_app_i.h | 1 + .../infrared/scenes/infrared_scene_learn.c | 26 ++++++++++++++++--- lib/infrared/worker/infrared_worker.c | 11 +++++++- lib/infrared/worker/infrared_worker.h | 8 ++++++ targets/f7/api_symbols.csv | 1 + 7 files changed, 44 insertions(+), 5 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index ca4a444b3..5f4b666af 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,7 @@ - Apps: - Sub-GHz: Sub-GHz Playlist Creator (by @coolerUA) - NFC: Ventra ULEV1 parser (by @hazardousvoltage) +- Infrared: "Decode only" mode to ignore RAW signals, make buttons in learn scene more intuitive (by @WillyJL) - UL: Sub-GHz: Add keeloq ironlogic aka il100 smart clone cloners support (by @xMasterX & Vitaly) - UL: iButton: Add TM01x Dallas write support (by @Leptopt1los) - UL: Display: Backlight option "Always ON" (by @Dmitry422) diff --git a/applications/main/infrared/infrared_app.c b/applications/main/infrared/infrared_app.c index 677eb1117..ec180a180 100644 --- a/applications/main/infrared/infrared_app.c +++ b/applications/main/infrared/infrared_app.c @@ -159,6 +159,7 @@ static InfraredApp* infrared_alloc(void) { app_state->is_otg_enabled = false; app_state->is_easy_mode = false; app_state->is_decode_enabled = true; + app_state->is_decode_forced = false; app_state->edit_target = InfraredEditTargetNone; app_state->edit_mode = InfraredEditModeNone; app_state->current_button_index = InfraredButtonIndexNone; diff --git a/applications/main/infrared/infrared_app_i.h b/applications/main/infrared/infrared_app_i.h index 0d9b440a8..38eadfd82 100644 --- a/applications/main/infrared/infrared_app_i.h +++ b/applications/main/infrared/infrared_app_i.h @@ -91,6 +91,7 @@ typedef struct { bool is_otg_enabled; /**< Whether OTG power (external 5V) is enabled. */ bool is_easy_mode; /**< Whether easy learning mode is enabled. */ bool is_decode_enabled; /**< Whether signal decoding is enabled. */ + bool is_decode_forced; /**< Whether signal decoding is forced. */ InfraredEditTarget edit_target : 8; /**< Selected editing target (a remote or a button). */ InfraredEditMode edit_mode : 8; /**< Selected editing operation (rename or delete). */ int32_t current_button_index; /**< Selected button index (move destination). */ diff --git a/applications/main/infrared/scenes/infrared_scene_learn.c b/applications/main/infrared/scenes/infrared_scene_learn.c index 8c6b557b7..d9be78c6c 100644 --- a/applications/main/infrared/scenes/infrared_scene_learn.c +++ b/applications/main/infrared/scenes/infrared_scene_learn.c @@ -146,9 +146,12 @@ void infrared_scene_learn_on_enter(void* context) { } dialog_ex_set_left_button_text( - dialog_ex, infrared->app_state.is_easy_mode ? "Manual" : "Easy"); + dialog_ex, infrared->app_state.is_easy_mode ? "Easy" : "Manual"); dialog_ex_set_right_button_text( - dialog_ex, infrared->app_state.is_decode_enabled ? "RAW" : "Decode"); + dialog_ex, + infrared->app_state.is_decode_forced ? "Decode" : + infrared->app_state.is_decode_enabled ? "Auto" : + "RAW"); dialog_ex_set_context(dialog_ex, context); dialog_ex_set_result_callback(dialog_ex, infrared_scene_learn_dialog_result_callback); @@ -179,11 +182,26 @@ bool infrared_scene_learn_on_event(void* context, SceneManagerEvent event) { consumed = true; } else if(event.event == DialogExResultRight) { // Toggle signal decoding - infrared->app_state.is_decode_enabled = !infrared->app_state.is_decode_enabled; + if(infrared->app_state.is_decode_forced) { + // Decode -> RAW + infrared->app_state.is_decode_enabled = false; + infrared->app_state.is_decode_forced = false; + } else if(infrared->app_state.is_decode_enabled) { + // Auto -> Decode + infrared->app_state.is_decode_forced = true; + } else { + // RAW -> Auto + infrared->app_state.is_decode_enabled = true; + } infrared_worker_rx_enable_signal_decoding( infrared->worker, infrared->app_state.is_decode_enabled); + infrared_worker_rx_force_signal_decoding( + infrared->worker, infrared->app_state.is_decode_forced); dialog_ex_set_right_button_text( - infrared->dialog_ex, infrared->app_state.is_decode_enabled ? "RAW" : "Decode"); + infrared->dialog_ex, + infrared->app_state.is_decode_forced ? "Decode" : + infrared->app_state.is_decode_enabled ? "Auto" : + "RAW"); consumed = true; } } else if(event.type == SceneManagerEventTypeBack) { diff --git a/lib/infrared/worker/infrared_worker.c b/lib/infrared/worker/infrared_worker.c index cc9361ccf..424d53d0a 100644 --- a/lib/infrared/worker/infrared_worker.c +++ b/lib/infrared/worker/infrared_worker.c @@ -79,6 +79,8 @@ struct InfraredWorker { bool overrun; } rx; }; + + bool decode_force; }; typedef struct { @@ -143,7 +145,7 @@ static void if(instance->rx.received_signal_callback) instance->rx.received_signal_callback( instance->rx.received_signal_context, &instance->signal); - } else { + } else if(!instance->decode_force) { /* Skip first timing if it starts from Space */ if((instance->signal.timings_cnt == 0) && !level) { return; @@ -236,6 +238,7 @@ InfraredWorker* infrared_worker_alloc(void) { instance->infrared_encoder = infrared_alloc_encoder(); instance->blink_enable = false; instance->decode_enable = true; + instance->decode_force = false; instance->notification = furi_record_open(RECORD_NOTIFICATION); instance->state = InfraredWorkerStateIdle; @@ -326,6 +329,12 @@ void infrared_worker_rx_enable_signal_decoding(InfraredWorker* instance, bool en instance->decode_enable = enable; } +void infrared_worker_rx_force_signal_decoding(InfraredWorker* instance, bool force) { + furi_check(instance); + + instance->decode_force = force; +} + void infrared_worker_tx_start(InfraredWorker* instance) { furi_check(instance); furi_check(instance->state == InfraredWorkerStateIdle); diff --git a/lib/infrared/worker/infrared_worker.h b/lib/infrared/worker/infrared_worker.h index 2edb19227..efde4a5df 100644 --- a/lib/infrared/worker/infrared_worker.h +++ b/lib/infrared/worker/infrared_worker.h @@ -84,6 +84,14 @@ void infrared_worker_rx_enable_blink_on_receiving(InfraredWorker* instance, bool */ void infrared_worker_rx_enable_signal_decoding(InfraredWorker* instance, bool enable); +/** Force decoding of received infrared signals, will ignore RAW signals. + * + * @param[in] instance - instance of InfraredWorker + * @param[in] enable - true if you want to force decoding + * false otherwise + */ +void infrared_worker_rx_force_signal_decoding(InfraredWorker* instance, bool force); + /** Clarify is received signal either decoded or raw * * @param[in] signal - received signal diff --git a/targets/f7/api_symbols.csv b/targets/f7/api_symbols.csv index 030d3b8a7..df0b83a92 100644 --- a/targets/f7/api_symbols.csv +++ b/targets/f7/api_symbols.csv @@ -2141,6 +2141,7 @@ Function,+,infrared_worker_get_decoded_signal,const InfraredMessage*,const Infra Function,+,infrared_worker_get_raw_signal,void,"const InfraredWorkerSignal*, const uint32_t**, size_t*" Function,+,infrared_worker_rx_enable_blink_on_receiving,void,"InfraredWorker*, _Bool" Function,+,infrared_worker_rx_enable_signal_decoding,void,"InfraredWorker*, _Bool" +Function,+,infrared_worker_rx_force_signal_decoding,void,"InfraredWorker*, _Bool" Function,+,infrared_worker_rx_set_received_signal_callback,void,"InfraredWorker*, InfraredWorkerReceivedSignalCallback, void*" Function,+,infrared_worker_rx_start,void,InfraredWorker* Function,+,infrared_worker_rx_stop,void,InfraredWorker*