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

Subversion Repositories openrisc

[/] [openrisc/] [trunk/] [rtos/] [ecos-3.0/] [packages/] [devs/] [touch/] [arm/] [aaed2000/] [current/] [src/] [aaed2000_ts.c] - Blame information for rev 786

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 786 skrzyp
//==========================================================================
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 Free Software Foundation, 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      
16
// version.                                                                 
17
//
18
// eCos is distributed in the hope that it will be useful, but WITHOUT      
19
// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or    
20
// FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License    
21
// for more details.                                                        
22
//
23
// You should have received a copy of the GNU General Public License        
24
// along with eCos; if not, write to the Free Software Foundation, Inc.,    
25
// 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.            
26
//
27
// As a special exception, if other files instantiate templates or use      
28
// macros or inline functions from this file, or you compile this file      
29
// and link it with other works to produce a work based on this file,       
30
// this file does not by itself cause the resulting work to be covered by   
31
// the GNU General Public License. However the source code for this file    
32
// must still be made available in accordance with section (3) of the GNU   
33
// General Public License v2.                                               
34
//
35
// This exception does not invalidate any other reasons why a work based    
36
// on this file might be covered by the GNU General Public License.         
37
// -------------------------------------------                              
38
// ####ECOSGPLCOPYRIGHTEND####                                              
39
//==========================================================================
40
//#####DESCRIPTIONBEGIN####
41
//
42
// Author(s):    gthomas
43
// Contributors: gthomas
44
// Date:         2002-03-05
45
// Purpose:      
46
// Description:  Touchscreen driver for Agilent AAED2000
47
//
48
//####DESCRIPTIONEND####
49
//
50
//==========================================================================
51
 
52
 
53
#include <pkgconf/devs_touch_aaed2000.h>
54
 
55
#include <cyg/kernel/kapi.h>
56
#include <cyg/hal/hal_io.h>
57
#include <cyg/hal/hal_arch.h>
58
#include <cyg/hal/drv_api.h>
59
#include <cyg/hal/hal_intr.h>
60
#include <cyg/hal/aaed2000.h>
61
#include <cyg/infra/cyg_type.h>
62
#include <cyg/infra/cyg_ass.h>
63
#include <cyg/infra/diag.h>
64
 
65
#include <cyg/fileio/fileio.h>  // For select() functionality
66
static cyg_selinfo      ts_select_info;
67
static cyg_bool         ts_select_active;
68
 
69
#include <cyg/io/devtab.h>
70
 
71
/* ADS7846 flags */
72
#define ADS_START               (1 << 7)
73
#define ADS_MEASURE_Y           (0x01 << 4)
74
#define ADS_MEASURE_X           (0x05 << 4)
75
#define ADS_MODE_12_BIT         0
76
#define ADS_PD0                 0
77
 
78
// Misc constants
79
#define TS_INT (1<<0)
80
#define X_THRESHOLD 0x80
81
#define Y_THRESHOLD 0x80
82
 
83
// Functions in this module
84
 
85
static Cyg_ErrNo ts_read(cyg_io_handle_t handle,
86
                         void *buffer,
87
                         cyg_uint32 *len);
88
static cyg_bool  ts_select(cyg_io_handle_t handle,
89
                           cyg_uint32 which,
90
                           cyg_addrword_t info);
91
static Cyg_ErrNo ts_set_config(cyg_io_handle_t handle,
92
                               cyg_uint32 key,
93
                               const void *buffer,
94
                               cyg_uint32 *len);
95
static Cyg_ErrNo ts_get_config(cyg_io_handle_t handle,
96
                               cyg_uint32 key,
97
                               void *buffer,
98
                               cyg_uint32 *len);
99
static bool      ts_init(struct cyg_devtab_entry *tab);
100
static Cyg_ErrNo ts_lookup(struct cyg_devtab_entry **tab,
101
                           struct cyg_devtab_entry *st,
102
                           const char *name);
103
 
104
CHAR_DEVIO_TABLE(aaed2000_ts_handlers,
105
                 NULL,                                   // Unsupported write() function
106
                 ts_read,
107
                 ts_select,
108
                 ts_get_config,
109
                 ts_set_config);
110
 
111
CHAR_DEVTAB_ENTRY(aaed2000_ts_device,
112
                  CYGDAT_DEVS_TOUCH_AAED2000_NAME,
113
                  NULL,                                   // Base device name
114
                  &aaed2000_ts_handlers,
115
                  ts_init,
116
                  ts_lookup,
117
                  NULL);                                  // Private data pointer
118
 
119
struct _event {
120
    short button_state;
121
    short xPos, yPos;
122
    short _unused;
123
};
124
#define MAX_EVENTS CYGNUM_DEVS_TOUCH_AAED2000_EVENT_BUFFER_SIZE
125
static int   num_events;
126
static int   _event_put, _event_get;
127
static struct _event _events[MAX_EVENTS];
128
 
129
static bool _is_open = false;
130
#ifdef DEBUG_RAW_EVENTS
131
static unsigned char _ts_buf[512];
132
static int _ts_buf_ptr = 0;
133
#endif
134
 
135
#define STACK_SIZE CYGNUM_HAL_STACK_SIZE_TYPICAL
136
static char ts_scan_stack[STACK_SIZE];
137
static cyg_thread ts_scan_thread_data;
138
static cyg_handle_t ts_scan_thread_handle;
139
#define SCAN_FREQ 20 // Hz
140
//#define SCAN_FREQ 5 // Hz
141
#define SCAN_DELAY ((1000/SCAN_FREQ)/10)
142
 
143
 
144
typedef struct {
145
    short min;
146
    short max;
147
    short span;
148
} bounds;
149
 
150
static bounds xBounds = {1024, 0, 1024};
151
static bounds yBounds = {1024, 0, 1024};
152
 
153
static Cyg_ErrNo
154
ts_read(cyg_io_handle_t handle,
155
        void *buffer,
156
        cyg_uint32 *len)
157
{
158
    struct _event *ev;
159
    int tot = *len;
160
    unsigned char *bp = (unsigned char *)buffer;
161
 
162
    cyg_scheduler_lock();  // Prevent interaction with DSR code
163
    while (tot >= sizeof(struct _event)) {
164
        if (num_events > 0) {
165
            ev = &_events[_event_get++];
166
            if (_event_get == MAX_EVENTS) {
167
                _event_get = 0;
168
            }
169
            // Self calibrate
170
            if (ev->xPos > xBounds.max) xBounds.max = ev->xPos;
171
            if (ev->xPos < xBounds.min) xBounds.min = ev->xPos;
172
            if (ev->yPos > yBounds.max) yBounds.max = ev->yPos;
173
            if (ev->yPos < yBounds.min) yBounds.min = ev->yPos;
174
            if ((xBounds.span = xBounds.max - xBounds.min) <= 1) {
175
                xBounds.span = 1;
176
            }
177
            if ((yBounds.span = yBounds.max - yBounds.min) <= 1) {
178
                yBounds.span = 1;
179
            }
180
            // Scale values - done here so these potentially lengthy
181
            // operations take place outside of interrupt processing
182
#ifdef DEBUG
183
            diag_printf("Raw[%d,%d], X[%d,%d,%d], Y[%d,%d,%d]",
184
                        ev->xPos, ev->yPos,
185
                        xBounds.max, xBounds.min, xBounds.span,
186
                        yBounds.max, yBounds.min, yBounds.span);
187
#endif
188
            ev->xPos = 640 - (((xBounds.max - ev->xPos) * 640) / xBounds.span);
189
            ev->yPos = 480 - (((yBounds.max - ev->yPos) * 480) / yBounds.span);
190
#ifdef DEBUG
191
            diag_printf(", Cooked[%d,%d]\n",
192
                        ev->xPos, ev->yPos);
193
#endif
194
            memcpy(bp, ev, sizeof(*ev));
195
            bp += sizeof(*ev);
196
            tot -= sizeof(*ev);
197
            num_events--;
198
        } else {
199
            break;  // No more events
200
        }
201
    }
202
    cyg_scheduler_unlock(); // Allow DSRs again
203
    *len -= tot;
204
    return ENOERR;
205
}
206
 
207
static cyg_bool
208
ts_select(cyg_io_handle_t handle,
209
          cyg_uint32 which,
210
          cyg_addrword_t info)
211
{
212
    if (which == CYG_FREAD) {
213
        cyg_scheduler_lock();  // Prevent interaction with DSR code
214
        if (num_events > 0) {
215
            cyg_scheduler_unlock();  // Reallow interaction with DSR code
216
            return true;
217
        }
218
        if (!ts_select_active) {
219
            ts_select_active = true;
220
            cyg_selrecord(info, &ts_select_info);
221
        }
222
        cyg_scheduler_unlock();  // Reallow interaction with DSR code
223
    }
224
    return false;
225
}
226
 
227
static Cyg_ErrNo
228
ts_set_config(cyg_io_handle_t handle,
229
              cyg_uint32 key,
230
              const void *buffer,
231
              cyg_uint32 *len)
232
{
233
    return EINVAL;
234
}
235
 
236
static Cyg_ErrNo
237
ts_get_config(cyg_io_handle_t handle,
238
              cyg_uint32 key,
239
              void *buffer,
240
              cyg_uint32 *len)
241
{
242
    return EINVAL;
243
}
244
 
245
static bool
246
ts_init(struct cyg_devtab_entry *tab)
247
{
248
    cyg_uint32 _dummy;
249
 
250
    // Initialize SSP interface
251
#if 0
252
    while (*(volatile cyg_uint32 *)AAEC_SSP_SR & AAEC_SSP_SR_RNE) {
253
        _dummy = *(volatile cyg_uint32 *)AAEC_SSP_DR;  // Drain FIFO
254
    }
255
#endif
256
    *(volatile cyg_uint32 *)AAEC_SSP_CR0 =
257
        (1 << AAEC_SSP_CR0_SSE) |                    // SSP enable
258
        (37 << AAEC_SSP_CR0_SCR) |                   // Serial clock rate
259
        (AAEC_SSP_CR0_FRF_NAT << AAEC_SSP_CR0_FRF) | // MicroWire
260
        ((12-1) << AAEC_SSP_CR0_SIZE);               // 12 bit words
261
    *(volatile cyg_uint32 *)AAEC_SSP_CR1 =
262
        (1 << AAEC_SSP_CR1_FEN);                     // Enable FIFO
263
    *(volatile cyg_uint32 *)AAEC_SSP_CPSR = 2;       // Clock prescale
264
    *(volatile cyg_uint32 *)AAEC_PFDDR &= ~(1<<0);  // TS uses port F bit 0
265
    cyg_drv_interrupt_acknowledge(CYGNUM_HAL_INTERRUPT_TS);
266
    cyg_selinit(&ts_select_info);
267
    return true;
268
}
269
 
270
static cyg_uint32
271
read_ts(int axis)
272
{
273
    cyg_uint32 res;
274
 
275
    *(volatile cyg_uint32 *)AAEC_SSP_DR = (axis | ADS_START | ADS_MODE_12_BIT | ADS_PD0);
276
    *(volatile cyg_uint32 *)AAEC_SSP_DR = (axis | ADS_START | ADS_MODE_12_BIT);
277
    // Wait for data
278
    while ((*(volatile cyg_uint32 *)AAEC_SSP_SR & AAEC_SSP_SR_RNE) == 0);
279
    res = *(volatile cyg_uint32 *)AAEC_SSP_DR;  // ignore first datum
280
    // Wait for data
281
    while ((*(volatile cyg_uint32 *)AAEC_SSP_SR & AAEC_SSP_SR_RNE) == 0);
282
    res = *(volatile cyg_uint32 *)AAEC_SSP_DR;
283
    return res;
284
}
285
 
286
static void
287
ts_scan(cyg_addrword_t param)
288
{
289
    short lastX, lastY;
290
    short x, y;
291
    struct _event *ev;
292
    bool pen_down;
293
 
294
    diag_printf("Touch Screen thread started\n");
295
    // Discard the first sample - it's always 0
296
    x = read_ts(ADS_MEASURE_X);
297
    y = read_ts(ADS_MEASURE_Y);
298
    lastX = lastY = -1;
299
    pen_down = false;
300
    while (true) {
301
        cyg_thread_delay(SCAN_DELAY);
302
        if ((*(volatile cyg_uint32 *)AAEC_PFDR & TS_INT) == 0) {
303
            // Pen is down
304
            x = read_ts(ADS_MEASURE_X);
305
            y = read_ts(ADS_MEASURE_Y);
306
//            diag_printf("X = %x, Y = %x\n", x, y);
307
            if ((x < X_THRESHOLD) || (y < Y_THRESHOLD)) {
308
                // Ignore 'bad' samples
309
                continue;
310
            }
311
            lastX = x;  lastY = y;
312
            pen_down = true;
313
        } else {
314
            if (pen_down) {
315
                // Capture first 'up' event
316
                pen_down = false;
317
                x = lastX;
318
                y = lastY;
319
            } else {
320
                continue;  // Nothing new to report
321
            }
322
        }
323
        if (num_events < MAX_EVENTS) {
324
            num_events++;
325
            ev = &_events[_event_put++];
326
            if (_event_put == MAX_EVENTS) {
327
                _event_put = 0;
328
            }
329
            ev->button_state = pen_down ? 0x04 : 0x00;
330
            ev->xPos = x;
331
            ev->yPos = y;
332
            if (ts_select_active) {
333
                ts_select_active = false;
334
                cyg_selwakeup(&ts_select_info);
335
            }
336
        }
337
#ifdef DEBUG_RAW_EVENTS
338
        memcpy(&_ts_buf[_ts_buf_ptr], pkt->data, 8);
339
        _ts_buf_ptr += 8;
340
        if (_ts_buf_ptr == 512) {
341
            diag_printf("TS handler\n");
342
            diag_dump_buf(_ts_buf, 512);
343
            _ts_buf_ptr = 0;
344
        }
345
#endif
346
    }
347
}
348
 
349
static Cyg_ErrNo
350
ts_lookup(struct cyg_devtab_entry **tab,
351
          struct cyg_devtab_entry *st,
352
          const char *name)
353
{
354
    if (!_is_open) {
355
        _is_open = true;
356
        cyg_thread_create(1,                      // Priority
357
                          ts_scan,                // entry
358
                          0,                      // entry parameter
359
                          "Touch Screen scan",    // Name
360
                          &ts_scan_stack[0],      // Stack
361
                          STACK_SIZE,             // Size
362
                          &ts_scan_thread_handle, // Handle
363
                          &ts_scan_thread_data    // Thread data structure
364
        );
365
        cyg_thread_resume(ts_scan_thread_handle);    // Start it
366
    }
367
    return ENOERR;
368
}

powered by: WebSVN 2.1.0

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