⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 keyboard.c

📁 嵌入式系统基础课件
💻 C
字号:
/* ============================================================ */
/* File: KEYBOARD.C						*/
/*								*/
/* Copyright (C) 2001, Daniel W. Lewis and Prentice-Hall	*/
/*								*/
/* Purpose: Library routines for access to the keyboard.	*/
/* See file LIBEPC.H for function descriptions.			*/
/*								*/
/* Designed for use with the DJGPP port of the GNU C/C++	*/
/* protected mode 386 compiler.					*/
/*								*/
/* Modification History:					*/
/*								*/
/* ============================================================ */

#include "libepc.h"

typedef struct STATE
	{
	BOOL	ins	;
	BOOL	rshift	;
	BOOL	lshift	;
	BOOL	alt	;
	BOOL	ctrl	;
	BOOL	caps	;
	BOOL	scrl	;
	BOOL	num	;
	} __attribute__((packed)) STATE ;

#define	KYBD_STS_PORT	0x64
#define	KYBD_DAT_PORT	0x60

#define	KYBD_DAT_RDY	0x01
#define	BREAK_CODE	0x80

PRIVATE void Install_ISR(void) ;
PRIVATE BOOL Dequeue(BYTE8 *ch) ;

#define	SIZE	20

extern void	KeyboardISR(void)	__asm__("KeyboardISR") ;
extern ISR	old_kybd_isr		__asm__("old_kybd_isr") ;

PRIVATE STATE state ; /* Initialized to all FALSE by loader */

PRIVATE BYTE8		scan_codes[SIZE] ;
PRIVATE unsigned int	nq = 0 ;
PRIVATE unsigned int	dq = 0 ;
PRIVATE unsigned int	count = 0 ;

