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 93

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 93 jeremybenn
/*!Print an escaped character
73
   Non-printable characters use their name:
74
   '\n' - ENTER
75
   ' '  - SPACE
76
   '\t' - TAB
77
 
78
   Any char > 127 (0x7f) is an error.
79
 
80
   Any other char less than 0x20 appears as ^<char>.                         */
81
/* --------------------------------------------------------------------------*/
82
static void
83
print_escaped_char (unsigned char  c)
84
{
85
  switch (c)
86
    {
87
    case '\n': printf ("Received: ENTER.\n"); return;
88
    case ' ':  printf ("Received: SPACE.\n"); return;
89
    case '\t': printf ("Received: TAB.\n");   return;
90
 
91
    default:
92
      if (c > 0x7f)
93
        {
94
          printf ("\nWarning: received erroneous character 0x%02x.\n",
95
                  (unsigned int) c);
96
        }
97
      else if (c < 0x20)
98
        {
99
          printf ("Received '^%c'.\n", '@' + c);
100
        }
101
      else
102
        {
103
          printf ("Received '%c'.\n", c);
104
        }
105
    }
106
}       /* print_escaped_char () */
107
 
108
 
109
/* --------------------------------------------------------------------------*/
110 90 jeremybenn
/*!Utility to read a 32 bit memory mapped register
111
 
112
   @param[in] addr  The address to read from
113
 
114
   @return  The result of the read                                           */
115
/* --------------------------------------------------------------------------*/
116
static unsigned long
117
getreg (unsigned long addr)
118
{
119
  return *((volatile unsigned char *)addr);
120
 
121
}       /* getreg () */
122
 
123
 
124
/* --------------------------------------------------------------------------*/
125
/*!Keyboard interrupt handler
126
 
127
   Receives codes in the keyboard base register. Reports the first specified
128
   number of them.
129
 
130
   @todo We only deal with shift keys here. Control, Alt and other funnies are
131
         left for the future. We also don't do extended sequences.
132
 
133
   If there is a zero in the register that is interpreted as meaning "No data
134
   more available" and the interrupt routine completes.
135
 
136
   Map the codes back to their characters. Fail on any bad chars.            */
137
/* --------------------------------------------------------------------------*/
138
static void
139
interrupt_handler ()
140
{
141
  /* String mapping 256 make codes to chars. 0xff means "invalid", 0xfe means
142
     "shift key". */
143
  static const unsigned char *make_codes = (unsigned char *)
144
    "\xff\xff" "1234567890-=\xff\t"
145
    "qwertyuiop[]\n\xff" "as"
146
    "dfghjkl;'`\xfe\\zxcv"
147
    "bnm,./\xfe\xff\xff \xff\xff\xff\xff\xff\xff"
148
    "\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff"
149
    "\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff"
150
    "\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff"
151
    "\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff"
152
    "\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff"
153
    "\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff"
154
    "\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff"
155
    "\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff"
156
    "\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff"
157
    "\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff"
158
    "\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff"
159
    "\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff";
160
 
161
  /* String mapping 256 make codes to chars in a shift context. 0xff means
162
     "invalid".  */
163
  static const unsigned char *make_shift_codes = (unsigned char *)
164
    "\xff\xff!@#$%^&*()_+\xff\t"
165
    "QWERTYUIOP{}\n\xff" "AS"
166
    "DFGHJKL:\"~\xff|ZXCV"
167
    "BNM<>?\xff\xff\xff \xff\xff\xff\xff\xff\xff"
168
    "\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff"
169
    "\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff"
170
    "\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff"
171
    "\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff"
172
    "\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff"
173
    "\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff"
174
    "\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff"
175
    "\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff"
176
    "\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff"
177
    "\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff"
178
    "\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff"
179
    "\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff";
180
 
181
  /* The break codes expected to correspond to a make code. 00 indicates an
182
     invalid code (should never be requested) */
183
  static const unsigned char *break_codes = (unsigned char *)
184
    "\x00\x81\x82\x83\x84\x85\x86\x87\x88\x89\x8a\x8b\x8c\x8d\x00\x8f"
185
    "\x90\x91\x92\x93\x94\x95\x96\x97\x98\x99\x9a\x9b\x9c\x00\x9e\x9f"
186
    "\xa0\xa1\xa2\xa3\xa4\xa5\xa6\xa7\xa8\xa9\xaa\xab\xac\xad\xae\xaf"
187
    "\xb0\xb1\xb2\xb3\xb4\xb5\xb6\x00\x00\xb9\x00\x00\x00\x00\x00\x00"
188
    "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
189
    "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
190
    "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
191
    "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
192
    "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
193
    "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
194
    "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
195
    "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
196
    "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
197
    "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
198
    "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
199
    "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00";
200
 
201
  /* State machine */
202
  static enum scan_state  state = STATE_START;
203
 
204
  /* Stuff to remember between states */
205
  static char shift_scan_made;
206
  static char char_scan_made;
207
 
208
  /* Get all the chars currently available */
209
  while (1)
210
    {
211
      unsigned char  x = getreg (KBD_BASE_ADD); /* Scan code */
212
      unsigned char  c;
213
 
214
      /* Give up if nothing more in the buffer */
215
      if (0 == x)
216
        {
217
          mtspr(SPR_PICSR, 0);           /* Mark interrupt complete */
218
          return;
219
        }
220
 
221
      /* Handle the scan code */
222
      switch (state)
223
        {
224
        case STATE_START:
225
 
226
          c = make_codes[(int) x];
227
 
228
          if (SHIFT_CHAR == c)
229
            {
230
              /* We had a shift key pressed */
231
              state           = STATE_SHIFT_MADE;
232
              shift_scan_made = x;
233
            }
234
          else
235
            {
236
              /* We had another key pressed. If it's valid record it,
237
                 otherwise blow up. */
238
              state = STATE_CHAR_MADE;
239
 
240
              if (INVALID_CHAR == c)
241
                {
242
                  fail ("Unrecognized make scan code");
243
                }
244
              else
245
                {
246 93 jeremybenn
                  print_escaped_char (c);
247 90 jeremybenn
                  char_scan_made = x;
248
                }
249
            }
250
 
251
          break;
252
 
253
        case STATE_SHIFT_MADE:
254
 
255
          c     = make_shift_codes[(int) x];
256
          state = STATE_SHIFT_CHAR_MADE;
257
 
258
          /* We had a key pressed after SHIFT. If it's valid, record it,
259
             otherwise blow up. */
260
          if (INVALID_CHAR == c)
261
            {
262
              fail ("Unrecognized make scan code");
263
            }
264
          else
265
            {
266 93 jeremybenn
              print_escaped_char (c);
267 90 jeremybenn
              char_scan_made = x;
268
            }
269
 
270
          break;
271
 
272
        case STATE_SHIFT_CHAR_MADE:
273
 
274
          /* Check the break matches the char scan made */
275
          if (x == break_codes[(int) char_scan_made])
276
            {
277
              state = STATE_SHIFT_CHAR_BROKEN;
278
            }
279
          else
280
            {
281
              fail ("Unrecognized break scan code");
282
            }
283
 
284
          break;
285
 
286
        case STATE_SHIFT_CHAR_BROKEN:
287
 
288
          /* Check the break matches the shift scan made */
289
          if (x == break_codes[(int) shift_scan_made])
290
            {
291
              state = STATE_START;
292
              num_chars_done++;
293
            }
294
          else
295
            {
296
              fail ("Unrecognized break scan code");
297
            }
298
 
299
          break;
300
 
301
        case STATE_CHAR_MADE:
302
 
303
          /* Check the break matches the char scan made */
304
          if (x == break_codes[(int) char_scan_made])
305
            {
306
              state = STATE_START;
307
              num_chars_done++;
308
            }
309
          else
310
            {
311
              fail ("Unrecognized break scan code");
312
            }
313
 
314
          break;
315
 
316
        default:
317
          fail ("*** ABORT ***: Unknown scan state");
318
        }
319
    }
320
}       /* interrupt_handler () */
321
 
322
 
323
/* --------------------------------------------------------------------------*/
324
/*!Simple keyboard test main program
325
 
326
   This appears to use the original XT scan code set, while the keyboard
327
   handler in Or1ksim generates codes appropriate to a US keyboard layout.
328
 
329
   Set up the interrupt handler and wait until the shared variable shows it
330
   has done enough chars
331
 
332
   @return  The return code from the program (always zero).                  */
333
/* --------------------------------------------------------------------------*/
334
int
335
main ()
336
{
337
  printf ("Reading from keyboard.\n");
338
 
339
  /* Use our low priority interrupt handler. Clear the shared completed flag. */
340
  excpt_int      = (unsigned long)interrupt_handler;
341
 
342
  /* Enable interrupts */
343
  printf ("Enabling interrupts.\n");
344
 
345
  mtspr (SPR_SR, mfspr(SPR_SR) | SPR_SR_IEE);
346
  mtspr (SPR_PICMR, mfspr(SPR_PICMR) | (0x00000001L << KBD_IRQ));
347
 
348 93 jeremybenn
  /* Wait until the interrupt handler is finished. */
349 90 jeremybenn
  while (num_chars_done < MAX_CHARS_TO_READ)
350
    {
351
    }
352
 
353
  /* Usual end report */
354
  report (0xdeaddead);
355
  return 0;
356
 
357
}       /* main () */

powered by: WebSVN 2.1.0

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