在http://blog.csdn.net/cuityanxi/article/details/18413725 中我有给出IR模拟的示例代码,但是只能作为参考;
若要在android中使用还有诸多问题,比如:android平台中有较多的中断会导致延时的误差很大,因此我有做改进,通过实验证实是很可靠的。
思路:用户空间:获取GPIO驱动设备句柄,将要发送的IR CODE write到dev中;
3、主要是通过raise_softirq使能软中断
4、中断处理函数,依据mscancode发送IR
若要在android中使用还有诸多问题,比如:android平台中有较多的中断会导致延时的误差很大,因此我有做改进,通过实验证实是很可靠的。
思路:用户空间:获取GPIO驱动设备句柄,将要发送的IR CODE write到dev中;
内核空间:利用内核中现有的GPIO驱动输出高低电平,使用内核软中断防止模拟时序时被中断导致延时误差大;GPIO设备读取数据后引发软中断产生模拟IR。
代码:
1. .h文件中的数据结构以及宏定义
struct IR_CODE
{
U16 uHead;
U8 uScancode;
U8 bOutreverse;
};
typedef struct GPIO_Reg GPIO_Reg_t;
typedef struct IR_CODE IR_CODE_t;
//add by yanxi for ir out start 140117
#define IR_HEAD0 0
#define IR_HEAD1 1
#define IR_TIME_BASE 2
#define IR_CODE_0 3
#define IR_CODE_1 4
#define IR_CODE_END 5
//38k = 26.315us
#define TIMER_9000US 342
#define TIMER_4500US 171
#define TIMER_560US 21
#define TIMER_1680US 63
//add by yanxi for ir out end 140117
2.当用户空间写数据到设备节点时, _MDrv_GPIO_Write被执行,通过copy_from_user 获取IR数据,并使用_MDrv_GPIO_SendIR发送IR
static ssize_t _MDrv_GPIO_Write(struct file *filp, const char __user *buf, size_t count, loff_t *f_pos)
{
IR_CODE_t mIR_CODE_t;
GPIO_PRINT("%s is invoked\n", __FUNCTION__);
copy_from_user(&mIR_CODE_t, (IR_CODE_t __user *) buf, sizeof(IR_CODE_t));
printk("\n yanxidebug uHead:%x uScancode:%x bOutreverse:%d",mIR_CODE_t.uHead,mIR_CODE_t.uScancode,mIR_CODE_t.bOutreverse);
_MDrv_GPIO_SendIR((unsigned int)mIR_CODE_t.uHead,(unsigned int)mIR_CODE_t.uScancode,(BOOL)mIR_CODE_t.bOutreverse);
return 0;
}
3、主要是通过raise_softirq使能软中断
static void _MDrv_GPIO_SendIR(unsigned int Head, int scancode, BOOL bOutreverse)
{
GPIO_PRINT("\n %s Head:%d scancode:%d bOutreverse:%d\n", __FUNCTION__,Head,scancode,bOutreverse);
mHead = Head;
mscancode = scancode;
mbOutreverse = bOutreverse;
raise_softirq(SENDIR_SOFTIRQ);
}
4、中断处理函数,依据mscancode发送IR
int irq_handle_function(int irq, void *device_id)
{
GPIO_PRINT("\n %s \n", __FUNCTION__);
S8 TranselateBitPos;
U8 Ir_trans_sta;
int mcount = 0;
unsigned int head = 0x007f;
U8 head0 = head >> 8;
U8 head1 = head &0x00ff;
U16 mkeycode = mscancode;
BOOL outreverse = true;
//init state
Ir_trans_sta=IR_HEAD0;
TranselateBitPos=32;
//send ir code
while(TranselateBitPos>=0)
{
mcount = 0;
switch(Ir_trans_sta)
{
case IR_HEAD0:
Ir_trans_sta= IR_HEAD1;
if(outreverse)
{
mcount = TIMER_9000US;
}
else
{
MHal_GPIO_Set_Low(0);
mdelay(9);
}
break;
case IR_HEAD1:
Ir_trans_sta= IR_TIME_BASE;
if(!outreverse)//outreverse true
{
mcount = TIMER_4500US;//output high ;38k
}
else
{
MHal_GPIO_Set_High(0);//outreverse false,low vol
mdelay(4);
udelay(500);
}
break;
case IR_TIME_BASE:
if(TranselateBitPos>24)
{
if( ((head0>>(32-TranselateBitPos)) & 0x1) == 0x1 )
Ir_trans_sta= IR_CODE_1;
else
Ir_trans_sta= IR_CODE_0;
}
else if(TranselateBitPos>16)
{
if( ((head1>>(24-TranselateBitPos)) & 0x1) == 0x1 )
Ir_trans_sta= IR_CODE_1;
else
Ir_trans_sta= IR_CODE_0;
}
else if(TranselateBitPos>8)
{
if( ((mkeycode>>(16-TranselateBitPos))&0x1) == 0x1 ){
Ir_trans_sta= IR_CODE_1;
}
else {
Ir_trans_sta= IR_CODE_0;
}
}
else if(TranselateBitPos>0)
{
if( ((mkeycode>>(8-TranselateBitPos))&0x1) == 0x1 )
Ir_trans_sta= IR_CODE_0;
else
Ir_trans_sta= IR_CODE_1;
}
else
{
Ir_trans_sta= IR_CODE_END;
}
if(!outreverse)
{
MHal_GPIO_Set_Low(0);
udelay(560);
}
else
{
mcount = TIMER_560US;
}
break;
case IR_CODE_0:
Ir_trans_sta= IR_TIME_BASE;
if(outreverse)
{
MHal_GPIO_Set_Low(0);
udelay(500);
}
else
{
mcount = TIMER_560US;
}
TranselateBitPos--;
break;
case IR_CODE_1:
Ir_trans_sta= IR_TIME_BASE;
if(outreverse)
{
MHal_GPIO_Set_Low(0);
udelay(1680);
}
else
{
mcount = TIMER_1680US;
}
TranselateBitPos--;
break;
case IR_CODE_END:
Ir_trans_sta= IR_HEAD0;
MHal_GPIO_Set_High(0);
TranselateBitPos=-1;//force to exit.
break;
default:break;
}
//38k generate
while(mcount-- > 0){
MHal_GPIO_Set_High(0);
MHal_GPIO_Set_High(0);
MHal_GPIO_Set_High(0);
MHal_GPIO_Set_High(0);
udelay(11);
MHal_GPIO_Set_Low(0);
MHal_GPIO_Set_Low(0);
MHal_GPIO_Set_Low(0);
MHal_GPIO_Set_Low(0);
udelay(11);
}
}
return IRQ_NONE;
}
完...