📄 rf_remote_unit.c
字号:
}
/**
* \brief Returns the network address of this device.
*
* Use \ref rfruGetMyDeviceAddress() to find out if a valid address is assigned to this device.
*
* \return UINT32 \n
* The network address of this device is found in the 24 least significant bits.
*/
UINT32 rfruGetNetworkAddress(void)
{
UINT32 nAddr;
nAddr = rfruData.pNetworkAddress[0];
nAddr <<= 8;
nAddr |= rfruData.pNetworkAddress[1];
nAddr <<= 8;
nAddr |= rfruData.pNetworkAddress[2];
return nAddr;
}
/**
* \brief Returns a pointer to the buffer where received RF_ACK 7 RF_NACK packets are stored.
*
* If the application need to check anything in the received \ref RF_ACK / \ref RF_NACK packets,
* for instance want to read the RSSI value (Received Signal Strength Indicator),
* this function will return a pointer to where they are stored.
*
* \return RF_PACKET \n
* A pointer to where received RF_ACK /RF_NACK packets are stored
*/
RF_PACKET __xdata * rfruGetpRxAckPkt()
{
return rfruData.pRxAckPkt;
}
//internal function, do not call from outside of this file
static void rfruSBReq(void)
{
//use the RxAckPkt buffer, a little slower than having a designated buffer. But this function is seldom used.
rfruData.pRxAckPkt->length = 6;
rfruData.pRxAckPkt->destAddress = 0xFF;
rfruData.pRxAckPkt->sourceAddress = rfruData.pTxAckPkt.sourceAddress;
rfruData.pRxAckPkt->networkAddress[0] = 0xFF;
rfruData.pRxAckPkt->networkAddress[1] = 0xFF;
rfruData.pRxAckPkt->networkAddress[2] = 0xFF;
rfruData.pRxAckPkt->flag = RF_BIND_REQUEST | RF_ACK_REQUEST;
rfruData.radio_state = RFRU_STATE_TX_BIND_REQUEST;
DMA_ABORT_CHANNEL(0);
//Setup DMA descriptor for reception of the reply packet
SET_WORD(rfruData.dmaFromRadioDesc.DESTADDRH, rfruData.dmaFromRadioDesc.DESTADDRL, (BYTE __xdata *) rfruData.pRxAckPkt);
//setup DMA for TX
SET_WORD(rfruData.dmaToRadioDesc.SRCADDRH, rfruData.dmaToRadioDesc.SRCADDRL, (BYTE __xdata *) rfruData.pRxAckPkt);
RF_START_DMA_TX(&rfruData.dmaToRadioDesc);
STX(); //start TX
}
//internal function, do not call from outside of this file
static void rfruHandleUnwantedPacket(void)
{
if(rfruData.rfTimeout) {
rfruHandleTimeout();
} else {
RF_START_DMA_RX(&rfruData.dmaFromRadioDesc);
SRX();
}
}
//internal function, do not call from outside of this file
static void rfruHandleTimeout(void)
{
switch (rfruData.radio_state)
{
case (RFRU_STATE_RX_ACK) :
rfruStopRadio();
rfruHookRfEvent(RFRU_EVENT_ACK_TIMEOUT, 0);
break;
case (RFRU_STATE_RX_DATA_PACKET) :
rfruStopRadio();
rfruHookRfEvent(RFRU_EVENT_DATA_PACKET_REQUEST_TIMEOUT, 0);
break;
case (RFRU_STATE_RX_BIND_RESPONSE) :
rfruStopRadio();
if(++rfruData.bindRequestRetries < RF_BIND_REQUEST_RETRIES) {
rfruSBReq();
} else {
rfruSetMyAddress(0xFF, 0xFF, 0xFF, 0xFF);
rfruHookRfEvent(RFRU_EVENT_BIND_REQUEST_TIMEOUT, 0);
}
break;
}
}
//internal function, do not call from outside of this file
static BYTE handleDataPacket(void)
{
BYTE callbackEvent;
if(rfruData.pRxPacket->flag & RF_ACK_REQUEST){
rfruData.pTxAckPkt.destAddress = rfruData.pRxPacket->sourceAddress;
rfruData.pTxAckPkt.flag = 0;
if(RF_GET_SEQ_BIT(rfruData.pRxSequenceBits, rfruData.pRxPacket->sourceAddress) != (rfruData.pRxPacket->flag & RF_SEQUENCE_BIT)) {
//if sequence bit is ok packet is acknowledged. Toggle sequence bit and send packet received callback
RF_TOGGLE_SEQ_BIT(rfruData.pRxSequenceBits, rfruData.pRxPacket->sourceAddress);
rfruData.pTxAckPkt.flag |= RF_ACK; //send ack
callbackEvent = RFRU_EVENT_DATA_PACKET_RECEIVED;
}
else {//a retransmission
rfruData.pTxAckPkt.flag |= RF_ACK; //send ack
callbackEvent = RFRU_EVENT_RETRANSMSSION_RECEIVED;
}
rfruData.radio_state = RFRU_STATE_TX_ACK_NACK;
//setup DMA for TX and start TX
SET_WORD(rfruData.dmaToRadioDesc.SRCADDRH, rfruData.dmaToRadioDesc.SRCADDRL, (BYTE __xdata *) &rfruData.pTxAckPkt);
RF_START_DMA_TX(&rfruData.dmaToRadioDesc);
STX();
}
else { //no ack requested, disregard sequence bit.
rfruData.radio_state = RFRU_STATE_IDLE;
callbackEvent = RFRU_EVENT_DATA_PACKET_RECEIVED;
}
return callbackEvent;
}
#pragma vector=RF_VECTOR
__interrupt void rfIrq(void)
{
BYTE callBack;
INT_ENABLE(INUM_T2, INT_OFF);//neccessary because rfruData.radio_state is changed both here (RF ISR) and in timer2 ISR
INT_SETFLAG(INUM_RF, INT_CLR); // Clear MCU interrupt flag
//Check if error has occurred
if(RFIF & (IRQ_TXUNF | IRQ_RXOVF) ) {//rx overflow or tx underflow
SIDLE();
DMA_ABORT_CHANNEL(0);
rfruData.radio_state = RFRU_STATE_IDLE;
STOP_RADIO_TIMEOUT();
rfruData.rfTimeout = FALSE;
RFIF = 0;
}
//check if radio has finished receiving or sending a packet.
else if(RFIF & IRQ_DONE)
{
RFIF = ~IRQ_DONE;
SIDLE();
//check the rfruData.radio_state
switch(rfruData.radio_state)
{
// *********** rfruData.radio_state indication radio was in TX, e.g. a packet is sent ***********
//finished sending a packet, does not expect a ansver
case (RFRU_STATE_TX_ACK_NACK) :
case (RFRU_STATE_TX_PKT_NO_ACK) :
rfruData.radio_state = RFRU_STATE_IDLE;
break;
//sent packet, expect ack
case (RFRU_STATE_TX_PKT_EXPECT_ACK) :
rfruData.radio_state = RFRU_STATE_RX_ACK;
PKTLEN = 6; //setup max packet length to avoid overflowing the ack packet buffer
RF_START_DMA_RX(&rfruData.dmaFromRadioDesc);
SRX(); //start rx
rfruData.rfTimeout = FALSE;
START_RADIO_TIMEOUT(rfruData.timer2Cnt); //start ack timeout
break;
//sent data request packet, expect data packet back
case (RFRU_STATE_TX_DATA_REQ) :
rfruData.radio_state = RFRU_STATE_RX_DATA_PACKET; //set radio state
PKTLEN = rfruData.maxPacketLength; //setup max packet length to avoid overflowing the rx packet buffer
RF_START_DMA_RX(&rfruData.dmaFromRadioDesc);
SRX(); //start rx
rfruData.rfTimeout = FALSE;
START_RADIO_TIMEOUT(rfruData.timer2Cnt); //start packet/NAKC timeout
break;
//sent a bind request, expect a bind response
case (RFRU_STATE_TX_BIND_REQUEST) :
rfruData.radio_state = RFRU_STATE_RX_BIND_RESPONSE; //set radio state
PKTLEN = 7; //setup max packet length to avoid overflowing the ack packet buffer
rfruData.pRxAckPkt->length = 0;
RF_START_DMA_RX(&rfruData.dmaFromRadioDesc);
SRX(); //start rx
rfruData.rfTimeout = FALSE;
START_RADIO_TIMEOUT(rfruData.timer2Cnt); //start bind reply timeout
break;
// *********** rfruData.radio_state indication radio was in RX, e.g. a packet is received ***********
case (RFRU_STATE_RX_DATA_PACKET) :
//verify length, CRC, and address in packet.
if((rfruData.pRxPacket->length < 6) || !(CHECK_CRC(rfruData.pRxPacket)) || !(CHECK_NETW_ADDR(rfruData.pRxPacket, rfruData.pNetworkAddress)) || (rfruData.pRxPacket->sourceAddress != rfruData.lastPktSentTo))
{
rfruHandleUnwantedPacket(); // a unwanted packet, go back to RX or timeout
INT_ENABLE(INUM_T2, INT_ON);//turn on timeout interrupt againg
}
//packet is valid, check packet type on the received packet
else if((rfruData.pRxPacket->flag & RF_PACKET_TYPE) == RF_DATA_PACKET)
{
// a incoming data packet.
STOP_RADIO_TIMEOUT();
rfruData.rfTimeout = FALSE;
callBack = handleDataPacket();
rfruHookRfEvent(callBack, 0);
}
else if((rfruData.pRxPacket->flag & RF_PACKET_TYPE) == RF_NACK)
{
//a nack packet is received (can happen after sending a data request)
STOP_RADIO_TIMEOUT();
rfruData.rfTimeout = FALSE;
rfruData.radio_state = RFRU_STATE_IDLE;
rfruHookRfEvent(RFRU_EVENT_DATA_REQUEST_NACKED, rfruData.pRxPacket->flag);
}
else
{
rfruHandleUnwantedPacket(); // a unwanted packet, go back to RX or timeout
INT_ENABLE(INUM_T2, INT_ON);//turn on timeout interrupt againg
}
break; //case (RFRU_STATE_RX_DATA_PACKET)
// expect a ack/nack packet
case (RFRU_STATE_RX_ACK) :
//verify CRC, and address in packet.
if((rfruData.pRxAckPkt->length != 6) || !(CHECK_CRC(rfruData.pRxAckPkt)) || !(CHECK_NETW_ADDR(rfruData.pRxAckPkt, rfruData.pNetworkAddress)) || (rfruData.pRxAckPkt->sourceAddress != rfruData.lastPktSentTo))
{
rfruHandleUnwantedPacket(); // a unwanted packet, go back to RX or timeout
INT_ENABLE(INUM_T2, INT_ON);//turn on timeout interrupt againg
}
else if((rfruData.pRxAckPkt->flag & RF_PACKET_TYPE) == RF_ACK)
{
STOP_RADIO_TIMEOUT();
rfruData.rfTimeout = FALSE;
rfruData.radio_state = RFRU_STATE_IDLE;
RF_TOGGLE_SEQ_BIT(rfruData.pTxSequenceBits, rfruData.pRxAckPkt->sourceAddress); //toggle sequence bit
rfruHookRfEvent(RFRU_EVENT_ACK_RECEIVED, rfruData.pRxAckPkt->flag);
}
else if((rfruData.pRxAckPkt->flag & RF_PACKET_TYPE) == RF_NACK)
{
STOP_RADIO_TIMEOUT();
rfruData.rfTimeout = FALSE;
rfruData.radio_state = RFRU_STATE_IDLE;
rfruHookRfEvent(RFRU_EVENT_NACK_RECEIVED, rfruData.pRxAckPkt->flag);
}
else{
rfruHandleUnwantedPacket(); // a unwanted packet, go back to RX or timeout
INT_ENABLE(INUM_T2, INT_ON);//turn on timeout interrupt againg
}
break;//case (RFRU_STATE_RX_ACK)
case (RFRU_STATE_RX_BIND_RESPONSE) :
if ((rfruData.pRxAckPkt->length != 7) || CHECK_CRC(rfruData.pRxAckPkt) && ((rfruData.pRxAckPkt->flag & RF_PACKET_TYPE) == RF_BIND_RESPONSE))
{
STOP_RADIO_TIMEOUT();
rfruData.rfTimeout = FALSE;
rfruData.radio_state = RFRU_STATE_IDLE; //set rfruData.radio_state
rfruSetMyAddress(rfruData.pRxAckPkt->networkAddress[0], rfruData.pRxAckPkt->networkAddress[1], rfruData.pRxAckPkt->networkAddress[2], rfruData.pRxAckPkt->data[0]);
RF_CLR_SEQ_BIT(rfruData.pRxSequenceBits, rfruData.pTxAckPkt.destAddress);//clear the sequence bit, both rx
RF_CLR_SEQ_BIT(rfruData.pTxSequenceBits, rfruData.pTxAckPkt.destAddress);//...and tx
rfruHookRfEvent(RFRU_EVENT_BIND_SUCCESSFULL, rfruData.pRxAckPkt->sourceAddress);
}
else
{
rfruHandleUnwantedPacket(); // a unwanted packet, go back to RX or timeout
INT_ENABLE(INUM_T2, INT_ON);//turn on timeout interrupt againg
}
break;
default:
SIDLE();
DMA_ABORT_CHANNEL(0);
rfruData.radio_state = RFRU_STATE_IDLE;
break;
}//switch(rfruData.radio_state)
}
}
//timer 2 / MAC timer Interrupt Service Routine.
//MAC timer is used to timeout ack/nack messages and other replies.
#pragma vector=T2_VECTOR
__interrupt void t2Irq(void)
{
INT_ENABLE(INUM_RF, INT_OFF);//neccessary because radio state change is done both here and in RF ISR
//check if we have started receiving or finished receiving a packet
if(PKTSTATUS & 0x88){
rfruData.rfTimeout = TRUE;
}
else{
//No SFD found or packet received.
rfruHandleTimeout();
}
INT_ENABLE(INUM_RF, INT_ON);
}
/// @}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -