📄 beaconsynchronizep.nc
字号:
// "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)
m_state = S_RECEIVING;
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 beacon within %lu symbols.\n", dt);
break;
case S_PREPARE:
m_state = S_RECEIVING;
dt = m_dt + IEEE154_MAX_BEACON_LISTEN_TIME(m_beaconOrder);
call TrackAlarm.startAt(m_lastBeaconRxTime, dt);
dbg_serial("BeaconSynchronizeP","Rx enabled, expecting beacon within %lu symbols.\n",
(uint32_t) ((m_lastBeaconRxTime + dt) - call TrackAlarm.getNow()));
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 {
ASSERT(m_state == S_RECEIVING && call RadioOff.off() == SUCCESS);
}
}
event message_t* BeaconRx.received(message_t *frame, const ieee154_timestamp_t *timestamp)
{
if (m_bufferBusy || !call FrameUtility.isBeaconFromCoord(frame))
{
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_beaconPtr;
m_bufferBusy = TRUE;
m_beaconPtr = frame;
if (timestamp != NULL)
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;
}
}
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");
m_numBeaconsLost += 1;
m_dt += m_beaconInterval;
m_bufferBusy = FALSE;
if (m_numBeaconsLost >= IEEE154_aMaxLostBeacons) {
// lost too many beacons, give up!
m_tracking = FALSE;
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);
} else
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_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_beaconPtr);
uint8_t pendingAddrMode = ADDR_MODE_NOT_PRESENT;
uint8_t coordBeaconOrder;
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_beaconPtr);
dbg_serial("BeaconSynchronizeP", "Got beacon, timestamp: %lu, offset to previous: %lu\n",
(uint32_t) timestamp, (uint32_t) (timestamp - m_lastBeaconRxTime));
m_numGtsSlots = (payload[2] & 7);
gtsFieldLength = 1 + ((m_numGtsSlots > 0) ? 1 + m_numGtsSlots * 3: 0);
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) {
// BLE is active; calculate the time offset from slot0
m_battLifeExtDuration = IEEE154_SHR_DURATION + frameLen * IEEE154_SYMBOLS_PER_OCTET;
if (frameLen > IEEE154_aMaxSIFSFrameSize)
m_battLifeExtDuration += call MLME_GET.macMinLIFSPeriod();
else
m_battLifeExtDuration += call MLME_GET.macMinSIFSPeriod();
m_battLifeExtDuration = m_battLifeExtDuration + call MLME_GET.macBattLifeExtPeriods() * 20;
} else
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) {
m_tracking = FALSE;
dbg_serial("BeaconSynchronizeP", "Stop tracking.\n");
if (m_updatePending) // there is already a new request ...
call RadioToken.request();
call RadioToken.release();
} else {
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 this frame anymore!)
if (autoRequest)
pendingAddrMode = call BeaconFrame.isLocalAddrPending(m_beaconPtr);
if (pendingAddrMode != ADDR_MODE_NOT_PRESENT) {
// the coord has pending data
uint8_t CoordAddrMode;
uint16_t CoordPANId;
uint8_t *CoordAddress;
uint8_t SrcAddrMode = pendingAddrMode;
if ((mhr[MHR_INDEX_FC2] & FC2_SRC_MODE_MASK) == FC2_SRC_MODE_SHORT)
CoordAddrMode = ADDR_MODE_SHORT_ADDRESS;
else
CoordAddrMode = ADDR_MODE_EXTENDED_ADDRESS;
CoordAddress = &(mhr[MHR_INDEX_ADDRESS+2]);
CoordPANId = *((nxle_uint16_t*) &(mhr[MHR_INDEX_ADDRESS]));
call DataRequest.poll(CoordAddrMode, CoordPANId, CoordAddress, SrcAddrMode);
}
// Beacon Tracking: update state
m_numBeaconsLost = 0;
// TODO: check PAN ID conflict here?
if (!autoRequest || beaconPayloadSize)
m_beaconPtr = signal MLME_BEACON_NOTIFY.indication(m_beaconPtr);
m_bufferBusy = FALSE;
}
dbg_serial_flush();
}
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;
}
command error_t TrackSingleBeacon.stop()
{
// will stop automatically after beacon was tracked/not found
return FAIL;
}
/* ----------------------- 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 m_numGtsSlots;
}
async command uint16_t IncomingSF.battLifeExtDuration()
{
return m_battLifeExtDuration;
}
async command const uint8_t* IncomingSF.gtsFields()
{
return m_gtsField;
}
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_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)
{
uint8_t *payload = call Frame.getPayload(frame);
ieee154_macPANId_t panID = *(nxle_uint16_t*) &payload[1];
if (panID == call MLME_GET.macPANId())
signal MLME_SYNC_LOSS.indication(
IEEE154_REALIGNMENT, // LossReason
panID, // PANId
payload[5], // LogicalChannel,
call Frame.getPayloadLength(frame) == 9 ? payload[8] : call MLME_GET.phyCurrentPage(),
NULL);
return frame;
}
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -