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

Subversion Repositories openrisc

[/] [openrisc/] [trunk/] [rtos/] [ecos-3.0/] [packages/] [hal/] [arm/] [edb7xxx/] [current/] [misc/] [kbd_support.c] - Blame information for rev 856

Go to most recent revision | Details | Compare with Previous | View Log

Line No. Rev Author Line
1 786 skrzyp
//==========================================================================
2
//
3
//        kbd_support.c
4
//
5
//        Cirrus Logic EDB7xxx eval board ASCII keyboard support functions
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:          1999-05-15
45
// Description:   Functions used to support ASCII keyboard
46
//####DESCRIPTIONEND####
47
 
48
static char kbd_server_stack[STACK_SIZE];
49
static cyg_thread kbd_server_thread_data;
50
static cyg_handle_t kbd_server_thread_handle;
51
 
52
static cyg_interrupt kbd_interrupt;
53
static cyg_handle_t  kbd_interrupt_handle;
54
 
55
static cyg_mbox      kbd_events_mbox;
56
static cyg_handle_t  kbd_events_mbox_handle;
57
static cyg_sem_t     kbd_sem;
58
 
59
static cyg_uint8 col_state[8];
60
static cyg_uint8 ext_state[8];
61
 
62
static void
63
kbd_delay(void)
64
{
65
    volatile int i;
66
    for (i = 0;  i < 250;  i++) ;
67
}
68
 
69
static void
70
kbd_scan(void)
71
{
72
    int i;
73
    cyg_uint8 port_data, ext_data;
74
    // Turn off drive (de-select) all columns
75
    *(volatile cyg_uint32 *)SYSCON1 = (*(volatile cyg_uint32 *)SYSCON1 & ~SYSCON1_KBD_CTL) |
76
        SYSCON1_KBD_LOW;
77
    for (i = 0;  i < 8;  i++) {
78
        // Select column 'i'
79
        *(volatile cyg_uint32 *)SYSCON1 = (*(volatile cyg_uint32 *)SYSCON1 & ~SYSCON1_KBD_CTL) |
80
            SYSCON1_KBD_COL(i);
81
        // Small pause to let the wires charge up :-)
82
        kbd_delay();
83
        // Grab the data
84
        col_state[i] = port_data = *(volatile cyg_uint8 *)PADR;
85
        ext_state[i] = ext_data = *(volatile cyg_uint8 *)KBD_PORT;
86
        // De-Select column 'i'
87
        *(volatile cyg_uint32 *)SYSCON1 = (*(volatile cyg_uint32 *)SYSCON1 & ~SYSCON1_KBD_CTL) |
88
            SYSCON1_KBD_TRISTATE;
89
        // Allow line to go slack
90
        kbd_delay();
91
    }
92
    // Turn on drive (select) all columns - necessary to see interrupts
93
    *(volatile cyg_uint32 *)SYSCON1 = (*(volatile cyg_uint32 *)SYSCON1 & ~SYSCON1_KBD_CTL) |
94
        SYSCON1_KBD_HIGH;
95
}
96
 
97
static cyg_uint8     kbd_state[128];      // Known state of each key
98
static cyg_uint8     kbd_new_state[128];  // Current state of each key
99
 
100
// Row #1
101
#define KBD_Escape     0x00
102
#define KBD_F1         0x01
103
#define KBD_F2         0x02
104
#define KBD_F3         0x03
105
#define KBD_F4         0x04
106
#define KBD_F5         0x05
107
#define KBD_F6         0x06
108
#define KBD_F7         0x07
109
#define KBD_F8         0x08
110
#define KBD_F9         0x09
111
#define KBD_F10        0x0A
112
#define KBD_NumLock    0x0B
113
#define KBD_SysReq     0x0C
114
#define KBD_ScrlLock   0x0D
115
#define KBD_Break      0x0E
116
// Row #2
117
#define KBD_1          0x10
118
#define KBD_2          0x11
119
#define KBD_3          0x12
120
#define KBD_4          0x13
121
#define KBD_5          0x14
122
#define KBD_6          0x15
123
#define KBD_7          0x16
124
#define KBD_8          0x17
125
#define KBD_9          0x18
126
#define KBD_0          0x19
127
#define KBD_Hyphen     0x1A
128
#define KBD_Equals     0x1B
129
#define KBD_BackSpace  0x1C
130
#define KBD_Home       0x1D
131
// Row #3
132
#define KBD_Tab        0x20
133
#define KBD_Q          0x21
134
#define KBD_W          0x22
135
#define KBD_E          0x23
136
#define KBD_R          0x24
137
#define KBD_T          0x25
138
#define KBD_Y          0x26
139
#define KBD_U          0x27
140
#define KBD_I          0x28
141
#define KBD_O          0x29
142
#define KBD_P          0x2A
143
#define KBD_LeftBrkt   0x2B
144
#define KBD_RightBrkt  0x2C
145
#define KBD_BackSlash  0x2D
146
#define KBD_PageUp     0x2E
147
// Row #4
148
#define KBD_CapsLock   0x30
149
#define KBD_A          0x31
150
#define KBD_S          0x32
151
#define KBD_D          0x33
152
#define KBD_F          0x34
153
#define KBD_G          0x35
154
#define KBD_H          0x36
155
#define KBD_J          0x37
156
#define KBD_K          0x38
157
#define KBD_L          0x39
158
#define KBD_SemiColon  0x3A
159
#define KBD_Quote      0x3B
160
#define KBD_Enter      0x3C
161
#define KBD_PageDown   0x3D
162
// Row #5
163
#define KBD_LeftShift  0x40
164
#define KBD_Z          0x41
165
#define KBD_X          0x42
166
#define KBD_C          0x43
167
#define KBD_V          0x44
168
#define KBD_B          0x45
169
#define KBD_N          0x46
170
#define KBD_M          0x47
171
#define KBD_Comma      0x48
172
#define KBD_Period     0x49
173
#define KBD_Slash      0x4A
174
#define KBD_RightShift 0x4B
175
#define KBD_UpArrow    0x4C
176
#define KBD_End        0x4D
177
// Row #6
178
#define KBD_Ctrl       0x50
179
#define KBD_Function   0x51
180
#define KBD_LeftAlt    0x52
181
#define KBD_Accent     0x53
182
#define KBD_Space      0x54
183
#define KBD_RightAlt   0x55
184
#define KBD_Ins        0x56
185
#define KBD_Del        0x57
186
#define KBD_LeftArrow  0x58
187
#define KBD_DownArrow  0x59
188
#define KBD_RightArrow 0x5A
189
 
190
#define KBD_Press      0x80  // Event has this bit when the key is pressed
191
#define KBD_Empty      0xFF
192
 
193
// Map column, bit -> keycode
194
static cyg_uint32    kbd_map[8][16] = {
195
    // Column #0
196
    {KBD_Escape,    KBD_1,          KBD_Tab,        KBD_CapsLock,
197
     KBD_BackSlash, KBD_Space,      KBD_LeftArrow,  KBD_UpArrow,
198
     KBD_DownArrow, KBD_RightArrow, KBD_LeftShift,  KBD_Ctrl,
199
     KBD_Function,  KBD_LeftAlt,    KBD_RightAlt,   KBD_RightShift },
200
    // Column #1
201
    {KBD_F5,        KBD_6,          KBD_T,          KBD_G,
202
     KBD_B,         KBD_Slash,      KBD_SemiColon,  KBD_P,
203
     KBD_Hyphen,    KBD_F10,        KBD_Empty,      KBD_Empty,
204
     KBD_Empty,     KBD_Empty,      KBD_Empty,      KBD_Empty     },
205
    // Column #2
206
    {KBD_F4,        KBD_5,          KBD_R,          KBD_F,
207
     KBD_V,         KBD_Del,        KBD_Quote,      KBD_LeftBrkt,
208
     KBD_Equals,    KBD_NumLock,    KBD_Empty,      KBD_Empty,
209
     KBD_Empty,     KBD_Empty,      KBD_Empty,      KBD_Empty },
210
    // Column #3
211
    {KBD_F3,        KBD_4,          KBD_E,          KBD_D,
212
     KBD_C,         KBD_Ins,        KBD_Empty,      KBD_RightBrkt,
213
     KBD_BackSpace, KBD_SysReq,     KBD_Empty,      KBD_Empty,
214
     KBD_Empty,     KBD_Empty,      KBD_Empty,      KBD_Empty },
215
    // Column #4
216
    {KBD_F2,        KBD_3,          KBD_W,          KBD_S,
217
     KBD_X,         KBD_Empty,      KBD_Enter,      KBD_Empty,
218
     KBD_Empty,     KBD_ScrlLock,   KBD_Empty,      KBD_Empty,
219
     KBD_Empty,     KBD_Empty,      KBD_Empty,      KBD_Empty },
220
    // Column #5
221
    {KBD_F1,        KBD_2,          KBD_Q,          KBD_A,
222
     KBD_Z,         KBD_End,        KBD_PageDown,   KBD_PageUp,
223
     KBD_Home,      KBD_Break,      KBD_Empty,      KBD_Empty,
224
     KBD_Empty,     KBD_Empty,      KBD_Empty,      KBD_Empty },
225
    // Column #6
226
    {KBD_F6,        KBD_7,          KBD_Y,          KBD_H,
227
     KBD_N,         KBD_Period,     KBD_L,          KBD_O,
228
     KBD_0,         KBD_F9,         KBD_Empty,      KBD_Empty,
229
     KBD_Empty,     KBD_Empty,      KBD_Empty,      KBD_Empty },
230
    // Column #7
231
    {KBD_F7,        KBD_8,          KBD_U,          KBD_J,
232
     KBD_M,         KBD_Comma,      KBD_K,          KBD_I,
233
     KBD_9,         KBD_F8,         KBD_Empty,      KBD_Empty,
234
     KBD_Empty,     KBD_Empty,      KBD_Empty,      KBD_Empty },
235
};
236
 
237
static cyg_uint8 kbd_chars[96] = {
238
    /* 0x00 - 0x0F */
239
    0x1B, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
240
    /* 0x10 - 0x1F */
241
     '1',  '2',  '3',  '4',  '5',  '6',  '7',  '8',  '9',  '0',  '-',  '=', 0x08, 0x00, 0x00, 0x00,
242
    /* 0x20 - 0x2F */
243
    '\t',  'q',  'w',  'e',  'r',  't',  'y',  'u',  'i',  'o',  'p',  '[',  ']', '\\', 0x00, 0x00,
244
    /* 0x30 - 0x3F */
245
    0x00,  'a',  's',  'd',  'f',  'g',  'h',  'j',  'k',  'l',  ';', '\'', 0x0D, 0x00, 0x00, 0x00,
246
    /* 0x40 - 0x4F */
247
    0x00,  'z',  'x',  'c',  'v',  'b',  'n',  'm',  ',',  '.',  '/', 0x00, 0x00, 0x00, 0x00, 0x00,
248
    /* 0x50 - 0x5F */
249
    0x00, 0x00, 0x00, 0x00,  ' ', 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
250
};
251
 
252
static cyg_uint8 kbd_shifted_chars[96] = {
253
    /* 0x00 - 0x0F */
254
    '\b', 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
255
    /* 0x10 - 0x1F */
256
     '!',  '@',  '#',  '$',  '%',  '^',  '&',  '*',  '(',  ')',  '_',  '+', 0x08, 0x00, 0x00, 0x00,
257
    /* 0x20 - 0x2F */
258
    '\t',  'Q',  'W',  'E',  'R',  'T',  'Y',  'U',  'I',  'O',  'P',  '{',  '}',  '|', 0x00, 0x00,
259
    /* 0x30 - 0x3F */
260
    0x00,  'A',  'S',  'D',  'F',  'G',  'H',  'J',  'K',  'L',  ':',  '"', 0x0D, 0x00, 0x00, 0x00,
261
    /* 0x40 - 0x4F */
262
    0x00,  'Z',  'X',  'C',  'V',  'B',  'N',  'M',  '<',  '>',  '?', 0x00, 0x00, 0x00, 0x00, 0x00,
263
    /* 0x50 - 0x5F */
264
    0x00, 0x00, 0x00, 0x00,  ' ', 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
265
};
266
 
267
// This ISR is called when the keyboard interrupt occurs
268
static int
269
keyboard_isr(cyg_vector_t vector, cyg_addrword_t data, HAL_SavedRegisters *regs)
270
{
271
    cyg_drv_interrupt_mask(CYGNUM_HAL_INTERRUPT_KBDINT);
272
    return (CYG_ISR_HANDLED|CYG_ISR_CALL_DSR);  // Run the DSR
273
}
274
 
275
// This DSR handles the keyboard [logical] processing
276
static void
277
keyboard_dsr(cyg_vector_t vector, cyg_ucount32 count, cyg_addrword_t data)
278
{
279
    // Tell the keyboard processing thread to give it a shot
280
    cyg_semaphore_post(&kbd_sem);
281
}
282
 
283
static void
284
kbd_server(cyg_addrword_t p)
285
{
286
    int col, bit, key, event, timeout;
287
    diag_printf("KBD server here\n");
288
    while (TRUE) {
289
        cyg_semaphore_wait(&kbd_sem);
290
        // As long as keys are pressed, scan and update
291
        timeout = 0;
292
        while (TRUE) {
293
            // Wait for 20ms - time to debounce keyboard
294
            cyg_thread_delay(2);
295
            // Scan keyboard
296
            kbd_scan();
297
            // Reset state
298
            for (key = 0;  key < sizeof(kbd_new_state);  key++) {
299
                kbd_new_state[key] = 0;
300
            }
301
            // Check state of all keys and send events for those that change
302
            for (col = 0;  col < 8;  col++) {
303
                for (bit = 0;  bit < 8;  bit++) {
304
                    if (col_state[col] & (1<<bit)) {
305
                        key = kbd_map[col][bit];
306
                        if (key != KBD_Empty) {
307
                            kbd_new_state[key] = 1;
308
                        }
309
                    }
310
                    if (ext_state[col] & (1<<bit)) {
311
                        key = kbd_map[col][bit+8];
312
                        if (key != KBD_Empty) {
313
                            kbd_new_state[key] = 1;
314
                        }
315
                    }
316
                }
317
            }
318
            // Compare new and old (known) states, generate events for changes
319
            // Send events for modifier keys first.
320
            for (key = 0;  key < sizeof(kbd_new_state);  key++) {
321
                if (kbd_state[key] != kbd_new_state[key]) {
322
                    event = 0xFF;
323
                    switch (key) {
324
                    case KBD_LeftShift:
325
                    case KBD_RightShift:
326
                    case KBD_Ctrl:
327
                    case KBD_LeftAlt:
328
                    case KBD_RightAlt:
329
                    case KBD_Function:
330
                    case KBD_CapsLock:
331
                        if (kbd_state[key]) {
332
                            // Key going up
333
                            event = key;
334
                        } else {
335
                            // Key going down
336
                            event = key + KBD_Press;
337
                        }
338
                        kbd_state[key] = kbd_new_state[key];
339
                    }
340
                    if (event != 0xFF) {
341
                        if (!cyg_mbox_tryput(kbd_events_mbox_handle, (void *)event)) {
342
                            diag_printf("KBD event lost: %x\n", event);
343
                        }
344
                    }
345
                }
346
            }
347
            // First key up events
348
            for (key = 0;  key < sizeof(kbd_new_state);  key++) {
349
                if (kbd_state[key] != kbd_new_state[key]) {
350
                    if (kbd_state[key]) {
351
                        // Key going up
352
                        event = key;
353
                    } else {
354
                        // Key going down
355
                        event = key + KBD_Press;
356
                    }
357
                    if (!cyg_mbox_tryput(kbd_events_mbox_handle, (void *)event)) {
358
                        diag_printf("KBD event lost: %x\n", event);
359
                    }
360
                }
361
                kbd_state[key] = kbd_new_state[key];
362
            }
363
            // Clear interrupt (true when keys are pressed)
364
            cyg_drv_interrupt_acknowledge(CYGNUM_HAL_INTERRUPT_KBDINT);
365
#if 0
366
            if (*(volatile cyg_uint32 *)INTSR2 & INTSR2_KBDINT) {
367
                timeout = 0;
368
            } else if (++timeout == 5) {
369
                // No keys for 100ms
370
                break;
371
            }
372
#endif
373
        }
374
        // Allow interrupts to happen again
375
        cyg_drv_interrupt_acknowledge(CYGNUM_HAL_INTERRUPT_KBDINT);
376
        cyg_drv_interrupt_unmask(CYGNUM_HAL_INTERRUPT_KBDINT);
377
    }
378
}
379
 
380
void
381
kbd_init(void)
382
{
383
    // Initialize environment, setup interrupt handler
384
    cyg_drv_interrupt_create(CYGNUM_HAL_INTERRUPT_KBDINT,
385
                             99,                     // Priority - what goes here?
386
                             0,                      //  Data item passed to interrupt handler
387
                             (cyg_ISR_t *)keyboard_isr,
388
                             (cyg_DSR_t *)keyboard_dsr,
389
                             &kbd_interrupt_handle,
390
                             &kbd_interrupt);
391
    cyg_drv_interrupt_attach(kbd_interrupt_handle);
392
    cyg_drv_interrupt_acknowledge(CYGNUM_HAL_INTERRUPT_KBDINT);
393
    cyg_drv_interrupt_unmask(CYGNUM_HAL_INTERRUPT_KBDINT);
394
    // Set up the mbox for keyboard data
395
    cyg_mbox_create(&kbd_events_mbox_handle, &kbd_events_mbox);
396
    // This semaphore is set when there is a keypress
397
    cyg_semaphore_init(&kbd_sem, 0);
398
    // Create a thread whose job it is to de-bounce the keyboard and
399
    // actually process the input, turning it into a series of events
400
    cyg_thread_create(10,                           // Priority - just a number
401
                      kbd_server,                   // entry
402
                      0,                            // initial parameter
403
                      "KBD_server",                 // Name
404
                      &kbd_server_stack[0],         // Stack
405
                      STACK_SIZE,                   // Size
406
                      &kbd_server_thread_handle,    // Handle
407
                      &kbd_server_thread_data       // Thread data structure
408
            );
409
    cyg_thread_resume(kbd_server_thread_handle);  // Start it
410
}
411
 
412
#define MOD_Shift    0x40
413
#define MOD_Ctrl     0x20
414
#define MOD_CapsLock 0x10
415
static cyg_uint32    kbd_modifiers;
416
 
417
cyg_uint8
418
kbd_getc(void)
419
{
420
    cyg_uint8 ch;
421
    cyg_uint32 kbd_event;
422
    while (TRUE) {
423
        kbd_event = (cyg_uint32)cyg_mbox_get(kbd_events_mbox_handle);
424
        switch (kbd_event & 0x7F) {
425
        case KBD_LeftShift:
426
        case KBD_RightShift:
427
            if (kbd_event & KBD_Press) {
428
                kbd_modifiers |= MOD_Shift;
429
            } else {
430
                kbd_modifiers &= ~MOD_Shift;
431
            }
432
            break;
433
        case KBD_Ctrl:
434
            if (kbd_event & KBD_Press) {
435
                kbd_modifiers |= MOD_Ctrl;
436
            } else {
437
                kbd_modifiers &= ~MOD_Ctrl;
438
            }
439
            break;
440
        case KBD_CapsLock:
441
            if (kbd_event & KBD_Press) {
442
                kbd_modifiers ^= MOD_CapsLock;
443
            }
444
            break;
445
        case KBD_LeftAlt:
446
        case KBD_RightAlt:
447
        case KBD_Function:
448
        default:
449
        }
450
        // Return character [if one has arrived]
451
        if (kbd_event & KBD_Press) {
452
            if (kbd_modifiers & (MOD_Shift|MOD_CapsLock)) {
453
                ch = kbd_shifted_chars[kbd_event & 0x7F];
454
            } else {
455
                ch = kbd_chars[kbd_event & 0x7F];
456
            }
457
            if (kbd_modifiers & MOD_Ctrl) {
458
                ch &= 0x1F;
459
            }
460
            if (ch) {
461
                return (ch);
462
            }
463
        }
464
    }
465
}

powered by: WebSVN 2.1.0

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