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

📄 keyb.c

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

#include <io.h>
#include "keyb.h"
#include "uart.h"
#include "delay.h"
#include "ps2proto.h"
#include "keybmaps.h"

volatile extern u08 Timer, TimerType;

u08 KeysToSend, FrontReleasing, SentCombo,
    CountFrontKeys,
    CountALT, CountCTR, CountSHF, CountNUM,
    ThumbSent, ThumbLast, ThumbLock;
u08 RowDebounce[4], RowNew[4], RowSave[4];

u08 KEYB_DoLookup( void );
extern u08 KEYB_LookupSingles( void );
extern u08 KEYB_LookupCombos( void );


void KEYB_Process1ControlKey_Immediate(u08 *count, u08 bitmask, u08 key);
void KEYB_Process1ControlKey_SaveLock(u08 bitmask, u08 key, u08 isBefore);
void KEYB_ControlKeySend(u08 tosend, u08 key);
void KEYB_ShowKeyChanges( void );


void KEYB_Init( void )
{
   outp(0x00, DDRROWS);
   outp(0x00, PORTROWS);

   outp(0x00, DDRCOLS);
   outp(0x00, PORTCOLS);

   KeysToSend = FALSE;
   FrontReleasing = FALSE;
   SentCombo = FALSE;
   Timer = 0;
   TimerType = ttNONE;
   CountFrontKeys = 0;
   CountALT = 0;
   CountCTR = 0;
   CountSHF = 0;
   CountNUM = 0;
   ThumbSent = 0;
   ThumbLock = 0;
   ThumbLast = 0;
   RowSave[THUMBrow] = 0;
}


u08 KEYB_DebounceKeyboard( void )
{
    u08 i, j;
#define READ_DELAY  4

    RowNew[Qrow] = 0;
    RowNew[Arow] = 0;
    RowNew[Zrow] = 0;

    for (i=1; i<0x40; i<<=1)
    {
        outp(i,DDRCOLS);
        outp(i,PORTCOLS);
        for (j=0;j<READ_DELAY;j++)
          asm("nop");

        if (bit_is_set(PINROWS, BITrowQ))
            RowNew[Qrow] |= i;

        if (bit_is_set(PINROWS, BITrowA))
            RowNew[Arow] |= i;

        if (bit_is_set(PINROWS, BITrowZ))
            RowNew[Zrow] |= i;
    }

    outp(0x40,DDRCOLS);
    outp(0x40,PORTCOLS);
    for (j=0;j<READ_DELAY;j++)
      asm("nop");

    RowNew[THUMBrow] = (inp(PINROWS)&0x70)>>BITrowQ<<3;
//    UART_Printfu08(inp(PINROWS)&0x70);  //diag

    outp(0x80,DDRCOLS);
    outp(0x80,PORTCOLS);
    for (j=0;j<READ_DELAY;j++)
      asm("nop");

    RowNew[THUMBrow] |= (inp(PINROWS)&0x70)>>BITrowQ;
//    UART_Printfu08(inp(PINROWS)&0x70);  //diag

    outp(0,DDRCOLS);
    outp(0,PORTCOLS);

    if (( RowDebounce[Qrow] != RowNew[Qrow] )
        || (RowDebounce[Arow] != RowNew[Arow])
        || (RowDebounce[Zrow] != RowNew[Zrow])
        || (RowDebounce[THUMBrow] != RowNew[THUMBrow]))
    {
        RowDebounce[Qrow] = RowNew[Qrow];
        RowDebounce[Arow] = RowNew[Arow];
        RowDebounce[Zrow] = RowNew[Zrow];
        RowDebounce[THUMBrow] = RowNew[THUMBrow];
        return 0;
    }
    else
    {
//    PRINT("-");
//        KEYB_ShowKeyChanges();              // diag
        return 1;
    }
}


u08 KEYB_GetKeyToSend( void ) // Sees if a front key is ready to send
{
    u08 out, i, j, newcount;

    out = 0;
    newcount = 0;

    for (i=0; i<MAX_ROW; i++)
        for (j=1; j<=MAX_COL; j<<=1)
            if (RowNew[i]&j)
                newcount++;

    if (CountFrontKeys > newcount)
        FrontReleasing = TRUE;
    else
        FrontReleasing = FALSE;

    CountFrontKeys = newcount;

    if (FrontReleasing)   // don't eval RowSave until new press & release
    {
//        KEYB_ShowKeyChanges();              // diag
        if (KeysToSend)
        {
            out = KEYB_DoLookup();
        }
        RowSave[Qrow] = RowNew[Qrow];
        RowSave[Arow] = RowNew[Arow];
        RowSave[Zrow] = RowNew[Zrow];

        if (!CountFrontKeys)
        {
            Timer = 0;
            TimerType = ttNONE;
            SentCombo = FALSE;
        }
    }
    else
    {
       if ((RowSave[Qrow] != RowNew[Qrow])
       || (RowSave[Arow] != RowNew[Arow])
       || (RowSave[Zrow] != RowNew[Zrow]))
       {
           KEYB_ShowKeyChanges();           // diag
           RowSave[Qrow] |= RowNew[Qrow];
           RowSave[Arow] |= RowNew[Arow];
           RowSave[Zrow] |= RowNew[Zrow];
           if (!KeysToSend)
           {
               KeysToSend = TRUE;

               Timer = INTERVAL_INITIAL;
               TimerType = ttINITIAL;
           }
       }
       else
           if ((TimerType!=ttNONE)&&(!Timer))
           {
                if (TimerType==ttINITIAL)
                    Timer = INTERVAL_PREREPEAT;
                else
                Timer = INTERVAL_REPEAT;

                TimerType = ttPREREPEAT;

                out = KEYB_DoLookup();
           }
   }

   if (!CountFrontKeys)
   {
       RowSave[THUMBrow] &= ~(FLPbit|FNCbit);
       RowSave[THUMBrow] |= RowNew[THUMBrow]&(FLPbit|FNCbit);
   }
   return out;
}


u08 KEYB_DoLookup( void )
{
    u08 i,j,out,count;

    out=0;
    count=0;

    for (i=0;i<MAX_ROW;i++)
        for (j=1;j<=MAX_COL;j<<=1)
            if (RowSave[i]&j)
                count++;

    if ((count==1)&&(!SentCombo))
    {
        out = KEYB_LookupSingles();
    }

    if (count>1)
    {
        out = KEYB_LookupCombos();
        SentCombo = TRUE;
    }

    KeysToSend = FALSE;

    return out;
}


u08 KEYB_LookupSingles( void )
{
    u08 *singlemap, i, j;

    if (FNCbit & RowSave[THUMBrow])
        singlemap = FNMap;
    else
        if ((NUMbit & RowSave[THUMBrow])&&(NUMbit & ~ThumbLock))
            singlemap = NumMap;
        else
            if ((NUMbit & ~RowSave[THUMBrow])&&(NUMbit & ThumbLock))
                singlemap = NumMap;
            else
                if (FLPbit & RowSave[THUMBrow])
                    singlemap = FlipMap;
                else
                    singlemap = StdMap;

    for (i=0;i<MAX_ROW;i++)
        for (j=1;j<=MAX_COL;j<<=1)
        {
            if (RowSave[i]&j)
            {
                return PRG_RDB(singlemap);
                break;
            }
            singlemap++;
        }
    return 0;
}

u08 KEYB_LookupCombos( void )
{
    u08 *currChord;

    if (FNCbit & RowSave[THUMBrow])
        currChord = FNChordMap;
    else
        currChord = ChordMap;

    while (PRG_RDB(&currChord[0]) != MAPEND)
    {
        if (   (RowSave[0] == PRG_RDB(&currChord[0]))
            && (RowSave[1] == PRG_RDB(&currChord[1]))
            && (RowSave[2] == PRG_RDB(&currChord[2])) )
            return PRG_RDB(&currChord[3]);

        currChord += 4;
    }
    return 0;
}


void KEYB_ShowKeyChanges( void )
{
    PRINT("\n\r0=");
    UART_Printfu08(RowNew[0]);
    PRINT("  1=");
    UART_Printfu08(RowNew[1]);
    PRINT("  2=");
    UART_Printfu08(RowNew[2]);
    PRINT("  3=");
    UART_Printfu08(RowNew[3]);
}


void KEYB_ProcessControlKeys_Immediate( void )
{
#ifdef debug_NACS
      printf("  rs.%2.2hx tk.%2.2hx ts.%2.2hx   ",
          RowSave[THUMBrow],ThumbLock,ThumbSent);
#endif

    KEYB_Process1ControlKey_Immediate(&CountALT,ALTbit,0xd5);
    KEYB_Process1ControlKey_Immediate(&CountCTR,CTRbit,0xd3);
    KEYB_Process1ControlKey_Immediate(&CountSHF,SHFbit,0xd1);
    KEYB_Process1ControlKey_Immediate(&CountNUM,NUMbit,0);

    ThumbLast = RowNew[THUMBrow];
}


// handles single control key
void KEYB_Process1ControlKey_Immediate(u08 *count, u08 bitmask, u08 key)
{
    u08 tosend;

    // count state changes
    if (*count&1) // count is 1 or 3
    {
        if (bitmask&~RowNew[THUMBrow])
          if (bitmask&ThumbLast)
              *count = (*count)+1;
    }
    else
    {
      if (bitmask&RowNew[THUMBrow])
          if (bitmask&~ThumbLast)
              *count = (*count)+1;
    }

    if (*count>0)
        RowSave[THUMBrow] |= RowNew[THUMBrow]&bitmask;
    else
        RowSave[THUMBrow] &= ~(bitmask&~RowNew[THUMBrow]);

    // toggles key lock
    if (*count>3)
    {
        *count = 0;
        ThumbLock ^= bitmask;
        RowSave[THUMBrow] &= ~bitmask;
        return;
    }

    if (!key)    // num: don't need to send anything
        return;

    tosend = (bitmask&RowNew[THUMBrow])^(bitmask&ThumbLock);
    if (tosend==(ThumbSent&bitmask))
        return;

    KEYB_ControlKeySend(tosend, key);

    // store key sent
    if (tosend)
        ThumbSent |= bitmask;
    else
        ThumbSent &= ~bitmask;
}


void KEYB_ProcessControlKeys_SaveLock( u08 isBefore )
{
    KEYB_Process1ControlKey_SaveLock(ALTbit,0xd5, isBefore);
    KEYB_Process1ControlKey_SaveLock(CTRbit,0xd3, isBefore);
    KEYB_Process1ControlKey_SaveLock(SHFbit,0xd1, isBefore);

  if (!isBefore)
  {
     CountALT = 0;
     CountCTR = 0;
     CountSHF = 0;
     CountNUM = 0;
     RowSave[THUMBrow] = RowNew[THUMBrow];
  }
}

void KEYB_Process1ControlKey_SaveLock(u08 bitmask, u08 key, u08 isBefore)
{
    u08 tosend = 0;

    tosend = (bitmask&RowSave[3])^(bitmask&ThumbLock);
    if (tosend==(ThumbSent&bitmask))
        return;

    if (isBefore)
        KEYB_ControlKeySend(tosend, key);
    else
        KEYB_ControlKeySend(!tosend, key);
}


void KEYB_ControlKeySend(u08 tosend, u08 key)
{
    if (tosend)
        PS2_SendScan( key );    // send press
    else
        PS2_SendScan( key+1 );  // send release
}

⌨️ 快捷键说明

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