[FL-2131] IR: continuous signal tx on learn scene (#1002)
Co-authored-by: あく <alleteam@gmail.com>
This commit is contained in:
		@@ -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);
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -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;
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -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
 | 
			
		||||
 
 | 
			
		||||
@@ -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();
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -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();
 | 
			
		||||
 
 | 
			
		||||
@@ -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); */
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -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 {
 | 
			
		||||
 
 | 
			
		||||
@@ -57,6 +57,8 @@ bool IrdaAppSceneAskBack::on_event(IrdaApp* app, IrdaAppEvent* event) {
 | 
			
		||||
            app->switch_to_previous_scene();
 | 
			
		||||
            consumed = true;
 | 
			
		||||
            break;
 | 
			
		||||
        default:
 | 
			
		||||
            break;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -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;
 | 
			
		||||
 
 | 
			
		||||
@@ -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);
 | 
			
		||||
            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);
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -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;
 | 
			
		||||
 
 | 
			
		||||
@@ -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));
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user