[FL-1250, FL-1252, FL-1323, FL-1324] New IRDA Application (part 1) (#497)

* Add new IrdaApp (half ready), add ButtonMenu

* Fix NEC's extension

* clang-format

* Fix leak

* Add submenu optional header

* IRDA: add Edit button

* clang-format

* IrdaApp: Fix scene flow

* Add IRDA NEC extended protocol

* IRDA: Add address/command length

Co-authored-by: SG <who.just.the.doctor@gmail.com>
This commit is contained in:
Albert Kharisov
2021-06-02 18:16:05 +03:00
committed by GitHub
parent d040515f84
commit 31c31db479
62 changed files with 2568 additions and 375 deletions

View File

@@ -0,0 +1,26 @@
#pragma once
#include <stdint.h>
#include <irda.h>
#include <gui/modules/dialog_ex.h>
class IrdaAppEvent {
public:
enum class Type : uint8_t {
Tick,
Back,
MenuSelected,
DialogExSelected,
NextScene,
IrdaMessageReceived,
TextEditDone,
PopupTimer,
};
union {
int32_t menu_index;
DialogExResult dialog_ex_result;
} payload;
Type type;
};

View File

@@ -0,0 +1,46 @@
#include "irda-app.hpp"
#include "irda.h"
#include <api-hal-irda.h>
void IrdaAppSignalReceiver::irda_rx_callback(void* ctx, bool level, uint32_t duration) {
IrdaAppEvent event;
const IrdaMessage* irda_message;
IrdaAppSignalReceiver* this_ = static_cast<IrdaAppSignalReceiver*>(ctx);
irda_message = irda_decode(this_->decoder, level, duration);
if(irda_message) {
this_->capture_stop();
this_->message = *irda_message;
event.type = IrdaAppEvent::Type::IrdaMessageReceived;
osStatus_t result = osMessageQueuePut(this_->event_queue, &event, 0, 0);
furi_check(result == osOK);
}
}
IrdaAppSignalReceiver::IrdaAppSignalReceiver(void)
: decoder(irda_alloc_decoder()) {
}
IrdaAppSignalReceiver::~IrdaAppSignalReceiver() {
api_hal_irda_rx_irq_deinit();
irda_free_decoder(decoder);
}
void IrdaAppSignalReceiver::capture_once_start(osMessageQueueId_t queue) {
event_queue = queue;
irda_reset_decoder(decoder);
api_hal_irda_rx_irq_init();
api_hal_irda_rx_irq_set_callback(IrdaAppSignalReceiver::irda_rx_callback, this);
}
void IrdaAppSignalReceiver::capture_stop(void) {
api_hal_irda_rx_irq_deinit();
}
IrdaMessage* IrdaAppSignalReceiver::get_last_message(void) {
return &message;
}
void IrdaAppSignalReceiver::send_message(const IrdaMessage* message) {
irda_send(message, 1);
}

View File

@@ -0,0 +1,19 @@
#include <furi.h>
#include <irda.h>
class IrdaAppSignalReceiver {
public:
IrdaAppSignalReceiver(void);
~IrdaAppSignalReceiver(void);
void capture_once_start(osMessageQueueId_t event_queue);
void capture_stop(void);
IrdaMessage* get_last_message(void);
void send_message(const IrdaMessage* message);
private:
osMessageQueueId_t event_queue;
static void irda_rx_callback(void* ctx, bool level, uint32_t duration);
IrdaHandler* decoder;
IrdaMessage message;
};

View File

@@ -0,0 +1,130 @@
#include "irda-app-remote-manager.hpp"
#include "furi.h"
#include <string>
#include <utility>
IrdaAppRemoteManager::IrdaAppRemoteManager() {
// Read from api-hal-storage, and fill remotes
}
static const std::string default_remote_name = "remote";
void IrdaAppRemoteManager::add_button(const char* button_name, const IrdaMessage* message) {
remotes[current_remote_index].buttons.emplace_back(button_name, message);
}
void IrdaAppRemoteManager::add_remote_with_button(
const char* button_name,
const IrdaMessage* message) {
bool found = true;
int i = 0;
// find first free common name for remote
do {
found = false;
++i;
for(const auto& it : remotes) {
if(it.name == (default_remote_name + std::to_string(i))) {
found = true;
break;
}
}
} while(found);
remotes.emplace_back(default_remote_name + std::to_string(i));
current_remote_index = remotes.size() - 1;
add_button(button_name, message);
}
IrdaAppRemote::IrdaAppRemote(std::string name)
: name(name) {
}
std::vector<std::string> IrdaAppRemoteManager::get_button_list(void) const {
std::vector<std::string> name_vector;
auto remote = remotes[current_remote_index];
name_vector.reserve(remote.buttons.size());
for(const auto& it : remote.buttons) {
name_vector.emplace_back(it.name);
}
// copy elision
return name_vector;
}
std::vector<std::string> IrdaAppRemoteManager::get_remote_list() const {
std::vector<std::string> name_vector;
name_vector.reserve(remotes.size());
for(const auto& it : remotes) {
name_vector.push_back(it.name);
}
// copy elision
return name_vector;
}
size_t IrdaAppRemoteManager::get_current_remote(void) const {
return current_remote_index;
}
size_t IrdaAppRemoteManager::get_current_button(void) const {
return current_button_index;
}
void IrdaAppRemote::add_button(
size_t remote_index,
const char* button_name,
const IrdaMessage* message) {
buttons.emplace_back(button_name, message);
}
const IrdaMessage* IrdaAppRemoteManager::get_button_data(size_t button_index) const {
furi_check(remotes[current_remote_index].buttons.size() > button_index);
auto& b = remotes[current_remote_index].buttons.at(button_index);
return &b.message;
}
void IrdaAppRemoteManager::set_current_remote(size_t index) {
furi_check(index < remotes.size());
current_remote_index = index;
}
void IrdaAppRemoteManager::set_current_button(size_t index) {
furi_check(current_remote_index < remotes.size());
furi_check(index < remotes[current_remote_index].buttons.size());
current_button_index = index;
}
void IrdaAppRemoteManager::delete_current_remote() {
remotes.erase(remotes.begin() + current_remote_index);
current_remote_index = 0;
}
void IrdaAppRemoteManager::delete_current_button() {
auto& buttons = remotes[current_remote_index].buttons;
buttons.erase(buttons.begin() + current_button_index);
current_button_index = 0;
}
std::string IrdaAppRemoteManager::get_current_button_name() {
auto buttons = remotes[current_remote_index].buttons;
return buttons[current_button_index].name;
}
std::string IrdaAppRemoteManager::get_current_remote_name() {
return remotes[current_remote_index].name;
}
void IrdaAppRemoteManager::rename_remote(const char* str) {
remotes[current_remote_index].name = str;
}
void IrdaAppRemoteManager::rename_button(const char* str) {
remotes[current_remote_index].buttons[current_button_index].name = str;
}
size_t IrdaAppRemoteManager::get_current_remote_buttons_number() {
return remotes[current_remote_index].buttons.size();
}

View File

@@ -0,0 +1,53 @@
#pragma once
#include <stdint.h>
#include <string>
#include <list>
#include <vector>
#include <irda.h>
class IrdaAppRemoteButton {
friend class IrdaAppRemoteManager;
std::string name;
IrdaMessage message;
public:
IrdaAppRemoteButton(const char* name, const IrdaMessage* message)
: name(name), message (*message) {}
~IrdaAppRemoteButton() {}
};
class IrdaAppRemote {
friend class IrdaAppRemoteManager;
std::vector<IrdaAppRemoteButton> buttons;
std::string name;
bool add(const IrdaMessage*);
void add_button(size_t remote_index, const char* button_name, const IrdaMessage* message);
public:
IrdaAppRemote(std::string name);
};
class IrdaAppRemoteManager {
size_t current_remote_index;
size_t current_button_index;
std::vector<IrdaAppRemote> remotes;
public:
std::vector<std::string> get_remote_list() const;
std::vector<std::string> get_button_list() const;
void add_remote_with_button(const char* button_name, const IrdaMessage* message);
void add_button(const char* button_name, const IrdaMessage* message);
size_t get_current_remote(void) const;
size_t get_current_button(void) const;
const IrdaMessage* get_button_data(size_t button_index) const;
void set_current_remote(size_t index);
void set_current_button(size_t index);
void rename_button(const char* str);
void rename_remote(const char* str);
std::string get_current_button_name();
std::string get_current_remote_name();
size_t get_current_remote_buttons_number();
void delete_current_button();
void delete_current_remote();
IrdaAppRemoteManager();
~IrdaAppRemoteManager() {};
};

View File

@@ -0,0 +1,110 @@
#include "furi.h"
#include "gui/modules/button_menu.h"
#include "gui/modules/dialog_ex.h"
#include "gui/modules/text_input.h"
#include "irda-app.hpp"
#include <callback-connector.h>
IrdaAppViewManager::IrdaAppViewManager() {
event_queue = osMessageQueueNew(10, sizeof(IrdaAppEvent), NULL);
view_dispatcher = view_dispatcher_alloc();
auto callback = cbc::obtain_connector(this, &IrdaAppViewManager::previous_view_callback);
gui = static_cast<Gui*>(furi_record_open("gui"));
view_dispatcher_attach_to_gui(view_dispatcher, gui, ViewDispatcherTypeFullscreen);
button_menu = button_menu_alloc();
submenu = submenu_alloc();
popup = popup_alloc();
dialog_ex = dialog_ex_alloc();
text_input = text_input_alloc();
add_view(ViewType::ButtonMenu, button_menu_get_view(button_menu));
add_view(ViewType::Submenu, submenu_get_view(submenu));
add_view(ViewType::Popup, popup_get_view(popup));
add_view(ViewType::DialogEx, dialog_ex_get_view(dialog_ex));
add_view(ViewType::TextInput, text_input_get_view(text_input));
view_set_previous_callback(button_menu_get_view(button_menu), callback);
view_set_previous_callback(submenu_get_view(submenu), callback);
view_set_previous_callback(popup_get_view(popup), callback);
view_set_previous_callback(dialog_ex_get_view(dialog_ex), callback);
view_set_previous_callback(text_input_get_view(text_input), callback);
}
IrdaAppViewManager::~IrdaAppViewManager() {
view_dispatcher_remove_view(
view_dispatcher, static_cast<uint32_t>(IrdaAppViewManager::ViewType::ButtonMenu));
view_dispatcher_remove_view(
view_dispatcher, static_cast<uint32_t>(IrdaAppViewManager::ViewType::TextInput));
view_dispatcher_remove_view(
view_dispatcher, static_cast<uint32_t>(IrdaAppViewManager::ViewType::DialogEx));
view_dispatcher_remove_view(
view_dispatcher, static_cast<uint32_t>(IrdaAppViewManager::ViewType::Submenu));
view_dispatcher_remove_view(
view_dispatcher, static_cast<uint32_t>(IrdaAppViewManager::ViewType::Popup));
submenu_free(submenu);
popup_free(popup);
button_menu_free(button_menu);
dialog_ex_free(dialog_ex);
text_input_free(text_input);
view_dispatcher_free(view_dispatcher);
furi_record_close("gui");
osMessageQueueDelete(event_queue);
}
void IrdaAppViewManager::switch_to(ViewType type) {
view_dispatcher_switch_to_view(view_dispatcher, static_cast<uint32_t>(type));
}
TextInput* IrdaAppViewManager::get_text_input() {
return text_input;
}
DialogEx* IrdaAppViewManager::get_dialog_ex() {
return dialog_ex;
}
Submenu* IrdaAppViewManager::get_submenu() {
return submenu;
}
Popup* IrdaAppViewManager::get_popup() {
return popup;
}
ButtonMenu* IrdaAppViewManager::get_button_menu() {
return button_menu;
}
osMessageQueueId_t IrdaAppViewManager::get_event_queue() {
return event_queue;
}
void IrdaAppViewManager::receive_event(IrdaAppEvent* event) {
if(osMessageQueueGet(event_queue, event, NULL, 100) != osOK) {
event->type = IrdaAppEvent::Type::Tick;
}
}
void IrdaAppViewManager::send_event(IrdaAppEvent* event) {
osStatus_t result = osMessageQueuePut(event_queue, event, 0, 0);
furi_check(result == osOK);
}
uint32_t IrdaAppViewManager::previous_view_callback(void* context) {
if(event_queue != NULL) {
IrdaAppEvent event;
event.type = IrdaAppEvent::Type::Back;
send_event(&event);
}
return VIEW_IGNORE;
}
void IrdaAppViewManager::add_view(ViewType view_type, View* view) {
view_dispatcher_add_view(view_dispatcher, static_cast<uint32_t>(view_type), view);
}

View File

@@ -0,0 +1,52 @@
#pragma once
#include "gui/modules/button_menu.h"
#include "gui/modules/text_input.h"
#include <furi.h>
#include <gui/view_dispatcher.h>
#include <gui/modules/dialog_ex.h>
#include <gui/modules/submenu.h>
#include <gui/modules/popup.h>
#include "irda-app.hpp"
class IrdaAppViewManager {
public:
enum class ViewType : uint8_t {
DialogEx,
TextInput,
Submenu,
ButtonMenu,
Popup,
};
IrdaAppViewManager();
~IrdaAppViewManager();
void switch_to(ViewType type);
void receive_event(IrdaAppEvent* event);
void send_event(IrdaAppEvent* event);
DialogEx* get_dialog_ex();
Submenu* get_submenu();
Popup* get_popup();
TextInput* get_text_input();
ButtonMenu* get_button_menu();
osMessageQueueId_t get_event_queue();
uint32_t previous_view_callback(void* context);
private:
ViewDispatcher* view_dispatcher;
Gui* gui;
TextInput* text_input;
DialogEx* dialog_ex;
Submenu* submenu;
Popup* popup;
ButtonMenu* button_menu;
osMessageQueueId_t event_queue;
void add_view(ViewType view_type, View* view);
};

View File

@@ -0,0 +1,156 @@
#include "irda-app.hpp"
#include <furi.h>
#include <gui/gui.h>
#include <input/input.h>
#include <stdarg.h>
#include <stdio.h>
#include <callback-connector.h>
void IrdaApp::run(void) {
IrdaAppEvent event;
bool consumed;
bool exit = false;
scenes[current_scene]->on_enter(this);
while(!exit) {
view_manager.receive_event(&event);
consumed = scenes[current_scene]->on_event(this, &event);
if(!consumed) {
if(event.type == IrdaAppEvent::Type::Back) {
exit = switch_to_previous_scene();
}
}
};
scenes[current_scene]->on_exit(this);
};
IrdaAppViewManager* IrdaApp::get_view_manager() {
return &view_manager;
}
void IrdaApp::set_learn_new_remote(bool value) {
learn_new_remote = value;
}
bool IrdaApp::get_learn_new_remote() {
return learn_new_remote;
}
void IrdaApp::switch_to_next_scene(Scene next_scene) {
previous_scenes_list.push_front(current_scene);
switch_to_next_scene_without_saving(next_scene);
}
void IrdaApp::switch_to_next_scene_without_saving(Scene next_scene) {
if(next_scene != Scene::Exit) {
scenes[current_scene]->on_exit(this);
current_scene = next_scene;
scenes[current_scene]->on_enter(this);
}
}
void IrdaApp::search_and_switch_to_previous_scene(const std::initializer_list<Scene>& scenes_list) {
Scene previous_scene = Scene::Start;
bool scene_found = false;
while(!scene_found) {
previous_scene = get_previous_scene();
for(Scene element : scenes_list) {
if(previous_scene == element) {
scene_found = true;
break;
}
}
}
scenes[current_scene]->on_exit(this);
current_scene = previous_scene;
scenes[current_scene]->on_enter(this);
}
bool IrdaApp::switch_to_previous_scene(uint8_t count) {
Scene previous_scene = Scene::Start;
for(uint8_t i = 0; i < count; i++) previous_scene = get_previous_scene();
if(previous_scene == Scene::Exit) return true;
scenes[current_scene]->on_exit(this);
current_scene = previous_scene;
scenes[current_scene]->on_enter(this);
return false;
}
IrdaApp::Scene IrdaApp::get_previous_scene() {
Scene scene = Scene::Exit;
if(!previous_scenes_list.empty()) {
scene = previous_scenes_list.front();
previous_scenes_list.pop_front();
}
return scene;
}
IrdaAppRemoteManager* IrdaApp::get_remote_manager() {
return &remote_manager;
}
IrdaAppSignalReceiver* IrdaApp::get_receiver() {
return &receiver;
}
void IrdaApp::set_text_store(uint8_t index, const char* text...) {
furi_check(index < text_store_max);
va_list args;
va_start(args, text);
vsnprintf(text_store[index], text_store_size, text, args);
va_end(args);
}
char* IrdaApp::get_text_store(uint8_t index) {
furi_check(index < text_store_max);
return text_store[index];
}
uint8_t IrdaApp::get_text_store_size() {
return text_store_size;
}
void IrdaApp::text_input_callback(void* context, char* text) {
IrdaApp* app = static_cast<IrdaApp*>(context);
IrdaAppEvent event;
event.type = IrdaAppEvent::Type::TextEditDone;
app->get_view_manager()->send_event(&event);
}
void IrdaApp::popup_callback(void* context) {
IrdaApp* app = static_cast<IrdaApp*>(context);
IrdaAppEvent event;
event.type = IrdaAppEvent::Type::PopupTimer;
app->get_view_manager()->send_event(&event);
}
void IrdaApp::set_edit_element(IrdaApp::EditElement value) {
element = value;
}
IrdaApp::EditElement IrdaApp::get_edit_element(void) {
return element;
}
void IrdaApp::set_edit_action(IrdaApp::EditAction value) {
action = value;
}
IrdaApp::EditAction IrdaApp::get_edit_action(void) {
return action;
}

View File

@@ -0,0 +1,108 @@
#pragma once
#include <map>
#include <irda.h>
#include <furi.h>
#include "irda-app-event.hpp"
#include "scene/irda-app-scene.hpp"
#include "irda-app-view-manager.hpp"
#include "irda-app-remote-manager.hpp"
#include "irda-app-receiver.hpp"
#include <forward_list>
#include <stdint.h>
class IrdaApp {
public:
enum class EditElement : uint8_t {
Button,
Remote,
};
enum class EditAction : uint8_t {
Rename,
Delete,
};
enum class Scene : uint8_t {
Exit,
Start,
Universal,
UniversalTV,
UniversalAudio,
UniversalAirConditioner,
Learn,
LearnSuccess,
LearnEnterName,
LearnDone,
LearnDoneAfter,
Remote,
RemoteList,
Edit,
EditKeySelect,
EditRename,
EditDelete,
EditRenameDone,
EditDeleteDone,
};
void run(void);
void switch_to_next_scene(Scene index);
void switch_to_next_scene_without_saving(Scene index);
bool switch_to_previous_scene(uint8_t count = 1);
Scene get_previous_scene();
IrdaAppViewManager* get_view_manager();
IrdaAppSignalReceiver* get_receiver();
void set_text_store(uint8_t index, const char* text...);
char* get_text_store(uint8_t index);
uint8_t get_text_store_size();
IrdaAppRemoteManager* get_remote_manager();
void search_and_switch_to_previous_scene(const std::initializer_list<Scene>& scenes_list);
void set_edit_element(EditElement value);
EditElement get_edit_element(void);
void set_edit_action(EditAction value);
EditAction get_edit_action(void);
bool get_learn_new_remote();
void set_learn_new_remote(bool value);
static void text_input_callback(void* context, char* text);
static void popup_callback(void* context);
IrdaApp() {}
~IrdaApp() {
for (auto &it : scenes)
delete it.second;
}
private:
static const uint8_t text_store_size = 128;
static const uint8_t text_store_max = 2;
char text_store[text_store_max][text_store_size + 1];
bool learn_new_remote;
EditElement element;
EditAction action;
IrdaAppSignalReceiver receiver;
IrdaAppViewManager view_manager;
IrdaAppRemoteManager remote_manager;
std::forward_list<Scene> previous_scenes_list;
Scene current_scene = Scene::Start;
std::map<Scene, IrdaAppScene*> scenes = {
{Scene::Start, new IrdaAppSceneStart()},
{Scene::Universal, new IrdaAppSceneUniversal()},
{Scene::Learn, new IrdaAppSceneLearn()},
{Scene::LearnSuccess, new IrdaAppSceneLearnSuccess()},
{Scene::LearnEnterName, new IrdaAppSceneLearnEnterName()},
{Scene::LearnDone, new IrdaAppSceneLearnDone()},
{Scene::LearnDoneAfter, new IrdaAppSceneLearnDoneAfter()},
{Scene::Remote, new IrdaAppSceneRemote()},
{Scene::RemoteList, new IrdaAppSceneRemoteList()},
{Scene::Edit, new IrdaAppSceneEdit()},
{Scene::EditKeySelect, new IrdaAppSceneEditKeySelect()},
{Scene::EditRename, new IrdaAppSceneEditRename()},
{Scene::EditDelete, new IrdaAppSceneEditDelete()},
{Scene::EditRenameDone, new IrdaAppSceneEditRenameDone()},
{Scene::EditDeleteDone, new IrdaAppSceneEditDeleteDone()},
};
};

View File

@@ -1,146 +0,0 @@
#include "irda-decoder-nec.h"
#include "string.h"
const uint32_t PREAMBULA_HIGH_MIN = 9000 - 900;
const uint32_t PREAMBULA_HIGH_MAX = 9000 + 900;
const uint32_t PREAMBULA_LOW_MIN = 4500 - 450;
const uint32_t PREAMBULA_LOW_MAX = 4500 + 450;
const uint32_t PREAMBULA_RETRY_LOW_MIN = 2500 - 350;
const uint32_t PREAMBULA_RETRY_LOW_MAX = 2500 + 250;
const uint32_t BIT_HIGH_MIN = 560 - 100;
const uint32_t BIT_HIGH_MAX = 560 + 100;
const uint32_t BIT_LOW_ONE_MIN = 1690 - 200;
const uint32_t BIT_LOW_ONE_MAX = 1690 + 200;
const uint32_t BIT_LOW_ZERO_MIN = 560 - 100;
const uint32_t BIT_LOW_ZERO_MAX = 560 + 100;
#define SET_STATE(_state) \
{ decoder->state = _state; }
#define TIME_FIT(_prefix) ((time > _prefix##_MIN) && (time < _prefix##_MAX))
#ifndef MIN
#define MIN(a, b) ((a) < (b) ? (a) : (b))
#endif
bool save_decoder_nec_data(IrDANecDecoder* decoder, IrDADecoderOutputData* out) {
bool result = false;
if((decoder->data.simple.cmd + decoder->data.simple.cmd_inverse) == 0xFF) {
if(out->data_length < sizeof(IrDANecDataType)) {
out->flags |= IRDA_TOO_SHORT_BUFFER;
}
memcpy(out->data, &decoder->data.data, MIN(sizeof(IrDANecDataType), out->data_length));
result = true;
} else {
reset_decoder_nec(decoder);
}
return result;
}
bool process_decoder_nec(
IrDANecDecoder* decoder,
bool polarity,
uint32_t time,
IrDADecoderOutputData* out) {
bool error = true;
bool result = false;
switch(decoder->state) {
case(WAIT_PREAMBULA_HIGH):
if(polarity) {
if(TIME_FIT(PREAMBULA_HIGH)) {
SET_STATE(WAIT_PREAMBULA_LOW);
}
}
// any values before preambula start is correct
error = false;
break;
case(WAIT_PREAMBULA_LOW):
if(!polarity) {
if(TIME_FIT(PREAMBULA_LOW)) {
// new data, reset storage
reset_decoder_nec(decoder);
SET_STATE(WAIT_BIT_HIGH);
error = false;
} else if(TIME_FIT(PREAMBULA_RETRY_LOW)) {
// wait for data repeat command
SET_STATE(WAIT_RETRY_HIGH);
error = false;
}
}
break;
case(WAIT_RETRY_HIGH):
if(polarity) {
if(TIME_FIT(BIT_HIGH)) {
SET_STATE(WAIT_PREAMBULA_HIGH);
// repeat event
result = save_decoder_nec_data(decoder, out);
out->flags |= IRDA_REPEAT;
error = false;
}
}
break;
case(WAIT_BIT_HIGH):
if(polarity) {
if(TIME_FIT(BIT_HIGH)) {
SET_STATE(WAIT_BIT_LOW);
error = false;
}
}
break;
case(WAIT_BIT_STOP_HIGH):
if(polarity) {
if(TIME_FIT(BIT_HIGH)) {
SET_STATE(WAIT_PREAMBULA_HIGH);
// message end event
result = save_decoder_nec_data(decoder, out);
error = false;
}
}
break;
case(WAIT_BIT_LOW):
if(!polarity) {
int8_t bit = -1;
if(TIME_FIT(BIT_LOW_ZERO)) {
SET_STATE(WAIT_BIT_HIGH);
bit = 0;
error = false;
} else if(TIME_FIT(BIT_LOW_ONE)) {
SET_STATE(WAIT_BIT_HIGH);
bit = 1;
error = false;
}
if(bit != -1) {
decoder->data.data |= (bit << decoder->current_data_index);
decoder->current_data_index++;
if(decoder->current_data_index > 31) {
decoder->current_data_index = 0;
SET_STATE(WAIT_BIT_STOP_HIGH);
}
}
}
break;
}
if(error) reset_decoder_nec(decoder);
return result;
}
void reset_decoder_nec(IrDANecDecoder* decoder) {
decoder->state = WAIT_PREAMBULA_HIGH;
decoder->data.data = 0;
decoder->current_data_index = 0;
}

View File

@@ -1,39 +0,0 @@
#pragma once
#include <stdint.h>
#include <stdbool.h>
#include "irda-decoder-types.h"
typedef enum {
WAIT_PREAMBULA_HIGH,
WAIT_PREAMBULA_LOW,
WAIT_RETRY_HIGH,
WAIT_BIT_HIGH,
WAIT_BIT_LOW,
WAIT_BIT_STOP_HIGH,
} IrDANecDecoderState;
typedef struct {
uint8_t addr2;
uint8_t addr1;
uint8_t cmd_inverse;
uint8_t cmd;
} IrDANecData;
typedef uint32_t IrDANecDataType;
typedef struct {
union {
IrDANecData simple;
IrDANecDataType data;
} data;
uint8_t current_data_index;
IrDANecDecoderState state;
} IrDANecDecoder;
bool process_decoder_nec(
IrDANecDecoder* decoder,
bool polarity,
uint32_t time,
IrDADecoderOutputData* out);
void reset_decoder_nec(IrDANecDecoder* decoder);

View File

@@ -1,12 +0,0 @@
#pragma once
#include <stdint.h>
typedef enum { IRDA_UNKNOWN, IRDA_NEC, IRDA_SAMSUNG } IrDAProtocolType;
typedef enum { IRDA_REPEAT = (1 << 0), IRDA_TOO_SHORT_BUFFER = (1 << 1) } IrDAProtocolFlags;
typedef struct {
IrDAProtocolType protocol;
uint8_t flags;
uint8_t* data; /** < ponter to output data, filled by app */
uint32_t data_length; /** < output data length, filled by app */
} IrDADecoderOutputData;

View File

@@ -1,41 +0,0 @@
#include "irda-decoder.h"
IrDADecoder* alloc_decoder(void) {
IrDADecoder* decoder = malloc(sizeof(IrDADecoder));
// init decoders
reset_decoder_nec(&decoder->nec);
return decoder;
}
void free_decoder(IrDADecoder* decoder) {
free(decoder);
}
bool process_decoder(
IrDADecoder* decoder,
bool start_polarity,
uint32_t* timings,
uint32_t timings_length,
IrDADecoderOutputData* out) {
bool result = false;
// zero result
memset(out->data, 0, out->data_length);
out->protocol = IRDA_UNKNOWN;
out->flags = 0;
// process data
for(uint32_t timings_index = 0; timings_index < timings_length; timings_index++) {
if(process_decoder_nec(&decoder->nec, start_polarity, timings[timings_index], out)) {
out->protocol = IRDA_NEC;
result = true;
break;
}
start_polarity = !start_polarity;
}
return result;
}

View File

@@ -1,17 +0,0 @@
#pragma once
#include <furi.h>
#include "irda-decoder-nec.h"
#include "irda-decoder-types.h"
typedef struct {
IrDANecDecoder nec;
} IrDADecoder;
IrDADecoder* alloc_decoder(void);
void free_decoder(IrDADecoder* decoder);
bool process_decoder(
IrDADecoder* decoder,
bool start_polarity,
uint32_t* timings,
uint32_t timings_length,
IrDADecoderOutputData* out);

View File

@@ -0,0 +1,9 @@
#include "irda-app.hpp"
extern "C" int32_t irda(void* p) {
IrdaApp* app = new IrdaApp();
app->run();
delete app;
return 0;
}

View File

@@ -290,7 +290,7 @@ void irda_rx_callback(void* ctx, bool level, uint32_t duration) {
}
}
int32_t irda(void* p) {
int32_t irda2(void* p) {
osMessageQueueId_t event_queue = osMessageQueueNew(32, sizeof(AppEvent), NULL);
State _state;

View File

@@ -1,19 +0,0 @@
#pragma once
// our tx pin is TIM2_CH4
extern TIM_HandleTypeDef TIM_A;
#define RC5_CARRIER_FREQUENCY 36000
#define RC5_DUTY_CYCLE 0.33
#define RC6_CARRIER_FREQUENCY 36000
#define RC6_DUTY_CYCLE 0.33
#define SAMSUNG_CARRIER_FREQUENCY 37900
#define SAMSUNG_DUTY_CYCLE 0.33
#define NEC_CARRIER_FREQUENCY 38000
#define NEC_DUTY_CYCLE 0.33
#define SIRC_CARRIER_FREQUENCY 40000
#define SIRC_DUTY_CYCLE 0.5

View File

@@ -0,0 +1,35 @@
#include "../irda-app.hpp"
void IrdaAppSceneEditDeleteDone::on_enter(IrdaApp* app) {
IrdaAppViewManager* view_manager = app->get_view_manager();
Popup* popup = view_manager->get_popup();
popup_set_icon(popup, 0, 2, I_DolphinMafia_115x62);
popup_set_text(popup, "Deleted", 83, 19, AlignLeft, AlignBottom);
popup_set_callback(popup, IrdaApp::popup_callback);
popup_set_context(popup, app);
popup_set_timeout(popup, 1500);
popup_enable_timeout(popup);
view_manager->switch_to(IrdaAppViewManager::ViewType::Popup);
}
bool IrdaAppSceneEditDeleteDone::on_event(IrdaApp* app, IrdaAppEvent* event) {
bool consumed = false;
if(event->type == IrdaAppEvent::Type::PopupTimer) {
if(app->get_edit_element() == IrdaApp::EditElement::Remote) {
app->search_and_switch_to_previous_scene(
{IrdaApp::Scene::Start, IrdaApp::Scene::RemoteList});
} else {
app->search_and_switch_to_previous_scene({IrdaApp::Scene::Remote});
}
consumed = true;
}
return consumed;
}
void IrdaAppSceneEditDeleteDone::on_exit(IrdaApp* app) {
}

View File

@@ -0,0 +1,81 @@
#include "../irda-app.hpp"
#include "irda.h"
#include <string>
#include <stdio.h>
static void dialog_result_callback(DialogExResult result, void* context) {
auto app = static_cast<IrdaApp*>(context);
IrdaAppEvent event;
event.type = IrdaAppEvent::Type::DialogExSelected;
event.payload.dialog_ex_result = result;
app->get_view_manager()->send_event(&event);
}
void IrdaAppSceneEditDelete::on_enter(IrdaApp* app) {
IrdaAppViewManager* view_manager = app->get_view_manager();
DialogEx* dialog_ex = view_manager->get_dialog_ex();
auto remote_manager = app->get_remote_manager();
if(app->get_edit_element() == IrdaApp::EditElement::Button) {
auto message = remote_manager->get_button_data(remote_manager->get_current_button());
dialog_ex_set_header(dialog_ex, "Delete button?", 64, 6, AlignCenter, AlignCenter);
app->set_text_store(
0,
"%s\n%s\nA=0x%0*lX C=0x%0*lX",
remote_manager->get_current_button_name().c_str(),
irda_get_protocol_name(message->protocol),
irda_get_protocol_address_length(message->protocol),
message->address,
irda_get_protocol_command_length(message->protocol),
message->command);
} else {
dialog_ex_set_header(dialog_ex, "Delete remote?", 64, 6, AlignCenter, AlignCenter);
app->set_text_store(
0,
"%s\n with %lu buttons",
remote_manager->get_current_remote_name().c_str(),
remote_manager->get_current_remote_buttons_number());
}
dialog_ex_set_text(dialog_ex, app->get_text_store(0), 64, 32, AlignCenter, AlignCenter);
dialog_ex_set_icon(dialog_ex, -1, -1, I_ButtonCenter_7x7);
dialog_ex_set_left_button_text(dialog_ex, "Back");
dialog_ex_set_right_button_text(dialog_ex, "Delete");
dialog_ex_set_result_callback(dialog_ex, dialog_result_callback);
dialog_ex_set_context(dialog_ex, app);
view_manager->switch_to(IrdaAppViewManager::ViewType::DialogEx);
}
bool IrdaAppSceneEditDelete::on_event(IrdaApp* app, IrdaAppEvent* event) {
bool consumed = false;
if(event->type == IrdaAppEvent::Type::DialogExSelected) {
switch(event->payload.dialog_ex_result) {
case DialogExResultLeft:
app->switch_to_previous_scene();
break;
case DialogExResultCenter:
furi_assert(0);
break;
case DialogExResultRight:
auto remote_manager = app->get_remote_manager();
if(app->get_edit_element() == IrdaApp::EditElement::Remote) {
remote_manager->delete_current_remote();
} else {
remote_manager->delete_current_button();
}
app->switch_to_next_scene(IrdaApp::Scene::EditDeleteDone);
break;
}
}
return consumed;
}
void IrdaAppSceneEditDelete::on_exit(IrdaApp* app) {
}

View File

@@ -0,0 +1,54 @@
#include "../irda-app.hpp"
#include "gui/modules/submenu.h"
static void submenu_callback(void* context, uint32_t index) {
IrdaApp* app = static_cast<IrdaApp*>(context);
IrdaAppEvent event;
event.type = IrdaAppEvent::Type::MenuSelected;
event.payload.menu_index = index;
app->get_view_manager()->send_event(&event);
}
void IrdaAppSceneEditKeySelect::on_enter(IrdaApp* app) {
IrdaAppViewManager* view_manager = app->get_view_manager();
Submenu* submenu = view_manager->get_submenu();
int i = 0;
const char* header = app->get_edit_action() == IrdaApp::EditAction::Rename ? "Rename key:" :
"Delete key:";
submenu_set_header(submenu, header);
auto remote_manager = app->get_remote_manager();
buttons_names = remote_manager->get_button_list();
for(const auto& it : buttons_names) {
submenu_add_item(submenu, it.c_str(), i++, submenu_callback, app);
}
view_manager->switch_to(IrdaAppViewManager::ViewType::Submenu);
}
bool IrdaAppSceneEditKeySelect::on_event(IrdaApp* app, IrdaAppEvent* event) {
bool consumed = false;
if(event->type == IrdaAppEvent::Type::MenuSelected) {
auto remote_manager = app->get_remote_manager();
remote_manager->set_current_button(event->payload.menu_index);
consumed = true;
if(app->get_edit_action() == IrdaApp::EditAction::Rename) {
app->switch_to_next_scene(IrdaApp::Scene::EditRename);
} else {
app->switch_to_next_scene(IrdaApp::Scene::EditDelete);
}
}
return consumed;
}
void IrdaAppSceneEditKeySelect::on_exit(IrdaApp* app) {
IrdaAppViewManager* view_manager = app->get_view_manager();
Submenu* submenu = view_manager->get_submenu();
submenu_clean(submenu);
}

View File

@@ -0,0 +1,31 @@
#include "../irda-app.hpp"
void IrdaAppSceneEditRenameDone::on_enter(IrdaApp* app) {
IrdaAppViewManager* view_manager = app->get_view_manager();
Popup* popup = view_manager->get_popup();
popup_set_icon(popup, 32, 5, I_DolphinNice_96x59);
popup_set_text(popup, "Saved!", 13, 22, AlignLeft, AlignTop);
popup_set_callback(popup, IrdaApp::popup_callback);
popup_set_context(popup, app);
popup_set_timeout(popup, 1500);
popup_enable_timeout(popup);
view_manager->switch_to(IrdaAppViewManager::ViewType::Popup);
}
bool IrdaAppSceneEditRenameDone::on_event(IrdaApp* app, IrdaAppEvent* event) {
bool consumed = false;
if(event->type == IrdaAppEvent::Type::PopupTimer) {
app->switch_to_next_scene(IrdaApp::Scene::Remote);
consumed = true;
}
return consumed;
}
void IrdaAppSceneEditRenameDone::on_exit(IrdaApp* app) {
}

View File

@@ -0,0 +1,46 @@
#include "../irda-app.hpp"
#include <cstdio>
void IrdaAppSceneEditRename::on_enter(IrdaApp* app) {
IrdaAppViewManager* view_manager = app->get_view_manager();
TextInput* text_input = view_manager->get_text_input();
auto remote_manager = app->get_remote_manager();
if(app->get_edit_element() == IrdaApp::EditElement::Button) {
auto button_name = remote_manager->get_current_button_name();
strncpy(app->get_text_store(0), button_name.c_str(), app->get_text_store_size());
} else {
auto remote_name = remote_manager->get_current_remote_name();
strncpy(app->get_text_store(0), remote_name.c_str(), app->get_text_store_size());
}
text_input_set_header_text(text_input, "Name the key");
text_input_set_result_callback(
text_input,
IrdaApp::text_input_callback,
app,
app->get_text_store(0),
app->get_text_store_size());
view_manager->switch_to(IrdaAppViewManager::ViewType::TextInput);
}
bool IrdaAppSceneEditRename::on_event(IrdaApp* app, IrdaAppEvent* event) {
bool consumed = false;
if(event->type == IrdaAppEvent::Type::TextEditDone) {
auto remote_manager = app->get_remote_manager();
if(app->get_edit_element() == IrdaApp::EditElement::Button) {
remote_manager->rename_button(app->get_text_store(0));
} else {
remote_manager->rename_remote(app->get_text_store(0));
}
app->switch_to_next_scene_without_saving(IrdaApp::Scene::EditRenameDone);
consumed = true;
}
return consumed;
}
void IrdaAppSceneEditRename::on_exit(IrdaApp* app) {
}

View File

@@ -0,0 +1,74 @@
#include "../irda-app.hpp"
typedef enum {
SubmenuIndexAddKey,
SubmenuIndexRenameKey,
SubmenuIndexDeleteKey,
SubmenuIndexRenameRemote,
SubmenuIndexDeleteRemote,
} SubmenuIndex;
static void submenu_callback(void* context, uint32_t index) {
IrdaApp* app = static_cast<IrdaApp*>(context);
IrdaAppEvent event;
event.type = IrdaAppEvent::Type::MenuSelected;
event.payload.menu_index = index;
app->get_view_manager()->send_event(&event);
}
void IrdaAppSceneEdit::on_enter(IrdaApp* app) {
IrdaAppViewManager* view_manager = app->get_view_manager();
Submenu* submenu = view_manager->get_submenu();
submenu_add_item(submenu, "Add key", SubmenuIndexAddKey, submenu_callback, app);
submenu_add_item(submenu, "Rename key", SubmenuIndexRenameKey, submenu_callback, app);
submenu_add_item(submenu, "Delete key", SubmenuIndexDeleteKey, submenu_callback, app);
submenu_add_item(submenu, "Rename remote", SubmenuIndexRenameRemote, submenu_callback, app);
submenu_add_item(submenu, "Delete remote", SubmenuIndexDeleteRemote, submenu_callback, app);
view_manager->switch_to(IrdaAppViewManager::ViewType::Submenu);
}
bool IrdaAppSceneEdit::on_event(IrdaApp* app, IrdaAppEvent* event) {
bool consumed = false;
if(event->type == IrdaAppEvent::Type::MenuSelected) {
switch(event->payload.menu_index) {
case SubmenuIndexAddKey:
app->switch_to_next_scene(IrdaApp::Scene::Learn);
break;
case SubmenuIndexRenameKey:
app->set_edit_action(IrdaApp::EditAction::Rename);
app->set_edit_element(IrdaApp::EditElement::Button);
app->switch_to_next_scene(IrdaApp::Scene::EditKeySelect);
break;
case SubmenuIndexDeleteKey:
app->set_edit_action(IrdaApp::EditAction::Delete);
app->set_edit_element(IrdaApp::EditElement::Button);
app->switch_to_next_scene(IrdaApp::Scene::EditKeySelect);
break;
case SubmenuIndexRenameRemote:
app->set_edit_action(IrdaApp::EditAction::Rename);
app->set_edit_element(IrdaApp::EditElement::Remote);
app->switch_to_next_scene(IrdaApp::Scene::EditRename);
break;
case SubmenuIndexDeleteRemote:
app->set_edit_action(IrdaApp::EditAction::Delete);
app->set_edit_element(IrdaApp::EditElement::Remote);
app->switch_to_next_scene(IrdaApp::Scene::EditDelete);
break;
}
consumed = true;
}
return consumed;
}
void IrdaAppSceneEdit::on_exit(IrdaApp* app) {
IrdaAppViewManager* view_manager = app->get_view_manager();
Submenu* submenu = view_manager->get_submenu();
submenu_clean(submenu);
}

View File

@@ -0,0 +1,34 @@
#include "../irda-app.hpp"
#include <string>
#include <stdio.h>
#include <gui/modules/popup.h>
void IrdaAppSceneLearnDoneAfter::on_enter(IrdaApp* app) {
auto view_manager = app->get_view_manager();
auto popup = view_manager->get_popup();
popup_set_icon(popup, 0, 30, I_IrdaSendShort_128x34);
popup_set_text(
popup, "Get ready!\nPoint flipper at target.", 64, 16, AlignCenter, AlignCenter);
popup_set_callback(popup, IrdaApp::popup_callback);
popup_set_context(popup, app);
popup_set_timeout(popup, 1500);
popup_enable_timeout(popup);
view_manager->switch_to(IrdaAppViewManager::ViewType::Popup);
}
bool IrdaAppSceneLearnDoneAfter::on_event(IrdaApp* app, IrdaAppEvent* event) {
bool consumed = false;
if(event->type == IrdaAppEvent::Type::PopupTimer) {
app->switch_to_next_scene(IrdaApp::Scene::Remote);
consumed = true;
}
return consumed;
}
void IrdaAppSceneLearnDoneAfter::on_exit(IrdaApp* app) {
}

View File

@@ -0,0 +1,42 @@
#include "../irda-app.hpp"
#include <string>
#include <stdio.h>
void IrdaAppSceneLearnDone::on_enter(IrdaApp* app) {
IrdaAppViewManager* view_manager = app->get_view_manager();
Popup* popup = view_manager->get_popup();
popup_set_icon(popup, 32, 5, I_DolphinNice_96x59);
if(app->get_learn_new_remote()) {
popup_set_text(popup, "New remote\ncreated!", 5, 7, AlignLeft, AlignTop);
} else {
popup_set_text(popup, "Saved!", 5, 7, AlignLeft, AlignTop);
}
popup_set_callback(popup, IrdaApp::popup_callback);
popup_set_context(popup, app);
popup_set_timeout(popup, 1500);
popup_enable_timeout(popup);
view_manager->switch_to(IrdaAppViewManager::ViewType::Popup);
}
bool IrdaAppSceneLearnDone::on_event(IrdaApp* app, IrdaAppEvent* event) {
bool consumed = false;
if(event->type == IrdaAppEvent::Type::PopupTimer) {
if(app->get_learn_new_remote()) {
app->switch_to_next_scene(IrdaApp::Scene::LearnDoneAfter);
} else {
app->switch_to_next_scene(IrdaApp::Scene::Remote);
}
consumed = true;
}
return consumed;
}
void IrdaAppSceneLearnDone::on_exit(IrdaApp* app) {
app->set_learn_new_remote(false);
}

View File

@@ -0,0 +1,51 @@
#include "../irda-app.hpp"
#include "gui/modules/text_input.h"
#include <callback-connector.h>
#include <string>
#include <stdio.h>
void IrdaAppSceneLearnEnterName::on_enter(IrdaApp* app) {
IrdaAppViewManager* view_manager = app->get_view_manager();
TextInput* text_input = view_manager->get_text_input();
auto receiver = app->get_receiver();
auto message = receiver->get_last_message();
app->set_text_store(
0,
"%.4s_%0*lX",
irda_get_protocol_name(message->protocol),
irda_get_protocol_command_length(message->protocol),
message->command);
text_input_set_header_text(text_input, "Name the key");
text_input_set_result_callback(
text_input,
IrdaApp::text_input_callback,
app,
app->get_text_store(0),
app->get_text_store_size());
view_manager->switch_to(IrdaAppViewManager::ViewType::TextInput);
}
bool IrdaAppSceneLearnEnterName::on_event(IrdaApp* app, IrdaAppEvent* event) {
bool consumed = false;
if(event->type == IrdaAppEvent::Type::TextEditDone) {
auto remote_manager = app->get_remote_manager();
auto receiver = app->get_receiver();
if(app->get_learn_new_remote()) {
remote_manager->add_remote_with_button(
app->get_text_store(0), receiver->get_last_message());
} else {
remote_manager->add_button(app->get_text_store(0), receiver->get_last_message());
}
app->switch_to_next_scene_without_saving(IrdaApp::Scene::LearnDone);
}
return consumed;
}
void IrdaAppSceneLearnEnterName::on_exit(IrdaApp* app) {
}

View File

@@ -0,0 +1,63 @@
#include "../irda-app.hpp"
#include "irda.h"
#include <string>
#include <stdio.h>
static void dialog_result_callback(DialogExResult result, void* context) {
auto app = static_cast<IrdaApp*>(context);
IrdaAppEvent event;
event.type = IrdaAppEvent::Type::DialogExSelected;
event.payload.dialog_ex_result = result;
app->get_view_manager()->send_event(&event);
}
void IrdaAppSceneLearnSuccess::on_enter(IrdaApp* app) {
IrdaAppViewManager* view_manager = app->get_view_manager();
DialogEx* dialog_ex = view_manager->get_dialog_ex();
auto receiver = app->get_receiver();
auto message = receiver->get_last_message();
app->set_text_store(0, "%s", irda_get_protocol_name(message->protocol));
app->set_text_store(
1,
"A: 0x%0*lX\nC: 0x%0*lX\n",
irda_get_protocol_address_length(message->protocol),
message->address,
irda_get_protocol_command_length(message->protocol),
message->command);
dialog_ex_set_header(dialog_ex, app->get_text_store(0), 95, 10, AlignCenter, AlignCenter);
dialog_ex_set_text(dialog_ex, app->get_text_store(1), 75, 23, AlignLeft, AlignTop);
dialog_ex_set_left_button_text(dialog_ex, "Retry");
dialog_ex_set_right_button_text(dialog_ex, "Save");
dialog_ex_set_icon(dialog_ex, 0, 1, I_DolphinExcited_64x63);
dialog_ex_set_result_callback(dialog_ex, dialog_result_callback);
dialog_ex_set_context(dialog_ex, app);
view_manager->switch_to(IrdaAppViewManager::ViewType::DialogEx);
}
bool IrdaAppSceneLearnSuccess::on_event(IrdaApp* app, IrdaAppEvent* event) {
bool consumed = false;
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:
furi_assert(0);
break;
case DialogExResultRight:
app->switch_to_next_scene(IrdaApp::Scene::LearnEnterName);
break;
}
}
return consumed;
}
void IrdaAppSceneLearnSuccess::on_exit(IrdaApp* app) {
}

