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

📄 rf_usb_dongle.c

📁 reference about wireless design which is helpful to everyone
💻 C
📖 第 1 页 / 共 2 页
字号:
/// \addtogroup module_rfud
/// @{
#include "cc2511_app_ex_lib_headers.h"


static BYTE __xdata AckPkt[10];//must be 10 to hold CRC
static RFUD_DATA __xdata rfudData;///internal module data

////internal functions, do not call from outside of this file
static rfudResetRadio(void);
static rfudSendDataPacket(RF_PACKET __xdata * pTxPacket);
static BYTE handleDataPacket(void);


/**
 * \brief Must be called once before any other functions in the rf_usb_dongle module.
 *
 * Initiates radio and everything associated with it. Does not start RX or TX.
 *
 * \note This function calculates the timeout settings for the mac timer based on the
 * CLOCKON.TICKSPD setting. Do not change CLOCKON.TICKSPD after this function has been called
 *
 * \param[in]  bufferSize \n
 * Set the size of the buffers that will later be given to the radio with the \ref rfudStartReceive() function.
 * The radio will use this number to make sure that it does not write outside the buffers.
 */
void rfudInit(BYTE bufferSize)
{
   BYTE i, temp;
   //set rx ack packet Ptr
   rfudData.pRxAckPkt = (RF_PACKET __xdata *) AckPkt;
   //setup radio, and calibrate
   halRfConfig(2433000);
   //calibrate when going to RX/TX
   MCSM0 = 0x10;
   rfudData.maxPacketLength = bufferSize - 3;
   PKTLEN = rfudData.maxPacketLength;
   MCSM1 = 0x00;
   rfudData.rxBufferNeeded = TRUE;

   rfudData.pTxAckPkt.length = 6;//length of tx ack packet

   for(i = 0; i < RF_SEQUENCE_BYTES; i++)
   {
      rfudData.pTxSequenceBits[i] = 0;
      rfudData.pRxSequenceBits[i] = 0;
   }
   //setup all fields in DMA descriptor for RX that newer change
   SET_WORD(rfudData.dmaFromRadioDesc.SRCADDRH, rfudData.dmaFromRadioDesc.SRCADDRL, &X_RFD);
   //SET_WORD(rfudData.dmaFromRadioDesc.DESTADDRH, rfudData.dmaFromRadioDesc.DESTADDRL, pRxBuffer);
   rfudData.dmaFromRadioDesc.VLEN       = VLEN_1_P_VALOFFIRST_P_2;
   SET_WORD(rfudData.dmaFromRadioDesc.LENH, rfudData.dmaFromRadioDesc.LENL, bufferSize);
   rfudData.dmaFromRadioDesc.WORDSIZE   = WORDSIZE_BYTE;
   rfudData.dmaFromRadioDesc.TMODE      = TMODE_SINGLE;
   rfudData.dmaFromRadioDesc.TRIG       = DMATRIG_RADIO;
   rfudData.dmaFromRadioDesc.DESTINC    = DESTINC_1;
   rfudData.dmaFromRadioDesc.SRCINC     = SRCINC_0;
   rfudData.dmaFromRadioDesc.IRQMASK    = IRQMASK_DISABLE;
   rfudData.dmaFromRadioDesc.M8         = M8_USE_8_BITS;
   rfudData.dmaFromRadioDesc.PRIORITY   = PRI_GUARANTEED;

   //setup all fields in DMA descriptor for TX that newer change
   SET_WORD(rfudData.dmaToRadioDesc.DESTADDRH, rfudData.dmaToRadioDesc.DESTADDRL, &X_RFD);
   rfudData.dmaToRadioDesc.VLEN       = VLEN_1_P_VALOFFIRST;
   SET_WORD(rfudData.dmaToRadioDesc.LENH, rfudData.dmaToRadioDesc.LENL, 256);
   rfudData.dmaToRadioDesc.WORDSIZE   = WORDSIZE_BYTE;
   rfudData.dmaToRadioDesc.TMODE      = TMODE_SINGLE;
   rfudData.dmaToRadioDesc.TRIG       = DMATRIG_RADIO;
   rfudData.dmaToRadioDesc.DESTINC    = DESTINC_0;
   rfudData.dmaToRadioDesc.SRCINC     = SRCINC_1;
   rfudData.dmaToRadioDesc.IRQMASK    = IRQMASK_DISABLE;
   rfudData.dmaToRadioDesc.M8         = M8_USE_8_BITS;
   rfudData.dmaToRadioDesc.PRIORITY   = PRI_GUARANTEED;

   rfudData.radio_state = RFUD_STATE_IDLE;
   RFIF &= ~(IRQ_DONE | IRQ_TXUNF | IRQ_RXOVF);
   RFIM |= (IRQ_DONE | IRQ_TXUNF | IRQ_RXOVF);
   INT_ENABLE(INUM_RF, INT_ON);

   // setup timer 2, used for ACK timeout
   halSetTimer2Period(3000, &temp, &i);
   rfudData.timer2Cnt = temp;
   T2CT = 0;
   T2CTL = 0x10;
   INT_ENABLE(INUM_T2, INT_ON);
   INT_GLOBAL_ENABLE(INT_ON);
}

/**
 * \brief Set the device address and network address on the rf_usb_dongle unit.
 *
 * Must be called once, after calling the \ref rfudInit().
 * Can be called later if the dongle want to change its address.
 * Normally the dongle will have device address 0x01, but this is up to the application.
 * The address can be seen as a single 32 bit address, however only devices with identical
 * network address can communicate with each other.
 *
 * \param[in]  networkAddress0 \n
 * Most significant byte in the network address
 *
 * \param[in]  networkAddress1 \n
 * Second most significant byte in the network address
 *
 * \param[in]  networkAddress2 \n
 * Least significant byte in the network address
 *
 * \param[in]  deviceAddress \n
 * Device address.
 */
void rfudSetMyAddress(BYTE networkAddress0, BYTE networkAddress1, BYTE networkAddress2, BYTE deviceAddress)
{
   rfudData.pNetworkAddress[0] = networkAddress0;
   rfudData.pNetworkAddress[1] = networkAddress1;
   rfudData.pNetworkAddress[2] = networkAddress2;

   //setup ack packet
   rfudData.pTxAckPkt.sourceAddress = deviceAddress; //source address
   rfudData.pTxAckPkt.networkAddress[0] = networkAddress0; //network(2) address
   rfudData.pTxAckPkt.networkAddress[1] = networkAddress1; //network(1) address

   rfudData.pTxAckPkt.networkAddress[2] = networkAddress2; //network(0) address

   //setup radio hardware address filter
   ADDR = deviceAddress;
   PKTCTRL1 |= 0x03;//Address check, 0 (0x00) and 255 (0xFF) broadcast
}


/**
 * \brief Used to check if the radio have a RX buffer, or if one need to be supplied.
 *
 * It is the applications responsibility to supply the rfud module with RX buffers when needed.
 * A RX buffer will be needed initially when first starting the radio, and then after each received packet.
 * If the rfud module does not have a RX buffer, the radio will be put in IDLE until one
 * is supplied.
 * This function should be included in the Main loop to regularly check if a buffer is needed.
 * If a buffer is needed, use the \ref rfudStartReceive() function to supply the rfud module
 * with a RX buffer.
 *
 * \note The buffer supplied must be at least as big as specified in the \ref rfudInit() bufferSize.
 * \return  BOOL \n
 * If \c TRUE the rfud module does not have a RX buffer, one must be supplied. \n
 * If \c FALSE the rfud module already have a RX buffer.
 */
BOOL rfudRxBufferNeeded(void)
{
   return (rfudData.rxBufferNeeded);
}


/**
 * \brief Gives the rfud module a RX buffer, and put the radio in RX.
 *
 * This function should be called when \ref rfudRxBufferNeeded() indicates that a new
 * RX buffer is needed by the radio.
 * If the rfud module does not have a RX buffer, the radio will be put in IDLE until one
 * is supplied.
 * This function will not accept a new buffer if the rfud module already have one, (will return FALSE).
 * If for some reason the buffer currently in use by the rfud module should not be used
 * any longer, call \ref rfudStopRadio(). The old buffer will then be discarded and a new
 * buffer can then be given to the rfud module with this function.
 *
 * \note The buffer supplied must be at least as big as specified in the \ref rfudInit() bufferSize.
 *
 * \param[in]  pRxPacketBuffer \n
 * A pointer to the RX buffer.
 *
 * \return  BOOL \n
 * If the rfud module already have a RX buffer this function will return FALSE. And the
 * rfud module will continue to use the old buffer. \n
 * If the rfud module did not have a RX buffer, this function will return TRUE, and the
 * supplied buffer will be used.
 */
BOOL rfudStartReceive(RF_PACKET __xdata * pRxPacketBuffer)
{
   //if we already have a RX buffer, dont change it
   if(!(rfudData.rxBufferNeeded)) return FALSE;

   INT_ENABLE(INUM_RF, INT_OFF);//neccessary because radio state change is done both here, in and in RF ISR
   pRxPacketBuffer->length = 0;
   rfudData.pRxPacket = pRxPacketBuffer;
   rfudData.rxBufferNeeded = FALSE;
   if(rfudData.radio_state == RFUD_STATE_IDLE) {
      rfudResetRadio();
   }
   INT_ENABLE(INUM_RF, INT_ON);

   return TRUE;
}


/**
 * \brief Used to put the radio in IDLE, and discard the RX buffer currently in use.
 *
 * This function is used when the application want to stop the radio, for example before
 * entering USB suspend.
 * Any ongoing transmissions, both RX and TX will be aborted. The current RX buffer
 * will be discarded, so a new one must be given using \ref rfudStartReceive() to start the
 * radio again.
 */
void rfudStopRadio(void)
{
   //set radio to idle
   SIDLE();
   RFIF = 0;
   INT_SETFLAG(INUM_RF, INT_CLR);

   STOP_RADIO_TIMEOUT();

   //set radio state
   rfudData.radio_state = RFUD_STATE_IDLE;

   //clear RX buffer
   rfudData.rxBufferNeeded = TRUE;

   //Abort any DMA transfers
   DMA_ABORT_CHANNEL(0);
}

//internal function, do not call from outside of this file
static rfudResetRadio(void)
{

   SIDLE();
   RFIF = 0;
   INT_SETFLAG(INUM_RF, INT_CLR);

   //set radio state
   if(rfudData.rxBufferNeeded) { rfudData.radio_state = RFUD_STATE_IDLE; }
   else {
      rfudData.radio_state = RFUD_STATE_GENERAL_RX;
      PKTLEN = rfudData.maxPacketLength;//setup max packet length
      //Setup DMA descriptor for reception of the packet
      rfudData.pRxPacket->length = 0;
      SET_WORD(rfudData.dmaFromRadioDesc.DESTADDRH, rfudData.dmaFromRadioDesc.DESTADDRL, (BYTE __xdata *) rfudData.pRxPacket);
      RF_START_DMA_RX(&rfudData.dmaFromRadioDesc);
      SRX();
   }
}

//internal function, do not call from outside of this file
static rfudSendDataPacket(RF_PACKET __xdata * pTxPacket)
{
   SIDLE();
   //copy source and network address to the packet
   pTxPacket->sourceAddress = rfudData.pTxAckPkt.sourceAddress;
   pTxPacket->networkAddress[0] = rfudData.pTxAckPkt.networkAddress[0];
   pTxPacket->networkAddress[1] = rfudData.pTxAckPkt.networkAddress[1];
   pTxPacket->networkAddress[2] = rfudData.pTxAckPkt.networkAddress[2];

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -