我的RTOS 之六 -- Touch移植(s5pv210+threadx+ucgui+touch)

很久没有关注RTOS了,所以也一直没有更新。最近闲了,把GPIO I2C调通了,简单移植了Touch,在S5PV210上使用。

调试I2C时,废了很多周折,最后借助示波器才发现一个小小的错误,折腾了很久很久。

简要说下步骤:

1、首先I2C驱动,使用GPIO I2C的方式

#include 
#include 

#define DELAY  10

#define SDA 0
#define SCL 1

#define 	GPD1CON 	(*(volatile unsigned long *) 0xE02000C0)
#define 	GPD1DAT		(*(volatile unsigned long *) 0xE02000C4)
#define 	GPD1PUD		(*(volatile unsigned long *) 0xE02000C8)
#define 	GPD1DRV		(*(volatile unsigned long *) 0xE02000CC)



#define SDA2_SET_INPUT (GPD1CON &= ~(0xf<<16))
#define SDA2_SET_OUTPUT (GPD1CON = (GPD1CON & (~(0x0f<<16))) | (0x1<<16))
#define SCL2_SET_INPUT (GPD1CON &= ~(0xf<<20));
#define SCL2_SET_OUTPUT (GPD1CON = (GPD1CON & (~(0x0f<<20))) | (0x1<<20))

#define SDA2_SET_VALUE(x) (GPD1DAT = (GPD1DAT & ~(1<<4)) | (x << 4))
#define SCL2_SET_VALUE(x) (GPD1DAT = (GPD1DAT & ~(1<<5)) | (x << 5))

#define SDA2_GET_VALUE ((GPD1DAT & (1<<4)) > 0 ? 1:0)
#define SCL2_GET_VALUE ((GPD1DAT & (1<<5)) > 0 ? 1:0)

void gpio_i2c_init(void)
{
	GPD1DRV = (GPD1DRV & ~(0x5 << 10) | (0x5 << 10));
	GPD1PUD = (GPD1DRV & ~(0xf << 10) | 0xa << 10);
	SCL2_SET_OUTPUT;
	SDA2_SET_OUTPUT;
	SDA2_SET_VALUE(1);
	SCL2_SET_VALUE(1);	
	
}
void i2c_start(void)
{	  
	SCL2_SET_OUTPUT;
	SDA2_SET_OUTPUT;
	SDA2_SET_VALUE(1);
	SCL2_SET_VALUE(1);
	
	udelay(DELAY);
	
	SDA2_SET_VALUE(0);
	udelay(DELAY);    
    	  
	SCL2_SET_VALUE(0);
	udelay(DELAY);
}

void i2c_stop(void)
{ 
	SCL2_SET_OUTPUT;
	SDA2_SET_OUTPUT;
	SDA2_SET_VALUE(0);
	SCL2_SET_VALUE(0);
	udelay(DELAY);
    
	SCL2_SET_VALUE(1);
	udelay(DELAY);
	SDA2_SET_VALUE(1);
	udelay(DELAY);
}

void i2c_send_ack(unsigned char ack)
{
	SCL2_SET_OUTPUT;
	SDA2_SET_OUTPUT;
	
	if(ack)
		SDA2_SET_VALUE(1); 
	else 
		SDA2_SET_VALUE(0); 
	udelay(DELAY);
	
	SCL2_SET_VALUE(1);
   	udelay(DELAY);
   	
	SCL2_SET_VALUE(0);
	udelay(DELAY);	
}

char i2c_receive_ack(void)
{
	char rc = 0;
	
	SCL2_SET_OUTPUT;
	SDA2_SET_INPUT;
	
	SCL2_SET_VALUE(1);
	udelay(DELAY);
	
	if(SDA2_GET_VALUE) {
		rc = 1;
	}
	SCL2_SET_VALUE(0);
	SDA2_SET_OUTPUT;
	SDA2_SET_VALUE(1);				
	return rc;
}

unsigned char i2c_send_byte(unsigned char send_byte)
{
	unsigned char rc = 0;
	unsigned char out_mask = 0x80;
	unsigned char value;
	unsigned char count = 8;
	
	SDA2_SET_OUTPUT;
	SCL2_SET_OUTPUT;
	
	while(count > 0) {                
		value = ((send_byte & out_mask) ? 1 : 0);   
		if (value == 1) {    					      		
			SDA2_SET_VALUE(1);     
		}    
		else {      					     	
			SDA2_SET_VALUE(0);     
		}    
		udelay(DELAY);
		                          
		SCL2_SET_VALUE(1);   		    
		udelay(DELAY);
		             
		SCL2_SET_VALUE(0);   
		udelay(DELAY);
		          
		out_mask >>= 1;      
		count--;       
	}
	
	SDA2_SET_VALUE(1);     
	rc = i2c_receive_ack();
	return rc;
}

void i2c_read_byte(unsigned char *buffer, unsigned char ack)
{
	unsigned char count = 0x08;
	unsigned char data = 0x00;
	unsigned char temp = 0;
	
	SDA2_SET_INPUT; 
	SCL2_SET_OUTPUT;
	
	while(count > 0) {
		SCL2_SET_VALUE(1);
		udelay(DELAY);
		temp = SDA2_GET_VALUE;    	
		data <<= 1;
		if (temp)
			data |= 0x01;
		SCL2_SET_VALUE(0);
		udelay(DELAY);
		count--;
    }
	i2c_send_ack(ack);//0 = ACK    1 = NACK
	*buffer = data;			
}

int gpio_i2c_master_send(unsigned int SlaveAddr, unsigned char *Data, unsigned int length)
{
	unsigned int i, j;
	int rc;
	
	SlaveAddr = (SlaveAddr << 1) & ~0x01;
	
	i2c_start();
	rc = i2c_send_byte(SlaveAddr);
	if(rc){
		printf("i2c_send_byte no ack 1\n");
		return -1;
	}

	for(j = 0; j < length; j++)	{
	rc = i2c_send_byte(Data[j]);//发送data
	if(rc){
			printf("i2c_send_byte no ack 2\n");
			return -1;
		}	
	}
	i2c_stop();//停止信号
	udelay(10);
	return 0;
}

int gpio_i2c_master_recv(unsigned int SlaveAddr, unsigned char *Data, unsigned int length)
{
	unsigned int i, j;
	unsigned int data;
	int rc;

	SlaveAddr = (SlaveAddr << 1) | 0x01;	
	
	i2c_start();

	rc = i2c_send_byte(SlaveAddr);
	if(rc) {
		printf("i2c_read_byte no ack 1\n");
		return -1;
	}

	for(j=0; j

2、Touch驱动

Touch IC为 FT5406, slave地址为0x70.

借助博友的一页芯片资料,写了最简单的单点读取:


我的RTOS 之六 -- Touch移植(s5pv210+threadx+ucgui+touch)_第1张图片

多点也很简单,可以参考android 多点触控协议上报点

#include 
#include 

struct touch_data touch_data;

int touch_irq()
{
	int i;
	int num = 0;
	int x, y;
	char reg[1] = {0};
	unsigned char buf[10];
	
	i2c_read_data(0x38, reg, buf, 7);

	if((num = (buf[2] & 0x0f)) == 0)
	{
		if(touch_data.isPress)
		{
			touch_data.isPress = 0;
			touch_data.x = -1;
			touch_data.y = -1;
			touch_event(touch_data.x, touch_data.y);
		}
		//printf("release\r\n");
		return 0;
	}
	x = (buf[3]&0x0f) << 8 | buf[4];
	y = (buf[5]&0x0f) << 8 | buf[6];
	//printf("num:%d, x:%d, y:%d\r\n", num, x, y);
	touch_data.x		= x;
	touch_data.y		= y;
	if(touch_data.isPress  == 0)
		touch_data.isPress  = 1;
	touch_event(touch_data.x, touch_data.y);
	return 0;
}

void touch_init(void)
{
	unsigned char uc_reg_value;
	unsigned char uc_reg_addr;
	unsigned char buf[1];
	unsigned char dst[1];

	touch_int_setup();
	
	i2c_read_data(0x38, buf, dst, 1);
	printf("touch fw:0x%x\r\n", dst[0]);
	buf[0] = 0x88;
	i2c_read_data(0x38, buf, dst, 1);
	printf("report rate:0x%x\r\n", dst[0] * 10);
	buf[0] = 0x80;
	i2c_read_data(0x38, buf, dst, 1);
	printf("touch threshold:0x%x\r\n", dst[0] * 4);

	intc_enable(NUM_EINT14);
}

在touch_init 初始化中能够取到touch固件信息,就说明i2c通信正常了。


3、看下效果^^

我的RTOS 之六 -- Touch移植(s5pv210+threadx+ucgui+touch)_第2张图片

我的RTOS 之六 -- Touch移植(s5pv210+threadx+ucgui+touch)_第3张图片



我的RTOS 之六 -- Touch移植(s5pv210+threadx+ucgui+touch)_第4张图片


最后两张的动画比较卡。



4:、存在问题及缺点

由于是电容屏,中断出发,触摸的时候,会不停的上报中断,会导致其他线程block,发生卡顿的情况,尤其画面比较复杂的时候,后期可以采取查询的方法,放在单独的线程当中或者降低touch的报点率;

另外就是lcd只有一层framebuffer,多层显示倒是ucgui的效率低下,后期优化可以同时打开至少两个framebuffer。


5、源码

http://download.csdn.net/detail/liujia2100/8859911


后期尝试移植lwip,搭配arduino,物联网^^.

你可能感兴趣的:(ARM&RTOS)