View File

@@ -0,0 +1,31 @@
#include "../irda-app.hpp"
void IrdaAppSceneLearn::on_enter(IrdaApp* app) {
auto view_manager = app->get_view_manager();
auto receiver = app->get_receiver();
auto event_queue = view_manager->get_event_queue();
receiver->capture_once_start(event_queue);
auto popup = view_manager->get_popup();
popup_set_icon(popup, 0, 32, I_IrdaLearnShort_128x31);
popup_set_text(
popup, "Point the remote at IR port\nand push the button", 5, 10, AlignLeft, AlignCenter);
popup_set_callback(popup, NULL);
view_manager->switch_to(IrdaAppViewManager::ViewType::Popup);
}
bool IrdaAppSceneLearn::on_event(IrdaApp* app, IrdaAppEvent* event) {
bool consumed = false;
if(event->type == IrdaAppEvent::Type::IrdaMessageReceived) {
app->switch_to_next_scene_without_saving(IrdaApp::Scene::LearnSuccess);
}
return consumed;
}
void IrdaAppSceneLearn::on_exit(IrdaApp* app) {
}

View File

@@ -0,0 +1,59 @@
#include "../irda-app.hpp"
typedef enum {
SubmenuIndexPlus = -1,
} SubmenuIndex;
static void submenu_callback(void* context, uint32_t index) {
IrdaApp* app = static_cast<IrdaApp*>(context);
IrdaAppEvent event;
event.type = IrdaAppEvent::Type::MenuSelected;
event.payload.menu_index = index;
app->get_view_manager()->send_event(&event);
}
void IrdaAppSceneRemoteList::on_enter(IrdaApp* app) {
IrdaAppViewManager* view_manager = app->get_view_manager();
Submenu* submenu = view_manager->get_submenu();
auto remote_manager = app->get_remote_manager();
int i = 0;
remote_names = remote_manager->get_remote_list();
for(auto& a : remote_names) {
submenu_add_item(submenu, a.c_str(), i++, submenu_callback, app);
}
submenu_add_item(
submenu, " +", SubmenuIndexPlus, submenu_callback, app);
view_manager->switch_to(IrdaAppViewManager::ViewType::Submenu);
}
bool IrdaAppSceneRemoteList::on_event(IrdaApp* app, IrdaAppEvent* event) {
bool consumed = false;
if(event->type == IrdaAppEvent::Type::MenuSelected) {
switch(event->payload.menu_index) {
case SubmenuIndexPlus:
app->set_learn_new_remote(true);
app->switch_to_next_scene(IrdaApp::Scene::Learn);
break;
default:
auto remote_manager = app->get_remote_manager();
remote_manager->set_current_remote(event->payload.menu_index);
app->switch_to_next_scene(IrdaApp::Scene::Remote);
consumed = true;
break;
}
}
return consumed;
}
void IrdaAppSceneRemoteList::on_exit(IrdaApp* app) {
IrdaAppViewManager* view_manager = app->get_view_manager();
Submenu* submenu = view_manager->get_submenu();
submenu_clean(submenu);
}

View File

@@ -0,0 +1,75 @@
#include "../irda-app.hpp"
#include "gui/modules/button_menu.h"
typedef enum {
ButtonIndexPlus = -2,
ButtonIndexEdit = -1,
} ButtonIndex;
static void button_menu_callback(void* context, int32_t index) {
IrdaApp* app = static_cast<IrdaApp*>(context);
IrdaAppEvent event;
event.type = IrdaAppEvent::Type::MenuSelected;
event.payload.menu_index = index;
app->get_view_manager()->send_event(&event);
}
void IrdaAppSceneRemote::on_enter(IrdaApp* app) {
IrdaAppViewManager* view_manager = app->get_view_manager();
ButtonMenu* button_menu = view_manager->get_button_menu();
auto remote_manager = app->get_remote_manager();
int i = 0;
buttons_names = remote_manager->get_button_list();
i = 0;
for(auto& name : buttons_names) {
button_menu_add_item(
button_menu, name.c_str(), i++, button_menu_callback, ButtonMenuItemTypeCommon, app);
}
button_menu_add_item(
button_menu, "+", ButtonIndexPlus, button_menu_callback, ButtonMenuItemTypeControl, app);
button_menu_add_item(
button_menu, "Edit", ButtonIndexEdit, button_menu_callback, ButtonMenuItemTypeControl, app);
app->set_text_store(0, "%s", remote_manager->get_current_remote_name().c_str());
button_menu_set_header(button_menu, app->get_text_store(0));
view_manager->switch_to(IrdaAppViewManager::ViewType::ButtonMenu);
}
bool IrdaAppSceneRemote::on_event(IrdaApp* app, IrdaAppEvent* event) {
bool consumed = true;
if(event->type == IrdaAppEvent::Type::MenuSelected) {
switch(event->payload.menu_index) {
case ButtonIndexPlus:
app->switch_to_next_scene(IrdaApp::Scene::Learn);
break;
case ButtonIndexEdit:
app->switch_to_next_scene(IrdaApp::Scene::Edit);
break;
default:
auto remote_manager = app->get_remote_manager();
auto message = remote_manager->get_button_data(event->payload.menu_index);
app->get_receiver()->send_message(message);
break;
}
} else if(event->type == IrdaAppEvent::Type::Back) {
app->search_and_switch_to_previous_scene(
{IrdaApp::Scene::Start, IrdaApp::Scene::RemoteList});
} else {
consumed = false;
}
return consumed;
}
void IrdaAppSceneRemote::on_exit(IrdaApp* app) {
IrdaAppViewManager* view_manager = app->get_view_manager();
ButtonMenu* button_menu = view_manager->get_button_menu();
button_menu_clean(button_menu);
}

View File

@@ -0,0 +1,59 @@
#include "../irda-app.hpp"
typedef enum {
SubmenuIndexUniversalLibrary,
SubmenuIndexLearnNewRemote,
SubmenuIndexSavedRemotes,
} SubmenuIndex;
static void submenu_callback(void* context, uint32_t index) {
IrdaApp* app = static_cast<IrdaApp*>(context);
IrdaAppEvent event;
event.type = IrdaAppEvent::Type::MenuSelected;
event.payload.menu_index = index;
app->get_view_manager()->send_event(&event);
}
void IrdaAppSceneStart::on_enter(IrdaApp* app) {
IrdaAppViewManager* view_manager = app->get_view_manager();
Submenu* submenu = view_manager->get_submenu();
submenu_add_item(
submenu, "Universal library", SubmenuIndexUniversalLibrary, submenu_callback, app);
submenu_add_item(
submenu, "Learn new remote", SubmenuIndexLearnNewRemote, submenu_callback, app);
submenu_add_item(submenu, "Saved remotes", SubmenuIndexSavedRemotes, submenu_callback, app);
view_manager->switch_to(IrdaAppViewManager::ViewType::Submenu);
}
bool IrdaAppSceneStart::on_event(IrdaApp* app, IrdaAppEvent* event) {
bool consumed = false;
if(event->type == IrdaAppEvent::Type::MenuSelected) {
switch(event->payload.menu_index) {
case SubmenuIndexUniversalLibrary:
app->switch_to_next_scene(IrdaApp::Scene::Universal);
break;
case SubmenuIndexLearnNewRemote:
app->set_learn_new_remote(true);
app->switch_to_next_scene(IrdaApp::Scene::Learn);
break;
case SubmenuIndexSavedRemotes:
app->switch_to_next_scene(IrdaApp::Scene::RemoteList);
break;
}
consumed = true;
}
return consumed;
}
void IrdaAppSceneStart::on_exit(IrdaApp* app) {
IrdaAppViewManager* view_manager = app->get_view_manager();
Submenu* submenu = view_manager->get_submenu();
submenu_clean(submenu);
}

View File

@@ -0,0 +1,57 @@
#include "../irda-app.hpp"
typedef enum {
SubmenuIndexUniversalTV,
SubmenuIndexUniversalAudio,
SubmenuIndexUniversalAirConditioner,
} SubmenuIndex;
static void submenu_callback(void* context, uint32_t index) {
IrdaApp* app = static_cast<IrdaApp*>(context);
IrdaAppEvent event;
event.type = IrdaAppEvent::Type::MenuSelected;
event.payload.menu_index = index;
app->get_view_manager()->send_event(&event);
}
void IrdaAppSceneUniversal::on_enter(IrdaApp* app) {
IrdaAppViewManager* view_manager = app->get_view_manager();
Submenu* submenu = view_manager->get_submenu();
submenu_add_item(submenu, "TV's", SubmenuIndexUniversalTV, submenu_callback, app);
submenu_add_item(submenu, "Audio Players", SubmenuIndexUniversalAudio, submenu_callback, app);
submenu_add_item(
submenu, "Air Conditioners", SubmenuIndexUniversalAirConditioner, submenu_callback, app);
view_manager->switch_to(IrdaAppViewManager::ViewType::Submenu);
}
bool IrdaAppSceneUniversal::on_event(IrdaApp* app, IrdaAppEvent* event) {
bool consumed = false;
if(event->type == IrdaAppEvent::Type::MenuSelected) {
switch(event->payload.menu_index) {
case SubmenuIndexUniversalTV:
// app->switch_to_next_scene(IrdaApp::Scene::UniversalTV);
break;
case SubmenuIndexUniversalAudio:
// app->switch_to_next_scene(IrdaApp::Scene::UniversalAudio);
break;
case SubmenuIndexUniversalAirConditioner:
// app->switch_to_next_scene(IrdaApp::Scene::UniversalAirConditioner);
break;
}
consumed = true;
}
return consumed;
}
void IrdaAppSceneUniversal::on_exit(IrdaApp* app) {
IrdaAppViewManager* view_manager = app->get_view_manager();
Submenu* submenu = view_manager->get_submenu();
submenu_clean(submenu);
}

View File

@@ -0,0 +1,130 @@
#pragma once
#include "../irda-app.hpp"
#include <api-hal-irda.h>
#include "irda.h"
#include <gui/elements.h>
#include <vector>
#include <string>
class IrdaApp;
class IrdaAppScene {
public:
virtual void on_enter(IrdaApp* app) = 0;
virtual bool on_event(IrdaApp* app, IrdaAppEvent* event) = 0;
virtual void on_exit(IrdaApp* app) = 0;
virtual ~IrdaAppScene(){};
private:
};
class IrdaAppSceneStart : public IrdaAppScene {
public:
void on_enter(IrdaApp* app) final;
bool on_event(IrdaApp* app, IrdaAppEvent* event) final;
void on_exit(IrdaApp* app) final;
};
class IrdaAppSceneUniversal : public IrdaAppScene {
public:
void on_enter(IrdaApp* app) final;
bool on_event(IrdaApp* app, IrdaAppEvent* event) final;
void on_exit(IrdaApp* app) final;
};
class IrdaAppSceneLearn : public IrdaAppScene {
public:
void on_enter(IrdaApp* app) final;
bool on_event(IrdaApp* app, IrdaAppEvent* event) final;
void on_exit(IrdaApp* app) final;
};
class IrdaAppSceneLearnSuccess : public IrdaAppScene {
public:
void on_enter(IrdaApp* app) final;
bool on_event(IrdaApp* app, IrdaAppEvent* event) final;
void on_exit(IrdaApp* app) final;
};
class IrdaAppSceneLearnEnterName : public IrdaAppScene {
public:
void on_enter(IrdaApp* app) final;
bool on_event(IrdaApp* app, IrdaAppEvent* event) final;
void on_exit(IrdaApp* app) final;
};
class IrdaAppSceneLearnDone : public IrdaAppScene {
public:
void on_enter(IrdaApp* app) final;
bool on_event(IrdaApp* app, IrdaAppEvent* event) final;
void on_exit(IrdaApp* app) final;
};
class IrdaAppSceneLearnDoneAfter : public IrdaAppScene {
public:
void on_enter(IrdaApp* app) final;
bool on_event(IrdaApp* app, IrdaAppEvent* event) final;
void on_exit(IrdaApp* app) final;
};
class IrdaAppSceneRemote : public IrdaAppScene {
public:
void on_enter(IrdaApp* app) final;
bool on_event(IrdaApp* app, IrdaAppEvent* event) final;
void on_exit(IrdaApp* app) final;
private:
std::vector<std::string> buttons_names;
};
class IrdaAppSceneRemoteList : public IrdaAppScene {
public:
void on_enter(IrdaApp* app) final;
bool on_event(IrdaApp* app, IrdaAppEvent* event) final;
void on_exit(IrdaApp* app) final;
std::vector<std::string> remote_names;
};
class IrdaAppSceneEdit : public IrdaAppScene {
public:
void on_enter(IrdaApp* app) final;
bool on_event(IrdaApp* app, IrdaAppEvent* event) final;
void on_exit(IrdaApp* app) final;
};
class IrdaAppSceneEditKeySelect : public IrdaAppScene {
public:
void on_enter(IrdaApp* app) final;
bool on_event(IrdaApp* app, IrdaAppEvent* event) final;
void on_exit(IrdaApp* app) final;
private:
std::vector<std::string> buttons_names;
};
class IrdaAppSceneEditRename : public IrdaAppScene {
public:
void on_enter(IrdaApp* app) final;
bool on_event(IrdaApp* app, IrdaAppEvent* event) final;
void on_exit(IrdaApp* app) final;
};
class IrdaAppSceneEditDelete : public IrdaAppScene {
public:
void on_enter(IrdaApp* app) final;
bool on_event(IrdaApp* app, IrdaAppEvent* event) final;
void on_exit(IrdaApp* app) final;
};
class IrdaAppSceneEditRenameDone : public IrdaAppScene {
public:
void on_enter(IrdaApp* app) final;
bool on_event(IrdaApp* app, IrdaAppEvent* event) final;
void on_exit(IrdaApp* app) final;
};
class IrdaAppSceneEditDeleteDone : public IrdaAppScene {
public:
void on_enter(IrdaApp* app) final;
bool on_event(IrdaApp* app, IrdaAppEvent* event) final;
void on_exit(IrdaApp* app) final;
};