#include <reg51.h>
#include "d11_cmds.h"
#include "misc.h"
#include "d11chap9.h"
#include "io.h"
#define CONST_CLK_FREQ 12
#define CONST_CLK_DIVIDER (48/CONST_CLK_FREQ)-1
#define DEFAULT_ADDRESS 0x00

/* Register Defintinitions */
/*====================*/
data unsigned char CLK_DIVIDER;
/*--------------------*/
data char yRotation;
data char xRotation;
data char clicked;
data unsigned char lock_write;

/* Function Prototype */
/*====================*/
void D11_initialise(void);
void USB_MAIN(void);
void Check_Mouse(void);
/*--------------------*/


void main(void)
{
	D11_initialise();
        while(1)
	{
		USB_MAIN();

                //------------------------------
                // Add your code here ..........
                //------------------------------
                Check_Mouse();
		    if (D11_SUSPEND && D11_INT_) //This is to ensure that all interrupt has been served.
      	    { //Power down the micro-controller here.
			EX0 = 1; //Enable the external INT0
			EA = 1; //enable Global Interrupt
			PCON = PCON | 0x02; //Power down here.
			EX0 = 0; //Micro-controller wakes up here.
			EA = 0;
			D11_SUSPEND = 1;
			if (D11_INT_)
			{
				SendResume();
			}
                }
	}
}

void USB_MAIN(void)
{
	if (!D11_INT_)
	{
		UpdateIntReg();
		if (ENDPT_INT & CTRL_ENDPT_OUT)
		{ /* Control Endpoint OUT Interrupt */
			ProcessCtrlOutEP();
		} else
		if (ENDPT_INT & CTRL_ENDPT_IN)
		{ /* Control Endpoint IN Interrupt */
			ProcessCtrlInEP();
		} else
		if (ENDPT_INT & ENDPT1_IN)
		{ /* Endpoint 1 IN Interrupt */
	            ReadEndptStatus(ENDPT1_IN); //Clears the IN interrupt
                  lock_write = 0;
		} else
		if (OTHER_INT & BUS_RESET)
		{ /* Bus Reset Condition */
                  DisOtherAddress();
                  SetAddress(DEFAULT_ADDRESS | 0x80); //Set to Default Address
        		DEVICE_STATUS = 0X02; //REMOTE WAKEUP ENABLED, BUS-POWERED
			OPERATIONS_STATUS = 0x00; //Device not configured on Power up
			CLK_DIVIDER = CONST_CLK_DIVIDER; //Clk Divider is initialised here
		}
	}
}

void D11_initialise(void)
{

        P0 = 0xFF;
        P1 = 0xFF;
        P2 = 0xFF;
        P3 = 0xFF;
        DEVICE_STATUS = 0X02; //REMOTE WAKEUP ENABLED, BUS-POWERED
	OPERATIONS_STATUS = 0x00; //Device not configured on Power up
	CLK_DIVIDER = CONST_CLK_DIVIDER; //Clk Divider is initialised here
      yRotation = 0;
      xRotation = 0;
	clicked = 0;
	D11_SUSPEND = 0; //Prevents D11 to go into Suspend state
      DisOtherAddress();
      SetAddress(DEFAULT_ADDRESS | 0x80); //Set to Default Address
	SetMode(0x87, CLK_DIVIDER);   //Disable softconnect
	delay_1s();//Wait till host can unhook
			//device driver before re-enumerating
			//again
	SetMode(0x97, CLK_DIVIDER);   //Enable softconnect, Debug Mode for timing
	D11_SUSPEND = 1; 
}

void Check_Mouse(void)
{
unsigned char changed = 0;
   SCAN = 0Xfb;
   if (!SCANIN0) 
   { //3x3 triggered
      yRotation--;
      xRotation++;
      changed = 1;        
   } else
   if (!SCANIN1) 
   { //3x2 triggered
      yRotation--;
      changed = 1;    
   } else
   if (!SCANIN2) 
   { //3x1 triggered
      yRotation--;
      xRotation--;
      changed = 1;        
   }

   SCAN = 0Xf7;
   if (!SCANIN0) 
   { //2x3 triggered
      xRotation++;
      changed = 1;    
   } else
   if (!SCANIN2) 
   { //2x1 triggered
      xRotation--;
      changed = 1;    
   }

   if (!SCANIN1) 
   { //2x2 triggered
       clicked = 1;    
       changed = 1;    
   } else 
   {
        if (clicked == 1) changed = 1;    
        clicked = 0;    
   }

   SCAN = 0Xef;
   if (!SCANIN0) 
   { //1x3 triggered
      yRotation++;
      xRotation++;
      changed = 1;            
   } else
   if (!SCANIN1) 
   { //1x2 triggered
      yRotation++;
      changed = 1;    
   } else
   if (!SCANIN2) 
   { //1x1 triggered
      yRotation++;
      xRotation--;
      changed = 1;        
   }

   SCAN = 0xff;

   if (changed & !lock_write)
   {
      DBUFFER[0] = 3; //SEND 3 BYTES TO HOST
      DBUFFER[1] = clicked; //Click Status
      DBUFFER[2] = xRotation; //Horizontal Status
      DBUFFER[3] = yRotation; //Vertical Status
      yRotation = 0;
      xRotation = 0;
      SelectEndpoint(ENDPOINT1_IN);
	WriteBuffer();
      ValidateBuffer();
      lock_write = 1;
   }
}
