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

Co-authored-by: あく <alleteam@gmail.com>
This commit is contained in:
Albert Kharisov 2022-02-19 00:16:22 +04:00 committed by GitHub
parent 3922ae93b7
commit ddd909faa0
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
12 changed files with 150 additions and 37 deletions

View File

@ -46,6 +46,8 @@ static void dialogs_app_message_callback(DialogExResult result, void* context) {
case DialogExResultCenter: case DialogExResultCenter:
message_context->result = DialogMessageButtonCenter; message_context->result = DialogMessageButtonCenter;
break; break;
default:
break;
} }
API_LOCK_UNLOCK(message_context->lock); API_LOCK_UNLOCK(message_context->lock);
} }

View File

@ -6,6 +6,7 @@ struct DialogEx {
View* view; View* view;
void* context; void* context;
DialogExResultCallback callback; DialogExResultCallback callback;
bool enable_extended_events;
}; };
typedef struct { typedef struct {
@ -96,17 +97,44 @@ static bool dialog_ex_view_input_callback(InputEvent* event, void* context) {
return true; return true;
}); });
// Process key presses only if(dialog_ex->callback) {
if(event->type == InputTypeShort && dialog_ex->callback) { if(event->type == InputTypeShort) {
if(event->key == InputKeyLeft && left_text != NULL) { if(event->key == InputKeyLeft && left_text != NULL) {
dialog_ex->callback(DialogExResultLeft, dialog_ex->context); dialog_ex->callback(DialogExResultLeft, dialog_ex->context);
consumed = true; consumed = true;
} else if(event->key == InputKeyOk && center_text != NULL) { } else if(event->key == InputKeyOk && center_text != NULL) {
dialog_ex->callback(DialogExResultCenter, dialog_ex->context); dialog_ex->callback(DialogExResultCenter, dialog_ex->context);
consumed = true; consumed = true;
} else if(event->key == InputKeyRight && right_text != NULL) { } else if(event->key == InputKeyRight && right_text != NULL) {
dialog_ex->callback(DialogExResultRight, dialog_ex->context); dialog_ex->callback(DialogExResultRight, dialog_ex->context);
consumed = true; 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; return true;
}); });
dialog_ex->enable_extended_events = false;
return dialog_ex; return dialog_ex;
} }
@ -262,3 +291,13 @@ void dialog_ex_reset(DialogEx* dialog_ex) {
dialog_ex->context = NULL; dialog_ex->context = NULL;
dialog_ex->callback = 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;
}

View File

@ -19,6 +19,12 @@ typedef enum {
DialogExResultLeft, DialogExResultLeft,
DialogExResultCenter, DialogExResultCenter,
DialogExResultRight, DialogExResultRight,
DialogExPressLeft,
DialogExPressCenter,
DialogExPressRight,
DialogExReleaseLeft,
DialogExReleaseCenter,
DialogExReleaseRight,
} DialogExResult; } DialogExResult;
/** DialogEx result callback type /** 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); 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 #ifdef __cplusplus
} }
#endif #endif

View File

@ -279,3 +279,8 @@ const IrdaAppSignal& IrdaApp::get_received_signal() const {
void IrdaApp::set_received_signal(const IrdaAppSignal& signal) { void IrdaApp::set_received_signal(const IrdaAppSignal& signal) {
received_signal = signal; received_signal = signal;
} }
void IrdaApp::signal_sent_callback(void* context) {
IrdaApp* app = static_cast<IrdaApp*>(context);
app->notify_blink_green();
}

View File

@ -87,6 +87,7 @@ public:
static void text_input_callback(void* context); static void text_input_callback(void* context);
static void popup_callback(void* context); static void popup_callback(void* context);
static void signal_sent_callback(void* context);
IrdaApp(); IrdaApp();
~IrdaApp(); ~IrdaApp();

View File

@ -1,8 +1,10 @@
#include "furi.h" #include <furi.h>
#include "gui/modules/button_panel.h" #include <gui/modules/button_panel.h>
#include <gui/modules/dialog_ex.h>
#include <callback-connector.h>
#include "irda_app.h" #include "irda_app.h"
#include "irda/irda_app_event.h" #include "irda/irda_app_event.h"
#include <callback-connector.h>
IrdaAppViewManager::IrdaAppViewManager() { IrdaAppViewManager::IrdaAppViewManager() {
event_queue = osMessageQueueNew(10, sizeof(IrdaAppEvent), NULL); event_queue = osMessageQueueNew(10, sizeof(IrdaAppEvent), NULL);
@ -113,11 +115,16 @@ void IrdaAppViewManager::receive_event(IrdaAppEvent* event) {
void IrdaAppViewManager::send_event(IrdaAppEvent* event) { void IrdaAppViewManager::send_event(IrdaAppEvent* event) {
uint32_t timeout = 0; 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. */ * but try to keep button release event - it switches off IRDA DMA sending. */
if(event->type == IrdaAppEvent::Type::MenuSelectedRelease) { if(event->type == IrdaAppEvent::Type::MenuSelectedRelease) {
timeout = 200; timeout = 200;
} }
if((event->type == IrdaAppEvent::Type::DialogExSelected) &&
(event->payload.dialog_ex_result == DialogExReleaseCenter)) {
timeout = 200;
}
osMessageQueuePut(event_queue, event, 0, timeout); osMessageQueuePut(event_queue, event, 0, timeout);
/* furi_check(result == osOK); */ /* furi_check(result == osOK); */
} }

View File

@ -50,6 +50,7 @@ public:
void on_enter(IrdaApp* app) final; void on_enter(IrdaApp* app) final;
bool on_event(IrdaApp* app, IrdaAppEvent* event) final; bool on_event(IrdaApp* app, IrdaAppEvent* event) final;
void on_exit(IrdaApp* app) final; void on_exit(IrdaApp* app) final;
bool button_pressed = false;
}; };
class IrdaAppSceneLearnEnterName : public IrdaAppScene { class IrdaAppSceneLearnEnterName : public IrdaAppScene {

View File

@ -57,6 +57,8 @@ bool IrdaAppSceneAskBack::on_event(IrdaApp* app, IrdaAppEvent* event) {
app->switch_to_previous_scene(); app->switch_to_previous_scene();
consumed = true; consumed = true;
break; break;
default:
break;
} }
} }

View File

@ -70,7 +70,7 @@ bool IrdaAppSceneEditDelete::on_event(IrdaApp* app, IrdaAppEvent* event) {
case DialogExResultCenter: case DialogExResultCenter:
furi_assert(0); furi_assert(0);
break; break;
case DialogExResultRight: case DialogExResultRight: {
auto remote_manager = app->get_remote_manager(); auto remote_manager = app->get_remote_manager();
bool result = false; bool result = false;
if(app->get_edit_element() == IrdaApp::EditElement::Remote) { if(app->get_edit_element() == IrdaApp::EditElement::Remote) {
@ -88,6 +88,9 @@ bool IrdaAppSceneEditDelete::on_event(IrdaApp* app, IrdaAppEvent* event) {
} }
break; break;
} }
default:
break;
}
} }
return consumed; return consumed;

View File

@ -1,9 +1,11 @@
#include "../irda_app.h" #include <gui/modules/dialog_ex.h>
#include <file_worker_cpp.h> #include <file_worker_cpp.h>
#include "irda.h"
#include <memory> #include <memory>
#include <dolphin/dolphin.h> #include <dolphin/dolphin.h>
#include "../irda_app.h"
#include "irda.h"
static void dialog_result_callback(DialogExResult result, void* context) { static void dialog_result_callback(DialogExResult result, void* context) {
auto app = static_cast<IrdaApp*>(context); auto app = static_cast<IrdaApp*>(context);
IrdaAppEvent event; IrdaAppEvent event;
@ -21,6 +23,11 @@ void IrdaAppSceneLearnSuccess::on_enter(IrdaApp* app) {
DOLPHIN_DEED(DolphinDeedIrLearnSuccess); DOLPHIN_DEED(DolphinDeedIrLearnSuccess);
app->notify_green_on(); 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(); auto signal = app->get_received_signal();
if(!signal.is_raw()) { 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_icon(dialog_ex, 0, 1, &I_DolphinReadingSuccess_59x63);
dialog_ex_set_result_callback(dialog_ex, dialog_result_callback); dialog_ex_set_result_callback(dialog_ex, dialog_result_callback);
dialog_ex_set_context(dialog_ex, app); dialog_ex_set_context(dialog_ex, app);
dialog_ex_enable_extended_events(dialog_ex);
view_manager->switch_to(IrdaAppViewManager::ViewType::DialogEx); view_manager->switch_to(IrdaAppViewManager::ViewType::DialogEx);
} }
@ -63,36 +71,65 @@ bool IrdaAppSceneLearnSuccess::on_event(IrdaApp* app, IrdaAppEvent* event) {
bool consumed = false; bool consumed = false;
if(event->type == IrdaAppEvent::Type::Tick) { if(event->type == IrdaAppEvent::Type::Tick) {
/* Send event every tick to suppress any switching off green light */ /* 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) { if(event->type == IrdaAppEvent::Type::DialogExSelected) {
switch(event->payload.dialog_ex_result) { switch(event->payload.dialog_ex_result) {
case DialogExResultLeft: 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; break;
case DialogExResultCenter: {
app->notify_sent_just_learnt();
auto signal = app->get_received_signal();
signal.transmit();
break;
}
case DialogExResultRight: { case DialogExResultRight: {
consumed = true;
FileWorkerCpp file_worker; FileWorkerCpp file_worker;
if(file_worker.check_errors()) { if(!button_pressed) {
app->switch_to_next_scene(IrdaApp::Scene::LearnEnterName); if(file_worker.check_errors()) {
} else { app->switch_to_next_scene(IrdaApp::Scene::LearnEnterName);
app->switch_to_previous_scene(); } else {
app->switch_to_previous_scene();
}
} }
break; 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: default:
break; break;
} }
} }
if(event->type == IrdaAppEvent::Type::Back) { 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; consumed = true;
} }
@ -104,4 +141,6 @@ void IrdaAppSceneLearnSuccess::on_exit(IrdaApp* app) {
DialogEx* dialog_ex = view_manager->get_dialog_ex(); DialogEx* dialog_ex = view_manager->get_dialog_ex();
dialog_ex_reset(dialog_ex); dialog_ex_reset(dialog_ex);
app->notify_green_off(); 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);
} }

View File

@ -29,11 +29,6 @@ static void button_menu_callback(void* context, int32_t index, InputType type) {
app->get_view_manager()->send_event(&event); 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) { void IrdaAppSceneRemote::on_enter(IrdaApp* app) {
IrdaAppViewManager* view_manager = app->get_view_manager(); IrdaAppViewManager* view_manager = app->get_view_manager();
ButtonMenu* button_menu = view_manager->get_button_menu(); 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( irda_worker_tx_set_get_signal_callback(
app->get_irda_worker(), irda_worker_tx_get_signal_steady_callback, app); app->get_irda_worker(), irda_worker_tx_get_signal_steady_callback, app);
irda_worker_tx_set_signal_sent_callback( 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(); buttons_names = remote_manager->get_button_list();
i = 0; i = 0;

View File

@ -320,6 +320,7 @@ void irda_worker_rx_enable_blink_on_receiving(IrdaWorker* instance, bool enable)
void irda_worker_tx_start(IrdaWorker* instance) { void irda_worker_tx_start(IrdaWorker* instance) {
furi_assert(instance); furi_assert(instance);
furi_assert(instance->state == IrdaWorkerStateIdle); 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 // size have to be greater than api hal irda async tx buffer size
xStreamBufferSetTriggerLevel(instance->stream, sizeof(IrdaWorkerTiming)); xStreamBufferSetTriggerLevel(instance->stream, sizeof(IrdaWorkerTiming));