示例#1
0
static irqreturn_t adc_irq(int irq, void *dev_id)
{
	static int cnt = 0;
	int adcdat0, adcdat1;
#if 1
	/* 优化措施2: 如果ADC完成时, 发现触摸笔已经松开, 则丢弃此次结果 */
	adcdat0 = s3c_ts_regs->adcdat0;
	adcdat1 = s3c_ts_regs->adcdat1;

	if (s3c_ts_regs->adcdat0 & (1<<15))	/* 已经松开 */
	{
		enter_wait_pen_down_mode();
	}
	else
	{
		printk("adc_irq cnt = %d, x = %d, y = %d\n", ++cnt, adcdat0 & 0xfff, adcdat1 & 0xfff);
		enter_wait_pen_up_mode();
	}
#endif

#if 0		
	printk("adc_irq cnt = %d, x = %d, y = %d\n", ++cnt,(int) (s3c_ts_regs->adcdat0 & 0xfff), (int) (s3c_ts_regs->adcdat1 & 0xfff));
	enter_wait_pen_up_mode();
#endif	
	return IRQ_HANDLED;
}
示例#2
0
static void s3c_ts_timer_function(unsigned long data)
{
	int adcdat0, adcdat1;
	int updown;
	
	/* 优化措施2: 如果ADC完成时, 发现触摸笔已经松开, 则丢弃此次结果 */
	adcdat0 = s3c_ts_regs->adcdat0;
	adcdat1 = s3c_ts_regs->adcdat1;

	/* dat0和dat1中bit15都是0, updown才是0, 0是down state */
	updown =! (!(adcdat0 & (1<<15))) && (!(adcdat1 & (1<<15)));
	
	if (s3c_ts_regs->adcdat1 & (1<<15))
//	if(updown)
	{
		/* 已经松开 */
		enter_wait_pen_down_mode();
	}
	else
	{
		/* 测量X/Y坐标 */
		enter_measure_xy_mode();
		start_adc();
	}
}
示例#3
0
static int s3c_ts_init(void)
{
	struct clk* clk;
	
	/* 1. 分配一个input_dev结构体 */
	s3c_ts_dev = input_allocate_device();

	/* 2. 设置 */
	/* 2.1 能产生哪类事件 */
	set_bit(EV_KEY, s3c_ts_dev->evbit);
	set_bit(EV_ABS, s3c_ts_dev->evbit);

	/* 2.2 能产生这类事件里的哪些事件 */
	set_bit(BTN_TOUCH, s3c_ts_dev->keybit);

	input_set_abs_params(s3c_ts_dev, ABS_X, 0, 0x3FF, 0, 0);
	input_set_abs_params(s3c_ts_dev, ABS_Y, 0, 0x3FF, 0, 0);
	input_set_abs_params(s3c_ts_dev, ABS_PRESSURE, 0, 1, 0, 0);


	/* 3. 注册 */
	input_register_device(s3c_ts_dev);

	/* 4. 硬件相关的操作 */
	/* 4.1 使能时钟(CLKCON[15]) */
	clk = clk_get(NULL, "adc");
	clk_enable(clk);

	/* 4.2 设置S3C2416的ADC/TS寄存器 */
	s3c_ts_regs = ioremap(0x58000000, sizeof(struct s3c_ts_regs));

	/* bit[14]  : 1-A/D converter prescaler enable
	 * bit[13:6]: A/D converter prescaler value,
	 *            65, ADCCLK=PCLK/(49+1)=66.6MHz/(65+1)=1MHz
	 * bit[0]: A/D conversion starts by enable. 先设为0
	 */
	s3c_ts_regs->adccon = (1<<14)|(65<<6);

//	request_irq(IRQ_TC, pen_down_up_irq, SA_SAMPLE_RANDOM, "ts_pen", NULL);
	request_irq(IRQ_TC, pen_down_up_irq, IRQF_SAMPLE_RANDOM, "ts_pen", NULL);
	request_irq(IRQ_ADC, adc_irq, IRQF_SAMPLE_RANDOM, "adc", NULL);

	/* 优化错施1: 
	 * 设置ADCDLY为最大值, 这使得电压稳定后再发出IRQ_TC中断
	 */
	s3c_ts_regs->adcdly = 0xffff;

	/* 优化措施5: 使用定时器处理长按,滑动的情况
	 * 
	 */
	init_timer(&ts_timer);
	ts_timer.function = s3c_ts_timer_function;
	add_timer(&ts_timer);
	
	enter_wait_pen_down_mode();
	
	return 0;
}
示例#4
0
static irqreturn_t adc_irq(int irq, void *dev_id)
{
	static int cnt = 0;
	static int x[4], y[4];
	int adcdat0, adcdat1;
	
	
	/* 优化措施2: 如果ADC完成时, 发现触摸笔已经松开, 则丢弃此次结果 */
	adcdat0 = s3c_ts_regs->adcdat0;
	adcdat1 = s3c_ts_regs->adcdat1;

	if (s3c_ts_regs->adcdat0 & (1<<15))
	{
		/* 已经松开 */
		cnt = 0;
		input_report_abs(s3c_ts_dev, ABS_PRESSURE, 0);
		input_report_key(s3c_ts_dev, BTN_TOUCH, 0);
		input_sync();
		enter_wait_pen_down_mode();

	}
	else
	{
		// printk("adc_irq cnt = %d, x = %d, y = %d\n", ++cnt, adcdat0 & 0x3ff, adcdat1 & 0x3ff);
		/* 优化措施3: 多次测量求平均值 */
		x[cnt] = adcdat0 & 0x3ff;
		y[cnt] = adcdat1 & 0x3ff;
		++cnt;
		if (cnt == 4)
		{
			/* 优化措施4: 软件过滤 */
			if (s3c_filter_ts(x, y))
			{			
				//printk("x = %d, y = %d\n", (x[0]+x[1]+x[2]+x[3])/4, (y[0]+y[1]+y[2]+y[3])/4);
				input_report_abs(s3c_ts_dev, ABS_X, (x[0]+x[1]+x[2]+x[3])/4);
				input_report_abs(s3c_ts_dev, ABS_Y, (y[0]+y[1]+y[2]+y[3])/4);
				input_report_abs(s3c_ts_dev, ABS_PRESSURE, 1);
				input_report_key(s3c_ts_dev, BTN_TOUCH, 1);
				input_sync();
			}
			cnt = 0;
			enter_wait_pen_up_mode();

			/* 启动定时器处理长按/滑动的情况 */
			mod_timer(&ts_timer, jiffies + HZ/100);
		}
		else
		{
			enter_measure_xy_mode();
			start_adc();
		}		
	}
	
	return IRQ_HANDLED;
}
示例#5
0
static irqreturn_t adc_irq(int irq, void *dev_id)
{
	static int cnt = 0;
	int adcdat0, adcdat1;
	static int x[4], y[4];
	int updown;
	
#if 1
	/* 优化措施2: 如果ADC完成时, 发现触摸笔已经松开, 则丢弃此次结果 */
	adcdat0 = s3c_ts_regs->adcdat0;
	adcdat1 = s3c_ts_regs->adcdat1;

	/* dat0和dat1中bit15都是0, updown才是0, 0是down state */
	updown =! (!(adcdat0 & (1<<15))) && (!(adcdat1 & (1<<15)));

	if (updown)	/* 已经松开 */
	{
		cnt = 0;
		enter_wait_pen_down_mode();	/* 进入等待按下模式 */
	}
	else			/* 已经按下 */
	{
//		printk("adc_irq cnt = %d, x = %d, y = %d\n", ++cnt, adcdat0 & 0xfff, adcdat1 & 0xfff);
//		enter_wait_pen_up_mode();

		/* 优化措施3: 多次测量求平均值 */
		x[cnt] = adcdat0 & 0xfff;
		y[cnt] = adcdat1 & 0xfff;
		++cnt;

		if (cnt == 4)
		{
			cnt = 0;
			printk("x = %d, y = %d\n", (x[0]+x[1]+x[2]+x[3])/4, (y[0]+y[1]+y[2]+y[3])/4);	
			enter_wait_pen_up_mode();	/* 进入等待弹起模式 */
		}
		else
		{
			enter_measure_xy_mode();
			start_adc();
		}
	}
#endif

#if 0		
	printk("adc_irq cnt = %d, x = %d, y = %d\n", ++cnt,(int) (s3c_ts_regs->adcdat0 & 0xfff), (int) (s3c_ts_regs->adcdat1 & 0xfff));
	enter_wait_pen_up_mode();
#endif	

	return IRQ_HANDLED;
}
// 3th里面的自动分离模式启动后需要的中断函数注册,具体函数内容在4.2里面
static irqreturn_t adc_irq(int irq, void *dev_id)
{

	static int cnt = 0;
	static int x[4],   y[4]; // 优化措施3  测量保存4次,然后求平均值
	int adcdat0, adcdat1;  // 寄存器的bit[15]是判断松开还是按下的  手册447

	// X,Y的值存在ADCDAT0 AND ADCDAT1寄存器里面  手册442  part3
	// 最低10位为x坐标值,不过这个值是电压值而已,和坐标值没有关系
		
	//  &&&&&&&&&&&&***********  如果ADC启动完成时,发现触摸笔已经松开,则测量值已经不准确,丢弃此次结果。
		
	adcdat0 = s3c_ts_regs->adcdat0 ;
	adcdat1 = s3c_ts_regs->adcdat1 ;

	if (s3c_ts_regs->adcdat0 & (1<<15))
	{
		// 如果触摸笔已经松开
		cnt = 0;  // 优化3 中要每4次求一次平均值
		enter_wait_pen_down_mode();
	}
	else
	{
		//printk ("adc_irq cnt = %d, x = %d,	y = %d\n", ++cnt, s3c_ts_regs->adcdat0 & 0x3ff, adcdat1 & 0x3ff);
		// *******运行到这里,如果没有等待松开操作,则开发板只进行一次测量后就没有反映了,所以在这里要加上如下语句。

		// 优化措施3 多次测量求平均值
		x[cnt] = s3c_ts_regs->adcdat0 & 0x3ff;
		y[cnt] = s3c_ts_regs->adcdat1 & 0x3ff;
		++cnt;
		if (cnt == 4)
		{
			//printk ("adc_irq cnt = %d, x = %d,	y = %d\n", ++cnt, (x[0]+x[1]+x[2]+x[3])/4,  (y[0]+y[1]+y[2]+y[3])/4);
			// 上面这行错误代码,错误在 ++cnt.
			printk (" x = %d,	y = %d\n", (x[0]+x[1]+x[2]+x[3])/4,  (y[0]+y[1]+y[2]+y[3])/4);
			cnt = 0;
			enter_wait_pen_up_mode();			
		}
		else
		{
			enter_measure_xy_mode();
			start_adc();	
		}

		enter_wait_pen_up_mode();  // 测量完毕要等待触摸笔松开

	}

	
	return IRQ_HANDLED;
}
示例#7
0
static void s3c_ts_timer_function(unsigned long data)
{
	if (s3c_ts_regs->adcdat0 & (1<<15))
	{
		/* 已经松开 */
		enter_wait_pen_down_mode();
	}
	else
	{
		/* 测量X/Y坐标 */
		enter_measure_xy_mode();
		start_adc();
	}
}
示例#8
0
static irqreturn_t pen_down_up_irq(int irq, void *dev_id)
{
	if(s3c_ts_regs->adcdat0 & (1<<15))
	{
		printk("pen up\n");
		enter_wait_pen_down_mode();
	}
	else
	{
//		printk("pen down\n");
//		enter_wait_pen_up_mode();
		enter_measure_xy_mode();
		start_adc();
	}
	return IRQ_HANDLED;
}
示例#9
0
static int s3c_ts_init(void)
{
	struct clk *clk;
	/*1.分配一个input结构体*/
	 s3c_ts_dev = input_allocate_device();
	
	/*2.设置*/
	/*2.1.能产生哪类事件  */
	set_bit(EV_KEY,s3c_ts_dev->evbit);
	set_bit(EV_ABS,s3c_ts_dev->evbit);
	/*2.2.能产生这类事件里的哪些事件  */
	set_bit(BTN_TOUCH,s3c_ts_dev->keybit);
	
	input_set_abs_params(s3c_ts_dev, ABS_X, 0, 0x3FF, 0, 0);
	input_set_abs_params(s3c_ts_dev, ABS_Y, 0, 0x3FF, 0, 0);
	input_set_abs_params(s3c_ts_dev, ABS_PRESSURE, 0, 1, 0, 0);


	/* 3. 注册 */
	input_register_device(s3c_ts_dev);

	/* 4. 硬件相关的操作 */
	/* 4.1 使能时钟(CLKCON[15]) */
	clk = clk_get(NULL, "adc");
	clk_enable(clk);
	
	/*4.2 设置S3C2440的ADC/TS寄存器 */
	s3c_ts_regs = ioremap(0x58000000, sizeof(struct s3c_ts_regs));

	/* bit[14]  : 1-A/D converter prescaler enable
	 * bit[13:6]: A/D converter prescaler value,
	 *            49, ADCCLK=PCLK/(49+1)=50MHz/(49+1)=1MHz
	 * bit[0]: A/D conversion starts by enable. 先设为0
	 */
	s3c_ts_regs->adccon = (1<<14) | (49<<6);

	request_irq(IRQ_TC, pen_down_up_irq , IRQF_SAMPLE_RANDOM,"ts_pen", NULL);
	request_irq(IRQ_ADC, adc_irq , IRQF_SAMPLE_RANDOM,"ts_pen", NULL);
	/* 优化措施1: 
	 *设置ADCDELAY,使得ADC稳定后发出IRQ_TC中断
	 *
	 */
	s3c_ts_regs->adcdly = 0xffff;
	
	enter_wait_pen_down_mode();
	return 0;
}
示例#10
0
static void tiny_ts_timer_function(unsigned long data)
{
	if (tiny_ts_regs->tsdatx1 & (1<<15))
	{
		/* 已经松开 */
		input_report_abs(s3c_ts_dev, ABS_PRESSURE, 0);
		input_report_key(s3c_ts_dev, BTN_TOUCH, 0);
		input_sync(s3c_ts_dev);
		enter_wait_pen_down_mode();
	}
	else
	{
		/* 测量X/Y坐标 */
		enter_measure_xy_mode();
		start_adc();
	}
}
示例#11
0
static irqreturn_t pen_down_up_irq(int irq, void *dev_id)
{
	if (tiny_ts_regs->tsdatx1 & (1<<15))
	{
		//printk("pen up\n");
		input_report_abs(s3c_ts_dev, ABS_PRESSURE, 0);
		input_report_key(s3c_ts_dev, BTN_TOUCH, 0);
		input_sync(s3c_ts_dev);
		enter_wait_pen_down_mode();
	}
	else
	{
		//printk("pen down\n");
		//enter_wait_pen_up_mode();
		enter_measure_xy_mode();
		start_adc();
	}
	return IRQ_HANDLED;
}
static irqreturn_t pen_down_up_irq(int irq, void *dev_id)

{
	if (s3c_ts_regs->adcdat0 & (1<<15))
	{
		printk("pen up\n");  //松开才能等待下一次等待模式
		enter_wait_pen_down_mode();
	}
	else
	{
	// 3th 开始,进行启动ADC,转换x,y坐标
	//printk("pen down\n"); //按下进入等待松开模式
	//enter_wait_pen_up_mode();
	// 触摸屏有xy分别分离模式和自动分离模式,我们取后一种自动分离模式,这种简单。
	enter_measure_xy_mode();
	start_adc();
	}
	return IRQ_HANDLED;
}
示例#13
0
static irqreturn_t pen_down_up_irq(int irq, void *dev_id)
{
	enter_no_operation_mode();
	
	if (s3c_ts_regs->adcdat0 & (1<<15))
	{
		printk("pen up\n");
		enter_wait_pen_down_mode();
	}
	else
	{
		printk("pen down\n");
//		enter_wait_pen_up_mode();
		enter_measure_xy_mode();
		start_adc();
	}

	/* 2416数据手册P554,XY_PST=0 */
	enter_no_operation_mode();
	
	return IRQ_HANDLED;
}
示例#14
0
static int s3c_ts_init(void)
{
	struct clk* clk;
	
	/* 1. 分配一个input_dev结构体 */
	tiny_ts_dev = input_allocate_device();

	/* 2. 设置 */
	/* 2.1 能产生哪类事件 */
	set_bit(EV_KEY, tiny_ts_dev->evbit);
	set_bit(EV_ABS, tiny_ts_dev->evbit);

	/* 2.2 能产生这类事件里的哪些事件 */
	set_bit(BTN_TOUCH, tiny_ts_dev->keybit);

	input_set_abs_params(tiny_ts_dev, ABS_X, 0, 0x3FF, 0, 0);
	input_set_abs_params(tiny_ts_dev, ABS_Y, 0, 0x3FF, 0, 0);
	input_set_abs_params(tiny_ts_dev, ABS_PRESSURE, 0, 1, 0, 0);


	/* 3. 注册 */
	input_register_device(tiny_ts_dev);

	/* 4. 硬件相关的操作 */
	/* 4.1 使能时钟(CLKCON[15]) */
	clk = clk_get(NULL, "adc");
	if (!clk || IS_ERR(clk)) {
		printk(KERN_INFO "failed to get adc clock source\n");
	}
	clk_enable(clk);
	printk("Tiny_TS clock got enabled :: %ld.%03ld Mhz\n", PRINT_MHZ(clk_get_rate(tiny_clk)));

	/* 4.2 设置S3C2440的ADC/TS寄存器 */
	tsadccon0 =  ioremap(0xE1700000, 4);
	tiny_ts_regs = ioremap(0xE1701000, sizeof(struct tiny_ts_regs));

	/* s5pv210有触摸屏接口0,1
	 * Tiny210开发板向外提供接口1
	 * 所以这里选择接口1
	 */
	tsadccon0 |= 1<<17;
	/* bit[14]  : 1-A/D converter prescaler enable
	 * bit[13:6]: A/D converter prescaler value,
	 *            65, ADCCLK=PCLKP/(65+1)=66.7MHz/(65+1)=1MHz
	 * bit[2]: 默认为1,即Standby mode,我们要设置为0,正常模式
	 * bit[0]: A/D conversion starts by enable. 先设为0
	 */
	tiny_ts_regs->tsadccon1 &= ~(1<<2);
	tiny_ts_regs->tsadccon1 |= (1<<14)|(65<<6);

	request_irq(IRQ_TC, pen_down_up_irq, IRQF_SAMPLE_RANDOM, "ts_pen", NULL);
	request_irq(IRQ_ADC, adc_irq, IRQF_SAMPLE_RANDOM, "adc", NULL);

	/* 优化措施1: 
	 * 设置ADCDLY为最大值, 这使得电压稳定后再发出IRQ_TC中断
	 */
	tiny_ts_regs->tsdaty1 = 0xffff;

	/* 优化措施5: 使用定时器处理长按,滑动的情况
	 * 
	 */
	init_timer(&ts_timer);
	ts_timer.function = tiny_ts_timer_function;
	add_timer(&ts_timer);

	enter_wait_pen_down_mode();
	
	return 0;
}
//第二步  开始写入口函数 
static int s3c_ts_init(void)
{
	struct clk* clk; 
	
//第五步 细化,把要做的东西写下来,以下框架为所有触摸屏程序的框架
		

	// 1.分配一个input_dev结构体
 	s3c_ts_dev = input_allocate_device();

 	// 2.设置,分两大类 参考8th Driver buttons.c
	// 2.1 能产生哪类事件
	set_bit(EV_KEY, s3c_ts_dev->evbit);  //EV_KEY表示会产生按键类事件,buttons_dev->evbit表示设置数组总的某一位可以产生案件类事件。
	set_bit(EV_ABS, s3c_ts_dev->evbit); //绝对位移 
	
	// 2.2 能产生这类操作中的哪些事件  
	set_bit(BTN_TOUCH,  s3c_ts_dev->keybit); //能够产生按键类事件中的触摸屏事件

	input_set_abs_params(s3c_ts_dev, ABS_X, 0, 0x3FF, 0, 0);  //最大尺寸为0x3ff.
	input_set_abs_params(s3c_ts_dev, ABS_Y, 0, 0x3FF, 0, 0);
	input_set_abs_params(s3c_ts_dev, ABS_PRESSURE, 0, 1, 0, 0);// 笔压力仅设置为两种 0和1.
	
	
 	// 3.注册
 	input_register_device (s3c_ts_dev);
	
 	// 4. 硬件相关的操作 硬件手册16章 
 	// 4.1 使能时钟(也就是设置CLKCON的bit[15])
 	clk = clk_get(NULL, "abc");
	clk_enable(clk);
	

	// 4.2 设置s3c2440的ADC (TS寄存器)
	// 操作TS寄存器,需要进行ioremap. 这样一个个的进行ioremap多麻烦, 
	// 写一个结构体就比较简单struct s3c_ts_regs.
	s3c_ts_regs = ioremap(0x58000000, sizeof(struct s3c_ts_regs)); //物理地址
	// 以下参数设置参照手册 444页
	// bit[14]    1-A/D converter prescaler enable 欲分频使能
	// bit[13:6]  1-A/D converter prescaler value 欲分频系数 
	//            设为49   ADCCLK = PCLK/(49+1) = 50MHz/(49+1)= 1MHz.0
	// bit[5:3]   模拟输入频道选择,暂时不设置
	// bit[2]     STDBM
	// bit[0]     A/D conversion starts by enable  先设为0;
	
	s3c_ts_regs->adccon = (1<<14) | (49<<6);

	request_irq(IRQ_TC, pen_down_up_irq, IRQF_SAMPLE_RANDOM, "ts_pen", NULL); //先设置一个中断,看触摸屏是否有动作,参考笔记 
	
	// 3th增加的自动分离测量模式,需要注册启动后的中断
	request_irq(IRQ_ADC, adc_irq, IRQF_SAMPLE_RANDOM, "adc", NULL);
	

	//&&&&&&&&&&%%%%%%% 优化措施1
	// 手册446 触摸屏有一个ADCDLY寄存器,设置为最大值,这使得电压稳定后再发出中断
	s3c_ts_regs->adcdly = 0xffff;
	

	enter_wait_pen_down_mode(); //增加该函数别忘了在前面声明,等待触摸笔按下模式

	return 0;
}