/* -------------------------------------------------------------------- */
/* Scan code translation table.						*/
/* The incoming scan code from the keyboard selects a row.		*/
/* The modifier status selects the column.				*/
/* The word at the intersection of the two is the scan/ASCII code to	*/
/* put into the PC's type ahead buffer.					*/
/* If the value fetched from the table is zero, then we do not put the	*/
/* character into the type ahead buffer.				*/
/* -------------------------------------------------------------------- */
PRIVATE WORD16 scan_ascii[][8] =
	{
	/* norm,  shft,   ctrl,    alt,    num,   caps,   shcap,  shnum */
/*--*/	{0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000},
/*ESC*/	{0x011B, 0x011B, 0x011B, 0x011B, 0x011B, 0x011B, 0x011B, 0x011B},
/*1 !*/	{0x0231, 0x0221, 0x0000, 0x7800, 0x0231, 0x0231, 0x0231, 0x0321},
/*2 @*/	{0x0332, 0x0340, 0x0300, 0x7900, 0x0332, 0x0332, 0x0332, 0x0332},
/*3 #*/	{0x0433, 0x0423, 0x0000, 0x7A00, 0x0433, 0x0433, 0x0423, 0x0423},
/*4 $*/	{0x0534, 0x0524, 0x0000, 0x7B00, 0x0534, 0x0534, 0x0524, 0x0524},
/*5 %*/	{0x0635, 0x0625, 0x0000, 0x7C00, 0x0635, 0x0635, 0x0625, 0x0625},
/*6 ^*/	{0x0736, 0x075E, 0x071E, 0x7D00, 0x0736, 0x0736, 0x075E, 0x075E},
/*7 &*/	{0x0837, 0x0826, 0x0000, 0x7E00, 0x0837, 0x0837, 0x0826, 0x0826},
/*8 **/	{0x0938, 0x092A, 0x0000, 0x7F00, 0x0938, 0x0938, 0x092A, 0x092A},
/*9 (*/	{0x0A39, 0x0A28, 0x0000, 0x8000, 0x0A39, 0x0A39, 0x0A28, 0x0A28},
/*0 )*/	{0x0B30, 0x0B29, 0x0000, 0x8100, 0x0B30, 0x0B30, 0x0B29, 0x0B29},
/*- _*/	{0x0C2D, 0x0C5F, 0x0000, 0x8200, 0x0C2D, 0x0C2D, 0x0C5F, 0x0C5F},
/*= +*/	{0x0D3D, 0x0D2B, 0x0000, 0x8300, 0x0D3D, 0x0D3D, 0x0D2B, 0x0D2B},
/*bksp*/{0x0E08, 0x0E08, 0x0E7F, 0x0000, 0x0E08, 0x0E08, 0x0E08, 0x0E08},
/*Tab*/	{0x0F09, 0x0F00, 0x0000, 0x0000, 0x0F09, 0x0F09, 0x0F00, 0x0F00},
/*Q*/	{0x1071, 0x1051, 0x1011, 0x1000, 0x1071, 0x1051, 0x1051, 0x1071},
/*W*/	{0x1177, 0x1057, 0x1017, 0x1100, 0x1077, 0x1057, 0x1057, 0x1077},
/*E*/	{0x1265, 0x1245, 0x1205, 0x1200, 0x1265, 0x1245, 0x1245, 0x1265},
/*R*/	{0x1372, 0x1352, 0x1312, 0x1300, 0x1272, 0x1252, 0x1252, 0x1272},
/*T*/	{0x1474, 0x1454, 0x1414, 0x1400, 0x1474, 0x1454, 0x1454, 0x1474},
/*Y*/	{0x1579, 0x1559, 0x1519, 0x1500, 0x1579, 0x1559, 0x1579, 0x1559},
/*U*/	{0x1675, 0x1655, 0x1615, 0x1600, 0x1675, 0x1655, 0x1675, 0x1655},
/*I*/	{0x1769, 0x1749, 0x1709, 0x1700, 0x1769, 0x1749, 0x1769, 0x1749},
/*O*/	{0x186F, 0x184F, 0x180F, 0x1800, 0x186F, 0x184F, 0x186F, 0x184F},
/*P*/	{0x1970, 0x1950, 0x1910, 0x1900, 0x1970, 0x1950, 0x1970, 0x1950},
/*[ {*/	{0x1A5B, 0x1A7B, 0x1A1B, 0x0000, 0x1A5B, 0x1A5B, 0x1A7B, 0x1A7B},
/*] }*/	{0x1B5D, 0x1B7D, 0x1B1D, 0x0000, 0x1B5D, 0x1B5D, 0x1B7D, 0x1B7D},
/*entr*/{0x1C0D, 0x1C0D, 0x1C0A, 0x0000, 0x1C0D, 0x1C0D, 0x1C0A, 0x1C0A},
/*ctrl*/{0x1D00, 0x1D00, 0x1D00, 0x1D00, 0x1D00, 0x1D00, 0x1D00, 0x1D00},
/*A*/   {0x1E61, 0x1E41, 0x1E01, 0x1E00, 0x1E61, 0x1E41, 0x1E61, 0x1E41},
/*S*/	{0x1F73, 0x1F53, 0x1F13, 0x1F00, 0x1F73, 0x1F53, 0x1F73, 0x1F53},
/*D*/	{0x2064, 0x2044, 0x2004, 0x2000, 0x2064, 0x2044, 0x2064, 0x2044},
/*F*/	{0x2166, 0x2146, 0x2106, 0x2100, 0x2166, 0x2146, 0x2166, 0x2146},
/*G*/	{0x2267, 0x2247, 0x2207, 0x2200, 0x2267, 0x2247, 0x2267, 0x2247},
/*H*/	{0x2368, 0x2348, 0x2308, 0x2300, 0x2368, 0x2348, 0x2368, 0x2348},
/*J*/	{0x246A, 0x244A, 0x240A, 0x2400, 0x246A, 0x244A, 0x246A, 0x244A},
/*K*/	{0x256B, 0x254B, 0x250B, 0x2500, 0x256B, 0x254B, 0x256B, 0x254B},
/*L*/	{0x266C, 0x264C, 0x260C, 0x2600, 0x266C, 0x264C, 0x266C, 0x264C},
/*; :*/	{0x273B, 0x273A, 0x0000, 0x0000, 0x273B, 0x273B, 0x273A, 0x273A},
/*' "*/	{0x2827, 0x2822, 0x0000, 0x0000, 0x2827, 0x2827, 0x2822, 0x2822},
/*` ~*/	{0x2960, 0x297E, 0x0000, 0x0000, 0x2960, 0x2960, 0x297E, 0x297E},
/*LShf*/{0x2A00, 0x2A00, 0x2A00, 0x2A00, 0x2A00, 0x2A00, 0x2A00, 0x2A00},
/*\ |*/	{0x2B5C, 0x2B7C, 0x2B1C, 0x0000, 0x2B5C, 0x2B5C, 0x2B7C, 0x2B7C},
/*Z*/	{0x2C7A, 0x2C5A, 0x2C1A, 0x2C00, 0x2C7A, 0x2C5A, 0x2C7A, 0x2C5A},
/*X*/	{0x2D78, 0x2D58, 0x2D18, 0x2D00, 0x2D78, 0x2D58, 0x2D78, 0x2D58},
/*C*/	{0x2E63, 0x2E43, 0x2E03, 0x2E00, 0x2E63, 0x2E43, 0x2E63, 0x2E43},
/*V*/	{0x2F76, 0x2F56, 0x2F16, 0x2F00, 0x2F76, 0x2F56, 0x2F76, 0x2F56},
/*B*/	{0x3062, 0x3042, 0x3002, 0x3000, 0x3062, 0x3042, 0x3062, 0x3042},
/*N*/	{0x316E, 0x314E, 0x310E, 0x3100, 0x316E, 0x314E, 0x316E, 0x314E},
/*M*/	{0x326D, 0x324D, 0x320D, 0x3200, 0x326D, 0x324D, 0x326D, 0x324D},
/*, <*/	{0x332C, 0x333C, 0x0000, 0x0000, 0x332C, 0x332C, 0x333C, 0x333C},
/*. >*/	{0x342E, 0x343E, 0x0000, 0x0000, 0x342E, 0x342E, 0x343E, 0x343E},
/*/ ?*/	{0x352F, 0x353F, 0x0000, 0x0000, 0x352F, 0x352F, 0x353F, 0x353F},
/*rshf*/{0x3600, 0x3600, 0x3600, 0x3600, 0x3600, 0x3600, 0x3600, 0x3600},
/** PS*/{0x372A, 0x0000, 0x3710, 0x0000, 0x372A, 0x372A, 0x0000, 0x0000},
/*alt*/	{0x3800, 0x3800, 0x3800, 0x3800, 0x3800, 0x3800, 0x3800, 0x3800},
/*spc*/	{0x3920, 0x3920, 0x3920, 0x0000, 0x3920, 0x3920, 0x3920, 0x3920},
/*caps*/{0x3A00, 0x3A00, 0x3A00, 0x3A00, 0x3A00, 0x3A00, 0x3A00, 0x3A00},
/*F1*/	{0x3B00, 0x5400, 0x5E00, 0x6800, 0x3B00, 0x3B00, 0x5400, 0x5400},
/*F2*/	{0x3C00, 0x5500, 0x5F00, 0x6900, 0x3C00, 0x3C00, 0x5500, 0x5500},
/*F3*/	{0x3D00, 0x5600, 0x6000, 0x6A00, 0x3D00, 0x3D00, 0x5600, 0x5600},
/*F4*/	{0x3E00, 0x5700, 0x6100, 0x6B00, 0x3E00, 0x3E00, 0x5700, 0x5700},
/*F5*/	{0x3F00, 0x5800, 0x6200, 0x6C00, 0x3F00, 0x3F00, 0x5800, 0x5800},
/*F6*/	{0x4000, 0x5900, 0x6300, 0x6D00, 0x4000, 0x4000, 0x5900, 0x5900},
/*F7*/	{0x4100, 0x5A00, 0x6400, 0x6E00, 0x4100, 0x4100, 0x5A00, 0x5A00},
/*F8*/	{0x4200, 0x5B00, 0x6500, 0x6F00, 0x4200, 0x4200, 0x5B00, 0x5B00},
/*F9*/	{0x4300, 0x5C00, 0x6600, 0x7000, 0x4300, 0x4300, 0x5C00, 0x5C00},
/*F10*/	{0x4400, 0x5D00, 0x6700, 0x7100, 0x4400, 0x4400, 0x5D00, 0x5D00},
/*num*/	{0x4500, 0x4500, 0x4500, 0x4500, 0x4500, 0x4500, 0x4500, 0x4500},
/*scrl*/{0x4600, 0x4600, 0x4600, 0x4600, 0x4600, 0x4600, 0x4600, 0x4600},
/*home*/{0x4700, 0x4737, 0x7700, 0x0000, 0x4737, 0x4700, 0x4737, 0x4700},
/*up*/	{0x4800, 0x4838, 0x0000, 0x0000, 0x4838, 0x4800, 0x4838, 0x4800},
/*pgup*/{0x4900, 0x4939, 0x8400, 0x0000, 0x4939, 0x4900, 0x4939, 0x4900},
/*-*/	{0x4A2D, 0x4A2D, 0x0000, 0x0000, 0x4A2D, 0x4A2D, 0x4A2D, 0x4A2D},
/*left*/{0x4B00, 0x4B34, 0x7300, 0x0000, 0x4B34, 0x4B00, 0x4B34, 0x4B00},
/*Cntr*/{0x4C00, 0x4C35, 0x0000, 0x0000, 0x4C35, 0x4C00, 0x4C35, 0x4C00},
/*rght*/{0x4D00, 0x4D36, 0x7400, 0x0000, 0x4D36, 0x4D00, 0x4D36, 0x4D00},
/*+*/	{0x4E2B, 0x4E2B, 0x0000, 0x0000, 0x4E2B, 0x4E2B, 0x4E2B, 0x4E2B},
/*end*/	{0x4F00, 0x4F31, 0x7500, 0x0000, 0x4F31, 0x4F00, 0x4F31, 0x4F00},
/*down*/{0x5000, 0x5032, 0x0000, 0x0000, 0x5032, 0x5000, 0x5032, 0x5000},
/*pgdn*/{0x5100, 0x5133, 0x7600, 0x0000, 0x5133, 0x5100, 0x5133, 0x5100},
/*ins*/	{0x5200, 0x5230, 0x0000, 0x0000, 0x5230, 0x5200, 0x5230, 0x5200},
/*del*/	{0x5300, 0x532E, 0x0000, 0x0000, 0x532E, 0x5300, 0x532E, 0x5300},
/*--*/	{0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000},
/*--*/	{0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000},
/*--*/	{0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000},
/*F11*/	{0x5700, 0x0000, 0x0000, 0x0000, 0x5700, 0x5700, 0x0000, 0x0000},
/*F12*/	{0x5800, 0x0000, 0x0000, 0x0000, 0x5800, 0x5800, 0x0000, 0x0000}
	} ;

/* ------------------------------------------------------------ */
/* Public functions ...						*/
/* ------------------------------------------------------------ */
BOOL ScanCodeRdy(void)
	{
	Install_ISR() ;
	return (count > 0) ;
	}

BYTE8 GetScanCode(void)
	{
	BYTE8 scan_code ;
	return Dequeue(&scan_code) ? scan_code : 0x00 ;
	}

WORD16 ScanCode2Ascii(BYTE8 code)
	{
	if (code == 0xE0 || code == 0xE1)	return 0x0000 ; /* ignore */
	if (code & 0x80)			return code << 8 ; /* KeyUp */
	if (code >= ENTRIES(scan_ascii))	return 0x0000 ; /* ignore */

	if (state.alt)	return scan_ascii[code][3] ;
	if (state.ctrl)	return scan_ascii[code][2] ;
	if (code >= 0x47)
		{
		if (state.num)
			{
			if (state.lshift || state.rshift)
				{
				return scan_ascii[code][7] ;
				}
			return scan_ascii[code][4] ;
			}
		}

	else if (state.caps)
		{
		if (state.lshift || state.rshift)
			{
			return scan_ascii[code][6] ;
			}
		return scan_ascii[code][5] ;
		}

	if (state.lshift || state.rshift)
		{
		return scan_ascii[code][1] ;
		}

	return scan_ascii[code][0] ;
	}

BOOL SetsKybdState(BYTE8 code)
	{
	switch (code)
		{
		case 0x36: state.rshift = TRUE  ; break ;
		case 0xB6: state.rshift = FALSE ; break ;

		case 0x2A: state.lshift = TRUE  ; break ;
		case 0xAA: state.lshift = FALSE ; break ;

		case 0x38: state.alt    = TRUE  ; break ;
		case 0xB8: state.alt	= FALSE ; break ;

		case 0x1D: state.ctrl	= TRUE  ; break ;
		case 0x9D: state.ctrl	= FALSE ; break ;

		case 0x3A: state.caps = !state.caps ;
		case 0xBA: break ;

		case 0x46: state.scrl = !state.scrl ;
		case 0xC6: break ;

		case 0x45: state.num  = !state.num  ;
		case 0xC5: break ;

		case 0x52: state.ins  = !state.ins  ;
		case 0xD2: break ;

		default:   return FALSE ;
		}

	return TRUE ;
	}

/* ------------------------------------------------------------ */
/* Private functions ...					*/
/* ------------------------------------------------------------ */
BOOL Enqueue(BYTE8 scan_code)	__asm("Enqueue") ;
BOOL Enqueue(BYTE8 scan_code)
	{
	BOOL full ;

	PUSHF ;
	CLI ;
	full = count >= SIZE ;
	if (!full)
		{
		scan_codes[nq] = scan_code ;
		if (++nq == SIZE) nq = 0 ;
		count++ ;
		}
	POPF ;
	return !full ;
	}

PRIVATE BOOL Dequeue(BYTE8 *scan_code)
	{
	BOOL empty ;

	PUSHF ;
	CLI ;
	empty = count <= 0 ;
	if (!empty)
		{
		*scan_code = scan_codes[dq] ;
		if (++dq == SIZE) dq = 0 ;
		count-- ;
		}
	POPF ;
	return !empty ;
	}

PRIVATE void Install_ISR(void)
	{
	static BOOL installed = FALSE ;

	if (installed) return ;
	old_kybd_isr = GetISR(IRQ2INT(IRQ_KYBD)) ;
	SetISR(IRQ2INT(IRQ_KYBD), KeyboardISR) ;
	outportb(0x21, inportb(0x21) & ~0x02) ;	/* Unmask IRQ1 (Keyboard) */
	installed = TRUE ;
	}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -