[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:
146
applications/irda/irda-decoder/irda-decoder-nec.c
Normal file
146
applications/irda/irda-decoder/irda-decoder-nec.c
Normal 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;
|
||||
}
|
39
applications/irda/irda-decoder/irda-decoder-nec.h
Normal file
39
applications/irda/irda-decoder/irda-decoder-nec.h
Normal 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);
|
12
applications/irda/irda-decoder/irda-decoder-types.h
Normal file
12
applications/irda/irda-decoder/irda-decoder-types.h
Normal 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;
|
41
applications/irda/irda-decoder/irda-decoder.c
Normal file
41
applications/irda/irda-decoder/irda-decoder.c
Normal 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;
|
||||
}
|
18
applications/irda/irda-decoder/irda-decoder.h
Normal file
18
applications/irda/irda-decoder/irda-decoder.h
Normal 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);
|
Reference in New Issue
Block a user