Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/ClusterM/flipperzero-firmware.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAlbert Kharisov <ah@bright-box.com>2021-07-16 19:43:54 +0300
committerGitHub <noreply@github.com>2021-07-16 19:43:54 +0300
commit13c5a8cb200df8e771d9f3fd2f5eb133d569017b (patch)
tree427f585f55dda4ecaa4c89df279fce204fb005b6 /applications/irda
parenta2dfa33a9f6dbc3503978e701fa458ebcd3983f2 (diff)
[FL-1505] Add RAW format (#576)
* Add RAW format * F5 stubs for build to pass * Fix saving decoded signal error * Irda: set ISR before starting timer, remove explicit NVIC configuration Co-authored-by: あく <alleteam@gmail.com>
Diffstat (limited to 'applications/irda')
-rw-r--r--applications/irda/cli/irda-cli.cpp174
-rw-r--r--applications/irda/irda-app-brute-force.cpp16
-rw-r--r--applications/irda/irda-app-brute-force.hpp3
-rw-r--r--applications/irda/irda-app-file-parser.cpp158
-rw-r--r--applications/irda/irda-app-file-parser.hpp21
-rw-r--r--applications/irda/irda-app-remote-manager.cpp40
-rw-r--r--applications/irda/irda-app-remote-manager.hpp15
-rw-r--r--applications/irda/irda-app-signal.cpp95
-rw-r--r--applications/irda/irda-app-signal.h61
-rw-r--r--applications/irda/irda-app-transceiver.cpp56
-rw-r--r--applications/irda/irda-app-transceiver.hpp21
-rw-r--r--applications/irda/irda-app.cpp17
-rw-r--r--applications/irda/irda-app.hpp13
-rw-r--r--applications/irda/irda_app_old.c434
-rw-r--r--applications/irda/scene/irda-app-scene-edit-delete.cpp29
-rw-r--r--applications/irda/scene/irda-app-scene-learn-enter-name.cpp30
-rw-r--r--applications/irda/scene/irda-app-scene-learn-success.cpp36
-rw-r--r--applications/irda/scene/irda-app-scene-learn.cpp54
-rw-r--r--applications/irda/scene/irda-app-scene-remote.cpp4
-rw-r--r--applications/irda/scene/irda-app-scene-universal-common.cpp2
20 files changed, 598 insertions, 681 deletions
diff --git a/applications/irda/cli/irda-cli.cpp b/applications/irda/cli/irda-cli.cpp
index 6a95e1d6..fb5be8fd 100644
--- a/applications/irda/cli/irda-cli.cpp
+++ b/applications/irda/cli/irda-cli.cpp
@@ -1,24 +1,48 @@
-#include "app-template.h"
-#include "cli/cli.h"
-#include "cmsis_os2.h"
+#include <api-hal-delay.h>
+#include <irda.h>
+#include <app-template.h>
+#include <cli/cli.h>
+#include <cmsis_os2.h>
+#include <irda_worker.h>
#include <furi.h>
#include <api-hal-irda.h>
-#include "irda.h"
#include <sstream>
#include <string>
#include <m-string.h>
+#include <irda_transmit.h>
-typedef struct IrdaCli {
- IrdaDecoderHandler* handler;
- osMessageQueueId_t message_queue;
-} IrdaCli;
-
-static void irda_rx_callback(void* ctx, bool level, uint32_t duration) {
- IrdaCli* irda_cli = (IrdaCli*)ctx;
- const IrdaMessage* message;
- message = irda_decode(irda_cli->handler, level, duration);
- if(message) {
- osMessageQueuePut(irda_cli->message_queue, message, 0, 0);
+static void signal_received_callback(void* context, IrdaWorkerSignal* received_signal) {
+ furi_assert(received_signal);
+ char buf[100];
+ size_t buf_cnt;
+ Cli* cli = (Cli*)context;
+
+ if(irda_worker_signal_is_decoded(received_signal)) {
+ const IrdaMessage* message = irda_worker_get_decoded_message(received_signal);
+ buf_cnt = sniprintf(
+ buf,
+ sizeof(buf),
+ "%s, A:0x%0*lX, C:0x%0*lX%s\r\n",
+ irda_get_protocol_name(message->protocol),
+ irda_get_protocol_address_length(message->protocol),
+ message->address,
+ irda_get_protocol_command_length(message->protocol),
+ message->command,
+ message->repeat ? " R" : "");
+ cli_write(cli, (uint8_t*)buf, buf_cnt);
+ } else {
+ const uint32_t* timings;
+ size_t timings_cnt;
+ irda_worker_get_raw_signal(received_signal, &timings, &timings_cnt);
+
+ buf_cnt = sniprintf(buf, sizeof(buf), "RAW, %d samples:\r\n", timings_cnt);
+ cli_write(cli, (uint8_t*)buf, buf_cnt);
+ for(size_t i = 0; i < timings_cnt; ++i) {
+ buf_cnt = sniprintf(buf, sizeof(buf), "%lu ", timings[i]);
+ cli_write(cli, (uint8_t*)buf, buf_cnt);
+ }
+ buf_cnt = sniprintf(buf, sizeof(buf), "\r\n");
+ cli_write(cli, (uint8_t*)buf, buf_cnt);
}
}
@@ -27,30 +51,19 @@ static void irda_cli_start_ir_rx(Cli* cli, string_t args, void* context) {
printf("IRDA is busy. Exit.");
return;
}
- IrdaCli irda_cli;
- irda_cli.handler = irda_alloc_decoder();
- irda_cli.message_queue = osMessageQueueNew(2, sizeof(IrdaMessage), NULL);
- api_hal_irda_rx_irq_init();
- api_hal_irda_rx_irq_set_callback(irda_rx_callback, &irda_cli);
+
+ IrdaWorker* worker = irda_worker_alloc();
+ irda_worker_set_context(worker, cli);
+ irda_worker_start(worker);
+ irda_worker_set_received_signal_callback(worker, signal_received_callback);
printf("Receiving IRDA...\r\nPress Ctrl+C to abort\r\n");
while(!cli_cmd_interrupt_received(cli)) {
- IrdaMessage message;
- if(osOK == osMessageQueueGet(irda_cli.message_queue, &message, NULL, 50)) {
- printf(
- "%s, A:0x%0*lX, C:0x%0*lX%s\r\n",
- irda_get_protocol_name(message.protocol),
- irda_get_protocol_address_length(message.protocol),
- message.address,
- irda_get_protocol_command_length(message.protocol),
- message.command,
- message.repeat ? " R" : "");
- }
+ delay(50);
}
- api_hal_irda_rx_irq_deinit();
- irda_free_decoder(irda_cli.handler);
- osMessageQueueDelete(irda_cli.message_queue);
+ irda_worker_stop(worker);
+ irda_worker_free(worker);
}
static void irda_cli_print_usage(void) {
@@ -63,38 +76,93 @@ static void irda_cli_print_usage(void) {
printf("\r\n");
}
-static void irda_cli_start_ir_tx(Cli* cli, string_t args, void* context) {
- if(api_hal_irda_rx_irq_is_busy()) {
- printf("IRDA is busy. Exit.");
- return;
- }
-
+static bool parse_message(const char* str, IrdaMessage* message) {
uint32_t command = 0;
uint32_t address = 0;
char protocol_name[32];
- int parsed = sscanf(string_get_cstr(args), "%31s %lX %lX", protocol_name, &address, &command);
+ int parsed = sscanf(str, "%31s %lX %lX", protocol_name, &address, &command);
if(parsed != 3) {
- printf("Wrong arguments.\r\n");
- irda_cli_print_usage();
- return;
+ return false;
}
IrdaProtocol protocol = irda_get_protocol_by_name(protocol_name);
if(!irda_is_protocol_valid(protocol)) {
- printf("Unknown protocol.\r\n");
- irda_cli_print_usage();
+ return false;
+ }
+
+ message->protocol = protocol;
+ message->address = address;
+ message->command = command;
+ message->repeat = false;
+
+ return true;
+}
+
+static bool parse_signal_raw(
+ const char* str,
+ uint32_t* timings,
+ uint32_t* timings_cnt,
+ float* duty_cycle,
+ float* frequency) {
+ char frequency_str[10];
+ char duty_cycle_str[10];
+ int parsed = sscanf(str, "RAW F:%9s DC:%9s", frequency_str, duty_cycle_str);
+ if(parsed != 2) return false;
+
+ *frequency = atoi(frequency_str);
+ *duty_cycle = (float)atoi(duty_cycle_str) / 100;
+ str += strlen(frequency_str) + strlen(duty_cycle_str) + 10;
+
+ uint32_t timings_cnt_max = *timings_cnt;
+ *timings_cnt = 0;
+
+ while(1) {
+ char timing_str[10];
+ for(; *str == ' '; ++str)
+ ;
+ if(1 != sscanf(str, "%9s", timing_str)) break;
+ str += strlen(timing_str);
+ uint32_t timing = atoi(timing_str);
+ if(timing <= 0) break;
+ if(*timings_cnt >= timings_cnt_max) break;
+ timings[*timings_cnt] = timing;
+ ++*timings_cnt;
+ }
+
+ printf("\r\nTransmit:");
+ for(size_t i = 0; i < *timings_cnt; ++i) {
+ printf(" %ld", timings[i]);
+ }
+ printf("\r\n");
+
+ return true;
+}
+
+static void irda_cli_start_ir_tx(Cli* cli, string_t args, void* context) {
+ if(api_hal_irda_rx_irq_is_busy()) {
+ printf("IRDA is busy. Exit.");
return;
}
- IrdaMessage message = {
- .protocol = protocol,
- .address = address,
- .command = command,
- .repeat = false,
- };
- irda_send(&message, 1);
+ IrdaMessage message;
+ const char* str = string_get_cstr(args);
+ float frequency;
+ float duty_cycle;
+ uint32_t* timings = (uint32_t*)furi_alloc(sizeof(uint32_t) * 1000);
+ uint32_t timings_cnt = 1000;
+
+ if(parse_message(str, &message)) {
+ irda_send(&message, 1);
+ } else if(parse_signal_raw(str, timings, &timings_cnt, &duty_cycle, &frequency)) {
+ irda_send_raw_ext(timings, timings_cnt, true, duty_cycle, frequency);
+ } else {
+ printf("Wrong arguments.\r\n");
+ irda_cli_print_usage();
+ }
+
+ free(timings);
}
extern "C" void irda_cli_init() {
diff --git a/applications/irda/irda-app-brute-force.cpp b/applications/irda/irda-app-brute-force.cpp
index 4866a524..21491e76 100644
--- a/applications/irda/irda-app-brute-force.cpp
+++ b/applications/irda/irda-app-brute-force.cpp
@@ -16,7 +16,7 @@ bool IrdaAppBruteForce::calculate_messages() {
file_parser.reset();
while(1) {
- auto message = file_parser.read_message(&file);
+ auto message = file_parser.read_signal(&file);
if(!message) break;
auto element = records.find(message->name);
if(element != records.cend()) {
@@ -37,19 +37,19 @@ void IrdaAppBruteForce::stop_bruteforce() {
}
// TODO: [FL-1418] replace with timer-chained consequence of messages.
-bool IrdaAppBruteForce::send_next_bruteforce(const IrdaAppSignalTransceiver& transceiver) {
+bool IrdaAppBruteForce::send_next_bruteforce(void) {
furi_assert(current_record.size());
- std::unique_ptr<IrdaAppFileParser::IrdaFileMessage> message;
+ std::unique_ptr<IrdaAppFileParser::IrdaFileSignal> file_signal;
do {
- message = file_parser.read_message(&file);
- } while(message && current_record.compare(message->name));
+ file_signal = file_parser.read_signal(&file);
+ } while(file_signal && current_record.compare(file_signal->name));
- if(message) {
- transceiver.send_message(&message->message);
+ if(file_signal) {
+ file_signal->signal.transmit();
}
- return !!message;
+ return !!file_signal;
}
bool IrdaAppBruteForce::start_bruteforce(int index, int& record_amount) {
diff --git a/applications/irda/irda-app-brute-force.hpp b/applications/irda/irda-app-brute-force.hpp
index 09a5002e..62b8f34e 100644
--- a/applications/irda/irda-app-brute-force.hpp
+++ b/applications/irda/irda-app-brute-force.hpp
@@ -2,7 +2,6 @@
#include "furi/check.h"
#include <unordered_map>
#include "irda-app-file-parser.hpp"
-#include "irda-app-transceiver.hpp"
class IrdaAppBruteForce {
@@ -26,7 +25,7 @@ class IrdaAppBruteForce {
public:
bool calculate_messages();
void stop_bruteforce();
- bool send_next_bruteforce(const IrdaAppSignalTransceiver& receiver);
+ bool send_next_bruteforce();
bool start_bruteforce(int index, int& record_amount);
void add_record(int index, const char* name);
diff --git a/applications/irda/irda-app-file-parser.cpp b/applications/irda/irda-app-file-parser.cpp
index 07c104b8..e0e274e5 100644
--- a/applications/irda/irda-app-file-parser.cpp
+++ b/applications/irda/irda-app-file-parser.cpp
@@ -1,26 +1,83 @@
#include "irda-app-file-parser.hpp"
+#include "irda-app-remote-manager.hpp"
+#include "irda-app-signal.h"
+#include <irda.h>
+#include <cstdio>
+#include <stdint.h>
+#include <string_view>
+#include <furi.h>
-std::unique_ptr<IrdaAppFileParser::IrdaFileMessage> IrdaAppFileParser::read_message(File* file) {
+uint32_t const IrdaAppFileParser::max_line_length = ((9 + 1) * 512 + 100);
+
+std::unique_ptr<IrdaAppFileParser::IrdaFileSignal> IrdaAppFileParser::read_signal(File* file) {
while(1) {
auto str = getline(file);
if(str.empty()) return nullptr;
- auto message = parse_message(str);
+ auto message = parse_signal(str);
+ if(!message.get()) {
+ message = parse_signal_raw(str);
+ }
if(message) return message;
}
}
-std::unique_ptr<IrdaAppFileParser::IrdaFileMessage>
- IrdaAppFileParser::parse_message(const std::string& str) const {
+bool IrdaAppFileParser::store_signal(File* file, const IrdaAppSignal& signal, const char* name) {
+ char* content = new char[max_line_length];
+ size_t written = 0;
+
+ if(!signal.is_raw()) {
+ auto message = signal.get_message();
+ auto protocol = message.protocol;
+
+ sniprintf(
+ content,
+ max_line_length,
+ "%.31s %.31s A:%0*lX C:%0*lX\n",
+ name,
+ irda_get_protocol_name(protocol),
+ irda_get_protocol_address_length(protocol),
+ message.address,
+ irda_get_protocol_command_length(protocol),
+ message.command);
+ written = strlen(content);
+ } else {
+ int duty_cycle = 100 * IRDA_COMMON_DUTY_CYCLE;
+ written += sniprintf(
+ &content[written],
+ max_line_length - written,
+ "%.31s RAW F:%d DC:%d",
+ name,
+ IRDA_COMMON_CARRIER_FREQUENCY,
+ duty_cycle);
+
+ auto& raw_signal = signal.get_raw_signal();
+ for(size_t i = 0; i < raw_signal.timings_cnt; ++i) {
+ written += sniprintf(
+ &content[written], max_line_length - written, " %ld", raw_signal.timings[i]);
+ furi_assert(written <= max_line_length);
+ }
+ written += snprintf(&content[written], max_line_length - written, "\n");
+ }
+ furi_assert(written < max_line_length);
+
+ size_t write_count = 0;
+ write_count = get_fs_api().file.write(file, content, written);
+ delete[] content;
+ return (file->error_id == FSE_OK) && (write_count == written);
+}
+
+std::unique_ptr<IrdaAppFileParser::IrdaFileSignal>
+ IrdaAppFileParser::parse_signal(const std::string& str) const {
char protocol_name[32];
uint32_t address;
uint32_t command;
- auto irda_file_message = std::make_unique<IrdaFileMessage>();
+ auto irda_file_signal = std::make_unique<IrdaFileSignal>();
int parsed = std::sscanf(
str.c_str(),
"%31s %31s A:%lX C:%lX",
- irda_file_message->name,
+ irda_file_signal->name,
protocol_name,
&address,
&command);
@@ -47,12 +104,97 @@ std::unique_ptr<IrdaAppFileParser::IrdaFileMessage>
return nullptr;
}
- irda_file_message->message = {
+ IrdaMessage message = {
.protocol = protocol,
.address = address,
.command = command,
.repeat = false,
};
- return irda_file_message;
+ irda_file_signal->signal.set_message(&message);
+
+ return irda_file_signal;
+}
+
+const char* find_first_not_of(const char* str, char symbol) {
+ const char* str_start = nullptr;
+ while(str != str_start) {
+ str_start = str;
+ str = strchr(str, symbol);
+ }
+
+ return str;
+}
+
+std::unique_ptr<IrdaAppFileParser::IrdaFileSignal>
+ IrdaAppFileParser::parse_signal_raw(const std::string& string) const {
+ char protocol_name[32];
+ uint32_t frequency;
+ uint32_t duty_cycle;
+ int str_len = string.size();
+ std::string_view str(string.c_str());
+ auto irda_file_signal = std::make_unique<IrdaFileSignal>();
+
+ int parsed = std::sscanf(
+ str.data(),
+ "%31s %31s F:%ld DC:%ld",
+ irda_file_signal->name,
+ protocol_name,
+ &frequency,
+ &duty_cycle);
+
+ if(parsed != 4) {
+ return nullptr;
+ }
+
+ char dummy[100] = {0};
+ int header_len = 0;
+ header_len = sniprintf(
+ dummy,
+ sizeof(dummy),
+ "%.31s %.31s F:%ld DC:%ld",
+ irda_file_signal->name,
+ protocol_name,
+ frequency,
+ duty_cycle);
+
+ furi_assert(header_len < str_len);
+ str.remove_prefix(header_len);
+
+ /* move allocated timings into raw signal object */
+ IrdaAppSignal::RawSignal raw_signal = {.timings_cnt = 0, .timings = new uint32_t[500]};
+ bool result = false;
+
+ while(!str.empty()) {
+ char buf[10];
+ size_t index = str.find_first_not_of(' ', 1);
+ if(index == std::string_view::npos) {
+ result = true;
+ break;
+ }
+ str.remove_prefix(index);
+ parsed = std::sscanf(str.data(), "%9s", buf);
+ if(parsed != 1) {
+ break;
+ }
+ str.remove_prefix(strlen(buf));
+
+ int value = atoi(buf);
+ if(value <= 0) {
+ break;
+ }
+ raw_signal.timings[raw_signal.timings_cnt] = value;
+ ++raw_signal.timings_cnt;
+ if(raw_signal.timings_cnt >= 500) {
+ break;
+ }
+ }
+
+ if(result) {
+ irda_file_signal->signal.set_raw_signal(raw_signal.timings, raw_signal.timings_cnt);
+ } else {
+ (void)irda_file_signal.release();
+ delete[] raw_signal.timings;
+ }
+ return irda_file_signal;
}
diff --git a/applications/irda/irda-app-file-parser.hpp b/applications/irda/irda-app-file-parser.hpp
index 55b27971..86a69a72 100644
--- a/applications/irda/irda-app-file-parser.hpp
+++ b/applications/irda/irda-app-file-parser.hpp
@@ -1,17 +1,26 @@
#pragma once
-#include "file_reader/file_reader.hpp"
-#include "irda.h"
+#include <file_reader/file_reader.h>
+#include <irda.h>
+#include "irda-app-remote-manager.hpp"
class IrdaAppFileParser : public FileReader {
public:
typedef struct {
char name[32];
- IrdaMessage message;
- } IrdaFileMessage;
+ IrdaAppSignal signal;
+ } IrdaFileSignal;
- std::unique_ptr<IrdaAppFileParser::IrdaFileMessage> read_message(File* file);
+ IrdaAppFileParser() {
+ /* Assume we can save max 512 samples */
+ set_max_line_length(max_line_length);
+ }
+
+ std::unique_ptr<IrdaAppFileParser::IrdaFileSignal> read_signal(File* file);
+ bool store_signal(File* file, const IrdaAppSignal& signal, const char* name);
private:
- std::unique_ptr<IrdaFileMessage> parse_message(const std::string& str) const;
+ static const uint32_t max_line_length;
+ std::unique_ptr<IrdaFileSignal> parse_signal(const std::string& str) const;
+ std::unique_ptr<IrdaFileSignal> parse_signal_raw(const std::string& str) const;
};
diff --git a/applications/irda/irda-app-remote-manager.cpp b/applications/irda/irda-app-remote-manager.cpp
index 4ae6c00c..1eef6b4d 100644
--- a/applications/irda/irda-app-remote-manager.cpp
+++ b/applications/irda/irda-app-remote-manager.cpp
@@ -33,16 +33,15 @@ static std::string
}
}
-bool IrdaAppRemoteManager::add_button(const char* button_name, const IrdaMessage* message) {
- remote->buttons.emplace_back(button_name, message);
+bool IrdaAppRemoteManager::add_button(const char* button_name, const IrdaAppSignal& signal) {
+ remote->buttons.emplace_back(button_name, signal);
return store();
}
bool IrdaAppRemoteManager::add_remote_with_button(
const char* button_name,
- const IrdaMessage* message) {
+ const IrdaAppSignal& signal) {
furi_check(button_name != nullptr);
- furi_check(message != nullptr);
std::vector<std::string> remote_list;
bool result = get_remote_list(remote_list);
@@ -51,7 +50,7 @@ bool IrdaAppRemoteManager::add_remote_with_button(
auto new_name = find_vacant_name(remote_list, default_remote_name);
remote = std::make_unique<IrdaAppRemote>(new_name);
- return add_button(button_name, message);
+ return add_button(button_name, signal);
}
IrdaAppRemote::IrdaAppRemote(const std::string& name)
@@ -70,12 +69,12 @@ std::vector<std::string> IrdaAppRemoteManager::get_button_list(void) const {
return name_vector;
}
-const IrdaMessage* IrdaAppRemoteManager::get_button_data(size_t index) const {
+const IrdaAppSignal& IrdaAppRemoteManager::get_button_data(size_t index) const {
furi_check(remote.get() != nullptr);
auto& buttons = remote->buttons;
furi_check(index < buttons.size());
- return &buttons.at(index).message;
+ return buttons.at(index).signal;
}
std::string IrdaAppRemoteManager::make_filename(const std::string& name) const {
@@ -166,7 +165,6 @@ size_t IrdaAppRemoteManager::get_number_of_buttons() {
bool IrdaAppRemoteManager::store(void) {
File file;
- uint16_t write_count;
std::string dirname(std::string("/") + irda_directory);
IrdaAppFileParser file_parser;
@@ -186,25 +184,9 @@ bool IrdaAppRemoteManager::store(void) {
return false;
}
- char content[128];
-
for(const auto& button : remote->buttons) {
- auto protocol = button.message.protocol;
-
- sniprintf(
- content,
- sizeof(content),
- "%.31s %.31s A:%0*lX C:%0*lX\n",
- button.name.c_str(),
- irda_get_protocol_name(protocol),
- irda_get_protocol_address_length(protocol),
- button.message.address,
- irda_get_protocol_command_length(protocol),
- button.message.command);
-
- auto content_len = strlen(content);
- write_count = file_parser.get_fs_api().file.write(&file, content, content_len);
- if(file.error_id != FSE_OK || write_count != content_len) {
+ bool result = file_parser.store_signal(&file, button.signal, button.name.c_str());
+ if(!result) {
file_parser.get_sd_api().show_error(
file_parser.get_sd_api().context, "Cannot write\nto key file");
file_parser.get_fs_api().file.close(&file);
@@ -267,9 +249,9 @@ bool IrdaAppRemoteManager::load(const std::string& name) {
remote = std::make_unique<IrdaAppRemote>(name);
while(1) {
- auto message = file_parser.read_message(&file);
- if(!message) break;
- remote->buttons.emplace_back(message->name, &message->message);
+ auto file_signal = file_parser.read_signal(&file);
+ if(!file_signal.get()) break;
+ remote->buttons.emplace_back(file_signal->name, file_signal->signal);
}
file_parser.get_fs_api().file.close(&file);
diff --git a/applications/irda/irda-app-remote-manager.hpp b/applications/irda/irda-app-remote-manager.hpp
index f7f068cd..fda82e7e 100644
--- a/applications/irda/irda-app-remote-manager.hpp
+++ b/applications/irda/irda-app-remote-manager.hpp
@@ -1,4 +1,5 @@
#pragma once
+#include <irda_worker.h>
#include <stdint.h>
#include <string>
#include <vector>
@@ -6,14 +7,16 @@
#include <irda.h>
#include <sd-card-api.h>
#include <filesystem-api.h>
+#include "irda-app-signal.h"
+
class IrdaAppRemoteButton {
friend class IrdaAppRemoteManager;
std::string name;
- IrdaMessage message;
+ IrdaAppSignal signal;
public:
- IrdaAppRemoteButton(const char* name, const IrdaMessage* message)
- : name(name), message (*message) {}
+ IrdaAppRemoteButton(const char* name, const IrdaAppSignal& signal)
+ : name(name), signal (signal) {}
~IrdaAppRemoteButton() {}
};
@@ -38,8 +41,8 @@ class IrdaAppRemoteManager {
std::string make_filename(const std::string& name) const;
public:
- bool add_remote_with_button(const char* button_name, const IrdaMessage* message);
- bool add_button(const char* button_name, const IrdaMessage* message);
+ bool add_remote_with_button(const char* button_name, const IrdaAppSignal& signal);
+ bool add_button(const char* button_name, const IrdaAppSignal& signal);
int find_remote_name(const std::vector<std::string>& strings);
bool rename_button(uint32_t index, const char* str);
@@ -50,7 +53,7 @@ public:
std::string get_button_name(uint32_t index);
std::string get_remote_name();
size_t get_number_of_buttons();
- const IrdaMessage* get_button_data(size_t button_index) const;
+ const IrdaAppSignal& get_button_data(size_t index) const;
bool delete_button(uint32_t index);
bool delete_remote();
diff --git a/applications/irda/irda-app-signal.cpp b/applications/irda/irda-app-signal.cpp
new file mode 100644
index 00000000..0a9a7956
--- /dev/null
+++ b/applications/irda/irda-app-signal.cpp
@@ -0,0 +1,95 @@
+#include "irda-app-signal.h"
+#include <irda_transmit.h>
+
+void IrdaAppSignal::copy_timings(const uint32_t* timings, size_t size) {
+ furi_assert(size);
+ furi_assert(timings);
+
+ if(size) {
+ payload.raw.timings = new uint32_t[size];
+ payload.raw.timings_cnt = size;
+ memcpy(payload.raw.timings, timings, size * sizeof(uint32_t));
+ }
+}
+
+void IrdaAppSignal::clear_timings() {
+ if(!decoded) {
+ delete[] payload.raw.timings;
+ payload.raw.timings_cnt = 0;
+ payload.raw.timings = nullptr;
+ }
+}
+
+IrdaAppSignal::IrdaAppSignal(const uint32_t* timings, size_t timings_cnt) {
+ decoded = false;
+ copy_timings(timings, timings_cnt);
+}
+
+IrdaAppSignal::IrdaAppSignal(const IrdaMessage* irda_message) {
+ decoded = true;
+ payload.message = *irda_message;
+}
+
+IrdaAppSignal& IrdaAppSignal::operator=(const IrdaAppSignal& other) {
+ clear_timings();
+ decoded = other.decoded;
+ if(decoded) {
+ payload.message = other.payload.message;
+ } else {
+ copy_timings(other.payload.raw.timings, other.payload.raw.timings_cnt);
+ }
+
+ return *this;
+}
+
+IrdaAppSignal::IrdaAppSignal(const IrdaAppSignal& other) {
+ decoded = other.decoded;
+ if(decoded) {
+ payload.message = other.payload.message;
+ } else {
+ copy_timings(other.payload.raw.timings, other.payload.raw.timings_cnt);
+ }
+}
+
+IrdaAppSignal::IrdaAppSignal(IrdaAppSignal&& other) {
+ clear_timings();
+
+ decoded = other.decoded;
+ if(decoded) {
+ payload.message = other.payload.message;
+ } else {
+ furi_assert(other.payload.raw.timings_cnt > 0);
+
+ payload.raw.timings = other.payload.raw.timings;
+ payload.raw.timings_cnt = other.payload.raw.timings_cnt;
+ other.payload.raw.timings = nullptr;
+ other.payload.raw.timings_cnt = 0;
+ }
+}
+
+void IrdaAppSignal::set_message(const IrdaMessage* irda_message) {
+ clear_timings();
+ decoded = true;
+ payload.message = *irda_message;
+}
+
+void IrdaAppSignal::set_raw_signal(uint32_t* timings, size_t timings_cnt) {
+ clear_timings();
+ decoded = false;
+ payload.raw.timings = timings;
+ payload.raw.timings_cnt = timings_cnt;
+}
+
+void IrdaAppSignal::copy_raw_signal(uint32_t* timings, size_t timings_cnt) {
+ clear_timings();
+ decoded = false;
+ copy_timings(timings, timings_cnt);
+}
+
+void IrdaAppSignal::transmit() const {
+ if(decoded) {
+ irda_send(&payload.message, 1);
+ } else {
+ irda_send_raw(payload.raw.timings, payload.raw.timings_cnt, true);
+ }
+}
diff --git a/applications/irda/irda-app-signal.h b/applications/irda/irda-app-signal.h
new file mode 100644
index 00000000..9701e2c1
--- /dev/null
+++ b/applications/irda/irda-app-signal.h
@@ -0,0 +1,61 @@
+#pragma once
+#include <irda_worker.h>
+#include <stdint.h>
+#include <string>
+#include <irda.h>
+
+class IrdaAppSignal {
+public:
+ typedef struct {
+ size_t timings_cnt;
+ uint32_t* timings;
+ } RawSignal;
+
+private:
+ bool decoded;
+ union {
+ IrdaMessage message;
+ RawSignal raw;
+ } payload;
+
+ void copy_timings(const uint32_t* timings, size_t size);
+ void clear_timings();
+
+public:
+ IrdaAppSignal() {
+ decoded = true;
+ payload.message.protocol = IrdaProtocolUnknown;
+ }
+
+ ~IrdaAppSignal() {
+ clear_timings();
+ }
+
+ IrdaAppSignal(const uint32_t* timings, size_t timings_cnt);
+ IrdaAppSignal(const IrdaMessage* irda_message);
+
+ IrdaAppSignal(const IrdaAppSignal& other);
+ IrdaAppSignal(IrdaAppSignal&& other);
+
+ IrdaAppSignal& operator=(const IrdaAppSignal& signal);
+
+ void set_message(const IrdaMessage* irda_message);
+ void set_raw_signal(uint32_t* timings, size_t timings_cnt);
+ void copy_raw_signal(uint32_t* timings, size_t timings_cnt);
+
+ void transmit() const;
+
+ bool is_raw(void) const {
+ return !decoded;
+ }
+
+ const IrdaMessage& get_message(void) const {
+ furi_assert(decoded);
+ return payload.message;
+ }
+
+ const RawSignal& get_raw_signal(void) const {
+ furi_assert(!decoded);
+ return payload.raw;
+ }
+};
diff --git a/applications/irda/irda-app-transceiver.cpp b/applications/irda/irda-app-transceiver.cpp
deleted file mode 100644
index c9f7d19c..00000000
--- a/applications/irda/irda-app-transceiver.cpp
+++ /dev/null
@@ -1,56 +0,0 @@
-#include "irda-app.hpp"
-#include "irda.h"
-#include <api-hal-irda.h>
-
-void IrdaAppSignalTransceiver::irda_rx_callback(void* ctx, bool level, uint32_t duration) {
- IrdaAppEvent event;
- const IrdaMessage* irda_message;
- IrdaAppSignalTransceiver* this_ = static_cast<IrdaAppSignalTransceiver*>(ctx);
-
- irda_message = irda_decode(this_->decoder, level, duration);
- if(irda_message) {
- this_->message = *irda_message;
- event.type = IrdaAppEvent::Type::IrdaMessageReceived;
- osStatus_t result = osMessageQueuePut(this_->event_queue, &event, 0, 0);
- furi_check(result == osOK);
- }
-}
-
-IrdaAppSignalTransceiver::IrdaAppSignalTransceiver(void)
- : capture_started(false)
- , decoder(irda_alloc_decoder()) {
-}
-
-IrdaAppSignalTransceiver::~IrdaAppSignalTransceiver() {
- capture_stop();
- irda_free_decoder(decoder);
-}
-
-void IrdaAppSignalTransceiver::capture_once_start(osMessageQueueId_t queue) {
- event_queue = queue;
- irda_reset_decoder(decoder);
- if(!capture_started) {
- capture_started = true;
- api_hal_irda_rx_irq_set_callback(IrdaAppSignalTransceiver::irda_rx_callback, this);
- api_hal_irda_rx_irq_init();
- }
-}
-
-void IrdaAppSignalTransceiver::capture_stop(void) {
- IrdaAppEvent event;
-
- if(capture_started) {
- capture_started = false;
- api_hal_irda_rx_irq_deinit();
- while(osMessageQueueGet(this->event_queue, &event, 0, 0) == osOK)
- ;
- }
-}
-
-IrdaMessage* IrdaAppSignalTransceiver::get_last_message(void) {
- return &message;
-}
-
-void IrdaAppSignalTransceiver::send_message(const IrdaMessage* message) const {
- irda_send(message, 1);
-}
diff --git a/applications/irda/irda-app-transceiver.hpp b/applications/irda/irda-app-transceiver.hpp
deleted file mode 100644
index e0c75b5b..00000000
--- a/applications/irda/irda-app-transceiver.hpp
+++ /dev/null
@@ -1,21 +0,0 @@
-#pragma once
-#include <furi.h>
-#include <irda.h>
-
-class IrdaAppSignalTransceiver {
-public:
- IrdaAppSignalTransceiver(void);
- ~IrdaAppSignalTransceiver(void);
- void capture_once_start(osMessageQueueId_t event_queue);
- void capture_stop(void);
- IrdaMessage* get_last_message(void);
- void send_message(const IrdaMessage* message) const;
-
-private:
- bool capture_started;
- osMessageQueueId_t event_queue;
- static void irda_rx_callback(void* ctx, bool level, uint32_t duration);
- IrdaDecoderHandler* decoder;
- IrdaMessage message;
-};
-
diff --git a/applications/irda/irda-app.cpp b/applications/irda/irda-app.cpp
index 4437ed96..6cd342ba 100644
--- a/applications/irda/irda-app.cpp
+++ b/applications/irda/irda-app.cpp
@@ -1,4 +1,5 @@
#include "irda-app.hpp"
+#include <irda_worker.h>
#include <furi.h>
#include <gui/gui.h>
#include <input/input.h>
@@ -99,10 +100,6 @@ IrdaAppRemoteManager* IrdaApp::get_remote_manager() {
return &remote_manager;
}
-IrdaAppSignalTransceiver* IrdaApp::get_transceiver() {
- return &transceiver;
-}
-
void IrdaApp::set_text_store(uint8_t index, const char* text...) {
furi_check(index < text_store_max);
@@ -220,3 +217,15 @@ void IrdaApp::notify_green_on() {
void IrdaApp::notify_green_off() {
notification_message(notification, &sequence_reset_green);
}
+
+IrdaWorker* IrdaApp::get_irda_worker() {
+ return irda_worker;
+}
+
+const IrdaAppSignal& IrdaApp::get_received_signal() const {
+ return received_signal;
+}
+
+void IrdaApp::set_received_signal(const IrdaAppSignal& signal) {
+ received_signal = signal;
+}
diff --git a/applications/irda/irda-app.hpp b/applications/irda/irda-app.hpp
index 0e76fc87..233c4c9f 100644
--- a/applications/irda/irda-app.hpp
+++ b/applications/irda/irda-app.hpp
@@ -7,10 +7,10 @@
#include "scene/irda-app-scene.hpp"
#include "irda-app-view-manager.hpp"
#include "irda-app-remote-manager.hpp"
-#include "irda-app-transceiver.hpp"
#include <forward_list>
#include <stdint.h>
#include <notification/notification-messages.h>
+#include <irda_worker.h>
class IrdaApp {
@@ -51,11 +51,15 @@ public:
bool switch_to_previous_scene(uint8_t count = 1);
Scene get_previous_scene();
IrdaAppViewManager* get_view_manager();
- IrdaAppSignalTransceiver* get_transceiver();
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();
+
+ IrdaWorker* get_irda_worker();
+ const IrdaAppSignal& get_received_signal() const;
+ void set_received_signal(const IrdaAppSignal& signal);
+
void search_and_switch_to_previous_scene(const std::initializer_list<Scene>& scenes_list);
void set_edit_element(EditElement value);
@@ -87,8 +91,10 @@ public:
IrdaApp() {
notification = static_cast<NotificationApp*>(furi_record_open("notification"));
+ irda_worker = irda_worker_alloc();
}
~IrdaApp() {
+ irda_worker_free(irda_worker);
furi_record_close("notification");
for (auto &it : scenes)
delete it.second;
@@ -103,9 +109,10 @@ private:
uint32_t current_button;
NotificationApp* notification;
- IrdaAppSignalTransceiver transceiver;
IrdaAppViewManager view_manager;
IrdaAppRemoteManager remote_manager;
+ IrdaWorker* irda_worker;
+ IrdaAppSignal received_signal;
std::forward_list<Scene> previous_scenes_list;
Scene current_scene = Scene::Start;
diff --git a/applications/irda/irda_app_old.c b/applications/irda/irda_app_old.c
deleted file mode 100644
index abfc30d6..00000000
--- a/applications/irda/irda_app_old.c
+++ /dev/null
@@ -1,434 +0,0 @@
-#include <furi.h>
-#include <api-hal.h>
-#include <gui/gui.h>
-#include <input/input.h>
-#include <cli/cli.h>
-#include <notification/notification-messages.h>
-
-#include <api-hal-irda.h>
-#include "irda.h"
-
-typedef enum {
- EventTypeTick,
- EventTypeKey,
- EventTypeRX,
-} EventType;
-
-typedef IrdaMessage IrDAPacket;
-
-typedef struct {
- union {
- InputEvent input;
- IrDAPacket rx;
- } value;
- EventType type;
-} AppEvent;
-
-//typedef struct {
-// IrdaProtocol protocol;
-// uint32_t address;
-// uint32_t command;
-//} IrDAPacket;
-
-#define IRDA_PACKET_COUNT 8
-
-typedef struct {
- osMessageQueueId_t cli_ir_rx_queue;
- Cli* cli;
- bool cli_cmd_is_active;
-} IrDAApp;
-
-typedef struct {
- uint8_t mode_id;
- uint16_t carrier_freq;
- uint8_t carrier_duty_cycle_id;
-
- uint8_t packet_id;
- IrDAPacket packets[IRDA_PACKET_COUNT];
-} State;
-
-typedef void (*ModeInput)(AppEvent*, State*);
-typedef void (*ModeRender)(Canvas*, State*);
-
-void input_carrier(AppEvent* event, State* state);
-void render_carrier(Canvas* canvas, State* state);
-void input_packet(AppEvent* event, State* state);
-void render_packet(Canvas* canvas, State* state);
-
-typedef struct {
- ModeRender render;
- ModeInput input;
-} Mode;
-
-const Mode modes[] = {
- {.render = render_carrier, .input = input_carrier},
- {.render = render_packet, .input = input_packet},
-};
-
-const float duty_cycles[] = {0.1, 0.25, 0.333, 0.5, 1.0};
-
-void render_carrier(Canvas* canvas, State* state) {
- canvas_set_font(canvas, FontSecondary);
- canvas_draw_str(canvas, 2, 25, "carrier mode >");
- canvas_draw_str(canvas, 2, 37, "? /\\ freq | \\/ duty cycle");
- {
- char buf[24];
- sprintf(buf, "frequency: %u Hz", state->carrier_freq);
- canvas_draw_str(canvas, 2, 50, buf);
- sprintf(
- buf, "duty cycle: %d/1000", (int)(duty_cycles[state->carrier_duty_cycle_id] * 1000));
- canvas_draw_str(canvas, 2, 62, buf);
- }
-}
-
-void input_carrier(AppEvent* event, State* state) {
- if(event->value.input.key == InputKeyOk) {
- if(event->value.input.type == InputTypePress) {
- api_hal_irda_pwm_set(duty_cycles[state->carrier_duty_cycle_id], state->carrier_freq);
- } else if(event->value.input.type == InputTypeRelease) {
- api_hal_irda_pwm_stop();
- }
- }
-
- if(event->value.input.type == InputTypeShort && event->value.input.key == InputKeyUp) {
- if(state->carrier_freq < 45000) {
- state->carrier_freq += 1000;
- } else {
- state->carrier_freq = 33000;
- }
- }
-
- if(event->value.input.type == InputTypeShort && event->value.input.key == InputKeyDown) {
- uint8_t duty_cycles_count = sizeof(duty_cycles) / sizeof(duty_cycles[0]);
- if(state->carrier_duty_cycle_id < (duty_cycles_count - 1)) {
- state->carrier_duty_cycle_id++;
- } else {
- state->carrier_duty_cycle_id = 0;
- }
- }
-}
-
-void render_packet(Canvas* canvas, State* state) {
- canvas_set_font(canvas, FontSecondary);
- canvas_draw_str(canvas, 2, 25, "< packet mode");
- canvas_draw_str(canvas, 2, 37, "? /\\ \\/ packet");
- {
- char buf[30];
- sprintf(
- buf,
- "P[%d]: %s 0x%lX 0x%lX",
- state->packet_id,
- irda_get_protocol_name(state->packets[state->packet_id].protocol),
- state->packets[state->packet_id].address,
- state->packets[state->packet_id].command);
- canvas_draw_str(canvas, 2, 50, buf);
- }
-}
-
-void input_packet(AppEvent* event, State* state) {
- if(event->value.input.key == InputKeyOk) {
- if(event->value.input.type == InputTypeShort) {
- IrdaMessage message = {
- .protocol = state->packets[state->packet_id].protocol,
- .address = state->packets[state->packet_id].address,
- .command = state->packets[state->packet_id].command,
- };
- irda_send(&message, 1);
- }
- }
-
- if(event->value.input.type == InputTypeShort && event->value.input.key == InputKeyDown) {
- if(state->packet_id < (IRDA_PACKET_COUNT - 1)) {
- state->packet_id++;
- };
- }
-
- if(event->value.input.type == InputTypeShort && event->value.input.key == InputKeyUp) {
- if(state->packet_id > 0) {
- state->packet_id--;
- };
- }
-}
-
-static void render_callback(Canvas* canvas, void* ctx) {
- State* state = (State*)acquire_mutex((ValueMutex*)ctx, 25);
-
- if(state != NULL) {
- canvas_clear(canvas);
- canvas_set_color(canvas, ColorBlack);
- canvas_set_font(canvas, FontPrimary);
- canvas_draw_str(canvas, 2, 12, "irda test");
-
- modes[state->mode_id].render(canvas, state);
-
- release_mutex((ValueMutex*)ctx, state);
- }
-}
-
-static void input_callback(InputEvent* input_event, void* ctx) {
- osMessageQueueId_t event_queue = ctx;
-
- AppEvent event;
- event.type = EventTypeKey;
- event.value.input = *input_event;
- osMessageQueuePut(event_queue, &event, 0, 0);
-}
-
-void init_packet(
- State* state,
- uint8_t index,
- IrdaProtocol protocol,
- uint32_t address,
- uint32_t command) {
- if(index >= IRDA_PACKET_COUNT) return;
- state->packets[index].protocol = protocol;
- state->packets[index].address = address;
- state->packets[index].command = command;
-}
-
-void irda_cli_cmd_rx(Cli* cli, string_t args, void* context) {
- furi_assert(context);
- IrDAPacket packet;
- IrDAApp* app = context;
- app->cli_cmd_is_active = true;
- bool exit = false;
-
- printf("Reading income packets...\r\nPress Ctrl+C to abort\r\n");
- while(!exit) {
- exit = cli_cmd_interrupt_received(app->cli);
- osStatus status = osMessageQueueGet(app->cli_ir_rx_queue, &packet, 0, 5);
- if(status == osOK) {
- printf(
- "%s "
- "Address:0x%02X Command: 0x%02X %s\r\n",
- irda_get_protocol_name(packet.protocol),
- (uint8_t)packet.address,
- (uint8_t)packet.command,
- packet.repeat ? "R" : "");
- }
- }
- printf("Interrupt command received");
- app->cli_cmd_is_active = false;
- return;
-}
-
-void irda_cli_cmd_tx(Cli* cli, string_t args, void* context) {
- furi_assert(context);
- ValueMutex* state_mutex = context;
- // Read protocol name
- IrdaProtocol protocol;
- string_t protocol_str;
- string_init(protocol_str);
- size_t ws = string_search_char(args, ' ');
- if(ws == STRING_FAILURE) {
- printf("Invalid input. Use ir_tx PROTOCOL ADDRESS COMMAND");
- string_clear(protocol_str);
- return;
- } else {
- string_set_n(protocol_str, args, 0, ws);
- string_right(args, ws);
- string_strim(args);
- }
- if(!string_cmp_str(protocol_str, "NEC")) {
- protocol = IrdaProtocolNEC;
- } else if(!string_cmp_str(protocol_str, "SAMSUNG")) {
- protocol = IrdaProtocolSamsung32;
- } else {
- printf("Incorrect protocol. Valid protocols: `NEC`, `SAMSUNG`");
- string_clear(protocol_str);
- return;
- }
- string_clear(protocol_str);
- // Read address
- uint16_t address = strtoul(string_get_cstr(args), NULL, 16);
- ws = string_search_char(args, ' ');
- if(!(ws == 4 || ws == 6)) {
- printf("Invalid address format. Use 4 [0-F] hex digits in 0xXXXX or XXXX formats");
- return;
- }
- string_right(args, ws);
- string_strim(args);
- // Read command
- uint16_t command = strtoul(string_get_cstr(args), NULL, 16);
- ws = string_search_char(args, '\0');
- if(!(ws == 4 || ws == 6)) {
- printf("Invalid command format. Use 4 [0-F] hex digits in 0xXXXX or XXXX formats");
- return;
- }
-
- State* state = (State*)acquire_mutex(state_mutex, 25);
- if(state == NULL) {
- printf("IRDA resources busy\r\n");
- return;
- }
-
- IrdaMessage message = {
- .protocol = protocol,
- .address = address,
- .command = command,
- };
- irda_send(&message, 1);
- release_mutex(state_mutex, state);
- return;
-}
-
-typedef struct {
- osMessageQueueId_t event_queue;
- IrdaDecoderHandler* handler;
-} IsrContext;
-
-void irda_rx_callback(void* ctx, bool level, uint32_t duration) {
- IsrContext* isr_context = ctx;
- const IrdaMessage* message = irda_decode(isr_context->handler, level, duration);
- AppEvent event;
- event.type = EventTypeRX;
-
- if(message) {
- event.value.rx = *message;
- furi_check(osMessageQueuePut(isr_context->event_queue, &event, 0, 0) == osOK);
- }
-}
-
-int32_t irda2(void* p) {
- osMessageQueueId_t event_queue = osMessageQueueNew(32, sizeof(AppEvent), NULL);
-
- State _state;
- uint8_t mode_count = sizeof(modes) / sizeof(modes[0]);
- uint8_t duty_cycles_count = sizeof(duty_cycles) / sizeof(duty_cycles[0]);
-
- _state.carrier_duty_cycle_id = duty_cycles_count - 2;
- _state.carrier_freq = 36000;
- _state.mode_id = 0;
- _state.packet_id = 0;
-
- IrDAApp irda_app;
- irda_app.cli = furi_record_open("cli");
- irda_app.cli_ir_rx_queue = osMessageQueueNew(1, sizeof(IrDAPacket), NULL);
- irda_app.cli_cmd_is_active = false;
-
- NotificationApp* notification = furi_record_open("notification");
-
- for(uint8_t i = 0; i < IRDA_PACKET_COUNT; i++) {
- init_packet(&_state, i, 0, 0, 0);
- }
-
- init_packet(&_state, 0, IrdaProtocolNEC, 0x00, 0x11);
- init_packet(&_state, 1, IrdaProtocolNEC, 0x08, 0x59);
- init_packet(&_state, 2, IrdaProtocolNEC, 0x00, 0x10);
- init_packet(&_state, 3, IrdaProtocolNEC, 0x00, 0x15);
- init_packet(&_state, 4, IrdaProtocolNEC, 0x00, 0x25);
- init_packet(&_state, 5, IrdaProtocolSamsung32, 0x0E, 0x0C);
- init_packet(&_state, 6, IrdaProtocolSamsung32, 0x0E, 0x0D);
- init_packet(&_state, 7, IrdaProtocolSamsung32, 0x0E, 0x0E);
-
- ValueMutex state_mutex;
- if(!init_mutex(&state_mutex, &_state, sizeof(State))) {
- printf("cannot create mutex\r\n");
- return 255;
- }
-
- ViewPort* view_port = view_port_alloc();
-
- view_port_draw_callback_set(view_port, render_callback, &state_mutex);
- view_port_input_callback_set(view_port, input_callback, event_queue);
-
- cli_add_command(irda_app.cli, "ir_rx", irda_cli_cmd_rx, &irda_app);
- cli_add_command(irda_app.cli, "ir_tx", irda_cli_cmd_tx, &state_mutex);
-
- // Open GUI and register view_port
- Gui* gui = furi_record_open("gui");
- gui_add_view_port(gui, view_port, GuiLayerFullscreen);
-
- IsrContext isr_context = {
- .handler = irda_alloc_decoder(),
- .event_queue = event_queue,
- };
- api_hal_irda_rx_irq_init();
- api_hal_irda_rx_irq_set_callback(irda_rx_callback, &isr_context);
-
- AppEvent event;
- while(1) {
- osStatus_t event_status = osMessageQueueGet(event_queue, &event, NULL, 500);
-
- if(event_status == osOK) {
- if(event.type == EventTypeKey) {
- State* state = (State*)acquire_mutex_block(&state_mutex);
-
- // press events
- if(event.value.input.type == InputTypeShort &&
- event.value.input.key == InputKeyBack) {
- release_mutex(&state_mutex, state);
-
- // remove all view_ports create by app
- gui_remove_view_port(gui, view_port);
- view_port_free(view_port);
-
- // free decoder
- delete_mutex(&state_mutex);
- osMessageQueueDelete(event_queue);
- osMessageQueueDelete(irda_app.cli_ir_rx_queue);
- cli_delete_command(irda_app.cli, "ir_rx");
- cli_delete_command(irda_app.cli, "ir_tx");
- furi_record_close("cli");
- furi_record_close("notification");
- api_hal_irda_rx_irq_deinit();
- irda_free_decoder(isr_context.handler);
-
- // exit
- return 0;
- }
-
- if(event.value.input.type == InputTypeShort &&
- event.value.input.key == InputKeyLeft) {
- if(state->mode_id > 0) {
- state->mode_id--;
- }
- }
-
- if(event.value.input.type == InputTypeShort &&
- event.value.input.key == InputKeyRight) {
- if(state->mode_id < (mode_count - 1)) {
- state->mode_id++;
- }
- }
-
- modes[state->mode_id].input(&event, state);
-
- release_mutex(&state_mutex, state);
- view_port_update(view_port);
-
- } else if(event.type == EventTypeRX) {
- notification_message(notification, &sequence_blink_red_10);
-
- // save only if we in packet mode
- State* state = (State*)acquire_mutex_block(&state_mutex);
- IrDAPacket packet = event.value.rx;
-
- if(state->mode_id == 1) {
- printf("P=%s ", irda_get_protocol_name(packet.protocol));
- printf("A=0x%02lX ", packet.address);
- printf("C=0x%02lX ", packet.command);
- if(packet.repeat) {
- printf("R");
- }
- printf("\r\n");
- // Save packet to state
- memcpy(&(state->packets[state->packet_id]), &packet, sizeof(IrDAPacket));
- }
- if(irda_app.cli_cmd_is_active) {
- // Send decoded packet to cli
- osMessageQueuePut(irda_app.cli_ir_rx_queue, &packet, 0, 0);
- }
-
- release_mutex(&state_mutex, state);
- view_port_update(view_port);
-
- // blink anyway
- notification_message(notification, &sequence_blink_green_10);
- }
-
- } else {
- // event timeout
- }
- }
-}
diff --git a/applications/irda/scene/irda-app-scene-edit-delete.cpp b/applications/irda/scene/irda-app-scene-edit-delete.cpp
index da817cba..c16ee7f2 100644
--- a/applications/irda/scene/irda-app-scene-edit-delete.cpp
+++ b/applications/irda/scene/irda-app-scene-edit-delete.cpp
@@ -20,17 +20,26 @@ void IrdaAppSceneEditDelete::on_enter(IrdaApp* app) {
auto remote_manager = app->get_remote_manager();
if(app->get_edit_element() == IrdaApp::EditElement::Button) {
- auto message = remote_manager->get_button_data(app->get_current_button());
+ auto signal = remote_manager->get_button_data(app->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_button_name(app->get_current_button()).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);
+ if(!signal.is_raw()) {
+ auto message = &signal.get_message();
+ app->set_text_store(
+ 0,
+ "%s\n%s\nA=0x%0*lX C=0x%0*lX",
+ remote_manager->get_button_name(app->get_current_button()).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 {
+ app->set_text_store(
+ 0,
+ "%s\nRAW\n%ld samples",
+ remote_manager->get_button_name(app->get_current_button()).c_str(),
+ signal.get_raw_signal().timings_cnt);
+ }
} else {
dialog_ex_set_header(dialog_ex, "Delete remote?", 64, 6, AlignCenter, AlignCenter);
app->set_text_store(
diff --git a/applications/irda/scene/irda-app-scene-learn-enter-name.cpp b/applications/irda/scene/irda-app-scene-learn-enter-name.cpp
index 45cd5ebf..be0b8d63 100644
--- a/applications/irda/scene/irda-app-scene-learn-enter-name.cpp
+++ b/applications/irda/scene/irda-app-scene-learn-enter-name.cpp
@@ -5,15 +5,20 @@ void IrdaAppSceneLearnEnterName::on_enter(IrdaApp* app) {
IrdaAppViewManager* view_manager = app->get_view_manager();
TextInput* text_input = view_manager->get_text_input();
- auto transceiver = app->get_transceiver();
- auto message = transceiver->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);
+ auto signal = app->get_received_signal();
+
+ if(!signal.is_raw()) {
+ auto message = &signal.get_message();
+ app->set_text_store(
+ 0,
+ "%.4s_%0*lX",
+ irda_get_protocol_name(message->protocol),
+ irda_get_protocol_command_length(message->protocol),
+ message->command);
+ } else {
+ auto raw_signal = signal.get_raw_signal();
+ app->set_text_store(0, "RAW_%d", raw_signal.timings_cnt);
+ }
text_input_set_header_text(text_input, "Name the key");
text_input_set_result_callback(
@@ -31,14 +36,13 @@ bool IrdaAppSceneLearnEnterName::on_event(IrdaApp* app, IrdaAppEvent* event) {
if(event->type == IrdaAppEvent::Type::TextEditDone) {
auto remote_manager = app->get_remote_manager();
- auto transceiver = app->get_transceiver();
bool result = false;
if(app->get_learn_new_remote()) {
result = remote_manager->add_remote_with_button(
- app->get_text_store(0), transceiver->get_last_message());
+ app->get_text_store(0), app->get_received_signal());
} else {
- result = remote_manager->add_button(
- app->get_text_store(0), transceiver->get_last_message());
+ result =
+ remote_manager->add_button(app->get_text_store(0), app->get_received_signal());
}
if(!result) {
diff --git a/applications/irda/scene/irda-app-scene-learn-success.cpp b/applications/irda/scene/irda-app-scene-learn-success.cpp
index 8b20f065..74e8db74 100644
--- a/applications/irda/scene/irda-app-scene-learn-success.cpp
+++ b/applications/irda/scene/irda-app-scene-learn-success.cpp
@@ -17,19 +17,26 @@ void IrdaAppSceneLearnSuccess::on_enter(IrdaApp* app) {
app->notify_green_on();
- auto transceiver = app->get_transceiver();
- auto message = transceiver->get_last_message();
+ auto signal = app->get_received_signal();
+
+ if(!signal.is_raw()) {
+ auto message = &signal.get_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);
+ } else {
+ dialog_ex_set_header(dialog_ex, "Unknown", 95, 10, AlignCenter, AlignCenter);
+ app->set_text_store(0, "%d samples", signal.get_raw_signal().timings_cnt);
+ dialog_ex_set_text(dialog_ex, app->get_text_store(0), 75, 23, AlignLeft, AlignTop);
+ }
- 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_center_button_text(dialog_ex, "Send");
@@ -50,9 +57,8 @@ bool IrdaAppSceneLearnSuccess::on_event(IrdaApp* app, IrdaAppEvent* event) {
break;
case DialogExResultCenter: {
app->notify_space_blink();
- auto transceiver = app->get_transceiver();
- auto message = transceiver->get_last_message();
- irda_send(message, 1);
+ auto signal = app->get_received_signal();
+ signal.transmit();
break;
}
case DialogExResultRight:
diff --git a/applications/irda/scene/irda-app-scene-learn.cpp b/applications/irda/scene/irda-app-scene-learn.cpp
index 890a523f..7fdd8bf7 100644
--- a/applications/irda/scene/irda-app-scene-learn.cpp
+++ b/applications/irda/scene/irda-app-scene-learn.cpp
@@ -1,14 +1,40 @@
#include "../irda-app.hpp"
+#include "../irda-app-event.hpp"
+#include <irda_worker.h>
-void IrdaAppSceneLearn::on_enter(IrdaApp* app) {
- auto view_manager = app->get_view_manager();
- auto transceiver = app->get_transceiver();
- auto event_queue = view_manager->get_event_queue();
+static void signal_received_callback(void* context, IrdaWorkerSignal* received_signal) {
+ furi_assert(context);
+ furi_assert(received_signal);
+
+ IrdaApp* app = static_cast<IrdaApp*>(context);
- transceiver->capture_once_start(event_queue);
+ if(irda_worker_signal_is_decoded(received_signal)) {
+ IrdaAppSignal signal(irda_worker_get_decoded_message(received_signal));
+ app->set_received_signal(signal);
+ } else {
+ const uint32_t* timings;
+ size_t timings_cnt;
+ irda_worker_get_raw_signal(received_signal, &timings, &timings_cnt);
+ IrdaAppSignal signal(timings, timings_cnt);
+ app->set_received_signal(signal);
+ }
+
+ irda_worker_set_received_signal_callback(app->get_irda_worker(), NULL);
+ IrdaAppEvent event;
+ event.type = IrdaAppEvent::Type::IrdaMessageReceived;
+ auto view_manager = app->get_view_manager();
+ view_manager->send_event(&event);
+}
+void IrdaAppSceneLearn::on_enter(IrdaApp* app) {
+ auto view_manager = app->get_view_manager();
auto popup = view_manager->get_popup();
+ auto worker = app->get_irda_worker();
+ irda_worker_set_context(worker, app);
+ irda_worker_set_received_signal_callback(worker, signal_received_callback);
+ irda_worker_start(worker);
+
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);
@@ -24,19 +50,27 @@ void IrdaAppSceneLearn::on_enter(IrdaApp* app) {
bool IrdaAppSceneLearn::on_event(IrdaApp* app, IrdaAppEvent* event) {
bool consumed = false;
- if(event->type == IrdaAppEvent::Type::Tick) {
+ switch(event->type) {
+ case IrdaAppEvent::Type::Tick:
consumed = true;
app->notify_red_blink();
- }
- if(event->type == IrdaAppEvent::Type::IrdaMessageReceived) {
+ break;
+ case IrdaAppEvent::Type::IrdaMessageReceived:
app->notify_success();
app->switch_to_next_scene_without_saving(IrdaApp::Scene::LearnSuccess);
+ irda_worker_stop(app->get_irda_worker());
+ break;
+ case IrdaAppEvent::Type::Back:
+ consumed = true;
+ irda_worker_stop(app->get_irda_worker());
+ app->switch_to_previous_scene();
+ break;
+ default:
+ furi_assert(0);
}
return consumed;
}
void IrdaAppSceneLearn::on_exit(IrdaApp* app) {
- auto transceiver = app->get_transceiver();
- transceiver->capture_stop();
}
diff --git a/applications/irda/scene/irda-app-scene-remote.cpp b/applications/irda/scene/irda-app-scene-remote.cpp
index dd1036f6..9260babe 100644
--- a/applications/irda/scene/irda-app-scene-remote.cpp
+++ b/applications/irda/scene/irda-app-scene-remote.cpp
@@ -64,8 +64,8 @@ bool IrdaAppSceneRemote::on_event(IrdaApp* app, IrdaAppEvent* event) {
default:
app->notify_click_and_blink();
auto remote_manager = app->get_remote_manager();
- auto message = remote_manager->get_button_data(event->payload.menu_index);
- app->get_transceiver()->send_message(message);
+ auto signal = remote_manager->get_button_data(event->payload.menu_index);
+ signal.transmit();
break;
}
} else if(event->type == IrdaAppEvent::Type::Back) {
diff --git a/applications/irda/scene/irda-app-scene-universal-common.cpp b/applications/irda/scene/irda-app-scene-universal-common.cpp
index 2eebe64f..53c8a246 100644
--- a/applications/irda/scene/irda-app-scene-universal-common.cpp
+++ b/applications/irda/scene/irda-app-scene-universal-common.cpp
@@ -63,7 +63,7 @@ bool IrdaAppSceneUniversalCommon::on_event(IrdaApp* app, IrdaAppEvent* event) {
auto view_manager = app->get_view_manager();
IrdaAppEvent tick_event = {.type = IrdaAppEvent::Type::Tick};
view_manager->send_event(&tick_event);
- if(brute_force.send_next_bruteforce(*app->get_transceiver())) {
+ if(brute_force.send_next_bruteforce()) {
progress_popup(app);
} else {
brute_force.stop_bruteforce();