📄 kbd_drvr.c
字号:
//==========================================================================
//
// kbd_drvr.c
//
// Agilent AAED2000 - keyboard driver
//
//==========================================================================
//####ECOSGPLCOPYRIGHTBEGIN####
// -------------------------------------------
// This file is part of eCos, the Embedded Configurable Operating System.
// Copyright (C) 1998, 1999, 2000, 2001, 2002 Red Hat, Inc.
//
// eCos is free software; you can redistribute it and/or modify it under
// the terms of the GNU General Public License as published by the Free
// Software Foundation; either version 2 or (at your option) any later version.
//
// eCos is distributed in the hope that it will be useful, but WITHOUT ANY
// WARRANTY; without even the implied warranty of MERCHANTABILITY or
// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
// for more details.
//
// You should have received a copy of the GNU General Public License along
// with eCos; if not, write to the Free Software Foundation, Inc.,
// 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
//
// As a special exception, if other files instantiate templates or use macros
// or inline functions from this file, or you compile this file and link it
// with other works to produce a work based on this file, this file does not
// by itself cause the resulting work to be covered by the GNU General Public
// License. However the source code for this file must still be made available
// in accordance with section (3) of the GNU General Public License.
//
// This exception does not invalidate any other reasons why a work based on
// this file might be covered by the GNU General Public License.
//
// Alternative licenses for eCos may be arranged by contacting Red Hat, Inc.
// at http://sources.redhat.com/ecos/ecos-license/
// -------------------------------------------
//####ECOSGPLCOPYRIGHTEND####
//==========================================================================
//#####DESCRIPTIONBEGIN####
//
// Author(s): gthomas
// Contributors: gthomas
// Date: 2001-11-03
// Description: Keyboard driver
//####DESCRIPTIONEND####
#include <pkgconf/hal.h>
#include <cyg/infra/diag.h>
#include <cyg/hal/hal_io.h> // IO macros
#include <cyg/hal/hal_if.h> // Virtual vector support
#include <cyg/hal/hal_arch.h> // Register state info
#include <cyg/hal/hal_intr.h> // HAL interrupt macros
#include <cyg/hal/aaed2000.h> // Board definitions
#include <cyg/hal/hal_cache.h>
//-----------------------------------------------------------------------------
// Keyboard definitions
// Standard [PC keyboard] scan codes
#define LSHIFT 0x2a
#define RSHIFT 0x36
#define CTRL 0x1d
#define ALT 0x38
#define CAPS 0x3a
#define NUMS 0x45
#define BREAK 0x80
// Bits for KBFlags
#define KBNormal 0x0000
#define KBShift 0x0001
#define KBCtrl 0x0002
#define KBAlt 0x0004
#define KBIndex 0x0007 // mask for the above
#define KBExtend 0x0010
#define KBAck 0x0020
#define KBResend 0x0040
#define KBShiftL (0x0080 | KBShift)
#define KBShiftR (0x0100 | KBShift)
#define KBCtrlL (0x0200 | KBCtrl)
#define KBCtrlR (0x0400 | KBCtrl)
#define KBAltL (0x0800 | KBAlt)
#define KBAltR (0x1000 | KBAlt)
#define KBCapsLock 0x2000
#define KBNumLock 0x4000
#define KBArrowUp 0x48
#define KBArrowRight 0x4D
#define KBArrowLeft 0x4B
#define KBArrowDown 0x50
//-----------------------------------------------------------------------------
// Keyboard Variables
static int KBFlags = 0;
static CYG_BYTE KBPending = 0xFF;
static CYG_BYTE KBScanTable[128][4] = {
// Normal Shift Control Alt
// 0x00
{ 0xFF, 0xFF, 0xFF, 0xFF, },
{ 0x1b, 0x1b, 0x1b, 0xFF, },
{ '1', '!', 0xFF, 0xFF, },
{ '2', '@', 0xFF, 0xFF, },
{ '3', '#', 0xFF, 0xFF, },
{ '4', '$', 0xFF, 0xFF, },
{ '5', '%', 0xFF, 0xFF, },
{ '6', '^', 0xFF, 0xFF, },
{ '7', '&', 0xFF, 0xFF, },
{ '8', '*', 0xFF, 0xFF, },
{ '9', '(', 0xFF, 0xFF, },
{ '0', ')', 0xFF, 0xFF, },
{ '-', '_', 0xFF, 0xFF, },
{ '=', '+', 0xFF, 0xFF, },
{ '\b', '\b', 0xFF, 0xFF, },
{ '\t', '\t', 0xFF, 0xFF, },
// 0x10
{ 'q', 'Q', 0x11, 0xFF, },
{ 'w', 'W', 0x17, 0xFF, },
{ 'e', 'E', 0x05, 0xFF, },
{ 'r', 'R', 0x12, 0xFF, },
{ 't', 'T', 0x14, 0xFF, },
{ 'y', 'Y', 0x19, 0xFF, },
{ 'u', 'U', 0x15, 0xFF, },
{ 'i', 'I', 0x09, 0xFF, },
{ 'o', 'O', 0x0F, 0xFF, },
{ 'p', 'P', 0x10, 0xFF, },
{ '[', '{', 0x1b, 0xFF, },
{ ']', '}', 0x1d, 0xFF, },
{ '\r', '\r', '\n', 0xFF, },
{ 0xFF, 0xFF, 0xFF, 0xFF, },
{ 'a', 'A', 0x01, 0xFF, },
{ 's', 'S', 0x13, 0xFF, },
// 0x20
{ 'd', 'D', 0x04, 0xFF, },
{ 'f', 'F', 0x06, 0xFF, },
{ 'g', 'G', 0x07, 0xFF, },
{ 'h', 'H', 0x08, 0xFF, },
{ 'j', 'J', 0x0a, 0xFF, },
{ 'k', 'K', 0x0b, 0xFF, },
{ 'l', 'L', 0x0c, 0xFF, },
{ ';', ':', 0xFF, 0xFF, },
{ 0x27, '"', 0xFF, 0xFF, },
{ '`', '~', 0xFF, 0xFF, },
{ '`', '~', 0xFF, 0xFF, },
{ '\\', '|', 0x1C, 0xFF, },
{ 'z', 'Z', 0x1A, 0xFF, },
{ 'x', 'X', 0x18, 0xFF, },
{ 'c', 'C', 0x03, 0xFF, },
{ 'v', 'V', 0x16, 0xFF, },
// 0x30
{ 'b', 'B', 0x02, 0xFF, },
{ 'n', 'N', 0x0E, 0xFF, },
{ 'm', 'M', 0x0D, 0xFF, },
{ ',', '<', 0xFF, 0xFF, },
{ '.', '>', 0xFF, 0xFF, },
{ '/', '?', 0xFF, 0xFF, },
{ 0xFF, 0xFF, 0xFF, 0xFF, },
{ 0xFF, 0xFF, 0xFF, 0xFF, },
{ 0xFF, 0xFF, 0xFF, 0xFF, },
{ ' ', ' ', ' ', ' ', },
{ 0xFF, 0xFF, 0xFF, 0xFF, },
{ 0xF1, 0xE1, 0xFF, 0xFF, },
{ 0xF2, 0xE2, 0xFF, 0xFF, },
{ 0xF3, 0xE3, 0xFF, 0xFF, },
{ 0xF4, 0xE4, 0xFF, 0xFF, },
{ 0xF5, 0xE5, 0xFF, 0xFF, },
// 0x40
{ 0xFF, 0xFF, 0xFF, 0xFF, },
{ 0xFF, 0xFF, 0xFF, 0xFF, },
{ 0xFF, 0xFF, 0xFF, 0xFF, },
{ 0xFF, 0xFF, 0xFF, 0xFF, },
{ 0xFF, 0xFF, 0xFF, 0xFF, },
{ 0xFF, 0xFF, 0xFF, 0xFF, },
{ 0xFF, 0xFF, 0xFF, 0xFF, },
{ 0xFF, 0xFF, 0xFF, 0xFF, },
{ 0x15, 0x15, 0x15, 0x15, },
{ 0x10, 0x10, 0x10, 0x10, },
{ 0xFF, 0xFF, 0xFF, 0xFF, },
{ 0xFF, 0xFF, 0xFF, 0xFF, },
{ 0xFF, 0xFF, 0xFF, 0xFF, },
{ 0xFF, 0xFF, 0xFF, 0xFF, },
{ 0xFF, 0xFF, 0xFF, 0xFF, },
{ 0xFF, 0xFF, 0xFF, 0xFF, },
// 0x50
{ 0x04, 0x04, 0x04, 0x04, },
{ 0x0e, 0x0e, 0x0e, 0x0e, },
{ 0xFF, 0xFF, 0xFF, 0xFF, },
{ 0xFF, 0xFF, 0xFF, 0xFF, },
{ 0xFF, 0xFF, 0xFF, 0xFF, },
{ 0xFF, 0xFF, 0xFF, 0xFF, },
{ 0xFF, 0xFF, 0xFF, 0xFF, },
{ 0xFF, 0xFF, 0xFF, 0xFF, },
{ 0xFF, 0xFF, 0xFF, 0xFF, },
{ 0xFF, 0xFF, 0xFF, 0xFF, },
{ 0xFF, 0xFF, 0xFF, 0xFF, },
{ 0xFF, 0xFF, 0xFF, 0xFF, },
{ 0xFF, 0xFF, 0xFF, 0xFF, },
{ 0xFF, 0xFF, 0xFF, 0xFF, },
{ 0xFF, 0xFF, 0xFF, 0xFF, },
{ 0xFF, 0xFF, 0xFF, 0xFF, },
// 0x60
{ 0xFF, 0xFF, 0xFF, 0xFF, },
{ 0xFF, 0xFF, 0xFF, 0xFF, },
{ 0xFF, 0xFF, 0xFF, 0xFF, },
{ 0xFF, 0xFF, 0xFF, 0xFF, },
{ 0xFF, 0xFF, 0xFF, 0xFF, },
{ 0xFF, 0xFF, 0xFF, 0xFF, },
{ 0xFF, 0xFF, 0xFF, 0xFF, },
{ 0xFF, 0xFF, 0xFF, 0xFF, },
{ 0xFF, 0xFF, 0xFF, 0xFF, },
{ 0xFF, 0xFF, 0xFF, 0xFF, },
{ 0xFF, 0xFF, 0xFF, 0xFF, },
{ 0xFF, 0xFF, 0xFF, 0xFF, },
{ 0xFF, 0xFF, 0xFF, 0xFF, },
{ 0xFF, 0xFF, 0xFF, 0xFF, },
{ 0xFF, 0xFF, 0xFF, 0xFF, },
{ 0xFF, 0xFF, 0xFF, 0xFF, },
// 0x70
{ 0xFF, 0xFF, 0xFF, 0xFF, },
{ 0xFF, 0xFF, 0xFF, 0xFF, },
{ 0xFF, 0xFF, 0xFF, 0xFF, },
{ 0xFF, 0xFF, 0xFF, 0xFF, },
{ 0xFF, 0xFF, 0xFF, 0xFF, },
{ 0xFF, 0xFF, 0xFF, 0xFF, },
{ 0xFF, 0xFF, 0xFF, 0xFF, },
{ 0xFF, 0xFF, 0xFF, 0xFF, },
{ 0xFF, 0xFF, 0xFF, 0xFF, },
{ 0xFF, 0xFF, 0xFF, 0xFF, },
{ 0xFF, 0xFF, 0xFF, 0xFF, },
{ 0xFF, 0xFF, 0xFF, 0xFF, },
{ 0xFF, 0xFF, 0xFF, 0xFF, },
{ 0xFF, 0xFF, 0xFF, 0xFF, },
{ 0xFF, 0xFF, 0xFF, 0xFF, },
{ 0xFF, 0xFF, 0xFF, 0xFF, },
};
static int KBIndexTab[8] = { 0, 1, 2, 2, 3, 3, 3, 3 };
//-----------------------------------------------------------------------------
#define AAED2000_KBD_COLS 8
#define AAED2000_KBD_ROWS 12
static unsigned int KB_rowState[AAED2000_KBD_COLS]; // Last known state Row x Col
// Map AAED2000 row/col to [PC standard] scancodes
static const int scancode[AAED2000_KBD_ROWS][AAED2000_KBD_COLS] =
{
{0x0A/*9*/, 0x25/*k*/, 0x17/*i*/, 0x09/*8*/, 0x24/*j*/, 0x15/*y*/, 0x08/*7*/, 0x00/*?*/},
{0x0B/*0*/, 0x32/*m*/, 0x19/*p*/, 0x26/*l*/, 0x23/*h*/, 0x16/*u*/, 0x07/*8*/, 0x00/*?*/},
{0x0C/*-*/, 0x18/*o*/, 0x1A/*{*/, 0x27/*:*/, 0x30/*b*/, 0x31/*n*/, 0x22/*g*/, 0x33/*<*/},
{0x0D/*+*/, 0x34/*>*/, 0x1B/*}*/, 0x28/*'*/, 0x48/*?*/, 0x14/*t*/, 0x00/*?*/, 0x00/*?*/},
{0x0E/*?*/, 0x35/*?*/, 0x2B/*|*/, 0x1C/*?*/, 0x4B/*?*/, 0x00/*?*/, 0x06/*5*/, 0x50/*?*/},
{0x00/*?*/, 0x00/*?*/, 0x00/*?*/, 0x00/*?*/, 0x00/*?*/, 0x00/*?*/, 0x00/*?*/, 0x00/*?*/},
{0x39/* */, 0x21/*f*/, 0x00/*?*/, 0x00/*?*/, 0x2E/*c*/, 0x13/*r*/, 0x05/*4*/, 0x2F/*v*/},
{0x4D/*?*/, 0x00/*?*/, 0x00/*?*/, 0x00/*?*/, 0x20/*d*/, 0x12/*e*/, 0x04/*3*/, 0x38/*?*/},
{0x00/*?*/, 0x00/*?*/, 0x00/*?*/, 0x00/*?*/, 0x1F/*s*/, 0x11/*w*/, 0x03/*2*/, 0x2D/*x*/},
{0x53/*?*/, 0x00/*?*/, 0x00/*?*/, 0x00/*?*/, 0x1E/*a*/, 0x10/*q*/, 0x02/*1*/, 0x2C/*z*/},
{0x00/*?*/, 0x2A/*?*/, 0x36/*?*/, 0x00/*?*/, 0x00/*?*/, 0x00/*?*/, 0x00/*?*/, 0x00/*?*/},
{0x00/*?*/, 0x00/*?*/, 0x00/*?*/, 0x00/*?*/, 0x3A/*?*/, 0x0F/*?*/, 0x29/*~*/, 0x1D/*?*/}
};
static bool
KeyboardScan(CYG_BYTE *code)
{
int row, col, i, down, up;
unsigned int state, prev_state;
int stable;
for (col = 0; col < AAED2000_KBD_COLS; col++) {
HAL_WRITE_UINT8(AAEC_KSCAN, col+8); // Assert column #n
for (i = 0, stable = 0, prev_state = 0;
(i < 1000) && (stable < 120); i++) {
HAL_READ_UINT32(AAED_EXT_GPIO, state);
if (state != prev_state) {
prev_state = state;
stable = 0;
} else {
stable++;
}
}
state &= (1<<AAED2000_KBD_ROWS)-1; // Mask off unused bits
if (state != KB_rowState[col]) {
// State changed
down = state & ~KB_rowState[col]; // Bits that went 0->1
up = ~state & KB_rowState[col]; // Bits that went 1->0
for (row = 0; row < AAED2000_KBD_ROWS; row++) {
if ((up|down) & (1<<row)) {
*code = scancode[row][col] | (up ? BREAK : 0);
// Only remember the bit we reported
KB_rowState[col] &= ~(1<<row);
state &= (1<<row);
KB_rowState[col] |= state;
return true;
}
}
}
}
HAL_WRITE_UINT8(AAEC_KSCAN, 0x07); // Turn off drivers
return false;
}
//-----------------------------------------------------------------------------
static CYG_BYTE
KeyboardAscii(CYG_BYTE scancode)
{
CYG_BYTE ascii = 0xFF;
// Start by handling all shift/ctl keys:
switch( scancode ) {
case 0xe0:
KBFlags |= KBExtend;
return 0xFF;
case 0xfa:
KBFlags |= KBAck;
return 0xFF;
case 0xfe:
KBFlags |= KBResend;
return 0xFF;
case LSHIFT:
KBFlags |= KBShiftL;
return 0xFF;
case LSHIFT | BREAK:
KBFlags &= ~KBShiftL;
return 0xFF;
case RSHIFT:
KBFlags |= KBShiftR;
return 0xFF;
case RSHIFT | BREAK:
KBFlags &= ~KBShiftR;
return 0xFF;
case CTRL:
if( KBFlags & KBExtend )
{
KBFlags |= KBCtrlR;
KBFlags &= ~KBExtend;
}
else KBFlags |= KBCtrlL;
return 0xFF;
case CTRL | BREAK:
if( KBFlags & KBExtend )
{
KBFlags &= ~KBCtrlR;
KBFlags &= ~KBExtend;
}
else KBFlags &= ~KBCtrlL;
return 0xFF;
case ALT:
if( KBFlags & KBExtend )
{
KBFlags |= KBAltR;
KBFlags &= ~KBExtend;
}
else KBFlags |= KBAltL;
return 0xFF;
case ALT | BREAK:
if( KBFlags & KBExtend )
{
KBFlags &= ~KBAltR;
KBFlags &= ~KBExtend;
}
else KBFlags &= ~KBAltL;
return 0xFF;
case CAPS:
KBFlags ^= KBCapsLock;
case CAPS | BREAK:
return 0xFF;
case NUMS:
KBFlags ^= KBNumLock;
case NUMS | BREAK:
return 0xFF;
case KBArrowUp:
case KBArrowDown:
#if 0 // Not really needed on this display
screen_pan = 0;
lcd_refresh();
#endif
break;
case KBArrowLeft:
#if 0 // Not really needed on this display
screen_pan -= SCREEN_PAN;
if (screen_pan < 0) screen_pan = 0;
lcd_refresh();
#endif
break;
case KBArrowRight:
#if 0 // Not really needed on this display
screen_pan += SCREEN_PAN;
if (screen_pan > (SCREEN_WIDTH-SCREEN_PAN)) screen_pan = SCREEN_WIDTH-SCREEN_PAN;
lcd_refresh();
#endif
break;
}
// Clear Extend flag if set
KBFlags &= ~KBExtend;
// Ignore all other BREAK codes
if( scancode & 0x80 ) return 0xFF;
// Here the scancode is for something we can turn
// into an ASCII value
ascii = KBScanTable[scancode & 0x7F][KBIndexTab[KBFlags & KBIndex]];
return ascii;
} /* KeyboardAscii */
//-----------------------------------------------------------------------------
int
aaed2000_KeyboardTest(void)
{
// If there is a pending character, return True
if( KBPending != 0xFF ) return true;
// If there is something waiting at the port, get it
for(;;) {
CYG_BYTE code, c;
if (!KeyboardScan(&code)) {
// No new activity
break;
}
// Translate to ASCII
c = KeyboardAscii(code);
// if it is a real ASCII char, save it and
// return True.
if( c != 0xFF ) {
KBPending = c;
return true;
}
}
// Otherwise return False
return false;
} /* KeyboardTest */
int
aaed2000_KeyboardGetc(void)
{
unsigned char ch = KBPending;
KBPending = 0xFF;
return ch;
}
cyg_bool
aaed2000_KeyboardInit(void)
{
int i;
for (i = 0; i < AAED2000_KBD_COLS; i++) {
KB_rowState[i] = 0;
}
KBFlags = 0;
return true;
} /* KeyboardInit */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -