OpenCores
URL https://opencores.org/ocsvn/openrisc/openrisc/trunk

Subversion Repositories openrisc

[/] [openrisc/] [trunk/] [rtos/] [ecos-2.0/] [packages/] [devs/] [touch/] [arm/] [aaed2000/] [v2_0/] [src/] [aaed2000_ts.c] - Blame information for rev 174

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 27 unneback
//==========================================================================
2
//
3
//      aaed2000_ts.c
4
//
5
//      Touchscreen driver for the Agilent aaed2000
6
//
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.
12
//
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.
16
//
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
20
// for more details.
21
//
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.
25
//
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.
32
//
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.
35
//
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####
42
//
43
// Author(s):    gthomas
44
// Contributors: gthomas
45
// Date:         2002-03-05
46
// Purpose:      
47
// Description:  Touchscreen driver for Agilent AAED2000
48
//
49
//####DESCRIPTIONEND####
50
//
51
//==========================================================================
52
 
53
 
54
#include <pkgconf/devs_touch_aaed2000.h>
55
 
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>
65
 
66
#include <cyg/fileio/fileio.h>  // For select() functionality
67
static cyg_selinfo      ts_select_info;
68
static cyg_bool         ts_select_active;
69
 
70
#include <cyg/io/devtab.h>
71
 
72
/* ADS7846 flags */
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
77
#define ADS_PD0                 0
78
 
79
// Misc constants
80
#define TS_INT (1<<0)
81
#define X_THRESHOLD 0x80
82
#define Y_THRESHOLD 0x80
83
 
84
// Functions in this module
85
 
86
static Cyg_ErrNo ts_read(cyg_io_handle_t handle,
87
                         void *buffer,
88
                         cyg_uint32 *len);
89
static cyg_bool  ts_select(cyg_io_handle_t handle,
90
                           cyg_uint32 which,
91
                           cyg_addrword_t info);
92
static Cyg_ErrNo ts_set_config(cyg_io_handle_t handle,
93
                               cyg_uint32 key,
94
                               const void *buffer,
95
                               cyg_uint32 *len);
96
static Cyg_ErrNo ts_get_config(cyg_io_handle_t handle,
97
                               cyg_uint32 key,
98
                               void *buffer,
99
                               cyg_uint32 *len);
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,
103
                           const char *name);
104
 
105
CHAR_DEVIO_TABLE(aaed2000_ts_handlers,
106
                 NULL,                                   // Unsupported write() function
107
                 ts_read,
108
                 ts_select,
109
                 ts_get_config,
110
                 ts_set_config);
111
 
112
CHAR_DEVTAB_ENTRY(aaed2000_ts_device,
113
                  CYGDAT_DEVS_TOUCH_AAED2000_NAME,
114
                  NULL,                                   // Base device name
115
                  &aaed2000_ts_handlers,
116
                  ts_init,
117
                  ts_lookup,
118
                  NULL);                                  // Private data pointer
119
 
120
struct _event {
121
    short button_state;
122
    short xPos, yPos;
123
    short _unused;
124
};
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];
129
 
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;
134
#endif
135
 
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)
143
 
144
 
145
typedef struct {
146
    short min;
147
    short max;
148
    short span;
149
} bounds;
150
 
151
static bounds xBounds = {1024, 0, 1024};
152
static bounds yBounds = {1024, 0, 1024};
153
 
154
static Cyg_ErrNo
155
ts_read(cyg_io_handle_t handle,
156
        void *buffer,
157
        cyg_uint32 *len)
158
{
159
    struct _event *ev;
160
    int tot = *len;
161
    unsigned char *bp = (unsigned char *)buffer;
162
 
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) {
168
                _event_get = 0;
169
            }
170
            // Self calibrate
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) {
176
                xBounds.span = 1;
177
            }
178
            if ((yBounds.span = yBounds.max - yBounds.min) <= 1) {
179
                yBounds.span = 1;
180
            }
181
            // Scale values - done here so these potentially lengthy
182
            // operations take place outside of interrupt processing
183
#ifdef DEBUG
184
            diag_printf("Raw[%d,%d], X[%d,%d,%d], Y[%d,%d,%d]",
185
                        ev->xPos, ev->yPos,
186
                        xBounds.max, xBounds.min, xBounds.span,
187
                        yBounds.max, yBounds.min, yBounds.span);
188
#endif
189
            ev->xPos = 640 - (((xBounds.max - ev->xPos) * 640) / xBounds.span);
190
            ev->yPos = 480 - (((yBounds.max - ev->yPos) * 480) / yBounds.span);
191
#ifdef DEBUG
192
            diag_printf(", Cooked[%d,%d]\n",
193
                        ev->xPos, ev->yPos);
194
#endif
195
            memcpy(bp, ev, sizeof(*ev));
196
            bp += sizeof(*ev);
197
            tot -= sizeof(*ev);
198
            num_events--;
199
        } else {
200
            break;  // No more events
201
        }
202
    }
203
    cyg_scheduler_unlock(); // Allow DSRs again
204
    *len -= tot;
205
    return ENOERR;
206
}
207
 
208
static cyg_bool
209
ts_select(cyg_io_handle_t handle,
210
          cyg_uint32 which,
211
          cyg_addrword_t info)
212
{
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
217
            return true;
218
        }
219
        if (!ts_select_active) {
220
            ts_select_active = true;
221
            cyg_selrecord(info, &ts_select_info);
222
        }
223
        cyg_scheduler_unlock();  // Reallow interaction with DSR code
224
    }
225
    return false;
226
}
227
 
228
static Cyg_ErrNo
229
ts_set_config(cyg_io_handle_t handle,
230
              cyg_uint32 key,
231
              const void *buffer,
232
              cyg_uint32 *len)
233
{
234
    return EINVAL;
235
}
236
 
237
static Cyg_ErrNo
238
ts_get_config(cyg_io_handle_t handle,
239
              cyg_uint32 key,
240
              void *buffer,
241
              cyg_uint32 *len)
242
{
243
    return EINVAL;
244
}
245
 
246
static bool
247
ts_init(struct cyg_devtab_entry *tab)
248
{
249
    cyg_uint32 _dummy;
250
 
251
    // Initialize SSP interface
252
#if 0
253
    while (*(volatile cyg_uint32 *)AAEC_SSP_SR & AAEC_SSP_SR_RNE) {
254
        _dummy = *(volatile cyg_uint32 *)AAEC_SSP_DR;  // Drain FIFO
255
    }
256
#endif
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);
268
    return true;
269
}
270
 
271
static cyg_uint32
272
read_ts(int axis)
273
{
274
    cyg_uint32 res;
275
 
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);
278
    // Wait for data
279
    while ((*(volatile cyg_uint32 *)AAEC_SSP_SR & AAEC_SSP_SR_RNE) == 0);
280
    res = *(volatile cyg_uint32 *)AAEC_SSP_DR;  // ignore first datum
281
    // Wait for data
282
    while ((*(volatile cyg_uint32 *)AAEC_SSP_SR & AAEC_SSP_SR_RNE) == 0);
283
    res = *(volatile cyg_uint32 *)AAEC_SSP_DR;
284
    return res;
285
}
286
 
287
static void
288
ts_scan(cyg_addrword_t param)
289
{
290
    short lastX, lastY;
291
    short x, y;
292
    struct _event *ev;
293
    bool pen_down;
294
 
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);
299
    lastX = lastY = -1;
300
    pen_down = false;
301
    while (true) {
302
        cyg_thread_delay(SCAN_DELAY);
303
        if ((*(volatile cyg_uint32 *)AAEC_PFDR & TS_INT) == 0) {
304
            // Pen is down
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
310
                continue;
311
            }
312
            lastX = x;  lastY = y;
313
            pen_down = true;
314
        } else {
315
            if (pen_down) {
316
                // Capture first 'up' event
317
                pen_down = false;
318
                x = lastX;
319
                y = lastY;
320
            } else {
321
                continue;  // Nothing new to report
322
            }
323
        }
324
        if (num_events < MAX_EVENTS) {
325
            num_events++;
326
            ev = &_events[_event_put++];
327
            if (_event_put == MAX_EVENTS) {
328
                _event_put = 0;
329
            }
330
            ev->button_state = pen_down ? 0x04 : 0x00;
331
            ev->xPos = x;
332
            ev->yPos = y;
333
            if (ts_select_active) {
334
                ts_select_active = false;
335
                cyg_selwakeup(&ts_select_info);
336
            }
337
        }
338
#ifdef DEBUG_RAW_EVENTS
339
        memcpy(&_ts_buf[_ts_buf_ptr], pkt->data, 8);
340
        _ts_buf_ptr += 8;
341
        if (_ts_buf_ptr == 512) {
342
            diag_printf("TS handler\n");
343
            diag_dump_buf(_ts_buf, 512);
344
            _ts_buf_ptr = 0;
345
        }
346
#endif
347
    }
348
}
349
 
350
static Cyg_ErrNo
351
ts_lookup(struct cyg_devtab_entry **tab,
352
          struct cyg_devtab_entry *st,
353
          const char *name)
354
{
355
    if (!_is_open) {
356
        _is_open = true;
357
        cyg_thread_create(1,                      // Priority
358
                          ts_scan,                // entry
359
                          0,                      // entry parameter
360
                          "Touch Screen scan",    // Name
361
                          &ts_scan_stack[0],      // Stack
362
                          STACK_SIZE,             // Size
363
                          &ts_scan_thread_handle, // Handle
364
                          &ts_scan_thread_data    // Thread data structure
365
        );
366
        cyg_thread_resume(ts_scan_thread_handle);    // Start it
367
    }
368
    return ENOERR;
369
}

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.