📄 sl811s.c
字号:
//*****************************************************************************************
// 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 + -