📄 rf_usb_dongle.h
字号:
#ifndef RF_USB_DONGLE_H
#define RF_USB_DONGLE_H
/** \addtogroup module_rfud RF USB Dongle protocol for CC2511 (rfud)
* \brief Simple radio framework intended to be used between CC2511 USB Dongle and CC2510 external devices.
*
* This is the USB Dongle protocol for CC2511 (rfud) it shold be implemented on the CC2511 USB Dongle.
*
* Please see \ref page_cc2511_rf_library "RF protocol CC2510 / CC2511 (rfru/rfud)"
* for an overview of the entire RF framework.
*
* To implement the rfud module on the CC2511 USB Dongle, do the following:
*
* Call the function \ref rfudInit() to setup the radio, and to give the RF module the packet size (buffer size). \n
* Call the function \ref rfudSetMyAddress() to give the address the CC2511 USB Dongle should use.
* See example below:
* \par Example 1: Setup radio and setting the address.
*
* \code
* rfudInit(100); //init RF framework, use buffers with length of 100 bytes.
* rfudSetMyAddress(0x11, 0x22, 0x33, 0x01); //set CC2511 USB Dongle address, network address = 0x112233, device address = 0x01
* \endcode
*
* Implement the following hooks in the main application:
* \li \ref rfudHookAckPkt()
* \li \ref rfudHookBindRequest()
* \li \ref rfudHookDataPktRequest()
* \li \ref rfudHookRfEvent()
*
* When an RF event occurs, a call will be made to the callback functions / hooks from the RF framework.
* See example below, the \ref module_fifo_buffer "FIFO Buffer (fifo)" is used for buffer handling in the example:
* \par Example 2: Implementing hooks.
*
* \code
* //A DATA_PACKET is received, the RF module needs to know it should send ACK or NACK
* BOOL rfudHookAckPkt(BYTE sourceAddress, BYTE __xdata * ackPktflag) {
* if(sourceAddress == remoteUnitAddress) { return TRUE; } //packet is from the correct remote device, send ACK
* else { return FALSE; } //Packet is from unknown sender, send NACK
* }
*
* //A DATA_REQUEST is received, the RF module needs to know it should send a DATA_PACKET or a NACK
* RF_PACKET __xdata * rfudHookDataPktRequest(BYTE sourceAddress) {
* RF_PACKET __xdata * pPktToSend;
* //if packet is from the right remote unit and we have data ready, send a packet
* if((sourceAddress == remoteUnitAddress) && (there is a data packet ready...)) {
* pPktToSend = (RF_PACKET __xdata *) pointer to packet...;
* if(more than one packet ready...) {
* //more than one packet of data ready, set data pending bit
* pPktToSend->flag |= RF_DATA_PENDING;
* }
* pPktToSend->flag |= RF_ACK_REQUEST;//if a ACK is wanted, set the ACK_REQUEST flag
* return pPktToSend;
* }
* return NULL;
* }
*
* //A BIND_REQUEST is received, the RF module need to know it the main application want to bind to the remote device
* // and if so, what address it should assign.
* BYTE rfudHookBindRequest(BYTE preferredAddress)
* {
* if(application want to bind to the remote device...) {
* //if the remote unit requests a valid address, let it have it. Else give it address 0x02.
* if((preferredAddress > 1) && (preferredAddress != 0xFF)) {
* remoteUnitAddress = preferredAddress; //store the address of the remote device for later use
* return preferredAddress; //return the address to the RF framework
* } else {
* remoteUnitAddress = 0x02; //store the address of the remote device for later use
* return 0x02; //return the address to the RF framework
* }
* }
* else { return 0; } //do not want to bind with the device.
* }
*
* // A RF event ha occurred, this hook notifies the main application
* void rfudHookRfEvent(BYTE rfEvent, BYTE eventData){
* RF_PACKET __xdata * pPktSendt;
* switch (rfEvent) {
* case RFUD_EVENT_DATA_PACKET_RECEIVED :
* if(eventData == remoteUnitAddress) { //if a data packet from remote device, save packet
* fifoFinishedEnqueue(RADIO_TO_USB_BUFFER);
* }
* break;
* case RFUD_EVENT_ACK_RECEIVED :
* //will only receive this callback a when receiving a ACK packet from the correct device after sending a DATA_PACKET
* //Hence this means a packet is successfully sent, removing it from the buffer
* fifoFinishedDequeue(USB_TO_RADIO_BUFFER);
* break;
* case RFUD_EVENT_NACK_RECEIVED :
* //Any code needed when a NACK is received
* break;
* case RFUD_EVENT_ACK_TIMEOUT :
* //Any code needed when a packet is sent and no ACK of NACK is received within the timeout period.
* break;
* }
* }
* \endcode
*
* In addition to handling calls to the hooks, the main application is responsible for supplying the RF framework with a receive buffer.
* A buffer will be needed when starting the RF framework for the firs time and then after each received packet.
* To check if the RF framework need a new buffer, call \ref rfudRxBufferNeeded(). \n
* To provide the rfud module with a receive buffer, call \ref rfudStartReceive(). \n
* Make sure that the buffer supplied to the RF framework is at least as large as specified in \ref rfudInit(), if the buffer is smaller
* the RF module may overwrite other data in the RAM.
* If the main application does not provide the RF framework with an rx buffer the radio will enter IDLE state,
* and no data will be received or transmitted until a buffer is provided. \n
* To ensure that the RF module always have a receive buffer the code example below should be inserted into the main loop.
* See example below, the \ref module_fifo_buffer "FIFO Buffer (fifo)" is used for buffer handling:
* \par Example 3: Providing rfud module with rx buffer.
*
* \code
* if(rfudRxBufferNeeded() && fifoGetFreeSlots(RADIO_TO_USB_BUFFER)) {
* //if radio needs a buffer, and a buffer is ready in the fifo module.
* rfudStartReceive((RF_PACKET __xdata *) fifoStartEnqueue(RADIO_TO_USB_BUFFER)); //give a rx buffer to the rfud module
* }
* \endcode
*
* To turn the radio off, call \ref rfudStopRadio().
*
* Please see the CC2511 Application Examples for implementations of the RF framework.
*
* @{
*/
/// \name Functions
//@{
//Function are described in the rf_usb_dongle.c file and in doxygen documentation.
void rfudInit(BYTE bufferSize);
void rfudSetMyAddress(BYTE networkAddress0, BYTE networkAddress1, BYTE networkAddress2, BYTE deviceAddress);
BOOL rfudRxBufferNeeded(void);
BOOL rfudStartReceive(RF_PACKET __xdata * pRxPacketBuffer);
void rfudStopRadio(void);
//@}
/// \name Callback functions
/// These callBack functions must be defined somewhere in the application.
/// They are called from rfud module when a rf event occurs.
//@{
/**
* \brief Called when a packet is received and application must decide if a ack should be sent or not.
*
* Called each time the radio receives a packet with the \c RF_ACK_REQUEST bit set. \n
* The packet can be found in the rxBuffer supplied to the RF module with \ref rfudStartReceive(). \n
* To make the delay before a ack is sent as short as possible, this function must be
* completed in the shortest time possible. No handling of the packet,
* except what is necessary to decide to ack or not should be done. \n
* As soon as the ack transmission has started, a new callback \ref rfudHookRfEvent()
* will tell the application to start handling the packet received. \n
* If the application returns \c TRUE, a \ref RF_ACK packet is sent. When the ack is sent
* a \ref rfudHookRfEvent() will tell the application to start handle the packet. \n
* If \c FALSE is returned, a \ref RF_NACK packet is sent and \ref rfudHookRfEvent() will NOT be called.
*
*\param[in] pktSourceAddress \n
* The device address of the device that the packet originates from. The network address will be equal to
* the network address on the CC2511 USB Dongle.
*
* \param[in] pAckPktflag \n
* A pointer to the flags in the \ref RF_ACK / \ref RF_NACK packet that will be sent. \n
* The application may set the flag: \ref RF_DATA_PENDING.
*
* \return BOOL \n
* TRUE if application want to send a \ref RF_ACK packet. \n
* FALSE if application want to send a \ref RF_NACK packet.
*/
BOOL rfudHookAckPkt(BYTE pktSourceAddress, BYTE __xdata * pAckPktflag);
/**
* \brief Called when a bind request is received and application must decide if it should be accepted
*
* Called each time the radio receives a \ref RF_BIND_REQUEST packet.
* To make the delay before a reply is sent as short as possible, this function must be
* completed in the shortest time possible.
*
* \param[in] preferredAddress \n
* The address the remote device has requested, if 0x00 the remote device has no preferred address.
* However it is up the dongle to assign addresses and the dongle may assign a different address
* than the one the remote device requests.
*
* \return BYTE \n
* The address the dongle assigns to the remote device. \n
* return 0 if no reply should be sent.(do not want to bind) \n
* Note that node address 0xFF is reserved. It is used during the binding sequence, and can not be assigned.
*/
BYTE rfudHookBindRequest(BYTE preferredAddress);
/**
* \brief Called when a \ref RF_DATA_REQUEST packet is received, application can send a \ref RF_DATA_PACKET if it has one ready.
*
* To make the delay before a reply is sent as short as possible, this function must be
* completed in the shortest time possible.
*
* All address fields in the packet is automaticly set by the RF framework. \n
* The following flags/fields in the \ref RF_PACKET.flag are also automatically set before packet is sent: \n
* \li \ref RF_PACKET_TYPE \n
* \li \ref RF_SEQUENCE_BIT \n
*
* The following flags/fields in the \ref RF_PACKET.flag must be set/cleared by the application before
* returning the pointer to the packet: \n
* \li \ref RF_DATA_PENDING \n
* \li \ref RF_ACK_REQUEST \n
*
* \param[in] sourceAddress \n
* The device address of the remote device that sent the \ref RF_DATA_REQUEST packet.
*
* \return RF_PACKET __xdata * \n
* If application has a packet ready, return a pointer to the packet. \n
* If no packet is ready, return 0.
*/
RF_PACKET __xdata * rfudHookDataPktRequest(BYTE sourceAddress);
/**
* \brief Called from the rfud module to notify the main application each time a RF event occurs.
*
* This function is called from within an interrupt, so it should be short and efficient. \n
* The parameter \c rfEvent will say which event has occurred. The parameter \c eventData hold additional information. \n
* The following rfEvents may occur:
* \li \ref RFUD_EVENT_DATA_PACKET_RECEIVED - A new data packet is received and ready to be read from the rx buffer.
* \c eventData contain the deviceAddress the received data packet originates from.
*
* \li \ref RFUD_EVENT_ACK_RECEIVED - An ACK packet is received.
* \c eventData contain the deviceAddress the received ACK packet originates from.
*
* \li \ref RFUD_EVENT_NACK_RECEIVED - An NACK packet is received.
* \c eventData contain the deviceAddress the received NACK packet originates from.
*
* \li \ref RFUD_EVENT_ACK_TIMEOUT - No ACK/NACK packet is received within the ack timeout period.
* \c eventData contain the deviceAddress the last packet was sent to e.g. the deviceAddress of the device that did not reply.
*
* \param[in] rfEvent \n
* This variable will tell what RF event that has occurred.
* \param[in] eventData \n
* This variable hold additional information about the event.
*/
void rfudHookRfEvent(BYTE rfEvent, BYTE eventData);
//@}
/// \name Module Data
//@{
/// RFUD internal module data, do not modify from outside this module.
typedef struct {
DMA_DESC dmaToRadioDesc; ///< Holds the DMA descriptor that is used to send data to the radio
DMA_DESC dmaFromRadioDesc; ///< Holds the DMA descriptor that is used to read data from the radio
BYTE timer2Cnt; ///< Holds the reset value for timer 2 / mac timer, used to time out replyes
BYTE pNetworkAddress[3]; ///< Holds the current network address
BYTE pTxSequenceBits[RF_SEQUENCE_BYTES]; ///< Holds sequence bit used in outgoing packets
BYTE pRxSequenceBits[RF_SEQUENCE_BYTES]; ///< Holds sequence bit used in incomming packets
RF_PACKET pTxAckPkt; ///< Buffer that holds an ack packet ready to be transmitted.
RF_PACKET __xdata * pRxAckPkt; ///< Buffer that incoming ack packet are stored in.
RF_PACKET __xdata * pRxPacket; ///< Pointer to where incoming (non ack) packets should be stored.
BYTE maxPacketLength; ///< Max packet length that can be received (buffer size).
BYTE lastPktSentTo; ///< Address to witch the last packet was sent, and ack is expected from.
BOOL rxBufferNeeded; ///< If true the radio has a pRxPacket buffer ready, and can receive packets.
BYTE radio_state; ///< The radio state machines current state
} RFUD_DATA;
//@}
/// \name RF EVENT
///Used as a parameter in the \ref rfudHookRfEvent() to tell application what rf event has occurred
//@{
/// A new data packet is received and ready to be read from the rx buffer.
#define RFUD_EVENT_DATA_PACKET_RECEIVED 0x01
/// An ACK packet is received.
#define RFUD_EVENT_ACK_RECEIVED 0x02
/// An NACK packet is received.
#define RFUD_EVENT_NACK_RECEIVED 0x03
/// No ACK/NACK packet i received within the ack timeout period.
#define RFUD_EVENT_ACK_TIMEOUT 0x04
//@}
/// \name radio_state
/// Used by the rf modules internal state machine, do not modify from outside this module.
//@{
/// Radio is in idle.
#define RFUD_STATE_IDLE 0x00
/// The radio is sending a packet, with the \ref RF_ACK_REQUEST bit set.
#define RFUD_STATE_TX_PKT_EXPECT_ACK 0x01
/// The radio is sending a packet, with the \ref RF_ACK_REQUEST bit cleared.
#define RFUD_STATE_TX_PKT_NO_ACK 0x02
/// Sending a \ref RF_ACK packet.
#define RFUD_STATE_TX_ACK 0x03
/// Sending a \ref RF_NACK packet.
#define RFUD_STATE_TX_NACK 0x04
/// Sending a \ref RF_BIND_RESPONSE (dongle).
#define RFUD_STATE_TX_BIND_RESPONSE 0x05
/// The radio is waiting for / receiving a packet.
#define RFUD_STATE_GENERAL_RX 0x06
/// The radio is waiting for / receiving a \ref RF_ACK or \ref RF_NACK packet.
#define RFUD_STATE_RX_ACK 0x07
//@}
#endif //RF_USB_DONGLE_H
///@}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -