SWRA734 December 2021 CC1312PSIP , CC1312R , CC1312R7 , CC1314R10 , CC1352P , CC1352P7 , CC1352R , CC1354P10 , CC1354R10 , CC2652P , CC2652P7 , CC2652R , CC2652RB , CC2652RSIP
For this particular scenario, it is enough to modify the application layer of the sensor device for a basic implementation of PAN coordinator switching.
static void abandonNetwork(void);
/* Maximum score used to evaluate a channel when looking for second coordinator */
#define JDLLC_MAX_ENERGY 255
#define JDDLC_MAX_RECONNECTION_ATTEMPTS 5
The first macro definition is used as a starting point for the energy detect scans that the sensor device must execute. And the second macro definition indicates the number of times the sensor will attempt to reconnect to its original PAN coordinator before switching to a different PAN coordinator.
void abandonNetwork(void)
{
/* stop polling */
if(!CONFIG_RX_ON_IDLE)
{
Ssf_setPollClock(0);
}
/* enable looking for new parent */
parentFound = false;
/* set devInfoBlock back to defaults */
devInfoBlock.panID = CONFIG_PAN_ID;
devInfoBlock.channel = JDLLC_INVALID_CHANNEL;
if(!CONFIG_FH_ENABLE)
{
devInfoBlock.coordShortAddr = 0xFFFF;
}
else
{
devInfoBlock.coordShortAddr = FH_COORD_SHORT_ADDR;
}
#ifdef FEATURE_MAC_SECURITY
ApiMac_secDeleteDevice(&devInfoBlock.devExtAddr);
#endif
/* Reset devInfoBlock to default values */
memset(&devInfoBlock.coordExtAddr[0], 0x00, APIMAC_SADDR_EXT_LEN);
devInfoBlock.devShortAddr = 0xFFFF;
memset(&devInfoBlock.devExtAddr[0], 0x00, APIMAC_SADDR_EXT_LEN);
devInfoBlock.beaconOrder = CONFIG_MAC_BEACON_ORDER;
devInfoBlock.superframeOrder = CONFIG_MAC_SUPERFRAME_ORDER;
devInfoBlock.currentDevState = Jdllc_deviceStates_scanActive;
devInfoBlock.prevDevState = Jdllc_deviceStates_scanActive;
devInfoBlock.dataFailures = 0;
devInfoBlock.pollInterval = CONFIG_POLLING_INTERVAL;
/* Stop the reporting timer */
Ssf_setReadingClock(0);
Ssf_clearNetworkInfo();
}
This function could be described as a “hard” disassociation that does not require an acknowledge from the PAN coordinator. This type of disassociation is valid in this case, because the PAN coordinator is no longer reachable and the sensor considers that it no longer exists.
For this particular case, the coordinator switching takes place after the sensor has repeatedly attempted to reconnect with its PAN coordinator using orphan scans. Once the number of failed orphan scans reaches the limit defined by the JDDLC_MAX_RECONNECTION_ATTEMPTS macro, the sensor makes a call to abandonNetwork()and triggers an energy detect scan.
The energy detect scan is used to perform an energy measurement on all available channels. If there is another PAN coordinator operating in one of those channels, the sensor device will tune to that channel and trigger either an active scan (Non-Beacon mode) or a passive scan (Beacon mode). Once this occurs, the sensor joins the new PAN coordinator.
static void scanCnfCb(ApiMac_mlmeScanCnf_t *pData)
{
if(pData->status == ApiMac_status_success)
{
if(pData->scanType == ApiMac_scantype_active)
{
// Existing code in the example
}
// Existing code in the example
else if(pData->scanType == ApiMac_scantype_energyDetect)
{
uint8_t *pResults;
uint8_t chan;
uint8_t currEnergy;
uint8_t lastEnergy = JDLLC_MAX_ENERGY;
uint8_t coordStartChan = 0;
pResults = pData->result.pEnergyDetect;
/* Get channel with best energy level */
for(chan = 0; chan < APIMAC_154G_MAX_NUM_CHANNEL; chan++)
{
/*
* A measured RSSI value is converted to a score between 0 and 255,
* using the minimum measured RSSI (-90 dBm) and saturation
* energy (-5 dBm) values and the formula:
* ED = (255 * (RSSI + 90))/85. A lower energy detect
* measurement represents a more suitable channel.
*/
if(JDLLC_IS_CHANNEL_MASK_SET(defaultChannelMask, chan))
{
currEnergy = pResults[chan];
if(currEnergy < lastEnergy)
{
coordStartChan = chan;
lastEnergy = currEnergy;
}
}
}
ApiMac_mlmeSetReqUint8(ApiMac_attribute_logicalChannel,
coordStartChan);
panIdMatch = true;
if(CONFIG_MAC_BEACON_ORDER == JDLLC_BEACON_ORDER_NON_BEACON)
{
/* non beacon network */
sendScanReq(ApiMac_scantype_active);
}
else if((CONFIG_MAC_BEACON_ORDER > 0) &&
(CONFIG_MAC_BEACON_ORDER < JDLLC_BEACON_ORDER_NON_BEACON))
{
/* beacon network */
updateState(Jdllc_states_joining);
sendScanReq(ApiMac_scantype_passive);
}
}
else
{
// Existing code in the example
if(((pData->scanType == ApiMac_scantype_orphan) && (pData->status
== ApiMac_status_noBeacon)))
{
static uint8_t orphanCounter;
if (orphanCounter <= JDDLC_MAX_RECONNECTION_ATTEMPTS)
{
devInfoBlock.prevDevState = devInfoBlock.currentDevState;
Ssf_setScanBackoffClock(CONFIG_ORPHAN_BACKOFF_INTERVAL);
orphanCounter++;
}
else
{
/* Give up trying to reconnect to the same coordinator
* and abandon network */
abandonNetwork();
panIdMatch = false;
/* Perform an ED scan to check available channels */
sendScanReq(ApiMac_scantype_energyDetect);
orphanCounter = 0;
}
}
}
// Existing code in the example
}