pwisa simulation framework overviewpawis.sourceforge.net/info/tutorial.pdf5.3 basic concepts 5.3.1...

22
+ +

Upload: others

Post on 12-Mar-2021

0 views

Category:

Documents


0 download

TRANSCRIPT

Page 1: PWiSA Simulation Framework Overviewpawis.sourceforge.net/info/tutorial.pdf5.3 Basic Concepts 5.3.1 Modularization The wireless sensor node is split up into modules, e.g. a CPU, the

PAWiS Simulation Framework Overview

Johann Glaser and Daniel Weber

July 1, 2008

Abstract

The PAWiS Simulation Framework facilitates thesimulation of wireless sensor networks. This in-cludes the internal structure of the sensor nodesas well as the network connecting them. Thisoverview document describes the basic principlesof the framework and gives a short introductionof its structure. A large part of this documentis taken by a tutorial including coding exampleswhich guide you to the usage of the framework.

1 Wireless Sensor Networks

Wireless sensor networks (WSN) are mainly usedin building automation, car interior devices, con-tainer tracking, bridge and vulcan maintenanceand monitoring as well as geological surveillance.The nodes comprise sensors for e.g. temperature,humidity, insolation, strain gauge and so on.

All nodes communicate with each other via anad-hoc multi-hop network. This means that thepackets are routed from node to node and therouting information accrues during the networkoperation. Special MAC and routing protocolswere developed for this purpose. The proba-bly best known is IEEE 802.15.4 ZigBee ([H+03],[IEE03]), but even more specialized protocols ex-ist (e.g. CSMA-MPS [MB04]).

The main development target is the low powerconsumption of every node to supply them withenergy scavenging or from a single battery, yetwith long lifetimes as long as 10 years.

2 Simulation Framework

The PAWiS Simulation Framework assists you inthe development and especially the optimizationof WSN nodes and network protocols. The inter-nal structure of the nodes as well as the commu-nication between them are simulated. The widerange of utilisation starts at tiny sensor nodes(e.g. the TinyMote [Roe04]) and reaches via tirepressure monitoring and car climate control toas complex systems as home entertainment (e.g.Sindrion [GSS+04]).

The internal structure of a node is built as avirtual prototype. This means that its function,the timing and power consumption as well ascommunication and node failures are simulated.With the true top down development methodol-ogy (see Fig. 1) the design starts at a functionalspecication and implementation. Guided by re-quirements the design is rened via architecturalmodels down to models reecting the actual im-plementation. On the other hand, physical con-straints eect the functional and architectural de-signs from bottom up.

Figure 1: Top down design methodology.

3 Work ow

The WSN node is split into functional blocks likea physical, a MAC, a routing and an applica-tion layer, a CPU, serial interface, AD convert-ers, timer and so on. Each of these blocks is thenmapped to modules in the simulation. For ev-ery functional block its module type is dened.This comprises its name and the standardized in-terfaces. For each of the module types severaldierent implementations can be prepared.The work ow of the design and optimization

of a WSN with the PAWiS Simulation Frame-work is depicted in Fig. 2. At the beginning thenode is composed from one module implementa-tion per module type from the module implemen-

1

Page 2: PWiSA Simulation Framework Overviewpawis.sourceforge.net/info/tutorial.pdf5.3 Basic Concepts 5.3.1 Modularization The wireless sensor node is split up into modules, e.g. a CPU, the

Figure 2: Renement cycles.

tations library. Then the modules are congured(e.g., clock frequency of the CPU, resolution ofthe ADC). In the next step the model is simu-lated and the results are evaluated.

Based on the simulation results the individualmodels are rened, i.e. their behaviour is imple-mented in more detail and more accurately. Ad-ditionally the modules' functions are altered toapproach to the design goals. The congurationof the models may be modied too and then thesimulation is performed again. Alternatively thecomposition of the total node may be changed, ifthe current selection of module implementationsdoes not meet the design goals.

These cyclic improvements of the models arecalled renement cycles and are the main track toenhance the development. When these renementcycles are completed, the nal outcome comprises

the function and

the architecture of the node, as well as

the implementation and

the power specication of every sub-module.

4 Optimization

Several strategies for the optimization of the wire-less sensor system are available. First of all asystem level optimization is performed. This in-cludes the node composition and even modica-tions of the whole system behavior like choosingdierent network layout or application patterns.The system level optimization guides you to anadequate system architecture.

In parallel cross-layer optimization is per-formed. This means that more than one networklayer is modied at a time. Probably each ofthese changes alone would degrade the node per-formance, but the interaction of them leads to animprovement of the total node.

All this optimization is performed by applyingthe following strategies.

Exchange the actual module implementationfor one module type, i.e. a dierent selectionfrom the library, e.g. a dual-slope, a Σ∆ oran SAR ADC. Another example is choosingdierent MAC protocols.

Partitioning of modules and/or functions bydividing the task between hardware and soft-ware, digital and analog or RF and baseband.For example a specic MAC protocol couldbe implemented in software or as a dedicatedhardware acceleration unit. A combinationof both is also possible.

The scale of a module, e.g. the resolution ofan ADC or the register count of a CPU.

Parameterization of modules, e.g. the tim-ing, transmission power and bit rate of a ra-dio transmitter.

5 The Framework

5.1 Structure

In Fig. 3 the basic structure and dependencies ofthe PAWiS Framework are depicted. The frame-work is based on the OMNeT++ discrete eventsimulation system and the C++ programminglanguage. The model programmer mostly inter-acts with the framework and C++.

The Framework requires the following tools:OMNeT++ discrete event simulator 3.3 andDoxygen 1.4.7. To compile on Unix machinesyou need the GCC compiler 4.0 or 4.1, Autoconf2.60a and Automake 1.9.6. On Windows the Mi-crosoft Visual Studio version 7 or 8 are required.Please consult the installation guide located athttps://clara.tuwien.ac.at/pawis/sim:doc.

2

Page 3: PWiSA Simulation Framework Overviewpawis.sourceforge.net/info/tutorial.pdf5.3 Basic Concepts 5.3.1 Modularization The wireless sensor node is split up into modules, e.g. a CPU, the

Figure 3: Structure of the PAWiS Framework.

5.2 Discrete Event Simulator

Since the PAWiS Simulation Framework is basedon the OMNeT++ Descrete Event SimulationSystem, we have to discuss how its event pro-cessing is working. Basically every module cangenerate new events which are stored in the socalled Future Event List (FEL). The simulationkernel steadily picks the earliest event (which hasthe semantic of a message transported from net-work node to node) from this FEL. The currentsimulation time, which is stored in a variable, isthen set to this event's time and the event is de-livered to the destination module.The destination module may itself insert new

events into the FEL. As soon as this task hasnished, the simulation kernel again consults theFEL and takes the earliest event.The simulation time therefore does not corre-

late to wall clock time, because it is only denedby the events generated during simulation. Forsimulations with large temporal distance betweenthe events, simulation time will elapse faster thanthe wall clock time. Contrary, simulations withdense temporal resolution, where the simulationkernel has to execute many events and their han-dlers, the simulation time may be slower than thewall clock time.

5.3 Basic Concepts

5.3.1 Modularization

The wireless sensor node is split up into modules,e.g. a CPU, the network protocol layers (applica-tion, routing, MAC, physical), a timer and so on.Each of these modules is implemented as a C++class derived from PawisModule.

5.3.2 Tasks

Within one module several tasks can be imple-mented and even run in parallel. The executionwithin one task is sequential but all tasks are run-ning concurrently. Every task is implemented asone class method.

This concurrency is implemented as coopera-tive multithreading, so every task has to denepoints where it passes execution to the simula-tion kernel. That means that the program ow isstopped at this point and later continues there.At these yield points the simulation time elapses.Everything between two such yield points hap-pens in the same instant of simulation time.

5.3.3 Functional Interfaces

Control ow transitions between two modules areimplemented as so called Functional Interfaces.These are similar to subroutine calls (see thegreen arrows in Fig. 4). Every functional interfaceis implemented as a task, so it can run in parallelto the other tasks. Note that the invocation of afunctional interface starts this task and after thetask has nished, the invocation returns. Thatmeans that functional interfaces are not runningpermanently but only when invoked.

Additionally at some points a module can de-ne a wait condition depending on another mod-ule. This is complemented by a mechanism totrigger a parallel task (see red arrows in Fig. 4).

Figure 4: Tasks inside modules and control owacross module borders.

3

Page 4: PWiSA Simulation Framework Overviewpawis.sourceforge.net/info/tutorial.pdf5.3 Basic Concepts 5.3.1 Modularization The wireless sensor node is split up into modules, e.g. a CPU, the

5.3.4 CPU

The submodules of a sensor node are usually ei-ther implemented as rmware (software), i.e. areexecuted by a CPU, or as dedicated hardware. Ev-ery module can have several tasks, and the can bemixed software and hardware tasks (e.g. the RFtransceiver hardware plus its driver). It is im-portant to note that software tasks can not runin parallel, since the CPU is only available once.Therefore the control ow is transferred from onemodule to another (think of subroutine call andreturn here) instead of triggered events.To model the power and time consumption of

software tasks the ideal case is a CPU simulatorwhich is fed by the actual rmware opcodes. Un-fortunately this is very time consuming. There-fore in the PAWiS framework the CPU simulationis split into two parts.The functional tasks of the rmware are writ-

ten in pure C++ code inside of the task methoditself. The timing and power consumption partis then delegated to the CPU module. It onlyreports its power consumption (on behalf of thereal module) and delays execution for the esti-mated processing time. This delegation is real-ized as requireCpu(percentage integer, percent-age oat, percentage memory access, percentageow control, duration). This call is one of theexit points of task coroutines.These requests include the estimated execu-

tion time of the rmware code on the CPU. Nowthink that the CPU of a given node should be re-placed during the optimization process (e.g., usean ARM instead of an MSP430) or change theconguration (e.g., use a faster crystal). Thiswould also require to modify all execution timeestimates in all modules of the node. To allows fora CPU exchange without the need to adapt othermodules the execution time estimates are referredto the so called norm CPU. This is an imaginarybut well dened CPU implementation (regardingits performance). The actual CPU model scalesits processing time and power consumption ac-cording to its individual properties and depend-ing on the percentages of execution types.The framework user has to implement the CPU

module as a C++ class derived from Cpu andoverride several virtual methods. See Sec. 6.5 fordetails.

5.3.5 Timing

Modeling time delays is dierent in rmwareand hardware modules. In hardware modulesjust use a wait(duration) call. There are thewaitUntil() and waitOrUntil() calls which al-low to wait for certain events.1 In rmware mod-

1These wait() calls are exit points of the coroutine.

ules this is not allowed, because it would standfor a wondrous jump in time.

How is a delay programmed in software? Oneway is a simple delay loop. This is easily modeledwith a call to requireCpu(). Note that such a de-lay must not be modeled as an actual loop in yourC++ code since it would only load your simula-tion host CPU but doesn't advance the simulationtime.

More complicated delay loops may have a ded-icated break condition to wait for a certain event(i.e., a ag set by an ISR or a dedicated timermodule). This can be implemented with therequireCpuUntil() and requireCpuOrUntil()methods.

Even more sophisticated delays utilize lowpower modes of the CPU. This sets the CPU to alow power mode which halts the execution untilan interrupt occurs. This will wake up the CPUwhich then continues its operation.

Note that time only elapses in wait() andrequireCpu() calls. Every C++ code you placebetween such calls virtually runs in the same timeinstant, i.e. no time elapses.

5.3.6 Interrupts

The interrupt handling is implemented in severalsteps. Within the modeled microcontroller nu-merous interrupt sources exist. These come fromsome other modules (e.g. a timer, an analog-digital-converter, ...). They are mapped to inter-rupt vectors. Every vector has a priority and aninterrupt service routine (ISR) assigned. Every-thing except the registration of the ISRs is real-ized within the CPUmodule (as described above).

Every (software) module can register its ISRfor an interrupt vector. When the interruptsource triggers an interrupt request, the CPUmodule maps it to the appropriate interrupt vec-tor, checks its priority and then transfers con-trol to the ISR. The currently running CPU task(read: the delay and power consumption) is in-terrupted and nished later.

5.3.7 Environment

All nodes are placed at 3D positions within theEnvironment. This manages the outer world ofall nodes including their surrounding and the RFchannel.

Besides the nodes themselves also other objectslike walls, oors, trees, interferers, heaters, lightsources, ... reside within the environment. Ad-ditionally global properties (e.g. the attenuationexponent b (see Sec. 5.3.8)) are dened. Every-thing is setup and congured with the scriptinginterface.

4

Page 5: PWiSA Simulation Framework Overviewpawis.sourceforge.net/info/tutorial.pdf5.3 Basic Concepts 5.3.1 Modularization The wireless sensor node is split up into modules, e.g. a CPU, the

Figure 5: The Environment with functions, ob-jects and sensor nodes

5.3.8 Air

The Air is a subcomponent of the environment tohandle the RF channels, which are dened by thenode placement and the obstacles between them.The RF signal is subject to wave propagation phe-nomenons like attenuation, reection, refraction,scattering and fading (multi-path propagation)from the transmitter to the receiver.

Theory The current implementation of the Aironly handles attenuation eects, because theother eects would require an enormous complex-ity in the simulator. For free space propagationthe receipient power is dened by

PRx = PTxGTx (−−−−→ϕTx,Rx) ·

GRx (−−−−→ϕRx,Tx)(λ

)2

d−b (1)

where GTx (−−−−→ϕTx,Rx) is the antenna gain of thetransmitter in the direction to the receiver andGRx (−−−−→ϕRx,Tx) is the antenna gain of the receiverin the direction to the transmitter. λ is the wave-length, d is the distance between the two nodesand b is the attenuation exponent. The latteris usually 2 for ideal free space propagation, butfor indoor environments higher values like 3.5 aremore appropriate.Alternatively the received power can be calcu-

lated by dividing the transmit power by the sur-face of a sphere 4πd2 (replacing the exponent byb) with radius equaling the distance of the receiverand transmitter d. This diluted power densityis then multiplied by the antenna area ARx of thereceiver.

PRx = PTx1

4πd−bARx (2)

The attenuation from the transmitter j to re-ceiver i is given by

Ai,j =PRx,i

PTx,j(3)

where i and j are the index of the node (i, j ∈1, 2, . . . , n). Calculating the attenuation from anynode to every other node gives the adjacency ma-trix

A =

A1,1 A1,2 · · · A1,n

A2,1 A2,2 · · · A2,n

......

. . ....

An,1 An,2 · · · An,n

(4)

Let the vectors−−→PTx and

−−→PRx hold the trans-

mitted and received power of all n nodes, respec-tively. Then the calculation of received power iseasily written by the matrix operation

−−→PRx = A

−−→PTx (5)

Since the results only make sense when a singletransmitter is active, only one value in

−−→PTx is dif-

ferent from zero and the matrix multiplication in(5) reduces to a single column scaling operation.The adjacency matrix is a precisely dened in-

terface from the environment to the data com-munication. For an actual environment setup Ais calculated. This is used during the networksimulation as shown in (5). Due to this simpleinterface, A can also be calculated by an externalRF channel simulation tool.The current implementation of the Air only

supports isotropic antennas with uniform antennagain. No obstacles are considered for the adja-cency matrix, though explicitly given additionalattenuations between every pair of two nodes aresupported.Every receiving node is notied of a data packet

transmitted via the Air. This notication con-tains the receiver power. The node then calcu-lates the signal to noise ratio (SNR) with its ownand the received noise power. From this SNR thebit error ratio (BER) is derived. The BER is afunction of the SNR which depends on the modu-lation format. From the BER the bit error countis calculated.

Implementation The implementation is de-scribed in Sec. 6.10.

5.3.9 Power Simulation

Every task simulates its power consumption. Atsimulation startup it registers at its power sup-ply module. This enables a hierarchy of powerdistribution. During simulation the actual con-sumption is calculated (by your C++ code) andreported to the power supply. This propagatesup the supply tree and is nally reported to thecentral Power Meter.The consumed power equals P = U · I. The

supply voltage U is provided by the supply mod-ule. Every consumer can have dierent electrical

5

Page 6: PWiSA Simulation Framework Overviewpawis.sourceforge.net/info/tutorial.pdf5.3 Basic Concepts 5.3.1 Modularization The wireless sensor node is split up into modules, e.g. a CPU, the

behavior. i.e. the current I depends in dier-ent ways on the supply voltage. Currently threekinds of power reporters are provided but you arefree to dene new ones.

ConstantReporter: I = Iconst. The currentdoes not depend on the supply voltage.

ResistiveReporter: I = UR . The supply

current is proportional to the supply voltage,typically as for a resistor.

LinearReporter: I = Iconst + UR . A constant

current plus a supply voltage dependant por-tion.

Dene your own reporter by deriving fromthe PowerReporter base class. This can im-plement any non-linear current characteris-tics you need.

The power supply module calculates its outputvoltage depending on the output current, there-fore dierent source behaviors are possible too.This results in a simple electrical network.At any point in a hardware task you can set a

new power reporter and its characteristics. Theprevious reporter is then replaced by a new one.The reporter handles all supply voltage changesaccording to its properties automatically.Note that only tasks which simulate dedi-

cated hardware consume power on their own.Tasks which simulate software tasks just use therequireCPU() method. The CPU module will re-port its power consumption and the additionalinfo for which task it is executing code.

6 Example

In this section we will discuss the implementationof a simple application doing some processing ina CPU and blinking a LED in parallel. This willdemonstrate all important concepts of the PAWiSFramework. For the description of the Environ-ment and the Air another example is introduced.

6.1 Modules

As shown in Fig. 6 the system is built of the fol-lowing modules: The main program is running inthe Application module (App) which is a puresoftware module. This is connected to the Timerand the LED to invoke their functions via theirfunctional interfaces. All modules (except theApp) are supplied by the power source LDO(low drop-out regulator). The timer can issue aninterrupt which interrupts the application pro-gram and starts the ISR (interrupt service rou-tine).

Figure 6: Modules of the LED example.

Every module is implemented as a C++class derived from the PAWiS Frameworkclass PawisModule (see Lst. 1). Inside ofthe class you have to use a special macroModule_Class_Members(class, parent, 0) whichdeclares the constructor and some other internalstu. Its rst parameter is always the name ofthe class, the second parameter is the parent classand the third must be 0.

In the class denition (see Lst. 3) you have toadd the macro Define_Module(class).

The class can contain as many member vari-ables and methods as you like.

Listing 1: Class declaration of the PAWiS moduleLed from led.h.

#include <memory>#include <base/paModule.h>#include "ledReporter.h"

using namespace pawis;

class Led : public PawisModule private:bool m_bState;std::auto_ptr<PowerSourceAdapter>m_pPowerAdapter;

void set(TaskControl &pa_oControl);

virtual void onStartup();virtual void onInit();

public:Module_Class_Members(Led, PawisModule, 0)

;

There are two virtual methods which you canoverride. They are automatically called uponstart of the simulation. onStartup() is rst exe-cuted for all modules, and then onInit() is exe-cuted for all modules. Therefore in onStartup()you have to register all your interfaces, powersources, . . . oered to other modules. InonInit() you can refer to the previously regis-tered items (of other modules). Read on for someexamples.

6

Page 7: PWiSA Simulation Framework Overviewpawis.sourceforge.net/info/tutorial.pdf5.3 Basic Concepts 5.3.1 Modularization The wireless sensor node is split up into modules, e.g. a CPU, the

6.1.1 The NED File

The module instantiation and connections be-tween each other are described in the so calledNED le. This is a text le used by the under-lying OMNeT++ framework to setup the wholenetwork.A NED le denes three types of objects which

are setup within a hierarchy. The highest level isthe network which we use to connect the individ-ual nodes. It is declared in a block of networkname : top module endnetwork (see Lst. 2). Seealso Sec. 5.3.7 how to build complex networks.The next lower level are compound modules de-

clared with module name ... endmodule blocks.They combine other compound or simple mod-ules and set their parameters and interconnect.Simple modules are the lowest level in the NED

hierarchy. These are the only items which ac-tually implement functionality. Therefore theyare the only items which have individual C++code provided by the programmer. That meansthat you will concentrate on the implementationof simple modules. To structure your networknodes you dene compound modules in the NEDle.The NED le is translated with the nedtool

tool (provided by OMNeT++) which creates aC++ source le with the postx _n.cpp. Thiscontains auto-generated C++ class declarationsfor the described compound modules and net-works. It must be compiled the same way as yourother C++ source les.A network node is built as a compound mod-

ule (see LedNode in Lst. 2). You can dene oneor more dierent types of network nodes. Thecompound module representing the network (hereLedNetwork) can instanciate any number of thesenodes. Simply ensure that your module codeimplements interoperability between the dierentkinds of nodes.

Listing 2: NED le for the LED example fromLed.ned.

simple SimpleCpuendsimple

simple Ledgates:in: App_in;out: App_out;

endsimple

simple Appgates:in: Timer_in;in: Led_in;out: Timer_out;out: Led_out;

endsimple

simple Timergates:in: App_in;out: App_out;

endsimple

simple Ldoendsimple

simple Batteryendsimple

simple Configparameters:ConfigFile: string;

endsimple

module LedNodeparameters:NodeId : const;

submodules:cpu : SimpleCpu;led : Led;app : App;timer : Timer;ldo : Ldo;battery : Battery;

connections:app.Led_out --> led.App_in;app.Led_in <-- led.App_out;app.Timer_out --> timer.App_in;app.Timer_in <-- timer.App_out;

endmodule

module LedNetworksubmodules:config : Configparameters:ConfigFile = "";

ln1: LedNodeparameters:NodeId = 1;

endmodule

network lednet : LedNetworkendnetwork

6.1.2 Messages

Modules can commmunicate each other by send-ing messages (through the corresponding gates).Each abstraction layer requires a message class,which is derived from the Pawis FrameworkBaseMessage class. Each implementation in-cludes the specic header elds for each layer.Messages can be easily implemented by writinga simple .msg le which is translated by theopp_msgc OMNeT++ application into a C++ lewith autogenerated methods to access the headerelds.

7

Page 8: PWiSA Simulation Framework Overviewpawis.sourceforge.net/info/tutorial.pdf5.3 Basic Concepts 5.3.1 Modularization The wireless sensor node is split up into modules, e.g. a CPU, the

6.2 Tasks

Every module is built of tasks. Each of these tasksis implemented as a method inside of the mod-ule's class. Their name can be chosen freely butthey must accept exactly one parameter of thetype TaskControl&. The return type is void (seeApp::myMain() and App::onTimer() in Lst. 3).The TaskControl& parameter holds an object

which is a unique representation of the task. Itcontains the status and context of the task as wellas some task-related methods like invoke() (seebelow).Tasks are virtually running in parallel as de-

scribed in Sec. 5.3.2. Their execution leaves atcertain (dened) points (yield). The simulationkernel then hands over control to other tasks. Theexecution of the task is then continued where itwas interrupted.Points where the execution is transferred to

other tasks are

wait(delay)

waitUntil(predicate)

waitOrUntil(delay , predicate)

requireCpu()

requireCpuUntil()

requireCpuOrUntil()

invoke() and invokeReturn() with vari-ous combinations of parameter types (seeSec. 6.3.2).

Please see the Doxygen documentation ofTaskControl for details and the exact parameterlists of these methods.Within every task you can have loops, if and

switch conditions, ... Note that you must includeyield points as described above or return from themethod after performing the desired job. Other-wise your C++ method will never give back con-trol to the simulation kernel (this is why we callthis cooperative multitasking). When the methodexits (e.g. with return), the task is nished.Every task models either a dedicated hardware

block (e.g. a timer, an AD converter, ...) or somesoftware running on the CPU (e.g. the routinglayer of your protocol). Within one module youcan have as many tasks and mix hardware andsoftware tasks as you need.All tasks can access the member variables of the

module class instance which are shared amongstthe tasks. This is even possible when the sametask method is running multiple times. For vari-ables which are unique to every task instanceuse the stack, i.e. declare local variables withinthe method. Note that every task has its own

stack, which is limited. To set the stack size,the functions startTask(), registerIsr() andregisterFunctionalInterface() oer an addi-tional parameter. Its default value currently is32kB.

A task can be started in two dierent ways.Tasks that should just run from the beginningon are started from the onInit() method (seeLst. 3) using the startTask(name, task method,params in, params out) call. Note that this func-tion can be used anywhere and anytime to cre-ate new tasks. Its rst parameter is the method(using a macro to cast to the proper type).The second and third parameters are pointers toParameterList objects for input and output pa-rameters, respectively. They can be 0 and arediscussed in detail with functional interfaces.

The second kind of task creation is using func-tional interfaces and is described below.

A call to startTask() is always non-blockingwhich means that the started task runs in paralleland independently. The starter does not wait forany condition (e.g. nishing) of it.

Listing 3: Implementation of the PAWiS moduleApp from app.cpp showing a task.

#include "app.h"

Define_Module(App);

void App::onInit() // init member variables// ...// register ISRsregisterIsr(CAST_TASK(App::onTimer), 17,"timer_isr");

// schedule initial taskstartTask("main",CAST_TASK(App::myMain),0,0);

void App::onTimer(TaskControl &pa_oControl) // do our internal workm_bLedState = !m_bLedState;

// set the LEDpa_oControl.requireCpu(0.5, 0.0, 0.2, 0.3,0.001f);

pa_oControl.invoke("Led", "set", m_bLedState);

// setup new timer eventpa_oControl.requireCpu(0.5, 0.0, 0.3, 0.2,0.005f);

pa_oControl.invoke("Timer", "start",(unsigned int)(20));

++m_nCounter;

// predicate function for requireCpuOrUntil()bool App::done() // test an external condition,

8

Page 9: PWiSA Simulation Framework Overviewpawis.sourceforge.net/info/tutorial.pdf5.3 Basic Concepts 5.3.1 Modularization The wireless sensor node is split up into modules, e.g. a CPU, the

// e.g. ADC has finished conversionif (m_nCounter > 2)

return true;return false;

void App::myMain(TaskControl &pa_oControl) // ...// start the LED togglingonTimer(pa_oControl);// Before Start waiting 50ms or the predicatepa_oControl.requireCpuOrUntil(0.1f,0.0f,0.0f,

0.9f, 0.05, CAST_PREDICATE(App::done));// main program running infinitelywhile (true)

pa_oControl.setCpuState(new SimpleCpu::CpuState(SimpleCpu::CpuState::pmSleep));

pa_oControl.requireCpu(/* ... */, 1.0e-6);

6.3 Functional Interfaces

The Timer as well as the LED oer a functionalinterface each which is used by the Application(red arrows in Fig. 6, method set() in Lst. 1 andstartTimer() in Lst. 4).

6.3.1 Setup

The functional interface must be registeredin onStartup() (and not in onInit()) withregisterFunctionalInterface(name, method,multiInvokable) (see Lst. 4). The rst parameteris a string with the name of the interface (referredto by other modules). The second parameter isa casted pointer to the task method. The thirdparameter tells the framework, if this functionalinterface is intended to be invoked multiple timesin parallel. When set to false the frameworkdoes additional sanity checks to warn the user ofmultiple invocations.

6.3.2 Invocation

Other modules can then invoke the functional in-terface with the method invoke(module, inter-face, params in, params out) (see onTimer() inLst. 3). There are multiple overloaded versionsof invoke() for several combinations of parame-ters as well as invokeReturn<typename>() meth-ods for typed return values. This are conveniencefunctions that you don't have to setup a param-eter list. For details please consult the Doxygendocumentation of TaskControl.Whenever a functional interface is invoked from

another module, a new task is created and itsmethod (here Timer::startTimer()) is executed.

When this method returns, invoke() returns tooand execution of the caller continues. That meansthat invoke() is always blocking (see both callsof invoke()).

6.3.3 Parameters

The task App::onTimer() also shows how to sup-ply parameters to a functional interface. The rstfunctional interface invocation to Led.set sup-plies one parameter of type bool. Here one of theabove mentioned overloaded versions of invoke()is used.Alternatively a ParameterList object could be

created and the parameter(s) added with theadd<type>(value) template method. When theinvocation returns the input parameter list is con-sumed, i.e. the added parameters are cleared.This means that the ownership of the parametersis transferred from the caller to the callee, whichis responsible for delete'ing reserved memory.This is not relevant for the overloaded invoke()methods with templated parameter types. TheParameterList object can be reused for thenext invocation of another functional interface.For convenience Timer.start, which requires anunsigned int specifying the delay in milliseconds(see Lst. 4) is again called with an overloadedinvoke().

Listing 4: Implementation of the PAWiS moduleTimer from timer.cpp.

#include "timer.h"

/* ... */

void Timer::onStartup() // register the functional interfaceregisterFunctionalInterface("start",CAST_TASK(Timer::startTimer), false);

void Timer::onInit() // setup interrupt sourcem_oTimerSource.setName("timer");// register our interrupt sourceregisterIntSource(m_oTimerSource);// Create power source adapter and reporterm_pPowerAdapter.reset(new PowerSourceAdapter(

*getContext().findPowerSource("ldo"),LdoPowerSource::src3V3, 0, true));

m_pPowerAdapter->setReporter(new LinearReporter(*this));

// Initial consumptionm_pPowerAdapter->getReporter<LinearReporter>()->set(0.0f, /* infinite */);

void Timer::countTimer(TaskControl &pa_oControl) // start the timer

9

Page 10: PWiSA Simulation Framework Overviewpawis.sourceforge.net/info/tutorial.pdf5.3 Basic Concepts 5.3.1 Modularization The wireless sensor node is split up into modules, e.g. a CPU, the

m_pPowerAdapter->getReporter<LinearReporter>().set(2.2e-3, 1.5e6);

// show that we are runningsetFillColor("#FF0000");// wait for the delaypa_oControl.wait(m_tDelay);// timer has run offm_pPowerAdapter->getReporter<LinearReporter>().

set(1.2e-3, 1.5e6);// show that the timer ran offsetFillColor("#00FF00");// issue an interrupt requestpa_oControl.intRequest(m_oTimerSource);

void Timer::startTimer(TaskControl &pa_oControl) // get the delay parameter and calc the secondsm_tDelay = pa_oControl.inParams()->get<unsigned int>(0) / 1000.0f;

// start parallel task doing the delaystartTask(CAST_TASK(Timer::countTimer), 0, 0);

The implementation of a functional interfaceis shown in Lst. 4. The (previously regis-tered) method Timer::startTimer() is executedupon the invocation of the functional interfaceTimer.set. This extracts the rst parameter (0)from the parameter list held by the TaskControl&object and stores it to a member variable. It isimportant that the type (supplied as a templateparameter) must exactly match to the one sup-plied to the according invoke().Secondly a new task is created with

startTask(). It will run in parallel (andtherefore independently) to the functional in-terface task which allows the method to returnimmediately.

6.4 Timing

6.4.1 Hardware tasks

As stated in Sec. 5.3.5 hardware tasksmodel time delays with the methodswait(delay), waitUntil(predicate function)and waitOrUntil(delay,predicate function).The rst function delays execution for a constantamount of time, the second function delaysexecution until a certain condition (tested bythe predicate function) is fullled. The thirdform returns after a constant delay or until thecondition is true, whichever happens rst. In thetask method Timer::countTimer() in Lst. 4 thetimer delay is realized with the wait() method.The parameter of wait(Or)Until() (and

requireCpu(Or)Until() is a so called predi-cate function which tells the simulation kernelwhether the (modeled) job has nished or not(see App::done()). This is evaluated as long aswait(Or)Until() is active. The function has

to return true to stop and false to continuewait(Or)Until().Usually the predicate function has to reside

within the same module where it is used. With aderived class from TaskControl::Predicate (e.g.the available TaskControl::ModulePredicate)you can implement predicate function acrossmodule boundaries.Note that both, wait() and wait(Or)Until(),

are blocking functions which means that simula-tion time elapses whenever they are used. There-fore they are yield points within the task method.

6.4.2 Software tasks

In software tasks a delay is modeled dierently asalready described in Sec. 5.3.5.

6.4.3 Trigger

As stated in Sec. 5.3.3 one task can wait for atrigger condition satised by another task. Thisis modeled by two separate tasks. The rst task isstarted from onInit() and uses a waitUntil() towait for the trigger. The second task implementsa functional interface and sets a class membervariable which is queried by the predicate func-tion used with the waitUntil().

6.5 CPU

As described in Sec. 5.3.4 the CPU usage issimulated with the requireCpu(percentage inte-ger, percentage oat, percentage memory ac-cess, percentage ow control, duration) methodfrom the TaskControl& object. In the methodApp::onTimer() in Lst. 3 this call is used twice.At rst the software eort to set the LED's stateis modeled, and the second call models the setupof the timer.requireCpu() is useful for tasks where the to-

tal execution time is principally determinable be-fore its start. For CPU tasks which run untila certain external condition set their end, therequireCpuUntil(percentage integer, percentageoat, percentage memory access, percentage owcontrol, predicate function) method is used, sim-ilar to the waitUntil() function.As already mentioned there is also

a combined delay and condition func-tion requireCpuOrUntil() (see Lst. 3,App::myMain()). The example shows howto model a task which is waiting for an externalcondition (e.g. a counter value is reached, thePHY has nished transmission, ...). To avoidinnite hangs a certain timeout is used as secondexit condition. Lst. 5 shows how such rmwarecode could look like. P1IN is a digital 8-bit inputport where the bit nr. 5 will go high when the

10

Page 11: PWiSA Simulation Framework Overviewpawis.sourceforge.net/info/tutorial.pdf5.3 Basic Concepts 5.3.1 Modularization The wireless sensor node is split up into modules, e.g. a CPU, the

external peripheral has nished its job. Thevariable timeout is used to count upwards and iscompared with the constant TIMEOUT_50ms. Itsvalue is precalculated so that the loop lasts for50ms when executed TIMEOUT_50ms times.

Listing 5: Sample code showing a waiting loopwith external condition and timeout.

timeout = 0;while (((P1IN & 0x20) == 0) &&

(timeout < TIMEOUT_50ms)) timeout++;

Note that the requireCpu() functions areblocking, which means that simulation timeelapses during their execution. Therefore theyare yield point of a task.The numbers given to requireCpu() are used

by the CPU implementation to determine the realexecution time and power consumption. The rstfour numbers reect the proportions of dierentprocessing types. You have to estimate them de-pending on your real code. Ensure that they sumup to 1.0.The fth parameter gives the total execution

time referred to the norm CPU. To determinethis you have several options. The most accu-rate is surely using a CPU simulation tool andmeasure the time for a certain task programmedas rmware code. Alternatively you can use realhardware and measure the processing time withan oscilloscope.2

Since the contribution of the CPU to powerconsumption and timing is rather small, these val-ues don't have to be very accurate. Therefore youcan also estimate the durations yourself.

6.5.1 Callbacks

A callback is a method which is called after acertain amount of time. It is scheduled withscheduleCallback(method,delay) and can becanceled with cancelCallback(). For furtherdetails consult the Doxygen documentation ofPawisBase.

6.5.2 CPU Module Implementation

The CPU implementation is a class derived fromthe PAWiS base class Cpu. You have to implementcertain virtual methods to customize the simu-lation model. For a very simple CPU you onlyhave to implement onInit(), calcCpuTime() andgetIntVectorPriority().

2Set a digital output of your micro controller high di-

rectly before your routine and back to low directly after-

wards. Attach the oscilloscope to this output pin and use

its measurement tools to get the duration of this pulse.

The method calcCpuTime() has to calculatethe real execution time of a processing requestdepending on the desired CPU characteristics. Inour example (see Lst. 6) we implement a CPUwith the same performance as the norm CPU andtherefore simply use the norm-CPU referred exe-cution time. Please consider the Doxygen docu-mentation of FuncCpuMessage on how to retrievethe percentage values of the individual processingdomains.

Since the CPU can handle interrupts, the prior-itizing of concurrent interrupts requires classica-tion of the individual interrupt vectors. You haveto implement this in getIntVectorPriority().Again, we stay simple and prioritize the vectorsaccording to their numerical value.

The initialization of the module in onInit()has to assign an interrupt mapping as describedin Sec. 6.7. This can also be done from anothermodule by retrieving a pointer to the CPU in-stance. Here we also setup a power reporter, fullyanalogous to Sec. 6.6.1.

A special feature of our simple CPU isthe sleep state. The user of the CPU usesTaskControl::setCpuState(TaskControl::Cpu-State) to set a new state (see Lst. 3). Note thatthe parameter is a class to allow unlimited fea-tures. We derive from this class and provide twodierent modes pmActive and pmSleep. Everytime the user uses setCpuState() the methodonStateChange() (see Lst. 6) is executed. De-pending on the supplied mode the accordingpower consumption is reported. Finally the CPUexecution is either pause()d or resume()d.

To reactivate the CPU in case of an inter-rupt the method onIsrEnter() uses the inter-nal method Cpu::setCpuState(). This imple-mentation results in the behavior that the CPUis woken by an interrupt and then stays ac-tive, even if the ISR has nished. Thereforein App::myMain() the power mode is set againin an innite loop (see Lst. 3). The methodalso shows an important fact: You have touse requireCpu() after deactivating the CPUto simulate the stopped execution. That meansthat simply calling setCpuState() only internallystores that the CPU is deactivated. To experiencethis fact a processing request has to be performedwhich will not start until the CPU is reactivatedagain.

You could also override the methodonIsrLeave() and set the power mode topmSleep again. Note that in this case the mainprogram could not wake up again, becauseevery interrupt deactivates the CPU after it hasnished. To solve this problem the ISR candecide whether the CPU should stay active afterits end or shut-down again.

11

Page 12: PWiSA Simulation Framework Overviewpawis.sourceforge.net/info/tutorial.pdf5.3 Basic Concepts 5.3.1 Modularization The wireless sensor node is split up into modules, e.g. a CPU, the

To implement this you have to utilize thefull power of using a class CpuState forsetCpuState(). With this you can communi-cate the desired behavior to the Cpu module.In Lst. 6 an immediate reaction of the orderedpower mode is accomplished in onStateChange()whereas in the above case the desired behavior ofa future event has to be stored and then handledin onIsrLeave(). The current power mode aswell as the power mode after returning from theISR have to be stored in a state stack which is ma-nipulated using a special CpuState class. An ex-ample of this topic is the CpuSimple of the ModuleLibrary.

Listing 6: Declaration and implementation of theCpu module from cpu.h.

/* ... */#include <base/paCpu.h>/* ... */

class SimpleCpu : public Cpu public:

class CpuState: public TaskControl::CpuState public:

typedef enum pmActive,pmSleep

t_PowerMode;private:t_PowerMode m_PowerMode;

public:CpuState(t_PowerMode pa_PowerMode) m_PowerMode = pa_PowerMode;

t_PowerMode getPowerMode() const return m_PowerMode;

;

private:std::auto_ptr<PowerSourceAdapter>

m_pPowerAdapter;InterruptMapping m_oIntMapping;

protected:virtual t_Time calcCpuTime(const FuncCpuMessage &pa_msgCpu)

return pa_msgCpu.getDuration();

virtual int getIntVectorPriority(TaskControl::t_IntVector pa_intVector)const

return pa_intVector;

virtual void onStateChange(/* ... */) const CpuState* stateNew =dynamic_cast<const CpuState*>(pa_stateNew);

if (stateNew->getPowerMode() ==CpuState::pmActive)

// CPU is activem_pPowerAdapter->getReporter<LinearReporter>()->set(3.2e-3, 1.5e3);

resume(); else // CPU in sleep statem_pPowerAdapter->getReporter<LinearReporter>()->set(5e-5, 1e6);

pause();

void onIsrEnter() setCpuState(new CpuState(CpuState::pmActive));

virtual void onInit() // setup power reporterm_pPowerAdapter.reset(new PowerSourceAdapter(

*getContext().findPowerSource("ldo"),LdoPowerSource::src3V3, 0, true));

m_pPowerAdapter->setReporter(new LinearReporter(*this));

// setup interrupt mappingm_oIntMapping.setMapping("timer", 17);setInterruptMapping(&m_oIntMapping);// set initial statesetCpuState(new CpuState(CpuState::pmActive));

public:Module_Class_Members(SimpleCpu, Cpu, 0)

;/* ... */

6.6 Power Simulation

6.6.1 Power Consumption

Only hardware tasks draw power on their own.The power consumption of software tasks is mod-eled by the CPU module which is activated withthe requireCpu() calls.

Permanent hardware tasks have to reg-ister at their power supply with a callto TaskControl::subscribePowerSource(sourcename, source number). The source name is astring which selects the supply module. Everysource can implement several outputs (e.g. anLDO with two dierent output voltages sourc-ing from one input). The second parameter isan integer specifying the supply module's outputnumber.

Afterwards the consumption reporter isset and congured. The template method

12

Page 13: PWiSA Simulation Framework Overviewpawis.sourceforge.net/info/tutorial.pdf5.3 Basic Concepts 5.3.1 Modularization The wireless sensor node is split up into modules, e.g. a CPU, the

TaskControl::getReporter<type>() returnsa reference to the internally stored reporterobject where type is the reporter class type (seeSec. 5.3.9). If you use dierent types within onetask after another the previous reporter object isdeleted and a new one is created. The referenceis used to execute the reporter's set(...) methodwhich accepts the parameters according to thereporter's properties.Reporting the consumption means that you

specify from now on I'm consuming n mA cur-rent. This is just the start of a periode. Its endis determined only by another set() invocationin the same task.Note that with the destruction of the

TaskControl object (which happens when yourtask has nished), the PowerReporter object isalso destroyed. That means that the power con-sumption of that task also stops. Therefore thedescribed method is only applicable for taskswhich are started once and will run forever.On the other hand you might as well imple-

ment tasks which only run for a certain while,e.g., to start some timer (see Lst. 4) or toswitch a device on or o (see Lst. 7). Suchtasks are usually invoked externally. In thatcase the task exits while the current consumptionshould continue. To implement this behavior youhave to instantiate your own PowerReporter andPowerSourceAdapter objects.Lets have a look at Lst. 7. The LED current

consumption is updated in the set() functionalinterface. If it is switched on, the forward voltageUf is set to 2.2V and the series resistor to 280Ω.To switch o the LED its series resistor is set to∞. This is a trick because we don't want to sim-ulate a switch. Note that the method set() im-mediately exits and assumes that the power con-sumption continues.Therefore in the method onInit() a

PowerSourceAdapter object is created. Thisis necessary to connect a PowerReporter toa PowerSource. This PowerReporter is thenassigned to the PowerSourceAdapter usingsetReporter(). A fully analogous case can befound in Lst. 4 where the method countTimer()implements a waiting timer task. It is started bystartTimer() and sets the power consumptionof the running timer. Then it uses wait() toimplement the timer delay and nally reports thepower consumption of the inactive timer, issuesan interrupt request end exits. This inactivepower consumption has to continue until it isnext invoked.

Listing 7: Class implementation of the PAWiSmodule Led from led.cpp.

/* ... */

void Led::onStartup() registerFunctionalInterface("set",CAST_TASK(Led::set), false);

void Led::onInit() // Create power source adapter and reporterm_pPowerAdapter.reset(new PowerSourceAdapter(

*getContext().findPowerSource("ldo"),LdoPowerSource::src5V, 0, true));

m_pPowerAdapter->setReporter(new LedReporter(*this));

// Initial consumptionm_pPowerAdapter->getReporter<LedReporter>()->set(0.0f, /* infinity */);

void Led::set(TaskControl &pa_oControl) m_bState = pa_oControl.inParams()->get<bool>(0);

if (m_bState) m_pPowerAdapter->getReporter<LedReporter>()->set(2.2f, 280.0f);

setFillColor("#40ff40"); else m_pPowerAdapter->getReporter<LedReporter>()->set(0.0f, /* infinity */);

setFillColor("#206020");

6.6.2 Power Sources

In your simulation most power sources will beconverters (LDO, DC/DC), i.e. no real sources.But you will have at least one real powersource (like a battery or a solar cell). Tobuild such power sources a class derived fromPowerSource or PendingPowerSource is imple-mented (see Lst. 8). These base classes are usedfor real sources (e.g. batteries) and for sourceswhich are themselves consumers (e.g. LDOs orbuck converters), respectively.In our example the LdoPowerSource imple-

ments two sources (NumSources) with 5V (src5V)and 3.3V (src3V3). These constants are used bythe consumers (see Lst. 4) and in calcVoltage()and calcCurrent() (see Lst. 9).The LdoPowerSource is itself a consumer and

therefore requires its own power source (see itsconstructor). BatterySource is the origin of en-ergy and thus doesn't have another source.The power source classes are instantiated in the

normal PawisModule Supply (see also Lst. 9).

Listing 8: Declaration of the power source moduleLdo from ldo.h.

13

Page 14: PWiSA Simulation Framework Overviewpawis.sourceforge.net/info/tutorial.pdf5.3 Basic Concepts 5.3.1 Modularization The wireless sensor node is split up into modules, e.g. a CPU, the

/* ... */#include <base/paPowerSource.h>#include <base/paLinearReporter.h>#include <base/paPendingPowerSource.h>#include <base/paLimitCycleBehaviour.h>/* ... */

class LdoPowerSource : public PendingPowerSource public:

static const unsigned int NumSources = 2;static const unsigned int src5V = 0;static const unsigned int src3V3 = 1;

private:float m_fSourceImpedance5V;float m_fSourceImpedance3V3;

protected:virtual t_Voltage calcVoltage(/* ... */);virtual t_Current calcCurrent(/* ... */);

public:LdoPowerSource(

PawisModule& pa_oModule,PowerSource* pa_pPowerSource,unsigned int pa_iPowerSourceNum);

;

class BatterySource : public PowerSource protected:

LinearReporter m_oReporter;virtual t_Voltage calcVoltage(/* ... */);

public:BatterySource(PawisModule& pa_oModule);

;

class Supply : public PawisModule private:

BatterySource* m_pBatterySource;LdoPowerSource* m_pLdoSource;void onStartup();

public:Module_Class_Members(Supply, PawisModule, 0)

;

/* ... */

Every supply class has to implement themethod calcVoltage() which is called when-ever an output current changes. In this exam-ple we implement two simple sources with con-stant output resistance m_fSourceImpedance5Vand m_fSourceImpedance3V3 (see Lst. 9). Sincethe LdoPowerSource itself is a consumer too, themethod calcCurrent() also has to be imple-mented. This must return the total current con-sumption. Its parameter OutputSource carriesthe information which output has changed so thatthe input current must be recalculated. In the ex-ample we have stored the individual output cur-rents in member variables and simply return thesum of them plus a constant quiescent current.

The BatterySource is implemented as a never

ending 12V source. The reporting of the energyorigin is done with m_oReporter). Note that thereporter is instantiated without a source, there-fore we have to set the input voltage by hand withsetVoltage().In LdoPowerSource's constructor we have to as-

sign an update behavior to our source. As de-scribed in Sec. 5.3.9 the output voltage of a sourcecan change on the current load. The current loaditself also depends on the output voltage, there-fore iterative calculation of the true values is per-formed. The update behavior class determineshow this updates are performed. Here we use aclass which limits the count of iterative cycles to2.

Listing 9: Implementation of the power sourcemodule Ldo from ldo.cpp.

/* ... */

/**** Ldo Module *****************************/

Define_Module(Supply);

void Supply::onStartup() // create and register the battery sourcem_pBatterySource = new BatterySource(*this);m_oThisContext.registerPowerSource("battery",

*m_pBatterySource);// create and register the LDO sourcem_pLdoSource = new LdoPowerSource(*this,m_pBatterySource, 0);

m_oThisContext.registerPowerSource("ldo",

*m_pLdoSource);

/**** LdoPowerSource *************************/

t_Voltage LdoPowerSource::calcVoltage(unsigned int pa_nSource,t_Current pa_fCurrentSum)

t_Voltage ret;switch(pa_nSource) case src5V:

ret = 5.0f -pa_fCurrentSum * m_fSourceImpedance5V;

break;case src3V3:ret = 3.3f -pa_fCurrentSum * m_fSourceImpedance3V3;

break;default:// error

return ret;

t_Current LdoPowerSource::calcCurrent(unsigned int pa_nOutputSource)

return (calcCurrentSum(src5V) +

14

Page 15: PWiSA Simulation Framework Overviewpawis.sourceforge.net/info/tutorial.pdf5.3 Basic Concepts 5.3.1 Modularization The wireless sensor node is split up into modules, e.g. a CPU, the

calcCurrentSum(src3V3) +m_fSourceCurrent3V3 + 10e-6);

LdoPowerSource::LdoPowerSource(PawisModule& pa_oModule,PowerSource* pa_pPowerSource,unsigned int pa_iPowerSourceNum) :PendingPowerSource(pa_oModule, NumSources)

// Source for our own power consumption.setPowerSource(*pa_pPowerSource,

pa_iPowerSourceNum);// setup internal variablesm_fSourceImpedance5V = 1.0f;m_fSourceImpedance3V3 = 1.5f;// update behaviorassignBehaviour(new LimitCycleBehaviour(2));

/**** BatterySource **************************/

BatterySource::BatterySource(PawisModule& pa_oModule) :m_oReporter(pa_oModule)

assignBehaviour(new LimitCycleBehaviour(2));m_oReporter.setVoltage(12.0);

t_Voltage BatterySource::calcVoltage(unsigned int pa_nSource,t_Current pa_fCurrentSum)

m_oReporter.set(pa_fCurrentSum, 1e6);// luckily we have an infinitely full batteryreturn m_oReporter.getInputVoltage();

6.6.3 Power Reporter

As already denoted in Sec. 5.3.9 there areseveral predened power reporter classes, e.g.ConstantReporter. For special consumption be-havior (i.e. non-linear current characteristics)you have to dene your own reporter class.The Led module shows the usage of the customLedReporter to implement the characteristic of aLED with a series resistor in a simplied way (seeLst. 10).The reporter is derived from the class

PowerReporter and has to implement the meth-ods calcCurrent() and set(). The pa-rameters of set() can be dened freely asyour simulated consumer requires. Herewe consider a (constant) forward voltage ofthe LED (pa_fVoltage) and a series resistor(pa_fResistorValue). In calcCurrent() thecurrent consumption at a given input voltage (re-trieved with getInputVoltage()) is calculated.In our case we have to ensure that the current is

non-negative.

Listing 10: Declaration and implementation ofthe custom power reporter LedReporter fromledReporter.cpp.

/* ... */

#include <base/paPowerReporter.h>

class LedReporter : public PowerReporter private:t_Voltage m_fVoltage;float m_fResistor;

public:LedReporter(PawisBase &pa_oBase) :PowerReporter(pa_oBase),m_fVoltage(0.0f),m_fResistor(/* infinity */)

virtual t_Current calcCurrent() if (getInputVoltage() > m_fVoltage) // valid condition: calc currentreturn(getInputVoltage() - m_fVoltage)/ m_fResistor;

else // otherwise - no currentreturn 0.0f;

void set(t_Voltage pa_fVoltage,float pa_fResistor)

m_fVoltage = pa_fVoltage;m_fResistor = pa_fResistor;currentChanged();

;

6.6.4 Power Logging

Whenever the power consumption of a taskchanges (i.e., the set() method of a power re-porter is invoked), it is logged to an external logle together with the time and module and taskinformation. Additionally the requesting moduleis stored, e.g. when the CPU consumes power onbehalf of the routing network layer.

To mark certain points in your processing thereportEvent(string) method can be used. Thestring is simply stored with a time stamp andmodule information in the log le.

The logged data is processed and visualizedwith the DataProcessing tool (see Fig. 7). Thegraph area shows the power consumption se-quence over time. The module hierarchy is shownin the bottom left of the windows. Click withthe right button at a modules name to change itscolor. When you move the mouse in the graph

15

Page 16: PWiSA Simulation Framework Overviewpawis.sourceforge.net/info/tutorial.pdf5.3 Basic Concepts 5.3.1 Modularization The wireless sensor node is split up into modules, e.g. a CPU, the

window, an overlay eld displays the current val-ues of all modules at the marked time.To zoom horizontally or vertically use the

shifters at the bottom right of the graph window.Click and hold the right mouse button to pan theimage. You can also use the scroll bars for that.The button [Reload] is used to reload the log le(e.g. after another simulation run). Use [Fit Key]to t the graph horizontally (i.e. time axis) and[FitValue] to t it vertically (i.e., power axis).

Figure 7: Screenshot of the DataProcessing tool.

6.7 Interrupts

To model interrupts with the PAWiS Frame-work the interrupt source has to register withregisterIntSource(intSource&). The parame-ter is a reference to a TaskControl::IntSourceobject. Use its setName() method before you reg-ister the source to name the interrupt source aslater used by the CPU interrupt mapping. Notethat this must be called within your onInit()method (see Lst. 4).To issue an interrupt request, the method

TaskControl::intRequest(intSource&) is used(see countTimer() in Lst. 4). This method isnon-blocking, i.e. it immediately returns and theinterrupt request is handled by the next coroutineyield point.To process an interrupt request, an interrupt

service routine (ISR) must be registered withregisterIsr(isrTask, intVector, name) (seeonInit() in Lst. 3). A separate task context iscreated for this ISR method (see App::onTimer()in Lst. 3) whenever it is executed. The ISR hasnished when you return from the method.It is important to note that the PAWiS Frame-

work separates between interrupt sources and in-terrupt vectors. Several interrupt sources can bemapped to a single vector (e.g. several timerevents share one interrupt vector). An inter-rupt source has a unique name within a node

set with the IntSouce::setName() method. In-terrupt vectors are represented by a number(TaskControl::t_IntVector = int). For everyinterrupt vector a single interrupt service routinecan be registered.The mapping from interrupt sources to inter-

rupt vectors is accomplished by the CPU (seeLst. 6). With setInterruptMapping(mapping)a pointer to an InterruptMapping object issupplied. This object will be used by theCpu class to determine the vector number inregisterIntSource().To setup the mapping use

InterruptMapping::setMapping(source name,vector) for every mapping from source to vector(see onInit() in Lst. 6).

6.8 Scripting

6.8.1 Usage

The PAWiS framework intrinsically supportsscripting with the embedded scripting engineLua. PAWiS Lua scripts can be used at variousoccurrences in the execution of a simulation run.A very important aspect is the usage of scriptsat network initialization time (i.e., these scriptscan be used to setup the network; see Sec. 6.9 fordetails). Listing 11 shows how a script can bespecied in order for being executed at networkinitialization. The Config module can processa parameter named InitScript which holds thelocation of a Lua script le to be executed at sim-ulation startup. This takes place before the rstmodule that is derived from PawisModule is beinginitialized.

Listing 11: NED File to reference a Lua initscript.

// ...

simple Configparameters:InitScript : string;

endsimple

module MyNetworksubmodules:myConfig : Configparameters:InitScript = "config.lua";

end

The supplied script will be executed imme-diately. In case a script contains a functionnamed init this function will be executed rightafter the script nishes execution. The script inLst. 12 shows the usage and consequence of aninit-function. When the script is initialized thevariable MyVar is rst created and a the value 17

16

Page 17: PWiSA Simulation Framework Overviewpawis.sourceforge.net/info/tutorial.pdf5.3 Basic Concepts 5.3.1 Modularization The wireless sensor node is split up into modules, e.g. a CPU, the

is assigned. Right after that the variable is in-creased by one. After the script execution thefunction init is called where MyVar is set to 200via the local variable MyLocalVar (note that allvariables in Lua are global except if they are de-ned as local).

Listing 12: Lua init script.

function otherFunc()-- use local temp variablelocal MyLocalVar = 200;return MyLocalVar;

end

function init()MyVar = otherFunc();

end

-- MyVar has global scope (within the script)MyVar = 17;MyVar = MyVar + 1;

A second way to bind Lua scripts to frame-work objects is that every module derived fromPawisModule also supports the InitScript pa-rameter. Though the behavior diers a little fromthe Cong module's usage. When an init scriptis assigned to a node module the script is exe-cuted for every instance of the module type andthe context of the script (the Lua stack) exists aslong as the instance exists. This is comparable tomultiple threads where each thread has its ownstack for execution. An important consequenceis that calls within such scripts are only relatedto one instance of a module and only modify thelocal environment (the Lua stack). Scripts thatare bound to an instance of a module are said tohave module context. For such scripts the frame-work oers additional module related functional-ity (see the Doxygen documentation of the classLuaFunctionalState).

6.8.2 Functionality

Several PAWiS functions are also available in Luascript code. Scripts provide easy access to func-tionality for moving, grouping, creating sensornodes, etc. They can also access and providePAWiS functional interfaces. The following sec-tion introduces some of the most important pos-sibilities of Lua scripts.

Node Grouping and Movement. The scriptin Lst. 13 gives a short example on how to groupnodes and translate the entire group. For thispurpose a node group needs to be created thatallows nodes to be added. Whenever the nodegroup is moved all its members are moved relativeto the origin of the node group.

Listing 13: Lua node grouping and movementscript.

function createNodes()-- create a group with origin (0/0)nodeGroup = pawis.createNodeGroup(0, 0);-- create 10 nodes and add to groupfor i = 1, 10 dopawis.addToNodeGroup(nodeGroup,pawis.createDefaultNode(i, "Node"..i, i * 10, 0

););

endend

function moveNodes(xOffset, yOffset)pawis.moveGroup(nodeGroup, xOffset, yOffset);

end

The script in Lst. 14 assumes to have mod-ule context and shows how to periodically up-date its housing node's position. An init scriptfor a module within a node can be set upwith the InitScript parameter of the Configmodule or in a Lua script itself with thepawis.bindLuaInitScript function. The exam-ple init function schedules a callback to Lua af-ter one second. When the callback is executed thenode is moved (with one millimeter per second tothe right) and another callback is scheduled againfor one second.

Listing 14: Lua position update script.

function updatePosition()local timeDelta = pawis.SimTime - lastUpdate;-- use the module context to get the node modulepawis.moveNode(module.Node, 1e-3 * timeDelta, 0);lastUpdate = pawis.SimTime;-- re-schedule a callback in 1 secondpawis.scheduleLuaCallback(1.0, updatePosition);

end

function init()-- schedule a callback in 1 secondpawis.scheduleLuaCallback(1.0, updatePosition);lastUpdate = pawis.SimTime;

end

For a detailed description of Lua to PAWiSframework bindings consult the Doxygen doc-umentation of the classes LuaPawisState andLuaFunctionalState. The rst class covers com-mon functions that are always available where thelatter covers functions that are only available inscripts with module context.

Handling Functional Interfaces. Lua gluecode also supports calling functional interfacesfrom scripts. The PAWiS framework dispatchessuch calls and invokes either C++ based code

17

Page 18: PWiSA Simulation Framework Overviewpawis.sourceforge.net/info/tutorial.pdf5.3 Basic Concepts 5.3.1 Modularization The wireless sensor node is split up into modules, e.g. a CPU, the

or other Lua script code. However, parame-ters of functional interfaces need to have stricttypes and order. As Lua does not have a notionof strict types (it utilizes dynamic typing) func-tional interface prototypes have to be speciedbefore they can be invoked. In order to intro-duce the notion of types the PAWiS frameworkprovides various pseudo types for Lua that canbe used to declare functional interface prototypes(i.e., pawis.int, pawis.uint, pawis.double,pawis.float, pawis.bool, pawis.message, ...).It is necessary that the types and order of theparameters exactly match the functional inter-face specication. In addition to calling interfacesfrom scripts the framework also supports the in-vocation of functional interfaces from the oppo-site side, i.e., calls from C++ to Lua script code.The script in Lst. 15 shows both scenar-

ios: on one hand it calls a functional inter-face and on the other hand it provides a func-tion that serves as a functional interface. Inthe function init it declares a functional in-terface prototype inc for the module Adder bycalling module.declareInterface with two in-teger input parameters and one integer outputparameter. After this call the script can in-voke this functional interface with the speci-ed parameters using control.invoke as shownin the function increment. With the call tothe module.bindInterface function the module's(i.e., the module that is bound to the script) func-tional interface named increment is bound to theLua function increment with the same parame-ters as before. Again, this function gets the spec-ied parameters in the specied order. When thisfunction is invoked it in turn also invokes anotherfunctional interface, i.e., the interface inc of themodule Adder (as declared before) and passes theresult back to the caller.

Listing 15: Lua script providing and calling afunctional interface.

function increment(value, increment)return control.invoke("Adder", "inc", value, increment

);end

function init()-- declare a functional interface prototypemodule.declareInterface(

"Adder","inc",pawis.int, pawis.int,pawis.int

);

-- bind Lua function to functional interfacemodule.bindInterface(

"increment",

increment,pawis.int, pawis.int,pawis.int

);end

6.9 Environment

The Environment holds all nodes, obstacles andglobal properties in a PAWiS simulation. It canbe seen as the container (or the current state) foreverything that is to be simulated. Most impor-tantly it holds all the sensor nodes on 3D posi-tions and properties for wireless communicationamong them.

6.9.1 Environment Denition

Node placement. The PAWiS framework of-fers multiple possibilities to instantiate and con-gure a simulation network. The OMNeT wayto instantiate nodes is to use the NED le (seeSec. 6.1.1). The example NED le in Lst. 16shows how to instantiate two nodes. First of allthe modules (simple and compound) need to bedened. The module that represents a sensornode is a compound module consisting of vari-ous submodules that are representing layers oraspects of your system. Then the submodules ofthe network (these are the actual nodes, i.e., in-stances of the node module types) are specied.In this example the variables holding the nodesare called node1 and node2 both of the type MyN-ode. In order for a node module to be PAWiS con-form it needs to specify the parameters NodeId,PosX, PosY (PosZ is optional and set to zero ifomitted).

Listing 16: NED le example for instantiatingtwo nodes.

simple Configparameters:InitScript : string,AttenuationExponent : numeric,BackgroundNoise : numeric,AntennaArea : numeric,MinReceivingPower : numeric,NodeClass : string;

endsimple

module MyNode// ...

endmodule

// ...

module MyNetworksubmodules:myConfig : Configparameters:

18

Page 19: PWiSA Simulation Framework Overviewpawis.sourceforge.net/info/tutorial.pdf5.3 Basic Concepts 5.3.1 Modularization The wireless sensor node is split up into modules, e.g. a CPU, the

InitScript = "config.lua",AttenuationExponent = 2.0,BackgroundNoise = 0.0,AntennaArea = 0.001,MinReceivingPower = 1e-15,NodeClass = "MyNode";

node1 : MyNodeparameters:

NodeId = 1,PosX = 100.0,PosY = 100.0,PosZ = 0.0;

node2 : MyNodeparameters:

NodeId = 2,PosX = 100.0,PosY = 200.0,PosZ = 0.0;

// ...endmodule

network myNetworkInstance : MyNetworkendnetwork

The NED le also shows the usage of the Congmodule. This module can be utilized to set upenvironment properties such as:

AntennaArea: Parameter is used by the Air tocalculate the received signal power (see (2)).It is used for every AirClient module withinthe Environment.

AttenuationExponent: Parameter gives the at-tenuation exponent b in (1) and (2).

BackgroundNoise: Minimal noise that is alwayseective when sending via the Air.

InitScript: Path to a script le that is executedwhen the network is initialized.

MinReceivingPower: Threshold for accepting asignal as message (every signal with powerbelow this threshold is treated as noise).

NodeClass: Default class (module type) for in-stantiating node modules.

PositionFactor: Parameter is used for scalingworld positions (in meters) to screen pixels.

An alternative and very exible way to specifya network is to use a Lua script. In order to utilizethis feature a network initialization script hook(as described in Sec. 6.8) needs to be installed.Listing 17 shows an example init function of sucha script. This script creates 100 nodes and placesthem on a 10 by 10 meters grid. At the beginningof the function some environment properties nec-essary for wireless communication are congured(note that these parameters can also be changed

during the simulation runtime to simulate chang-ing communication conditions). Scripting sup-ports the same properties as the Cong modulefrom the NED le.

Listing 17: Lua script example for setting up anetwork.

function init()pawis.AttenuationExponent = 2.0;pawis.BackgroundNoise = 0.0;pawis.AntennaArea = 0.001;pawis.MinReceivingPower = 1e-15;pawis.NodeClass = "MyNode";local id = 1;for y = 1, 10 dofor x = 1, 10 dolocal aNode =pawis.createDefaultNode("Node"..id,id,x, y

);id = id + 1;

endend

end

Using scripts to set up networks allows forcomplex spatial distributions of nodes (note thattopology can not be setup; it is a mere result ofsignal power between senders and receivers).

Attenuation. The attenuation between thesensor nodes is mainly calculated by their dis-tance. Currently no obstacles are considered (seeSec. 5.3.8). In order to adjust the attenuationbetween two nodes the PAWiS framework oersthe possibility to manually specify a multiplica-tive factor for attenuation between pairs of nodes.Whenever such an individual attenuation is setup the attenuation that results from the distancebetween two nodes is multiplied with this fac-tor. The Lua script in Lst. 18 creates 10 ad-jacent nodes in a function called setupNodes.Right after creating the nodes the attenuationbetween nodes 1 and 2 and the attenuation be-tween nodes 2 and 3 is adjusted with the callto pawis.setAttenuation. The function takes apair of node IDs and an attenuation factor thatis a multiplicative factor (i.e., values above 1 addattenuation while values below 1 reduce attenua-tion) for power.

Listing 18: Lua script example for specifying cus-tom attenuation between nodes.

function setupNodes()local id = 1;for x = 1, 10 dolocal aNode =pawis.createDefaultNode("Node"..id,

19

Page 20: PWiSA Simulation Framework Overviewpawis.sourceforge.net/info/tutorial.pdf5.3 Basic Concepts 5.3.1 Modularization The wireless sensor node is split up into modules, e.g. a CPU, the

id, x, 0);

id = id + 1;endpawis.setAttenuation(1, 2, 2.0,2, 3, 2.0

);

end

6.10 Air

The module of your node which connects tothe Air must be derived from AirClient-Module.3 The transmitter uses the methodsendToAir(message, bit count, transmit power,transmission ID) to transfer the data to the Air.The parameter message is the message as an ob-ject which is derived from BaseMessage. Thenumber of bits in the packet is specied by bitcount, which will be used for calculating the dura-tion. The transmit power is given in Watts. Themeaning of transmission ID is described below.When the packet transmission is complete, thecallback method void onAirDataTransmitted()is executed.On the receiving side at the start of a transmis-

sion the callback method bool acceptAirData-Start(signal power, &preview bits, transmissionID) is called. This should return true if thepacket will be accepted (i.e. the receiver is listen-ing). During the reception of the packet no newpackets can be received, therefore false must bereturned. Obviously when the radio is not in lis-ten state false should be returned too. The sig-nal power at the receiver is given in Watts.When the packet reception is nished, the call-

back method onAirDataArrived(message, bitcount, bit errors) is executed. It should imple-ment the actual data packet handling. messageand bit count are the message object and thevalue supplied to sendToAir(). The number ofbit errors which were introduced to the packetduring transmission are given in bit errors. Notethat message is unaltered (i.e. without errors).Only the number of bit errors is given and youdon't know which bits of the message were dis-turbed.Since the method onAirDataArrived() is only

executed after the full packet was received, nonotication is provided while the transmissionis in progress. For some addressing schemes orspecial receivers this might be necessary, there-fore the (output) parameter &preview bits of

3This is derived from PawisModule so your module is all

like a normal module.

acceptAirDataStart() should be set to the num-ber of bits, after which you want to be notied.The virtual callback method onPreviewPacket()will be executed. Set it to 0 if you don't want anadditional notication.

If during the transmission another node startsto send, its signal is uncorrelated to the rstsender. This can be modeled as noise and there-fore decrease in SNR (from the receivers pointof view). Such events can happen several timesduring the transmission of a data packet and thereceiver has to deal with changing SNR through-out the packet. The nal count of bit errors thusresults from this train of dierent SNR values andis assembled of the portions of constant SNR.

The number of bit errors within a period of con-stant SNR is calculated by the callback methodunsigned int calcBitErrors(SNR, bit count).It should use the given SNR value and calculatethe BER and further the number of bit errors.

The simulation of a shared channel via multipleaccess schemes like TDMA, FDMA and CDMAis enabled in two dierent ways. The case ofTDMA is trivial, because we already have a timedomain simulation. FDMA and CDMA, on theother hand, occupy the medium concurrently andare only separated by a frequency channel orby coding groups. To implement this behaviorthe transmission ID parameter of the methodsacceptAirDataStart() and sendToAir() is used.This is an unsigned int with no internal mean-ing. You dene which value represents whichchannel (or whatever else you like), hence it isjust an ID.

When sending a packet with sendToAir() sim-ply specify the appropriate ID (e.g. to statethe frequency channel or the coding group).All other nodes get notied by the methodacceptAirDataStart() which also supplies theID. In this function you dene how dierent IDsare handled. In Lst. 19 we only accept the packetif it is sent with the same ID as our own (OwnTID).

If a node doesn't accept a packet the signalis again regarded as noise. Usually an input l-ter of the receiver attenuates signals at neigh-bor channels. This is modeled by the methodcalcInterferingNoise(). This is the placewhere you specify the input lter characteris-tics (side channel suppression, ... for FDMA) orthe coding gain (for CDMA). The return valueis a factor which is multiplied by the receivedpower, hence its return value should be ≤ 1.0.If you don't care about the channel ID, simplyreturn 1.0 and don't handle the transmission IDin acceptAirDataStart().

Listing 19 gives an example of a physical layerimplementation. The function calcBitErrors()calculates the absolute amount of bit errors for a

20

Page 21: PWiSA Simulation Framework Overviewpawis.sourceforge.net/info/tutorial.pdf5.3 Basic Concepts 5.3.1 Modularization The wireless sensor node is split up into modules, e.g. a CPU, the

given SNR pa_fSnr and bit count pa_nBitCount.The bit error ratio (BER) is derived from theSNR by the function calc_BER() which dependson the modulation format. It is not shownhere. The number of bit errors is binomiallydistributed and calculated with the OMNeT++function binomial(n,p).The function onAirDataStart() demonstrates

how the return value depends on the internalstate of the receiver. If the signal power is be-low a certain sensitivity level the receiver cannotsynchronize to the RF signal and thus doesn't re-ceive the signal. If the signal is sent on the wrongchannel the packet is also not accepted.

onAirDataArrived() is executed when thepacket reception is done. This will update the in-ternal transceiver state and forward the messageto the upper layers.

The upper layers have to set the physicallayer into listen mode, which is done with thePhy::listen() functional interface. It rstactivates the receiver (by setting its state torsListen. Then it waits until a packet is receivedor a timeout is reached. A status and the receivedpacket are then returned to the caller (i.e. theMAC layer).

To send a packet the functional interfacePhy::send() is invoked from an upper layer. Thissets the transceiver state and uses sendToAir()to start the actual transmission. As soon as it hasnished the callback onAirDataTransmitted()sets the transceiver state back to idle and informsthe upper layers of the completed transmission.Note that this is stateless and the integrity is notensured. This has to be accomplished by upperlayers.

Listing 19: Implementation of the physical layerPhy interfacing to the Air from phy.cpp.

/* ... */

/**** Interface to the Air ****/unsigned int Phy::calcBitErrors(double SNR,unsigned int BitCount)

// ...BER = calcBER(SNR);Errors = binomial(BitCount, BER);return BitErrorCount;

double Phy::calcInterferingNoise(unsigned int TransmissionID)

return calcNeighChan(OwnTID, TransmissionID);

bool Phy::acceptAirDataStart(double SignalPower,

int &PreviewBits,unsigned int TransmissionID)

PreviewBit = 0;switch (RadioState) case rsListen:

if ((SignalPower > MinPower) &&(TransmissionId == OwnTID))

RadioState = rsReceive;return true;

elsereturn false;

case rsReceive:default:return false;

void Phy::onAirDataArrived(BaseMessage *Data,unsigned int BitCount,unsigned int BitErrors)

// handle radio stateRadioState = rsFSON;// inform MAC layer// ...

void Phy::onAirDataTransmitted(void) // handle radio stateRadioState = rsFSON;// inform MAC layer// ...

/**** Functional Interfaces ****/void Phy::listen(TaskControl &pa_oControl) // ...RadioState = rsListen;// ...

void Phy::send(TaskControl &pa_oControl) // ...RadioState = rsSend;sendToAir(txData.dup(), txData.getLength()*8,m_dOutputPower, OwnTID);

// ...

/* ... */

6.11 Summary

6.11.1 Tasks

Overview of tasks

Task

FI: single invoke

FI: multi invoke

21

Page 22: PWiSA Simulation Framework Overviewpawis.sourceforge.net/info/tutorial.pdf5.3 Basic Concepts 5.3.1 Modularization The wireless sensor node is split up into modules, e.g. a CPU, the

Call Back

Predicate functions

6.11.2 Casts

The following casts are available

CAST_TASK() is used forregisterFunctionalInterface() andstartTask() to cast a task method.

CAST_CALLBACK() is used forscheduleCallback().

CAST_PREDICATE() is used withrequireCpuUntil(), requireCpuOrUntil()and waitUntil().

7 Important Notes

7.1 OMNeT++ Messages

When directly using OMNeT++ messagesthe owner is responsible to delete the mes-sage. This is not always the creator!

Never send OMNeT++ messages directly,only use them as data type.

When a message is supplied to a task (e.g.,with invoke()) the called task is the newowner of the message. After return from thistask the input parameters are invalid. To re-turn values use the output parameters. Theinput parameters are automatically clearedat the return of invoke().

When a message is supplied to a methodof the framework, the framework is the newowner of this message and thus also respon-sible to delete it.

7.2 Software and hardware tasks

Software tasks must not invoke() hardwaretasks and vice versa. This is checked bythe framework and leads to a runtime error.Nonetheless, software tasks can start a hard-ware task with startTask()

8 Patterns

8.1 Non-blocking functional inter-

faces

To implement a functional interface which re-turns immediately but starts a parallel action(e.g. starting an ADC conversion), use the follow-ing approach. Write the code which runs in paral-lel in a separate task method. In your functional

interface code use startTask() to start that sep-arate task. When this has done its job simplyquit the method (e.g. at its end or with return.

8.2 More to come

References

[GSS+04] Y. Gsottberger, X. Shi, G. Stromberg,W. Weber, T.F. Sturm, H. Linde,E. Naroska, and P.; Schramm. Sin-drion: a prototype system for low-power wireless control networks. InIEEE International Conference onMobile Ad-hoc and Sensor Systems,pages 513 515, 25-27 October 2004.

[H+03] Robert F. Heile et al. 802.15.4: Wire-less Medium Access Control (MAC)and Physical Layer (PHY) Specica-tions for Low-Rate Wireless PersonalArea Networks (LR-WPANs). Tech-nical report, IEEE Computer Society,1. October 2003.

[IEE03] IEEE Std. 802.15.4-2003, IEEE Stan-dard for Information Technology -Telecommunications and InformationExchange between Systems - Lo-cal and Metropolitan Area Networks(WPANs), 2003.

[MB04] Stefan Mahlknecht and Michael Böck.CSMA-MPS: A Minimum Pream-ble Sampling MAC Protocol forLow Power Wireless Sensor Networks.WFCS, 2004.

[Roe04] Matthias Roetzer. Routing in en-ergieautarken Funksensornetzwerken.Master's thesis, Vienna University ofTechnology, 2004.

22