Просмотр исходного кода

[FL-2131] IR: continuous signal tx on learn scene (#1002)

Co-authored-by: あく <alleteam@gmail.com>
Albert Kharisov 3 лет назад
Родитель
Сommit
ddd909faa0

+ 2 - 0
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);
 }

+ 50 - 11
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;
+}

+ 18 - 0
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

+ 5 - 0
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<IrdaApp*>(context);
+    app->notify_blink_green();
+}

+ 1 - 0
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();

+ 11 - 4
applications/irda/irda_app_view_manager.cpp

@@ -1,8 +1,10 @@
-#include "furi.h"
-#include "gui/modules/button_panel.h"
+#include <furi.h>
+#include <gui/modules/button_panel.h>
+#include <gui/modules/dialog_ex.h>
+#include <callback-connector.h>
+
 #include "irda_app.h"
 #include "irda/irda_app_event.h"
-#include <callback-connector.h>
 
 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); */
 }

+ 1 - 0
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 {

+ 2 - 0
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;
         }
     }
 

+ 4 - 1
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;

+ 54 - 15
applications/irda/scene/irda_app_scene_learn_success.cpp

@@ -1,9 +1,11 @@
-#include "../irda_app.h"
+#include <gui/modules/dialog_ex.h>
 #include <file_worker_cpp.h>
-#include "irda.h"
 #include <memory>
 #include <dolphin/dolphin.h>
 
+#include "../irda_app.h"
+#include "irda.h"
+
 static void dialog_result_callback(DialogExResult result, void* context) {
     auto app = static_cast<IrdaApp*>(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);
-            break;
-        case DialogExResultCenter: {
-            app->notify_sent_just_learnt();
-            auto signal = app->get_received_signal();
-            signal.transmit();
+            consumed = true;
+            if(!button_pressed) {
+                app->switch_to_next_scene_without_saving(IrdaApp::Scene::Learn);
+            }
             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);
 }

+ 1 - 6
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<IrdaApp*>(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;

+ 1 - 0
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));