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

Subversion Repositories openrisc

[/] [openrisc/] [trunk/] [rtos/] [ecos-3.0/] [packages/] [hal/] [arm/] [sa11x0/] [ipaq/] [current/] [src/] [atmel_support.c] - Blame information for rev 786

Details | Compare with Previous | View Log

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

powered by: WebSVN 2.1.0

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