📄 ps2kb.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 + -