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-05-18 13:51:00 +0300
committerGitHub <noreply@github.com>2021-05-18 13:51:00 +0300
commit3114a2d4b8fc3ec13e5542377d65ac2c922bc7c3 (patch)
tree4246eba9cc9f44615fb6b6feb03e1619b15739a9 /applications/irda
parentba0419276e26ba6bf32688e0bf0af4b3c544dd1a (diff)
[FL-1156, FL-1249] Add IRDA encoder/decoder library (#451)
* Add cscope db generation * Add api-hal-irda, TIM2: HAL->LL * Add libirda: pwm decoding * Universal state machine * Add irda decoder library * Move IRDA capture to standalone tool * Add encoder/decoder samsung32, NEC, fix bugs * Port current App to new Irda lib * Fix clang format for test data * Port IRDA api-hal to f6 Co-authored-by: あく <alleteam@gmail.com>
Diffstat (limited to 'applications/irda')
-rw-r--r--[-rwxr-xr-x]applications/irda/irda_app.c (renamed from applications/irda/irda.c)257
-rw-r--r--applications/irda/irda_nec.c55
-rw-r--r--applications/irda/irda_nec.h4
-rw-r--r--applications/irda/irda_samsung.c47
-rw-r--r--applications/irda/irda_samsung.h4
5 files changed, 98 insertions, 269 deletions
diff --git a/applications/irda/irda.c b/applications/irda/irda_app.c
index 6944f276..2833fc71 100755..100644
--- a/applications/irda/irda.c
+++ b/applications/irda/irda_app.c
@@ -4,10 +4,8 @@
#include <input/input.h>
#include <cli/cli.h>
-#include "irda_nec.h"
-#include "irda_samsung.h"
-#include "irda_protocols.h"
-#include "irda-decoder/irda-decoder.h"
+#include <api-hal-irda.h>
+#include "irda.h"
typedef enum {
EventTypeTick,
@@ -15,24 +13,21 @@ typedef enum {
EventTypeRX,
} EventType;
-typedef struct {
- bool edge;
- uint32_t lasted;
-} RXValue;
+typedef IrdaMessage IrDAPacket;
typedef struct {
union {
InputEvent input;
- RXValue rx;
+ IrDAPacket rx;
} value;
EventType type;
} AppEvent;
-typedef struct {
- IrDAProtocolType protocol;
- uint32_t address;
- uint32_t command;
-} IrDAPacket;
+//typedef struct {
+// IrdaProtocol protocol;
+// uint32_t address;
+// uint32_t command;
+//} IrDAPacket;
#define IRDA_PACKET_COUNT 8
@@ -88,9 +83,9 @@ void render_carrier(Canvas* canvas, State* state) {
void input_carrier(AppEvent* event, State* state) {
if(event->value.input.key == InputKeyOk) {
if(event->value.input.type == InputTypePress) {
- irda_pwm_set(duty_cycles[state->carrier_duty_cycle_id], state->carrier_freq);
+ api_hal_irda_pwm_set(duty_cycles[state->carrier_duty_cycle_id], state->carrier_freq);
} else if(event->value.input.type == InputTypeRelease) {
- irda_pwm_stop();
+ api_hal_irda_pwm_stop();
}
}
@@ -117,27 +112,12 @@ void render_packet(Canvas* canvas, State* state) {
canvas_draw_str(canvas, 2, 25, "< packet mode");
canvas_draw_str(canvas, 2, 37, "? /\\ \\/ packet");
{
- const char* protocol;
-
- switch(state->packets[state->packet_id].protocol) {
- case IRDA_NEC:
- protocol = "NEC";
- break;
- case IRDA_SAMSUNG:
- protocol = "SAMS";
- break;
- case IRDA_UNKNOWN:
- default:
- protocol = "UNK";
- break;
- }
-
- char buf[24];
+ char buf[30];
sprintf(
buf,
"P[%d]: %s 0x%lX 0x%lX",
state->packet_id,
- protocol,
+ 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);
@@ -147,20 +127,12 @@ void render_packet(Canvas* canvas, State* state) {
void input_packet(AppEvent* event, State* state) {
if(event->value.input.key == InputKeyOk) {
if(event->value.input.type == InputTypeShort) {
- switch(state->packets[state->packet_id].protocol) {
- case IRDA_NEC:
- ir_nec_send(
- state->packets[state->packet_id].address,
- state->packets[state->packet_id].command);
- break;
- case IRDA_SAMSUNG:
- ir_samsung_send(
- state->packets[state->packet_id].address,
- state->packets[state->packet_id].command);
- break;
- default:
- break;
- }
+ 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);
}
}
@@ -201,39 +173,10 @@ static void input_callback(InputEvent* input_event, void* ctx) {
osMessageQueuePut(event_queue, &event, 0, 0);
}
-void irda_timer_capture_callback(void* htim, void* comp_ctx) {
- TIM_HandleTypeDef* _htim = (TIM_HandleTypeDef*)htim;
- osMessageQueueId_t event_queue = (osMessageQueueId_t)comp_ctx;
-
- if(_htim->Instance == TIM2) {
- AppEvent event;
- event.type = EventTypeRX;
- uint32_t channel;
-
- if(_htim->Channel == HAL_TIM_ACTIVE_CHANNEL_1) {
- // falling event
- event.value.rx.edge = false;
- channel = TIM_CHANNEL_1;
- } else if(_htim->Channel == HAL_TIM_ACTIVE_CHANNEL_2) {
- // rising event
- event.value.rx.edge = true;
- channel = TIM_CHANNEL_2;
- } else {
- // not our event
- return;
- }
-
- event.value.rx.lasted = HAL_TIM_ReadCapturedValue(_htim, channel);
- __HAL_TIM_SET_COUNTER(_htim, 0);
-
- osMessageQueuePut(event_queue, &event, 0, 0);
- }
-}
-
void init_packet(
State* state,
uint8_t index,
- IrDAProtocolType protocol,
+ IrdaProtocol protocol,
uint32_t address,
uint32_t command) {
if(index >= IRDA_PACKET_COUNT) return;
@@ -252,18 +195,15 @@ void irda_cli_cmd_rx(string_t args, void* context) {
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, 50);
+ osStatus status = osMessageQueueGet(app->cli_ir_rx_queue, &packet, 0, 5);
if(status == osOK) {
- if(packet.protocol == IRDA_NEC) {
- printf("NEC ");
- } else if(packet.protocol == IRDA_SAMSUNG) {
- printf("SAMSUNG ");
- }
printf(
- "Address:0x%02X%02X Command: 0x%02X\r\n",
- (uint8_t)(packet.address >> 8),
+ "%s "
+ "Address:0x%02X Command: 0x%02X %s\r\n",
+ irda_get_protocol_name(packet.protocol),
(uint8_t)packet.address,
- (uint8_t)packet.command);
+ (uint8_t)packet.command,
+ packet.repeat ? "R" : "");
}
}
printf("Interrupt command received");
@@ -275,7 +215,7 @@ void irda_cli_cmd_tx(string_t args, void* context) {
furi_assert(context);
ValueMutex* state_mutex = context;
// Read protocol name
- IrDAProtocolType protocol;
+ IrdaProtocol protocol;
string_t protocol_str;
string_init(protocol_str);
size_t ws = string_search_char(args, ' ');
@@ -289,9 +229,9 @@ void irda_cli_cmd_tx(string_t args, void* context) {
string_strim(args);
}
if(!string_cmp_str(protocol_str, "NEC")) {
- protocol = IRDA_NEC;
+ protocol = IrdaProtocolNEC;
} else if(!string_cmp_str(protocol_str, "SAMSUNG")) {
- protocol = IRDA_SAMSUNG;
+ protocol = IrdaProtocolSamsung32;
} else {
printf("Incorrect protocol. Valid protocols: `NEC`, `SAMSUNG`");
string_clear(protocol_str);
@@ -320,15 +260,34 @@ void irda_cli_cmd_tx(string_t args, void* context) {
printf("IRDA resources busy\r\n");
return;
}
- if(protocol == IRDA_NEC) {
- ir_nec_send(address, command);
- } else if(protocol == IRDA_SAMSUNG) {
- ir_samsung_send(address, command);
- }
+
+ IrdaMessage message = {
+ .protocol = protocol,
+ .address = address,
+ .command = command,
+ };
+ irda_send(&message, 1);
release_mutex(state_mutex, state);
return;
}
+typedef struct {
+ osMessageQueueId_t event_queue;
+ IrdaHandler* 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_assert(osOK == osMessageQueuePut(isr_context->event_queue, &event, 0, 0));
+ }
+}
+
int32_t irda(void* p) {
osMessageQueueId_t event_queue = osMessageQueueNew(32, sizeof(AppEvent), NULL);
@@ -347,17 +306,17 @@ int32_t irda(void* p) {
irda_app.cli_cmd_is_active = false;
for(uint8_t i = 0; i < IRDA_PACKET_COUNT; i++) {
- init_packet(&_state, i, IRDA_UNKNOWN, 0, 0);
+ init_packet(&_state, i, 0, 0, 0);
}
- init_packet(&_state, 0, IRDA_NEC, 0xFF00, 0x11);
- init_packet(&_state, 1, IRDA_NEC, 0xF708, 0x59);
- init_packet(&_state, 2, IRDA_NEC, 0xFF00, 0x10);
- init_packet(&_state, 3, IRDA_NEC, 0xFF00, 0x15);
- init_packet(&_state, 4, IRDA_NEC, 0xFF00, 0x25);
- init_packet(&_state, 5, IRDA_SAMSUNG, 0xE0E, 0xF30C);
- init_packet(&_state, 6, IRDA_SAMSUNG, 0xE0E, 0xF40D);
- init_packet(&_state, 7, IRDA_SAMSUNG, 0xE0E, 0xF50E);
+ 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))) {
@@ -377,13 +336,12 @@ int32_t irda(void* p) {
Gui* gui = furi_record_open("gui");
gui_add_view_port(gui, view_port, GuiLayerFullscreen);
- // setup irda rx timer
- tim_irda_rx_init();
-
- // add timer capture interrupt
- api_interrupt_add(irda_timer_capture_callback, InterruptTypeTimerCapture, event_queue);
-
- IrDADecoder* decoder = alloc_decoder();
+ 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) {
@@ -396,7 +354,6 @@ int32_t irda(void* p) {
// press events
if(event.value.input.type == InputTypeShort &&
event.value.input.key == InputKeyBack) {
- api_interrupt_remove(irda_timer_capture_callback, InterruptTypeTimerCapture);
release_mutex(&state_mutex, state);
// remove all view_ports create by app
@@ -404,14 +361,14 @@ int32_t irda(void* p) {
view_port_free(view_port);
// free decoder
- free_decoder(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");
+ api_hal_irda_rx_irq_deinit();
+ irda_free_decoder(isr_context.handler);
// exit
return 0;
@@ -437,58 +394,40 @@ int32_t irda(void* p) {
view_port_update(view_port);
} else if(event.type == EventTypeRX) {
- IrDADecoderOutputData out;
- const uint8_t out_data_length = 4;
- uint8_t out_data[out_data_length];
-
- out.data_length = out_data_length;
- out.data = out_data;
-
- api_hal_light_set(LightRed, event.value.rx.edge ? 0x00 : 0xFF);
-
- bool decoded =
- process_decoder(decoder, event.value.rx.edge, &event.value.rx.lasted, 1, &out);
-
- if(decoded) {
- // save only if we in packet mode
- State* state = (State*)acquire_mutex_block(&state_mutex);
- IrDAPacket packet;
- packet.protocol = IRDA_NEC;
- packet.address = out_data[1] << 8 | out_data[0];
- packet.command = out_data[2];
-
- if(state->mode_id == 1) {
- if(out.protocol == IRDA_NEC) {
- printf("P=NEC ");
- printf("A=0x%02X%02X ", out_data[1], out_data[0]);
- printf("C=0x%02X ", out_data[2]);
- if(out.flags & IRDA_REPEAT) {
- printf("R");
- }
- printf("\r\n");
- // Save packet to state
- memcpy(
- &(state->packets[state->packet_id]), &packet, sizeof(IrDAPacket));
- } else {
- printf("Unknown protocol\r\n");
- }
- }
- if(irda_app.cli_cmd_is_active) {
- // Send decoded packet to cli
- osMessageQueuePut(irda_app.cli_ir_rx_queue, &packet, 0, 0);
+ api_hal_light_set(LightRed, 0xFF);
+ delay(60);
+ api_hal_light_set(LightRed, 0xFF);
+
+ // 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);
+ release_mutex(&state_mutex, state);
+ view_port_update(view_port);
- // blink anyway
- api_hal_light_set(LightGreen, 0xFF);
- api_hal_light_set(LightGreen, 0x00);
- }
+ // blink anyway
+ api_hal_light_set(LightGreen, 0xFF);
+ api_hal_light_set(LightGreen, 0x00);
}
} else {
// event timeout
}
}
-} \ No newline at end of file
+}
diff --git a/applications/irda/irda_nec.c b/applications/irda/irda_nec.c
deleted file mode 100644
index 72f6230c..00000000
--- a/applications/irda/irda_nec.c
+++ /dev/null
@@ -1,55 +0,0 @@
-#include <furi.h>
-#include <api-hal.h>
-
-#include "irda_nec.h"
-#include "irda_protocols.h"
-
-void ir_nec_preambula(void) {
- // 9ms carrier + 4.5ms pause
- irda_pwm_set(NEC_DUTY_CYCLE, NEC_CARRIER_FREQUENCY);
- delay_us(9000);
- irda_pwm_stop();
- delay_us(4500);
-}
-
-void ir_nec_send_bit(bool bit) {
- // 0 is 562.5us carrier + 1687.5us pause
- // 1 is 562.5us carrier + 562.5us pause
- irda_pwm_set(NEC_DUTY_CYCLE, NEC_CARRIER_FREQUENCY);
- delay_us(562.5);
- irda_pwm_stop();
- if(bit) {
- delay_us(562.5);
- } else {
- delay_us(1687.5);
- }
-}
-
-void ir_nec_send_byte(uint8_t data) {
- for(uint8_t i = 0; i < 8; i++) {
- ir_nec_send_bit((data & (1 << (i))) != 0);
- }
-}
-
-void ir_nec_send(uint16_t addr, uint8_t data) {
- // nec protocol is:
- // preambula + addr + inverse addr + command + inverse command + bit pulse
- //
- // oddly enough, my analyzer (https://github.com/ukw100/IRMP) displays the reverse command
- // and I don’t know if this is my fault or a feature of the analyzer
- // TODO: check the dictionary and check with a known remote
- uint8_t nec_packet[4] = {~(uint8_t)addr, ~(uint8_t)(addr >> 8), ~(uint8_t)data, data};
-
- osKernelLock();
- __disable_irq();
-
- ir_nec_preambula();
- ir_nec_send_byte(nec_packet[0]);
- ir_nec_send_byte(nec_packet[1]);
- ir_nec_send_byte(nec_packet[2]);
- ir_nec_send_byte(nec_packet[3]);
- ir_nec_send_bit(1);
-
- __enable_irq();
- osKernelUnlock();
-} \ No newline at end of file
diff --git a/applications/irda/irda_nec.h b/applications/irda/irda_nec.h
deleted file mode 100644
index 5506b1e7..00000000
--- a/applications/irda/irda_nec.h
+++ /dev/null
@@ -1,4 +0,0 @@
-#pragma once
-#include <furi.h>
-
-void ir_nec_send(uint16_t addr, uint8_t data); \ No newline at end of file
diff --git a/applications/irda/irda_samsung.c b/applications/irda/irda_samsung.c
deleted file mode 100644
index 6be36a2b..00000000
--- a/applications/irda/irda_samsung.c
+++ /dev/null
@@ -1,47 +0,0 @@
-#include <furi.h>
-#include <api-hal.h>
-
-#include "irda_samsung.h"
-#include "irda_protocols.h"
-
-void ir_samsung_preambula(void) {
- irda_pwm_set(SAMSUNG_DUTY_CYCLE, SAMSUNG_CARRIER_FREQUENCY);
- delay_us(4500);
- irda_pwm_stop();
- delay_us(4500);
-}
-
-void ir_samsung_send_bit(bool bit) {
- irda_pwm_set(SAMSUNG_DUTY_CYCLE, SAMSUNG_CARRIER_FREQUENCY);
- delay_us(560);
- irda_pwm_stop();
- if(bit) {
- delay_us(1590);
- } else {
- delay_us(560);
- }
-}
-
-void ir_samsung_send_byte(uint8_t data) {
- for(uint8_t i = 0; i < 8; i++) {
- ir_samsung_send_bit((data & (1 << (i))) != 0);
- }
-}
-
-void ir_samsung_send(uint16_t addr, uint16_t data) {
- uint8_t samsung_packet[4] = {
- (uint8_t)addr, (uint8_t)(addr >> 8), (uint8_t)data, (uint8_t)(data >> 8)};
-
- osKernelLock();
- __disable_irq();
-
- ir_samsung_preambula();
- ir_samsung_send_byte(samsung_packet[0]);
- ir_samsung_send_byte(samsung_packet[1]);
- ir_samsung_send_byte(samsung_packet[2]);
- ir_samsung_send_byte(samsung_packet[3]);
- ir_samsung_send_bit(0);
-
- __enable_irq();
- osKernelUnlock();
-} \ No newline at end of file
diff --git a/applications/irda/irda_samsung.h b/applications/irda/irda_samsung.h
deleted file mode 100644
index 85f98abe..00000000
--- a/applications/irda/irda_samsung.h
+++ /dev/null
@@ -1,4 +0,0 @@
-#pragma once
-#include <furi.h>
-
-void ir_samsung_send(uint16_t addr, uint16_t data); \ No newline at end of file