📄 rf_usb_dongle.c
字号:
/// \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 + -