📄 rf_usb_dongle.c
字号:
//set sequence bit
if(RF_GET_SEQ_BIT(rfudData.pTxSequenceBits, pTxPacket->destAddress)) { pTxPacket->flag &= ~RF_SEQUENCE_BIT; }
else { pTxPacket->flag |= RF_SEQUENCE_BIT; }
//set packet type bit
pTxPacket->flag &= ~RF_PACKET_TYPE;
pTxPacket->flag |= RF_DATA_PACKET;
//set if rf state (ack or nack expected)
if(pTxPacket->flag & RF_ACK_REQUEST) {
rfudData.radio_state = RFUD_STATE_TX_PKT_EXPECT_ACK;
//Setup DMA descriptor for reception of the ack packet
rfudData.pRxAckPkt->length = 0;
SET_WORD(rfudData.dmaFromRadioDesc.DESTADDRH, rfudData.dmaFromRadioDesc.DESTADDRL, (BYTE __xdata *) rfudData.pRxAckPkt);
}
else { rfudData.radio_state = RFUD_STATE_TX_PKT_NO_ACK; }
rfudData.lastPktSentTo = pTxPacket->destAddress;
//setup DMA
SET_WORD(rfudData.dmaToRadioDesc.SRCADDRH, rfudData.dmaToRadioDesc.SRCADDRL, (BYTE __xdata *) pTxPacket);
RF_START_DMA_TX(&rfudData.dmaToRadioDesc);
//start TX
STX();
}
//internal function, do not call from outside of this file
static BYTE handleDataPacket(void)
{
BYTE callbackEvent = 0;
if(rfudData.pRxPacket->flag & RF_ACK_REQUEST){
rfudData.pTxAckPkt.length = 6;
rfudData.pTxAckPkt.destAddress = rfudData.pRxPacket->sourceAddress;
rfudData.pTxAckPkt.flag = 0;
//if sequence bit is ok
if(RF_GET_SEQ_BIT(rfudData.pRxSequenceBits, rfudData.pRxPacket->sourceAddress) != (rfudData.pRxPacket->flag & RF_SEQUENCE_BIT)) {
//ask application if packet should be acked.
if(rfudHookAckPkt(rfudData.pRxPacket->sourceAddress, &rfudData.pTxAckPkt.flag)) {
//if packet is acknowledged, toggle sequence bit and send packet received callback
RF_TOGGLE_SEQ_BIT(rfudData.pRxSequenceBits, rfudData.pRxPacket->sourceAddress);
rfudData.pTxAckPkt.flag |= RF_ACK; //send ack
rfudData.radio_state = RFUD_STATE_TX_ACK;
callbackEvent = RFUD_EVENT_DATA_PACKET_RECEIVED;
}
//packet is nacked, dont send packet received callback, just finish the nack sending and go back to rx
else {
rfudData.pTxAckPkt.flag |= RF_NACK;//send nack
rfudData.radio_state = RFUD_STATE_TX_NACK;
}
}
else {//a retransmission
rfudData.pTxAckPkt.flag |= RF_ACK; //send ack
rfudData.radio_state = RFUD_STATE_TX_ACK;
}
//setup DMA for TX
SET_WORD(rfudData.dmaToRadioDesc.SRCADDRH, rfudData.dmaToRadioDesc.SRCADDRL, &rfudData.pTxAckPkt);
RF_START_DMA_TX(&rfudData.dmaToRadioDesc);
STX();
}
else { //no ack requested, disregard sequence bit.
rfudData.radio_state = RFUD_STATE_IDLE;
rfudData.rxBufferNeeded = TRUE;
callbackEvent = RFUD_EVENT_DATA_PACKET_RECEIVED;
}
return callbackEvent;
}
#pragma vector=RF_VECTOR
__interrupt void rfIrq(void)
{
BYTE callBack;
RF_PACKET __xdata * pTxPacket;
INT_SETFLAG(INUM_RF, INT_CLR); // Clear MCU interrupt flag
INT_ENABLE(INUM_T2, INT_OFF);//neccessary because rfudData.radio_state is changed both here (RF ISR) and in timer2 ISR
if(RFIF & (IRQ_TXUNF | IRQ_RXOVF) ) {//rx overflow or tx underflow
STOP_RADIO_TIMEOUT();
rfudResetRadio();
RFIF = 0;
}
//check if radio has finished receiving or sending a packet.
else if(RFIF & IRQ_DONE)
{
RFIF = ~IRQ_DONE;
SIDLE();
//check the rfudData.radio_state
switch(rfudData.radio_state)
{
//finished sending a packet that does not expect any answer
case (RFUD_STATE_TX_ACK) :
case (RFUD_STATE_TX_PKT_NO_ACK) :
case (RFUD_STATE_TX_NACK) :
case (RFUD_STATE_TX_BIND_RESPONSE) :
rfudResetRadio();
break;
//sent packet, expect ack
case (RFUD_STATE_TX_PKT_EXPECT_ACK) :
rfudData.radio_state = RFUD_STATE_RX_ACK;
//setup max packet length to avoid overflowing the ack packet buffer
PKTLEN = 6;
//start rx
RF_START_DMA_RX(&rfudData.dmaFromRadioDesc);
SRX();
//start ack timeout
START_RADIO_TIMEOUT(rfudData.timer2Cnt);
break;
case (RFUD_STATE_GENERAL_RX) :
//verify length and CRC
if((rfudData.pRxPacket->length < 6) || !(CHECK_CRC(rfudData.pRxPacket)))
{
//packet not valid, go back to RX.
rfudResetRadio();
}
//if correct network address
else if(CHECK_NETW_ADDR(rfudData.pRxPacket, rfudData.pNetworkAddress))
{
//packet is valid, check packet type on the received packet
switch (rfudData.pRxPacket->flag & RF_PACKET_TYPE) {
// a incoming data packet.
case (RF_DATA_PACKET) :
callBack = handleDataPacket();
if(callBack)
{
rfudData.rxBufferNeeded = TRUE; //RX buffer is no longer available
rfudHookRfEvent(callBack, rfudData.pRxPacket->sourceAddress);
}
break;
// a incoming data request.
case (RF_DATA_REQUEST) :
rfudData.radio_state = RFUD_STATE_IDLE;
//send a callback to application to find out what to do
pTxPacket = rfudHookDataPktRequest(rfudData.pRxPacket->sourceAddress);
//if a data packet should be sent
if(pTxPacket) {
pTxPacket->destAddress = rfudData.pRxPacket->sourceAddress;//set destination address.
rfudSendDataPacket(pTxPacket);
}
//if not send a NACK data packet
else {
rfudData.pTxAckPkt.flag = RF_NACK;
rfudData.pTxAckPkt.length = 6;
rfudData.pTxAckPkt.destAddress = rfudData.pRxPacket->sourceAddress;
rfudData.radio_state = RFUD_STATE_TX_NACK;
//setup DMA
SET_WORD(rfudData.dmaToRadioDesc.SRCADDRH, rfudData.dmaToRadioDesc.SRCADDRL, (BYTE __xdata *) &rfudData.pTxAckPkt);
RF_START_DMA_TX(&rfudData.dmaToRadioDesc);
//start TX
STX();
}
break;
// a unwanted packet, go back to RX
default:
rfudResetRadio();
break;
}
}
//Check if packet is a bind request, and the RSSI value is high enough.
else if(CHECK_IF_BIND_REQUEST(rfudData.pRxPacket))
{
//send a callback to application, asking if a reply should be sent and if so what address the unit should get.
rfudData.pTxAckPkt.data[0] = rfudHookBindRequest(rfudData.pRxPacket->sourceAddress);
//if application wants to send a bind response
if(rfudData.pTxAckPkt.data[0])
{
//setup bind respond packet, use rfudData.pTxAckPkt to save memory.
rfudData.pTxAckPkt.length = 7;
rfudData.pTxAckPkt.destAddress = 0xFF;
rfudData.pTxAckPkt.flag = RF_BIND_RESPONSE;
rfudData.radio_state = RFUD_STATE_TX_BIND_RESPONSE;
//setup DMA for TX
SET_WORD(rfudData.dmaToRadioDesc.SRCADDRH, rfudData.dmaToRadioDesc.SRCADDRL, (BYTE __xdata *) &rfudData.pTxAckPkt);
RF_START_DMA_TX(&rfudData.dmaToRadioDesc);
STX();
//clear the sequence bit, both rx and tx
RF_CLR_SEQ_BIT(rfudData.pRxSequenceBits, rfudData.pTxAckPkt.data[0]);
RF_CLR_SEQ_BIT(rfudData.pTxSequenceBits, rfudData.pTxAckPkt.data[0]);
}
else
{ // dont want to bind, go back to RX
rfudResetRadio();
}
}
else
{ // a unwanted packet, go back to RX
rfudResetRadio();
}
break; //case (RFUD_STATE_GENERAL_RX)
// expect a ack/nack packet
case (RFUD_STATE_RX_ACK) :
//verify length, CRC, and address in packet.
if((rfudData.pRxAckPkt->length == 6) && CHECK_CRC(rfudData.pRxAckPkt) && CHECK_NETW_ADDR(rfudData.pRxAckPkt, rfudData.pNetworkAddress) && (rfudData.pRxAckPkt->sourceAddress == rfudData.lastPktSentTo))
{
if((rfudData.pRxAckPkt->flag & RF_PACKET_TYPE) == RF_ACK)
{
STOP_RADIO_TIMEOUT();
rfudResetRadio();
//toggle sequence bit
RF_TOGGLE_SEQ_BIT(rfudData.pTxSequenceBits, rfudData.pRxAckPkt->sourceAddress);
rfudHookRfEvent(RFUD_EVENT_ACK_RECEIVED, rfudData.pRxAckPkt->sourceAddress);
}
else if((rfudData.pRxAckPkt->flag & RF_PACKET_TYPE) == RF_NACK)
{
STOP_RADIO_TIMEOUT();
rfudResetRadio();
rfudHookRfEvent(RFUD_EVENT_NACK_RECEIVED, rfudData.pRxAckPkt->sourceAddress);
}
// a unwanted packet, go back to RX
else{
rfudResetRadio();
INT_ENABLE(INUM_T2, INT_ON);//Turn timer 2 interrupt back on to enable timeout
}
}else
{ //packet not valid, go back to RX.
rfudResetRadio();
INT_ENABLE(INUM_T2, INT_ON);//Turn timer 2 interrupt back on to enable timeout
}
break;//case (RFUD_STATE_RX_ACK)
default :
rfudResetRadio();
break;
}//switch(rfudData.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
if(rfudData.radio_state == RFUD_STATE_RX_ACK)
{
if(!(PKTSTATUS & 0x88)){
rfudHookRfEvent(RFUD_EVENT_ACK_TIMEOUT, rfudData.lastPktSentTo);
rfudResetRadio();
}
}
INT_ENABLE(INUM_RF, INT_ON);
}
/// @}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -