我54123 发表于 2016-9-6 18:17:31

[hide]
Tiny210v2上没有四线电阻屏的接口,可直接从核心板上引出四根线连接至四线电阻屏,下面为四线电阻屏的驱动源码,我已经在Tiny210v2上测试OK。有兴趣的朋友可以看看。

#include <linux/kernel.h>

#include <linux/module.h>

#include <linux/slab.h>

#include <linux/input.h>

#include <linux/init.h>

#include <linux/errno.h>

#include <linux/serio.h>

#include <linux/delay.h>

#include <linux/clk.h>

#include <linux/wait.h>

#include <linux/sched.h>

#include <linux/cdev.h>

#include <linux/miscdevice.h>


#include <asm/io.h>

#include <asm/irq.h>

#include <asm/uaccess.h>


#include <mach/map.h>

#include <mach/regs-clock.h>

#include <mach/regs-adc.h>

#include <mach/regs-gpio.h>

#include <plat/regs-timer.h>



struct tiny210_ts_regs{

    unsigned long tsadccon1;

    unsigned long tscon1;

    unsigned long tsdly1;

    unsigned long tsdatx1;

    unsigned long tsdaty1;

    unsigned long tspenstat1;

    unsigned long clrintadc1;

    unsigned long noregs;

    unsigned long clrintpen1;

};


struct tiny210_ts_regs_1{

    unsigned long tsadccon0;

    unsigned long tscon0;

    unsigned long tsdly0;

    unsigned long tsdatx0;

    unsigned long tsdaty0;

    unsigned long tspenstat0;

    unsigned long clrintadc0;

    unsigned long adcmux;

    unsigned long clrintpen0;

};


static struct input_dev *tiny210_ts_dev;


static volatile struct tiny210_ts_regs *tiny210_ts_regs;

static volatile struct tiny210_ts_regs_1*tiny210_ts_regs_1;


static struct timer_list ts_timer;


static void enter_wait_pen_down_mode(void)

{

    tiny210_ts_regs->tscon1 = 0xd3;

}


static void enter_wait_pen_up_mode(void)

{

    tiny210_ts_regs->tscon1 = 0x1d3;

}


static void enter_measure_xy_mode(void)

{

    tiny210_ts_regs->tscon1 = (1<<3) (1<<2);

}


static void start_adc(void)

{

    tiny210_ts_regs->tsadccon1 = (1<<0);

}


static int tiny210_filter_ts(int x[], int y[])

{

#define ERR_LIMIT 50

    int avr_x, avr_y;

    int det_x, det_y;


    avr_x = (x[0]+x[1])/2;

    avr_y = (y[0]+y[1])/2;


    det_x = (x[2] > avr_x) ? (x[2] - avr_x) : (avr_x - x[2]);

    det_y = (y[2] > avr_y) ? (y[2] - avr_y) : (avr_y - y[2]);


    if((det_x > ERR_LIMIT) (det_y > ERR_LIMIT))

        return 0;


    avr_x = (x[1] + x[2])/2;

    avr_y = (y[1] + y[2])/2;


    det_x = (x[3] > avr_x) ? (x[3] - avr_x) : (avr_x - x[3]);

    det_y = (y[3] > avr_y) ? (y[3] - avr_y) : (avr_y - y[3]);


    if((det_x > ERR_LIMIT) (det_y > ERR_LIMIT))

        return 0;


    return 1;

}


static void tiny210_ts_timer_function(unsigned long data)

{

    if(tiny210_ts_regs->tsdatx1 & (1<<15))

        {

            input_report_abs(tiny210_ts_dev, ABS_PRESSURE, 0);

            input_report_key(tiny210_ts_dev, BTN_TOUCH, 0);

            input_sync(tiny210_ts_dev);

            enter_wait_pen_down_mode();

        }

    else

        {

            enter_measure_xy_mode();

            start_adc();

        }

}


static irqreturn_t adc_irq(int irq, void *dev_id)

{

    tiny210_ts_regs->clrintadc1 = 0;

    static int cnt = 0;

    static int x[4], y[4];

    int adcdatx,adcdaty;

   

    adcdatx = tiny210_ts_regs->tsdatx1;

    adcdaty = tiny210_ts_regs->tsdaty1;


    if(tiny210_ts_regs->tsdatx1 & (1<<15))

        {

            cnt = 0;

            input_report_abs(tiny210_ts_dev, ABS_PRESSURE, 0);

            input_report_key(tiny210_ts_dev, BTN_TOUCH, 0);

            input_sync(tiny210_ts_dev);

            enter_wait_pen_down_mode();

        }

    else

        {

            //printk("adc_irq cnt = %d, x = %d, y = %d
",++cnt,adcdatx & 0xfff, adcdaty & 0xfff);

            x[cnt] = adcdatx & 0xfff;

            y[cnt] = adcdaty & 0xfff;

            ++cnt;


            if(cnt == 4)

                {

                    if(tiny210_filter_ts(x,y))

                        {

                            //printk("x = %d, y = %d
",(x[0]+x[1]+x[2]+x[3])/4, (y[0]+y[1]+y[2]+y[3])/4);

                            input_report_abs(tiny210_ts_dev, ABS_X, (x[0]+x[1]+x[2]+x[3])/4);

                            input_report_abs(tiny210_ts_dev, ABS_Y, (y[0]+y[1]+y[2]+y[3])/4);

                            input_report_abs(tiny210_ts_dev, ABS_PRESSURE, 1);

                            input_report_key(tiny210_ts_dev, BTN_TOUCH, 1);

                            input_sync(tiny210_ts_dev);

                        }

                    cnt = 0;

                    enter_wait_pen_up_mode();

                }

            else

                {

                    enter_measure_xy_mode();

                    start_adc();

                }

        }

    return IRQ_HANDLED;

}


static irqreturn_t pen_down_up_irq(int irq, void *dev_id)

{

    tiny210_ts_regs->clrintpen1 = 0;

    if(tiny210_ts_regs->tsdatx1 & (1<<15))

        {

            //printk("pen up
");

            input_report_abs(tiny210_ts_dev, ABS_PRESSURE, 0);

            input_report_key(tiny210_ts_dev, BTN_TOUCH, 0);

            input_sync(tiny210_ts_dev);

            enter_wait_pen_down_mode();

        }

    else

        {

            //printk("pen down
");

            //enter_wait_pen_up_mode();

            enter_measure_xy_mode();

            start_adc();

        }

    return IRQ_HANDLED;

}


static int tiny210_ts_init(void)

{

    struct clk* clk;

   

    tiny210_ts_dev = input_allocate_device();

   

    set_bit(EV_KEY, tiny210_ts_dev->evbit);

    set_bit(EV_ABS, tiny210_ts_dev->evbit);


    set_bit(BTN_TOUCH, tiny210_ts_dev->keybit);


    input_set_abs_params(tiny210_ts_dev, ABS_X, 0, 0xfff, 0, 0);

    input_set_abs_params(tiny210_ts_dev, ABS_Y, 0, 0xfff, 0, 0);

    input_set_abs_params(tiny210_ts_dev, ABS_PRESSURE, 0, 1, 0, 0);


    input_register_device(tiny210_ts_dev);


    tiny210_ts_regs_1= ioremap(0xE1700000, sizeof(struct tiny210_ts_regs_1));

    tiny210_ts_regs = ioremap(0xE1701000,sizeof(struct tiny210_ts_regs));


    clk = clk_get(NULL, "adc");

    clk_enable(clk);


       tiny210_ts_regs_1->tsadccon0 = (1<<17);

    tiny210_ts_regs->tsadccon1 &= ~(1<<2);

    tiny210_ts_regs->tsadccon1 = (1<<14) (1<<16) (65<<6);

   

    request_irq(IRQ_PENDN1, pen_down_up_irq, IRQF_SAMPLE_RANDOM, "ts_pen", NULL);

    request_irq(IRQ_ADC1, adc_irq, IRQF_SAMPLE_RANDOM, "adc", NULL);

   

    tiny210_ts_regs->tsdly1 = 0xffff;


    init_timer(&ts_timer);

    ts_timer.function = tiny210_ts_timer_function;

    add_timer(&ts_timer);

   

    enter_wait_pen_down_mode();

   

    return 0;

}


static void tiny210_ts_exit(void)

{

    input_unregister_device(tiny210_ts_dev);

    input_free_device(tiny210_ts_dev);

    iounmap(tiny210_ts_regs);

    iounmap(tiny210_ts_regs_1);

    free_irq(IRQ_PENDN1, NULL);

    free_irq(IRQ_ADC1, NULL);

    del_timer(&ts_timer);

}


module_init(tiny210_ts_init);

module_exit(tiny210_ts_exit);

MODULE_AUTHOR("jany_linux");

[table=100%,#ffffff]MODULE_LICENSE("GPL");
[/table][/hide]
本主题需向作者支付 5 枚金币 才能浏览 购买主题

xzcxnihd 发表于 2016-9-6 19:14:46

谢谢楼主分享

ruili 发表于 2016-9-7 08:53:00

你的原创吗

bao770119 发表于 2017-4-26 10:02:31

参考一下

xintaisniper 发表于 2020-3-3 14:19:44

感谢分享。。。

tiny2010 发表于 2020-9-10 08:38:15

tiny2010 发表于 2020-9-14 09:00:09

tiny2010 发表于 2020-9-15 08:54:37

tiny2010 发表于 2020-12-23 08:57:34

tiny2010 发表于 2020-12-24 08:47:36

页: [1] 2
查看完整版本: 在Tiny210v2上实现四线电阻屏触摸,有兴趣的朋友可以看看