From f12f505065058ff351fdd8b549abb7f9e7408e00 Mon Sep 17 00:00:00 2001 From: William Vallet Date: Wed, 8 May 2024 22:56:34 +0200 Subject: [PATCH] Add command conversion to IR decoder --- README.md | 14 +++++++++++++ include/ir_decoder.h | 2 +- src/ir_decoder.c | 48 +++++++++++++++++++++++++++++++++++++++----- src/main.c | 2 +- 4 files changed, 59 insertions(+), 7 deletions(-) diff --git a/README.md b/README.md index 531f5ac..f42abfd 100644 --- a/README.md +++ b/README.md @@ -52,3 +52,17 @@ The following control commands are: - **Volume up**: Increase the volume - **Volume down**: Decrease the volume - **Mute**: Cut off the volume + +## Infrared remote decoder + +Currently, NEC protocol is only supported. Remote NEC E553 is used as commands +base. Here are the following commands ID supported: + +Command | Code 0 +------------|:------: +Play/Pause | 0xF20D +Previous | 0xE31C +Next | 0xE718 +Volume Up | 0xF30C +Volume Down | 0xEF10 +Mute | 0xFB04 diff --git a/include/ir_decoder.h b/include/ir_decoder.h index 0b9cbe6..5b3fa6a 100644 --- a/include/ir_decoder.h +++ b/include/ir_decoder.h @@ -10,7 +10,7 @@ #include // Initialise IR decoder (RMT driver and parsing task). -extern void ir_decoder_init(uint8_t gpio_num); +extern void ir_decoder_init(uint8_t gpio_num, uint8_t codeset); // Event parser for NEC protocol. // Return true if parsing was successful, else false. extern bool ir_decoder_format_nec( diff --git a/src/ir_decoder.c b/src/ir_decoder.c index ef89db5..9fb1a83 100644 --- a/src/ir_decoder.c +++ b/src/ir_decoder.c @@ -3,6 +3,7 @@ * Copyright (c) 2024 William Vallet */ +#include "command.h" #include "ir_decoder.h" #include "driver/rmt_rx.h" #include "freertos/FreeRTOS.h" @@ -21,6 +22,7 @@ typedef struct { + uint8_t codeset; rmt_channel_handle_t rmt_handle; StaticTask_t task; StaticQueue_t queue; @@ -31,6 +33,30 @@ typedef struct static ir_decoder_handle_t ir_decoder_handle; +static const uint16_t ir_decoder_codeset[][COMMAND_NB_MAX] = { + // Play/Pause, Previous, Next , Mute , Volume+, Volume- + { 0xF20D , 0xE31C , 0xE718, 0xFB04, 0xF30C , 0xEF10 } +}; +static const size_t ir_decoder_codeset_nb = + sizeof(ir_decoder_codeset) / sizeof(COMMAND_NB_MAX * sizeof(uint16_t)); + +static bool ir_decoder_parse_codeset( + uint8_t codeset, uint16_t ir_cmd, command_t * const cmd) +{ + assert(codeset < ir_decoder_codeset_nb); + assert(cmd); + const uint16_t * const codeset_cfg = ir_decoder_codeset[codeset]; + for (size_t i = 0; i < COMMAND_NB_MAX; i++) + { + if (codeset_cfg[i] == ir_cmd) + { + *cmd = (command_t) i; + return true; + } + } + return false; +} + // Start RMT reception for specific decoder. static void ir_decoder_receive(ir_decoder_handle_t * const handle) { @@ -75,12 +101,21 @@ static void ir_decoder_task_handler(void *context) (QueueHandle_t) &handle->queue, &event, pdMS_TO_TICKS(1000))) { // Send to parsing method. - uint16_t address; - uint16_t command; - if (ir_decoder_format_nec(&event, &address, &command)) + uint16_t ir_address; + uint16_t ir_command; + if (ir_decoder_format_nec(&event, &ir_address, &ir_command)) { + command_t command; printf("IR decoder [NEC]: address=%04x command=%04x\r\n", - address, command); + ir_address, ir_command); + // Convert command if not a repeat and push it. + if (ir_command != 0u + && ir_decoder_parse_codeset( + handle->codeset, ir_command, &command) + && command_push(command)) + printf("IR decoder: pushed\r\n"); + else + printf("IR decoder: command ignored\r\n"); } else printf("IR decoder failed\r\n"); @@ -90,8 +125,9 @@ static void ir_decoder_task_handler(void *context) } } -void ir_decoder_init(uint8_t gpio_num) +void ir_decoder_init(uint8_t gpio_num, uint8_t codeset) { + assert(codeset < ir_decoder_codeset_nb); memset(&ir_decoder_handle, 0, sizeof(ir_decoder_handle_t)); const rmt_rx_channel_config_t rmt_cfg = { .gpio_num = gpio_num, @@ -102,6 +138,8 @@ void ir_decoder_init(uint8_t gpio_num) const rmt_rx_event_callbacks_t rmt_cbs = { .on_recv_done = ir_decoder_rmt_handler }; + // Register codeset. + ir_decoder_handle.codeset = codeset; // Initialise RX channel. ESP_ERROR_CHECK(rmt_new_rx_channel(&rmt_cfg, &ir_decoder_handle.rmt_handle)); // Initialise RX queue and register handler. diff --git a/src/main.c b/src/main.c index 28c2b02..f1ed02d 100644 --- a/src/main.c +++ b/src/main.c @@ -50,7 +50,7 @@ void app_main(void) // Initialise command processing. command_init(); // IR decoder configuration. - ir_decoder_init(BOARD_IO_IR_RX); + ir_decoder_init(BOARD_IO_IR_RX, 0); // Process. led_soft_t led_soft = SOFT_ON; while (1)