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

📄 ps2proto.c

📁 单手PC键盘(at90s8515)
💻 C
字号:
// ps2proto.c

#include <io.h>
#include "ps2proto.h"
#include "uart.h"
#include "delay.h"
#include "ps2protomaps.h"

u08   lastSentByte;
u08   ReceiveError;

u08 PS2_SendByte( u08 abyte, u08 badParity );
u08 PS2_SendBit( u08 abit );
u08 PS2_SendHalfBit( u08 linesOut );

u08 PS2_ReceiveByte( void );
u08 PS2_ReceiveBit( void );

u08 PS2_SendScan( u08 out );
void PS2_SendScanLong( u08 *out );
void PS2_SendScanByte( u08 out );


void PS2_Init( void )
{
    outp(0x00, KDDR);
    outp(0x0f, KPORT);

    while ((inp(KPIN)&(KCLOCKIN|KDATAIN))!=(KCLOCKIN|KDATAIN))
        asm("nop");

    outp( BV(KbitDATAOUT) | BV(KbitCLOCKOUT), KDDR);
    cbi(KPORT, KbitDATAIN);
    cbi(KPORT, KbitCLOCKIN);

    PS2_SendByte(0xAA,FALSE);
    PRINT("\n\r! ");
    UART_PrintfProgStr(macro1);
    PRINT("\n\r");

}


u08 PS2_SendByte( u08 abyte, u08 badParity )
{
  u08 i,j,parity,status;

  for (i=0;i<8;i++)
  {
      if ((inp(KPIN)&KCLOCKIN)!=0) break;
      DELAY_25us();
  }

  if ((inp(KPIN)&KCLOCKIN)==0)
  {
      status = 0xbb; //busy
  }
  else
  {
      lastSentByte = abyte;
      parity = (badParity)?0:1;
      status = PS2_SendBit(0);
      if (!status)
      {
          for (i=0;i<8;i++)
          {
              if (abyte&1) {parity++;}
              status = PS2_SendBit(abyte&1);
              if (status)
                  break;
              else
                  abyte >>= 1;
          }
          if (!status)
              status = PS2_SendBit(parity&1);

          if (!status)
              status = PS2_SendBit(1);
      }
      outp(KDATAOUT|KCLOCKOUT,KPORT);

      if (!status)
      {
          i=0;
          while((i<4)&&(inp(KPIN)&KCLOCKIN))
          {
              DELAY_FullClock();
              i++;
          }

          if (i==4)
              status=4;

          if (!status)
          {
              i=0;
              while((i<100)&&((inp(KPIN)&KCLOCKIN)==0))
              {
                  j=0;
                  while((j<4)&&((inp(KPIN)&KCLOCKIN)==0))
                  {
                      DELAY_25us();
                      j++;
                  }
                  i++;
              }
              if (i==100)
                  status=100;
          }
      }
  }

  return status;
}


u08 PS2_SendBit( u08 abit )
{
   u08 dataNoClock, dataWithClock, result;

   dataNoClock = (abit)?KDATAOUT:0;
   dataWithClock = dataNoClock|KCLOCKOUT;

   result = PS2_SendHalfBit(dataWithClock);

   if (!result)
       result = PS2_SendHalfBit(dataNoClock);

   return result;
}

u08 PS2_SendHalfBit( u08 linesOut )
{
    u08 linesIn;

    outp(linesOut,KPORT);
    DELAY_FullClock();

    linesIn = (inp(KPIN)>>1)&linesOut;  // here's that 1 bit higher assumption
    if (linesIn != linesOut)
        return 2;
    else
        return 0;
}


u08 PS2_ReceiveByte( void )
{
  u08 i,dataIn,parityCalc,parityIn;

  ReceiveError=0;
  dataIn = 0;

  if (((inp(KPIN)&(KDATAIN))==KDATAIN))
  {
      ReceiveError = 0xaa; // host not sending
  }
  else
  {
      parityCalc = 1;

      outp(KDATAOUT|KCLOCKOUT,KPORT);

      // wait 125us for high
      ReceiveError = 3;
      for (i=0;i<5;i++)
      {
          if (inp(KPIN)&KCLOCKIN)
          {
              ReceiveError = 0;
              break;
          }
          DELAY_25us();
      }

      // leave high for 1ms
      for (i=0;i<3;i++)
          DELAY_25us();

      outp(KDATAOUT,KPORT);
      DELAY_FullClock();

      for (i=0;i<8;i++)
      {
          dataIn>>=1;
          if (PS2_ReceiveBit())
          {
              parityCalc++;
              dataIn+=0x80;
          }
      }
      parityIn=(PS2_ReceiveBit())?1:0;

      outp(KDATAOUT|KCLOCKOUT,KPORT);
      DELAY_HalfClock();
      ReceiveError = ((inp(KPIN)&KDATAIN))?0:1;

      if (!ReceiveError)
      {
          outp(KCLOCKOUT,KPORT);
          DELAY_HalfClock();
          outp(0,KPORT);
          DELAY_FullClock();

          ReceiveError=(parityIn!=(parityCalc&1))?2:0;
      }

      outp(KDATAOUT|KCLOCKOUT,KPORT);
  }
  return dataIn;
}


u08 PS2_ReceiveBit( void )
{
    u08 result;

    outp(KDATAOUT|KCLOCKOUT,KPORT);
    DELAY_HalfClock();
    result = ((inp(KPIN)&KDATAIN))?1:0;
    DELAY_HalfClock();
    outp(KDATAOUT,KPORT);
    DELAY_FullClock();

    return result;
}


void PS2_Proto( void )
{
    u08 data;

    data = PS2_ReceiveByte();
    if (ReceiveError!=0xaa)
    {
        if (ReceiveError)
        {
            PS2_SendByte(0xfe,0);
            return;
        }
        else if (data==0xfe)
            PS2_SendByte(lastSentByte,0);
        else if (data==0xee)
        {
            PS2_SendByte(0xee,0);
        }
        else if (data==0xf2)
        {
            PS2_SendByte(0xab,0);
            PS2_SendByte(0x83,0);
        }
        else if (data==0xff)
        {
            PS2_SendByte(0xfa,0);
            PS2_SendByte(0xaa,0);
        }
        else
            PS2_SendByte(0xfa,0);
    }
}

u08 PS2_SendScan( u08 out )
{
    u08 i,j,ScanOut,temp,*macro;

    ScanOut = 0;
    PRINT("\n\r ss=");
    UART_Printfu08(out);
    if (out > 0x1f)
    {
        PRINT(" ");
        UART_SendByte(out);
    }


    if (out>  0xfc)
        return 1;

    else if (out>= 0xf0)
    {
        ScanOut = PRG_RDB(&ScanF0s[out-0xF0-1]);
    }
    else if (out> 0xed)
        return 2;
    else if (out>= 0xe0)
    {
        ScanOut = PRG_RDB(&ScanE0s[out-0xE0]);
        if ((out< 0xec)||(!out&1))
        {
            PS2_SendScanByte(0xe0);
            PS2_SendScanByte(ScanOut);
        }

        if ((out< 0xec)||(out&1))
        {
            PS2_SendScanByte(0xf0);
            PS2_SendScanByte(0xe0);
            PS2_SendScanByte(ScanOut);
        }
        return 0;
    }
    else if (out==0xde)
    {
        PS2_SendScanLong( ScanPrtScrn );
        return 0;
    }
    else if (out==0xdf)
    {
        PS2_SendScanLong( ScanPause );
        return 0;
    }
    else if (out> 0xd8)
        return 3;
    else if (out>= 0xd1)
    {
        ScanOut = PRG_RDB(&ScanC0s[out-0xC0]);
        if (out&1)
        {
            PS2_SendScanByte(ScanOut);
        }
        else
        {
            PS2_SendScanByte(0xf0);
            PS2_SendScanByte(ScanOut);
        }
        return 0;
    }
    else if (out>= 0xc0)
    {
        ScanOut = PRG_RDB(&ScanC0s[out-0xC0]);
    }
    else if (out >= 0xa0)
    {
        macro = 0;
        if (out == 0xa0) {
            macro = macro1;
        }

        if (macro)
        {

            PRINT("\n\r");
            UART_PrintfProgStr(macro);
            PRINT("\n\r");

            j = 0;
            while ( (out=PRG_RDB(&macro[j])) )
            {
                if ( (temp=PS2_SendScan(out)) )
                  return temp;

                j++;
            }
        }
        return 0;
    }
    else
    {
        i = 0;

        while ( (temp=PRG_RDB(&asciiToScan[i])) && (temp != out))
            i+=2;

        if (temp)
            ScanOut = PRG_RDB(&asciiToScan[i+1]);
        else
            return 4;
    }

    PS2_SendScanByte(ScanOut);
    PS2_SendScanByte(0xf0);
    PS2_SendScanByte(ScanOut);
    return 0;
}

void PS2_SendScanLong( u08 *out )
{
    u08 i;

    i=0;
    while (PRG_RDB(&out[i]))
    {
        PS2_SendScanByte(PRG_RDB(&out[i]));
        i++;
    }
}


void PS2_SendScanByte( u08 out )
{
    PS2_SendByte(out,FALSE);
}

⌨️ 快捷键说明

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