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

📄 ps2kb.c

📁 标准PS2键盘驱动程序
💻 C
字号:
#include "includes.h"
#include "ps2kb.h" 
#include "i8259.h"
#include "gpio.h"
#include "serial.h"

extern far INT8U atxtcode;
extern far INT8U singleasc;
extern far INT8U vtshifasc;
extern far INT8U vtctrlasc;
extern far INT8U exsingfun;
extern far INT8U exctrlfun;
extern far INT8U pcaltcode;
extern far INT8U pcctrlfun;
extern far INT8U pcshiffun;
extern far INT8U pcsingfun;
INT8U testram=0;
extern far INT16U PwrOn;

extern INT8 gpioc;
extern INT8 mcr;

KBBUF ps2kb;
INT8U ReleFlg;
INT8U kb_flag;
INT8U led_flag;
INT8U ledflag;
INT8U insflag;

int InitPs2Kb(void)
{
	INT8 v;
	
	ps2kb.len = 0;
	ps2kb.WriteP = ps2kb.ReadP = (INT16U *)ps2kb.buff;
	setvect(0x16, int16);
	setvect(PS2KEY_VECT, Ps2KbInt);

	outportb(SEQREG, 0x08);
	v = inportb(SEQREG+1);
	v |= 0x20;
	outport(SEQREG, (v<<8)+0x08);
	setgpio(2, 3, 0);

	outportb(PS2KB_PORT_S, 0x60);
	outportb(PS2KB_PORT_D, 0x5d);
	outportb(PS2KB_PORT_D, 0xae);
	putch('.');
	if(PwrOn!=0x55aa){
		ps2get(PS2KB_PORT_D, 0xffff);
	}
 	putch('.');
 	if(sendcmd(0xff))
 		return -1;
 	putch('.');
 	if(ps2get(PS2KB_PORT_D, 0xffff)==0xff)
 		return -1;
 	if(ps2get(PS2KB_PORT_D, 0xffff)==0xff)
 		return -1;
 	putch('.');
 	if(sendcmd(0xf3))
 		return -1;
 	putch('.');
 	if(ps2get(PS2KB_PORT_D, 0xffff)==0xff)
 		return -1;
 	sendcmd(0);
	if(ps2get(PS2KB_PORT_D, 0xffff)==0xff)
		return -1;
 	putch('.');
	return 0;
}

void interrupt Ps2KbInt(void)
{
	INT8U keyval;
	
	while(inportb(PS2KB_PORT_S)&1){
		keyval = inportb(PS2KB_PORT_D);
		if(keyval!=0xaa && keyval!=0xfa){
			keyval = attoxt(keyval);
			if(keyval){
				if(keyval==0xf0)
					ReleFlg |= RELEFLG;
				else{
					if(ReleFlg&RELEFLG)
						keyval |= 0x80;
					ReleFlg &= CLRELEFLG;
					pc101kb(keyval);
				}
			}
		}
	}
	nop();
	eoi();
}

INT8U attoxt(INT8U keyval)
{
	INT8U *s;
	
	if(keyval<0x85)
	{
		s = &atxtcode;
		keyval = *(s+keyval);
	}
	return keyval;
}

void pc101kb(INT8U keyval)
{
	INT8U keyval1, *s;
	
	keyval1=keyval;
	if(keyval==0xe1){
		kb_flag |= STE1FLG;
		return;
	}
	if(keyval==0xe0){
		kb_flag |= STE0FLG;
		return;
	}
	if(kb_flag&STE1FLG){
		if(keyval==0xc5){
			kb_flag &= CLE1FLG;
			savekeyval(PAUSKEY, &ps2kb);
		}
		return;
	}
	if(kb_flag&STE0FLG){
		kb_flag &= CLE0FLG;
		keyval &= 0x7f;
		
		if(keyval==CTRLP){
			if(keyval1&0x80)
				kb_flag&=CLCTRLF;
			else
				kb_flag|=STCTRLF;
		}
		else if(keyval1==INSERT){
			insflag ^= 1;
		}
		else if(kb_flag&(STLSHFF+STRSHFF)){
			if(keyval1==PDENTER){
				savekeyval(SFPADET, &ps2kb);
			}
		}
		else{
			keyval1 -= 0x1c;
			s = &exsingfun;
			if(kb_flag&STCTRLF)
				s = &exctrlfun;
			keyval1 = *(s+keyval1);
			if(keyval1)
				savekeyval(keyval1<<8, &ps2kb);
		}
		return;
	}
//------pc normal key
	if(keyval&0x80){
		if(keyval==ALTR)
			kb_flag &= CLLALTF;
		else if(keyval==CTRLR)
			kb_flag &= CLCTRLF;
		else if(keyval==LSHIFTR)
			kb_flag &= CLLSHFF;
		else if(keyval==RSHIFTR)
			kb_flag &= CLRSHFF;
		else if(keyval==CAPSLKR)
			ledflag &= CLCAPSF;
		else if(keyval==SCRLCKR)
			ledflag &= CLSCRLF;
		else if(keyval==NUMLCKR)
			ledflag &= CLNUMLF;
		return;
	}
	else{
		if(keyval==ALTP){
			kb_flag |= STLALTF;
			return;
		}
		else if(keyval==CTRLP){
			kb_flag |= STLCTRLF;
			return;
		}
		else if(keyval==LSHIFTP){
			kb_flag |= STLSHFF;
			return;
		}
		else if(keyval==RSHIFTP){
			kb_flag |= STRSHFF;
			return;
		}
		else if(keyval==CAPSLKP){
			if(!(ledflag&CAPSFLG)){
				led_flag ^= CAPSFLG;
				ledflag ^= CAPSFLG;
				lightled(led_flag);
			}
			return;
		}
		else if(kb_flag&STLALTF){
			s = &pcaltcode;
			goto pcgetfun;
		}
		else if(keyval>=0x3b){
			keyval -= 0x3b;
			if(kb_flag&STCTRLF){
				s = &pcctrlfun;
				goto pcgetfun;
			}
			else if(kb_flag&(STLSHFF+STRSHFF)){
				s = &pcshiffun;
				goto pcgetfun;
			}
			s = &pcsingfun;
			if(keyval==(0x45-0x3b)){
				led_flag ^= NUMLFLG;
				lightled(led_flag);
				goto pcgetfun;
			}
			else if(keyval==(0x46-0x3b)){
				led_flag ^= SCRLFLG;
				lightled(led_flag);
			}
		pcgetfun:	
			keyval1 = *(s+keyval);
			if(keyval1){
				savekeyval(keyval1<<8, &ps2kb);	
				return;
			}
		}
		else{
			if(kb_flag&STCTRLF){
				s = &vtctrlasc;
				keyval = *(s+keyval);
				if(keyval1==1)
					keyval1=CTRLESC;
				else if(keyval1==0x37)
					return;
				savekeyval((keyval1<<8)+keyval, &ps2kb);
			}
			else if(kb_flag&(STLSHFF+STRSHFF)){
				s = &vtshifasc;
				keyval = *(s+keyval);
				if(keyval>=0x10){
					if(keyval==',')
						keyval='<';
					else if(keyval=='.')
						keyval='>';
					else if(keyval=='>')
						return;
					savekeyv(keyval1, keyval);
				}
				else if(keyval1!=1){
					savekeyval(keyval<<8, &ps2kb);
				}
				return;
			}
			else{
				s = &singleasc;
				keyval = *(s+keyval);
				if(keyval=='<'){
					savekeyval(PADSTAR, &ps2kb);
				}
				else
					savekeyv(keyval1, keyval);
			}
		}
	}
}


void savekeyv(INT8U keyval1, INT8U keyval)
{
	if(led_flag&CAPSFLG){
		if(keyval>='A'&&keyval<'[')
			keyval |= 0x20;
		else if(keyval>='a'&& keyval<'{')
			keyval &= 0xdf;
	}
	savekeyval((keyval1<<8)+keyval, &ps2kb);
}

void savekeyval(INT16U kv, KBBUF *kb)
{
	if(kb->len<16){
		*kb->WriteP++ = kv;
		if(kb->WriteP>=kb->buff+16)
			kb->WriteP = kb->buff;
		kb->len++;
	}
}


INT16U ReadKey(INT8U *err, KBBUF *kb)
{
	INT16U keyv;
	
	if(kb->len){
		kb->len--;
		keyv = *kb->ReadP++;
		if(kb->ReadP>=kb->buff+16)
			kb->ReadP = kb->buff;
		*err = 0;
	}
	else{
		*err = -1;
		keyv = 0;
	}
	return keyv;
}

void lightled(INT8U led_flag)
{
	INT32U i;
	
	sendcmd(0xed);
	for(i=0;i<0xffff;i++){
		if(inportb(PS2KB_PORT_S)&1){
			inportb(PS2KB_PORT_D);
			break;
		}
	}
	sendcmd(led_flag);
	for(i=0;i<0xffff;i++){
		if(inportb(PS2KB_PORT_S)&1){
			inportb(PS2KB_PORT_D);
			break;
		}
	}
}
#pragma argsused
void interrupt int16(INT16U bp, INT16U di, INT16U si, INT16U ds, INT16U es, INT16U dx, 
		     INT16U cx, INT16U bx, INT16U ax, INT16U ip, INT16U	cs, INT16U psw)
{
	int kv;
	
	switch(highbyte(ax)){
		
		
		case 0:
			while((ps2kb.len)==0);
			ps2kb.len--;
			kv = *ps2kb.ReadP++;
			if(ps2kb.ReadP>=ps2kb.buff+16)
				ps2kb.ReadP = ps2kb.buff;
			ax = kv;
			break;
		case 1:
			if(ps2kb.len){
				psw |= 0x40;
				ax = *ps2kb.ReadP;
			}
			else
				psw &= 0xbf;
			break;
		case 2:
			ax &= 0xff00;
			ax |= (kb_flag&1)<<1;
			ax |= (kb_flag&2)>>1;
			ax |= (kb_flag&4);
			ax |= (kb_flag&0x10)>>1;
			ax |= (led_flag&1)<<4;
			ax |= (led_flag&2)<<4;
			ax |= (led_flag&4)<<4;
			ax |= (insflag&1)<<7;
			break;
		case 3:
			ps2sndcmd(PS2KB_PORT_D, 0xf3);
			ps2get(PS2KB_PORT_D, 0);
			ps2sndcmd(PS2KB_PORT_D, (INT8)ax);
			ps2get(PS2KB_PORT_D, 0);
			break;
		case 4:
			break;
		case 5:
			break;
		default:
			break;
	}
	
}

void ps2sndcmd(INT16U port, INT8U v)
{
	while(inportb(port+1)&2);
	outportb(port, v);
}

INT8U ps2get(INT16U port, INT32U timeo)
{
	INT8U v;
	
	if(timeo){
		while(timeo--&&((v=inportb(port+1)&1)==0));
		if((timeo!=0)&&v){
			return inportb(port);
		}
		else
			return 255;
	}
	else{
		while((v=inportb(port+1)&1)==0);
		return inportb(port);
	}
	
	
}



INT8U readclkdat(void)
{
	asm {
		mov dx, GPIO_PORT
		mov al, GPIOC_DAT
		out dx, al
		inc dx
		in al, dx
	}
	return _AL;
}

INT8U checkparity(INT8U data)
{
	char parity;
	int i;
	
	parity = 0;
	for(i=0;i<8;i++){
		if(data&1)
			parity++;
		data >>= 1;
	}
	return (data%2);
}


int sendcmd(INT8U cmd)
{
	char parity;
	char cmd0;
	int i, j;
	char ioc;
	INT16U bitfrm[11];

	cmd0 = cmd;
	parity = 0;
	for(i=0;i<8;i++){
		if(cmd0&1){
			parity ++;
			bitfrm[i] = ((gpioc|1)<<8)+GPIOC_DAT;
		}
		else{
			bitfrm[i] = ((gpioc&0xfe)<<8)+GPIOC_DAT;
		}
		cmd0 >>= 1;
	}
	if(!(parity%2)){
		bitfrm[i++] = ((gpioc|1)<<8)+GPIOC_DAT;
	}
	else{
		bitfrm[i++] = ((gpioc&0xfe)<<8)+GPIOC_DAT;
	}
	bitfrm[i++] = ((gpioc|1)<<8)+GPIOC_DAT;
	
	outportb(CommPort1+ModemControlReg, mcr=mcr|1);
	outport(GPIO_PORT, (3<<8)+GPIOC_CTL);	// 时钟线数据线做输出
	ioc = gpioc;				
	ioc &= 0xfc;
	outport(GPIO_PORT, (ioc<<8)+GPIOC_DAT);	// 拉低时钟线至少100us
	for(i=0;i<500;i++);			// 延时
	outport(GPIO_PORT, (1<<8)+GPIOC_CTL);   // 释放时钟线
	for(i=0;i<10;i++){
		j = 0x7fff;
		while(--j&&(readclkdat()&2));		// 等待设备将时钟线拉低
		if(!j) goto Err;
		outport(GPIO_PORT, bitfrm[i]);
		while(!(readclkdat()&2));	// 等待设备将时钟线拉高
	}
	outport(GPIO_PORT, (0<<8)+GPIOC_CTL);   // 释放数据线
	j = 0x7fff;
	while(--j&&(readclkdat()&1));		// 等待设备将数据线拉低
	if(!j) goto Err;
	j = 0x7fff;
	while(--j&&(readclkdat()&2));			// 等待设备将时钟线拉低
	if(!j) goto Err;
	j = 0x7fff;
	while(--j&&!(readclkdat()&2));		// 等待设备释放时钟线
	if(!j) goto Err;
	j = 0x7fff;
	while(--j&&!(readclkdat()&1));		// 等待设备释放数据线
	if(!j) goto Err;
	outportb(CommPort1+ModemControlReg, mcr=mcr&0xfe); 
	return 0;
   Err:
   	outportb(CommPort1+ModemControlReg, mcr=mcr&0xfe);
   	return -1;
}

INT8 recvdata(char *err)
{
	INT8 v, parity, stop;
	int i;
	
	if(readclkdat()&2){
		*err = -1;
		return 0;
	}
	else{
		i=8; v = 0;
		while(i--){
			v >>= 1;
			while(!(readclkdat()&2));	// 等待时钟拉高
			while(readclkdat()&2);		// 等待时钟拉低
			if(readclkdat()&1)
				v |= 0x80;
			else
				v &= 0x7f;
		}
		while(!(readclkdat()&2));	// 等待时钟拉高
		while(readclkdat()&2);		// 等待时钟拉低
		parity = readclkdat()&1;	// 奇偶检验位
		while(!(readclkdat()&2));	// 等待时钟拉高
		while(readclkdat()&2);		// 等待时钟拉低
		stop = (readclkdat()&1)<<1;	// 停止位
		while(!(readclkdat()&2));	// 等待时钟拉高
		while(!(readclkdat()&1));	// 等待数据拉高
		if((parity==checkparity(v))&&stop){
			*err = -1;
			return 0;
		}
		*err = 0;
		return v;	// 
	}
}

⌨️ 快捷键说明

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