/* 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 KB_WakeUp_State( void )                     // Set scan out line to low
  { P1 &= 0xF8;                                  // P1.0 ~ P1.2
    P2 = 0x00;                                   // P2
    P3 &= 0x80;                                  // P3.0 ~ P3.6
  }


void KB_Normal_State( void )                     // Set scan out line to High
  { P1 |= 0x07;                                  // P1.0 ~ P1.2
    P2 = 0xFF;                                   // P2
    P3 |= 0x7F;                                  // P3.0 ~ P3.6
  }


void Initial_KB( void )
  { 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 );
    
    KB.M_KB.Busy = CLR;                          // SET when pass key code to host
    KB.M_KB.Key = 0x00;
    KB.M_KB.ChangeFlag = CLR;
  }


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[18][3]= 
      {
        {0xFE,0xFF,0xFF},{0xFD,0xFF,0xFF},{0xFB,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,0xFE},{0xFF,0xFF,0xFD},{0xFF,0xFF,0xFB},{0xFF,0xFF,0xF7},
        {0xFF,0xFF,0xEF},{0xFF,0xFF,0xDF},{0xFF,0xFF,0xBF}
      };
    
    USB[IEN] = CLR;                              // Disable USB all related interrupts

    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

    KB_Normal_State();
    
    USB[IEN] = ( EF | EFSR );                    // Enable USB all related interrupts
    
    return KB.Scan.Tmp;
  }


void KB_Get_KeyCode( void )                      // For Megawin ( Large )
  { code BYTE KeyCode_Table[]= 
      { 0x00,0x4C,0x4B,0x4E,0x4A,0x50,0x4A,0x4F, // P1.0
        0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, // P1.1 (X)
        0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, // P1.2 (X)
        0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, // P2.0 
        0x1D,0x39,0x04,0x29,0x2B,0x14,0x35,0x1E, // P2.1 (ok)
        0x38,0x2E,0x33,0x34,0x2F,0x13,0x2D,0x27, // P2.2 (ok)
        0x2C,0x48,0x58,0x2A,0x00,0x52,0x31,0x51, // P2.3 (ok)
        0xE1,0x00,0x00,0x00,0x00,0xE5,0x00,0x00, // P2.4 (ok)
        0x00,0x00,0xE4,0x00,0xE0,0x00,0x00,0x00, // P2.5 (ok)
        0x00,0x00,0x00,0xE3,0x00,0x00,0x00,0x00, // P2.6 (ok)
        0x1B,0x41,0x16,0x40,0x3F,0x1A,0x3E,0x1F, // P2.7 (ok)
        0x19,0x05,0x09,0x0A,0x17,0x15,0x22,0x21, // P3.0 (ok)
        0x06,0x3A,0x07,0x3D,0x3C,0x08,0x3B,0x20, // P3.1 (ok)
        0x00,0xE6,0x00,0x00,0x00,0x00,0x00,0xE2, // P3.2 (ok)
        0x10,0x11,0x0D,0x0B,0x1C,0x18,0x23,0x24, // P3.3 (ok)
        0x36,0x00,0x0E,0x47,0x30,0x0C,0x31,0x25, // P3.4 (ok)
        0x00,0x00,0x00,0x00,0x00,0x00,0x65,0x00, // P3.5 (ok)
        0x37,0x45,0x0F,0x44,0x43,0x12,0x42,0x26  // P3.6 (ok)
      };
        
    KB.Key.Code = KeyCode_Table[KB.Key.Index];
  }  


BIT KB_Check_Multi_Key( void )
  { KB.i = 0;
    KB.Tmp = 0;
    while( KB.i < 8 )
      { if ( KB.Scan.Code & ( 0x80 >> KB.i ) )
          { KB.Tmp++;
            if ( KB.Tmp == 2 )
              return SET;
          }
      	KB.i++;
      } 
    return CLR;
  }


BIT KB_Check_Same_Key( void )
  { KB.i = KB.Scan.Column + 1;
    if ( KB.i == MAX_COLUMN )
      KB.i = 0;
    while( KB.i != KB.Scan.Column )
      { KB.Tmp = KB_Scaning( KB.i );
        if ( KB.Tmp == KB.Scan.Code )
          return SET;
      	KB.i++;
      	if ( KB.i == MAX_COLUMN )
          KB.i = 0;
      }
    
    KB.Tmp = KB_Scaning( KB.i );                 // Now, KB.i = KB.Scan.Column
    if ( KB.Tmp != KB.Scan.Code )                // For double confirm " Scan code "
      return SET;
    
    return CLR;
  }


BYTE KB_Check_Ghost_Key( void )
  { if ( KB_Check_Multi_Key() )                  // Passable have " Ghost Key "
      { if ( KB_Check_Same_Key() )
      	  return SET;
      }
    return CLR;
  }


void KB_Store_Media_KeyCode( void )
  { switch( KB.M_KB.Key & 0x0F )
      { case VOLUMEUP_KEY:     KB.M_KB.Code[0] = 0x01; // Report ID
                           KB.M_KB.Code[1] = VOLUMEUP_KEY;
                           break;
        case VOLUMEDOWN_KEY:   KB.M_KB.Code[0] = 0x01; // Report ID
                           KB.M_KB.Code[1] = VOLUMEDOWN_KEY;
                           break;
        case VOLUMEMUTE_KEY:   KB.M_KB.Code[0] = 0x01; // Report ID
                           KB.M_KB.Code[1] = VOLUMEMUTE_KEY;
                           break;
        case KEYPLAYPAUSE_KEY: KB.M_KB.Code[0] = 0x01; // Report ID
                           KB.M_KB.Code[1] = KEYPLAYPAUSE_KEY;
                           break;
        case KEYNEXT_KEY:      KB.M_KB.Code[0] = 0x01; // Report ID
                           KB.M_KB.Code[1] = KEYNEXT_KEY;
                           break;
        case KEYPREVIOUS_KEY:  KB.M_KB.Code[0] = 0x01; // Report ID
                           KB.M_KB.Code[1] = KEYPREVIOUS_KEY;
                           break;
      	case KEYSTOP_KEY:      KB.M_KB.Code[0] = 0x01; // Report ID
                           KB.M_KB.Code[1] = KEYSTOP_KEY;
                           break;
      	case KEYMEDIAPLAY_KEY: KB.M_KB.Code[0] = 0x01; // Report ID
                           KB.M_KB.Code[1] = KEYMEDIAPLAY_KEY;
                           break;
      	case KEYSEARCH_KEY:    KB.M_KB.Code[0] = 0x01; // Report ID
                           KB.M_KB.Code[1] = KEYSEARCH_KEY;
                           break;                           
      	case KEYEMAIL_KEY:     KB.M_KB.Code[0] = 0x01; // Report ID
                           KB.M_KB.Code[1] = KEYEMAIL_KEY;
                           break;
      	case KEYWWW_KEY:       KB.M_KB.Code[0] = 0x01; // Report ID
                           KB.M_KB.Code[1] = KEYWWW_KEY;
                           break;
      	case KEYSLEEP_KEY:     KB.M_KB.Code[0] = 0x02; // Report ID
                           KB.M_KB.Code[1] = KEYSLEEP_KEY - KEYWWW_KEY; // Index for " 1 "
                           break;
      	case KEYPOWER_KEY:     KB.M_KB.Code[0] = 0x02; // Report ID
                           KB.M_KB.Code[1] = KEYPOWER_KEY - KEYWWW_KEY; // Index for " 2 "
                           break;
      	case KEYWAKEUP_KEY:    KB.M_KB.Code[0] = 0x02; // Report ID
                           KB.M_KB.Code[1] = KEYWAKEUP_KEY - KEYWWW_KEY; // Index for " 3 "
                           break;
      	default:           KB.M_KB.Code[0] = 0x01; // Report ID
      	                   KB.M_KB.Code[1] = 0x00;
      	                   break;
      }
  }


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();                    // 0x70~0x7F for Media Key , 0xF0 ~ 0xFF Reserve
      	    if ((( KB.Key.Code & 0x70 ) == 0x70 )||(( KB.Key.Code & 0xF0 ) == 0xF0 ))
      	      { if ( KB.M_KB.Key == 0x00 )
      	      	  { KB.M_KB.ChangeFlag = SET;
      	      	    KB.M_KB.Key = KB.Key.Code;
      	      	    KB_Store_Media_KeyCode();
      	      	  }
//      	      	else if ( KB.M_KB.Key == KB.Key.Code )
                else
      	      	  { KB.M_KB.ChangeFlag = SET;
      	      	    KB.M_KB.Key = 0x00;
      	      	    KB_Store_Media_KeyCode();
      	      	  }
      	      }
      	    else
      	      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.Scan.Code )                          // Some key has been " PRESS "
      KB.Key.GhostFlag = KB_Check_Ghost_Key();
    
    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;
      }
    
    if ( KB.M_KB.ChangeFlag )
      { EA = 0;
        USB[EPINDEX] = EP2;
        KB.i = 0;
        while( KB.i < 2 )
          { USB[TXDAT] = KB.M_KB.Code[KB.i];
            KB.i++;
          }
        KB.M_KB.Busy = SET;
        USB[TXCNT] = KB.i;
        USB[EPINDEX] = EP0;
        EA = 1;
        while( KB.M_KB.Busy == SET );        // Wait " USB Tx " complete
        KB.M_KB.ChangeFlag = CLR;
      }
  }