[FL-1250, FL-1252, FL-1323, FL-1324] New IRDA Application (part 1) (#497)

* Add new IrdaApp (half ready), add ButtonMenu

* Fix NEC's extension

* clang-format

* Fix leak

* Add submenu optional header

* IRDA: add Edit button

* clang-format

* IrdaApp: Fix scene flow

* Add IRDA NEC extended protocol

* IRDA: Add address/command length

Co-authored-by: SG <who.just.the.doctor@gmail.com>
This commit is contained in:
Albert Kharisov
2021-06-02 18:16:05 +03:00
committed by GitHub
parent d040515f84
commit 31c31db479
62 changed files with 2568 additions and 375 deletions

View File

@@ -12,6 +12,7 @@ struct IrdaHandler {
typedef struct {
IrdaAlloc alloc;
IrdaDecode decode;
IrdaReset reset;
IrdaFree free;
} IrdaDecoders;
@@ -24,6 +25,8 @@ typedef struct {
const char* name;
IrdaDecoders decoder;
IrdaEncoders encoder;
uint8_t address_length;
uint8_t command_length;
} IrdaProtocolImplementation;
@@ -35,9 +38,12 @@ static const IrdaProtocolImplementation irda_protocols[] = {
.decoder = {
.alloc = irda_decoder_samsung32_alloc,
.decode = irda_decoder_samsung32_decode,
.reset = irda_decoder_samsung32_reset,
.free = irda_decoder_samsung32_free},
.encoder = {
.encode = irda_encoder_samsung32_encode}
.encode = irda_encoder_samsung32_encode},
.address_length = 2,
.command_length = 2,
},
// #1
{ .protocol = IrdaProtocolNEC,
@@ -45,9 +51,25 @@ static const IrdaProtocolImplementation irda_protocols[] = {
.decoder = {
.alloc = irda_decoder_nec_alloc,
.decode = irda_decoder_nec_decode,
.reset = irda_decoder_nec_reset,
.free = irda_decoder_nec_free},
.encoder = {
.encode = irda_encoder_nec_encode}
.encode = irda_encoder_nec_encode},
.address_length = 2,
.command_length = 2,
},
// #2
{ .protocol = IrdaProtocolNECext,
.name = "NECext",
.decoder = {
.alloc = irda_decoder_necext_alloc,
.decode = irda_decoder_nec_decode,
.reset = irda_decoder_nec_reset,
.free = irda_decoder_nec_free},
.encoder = {
.encode = irda_encoder_necext_encode},
.address_length = 4,
.command_length = 2,
},
};
@@ -93,6 +115,12 @@ void irda_free_decoder(IrdaHandler* handler) {
free(handler);
}
void irda_reset_decoder(IrdaHandler* handler) {
for (int i = 0; i < COUNT_OF(irda_protocols); ++i) {
irda_protocols[i].decoder.reset(handler->ctx[i]);
}
}
void irda_send(const IrdaMessage* message, int times) {
furi_assert(message);
@@ -109,3 +137,11 @@ const char* irda_get_protocol_name(IrdaProtocol protocol) {
return irda_protocols[protocol].name;
}
uint8_t irda_get_protocol_address_length(IrdaProtocol protocol) {
return irda_protocols[protocol].address_length;
}
uint8_t irda_get_protocol_command_length(IrdaProtocol protocol) {
return irda_protocols[protocol].command_length;
}

View File

@@ -13,6 +13,7 @@ typedef struct IrdaHandler IrdaHandler;
typedef enum {
IrdaProtocolSamsung32 = 0,
IrdaProtocolNEC = 1,
IrdaProtocolNECext = 2,
} IrdaProtocol;
typedef struct {
@@ -50,6 +51,13 @@ const IrdaMessage* irda_decode(IrdaHandler* handler, bool level, uint32_t durati
*/
void irda_free_decoder(IrdaHandler* handler);
/**
* Reset IRDA decoder.
*
* \param[in] handler - handler to irda decoders. Should be aquired with \c irda_alloc_decoder().
*/
void irda_reset_decoder(IrdaHandler* handler);
/**
* Send message over IRDA.
*
@@ -66,6 +74,22 @@ void irda_send(const IrdaMessage* message, int times);
*/
const char* irda_get_protocol_name(IrdaProtocol protocol);
/**
* Get address length by protocol enum.
*
* \param[in] protocol - protocol identifier.
* \return length of address in nibbles.
*/
uint8_t irda_get_protocol_address_length(IrdaProtocol protocol);
/**
* Get command length by protocol enum.
*
* \param[in] protocol - protocol identifier.
* \return length of command in nibbles.
*/
uint8_t irda_get_protocol_command_length(IrdaProtocol protocol);
#ifdef __cplusplus
}
#endif

View File

@@ -1,3 +1,4 @@
#include "irda_common_decoder_i.h"
#include <stdbool.h>
#include <furi.h>
#include "irda_i.h"
@@ -164,3 +165,12 @@ void irda_common_decoder_free(void* decoder) {
free(decoder);
}
void irda_common_decoder_reset(void* decoder) {
furi_assert(decoder);
IrdaCommonDecoder* common_decoder = decoder;
common_decoder->state = IrdaCommonStateWaitPreamble;
common_decoder->timings_cnt = 0;
common_decoder->databit_cnt = 0;
}

View File

@@ -68,5 +68,6 @@ static inline void shift_left_array(uint32_t *array, uint32_t len, uint32_t shif
IrdaMessage* irda_common_decode(IrdaCommonDecoder *decoder, bool level, uint32_t duration);
void* irda_common_decoder_alloc(const IrdaCommonProtocolSpec *protocol);
void irda_common_decoder_free(void* decoder);
void irda_common_decoder_reset(void* decoder);
DecodeStatus irda_common_decode_pdwm(IrdaCommonDecoder* decoder);

View File

@@ -7,6 +7,7 @@
typedef void* (*IrdaAlloc) (void);
typedef IrdaMessage* (*IrdaDecode) (void* ctx, bool level, uint32_t duration);
typedef void (*IrdaReset) (void*);
typedef void (*IrdaFree) (void*);
typedef void (*IrdaEncode)(uint32_t address, uint32_t command, bool repeat);

View File

@@ -36,7 +36,10 @@
#define IRDA_NEC_BIT_TOLERANCE 120 // us
void* irda_decoder_nec_alloc(void);
void* irda_decoder_necext_alloc(void);
void irda_encoder_nec_encode(uint32_t address, uint32_t command, bool repeat);
void irda_encoder_necext_encode(uint32_t address, uint32_t command, bool repeat);
void irda_decoder_nec_reset(void* decoder);
void irda_decoder_nec_free(void* decoder);
IrdaMessage* irda_decoder_nec_decode(void* decoder, bool level, uint32_t duration);
@@ -73,6 +76,7 @@ IrdaMessage* irda_decoder_nec_decode(void* decoder, bool level, uint32_t duratio
void* irda_decoder_samsung32_alloc(void);
void irda_encoder_samsung32_encode(uint32_t address, uint32_t command, bool repeat);
void irda_decoder_samsung32_reset(void* decoder);
void irda_decoder_samsung32_free(void* decoder);
IrdaMessage* irda_decoder_samsung32_decode(void* decoder, bool level, uint32_t duration);

View File

@@ -3,9 +3,12 @@
#include <furi.h>
#include "../irda_i.h"
static bool interpret_nec(IrdaCommonDecoder* decoder);
static bool interpret_necext(IrdaCommonDecoder* decoder);
static DecodeStatus decode_repeat_nec(IrdaCommonDecoder* decoder);
static const IrdaCommonProtocolSpec protocol_nec = {
{
IRDA_NEC_PREAMBULE_MARK,
@@ -23,15 +26,33 @@ static const IrdaCommonProtocolSpec protocol_nec = {
decode_repeat_nec,
};
static const IrdaCommonProtocolSpec protocol_necext = {
{
IRDA_NEC_PREAMBULE_MARK,
IRDA_NEC_PREAMBULE_SPACE,
IRDA_NEC_BIT1_MARK,
IRDA_NEC_BIT1_SPACE,
IRDA_NEC_BIT0_MARK,
IRDA_NEC_BIT0_SPACE,
IRDA_NEC_PREAMBLE_TOLERANCE,
IRDA_NEC_BIT_TOLERANCE,
},
32,
irda_common_decode_pdwm,
interpret_necext,
decode_repeat_nec,
};
static bool interpret_nec(IrdaCommonDecoder* decoder) {
furi_assert(decoder);
bool result = false;
uint16_t address = decoder->data[0] | (decoder->data[1] << 8);
uint8_t address = decoder->data[0];
uint8_t address_inverse = decoder->data[1];
uint8_t command = decoder->data[2];
uint8_t command_inverse = decoder->data[3];
if((command == (uint8_t)~command_inverse)) {
if ((command == (uint8_t) ~command_inverse) && (address == (uint8_t) ~address_inverse)) {
decoder->message.command = command;
decoder->message.address = address;
decoder->message.repeat = false;
@@ -41,6 +62,24 @@ static bool interpret_nec(IrdaCommonDecoder* decoder) {
return result;
}
// Some NEC's extensions allow 16 bit address
static bool interpret_necext(IrdaCommonDecoder* decoder) {
furi_assert(decoder);
bool result = false;
uint8_t command = decoder->data[2];
uint8_t command_inverse = decoder->data[3];
if(command == (uint8_t)~command_inverse) {
decoder->message.command = command;
decoder->message.address = decoder->data[0] | (decoder->data[1] << 8);
decoder->message.repeat = false;
result = true;
}
return result;
}
// timings start from Space (delay between message and repeat)
static DecodeStatus decode_repeat_nec(IrdaCommonDecoder* decoder) {
furi_assert(decoder);
@@ -69,6 +108,10 @@ void* irda_decoder_nec_alloc(void) {
return irda_common_decoder_alloc(&protocol_nec);
}
void* irda_decoder_necext_alloc(void) {
return irda_common_decoder_alloc(&protocol_necext);
}
IrdaMessage* irda_decoder_nec_decode(void* decoder, bool level, uint32_t duration) {
return irda_common_decode(decoder, level, duration);
}
@@ -76,3 +119,8 @@ IrdaMessage* irda_decoder_nec_decode(void* decoder, bool level, uint32_t duratio
void irda_decoder_nec_free(void* decoder) {
irda_common_decoder_free(decoder);
}
void irda_decoder_nec_reset(void* decoder) {
irda_common_decoder_reset(decoder);
}

View File

@@ -42,3 +42,21 @@ void irda_encoder_nec_encode(uint32_t addr, uint32_t cmd, bool repeat) {
}
}
// Some NEC's extensions allow 16 bit address
void irda_encoder_necext_encode(uint32_t addr, uint32_t cmd, bool repeat) {
uint16_t address = addr & 0xFFFF;
uint8_t command = cmd & 0xFF;
uint8_t command_inverse = (uint8_t) ~command;
if (!repeat) {
irda_encode_nec_preamble();
irda_encode_byte(&encoder_timings, (uint8_t) address);
irda_encode_byte(&encoder_timings, (uint8_t) (address >> 8));
irda_encode_byte(&encoder_timings, command);
irda_encode_byte(&encoder_timings, command_inverse);
irda_encode_bit(&encoder_timings, 1);
} else {
irda_encode_nec_repeat();
}
}

View File

@@ -85,3 +85,7 @@ void irda_decoder_samsung32_free(void* decoder) {
irda_common_decoder_free(decoder);
}
void irda_decoder_samsung32_reset(void* decoder) {
irda_common_decoder_reset(decoder);
}