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

Subversion Repositories or1k

[/] [or1k/] [trunk/] [ecos-2.0/] [packages/] [hal/] [arm/] [sa11x0/] [ipaq/] [v2_0/] [src/] [atmel_support.c] - Blame information for rev 1765

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 1254 phoenix
//==========================================================================
2
//
3
//        atmel_support.c
4
//
5
//        SA1110/iPAQ - Atmel micro-controller support routines
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:          2001-02-27
46
// Description:   Simple Atmel support
47
//####DESCRIPTIONEND####
48
 
49
#include <pkgconf/system.h>
50
#include <pkgconf/hal.h>
51
 
52
#ifdef CYGPKG_REDBOOT
53
#include <redboot.h>
54
#endif
55
 
56
#include <cyg/infra/diag.h>
57
#include <cyg/hal/hal_if.h>       // Virtual vector functions
58
#include <cyg/hal/hal_io.h>       // IO macros
59
#include <cyg/hal/hal_arch.h>     // Register state info
60
#include <cyg/hal/hal_intr.h>     // HAL interrupt macros
61
 
62
#include <cyg/hal/hal_sa11x0.h>   // Board definitions
63
#include <cyg/hal/ipaq.h>
64
#include <cyg/hal/hal_cache.h>
65
 
66
#ifdef CYGPKG_IO
67
// Need to export interrupt driven interfaces
68
#include <cyg/hal/drv_api.h>
69
#define ATMEL_INT CYGNUM_HAL_INTERRUPT_UART1
70
static cyg_interrupt atmel_interrupt;
71
static cyg_handle_t  atmel_interrupt_handle;
72
#endif
73
 
74
#include <cyg/hal/atmel_support.h>        // Interfaces, commands
75
 
76
externC void *memcpy(void *, const void *, size_t);
77
 
78
struct sa11x0_serial {
79
  volatile cyg_uint32 utcr0;
80
  volatile cyg_uint32 utcr1;
81
  volatile cyg_uint32 utcr2;
82
  volatile cyg_uint32 utcr3;
83
  volatile cyg_uint32 pad0010;
84
  volatile cyg_uint32 utdr;
85
  volatile cyg_uint32 pad0018;
86
  volatile cyg_uint32 utsr0;
87
  volatile cyg_uint32 utsr1;
88
};
89
 
90
#define ATMEL_PUTQ_SIZE 32
91
unsigned char atmel_putq[ATMEL_PUTQ_SIZE];
92
int atmel_putq_put, atmel_putq_get;
93
 
94
bool atmel_use_ints;
95
 
96
void
97
atmel_putc(unsigned char c)
98
{
99
    atmel_putq[atmel_putq_put++] = c;
100
    if (atmel_putq_put == ATMEL_PUTQ_SIZE) {
101
        atmel_putq_put = 0;
102
    }
103
}
104
 
105
static atmel_handler *handlers[NUM_ATMEL_CMDS];
106
 
107
static void
108
null_handler(atmel_pkt *pkt)
109
{
110
    diag_printf("Atmel - packet ignored: %x\n", pkt->data[0]);
111
    diag_dump_buf(pkt->data, 16);
112
}
113
 
114
//
115
// Register a handler for a particular packet type
116
//
117
void
118
atmel_register(int cmd, atmel_handler *fun)
119
{
120
    handlers[cmd] = fun;
121
}
122
 
123
//
124
// This routine is called to process an input character from the
125
// Atmel micro-controller.  Since command packets are multiple
126
// characters, this routine has to keep state for the packet.  Once
127
// a complete packet is received, the appropriate handler function
128
// will be called (if the checksum matches)
129
//
130
static void
131
atmel_in(unsigned char ch)
132
{
133
    static atmel_pkt pkt;
134
    static unsigned char cksum;
135
    static bool sof = false;
136
 
137
    if (!sof) {
138
        // Wait for start of packet (SOF)
139
        if (ch != SOF) {
140
            return;  // Just ignore out of order characters
141
        }
142
        sof = true;
143
        pkt.size = 0;
144
        return;
145
    }
146
    if (pkt.size == 0) {
147
        // First byte of packet - command+length;
148
        pkt.len = (ch & 0x0F) + 1;
149
        cksum = 0;
150
    }
151
    pkt.data[pkt.size++] = ch;
152
    if (pkt.size > pkt.len) {
153
        // End of packet data
154
        if (cksum == ch) {
155
            (*handlers[pkt.data[0] >> 4])(&pkt);
156
        }
157
        sof = false;
158
    } else {
159
        cksum += ch;
160
    }
161
}
162
 
163
//
164
// This [internal] routine is used to handle data from the Atmel micro-controller
165
//
166
static void
167
atmel_poll(void)
168
{
169
    volatile struct sa11x0_serial *base = (volatile struct sa11x0_serial *)SA11X0_UART1_BASE;
170
    unsigned char ch;
171
 
172
    while ((base->utsr1 & SA11X0_UART_RX_FIFO_NOT_EMPTY) != 0) {
173
        ch = (char)base->utdr;
174
        atmel_in(ch);
175
    }
176
}
177
 
178
//
179
// This [internal] routine is used to send data to the Atmel micro-controller
180
//
181
static void
182
atmel_flush(void)
183
{
184
    volatile struct sa11x0_serial *base = (volatile struct sa11x0_serial *)SA11X0_UART1_BASE;
185
 
186
#ifdef CYGPKG_IO
187
    cyg_drv_isr_lock();
188
#endif
189
    while (atmel_putq_get != atmel_putq_put) {
190
        if ((base->utsr1 & SA11X0_UART_TX_FIFO_NOT_FULL) == 0) {
191
            // Wait forever if in non-interrupt mode
192
            if (atmel_use_ints) {
193
                break;
194
            }
195
        } else {
196
            base->utdr = atmel_putq[atmel_putq_get++];
197
            if (atmel_putq_get == ATMEL_PUTQ_SIZE) {
198
                atmel_putq_get = 0;
199
            }
200
        }
201
    }
202
#ifdef CYGPKG_IO
203
    cyg_drv_isr_unlock();
204
#endif
205
}
206
 
207
#ifdef CYGPKG_IO
208
 
209
// Low level interrupt handler (ISR)
210
static cyg_uint32
211
atmel_ISR(cyg_vector_t vector, cyg_addrword_t data)
212
{
213
    cyg_drv_interrupt_mask(vector);
214
    cyg_drv_interrupt_acknowledge(vector);
215
    return CYG_ISR_CALL_DSR;  // Cause DSR to be run
216
}
217
 
218
// High level interrupt handler (DSR)
219
static void
220
atmel_DSR(cyg_vector_t vector, cyg_ucount32 count, cyg_addrword_t data)
221
{
222
    volatile struct sa11x0_serial *base = (volatile struct sa11x0_serial *)SA11X0_UART1_BASE;
223
    unsigned int stat0 = base->utsr0;
224
 
225
    if (stat0 & SA11X0_UART_TX_SERVICE_REQUEST) {
226
        atmel_flush();
227
    }
228
    if (stat0 & (SA11X0_UART_RX_SERVICE_REQUEST|SA11X0_UART_RX_IDLE)) {
229
        atmel_poll();
230
        base->utsr0 = SA11X0_UART_RX_IDLE;  // Need to clear this manually
231
    }
232
    cyg_drv_interrupt_unmask(vector);
233
}
234
 
235
//
236
// Connect/disconnect interrupt processing
237
//
238
void
239
atmel_interrupt_mode(bool enable)
240
{
241
    volatile struct sa11x0_serial *base = (volatile struct sa11x0_serial *)SA11X0_UART1_BASE;
242
 
243
    if (enable) {
244
        // Enable the receiver (with interrupts) and the transmitter.
245
        base->utcr3 = SA11X0_UART_RX_ENABLED |
246
                      SA11X0_UART_TX_ENABLED |
247
                      SA11X0_UART_RX_FIFO_INT_ENABLED;
248
        cyg_drv_interrupt_unmask(ATMEL_INT);
249
    } else {
250
        cyg_drv_interrupt_mask(ATMEL_INT);
251
    }
252
    atmel_use_ints = enable;
253
}
254
#endif
255
 
256
//
257
// Set up the Atmel micro-controller environment
258
//
259
void
260
atmel_init(void)
261
{
262
    volatile struct sa11x0_serial *base = (volatile struct sa11x0_serial *)SA11X0_UART1_BASE;
263
    cyg_uint32 brd;
264
    int i;
265
    static bool _init = false;
266
 
267
    if (_init) return;
268
 
269
    // Disable Receiver and Transmitter (clears FIFOs)
270
    base->utcr3 = SA11X0_UART_RX_DISABLED | SA11X0_UART_TX_DISABLED;
271
 
272
    // Clear sticky (writable) status bits.
273
    base->utsr0 = SA11X0_UART_RX_IDLE | SA11X0_UART_RX_BEGIN_OF_BREAK |
274
                  SA11X0_UART_RX_END_OF_BREAK;
275
 
276
    // Set UART to 8N1 (8 data bits, no partity, 1 stop bit)
277
    base->utcr0 = SA11X0_UART_PARITY_DISABLED | SA11X0_UART_STOP_BITS_1 |
278
                  SA11X0_UART_DATA_BITS_8;
279
 
280
    // Set the desired baud rate.
281
    brd = SA11X0_UART_BAUD_RATE_DIVISOR(115200);
282
    base->utcr1 = (brd >> 8) & SA11X0_UART_H_BAUD_RATE_DIVISOR_MASK;
283
    base->utcr2 = brd & SA11X0_UART_L_BAUD_RATE_DIVISOR_MASK;
284
 
285
    // Enable the receiver and the transmitter.
286
    base->utcr3 = SA11X0_UART_RX_ENABLED | SA11X0_UART_TX_ENABLED;
287
 
288
    // Set up character queues
289
    atmel_putq_put = atmel_putq_get = 0;
290
    atmel_use_ints = false;
291
 
292
    // Set up handlers
293
    for (i = 0;  i < NUM_ATMEL_CMDS;  i++) {
294
        atmel_register(i, null_handler);
295
    }
296
 
297
#ifdef CYGPKG_IO
298
    cyg_drv_interrupt_create(ATMEL_INT,
299
                             99,                     // Priority - unused
300
                             (cyg_addrword_t)base,   // Data item passed to interrupt handler
301
                             atmel_ISR,
302
                             atmel_DSR,
303
                             &atmel_interrupt_handle,
304
                             &atmel_interrupt);
305
    cyg_drv_interrupt_attach(atmel_interrupt_handle);
306
#endif
307
 
308
    _init = true;
309
}
310
 
311
static void
312
atmel_pkt_send(atmel_pkt *pkt)
313
{
314
    int i;
315
 
316
    for (i = 0;  i < pkt->len;  i++) {
317
        atmel_putc(pkt->data[i]);
318
    }
319
    atmel_flush();
320
}
321
 
322
bool
323
atmel_send(int cmd, unsigned char *data, int len)
324
{
325
    atmel_pkt pkt;
326
    unsigned char cksum, *dp;
327
    int i;
328
 
329
    dp = pkt.data;
330
    *dp++ = SOF;
331
    *dp++ = cksum = (cmd << 4) | len;
332
    for (i = 0;  i < len;  i++) {
333
        *dp++ = data[i];
334
        cksum += data[i];
335
    }
336
    *dp = cksum;
337
    pkt.len = len + 3;
338
    atmel_pkt_send(&pkt);
339
    return true;
340
}
341
 
342
#define MAX_TS_EVENTS      32
343
static struct ts_event ts_event_list[MAX_TS_EVENTS];
344
static int num_ts_events = 0;
345
static int ts_event_get, ts_event_put;
346
 
347
static void
348
ts_event_handler(atmel_pkt *pkt)
349
{
350
    unsigned char *buf = pkt->data;
351
    static bool up = true;
352
    static int down_count = 0;
353
    struct ts_event *tse;
354
 
355
    if (num_ts_events == MAX_TS_EVENTS) {
356
        return;
357
    }
358
    if ((buf[0] & 0x0F) == 0) {
359
        // Stylus up
360
        up = true;
361
        down_count = 0;
362
        tse = &ts_event_list[ts_event_put++];
363
        if (ts_event_put == MAX_TS_EVENTS) {
364
            ts_event_put = 0;
365
        }
366
        num_ts_events++;
367
        tse->x = (buf[1] << 8) | buf[2];
368
        tse->y = (buf[3] << 8) | buf[4];
369
        tse->up = up;
370
    } else {
371
        up = false;
372
        if (down_count++ == 0) {
373
            // First 'down' event
374
        } else {
375
        }
376
        {
377
            tse = &ts_event_list[ts_event_put++];
378
            if (ts_event_put == MAX_TS_EVENTS) {
379
                ts_event_put = 0;
380
            }
381
            num_ts_events++;
382
            tse->x = (buf[1] << 8) | buf[2];
383
            tse->y = (buf[3] << 8) | buf[4];
384
            tse->up = up;
385
        }
386
    }
387
}
388
 
389
bool
390
ts_get_event(struct ts_event *tse)
391
{
392
    static bool _init = false;
393
 
394
    if (!_init) {
395
        atmel_register(ATMEL_CMD_TOUCH, ts_event_handler);
396
        atmel_register(ATMEL_CMD_UNKNOWN, ts_event_handler);
397
        _init = true;
398
    }
399
 
400
    if (num_ts_events == 0) {
401
        atmel_poll();
402
    }
403
    if (num_ts_events) {
404
        num_ts_events--;
405
        memcpy(tse, &ts_event_list[ts_event_get++], sizeof(*tse));
406
        if (ts_event_get == MAX_TS_EVENTS) {
407
            ts_event_get = 0;
408
        }
409
        return true;
410
    } else {
411
        return false;
412
    }
413
}
414
 
415
#define MAX_KEY_EVENTS     8
416
static struct key_event key_event_list[MAX_KEY_EVENTS];
417
static int num_key_events = 0;
418
static int key_event_get, key_event_put;
419
 
420
static void
421
kbd_event_handler(atmel_pkt *pkt)
422
{
423
    unsigned char *buf = pkt->data;
424
    struct key_event *ke;
425
 
426
    if (num_key_events == MAX_KEY_EVENTS) {
427
        return;
428
    }
429
//    printf("Keybd = %x\n", buf[1]);
430
    ke = &key_event_list[key_event_put++];
431
    if (key_event_put == MAX_KEY_EVENTS) {
432
        key_event_put = 0;
433
    }
434
    ke->button_info = buf[1];
435
    num_key_events++;
436
}
437
 
438
bool
439
key_get_event(struct key_event *ke)
440
{
441
    static bool _init = false;
442
 
443
    if (!_init) {
444
        atmel_register(ATMEL_CMD_KEYBD, kbd_event_handler);
445
        _init = true;
446
    }
447
 
448
    if (num_key_events == 0) {
449
        atmel_poll();
450
    }
451
    if (num_key_events) {
452
        num_key_events--;
453
        memcpy(ke, &key_event_list[key_event_get++], sizeof(*ke));
454
        if (key_event_get == MAX_KEY_EVENTS) {
455
            key_event_get = 0;
456
        }
457
        return true;
458
    } else {
459
        return false;
460
    }
461
}
462
 
463
#ifdef CYGPKG_REDBOOT
464
 
465
void
466
atmel_check(bool is_idle)
467
{
468
}
469
RedBoot_idle(atmel_check, RedBoot_BEFORE_NETIO);
470
#endif

powered by: WebSVN 2.1.0

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