/* This version does not detect the Ghost Key  */
/* It could be implement by user application   */

#include <intrins.h>                             // for _nop_();
#include <string.h>                              // for memset();
#include "GLOBAL.H"
#include "USB.H"
#include "KEYBOARD.H"


//-----USB.C-----//
extern EP0INFO Ep0;


bdata BYTE LED_STATUS;
sbit NumLock = LED_STATUS^0;
sbit Caps = LED_STATUS^1;
sbit ScrollLock = LED_STATUS^2;

KEYBOARD KB;


void Initial_KB( void )
  { KBPATN = 0xFF;
    KBCON = 0x00;
    KBMASK = 0x00;                               // Will Disable KP Interrupt
    
    LED_STATUS = 0x00;                           // Defaul LED off
    
    KB.Act = CLR;
    KB.Key.Busy = CLR;                           // SET when pass key code to host
    KB.Scan.Column = 0;                          // For scaning
    KB.Key.ChangeFlag = CLR;
    KB.Key.GhostFlag = CLR;
    
    memset( KB.Scan.Store , 0 , MAX_COLUMN );
    
    KB.HostIndex = 0;
    memset( KB.ToHost.Code , 0 , 8 );
  }


void KB_LED_Off( void )
  { NumLock_LED = SET;
    Caps_LED = SET;
    ScrollLock_LED = SET;
  }


void KB_LED_Status( void )
  { NumLock_LED = ~NumLock;
    Caps_LED = ~Caps;
    ScrollLock_LED = ~ScrollLock;
  }


void KB_Delay1us( BYTE Delaytime )
  { for ( Delaytime ; Delaytime>0 ; Delaytime-- )
       { _nop_();
       }
  }


// Scan_index = 18 for Key Press test
BYTE KB_Scaning( BYTE Scan_index )
  { code BYTE KeyScan_Table[19][3]= 
      {
        {0xFE,0xFF,0xFF},{0xFD,0xFF,0xFF},{0xFB,0xFF,0xFF},{0xF7,0xFF,0xFF},
        {0xEF,0xFF,0xFF},{0xDF,0xFF,0xFF},{0xBF,0xFF,0xFF},{0x7F,0xFF,0xFF},
        {0xFF,0xFE,0xFF},{0xFF,0xFD,0xFF},{0xFF,0xFB,0xFF},{0xFF,0xF7,0xFF},
        {0xFF,0xEF,0xFF},{0xFF,0xDF,0xFF},{0xFF,0xBF,0xFF},{0xFF,0x7F,0xFF},
        {0xFF,0xFF,0xF7},{0xFF,0xFF,0xEF},{0x00,0x00,0xE7}
      };

    P1 = KeyScan_Table[Scan_index][0];
    P2 = KeyScan_Table[Scan_index][1];
    P3 = P3&KeyScan_Table[Scan_index][2];
    
    KB_Delay1us( 10 );
    
    KB.Scan.Tmp = P0;                            // 1101,1111 -> 0 for Key " PRESS "
    KB.Scan.Tmp = ~KB.Scan.Tmp;                  // 0010,0000

    P1 = 0xFF;
    P2 = 0xFF;
    P3 = P3|0x18;
    
    return KB.Scan.Tmp;
  }


void KB_Get_KeyCode( void )                      // For Megawin ( Small )
  { code BYTE KeyCode_Table[]= 
      { 0x11,0x10,0x0B,0x0D,0x18,0x23,0x24,0x1C,
        0x05,0x19,0x0A,0x09,0x15,0x22,0x21,0x17,
        0x00,0x06,0x3D,0x07,0x08,0x3B,0x20,0x3C,
        0x00,0x1B,0x00,0x16,0x1A,0x3A,0x1F,0x39,
        0x00,0x1D,0x29,0x04,0x14,0x35,0x1E,0x2B,
        0x4F,0x54,0x62,0x5A,0x60,0x49,0x45,0x5D,
        0x51,0x53,0x00,0x59,0x5F,0x4C,0x44,0x5C,
        0x00,0xE5,0x00,0x00,0x00,0x00,0x00,0xE1,
        0x00,0xE4,0x00,0x00,0x00,0xE0,0x00,0x00,
        0x50,0x48,0x52,0x58,0x57,0x4A,0x4D,0x00,
        0x00,0x37,0x00,0x0F,0x12,0x41,0x26,0x40,
        0x00,0x36,0x3F,0x0E,0x0C,0x2E,0x25,0x30,
        0x56,0x55,0x63,0x5B,0x61,0x4B,0x4E,0x5E,
        0x00,0x00,0x00,0xE3,0x65,0x00,0x00,0x00,
        0xE6,0x00,0xE2,0x00,0x47,0x00,0x46,0x00,
        0x00,0xE7,0x00,0x00,0x00,0x00,0x00,0x00,
        0x2C,0x28,0x3E,0x31,0x00,0x42,0x43,0x2A,
        0x38,0x00,0x34,0x33,0x13,0x2D,0x27,0x2F
      };
        
    KB.Key.Code = KeyCode_Table[KB.Key.Index];
  }     
        

void KB_Check_Key_Change( void )
  { KB.i = 0;
    KB.Tmp = 0x01;
    KB.Scan.Tmp ^= KB.Scan.Code;                 // Get " Change Bit "
    while( KB.i < 8 )
      { if ( KB.Scan.Tmp & KB.Tmp )
      	  { KB.Key.Index = KB.Scan.Column << 3;  // X*8
      	    KB.Key.Index += KB.i;
      	    KB_Get_KeyCode();
            KB.Key.ChangeFlag = SET;
      	  }
      	KB.i++;
      	KB.Tmp <<= 1;
      }
  }


void KB_Store_KeyCode( void )
  { if (( KB.Key.Code & 0xF8 ) == 0xE0 )         // Modifier
      { switch( KB.Key.Code )	
          { case L_CTRL:  KB.ToHost.Part.Modifier.LeftCtrl = 1;
                          break;
            case L_SHIFT: KB.ToHost.Part.Modifier.LeftShift = 1;
                          break;
            case L_ALT:   KB.ToHost.Part.Modifier.LeftAlt = 1;
                          break;
            case L_GUI:   KB.ToHost.Part.Modifier.LeftGui = 1;
                          break;
            case R_CTRL:  KB.ToHost.Part.Modifier.RightCtrl = 1;
                          break;
            case R_SHIFT: KB.ToHost.Part.Modifier.RightShift = 1;
                          break;
            case R_ALT:   KB.ToHost.Part.Modifier.RightAlt = 1;
                          break;
            case R_GUI:   KB.ToHost.Part.Modifier.RightGui = 1;
                          break;
          }
      }
    else
      { if ( KB.HostIndex == 6 )                 // Error Key ( More then 6 key )
          KB.Key.GhostFlag = SET;
        else
          { KB.ToHost.Part.Code[KB.HostIndex] = KB.Key.Code;
            KB.HostIndex++;
          }
      }
  }


void KB_Check_Valid_Key( void )
  { KB.i = 0;
    KB.Tmp = 0x01;
    while( KB.i < 8 )
      { if ( KB.Scan.Code & KB.Tmp )             // 
      	  { KB.Key.Index = KB.Scan.Column << 3;  // X*8
      	    KB.Key.Index += KB.i;
      	    KB_Get_KeyCode();
      	    KB_Store_KeyCode();
      	  }
      	KB.i++;
      	KB.Tmp <<= 1;
      }
  }


void KB_Scan_Key( void )
  { if ( Ep0.EmuOk == CLR )
      return;
    
    if ( KB.Act == CLR )
      return;
    
    if ( KB.Scan.Column == MAX_COLUMN )
      KB.Scan.Column = 0;
      
    while( 1 )
      { KB.Scan.Code = KB_Scaning( KB.Scan.Column );
        if ( KB.Scan.Code == KB.Scan.Store[KB.Scan.Column] )
          break;
        
        KB_Delay1us( 100 );                      // For Double Check
        
        KB.Tmp = KB_Scaning( KB.Scan.Column );
        if ( KB.Tmp == KB.Scan.Code )
          break;
      }
    
    KB.Key.GhostFlag = CLR;

    if ( KB.Key.GhostFlag == CLR )               // Not Ghost Key
      { KB.Scan.Tmp = KB.Scan.Store[KB.Scan.Column];
      	KB_Check_Key_Change();
      	KB.Scan.Store[KB.Scan.Column] = KB.Scan.Code;
      	KB_Check_Valid_Key();
      }
        
    KB_Delay1us( 250 );
    KB_Delay1us( 250 );                          // 
    
    KB.Scan.Column++;
  }


void KB_Send_Key( void )
  { if ( Ep0.EmuOk == CLR )
      return;
    
    if ( KB.Act == CLR )
      return;
    
    if ( KB.Scan.Column == MAX_COLUMN )
      { if ( KB.Key.GhostFlag )
          { KB.ToHost.Code[0]=0x00;
            KB.ToHost.Code[1]=0x00;
            KB.ToHost.Code[2]=0x01;
            KB.ToHost.Code[3]=0x01;
            KB.ToHost.Code[4]=0x01;
            KB.ToHost.Code[5]=0x01;
            KB.ToHost.Code[6]=0x01;
            KB.ToHost.Code[7]=0x01;
            EA = 0;
            USB[EPINDEX] = EP1;
            KB.i = 0;
            while( KB.i < 8 )
              { USB[TXDAT] = KB.ToHost.Code[KB.i];
                KB.i++;
              }
            KB.Key.Busy = SET;
            USB[TXCNT] = KB.i;
            USB[EPINDEX] = EP0;
            EA = 1;
            while( KB.Key.Busy == SET );         // Wait " USB Tx " complete
          }
        else if ( KB.Key.ChangeFlag )   
          { EA = 0;
            USB[EPINDEX] = EP1;
            KB.i = 0;
            while( KB.i < 8 )
              { USB[TXDAT] = KB.ToHost.Code[KB.i];
                KB.i++;
              }
            KB.Key.Busy = SET;
            USB[TXCNT] = KB.i;
            USB[EPINDEX] = EP0;
            EA = 1;
            while( KB.Key.Busy == SET );         // Wait " USB Tx " complete
          } 
        
        KB.HostIndex = 0;
        memset( KB.ToHost.Code , 0 , 8 );
        KB.Key.ChangeFlag = CLR;
        KB.Key.GhostFlag = CLR;
      }
  }