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

📄 combi.c

📁 这是使用CYPRESS的7C637xx芯片完成USB鼠标的例子。
💻 C
📖 第 1 页 / 共 5 页
字号:
void ReadData(void);
void SetStreamMode(void);
void StatusRequest(void);
char SetResolution(char p);
void SetScaling(void);
void ResetScaling(void);
char GetByte ( void);
void ProcessCommand(char p);
void SendMouseData(void);
void Put(char p);
void PutMsgBuff(void);
void SendMouseData(void);
void ps2main(void);
void PutNextByte(void);
void ReInitialize(void);
void ResetInterval(void);
void Ps2MouseTask(void);


/*
**
** FUNCTION:		ClearRam
**
** PURPOSE:			Clears all RAM except data and program stacks.  
**
** PARAMETERS:		none
**
** DESCRIPTION:		Written in assembler so that only X and A are used ( no variables
**					that might be cleared as a result of this function executing)
**
*/

void ClearRam(void)
{
    #asm 
    mov     X,REGISTER_SIZE - 1
    mov     A,0
lp:
    mov     [X + REGISTER_START],A
    dec     X
    jnc     lp
    #endasm
    return;
    }


/*
**
** FUNCTION:		IsUsbInterface
**
** PURPOSE:			Determines whether a USB or PS/2 host is connected upstream.  
**
** PARAMETERS:		none
**
** DESCRIPTION:		This function performs the following algorithm:

					1) Wake up and delay 50mS. Initialize the PS2 BAT delay counter.

					2) For a period of 2mS, poll the SCLK and SDATA lines every 10uS.
					   If we get 4 samples in a row with non-zero data on either line, 
					   detect PS2. If the 2mS expires, go to (3).

					3) Enable USB pull up resistor and delay 500uS. 
					   Poll the SCLK and SDATA lines indefinitely 
					   until a non-zero condition exists on either line. 
					   During this polling period, we begin to count down the PS2 BAT delay.  
					   If SCLK(D+) is sampled high, detect PS2. If SDATA(D-) 
					   is sampled high, go to (4).

					4) Disable the USB connect resistor and Delay 100uS.  
						if D+ and D- are both 0, detect  USB, else detect PS2.
*/

char 	IsUsbInterface(void)
{

	char temp;
	char samples = 4;
     bBatDelay = (500 - 50);								//initialize BAT delay to 500 msec
	temp = MsecStatus.b1msCounter+50;					    //wait 50 msec
  														    
	while (temp != MsecStatus.b1msCounter)
		RESET_COP();
	temp = MsecStatus.b1msCounter+2;
	while (temp != MsecStatus.b1msCounter)					//for 2 msec, sample clock and data
	{
		if ((PORT2 & (PS2_CLOCK_BIT | PS2_DATA_BIT)) && (!--samples))
				return(0);									//4  consecutive samples of either clock or data high, it's ps2
		samples = 4;					
	}

	USB_STATUS = (VREG_ENABLE_MASK | FORCE_NEG_OPEN_POS_OPEN);//enable USB pullup 
	Delay(250);												//and delay 250 usec
	while (1)												//wait forever
	{
		RESET_COP();
		if (MsecStatus.b1msFlags & ONE_MSEC_FLAG)
		{
			if (bBatDelay)									//if a msec expires, decrease bat delay
				bBatDelay--;
			MsecStatus.b1msFlags &= ~ONE_MSEC_FLAG;
		}
		if (PORT2 & PS2_CLOCK_BIT)							
			return(0);										//clock bit high it's ps2
		if (PORT2 & PS2_DATA_BIT)							//data bit high, quit the loop
			break;
	}
	USB_STATUS = FORCE_NEG_OPEN_POS_OPEN;					//disable USB pullup 
    Delay(100);  
	return(!(PORT2 & (PS2_CLOCK_BIT | PS2_DATA_BIT)));		//if both clock and data go low, it's usb
}


/*
**
** FUNCTION:		MY_RESET_ISR
**
** PURPOSE:			Reset ISR, vectored to during power-up or watchdog reset.  
**
** PARAMETERS:		none
**
** DESCRIPTION:		This function performs the following initialization:
**					
**					1)disables interrupts;
**					2)resets the watchdog;
**					3)initializes data stack pointer;
**					4)clears ram;
**					5)initializes port I/O;
*					6)enables 1msec interrupt;
**					7)jumps to main loop
**					
**
*/

void MY_RESET_ISR(void)
{
    DI();											//disable ints
	RESET_COP();									//reset watchdog

	/*
	** use assembler to initialize data stack
	*/
#asm (mov A,RAM_START + STACK_SIZE-1)			        
#asm (swap A,dsp)
      ClearRam();
	USB_STATUS = FORCE_NEG_OPEN_POS_OPEN;						//drive D+,D- to Hi-Z
	PORT0_MODE1 = PORT0_MODE1_INIT;								//set up port modes
	PORT0_MODE0 = PORT0_MODE0_INIT;								//
	PORT1_MODE0 = PORT1_MODE0_INIT ;							//
	PORT1_MODE1 = PORT1_MODE1_INIT;								//
	PORT0 = PORT0_INIT;											//set up initial values
	PORT1 = PORT1_INIT;											//
	PORT0IE = PORT0_INIT;										//set up for GPIO interrupts on switch inputs
	PORT1IE = PORT1_INIT;										//
	PORT0IP = ~PORT0_INIT;										//set up for negative edges interrupts switch inputs
	PORT1IP = ~PORT1_INIT;
	GLOBAL_INTERRUPT = MILLISECOND_ENABLE; 						//enable all pertinent interrupts
	EI();
    #asm (jmp main)
 }


/*
**
** FUNCTION:		main
**
** PURPOSE:			determines interface (usb or ps2) and dispatches to appropriate code.  
**
** PARAMETERS:		none
**
** DESCRIPTION:		
**					
**
*/

 void main(void)
 {
    if (IsUsbInterface())								//if it is USB
    {
          UsbReInitialize();							//initialize USB variables
          usbmain();									//and go to usbmain
	}
	ps2main();											//else straight to ps2
}


/*
**
** FUNCTION:		ProcessOptics
**
** PURPOSE:			Extracts optics data from the queue, and accumulates X,Y, and Z counts
**					based on the state data of each quadrature pair.
** PARAMETERS:		none
**
** DESCRIPTION:		This routine is called from the main loop to process the optical data that has
**					accumulated during successive 128 usec interrupts. For each byte in the optics queue,
**					it extracts the X,Y,and Z state data, and uses the state data from the previous sample
**					to increment/decrement/hold the corresponding count data.	
**					
**
*/

void ProcessOptics(void)
{   
	char temp;
    char temp1;
      if (OpticsQueue.bLen > 16)								//somehow the queue overflowed
      {
		  DI();													//this should never happen, but if so
		  OpticsQueue.headP =									//reset the queue pointers and quit
		  OpticsQueue.tailP = bOpticsArray;
		  OpticsQueue.bLen = 0;
		  EI();
		  return;
      }
	while (OpticsQueue.bLen)
	{
		temp = GET_X_OPTICS(*OpticsQueue.tailP);				//get X quadrature inputs into [1:0]
		temp1 = temp;											//save temporarily
		temp |= Optics.bXstate;									//or in with previous state 
		Optics.bXstate = temp1 << 2;							//shift X inputs into [3:2] and save for next pass
		temp1 = Mouse.bXcount;
		Mouse.bXcount += quad_table[temp];						//use quadrature lookup to inc/dec xcount
		if ((unsigned char) Mouse.bXcount == 0x80)								//if overflow in either direction
			Mouse.bXcount = temp1;								//restore old count
																
		temp = GET_Y_OPTICS(*OpticsQueue.tailP);				//repeat for Y.....
		temp1 = temp;
		temp |= Optics.bYstate;
		Optics.bYstate = temp1 << 2;
		temp1 = Mouse.bYcount;
		Mouse.bYcount -= quad_table[temp];						//note, y counts need to be negated for proper direction
		if ((unsigned char) Mouse.bYcount == 0x80)
			Mouse.bYcount = temp1;

		temp = GET_Z_OPTICS(*OpticsQueue.tailP);				//repeat for Z....
		temp1 = temp;
		temp |= Optics.bZstate;
		Optics.bZstate = temp1 << 2;
		temp1 = Mouse.bZcount;
		Mouse.bZcount += z_quad_table[temp];
		if ((unsigned char) Mouse.bZcount == 0x80)
			Mouse.bZcount = temp1;

		*OpticsQueue.tailP++;									//manage queue pointers
 		if (OpticsQueue.tailP == &bOpticsArray[16])				//wrap them if necessary
			OpticsQueue.tailP = bOpticsArray;
		OpticsQueue.bLen--;
	}
}


/*
**
** FUNCTION:		MICROSECONDx128_ISR
**
** PURPOSE:			128 usec ISR.  
**
** PARAMETERS:		none
**
** DESCRIPTION:		
**					This ISR samples the mouse optics and places the sample in a queue for
**					later processing by the main loop. This is done to minimize the execution time
**					of this ISR, which can interrupt during the time ps/2 bits are being clocked
**					to the host.  The timing of the ps/2 clocking is critical (20 us margin),
**					so the corresponding execution time of this ISR must be kept to less than 20 us.
**					
**
*/

void MICROSECONDx128_ISR(void)
{
	PUSHA();
	PUSHX();
	*OpticsQueue.headP++ = OPTICS_PORT;							//sample optical data
	OpticsQueue.bLen++;											//manage queue pointers and length
	if (OpticsQueue.headP == &bOpticsArray[16])					//wrap pointers if necessary
		OpticsQueue.headP = bOpticsArray;
	POPX();
	POPA();
}


/*
**
** FUNCTION:		MILLISECOND_ISR
**
** PURPOSE:			1 msec ISR.  
**
** PARAMETERS:		none
**
** DESCRIPTION:		
**					This ISR maintains the 1msec counter variable,
**					and sets a flag indicating a 1msec interrupt has occurred. The main loop uses
**					these variables for timing purposes.
*/

void MILLISECOND_ISR(void)
{
    PUSHA();										//save A
    RESET_COP();
	MsecStatus.b1msFlags |= ONE_MSEC_FLAG;			//set flag for main loop
	MsecStatus.b1msCounter++;					    //increment 1msec counter
    POPA();
	return;
}


/*
**
** FUNCTION:		DebounceButtons
**
** PURPOSE:			Debounces the mouse switch inputs  
**
** PARAMETERS:		none
**
** DESCRIPTION:	 
**					This routine should be called at regular intervals from the main loop
**					to debounce the mouse switch inputs.  It maintains a count of the number
**					of successive identical samples of the switch inputs, and returns a 1
**					if the switch inputs have changed have been stable for the debounce interval.
*/

char GetButtons(void)
{
	char bButtons = 0;


	if (LEFT_SWITCH_ASSERTED)						//format an internal copy of the switches
		bButtons |= BIT0;							//this happens to be the USB format!
	if (RIGHT_SWITCH_ASSERTED)
		bButtons |= BIT1;
	/*
	** if Zwheel is enabled in either USB or PS2 mode, report the middle switch
	*/
	if ((MouseParms.bZmouse || DeviceStatus.bProtocol) && (MIDDLE_SWITCH_ASSERTED))
		bButtons |= BIT2;
	return(bButtons);
}

char DebounceButtons(void)
{
    char bButtons;
	bButtons = GetButtons();
 	if (bButtons == bLastButtons)				    //if same as last sample
	{
		  if (bDebounceCount && !--bDebounceCount)  //and debounce interval just expired
		  {
			  Mouse.bButtons = bLastButtons;			//record new buttons
			  return(1);							//and flag that a button change occurred
		  }
		  return(0);								//else no change yet occurred
	}
	bLastButtons = bButtons;						//buttons aren't stable, reset debounce count
	bDebounceCount = DEBOUNCE_COUNT;				//
	return(0);
}


/*
**
** FUNCTION:		USB_BUS_RESET_ISR
**
** PURPOSE:			Bus Reset ISR, vectored to during USB bus reset.  
**
** PARAMETERS:		none
**
** DESCRIPTION:		This function performs the following initialization:
**					
**					1)disables interrupts;
**					2)resets the watchdog;
**					3)initialized data stack pointer and program stack pointer;
**					4 clears ram;
**					5)makes a call to initialize system variables;
**					6)enables device to respond at address 0;
**					7)jumps to main loop
**					
**
*/

void USB_BUS_RESET_ISR(void)
{

    DI();
	RESET_COP();						//tickle watchdog
										//initialize stacks using assembler
#asm (mov A,RAM_START + STACK_SIZE-1)			        
#asm (swap A,dsp)
#asm (mov A,0)
#asm (mov psp,a)
	ClearRam();
	UsbReInitialize();						//reinitialize all system variables

	USB_DEVICE_A = 0x80;  // enable endpoint zero response at address 0
	EP_A0_MODE = USB_MODE_STALL_IN_OUT;
										//and make the leap to the main loop
#asm(jmp usbmain)							
}


/*
**
** FUNCTION:		WAKEUP_ISR
**
** PURPOSE:			ISR for wakeup interrupt.  
**
** PARAMETERS:		none
**
** DESCRIPTION:		The wakeup ISR increments a global counter which is used to "tune" the
**					frequency of the occurrence of the ISR itself (See routine TuneWakeup).
**
*/

void WAKEUP_ISR(void)
{
	bWakeupCount++;
}


/*
**
** FUNCTION:		GPIO_ISR
**
** PURPOSE:			ISR for wakeup interrupt. does nothing except returns  
**
** PARAMETERS:		none
**
** DESCRIPTION:	
**
*/

void GPIO_ISR(void)
{
	
}


/*
**
** FUNCTION:		USB_A_EP0_ISR
**
** PURPOSE:			Endpoint 0 Interrupt Service Routine.  
**
** PARAMETERS:		none
**
** DESCRIPTION:	 
**					this routine is entered upon receiving an endpoint 0 interrupt.
**					EP0 interrupts occur during the Setup, data , and status phases of a
**					setup transaction.  This ISR dispatches the proper routine to handle
**					one of these phases. The interrupt will remain active until the
**					phase in question is completely handled.
*/

void USB_A_EP0_ISR(void)
{
	PUSHA();												//save A and X,they'll get wasted
	PUSHX();
	if (EP_A0_MODE & (1 << ACKNOWLEDGE))					//if this packet was acknowledged,

⌨️ 快捷键说明

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