#include "GLOBAL.H"
#include "USB.H"
#include "MOUSE.H"


//-----MCU.C-----//
extern void Delay_5us( void );
extern void Delay_Xms( BYTE );


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

MOUSE Mouse;


void MS_Delay_x5us( BYTE x )
  { while( x )
      { Delay_5us();
        x--;
      }
  }


BIT MS_Wait_CLK_High( void )
  { BYTE i;
    
    
    i = 200;                                     // Check 1ms
    while( i )
      { if ( MS_CLK == SET )
          break;
        Delay_5us();
        i--;
      }
    
    if ( i )
      { MS_Delay_x5us( 3 );                      // Delay 15us
      	return CLR;                              // ok
      }
    else
      { IE3 = CLR;                               // Clear External interrupt 3 flag
        EA = SET;                                // Enalbe all interrupt 
      	return SET;                              // fail
      }
  }


BIT MS_Wait_CLK_Low( void )
  { BYTE i;
    
    
    i = 200;                                     // Check 1ms
    while( i )
      { if ( MS_CLK == CLR )
          break;
        Delay_5us();
        i--;
      }
    
    if ( i )
      { MS_Delay_x5us( 3 );                      // Delay 15us
      	return CLR;                              // ok
      }
    else
      { MS_DTA = SET;                            // ***Mouse Not present***
      	IE3 = CLR;                               // Clear External interrupt 3 flag
        EA = SET;                                // Enalbe all interrupt 
      	return SET;                              // fail
      }
  }


BIT MS_Wait_DTA_High( void )
  { BYTE i;
    
    
    i = 200;                                     // Check 1ms
    while( i )
      { if ( MS_DTA == SET )
          break;
        Delay_5us();
        i--;
      }
    
    if ( i )
      { MS_Delay_x5us( 3 );                      // Delay 15us
      	return CLR;                              // ok
      }
    else
      { IE3 = CLR;                               // Clear External interrupt 3 flag
        EA = SET;                                // Enalbe all interrupt 
      	return SET;                              // fail
      }
  }


void MS_Send_Data_To_Device( BYTE Data )
  { BIT Parity = 1;
    BYTE i;
    
    
    EA = CLR;                                    // Disable ALL interrupt
    
    MS_CLK = CLR;
    MS_Delay_x5us( 40 );                         // Delay 200us
    
    MS_DTA = CLR;
    MS_Delay_x5us( 9 );                          // Delay 45us
    
    MS_CLK = SET;
    if ( MS_Wait_CLK_High() )
      return;
    if ( MS_Wait_CLK_Low() )
      return;
    
    i = 8;
    while( i )                                   // Send Data
      { if (( Data & 0x01 ) == 0x01 )
          { MS_DTA = SET;
            Parity = ~Parity;
          }
        else
          MS_DTA = CLR;
        
        if ( MS_Wait_CLK_High() )
          return;
        if ( MS_Wait_CLK_Low() )
          return;
      	
      	Data >>= 1;
      	i--;
      }
    
    if ( Parity )                                // Send Parity bit
      MS_DTA = SET;
    else
      MS_DTA = CLR;
    
    if ( MS_Wait_CLK_High() )
      return;
    if ( MS_Wait_CLK_Low() )
      return;
    
    MS_DTA = SET;                                // Release Data line
                                                 // Stop bit
    if ( MS_Wait_CLK_High() )
      return;
    if ( MS_Wait_CLK_Low() )
      return;
                                                 // Ack bit
    if ( MS_Wait_CLK_High() )
      return;
    if ( MS_Wait_DTA_High() )
      return;
    
    IE3 = CLR;                                   // Clear External interrupt 3 flag
    EA = SET;                                    // Enalbe all interrupt
  }


void MS_Receive_Data_From_Device( void )
  { BYTE Data = 0;
    BYTE i;
    
    
    EA = CLR;                                    // Disable ALL interrupt
                                                 // Start Bit
    if ( MS_Wait_CLK_Low() )
      return;
    if ( MS_Wait_CLK_High() )
      return;
    
    i = 8;
    while( i )
      { Data >>= 1;
        
      	if ( MS_Wait_CLK_Low() )
          return;
        
        if ( MS_DTA == SET )
          Data += 0x80;                          // Data -> LSB first
        
        if ( MS_Wait_CLK_High() )
          return;
        
        i--;
      }
                                                 // Parity bit
    if ( MS_Wait_CLK_Low() )
      return;
    if ( MS_Wait_CLK_High() )
      return;
                                                 // Stop bit
    if ( MS_Wait_CLK_Low() )
      return;
    if ( MS_Wait_CLK_High() )
      return;

    if (( Mouse.TimeOut == 0 )||( Mouse.Index == 4 ))
      { Mouse.Index = 0;
        Mouse.Data[3] = 0;
      }
    
    Mouse.Data[Mouse.Index] = Data;
    Mouse.Index++;
    Mouse.TimeOut = 2;
    
    USB[UIFLG] = SOFIF;
    USB[UIE] |= SOFIE;
    
    IE3 = CLR;                                   // Clear External interrupt 3 flag
    EA = SET;                                    // Enalbe all interrupt
  }


void Initial_MS( void )
  { Mouse.Act = CLR;
    Mouse.Stage = MS_POWER_ON;
    Mouse.TimeOut = 0;
    Mouse.Index = 0;
    
    EX3 = CLR;                                   // Disable External interrupt 3
    IL3 = CLR;                                   // Failing/Low level
    IT3 = SET;                                   // Edge trigger
    PX3 = SET;                                   // Int3( for Mouse ) high priority ( in IP sfr )
  }


void MS_Send_Key( void )
  { BYTE i;
    
    
    if ( Ep0.EmuOk == CLR )
      return;
      
    if ( Mouse.Act == CLR )
      return;
    
    if ( Mouse.Stage == MS_POWER_ON )
      { IE3 = CLR;                               // Clear External interrupt 3 flag
        EX3 = SET;                               // Enable External interrupt 3
      	
      	Mouse.Stage = MS_WAIT;
      	
      	Mouse.TimeOut = 255;
    
        USB[UIFLG] = SOFIF;
        USB[UIE] |= SOFIE;
      }
    else if (( Mouse.Stage == MS_WAIT )&&( Mouse.TimeOut == 0 ))
      { Mouse.Stage = MS_SET_SAMPLE_RATE_C8;
        MS_Send_Data_To_Device( 0xF3 );          // Set Sample Rate
      }
    
    if (( Mouse.TimeOut == 0 )&&( Mouse.Index != 0 ))
      { if ( Mouse.Index == 1 )
          { Mouse.Index = 0;
            if ( Mouse.Data[0] == 0xFA )
              { if ( Mouse.Stage == MS_SET_SAMPLE_RATE_C8 )
          	  { Mouse.Stage = MS_SET_DECIMAL_C8;
                    MS_Send_Data_To_Device( 0xC8 );
          	  }
          	else if ( Mouse.Stage == MS_SET_DECIMAL_C8 )
          	  { Mouse.Stage = MS_SET_SAMPLE_RATE_64;
                    MS_Send_Data_To_Device( 0xF3 );
          	  }
          	else if ( Mouse.Stage == MS_SET_SAMPLE_RATE_64 )
          	  { Mouse.Stage = MS_SET_DECIMAL_64;
                    MS_Send_Data_To_Device( 0x64 );
          	  }
          	else if ( Mouse.Stage == MS_SET_DECIMAL_64 )
          	  { Mouse.Stage = MS_SET_SAMPLE_RATE_50;
                    MS_Send_Data_To_Device( 0xF3 );
          	  }
          	else if ( Mouse.Stage == MS_SET_SAMPLE_RATE_50 )
          	  { Mouse.Stage = MS_SET_DECIMAL_50;
                    MS_Send_Data_To_Device( 0x50 );
          	  }
          	else if ( Mouse.Stage == MS_SET_DECIMAL_50 )
          	  { Mouse.Stage = MS_OK;
          	    MS_Send_Data_To_Device( 0xF4 );// Enable Device
          	  }
              }
          }
        else if ( Mouse.Index == 2 )             // Device( Mouse ) Initial OK
          { Mouse.Index = 0;
            if (( Mouse.Data[0] == 0xAA )&&( Mouse.Data[1] == 0x00 ))
              { Mouse.Stage = MS_SET_SAMPLE_RATE_C8;
                MS_Send_Data_To_Device( 0xF3 );  // Set Sample Rate
              }
          }
        else                                     // Send Data to Host
          { Mouse.Index = 0;
            
            if (( Mouse.Data[0] & 0xC0 )||(( Mouse.Data[0] & 0x08 ) == 0x00 ))
              return;                            // X or Y Overflow or bit3 != 1
            
            EA = 0;
            
            if (( Mouse.Data[0] & 0x10 ) == 00 ) // X sign bit ( + )
              Mouse.Data[1] &= 0x7F;             // Remove MSB for sign bit
            
            Mouse.Data[2] -= 1;
            Mouse.Data[2] = ~Mouse.Data[2];
            if ( Mouse.Data[0] & 0x20 )          // Y sign bit ( - )
              Mouse.Data[2] &= 0x7F;             // Remove MSB for sign bit
            
            Mouse.Data[3] -= 1;
            Mouse.Data[3] = ~Mouse.Data[3];      // Wheel
            
            Mouse.Data[0] &= 0x07;
          	
            USB[EPINDEX] = EP2;
            i = 0;
            while( i < 4 )
              { USB[TXDAT] = Mouse.Data[i];
                i++;
              }
            Mouse.Busy = SET;
            USB[TXCNT] = i;
            USB[EPINDEX] = EP0;
            EA = 1;
            while( Mouse.Busy == SET );      // Wait " USB Tx " complete
          }
      }
  }