trafficmonitorlayerp.nc

来自「tinyos-2.x.rar」· NC 代码 · 共 246 行

NC
246
字号
/*
 * Copyright (c) 2007, Vanderbilt University
 * All rights reserved.
 *
 * Permission to use, copy, modify, and distribute this software and its
 * documentation for any purpose, without fee, and without written agreement is
 * hereby granted, provided that the above copyright notice, the following
 * two paragraphs and the author appear in all copies of this software.
 * 
 * IN NO EVENT SHALL THE VANDERBILT UNIVERSITY BE LIABLE TO ANY PARTY FOR
 * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT
 * OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF THE VANDERBILT
 * UNIVERSITY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 * 
 * THE VANDERBILT UNIVERSITY SPECIFICALLY DISCLAIMS ANY WARRANTIES,
 * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
 * AND FITNESS FOR A PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS
 * ON AN "AS IS" BASIS, AND THE VANDERBILT UNIVERSITY HAS NO OBLIGATION TO
 * PROVIDE MAINTENANCE, SUPPORT, reportS, ENHANCEMENTS, OR MODIFICATIONS.
 *
 * Author: Miklos Maroti
 */

#include <Tasklet.h>

/*
 * You have to make sure that the maximum channel time in one report
 * period times (1 << TRAFFIC_MONITOR_DECAY) is less than 65535.
 */
#ifndef TRAFFIC_MONITOR_DECAY
#define TRAFFIC_MONITOR_DECAY	3
#endif

module TrafficMonitorLayerP
{
	provides
	{
		interface RadioSend;
		interface RadioReceive;
		interface RadioState;
	}

	uses
	{
		interface TrafficMonitorConfig;
		interface RadioSend as SubSend;
		interface RadioReceive as SubReceive;
		interface RadioState as SubState;
		interface Timer<TMilli> as Timer;
		interface Neighborhood;
		interface NeighborhoodFlag;
		interface Tasklet;
#ifdef RADIO_DEBUG
		interface DiagMsg;
#endif
	}
}

implementation
{
	tasklet_norace message_t *txMsg;
	tasklet_norace uint8_t neighborCount;

	tasklet_norace uint16_t txAverage;
	tasklet_norace uint16_t rxAverage;
	tasklet_norace uint8_t neighborAverage;
	tasklet_norace uint8_t errorAverage;

	enum
	{
		// the maximum average value
		TRAFFIC_MONITOR_UINT8_MAX = 1 << (7-TRAFFIC_MONITOR_DECAY),

		// the unsignificant bits of the averaged values
		TRAFFIC_MONITOR_MASK = (1 << TRAFFIC_MONITOR_DECAY) - 1,

		// to get the ceiling integer value
		TRAFFIC_MONITOR_ROUND_UP = (1 << TRAFFIC_MONITOR_DECAY) - 1,
	};

	tasklet_async event void SubSend.ready()
	{
		signal RadioSend.ready();
	}

	tasklet_async command error_t RadioSend.send(message_t* msg)
	{
		txMsg = msg;
		return call SubSend.send(msg);
	}

	tasklet_async event void SubSend.sendDone(error_t error)
	{
		if( error == SUCCESS )
			txAverage += call TrafficMonitorConfig.getChannelTime(txMsg);

		signal RadioSend.sendDone(error);
	}

	tasklet_async event bool SubReceive.header(message_t* msg)
	{
		return signal RadioReceive.header(msg);
	}

	tasklet_async event message_t* SubReceive.receive(message_t* msg)
	{
		uint8_t index;

		rxAverage += call TrafficMonitorConfig.getChannelTime(msg);

		index = call Neighborhood.insertNode(call TrafficMonitorConfig.getSender(msg));
		if( ! call NeighborhoodFlag.get(index) )
		{
			if( neighborCount < TRAFFIC_MONITOR_UINT8_MAX )
			{
				++neighborCount;
				call NeighborhoodFlag.set(index);
			}
		}

		return signal RadioReceive.receive(msg);
	}

	tasklet_async event void TrafficMonitorConfig.channelError()
	{
		if( errorAverage < 255 )
			++errorAverage;
	}

	uint8_t debugCounter;

	event void Timer.fired()
	{
		uint8_t fraction;

		call Tasklet.suspend();

		txAverage -= (txAverage >> TRAFFIC_MONITOR_DECAY);
		rxAverage -= (rxAverage >> TRAFFIC_MONITOR_DECAY);
		errorAverage -= (errorAverage >> TRAFFIC_MONITOR_DECAY);

		// we could get stuck in the [1,7] range with no neighbors, so be more precise
		fraction = neighborAverage >> TRAFFIC_MONITOR_DECAY;
		if( fraction == neighborCount && (neighborAverage & TRAFFIC_MONITOR_MASK) != 0 )
			--neighborAverage;
		else
			neighborAverage += neighborCount - fraction;

		call NeighborhoodFlag.clearAll();
		neighborCount = 0;

		call Tasklet.resume();

#ifdef RADIO_DEBUG
		if( ++debugCounter >= 10 && call DiagMsg.record() )
		{
			debugCounter = 0;

			call DiagMsg.str("traffic");
			call DiagMsg.uint16(signal TrafficMonitorConfig.getTransmitAverage());
			call DiagMsg.uint16(signal TrafficMonitorConfig.getReceiveAverage());
			call DiagMsg.uint8(signal TrafficMonitorConfig.getNeighborAverage());
			call DiagMsg.uint8(signal TrafficMonitorConfig.getErrorAverage());
			call DiagMsg.send();
		}
#endif
	}

	tasklet_async event void Tasklet.run()
	{
	}

	tasklet_async event uint16_t TrafficMonitorConfig.getTransmitAverage()
	{
		return txAverage >> TRAFFIC_MONITOR_DECAY;
	}

	tasklet_async event uint16_t TrafficMonitorConfig.getReceiveAverage()
	{
		return rxAverage >> TRAFFIC_MONITOR_DECAY;
	}

	tasklet_async event uint8_t TrafficMonitorConfig.getNeighborAverage()
	{
		return (neighborAverage + TRAFFIC_MONITOR_ROUND_UP) >> TRAFFIC_MONITOR_DECAY;
	}

	tasklet_async event uint8_t TrafficMonitorConfig.getErrorAverage()
	{
		return errorAverage >> TRAFFIC_MONITOR_DECAY;
	}

	tasklet_async event void Neighborhood.evicted(uint8_t index) { }

	enum
	{
		RADIO_CMD_NONE = 0,
		RADIO_CMD_TURNON = 1,
		RADIO_CMD_TURNOFF = 2,
	};
	tasklet_norace uint8_t radioCmd;

	tasklet_async command error_t RadioState.turnOff()
	{
		radioCmd = RADIO_CMD_TURNOFF;
		return call SubState.turnOff();
	}

	tasklet_async command error_t RadioState.standby()
	{
		radioCmd = RADIO_CMD_TURNOFF;
		return call SubState.standby();
	}

	tasklet_async command error_t RadioState.turnOn()
	{
		radioCmd = RADIO_CMD_TURNON;
		return call SubState.turnOn();
	}

	tasklet_async command error_t RadioState.setChannel(uint8_t channel)
	{
		radioCmd = RADIO_CMD_NONE;
		return call SubState.setChannel(channel);
	}

	tasklet_async command uint8_t RadioState.getChannel()
	{
		return call SubState.getChannel();
	}

	task void startStopTimer()
	{
		if( radioCmd == RADIO_CMD_TURNON )
			call Timer.startPeriodic(call TrafficMonitorConfig.getUpdatePeriod());
		else if( radioCmd == RADIO_CMD_TURNOFF )
			call Timer.stop();
	}

	tasklet_async event void SubState.done()
	{
		post startStopTimer();
		signal RadioState.done();
	}
}

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?