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

📄 sl811s.c

📁 软件中包含了Cypress的SL811 USB接口芯片的固件程序以及如何51单片机进行操作的例子
💻 C
📖 第 1 页 / 共 2 页
字号:
//*****************************************************************************************
// Cypress Semiconductor - Customer Design Center 
//*****************************************************************************************
// Project		: (SL811S + Audio Control + Internet Control) Demo Code
// File			: sl811s.c
// H/W Target	: SL811HST(Rev 1.5) + EZUSB DEV KIT
// DCE/FAE		: Shawn Ng (cxn)
// Last Update	: 03/01/02
//
//*****************************************************************************************
// Code and Xdata Memory Space
//*****************************************************************************************
// IMPORTANT : 
// 
// 1) EZ811 Demo Board:	JP1 - Select Slave Mode
//						JP2 - Select Full Speed
//						JP3 - Select Dev Kit power
// 
// 2) Currently code support on 3 buttons only, Mute(PC0), Vol Up(PC1) and Vol Down(PC2)
//
// 3) PROGRAM'S CODE/XDATA MEMORY ALLOCATION:
//    Program Code Space	: 0x0080 ~ 0x1B3F -> size:0x1AC0, 6848 bytes available
//    Program xdata Space	: 0x2000 ~ 0x2400 -> size:0x0400, 1024 bytes available
//
//*****************************************************************************************
// SL811HST + EZUSB Hardware Interface:
//*****************************************************************************************
// SL811HST		<-->	AN2131QC	<-->	FUNCTIONS (looking from SL811H side)
// A0			<-->	A0			<-->	(I) Address entry for SL811H, '0'-addr, '1'-data
// D0 ~ D7		<-->	D0 ~ D7		<-->	(B) 8-bit Data Bus
// nCS			<-->	A15			<-->	(I) Enable lower 32K memory(where SL811H is mapped)
// nRD 			<-->	nRD (PC7)	<-->	(I) Read (active low)
// nWR			<-->	nWR (PC6)	<-->	(I) Write (active low)
// nRST			<-->	PB0			<-->	(I) SL811HST's reset (active low)
// MS_SEL		<-->	PB1			<-->	(I) SL811HST's master/slave select, '0'-host
// INTR			<-->	INT4 (PB4)	<-->	(O) SL811HST's interrupt (active high) not used
// ACTIVE_LED	<-->	PB6			<-->	Blink - waiting for enum, On - enumerated
//
//*****************************************************************************************
// LEDs + EZUSB Hardware Interface: (only for Host Mode)
//*****************************************************************************************
// PORT0_LED	<-->	PC0			<--> 	(O) Device attached to SL811H (in host mode)
// PORT1_LED	<-->	PC1			<--> 	(O) Device attached to Port 1 of CY65100
// PORT2_LED	<-->	PC2			<--> 	(O) Device attached to Port 2 of CY65100
// PORT3_LED	<-->	PC3			<--> 	(O) Device attached to Port 3 of CY65100
// PORT4_LED	<-->	PC4			<--> 	(O) Device attached to Port 4 of CY65100
// PORT5_LED	<-->	PC4			<--> 	(O) Not Used
//
//*****************************************************************************************
// Audio Buttons + EZUSB Hardware Interface: (only for Slave Mode)
//*****************************************************************************************
// MUTE_KEY		<-->	PC0			<--> 	(I) Mute Button (active low)
// VOL_UP_KEY	<-->	PC1			<--> 	(I) Volume Up button
// VOL_DN_KEY	<-->	PC2			<--> 	(I) Volume Down button
//
//*****************************************************************************************
// History		:
//*****************************************************************************************
// cxn - 02/20/02	Set/Get Idle/Protocol - HIDview compliant
// cxn - 02/21/02	Chapter9 Compliant
// cxn - 02/28/02	Implemented HID Consumer Control (hardware is only 3 keys)
//
//*****************************************************************************************
// Include files
//*****************************************************************************************
#include "sl811s.h"
#include "descp.h"

//*****************************************************************************************
// Variables Define
//*****************************************************************************************
typedef struct				
{
    BYTE bmRequest;					// SETUP Token Protocol
    BYTE bRequest;
    WORD wValue;
    WORD wIndex;
    WORD wLength;
} 	SetupPKG, *pSetupPKG;

//----------------------------------
// SL811S Variables
//----------------------------------
xdata BYTE 	SL811H_ADDR	_at_ 0x4000;// A0 = '0' - Addr (A15 = nCS of SL811HS)
xdata BYTE 	SL811H_DATA _at_ 0x4001;// A0 = '1' - Data

xdata BYTE	Slave_USBaddr;			// USB device address
xdata BYTE	Slave_ConfigVal;		// Device configuration value
xdata BYTE	Slave_Protocol;			// HID device protocol status
xdata BYTE	Slave_IdleRate;			// HID device idle rate value
xdata BYTE	Slave_RemoteWU;			// Device remote wakeup stats
xdata BYTE	Slave_inEPstall;		// EP0 ~ EP7's IN stall status
xdata BYTE	Slave_outEPstall;		// EP0 ~ EP7's OUT stall status
xdata BYTE	Slave_IfcAlt[MAXIFCNUM];// 8 interface(Ep0~7) contain alternate setting value

xdata BYTE	Audio_Keys;				// Audio Control BitMap
xdata BYTE	Prev_Audio_Keys;
xdata BYTE	Internet_Keys;			// Internet Control BitMap
xdata BYTE	Prev_Internet_Keys;

SetupPKG 	dReq;					// Setup token struct
WORD		len_req;				// length of data for EP0
WORD		sof_cnt;				// 1ms counter
BYTE		ep1_toggle;				// EP1 DATA toggle state
BYTE		in_buffer_idx;			// EP0 IN data buffer tracking

BYTE bdata 	flags;					// Flag Bitmap
sbit dev_first  = flags ^ 0;		// status for 8-byte EP0 transfer
sbit timeout  	= flags ^ 1;		// time out for debounce
sbit enum_done 	= flags ^ 2;		// end of enum, (end of report descp)

extern 	BYTE 	Toggle_SW;			// Toggle switch

BOOL 		IN_NULL;				// EP0's IN null packet transmission
BOOL 		IN_EXACT;				// EP0's IN data length requested is extact of EP0_LEN
BOOL 		BUS_POWERED;			// Bus powered device 

//*****************************************************************************************
// Byte Read from SL811H
// a = register address
// return = data in register
//*****************************************************************************************
BYTE SL811Read(BYTE a)
{  
	SL811H_ADDR = a;			
	return (SL811H_DATA);
}

//*****************************************************************************************
// Byte Write to SL811H
// a = register address
// d = data to be written to this register address
//*****************************************************************************************
void SL811Write(BYTE a, BYTE d)
{  
	SL811H_ADDR = a;	
	SL811H_DATA = d;
}

//*****************************************************************************************
// Buffer Read from SL811H
// addr = buffer start address
// s    = return buffer address where data are to be save/read
// c	= buffer data length
//*****************************************************************************************
void SL811BufRead(BYTE addr, BYTE *s, BYTE c)
{	
	SL811H_ADDR = addr;	
   	while (c--) 
		*s++ = SL811H_DATA;
}

//*****************************************************************************************
// Buffer Write  to SL811H
// addr = buffer start address
// s    = buffer address where data are to be written
// c	= buffer data length
//*****************************************************************************************
void SL811BufWrite(BYTE addr, BYTE *s, BYTE c)
{	
	SL811H_ADDR = addr;	
   	while (c--) 
		SL811H_DATA = *s++;
}

//*****************************************************************************************
// Swap high and low byte 
//*****************************************************************************************
WORD WordSwap(WORD input)
{
	return(((input&0x00FF)<<8)|((input&0xFF00)>>8));
}

//*****************************************************************************************
// Audio Control Key Scanning Routine 
//*****************************************************************************************
void audio_key_scan(void)
{
	Audio_Keys = (~PINSC) & AUDIO_KEYS;				// Mute/Vol Up/Vol Down Keys
	if(Audio_Keys != Prev_Audio_Keys)				// Detect for any changes
	{
		SL811Write(EP1A_Slave_Buf,Audio_Keys);		// send bitmap back to host
		EP1A_IN_Arm(EP1A_Slave_Buf,2,ep1_toggle);	// Arm Ep1 and toggle data
	}
	Prev_Audio_Keys = Audio_Keys;					// update previous key states
}

//*****************************************************************************************
// Internet Control Key Scanning Routine
//*****************************************************************************************
void internet_key_scan(void)
{
	return;
}

//*****************************************************************************************
// EP1 interrupt service routine 
//*****************************************************************************************
int ep1_isr(void)
{
	SL811Write(IntStatus,EP1_DONE);					// clear EP1 interrupt	
	if(SL811Read(EP1AStatus) & EP_ACK)				// check for ACK bit set
		ep1_toggle = (((SL811Read(EP1AControl)&DATAX)==0) ? 1:0);			
													// toggle DATA sequence		
	return;
}

//*****************************************************************************************
// EP1's IN Token Arming (using Set A)
//*****************************************************************************************
void EP1A_IN_Arm(BYTE buf_adr, BYTE len, BYTE seq)
{												
    SL811Write(EP1AAddress,buf_adr); 				// ep1 address buffer start adress
	SL811Write(EP1AXferLen,len);					// max length of transfer allowed
	if(seq)
	    SL811Write(EP1AControl,DATA1_IN);			// armed to transmit to host, DATA1
	else
	    SL811Write(EP1AControl,DATA0_IN);			// armed to transmit to host, DATA0
}

//*****************************************************************************************
// SOF interrupt service routine (act as 1ms timer)
//*****************************************************************************************
int sof_isr(void)
{
	SL811Write(IntStatus,SOF_DONE);					// clear SOF interrupt		
	sof_cnt++;										// track msec timing

	if(sof_cnt==TIME_OUT)							// reset counter on specify 
	{												// time out.				
		sof_cnt	= 0;								
		timeout = 1;								// set timeout flag
	}

	return;
}

//*****************************************************************************************
// EP0 interrupt service routine
//*****************************************************************************************
int ep0_isr(void)
{
	BYTE 	status, byte_rx, len_xfr;
	BYTE	data_seq, req_type;

	SL811Write(IntStatus,EP0_DONE);								// clear EP0 interrupt	
	status 	= SL811Read(EP0AStatus);							// get packet status
	byte_rx = SL811Read(EP0AXferLen) - SL811Read(EP0ACounter);	// get no. of bytes received
																// for OUT data from host
	//----------------------------------------------------------------------------------------
	// ACK received 
	//----------------------------------------------------------------------------------------
	if(status & EP_ACK)
	{
		//----------------------------------------------------------------
		// Set newly assigned USB address
		//----------------------------------------------------------------
		if(Slave_USBaddr)								
		{														// if new USB address was assigned, 
		    SL811Write(USBAddress,Slave_USBaddr);				// communicate all USB transaction	
			Slave_USBaddr = 0;									// using this new address.				
		}

		//================================================================
		// SETUP's ACKed
		//================================================================
		if(status & EP_SETUP)					
		{
	    	SL811BufRead(EP0A_Slave_Buf, (BYTE*)&dReq, byte_rx); 		// capture SETUP data request
			len_req = WordSwap(dReq.wLength);							// len_req = actual requested length
			in_buffer_idx = 0;											// reset buffer locatio indexing
			IN_NULL = FALSE;											// these are for IN-NULL packet
			IN_EXACT = FALSE;											// transfer condition
			req_type = (dReq.bmRequest&0x60)>>5;						// decode for Std,Class,Vendor type

		    switch (req_type)											// Parse bmRequest Type
			{
				//---------------------------------------------------------------------
				// Standard USB Requests
				//---------------------------------------------------------------------
				case STD_REQUEST:
				    switch (dReq.bRequest)								// Parse bRequest
    				{
	    				case GET_DESCRIPTOR:
		           			switch ((BYTE)dReq.wValue)   				// Parse wValue
	    		 	      	{         
	   	        		 		case DEVICE:
									SL811BufWrite(EP0A_Slave_Buf,(BYTE*)Dev_Descp,DEV_LEN);	// load Device Descp
									len_req = (len_req>=DEV_LEN) ? DEV_LEN:len_req;			// get exact data length
					               	break;

			             		case CONFIGURATION:
									SL811BufWrite(EP0A_Slave_Buf,(BYTE*)Cfg_Descp,CFG_LEN);	// load Config Descp	
									len_req = (len_req>=CFG_LEN) ? CFG_LEN:len_req;			// get exact data length
			            		   	break;

			             		case HID_DEV:
									SL811BufWrite(EP0A_Slave_Buf,(BYTE*)Cfg_Descp+18,HID_LEN);// load HID Class Descp	
									len_req = (len_req>=HID_LEN) ? HID_LEN:len_req;			// get exact data length
			            		   	break;

			             		case HID_REPORT:
									SL811BufWrite(EP0A_Slave_Buf,(BYTE*)Rep_Descp,REP_LEN);	// load Report Descp	
									len_req = (len_req>=REP_LEN) ? REP_LEN:len_req;			// get exact data length
				        	       	break;

			             		case STRING:
									switch(dReq.wValue>>8)									// get string index
									{
										case 0x00: SL811BufWrite(EP0A_Slave_Buf,(BYTE*)LangString,LangString[0]);
												   len_req = (len_req>=LangString[0]) ? LangString[0]:len_req;
												   break;				
										case 0x01: SL811BufWrite(EP0A_Slave_Buf,(BYTE*)MfgString,MfgString[0]);
												   len_req = (len_req>=MfgString[0]) ? MfgString[0]:len_req;
												   break;		
										case 0x02: SL811BufWrite(EP0A_Slave_Buf,(BYTE*)ProdString,ProdString[0]);
												   len_req = (len_req>=ProdString[0]) ? ProdString[0]:len_req;
												   break;		
									}
									break;	
							}	

							if (len_req == WordSwap(dReq.wLength))					// if requested length is equal to the
								IN_EXACT = TRUE;									// exact length of descriptor, set IN_EXACT
																					// is use during IN-NULL pkt trasnmission
							len_xfr = (len_req>=EP0_LEN) ? EP0_LEN:(BYTE)len_req;	// get current IN transfer length
							EP0A_IN_Arm(EP0A_Slave_Buf,len_xfr,1);					// Arm IN response, start with DATA1 seq
							in_buffer_idx += len_xfr;								// update to next muliple buffer location
							len_req -= len_xfr;										// update data length for current transfer
							break;

	    				case GET_CONFIG:
							SL811Write(EP0A_Slave_Buf,Slave_ConfigVal);				// load current configuration value
							EP0A_IN_Arm(EP0A_Slave_Buf,1,1);						// send 1 byte data back to host
							len_req = 0;
							break;

	    				case GET_INTERFACE:
							SL811Write(EP0A_Slave_Buf,Slave_IfcAlt[dReq.wIndex>>8]);// load current alternate setting
							EP0A_IN_Arm(EP0A_Slave_Buf,1,1);						// send 1 byte data back to host
							len_req = 0;
							break;

	    				case GET_STATUS:
							switch(dReq.bmRequest&0x03)								// check for recipients
							{
								case RECIPIENT_DEV:									// load current device status
									SL811Write(EP0A_Slave_Buf,(Slave_RemoteWU<<1)|BUS_POWERED);	
									break;
								case RECIPIENT_IFC:							
									SL811Write(EP0A_Slave_Buf,0);					// first byte = 0
									break;
								case RECIPIENT_ENP:							
									if((dReq.wIndex>>8) & 0x80)						// for IN direction endpoint
									{
										if(Slave_inEPstall & (0x01<<((dReq.wIndex>>8)&0x0F)))	
											SL811Write(EP0A_Slave_Buf,1);			// first byte = 1 (IN endpoint stall)		
										else
											SL811Write(EP0A_Slave_Buf,0);			// first byte = 0 (IN endpoint not stall)		
									}
									else									 		// for OUT direction endpoint
									{
										if(Slave_outEPstall & (0x01<<((dReq.wIndex>>8)&0x0F)))	
											SL811Write(EP0A_Slave_Buf,1);			// first byte = 1 (OUT endpoint stall)		
										else
											SL811Write(EP0A_Slave_Buf,0);			// first byte = 0 (OUT endpoint not stall)		

⌨️ 快捷键说明

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