From ddd909faa0f114172c4c9ebff427130afd5762ac Mon Sep 17 00:00:00 2001 From: Albert Kharisov Date: Sat, 19 Feb 2022 00:16:22 +0400 Subject: [PATCH] [FL-2131] IR: continuous signal tx on learn scene (#1002) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: あく --- applications/dialogs/dialogs_module_message.c | 2 + applications/gui/modules/dialog_ex.c | 61 +++++++++++++--- applications/gui/modules/dialog_ex.h | 18 +++++ applications/irda/irda_app.cpp | 5 ++ applications/irda/irda_app.h | 1 + applications/irda/irda_app_view_manager.cpp | 15 ++-- applications/irda/scene/irda_app_scene.h | 1 + .../irda/scene/irda_app_scene_ask_back.cpp | 2 + .../irda/scene/irda_app_scene_edit_delete.cpp | 5 +- .../scene/irda_app_scene_learn_success.cpp | 69 +++++++++++++++---- .../irda/scene/irda_app_scene_remote.cpp | 7 +- lib/irda/worker/irda_worker.c | 1 + 12 files changed, 150 insertions(+), 37 deletions(-) diff --git a/applications/dialogs/dialogs_module_message.c b/applications/dialogs/dialogs_module_message.c index 2607940f..ec2efd2e 100644 --- a/applications/dialogs/dialogs_module_message.c +++ b/applications/dialogs/dialogs_module_message.c @@ -46,6 +46,8 @@ static void dialogs_app_message_callback(DialogExResult result, void* context) { case DialogExResultCenter: message_context->result = DialogMessageButtonCenter; break; + default: + break; } API_LOCK_UNLOCK(message_context->lock); } diff --git a/applications/gui/modules/dialog_ex.c b/applications/gui/modules/dialog_ex.c index 6be455f8..c01fb4c5 100755 --- a/applications/gui/modules/dialog_ex.c +++ b/applications/gui/modules/dialog_ex.c @@ -6,6 +6,7 @@ struct DialogEx { View* view; void* context; DialogExResultCallback callback; + bool enable_extended_events; }; typedef struct { @@ -96,17 +97,44 @@ static bool dialog_ex_view_input_callback(InputEvent* event, void* context) { return true; }); - // Process key presses only - if(event->type == InputTypeShort && dialog_ex->callback) { - if(event->key == InputKeyLeft && left_text != NULL) { - dialog_ex->callback(DialogExResultLeft, dialog_ex->context); - consumed = true; - } else if(event->key == InputKeyOk && center_text != NULL) { - dialog_ex->callback(DialogExResultCenter, dialog_ex->context); - consumed = true; - } else if(event->key == InputKeyRight && right_text != NULL) { - dialog_ex->callback(DialogExResultRight, dialog_ex->context); - consumed = true; + if(dialog_ex->callback) { + if(event->type == InputTypeShort) { + if(event->key == InputKeyLeft && left_text != NULL) { + dialog_ex->callback(DialogExResultLeft, dialog_ex->context); + consumed = true; + } else if(event->key == InputKeyOk && center_text != NULL) { + dialog_ex->callback(DialogExResultCenter, dialog_ex->context); + consumed = true; + } else if(event->key == InputKeyRight && right_text != NULL) { + dialog_ex->callback(DialogExResultRight, dialog_ex->context); + consumed = true; + } + } + + if(event->type == InputTypePress && dialog_ex->enable_extended_events) { + if(event->key == InputKeyLeft && left_text != NULL) { + dialog_ex->callback(DialogExPressLeft, dialog_ex->context); + consumed = true; + } else if(event->key == InputKeyOk && center_text != NULL) { + dialog_ex->callback(DialogExPressCenter, dialog_ex->context); + consumed = true; + } else if(event->key == InputKeyRight && right_text != NULL) { + dialog_ex->callback(DialogExPressRight, dialog_ex->context); + consumed = true; + } + } + + if(event->type == InputTypeRelease && dialog_ex->enable_extended_events) { + if(event->key == InputKeyLeft && left_text != NULL) { + dialog_ex->callback(DialogExReleaseLeft, dialog_ex->context); + consumed = true; + } else if(event->key == InputKeyOk && center_text != NULL) { + dialog_ex->callback(DialogExReleaseCenter, dialog_ex->context); + consumed = true; + } else if(event->key == InputKeyRight && right_text != NULL) { + dialog_ex->callback(DialogExReleaseRight, dialog_ex->context); + consumed = true; + } } } @@ -144,6 +172,7 @@ DialogEx* dialog_ex_alloc() { return true; }); + dialog_ex->enable_extended_events = false; return dialog_ex; } @@ -262,3 +291,13 @@ void dialog_ex_reset(DialogEx* dialog_ex) { dialog_ex->context = NULL; dialog_ex->callback = NULL; } + +void dialog_ex_enable_extended_events(DialogEx* dialog_ex) { + furi_assert(dialog_ex); + dialog_ex->enable_extended_events = true; +} + +void dialog_ex_disable_extended_events(DialogEx* dialog_ex) { + furi_assert(dialog_ex); + dialog_ex->enable_extended_events = false; +} diff --git a/applications/gui/modules/dialog_ex.h b/applications/gui/modules/dialog_ex.h index 871bb28a..4c609423 100644 --- a/applications/gui/modules/dialog_ex.h +++ b/applications/gui/modules/dialog_ex.h @@ -19,6 +19,12 @@ typedef enum { DialogExResultLeft, DialogExResultCenter, DialogExResultRight, + DialogExPressLeft, + DialogExPressCenter, + DialogExPressRight, + DialogExReleaseLeft, + DialogExReleaseCenter, + DialogExReleaseRight, } DialogExResult; /** DialogEx result callback type @@ -145,6 +151,18 @@ void dialog_ex_set_right_button_text(DialogEx* dialog_ex, const char* text); */ void dialog_ex_reset(DialogEx* dialog_ex); +/** Enable press/release events + * + * @param dialog_ex DialogEx instance + */ +void dialog_ex_enable_extended_events(DialogEx* dialog_ex); + +/** Disable press/release events + * + * @param dialog_ex DialogEx instance + */ +void dialog_ex_disable_extended_events(DialogEx* dialog_ex); + #ifdef __cplusplus } #endif diff --git a/applications/irda/irda_app.cpp b/applications/irda/irda_app.cpp index c524b2d2..184ed34e 100644 --- a/applications/irda/irda_app.cpp +++ b/applications/irda/irda_app.cpp @@ -279,3 +279,8 @@ const IrdaAppSignal& IrdaApp::get_received_signal() const { void IrdaApp::set_received_signal(const IrdaAppSignal& signal) { received_signal = signal; } + +void IrdaApp::signal_sent_callback(void* context) { + IrdaApp* app = static_cast(context); + app->notify_blink_green(); +} diff --git a/applications/irda/irda_app.h b/applications/irda/irda_app.h index e8de29bb..32ca3c2c 100644 --- a/applications/irda/irda_app.h +++ b/applications/irda/irda_app.h @@ -87,6 +87,7 @@ public: static void text_input_callback(void* context); static void popup_callback(void* context); + static void signal_sent_callback(void* context); IrdaApp(); ~IrdaApp(); diff --git a/applications/irda/irda_app_view_manager.cpp b/applications/irda/irda_app_view_manager.cpp index 63ac3999..46008bc0 100644 --- a/applications/irda/irda_app_view_manager.cpp +++ b/applications/irda/irda_app_view_manager.cpp @@ -1,8 +1,10 @@ -#include "furi.h" -#include "gui/modules/button_panel.h" +#include +#include +#include +#include + #include "irda_app.h" #include "irda/irda_app_event.h" -#include IrdaAppViewManager::IrdaAppViewManager() { event_queue = osMessageQueueNew(10, sizeof(IrdaAppEvent), NULL); @@ -113,11 +115,16 @@ void IrdaAppViewManager::receive_event(IrdaAppEvent* event) { void IrdaAppViewManager::send_event(IrdaAppEvent* event) { uint32_t timeout = 0; - /* Rapid button hammering on Remote Scene causes queue overflow - ignore it, + /* Rapid button hammering on signal send scenes causes queue overflow - ignore it, * but try to keep button release event - it switches off IRDA DMA sending. */ if(event->type == IrdaAppEvent::Type::MenuSelectedRelease) { timeout = 200; } + if((event->type == IrdaAppEvent::Type::DialogExSelected) && + (event->payload.dialog_ex_result == DialogExReleaseCenter)) { + timeout = 200; + } + osMessageQueuePut(event_queue, event, 0, timeout); /* furi_check(result == osOK); */ } diff --git a/applications/irda/scene/irda_app_scene.h b/applications/irda/scene/irda_app_scene.h index f687d405..458a92ad 100644 --- a/applications/irda/scene/irda_app_scene.h +++ b/applications/irda/scene/irda_app_scene.h @@ -50,6 +50,7 @@ public: void on_enter(IrdaApp* app) final; bool on_event(IrdaApp* app, IrdaAppEvent* event) final; void on_exit(IrdaApp* app) final; + bool button_pressed = false; }; class IrdaAppSceneLearnEnterName : public IrdaAppScene { diff --git a/applications/irda/scene/irda_app_scene_ask_back.cpp b/applications/irda/scene/irda_app_scene_ask_back.cpp index 34c8b61f..f7c37110 100644 --- a/applications/irda/scene/irda_app_scene_ask_back.cpp +++ b/applications/irda/scene/irda_app_scene_ask_back.cpp @@ -57,6 +57,8 @@ bool IrdaAppSceneAskBack::on_event(IrdaApp* app, IrdaAppEvent* event) { app->switch_to_previous_scene(); consumed = true; break; + default: + break; } } diff --git a/applications/irda/scene/irda_app_scene_edit_delete.cpp b/applications/irda/scene/irda_app_scene_edit_delete.cpp index 36dcbd01..26204801 100644 --- a/applications/irda/scene/irda_app_scene_edit_delete.cpp +++ b/applications/irda/scene/irda_app_scene_edit_delete.cpp @@ -70,7 +70,7 @@ bool IrdaAppSceneEditDelete::on_event(IrdaApp* app, IrdaAppEvent* event) { case DialogExResultCenter: furi_assert(0); break; - case DialogExResultRight: + case DialogExResultRight: { auto remote_manager = app->get_remote_manager(); bool result = false; if(app->get_edit_element() == IrdaApp::EditElement::Remote) { @@ -88,6 +88,9 @@ bool IrdaAppSceneEditDelete::on_event(IrdaApp* app, IrdaAppEvent* event) { } break; } + default: + break; + } } return consumed; diff --git a/applications/irda/scene/irda_app_scene_learn_success.cpp b/applications/irda/scene/irda_app_scene_learn_success.cpp index 3ca828d2..dfb889b0 100644 --- a/applications/irda/scene/irda_app_scene_learn_success.cpp +++ b/applications/irda/scene/irda_app_scene_learn_success.cpp @@ -1,9 +1,11 @@ -#include "../irda_app.h" +#include #include -#include "irda.h" #include #include +#include "../irda_app.h" +#include "irda.h" + static void dialog_result_callback(DialogExResult result, void* context) { auto app = static_cast(context); IrdaAppEvent event; @@ -21,6 +23,11 @@ void IrdaAppSceneLearnSuccess::on_enter(IrdaApp* app) { DOLPHIN_DEED(DolphinDeedIrLearnSuccess); app->notify_green_on(); + irda_worker_tx_set_get_signal_callback( + app->get_irda_worker(), irda_worker_tx_get_signal_steady_callback, app); + irda_worker_tx_set_signal_sent_callback( + app->get_irda_worker(), IrdaApp::signal_sent_callback, app); + auto signal = app->get_received_signal(); if(!signal.is_raw()) { @@ -55,6 +62,7 @@ void IrdaAppSceneLearnSuccess::on_enter(IrdaApp* app) { dialog_ex_set_icon(dialog_ex, 0, 1, &I_DolphinReadingSuccess_59x63); dialog_ex_set_result_callback(dialog_ex, dialog_result_callback); dialog_ex_set_context(dialog_ex, app); + dialog_ex_enable_extended_events(dialog_ex); view_manager->switch_to(IrdaAppViewManager::ViewType::DialogEx); } @@ -63,36 +71,65 @@ bool IrdaAppSceneLearnSuccess::on_event(IrdaApp* app, IrdaAppEvent* event) { bool consumed = false; if(event->type == IrdaAppEvent::Type::Tick) { /* Send event every tick to suppress any switching off green light */ - app->notify_green_on(); + if(!button_pressed) { + app->notify_green_on(); + } } if(event->type == IrdaAppEvent::Type::DialogExSelected) { switch(event->payload.dialog_ex_result) { case DialogExResultLeft: - app->switch_to_next_scene_without_saving(IrdaApp::Scene::Learn); + consumed = true; + if(!button_pressed) { + app->switch_to_next_scene_without_saving(IrdaApp::Scene::Learn); + } break; - case DialogExResultCenter: { - app->notify_sent_just_learnt(); - auto signal = app->get_received_signal(); - signal.transmit(); - break; - } case DialogExResultRight: { + consumed = true; FileWorkerCpp file_worker; - if(file_worker.check_errors()) { - app->switch_to_next_scene(IrdaApp::Scene::LearnEnterName); - } else { - app->switch_to_previous_scene(); + if(!button_pressed) { + if(file_worker.check_errors()) { + app->switch_to_next_scene(IrdaApp::Scene::LearnEnterName); + } else { + app->switch_to_previous_scene(); + } } break; } + case DialogExPressCenter: + if(!button_pressed) { + button_pressed = true; + app->notify_click_and_green_blink(); + + auto signal = app->get_received_signal(); + if(signal.is_raw()) { + irda_worker_set_raw_signal( + app->get_irda_worker(), + signal.get_raw_signal().timings, + signal.get_raw_signal().timings_cnt); + } else { + irda_worker_set_decoded_signal(app->get_irda_worker(), &signal.get_message()); + } + + irda_worker_tx_start(app->get_irda_worker()); + } + break; + case DialogExReleaseCenter: + if(button_pressed) { + button_pressed = false; + irda_worker_tx_stop(app->get_irda_worker()); + app->notify_green_off(); + } + break; default: break; } } if(event->type == IrdaAppEvent::Type::Back) { - app->switch_to_next_scene(IrdaApp::Scene::AskBack); + if(!button_pressed) { + app->switch_to_next_scene(IrdaApp::Scene::AskBack); + } consumed = true; } @@ -104,4 +141,6 @@ void IrdaAppSceneLearnSuccess::on_exit(IrdaApp* app) { DialogEx* dialog_ex = view_manager->get_dialog_ex(); dialog_ex_reset(dialog_ex); app->notify_green_off(); + irda_worker_tx_set_get_signal_callback(app->get_irda_worker(), nullptr, nullptr); + irda_worker_tx_set_signal_sent_callback(app->get_irda_worker(), nullptr, nullptr); } diff --git a/applications/irda/scene/irda_app_scene_remote.cpp b/applications/irda/scene/irda_app_scene_remote.cpp index 7138eb44..b8b0aa6c 100644 --- a/applications/irda/scene/irda_app_scene_remote.cpp +++ b/applications/irda/scene/irda_app_scene_remote.cpp @@ -29,11 +29,6 @@ static void button_menu_callback(void* context, int32_t index, InputType type) { app->get_view_manager()->send_event(&event); } -static void irda_app_message_sent_callback(void* context) { - IrdaApp* app = static_cast(context); - app->notify_blink_green(); -} - void IrdaAppSceneRemote::on_enter(IrdaApp* app) { IrdaAppViewManager* view_manager = app->get_view_manager(); ButtonMenu* button_menu = view_manager->get_button_menu(); @@ -44,7 +39,7 @@ void IrdaAppSceneRemote::on_enter(IrdaApp* app) { irda_worker_tx_set_get_signal_callback( app->get_irda_worker(), irda_worker_tx_get_signal_steady_callback, app); irda_worker_tx_set_signal_sent_callback( - app->get_irda_worker(), irda_app_message_sent_callback, app); + app->get_irda_worker(), IrdaApp::signal_sent_callback, app); buttons_names = remote_manager->get_button_list(); i = 0; diff --git a/lib/irda/worker/irda_worker.c b/lib/irda/worker/irda_worker.c index 18de4f15..40636dfd 100644 --- a/lib/irda/worker/irda_worker.c +++ b/lib/irda/worker/irda_worker.c @@ -320,6 +320,7 @@ void irda_worker_rx_enable_blink_on_receiving(IrdaWorker* instance, bool enable) void irda_worker_tx_start(IrdaWorker* instance) { furi_assert(instance); furi_assert(instance->state == IrdaWorkerStateIdle); + furi_assert(instance->tx.get_signal_callback); // size have to be greater than api hal irda async tx buffer size xStreamBufferSetTriggerLevel(instance->stream, sizeof(IrdaWorkerTiming));