Bladeren bron

port calibration from stm32 radio, complete touch panel driver

git-svn-id: https://rt-thread.googlecode.com/svn/trunk@708 bbd45198-f89e-11dd-88c7-29a3b14d5316
qiuyiuestc 15 jaren geleden
bovenliggende
commit
ca81f820f3
5 gewijzigde bestanden met toevoegingen van 439 en 70 verwijderingen
  1. 1 1
      bsp/mini2440/SConscript
  2. 9 7
      bsp/mini2440/application.c
  3. 233 0
      bsp/mini2440/calibration.c
  4. 175 62
      bsp/mini2440/touch.c
  5. 21 0
      bsp/mini2440/touch.h

+ 1 - 1
bsp/mini2440/SConscript

@@ -11,7 +11,7 @@ group['CPPPATH'] = [RTT_ROOT + '/bsp/mini2440']
 group['CPPDEFINES'] = []
 group['LINKFLAGS'] = ''
 
-src_bsp = ['application.c', 'startup.c', 'board.c', 'rtc_calendar.c', 'info.c', 'today.c', 'picture.c', 'osc.c', 'device_info.c', 'run_module.c']
+src_bsp = ['application.c', 'startup.c', 'board.c', 'rtc_calendar.c', 'calibration.c', 'info.c', 'today.c', 'picture.c', 'osc.c', 'device_info.c', 'run_module.c']
 src_drv = ['console.c', 'led.c']
 
 if rtconfig.RT_USING_DFS:

+ 9 - 7
bsp/mini2440/application.c

@@ -20,6 +20,7 @@
 
 #include <board.h>
 #include <rtthread.h>
+#include "touch.h"
 #include "led.h"
 
 #ifdef RT_USING_DFS
@@ -63,6 +64,14 @@ void rt_init_thread_entry(void* parameter)
 	}
 #endif
 
+#ifdef RT_USING_RTGUI
+	{
+		rtgui_touch_hw_init();
+		
+		rtgui_startup();
+	}
+#endif
+
 /* LwIP Initialization */
 #ifdef RT_USING_LWIP
 	{
@@ -81,12 +90,6 @@ void rt_init_thread_entry(void* parameter)
 	}
 #endif
 
-#ifdef RT_USING_RTGUI
-	{
-		rt_hw_touch_init();
-		rtgui_startup();
-	}
-#endif
 }
 
 void rt_led_thread_entry(void* parameter)
@@ -106,7 +109,6 @@ void rt_led_thread_entry(void* parameter)
 	}
 }
 
-
 int rt_application_init()
 {
 	rt_thread_t init_thread;

+ 233 - 0
bsp/mini2440/calibration.c

@@ -0,0 +1,233 @@
+#include <rtgui/rtgui.h>
+#include <rtgui/dc.h>
+#include <rtgui/rtgui_system.h>
+#include <rtgui/widgets/window.h>
+
+#include "touch.h"
+
+#define CALIBRATION_STEP_LEFTTOP		0
+#define CALIBRATION_STEP_RIGHTTOP		1
+#define CALIBRATION_STEP_RIGHTBOTTOM	2
+#define CALIBRATION_STEP_LEFTBOTTOM		3
+#define CALIBRATION_STEP_CENTER			4
+
+#define TOUCH_WIN_UPDATE				1
+#define TOUCH_WIN_CLOSE					2
+
+struct calibration_session
+{
+	rt_uint8_t step;
+
+	struct calibration_data data;
+
+	rt_uint16_t width; rt_uint16_t height;
+
+	rt_device_t device;
+	rt_thread_t tid;
+};
+static struct calibration_session* calibration_ptr = RT_NULL;
+
+static void calibration_data_post(rt_uint16_t x, rt_uint16_t y)
+{
+	if (calibration_ptr != RT_NULL)
+	{
+		switch (calibration_ptr->step)
+		{
+		case CALIBRATION_STEP_LEFTTOP:
+			calibration_ptr->data.min_x = x;
+			calibration_ptr->data.min_y = y;
+			break;
+			
+		case CALIBRATION_STEP_RIGHTTOP:
+			calibration_ptr->data.max_x = x;
+			calibration_ptr->data.min_y = (calibration_ptr->data.min_y + y)/2;
+			break;
+			
+		case CALIBRATION_STEP_LEFTBOTTOM:
+			calibration_ptr->data.min_x = (calibration_ptr->data.min_x + x)/2;
+			calibration_ptr->data.max_y = y;
+			break;
+
+		case CALIBRATION_STEP_RIGHTBOTTOM:
+			calibration_ptr->data.max_x = (calibration_ptr->data.max_x + x)/2;
+			calibration_ptr->data.max_y = (calibration_ptr->data.max_y + y)/2;
+			break;
+
+		case CALIBRATION_STEP_CENTER:
+			/* calibration done */
+			{
+				struct rtgui_event_command ecmd;
+				RTGUI_EVENT_COMMAND_INIT(&ecmd);
+				ecmd.command_id = TOUCH_WIN_CLOSE;
+
+				rtgui_thread_send(calibration_ptr->tid, &ecmd.parent, sizeof(struct rtgui_event_command));
+			}
+			return;
+		}
+
+		calibration_ptr->step ++;
+
+		/* post command event */
+		{
+			struct rtgui_event_command ecmd;
+			RTGUI_EVENT_COMMAND_INIT(&ecmd);
+			ecmd.command_id = TOUCH_WIN_UPDATE;
+
+			rtgui_thread_send(calibration_ptr->tid, &ecmd.parent, sizeof(struct rtgui_event_command));
+		}
+	}
+}
+
+rt_bool_t calibration_event_handler(struct rtgui_widget* widget, struct rtgui_event* event)
+{
+	switch (event->type)
+	{
+	case RTGUI_EVENT_PAINT:
+	{
+		struct rtgui_dc* dc;
+		struct rtgui_rect rect;
+
+		dc = rtgui_dc_begin_drawing(widget);
+		if (dc == RT_NULL) break;
+
+		/* get rect information */
+		rtgui_widget_get_rect(widget, &rect);
+
+		/* clear whole window */
+		RTGUI_WIDGET_BACKGROUND(widget) = white;
+		rtgui_dc_fill_rect(dc, &rect);
+
+		/* reset color */
+		RTGUI_WIDGET_BACKGROUND(widget) = green;
+		RTGUI_WIDGET_FOREGROUND(widget) = black;
+
+		switch (calibration_ptr->step)
+		{
+			case CALIBRATION_STEP_LEFTTOP:
+				rtgui_dc_draw_hline(dc, 1, 1 + 15, 1);
+				rtgui_dc_draw_vline(dc, 1, 1, 1 + 15);
+				RTGUI_WIDGET_FOREGROUND(widget) = red;
+				rtgui_dc_fill_circle(dc, 0, 0, 4);
+				break;
+				
+			case CALIBRATION_STEP_RIGHTTOP:
+				rtgui_dc_draw_hline(dc, calibration_ptr->width - 1 - 15, calibration_ptr->width - 1, 1);
+				rtgui_dc_draw_vline(dc, calibration_ptr->width - 1, 1, 1 + 15);
+				RTGUI_WIDGET_FOREGROUND(widget) = red;
+				rtgui_dc_fill_circle(dc, calibration_ptr->width - 1, 0, 4);
+				break;
+				
+			case CALIBRATION_STEP_LEFTBOTTOM:
+				rtgui_dc_draw_hline(dc, 1, 1 + 15, calibration_ptr->height - 1);
+				rtgui_dc_draw_vline(dc, 1, calibration_ptr->height - 1 - 15, calibration_ptr->height - 1);
+				RTGUI_WIDGET_FOREGROUND(widget) = red;
+				rtgui_dc_fill_circle(dc, 0, calibration_ptr->height - 1, 4);
+				break;
+			
+			case CALIBRATION_STEP_RIGHTBOTTOM:
+				rtgui_dc_draw_hline(dc, calibration_ptr->width - 1 - 15, calibration_ptr->width - 1, calibration_ptr->height - 1);
+				rtgui_dc_draw_vline(dc, calibration_ptr->width - 1, calibration_ptr->height - 1 - 15, calibration_ptr->height - 1);
+				RTGUI_WIDGET_FOREGROUND(widget) = red;
+				rtgui_dc_fill_circle(dc, calibration_ptr->width - 1, calibration_ptr->height - 1, 4);
+				break;
+			
+			case CALIBRATION_STEP_CENTER:
+				rtgui_dc_draw_hline(dc, calibration_ptr->width/2 - 15, calibration_ptr->width/2 + 15, calibration_ptr->height/2);
+				rtgui_dc_draw_vline(dc, calibration_ptr->width/2, calibration_ptr->height/2 - 15, calibration_ptr->height/2 + 15);
+				RTGUI_WIDGET_FOREGROUND(widget) = red;
+				rtgui_dc_fill_circle(dc, calibration_ptr->width/2, calibration_ptr->height/2, 4);
+				break;
+		}
+		rtgui_dc_end_drawing(dc);
+	}
+		break;
+
+	case RTGUI_EVENT_COMMAND:
+		{
+			struct rtgui_event_command* ecmd = (struct rtgui_event_command*)event;
+			
+			switch (ecmd->command_id)
+			{
+			case TOUCH_WIN_UPDATE:
+				rtgui_widget_update(widget);
+				break;
+			case TOUCH_WIN_CLOSE:
+				rtgui_win_close(RTGUI_WIN(widget));
+				break;
+			}
+		}
+		return RT_TRUE;
+
+	default:
+		rtgui_win_event_handler(widget, event);
+	}
+
+	return RT_FALSE;
+}
+
+void calibration_entry(void* parameter)
+{
+	rt_mq_t mq;
+	rtgui_win_t* win;
+	struct rtgui_rect rect;
+
+	mq = rt_mq_create("cali", 40, 8, RT_IPC_FLAG_FIFO);
+	if (mq == RT_NULL) return;
+
+	rtgui_thread_register(rt_thread_self(), mq);
+
+	rtgui_graphic_driver_get_default_rect(&rect);
+
+	/* set screen rect */
+	calibration_ptr->width = rect.x2;
+	calibration_ptr->height = rect.y2;
+
+	/* create calibration window */
+	win = rtgui_win_create(RT_NULL,
+		"calibration", &rect, RTGUI_WIN_STYLE_NO_TITLE | RTGUI_WIN_STYLE_NO_BORDER);
+	rtgui_widget_set_event_handler(RTGUI_WIDGET(win), calibration_event_handler);
+	if (win != RT_NULL)
+	{
+		rtgui_win_show(win, RT_FALSE);
+		// rtgui_widget_update(RTGUI_WIDGET(win));
+		rtgui_win_event_loop(win);
+	}
+
+	rtgui_thread_deregister(rt_thread_self());
+	rt_mq_delete(mq);
+
+	/* set calibration data */
+	rt_device_control(calibration_ptr->device, RT_TOUCH_CALIBRATION_DATA, &calibration_ptr->data);
+
+	/* recover to normal */
+	rt_device_control(calibration_ptr->device, RT_TOUCH_NORMAL, RT_NULL);
+
+	/* release memory */
+	rt_free(calibration_ptr);
+	calibration_ptr = RT_NULL;
+}
+
+void calibration_init()
+{
+	rt_device_t device;
+
+	device = rt_device_find("touch");
+	if (device == RT_NULL) return; /* no this device */
+
+	calibration_ptr = (struct calibration_session*)rt_malloc(sizeof(struct calibration_session));
+	rt_memset(calibration_ptr, 0, sizeof(struct calibration_data));
+	calibration_ptr->device = device;
+
+	rt_device_control(calibration_ptr->device, RT_TOUCH_CALIBRATION, (void*)calibration_data_post);
+
+	calibration_ptr->tid = rt_thread_create("cali", calibration_entry, RT_NULL,
+		2048, 20, 5);
+	if (calibration_ptr->tid != RT_NULL) rt_thread_startup(calibration_ptr->tid);
+}
+#include <finsh.h>
+void calibration()
+{
+	calibration_init();
+}
+FINSH_FUNCTION_EXPORT(calibration, perform touch calibration);
+

+ 175 - 62
bsp/mini2440/touch.c

@@ -1,9 +1,11 @@
 #include <rthw.h>
 #include <rtthread.h>
 #include <s3c24x0.h>
-#include <rtgui/event.h>
+#include <rtgui/rtgui_system.h>
 #include <rtgui/rtgui_server.h>
 
+#include "touch.h"
+
 /* ADCCON Register Bits */
 #define S3C2410_ADCCON_ECFLG		(1<<15)
 #define S3C2410_ADCCON_PRSCEN		(1<<14)
@@ -16,7 +18,6 @@
 #define S3C2410_ADCCON_ENABLE_START	(1<<0)
 #define S3C2410_ADCCON_STARTMASK	(0x3<<0)
 
-
 /* ADCTSC Register Bits */
 #define S3C2410_ADCTSC_UD_SEN		(1<<8) /* ghcstop add for s3c2440a */
 #define S3C2410_ADCTSC_YM_SEN		(1<<7)
@@ -46,6 +47,11 @@
 #define AUTOPST	     (S3C2410_ADCTSC_YM_SEN | S3C2410_ADCTSC_YP_SEN | S3C2410_ADCTSC_XP_SEN | \
 		     S3C2410_ADCTSC_AUTO_PST | S3C2410_ADCTSC_XY_PST(0))
 
+#define X_MIN		74
+#define X_MAX		934
+#define Y_MIN		89
+#define Y_MAX		920
+
 struct s3c2410ts
 {
 	long xp;
@@ -60,75 +66,113 @@ struct s3c2410ts
 };
 static struct s3c2410ts ts;
 
-#define X_MIN		74
-#define X_MAX		934
-#define Y_MIN		89
-#define Y_MAX		920
-
-#ifdef RT_USING_RTGUI
-#include <rtgui/event.h>
-void report_touch_input(int updown)
+struct rtgui_touch_device
 {
-	long xp, yp;
-	struct rtgui_event_mouse emouse;
+    struct rt_device parent;
 
-	xp = ts.xp >> ts.shift;
-	yp = ts.yp >> ts.shift;
+    rt_timer_t poll_timer;
+    rt_uint16_t x, y;
 
-	xp = 240 * (xp-X_MIN)/(X_MAX-X_MIN);
-	yp = 320 - (320*(yp-Y_MIN)/(Y_MAX-Y_MIN));
+    rt_bool_t calibrating;
+    rt_touch_calibration_func_t calibration_func;
 
-	emouse.parent.type = RTGUI_EVENT_MOUSE_BUTTON;
-	emouse.parent.sender = RT_NULL;
+    rt_uint16_t min_x, max_x;
+    rt_uint16_t min_y, max_y;
+};
+static struct rtgui_touch_device *touch = RT_NULL;
+static int first_down_report;
 
-	emouse.x = xp;
-	emouse.y = yp;
+#include <rtgui/event.h>
+static void report_touch_input(int updown)
+{
+	struct rtgui_event_mouse emouse;
 
 	/* set emouse button */
+	emouse.button |= RTGUI_MOUSE_BUTTON_LEFT;
+	emouse.parent.sender = RT_NULL;
+	
 	if (updown)
 	{
-		emouse.button = RTGUI_MOUSE_BUTTON_DOWN;
+		ts.xp = ts.xp / ts.count;
+		ts.yp = ts.yp / ts.count;;
+
+		ts.xp = 240 * (ts.xp-touch->min_x)/(touch->max_x-touch->min_x);
+		ts.yp = 320 - (320*(ts.yp-touch->min_y)/(touch->max_y-touch->min_y));
+
+		touch->x = ts.xp;
+		touch->y = ts.yp;
+
+		emouse.x = touch->x;
+		emouse.y = touch->y;
+	
+		if(first_down_report == 1)
+		{
+			emouse.parent.type = RTGUI_EVENT_MOUSE_BUTTON;
+			emouse.button |= RTGUI_MOUSE_BUTTON_DOWN;
+		}
+		else
+		{	
+			emouse.parent.type = RTGUI_EVENT_MOUSE_MOTION;
+			emouse.button = 0;
+		}	
 	}
 	else
 	{
-		emouse.button = RTGUI_MOUSE_BUTTON_UP;
+		emouse.x = touch->x;
+		emouse.y = touch->y;	
+		emouse.parent.type = RTGUI_EVENT_MOUSE_BUTTON;
+		emouse.button |= RTGUI_MOUSE_BUTTON_UP;
+		if ((touch->calibrating == RT_TRUE) && (touch->calibration_func != RT_NULL))
+		{
+			/* callback function */
+			touch->calibration_func(emouse.x, emouse.y);
+		}
 	}
 
-	/* rt_kprintf("touch %s: ts.x: %d, ts.y: %d, count:%d\n", updown? "down" : "up",
-		xp, yp, ts.count);  */
-
-	emouse.button |= RTGUI_MOUSE_BUTTON_LEFT;
-
-	rtgui_server_post_event((&emouse.parent), sizeof(emouse));
+	/*	
+		rt_kprintf("touch %s: ts.x: %d, ts.y: %d\n", updown? "down" : "up",
+		touch->x, touch->y);
+	*/
+	
+	/* send event to server */
+	if (touch->calibrating != RT_TRUE)
+	{	
+		rtgui_server_post_event((&emouse.parent), sizeof(emouse));
+	}	
 }
-#endif
 
-static int first_down_report;
-/* fixed me, use timer to support move action */
-static void touch_timer_fire(void)
+static void touch_timer_fire(void* parameter)
 {
-	if (ts.count == 3)
+  	rt_uint32_t data0;
+  	rt_uint32_t data1;
+	int updown;
+
+  	data0 = ADCDAT0;
+  	data1 = ADCDAT1;
+
+ 	updown = (!(data0 & S3C2410_ADCDAT0_UPDOWN)) && (!(data1 & S3C2410_ADCDAT0_UPDOWN));
+
+ 	if (updown)
 	{
-		 if (first_down_report)
+ 		if (ts.count != 0)
 		{
-#ifdef RT_USING_RTGUI
-			report_touch_input(1);
-			first_down_report = 0;
-#endif
-		}
-	}
+			report_touch_input(updown);
+ 		}
+
+ 		ts.xp = 0;
+ 		ts.yp = 0;
+ 		ts.count = 0;
 
-	ADCTSC = S3C2410_ADCTSC_PULL_UP_DISABLE | AUTOPST;
-	ADCCON |= S3C2410_ADCCON_ENABLE_START;
+ 		ADCTSC = S3C2410_ADCTSC_PULL_UP_DISABLE | AUTOPST;
+ 		ADCCON |= S3C2410_ADCCON_ENABLE_START;
+ 	}
 }
 
-void s3c2410_adc_stylus_action(void)
+static void s3c2410_adc_stylus_action(void)
 {
 	rt_uint32_t data0;
 	rt_uint32_t data1;
 
-	SUBSRCPND |= BIT_SUB_ADC;
-
 	data0 = ADCDAT0;
 	data1 = ADCDAT1;
 	
@@ -143,48 +187,56 @@ void s3c2410_adc_stylus_action(void)
 	}
 	else
 	{
-		//touch_timer_fire();
+		if (first_down_report)
+		{
+			report_touch_input(1);
+			ts.xp = 0;
+			ts.yp = 0;
+			ts.count = 0;
+			first_down_report = 0;
+		}
+		/* start timer */
+		rt_timer_start(touch->poll_timer);
 		ADCTSC = WAIT4INT(1);
 	}
+
+	SUBSRCPND |= BIT_SUB_ADC;
 }
 
-void s3c2410_intc_stylus_updown(void)
+static void s3c2410_intc_stylus_updown(void)
 {
 	rt_uint32_t data0;
 	rt_uint32_t data1;
 	int updown;
 
-	SUBSRCPND |= BIT_SUB_TC;
-
 	data0 = ADCDAT0;
 	data1 = ADCDAT1;
 
 	updown = (!(data0 & S3C2410_ADCDAT0_UPDOWN)) && (!(data1 & S3C2410_ADCDAT0_UPDOWN));
 
+	/* rt_kprintf("stylus: %s\n", updown? "down" : "up"); */
+
 	if (updown) 
 	{
-		touch_timer_fire();
-	}
+		touch_timer_fire(0);
+	}	
 	else
 	{
+		/* stop timer */
+		rt_timer_stop(touch->poll_timer);
+		first_down_report = 1;
 		if (ts.xp >= 0 && ts.yp >= 0)
 		{
-		#ifdef RT_USING_RTGUI
-			report_touch_input(1);
-			report_touch_input(0);
-			first_down_report = 1;
-		#endif
+			report_touch_input(updown);
 		}
-
-		ts.xp = 0;
-		ts.yp = 0;
 		ts.count = 0;
-	
 		ADCTSC = WAIT4INT(0);
 	}
+
+	SUBSRCPND |= BIT_SUB_TC;
 }
 
-void rt_touch_handler(int irqno)
+static void rt_touch_handler(int irqno)
 {
 	if (SUBSRCPND & BIT_SUB_ADC)
 	{
@@ -202,7 +254,8 @@ void rt_touch_handler(int irqno)
 	INTPND |= (rt_uint32_t)(1 << INTADC);
 }
 
-void rt_hw_touch_init(void)
+/* RT-Thread Device Interface */
+static rt_err_t rtgui_touch_init (rt_device_t dev)
 {
 	/* init touch screen structure */
 	rt_memset(&ts, 0, sizeof(struct s3c2410ts));
@@ -232,5 +285,65 @@ void rt_hw_touch_init(void)
 	INTSUBMSK &= ~BIT_SUB_TC;
 
 	first_down_report = 1;
+
+	return RT_EOK;
+}
+
+static rt_err_t rtgui_touch_control (rt_device_t dev, rt_uint8_t cmd, void *args)
+{
+    switch (cmd)
+    {
+    case RT_TOUCH_CALIBRATION:
+        touch->calibrating = RT_TRUE;
+        touch->calibration_func = (rt_touch_calibration_func_t)args;
+        break;
+
+    case RT_TOUCH_NORMAL:
+        touch->calibrating = RT_FALSE;
+        break;
+
+    case RT_TOUCH_CALIBRATION_DATA:
+    {
+        struct calibration_data* data;
+
+        data = (struct calibration_data*) args;
+
+        //update
+        touch->min_x = data->min_x;
+        touch->max_x = data->max_x;
+        touch->min_y = data->min_y;
+        touch->max_y = data->max_y;
+    }
+    break;
+    }
+
+    return RT_EOK;
+}
+
+void rtgui_touch_hw_init(void)
+{
+    touch = (struct rtgui_touch_device*)rt_malloc (sizeof(struct rtgui_touch_device));
+    if (touch == RT_NULL) return; /* no memory yet */
+
+    /* clear device structure */
+    rt_memset(&(touch->parent), 0, sizeof(struct rt_device));
+    touch->calibrating = RT_FALSE;
+    touch->min_x = X_MIN;
+    touch->max_x = X_MAX;
+    touch->min_y = Y_MIN;
+    touch->max_y = X_MAX;
+
+    /* init device structure */
+    touch->parent.type = RT_Device_Class_Unknown;
+    touch->parent.init = rtgui_touch_init;
+    touch->parent.control = rtgui_touch_control;
+    touch->parent.private = RT_NULL;
+
+    /* create 1/8 second timer */
+    touch->poll_timer = rt_timer_create("touch", touch_timer_fire, RT_NULL,
+                                        RT_TICK_PER_SECOND/8, RT_TIMER_FLAG_PERIODIC);
+
+    /* register touch device to RT-Thread */
+    rt_device_register(&(touch->parent), "touch", RT_DEVICE_FLAG_RDWR);
 }
 

+ 21 - 0
bsp/mini2440/touch.h

@@ -0,0 +1,21 @@
+#ifndef __TOUCH_H__
+#define __TOUCH_H__
+
+#include <rtthread.h>
+
+#define RT_TOUCH_NORMAL				0
+#define RT_TOUCH_CALIBRATION_DATA	1
+#define RT_TOUCH_CALIBRATION 		2
+
+struct calibration_data
+{
+	rt_uint16_t min_x, max_x;
+	rt_uint16_t min_y, max_y;
+};
+
+typedef void (*rt_touch_calibration_func_t)(rt_uint16_t x, rt_uint16_t y);
+
+void rtgui_touch_hw_init(void);
+
+#endif
+