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

📄 mac.c

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

macRxFSM_start:

  switch(macRxState)  {
  case MAC_RXSTATE_IDLE:
    if (macRxBuffEmpty()) break;   //no data, break
    //buffer not empty, start decode
    pkt = macGetRxPacket();
    //dbgPrintPacket(pkt->data+1, *(pkt->data));
    //must be either a DATA, BCN, or MAC packet
    //at this point, we throw away BCN packets if are not waiting
    //for a beacon response
    if ((LRWPAN_IS_BCN(*(pkt->data+1))) &&
        !mac_pib.flags.bits.WaitingForBeaconResponse) {
          DEBUG_STRING(DBG_INFO,"MAC: Received BCN pkt, discarding.\n");
          macFreeRxPacket(TRUE);
          break;
        }
    if (LRWPAN_IS_ACK(*(pkt->data+1))) {
      //This should not happen. ACK packets should be parsed
      //in the HAL layer that copies ACK packets to temp storage.
      //will keep this for completeness.
      DEBUG_STRING(DBG_INFO,"MAC: Received ACK pkt in macStartRxDecode, discarding, check ack packet parsing..\n");
      macFreeRxPacket(TRUE);
      break;
    }
    //at this point, we have a DATA, MAC CMD, or BCN packet.. do something with it.
    //need to parse the header information get to the payload.
    a_mac_rx_data.orgpkt = pkt;
    macParseHdr();
    if ((LRWPAN_IS_BCN(*(pkt->data+1)))){
      DEBUG_STRING(DBG_INFO,"MAC: Parsing BCN pkt.\n");
      //now finished with it.
      macParseBeacon();
      macFreeRxPacket(TRUE);
      break;
    }

    if (LRWPAN_IS_DATA(*(pkt->data+1))){
		//this is a data packet, check if we should reject it
        if (!macCheckDataRejection()) {
            //we need to reject this packet.
            DEBUG_STRING(DBG_INFO,"MAC: Rejecting Data packet from unassociated node, rejecting.\n");
            macFreeRxPacket(TRUE);
            break;
        }
       mac_pib.last_data_rx_time = halGetMACTimer();  //time of last data or mac command
      //at this point, will accept packet, indicate this to network layer
      //set a flag, and pass the nwkStart offset to the NWK layer
      //RX buffer.
      macRxState = MAC_RXSTATE_NWK_HANDOFF;
      goto macRxFSM_start;
    }

    //at this point, we have a MAC command packet, lets do something with it.
    DEBUG_STRING(DBG_INFO,"MAC: Received MAC cmd packet, proceeding.\n");

    //there are some MAC CMDs that we can handle right here.
    //If it is a response, we handle it here. If it is a request,
    //that has to be handled in the main FSM.
    cmd = *(a_mac_rx_data.orgpkt->data + a_mac_rx_data.pload_offset);
    switch(cmd) {
    case LRWPAN_MACCMD_ASSOC_RSP:
#ifndef LRWPAN_COORDINATOR
      if (mac_pib.flags.bits.WaitingForAssocResponse){
        macParseAssocResponse();
      }					
#endif				
      //free this packet, we are finished with it.
      macFreeRxPacket(TRUE);
      break;

	case LRWPAN_MACCMD_COORD_REALIGN:
#ifndef LRWPAN_COORDINATOR
      if (mac_pib.flags.bits.WaitingForOrphanResponse){
        macParseOrphanResponse();
      }					
#endif				
      //free this packet, we are finished with it.
      macFreeRxPacket(TRUE);
      break;



#ifdef LRWPAN_FFD
      //only FFDs handle this
    case LRWPAN_MACCMD_BCN_REQ:
    case LRWPAN_MACCMD_ASSOC_REQ:
	case LRWPAN_MACCMD_ORPHAN:
      //requests must be handled in the main FSM. We need to signal that a MAC
      //CMD packet is packet is pending, and freeze the RX FSM until the
      //main FSM has taken care of it.
      mac_pib.flags.bits.macPending = 1;
      macRxState = MAC_RXSTATE_CMD_PENDING;
      break;
#endif

    default:
      //unhandled MAC packets
      DEBUG_STRING(DBG_INFO,"MAC: Received MAC CMD that is not implemented or not handled by this node, discarding.\n");
      DEBUG_STRING(DBG_INFO,"Cmd is: ");
      DEBUG_UINT8(DBG_INFO,cmd);
      DEBUG_STRING(DBG_INFO,"\n");
      macFreeRxPacket(TRUE);
      break;

    }			

    break;
  case MAC_RXSTATE_NWK_HANDOFF:
		  if (nwkRxBusy()) break;    //nwkRX is still busy
                  //handoff the current packet
                  nwkRxHandoff();
                  //we are finished with this packet.
                  //free the MAC resource, but not the memory. The NWK layer
                  // or above has to free the memory
                  macFreeRxPacket(FALSE);
                  macRxState = MAC_RXSTATE_IDLE;
                  break;
  case MAC_RXSTATE_CMD_PENDING:
    if (mac_pib.flags.bits.macPending ) break;
			 //when macPending is cleared, this means main FSM is finished with packet.
			 //So free the packet, and start parsing new packets again
			 macFreeRxPacket(TRUE);
                         macRxState = MAC_RXSTATE_IDLE;
                         break;


  default: break;

  }

}

//parse the header currently in a_mac_rx_data
//return the offset to the network header.

static void macParseHdr() {
  BYTE *ptr;
  BYTE len,i;
  BYTE srcmode, dstmode;

  ptr = a_mac_rx_data.orgpkt->data;

  //skip first byte since the first byte in the a_mac_rx_data.orgpkt is the
  //packet length
  len = 1;ptr++;


  a_mac_rx_data.fcflsb = *ptr; ptr++;
  a_mac_rx_data.fcfmsb = *ptr; ptr++;
  dstmode = LRWPAN_GET_DST_ADDR(a_mac_rx_data.fcfmsb);
  srcmode = LRWPAN_GET_SRC_ADDR(a_mac_rx_data.fcfmsb);

  //skip DSN
  ptr++;
  len = len +3;

  if (dstmode != LRWPAN_ADDRMODE_NOADDR){
    //get the DEST PANDID
    a_mac_rx_data.DestPANID = *ptr;
    ptr++;
    a_mac_rx_data.DestPANID += (((UINT16)*ptr) << 8);
    ptr++;
    len = len + 2;
  }
  //DST address
  if (dstmode == LRWPAN_ADDRMODE_SADDR) {
    a_mac_rx_data.DestAddr.saddr = *ptr;
    ptr++;
    a_mac_rx_data.DestAddr.saddr += (((UINT16)*ptr) << 8);
    ptr++;
    len = len + 2;

  }else if (dstmode == LRWPAN_ADDRMODE_LADDR) {
    for (i=0;i<8;i++) {
      a_mac_rx_data.DestAddr.laddr.bytes[i] = *ptr;
      ptr++;
    }
    len = len + 8;
  }


  if ( !LRWPAN_GET_INTRAPAN(a_mac_rx_data.fcflsb) &&
      srcmode != LRWPAN_ADDRMODE_NOADDR
        ) {
          //PANID present if INTRAPAN is zero, and src is nonzero
          a_mac_rx_data.SrcPANID = *ptr;
          ptr++;
          a_mac_rx_data.SrcPANID += (((UINT16)*ptr) << 8);
          ptr++;
          len = len + 2;
        }
  //SRC address
  if (srcmode == LRWPAN_ADDRMODE_SADDR) {
    a_mac_rx_data.SrcAddr.saddr = *ptr;
    ptr++;
    a_mac_rx_data.SrcAddr.saddr += (((UINT16)*ptr) << 8);
    ptr++;
    len = len + 2;

  }else if (srcmode == LRWPAN_ADDRMODE_LADDR) {
    for (i=0;i<8;i++) {
      a_mac_rx_data.SrcAddr.laddr.bytes[i] = *ptr;
      ptr++;
    }
    len = len + 8;
  }
  //save offset.
  a_mac_rx_data.pload_offset = len;
}

#ifdef LRWPAN_FFD
//Beacon payload format
// nwk magic number ( 4 bytes) | mac depth
static void macFormatBeacon(void){
  BYTE i;

  //fill in the beacon payload, we have the TX buffer lock
  phy_pib.currentTxFrm = &tmpTxBuff[LRWPAN_MAX_FRAME_SIZE];
#ifndef LRWPAN_ZIGBEE_BEACON_COMPLY
  //fill in the magic number
  --phy_pib.currentTxFrm;
  *phy_pib.currentTxFrm = LRWPAN_NWK_MAGICNUM_B3;
  --phy_pib.currentTxFrm;
  *phy_pib.currentTxFrm = LRWPAN_NWK_MAGICNUM_B2;
  --phy_pib.currentTxFrm;
  *phy_pib.currentTxFrm = LRWPAN_NWK_MAGICNUM_B1;
  --phy_pib.currentTxFrm;
  *phy_pib.currentTxFrm = LRWPAN_NWK_MAGICNUM_B0;
#endif

  //next three bytes are zero for timestep difference
  //for multi-hop beaconing networks. This is currently filled in
  //as zero
  --phy_pib.currentTxFrm;
  *phy_pib.currentTxFrm =0;
  --phy_pib.currentTxFrm;
  *phy_pib.currentTxFrm =0;
  --phy_pib.currentTxFrm;
  *phy_pib.currentTxFrm =0;

  //see if I have space for an END device
  --phy_pib.currentTxFrm;
  if (mac_pib.ChildRFDs == LRWPAN_MAX_NON_ROUTER_CHILDREN) {
	  *phy_pib.currentTxFrm =0; //no room
  } else {
      *phy_pib.currentTxFrm =1;  //have space.
  }

  //fill in my depth
  --phy_pib.currentTxFrm;
  *phy_pib.currentTxFrm = mac_pib.depth;

  //see if I have space for a ROUTER device
  --phy_pib.currentTxFrm;
  if (mac_pib.ChildRouters == LRWPAN_MAX_ROUTERS_PER_PARENT) {
	  *phy_pib.currentTxFrm =0; //no room
  } else {
      *phy_pib.currentTxFrm =1;  //have space.
  }

   //network protocol version
  --phy_pib.currentTxFrm;
  *phy_pib.currentTxFrm =LRWPAN_ZIGBEE_PROTOCOL_VER;

   //stack protocol
   --phy_pib.currentTxFrm;
   *phy_pib.currentTxFrm =LRWPAN_STACK_PROFILE;

   //Zigbee protocol ID
   --phy_pib.currentTxFrm;
   *phy_pib.currentTxFrm =LRWPAN_ZIGBEE_PROTOCOL_ID;

  //pending address field
  --phy_pib.currentTxFrm;
  *phy_pib.currentTxFrm = 0;  //makes this a NOP

  //GTS directions field
  --phy_pib.currentTxFrm;
  *phy_pib.currentTxFrm = 0;  //makes this a NOP

  //2 bytes of superframe
#ifdef LRWPAN_COORDINATOR
  i = LRWPAN_BEACON_SF_PAN_COORD_MASK;
#else
  i = 0;
#endif
  if (mac_pib.flags.bits.macAssociationPermit) {
    i = i | LRWPAN_BEACON_SF_ASSOC_PERMIT_MASK;
  }
  --phy_pib.currentTxFrm;
  *phy_pib.currentTxFrm = i;  //MSB of superframe

  --phy_pib.currentTxFrm;
  *phy_pib.currentTxFrm = 0xFF; //LSB of superframe

  phy_pib.currentTxFlen = LRWPAN_NWK_BEACON_SIZE;

}

#endif

//parse the beacon
static void macParseBeacon(void){
  BYTE *ptr;
  BYTE depth;

  if ( (*(a_mac_rx_data.orgpkt->data)-a_mac_rx_data.pload_offset-PACKET_FOOTER_SIZE +1)
      != LRWPAN_NWK_BEACON_SIZE  ) {
        return; //wrong length
      }

  ptr = a_mac_rx_data.orgpkt->data + a_mac_rx_data.pload_offset;
  //check association bit in MSB of superframe
  if (!LRWPAN_GET_BEACON_SF_ASSOC_PERMIT(*(ptr+1))) {
    //cannot associate with this node. reject
    return;
  }
  // point at payload (skip four bytes of header)
  ptr = ptr + 4;
  //skip if any mismatches on protocol ID/Ver, stack profile, etc.
  //check protocol ID
  if (*ptr != LRWPAN_ZIGBEE_PROTOCOL_ID) return;
  ptr++;
  //check stack profile
  if (*ptr != LRWPAN_STACK_PROFILE) return;
  ptr++;
  //check protocol version
  if (*ptr != LRWPAN_ZIGBEE_PROTOCOL_VER) return;
  ptr++;

  //check router capacity
  //for right now, if I am a router, I have to join as a router.
  //no option as of now for a router joining as an end-device
#ifdef LRWPAN_FFD
  //only routers have to check this
  if (*ptr == 0) return;  //no room to join as router
#endif

  ptr++;

  //get the depth
  depth = *ptr;
  ptr++;

  //check end device capacity
#ifdef LRWPAN_RFD
  //only end devices have to check this.
  if (*ptr == 0) return;  //no room to join as end device
#endif
  ptr++;

  //skip the next three bytes, only for beaconing.
  ptr = ptr + 3;

#ifndef LRWPAN_ZIGBEE_BEACON_COMPLY
  //check the magic number
  if (*ptr != LRWPAN_NWK_MAGICNUM_B0) return;
  ptr++;
  if (*ptr != LRWPAN_NWK_MAGICNUM_B1) return;
  ptr++;
  if (*ptr != LRWPAN_NWK_MAGICNUM_B2) return;
  ptr++;
  if (*ptr != LRWPAN_NWK_MAGICNUM_B3) return;
  ptr++;
#endif

  //at this point, we could accept this node as a parent
  if ((mac_pib.bcnDepth == 0xFF) ||
      (a_mac_rx_data.orgpkt->rssi > mac_pib.bcnRSSI)) {
        //either our first response, or from a closer node
        //save this information.
        //use value with higher RSSI.
        //the RSSI byte is assumed to be formatted as HIGHER IS BETTER
        //the HAL layer converts any native signed RSSI to an unsigned value

        mac_pib.bcnDepth = depth;  //get depth
        mac_pib.bcnRSSI = a_mac_rx_data.orgpkt->rssi;
        mac_pib.bcnSADDR = a_mac_rx_data.SrcAddr.saddr;
        mac_pib.bcnPANID = a_mac_rx_data.SrcPANID;
        DEBUG_STRING(DBG_INFO,"MAC: Bcn rsp is Panid: ");
        DEBUG_UINT16(DBG_INFO, mac_pib.bcnPANID);
         DEBUG_STRING(DBG_INFO,", Saddr: ");
       DEBUG_UINT16(DBG_INFO, mac_pib.bcnSADDR);
        DEBUG_STRING(DBG_INFO,", LQI: ");
       DEBUG_UINT8(DBG_INFO, mac_pib.bcnRSSI);
          DEBUG_STRING(DBG_INFO,", Dpth: ");
       DEBUG_UINT8(DBG_INFO, mac_pib.bcnDepth);
       DEBUG_STRING(DBG_INFO,"\n");
      }
  mac_pib.flags.bits.GotBeaconResponse = 1;
}


static void macFormatAssocRequest(void){
  //fill in payload of request
  phy_pib.currentTxFrm = &tmpTxBuff[LRWPAN_MAX_FRAME_SIZE];

#ifndef IEEE_802_COMPLY
  //put the magic number in the association request
  phy_pib.currentTxFrm--;
  *phy_pib.currentTxFrm = LRWPAN_NWK_MAGICNUM_B3;

  phy_pib.currentTxFrm--;
  *phy_pib.currentTxFrm = LRWPAN_NWK_MAGICNUM_B2;

  phy_pib.currentTxFrm--;
  *phy_pib.currentTxFrm = LRWPAN_NWK_MAGICNUM_B1;

⌨️ 快捷键说明

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