📄 main.c
字号:
#include "cc2511_app_ex_lib_headers.h"
#include "cc2511_usb_library_headers.h"
#include "usb_cdc.h"
#define USB_TO_RADIO_BUFFER 0
#define RADIO_TO_USB_BUFFER 1
#define USB_MAX_PACKET_SIZE 64
#define DONGLE_ADDRESS 0x01
#define NETWORK_ADDRESS0 0x12
#define NETWORK_ADDRESS1 0x13
#define NETWORK_ADDRESS2 0x14
#define USB_RX_TIMEOUT 10
#define BUFFER_SIZE 137
#define MAX_DATA_BYTES ((BUFFER_SIZE - HEADER_LENGTH) - CRC_LENGTH)
#define MAX_LENGTH_BYTE (BUFFER_SIZE - 3)
typedef struct {
DWORD dteRate;
BYTE charFormat;
BYTE parityType;
BYTE dataBits;
} CDC_LINE_CODING_STRUCTURE;
void uartTimeoutCallBack(void);
RF_PACKET __xdata * pTxBuf;
BOOL __xdata uartTxPacketTimeout;
BYTE __xdata uartTxPacketTimeoutIndex;
BYTE remoteUnitAddress;
BYTE __data uartTxBytesLeft;
CDC_LINE_CODING_STRUCTURE lineCoding;
void main( void )
{
RF_PACKET __xdata * pTempPacketBuffer;
BYTE __xdata * pBuf;
BYTE length, temp;
BYTE usbPacketPartsSent;
BYTE alreadySent;
CLKCON = 0x80; // Enable XOSC
while ((SLEEP & 0x40) == 0); // Wait until XOSC/USB clock has stabalized
fifoInit();
t4mgrInit(1000);
rfudInit(BUFFER_SIZE);
rfudSetMyAddress(NETWORK_ADDRESS0, NETWORK_ADDRESS1, NETWORK_ADDRESS2, (BYTE) DONGLE_ADDRESS);
//set default line coding.
lineCoding.dteRate = 115200;
lineCoding.charFormat = CDC_CHAR_FORMAT_2_STOP_BIT;
lineCoding.parityType = CDC_PARITY_TYPE_NONE;
lineCoding.dataBits = 8;
//when filling the buffer from the USB, the length byte is used, hence we must set it
//to default (HEADER_LENGTH - 1) in all the buffers.
while(pTempPacketBuffer = (RF_PACKET __xdata *) fifoStartEnqueue(USB_TO_RADIO_BUFFER)) {
pTempPacketBuffer->length = (HEADER_LENGTH - 1);
fifoFinishedEnqueue(USB_TO_RADIO_BUFFER);
}
//dequeue all the packets again.
while(fifoGetUsedSlots(USB_TO_RADIO_BUFFER)) { fifoFinishedDequeue(USB_TO_RADIO_BUFFER); }
uartTxPacketTimeoutIndex = t4mgrSetupCallback(T4MGR_SUSPENDED_CALLBACK, uartTimeoutCallBack);
// Initialize the USB framework
usbfwInit();
// Initialize the USB interrupt handler with bit mask containing all processed USBIRQ events
usbirqInit(0xFFFF);
// Enable interrupts
INT_GLOBAL_ENABLE(TRUE);
while(1){
//USB related
// Handle reset signaling on the bus
if (USBIRQ_GET_EVENT_MASK() & USBIRQ_EVENT_RESET) {
USBIRQ_CLEAR_EVENTS(0xFFFF);
usbfwResetHandler();
USBPOW = USBPOW_SUSPEND_EN;
}
// Handle packets on EP0
if (USBIRQ_GET_EVENT_MASK() & USBIRQ_EVENT_SETUP) {
USBIRQ_CLEAR_EVENTS(USBIRQ_EVENT_SETUP);
usbfwSetupHandler();
}
// Handle USB suspend
if (USBIRQ_GET_EVENT_MASK() & USBIRQ_EVENT_SUSPEND) {
USBIRQ_CLEAR_EVENTS(USBIRQ_EVENT_SUSPEND);// Clear USB suspend interrupt
rfudStopRadio(); // turn off the radio
usbsuspEnter();// calling this function will take the chip into PM1 until a USB resume is deteceted.
USBIRQ_CLEAR_EVENTS(USBIRQ_EVENT_RESUME); // Clear USB resume interrupt.
}
//USB ready to accept new IN packet and there is data in the RADIO_TO_USB_BUFFER buffer.
INT_GLOBAL_ENABLE(FALSE);
USBFW_SELECT_ENDPOINT(4);
if ((!(USBCSIL & USBCSIL_INPKT_RDY)) && (fifoGetUsedSlots(RADIO_TO_USB_BUFFER))) {
INT_GLOBAL_ENABLE(TRUE);
alreadySent = usbPacketPartsSent * USB_MAX_PACKET_SIZE;
pTempPacketBuffer = (RF_PACKET __xdata *) fifoStartDequeue(RADIO_TO_USB_BUFFER);
length = pTempPacketBuffer->length - (HEADER_LENGTH - 1);
length -= alreadySent; //if part of packet is already sent
//must be "length >=" to send a empty packet last if length is equeal to (x * 64)
if(length >= USB_MAX_PACKET_SIZE) {
length = USB_MAX_PACKET_SIZE;
usbPacketPartsSent++;
}else {usbPacketPartsSent = 0; } //last part, reset usbPacketPartsSent
usbfwWriteFifo(&USBF4, length, &pTempPacketBuffer->data[alreadySent]);
USBCSIL |= USBCSIL_INPKT_RDY;
//if entire buffer is transferred to USB fifo
if(usbPacketPartsSent == 0)
{
pBuf[0] = 0;//set size of packet in buffer = 0
fifoFinishedDequeue(RADIO_TO_USB_BUFFER);
}
}
INT_GLOBAL_ENABLE(TRUE);
//USB has a OUT packet and there is room in the USB_TO_RADIO_BUFFER buffer
if((USBIRQ_GET_EVENT_MASK() & USBIRQ_EVENT_EP4OUT) && (fifoGetFreeSlots(USB_TO_RADIO_BUFFER))) {
INT_GLOBAL_ENABLE(FALSE);
USBFW_SELECT_ENDPOINT(4);
//if new packet is ready in USB FIFO
if ((USBCSOL & USBCSOL_OUTPKT_RDY)) {
//get length of packet
length = USBCNTL;
INT_GLOBAL_ENABLE(TRUE);
//while more data ready and fifo is not full
while((length) && (pTempPacketBuffer = (RF_PACKET __xdata *) fifoStartEnqueue(USB_TO_RADIO_BUFFER)))
{
temp = MAX_LENGTH_BYTE - pTempPacketBuffer->length; //find how many bytes there is room for
//If starting on a new buffer slot, start timer4mgr timeout
if(temp == (MAX_LENGTH_BYTE - (HEADER_LENGTH - 1))){
t4mgrModifyCallback(uartTxPacketTimeoutIndex, USB_RX_TIMEOUT, 0);
}
//If not enough room in the current buffer to store all the new data
//or just enough room, but the buffer will be completely full.
if(length >= temp)
{
usbfwReadFifo(&USBF4, temp, (BYTE __xdata *) &pTempPacketBuffer->data[pTempPacketBuffer->length - (HEADER_LENGTH - 1)]);
pTempPacketBuffer->length += temp; //update length byte of buffer
fifoFinishedEnqueue(USB_TO_RADIO_BUFFER); //Buffer is full, finish enqueue
t4mgrModifyCallback(uartTxPacketTimeoutIndex, T4MGR_SUSPENDED_CALLBACK, 0);// stop timer4Callback
uartTxPacketTimeout = FALSE;
//if entire packet is read from USB fifo, clear pkt ready flag.
length -= temp;
if(length == 0){
INT_GLOBAL_ENABLE(FALSE);
USBFW_SELECT_ENDPOINT(4);
USBCSOL &= ~USBCSOL_OUTPKT_RDY; //clear pkt ready flag.
INT_GLOBAL_ENABLE(TRUE);
}
}
//if enough room in current buffer
else
{
usbfwReadFifo(&USBF4, length, (BYTE __xdata *) &pTempPacketBuffer->data[pTempPacketBuffer->length - (HEADER_LENGTH - 1)]);
pTempPacketBuffer->length += length; //update length byte of buffer
length = 0;
INT_GLOBAL_ENABLE(FALSE);
USBFW_SELECT_ENDPOINT(4);
USBCSOL &= ~USBCSOL_OUTPKT_RDY; //clear pkt ready flag.
INT_GLOBAL_ENABLE(TRUE);
}
}
}
INT_GLOBAL_ENABLE(TRUE);
}
//Radio related
//Radio does not have a RX buffer..
if(rfudRxBufferNeeded()) {
INT_GLOBAL_ENABLE(FALSE);
if(fifoGetFreeSlots(RADIO_TO_USB_BUFFER))//..and we have a buffer ready.
{
//Give the rfud module a RX buffer so the radio can go to RX.
rfudStartReceive((RF_PACKET __xdata *) fifoStartEnqueue(RADIO_TO_USB_BUFFER));
}
INT_GLOBAL_ENABLE(TRUE);
}
//Application related
//timeout to avoid to high latency on data sent.
if(uartTxPacketTimeout) {
INT_GLOBAL_ENABLE(FALSE);
fifoFinishedEnqueue(USB_TO_RADIO_BUFFER);
uartTxPacketTimeout = FALSE;
INT_GLOBAL_ENABLE(TRUE);
}
}
}
// ****************************************************************************************
// Callback function called from timer4 manager
// ****************************************************************************************
void uartTimeoutCallBack(void)
{
t4mgrModifyCallback(uartTxPacketTimeoutIndex, T4MGR_SUSPENDED_CALLBACK, 0);
uartTxPacketTimeout = TRUE;
}
// ****************************************************************************************
// All Hooks and functions required by the RF library.
// ****************************************************************************************
BOOL rfudHookAckPkt(BYTE sourceAddress, BYTE __xdata * ackPktflag){
//if packet is from unknown sender, send NACK
if(sourceAddress != remoteUnitAddress) { return FALSE; }
//if we have data ready, set RF_DATA_PENDING flag
if(fifoGetUsedSlots(USB_TO_RADIO_BUFFER)) {
*ackPktflag |= RF_DATA_PENDING;
}
//ack only if 2 or more slots are ready, to be able to go RX imidatly after sending ACK
if(fifoGetFreeSlots(RADIO_TO_USB_BUFFER) > 1){ return TRUE; }
else { return FALSE; }
}
RF_PACKET __xdata * rfudHookDataPktRequest(BYTE sourceAddress) {
BYTE slotsReady;
RF_PACKET __xdata * pPktToSend;
//if packet is from the right remote unit and we have data ready, send a packet
if((sourceAddress == remoteUnitAddress) && (slotsReady = fifoGetUsedSlots(USB_TO_RADIO_BUFFER)))
{
pPktToSend = (RF_PACKET __xdata *) fifoStartDequeue(USB_TO_RADIO_BUFFER);
if(slotsReady > 1) { pPktToSend->flag |= RF_DATA_PENDING; }//more than one packet of data ready, set data pending bit
pPktToSend->flag |= RF_ACK_REQUEST;
return pPktToSend;
}
return NULL;
}
BYTE rfudHookBindRequest(BYTE preferredAddress)
{
//Always accept bind requests. If the remote unit requests a sensible address, let it have it. Else give it address 0x02.
if((preferredAddress > 1) && (preferredAddress != 0xFF))
{
remoteUnitAddress = preferredAddress;
return preferredAddress;
}
else {
remoteUnitAddress = 0x02;
return 0x02;
}
}
void rfudHookRfEvent(BYTE rfEvent, BYTE eventData){
RF_PACKET __xdata * pPktSendt;
switch (rfEvent)
{
case RFUD_EVENT_DATA_PACKET_RECEIVED :
//if a data packet from remote device, save packet
if(eventData == remoteUnitAddress)
{
INT_GLOBAL_ENABLE(FALSE);
fifoFinishedEnqueue(RADIO_TO_USB_BUFFER);
INT_GLOBAL_ENABLE(TRUE);
}
break;
case RFUD_EVENT_ACK_RECEIVED :
//reset the length byte to indicate empty packet
pPktSendt = (RF_PACKET __xdata *) fifoStartDequeue(USB_TO_RADIO_BUFFER);
pPktSendt->length = (HEADER_LENGTH - 1);
//a packet successfully sent
INT_GLOBAL_ENABLE(FALSE);
fifoFinishedDequeue(USB_TO_RADIO_BUFFER);
INT_GLOBAL_ENABLE(TRUE);
break;
case RFUD_EVENT_NACK_RECEIVED :
//dont care
break;
case RFUD_EVENT_ACK_TIMEOUT :
//dont care
break;
}
}
// ****************************************************************************************
// All Hooks and functions required by the USB library.
// ****************************************************************************************
// **************** Process USB class requests with OUT data phase ************************
void usbcrHookProcessOut(void) {
// Process USB class requests with OUT data phase, or stall endpoint 0 when unsupported
//usbfwData.ep0Status = EP_STALL;
if (usbSetupHeader.request == CDC_SET_CONTROL_LINE_STATE) {
} else if(usbSetupHeader.request == CDC_SET_LINE_CODING) {
//TODO implement
if(usbfwData.ep0Status == EP_IDLE)
{
usbSetupData.pBuffer = (BYTE *) &lineCoding;
usbfwData.ep0Status = EP_RX;
}
else if(usbfwData.ep0Status == EP_RX) { }
}
// Unknown request?
else {
usbfwData.ep0Status = EP_STALL;
//usbfwData.ep0Status = EP_TX;
}
}
// **************** Process USB class requests with IN data phase *************************
void usbcrHookProcessIn(void) {
// Process USB class requests with IN data phase, or stall endpoint 0 when unsupported
if (usbSetupHeader.request == CDC_GET_LINE_CODING) {
// First the endpoint status is EP_IDLE...
if (usbfwData.ep0Status == EP_IDLE) {
usbSetupData.pBuffer = (BYTE *) &lineCoding;
usbSetupData.bytesLeft = 7;
usbfwData.ep0Status = EP_TX;
// Then the endpoint status is EP_TX (remember: we did that here when setting up the buffer)
} else if (usbfwData.ep0Status == EP_TX) {
// usbfwData.ep0Status is automatically reset to EP_IDLE when returning to usbfwSetupHandler()
}
// Unknown request?
} else {
//usbData.ep0Status = EP_STALL;
usbfwData.ep0Status = EP_TX;
}
}
// ******************************** Unsupported USB hooks ********************************
void usbvrHookProcessOut(void) {usbfwData.ep0Status = EP_STALL; }
void usbvrHookProcessIn(void) {usbfwData.ep0Status = EP_STALL; }
// ************************ unsupported/unhandled standard requests **********************
void usbsrHookSetDescriptor(void) { usbfwData.ep0Status = EP_STALL; }
void usbsrHookSynchFrame(void) { usbfwData.ep0Status = EP_STALL; }
void usbsrHookClearFeature(void) { usbfwData.ep0Status = EP_STALL; }
void usbsrHookSetFeature(void) { usbfwData.ep0Status = EP_STALL; }
void usbsrHookModifyGetStatus(BYTE recipient, BYTE index, WORD __xdata *pStatus) { }
// ************************ USB standard request event processing *************************
void usbsrHookProcessEvent(BYTE event, UINT8 index) {
// Process relevant events, one at a time.
switch (event) {
case USBSR_EVENT_CONFIGURATION_CHANGING : //(the device configuration is about to change)
break;
case USBSR_EVENT_CONFIGURATION_CHANGED :// (the device configuration has changed)
break;
case USBSR_EVENT_INTERFACE_CHANGING ://(the alternate setting of the given interface is about to change)
break;
case USBSR_EVENT_INTERFACE_CHANGED : //(the alternate setting of the given interface has changed)
break;
case USBSR_EVENT_REMOTE_WAKEUP_ENABLED ://(remote wakeup has been enabled by the host)
break;
case USBSR_EVENT_REMOTE_WAKEUP_DISABLED ://(remote wakeup has been disabled by the host)
break;
case USBSR_EVENT_EPIN_STALL_CLEARED ://(the given IN endpoint's stall condition has been cleared the host)
break;
case USBSR_EVENT_EPIN_STALL_SET ://(the given IN endpoint has been stalled by the host)
break;
case USBSR_EVENT_EPOUT_STALL_CLEARED ://(the given OUT endpoint's stall condition has been cleared the host)
break;
case USBSR_EVENT_EPOUT_STALL_SET ://(the given OUT endpoint has been stalled by the PC)
break;
}
}
// ************************ USB interrupt event processing ********************************
void usbirqHookProcessEvents(void) {
// Handle events that require immediate processing here
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -