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

📄 main.c

📁 reference about wireless design which is helpful to everyone
💻 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 + -