diff --git a/bsp/mini2440/SConscript b/bsp/mini2440/SConscript index acbc699cb76e15d369cd8cd23088d1f58a240a49..ef49448b7b476aab55aea5ed66fb7a464eaae216 100644 --- a/bsp/mini2440/SConscript +++ b/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: diff --git a/bsp/mini2440/application.c b/bsp/mini2440/application.c index 5d591867ec56703bee358642db8f70522f7a2b87..97690e466ce92255de169712cc5324e40e576045 100644 --- a/bsp/mini2440/application.c +++ b/bsp/mini2440/application.c @@ -20,6 +20,7 @@ #include #include +#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; diff --git a/bsp/mini2440/calibration.c b/bsp/mini2440/calibration.c new file mode 100644 index 0000000000000000000000000000000000000000..d15270bffd64d3f86c3b1e8e6fb32a06467f82f7 --- /dev/null +++ b/bsp/mini2440/calibration.c @@ -0,0 +1,233 @@ +#include +#include +#include +#include + +#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 +void calibration() +{ + calibration_init(); +} +FINSH_FUNCTION_EXPORT(calibration, perform touch calibration); + diff --git a/bsp/mini2440/touch.c b/bsp/mini2440/touch.c index 8aef45a23b8cd12a70f9f41b915bc4e334612309..c1d30aa44215ff4d62a2005b4a466836b8ade1da 100644 --- a/bsp/mini2440/touch.c +++ b/bsp/mini2440/touch.c @@ -1,9 +1,11 @@ #include #include #include -#include +#include #include +#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 -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 +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); } diff --git a/bsp/mini2440/touch.h b/bsp/mini2440/touch.h new file mode 100644 index 0000000000000000000000000000000000000000..2a1296bbefda62b329f8c03271d5f370ccf639f1 --- /dev/null +++ b/bsp/mini2440/touch.h @@ -0,0 +1,21 @@ +#ifndef __TOUCH_H__ +#define __TOUCH_H__ + +#include + +#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 +