flipperzero-firmware/applications/irda/irda-decoder/irda-decoder-nec.c

146 lines
4.0 KiB
C
Raw Normal View History

#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;
}