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

📄 nwk.c

📁 本程序是基于Zigbee协议的无线温度传感器网络系统
💻 C
📖 第 1 页 / 共 2 页
字号:
	--phy_pib.currentTxFrm;
	*phy_pib.currentTxFrm = (BYTE) (a_nwk_tx_data.dstSADDR);

	//frame control
	--phy_pib.currentTxFrm;
	*phy_pib.currentTxFrm = a_nwk_tx_data.fcfmsb;
	--phy_pib.currentTxFrm;
	*phy_pib.currentTxFrm = a_nwk_tx_data.fcflsb;

	//network header is fixed size
	phy_pib.currentTxFlen +=  8;

nwkTxData_addmac:
	//fill in the MAC fields. For now, we don't support inter-PAN
	// so the PANID has to be our mac PANID
	a_mac_tx_data.DestPANID = mac_pib.macPANID;
	a_mac_tx_data.SrcPANID = mac_pib.macPANID;

	if (a_nwk_tx_data.dstSADDR == LRWPAN_SADDR_USE_LADDR ){
		//long address is specified from above.  We assume they know where
		//they are going no routing necessary
		a_mac_tx_data.fcfmsb = LRWPAN_FCF_DSTMODE_LADDR|LRWPAN_FCF_SRCMODE_LADDR;
		//copy in the long address
		halUtilMemCopy(&a_mac_tx_data.DestAddr.laddr.bytes[0], a_nwk_tx_data.dstLADDR, 8);
	} else {
		//lets do some routing
#ifdef LRWPAN_RFD
		//RFD's are easy. Always send to parent, our SRC address is always long
		//so that parent can confirm that the RFD is still in their neighbor table
		//will use the parent short address
		a_mac_tx_data.fcfmsb = LRWPAN_FCF_DSTMODE_SADDR|LRWPAN_FCF_SRCMODE_LADDR;
		a_mac_tx_data.DestAddr.saddr = mac_pib.macCoordShortAddress;
#else
		{
			SADDR newDstSADDR;
			//this is router. need to determine the new dstSADDR
			newDstSADDR = a_nwk_tx_data.dstSADDR; //default
			DEBUG_STRING(DBG_INFO,"Routing pkt to: ");
            DEBUG_UINT16(DBG_INFO,newDstSADDR);
			if (a_nwk_tx_data.dstSADDR != LRWPAN_BCAST_SADDR) {
				//not broadcast address
				newDstSADDR = ntFindNewDst(a_nwk_tx_data.dstSADDR);
				DEBUG_STRING(DBG_INFO," through: ");
                DEBUG_UINT16(DBG_INFO,newDstSADDR);
				if (newDstSADDR == LRWPAN_BCAST_SADDR) {
					DEBUG_STRING(DBG_INFO,", UNROUTABLE, error!\n ");
					//error indicator. An unroutable packet from here.
					a_mac_service.args.error.status = LRWPAN_STATUS_NWK_PACKET_UNROUTABLE;
					a_mac_service.cmd = LRWPAN_SVC_MAC_ERROR;
					goto nwkTxData_sendit;
				}
				DEBUG_STRING(DBG_INFO,"\n");
			}

			//fill it in.
			a_mac_tx_data.fcfmsb = LRWPAN_FCF_DSTMODE_SADDR|LRWPAN_FCF_SRCMODE_LADDR;
			a_mac_tx_data.DestAddr.saddr = newDstSADDR;
		}
#endif

	}


	//for data frames, we want a MAC level ACK, unless it is a broadcast.
	if ( ((LRWPAN_GET_DST_ADDR(a_mac_tx_data.fcfmsb)) == LRWPAN_ADDRMODE_SADDR) &&
		a_mac_tx_data.DestAddr.saddr == LRWPAN_BCAST_SADDR) {
			//no MAC ACK
			a_mac_tx_data.fcflsb = LRWPAN_FRAME_TYPE_DATA|LRWPAN_FCF_INTRAPAN_MASK ;
		}else {
			a_mac_tx_data.fcflsb = LRWPAN_FRAME_TYPE_DATA|LRWPAN_FCF_INTRAPAN_MASK |LRWPAN_FCF_ACKREQ_MASK;
		}

		//send it.
		a_mac_service.cmd = LRWPAN_SVC_MAC_GENERIC_TX;



nwkTxData_sendit:

		macDoService();

}



static void nwkRxFSM(void) {
	BYTE *ptr;

nwkRxFSM_start:

	switch(nwkRxState) {
		case NWK_RXSTATE_IDLE:
			break;
		case NWK_RXSTATE_START:
			//we have a packet, lets check it out.
			ptr = a_nwk_rx_data.orgpkt.data + a_nwk_rx_data.nwkOffset;
			if (NWK_IS_CMD(*ptr)) {
				//currently don't handle CMD packets. Discard.
				DEBUG_STRING(DBG_INFO,"NWK: Received NWK CMD packet, discarding.\n");
				//MAC resource already free; need to free the MEM resource
				MemFree(a_nwk_rx_data.orgpkt.data);
				nwkRxState = NWK_RXSTATE_IDLE;
				break;
			}
			//this is a data packet. do more parsing.
			nwkParseHdr(ptr);

			//see if this is for us.
			if ((a_nwk_rx_data.dstSADDR == LRWPAN_BCAST_SADDR) ||
				(a_nwk_rx_data.dstSADDR == LRWPAN_SADDR_USE_LADDR) ||
				(a_nwk_rx_data.dstSADDR == macGetShortAddr())) {
					//hand this off to the APS layer
					nwkRxState = NWK_RXSTATE_APS_HANDOFF;
				} else {
					//have to route this packet
					nwkRxState = NWK_RXSTATE_DOROUTE;
				}
				goto nwkRxFSM_start;

		case NWK_RXSTATE_APS_HANDOFF:
			if (apsRxBusy()) break;    //apsRX is still busy
			//handoff the current packet
			apsRxHandoff();
			//we are finished with this packet.
			//we don't need to do anything to free this resource other
			// than to change state
			nwkRxState = NWK_RXSTATE_IDLE;
			break;


		case NWK_RXSTATE_DOROUTE:
#ifdef LRWPAN_RFD
			//RFD somehow got a data packet not intended for it.
			//should never happen, but put code here anyway to discard it.
			DEBUG_STRING(DBG_INFO,"NWK: RFD received spurious datapacket, discarding.\n");
			MemFree(a_nwk_rx_data.orgpkt.data);
			nwkRxState = NWK_RXSTATE_IDLE;
#else
			//first, check the radius, if zero, then discard.
			if (!(*(ptr+6))) {
				DEBUG_STRING(DBG_INFO,"NWK: Data packet is out of hops for dest: ");
				DEBUG_UINT16(DBG_INFO,a_nwk_rx_data.dstSADDR);
                DEBUG_STRING(DBG_INFO,", discarding...\n");
				MemFree(a_nwk_rx_data.orgpkt.data);
				nwkRxState = NWK_RXSTATE_IDLE;
				break;
			}
			DEBUG_STRING(DBG_INFO,"NWK: Routing NWK Packet to: ");
			DEBUG_UINT16(DBG_INFO,a_nwk_rx_data.dstSADDR);
			DEBUG_STRING(DBG_INFO,"\n");
			//this packet requires routing, not destined for us.
			if (nwkRxBuffFull()) {
				//no more room. discard this packet
				DEBUG_STRING(DBG_INFO,"NWK: FWD buffer full, discarding pkt.\n");
				DEBUG_STRING(DBG_INFO,"NWK state: ");
				DEBUG_UINT8(DBG_INFO,nwkState);
				DEBUG_STRING(DBG_INFO,"MAC state: ");
				DEBUG_UINT8(DBG_INFO,macState);
				DEBUG_STRING(DBG_INFO,"\n");
				MemFree(a_nwk_rx_data.orgpkt.data);
				nwkRxState = NWK_RXSTATE_IDLE;
			}else {
				//ok, add this pkt to the buffer
				nwk_pib.rxHead++;
				if (nwk_pib.rxHead == NWK_RXBUFF_SIZE) nwk_pib.rxHead = 0;
				//save it.
				nwk_pib.rxBuff[nwk_pib.rxHead].data = a_nwk_rx_data.orgpkt.data;
				nwk_pib.rxBuff[nwk_pib.rxHead].nwkOffset = a_nwk_rx_data.nwkOffset;
				nwkRxState = NWK_RXSTATE_IDLE;
				//this packet will be retransmitted by nwkFSM
			}

#endif

			break;

		default:
			break;

	}


}



//Callback from MAC Layer
//Returns TRUE if nwk is still busy with last RX packet.

BOOL nwkRxBusy(void){
	return(nwkRxState != NWK_RXSTATE_IDLE);
}

//Callback from MAC Layer
//Hands off parsed packet from MAC layer, frees MAC for parsing
//next packet.
void nwkRxHandoff(void){

	a_nwk_rx_data.orgpkt.data = a_mac_rx_data.orgpkt->data;
	a_nwk_rx_data.orgpkt.rssi = a_mac_rx_data.orgpkt->rssi;
	a_nwk_rx_data.nwkOffset = a_mac_rx_data.pload_offset;
	nwkRxState = NWK_RXSTATE_START;
}

static void nwkParseHdr(BYTE *ptr) {

	//ptr is pointing at nwk header. Get the SRC/DST nodes.
	ptr= ptr+2;
	//get Dst SADDR
	a_nwk_rx_data.dstSADDR = *ptr;
	ptr++;
	a_nwk_rx_data.dstSADDR += (((UINT16)*ptr) << 8);
	ptr++;

	//get Src SADDR
	a_nwk_rx_data.srcSADDR = *ptr;
	ptr++;
	a_nwk_rx_data.srcSADDR += (((UINT16)*ptr) << 8);
	ptr++;


}

#ifdef LRWPAN_FFD

//copies packet to forward from heap space to TXbuffer space
void nwkCopyFwdPkt(void){
	BYTE *srcptr, len;
	NWK_FWD_PKT *pkt;

	phy_pib.currentTxFrm = &tmpTxBuff[LRWPAN_MAX_FRAME_SIZE];
	//get next PKT
	pkt = nwkGetRxPacket();
	
	srcptr = pkt->data;  //points at original packet in heapspace

	//compute bytes to copy.
	//nwkoffset is the offset of the nwkheader in the original packet
	len = *(srcptr) - pkt->nwkOffset - PACKET_FOOTER_SIZE + 1 ;


	//point this one byte past the end of the packet
	srcptr = srcptr
		+ *(srcptr) //length of original packet, not including this byte
		+ 1         //add one for first byte which contains packet length
		- PACKET_FOOTER_SIZE; //subtract footer bytes, don't want to copy these.
	//save length
	phy_pib.currentTxFlen = len;
	//copy from heap space to TXBuffer space
	do {
		srcptr--; phy_pib.currentTxFrm--;
		*phy_pib.currentTxFrm = *srcptr;
		len--;
	}while(len);
	nwkFreeRxPacket(TRUE);  //free this packet
	//some final steps
	//get the dstSADDR, needed for routing.
	a_nwk_tx_data.dstSADDR = *(phy_pib.currentTxFrm+2);
	a_nwk_tx_data.dstSADDR += (((UINT16)*(phy_pib.currentTxFrm+3)) << 8);

	//decrement the radius before sending it on.
	*(phy_pib.currentTxFrm+6)= *(phy_pib.currentTxFrm+6)- 1;
	a_nwk_tx_data.radius = *(phy_pib.currentTxFrm+6);

	
	//leave the SADDR unchanged as we want to know where this originated from!
#if 0
	//replace the SADDR with our SADDR
	*(phy_pib.currentTxFrm+4) = (BYTE) macGetShortAddr();
	*(phy_pib.currentTxFrm+5) = (BYTE) (macGetShortAddr() >>8);
#endif

}

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

static BOOL nwkRxBuffEmpty(void){
	return(nwk_pib.rxTail == nwk_pib.rxHead);
}

//this does NOT remove the packet from the buffer
static NWK_FWD_PKT *nwkGetRxPacket(void) {
	BYTE tmp;
	if (nwk_pib.rxTail == nwk_pib.rxHead) return(NULL);
	tmp = nwk_pib.rxTail+1;
	if (tmp == NWK_RXBUFF_SIZE) tmp = 0;
	return(&nwk_pib.rxBuff[tmp]);
}

//frees the first packet in the buffer.
static void nwkFreeRxPacket(BOOL freemem) {
	nwk_pib.rxTail++;
	if (nwk_pib.rxTail == NWK_RXBUFF_SIZE) nwk_pib.rxTail = 0;
	if (freemem) MemFree(nwk_pib.rxBuff[nwk_pib.rxTail].data);
}

#endif

//given a router child SADDR, find the parent router SADDR
UINT16 nwkFindParentSADDR(SADDR childSADDR) {

	UINT8 currentDepth;
	SADDR currentParent;
	SADDR currentRouter;
	SADDR maxSADDR;
	UINT8 i;


	currentDepth = 1;
	currentParent = 0;
	do {
		for (i=0; i<LRWPAN_MAX_ROUTERS_PER_PARENT; i++) {
			if (i==0) currentRouter = currentParent+1;
			else currentRouter += ntGetCskip(currentDepth);
			if (childSADDR == currentRouter) return(currentRouter);
			maxSADDR = ntGetMaxSADDR(currentRouter,currentDepth+1);
			if ((childSADDR > currentRouter) && (childSADDR <= maxSADDR))
				break; //must go further down the tree
		}
		currentDepth++;
		currentParent = currentRouter;
	}
	while (currentDepth < LRWPAN_MAX_DEPTH-1);
	//if we reach here, could not find an address. Return 0 as an error
	return(0);
}

UINT16 nwkGetHopsToDest(SADDR dstSADDR){

	UINT16 numHops;
	SADDR currentParent, maxSADDR;
	UINT8 currentDepth;
	UINT8 i;
	SADDR currentRouter;

	numHops = 1;            //return a minimum value of 1

	currentDepth = 0;
	//first compute hops up the tree then down the tree
	if ( macGetShortAddr() == 0) goto nwkGetHopsToDest_down;  //this is the coordinator
	if (macGetShortAddr() == dstSADDR) return(1);  //to myself, should not happen, but return min value
	currentParent = mac_pib.macCoordShortAddress; //start with my parent address
	currentDepth = mac_pib.depth - 1; //depth of my parent.
	do {
		if (currentParent == dstSADDR) return(numHops);  //destination is one of my parent nodes.
		if (currentParent == 0) break;         //at coordinator.
		//compute the max SADDR address range of parent

		maxSADDR = ntGetMaxSADDR(currentParent,currentDepth+1);  //depth of parent's children
		if ((dstSADDR > currentParent) &&  (dstSADDR <= maxSADDR)) {
			//this address is in this router's range, stop going up.
			break;
		}
		//go up a level
		currentDepth--;
		numHops++;
		if (currentDepth == 0 ) currentParent =0;
		else { currentParent = nwkFindParentSADDR(currentParent);
		if (!currentParent) {
			//could not find, set numHops to maximum and return
			return(LRWPAN_MAX_DEPTH<<1);
		}
		}
	}while(1);

nwkGetHopsToDest_down:
	currentDepth++; //increment depth, as this should reflect my current children
	//now search going down.
	do {
		//destination is in the current parent's range
		//see if it is one of the routers or children.
		//first see if it is one of the children of current parent
		numHops++;
		maxSADDR = ntGetMaxSADDR(currentParent,currentDepth);
		if (dstSADDR > (maxSADDR-LRWPAN_MAX_NON_ROUTER_CHILDREN) &&
			dstSADDR <= maxSADDR) break;  //it is one of the children nodes
		for (i=0; i<LRWPAN_MAX_ROUTERS_PER_PARENT; i++) {
			if (i==0) currentRouter = currentParent+1;
			else currentRouter += ntGetCskip(currentDepth);

			if (dstSADDR == currentRouter) return(currentRouter);
			maxSADDR = ntGetMaxSADDR(currentRouter,currentDepth+1);
			if ((dstSADDR > currentRouter) && (dstSADDR <= maxSADDR))
				break; //must go further down the tree
		}
		if (i == LRWPAN_MAX_ROUTERS_PER_PARENT) {
			//must be one of my non-router children, increment hops, return
			return(numHops);
		}
		currentDepth++;
		currentParent = currentRouter;

	}while(currentDepth < LRWPAN_MAX_DEPTH-1);

	if (numHops > LRWPAN_NWK_MAX_RADIUS) {
		DEBUG_STRING(DBG_ERR,"nwkGetHopsToDest: Error in hop calculation: ");
		DEBUG_UINT8(DBG_ERR,numHops);
		DEBUG_STRING(DBG_ERR,"\n");
		numHops = LRWPAN_NWK_MAX_RADIUS-1;
	}
	return(numHops);
}







⌨️ 快捷键说明

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