Skip to content

Commit

Permalink
Infrared: RCA protocol support (#2823)
Browse files Browse the repository at this point in the history
* RCA protocol support
* Add unit test

Co-authored-by: あく <[email protected]>
  • Loading branch information
xMasterX and skotopes authored Jul 11, 2023
1 parent 1361148 commit 14fc960
Show file tree
Hide file tree
Showing 10 changed files with 332 additions and 0 deletions.
12 changes: 12 additions & 0 deletions applications/debug/unit_tests/infrared/infrared_test.c
Original file line number Diff line number Diff line change
Expand Up @@ -425,6 +425,7 @@ MU_TEST(infrared_test_decoder_mixed) {
infrared_test_run_decoder(InfraredProtocolSamsung32, 1);
infrared_test_run_decoder(InfraredProtocolSIRC, 3);
infrared_test_run_decoder(InfraredProtocolKaseikyo, 1);
infrared_test_run_decoder(InfraredProtocolRCA, 1);
}

MU_TEST(infrared_test_decoder_nec) {
Expand Down Expand Up @@ -499,6 +500,15 @@ MU_TEST(infrared_test_decoder_kaseikyo) {
infrared_test_run_decoder(InfraredProtocolKaseikyo, 6);
}

MU_TEST(infrared_test_decoder_rca) {
infrared_test_run_decoder(InfraredProtocolRCA, 1);
infrared_test_run_decoder(InfraredProtocolRCA, 2);
infrared_test_run_decoder(InfraredProtocolRCA, 3);
infrared_test_run_decoder(InfraredProtocolRCA, 4);
infrared_test_run_decoder(InfraredProtocolRCA, 5);
infrared_test_run_decoder(InfraredProtocolRCA, 6);
}

MU_TEST(infrared_test_encoder_decoder_all) {
infrared_test_run_encoder_decoder(InfraredProtocolNEC, 1);
infrared_test_run_encoder_decoder(InfraredProtocolNECext, 1);
Expand All @@ -509,6 +519,7 @@ MU_TEST(infrared_test_encoder_decoder_all) {
infrared_test_run_encoder_decoder(InfraredProtocolRC5, 1);
infrared_test_run_encoder_decoder(InfraredProtocolSIRC, 1);
infrared_test_run_encoder_decoder(InfraredProtocolKaseikyo, 1);
infrared_test_run_encoder_decoder(InfraredProtocolRCA, 1);
}

MU_TEST_SUITE(infrared_test) {
Expand All @@ -527,6 +538,7 @@ MU_TEST_SUITE(infrared_test) {
MU_RUN_TEST(infrared_test_decoder_samsung32);
MU_RUN_TEST(infrared_test_decoder_necext1);
MU_RUN_TEST(infrared_test_decoder_kaseikyo);
MU_RUN_TEST(infrared_test_decoder_rca);
MU_RUN_TEST(infrared_test_decoder_mixed);
MU_RUN_TEST(infrared_test_encoder_decoder_all);
}
Expand Down
105 changes: 105 additions & 0 deletions assets/unit_tests/infrared/test_rca.irtest
Original file line number Diff line number Diff line change
@@ -0,0 +1,105 @@
Filetype: IR tests file
Version: 1
#
name: decoder_input1
type: raw
data: 1000000 3994 3969 552 1945 551 1945 552 1945 551 1945 552 946 551 947 550 1947 548 951 546 1953 542 979 518 1979 517 981 492 1006 491 1006 492 1006 492 1006 492 2005 492 2005 492 1006 492 2005 492 1006 492 2005 492 1006 492 2006 491
#
name: decoder_expected1
type: parsed_array
count: 1
#
protocol: RCA
address: 0F 00 00 00
command: 54 00 00 00
repeat: false
#
name: decoder_input2
type: raw
data: 1000000 4055 3941 605 1891 551 1947 550 1946 551 1946 551 947 551 947 550 1947 549 949 548 1951 545 1977 519 1978 519 1979 518 980 518 980 518 980 518 980 518 1979 518 1979 518 981 517 1979 518 980 518 980 518 980 518 980 518
#
name: decoder_expected2
type: parsed_array
count: 1
#
protocol: RCA
address: 0F 00 00 00
command: F4 00 00 00
repeat: false
#
name: decoder_input3
type: raw
data: 1000000 4027 3970 551 1946 550 1946 551 1946 551 1946 551 946 551 947 550 1947 549 949 547 1951 545 1978 518 1979 492 1006 492 1007 491 1006 492 1006 492 1006 492 2006 491 2006 491 1006 492 2006 491 1007 491 1007 491 1006 492 2006 491
#
name: decoder_expected3
type: parsed_array
count: 1
#
protocol: RCA
address: 0F 00 00 00
command: 74 00 00 00
repeat: false
#
name: decoder_input4
type: raw
data: 1000000 4021 3941 551 1946 550 1946 551 1946 551 1945 552 946 551 947 550 1947 549 950 547 1952 544 1977 519 979 519 1979 518 980 518 980 518 980 518 980 518 1979 518 1979 518 980 518 1979 518 980 518 980 518 1979 518 980 518
#
name: decoder_expected4
type: parsed_array
count: 1
#
protocol: RCA
address: 0F 00 00 00
command: B4 00 00 00
repeat: false
#
name: decoder_input5
type: raw
data: 1000000 4022 3941 551 1946 551 1946 577 1919 578 1919 578 920 552 946 551 1946 550 947 550 1949 547 1952 544 978 520 979 519 980 518 980 518 980 518 980 518 1979 518 1979 518 980 518 1979 518 980 518 980 518 1979 518 1980 517
#
name: decoder_expected5
type: parsed_array
count: 1
#
protocol: RCA
address: 0F 00 00 00
command: 34 00 00 00
repeat: false
#
name: decoder_input6
type: raw
data: 1000000 3995 3968 552 1944 552 1946 550 1946 550 1946 551 947 550 948 549 1947 549 1949 547 1952 544 1978 518 1979 492 2005 492 1006 492 1006 492 1006 492 1006 492 2005 492 2005 492 1006 492 1006 492 1006 492 1006 492 1006 492 1006 492
#
name: decoder_expected6
type: parsed_array
count: 1
#
protocol: RCA
address: 0F 00 00 00
command: FC 00 00 00
repeat: false
#
name: encoder_decoder_input1
type: parsed_array
count: 4
#
protocol: RCA
address: 0F 00 00 00
command: 74 00 00 00
repeat: false
#
protocol: RCA
address: 0F 00 00 00
command: B4 00 00 00
repeat: false
#
protocol: RCA
address: 0F 00 00 00
command: 34 00 00 00
repeat: false
#
protocol: RCA
address: 0F 00 00 00
command: FC 00 00 00
repeat: false
#
17 changes: 17 additions & 0 deletions documentation/file_formats/InfraredFileFormats.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,22 @@
# Infrared Flipper File Formats


## Supported protocols list for `type: parsed`
```
NEC
NECext
NEC42
NEC42ext
Samsung32
RC6
RC5
RC5X
SIRC
SIRC15
SIRC20
Kaseikyo
RCA
```
## Infrared Remote File Format

### Example
Expand Down
15 changes: 15 additions & 0 deletions lib/infrared/encoder_decoder/infrared.c
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
#include "rc6/infrared_protocol_rc6.h"
#include "sirc/infrared_protocol_sirc.h"
#include "kaseikyo/infrared_protocol_kaseikyo.h"
#include "rca/infrared_protocol_rca.h"

typedef struct {
InfraredAlloc alloc;
Expand Down Expand Up @@ -127,6 +128,20 @@ static const InfraredEncoderDecoder infrared_encoder_decoder[] = {
.free = infrared_encoder_kaseikyo_free},
.get_protocol_variant = infrared_protocol_kaseikyo_get_variant,
},
{
.decoder =
{.alloc = infrared_decoder_rca_alloc,
.decode = infrared_decoder_rca_decode,
.reset = infrared_decoder_rca_reset,
.check_ready = infrared_decoder_rca_check_ready,
.free = infrared_decoder_rca_free},
.encoder =
{.alloc = infrared_encoder_rca_alloc,
.encode = infrared_encoder_rca_encode,
.reset = infrared_encoder_rca_reset,
.free = infrared_encoder_rca_free},
.get_protocol_variant = infrared_protocol_rca_get_variant,
},
};

static int infrared_find_index_by_protocol(InfraredProtocol protocol);
Expand Down
1 change: 1 addition & 0 deletions lib/infrared/encoder_decoder/infrared.h
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ typedef enum {
InfraredProtocolSIRC15,
InfraredProtocolSIRC20,
InfraredProtocolKaseikyo,
InfraredProtocolRCA,
InfraredProtocolMAX,
} InfraredProtocol;

Expand Down
45 changes: 45 additions & 0 deletions lib/infrared/encoder_decoder/rca/infrared_decoder_rca.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
#include "infrared_protocol_rca_i.h"
#include <core/check.h>

InfraredMessage* infrared_decoder_rca_check_ready(void* ctx) {
return infrared_common_decoder_check_ready(ctx);
}

bool infrared_decoder_rca_interpret(InfraredCommonDecoder* decoder) {
furi_assert(decoder);

uint32_t* data = (void*)&decoder->data;

uint8_t address = (*data & 0xF);
uint8_t command = (*data >> 4) & 0xFF;
uint8_t address_inverse = (*data >> 12) & 0xF;
uint8_t command_inverse = (*data >> 16) & 0xFF;
uint8_t inverse_address_inverse = (uint8_t)~address_inverse & 0xF;
uint8_t inverse_command_inverse = (uint8_t)~command_inverse;

if((command == inverse_command_inverse) && (address == inverse_address_inverse)) {
decoder->message.protocol = InfraredProtocolRCA;
decoder->message.address = address;
decoder->message.command = command;
decoder->message.repeat = false;
return true;
}

return false;
}

void* infrared_decoder_rca_alloc(void) {
return infrared_common_decoder_alloc(&infrared_protocol_rca);
}

InfraredMessage* infrared_decoder_rca_decode(void* decoder, bool level, uint32_t duration) {
return infrared_common_decode(decoder, level, duration);
}

void infrared_decoder_rca_free(void* decoder) {
infrared_common_decoder_free(decoder);
}

void infrared_decoder_rca_reset(void* decoder) {
infrared_common_decoder_reset(decoder);
}
37 changes: 37 additions & 0 deletions lib/infrared/encoder_decoder/rca/infrared_encoder_rca.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
#include "infrared_protocol_rca_i.h"

#include <core/check.h>

void infrared_encoder_rca_reset(void* encoder_ptr, const InfraredMessage* message) {
furi_assert(encoder_ptr);
furi_assert(message);

InfraredCommonEncoder* encoder = encoder_ptr;
infrared_common_encoder_reset(encoder);

uint32_t* data = (void*)encoder->data;

uint8_t address = message->address;
uint8_t address_inverse = ~address;
uint8_t command = message->command;
uint8_t command_inverse = ~command;

*data = address & 0xF;
*data |= command << 4;
*data |= (address_inverse & 0xF) << 12;
*data |= command_inverse << 16;

encoder->bits_to_encode = encoder->protocol->databit_len[0];
}

void* infrared_encoder_rca_alloc(void) {
return infrared_common_encoder_alloc(&infrared_protocol_rca);
}

void infrared_encoder_rca_free(void* encoder_ptr) {
infrared_common_encoder_free(encoder_ptr);
}

InfraredStatus infrared_encoder_rca_encode(void* encoder_ptr, uint32_t* duration, bool* level) {
return infrared_common_encode(encoder_ptr, duration, level);
}
40 changes: 40 additions & 0 deletions lib/infrared/encoder_decoder/rca/infrared_protocol_rca.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
#include "infrared_protocol_rca_i.h"

const InfraredCommonProtocolSpec infrared_protocol_rca = {
.timings =
{
.preamble_mark = INFRARED_RCA_PREAMBLE_MARK,
.preamble_space = INFRARED_RCA_PREAMBLE_SPACE,
.bit1_mark = INFRARED_RCA_BIT1_MARK,
.bit1_space = INFRARED_RCA_BIT1_SPACE,
.bit0_mark = INFRARED_RCA_BIT0_MARK,
.bit0_space = INFRARED_RCA_BIT0_SPACE,
.preamble_tolerance = INFRARED_RCA_PREAMBLE_TOLERANCE,
.bit_tolerance = INFRARED_RCA_BIT_TOLERANCE,
.silence_time = INFRARED_RCA_SILENCE,
.min_split_time = INFRARED_RCA_MIN_SPLIT_TIME,
},
.databit_len[0] = 24,
.no_stop_bit = false,
.decode = infrared_common_decode_pdwm,
.encode = infrared_common_encode_pdwm,
.interpret = infrared_decoder_rca_interpret,
.decode_repeat = NULL,
.encode_repeat = NULL,
};

static const InfraredProtocolVariant infrared_protocol_variant_rca = {
.name = "RCA",
.address_length = 4,
.command_length = 8,
.frequency = INFRARED_COMMON_CARRIER_FREQUENCY,
.duty_cycle = INFRARED_COMMON_DUTY_CYCLE,
.repeat_count = INFRARED_RCA_REPEAT_COUNT_MIN,
};

const InfraredProtocolVariant* infrared_protocol_rca_get_variant(InfraredProtocol protocol) {
if(protocol == InfraredProtocolRCA)
return &infrared_protocol_variant_rca;
else
return NULL;
}
30 changes: 30 additions & 0 deletions lib/infrared/encoder_decoder/rca/infrared_protocol_rca.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
#pragma once

#include "../infrared_i.h"

/***************************************************************************************************
* RCA protocol description
* https://www.sbprojects.net/knowledge/ir/rca.php
****************************************************************************************************
* Preamble Preamble Pulse Distance/Width Pause Preamble Preamble
* mark space Modulation up to period repeat repeat
* mark space
*
* 4000 4000 24 bit ...8000 4000 4000
* __________ _ _ _ _ _ _ _ _ _ _ _ _ _ ___________
* ____ __________ _ _ _ __ __ __ _ _ __ __ _ _ ________________ ___________
*
***************************************************************************************************/

void* infrared_decoder_rca_alloc(void);
void infrared_decoder_rca_reset(void* decoder);
void infrared_decoder_rca_free(void* decoder);
InfraredMessage* infrared_decoder_rca_check_ready(void* decoder);
InfraredMessage* infrared_decoder_rca_decode(void* decoder, bool level, uint32_t duration);

void* infrared_encoder_rca_alloc(void);
InfraredStatus infrared_encoder_rca_encode(void* encoder_ptr, uint32_t* duration, bool* level);
void infrared_encoder_rca_reset(void* encoder_ptr, const InfraredMessage* message);
void infrared_encoder_rca_free(void* encoder_ptr);

const InfraredProtocolVariant* infrared_protocol_rca_get_variant(InfraredProtocol protocol);
30 changes: 30 additions & 0 deletions lib/infrared/encoder_decoder/rca/infrared_protocol_rca_i.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
#pragma once

#include "../common/infrared_common_i.h"

#define INFRARED_RCA_PREAMBLE_MARK 4000
#define INFRARED_RCA_PREAMBLE_SPACE 4000
#define INFRARED_RCA_BIT1_MARK 500
#define INFRARED_RCA_BIT1_SPACE 2000
#define INFRARED_RCA_BIT0_MARK 500
#define INFRARED_RCA_BIT0_SPACE 1000
#define INFRARED_RCA_REPEAT_PERIOD 8000
#define INFRARED_RCA_SILENCE INFRARED_RCA_REPEAT_PERIOD

#define INFRARED_RCA_MIN_SPLIT_TIME INFRARED_RCA_REPEAT_PAUSE_MIN
#define INFRARED_RCA_REPEAT_PAUSE_MIN 4000
#define INFRARED_RCA_REPEAT_PAUSE_MAX 150000
#define INFRARED_RCA_REPEAT_COUNT_MIN 1
#define INFRARED_RCA_REPEAT_MARK INFRARED_RCA_PREAMBLE_MARK
#define INFRARED_RCA_REPEAT_SPACE INFRARED_RCA_PREAMBLE_SPACE
#define INFRARED_RCA_PREAMBLE_TOLERANCE 200 // us
#define INFRARED_RCA_BIT_TOLERANCE 120 // us

extern const InfraredCommonProtocolSpec infrared_protocol_rca;

bool infrared_decoder_rca_interpret(InfraredCommonDecoder* decoder);
InfraredStatus infrared_decoder_rca_decode_repeat(InfraredCommonDecoder* decoder);
InfraredStatus infrared_encoder_rca_encode_repeat(
InfraredCommonEncoder* encoder,
uint32_t* duration,
bool* level);

0 comments on commit 14fc960

Please sign in to comment.