前不久接触到红外NEC编码,闲来无事,就想在Android上面实现红外NEC编码的解析(如果不了解NEC编码的同学,可以找度娘,相关资料很多很详细)。由于接收管的原因,收到的红外波形和发射的红外波形是一样的,比如:接收到的引导码是9ms的高电平和4.5ms的低电平,重复码是9ms高电平和2.25ms低电平,0是0.56ms高电平和0.56ms低电平,1是0.56高电平和1.69ms低电平,另外每个编码发送完成后会有一个高电平表示结束(可以用示波器查看)。
具体的思路:
1、数据采集,中断采用边沿触发的方式,两次中断间隔时间相减就是高或者低电平持续时间,然后把记录到的数据放入一个queue里面,queue使用的是kernel自带的kfifo,这样就获得数据,然后唤醒下面2中的kernel thread处理queue里面的数据
2、数据处理,创建一个kernel thread,在线程里面不断的读取queue里面的数据,先通过 process_ir_rx_cmd 判断是引导码还是重复码,如果是引导码接下来使用 process_ir_rx_data 解析处理相关数据,如果是重复码就上报之前的数据即可。
具体的代码如下:
#include <linux/module.h>
#include <linux/interrupt.h>
#include <linux/of.h>
#include <linux/of_irq.h>
#include <linux/platform_device.h>
#include <linux/pinctrl/consumer.h>
#include <linux/time.h>
#include <linux/kfifo.h>
#include <linux/kthread.h>
#include <linux/wait.h>
#include <linux/input.h>
static struct platform_device *ir_rx_dev = NULL;
static int irq_num;
static unsigned int trigger_level;
static struct task_struct *ir_rx_ts;
static struct input_dev *ir_rx_input_dev=NULL;
//定义相关命令和数据解析的状态
enum ir_rx_state{
IR_RX_OK,
IR_RX_CMD_START,
IR_RX_CMD_REPEAT,
IR_RX_CMD_ERROR,
IR_RX_DATA_0,
IR_RX_DATA_1,
IR_RX_DATA_ERR,
};
//用一个二维数组保存接收到的红外命令和底层键值得对应关系
static unsigned int data_key_map[18][2]={
{66,KEY_0},
{22,KEY_1},
{25,KEY_2},
{13,KEY_3},
{12,KEY_4},
{24,KEY_5},
{94,KEY_6},
{8,KEY_7},
{28,KEY_8},
{90,KEY_9},
{7,KEY_VOLUMEDOWN},
{9,KEY_VOLUMEUP},
{70,KEY_UP},
{21,KEY_DOWN},
{68,KEY_LEFT},
{67,KEY_RIGHT},
{64,KEY_PAUSE},
{74,KEY_BACK},
};
//用来保存数据 time和高低电平的状态
typedef struct{
struct timespec tv;
int level;//1 falling 2 rasing