📄 router.c
字号:
#include <string.h>#include "zigbee.h" // Zigbee defs#if defined(MCHP_C18)#include <stdio.h>#endif#include "msstate.h"#include "sralloc.h"#include "Console.h"#include "bugfix.h"#include "board.h"#include "router.h"#include "app.h"#define BIND_WAIT_DURATION (6*TICK_SECOND)#define MAX_MESSAGE_WAIT (1*TICK_SECOND)BYTE current_channel;static int channel_map = 0xFFFF;static ZCODE MSU_ConfigTask(void);ROM char * const configFailedMsg = "Config failed. Press Reset\r\n";ROM char * const rejoinSuccessMsg = "Rejoin successful.\r\n";ROM char * const rejoinFailedMsg = "Rejoin failed.\r\n";ROM char * const initMsg = "\r\nDoing network initialization\r\n";ROM char * const joinAttemptMsg = "Attempting to join a coordinator...\r\n";ROM char * const associateSuccessMsg = "\r\nSuccessfully associated.\r\n";ROM char * const associateFailMsg = "\r\nFailed to associate.\r\n";ROM char * const demoBindCompleteMsg = "Demo binding complete.\r\n";ROM char * const demoBindFailedMsg = "\r\nBinding failed. Not associated?\r\n";ROM char * const macAddrNowAssignedMsg = "MAC Address has now been assigned...\r\n";ROM char * const macAddrNotAssignedMsg = "MAC Address is not assigned, auto setting MAC address...\r\n";ROM char * const newNodeJoinedMsg = "A new node has just joined.\r\n";ROM char * const newNodeRejoinedMsg = "A familiar node has just rejoined.\r\n";ROM char * const nodeLeftMsg = "A node has left the network.\r\n";#define COORD_SHORT_ADDR 0void InitializeNetwork(void){ APP_STATE smApp; CLRWDT(); // This is to initialize tick manager required for Zigbee stack modules. TickInit(); // turn the LEDs off. D2 used to indicate transmission activity // we will turn on D1 when we join a network. On a successful bind or first message // recieved, it will be turned off. D1 = 0; D2 = 0; // This demo application uses S3 switch to enter into configuration mode. // Actual application may implelement any logic to select configuratoin mode // or may not have any - completely application dependent. if ( S3 == 0 ) appFlags.bits.bInConfigMode = TRUE; // If MAC long address is not assigned, enter configuration by default. if ( !IsMACAddrAssigned() ) { ConsolePutROMString(macAddrNotAssignedMsg); //appFlags.bits.bInConfigMode = TRUE; DISABLE_WDT(); AutoSetNodeId(MAC_LONG_ADDR_BYTE3,MAC_LONG_ADDR_BYTE2, MAC_LONG_ADDR_BYTE1, MAC_LONG_ADDR_BYTE0); //auto set the node id ENABLE_WDT(); ConsolePutROMString(macAddrNowAssignedMsg); } sprintf(tmpbuf,(ROM char *)"Node ID: 0x%02x%02x%02x%02x\n\r", MAC_LONG_ADDR_BYTE3,MAC_LONG_ADDR_BYTE2, MAC_LONG_ADDR_BYTE1,MAC_LONG_ADDR_BYTE0); ConsolePutString((BYTE *)tmpbuf); // This is main Zigbee stack initialization call. // MAC will be in disable state until enabled. APLInit(); // Enable global interrupts. GIEL = 1; GIEH = 1; // We have to enable MAC separately. This way you can disable and enable as per your // requirement. APLEnable(); // Start with Init state. smApp = SM_APP_INIT; // this will exit after network is started smApp = SM_APP_INIT; while( smApp != SM_APP_NORMAL_START ) { // Toggle RA4 to indicate how long we execute this loop LATA4 ^= 1; // Keep watchdog happy CLRWDT(); // This is the main stack task, responsible for Zigbee stack related functionality. // This function must be called before all Zigbee tasks. // Actual application task functions can be called in any order. APLTask(); KeepRxAlive(); // This demo application provides two modes of operations - config and normal. // In config mode, this node will attempt to associate with available coordinator. // In normal mode, it will simply rejoin previously associated coordinator. // You may change this logic as per your application requirements. switch(smApp) { case SM_APP_INIT: // If S3 was pressed on startup, go to config mode. if ( appFlags.bits.bInConfigMode == TRUE ) smApp = SM_APP_CONFIG_START; // Or else go join a network else smApp = SM_APP_NET_JOIN; break; case SM_APP_CONFIG_START: // While in config mode, disable watchdog. // Normally, you would want to keep watchdog enabled all the time, but in this demo that would // amount to increased complexity and make this demo difficult to understand. // Actual application code may afford extra complexity. DISABLE_WDT(); // This is a blocking call. Note that watchdog is already disabled. if (MSU_ConfigTask() != ZCODE_NO_ERROR) { // we have failed ConsolePutROMString(configFailedMsg); while(1); } // Mark that we are no longer in config mode. appFlags.bits.bInConfigMode = FALSE; smApp = SM_APP_NORMAL_START; // After config mode, enable watchdog ENABLE_WDT(); break; case SM_APP_NET_JOIN: // This node will try to rejoin previously associated network. // This will make sure that we join to a known network. // Actual logic would depend on the application requirements. APLRejoin(); smApp = SM_APP_NET_JOIN_WAIT; break; case SM_APP_NET_JOIN_WAIT: // See if rejoin is complete. if ( APLIsRejoinComplete() ) { // If there was no error, continue with normal logic. // Or else handle as per application requirements. if ( GetLastZError() == ZCODE_NO_ERROR ) { ConsolePutROMString(rejoinSuccessMsg); smApp = SM_APP_NORMAL_START; } // else there was an error and needs to be addressed. else { ConsolePutROMString(rejoinFailedMsg); // This action would depend on application. // lets try disabling WDT, and doing reset DISABLE_WDT(); RESET(); } } break; } }}// If S3 button held down on reset, then try to join a network// this version DOES NOT TRY TO BIND#define NETWORK_JOIN_TIME (TICK_SECOND*5)static ZCODE MSU_ConfigTask(void){ ZCODE errcode; TICK startTime; BYTE last_channel; errcode = 0; ConsolePutROMString(initMsg); // While in config mode, disable PORTB interrupt-on-change. RBIE = 0; // current_channel is set in our AppOkayToUseChannel() callback last_channel = current_channel; // Wait for S3 to get released while( S3 == 0 ); startTime = TickGet(); // try to join network ConsolePutROMString(joinAttemptMsg); // Enable Watchdog to catch any lock-ups. ENABLE_WDT(); APLJoin(); while(1) { CLRWDT(); APLTask(); KeepRxAlive(); if ( APLIsJoinComplete() ) { errcode = GetLastZError(); if ( errcode == ZCODE_NO_ERROR ) { D1 = 1; //turn on to indicate network joined ConsolePutROMString(associateSuccessMsg); } else{ ConsolePutROMString(associateFailMsg); } break; } // the channel_map variable is used to keep track of channels // where a coordinator has rejected us so we can try the next one if (TickGetDiff(TickGet(), startTime) > NETWORK_JOIN_TIME) { //hmmm...coordinator responding, but rejecting us. if (current_channel == 26) { DISABLE_WDT(); sprintf(tmpbuf,(ROM char *)"Timeout Rejection on Channel %d, giving up\n\r", current_channel); ConsolePutString((BYTE *)tmpbuf); return(ZCODE_CHANNEL_BUSY); // return any code that is not NO_ERROR } else { // lets mark this channel as bad channel_map = channel_map & ~(1 << (current_channel - 11)); } } if (last_channel != current_channel) { //trying a different channel, restart timer startTime = TickGet(); last_channel = current_channel; } }//end while(1) if (errcode != ZCODE_NO_ERROR) { // Disable watchdog before returning. DISABLE_WDT(); } return(errcode);}// Callback to an end device.// Called when a suitable coordinator is found as part of associate process.// Return TRUE if okay to associate.// May use PANDesc.for more information about this coordinator.// See MAC.h for definition of PANDesc.BOOL AppOkayToAssociate(void){ return TRUE;}ROM char * const channel_fmt = "In channel: %d\r\n" ;ROM char * const reject_channel_fmt = "Rejecting channel: %d\r\n" ;BOOL AppOkayToUseChannel(BYTE channel){ // This demo uses all available channels // You may check given channel against your allowable channels and return TRUE // or FALSE as needed. // For 2.4GHz, channel = 11 through 26. // see if its ok to use this channel // Channel map is used by MSU_ConfigTask to try different channels current_channel = channel; if ( channel_map & (((int)1) << (channel - 11))) { sprintf(tmpbuf,channel_fmt,channel); ConsolePutString((BYTE *)tmpbuf); return TRUE; } else { sprintf(tmpbuf,reject_channel_fmt,channel); ConsolePutString((BYTE *)tmpbuf); return FALSE; }}// Callback to application to noify of new node joining our network.void AppNewNodeJoined(LONG_ADDR *nodeAddr, BOOL bIsRejoined){ // A new node has just joined (or rejoined). // In this demo application, once a new node has joined, we want to save its // association permanently into NVM. if ( bIsRejoined == FALSE ) { // You may want to check the nodeAddr and do something specific based // on that node. This demo app does not any do anything special. APLCommitTableChanges(); // Display that a new node has joined. ConsolePutROMString(newNodeJoinedMsg); } else { // Display that a previous node has rejoined. ConsolePutROMString(newNodeRejoinedMsg); }}// Callback to application to notify if this node should be accepted to our network.BOOL AppOkayToAcceptThisNode(LONG_ADDR *longAddr){ // THIS HAS BEEN MODIFIED FROM THE ORIGINAL DEMO WHICH ACCEPTED ALL NODES! // modified to only accept nodes whose Long address bytes // v[2] thru v[7] match ours for rejection while testing // use the LSByte to force a RFD node to join the router instead of // of a coordinator. This is for demo purposes only so that the RFD // does not have to physically out of range of the router if ((longAddr->v[0] < 0x80) && (macInfo.longAddr.v[2] == longAddr->v[2]) && (macInfo.longAddr.v[3] == longAddr->v[3]) && (macInfo.longAddr.v[4] == longAddr->v[4]) && (macInfo.longAddr.v[5] == longAddr->v[5]) && (macInfo.longAddr.v[6] == longAddr->v[6]) && (macInfo.longAddr.v[7] == longAddr->v[7]) ) { return TRUE; } else { return FALSE; }}// Callback to application to notify that a node has left the network.void AppNodeLeft(LONG_ADDR *nodeAddr){ // Display a message that a node has left the network. ConsolePutROMString(nodeLeftMsg); // Update our NVM table. APLCommitTableChanges(); // Do application specific action here.}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -