?? f320_usb_common.c
字號:
//-----------------------------------------------------------------------------
// F320_USB_Common.c
//-----------------------------------------------------------------------------
// Copyright 2005 Silicon Laboratories, Inc.
// http://www.silabs.com
//
// Program Description:
//
// This is the module that handles common USB functions, including primary USB
// interrupt service routine, an endpoint zero handler, and fifo read and write
// routines.
//
//
// FID: 32X000070
// Target: C8051F320
// Tool chain: KEIL C51 7.0.0.1 / KEIL A51 7.0.0.1
// Silicon Laboratories IDE version 2.3
// Command Line: See Readme.txt
// Project Name: F320_TONE_GENERATOR
//
// Release 1.0
// -Initial Revision (PD)
// -05 JUL 2006
//
//
//-----------------------------------------------------------------------------
// Includes
//-----------------------------------------------------------------------------
#include "c8051f320.h" // SFR declarations
#include "F320_Tone_Generator_Main.h" // Main project header
#include "F320_USB_Register.h" // USB core register header
#include "F320_USB_Common.h" // USB protocol header
#include "F320_USB_Descriptor.h" // USB descriptor definitions
#include "F320_SineWaveGenerator.h"
//-----------------------------------------------------------------------------
// Variable Declaration
//-----------------------------------------------------------------------------
idata setup_buffer Setup; // Buffer for device request
idata BYTE USB_State; // Holds the USB State
idata unsigned int DataSize; // Size of data to return
idata unsigned int DataSent; // Amount of data sent
idata BYTE* DataPtr; // Pointer to data
// Endpoint status array
idata BYTE Ep_Status[4] = { EP_IDLE, EP_IDLE, EP_IDLE, EP_IDLE };
sbit LED1 = P2^3;
sbit LED2 = P2^2;
//-----------------------------------------------------------------------------
// Local Functions
//-----------------------------------------------------------------------------
void IsochronousTimer_Start(void);
void IsochronousTimer_Reset(void);
void IsochronousTimer_Stop(void);
//-----------------------------------------------------------------------------
// Usb_ISR
//
// Return Value : None
// Parameters : None
//
// Called after any USB type interrupt, this handler determines which type of
// interrupt occurred, and calls the specific routine to handle it.
//
//-----------------------------------------------------------------------------
void Usb_ISR (void) interrupt 8 using USB_REGISTER_BANK
{
data BYTE bCommon, bIn, bOut, ControlReg;
POLL_READ_BYTE (CMINT, bCommon); // Read all interrupt registers POLL_READ_BYTE (IN1INT, bIn); // this read also clears the register
POLL_READ_BYTE (OUT1INT, bOut);
LED1 = 0;
if (bCommon)
{
if (bCommon & rbSOF)
{
POLL_WRITE_BYTE (INDEX, 3);
POLL_READ_BYTE (EINCSR1, ControlReg);
if (ControlReg & rbInUNDRUN)
{
// Clear under run bit
POLL_WRITE_BYTE (EINCSR1, 0x00);
Turn_On_Stream ();
IsochronousTimer_Start();
}
}
if (bCommon & rbRSTINT) Usb_Reset ();
if (bCommon & rbSUSINT) Usb_Suspend ();
}
if (bIn & rbEP0)
{
// Handle Setup packet received or transmitted
Handle_Setup ();
}
if (bIn & rbIN3)
{
IsochronousTimer_Reset();
Handle_In3 (); // Handle In Packet sent
}
if (bOut & rbOUT2)
{
bOut++;
}
}
//-----------------------------------------------------------------------------
// Usb_Reset
//-----------------------------------------------------------------------------
//
// Return Value : None
// Parameters : None
//
// Clears USB inhibit bit and sets endpoint states to default.
//
//-----------------------------------------------------------------------------
void Usb_Reset (void) using USB_REGISTER_BANK
{
USB_State = DEV_DEFAULT; // Set device state to default
// Clear USB inhibit bit, enable suspend detection, turn off ISO update
POLL_WRITE_BYTE (POWER, 0x01);
Ep_Status[0] = EP_IDLE; // Set default Endpoint Status
Ep_Status[1] = EP_HALT;
Ep_Status[2] = EP_HALT;
Ep_Status[3] = EP_HALT;
}
//-----------------------------------------------------------------------------
// Handle_Setup
//-----------------------------------------------------------------------------
//
// Return Value : None
// Parameters : None
//
// Decodes incoming setup requests, loads data packets on fifo in transmit
// mode, and retrieves data from fifo in receive mode.
//
//-----------------------------------------------------------------------------
void Handle_Setup (void) using USB_REGISTER_BANK
{
data BYTE ControlReg; // Storage for EP control register
POLL_WRITE_BYTE (INDEX, 0); // Set Index to Endpoint Zero
POLL_READ_BYTE (E0CSR, ControlReg); // Read control register
// Handle Status Phase of Set Address command
if (Ep_Status[0] == EP_ADDRESS)
{
POLL_WRITE_BYTE (FADDR, Setup.wValue.c[LSB]);
Ep_Status[0] = EP_IDLE;
}
// If last packet was a sent stall, reset STSTL bit and return EP0 to idle
if (ControlReg & rbSTSTL)
{
POLL_WRITE_BYTE (E0CSR, 0);
Ep_Status[0] = EP_IDLE;
return;
}
// If last setup transaction was ended prematurely set Serviced Setup End
// bit and return EP0 to idle state
if (ControlReg & rbSUEND)
{
POLL_WRITE_BYTE (E0CSR, rbSSUEND);
Ep_Status[0] = EP_IDLE;
}
if (Ep_Status[0] == EP_IDLE) // If Endpoint 0 is in idle mode
{
// Make sure that EP 0 has an Out Packet ready from host although if EP0
// is idle, this should always be the case
if (ControlReg & rbOPRDY)
{
// Get Setup Packet off of Fifo, it is currently Big-Endian
FIFO_Read (FIFO_EP0, 8, (BYTE *)&Setup);
Setup.wValue.i = Setup.wValue.c[MSB] + 256*Setup.wValue.c[LSB];
Setup.wIndex.i = Setup.wIndex.c[MSB] + 256*Setup.wIndex.c[LSB];
Setup.wLength.i = Setup.wLength.c[MSB] + 256*Setup.wLength.c[LSB];
if ((Setup.bmRequestType & TYPE_MASK) == CLASS_TYPE)
{
// Call correct subroutine to handle each kind of
// class-specific request
switch (Setup.bRequest)
{
case GET_CUR: Get_Cur (); break;
case SET_IDLE: Set_Idle (); break;
// The Get Report HID command type has an overlap
// with Set Cur in audio driver, the request type
// can be used to tell the difference.
case GET_REPORT:
if (Setup.bmRequestType & 0x80)
{
Get_Report ();
}
else Set_Cur ();
break;
case SET_REPORT: Set_Report (); break;
// Send stall to host if invalid request
default: Force_Stall (); break;
}
}
else
{
// Call correct subroutine to handle each kind of
// standard request
switch (Setup.bRequest)
{
case GET_STATUS: Get_Status (); break;
case CLEAR_FEATURE: Clear_Feature (); break;
case SET_FEATURE: Set_Feature (); break;
case SET_ADDRESS: Set_Address (); break;
case GET_DESCRIPTOR: Get_Descriptor (); break;
case GET_CONFIGURATION: Get_Configuration (); break;
case SET_CONFIGURATION: Set_Configuration (); break;
case GET_INTERFACE: Get_Interface (); break;
case SET_INTERFACE: Set_Interface (); break;
// Send stall to host if invalid request
default: Force_Stall (); break;
}
}
}
}
if (Ep_Status[0] == EP_TX) // See if endpoint should transmit
{
if (!(ControlReg & rbINPRDY)) // Don't overwrite last packet
{
POLL_READ_BYTE (E0CSR, ControlReg);
// Check to see if Setup End or Out Packet received, if so do not put
// any new data on FIFO
if ((!(ControlReg & rbSUEND)) || (!(ControlReg & rbOPRDY)))
{
// Add In Packet ready flag to E0CSR bitmask
ControlReg = rbINPRDY;
if (DataSize >= EP0_PACKET_SIZE)
{
// Break Data into multiple packets if larger than Max Packet
FIFO_Write (FIFO_EP0, EP0_PACKET_SIZE, (BYTE *)DataPtr);
DataPtr += EP0_PACKET_SIZE;
DataSize -= EP0_PACKET_SIZE;
DataSent += EP0_PACKET_SIZE;
}
else
{
// If data is less than Max Packet size or zero
FIFO_Write (FIFO_EP0, DataSize, (BYTE *)DataPtr);
ControlReg |= rbDATAEND;
Ep_Status[0] = EP_IDLE;
}
if (DataSent == Setup.wLength.i)
{
// This case exists when the host requests an even multiple of
// your endpoint zero max packet size, and you need to exit
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -