* ========================================================================
*/
+/**
+ * This module is responsible for periodic beacon tracking in a
+ * beacon-enabled PAN.
+ */
#include "TKN154_MAC.h"
-#include "TKN154_DEBUG.h"
module BeaconSynchronizeP
{
interface MLME_SYNC;
interface MLME_BEACON_NOTIFY;
interface MLME_SYNC_LOSS;
+ interface SuperframeStructure as IncomingSF;
interface GetNow<bool> as IsTrackingBeacons;
- interface GetNow<uint32_t> as CapStart;
- interface GetNow<ieee154_reftime_t*> as CapStartRefTime;
- interface GetNow<uint32_t> as CapLen;
- interface GetNow<uint32_t> as CapEnd;
- interface GetNow<uint32_t> as CfpEnd;
- interface GetNow<uint32_t> as CfpLen;
- interface GetNow<uint32_t> as BeaconInterval;
- interface GetNow<bool> as IsBLEActive;
- interface GetNow<uint16_t> as BLELen;
- interface GetNow<uint8_t*> as GtsField;
- interface GetNow<uint32_t> as SfSlotDuration;
- interface GetNow<uint8_t> as FinalCapSlot;
- interface GetNow<uint8_t> as NumGtsSlots;
- interface GetNow<bool> as IsRxBroadcastPending;
+ interface SplitControl as TrackSingleBeacon;
}
uses
{
interface MLME_GET;
interface MLME_SET;
interface FrameUtility;
- interface Notify<bool> as FindBeacon;
interface IEEE154BeaconFrame as BeaconFrame;
interface Alarm<TSymbolIEEE802154,uint32_t> as TrackAlarm;
interface RadioRx as BeaconRx;
interface RadioOff;
- interface Get<bool> 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;
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)
{
panID, // PANId
payload[5], // LogicalChannel,
call Frame.getPayloadLength(frame) == 9 ? payload[8] : call MLME_GET.phyCurrentPage(),
- NULL
- );
+ NULL);
return frame;
}
}