Skip to content

Commit

Permalink
[FL-1505] Add RAW format (#576)
Browse files Browse the repository at this point in the history
* 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: あく <[email protected]>
  • Loading branch information
Albert Kharisov and skotopes authored Jul 16, 2021
1 parent a2dfa33 commit 13c5a8c
Show file tree
Hide file tree
Showing 50 changed files with 1,236 additions and 941 deletions.
174 changes: 121 additions & 53 deletions applications/irda/cli/irda-cli.cpp
Original file line number Diff line number Diff line change
@@ -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);
}
}

Expand All @@ -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) {
Expand All @@ -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() {
Expand Down
16 changes: 8 additions & 8 deletions applications/irda/irda-app-brute-force.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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()) {
Expand All @@ -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) {
Expand Down
3 changes: 1 addition & 2 deletions applications/irda/irda-app-brute-force.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@
#include "furi/check.h"
#include <unordered_map>
#include "irda-app-file-parser.hpp"
#include "irda-app-transceiver.hpp"


class IrdaAppBruteForce {
Expand All @@ -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);

Expand Down
Loading

0 comments on commit 13c5a8c

Please sign in to comment.