--- /dev/null
+%load file written out by FtspDataLogger.java class\r
+%arg0 - filename, e.g. '1205543689171.report'\r
+function FTSPDataAnalyzer(file, varargin)\r
+[c1 c2 c3 c4 c5]= textread(file, '%u %u %u %u %u', 'commentstyle', 'shell');\r
+data = [c2 c3 c4 c5]; %skipping the first column (java time)\r
+data1 = sortrows(sortrows(data,1),2);\r
+newdata = [];\r
+\r
+row=1;\r
+newrow=1;\r
+unsynced=0;\r
+while (row<=size(data1,1))\r
+\r
+ seqnum=data1(row,2);\r
+\r
+ data2=[];\r
+ row2=1;\r
+ tmprow1=row;\r
+ while (row <= size(data1,1) && data1(row,2)==seqnum)\r
+ if (data1(row,4)==0)\r
+ data2(row2,1)=data1(row,3);\r
+ row2= row2+ 1;\r
+ else\r
+ unsynced=unsynced+1;\r
+ end\r
+ row = row + 1;\r
+ end\r
+ \r
+ if (row2>1)\r
+ row2size=row2-1;\r
+ rcvdsize=row-tmprow1;\r
+ newdata(newrow,1) = seqnum;\r
+ newdata(newrow,2) = mad(data2(1:row2size,1));\r
+ newdata(newrow,3) = mean(data2(1:row2size,1));\r
+ newdata(newrow,4) = row2size/rcvdsize;\r
+ newrow = newrow + 1;\r
+ end\r
+end\r
+\r
+if (length(newdata)==0)\r
+ disp('no data found (at least one data point from a synchronized mote is required)!');\r
+else\r
+ newsize=newrow-1;\r
+ subplot(3,1,1);\r
+ plot(newdata(1:newsize,1),newdata(1:newsize,2));\r
+ title(sprintf('TimeSync Errors'));\r
+ subplot(3,1,2);\r
+ plot(newdata(1:newsize,1),newdata(1:newsize,3));\r
+ title(sprintf('Avg Glob Time'));\r
+ subplot(3,1,3);\r
+ plot(newdata(1:newsize,1),newdata(1:newsize,4),'b-');\r
+ title(sprintf('%% Synced Motes'));\r
+\r
+ disp(sprintf('total unsycned num %d (all %d)',unsynced,newsize));\r
+ disp(sprintf('avg %0.3f',mean(newdata(1:newsize,2))));\r
+ disp(sprintf('max %d',max(newdata(1:newsize,2))));\r
+ savedata = newdata(1:newsize,:);\r
+ save data.out savedata -ASCII;\r
+end\r
+
\ No newline at end of file
--- /dev/null
+/* tab:4
+ * "Copyright (c) 2000-2003 The Regents of the University of California.
+ * 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 UNIVERSITY OF CALIFORNIA 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 UNIVERSITY OF
+ * CALIFORNIA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * THE UNIVERSITY OF CALIFORNIA 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 UNIVERSITY OF CALIFORNIA HAS NO OBLIGATION TO
+ * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS."
+ *
+ * Copyright (c) 2002-2007 Intel Corporation
+ * All rights reserved.
+ *
+ * This file is distributed under the terms in the attached INTEL-LICENSE
+ * file. If you do not find these files, copies can be found by writing to
+ * Intel Research Berkeley, 2150 Shattuck Avenue, Suite 1300, Berkeley, CA,
+ * 94704. Attention: Intel License Inquiry.
+ */
+
+
+/**
+ * @author Brano Kusy
+ */
+
+import java.io.FileOutputStream;
+import java.io.PrintStream;
+import net.tinyos.message.*;
+import net.tinyos.util.*;
+
+public class FtspDataLogger implements MessageListener {
+ public class RunWhenShuttingDown extends Thread {
+ public void run()
+ {
+ System.out.println("Control-C caught. Shutting down...");
+ if (outReport!=null)
+ outReport.close();
+ }
+ }
+
+ MoteIF mote; // For talking to the antitheft root node
+
+ void connect()
+ {
+ try {
+ mote = new MoteIF(PrintStreamMessenger.err);
+ mote.registerListener(new TestFtspMsg(), this);
+ System.out.println("Connection ok!");
+ }
+ catch(Exception e) {
+ e.printStackTrace();
+ System.exit(2);
+ }
+ }
+ PrintStream outReport = null;
+
+ public FtspDataLogger() {
+ connect();
+ Runtime.getRuntime().addShutdownHook(new RunWhenShuttingDown());
+ String name=""+System.currentTimeMillis();
+ try
+ {
+ outReport = new PrintStream(new FileOutputStream(name+".report"));
+ outReport.println("#[JAVA_TIME] [NODE_ID] [SEQ_NUM] [GLOB_TIME] [IS_TIME_VALID]");
+ }
+ catch (Exception e)
+ {
+ System.out.println("FtspDataLogger.FtspDataLogger(): "+e.toString());
+ }
+ }
+
+ public void writeReprot(TestFtspMsg tspr)
+ {
+ String foo = (System.currentTimeMillis()
+ +" "+tspr.get_src_addr()+" "+tspr.get_counter()
+ +" "+tspr.get_global_rx_timestamp()+" "+tspr.get_is_synced());
+ outReport.println(foo);
+ System.out.println(foo);
+ outReport.flush();
+ }
+
+ public void writeFullReprot(TestFtspMsg tspr)
+ {
+ String foo = (System.currentTimeMillis()
+ +" "+tspr.get_src_addr()
+ +" "+tspr.get_counter()
+ +" "+tspr.get_local_rx_timestamp()
+ +" "+tspr.get_global_rx_timestamp()
+ +" "+tspr.get_skew_times_1000000()
+ +" "+tspr.get_is_synced()
+ +" "+tspr.get_ftsp_root_addr()
+ +" "+tspr.get_ftsp_seq()
+ +" "+tspr.get_ftsp_table_entries());
+ outReport.println(foo);
+ System.out.println(foo);
+ outReport.flush();
+ }
+
+ public void messageReceived(int dest_addr, Message msg)
+ {
+ if (msg instanceof TestFtspMsg)
+ //writeFullReprot((TestFtspMsg)msg);
+ writeReprot((TestFtspMsg)msg);
+ }
+
+ /* Just start the app... */
+ public static void main(String[] args)
+ {
+ new FtspDataLogger();
+ }
+}
\ No newline at end of file
--- /dev/null
+#!/usr/bin/env python
+
+import sys, time
+import tos
+
+AM_TEST_FTSP_MSG = 137
+
+class FtspMsg(tos.Packet):
+ def __init__(self, packet = None):
+ tos.Packet.__init__(self,
+ [('src_addr', 'int', 2),
+ ('counter', 'int', 2),
+ ('local_rx_timestamp', 'int', 4),
+ ('global_rx_timestamp', 'int', 4),
+ ('skew_times_1000000', 'int', 4),
+ ('is_synced', 'int', 1),
+ ('ftsp_root_addr', 'int', 2),
+ ('ftsp_seq', 'int', 1),
+ ('ftsp_table_entries', 'int', 2)],
+ packet)
+
+if '-h' in sys.argv:
+ print "Usage:", sys.argv[0], "serial@/dev/ttyUSB0:57600"
+ sys.exit()
+
+am = tos.AM()
+
+while True:
+ p = am.read()
+ if p and p.type == AM_TEST_FTSP_MSG:
+ msg = FtspMsg(p.data)
+ print int(time.time()), msg.src_addr, msg.counter, msg.global_rx_timestamp, msg.is_synced
+ #print msg
--- /dev/null
+BUILD_EXTRA_DEPS = FtspDataLogger.class
+CLEAN_EXTRA = *.class TestFtspMsg.java
+
+FtspDataLogger.class: TestFtspMsg.java
+ javac *.java
+
+TestFtspMsg.java: TestFtsp.h
+ mig java -target=$(PLATFORM) $(CFLAGS) -java-classname=TestFtspMsg TestFtsp.h test_ftsp_msg -o $@
+
+COMPONENT=TestFtspAppC
+
+PFLAGS += -DTIMESYNC_RATE=3
+#PFLAGS += -DTIMESYNC_DEBUG
+
+PFLAGS += -I$(TOSDIR)/lib/ftsp -I$(TOSDIR)/../apps/RadioCountToLeds
+
+include $(MAKERULES)
--- /dev/null
+FtspDataAnalyzer.m\r
+\r
+-------------------------------------------------------------------------------\r
+Author/Contact:\r
+---------------\r
+ Brano Kusy: branislav.kusy@gmail.com\r
+\r
+-------------------------------------------------------------------------------\r
+DESCRIPTION:\r
+------------\r
+\r
+FtspDataAnalyzer.m works with data logs collected by FtspDataLogger.java and\r
+calculates the maximum and average timesync error over time.\r
+\r
+-------------------------------------------------------------------------------\r
+STEP BY STEP GUIDE TO RUN OUR TEST SCENARIO:\r
+--------------------------------------------\r
+1. program and start motes as described in ./README.txt\r
+2. start SerialForwarder and FtspDataLogger.java as described in ./README.txt\r
+3. 'current_time.report' file (where current_time is a number) is created in ./\r
+ this file is updated with data in the real time\r
+4. let the experiment run for some time\r
+5. start matlab and enter (assuming your current_time was 1206126224593)\r
+ FTSPDataAnalyzer('1206126224593.report')\r
+ this will plot the mean absolute timesync error, global time, and number of\r
+ synced motes; this can be done while experiment is running\r
+6. Matlab also creates data.out file which contains data in the following format\r
+ #seqNum mean_abs_error global_time num_synced_motes\r
+ mean_abs_error is calculated as mean absolute deviation from the mean (mad)\r
+\r
+Simulating multi-hop:\r
+1. define TIMESYNC_DEBUG in the Makefile\r
+2. recompile and upload TestFTSP app to n motes with special NODE_IDs:\r
+ using 'make micaz reinstall.0xAB', nodes 0xAB and 0xCD can communicate\r
+ iff 2D grid coordinates (A,B) and (C,D) are neighbors in a 2D grid\r
+ \r
+-------------------------------------------------------------------------------\r
+EVALUATION:\r
+--------------------------------------------\r
+ - deployment setup: 11 nodes in a 5x3 grid using simulated multi-hop (4 points\r
+ were vacant as we only used 11 nodes). the max number of hops was 5.\r
+ - parameters: sync period 10sec, polling period 3 sec\r
+ - experiment length: 100 minutes\r
+ - results (1 jiffy is ~30.5 us)\r
+ 1.53 jiffy avg error (~50us)\r
+ 3.5 jiffy max error (~100us)
\ No newline at end of file
--- /dev/null
+TestFtsp
+
+-------------------------------------------------------------------------------
+Author/Contact:
+---------------
+ Brano Kusy: branislav.kusy@gmail.com
+ Janos Sallai: janos.sallai@vanderbilt.edu
+ Miklos Maroti: mmaroti@gmail.com
+
+-------------------------------------------------------------------------------
+DESCRIPTION:
+------------
+ The TestFtsp application tests the Flooding Time Synchronization Protocol
+ (FTSP) implementation. A network of motes programmed with TestFtsp run the
+ FTSP protocol to time synchronize, and sends to the base station the global
+ reception timestamps of messages broadcast by a dedicated beacon mote
+ programmed with RadioCountToLeds. Ideally, the global reception timestamps of
+ the same RadioCountToLeds message should agree for all TestFtsp motes (with a
+ small synchronization error).
+
+-------------------------------------------------------------------------------
+SUPPORTED PLATFORMS:
+--------------------------------------------
+ The supported platforms are micaz, telosb and iris.
+
+-------------------------------------------------------------------------------
+STEP BY STEP GUIDE TO RUN OUR TEST SCENARIO:
+--------------------------------------------
+ - program one mote with apps/RadioCountToLeds
+ - program multiple motes with TestFtsp
+ - program a mote with apps/BaseStation, leave it on the programming board
+ - turn on all the motes
+ - start the FtspDataLogger java application (type "java FtspDataLogger")
+
+-------------------------------------------------------------------------------
+REPORTED DATA:
+--------------
+ The most important reported data is the global time of arrival of the beacons.
+ The beacon msg arrives to all clients at the same time instant, thus reported
+ global times should be the same for all clients for the same sequence number.
+
+ Each message contains:
+ - the time of message reception by the java app [JAVA_TIME]
+ - the node ID of the mote that is sending this report [NODE_ID]
+ - the sequence number of the RadioCountToLeds message that is increased
+ for each new polling msg [SEQ_NUM]
+ - the global time when the polling message arrived [GLOB_TIME]
+ - a result_t value indicating if the timestamp is valid [IS_TIME_VALID]
+ (a result_t of 0 denotes a valid timestamp)
+
+If the application is running correctly, then the output should show
+reports from the different FTSP nodes with valid timestamps and similar
+global time values. For example, this is a trace with two FTSP nodes,
+with IDs 1 and 5:
+
+1214516486569 1 10916 433709 0
+1214516486569 5 10916 433709 0
+1214516486809 5 10917 433964 0
+1214516486809 1 10917 433963 0
+1214516487045 5 10918 434210 0
+1214516487053 1 10918 434210 0
+1214516487285 1 10919 434454 0
+1214516487293 5 10919 434455 0
+
+One way to test if FTSP is operating correctly is to turn off one of
+the FTSP nodes. For a short time, that node's global times will differ
+significantly and its valid flag will not be 0. For example, this
+is what it looks like when node 1 in the earlier trace is reset:
+
+1214516490953 5 10934 438208 0
+1214516491201 5 10935 438460 0
+1214516491441 5 10936 438712 0
+1214516491685 5 10937 438964 0
+1214516492169 5 10939 439455 0
+1214516492417 1 10940 243 1
+1214516492421 5 10940 439706 0
+1214516492665 5 10941 439960 0
+1214516492669 1 10941 497 1
+1214516492905 5 10942 440213 0
+...
+1214516497541 1 10961 5495 1
+1214516497549 5 10961 444958 0
+1214516497793 1 10962 5747 1
+1214516498025 1 10963 445456 0
+1214516498033 5 10963 445455 0
+1214516498277 5 10964 445705 0
+1214516498285 1 10964 445707 0
+1214516498521 1 10965 445964 0
+
+This output is also saved in a file named 'current_timestamp.report'.
+'.report' files can be used with the FtspDataAnalyzer.m Matlab
+application. Mean absolute timesync error, global time, and % of
+synced motes will be plotted.
--- /dev/null
+/*
+ * Copyright (c) 2002, 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, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
+ *
+ * @author: Miklos Maroti, Brano Kusy (kusy@isis.vanderbilt.edu)
+ * Ported to T2: 3/17/08 by Brano Kusy (branislav.kusy@gmail.com)
+ */
+
+#ifndef TEST_FTSP_H
+#define TEST_FTSP_H
+
+typedef nx_struct test_ftsp_msg
+{
+ nx_uint16_t src_addr;
+ nx_uint16_t counter;
+ nx_uint32_t local_rx_timestamp;
+ nx_uint32_t global_rx_timestamp;
+ nx_int32_t skew_times_1000000;
+ nx_uint8_t is_synced;
+ nx_uint16_t ftsp_root_addr;
+ nx_uint8_t ftsp_seq;
+ nx_uint8_t ftsp_table_entries;
+} test_ftsp_msg_t;
+
+enum
+{
+ AM_TEST_FTSP_MSG = 137
+};
+
+#endif
--- /dev/null
+/*
+ * Copyright (c) 2002, 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, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
+ *
+ * @author: Miklos Maroti, Brano Kusy (kusy@isis.vanderbilt.edu)
+ * Ported to T2: 3/17/08 by Brano Kusy (branislav.kusy@gmail.com)
+ */
+
+#include "TestFtsp.h"
+#include "RadioCountToLeds.h"
+
+configuration TestFtspAppC {
+}
+
+implementation {
+ components MainC, TimeSyncC;
+
+ MainC.SoftwareInit -> TimeSyncC;
+ TimeSyncC.Boot -> MainC;
+
+ components TestFtspC as App;
+ App.Boot -> MainC;
+
+ components ActiveMessageC;
+ App.RadioControl -> ActiveMessageC;
+ App.Receive -> ActiveMessageC.Receive[AM_RADIO_COUNT_MSG];
+ App.AMSend -> ActiveMessageC.AMSend[AM_TEST_FTSP_MSG];
+ App.Packet -> ActiveMessageC;
+ App.PacketTimeStamp -> ActiveMessageC;
+
+ components LedsC;
+
+ App.GlobalTime -> TimeSyncC;
+ App.TimeSyncInfo -> TimeSyncC;
+ App.Leds -> LedsC;
+
+}
--- /dev/null
+/*
+ * Copyright (c) 2002, 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, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
+ *
+ * @author: Miklos Maroti, Brano Kusy (kusy@isis.vanderbilt.edu)
+ * Ported to T2: 3/17/08 by Brano Kusy (branislav.kusy@gmail.com)
+ */
+
+#include "TestFtsp.h"
+#include "RadioCountToLeds.h"
+
+module TestFtspC
+{
+ uses
+ {
+ interface GlobalTime<TMilli>;
+ interface TimeSyncInfo;
+ interface Receive;
+ interface AMSend;
+ interface Packet;
+ interface Leds;
+ interface PacketTimeStamp<TMilli,uint32_t>;
+ interface Boot;
+ interface SplitControl as RadioControl;
+ }
+}
+
+implementation
+{
+ message_t msg;
+ bool locked = FALSE;
+
+ event void Boot.booted() {
+ call RadioControl.start();
+ }
+
+ event message_t* Receive.receive(message_t* msgPtr, void* payload, uint8_t len)
+ {
+ call Leds.led0Toggle();
+ if (!locked && call PacketTimeStamp.isValid(msgPtr)) {
+ radio_count_msg_t* rcm = (radio_count_msg_t*)call Packet.getPayload(msgPtr, sizeof(radio_count_msg_t));
+ test_ftsp_msg_t* report = (test_ftsp_msg_t*)call Packet.getPayload(&msg, sizeof(test_ftsp_msg_t));
+
+ uint32_t rxTimestamp = call PacketTimeStamp.timestamp(msgPtr);
+
+ report->src_addr = TOS_NODE_ID;
+ report->counter = rcm->counter;
+ report->local_rx_timestamp = rxTimestamp;
+ report->is_synced = call GlobalTime.local2Global(&rxTimestamp);
+ report->global_rx_timestamp = rxTimestamp;
+ report->skew_times_1000000 = (uint32_t)call TimeSyncInfo.getSkew()*1000000UL;
+ report->ftsp_root_addr = call TimeSyncInfo.getRootID();
+ report->ftsp_seq = call TimeSyncInfo.getSeqNum();
+ report->ftsp_table_entries = call TimeSyncInfo.getNumEntries();
+
+ if (call AMSend.send(AM_BROADCAST_ADDR, &msg, sizeof(test_ftsp_msg_t)) == SUCCESS) {
+ locked = TRUE;
+ }
+ }
+
+ return msgPtr;
+ }
+
+ event void AMSend.sendDone(message_t* ptr, error_t success) {
+ locked = FALSE;
+ return;
+ }
+
+ event void RadioControl.startDone(error_t err) {}
+ event void RadioControl.stopDone(error_t error){}
+}
--- /dev/null
+#!/usr/bin/env python
+
+import sys, time
+import tos
+
+AM_TEST_FTSP_MSG = 137
+
+class FtspMsg(tos.Packet):
+ def __init__(self, packet = None):
+ tos.Packet.__init__(self,
+ [('src_addr', 'int', 2),
+ ('counter', 'int', 2),
+ ('local_rx_timestamp', 'int', 4),
+ ('global_rx_timestamp', 'int', 4),
+ ('skew_times_1000000', 'int', 4),
+ ('is_synced', 'int', 1),
+ ('ftsp_root_addr', 'int', 2),
+ ('ftsp_seq', 'int', 1),
+ ('ftsp_table_entries', 'int', 2)],
+ packet)
+
+if '-h' in sys.argv:
+ print "Usage:", sys.argv[0], "serial@/dev/ttyUSB0:57600"
+ sys.exit()
+
+am = tos.AM()
+
+while True:
+ p = am.read()
+ if p and p.type == AM_TEST_FTSP_MSG:
+ msg = FtspMsg(p.data)
+ print int(time.time()), msg.src_addr, msg.counter, msg.global_rx_timestamp, msg.is_synced
+ #print msg
--- /dev/null
+SENSORBOARD=quantoplus
+
+COMPONENT=TestFtspAppC
+
+PFLAGS += -DTIMESYNC_RATE=10
+#PFLAGS += -DTIMESYNC_DEBUG
+#PFLAGS += -DCC2420_CHANNEL=26
+CFLAGS += -DTOSH_DATA_LENGTH=50
+#CFLAGS += -DCOUNT_LOG
+
+PFLAGS += -I$(TOSDIR)/lib/ftsp -I$(TOSDIR)/../apps/RadioCountToLeds -I$(TOSDIR)/lib/printf
+
+CFLAGS += -DLPL_INTERVAL=200
+CFLAGS += -DLOW_POWER_LISTENING
+
+include $(MAKERULES)
--- /dev/null
+First, program several nodes with this TestFtsp application. In addition,
+you will need one TinyOS Basestation that listens for messages, and one
+beacon node. Program the beacon node with the RadioCountToLed application
+from the TestFtsp32kLplBeaconer directory. This is a special modification of
+the RadioCountToLed code which allows to evaluate a duty-cycled ftsp
+network. The regular RadioCountToLed code doesn't work, since a LPL
+broadcast message gets transmitted more than just once. Thus, there is a
+disambiguity in which precise broadcast message was actually timestamped by
+the TestFtsp application. The modifications take care of this by using the
+TimeSyncAMSend interface and setting an arbitrary event time. Thus, on
+reception, the TestFtsp code can account for this delayed send.
+
+To evaluate the synchronization precision, use the FtspDataLogger.py
+application. First, you will need a serial forwarder that connects to the
+BaseStation node. Then, run the python application like this:
+python FtspDataLogger.py sf@localhost:9002
+
+You should now see messages coming in, one per line. The first value is the
+current time as a unix timestamp. The last line is a binary value indicating
+if there was some missed data, and thus the values are not good (indicated
+by a 1), or if all the nodes are synchronized and we received a value for
+each and every one of them (indicated by a 0).
+
+Note!!!!!
+- the basestation should also define
+ CFLAGS += -DTOSH_DATA_LENGTH=50
+ in the makefile. Else, the reports will not fit into 1 tinyos message, and
+ they will get silently dropped.
+- 32k timesync only works for certain platforms (those that provide 32khz
+ counter), if your platform does not support the counter, LPL still works,
+ but you need to use TMilli timesync
--- /dev/null
+/*
+ * Copyright (c) 2002, 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, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
+ *
+ * @author: Miklos Maroti, Brano Kusy (kusy@isis.vanderbilt.edu)
+ * Ported to T2: 3/17/08 by Brano Kusy (branislav.kusy@gmail.com)
+ */
+
+#ifndef TEST_FTSP_H
+#define TEST_FTSP_H
+
+typedef nx_struct test_ftsp_msg
+{
+ nx_uint16_t src_addr;
+ nx_uint16_t counter;
+ nx_uint32_t local_rx_timestamp;
+ nx_uint32_t global_rx_timestamp;
+ nx_int32_t skew_times_1000000;
+ nx_float skew;
+ nx_uint8_t is_synced;
+ nx_uint16_t ftsp_root_addr;
+ nx_uint8_t ftsp_seq;
+ nx_uint8_t ftsp_table_entries;
+ nx_uint32_t localAverage;
+ nx_int32_t offsetAverage;
+} test_ftsp_msg_t;
+
+enum
+{
+ AM_TEST_FTSP_MSG = 137
+};
+
+#endif
--- /dev/null
+/*
+ * Copyright (c) 2002, 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, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
+ *
+ * @author: Miklos Maroti, Brano Kusy (kusy@isis.vanderbilt.edu)
+ * Ported to T2: 3/17/08 by Brano Kusy (branislav.kusy@gmail.com)
+ * Adapted for LPL: 6/16/09 by Thomas Schmid (thomas.schmid@ucla.edu)
+ */
+
+#include "TestFtsp.h"
+#include "RadioCountToLeds.h"
+
+configuration TestFtspAppC {
+}
+
+implementation {
+ components MainC, TimeSync32kC;
+
+ MainC.SoftwareInit -> TimeSync32kC;
+ TimeSync32kC.Boot -> MainC;
+
+ components TestFtspC as App;
+ App.Boot -> MainC;
+
+ components ActiveMessageC;
+ components TimeSyncMessageC;
+ App.RadioControl -> ActiveMessageC;
+ App.Receive -> TimeSyncMessageC.Receive[AM_RADIO_COUNT_MSG];
+ App.TimeSyncPacket -> TimeSyncMessageC;
+ App.AMSend -> ActiveMessageC.AMSend[AM_TEST_FTSP_MSG];
+ App.Packet -> ActiveMessageC;
+ App.PacketTimeStamp -> ActiveMessageC;
+
+ components RandomC;
+ App.Random -> RandomC;
+
+ components new TimerMilliC() as Timer0;
+ App.RandomTimer -> Timer0;
+
+ components LedsC;
+
+ App.GlobalTime -> TimeSync32kC;
+ App.TimeSyncInfo -> TimeSync32kC;
+ App.Leds -> LedsC;
+
+#ifdef LOW_POWER_LISTENING
+ components CC2420ActiveMessageC;
+ App.LowPowerListening -> CC2420ActiveMessageC;
+#endif
+
+}
--- /dev/null
+/*
+ * Copyright (c) 2002, 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, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
+ *
+ * @author: Miklos Maroti, Brano Kusy (kusy@isis.vanderbilt.edu)
+ * Ported to T2: 3/17/08 by Brano Kusy (branislav.kusy@gmail.com)
+ * Ported for LPL: Thomas Schmid (thomas.schmid@ucla.edu)
+ */
+
+#include "TestFtsp.h"
+#include "RadioCountToLeds.h"
+
+module TestFtspC
+{
+ uses
+ {
+ interface GlobalTime<T32khz>;
+ interface TimeSyncInfo;
+ interface Receive;
+ interface AMSend;
+ interface Packet;
+ interface Leds;
+ interface PacketTimeStamp<T32khz,uint32_t>;
+ interface Boot;
+ interface SplitControl as RadioControl;
+ interface Timer<TMilli> as RandomTimer;
+ interface Random;
+
+ interface TimeSyncPacket<T32khz,uint32_t>;
+
+#ifdef LOW_POWER_LISTENING
+ interface LowPowerListening;
+#endif
+
+ }
+}
+
+implementation
+{
+ enum {
+ ACT_TESTFTSP = 0x11,
+ };
+
+ message_t msg;
+ bool locked = FALSE;
+ test_ftsp_msg_t* report;
+
+ event void Boot.booted() {
+ call RadioControl.start();
+ }
+
+ event message_t* Receive.receive(message_t* msgPtr, void* payload, uint8_t len)
+ {
+ if (!(call PacketTimeStamp.isValid(msgPtr))){
+ call Leds.led1Toggle();
+ }
+ if (!locked && call PacketTimeStamp.isValid(msgPtr)) {
+ radio_count_msg_t* rcm = (radio_count_msg_t*)call Packet.getPayload(msgPtr, sizeof(radio_count_msg_t));
+ if(call TimeSyncPacket.isValid(msgPtr)) {
+ uint32_t rxTimestamp = call TimeSyncPacket.eventTime(msgPtr);
+ report = (test_ftsp_msg_t*)call Packet.getPayload(&msg, sizeof(test_ftsp_msg_t));
+
+ report->src_addr = TOS_NODE_ID;
+ report->counter = rcm->counter;
+ report->local_rx_timestamp = rxTimestamp;
+ report->is_synced = call GlobalTime.local2Global(&rxTimestamp);
+ report->global_rx_timestamp = rxTimestamp;
+ report->skew_times_1000000 = (uint32_t)call TimeSyncInfo.getSkew()*1000000UL;
+ report->skew = call TimeSyncInfo.getSkew();
+ report->ftsp_root_addr = call TimeSyncInfo.getRootID();
+ report->ftsp_seq = call TimeSyncInfo.getSeqNum();
+ report->ftsp_table_entries = call TimeSyncInfo.getNumEntries();
+ report->localAverage = call TimeSyncInfo.getSyncPoint();
+ report->offsetAverage = call TimeSyncInfo.getOffset();
+
+ locked = TRUE;
+ call RandomTimer.startOneShot(call Random.rand16() % (64));
+ }
+ }
+
+ return msgPtr;
+ }
+
+ event void RandomTimer.fired()
+ {
+#ifdef LOW_POWER_LISTENING
+ call LowPowerListening.setRxSleepInterval(&msg, LPL_INTERVAL);
+#endif
+ if(locked && (call AMSend.send(4000, &msg, sizeof(test_ftsp_msg_t)) == SUCCESS)){
+ call Leds.led2On();
+ } else {
+ locked = FALSE;
+ }
+ }
+
+ event void AMSend.sendDone(message_t* ptr, error_t success) {
+ locked = FALSE;
+ call Leds.led2Off();
+ return;
+ }
+
+ event void RadioControl.startDone(error_t err) {
+#ifdef LOW_POWER_LISTENING
+ call LowPowerListening.setLocalSleepInterval(LPL_INTERVAL);
+#endif
+ }
+ event void RadioControl.stopDone(error_t error){}
+}
--- /dev/null
+#
+# This class is automatically generated by mig. DO NOT EDIT THIS FILE.
+# This class implements a Python interface to the 'TestFtspMsg'
+# message type.
+#
+
+import tinyos.message.Message
+
+# The default size of this message type in bytes.
+DEFAULT_MESSAGE_SIZE = 33
+
+# The Active Message type associated with this message.
+AM_TYPE = 137
+
+class TestFtspMsg(tinyos.message.Message.Message):
+ # Create a new TestFtspMsg of size 33.
+ def __init__(self, data="", addr=None, gid=None, base_offset=0, data_length=33):
+ tinyos.message.Message.Message.__init__(self, data, addr, gid, base_offset, data_length)
+ self.amTypeSet(AM_TYPE)
+
+ # Get AM_TYPE
+ def get_amType(cls):
+ return AM_TYPE
+
+ get_amType = classmethod(get_amType)
+
+ #
+ # Return a String representation of this message. Includes the
+ # message type name and the non-indexed field values.
+ #
+ def __str__(self):
+ s = "Message <TestFtspMsg> \n"
+ try:
+ s += " [src_addr=0x%x]\n" % (self.get_src_addr())
+ except:
+ pass
+ try:
+ s += " [counter=0x%x]\n" % (self.get_counter())
+ except:
+ pass
+ try:
+ s += " [local_rx_timestamp=0x%x]\n" % (self.get_local_rx_timestamp())
+ except:
+ pass
+ try:
+ s += " [global_rx_timestamp=0x%x]\n" % (self.get_global_rx_timestamp())
+ except:
+ pass
+ try:
+ s += " [skew_times_1000000=0x%x]\n" % (self.get_skew_times_1000000())
+ except:
+ pass
+ try:
+ s += " [skew=0x%x]\n" % (self.get_skew())
+ except:
+ pass
+ try:
+ s += " [is_synced=0x%x]\n" % (self.get_is_synced())
+ except:
+ pass
+ try:
+ s += " [ftsp_root_addr=0x%x]\n" % (self.get_ftsp_root_addr())
+ except:
+ pass
+ try:
+ s += " [ftsp_seq=0x%x]\n" % (self.get_ftsp_seq())
+ except:
+ pass
+ try:
+ s += " [ftsp_table_entries=0x%x]\n" % (self.get_ftsp_table_entries())
+ except:
+ pass
+ try:
+ s += " [localAverage=0x%x]\n" % (self.get_localAverage())
+ except:
+ pass
+ try:
+ s += " [offsetAverage=0x%x]\n" % (self.get_offsetAverage())
+ except:
+ pass
+ return s
+
+ # Message-type-specific access methods appear below.
+
+ #
+ # Accessor methods for field: src_addr
+ # Field type: int
+ # Offset (bits): 0
+ # Size (bits): 16
+ #
+
+ #
+ # Return whether the field 'src_addr' is signed (False).
+ #
+ def isSigned_src_addr(self):
+ return False
+
+ #
+ # Return whether the field 'src_addr' is an array (False).
+ #
+ def isArray_src_addr(self):
+ return False
+
+ #
+ # Return the offset (in bytes) of the field 'src_addr'
+ #
+ def offset_src_addr(self):
+ return (0 / 8)
+
+ #
+ # Return the offset (in bits) of the field 'src_addr'
+ #
+ def offsetBits_src_addr(self):
+ return 0
+
+ #
+ # Return the value (as a int) of the field 'src_addr'
+ #
+ def get_src_addr(self):
+ return self.getUIntElement(self.offsetBits_src_addr(), 16, 1)
+
+ #
+ # Set the value of the field 'src_addr'
+ #
+ def set_src_addr(self, value):
+ self.setUIntElement(self.offsetBits_src_addr(), 16, value, 1)
+
+ #
+ # Return the size, in bytes, of the field 'src_addr'
+ #
+ def size_src_addr(self):
+ return (16 / 8)
+
+ #
+ # Return the size, in bits, of the field 'src_addr'
+ #
+ def sizeBits_src_addr(self):
+ return 16
+
+ #
+ # Accessor methods for field: counter
+ # Field type: int
+ # Offset (bits): 16
+ # Size (bits): 16
+ #
+
+ #
+ # Return whether the field 'counter' is signed (False).
+ #
+ def isSigned_counter(self):
+ return False
+
+ #
+ # Return whether the field 'counter' is an array (False).
+ #
+ def isArray_counter(self):
+ return False
+
+ #
+ # Return the offset (in bytes) of the field 'counter'
+ #
+ def offset_counter(self):
+ return (16 / 8)
+
+ #
+ # Return the offset (in bits) of the field 'counter'
+ #
+ def offsetBits_counter(self):
+ return 16
+
+ #
+ # Return the value (as a int) of the field 'counter'
+ #
+ def get_counter(self):
+ return self.getUIntElement(self.offsetBits_counter(), 16, 1)
+
+ #
+ # Set the value of the field 'counter'
+ #
+ def set_counter(self, value):
+ self.setUIntElement(self.offsetBits_counter(), 16, value, 1)
+
+ #
+ # Return the size, in bytes, of the field 'counter'
+ #
+ def size_counter(self):
+ return (16 / 8)
+
+ #
+ # Return the size, in bits, of the field 'counter'
+ #
+ def sizeBits_counter(self):
+ return 16
+
+ #
+ # Accessor methods for field: local_rx_timestamp
+ # Field type: long
+ # Offset (bits): 32
+ # Size (bits): 32
+ #
+
+ #
+ # Return whether the field 'local_rx_timestamp' is signed (False).
+ #
+ def isSigned_local_rx_timestamp(self):
+ return False
+
+ #
+ # Return whether the field 'local_rx_timestamp' is an array (False).
+ #
+ def isArray_local_rx_timestamp(self):
+ return False
+
+ #
+ # Return the offset (in bytes) of the field 'local_rx_timestamp'
+ #
+ def offset_local_rx_timestamp(self):
+ return (32 / 8)
+
+ #
+ # Return the offset (in bits) of the field 'local_rx_timestamp'
+ #
+ def offsetBits_local_rx_timestamp(self):
+ return 32
+
+ #
+ # Return the value (as a long) of the field 'local_rx_timestamp'
+ #
+ def get_local_rx_timestamp(self):
+ return self.getUIntElement(self.offsetBits_local_rx_timestamp(), 32, 1)
+
+ #
+ # Set the value of the field 'local_rx_timestamp'
+ #
+ def set_local_rx_timestamp(self, value):
+ self.setUIntElement(self.offsetBits_local_rx_timestamp(), 32, value, 1)
+
+ #
+ # Return the size, in bytes, of the field 'local_rx_timestamp'
+ #
+ def size_local_rx_timestamp(self):
+ return (32 / 8)
+
+ #
+ # Return the size, in bits, of the field 'local_rx_timestamp'
+ #
+ def sizeBits_local_rx_timestamp(self):
+ return 32
+
+ #
+ # Accessor methods for field: global_rx_timestamp
+ # Field type: long
+ # Offset (bits): 64
+ # Size (bits): 32
+ #
+
+ #
+ # Return whether the field 'global_rx_timestamp' is signed (False).
+ #
+ def isSigned_global_rx_timestamp(self):
+ return False
+
+ #
+ # Return whether the field 'global_rx_timestamp' is an array (False).
+ #
+ def isArray_global_rx_timestamp(self):
+ return False
+
+ #
+ # Return the offset (in bytes) of the field 'global_rx_timestamp'
+ #
+ def offset_global_rx_timestamp(self):
+ return (64 / 8)
+
+ #
+ # Return the offset (in bits) of the field 'global_rx_timestamp'
+ #
+ def offsetBits_global_rx_timestamp(self):
+ return 64
+
+ #
+ # Return the value (as a long) of the field 'global_rx_timestamp'
+ #
+ def get_global_rx_timestamp(self):
+ return self.getUIntElement(self.offsetBits_global_rx_timestamp(), 32, 1)
+
+ #
+ # Set the value of the field 'global_rx_timestamp'
+ #
+ def set_global_rx_timestamp(self, value):
+ self.setUIntElement(self.offsetBits_global_rx_timestamp(), 32, value, 1)
+
+ #
+ # Return the size, in bytes, of the field 'global_rx_timestamp'
+ #
+ def size_global_rx_timestamp(self):
+ return (32 / 8)
+
+ #
+ # Return the size, in bits, of the field 'global_rx_timestamp'
+ #
+ def sizeBits_global_rx_timestamp(self):
+ return 32
+
+ #
+ # Accessor methods for field: skew_times_1000000
+ # Field type: int
+ # Offset (bits): 96
+ # Size (bits): 32
+ #
+
+ #
+ # Return whether the field 'skew_times_1000000' is signed (False).
+ #
+ def isSigned_skew_times_1000000(self):
+ return False
+
+ #
+ # Return whether the field 'skew_times_1000000' is an array (False).
+ #
+ def isArray_skew_times_1000000(self):
+ return False
+
+ #
+ # Return the offset (in bytes) of the field 'skew_times_1000000'
+ #
+ def offset_skew_times_1000000(self):
+ return (96 / 8)
+
+ #
+ # Return the offset (in bits) of the field 'skew_times_1000000'
+ #
+ def offsetBits_skew_times_1000000(self):
+ return 96
+
+ #
+ # Return the value (as a int) of the field 'skew_times_1000000'
+ #
+ def get_skew_times_1000000(self):
+ return self.getSIntElement(self.offsetBits_skew_times_1000000(), 32, 1)
+
+ #
+ # Set the value of the field 'skew_times_1000000'
+ #
+ def set_skew_times_1000000(self, value):
+ self.setSIntElement(self.offsetBits_skew_times_1000000(), 32, value, 1)
+
+ #
+ # Return the size, in bytes, of the field 'skew_times_1000000'
+ #
+ def size_skew_times_1000000(self):
+ return (32 / 8)
+
+ #
+ # Return the size, in bits, of the field 'skew_times_1000000'
+ #
+ def sizeBits_skew_times_1000000(self):
+ return 32
+
+ #
+ # Accessor methods for field: skew
+ # Field type: int
+ # Offset (bits): 128
+ # Size (bits): 32
+ #
+
+ #
+ # Return whether the field 'skew' is signed (False).
+ #
+ def isSigned_skew(self):
+ return False
+
+ #
+ # Return whether the field 'skew' is an array (False).
+ #
+ def isArray_skew(self):
+ return False
+
+ #
+ # Return the offset (in bytes) of the field 'skew'
+ #
+ def offset_skew(self):
+ return (128 / 8)
+
+ #
+ # Return the offset (in bits) of the field 'skew'
+ #
+ def offsetBits_skew(self):
+ return 128
+
+ #
+ # Return the value (as a int) of the field 'skew'
+ #
+ def get_skew(self):
+ return self.getFloatElement(self.offsetBits_skew(), 32, 0)
+
+ #
+ # Set the value of the field 'skew'
+ #
+ def set_skew(self, value):
+ self.setSIntElement(self.offsetBits_skew(), 32, value, 1)
+
+ #
+ # Return the size, in bytes, of the field 'skew'
+ #
+ def size_skew(self):
+ return (32 / 8)
+
+ #
+ # Return the size, in bits, of the field 'skew'
+ #
+ def sizeBits_skew(self):
+ return 32
+
+ #
+ # Accessor methods for field: is_synced
+ # Field type: short
+ # Offset (bits): 160
+ # Size (bits): 8
+ #
+
+ #
+ # Return whether the field 'is_synced' is signed (False).
+ #
+ def isSigned_is_synced(self):
+ return False
+
+ #
+ # Return whether the field 'is_synced' is an array (False).
+ #
+ def isArray_is_synced(self):
+ return False
+
+ #
+ # Return the offset (in bytes) of the field 'is_synced'
+ #
+ def offset_is_synced(self):
+ return (160 / 8)
+
+ #
+ # Return the offset (in bits) of the field 'is_synced'
+ #
+ def offsetBits_is_synced(self):
+ return 160
+
+ #
+ # Return the value (as a short) of the field 'is_synced'
+ #
+ def get_is_synced(self):
+ return self.getUIntElement(self.offsetBits_is_synced(), 8, 1)
+
+ #
+ # Set the value of the field 'is_synced'
+ #
+ def set_is_synced(self, value):
+ self.setUIntElement(self.offsetBits_is_synced(), 8, value, 1)
+
+ #
+ # Return the size, in bytes, of the field 'is_synced'
+ #
+ def size_is_synced(self):
+ return (8 / 8)
+
+ #
+ # Return the size, in bits, of the field 'is_synced'
+ #
+ def sizeBits_is_synced(self):
+ return 8
+
+ #
+ # Accessor methods for field: ftsp_root_addr
+ # Field type: int
+ # Offset (bits): 168
+ # Size (bits): 16
+ #
+
+ #
+ # Return whether the field 'ftsp_root_addr' is signed (False).
+ #
+ def isSigned_ftsp_root_addr(self):
+ return False
+
+ #
+ # Return whether the field 'ftsp_root_addr' is an array (False).
+ #
+ def isArray_ftsp_root_addr(self):
+ return False
+
+ #
+ # Return the offset (in bytes) of the field 'ftsp_root_addr'
+ #
+ def offset_ftsp_root_addr(self):
+ return (168 / 8)
+
+ #
+ # Return the offset (in bits) of the field 'ftsp_root_addr'
+ #
+ def offsetBits_ftsp_root_addr(self):
+ return 168
+
+ #
+ # Return the value (as a int) of the field 'ftsp_root_addr'
+ #
+ def get_ftsp_root_addr(self):
+ return self.getUIntElement(self.offsetBits_ftsp_root_addr(), 16, 1)
+
+ #
+ # Set the value of the field 'ftsp_root_addr'
+ #
+ def set_ftsp_root_addr(self, value):
+ self.setUIntElement(self.offsetBits_ftsp_root_addr(), 16, value, 1)
+
+ #
+ # Return the size, in bytes, of the field 'ftsp_root_addr'
+ #
+ def size_ftsp_root_addr(self):
+ return (16 / 8)
+
+ #
+ # Return the size, in bits, of the field 'ftsp_root_addr'
+ #
+ def sizeBits_ftsp_root_addr(self):
+ return 16
+
+ #
+ # Accessor methods for field: ftsp_seq
+ # Field type: short
+ # Offset (bits): 184
+ # Size (bits): 8
+ #
+
+ #
+ # Return whether the field 'ftsp_seq' is signed (False).
+ #
+ def isSigned_ftsp_seq(self):
+ return False
+
+ #
+ # Return whether the field 'ftsp_seq' is an array (False).
+ #
+ def isArray_ftsp_seq(self):
+ return False
+
+ #
+ # Return the offset (in bytes) of the field 'ftsp_seq'
+ #
+ def offset_ftsp_seq(self):
+ return (184 / 8)
+
+ #
+ # Return the offset (in bits) of the field 'ftsp_seq'
+ #
+ def offsetBits_ftsp_seq(self):
+ return 184
+
+ #
+ # Return the value (as a short) of the field 'ftsp_seq'
+ #
+ def get_ftsp_seq(self):
+ return self.getUIntElement(self.offsetBits_ftsp_seq(), 8, 1)
+
+ #
+ # Set the value of the field 'ftsp_seq'
+ #
+ def set_ftsp_seq(self, value):
+ self.setUIntElement(self.offsetBits_ftsp_seq(), 8, value, 1)
+
+ #
+ # Return the size, in bytes, of the field 'ftsp_seq'
+ #
+ def size_ftsp_seq(self):
+ return (8 / 8)
+
+ #
+ # Return the size, in bits, of the field 'ftsp_seq'
+ #
+ def sizeBits_ftsp_seq(self):
+ return 8
+
+ #
+ # Accessor methods for field: ftsp_table_entries
+ # Field type: short
+ # Offset (bits): 192
+ # Size (bits): 8
+ #
+
+ #
+ # Return whether the field 'ftsp_table_entries' is signed (False).
+ #
+ def isSigned_ftsp_table_entries(self):
+ return False
+
+ #
+ # Return whether the field 'ftsp_table_entries' is an array (False).
+ #
+ def isArray_ftsp_table_entries(self):
+ return False
+
+ #
+ # Return the offset (in bytes) of the field 'ftsp_table_entries'
+ #
+ def offset_ftsp_table_entries(self):
+ return (192 / 8)
+
+ #
+ # Return the offset (in bits) of the field 'ftsp_table_entries'
+ #
+ def offsetBits_ftsp_table_entries(self):
+ return 192
+
+ #
+ # Return the value (as a short) of the field 'ftsp_table_entries'
+ #
+ def get_ftsp_table_entries(self):
+ return self.getUIntElement(self.offsetBits_ftsp_table_entries(), 8, 1)
+
+ #
+ # Set the value of the field 'ftsp_table_entries'
+ #
+ def set_ftsp_table_entries(self, value):
+ self.setUIntElement(self.offsetBits_ftsp_table_entries(), 8, value, 1)
+
+ #
+ # Return the size, in bytes, of the field 'ftsp_table_entries'
+ #
+ def size_ftsp_table_entries(self):
+ return (8 / 8)
+
+ #
+ # Return the size, in bits, of the field 'ftsp_table_entries'
+ #
+ def sizeBits_ftsp_table_entries(self):
+ return 8
+
+ #
+ # Accessor methods for field: localAverage
+ # Field type: long
+ # Offset (bits): 200
+ # Size (bits): 32
+ #
+
+ #
+ # Return whether the field 'localAverage' is signed (False).
+ #
+ def isSigned_localAverage(self):
+ return False
+
+ #
+ # Return whether the field 'localAverage' is an array (False).
+ #
+ def isArray_localAverage(self):
+ return False
+
+ #
+ # Return the offset (in bytes) of the field 'localAverage'
+ #
+ def offset_localAverage(self):
+ return (200 / 8)
+
+ #
+ # Return the offset (in bits) of the field 'localAverage'
+ #
+ def offsetBits_localAverage(self):
+ return 200
+
+ #
+ # Return the value (as a long) of the field 'localAverage'
+ #
+ def get_localAverage(self):
+ return self.getUIntElement(self.offsetBits_localAverage(), 32, 1)
+
+ #
+ # Set the value of the field 'localAverage'
+ #
+ def set_localAverage(self, value):
+ self.setUIntElement(self.offsetBits_localAverage(), 32, value, 1)
+
+ #
+ # Return the size, in bytes, of the field 'localAverage'
+ #
+ def size_localAverage(self):
+ return (32 / 8)
+
+ #
+ # Return the size, in bits, of the field 'localAverage'
+ #
+ def sizeBits_localAverage(self):
+ return 32
+
+ #
+ # Accessor methods for field: offsetAverage
+ # Field type: int
+ # Offset (bits): 232
+ # Size (bits): 32
+ #
+
+ #
+ # Return whether the field 'offsetAverage' is signed (False).
+ #
+ def isSigned_offsetAverage(self):
+ return False
+
+ #
+ # Return whether the field 'offsetAverage' is an array (False).
+ #
+ def isArray_offsetAverage(self):
+ return False
+
+ #
+ # Return the offset (in bytes) of the field 'offsetAverage'
+ #
+ def offset_offsetAverage(self):
+ return (232 / 8)
+
+ #
+ # Return the offset (in bits) of the field 'offsetAverage'
+ #
+ def offsetBits_offsetAverage(self):
+ return 232
+
+ #
+ # Return the value (as a int) of the field 'offsetAverage'
+ #
+ def get_offsetAverage(self):
+ return self.getSIntElement(self.offsetBits_offsetAverage(), 32, 1)
+
+ #
+ # Set the value of the field 'offsetAverage'
+ #
+ def set_offsetAverage(self, value):
+ self.setSIntElement(self.offsetBits_offsetAverage(), 32, value, 1)
+
+ #
+ # Return the size, in bytes, of the field 'offsetAverage'
+ #
+ def size_offsetAverage(self):
+ return (32 / 8)
+
+ #
+ # Return the size, in bits, of the field 'offsetAverage'
+ #
+ def sizeBits_offsetAverage(self):
+ return 32
+
--- /dev/null
+COMPONENT=RadioCountToLedsAppC
+
+CFLAGS += -DLPL_INTERVAL=200
+CFLAGS += -DLOW_POWER_LISTENING
+
+include $(MAKERULES)
+
--- /dev/null
+/*
+ * "Copyright (c) 2004-2005 The Regents of the University of California.
+ * 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 UNIVERSITY OF CALIFORNIA 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 UNIVERSITY OF
+ * CALIFORNIA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * THE UNIVERSITY OF CALIFORNIA 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 UNIVERSITY OF CALIFORNIA HAS NO OBLIGATION TO
+ * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS."
+ *
+ * Copyright (c) 2002-2003 Intel Corporation
+ * All rights reserved.
+ *
+ * This file is distributed under the terms in the attached INTEL-LICENSE
+ * file. If you do not find these files, copies can be found by writing to
+ * Intel Research Berkeley, 2150 Shattuck Avenue, Suite 1300, Berkeley, CA,
+ * 94704. Attention: Intel License Inquiry.
+ */
+
+#ifndef RADIO_COUNT_TO_LEDS_H
+#define RADIO_COUNT_TO_LEDS_H
+
+typedef nx_struct radio_count_msg {
+ nx_uint16_t counter;
+} radio_count_msg_t;
+
+enum {
+ AM_RADIO_COUNT_MSG = 6,
+};
+
+#endif
--- /dev/null
+// $Id$
+
+/* tab:4
+ * "Copyright (c) 2000-2005 The Regents of the University of California.
+ * 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 UNIVERSITY OF CALIFORNIA 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 UNIVERSITY OF
+ * CALIFORNIA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * THE UNIVERSITY OF CALIFORNIA 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 UNIVERSITY OF CALIFORNIA HAS NO OBLIGATION TO
+ * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS."
+ *
+ * Copyright (c) 2002-2003 Intel Corporation
+ * All rights reserved.
+ *
+ * This file is distributed under the terms in the attached INTEL-LICENSE
+ * file. If you do not find these files, copies can be found by writing to
+ * Intel Research Berkeley, 2150 Shattuck Avenue, Suite 1300, Berkeley, CA,
+ * 94704. Attention: Intel License Inquiry.
+ */
+
+#include "RadioCountToLeds.h"
+#include "Timer.h"
+
+/**
+ * Configuration for the RadioCountToLeds application. RadioCountToLeds
+ * maintains a 4Hz counter, broadcasting its value in an AM packet
+ * every time it gets updated. A RadioCountToLeds node that hears a counter
+ * displays the bottom three bits on its LEDs. This application is a useful
+ * test to show that basic AM communication and timers work.
+ *
+ * @author Philip Levis
+ * @date June 6 2005
+ */
+
+configuration RadioCountToLedsAppC {}
+implementation {
+ components MainC, new RadioCountToLedsC(T32khz) as App, LedsC;
+ components new AMReceiverC(AM_RADIO_COUNT_MSG);
+ components new TimerMilliC();
+ components TimeSyncMessageC as ActiveMessageC;
+
+ App.Boot -> MainC.Boot;
+
+ App.Receive -> AMReceiverC;
+ App.AMSend -> ActiveMessageC.TimeSyncAMSend32khz[AM_RADIO_COUNT_MSG];
+ App.AMControl -> ActiveMessageC;
+ App.Leds -> LedsC;
+ App.MilliTimer -> TimerMilliC;
+ App.Packet -> ActiveMessageC;
+
+ components Counter32khz32C, new CounterToLocalTimeC(T32khz) as LocalTime32khzC;
+ LocalTime32khzC.Counter -> Counter32khz32C;
+ App.LocalTime -> LocalTime32khzC;
+
+
+#ifdef LOW_POWER_LISTENING
+ components CC2420ActiveMessageC;
+ App.LowPowerListening -> CC2420ActiveMessageC;
+#endif
+
+}
+
+
--- /dev/null
+// $Id$
+
+/* tab:4
+ * "Copyright (c) 2000-2005 The Regents of the University of California.
+ * 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 UNIVERSITY OF CALIFORNIA 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 UNIVERSITY OF
+ * CALIFORNIA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * THE UNIVERSITY OF CALIFORNIA 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 UNIVERSITY OF CALIFORNIA HAS NO OBLIGATION TO
+ * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS."
+ *
+ * Copyright (c) 2002-2003 Intel Corporation
+ * All rights reserved.
+ *
+ * This file is distributed under the terms in the attached INTEL-LICENSE
+ * file. If you do not find these files, copies can be found by writing to
+ * Intel Research Berkeley, 2150 Shattuck Avenue, Suite 1300, Berkeley, CA,
+ * 94704. Attention: Intel License Inquiry.
+ */
+
+#include "Timer.h"
+#include "RadioCountToLeds.h"
+
+/**
+ * Implementation of the RadioCountToLeds application. RadioCountToLeds
+ * maintains a 4Hz counter, broadcasting its value in an AM packet
+ * every time it gets updated. A RadioCountToLeds node that hears a counter
+ * displays the bottom three bits on its LEDs. This application is a useful
+ * test to show that basic AM communication and timers work.
+ *
+ * @author Philip Levis
+ * @date June 6 2005
+ */
+
+generic module RadioCountToLedsC(typedef precision_tag) @safe() {
+ uses {
+ interface Leds;
+ interface Boot;
+ interface Receive;
+ interface TimeSyncAMSend<precision_tag,uint32_t> as AMSend;
+ interface Timer<TMilli> as MilliTimer;
+ interface SplitControl as AMControl;
+ interface Packet;
+
+ interface LocalTime<precision_tag> as LocalTime;
+
+
+#ifdef LOW_POWER_LISTENING
+ interface LowPowerListening;
+#endif
+
+ }
+}
+implementation {
+
+ message_t packet;
+
+ bool locked;
+ uint16_t counter = 0;
+
+ event void Boot.booted() {
+ call AMControl.start();
+ }
+
+ event void AMControl.startDone(error_t err) {
+ if (err == SUCCESS) {
+ call MilliTimer.startPeriodic(2*1024);
+ }
+ else {
+ call AMControl.start();
+ }
+ }
+
+ event void AMControl.stopDone(error_t err) {
+ // do nothing
+ }
+
+ event void MilliTimer.fired() {
+ uint32_t time = call LocalTime.get();
+ counter++;
+ dbg("RadioCountToLedsC", "RadioCountToLedsC: timer fired, counter is %hu.\n", counter);
+ if (locked) {
+ return;
+ }
+ else {
+ radio_count_msg_t* rcm = (radio_count_msg_t*)call Packet.getPayload(&packet, sizeof(radio_count_msg_t));
+ if (rcm == NULL) {
+ return;
+ }
+
+ rcm->counter = counter;
+#ifdef LOW_POWER_LISTENING
+ call LowPowerListening.setRxSleepInterval(&packet, LPL_INTERVAL);
+#endif
+
+ if (call AMSend.send(AM_BROADCAST_ADDR, &packet, sizeof(radio_count_msg_t), time) == SUCCESS) {
+ dbg("RadioCountToLedsC", "RadioCountToLedsC: packet sent.\n", counter);
+ locked = TRUE;
+ }
+ }
+ }
+
+ event message_t* Receive.receive(message_t* bufPtr,
+ void* payload, uint8_t len) {
+ dbg("RadioCountToLedsC", "Received packet of length %hhu.\n", len);
+ if (len != sizeof(radio_count_msg_t)) {return bufPtr;}
+ else {
+ radio_count_msg_t* rcm = (radio_count_msg_t*)payload;
+ if (rcm->counter & 0x1) {
+ call Leds.led0On();
+ }
+ else {
+ call Leds.led0Off();
+ }
+ if (rcm->counter & 0x2) {
+ call Leds.led1On();
+ }
+ else {
+ call Leds.led1Off();
+ }
+ if (rcm->counter & 0x4) {
+ call Leds.led2On();
+ }
+ else {
+ call Leds.led2Off();
+ }
+ return bufPtr;
+ }
+ }
+
+ event void AMSend.sendDone(message_t* bufPtr, error_t error) {
+ if (&packet == bufPtr) {
+ locked = FALSE;
+ }
+ }
+
+}