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

📄 rf_usb_dongle.c

📁 reference about wireless design which is helpful to everyone
💻 C
📖 第 1 页 / 共 2 页
字号:

   //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 + -