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

📄 rf_remote_unit.c

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

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