1 //==========================================================================
5 // Touchscreen driver for the Compaq iPAQ
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 Compaq IPAQ
49 //####DESCRIPTIONEND####
51 //==========================================================================
54 #include <pkgconf/devs_touch_ipaq.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/hal_sa11x0.h>
62 #include <cyg/hal/ipaq.h>
63 #include <cyg/infra/cyg_type.h>
64 #include <cyg/infra/cyg_ass.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>
71 #include <cyg/hal/atmel_support.h>
73 // Functions in this module
75 static Cyg_ErrNo ts_read(cyg_io_handle_t handle,
78 static cyg_bool ts_select(cyg_io_handle_t handle,
81 static Cyg_ErrNo ts_set_config(cyg_io_handle_t handle,
85 static Cyg_ErrNo ts_get_config(cyg_io_handle_t handle,
89 static bool ts_init(struct cyg_devtab_entry *tab);
90 static Cyg_ErrNo ts_lookup(struct cyg_devtab_entry **tab,
91 struct cyg_devtab_entry *st,
94 CHAR_DEVIO_TABLE(ipaq_ts_handlers,
95 NULL, // Unsupported write() function
101 CHAR_DEVTAB_ENTRY(ipaq_ts_device,
102 CYGDAT_DEVS_TOUCH_IPAQ_NAME,
103 NULL, // Base device name
107 NULL); // Private data pointer
114 #define MAX_EVENTS CYGNUM_DEVS_TOUCH_IPAQ_EVENT_BUFFER_SIZE
115 static int num_events;
116 static int _event_put, _event_get;
117 static bool pen_down = false;
118 static struct _event _events[MAX_EVENTS];
120 static bool _is_open = false;
121 #ifdef DEBUG_RAW_EVENTS
122 static unsigned char _ts_buf[512];
123 static int _ts_buf_ptr = 0;
127 // Note: this routine is called from the Atmel processing DSR
130 ts_handler(atmel_pkt *pkt)
132 unsigned char *dp = pkt->data;
133 static short lastX, lastY;
137 #ifdef DEBUG_RAW_EVENTS
138 memcpy(&_ts_buf[_ts_buf_ptr], pkt->data, 8);
140 if (_ts_buf_ptr == 512) {
141 diag_printf("TS handler\n");
142 diag_dump_buf(_ts_buf, 512);
146 // Try and interpret the mouse data
147 if ((dp[0] & 0x0F) == 0) {
148 // This is a pen up event
153 // Some sort of event with the pen down
154 x = lastX = (dp[1] << 8) | dp[2];
155 y = lastY = (dp[3] << 8) | dp[4];
158 if (num_events < MAX_EVENTS) {
160 ev = &_events[_event_put++];
161 if (_event_put == MAX_EVENTS) {
164 ev->button_state = pen_down ? 0x04 : 0x00;
167 if (ts_select_active) {
168 ts_select_active = false;
169 cyg_selwakeup(&ts_select_info);
180 static bounds xBounds = {1024, 0, 1024};
181 static bounds yBounds = {1024, 0, 1024};
184 ts_read(cyg_io_handle_t handle,
190 unsigned char *bp = (unsigned char *)buffer;
192 cyg_scheduler_lock(); // Prevent interaction with DSR code
193 while (tot >= sizeof(struct _event)) {
194 if (num_events > 0) {
195 ev = &_events[_event_get++];
196 if (_event_get == MAX_EVENTS) {
200 if (ev->xPos > xBounds.max) xBounds.max = ev->xPos;
201 if (ev->xPos < xBounds.min) xBounds.min = ev->xPos;
202 if (ev->yPos > yBounds.max) yBounds.max = ev->yPos;
203 if (ev->yPos < yBounds.min) yBounds.min = ev->yPos;
204 if ((xBounds.span = xBounds.max - xBounds.min) <= 1) {
207 if ((yBounds.span = yBounds.max - yBounds.min) <= 1) {
210 // Scale values - done here so these potentially lengthy
211 // operations take place outside of interrupt processing
212 ev->xPos = ((xBounds.max - ev->xPos) * 320) / xBounds.span;
213 ev->yPos = ((yBounds.max - ev->yPos) * 240) / yBounds.span;
214 memcpy(bp, ev, sizeof(*ev));
219 break; // No more events
222 cyg_scheduler_unlock(); // Allow DSRs again
228 ts_select(cyg_io_handle_t handle,
232 if (which == CYG_FREAD) {
233 cyg_scheduler_lock(); // Prevent interaction with DSR code
234 if (num_events > 0) {
235 cyg_scheduler_unlock(); // Reallow interaction with DSR code
238 if (!ts_select_active) {
239 ts_select_active = true;
240 cyg_selrecord(info, &ts_select_info);
242 cyg_scheduler_unlock(); // Reallow interaction with DSR code
248 ts_set_config(cyg_io_handle_t handle,
257 ts_get_config(cyg_io_handle_t handle,
266 ts_init(struct cyg_devtab_entry *tab)
268 cyg_selinit(&ts_select_info);
273 ts_lookup(struct cyg_devtab_entry **tab,
274 struct cyg_devtab_entry *st,
279 atmel_register(ATMEL_CMD_TOUCH, ts_handler);
280 atmel_interrupt_mode(true);