#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/fs.h>
#include <linux/init.h>
#include <linux/delay.h>
#include <linux/poll.h>
#include <linux/irq.h>
#include <asm/irq.h>
#include <asm/io.h>
#include <linux/interrupt.h>
#include <asm/uaccess.h>
#include <mach/hardware.h>
#include <linux/platform_device.h>
#include <linux/cdev.h>
#include <linux/miscdevice.h>
#include <plat/regs-timer.h>
#include <asm/mach/time.h>
#include <linux/clk.h>
#include <asm/io.h>
#include <plat/gpio-cfg.h>
#include <plat/regs-clock.h>
#include <plat/regs-gpio.h>
#include <plat/gpio-bank-n.h>
#define DEVICE_NAME "ir"
#define IR_IRQ_EINT_N 12
#define TIMER_CNT (long)(20000-__raw_readl(S3C_TCNTO(0)))
static volatile char ir_values[4] = {0};
static DECLARE_WAIT_QUEUE_HEAD(ir_waitq);
static volatile int ev_code=0;
static volatile unsigned long Tcon=0;
static void timer_start(void)
{
__raw_writel(20000, S3C_TCNTB(0));
__raw_writel(10000, S3C_TCMPB(0));
Tcon |= 2; //manual update bit
__raw_writel(Tcon, S3C_TCON);
Tcon &= ~2; //clear manual update bit
__raw_writel(Tcon, S3C_TCON);
Tcon |= 1; //start timer
__raw_writel(Tcon, S3C_TCON);
}
static void timer_stop(void)
{
Tcon &= ~1;
__raw_writel(Tcon, S3C_TCON);
}
static unsigned long get_ir_io_val(void)
{
unsigned long tmp;
tmp = readl(S3C64XX_GPNDAT);
tmp &= (1 << IR_IRQ_EINT_N);
return tmp;
}
static unsigned long Ir_Get_Low(void)
{
unsigned long tmp;
timer_start();
do{
tmp = TIMER_CNT;
}while ((get_ir_io_val() == 0) && (tmp < 10000));
timer_stop();
return tmp;
}
static unsigned long Ir_Get_High(void)
{
unsigned long tmp;
timer_start();
do{
tmp = TIMER_CNT;
}while ((get_ir_io_val() != 0) && (tmp < 10000));
timer_stop();
return tmp;
}
static irqreturn_t ir_interrupt(int irq, void *dev_id)
{
unsigned long i,j,temp;
temp = readl(S3C64XX_GPNCON);
temp &= ~(0x3<<(2*IR_IRQ_EINT_N));
writel(temp, S3C64XX_GPNCON);
temp = Ir_Get_Low();
if ((temp < 8500) || (temp > 9500)) //引导脉冲低电平8500~9500us
goto end;
temp = Ir_Get_High();
if ((temp < 4000) || (temp > 5000)) //引导脉冲高电平4000~5000us
goto end;
for (i=0; i<4; i++) //4个字节
{
for (j=0; j<8; j++) //每个字节8位
{
temp = Ir_Get_Low();
if ((temp < 200) || (temp > 800)) //200~800us
goto end;
temp = Ir_Get_High();
if ((temp < 200) || (temp > 2000)) //200~2000us
goto end;
ir_values[i] >>= 1;
if (temp > 1120) //1120us
ir_values[i] |= 0x80;
}
}
//printk("ir:%x,%x,%x,%x\n",ir_values[0],ir_values[1],ir_values[2],ir_values[3]);
ev_code = 1;
wake_up_interruptible(&ir_waitq);
end:
temp = readl(S3C64XX_GPNCON);
temp |= (0x2<<(2*IR_IRQ_EINT_N));
writel(temp, S3C64XX_GPNCON);
return IRQ_RETVAL(IRQ_HANDLED);
}
static int s3c64xx_ir_open(struct inode *inode, struct file *file)
{
struct clk *clk_p;
unsigned long tcfg1;
unsigned long tcfg0;
unsigned long pclk;
int err = 0;
tcfg1 = __raw_readl(S3C_TCFG1);
tcfg0 = __raw_readl(S3C_TCFG0);
clk_p = clk_get(NULL, "pclk"); //get pclk
pclk = clk_get_rate(clk_p);
tcfg0 &= ~S3C_TCFG_PRESCALER0_MASK; //1 us
tcfg0 |= (pclk/1000000 - 1);
tcfg1 &= ~S3C_TCFG1_MUX0_MASK; //mux = 1/1
tcfg1 |= S3C_TCFG1_MUX0_DIV1;
__raw_writel(tcfg1, S3C_TCFG1);
__raw_writel(tcfg0, S3C_TCFG0);
Tcon = __raw_readl(S3C_TCON);
Tcon &= ~0x1f; //disable deadzone, One-Shot, inv-off, TCNTB0&TCMPB0
__raw_writel(Tcon, S3C_TCON);
err = request_irq(IRQ_EINT(IR_IRQ_EINT_N), ir_interrupt, IRQ_TYPE_EDGE_FALLING, DEVICE_NAME, NULL);
if (err)
{
disable_irq(IRQ_EINT(IR_IRQ_EINT_N));
free_irq(IRQ_EINT(IR_IRQ_EINT_N), NULL);
return -EBUSY;
}
ev_code = 0;
return 0;
}
static int s3c64xx_ir_close(struct inode *inode, struct file *file)
{
disable_irq(IRQ_EINT(IR_IRQ_EINT_N));
free_irq(IRQ_EINT(IR_IRQ_EINT_N), NULL);
return 0;
}
static int s3c64xx_ir_read(struct file *filp, char __user *buff, size_t count, loff_t *offp)
{
unsigned long err;
if (!ev_code)
{
if (filp->f_flags & O_NONBLOCK)
return -EAGAIN;
else
wait_event_interruptible(ir_waitq, ev_code);
}
ev_code = 0;
err = copy_to_user((void *)buff, (const void *)(&ir_values), 4);
return err ? -EFAULT : 4;
}
static unsigned int s3c64xx_ir_poll( struct file *file, struct poll_table_struct *wait)
{
unsigned int mask = 0;
poll_wait(file, &ir_waitq, wait);
if (ev_code)
mask |= POLLIN | POLLRDNORM;
return mask;
}
static struct file_operations dev_fops = {
.owner = THIS_MODULE,
.open = s3c64xx_ir_open,
.release = s3c64xx_ir_close,
.read = s3c64xx_ir_read,
.poll = s3c64xx_ir_poll,
};
static struct miscdevice misc = {
.minor = MISC_DYNAMIC_MINOR,
.name = DEVICE_NAME,
.fops = &dev_fops,
};
static int __init dev_init(void)
{
int ret;
ret = misc_register(&misc);
printk (DEVICE_NAME"\tinitialized\n");
return ret;
}
static void __exit dev_exit(void)
{
misc_deregister(&misc);
}
module_init(dev_init);
module_exit(dev_exit);
MODULE_LICENSE("GPL");
MODULE_AUTHOR("cole3");
ir.rar_linux 红外
版权申诉
6 浏览量
2022-09-19
18:41:25
上传
评论
收藏 39KB RAR 举报
局外狗
- 粉丝: 67
- 资源: 1万+
最新资源
- 深圳市生态环境局年度声环境质量状况
- 基于TMS320F28335的开关电源模块并联供电系统(电路图+源码)
- C#毕业设计-基于asp.net的MVC网上书店管理系统(源码+数据库+文档).zip
- 肇庆市怀集县应急避难场所统计表信息
- 飞行昆虫机器人 飞行昆虫机器人
- 崩铁2.3(SourlCool版).apk
- 知识蒸馏-基于Pytorch通过匹配训练轨迹进行数据集蒸馏-附项目源码+流程教程-优质项目实战.zip
- 儿童节 python庆祝代码简要介绍-20240601.docx
- 知识蒸馏-基于Pytorch实现的语义分割结构化知识蒸馏算法-附项目源码+流程教程-优质项目实战.zip
- 小白物联网智能家居毕设参考STM32+ESP8266/MQTT+OneNet+UniApp
资源上传下载、课程学习等过程中有任何疑问或建议,欢迎提出宝贵意见哦~我们会及时处理!
点击此处反馈