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

Subversion Repositories openrisc

[/] [openrisc/] [trunk/] [or1ksim/] [testsuite/] [test-code-or1k/] [kbdtest/] [kbdtest.c] - Blame information for rev 90

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

Line No. Rev Author Line
1 90 jeremybenn
/* kbdtest.c. Test of Or1ksim keyboard
2
 
3
   Copyright (C) 1999-2006 OpenCores
4
   Copyright (C) 2010 Embecosm Limited
5
 
6
   Contributors various OpenCores participants
7
   Contributor Jeremy Bennett <jeremy.bennett@embecosm.com>
8
 
9
   This file is part of OpenRISC 1000 Architectural Simulator.
10
 
11
   This program is free software; you can redistribute it and/or modify it
12
   under the terms of the GNU General Public License as published by the Free
13
   Software Foundation; either version 3 of the License, or (at your option)
14
   any later version.
15
 
16
   This program is distributed in the hope that it will be useful, but WITHOUT
17
   ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
18
   FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
19
   more details.
20
 
21
   You should have received a copy of the GNU General Public License along
22
   with this program.  If not, see <http:  www.gnu.org/licenses/>.  */
23
 
24
/* ----------------------------------------------------------------------------
25
   This code is commented throughout for use with Doxygen.
26
   --------------------------------------------------------------------------*/
27
 
28
#include "support.h"
29
#include "spr-defs.h"
30
#include "board.h"
31
 
32
 
33
/*! Maximum number of characters to read before giving up. */
34
#define MAX_CHARS_TO_READ  25
35
 
36
/*! A character used to indicate shift */
37
#define SHIFT_CHAR 0xfe
38
 
39
/*! An invalid character */
40
#define INVALID_CHAR 0xff
41
 
42
/*! Enumeration of state machine for processing scan codes */
43
enum  scan_state {
44
  STATE_START,
45
  STATE_SHIFT_MADE,
46
  STATE_SHIFT_CHAR_MADE,
47
  STATE_SHIFT_CHAR_BROKEN,
48
  STATE_CHAR_MADE
49
};
50
 
51
/*! Shared volatile flag counting how many chars have been done. */
52
static volatile int num_chars_done;
53
 
54
 
55
/* --------------------------------------------------------------------------*/
56
/*!Report failure
57
 
58
  Terminate execution.
59
 
60
  @param[in] msg  Description of test which failed.                          */
61
/* --------------------------------------------------------------------------*/
62
void fail (char *msg)
63
{
64
  printf ("Test failed: %s\n", msg);
65
  report (0xeeeeeeee);
66
  exit (1);
67
 
68
}       /* fail () */
69
 
70
 
71
/* --------------------------------------------------------------------------*/
72
/*!Utility to read a 32 bit memory mapped register
73
 
74
   @param[in] addr  The address to read from
75
 
76
   @return  The result of the read                                           */
77
/* --------------------------------------------------------------------------*/
78
static unsigned long
79
getreg (unsigned long addr)
80
{
81
  return *((volatile unsigned char *)addr);
82
 
83
}       /* getreg () */
84
 
85
 
86
/* --------------------------------------------------------------------------*/
87
/*!Keyboard interrupt handler
88
 
89
   Receives codes in the keyboard base register. Reports the first specified
90
   number of them.
91
 
92
   @todo We only deal with shift keys here. Control, Alt and other funnies are
93
         left for the future. We also don't do extended sequences.
94
 
95
   If there is a zero in the register that is interpreted as meaning "No data
96
   more available" and the interrupt routine completes.
97
 
98
   Map the codes back to their characters. Fail on any bad chars.            */
99
/* --------------------------------------------------------------------------*/
100
static void
101
interrupt_handler ()
102
{
103
  /* String mapping 256 make codes to chars. 0xff means "invalid", 0xfe means
104
     "shift key". */
105
  static const unsigned char *make_codes = (unsigned char *)
106
    "\xff\xff" "1234567890-=\xff\t"
107
    "qwertyuiop[]\n\xff" "as"
108
    "dfghjkl;'`\xfe\\zxcv"
109
    "bnm,./\xfe\xff\xff \xff\xff\xff\xff\xff\xff"
110
    "\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff"
111
    "\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff"
112
    "\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff"
113
    "\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff"
114
    "\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff"
115
    "\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff"
116
    "\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff"
117
    "\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff"
118
    "\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff"
119
    "\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff"
120
    "\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff"
121
    "\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff";
122
 
123
  /* String mapping 256 make codes to chars in a shift context. 0xff means
124
     "invalid".  */
125
  static const unsigned char *make_shift_codes = (unsigned char *)
126
    "\xff\xff!@#$%^&*()_+\xff\t"
127
    "QWERTYUIOP{}\n\xff" "AS"
128
    "DFGHJKL:\"~\xff|ZXCV"
129
    "BNM<>?\xff\xff\xff \xff\xff\xff\xff\xff\xff"
130
    "\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff"
131
    "\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff"
132
    "\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff"
133
    "\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff"
134
    "\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff"
135
    "\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff"
136
    "\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff"
137
    "\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff"
138
    "\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff"
139
    "\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff"
140
    "\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff"
141
    "\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff";
142
 
143
  /* The break codes expected to correspond to a make code. 00 indicates an
144
     invalid code (should never be requested) */
145
  static const unsigned char *break_codes = (unsigned char *)
146
    "\x00\x81\x82\x83\x84\x85\x86\x87\x88\x89\x8a\x8b\x8c\x8d\x00\x8f"
147
    "\x90\x91\x92\x93\x94\x95\x96\x97\x98\x99\x9a\x9b\x9c\x00\x9e\x9f"
148
    "\xa0\xa1\xa2\xa3\xa4\xa5\xa6\xa7\xa8\xa9\xaa\xab\xac\xad\xae\xaf"
149
    "\xb0\xb1\xb2\xb3\xb4\xb5\xb6\x00\x00\xb9\x00\x00\x00\x00\x00\x00"
150
    "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
151
    "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
152
    "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
153
    "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
154
    "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
155
    "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
156
    "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
157
    "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
158
    "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
159
    "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
160
    "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
161
    "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00";
162
 
163
  /* State machine */
164
  static enum scan_state  state = STATE_START;
165
 
166
  /* Stuff to remember between states */
167
  static char shift_scan_made;
168
  static char char_scan_made;
169
 
170
  /* Get all the chars currently available */
171
  while (1)
172
    {
173
      unsigned char  x = getreg (KBD_BASE_ADD); /* Scan code */
174
      unsigned char  c;
175
 
176
      /* Give up if nothing more in the buffer */
177
      if (0 == x)
178
        {
179
          mtspr(SPR_PICSR, 0);           /* Mark interrupt complete */
180
          return;
181
        }
182
 
183
      /* Handle the scan code */
184
      switch (state)
185
        {
186
        case STATE_START:
187
 
188
          c = make_codes[(int) x];
189
 
190
          if (SHIFT_CHAR == c)
191
            {
192
              /* We had a shift key pressed */
193
              state           = STATE_SHIFT_MADE;
194
              shift_scan_made = x;
195
            }
196
          else
197
            {
198
              /* We had another key pressed. If it's valid record it,
199
                 otherwise blow up. */
200
              state = STATE_CHAR_MADE;
201
 
202
              if (INVALID_CHAR == c)
203
                {
204
                  fail ("Unrecognized make scan code");
205
                }
206
              else
207
                {
208
                  printf ("%c", c);
209
                  char_scan_made = x;
210
                }
211
            }
212
 
213
          break;
214
 
215
        case STATE_SHIFT_MADE:
216
 
217
          c     = make_shift_codes[(int) x];
218
          state = STATE_SHIFT_CHAR_MADE;
219
 
220
          /* We had a key pressed after SHIFT. If it's valid, record it,
221
             otherwise blow up. */
222
          if (INVALID_CHAR == c)
223
            {
224
              fail ("Unrecognized make scan code");
225
            }
226
          else
227
            {
228
              printf ("%c", c);
229
              char_scan_made = x;
230
            }
231
 
232
          break;
233
 
234
        case STATE_SHIFT_CHAR_MADE:
235
 
236
          /* Check the break matches the char scan made */
237
          if (x == break_codes[(int) char_scan_made])
238
            {
239
              state = STATE_SHIFT_CHAR_BROKEN;
240
            }
241
          else
242
            {
243
              fail ("Unrecognized break scan code");
244
            }
245
 
246
          break;
247
 
248
        case STATE_SHIFT_CHAR_BROKEN:
249
 
250
          /* Check the break matches the shift scan made */
251
          if (x == break_codes[(int) shift_scan_made])
252
            {
253
              state = STATE_START;
254
              num_chars_done++;
255
            }
256
          else
257
            {
258
              fail ("Unrecognized break scan code");
259
            }
260
 
261
          break;
262
 
263
        case STATE_CHAR_MADE:
264
 
265
          /* Check the break matches the char scan made */
266
          if (x == break_codes[(int) char_scan_made])
267
            {
268
              state = STATE_START;
269
              num_chars_done++;
270
            }
271
          else
272
            {
273
              fail ("Unrecognized break scan code");
274
            }
275
 
276
          break;
277
 
278
        default:
279
          fail ("*** ABORT ***: Unknown scan state");
280
        }
281
    }
282
}       /* interrupt_handler () */
283
 
284
 
285
/* --------------------------------------------------------------------------*/
286
/*!Simple keyboard test main program
287
 
288
   This appears to use the original XT scan code set, while the keyboard
289
   handler in Or1ksim generates codes appropriate to a US keyboard layout.
290
 
291
   Set up the interrupt handler and wait until the shared variable shows it
292
   has done enough chars
293
 
294
   @return  The return code from the program (always zero).                  */
295
/* --------------------------------------------------------------------------*/
296
int
297
main ()
298
{
299
  printf ("Reading from keyboard.\n");
300
 
301
  /* Use our low priority interrupt handler. Clear the shared completed flag. */
302
  excpt_int      = (unsigned long)interrupt_handler;
303
 
304
  /* Enable interrupts */
305
  printf ("Enabling interrupts.\n");
306
 
307
  mtspr (SPR_SR, mfspr(SPR_SR) | SPR_SR_IEE);
308
  mtspr (SPR_PICMR, mfspr(SPR_PICMR) | (0x00000001L << KBD_IRQ));
309
 
310
  /* Wait until the interrupt handler is finished */
311
  while (num_chars_done < MAX_CHARS_TO_READ)
312
    {
313
    }
314
 
315
  /* Usual end report */
316
  report (0xdeaddead);
317
  return 0;
318
 
319
}       /* main () */

powered by: WebSVN 2.1.0

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