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

📄 mac.c

📁 本程序是基于Zigbee协议的无线温度传感器网络系统
💻 C
📖 第 1 页 / 共 4 页
字号:

             mac_pib.flags.bits.WaitingForAssocResponse = 1;
             //send to coordinator with Short address = 0;
             a_mac_tx_data.SrcPANID = 0xFFFF;

             //Transmit it
             macTxData();
             macState = MAC_STATE_ASSOC_REQ_WAIT1;
             break;		
           default: break;
           }//end switch cmd
           break;


	 case MAC_STATE_ASSOC_REQ_WAIT1:
           if (!macTXIdle()) break;
           //TX is finished
           phyReleaseTxLock();		
           if (macTxFSM_status != LRWPAN_STATUS_SUCCESS) {
             //no sense waiting any longer, nobody responded to MAC-level ACK
             a_mac_service.status = macTxFSM_status;
             mac_pib.flags.bits.WaitingForAssocResponse = 0;
             macState = MAC_STATE_IDLE;			
             break;
           }

           //now need to wait for association response
           //start a timer
           mac_utility_timer = halGetMACTimer();
           macState = MAC_STATE_ASSOC_REQ_WAIT2;
           break;

	 case MAC_STATE_ASSOC_REQ_WAIT2:
           if (mac_pib.flags.bits.macIsAssociated) {
             //association successful, hooray!
             a_mac_service.status = LRWPAN_STATUS_SUCCESS;
             mac_pib.flags.bits.WaitingForAssocResponse = 0;
             macState = MAC_STATE_IDLE;	
           }else if ((halMACTimerNowDelta(mac_utility_timer))>MAC_ASSOC_WAIT_TIME  ){
             //timeout on association, give it up
             a_mac_service.status = LRWPAN_STATUS_MAC_ASSOCIATION_TIMEOUT;
             DEBUG_STRING(DBG_INFO,"MAC: Association timeout\n");
             mac_pib.flags.bits.WaitingForAssocResponse = 0;
             macState = MAC_STATE_IDLE;	
           }

           break;

		

		 case MAC_STATE_ORPHAN_WAIT1:
		      if (!macTXIdle()) break;
			  //TX is finished
              phyReleaseTxLock();		
			  if (macTxFSM_status != LRWPAN_STATUS_SUCCESS){
				  //don't wait, TX failed
				  DEBUG_STRING(DBG_INFO,"Orphan Notify TX failed\n");
				  mac_pib.flags.bits.WaitingForOrphanResponse = 0;
				  a_mac_service.status = macTxFSM_status;
				  macState = MAC_STATE_IDLE;
				  break;
			  }
             //now need to wait for association response
             //start a timer
             mac_utility_timer = halGetMACTimer();
             macState = MAC_STATE_ORPHAN_WAIT2;
             break;

		 case MAC_STATE_ORPHAN_WAIT2:
			 if (mac_pib.flags.bits.GotOrphanResponse) {
                //rejoin successfull
                a_mac_service.status = LRWPAN_STATUS_SUCCESS;
                mac_pib.flags.bits.WaitingForOrphanResponse = 0;
                mac_pib.flags.bits.GotOrphanResponse = 0;
                macState = MAC_STATE_IDLE;					
			 } else if ((halMACTimerNowDelta(mac_utility_timer))>MAC_ORPHAN_WAIT_TIME ){
                   //timeout on rejoin, give it up
                  a_mac_service.status = LRWPAN_STATUS_MAC_ORPHAN_TIMEOUT;
                  DEBUG_STRING(DBG_INFO,"MAC: Orphan timeout\n");
                  mac_pib.flags.bits.WaitingForOrphanResponse = 0;
                  macState = MAC_STATE_IDLE;	
            }
			break;

	 case MAC_STATE_GENERIC_TX_WAIT:
           if (!macTXIdle()) break;
           //TX is finished, copy status
           a_mac_service.status = macTxFSM_status;
           macState = MAC_STATE_IDLE;	
           break;
           //this is used by MAC CMDs in general which send a packet with no ACK.
	 case MAC_STATE_GENERIC_TX_WAIT_AND_UNLOCK:
           if (!macTXIdle()) break;
           //TX is finished, copy status
           a_mac_service.status = macTxFSM_status;
           macState = MAC_STATE_IDLE;	
           //also unlock TX buffer
           phyReleaseTxLock();
           break;
#ifdef LRWPAN_FFD
	 case MAC_STATE_HANDLE_ORPHAN_NOTIFY:
		   //first, check to see if this node is in my neighbor table
		   nt_ptr = ntFindByLADDR(&a_mac_rx_data.SrcAddr.laddr);
		   if (!nt_ptr) {
			   //not my orphan, ignoring
			   DEBUG_STRING(DBG_INFO,"MAC: Received orphan notify, but not my orphan, ignoring.\n");
               macState = MAC_STATE_IDLE;	
               //also unlock TX buffer
               phyReleaseTxLock();
			   break;
		   }
		   DEBUG_STRING(DBG_INFO,"Sending Coord Realign (Orphan response)\n");
		   //at this point, we have an orphan. Send a response.
		   macFormatCoordRealign(mac_addr_tbl[nt_ptr->map_index].saddr);
           goto mac_state_send_assoc_response1;  //shared code
		

	 case MAC_STATE_SEND_BEACON_RESPONSE:
           //got a Beacon Request, send the response
           DEBUG_STRING(DBG_INFO,"Sending BCN Response\n");
           macFormatBeacon();
           a_mac_tx_data.fcflsb = LRWPAN_FRAME_TYPE_BEACON;
           a_mac_tx_data.fcfmsb = LRWPAN_FCF_DSTMODE_NOADDR|LRWPAN_FCF_SRCMODE_SADDR;
           a_mac_tx_data.SrcAddr = macGetShortAddr();
           a_mac_tx_data.SrcPANID = mac_pib.macPANID;
           macTxData();
           macState = MAC_STATE_GENERIC_TX_WAIT_AND_UNLOCK;
           break;

	 case MAC_STATE_SEND_ASSOC_RESPONSE:
		   DEBUG_STRING(DBG_INFO,"Sending Association Response\n");
           macFormatAssociationResponse();
mac_state_send_assoc_response1:

           a_mac_tx_data.fcflsb = LRWPAN_FRAME_TYPE_MAC|LRWPAN_FCF_ACKREQ_MASK;
           a_mac_tx_data.fcfmsb = LRWPAN_FCF_DSTMODE_LADDR|LRWPAN_FCF_SRCMODE_LADDR;
           a_mac_tx_data.DestAddr.laddr.bytes[0] = a_mac_rx_data.SrcAddr.laddr.bytes[0];
           a_mac_tx_data.DestAddr.laddr.bytes[1] = a_mac_rx_data.SrcAddr.laddr.bytes[1];
           a_mac_tx_data.DestAddr.laddr.bytes[2] = a_mac_rx_data.SrcAddr.laddr.bytes[2];
           a_mac_tx_data.DestAddr.laddr.bytes[3] = a_mac_rx_data.SrcAddr.laddr.bytes[3];
           a_mac_tx_data.DestAddr.laddr.bytes[4] = a_mac_rx_data.SrcAddr.laddr.bytes[4];
           a_mac_tx_data.DestAddr.laddr.bytes[5] = a_mac_rx_data.SrcAddr.laddr.bytes[5];
           a_mac_tx_data.DestAddr.laddr.bytes[6] = a_mac_rx_data.SrcAddr.laddr.bytes[6];
           a_mac_tx_data.DestAddr.laddr.bytes[7] = a_mac_rx_data.SrcAddr.laddr.bytes[7];
           a_mac_tx_data.DestPANID = mac_pib.macPANID;
           macTxData();
           macState = MAC_STATE_GENERIC_TX_WAIT_AND_UNLOCK;
           break;


#endif


	 default: break;
  }
}


//called by HAL when TX for current packet is finished
void macTxCallback(void) {
  if (LRWPAN_GET_ACK_REQUEST(*(phy_pib.currentTxFrm))) {
    mac_pib.flags.bits.ackPending = 1;  //we are requesting an ack for this packet
    //record the time of this packet
    mac_pib.tx_start_time = halISRGetMACTimer();
  }
}

//we pass in the pointer to the packet
//first byte is packet length
void macRxCallback(BYTE *ptr, BYTE rssi) {

  //if this is an ACK, update the current timeout, else indicate
  // that an ACK is pending
  //   check length                      check frame control field
  if ((*ptr == LRWPAN_ACKFRAME_LENGTH ) && LRWPAN_IS_ACK(*(ptr+1))) {
    //do not save ACK frames
    //this is an ACK, see if it is our ACK, check DSN
    if (*(ptr+3) == mac_pib.macDSN) {
      //DSN matches, assume this is our ack, clear the ackPending flag
      mac_pib.flags.bits.ackPending = 0;
      DEBUG_CHAR( DBG_ITRACE,DBG_CHAR_OURACK  );
    }
  } else {
    //save the packet, we assume the Physical/Hal layer has already checked
    //if the MAC buffer has room
    mac_pib.rxHead++;
    if (mac_pib.rxHead == MAC_RXBUFF_SIZE) mac_pib.rxHead = 0;
    //save it.
    mac_pib.rxBuff[mac_pib.rxHead].data = ptr;     //save pointer
    mac_pib.rxBuff[mac_pib.rxHead].rssi = rssi;    //save RSSI value
  }
}

BOOL macRxBuffFull(void){
  BYTE tmp;
  //if next write would go to where Tail is, then buffer is full
  tmp = mac_pib.rxHead+1;
  if (tmp == MAC_RXBUFF_SIZE) tmp = 0;
  return(tmp == mac_pib.rxTail);
}

BOOL macRxBuffEmpty(void){
  return(mac_pib.rxTail == mac_pib.rxHead);
}

//this does NOT remove the packet from the buffer
MACPKT *macGetRxPacket(void) {
  BYTE tmp;	
  if (mac_pib.rxTail == mac_pib.rxHead) return(NULL);
  tmp = mac_pib.rxTail+1;
  if (tmp == MAC_RXBUFF_SIZE) tmp = 0;
  return(&mac_pib.rxBuff[tmp]);
}

//frees the first packet in the buffer.
void macFreeRxPacket(BOOL freemem) {
  mac_pib.rxTail++;
  if (mac_pib.rxTail == MAC_RXBUFF_SIZE) mac_pib.rxTail = 0;
  if (freemem) MemFree(mac_pib.rxBuff[mac_pib.rxTail].data);
}




/************
The TxInProgress bit is set when the macTxData function
is called the first time to actually format the header and
send the packet. After that, each loop through the macTxFSM
checks to see if the TX started and finished correctly, and
if an ACK was received if one was requested.  The FSM becomes
idle if:
a. the PHY TX returns an error
b. the PHY TX returned success and either no ACK was
requested or we received the correct ACK
c. the PHY TX returned success and we exhausted retries.

**************/

static void macTxFSM(void) {
  if(!macTXIdle()) {
    //we are not idle
    if (phyIdle()) {
      //cannot check anything until PHY is idle
      if (a_phy_service.status != LRWPAN_STATUS_SUCCESS) {
        //don't bother waiting for ACK, TX did not start correctly
        mac_pib.flags.bits.ackPending = 0;
        macSetTxIdle();  //mark TX as idle
        macTxFSM_status = a_phy_service.status; //return status
      } else if (!mac_pib.flags.bits.ackPending) {
        //either no ACK requested or ACK has been received
        macSetTxIdle();  //finished successfully, mark as idle
        macTxFSM_status = LRWPAN_STATUS_SUCCESS;
      }
      //check timeout
      else if (halMACTimerNowDelta(mac_pib.tx_start_time)> mac_pib.macAckWaitDuration)
      {
        // ACK timeout
        if (mac_pib.currentAckRetries) mac_pib.currentAckRetries--;
        if (!mac_pib.currentAckRetries) {
          //retries are zero. We have failed.
          macTxFSM_status = LRWPAN_STATUS_MAC_MAX_RETRIES_EXCEEDED;
          macSetTxIdle();
          DEBUG_STRING(1,"MAC TX Retry exceeded\n");
        } else {
          //retry...
          macTxData();  //reuse the last packet.
        }
      }	

    }

  }

}

//format the packet and send it
//this is NOT used for either beacon or ack frames, only for data and MAC frames
//a side effect of this function is that if the source address mode is SHORT
//and our MAC short address is 0xFFFE, then the source address mode is forced to
//long as per the IEEE SPEC.

//this builds the header in reverse order since we adding header bytes to
//headers already added by APS, NWK layers.

//Add the MAC header, then send it to PHY
static void macTxData(void) {
  BYTE c;
  BYTE dstmode, srcmode;

  if (macTXIdle()) {
    //first time we are sending this packet, format the header
    //used static space for header. If need to store, will copy it later
    //format the header
				
    dstmode = LRWPAN_GET_DST_ADDR(a_mac_tx_data.fcfmsb);
    srcmode = LRWPAN_GET_SRC_ADDR(a_mac_tx_data.fcfmsb);

    if (mac_pib.macPANID == 0xFFFE && srcmode == LRWPAN_ADDRMODE_SADDR) {
      //our short address is 0xFFFE, force srcmode to long address
      srcmode = LRWPAN_ADDRMODE_LADDR;
      //clear src mode
      a_mac_tx_data.fcfmsb = a_mac_tx_data.fcfmsb & ~LRWPAN_FCF_SRCMODE_MASK;
      //set to long address
      LRWPAN_SET_SRC_ADDR(a_mac_tx_data.fcfmsb,LRWPAN_ADDRMODE_LADDR);
    }

    //format src Address
    switch(srcmode){
    case LRWPAN_ADDRMODE_NOADDR:
				  break;
    case LRWPAN_ADDRMODE_SADDR:
				  phy_pib.currentTxFrm--;
                                  *phy_pib.currentTxFrm = (BYTE)(a_mac_tx_data.SrcAddr >> 8);
                                  phy_pib.currentTxFrm--;
                                  *phy_pib.currentTxFrm = (BYTE)a_mac_tx_data.SrcAddr;				
                                  phy_pib.currentTxFlen=phy_pib.currentTxFlen+2;
                                  break;
    case LRWPAN_ADDRMODE_LADDR:
				  //this has to be our own long address, get it
				  halGetProcessorIEEEAddress(phy_pib.currentTxFrm-8);
                                  phy_pib.currentTxFlen=phy_pib.currentTxFlen+8;
                                  phy_pib.currentTxFrm = phy_pib.currentTxFrm-8;
                                  break;
    default:
				  break;
    }

    //format src PANID
    if ( !LRWPAN_GET_INTRAPAN(a_mac_tx_data.fcflsb) &&
        srcmode != LRWPAN_ADDRMODE_NOADDR
          ) {
            phy_pib.currentTxFrm--;
            *phy_pib.currentTxFrm = (BYTE) (a_mac_tx_data.SrcPANID >> 8);
            phy_pib.currentTxFrm--;
            *phy_pib.currentTxFrm = (BYTE)a_mac_tx_data.SrcPANID;
            phy_pib.currentTxFlen=phy_pib.currentTxFlen+2;
          }

    //format dst Address
    switch(dstmode){
    case LRWPAN_ADDRMODE_NOADDR:
      break;
		  case LRWPAN_ADDRMODE_SADDR:
                    phy_pib.currentTxFrm--;
                    *phy_pib.currentTxFrm = (BYTE)(a_mac_tx_data.DestAddr.saddr >> 8);
                    phy_pib.currentTxFrm--;
                    *phy_pib.currentTxFrm = (BYTE)a_mac_tx_data.DestAddr.saddr;
                    phy_pib.currentTxFlen=phy_pib.currentTxFlen+2;
                    break;
		  case LRWPAN_ADDRMODE_LADDR:
                    for(c=0;c<8;c++) {
                      phy_pib.currentTxFrm--;
                      *phy_pib.currentTxFrm = a_mac_tx_data.DestAddr.laddr.bytes[7-c];
                    }
                    phy_pib.currentTxFlen=phy_pib.currentTxFlen+8;
                    break;
		  default:
                    break;
    }

    //format dst PANID, will be present if both dst is nonzero
    if (dstmode != LRWPAN_ADDRMODE_NOADDR){
      phy_pib.currentTxFrm--;
      *phy_pib.currentTxFrm = (BYTE) (a_mac_tx_data.DestPANID >> 8);
      phy_pib.currentTxFrm--;
      *phy_pib.currentTxFrm = (BYTE)a_mac_tx_data.DestPANID;					
      phy_pib.currentTxFlen=phy_pib.currentTxFlen+2;
    }

    //format dsn
    mac_pib.macDSN = halGetRandomByte();
    phy_pib.currentTxFrm--;
    *phy_pib.currentTxFrm = mac_pib.macDSN; //set DSN		

    //format MSB Fcontrol
    phy_pib.currentTxFrm--;
    *phy_pib.currentTxFrm = a_mac_tx_data.fcfmsb;

    //format LSB Fcontrol
    phy_pib.currentTxFrm--;
    *phy_pib.currentTxFrm = a_mac_tx_data.fcflsb;		

    phy_pib.currentTxFlen = phy_pib.currentTxFlen + 3; //DSN, FCFLSB, FCFMSB


    // at this point, we will attempt a TX
    mac_pib.flags.bits.ackPending = 0;


    //now send the data, ignore the GTS and INDIRECT bits for now
    DEBUG_STRING(DBG_TX,"TX DSN: ");
    DEBUG_UINT8(DBG_TX,mac_pib.macDSN);
    DEBUG_STRING(DBG_TX,"\n");

    macSetTxBusy();
    mac_pib.currentAckRetries = mac_pib.macMaxAckRetries;
    macTxFSM_status = LRWPAN_STATUS_MAC_INPROGRESS;
  }

  a_phy_service.cmd = LRWPAN_SVC_PHY_TX_DATA;

  phyDoService();
}


//might be able to simplify this later.

static void macRxFSM(void){
  MACPKT *pkt;
  BYTE cmd;

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -