[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:
@@ -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;
|
||||
}
|
||||
|
||||
|
@@ -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
|
||||
|
@@ -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;
|
||||
}
|
||||
|
||||
|
@@ -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);
|
||||
|
||||
|
@@ -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);
|
||||
|
@@ -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);
|
||||
|
||||
|
@@ -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);
|
||||
}
|
||||
|
||||
|
@@ -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();
|
||||
}
|
||||
}
|
||||
|
||||
|
@@ -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);
|
||||
}
|
||||
|
||||
|
Reference in New Issue
Block a user