/** \brief Find neighbor to which to send KA. This function iterates through the neighbor table and identifies the neighbor we need to send a KA to, if any. This neighbor satisfies the following conditions: - it is one of our preferred parents - we haven't heard it for over \return A pointer to te neighbor's address, or NULL if no KA is needed. */ open_addr_t* neighbors_KaNeighbor() { uint8_t i; uint16_t timeSinceHeard; open_addr_t* addrPreferred; open_addr_t* addrOther; // initialize addrPreferred = NULL; addrOther = NULL; // scan through the neighbor table, and populate addrPreferred and addrOther for (i=0;i<MAXNUMNEIGHBORS;i++) { if (neighbors_vars.neighbors[i].used==1) { timeSinceHeard = ieee154e_asnDiff(&neighbors_vars.neighbors[i].asn); if (timeSinceHeard>KATIMEOUT) { // this neighbor needs to be KA'ed if (neighbors_vars.neighbors[i].parentPreference==MAXPREFERENCE) { // its a preferred parent addrPreferred = &(neighbors_vars.neighbors[i].addr_64b); } else { // its not a preferred parent // poipoi: don't KA to non-preferred parent //addrOther = &(neighbors_vars.neighbors[i].addr_64b); } } } } // return the addr of the most urgent KA to send if (addrPreferred!=NULL) { return addrPreferred; } else if (addrOther!=NULL) { return addrOther; } else { return NULL; } }
/** \brief Calculated how many slots have elapsed since last synchronized. \param[in] timeCorrection time to be corrected \param[in] timesource The address of neighbor. \return the number of slots */ void adaptive_sync_preprocess(int16_t timeCorrection, open_addr_t timesource){ uint8_t array[5]; // stop calculating compensation period when compensateThreshold exceeds KATIMEOUT and drift is not changed if( adaptive_sync_vars.compensateThreshold > MAXKAPERIOD && adaptive_sync_vars.driftChanged == FALSE ) { if(timeCorrection > LIMITLARGETIMECORRECTION) { //once I get a large time correction, it means previous calcluated drift is not accurate yet. The clock drift is changed. adaptive_sync_driftChanged(); } return; } // check whether I am synchronized and also check whether it's the same neighbor synchronized to last time? if( adaptive_sync_vars.driftChanged == FALSE && ieee154e_isSynch() && packetfunctions_sameAddress(×ource, &(adaptive_sync_vars.compensationInfo_vars.neighborID)) ) { // only calcluate when asnDiff > compensateThresholdThreshold. (this is used for guaranteeing accuracy ) if(ieee154e_asnDiff(&adaptive_sync_vars.oldASN) > adaptive_sync_vars.compensateThreshold) { // calculate compensation interval adaptive_sync_calculateCompensatedSlots(timeCorrection); // reset compensationtTicks and sumOfTC after calculation adaptive_sync_vars.compensateTicks = 0; adaptive_sync_vars.sumOfTC = 0; // update threshold adaptive_sync_vars.compensateThreshold *= 2; sixtop_setKaPeriod(adaptive_sync_vars.compensateThreshold); // update oldASN ieee154e_getAsn(array); adaptive_sync_vars.oldASN.bytes0and1 = ((uint16_t) array[1] << 8) | ((uint16_t) array[0]); adaptive_sync_vars.oldASN.bytes2and3 = ((uint16_t) array[3] << 8) | ((uint16_t) array[2]); adaptive_sync_vars.oldASN.byte4 = array[4]; } else { // record the timeCorrection, if not calculate. adaptive_sync_vars.sumOfTC += timeCorrection; } } else { adaptive_sync_vars.compensateThreshold = BASIC_COMPENSATION_THRESHOLD; sixtop_setKaPeriod(adaptive_sync_vars.compensateThreshold); // when I joined the network, or changed my time parent, reset adaptive_sync relative variables adaptive_sync_vars.clockState = S_NONE; adaptive_sync_vars.elapsedSlots = 0; adaptive_sync_vars.compensationTimeout = 0; adaptive_sync_vars.compensateTicks = 0; adaptive_sync_vars.sumOfTC = 0; // update oldASN ieee154e_getAsn(array); adaptive_sync_vars.oldASN.bytes0and1 = ((uint16_t) array[1] << 8) | ((uint16_t) array[0]); adaptive_sync_vars.oldASN.bytes2and3 = ((uint16_t) array[3] << 8) | ((uint16_t) array[2]); adaptive_sync_vars.oldASN.byte4 = array[4]; // record this neighbor as my time source memcpy(&(adaptive_sync_vars.compensationInfo_vars.neighborID), ×ource, sizeof(open_addr_t)); } }
/** \brief Calculate the compensation interval, in number of slots. \param[in] timeCorrection time to be corrected \returns compensationSlots the number of slots. */ void adaptive_sync_calculateCompensatedSlots(int16_t timeCorrection) { bool isFirstSync; // is this the first sync after joining network? uint16_t totalTimeCorrectionTicks; // how much error in ticks since last synchronization. if(adaptive_sync_vars.clockState == S_NONE) { isFirstSync = TRUE; } else { isFirstSync = FALSE; } adaptive_sync_vars.elapsedSlots = ieee154e_asnDiff(&adaptive_sync_vars.oldASN); if(isFirstSync) { if(timeCorrection > 1) { adaptive_sync_vars.clockState = S_FASTER; adaptive_sync_vars.compensationInfo_vars.compensationSlots = SYNC_ACCURACY*adaptive_sync_vars.elapsedSlots; adaptive_sync_vars.compensationInfo_vars.compensationSlots /= timeCorrection; } else { if(timeCorrection < -1) { adaptive_sync_vars.clockState = S_SLOWER; adaptive_sync_vars.compensationInfo_vars.compensationSlots = SYNC_ACCURACY*adaptive_sync_vars.elapsedSlots; adaptive_sync_vars.compensationInfo_vars.compensationSlots /= (-timeCorrection); } else { //timeCorrection = {-1,1}, it's not accurate when timeCorrection belongs to {-1,1} //nothing is needed to do with this case. } } } else { if(adaptive_sync_vars.clockState == S_SLOWER) { totalTimeCorrectionTicks = adaptive_sync_vars.compensateTicks; totalTimeCorrectionTicks -= timeCorrection+adaptive_sync_vars.sumOfTC; } else { totalTimeCorrectionTicks = adaptive_sync_vars.compensateTicks; totalTimeCorrectionTicks += timeCorrection+adaptive_sync_vars.sumOfTC; } if(totalTimeCorrectionTicks == 0) { // totalTimeCorrectionTicks should be always positive if drift of clock is constant. if totalTimeCorrectionTIcks become zero, it means the drift changed for some reasons. adaptive_sync_driftChanged(); } else { adaptive_sync_vars.compensationInfo_vars.compensationSlots = SYNC_ACCURACY*adaptive_sync_vars.elapsedSlots; adaptive_sync_vars.compensationInfo_vars.compensationSlots /= totalTimeCorrectionTicks; } } adaptive_sync_vars.compensationTimeout = adaptive_sync_vars.compensationInfo_vars.compensationSlots; }
/** \brief Find neighbor to which to send KA. This function iterates through the neighbor table and identifies the neighbor we need to send a KA to, if any. This neighbor satisfies the following conditions: - it is one of our preferred parents - we haven't heard it for over kaPeriod \param[in] kaPeriod The maximum number of slots I'm allowed not to have heard it. \returns A pointer to the neighbor's address, or NULL if no KA is needed. */ open_addr_t* neighbors_getKANeighbor(uint16_t kaPeriod) { uint8_t i; uint16_t timeSinceHeard; open_addr_t* addrPreferred; open_addr_t* addrOther; // initialize addrPreferred = NULL; addrOther = NULL; // scan through the neighbor table, and populate addrPreferred and addrOther for (i=0;i<MAXNUMNEIGHBORS;i++) { if (neighbors_vars.neighbors[i].used==1) { timeSinceHeard = ieee154e_asnDiff(&neighbors_vars.neighbors[i].asn); if (timeSinceHeard>kaPeriod) { // this neighbor needs to be KA'ed to if (neighbors_vars.neighbors[i].parentPreference==MAXPREFERENCE) { // its a preferred parent addrPreferred = &(neighbors_vars.neighbors[i].addr_64b); } else { // its not a preferred parent // Note: commented out since policy is not to KA to non-preferred parents // addrOther = &(neighbors_vars.neighbors[i].addr_64b); } } } } // return the EUI64 of the most urgent KA to send: // - if available, preferred parent // - if not, non-preferred parent if (addrPreferred!=NULL) { return addrPreferred; } else if (addrOther!=NULL) { return addrOther; } else { return NULL; } }
void light_trigger_SENSOR(void) { bool iShouldSend; uint8_t pktId; #ifdef LIGHT_FAKESEND uint16_t numAsnSinceLastEvent; #else callbackRead_cbt light_read_cb; #endif #ifdef LIGHT_FAKESEND // how many cells since the last time I transmitted? numAsnSinceLastEvent = ieee154e_asnDiff(&light_vars.lastEventAsn); // set light_reading to fake high/low value to trigger packets if (numAsnSinceLastEvent>LIGHT_FAKESEND_PERIOD) { if (light_vars.light_reading<LUX_THRESHOLD) { light_vars.light_reading=2*LUX_THRESHOLD; } else { light_vars.light_reading=0; } } #else // current light reading light_read_cb = sensors_getCallbackRead(SENSOR_LIGHT); light_vars.light_reading = light_read_cb(); #endif // detect light state switches if ( light_vars.light_state==FALSE && (light_vars.light_reading >= (LUX_THRESHOLD + LUX_HYSTERESIS))) { // light was just turned on light_vars.light_state = TRUE; debugpins_light_set(); leds_light_on(); iShouldSend = TRUE; } else if (light_vars.light_state==TRUE && (light_vars.light_reading < (LUX_THRESHOLD - LUX_HYSTERESIS))) { // light was just turned off light_vars.light_state = FALSE; debugpins_light_clr(); leds_light_off(); iShouldSend = TRUE; } else { // light stays in same state iShouldSend = FALSE; } // abort if no packet to send if (iShouldSend==FALSE) { return; } //=== if I get here, I send a packet // remember the current ASN ieee154e_getAsnStruct(&light_vars.lastEventAsn); // increment the burstId light_vars.burstId = (light_vars.burstId+1)%16; // send burst of LIGHT_BURSTSIZE packets for (pktId=0;pktId<LIGHT_BURSTSIZE;pktId++) { light_send_one_packet(pktId); } }