1 //==========================================================================
5 // Touchscreen driver for the Agilent aaed2000
7 //==========================================================================
8 //####ECOSGPLCOPYRIGHTBEGIN####
9 // -------------------------------------------
10 // This file is part of eCos, the Embedded Configurable Operating System.
11 // Copyright (C) 1998, 1999, 2000, 2001, 2002 Red Hat, Inc.
13 // eCos is free software; you can redistribute it and/or modify it under
14 // the terms of the GNU General Public License as published by the Free
15 // Software Foundation; either version 2 or (at your option) any later version.
17 // eCos is distributed in the hope that it will be useful, but WITHOUT ANY
18 // WARRANTY; without even the implied warranty of MERCHANTABILITY or
19 // FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
22 // You should have received a copy of the GNU General Public License along
23 // with eCos; if not, write to the Free Software Foundation, Inc.,
24 // 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
26 // As a special exception, if other files instantiate templates or use macros
27 // or inline functions from this file, or you compile this file and link it
28 // with other works to produce a work based on this file, this file does not
29 // by itself cause the resulting work to be covered by the GNU General Public
30 // License. However the source code for this file must still be made available
31 // in accordance with section (3) of the GNU General Public License.
33 // This exception does not invalidate any other reasons why a work based on
34 // this file might be covered by the GNU General Public License.
36 // Alternative licenses for eCos may be arranged by contacting Red Hat, Inc.
37 // at http://sources.redhat.com/ecos/ecos-license/
38 // -------------------------------------------
39 //####ECOSGPLCOPYRIGHTEND####
40 //==========================================================================
41 //#####DESCRIPTIONBEGIN####
44 // Contributors: gthomas
47 // Description: Touchscreen driver for Agilent AAED2000
49 //####DESCRIPTIONEND####
51 //==========================================================================
54 #include <pkgconf/devs_touch_aaed2000.h>
56 #include <cyg/kernel/kapi.h>
57 #include <cyg/hal/hal_io.h>
58 #include <cyg/hal/hal_arch.h>
59 #include <cyg/hal/drv_api.h>
60 #include <cyg/hal/hal_intr.h>
61 #include <cyg/hal/aaed2000.h>
62 #include <cyg/infra/cyg_type.h>
63 #include <cyg/infra/cyg_ass.h>
64 #include <cyg/infra/diag.h>
66 #include <cyg/fileio/fileio.h> // For select() functionality
67 static cyg_selinfo ts_select_info;
68 static cyg_bool ts_select_active;
70 #include <cyg/io/devtab.h>
73 #define ADS_START (1 << 7)
74 #define ADS_MEASURE_Y (0x01 << 4)
75 #define ADS_MEASURE_X (0x05 << 4)
76 #define ADS_MODE_12_BIT 0
81 #define X_THRESHOLD 0x80
82 #define Y_THRESHOLD 0x80
84 // Functions in this module
86 static Cyg_ErrNo ts_read(cyg_io_handle_t handle,
89 static cyg_bool ts_select(cyg_io_handle_t handle,
92 static Cyg_ErrNo ts_set_config(cyg_io_handle_t handle,
96 static Cyg_ErrNo ts_get_config(cyg_io_handle_t handle,
100 static bool ts_init(struct cyg_devtab_entry *tab);
101 static Cyg_ErrNo ts_lookup(struct cyg_devtab_entry **tab,
102 struct cyg_devtab_entry *st,
105 CHAR_DEVIO_TABLE(aaed2000_ts_handlers,
106 NULL, // Unsupported write() function
112 CHAR_DEVTAB_ENTRY(aaed2000_ts_device,
113 CYGDAT_DEVS_TOUCH_AAED2000_NAME,
114 NULL, // Base device name
115 &aaed2000_ts_handlers,
118 NULL); // Private data pointer
125 #define MAX_EVENTS CYGNUM_DEVS_TOUCH_AAED2000_EVENT_BUFFER_SIZE
126 static int num_events;
127 static int _event_put, _event_get;
128 static struct _event _events[MAX_EVENTS];
130 static bool _is_open = false;
131 #ifdef DEBUG_RAW_EVENTS
132 static unsigned char _ts_buf[512];
133 static int _ts_buf_ptr = 0;
136 #define STACK_SIZE CYGNUM_HAL_STACK_SIZE_TYPICAL
137 static char ts_scan_stack[STACK_SIZE];
138 static cyg_thread ts_scan_thread_data;
139 static cyg_handle_t ts_scan_thread_handle;
140 #define SCAN_FREQ 20 // Hz
141 //#define SCAN_FREQ 5 // Hz
142 #define SCAN_DELAY ((1000/SCAN_FREQ)/10)
151 static bounds xBounds = {1024, 0, 1024};
152 static bounds yBounds = {1024, 0, 1024};
155 ts_read(cyg_io_handle_t handle,
161 unsigned char *bp = (unsigned char *)buffer;
163 cyg_scheduler_lock(); // Prevent interaction with DSR code
164 while (tot >= sizeof(struct _event)) {
165 if (num_events > 0) {
166 ev = &_events[_event_get++];
167 if (_event_get == MAX_EVENTS) {
171 if (ev->xPos > xBounds.max) xBounds.max = ev->xPos;
172 if (ev->xPos < xBounds.min) xBounds.min = ev->xPos;
173 if (ev->yPos > yBounds.max) yBounds.max = ev->yPos;
174 if (ev->yPos < yBounds.min) yBounds.min = ev->yPos;
175 if ((xBounds.span = xBounds.max - xBounds.min) <= 1) {
178 if ((yBounds.span = yBounds.max - yBounds.min) <= 1) {
181 // Scale values - done here so these potentially lengthy
182 // operations take place outside of interrupt processing
184 diag_printf("Raw[%d,%d], X[%d,%d,%d], Y[%d,%d,%d]",
186 xBounds.max, xBounds.min, xBounds.span,
187 yBounds.max, yBounds.min, yBounds.span);
189 ev->xPos = 640 - (((xBounds.max - ev->xPos) * 640) / xBounds.span);
190 ev->yPos = 480 - (((yBounds.max - ev->yPos) * 480) / yBounds.span);
192 diag_printf(", Cooked[%d,%d]\n",
195 memcpy(bp, ev, sizeof(*ev));
200 break; // No more events
203 cyg_scheduler_unlock(); // Allow DSRs again
209 ts_select(cyg_io_handle_t handle,
213 if (which == CYG_FREAD) {
214 cyg_scheduler_lock(); // Prevent interaction with DSR code
215 if (num_events > 0) {
216 cyg_scheduler_unlock(); // Reallow interaction with DSR code
219 if (!ts_select_active) {
220 ts_select_active = true;
221 cyg_selrecord(info, &ts_select_info);
223 cyg_scheduler_unlock(); // Reallow interaction with DSR code
229 ts_set_config(cyg_io_handle_t handle,
238 ts_get_config(cyg_io_handle_t handle,
247 ts_init(struct cyg_devtab_entry *tab)
251 // Initialize SSP interface
253 while (*(volatile cyg_uint32 *)AAEC_SSP_SR & AAEC_SSP_SR_RNE) {
254 _dummy = *(volatile cyg_uint32 *)AAEC_SSP_DR; // Drain FIFO
257 *(volatile cyg_uint32 *)AAEC_SSP_CR0 =
258 (1 << AAEC_SSP_CR0_SSE) | // SSP enable
259 (37 << AAEC_SSP_CR0_SCR) | // Serial clock rate
260 (AAEC_SSP_CR0_FRF_NAT << AAEC_SSP_CR0_FRF) | // MicroWire
261 ((12-1) << AAEC_SSP_CR0_SIZE); // 12 bit words
262 *(volatile cyg_uint32 *)AAEC_SSP_CR1 =
263 (1 << AAEC_SSP_CR1_FEN); // Enable FIFO
264 *(volatile cyg_uint32 *)AAEC_SSP_CPSR = 2; // Clock prescale
265 *(volatile cyg_uint32 *)AAEC_PFDDR &= ~(1<<0); // TS uses port F bit 0
266 cyg_drv_interrupt_acknowledge(CYGNUM_HAL_INTERRUPT_TS);
267 cyg_selinit(&ts_select_info);
276 *(volatile cyg_uint32 *)AAEC_SSP_DR = (axis | ADS_START | ADS_MODE_12_BIT | ADS_PD0);
277 *(volatile cyg_uint32 *)AAEC_SSP_DR = (axis | ADS_START | ADS_MODE_12_BIT);
279 while ((*(volatile cyg_uint32 *)AAEC_SSP_SR & AAEC_SSP_SR_RNE) == 0);
280 res = *(volatile cyg_uint32 *)AAEC_SSP_DR; // ignore first datum
282 while ((*(volatile cyg_uint32 *)AAEC_SSP_SR & AAEC_SSP_SR_RNE) == 0);
283 res = *(volatile cyg_uint32 *)AAEC_SSP_DR;
288 ts_scan(cyg_addrword_t param)
295 diag_printf("Touch Screen thread started\n");
296 // Discard the first sample - it's always 0
297 x = read_ts(ADS_MEASURE_X);
298 y = read_ts(ADS_MEASURE_Y);
302 cyg_thread_delay(SCAN_DELAY);
303 if ((*(volatile cyg_uint32 *)AAEC_PFDR & TS_INT) == 0) {
305 x = read_ts(ADS_MEASURE_X);
306 y = read_ts(ADS_MEASURE_Y);
307 // diag_printf("X = %x, Y = %x\n", x, y);
308 if ((x < X_THRESHOLD) || (y < Y_THRESHOLD)) {
309 // Ignore 'bad' samples
312 lastX = x; lastY = y;
316 // Capture first 'up' event
321 continue; // Nothing new to report
324 if (num_events < MAX_EVENTS) {
326 ev = &_events[_event_put++];
327 if (_event_put == MAX_EVENTS) {
330 ev->button_state = pen_down ? 0x04 : 0x00;
333 if (ts_select_active) {
334 ts_select_active = false;
335 cyg_selwakeup(&ts_select_info);
338 #ifdef DEBUG_RAW_EVENTS
339 memcpy(&_ts_buf[_ts_buf_ptr], pkt->data, 8);
341 if (_ts_buf_ptr == 512) {
342 diag_printf("TS handler\n");
343 diag_dump_buf(_ts_buf, 512);
351 ts_lookup(struct cyg_devtab_entry **tab,
352 struct cyg_devtab_entry *st,
357 cyg_thread_create(1, // Priority
359 0, // entry parameter
360 "Touch Screen scan", // Name
361 &ts_scan_stack[0], // Stack
363 &ts_scan_thread_handle, // Handle
364 &ts_scan_thread_data // Thread data structure
366 cyg_thread_resume(ts_scan_thread_handle); // Start it