217 lines
6.2 KiB
C
217 lines
6.2 KiB
C
#include "ir_decoder.h"
|
|
#include "jiffies.h"
|
|
|
|
#define LOG_TAG_CONST PERI
|
|
#define LOG_TAG "[ir_decode]"
|
|
#define LOG_ERROR_ENABLE
|
|
#define LOG_DEBUG_ENABLE
|
|
#define LOG_INFO_ENABLE
|
|
/* #define LOG_DUMP_ENABLE */
|
|
#define LOG_CLI_ENABLE
|
|
|
|
#include "debug.h"
|
|
|
|
#define NEC_NBITS 32
|
|
#define NEC_TIME_DEVIATION 10 //允许10%偏差
|
|
#define NEC_UNIT_TIME 563
|
|
#define NEC_HEADER_TIME ((16 + 8) * NEC_UNIT_TIME)
|
|
#define NEC_BIT_0_TIME ((1 + 1) * NEC_UNIT_TIME)
|
|
#define NEC_BIT_1_TIME ((3 + 1) * NEC_UNIT_TIME)
|
|
#define NEC_REPEAT_TIME ((16 + 4) * NEC_UNIT_TIME)
|
|
#define NEC_TIMEOUT_MS 150 //150ms
|
|
|
|
enum nec_data_type {
|
|
NEC_ERROR = 0,
|
|
NEC_HEAD,
|
|
NEC_BIT_1,
|
|
NEC_BIT_0,
|
|
NEC_REPEAT,
|
|
};
|
|
struct ir_decode_t {
|
|
u32 jiffies; //记录当前系统时间
|
|
u32 ir_data; //存储接收到的红外数据,4*8bit = (cmd_not + cmd +addr_not + addr)
|
|
u8 capture_tid; //用于捕获功能的tiemr_id
|
|
u8 bit_count; //有效bit个数
|
|
u8 command_count; //有效命令个数
|
|
};
|
|
static struct ir_decode_t _ir_decode;
|
|
static struct ir_decode_t *ir_decode = &_ir_decode;
|
|
static u32 get_cur_jiffies()
|
|
{
|
|
return jiffies;
|
|
}
|
|
static u32 jiffies_timeout_check()
|
|
{
|
|
u32 jiffies_cur = get_cur_jiffies();
|
|
int jiffies_diff = jiffies_cur - ir_decode->jiffies;
|
|
ir_decode->jiffies = jiffies_cur;
|
|
//判断是否溢出
|
|
if (jiffies_diff < 0) {
|
|
jiffies_diff += 0xffffffff;
|
|
}
|
|
//判断两次下降沿间隔时间是否超时
|
|
if (jiffies_to_msecs(jiffies_diff) >= NEC_TIMEOUT_MS) {
|
|
return 1;
|
|
} else {
|
|
return 0;
|
|
}
|
|
}
|
|
static u32 is_time_within(u32 t, u32 center, u32 deviation)
|
|
{
|
|
if (__builtin_abs(((int)t - (int)center)) < (center * deviation / 100)) {
|
|
return 1;
|
|
} else {
|
|
return 0;
|
|
}
|
|
}
|
|
static u32 ir_decoder_pulse_check(u32 us)
|
|
{
|
|
u32 type;
|
|
if (is_time_within(us, NEC_HEADER_TIME, NEC_TIME_DEVIATION)) {
|
|
type = NEC_HEAD;
|
|
} else if (is_time_within(us, NEC_BIT_0_TIME, NEC_TIME_DEVIATION)) {
|
|
type = NEC_BIT_0;
|
|
} else if (is_time_within(us, NEC_BIT_1_TIME, NEC_TIME_DEVIATION)) {
|
|
type = NEC_BIT_1;
|
|
} else if (is_time_within(us, NEC_REPEAT_TIME, NEC_TIME_DEVIATION)) {
|
|
type = NEC_REPEAT;
|
|
} else {
|
|
type = NEC_ERROR;
|
|
}
|
|
log_debug("us = %d, type = %d\n", us, type);
|
|
return type;
|
|
}
|
|
static void ir_decoder_bit_count_check()
|
|
{
|
|
if (ir_decode->bit_count == NEC_NBITS) {
|
|
ir_decode->command_count++;
|
|
log_debug("ir_data:0x%08x, command_count:%d\n", ir_decode->ir_data, ir_decode->command_count);
|
|
}
|
|
}
|
|
|
|
static void ir_decode_irq(u32 tid, void *arg)
|
|
{
|
|
u32 us = gptimer_get_capture_cnt2us(tid);
|
|
//超时或第一个边沿直接退出
|
|
if (jiffies_timeout_check()) {
|
|
return;
|
|
}
|
|
u32 type = ir_decoder_pulse_check(us);
|
|
|
|
switch (type) {
|
|
case NEC_HEAD:
|
|
ir_decode->bit_count = 0;
|
|
ir_decode->command_count = 0;
|
|
break;
|
|
case NEC_BIT_1:
|
|
ir_decode->ir_data >>= 1;
|
|
ir_decode->ir_data |= 0x80000000;
|
|
ir_decode->bit_count++;
|
|
ir_decoder_bit_count_check();
|
|
break;
|
|
case NEC_BIT_0:
|
|
ir_decode->ir_data >>= 1;
|
|
ir_decode->bit_count++;
|
|
ir_decoder_bit_count_check();
|
|
break;
|
|
case NEC_REPEAT:
|
|
ir_decoder_bit_count_check();
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
}
|
|
|
|
void ir_decoder_init(const struct gptimer_config *gt_cfg)
|
|
{
|
|
log_info("%s()\n", __func__);
|
|
memset(ir_decode, 0, sizeof(struct ir_decode_t));
|
|
ir_decode->jiffies = get_cur_jiffies();
|
|
#ifdef TCFG_IR_DECODER_TID
|
|
ir_decode->capture_tid = gptimer_init(TCFG_IR_DECODER_TID, gt_cfg); //用户配置固定timer
|
|
#else
|
|
ir_decode->capture_tid = gptimer_init(TIMERx, gt_cfg); //内部分配空闲timer
|
|
#endif
|
|
log_info("ir_decode->capture_tid = %d\n", ir_decode->capture_tid);
|
|
if (gt_cfg->mode == GPTIMER_MODE_CAPTURE_EDGE_RISE) {
|
|
gpio_set_mode(gt_cfg->capture.port, gt_cfg->capture.pin, PORT_INPUT_PULLDOWN_10K);//开下拉
|
|
} else if (gt_cfg->mode == GPTIMER_MODE_CAPTURE_EDGE_FALL) {
|
|
gpio_set_mode(gt_cfg->capture.port, gt_cfg->capture.pin, PORT_INPUT_PULLUP_10K);//开上拉
|
|
}
|
|
if (gt_cfg->irq_cb == NULL) {
|
|
gptimer_set_irq_callback(ir_decode->capture_tid, ir_decode_irq);
|
|
}
|
|
gptimer_start(ir_decode->capture_tid);
|
|
}
|
|
|
|
void ir_decoder_deinit()
|
|
{
|
|
gptimer_deinit(ir_decode->capture_tid);
|
|
}
|
|
|
|
u32 ir_decoder_get_data(void)
|
|
{
|
|
u32 data = -1;
|
|
if (ir_decode->command_count) {
|
|
ir_decode->command_count--;
|
|
data = ir_decode->ir_data;
|
|
}
|
|
return data;
|
|
}
|
|
u32 ir_decoder_get_command_value(void)
|
|
{
|
|
u32 data = ir_decoder_get_data();
|
|
if (data == -1) {
|
|
return -1;
|
|
}
|
|
u8 cmd = (data >> 16) & 0xff;
|
|
u8 cmd_not = (data >> 24) & 0xff;
|
|
if ((cmd ^ cmd_not) != 0xff) {
|
|
cmd = -1;
|
|
}
|
|
return cmd;
|
|
}
|
|
u32 ir_decoder_get_command_value_uncheck(void)
|
|
{
|
|
u32 data = ir_decoder_get_data();
|
|
if (data == -1) {
|
|
return -1;
|
|
}
|
|
u8 cmd = (data >> 16) & 0xff;
|
|
return cmd;
|
|
}
|
|
u32 ir_decoder_get_address_value(void)
|
|
{
|
|
u32 data = ir_decoder_get_data();
|
|
if (data == -1) {
|
|
return -1;
|
|
}
|
|
u8 addr = (data >> 0) & 0xff;
|
|
u8 addr_not = (data >> 8) & 0xff;
|
|
if ((addr ^ addr_not) != 0xff) {
|
|
addr = (u8) - 1;
|
|
}
|
|
return addr;
|
|
}
|
|
u32 ir_decoder_get_address_value_uncheck(void)
|
|
{
|
|
u32 data = ir_decoder_get_data();
|
|
if (data == -1) {
|
|
return -1;
|
|
}
|
|
u8 addr = (data >> 0) & 0xff;
|
|
return addr;
|
|
}
|
|
void ir_decoder_dump()
|
|
{
|
|
printf("header:%d, header_min:%d, header_max:%d\n",
|
|
NEC_HEADER_TIME, (NEC_HEADER_TIME * (100 - NEC_TIME_DEVIATION) / 100), (NEC_HEADER_TIME * (100 + NEC_TIME_DEVIATION) / 100));
|
|
printf("bit0:%d, bit0_min:%d, bit0_max:%d\n",
|
|
NEC_BIT_0_TIME, (NEC_BIT_0_TIME * (100 - NEC_TIME_DEVIATION) / 100), (NEC_BIT_0_TIME * (100 + NEC_TIME_DEVIATION) / 100));
|
|
printf("bit1:%d, bit1_min:%d, bit1_max:%d\n",
|
|
NEC_BIT_1_TIME, (NEC_BIT_1_TIME * (100 - NEC_TIME_DEVIATION) / 100), (NEC_BIT_1_TIME * (100 + NEC_TIME_DEVIATION) / 100));
|
|
printf("repeat:%d, repeat_min:%d, repeat_max:%d\n",
|
|
NEC_REPEAT_TIME, (NEC_REPEAT_TIME * (100 - NEC_TIME_DEVIATION) / 100), (NEC_REPEAT_TIME * (100 + NEC_TIME_DEVIATION) / 100));
|
|
}
|
|
|