X-Git-Url: https://oss.titaniummirror.com/gitweb/?p=tinyos-2.x.git;a=blobdiff_plain;f=tos%2Flib%2Fmac%2Ftkn154%2FBeaconSynchronizeP.nc;h=ff2a0c0061438d1b75fdd1b00e8e741f01ed00aa;hp=e7c39110a2a2f6cba0bc48281ddebd4e3dd0b6f9;hb=e9bfab607e051bae6afb47b44892ce37541d1b44;hpb=adf1de6c009d13b7b52e68535c63b28f59c97400 diff --git a/tos/lib/mac/tkn154/BeaconSynchronizeP.nc b/tos/lib/mac/tkn154/BeaconSynchronizeP.nc index e7c39110..ff2a0c00 100644 --- a/tos/lib/mac/tkn154/BeaconSynchronizeP.nc +++ b/tos/lib/mac/tkn154/BeaconSynchronizeP.nc @@ -33,9 +33,12 @@ * ======================================================================== */ +/** + * This module is responsible for periodic beacon tracking in a + * beacon-enabled PAN. + */ #include "TKN154_MAC.h" -#include "TKN154_DEBUG.h" module BeaconSynchronizeP { @@ -45,345 +48,411 @@ module BeaconSynchronizeP interface MLME_SYNC; interface MLME_BEACON_NOTIFY; interface MLME_SYNC_LOSS; + interface SuperframeStructure as IncomingSF; interface GetNow as IsTrackingBeacons; - interface GetNow as CapStart; - interface GetNow as CapStartRefTime; - interface GetNow as CapLen; - interface GetNow as CapEnd; - interface GetNow as CfpEnd; - interface GetNow as CfpLen; - interface GetNow as BeaconInterval; - interface GetNow as IsBLEActive; - interface GetNow as BLELen; - interface GetNow as GtsField; - interface GetNow as SfSlotDuration; - interface GetNow as FinalCapSlot; - interface GetNow as NumGtsSlots; - interface GetNow as IsRxBroadcastPending; + interface SplitControl as TrackSingleBeacon; } uses { interface MLME_GET; interface MLME_SET; interface FrameUtility; - interface Notify as FindBeacon; interface IEEE154BeaconFrame as BeaconFrame; interface Alarm as TrackAlarm; interface RadioRx as BeaconRx; interface RadioOff; - interface Get as IsBeaconEnabledPAN; interface DataRequest; interface FrameRx as CoordRealignmentRx; - interface Resource as Token; - interface ResourceTransfer as TokenToCap; + interface TransferableResource as RadioToken; interface TimeCalc; interface IEEE154Frame as Frame; interface Leds; - interface Ieee802154Debug as Debug; } } implementation { + /* state variables */ + norace uint8_t m_state; + norace uint8_t m_numBeaconsMissed; - enum { - S_PREPARE = 0, - S_RXNOW = 1, - S_RADIO_OFF = 2, - S_FIRST_SCAN= 3, - - RX_DURATION = 1000, // listen for a beacon for RX_DURATION symbols - RX_LAG = 100, // start to listen for a RX_LAG before expected arrival - }; - - norace bool m_tracking = FALSE; - bool m_updatePending = FALSE; + /* temporary buffers for the MLME-SYNC parameters */ uint8_t m_updateLogicalChannel; bool m_updateTrackBeacon; - bool m_stopTracking = FALSE; - bool m_internalRequest = FALSE; - - uint8_t m_numBeaconsLost; - uint8_t m_coordAddress[8]; - message_t m_beaconBuffer; - norace message_t *m_beaconBufferPtr = &m_beaconBuffer; - norace bool m_beaconSwapBufferReady = TRUE; - norace uint32_t m_beaconInterval; + + /* variables that describe the current beacon configuration */ + norace ieee154_macBeaconOrder_t m_beaconOrder; norace uint32_t m_dt; norace uint32_t m_lastBeaconRxTime; - norace ieee154_reftime_t m_lastBeaconRxRefTime; - norace uint8_t m_state; - norace uint8_t m_beaconOrder; + norace ieee154_timestamp_t m_lastBeaconRxRefTime; + message_t m_beacon; + norace message_t *m_beaconPtr = &m_beacon; + + /* variables that describe the latest superframe */ norace uint32_t m_sfSlotDuration; - norace uint8_t m_finalCapSlot; + norace bool m_framePendingBit; + norace uint8_t m_numCapSlots; norace uint8_t m_numGtsSlots; - norace uint16_t m_BLELen; - norace bool m_broadcastPending; + norace uint16_t m_battLifeExtDuration; uint8_t m_gtsField[1+1+3*7]; + + enum { + RX_PREPARE = 0x00, + RX_RECEIVING = 0x01, + RX_RADIO_OFF = 0x02, + RX_FIRST_SCAN= 0x03, + RX_MASK = 0x03, + + MODE_INACTIVE = 0x00, + MODE_TRACK_SINGLE = 0x04, + MODE_TRACK_CONTINUOUS = 0x08, + MODE_MASK = 0x0C, + + BEACON_RECEIVED = 0x10, + UPDATE_PENDING = 0x20, + INTERNAL_REQUEST = 0x40, + EXTERNAL_REQUEST = 0x80, + }; + + /* function/task prototypes */ + void trackNextBeacon(); + uint32_t getBeaconInterval(ieee154_macBeaconOrder_t BO); task void processBeaconTask(); + task void signalGrantedTask(); + /* accessing/manipulating the current state */ + void setBeaconReceived() { m_state |= BEACON_RECEIVED; } + void resetBeaconReceived() { m_state &= ~BEACON_RECEIVED; } + bool wasBeaconReceived() { return (m_state & BEACON_RECEIVED) ? TRUE : FALSE; } + void setUpdatePending() { m_state |= UPDATE_PENDING; } + void resetUpdatePending() { m_state &= ~UPDATE_PENDING; } + bool isUpdatePending() { return (m_state & UPDATE_PENDING) ? TRUE : FALSE; } + void setInternalRequest() { m_state |= INTERNAL_REQUEST; } + void resetInternalRequest() { m_state &= ~INTERNAL_REQUEST; } + bool isInternalRequest() { return (m_state & INTERNAL_REQUEST) ? TRUE : FALSE; } + void setExternalRequest() { m_state |= EXTERNAL_REQUEST; } + void resetExternalRequest() { m_state &= ~EXTERNAL_REQUEST; } + bool isExternalRequest() { return (m_state & EXTERNAL_REQUEST) ? TRUE : FALSE; } + uint8_t getMode() { return (m_state & MODE_MASK); } + void setMode(uint8_t mode) { m_state &= ~MODE_MASK; m_state |= (mode & MODE_MASK); } + uint8_t getRxState() { return (m_state & RX_MASK); } + void setRxState(uint8_t state) { m_state &= ~RX_MASK; m_state |= (state & RX_MASK); } + command error_t Reset.init() { - if (call Token.isOwner()){ - call Leds.led0On(); // internal error - return FAIL; - } - if (m_tracking || m_updatePending) + // Reset this component - will only be called while we're not owning the token + if (call IsTrackingBeacons.getNow() || + (isUpdatePending() && isExternalRequest() && m_updateTrackBeacon)) signal MLME_SYNC_LOSS.indication( IEEE154_BEACON_LOSS, call MLME_GET.macPANId(), call MLME_GET.phyCurrentChannel(), call MLME_GET.phyCurrentPage(), NULL); - m_updatePending = m_stopTracking = m_tracking = FALSE; + if (isInternalRequest()) + signal TrackSingleBeacon.startDone(FAIL); + resetUpdatePending(); + resetInternalRequest(); + resetExternalRequest(); + setMode(MODE_INACTIVE); return SUCCESS; } -/* ----------------------- MLME-SYNC ----------------------- */ -/* - * Allows to synchronize with a coordinator. - */ + /* ----------------------- MLME-SYNC ----------------------- */ + /* + * Allows to synchronize with the beacons from a coordinator. + */ command ieee154_status_t MLME_SYNC.request ( uint8_t logicalChannel, uint8_t channelPage, bool trackBeacon) { + error_t status = IEEE154_SUCCESS; uint32_t supportedChannels = IEEE154_SUPPORTED_CHANNELS; uint32_t currentChannelBit = 1; currentChannelBit <<= logicalChannel; if (!(currentChannelBit & supportedChannels) || (call MLME_GET.macPANId() == 0xFFFF) || - (channelPage != IEEE154_SUPPORTED_CHANNELPAGE) || !call IsBeaconEnabledPAN.get()) - return IEEE154_INVALID_PARAMETER; - - call Debug.log(LEVEL_INFO,SyncP_REQUEST, logicalChannel, channelPage, trackBeacon); - if (!trackBeacon && m_tracking){ - // stop tracking after next received beacon - m_stopTracking = TRUE; - } else { - m_stopTracking = FALSE; - m_updateLogicalChannel = logicalChannel; + (channelPage != IEEE154_SUPPORTED_CHANNELPAGE) || !IEEE154_BEACON_ENABLED_PAN) + status = IEEE154_INVALID_PARAMETER; + else { m_updateTrackBeacon = trackBeacon; - m_updatePending = TRUE; - m_internalRequest = FALSE; - call Debug.log(LEVEL_INFO,SyncP_RESOURCE_REQUEST, 0, 0, 0); - call Token.request(); + m_updateLogicalChannel = logicalChannel; + setExternalRequest(); + setUpdatePending(); + call RadioToken.request(); } - call Debug.flush(); - return IEEE154_SUCCESS; + + dbg_serial("BeaconSynchronizeP", "MLME_SYNC.request -> result: %lu\n", (uint32_t) status); + return status; } - event void FindBeacon.notify( bool val ) + event void RadioToken.granted() { - if (!m_tracking && !m_updatePending){ - // find a single beacon now (treat this like a user request) - m_updateLogicalChannel = call MLME_GET.phyCurrentChannel(); - m_updateTrackBeacon = FALSE; - m_updatePending = TRUE; - m_internalRequest = TRUE; - call Token.request(); - } + if (isUpdatePending()) { + dbg_serial("BeaconSynchronizeP", "Updating configuration...\n"); + if (m_updateTrackBeacon) + setMode(MODE_TRACK_CONTINUOUS); + else + setMode(MODE_TRACK_SINGLE); + call MLME_SET.phyCurrentChannel(m_updateLogicalChannel); + m_beaconOrder = call MLME_GET.macBeaconOrder(); + m_dt = getBeaconInterval(m_beaconOrder); + m_numBeaconsMissed = IEEE154_aMaxLostBeacons; // will be reset when first beacon is received + resetUpdatePending(); + setRxState(RX_FIRST_SCAN); + } + trackNextBeacon(); + } + + async event void RadioToken.transferredFrom(uint8_t clientFrom) + { + dbg_serial("BeaconSynchronizeP", "Got token (transferred).\n"); + if (isUpdatePending()) + post signalGrantedTask(); + else + trackNextBeacon(); } - event void Token.granted() + task void signalGrantedTask() + { + signal RadioToken.granted(); + } + + void trackNextBeacon() { bool missed = FALSE; - call Debug.flush(); - call Debug.log(LEVEL_INFO,SyncP_GOT_RESOURCE, m_lastBeaconRxTime+m_beaconInterval, - m_beaconInterval, (m_updatePending<<1)+m_tracking); - if (m_updatePending){ - m_state = S_FIRST_SCAN; - m_updatePending = FALSE; - m_beaconOrder = call MLME_GET.macBeaconOrder(); - if (m_beaconOrder >= 15) - m_beaconOrder = 14; - call MLME_SET.phyCurrentChannel(m_updateLogicalChannel); - m_tracking = m_updateTrackBeacon; - m_beaconInterval = ((uint32_t) 1 << m_beaconOrder) * (uint32_t) IEEE154_aBaseSuperframeDuration; - m_dt = m_beaconInterval; - m_numBeaconsLost = IEEE154_aMaxLostBeacons; // will be reset when beacon is received - call Debug.log(LEVEL_INFO,SyncP_UPDATING, call MLME_GET.macCoordShortAddress(), - call MLME_GET.macPANId(), m_updateLogicalChannel); - } else { - m_state = S_PREPARE; - if (!m_tracking){ - call Debug.log(LEVEL_INFO,SyncP_RELEASE_RESOURCE, 0, 0, 0); - call Token.release(); - return; - } - while (call TimeCalc.hasExpired(m_lastBeaconRxTime, m_dt)){ // missed a beacon - call Debug.log(LEVEL_INFO,SyncP_BEACON_MISSED_1, m_lastBeaconRxTime, m_dt, missed); - m_dt += m_beaconInterval; - m_numBeaconsLost++; + + if (getMode() == MODE_INACTIVE) { + // nothing to do, just give up the token + dbg_serial("BeaconSynchronizeP", "Stop tracking.\n"); + call RadioToken.release(); + return; + } + + if (getRxState() != RX_FIRST_SCAN) { + + dbg_serial("BeaconSynchronizeP","Token.transferred(), expecting beacon in %lu symbols.\n", + (uint32_t) ((m_lastBeaconRxTime + m_dt) - call TrackAlarm.getNow())); + + // we have received at least one previous beacon, get ready for the next + setRxState(RX_PREPARE); + + while (call TimeCalc.hasExpired(m_lastBeaconRxTime, m_dt)) { // missed a beacon! + dbg_serial("BeaconSynchronizeP", "Missed a beacon, expected it: %lu, now: %lu\n", + m_lastBeaconRxTime + m_dt, call TrackAlarm.getNow()); missed = TRUE; + m_dt += getBeaconInterval(m_beaconOrder); + m_numBeaconsMissed++; } - if (m_numBeaconsLost >= IEEE154_aMaxLostBeacons){ + + if (m_numBeaconsMissed >= IEEE154_aMaxLostBeacons) { + dbg_serial("BeaconSynchronizeP", "Missed too many beacons.\n"); post processBeaconTask(); return; } - if (missed){ - call Token.request(); - call Debug.log(LEVEL_INFO,SyncP_RELEASE_RESOURCE, m_lastBeaconRxTime, m_dt, missed); - call Token.release(); + + if (missed) { + // let other components get a chance to use the radio + call RadioToken.request(); + dbg_serial("BeaconSynchronizeP", "Skipping a beacon.\n"); + call RadioToken.release(); return; } } - if (!call RadioOff.isOff()) - call RadioOff.off(); - else + + if (call RadioOff.isOff()) signal RadioOff.offDone(); + else if (call RadioOff.off() != SUCCESS) + ASSERT(0); } - async event void TrackAlarm.fired() + async event void RadioOff.offDone() { - call Debug.log(LEVEL_IMPORTANT,SyncP_TRACK_ALARM, m_state,m_lastBeaconRxTime,m_dt); - atomic { - switch (m_state) - { - case S_PREPARE: - call BeaconRx.prepare(); - break; - case S_RADIO_OFF: - call RadioOff.off(); - break; - } + uint32_t delay = IEEE154_RADIO_RX_DELAY + IEEE154_MAX_BEACON_JITTER(m_beaconOrder); + + if (getRxState() == RX_FIRST_SCAN) { + // initial scan: switch to Rx immediately + call BeaconRx.enableRx(0, 0); + } else if (getRxState() == RX_PREPARE) { + if (!call TimeCalc.hasExpired(m_lastBeaconRxTime - delay, m_dt)) + call TrackAlarm.startAt(m_lastBeaconRxTime - delay, m_dt); + else + signal TrackAlarm.fired(); + } else { + post processBeaconTask(); } } - async event void BeaconRx.prepareDone() + async event void BeaconRx.enableRxDone() { - error_t result; - if (m_state == S_FIRST_SCAN){ - m_state = S_RADIO_OFF; - atomic { - call BeaconRx.receive(NULL, 0); - call TrackAlarm.start((((uint32_t) 1 << m_beaconOrder) + (uint32_t) 1) * - (uint32_t) IEEE154_aBaseSuperframeDuration * (uint32_t) IEEE154_aMaxLostBeacons); - } - } else { - m_state = S_RADIO_OFF; - result = call BeaconRx.receive(&m_lastBeaconRxRefTime, m_dt-RX_LAG); - call Debug.log(LEVEL_IMPORTANT,SyncP_RX_ON, m_lastBeaconRxTime, call TrackAlarm.getNow(), m_dt+RX_DURATION); - if (result != SUCCESS) - call Debug.log(LEVEL_IMPORTANT,SyncP_RADIO_BUSY, result, 0, 0); - call TrackAlarm.startAt(m_lastBeaconRxTime, m_dt + RX_DURATION); + uint32_t dt; + uint8_t previousState = getRxState(); + + setRxState(RX_RECEIVING); + + switch (previousState) + { + case RX_FIRST_SCAN: + // "To acquire beacon synchronization, a device shall enable its + // receiver and search for at most [aBaseSuperframeDuration * (2^n + 1)] + // symbols, where n is the value of macBeaconOrder [...] Once the number + // of missed beacons reaches aMaxLostBeacons, the MLME shall notify the + // next higher layer." (Sect. 7.5.4.1) + dt = (((uint32_t) 1 << m_beaconOrder) + (uint32_t) 1) * + (uint32_t) IEEE154_aBaseSuperframeDuration * + (uint32_t) IEEE154_aMaxLostBeacons; + call TrackAlarm.start(dt); + dbg_serial("BeaconSynchronizeP","Rx enabled, expecting first beacon within next %lu symbols.\n", dt); + break; + case RX_PREPARE: + dt = m_dt + IEEE154_MAX_BEACON_LISTEN_TIME(m_beaconOrder); + call TrackAlarm.startAt(m_lastBeaconRxTime, dt); + dbg_serial("BeaconSynchronizeP","Rx enabled, expecting beacon within next %lu symbols.\n", + (uint32_t) ((m_lastBeaconRxTime + dt) - call TrackAlarm.getNow())); + break; + default: + ASSERT(0); + break; } } - event message_t* BeaconRx.received(message_t *frame, ieee154_reftime_t *timestamp) + async event void TrackAlarm.fired() { - uint8_t *mhr = MHR(frame); - call Debug.log(LEVEL_INFO,SyncP_RX_PACKET,*((nxle_uint32_t*) &mhr[MHR_INDEX_ADDRESS]), - mhr[MHR_INDEX_FC1] & FC1_FRAMETYPE_MASK,mhr[MHR_INDEX_SEQNO]); - if (!m_beaconSwapBufferReady || !call FrameUtility.isBeaconFromCoord(frame)) - { - call Debug.log(LEVEL_IMPORTANT,SyncP_RX_GARBAGE, m_beaconSwapBufferReady, 0, 0); + if (getRxState() == RX_PREPARE) { // enable Rx + uint32_t maxBeaconJitter = IEEE154_MAX_BEACON_JITTER(m_beaconOrder); + if (maxBeaconJitter > m_dt) + maxBeaconJitter = m_dt; // receive immediately + call BeaconRx.enableRx(m_lastBeaconRxTime, m_dt - maxBeaconJitter); + } else { // disable Rx + error_t error = call RadioOff.off(); + ASSERT(getRxState() == RX_RECEIVING && error == SUCCESS); + } + } + + event message_t* BeaconRx.received(message_t *frame, const ieee154_timestamp_t *timestamp) + { + if (wasBeaconReceived()) { + dbg_serial("BeaconSynchronizeP", "Got another beacon! -> ignoring it ...\n"); + return frame; + } else if (!call FrameUtility.isBeaconFromCoord(frame)) { + dbg_serial("BeaconSynchronizeP", "Got a beacon, but not from my coordinator.\n"); return frame; } else { - message_t *tmp = m_beaconBufferPtr; - call TrackAlarm.stop(); - m_beaconSwapBufferReady = FALSE; - m_beaconBufferPtr = frame; + message_t *tmp = m_beaconPtr; + setBeaconReceived(); + m_beaconPtr = frame; if (timestamp != NULL) - memcpy(&m_lastBeaconRxRefTime, timestamp, sizeof(ieee154_reftime_t)); - call RadioOff.off(); + memcpy(&m_lastBeaconRxRefTime, timestamp, sizeof(ieee154_timestamp_t)); + if (getRxState() == RX_RECEIVING) { + call TrackAlarm.stop(); // may fail + call RadioOff.off(); // may fail + } return tmp; } } - async event void RadioOff.offDone() - { - if (m_state == S_FIRST_SCAN) - call BeaconRx.prepare(); - else if (m_state == S_PREPARE) - call TrackAlarm.startAt(m_lastBeaconRxTime, m_dt - IEEE154_RADIO_RX_PREPARE_DELAY); - else - post processBeaconTask(); - } + task void processBeaconTask() { + // task will be executed after every (un)successful attempt to track a beacon + bool wasInternalRequest = isInternalRequest(); + + if (wasBeaconReceived() && !call Frame.isTimestampValid(m_beaconPtr)) { + dbg_serial("BeaconSynchronizeP", "Received beacon has invalid timestamp, discarding it!\n"); + resetBeaconReceived(); + } - // valid beacon timestamp is pre-condition for slotted CSMA-CA - if (m_beaconSwapBufferReady || !call Frame.isTimestampValid(m_beaconBufferPtr)){ - // missed a beacon! - m_numBeaconsLost++; - m_dt += m_beaconInterval; - call Debug.log(LEVEL_IMPORTANT, SyncP_BEACON_MISSED_3,m_numBeaconsLost,0,m_lastBeaconRxTime); - if (m_numBeaconsLost >= IEEE154_aMaxLostBeacons){ - m_tracking = FALSE; - call Debug.log(LEVEL_IMPORTANT, SyncP_LOST_SYNC,0,0,0); - call Leds.led2Off(); - if (m_internalRequest) - call TokenToCap.transfer(); - else - signal MLME_SYNC_LOSS.indication( - IEEE154_BEACON_LOSS, - call MLME_GET.macPANId(), - call MLME_GET.phyCurrentChannel(), - call MLME_GET.phyCurrentPage(), - NULL // security - ); - } else - call Token.request(); // make another request again (before giving the token up) - call Debug.log(LEVEL_INFO,SyncP_RELEASE_RESOURCE, 0, 0, 0); - call Token.release(); + if (getMode() == MODE_TRACK_SINGLE) + setMode(MODE_INACTIVE); // we're done with a single shot + resetInternalRequest(); + + // whether we next release the token or pass it to the CAP + // component, we want it back (because we decide later + // whether we'll actually stop tracking the beacon in future) + call RadioToken.request(); + + if (!wasBeaconReceived()) { + + resetBeaconReceived(); // buffer ready + m_numBeaconsMissed += 1; + m_dt += getBeaconInterval(m_beaconOrder); + dbg_serial("BeaconSynchronizeP", "Missed a beacon (total missed: %lu).\n", (uint32_t) m_numBeaconsMissed); + + if (wasInternalRequest) { + // note: if it only was an internal request, the + // mode was reset above already (SINGLE_SHOT) + signal TrackSingleBeacon.startDone(FAIL); + } + if (isExternalRequest() && m_numBeaconsMissed >= IEEE154_aMaxLostBeacons) { + resetExternalRequest(); + setMode(MODE_INACTIVE); + dbg_serial("BeaconSynchronizeP", "MLME_SYNC_LOSS!\n"); + signal MLME_SYNC_LOSS.indication( + IEEE154_BEACON_LOSS, + call MLME_GET.macPANId(), + call MLME_GET.phyCurrentChannel(), + call MLME_GET.phyCurrentPage(), + NULL); + } + + call RadioToken.release(); + } else { - // got the beacon! - uint8_t *payload = (uint8_t *) m_beaconBufferPtr->data; + // received the beacon! + uint8_t *payload = (uint8_t *) m_beaconPtr->data; ieee154_macAutoRequest_t autoRequest = call MLME_GET.macAutoRequest(); uint8_t pendAddrSpecOffset = 3 + (((payload[2] & 7) > 0) ? 1 + (payload[2] & 7) * 3: 0); // skip GTS uint8_t pendAddrSpec = payload[pendAddrSpecOffset]; uint8_t *beaconPayload = payload + pendAddrSpecOffset + 1; - uint8_t beaconPayloadSize = call BeaconFrame.getBeaconPayloadLength(m_beaconBufferPtr); + uint8_t beaconPayloadSize = call BeaconFrame.getBeaconPayloadLength(m_beaconPtr); uint8_t pendingAddrMode = ADDR_MODE_NOT_PRESENT; - uint8_t coordBeaconOrder; - uint8_t *mhr = MHR(m_beaconBufferPtr); - uint8_t frameLen = ((uint8_t*) m_beaconBufferPtr)[0] & FRAMECTL_LENGTH_MASK; + uint8_t *mhr = MHR(m_beaconPtr); + uint8_t frameLen = ((uint8_t*) m_beaconPtr)[0] & FRAMECTL_LENGTH_MASK; uint8_t gtsFieldLength; - uint32_t timestamp = call Frame.getTimestamp(m_beaconBufferPtr); + uint32_t timestamp = call Frame.getTimestamp(m_beaconPtr); - call Debug.log(LEVEL_INFO, SyncP_BEACON_RX, m_lastBeaconRxTime, timestamp, mhr[2]); + dbg_serial("BeaconSynchronizeP", "Got beacon, timestamp: %lu, offset to previous: %lu\n", + (uint32_t) timestamp, (uint32_t) (timestamp - m_lastBeaconRxTime)); + + m_numBeaconsMissed = 0; m_numGtsSlots = (payload[2] & 7); gtsFieldLength = 1 + ((m_numGtsSlots > 0) ? 1 + m_numGtsSlots * 3: 0); m_lastBeaconRxTime = timestamp; - m_finalCapSlot = (payload[1] & 0x0F); + m_numCapSlots = (payload[1] & 0x0F) + 1; m_sfSlotDuration = (((uint32_t) 1) << ((payload[0] & 0xF0) >> 4)) * IEEE154_aBaseSlotDuration; memcpy(m_gtsField, &payload[2], gtsFieldLength); // check for battery life extension - if (payload[1] & 0x10){ + if (payload[1] & 0x10) { // BLE is active; calculate the time offset from slot0 - m_BLELen = IEEE154_SHR_DURATION + frameLen * IEEE154_SYMBOLS_PER_OCTET; + m_battLifeExtDuration = IEEE154_SHR_DURATION + frameLen * IEEE154_SYMBOLS_PER_OCTET; if (frameLen > IEEE154_aMaxSIFSFrameSize) - m_BLELen += call MLME_GET.macMinLIFSPeriod(); + m_battLifeExtDuration += call MLME_GET.macMinLIFSPeriod(); else - m_BLELen += call MLME_GET.macMinSIFSPeriod(); - m_BLELen += call MLME_GET.macBattLifeExtPeriods(); + m_battLifeExtDuration += call MLME_GET.macMinSIFSPeriod(); + m_battLifeExtDuration = m_battLifeExtDuration + call MLME_GET.macBattLifeExtPeriods() * 20; } else - m_BLELen = 0; - m_broadcastPending = mhr[MHR_INDEX_FC1] & FC1_FRAME_PENDING ? TRUE : FALSE; - coordBeaconOrder = (payload[0] & 0x0F); - m_dt = m_beaconInterval = ((uint32_t) 1 << coordBeaconOrder) * (uint32_t) IEEE154_aBaseSuperframeDuration; - if (m_stopTracking){ - m_tracking = FALSE; - call Debug.log(LEVEL_INFO,SyncP_RELEASE_RESOURCE, 0, 0, 0); - call Token.release(); - } else { - error_t req = call Token.request(); - call Debug.log(LEVEL_INFO,SyncP_TRANSFER_RESOURCE, req, 0, 0); - call TokenToCap.transfer(); - } + m_battLifeExtDuration = 0; + + m_framePendingBit = mhr[MHR_INDEX_FC1] & FC1_FRAME_PENDING ? TRUE : FALSE; + m_beaconOrder = (payload[0] & 0x0F); + m_dt = getBeaconInterval(m_beaconOrder); + + dbg_serial("BeaconSynchronizeP", "Handing over to CAP.\n"); + call RadioToken.transferTo(RADIO_CLIENT_DEVICECAP); if (pendAddrSpec & PENDING_ADDRESS_SHORT_MASK) beaconPayload += (pendAddrSpec & PENDING_ADDRESS_SHORT_MASK) * 2; if (pendAddrSpec & PENDING_ADDRESS_EXT_MASK) beaconPayload += ((pendAddrSpec & PENDING_ADDRESS_EXT_MASK) >> 4) * 8; + // check for pending data (once we signal MLME_BEACON_NOTIFY we cannot - // touch the frame anymore) + // touch this frame anymore!) if (autoRequest) - pendingAddrMode = call BeaconFrame.isLocalAddrPending(m_beaconBufferPtr); - if (pendingAddrMode != ADDR_MODE_NOT_PRESENT){ + pendingAddrMode = call BeaconFrame.isLocalAddrPending(m_beaconPtr); + if (pendingAddrMode != ADDR_MODE_NOT_PRESENT) { // the coord has pending data uint8_t CoordAddrMode; uint16_t CoordPANId; @@ -397,55 +466,102 @@ implementation CoordPANId = *((nxle_uint16_t*) &(mhr[MHR_INDEX_ADDRESS])); call DataRequest.poll(CoordAddrMode, CoordPANId, CoordAddress, SrcAddrMode); } - // Beacon Tracking: update state - call Debug.log(LEVEL_INFO, SyncP_NEXT_RX_TIME, 0, timestamp, m_beaconInterval); - m_numBeaconsLost = 0; - // TODO: check PAN ID conflict here? + if (!autoRequest || beaconPayloadSize) - m_beaconBufferPtr = signal MLME_BEACON_NOTIFY.indication(m_beaconBufferPtr); - m_beaconSwapBufferReady = TRUE; + m_beaconPtr = signal MLME_BEACON_NOTIFY.indication(m_beaconPtr); + resetBeaconReceived(); // buffer ready } + dbg_serial_flush(); } - async command bool IsTrackingBeacons.getNow(){ return m_tracking;} - - default event message_t* MLME_BEACON_NOTIFY.indication (message_t* frame){return frame;} + command error_t TrackSingleBeacon.start() + { + // Track a single beacon now + dbg_serial("BeaconSynchronizeP", "Internal request.\n"); + setInternalRequest(); + call RadioToken.request(); + if (!isUpdatePending()) { + m_updateLogicalChannel = call MLME_GET.phyCurrentChannel(); + m_updateTrackBeacon = FALSE; + setUpdatePending(); + } + return SUCCESS; + } - default event void MLME_SYNC_LOSS.indication ( - ieee154_status_t lossReason, - uint16_t panID, - uint8_t logicalChannel, - uint8_t channelPage, - ieee154_security_t *security){} + command error_t TrackSingleBeacon.stop() + { + // we will stop automatically after beacon was tracked/not found + return FAIL; + } - event void DataRequest.pollDone(){} - - async command uint8_t* GtsField.getNow() { return m_gtsField; } - async command uint32_t SfSlotDuration.getNow() { return m_sfSlotDuration; } - async command uint8_t FinalCapSlot.getNow() { return m_finalCapSlot; } - async command uint32_t CapStart.getNow() { return m_lastBeaconRxTime; } - async command ieee154_reftime_t* CapStartRefTime.getNow() { return &m_lastBeaconRxRefTime; } - async command uint32_t CapLen.getNow() { return call SfSlotDuration.getNow() * (call FinalCapSlot.getNow() + 1);} - async command uint32_t CapEnd.getNow() + /* ----------------------- SF Structure, etc. ----------------------- */ + + async command uint32_t IncomingSF.sfStartTime() + { + return m_lastBeaconRxTime; + } + + async command uint16_t IncomingSF.sfSlotDuration() + { + return m_sfSlotDuration; + } + + async command uint8_t IncomingSF.numCapSlots() { - return call CapStart.getNow() + call CapLen.getNow(); + return m_numCapSlots; } - async command uint32_t CfpEnd.getNow() + + async command uint8_t IncomingSF.numGtsSlots() { - return call CapStart.getNow() + call SfSlotDuration.getNow() * IEEE154_aNumSuperframeSlots; + return m_numGtsSlots; } - async command uint32_t CfpLen.getNow() + + async command uint16_t IncomingSF.battLifeExtDuration() + { + return m_battLifeExtDuration; + } + + async command const uint8_t* IncomingSF.gtsFields() { - return call SfSlotDuration.getNow() * (15 - call FinalCapSlot.getNow()); + return m_gtsField; } - async command uint32_t BeaconInterval.getNow() + + async command uint16_t IncomingSF.guardTime() + { + return IEEE154_MAX_BEACON_JITTER(m_beaconOrder) + IEEE154_RADIO_RX_DELAY; + } + + async command const ieee154_timestamp_t* IncomingSF.sfStartTimeRef() { - return m_beaconInterval; + return &m_lastBeaconRxRefTime; } - async command uint8_t NumGtsSlots.getNow() { return m_numGtsSlots; } - async command bool IsBLEActive.getNow(){ return m_BLELen>0;} - async command uint16_t BLELen.getNow(){ return m_BLELen;} - async command bool IsRxBroadcastPending.getNow() { return m_broadcastPending; } + + async command bool IncomingSF.isBroadcastPending() + { + return m_framePendingBit; + } + + async command bool IsTrackingBeacons.getNow() + { + return (getMode() == MODE_TRACK_CONTINUOUS); + } + + uint32_t getBeaconInterval(ieee154_macBeaconOrder_t BO) + { + if (BO >= 15) + BO = 14; + return (((uint32_t) 1 << BO) * (uint32_t) IEEE154_aBaseSuperframeDuration); + } + + event void DataRequest.pollDone() {} + + default event message_t* MLME_BEACON_NOTIFY.indication (message_t* frame) {return frame;} + default event void MLME_SYNC_LOSS.indication ( + ieee154_status_t lossReason, + uint16_t panID, + uint8_t logicalChannel, + uint8_t channelPage, + ieee154_security_t *security) {} event message_t* CoordRealignmentRx.received(message_t* frame) { @@ -457,8 +573,7 @@ implementation panID, // PANId payload[5], // LogicalChannel, call Frame.getPayloadLength(frame) == 9 ? payload[8] : call MLME_GET.phyCurrentPage(), - NULL - ); + NULL); return frame; } }