📄 main.c
字号:
}
static void PrepareTransmitSegment(uchar index)
/******************************************************************************
Function : static void PrepareTransmitSegment()
Parameters : (uchar index) - current byte index into txReport.
Description: Prepare next segment of feature report for transmission.
******************************************************************************/
{
data uchar cbData;
data uchar i;
if (returnStatus)
{
if (index == 0) // Prepare the whole status report on first call
{
status.u.cmd = CMD_STATUS;
status.u.status.currentCmd = currentCmd.u.cmd;
status.u.status.page = UPSD_xreg.PAGE;
status.u.status.vm = UPSD_xreg.VM;
memcpy(&txReport, &status, CMD_SIZE);
}
return;
}
/*= The Read command is executed very fast, it can be present at this place.
If you use some time-consuming operations
or your routine takes more than 450us, place your code
instead of CMD_ERASE, where can be long services ... =*/
switch (currentCmd.u.cmd)
{
case CMD_READ:
if (index == 0) // First segment needs 0 command byte to indicate data
{
cbData = min(currentCmd.u.rw.nBytes, EP0_SIZE - 1);
index = 1;
txReport.u.cmd = 0;
}
else
{
cbData = min(currentCmd.u.rw.nBytes, EP0_SIZE);
}
ReadBufferFromFlash(
currentCmd.u.rw.address,
txReport.u.buffer + index,
cbData);
currentCmd.u.rw.address += cbData;
if ((currentCmd.u.rw.nBytes -= cbData) == 0)
{
currentCmd.u.cmd = 0; // All done
}
break;
default:
for (i = 0; i < EP0_SIZE; i++)
{
txReport.u.buffer[index + i] = 0;
}
break;
}
}
static void OnReportTransmitted()
/******************************************************************************
Function : static void OnReportTransmitted()
Parameters : none
Description: A complete feature report has been successfully transmitted.
******************************************************************************/
{
if (returnStatus)
{
returnStatus = FALSE;
}
if (currentCmd.u.cmd) // If there's more data to go ...
{
PrepareTransmitSegment(0); // Prepare first segment of next report
}
}
static void OnReportSegmentReceived(uchar cbReceived)
/******************************************************************************
Function : static void OnReportSegmentReceived()
Parameters : (uchar cbReceived)
Description: Called as each EP0_SIZE segment of a report is received.
******************************************************************************/
{
data uchar cbData;
data uchar index;
// If this is data coming in (not a new command) ...
if (rcvReport.u.cmd == 0)
{
// Process the incoming data based on the current command
switch (currentCmd.u.cmd)
{
case CMD_WRITE:
if (rcvIndex == 0) // Skip over command byte in first packet
{
if (cbReceived <= 1)
{
return; // Error
}
cbData = min(currentCmd.u.rw.nBytes, cbReceived - 1);
index = rcvIndex + 1;
}
else
{
cbData = min(currentCmd.u.rw.nBytes, cbReceived);
index = rcvIndex;
}
WriteBufferToFlash(
currentCmd.u.rw.flash,
currentCmd.u.rw.address,
rcvReport.u.buffer + index,
cbData);
currentCmd.u.rw.address += cbData;
currentCmd.u.rw.nBytes -= cbData;
if (currentCmd.u.rw.nBytes == 0)
{
currentCmd.u.cmd = 0; // All done
if (currentCmd.u.rw.flash == PRIMARY_FLASH)
{
flash_reset();
}
else
{
flash_boot_reset();
}
}
break;
default:
break;
}
}
}
static void OnReportReceived()
/******************************************************************************
Function : static void OnReportReceived()
Parameters : none
Description: Called after all segments of a report have been received.
******************************************************************************/
{
// Here you can have SRC routine long as you want ..
if (rcvReport.u.cmd) // If this is a new command coming in ...
{
if (rcvReport.u.cmd == CMD_STATUS)
{
// For CMD_GET_STATUS, don't overwrite current cmd we're working on
returnStatus = TRUE;
}
else
{
// Copy into 'current command' global variable
memcpy(currentCmd.u.buffer, rcvReport.u.buffer, sizeof(rcvReport));
memset((uchar*)&status, 0, sizeof(status));
// g_debug1 = currentCmd.u.cmd;
}
// Some commands are processed at this point
switch (rcvReport.u.cmd)
{
case CMD_RESET:
WDKEY=0; // watchdog will trigger reset in a second
currentCmd.u.cmd = 0;
break;
case CMD_SET_PAGE:
UPSD_xreg.PAGE = rcvReport.u.setRegs.page;
currentCmd.u.cmd = 0;
break;
case CMD_SET_VM:
UPSD_xreg.VM = rcvReport.u.setRegs.vm;
currentCmd.u.cmd = 0;
break;
case CMD_SET_REGS:
UPSD_xreg.PAGE = rcvReport.u.setRegs.page;
UPSD_xreg.VM = rcvReport.u.setRegs.vm;
currentCmd.u.cmd = 0;
break;
default:
// Prepare first segment of any response to go back to host
PrepareTransmitSegment(0);
break;
}
}
}
static BOOL HandleReport()
/******************************************************************************
Function : static BOOL HandleReport()
Parameters : none
Description: Handles HID Get_Report and Set_Report SETUP packets.
Returns TRUE if the SETUP packet is a Get_Report or Set_Report
request; else returns FALSE.
******************************************************************************/
{
// If it is a HID Set_Report request...
if ((setupPacket.bmRequestType == CLASS_INTERFACE_TO_DEVICE)
&& (setupPacket.bRequest == HID_SET_REPORT))
{
rcvIndex = 0; // Prepare to receive report
return TRUE;
}
// Else if it is a HID Get_Report request ...
else if ((setupPacket.bmRequestType == CLASS_INTERFACE_TO_HOST)
&& (setupPacket.bRequest == HID_GET_REPORT))
{
// Transmit first segment of response (should be already prepared)
UCON0 &= ~uTSEQ0;
TransmitDataEP0(txReport.u.buffer, EP0_SIZE);
txIndex = EP0_SIZE; // Prepare next segment while first one is going out
PrepareTransmitSegment(txIndex);
return TRUE;
}
return FALSE;
}
bdata char USB_ISR_FLAGS = 0;
sbit GoOnResume = USB_ISR_FLAGS ^ 0;
sbit GoOnSuspend = USB_ISR_FLAGS ^ 7;
static void OnUSBSuspend()
/******************************************************************************
Function : static void OnUSBSuspend()
Parameters : none
Description: service routine for USB Suspend event
******************************************************************************/
{
data char bie,biea;
printfLCD("\n* SUSPEND MODE *\n");
printfLCD("\rCPU in Idle mode");
bie = IE;
biea = IEA;
IEA = 1; // disable all INTs except USB
IE = 128; // disable all INTs except USB
SUSPND = 1; //Enter suspend mode for uPSD
GoOnSuspend = 0; //clear global Suspend flag
// entering SUSPEND or setting SUSPNDF causes to top the clocks to the USB
// and causes the USB module to enter Suspend Mode.
UIEN |= uRESUMIE; // enable resume INT
PCON |= 1; //Enter Idle mode
// here the uPSD sleeps and waits for the next INT
SUSPND = 0; //clear the flag
IE = bie;
IEA = biea;
UIEN &= ~uRESUMIE; // disable resume INT
RESUMF = 0; //clear the flag
printfLCD("\r \n"); //clear display
printfLCD("\r \r"); //clear display
printfLCD("\r*USB DEMO V.2.1*\n"); //dislay the string
}
void main() using 0
/******************************************************************************
Function : void main()
Parameters : none
Description: Main routine, start of your program
******************************************************************************/
{
data char c;
// Initialize globals
// The following two lines can be deleted if no USB Disconnect feature is implemented
#ifdef DisconnectOnDemand
UPSD_xreg.DIRECTION_B |= 0x03; // set PSD-PB0,1 DDR high
UPSD_xreg.DATAOUT_B = 0x03; // disable LED2, low level active /01/02
#endif
memset((uchar*)&status, 0, sizeof(status));
memset((uchar*)¤tCmd, 0, sizeof(currentCmd));
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -