📄 beaconsynchronizep.nc
字号:
/*
* Copyright (c) 2008, Technische Universitaet Berlin
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* - Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* - Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* - Neither the name of the Technische Universitaet Berlin nor the names
* of its contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
* TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
* OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
* OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
* USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* - Revision -------------------------------------------------------------
* $Revision: 1.10 $
* $Date: 2009/10/16 12:25:45 $
* @author Jan Hauer <hauer@tkn.tu-berlin.de>
* ========================================================================
*/
/**
* This module is responsible for periodic beacon tracking in a
* beacon-enabled PAN.
*/
#include "TKN154_MAC.h"
module BeaconSynchronizeP
{
provides
{
interface Init as Reset;
interface MLME_SYNC;
interface MLME_BEACON_NOTIFY;
interface MLME_SYNC_LOSS;
interface SuperframeStructure as IncomingSF;
interface GetNow<bool> as IsTrackingBeacons;
interface StdControl as TrackSingleBeacon;
}
uses
{
interface MLME_GET;
interface MLME_SET;
interface FrameUtility;
interface IEEE154BeaconFrame as BeaconFrame;
interface Alarm<TSymbolIEEE802154,uint32_t> as TrackAlarm;
interface RadioRx as BeaconRx;
interface RadioOff;
interface DataRequest;
interface FrameRx as CoordRealignmentRx;
interface TransferableResource as RadioToken;
interface TimeCalc;
interface IEEE154Frame as Frame;
interface Leds;
}
}
implementation
{
/* state variables */
norace bool m_tracking;
bool m_stopTracking ;
norace uint8_t m_numBeaconsLost;
norace uint8_t m_state;
norace bool m_bufferBusy;
/* buffers for the parameters of the MLME-SYNC request */
norace bool m_updatePending;
uint8_t m_updateLogicalChannel;
bool m_updateTrackBeacon;
/* variables that describe the current configuration */
norace uint32_t m_beaconInterval;
norace uint32_t m_dt;
norace uint32_t m_lastBeaconRxTime;
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 bool m_framePendingBit;
norace uint8_t m_numCapSlots;
norace uint8_t m_numGtsSlots;
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()
{
// 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,
call MLME_GET.macPANId(),
call MLME_GET.phyCurrentChannel(),
call MLME_GET.phyCurrentPage(),
NULL);
m_updatePending = m_stopTracking = m_tracking = FALSE;
return SUCCESS;
}
/* ----------------------- 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) || !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 RadioToken.granted()
{
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_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
}
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;
}
// 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++;
}
if (m_numBeaconsLost >= IEEE154_aMaxLostBeacons) {
dbg_serial("BeaconSynchronizeP", "Missed too many beacons.\n");
post processBeaconTask();
return;
}
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())
signal RadioOff.offDone();
else if (call RadioOff.off() != SUCCESS)
ASSERT(0);
}
async event void RadioOff.offDone()
{
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.enableRxDone()
{
uint32_t dt;
switch (m_state)
{
case S_INITIAL_SCAN:
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -