[FL-572][FL-577] Irda receive feature (#282)

* fix "state not acquired error"
* add InterruptTypeComparatorTrigger to interrupt mgr, use interrupt mgr in irda app
* separate init irda timer
* capture events buffer by app
* irda common decoder
* irda nec decoder realization
* finished work with decoder
* fix app path
* fix widget remove on exit
* nec receive, store and send
* init some packets
This commit is contained in:
DrZlo13
2021-01-08 02:28:35 +10:00
committed by GitHub
parent c70ed2f349
commit d65e9b04ce
12 changed files with 492 additions and 146 deletions

View File

@@ -0,0 +1,146 @@
#include "irda-decoder-nec.h"
#include "string.h"
const uint32_t PREAMBULA_HIGH_MIN = 9000 - 900;
const uint32_t PREAMBULA_HIGH_MAX = 9000 + 900;
const uint32_t PREAMBULA_LOW_MIN = 4500 - 450;
const uint32_t PREAMBULA_LOW_MAX = 4500 + 450;
const uint32_t PREAMBULA_RETRY_LOW_MIN = 2500 - 350;
const uint32_t PREAMBULA_RETRY_LOW_MAX = 2500 + 250;
const uint32_t BIT_HIGH_MIN = 560 - 100;
const uint32_t BIT_HIGH_MAX = 560 + 100;
const uint32_t BIT_LOW_ONE_MIN = 1690 - 200;
const uint32_t BIT_LOW_ONE_MAX = 1690 + 200;
const uint32_t BIT_LOW_ZERO_MIN = 560 - 100;
const uint32_t BIT_LOW_ZERO_MAX = 560 + 100;
#define SET_STATE(_state) \
{ decoder->state = _state; }
#define TIME_FIT(_prefix) ((time > _prefix##_MIN) && (time < _prefix##_MAX))
#ifndef MIN
#define MIN(a, b) ((a) < (b) ? (a) : (b))
#endif
bool save_decoder_nec_data(IrDANecDecoder* decoder, IrDADecoderOutputData* out) {
bool result = false;
if((decoder->data.simple.cmd + decoder->data.simple.cmd_inverse) == 0xFF) {
if(out->data_length < sizeof(IrDANecDataType)) {
out->flags |= IRDA_TOO_SHORT_BUFFER;
}
memcpy(out->data, &decoder->data.data, MIN(sizeof(IrDANecDataType), out->data_length));
result = true;
} else {
reset_decoder_nec(decoder);
}
return result;
}
bool process_decoder_nec(
IrDANecDecoder* decoder,
bool polarity,
uint32_t time,
IrDADecoderOutputData* out) {
bool error = true;
bool result = false;
switch(decoder->state) {
case(WAIT_PREAMBULA_HIGH):
if(polarity) {
if(TIME_FIT(PREAMBULA_HIGH)) {
SET_STATE(WAIT_PREAMBULA_LOW);
}
}
// any values before preambula start is correct
error = false;
break;
case(WAIT_PREAMBULA_LOW):
if(!polarity) {
if(TIME_FIT(PREAMBULA_LOW)) {
// new data, reset storage
reset_decoder_nec(decoder);
SET_STATE(WAIT_BIT_HIGH);
error = false;
} else if(TIME_FIT(PREAMBULA_RETRY_LOW)) {
// wait for data repeat command
SET_STATE(WAIT_RETRY_HIGH);
error = false;
}
}
break;
case(WAIT_RETRY_HIGH):
if(polarity) {
if(TIME_FIT(BIT_HIGH)) {
SET_STATE(WAIT_PREAMBULA_HIGH);
// repeat event
result = save_decoder_nec_data(decoder, out);
out->flags |= IRDA_REPEAT;
error = false;
}
}
break;
case(WAIT_BIT_HIGH):
if(polarity) {
if(TIME_FIT(BIT_HIGH)) {
SET_STATE(WAIT_BIT_LOW);
error = false;
}
}
break;
case(WAIT_BIT_STOP_HIGH):
if(polarity) {
if(TIME_FIT(BIT_HIGH)) {
SET_STATE(WAIT_PREAMBULA_HIGH);
// message end event
result = save_decoder_nec_data(decoder, out);
error = false;
}
}
break;
case(WAIT_BIT_LOW):
if(!polarity) {
int8_t bit = -1;
if(TIME_FIT(BIT_LOW_ZERO)) {
SET_STATE(WAIT_BIT_HIGH);
bit = 0;
error = false;
} else if(TIME_FIT(BIT_LOW_ONE)) {
SET_STATE(WAIT_BIT_HIGH);
bit = 1;
error = false;
}
if(bit != -1) {
decoder->data.data |= (bit << decoder->current_data_index);
decoder->current_data_index++;
if(decoder->current_data_index > 31) {
decoder->current_data_index = 0;
SET_STATE(WAIT_BIT_STOP_HIGH);
}
}
}
break;
}
if(error) reset_decoder_nec(decoder);
return result;
}
void reset_decoder_nec(IrDANecDecoder* decoder) {
decoder->state = WAIT_PREAMBULA_HIGH;
decoder->data.data = 0;
decoder->current_data_index = 0;
}

View File

@@ -0,0 +1,39 @@
#pragma once
#include <stdint.h>
#include <stdbool.h>
#include "irda-decoder-types.h"
typedef enum {
WAIT_PREAMBULA_HIGH,
WAIT_PREAMBULA_LOW,
WAIT_RETRY_HIGH,
WAIT_BIT_HIGH,
WAIT_BIT_LOW,
WAIT_BIT_STOP_HIGH,
} IrDANecDecoderState;
typedef struct {
uint8_t addr2;
uint8_t addr1;
uint8_t cmd_inverse;
uint8_t cmd;
} IrDANecData;
typedef uint32_t IrDANecDataType;
typedef struct {
union {
IrDANecData simple;
IrDANecDataType data;
} data;
uint8_t current_data_index;
IrDANecDecoderState state;
} IrDANecDecoder;
bool process_decoder_nec(
IrDANecDecoder* decoder,
bool polarity,
uint32_t time,
IrDADecoderOutputData* out);
void reset_decoder_nec(IrDANecDecoder* decoder);

View File

@@ -0,0 +1,12 @@
#pragma once
#include <stdint.h>
typedef enum { IRDA_UNKNOWN, IRDA_NEC, IRDA_SAMSUNG } IrDAProtocolType;
typedef enum { IRDA_REPEAT = (1 << 0), IRDA_TOO_SHORT_BUFFER = (1 << 1) } IrDAProtocolFlags;
typedef struct {
IrDAProtocolType protocol;
uint8_t flags;
uint8_t* data; /** < ponter to output data, filled by app */
uint32_t data_length; /** < output data length, filled by app */
} IrDADecoderOutputData;

View File

@@ -0,0 +1,41 @@
#include "irda-decoder.h"
IrDADecoder* alloc_decoder(void) {
IrDADecoder* decoder = malloc(sizeof(IrDADecoder));
// init decoders
reset_decoder_nec(&decoder->nec);
return decoder;
}
void free_decoder(IrDADecoder* decoder) {
free(decoder);
}
bool process_decoder(
IrDADecoder* decoder,
bool start_polarity,
uint32_t* timings,
uint32_t timings_length,
IrDADecoderOutputData* out) {
bool result = false;
// zero result
memset(out->data, 0, out->data_length);
out->protocol = IRDA_UNKNOWN;
out->flags = 0;
// process data
for(uint32_t timings_index = 0; timings_index < timings_length; timings_index++) {
if(process_decoder_nec(&decoder->nec, start_polarity, timings[timings_index], out)) {
out->protocol = IRDA_NEC;
result = true;
break;
}
start_polarity = !start_polarity;
}
return result;
}

View File

@@ -0,0 +1,18 @@
#pragma once
#include "flipper.h"
#include "flipper_v2.h"
#include "irda-decoder-nec.h"
#include "irda-decoder-types.h"
typedef struct {
IrDANecDecoder nec;
} IrDADecoder;
IrDADecoder* alloc_decoder(void);
void free_decoder(IrDADecoder* decoder);
bool process_decoder(
IrDADecoder* decoder,
bool start_polarity,
uint32_t* timings,
uint32_t timings_length,
IrDADecoderOutputData* out);