* ========================================================================
*/
+/**
+ * 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 StdControl 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 bool m_tracking;
+ bool m_stopTracking ;
+ norace uint8_t m_numBeaconsLost;
+ norace uint8_t m_state;
+ norace bool m_bufferBusy;
- 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;
+ /* buffers for the parameters of the MLME-SYNC request */
+ norace bool m_updatePending;
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;
+
+ /* variables that describe the current configuration */
norace uint32_t m_beaconInterval;
norace uint32_t m_dt;
norace uint32_t m_lastBeaconRxTime;
- norace ieee154_reftime_t m_lastBeaconRxRefTime;
- norace uint8_t m_state;
+ norace ieee154_timestamp_t m_lastBeaconRxRefTime;
norace uint8_t m_beaconOrder;
+ 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 {
+ S_PREPARE = 0,
+ S_RECEIVING = 1,
+ S_RADIO_OFF = 2,
+ S_INITIAL_SCAN= 3,
+
+ };
+
+
+ /* function/task prototypes */
task void processBeaconTask();
+ void trackNextBeacon();
+ task void signalGrantedTask();
command error_t Reset.init()
{
- if (call Token.isOwner()){
- call Leds.led0On(); // internal error
- return FAIL;
- }
+ // reset this component. will only be called
+ // while we're not owning the token
if (m_tracking || m_updatePending)
signal MLME_SYNC_LOSS.indication(
IEEE154_BEACON_LOSS,
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;
- m_updateTrackBeacon = trackBeacon;
- m_updatePending = TRUE;
- m_internalRequest = FALSE;
- call Debug.log(LEVEL_INFO,SyncP_RESOURCE_REQUEST, 0, 0, 0);
- call Token.request();
- }
- call Debug.flush();
- return IEEE154_SUCCESS;
- }
-
- event void FindBeacon.notify( bool val )
- {
- 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();
+ (channelPage != IEEE154_SUPPORTED_CHANNELPAGE) || !IEEE154_BEACON_ENABLED_PAN)
+ status = IEEE154_INVALID_PARAMETER;
+ else {
+ if (!trackBeacon && m_tracking) {
+ // stop tracking after next received beacon
+ m_stopTracking = TRUE;
+ } else {
+ m_stopTracking = FALSE;
+ m_updateLogicalChannel = logicalChannel;
+ m_updateTrackBeacon = trackBeacon;
+ m_updatePending = TRUE;
+ atomic {
+ // if we are tracking then we'll get the RadioToken automatically,
+ // otherwise request it now
+ if (!m_tracking && !call RadioToken.isOwner())
+ call RadioToken.request();
+ }
+ }
}
+ dbg_serial("BeaconSynchronizeP", "MLME_SYNC.request -> result: %lu\n", (uint32_t) status);
+ return status;
}
- event void Token.granted()
+ event void RadioToken.granted()
{
- 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;
+ dbg_serial("BeaconSynchronizeP","Got token, expecting beacon in %lu\n",
+ (uint32_t) ((m_lastBeaconRxTime + m_dt) - call TrackAlarm.getNow()));
+ if (m_updatePending) {
+ dbg_serial("BeaconSynchronizeP", "Preparing initial scan\n");
+ m_state = S_INITIAL_SCAN;
m_updatePending = FALSE;
m_beaconOrder = call MLME_GET.macBeaconOrder();
if (m_beaconOrder >= 15)
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();
+ }
+ trackNextBeacon();
+ }
+
+ async event void RadioToken.transferredFrom(uint8_t clientFrom)
+ {
+ dbg_serial("BeaconSynchronizeP","Token.transferred(), expecting beacon in %lu symbols.\n",
+ (uint32_t) ((m_lastBeaconRxTime + m_dt) - call TrackAlarm.getNow()));
+ if (m_updatePending)
+ post signalGrantedTask();
+ else
+ trackNextBeacon();
+ }
+
+
+ task void signalGrantedTask()
+ {
+ signal RadioToken.granted();
+ }
+
+ void trackNextBeacon()
+ {
+ bool missed = FALSE;
+
+ if (m_state != S_INITIAL_SCAN) {
+
+ if (!m_tracking) {
+ // nothing to do, just give up the token
+ dbg_serial("BeaconSynchronizeP", "Stop tracking.\n");
+ call RadioToken.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);
+
+ // we have received at least one previous beacon
+ m_state = S_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 += m_beaconInterval;
m_numBeaconsLost++;
- missed = TRUE;
}
- if (m_numBeaconsLost >= IEEE154_aMaxLostBeacons){
+
+ if (m_numBeaconsLost >= 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", "Allowing other components to get the token.\n");
+ call RadioToken.release();
return;
}
}
- if (!call RadioOff.isOff())
- call RadioOff.off();
- else
+
+ if (call RadioOff.isOff())
signal RadioOff.offDone();
+ else
+ ASSERT(call RadioOff.off() == SUCCESS);
}
- 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 (m_state == S_INITIAL_SCAN) {
+ // initial scan
+ call BeaconRx.enableRx(0, 0);
+ } else if (m_state == S_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);
+ switch (m_state)
+ {
+ case S_INITIAL_SCAN:
+ m_state = S_RECEIVING;
call TrackAlarm.start((((uint32_t) 1 << m_beaconOrder) + (uint32_t) 1) *
- (uint32_t) IEEE154_aBaseSuperframeDuration * (uint32_t) IEEE154_aMaxLostBeacons);
- }
+ (uint32_t) IEEE154_aBaseSuperframeDuration * (uint32_t) IEEE154_aMaxLostBeacons);
+ break;
+ case S_PREPARE:
+ m_state = S_RECEIVING;
+ dbg_serial("BeaconSynchronizeP","Rx enabled, expecting beacon in %lu symbols.\n",
+ (uint32_t) ((m_lastBeaconRxTime + m_dt) - call TrackAlarm.getNow()));
+ call TrackAlarm.startAt(m_lastBeaconRxTime, m_dt + IEEE154_MAX_BEACON_LISTEN_TIME(m_beaconOrder));
+ break;
+ default:
+ ASSERT(0);
+ break;
+ }
+ }
+
+ async event void TrackAlarm.fired()
+ {
+ if (m_state == S_PREPARE) {
+ 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 {
- 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);
+ ASSERT(m_state == S_RECEIVING && call RadioOff.off() == SUCCESS);
}
}
- event message_t* BeaconRx.received(message_t *frame, ieee154_reftime_t *timestamp)
+ event message_t* BeaconRx.received(message_t *frame, const ieee154_timestamp_t *timestamp)
{
- 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))
+ if (m_bufferBusy || !call FrameUtility.isBeaconFromCoord(frame))
{
- call Debug.log(LEVEL_IMPORTANT,SyncP_RX_GARBAGE, m_beaconSwapBufferReady, 0, 0);
+ if (m_bufferBusy) {
+ dbg_serial("BeaconSynchronizeP", "Got another beacon, dropping it.\n");}
+ else
+ 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;
+ m_bufferBusy = TRUE;
+ 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 (m_state == S_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()
{
+ // if we received a beacon from our coordinator then it is processed now
+ if (!m_bufferBusy || !call Frame.isTimestampValid(m_beaconPtr)) {
+ // missed a beacon or received a beacon with invalid timestamp
+ if (!m_bufferBusy)
+ dbg_serial("BeaconSynchronizeP", "No beacon received!\n");
+ else
+ dbg_serial("BeaconSynchronizeP", "Beacon has invalid timestamp!\n");
- // valid beacon timestamp is pre-condition for slotted CSMA-CA
- if (m_beaconSwapBufferReady || !call Frame.isTimestampValid(m_beaconBufferPtr)){
- // missed a beacon!
- m_numBeaconsLost++;
+ m_numBeaconsLost += 1;
m_dt += m_beaconInterval;
- call Debug.log(LEVEL_IMPORTANT, SyncP_BEACON_MISSED_3,m_numBeaconsLost,0,m_lastBeaconRxTime);
- if (m_numBeaconsLost >= IEEE154_aMaxLostBeacons){
+ m_bufferBusy = FALSE;
+
+ if (m_numBeaconsLost >= IEEE154_aMaxLostBeacons) {
+ // lost too many beacons, give up!
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(
+ 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 // security
- );
+ NULL);
} 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();
+ call RadioToken.request(); // make another request again (before giving the token up)
+
+ call RadioToken.release();
} else {
// got the beacon!
- uint8_t *payload = (uint8_t *) m_beaconBufferPtr->data;
+ 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);
+
+ dbg_serial("BeaconSynchronizeP", "Got beacon, timestamp: %lu, offset to previous: %lu\n",
+ (uint32_t) timestamp, (uint32_t) (timestamp - m_lastBeaconRxTime));
- call Debug.log(LEVEL_INFO, SyncP_BEACON_RX, m_lastBeaconRxTime, timestamp, mhr[2]);
m_numGtsSlots = (payload[2] & 7);
gtsFieldLength = 1 + ((m_numGtsSlots > 0) ? 1 + m_numGtsSlots * 3: 0);
- m_lastBeaconRxTime = timestamp + IEEE154_SYNC_SYMBOL_OFFSET - IEEE154_SYMBOLS_PER_OCTET - IEEE154_PREAMBLE_LENGTH;
- m_finalCapSlot = (payload[1] & 0x0F);
+ m_lastBeaconRxTime = timestamp;
+ 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;
+ m_battLifeExtDuration = 0;
+
+ m_framePendingBit = 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){
+
+ if (m_stopTracking) {
m_tracking = FALSE;
- call Debug.log(LEVEL_INFO,SyncP_RELEASE_RESOURCE, 0, 0, 0);
- call Token.release();
+ dbg_serial("BeaconSynchronizeP", "Stop tracking.\n");
+ if (m_updatePending) // there is already a new request ...
+ call RadioToken.request();
+ call RadioToken.release();
} else {
- error_t req = call Token.request();
- call Debug.log(LEVEL_INFO,SyncP_TRANSFER_RESOURCE, req, 0, 0);
- call TokenToCap.transfer();
+ dbg_serial("BeaconSynchronizeP", "Handing over to CAP.\n");
+ // we pass on the token now, but make a reservation to get it back
+ // to receive the next beacon (at the start of the next superframe)
+ call RadioToken.request();
+ 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);
+ m_bufferBusy = FALSE;
}
+ 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
+ if (!m_tracking && !m_updatePending && !call RadioToken.isOwner()) {
+ // find a single beacon now (treat this like a user request)
+ m_updateLogicalChannel = call MLME_GET.phyCurrentChannel();
+ m_updateTrackBeacon = FALSE;
+ m_stopTracking = TRUE;
+ m_updatePending = TRUE;
+ call RadioToken.request();
+ }
+ 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()
+ {
+ // 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 m_numCapSlots;
+ }
+
+ async command uint8_t IncomingSF.numGtsSlots()
{
- return call CapStart.getNow() + call CapLen.getNow();
+ return m_numGtsSlots;
}
- async command uint32_t CfpEnd.getNow()
+
+ async command uint16_t IncomingSF.battLifeExtDuration()
{
- return call CapStart.getNow() + call SfSlotDuration.getNow() * IEEE154_aNumSuperframeSlots;
+ return m_battLifeExtDuration;
}
- async command uint32_t CfpLen.getNow()
+
+ 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 m_beaconInterval;
+ return IEEE154_MAX_BEACON_JITTER(m_beaconOrder) + IEEE154_RADIO_RX_DELAY;
}
- 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 const ieee154_timestamp_t* IncomingSF.sfStartTimeRef()
+ {
+ return &m_lastBeaconRxRefTime;
+ }
+
+ async command bool IncomingSF.isBroadcastPending()
+ {
+ return m_framePendingBit;
+ }
+
+ async command bool IsTrackingBeacons.getNow()
+ {
+ return m_tracking;
+ }
+
+ 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;
}
}