]> git.kernelconcepts.de Git - karo-tx-redboot.git/blob - packages/hal/arm/arm9/aaed2000/v2_0/src/kbd_drvr.c
Initial revision
[karo-tx-redboot.git] / packages / hal / arm / arm9 / aaed2000 / v2_0 / src / kbd_drvr.c
1 //==========================================================================
2 //
3 //        kbd_drvr.c
4 //
5 //        Agilent AAED2000 - keyboard driver
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-11-03
46 // Description:   Keyboard driver
47 //####DESCRIPTIONEND####
48
49 #include <pkgconf/hal.h>
50
51 #include <cyg/infra/diag.h>
52 #include <cyg/hal/hal_io.h>       // IO macros
53 #include <cyg/hal/hal_if.h>       // Virtual vector support
54 #include <cyg/hal/hal_arch.h>     // Register state info
55 #include <cyg/hal/hal_intr.h>     // HAL interrupt macros
56
57 #include <cyg/hal/aaed2000.h>  // Board definitions
58 #include <cyg/hal/hal_cache.h>
59
60 //-----------------------------------------------------------------------------
61 // Keyboard definitions
62
63 // Standard [PC keyboard] scan codes
64
65 #define LSHIFT          0x2a
66 #define RSHIFT          0x36
67 #define CTRL            0x1d
68 #define ALT             0x38
69 #define CAPS            0x3a
70 #define NUMS            0x45
71
72 #define BREAK           0x80
73
74 // Bits for KBFlags
75
76 #define KBNormal        0x0000
77 #define KBShift         0x0001
78 #define KBCtrl          0x0002
79 #define KBAlt           0x0004
80 #define KBIndex         0x0007  // mask for the above
81
82 #define KBExtend        0x0010
83 #define KBAck           0x0020
84 #define KBResend        0x0040
85 #define KBShiftL        (0x0080 | KBShift)
86 #define KBShiftR        (0x0100 | KBShift)
87 #define KBCtrlL         (0x0200 | KBCtrl)
88 #define KBCtrlR         (0x0400 | KBCtrl)
89 #define KBAltL          (0x0800 | KBAlt)
90 #define KBAltR          (0x1000 | KBAlt)
91 #define KBCapsLock      0x2000
92 #define KBNumLock       0x4000
93
94 #define KBArrowUp       0x48
95 #define KBArrowRight    0x4D
96 #define KBArrowLeft     0x4B
97 #define KBArrowDown     0x50
98
99 //-----------------------------------------------------------------------------
100 // Keyboard Variables
101
102 static  int     KBFlags = 0;
103
104 static  CYG_BYTE        KBPending = 0xFF;
105
106 static  CYG_BYTE        KBScanTable[128][4] = {
107 //      Normal          Shift           Control         Alt
108 // 0x00
109     {   0xFF,           0xFF,           0xFF,           0xFF,   },
110     {   0x1b,           0x1b,           0x1b,           0xFF,   },
111     {   '1',            '!',            0xFF,           0xFF,   },
112     {   '2',            '@',            0xFF,           0xFF,   },
113     {   '3',            '#',            0xFF,           0xFF,   },
114     {   '4',            '$',            0xFF,           0xFF,   },
115     {   '5',            '%',            0xFF,           0xFF,   },
116     {   '6',            '^',            0xFF,           0xFF,   },
117     {   '7',            '&',            0xFF,           0xFF,   },
118     {   '8',            '*',            0xFF,           0xFF,   },
119     {   '9',            '(',            0xFF,           0xFF,   },
120     {   '0',            ')',            0xFF,           0xFF,   },
121     {   '-',            '_',            0xFF,           0xFF,   },
122     {   '=',            '+',            0xFF,           0xFF,   },
123     {   '\b',           '\b',           0xFF,           0xFF,   },
124     {   '\t',           '\t',           0xFF,           0xFF,   },
125 // 0x10
126     {   'q',            'Q',            0x11,           0xFF,   },
127     {   'w',            'W',            0x17,           0xFF,   },
128     {   'e',            'E',            0x05,           0xFF,   },
129     {   'r',            'R',            0x12,           0xFF,   },
130     {   't',            'T',            0x14,           0xFF,   },
131     {   'y',            'Y',            0x19,           0xFF,   },
132     {   'u',            'U',            0x15,           0xFF,   },
133     {   'i',            'I',            0x09,           0xFF,   },
134     {   'o',            'O',            0x0F,           0xFF,   },
135     {   'p',            'P',            0x10,           0xFF,   },
136     {   '[',            '{',            0x1b,           0xFF,   },
137     {   ']',            '}',            0x1d,           0xFF,   },
138     {   '\r',           '\r',           '\n',           0xFF,   },
139     {   0xFF,           0xFF,           0xFF,           0xFF,   },
140     {   'a',            'A',            0x01,           0xFF,   },
141     {   's',            'S',            0x13,           0xFF,   },
142 // 0x20
143     {   'd',            'D',            0x04,           0xFF,   },
144     {   'f',            'F',            0x06,           0xFF,   },
145     {   'g',            'G',            0x07,           0xFF,   },
146     {   'h',            'H',            0x08,           0xFF,   },
147     {   'j',            'J',            0x0a,           0xFF,   },
148     {   'k',            'K',            0x0b,           0xFF,   },
149     {   'l',            'L',            0x0c,           0xFF,   },
150     {   ';',            ':',            0xFF,           0xFF,   },
151     {   0x27,           '"',            0xFF,           0xFF,   },
152     {   '`',            '~',            0xFF,           0xFF,   },
153     {   '`',            '~',            0xFF,           0xFF,   },
154     {   '\\',           '|',            0x1C,           0xFF,   },
155     {   'z',            'Z',            0x1A,           0xFF,   },
156     {   'x',            'X',            0x18,           0xFF,   },
157     {   'c',            'C',            0x03,           0xFF,   },
158     {   'v',            'V',            0x16,           0xFF,   },
159 // 0x30
160     {   'b',            'B',            0x02,           0xFF,   },
161     {   'n',            'N',            0x0E,           0xFF,   },
162     {   'm',            'M',            0x0D,           0xFF,   },
163     {   ',',            '<',            0xFF,           0xFF,   },
164     {   '.',            '>',            0xFF,           0xFF,   },
165     {   '/',            '?',            0xFF,           0xFF,   },
166     {   0xFF,           0xFF,           0xFF,           0xFF,   },
167     {   0xFF,           0xFF,           0xFF,           0xFF,   },
168     {   0xFF,           0xFF,           0xFF,           0xFF,   },
169     {   ' ',            ' ',            ' ',            ' ',    },
170     {   0xFF,           0xFF,           0xFF,           0xFF,   },
171     {   0xF1,           0xE1,           0xFF,           0xFF,   },
172     {   0xF2,           0xE2,           0xFF,           0xFF,   },
173     {   0xF3,           0xE3,           0xFF,           0xFF,   },
174     {   0xF4,           0xE4,           0xFF,           0xFF,   },
175     {   0xF5,           0xE5,           0xFF,           0xFF,   },
176 // 0x40
177     {   0xFF,           0xFF,           0xFF,           0xFF,   },
178     {   0xFF,           0xFF,           0xFF,           0xFF,   },
179     {   0xFF,           0xFF,           0xFF,           0xFF,   },
180     {   0xFF,           0xFF,           0xFF,           0xFF,   },
181     {   0xFF,           0xFF,           0xFF,           0xFF,   },
182     {   0xFF,           0xFF,           0xFF,           0xFF,   },
183     {   0xFF,           0xFF,           0xFF,           0xFF,   },
184     {   0xFF,           0xFF,           0xFF,           0xFF,   },
185
186     {   0x15,           0x15,           0x15,           0x15,   },
187     {   0x10,           0x10,           0x10,           0x10,   },
188     {   0xFF,           0xFF,           0xFF,           0xFF,   },
189     {   0xFF,           0xFF,           0xFF,           0xFF,   },
190     {   0xFF,           0xFF,           0xFF,           0xFF,   },
191     {   0xFF,           0xFF,           0xFF,           0xFF,   },
192     {   0xFF,           0xFF,           0xFF,           0xFF,   },
193     {   0xFF,           0xFF,           0xFF,           0xFF,   },
194 // 0x50
195     {   0x04,           0x04,           0x04,           0x04,   },
196     {   0x0e,           0x0e,           0x0e,           0x0e,   },
197     {   0xFF,           0xFF,           0xFF,           0xFF,   },
198     {   0xFF,           0xFF,           0xFF,           0xFF,   },
199     {   0xFF,           0xFF,           0xFF,           0xFF,   },
200     {   0xFF,           0xFF,           0xFF,           0xFF,   },
201     {   0xFF,           0xFF,           0xFF,           0xFF,   },
202     {   0xFF,           0xFF,           0xFF,           0xFF,   },
203     {   0xFF,           0xFF,           0xFF,           0xFF,   },
204     {   0xFF,           0xFF,           0xFF,           0xFF,   },
205     {   0xFF,           0xFF,           0xFF,           0xFF,   },
206     {   0xFF,           0xFF,           0xFF,           0xFF,   },
207     {   0xFF,           0xFF,           0xFF,           0xFF,   },
208     {   0xFF,           0xFF,           0xFF,           0xFF,   },
209     {   0xFF,           0xFF,           0xFF,           0xFF,   },
210     {   0xFF,           0xFF,           0xFF,           0xFF,   },
211 // 0x60
212     {   0xFF,           0xFF,           0xFF,           0xFF,   },
213     {   0xFF,           0xFF,           0xFF,           0xFF,   },
214     {   0xFF,           0xFF,           0xFF,           0xFF,   },
215     {   0xFF,           0xFF,           0xFF,           0xFF,   },
216     {   0xFF,           0xFF,           0xFF,           0xFF,   },
217     {   0xFF,           0xFF,           0xFF,           0xFF,   },
218     {   0xFF,           0xFF,           0xFF,           0xFF,   },
219     {   0xFF,           0xFF,           0xFF,           0xFF,   },
220     {   0xFF,           0xFF,           0xFF,           0xFF,   },
221     {   0xFF,           0xFF,           0xFF,           0xFF,   },
222     {   0xFF,           0xFF,           0xFF,           0xFF,   },
223     {   0xFF,           0xFF,           0xFF,           0xFF,   },
224     {   0xFF,           0xFF,           0xFF,           0xFF,   },
225     {   0xFF,           0xFF,           0xFF,           0xFF,   },
226     {   0xFF,           0xFF,           0xFF,           0xFF,   },
227     {   0xFF,           0xFF,           0xFF,           0xFF,   },
228 // 0x70
229     {   0xFF,           0xFF,           0xFF,           0xFF,   },
230     {   0xFF,           0xFF,           0xFF,           0xFF,   },
231     {   0xFF,           0xFF,           0xFF,           0xFF,   },
232     {   0xFF,           0xFF,           0xFF,           0xFF,   },
233     {   0xFF,           0xFF,           0xFF,           0xFF,   },
234     {   0xFF,           0xFF,           0xFF,           0xFF,   },
235     {   0xFF,           0xFF,           0xFF,           0xFF,   },
236     {   0xFF,           0xFF,           0xFF,           0xFF,   },
237     {   0xFF,           0xFF,           0xFF,           0xFF,   },
238     {   0xFF,           0xFF,           0xFF,           0xFF,   },
239     {   0xFF,           0xFF,           0xFF,           0xFF,   },
240     {   0xFF,           0xFF,           0xFF,           0xFF,   },
241     {   0xFF,           0xFF,           0xFF,           0xFF,   },
242     {   0xFF,           0xFF,           0xFF,           0xFF,   },
243     {   0xFF,           0xFF,           0xFF,           0xFF,   },
244     {   0xFF,           0xFF,           0xFF,           0xFF,   },
245 };
246
247 static int KBIndexTab[8] = { 0, 1, 2, 2, 3, 3, 3, 3 };
248
249 //-----------------------------------------------------------------------------
250
251 #define AAED2000_KBD_COLS 8
252 #define AAED2000_KBD_ROWS 12
253
254 static unsigned int KB_rowState[AAED2000_KBD_COLS];  // Last known state Row x Col
255
256 // Map AAED2000 row/col to [PC standard] scancodes
257 static const int scancode[AAED2000_KBD_ROWS][AAED2000_KBD_COLS] =
258 {
259     {0x0A/*9*/, 0x25/*k*/, 0x17/*i*/, 0x09/*8*/, 0x24/*j*/, 0x15/*y*/, 0x08/*7*/, 0x00/*?*/},
260     {0x0B/*0*/, 0x32/*m*/, 0x19/*p*/, 0x26/*l*/, 0x23/*h*/, 0x16/*u*/, 0x07/*8*/, 0x00/*?*/},
261     {0x0C/*-*/, 0x18/*o*/, 0x1A/*{*/, 0x27/*:*/, 0x30/*b*/, 0x31/*n*/, 0x22/*g*/, 0x33/*<*/},
262     {0x0D/*+*/, 0x34/*>*/, 0x1B/*}*/, 0x28/*'*/, 0x48/*?*/, 0x14/*t*/, 0x00/*?*/, 0x00/*?*/},
263     {0x0E/*?*/, 0x35/*?*/, 0x2B/*|*/, 0x1C/*?*/, 0x4B/*?*/, 0x00/*?*/, 0x06/*5*/, 0x50/*?*/},
264     {0x00/*?*/, 0x00/*?*/, 0x00/*?*/, 0x00/*?*/, 0x00/*?*/, 0x00/*?*/, 0x00/*?*/, 0x00/*?*/},
265     {0x39/* */, 0x21/*f*/, 0x00/*?*/, 0x00/*?*/, 0x2E/*c*/, 0x13/*r*/, 0x05/*4*/, 0x2F/*v*/},
266     {0x4D/*?*/, 0x00/*?*/, 0x00/*?*/, 0x00/*?*/, 0x20/*d*/, 0x12/*e*/, 0x04/*3*/, 0x38/*?*/},
267     {0x00/*?*/, 0x00/*?*/, 0x00/*?*/, 0x00/*?*/, 0x1F/*s*/, 0x11/*w*/, 0x03/*2*/, 0x2D/*x*/},
268     {0x53/*?*/, 0x00/*?*/, 0x00/*?*/, 0x00/*?*/, 0x1E/*a*/, 0x10/*q*/, 0x02/*1*/, 0x2C/*z*/},
269     {0x00/*?*/, 0x2A/*?*/, 0x36/*?*/, 0x00/*?*/, 0x00/*?*/, 0x00/*?*/, 0x00/*?*/, 0x00/*?*/},
270     {0x00/*?*/, 0x00/*?*/, 0x00/*?*/, 0x00/*?*/, 0x3A/*?*/, 0x0F/*?*/, 0x29/*~*/, 0x1D/*?*/}
271 };
272
273 static bool
274 KeyboardScan(CYG_BYTE *code)
275 {
276     int row, col, i, down, up;
277     unsigned int state, prev_state;
278     int stable;
279
280     for (col = 0;  col < AAED2000_KBD_COLS;  col++) {
281         HAL_WRITE_UINT8(AAEC_KSCAN, col+8);  // Assert column #n
282         
283         for (i = 0, stable = 0, prev_state = 0;
284              (i < 1000) && (stable < 120);  i++) {
285             HAL_READ_UINT32(AAED_EXT_GPIO, state);
286             if (state != prev_state) {
287                 prev_state = state;
288                 stable = 0;
289             } else {
290                 stable++;
291             }
292         }
293         state &= (1<<AAED2000_KBD_ROWS)-1;   // Mask off unused bits
294         if (state != KB_rowState[col]) {
295             // State changed
296             down = state & ~KB_rowState[col];  // Bits that went 0->1
297             up = ~state & KB_rowState[col];    // Bits that went 1->0
298             for (row = 0;  row < AAED2000_KBD_ROWS;  row++) {
299                 if ((up|down) & (1<<row)) {
300                     *code = scancode[row][col] | (up ? BREAK : 0);
301                     // Only remember the bit we reported
302                     KB_rowState[col] &= ~(1<<row);
303                     state &= (1<<row);
304                     KB_rowState[col] |= state;
305                     return true;
306                 }
307             }
308         }
309     }
310     HAL_WRITE_UINT8(AAEC_KSCAN, 0x07);  // Turn off drivers
311     return false;
312 }
313
314 //-----------------------------------------------------------------------------
315
316 static CYG_BYTE 
317 KeyboardAscii(CYG_BYTE scancode)
318 {
319     CYG_BYTE ascii = 0xFF;
320
321     // Start by handling all shift/ctl keys:
322
323     switch( scancode ) {
324     case 0xe0:
325         KBFlags |= KBExtend;
326         return 0xFF;
327
328     case 0xfa:
329         KBFlags |= KBAck;
330         return 0xFF;
331
332     case 0xfe:
333         KBFlags |= KBResend;
334         return 0xFF;
335
336     case LSHIFT:
337         KBFlags |= KBShiftL;
338         return 0xFF;
339
340     case LSHIFT | BREAK:
341         KBFlags &= ~KBShiftL;
342         return 0xFF;
343
344     case RSHIFT:
345         KBFlags |= KBShiftR;
346         return 0xFF;
347
348     case RSHIFT | BREAK:
349         KBFlags &= ~KBShiftR;
350         return 0xFF;
351
352     case CTRL:
353         if( KBFlags & KBExtend )
354         {
355             KBFlags |= KBCtrlR;
356             KBFlags &= ~KBExtend;
357         }
358         else    KBFlags |= KBCtrlL;
359         return 0xFF;
360
361     case CTRL | BREAK:
362         if( KBFlags & KBExtend )
363         {
364             KBFlags &= ~KBCtrlR;
365             KBFlags &= ~KBExtend;
366         }
367         else    KBFlags &= ~KBCtrlL;
368         return 0xFF;
369
370
371     case ALT:
372         if( KBFlags & KBExtend )
373         {
374             KBFlags |= KBAltR;
375             KBFlags &= ~KBExtend;
376         }
377         else    KBFlags |= KBAltL;
378         return 0xFF;
379
380     case ALT | BREAK:
381         if( KBFlags & KBExtend )
382         {
383             KBFlags &= ~KBAltR;
384             KBFlags &= ~KBExtend;
385         }
386         else    KBFlags &= ~KBAltL;
387         return 0xFF;
388
389     case CAPS:
390         KBFlags ^= KBCapsLock;
391     case CAPS | BREAK:
392         return 0xFF;
393
394     case NUMS:
395         KBFlags ^= KBNumLock;
396     case NUMS | BREAK:
397         return 0xFF;
398
399     case KBArrowUp:
400     case KBArrowDown:
401 #if 0 // Not really needed on this display
402         screen_pan = 0;
403         lcd_refresh();
404 #endif
405         break;
406     case KBArrowLeft:
407 #if 0 // Not really needed on this display
408         screen_pan -= SCREEN_PAN;
409         if (screen_pan < 0) screen_pan = 0;
410         lcd_refresh();
411 #endif
412         break;
413     case KBArrowRight:
414 #if 0 // Not really needed on this display
415         screen_pan += SCREEN_PAN;
416         if (screen_pan > (SCREEN_WIDTH-SCREEN_PAN)) screen_pan = SCREEN_WIDTH-SCREEN_PAN;
417         lcd_refresh();
418 #endif
419         break;
420
421     }
422
423     // Clear Extend flag if set
424     KBFlags &= ~KBExtend;
425
426     // Ignore all other BREAK codes
427     if( scancode & 0x80 ) return 0xFF;
428
429     // Here the scancode is for something we can turn
430     // into an ASCII value
431
432     ascii = KBScanTable[scancode & 0x7F][KBIndexTab[KBFlags & KBIndex]];
433
434     return ascii;
435 } /* KeyboardAscii */
436
437 //-----------------------------------------------------------------------------
438
439 int 
440 aaed2000_KeyboardTest(void)
441 {
442     // If there is a pending character, return True
443     if( KBPending != 0xFF ) return true;
444
445     // If there is something waiting at the port, get it
446     for(;;) {
447         CYG_BYTE code, c;
448
449         if (!KeyboardScan(&code)) {
450             // No new activity
451             break;
452         }
453
454         // Translate to ASCII
455         c = KeyboardAscii(code);
456                 
457         // if it is a real ASCII char, save it and
458         // return True.
459         if( c != 0xFF ) {
460             KBPending = c;
461             return true;
462         }
463     }
464
465     // Otherwise return False
466     return false;
467         
468 } /* KeyboardTest */
469
470 int 
471 aaed2000_KeyboardGetc(void)
472 {
473     unsigned char ch = KBPending;
474     KBPending = 0xFF;
475     return ch;
476 }
477
478 cyg_bool
479 aaed2000_KeyboardInit(void)
480 {
481     int i;
482
483     for (i = 0; i < AAED2000_KBD_COLS;  i++) {
484         KB_rowState[i] = 0;
485     }
486     KBFlags = 0;
487
488     return true;
489 } /* KeyboardInit */