[Tinyos-2-commits] CVS: tinyos-2.x/tos/lib/ftsp GlobalTime.nc, NONE, 1.1 TimeSyncC.nc, NONE, 1.1 TimeSyncInfo.nc, NONE, 1.1 TimeSyncMode.nc, NONE, 1.1 TimeSyncMsg.h, NONE, 1.1 TimeSyncNotify.nc, NONE, 1.1 TimeSyncP.nc, NONE, 1.1
Janos Sallai
sallai at users.sourceforge.net
Tue Jun 10 15:16:15 PDT 2008
Update of /cvsroot/tinyos/tinyos-2.x/tos/lib/ftsp
In directory sc8-pr-cvs10.sourceforge.net:/tmp/cvs-serv16035
Added Files:
GlobalTime.nc TimeSyncC.nc TimeSyncInfo.nc TimeSyncMode.nc
TimeSyncMsg.h TimeSyncNotify.nc TimeSyncP.nc
Log Message:
checking in FTSP to tos/lib
--- NEW FILE: GlobalTime.nc ---
/*
* 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 at isis.vanderbilt.edu)
* Ported to T2: 3/17/08 by Brano Kusy (branislav.kusy at gmail.com)
*/
interface GlobalTime<precision_tag>
{
/**
* Returns the current local time of this mote.
*/
async command uint32_t getLocalTime();
/**
* Reads the current global time. This method is a combination
* of <code>getLocalTime</code> and <code>local2Global</code>.
* @return SUCCESS if this mote is synchronized, FAIL otherwise.
*/
async command error_t getGlobalTime(uint32_t *time);
/**
* Converts the local time given in <code>time</code> into the
* corresponding global time and stores this again in
* <code>time</code>. The following equation is used to compute the
* conversion:
*
* globalTime = localTime + offset + skew * (localTime - syncPoint)
*
* The skew is normalized to 0.0 (1.0 is subtracted) to increase the
* machine precision. The syncPoint value is periodically updated to
* increase the machine precision of the floating point arithmetic and
* also to allow time wrap.
*
* @return SUCCESS if this mote is synchronized, FAIL otherwise.
*/
async command error_t local2Global(uint32_t *time);
/**
* Converts the global time given in <code>time</code> into the
* correspoding local time and stores this again in
* <code>time</code>. This method performs the inverse of the
* <code>local2Global</clode> transformation.
*
* @return SUCCESS if this mote is synchronized, FAIL otherwise.
*/
async command error_t global2Local(uint32_t *time);
}
--- NEW FILE: TimeSyncC.nc ---
/*
* 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, Janos Sallai
* Date last modified: 3/17/03
* Ported to T2: 3/17/08 by Brano Kusy (branislav.kusy at gmail.com)
*/
#include "TimeSyncMsg.h"
configuration TimeSyncC
{
uses interface Boot;
provides interface Init;
provides interface StdControl;
provides interface GlobalTime<TMilli>;
//interfaces for extra fcionality: need not to be wired
provides interface TimeSyncInfo;
provides interface TimeSyncMode;
provides interface TimeSyncNotify;
}
implementation
{
components new TimeSyncP(TMilli);
GlobalTime = TimeSyncP;
StdControl = TimeSyncP;
Init = TimeSyncP;
Boot = TimeSyncP;
TimeSyncInfo = TimeSyncP;
TimeSyncMode = TimeSyncP;
TimeSyncNotify = TimeSyncP;
components TimeSyncMessageC as ActiveMessageC;
TimeSyncP.RadioControl -> ActiveMessageC;
TimeSyncP.Send -> ActiveMessageC.TimeSyncAMSendMilli[AM_TIMESYNCMSG];
TimeSyncP.Receive -> ActiveMessageC.Receive[AM_TIMESYNCMSG];
TimeSyncP.TimeSyncPacket -> ActiveMessageC;
components HilTimerMilliC;
TimeSyncP.LocalTime -> HilTimerMilliC;
components new TimerMilliC() as TimerC;
TimeSyncP.Timer -> TimerC;
#if defined(TIMESYNC_LEDS)
components LedsC;
#else
components NoLedsC as LedsC;
#endif
TimeSyncP.Leds -> LedsC;
}
--- NEW FILE: TimeSyncInfo.nc ---
/*
* 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 at isis.vanderbilt.edu)
* Ported to T2: 3/17/08 by Brano Kusy (branislav.kusy at gmail.com)
*/
interface TimeSyncInfo
{
/**
* Returns current offset of the local time wrt global time.
*/
async command uint32_t getOffset();
/**
* Returns current skew of the local time wrt global time.
* This value is normalized to 0.0 (1.0 is subtracted) to get maximum
* representation precision.
*/
async command float getSkew();
/**
* Returns the local time of the last synchronization point. This
* value is close to the current local time and updated when a new
* time synchronization message arrives.
*/
async command uint32_t getSyncPoint();
/**
* Returns the current root to which this node is synchronized.
*/
async command uint16_t getRootID();
/**
* Returns the latest seq number seen from the current root.
*/
async command uint8_t getSeqNum();
/**
* Returns the number of entries stored currently in the
* regerssion table.
*/
async command uint8_t getNumEntries();
/**
* Returns the value of heartBeats variable.
*/
async command uint8_t getHeartBeats();
}
--- NEW FILE: TimeSyncMode.nc ---
/*
* 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 at isis.vanderbilt.edu)
* Ported to T2: 3/17/08 by Brano Kusy (branislav.kusy at gmail.com)
*/
/**
* the time sync module can work in two modes:
* - TS_TIMER_MODE (default): TS msgs sent period. from the timer
* - TS_USER_MODE: TS msgs sent only when explic. asked by user
* via TimeSyncMode.send() command, TimeSync.Timer
* is stopped in this mode
*/
interface TimeSyncMode
{
/**
* Sets the current mode of the TimeSync module.
* returns FAIL if didn't succeed
*/
command error_t setMode(uint8_t mode);
/**
* Gets the current mode of the TimeSync module.
*/
command uint8_t getMode();
/**
* command to send out time synchronization message.
* returns FAIL if TimeSync not in TS_USER_MODE
*/
command error_t send();
}
--- NEW FILE: TimeSyncMsg.h ---
/*
* 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 at isis.vanderbilt.edu)
* Ported to T2: 3/17/08 by Brano Kusy (branislav.kusy at gmail.com)
*/
#if defined(TIMESYNCMSG_H)
#else
#define TIMESYNCMSG_H
typedef nx_struct TimeSyncMsg
{
nx_uint16_t rootID; // the node id of the synchronization root
nx_uint16_t nodeID; // the node if of the sender
nx_uint8_t seqNum; // sequence number for the root
/* This field is initially set to the offset between global time and local
* time. The TimeStamping component will add the current local time when the
* message is actually transmitted. Thus the receiver will receive the
* global time of the sender when the message is actually sent. */
nx_uint32_t globalTime;
//just for convenience
nx_uint32_t localTime;
} TimeSyncMsg;
enum {
AM_TIMESYNCMSG = 0xAA,
TIMESYNCMSG_LEN = sizeof(TimeSyncMsg) - sizeof(nx_uint32_t),
TS_TIMER_MODE = 0, // see TimeSyncMode interface
TS_USER_MODE = 1, // see TimeSyncMode interface
};
#endif
--- NEW FILE: TimeSyncNotify.nc ---
/*
* 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 at isis.vanderbilt.edu)
* Ported to T2: 3/17/08 by Brano Kusy (branislav.kusy at gmail.com)
*/
/**
* time sync module (TimeSyncM) provides notification of arriving
* and transmitted time-sync msgs through TimeSyncNotify interface:
*/
interface TimeSyncNotify
{
/**
* fired when time-sync msg is received and accepted
*/
event void msg_received();
/**
* fired when time-sync msg is sent by TimeSyncM or the sending did not
* succeed
*/
event void msg_sent();
}
--- NEW FILE: TimeSyncP.nc ---
/*
* 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 at isis.vanderbilt.edu), Janos Sallai
* Ported to T2: 3/17/08 by Brano Kusy (branislav.kusy at gmail.com)
*/
#include "TimeSyncMsg.h"
generic module TimeSyncP(typedef precision_tag)
{
provides
{
interface Init;
interface StdControl;
interface GlobalTime<precision_tag>;
//interfaces for extra functionality: need not to be wired
interface TimeSyncInfo;
interface TimeSyncMode;
interface TimeSyncNotify;
}
uses
{
interface Boot;
interface SplitControl as RadioControl;
interface TimeSyncAMSend<precision_tag,uint32_t> as Send;
interface Receive;
interface Timer<TMilli>;
interface Leds;
interface TimeSyncPacket<precision_tag,uint32_t>;
interface LocalTime<precision_tag> as LocalTime;
}
}
implementation
{
#ifndef TIMESYNC_RATE
#define TIMESYNC_RATE 10
#endif
enum {
MAX_ENTRIES = 8, // number of entries in the table
BEACON_RATE = TIMESYNC_RATE, // how often send the beacon msg (in seconds)
ROOT_TIMEOUT = 5, //time to declare itself the root if no msg was received (in sync periods)
IGNORE_ROOT_MSG = 4, // after becoming the root ignore other roots messages (in send period)
ENTRY_VALID_LIMIT = 4, // number of entries to become synchronized
ENTRY_SEND_LIMIT = 3, // number of entries to send sync messages
ENTRY_THROWOUT_LIMIT = 100, // if time sync error is bigger than this clear the table
};
typedef struct TableItem
{
uint8_t state;
uint32_t localTime;
int32_t timeOffset; // globalTime - localTime
} TableItem;
enum {
ENTRY_EMPTY = 0,
ENTRY_FULL = 1,
};
TableItem table[MAX_ENTRIES];
uint8_t tableEntries;
enum {
STATE_IDLE = 0x00,
STATE_PROCESSING = 0x01,
STATE_SENDING = 0x02,
STATE_INIT = 0x04,
};
uint8_t state, mode;
/*
We do linear regression from localTime to timeOffset (globalTime - localTime).
This way we can keep the slope close to zero (ideally) and represent it
as a float with high precision.
timeOffset - offsetAverage = skew * (localTime - localAverage)
timeOffset = offsetAverage + skew * (localTime - localAverage)
globalTime = localTime + offsetAverage + skew * (localTime - localAverage)
*/
float skew;
uint32_t localAverage;
int32_t offsetAverage;
uint8_t numEntries; // the number of full entries in the table
message_t processedMsgBuffer;
message_t* processedMsg;
message_t outgoingMsgBuffer;
TimeSyncMsg* outgoingMsg;
uint8_t heartBeats; // the number of sucessfully sent messages
// since adding a new entry with lower beacon id than ours
async command uint32_t GlobalTime.getLocalTime()
{
return call LocalTime.get();
}
async command error_t GlobalTime.getGlobalTime(uint32_t *time)
{
*time = call GlobalTime.getLocalTime();
return call GlobalTime.local2Global(time);
}
error_t is_synced()
{
if (numEntries>=ENTRY_VALID_LIMIT || outgoingMsg->rootID==TOS_NODE_ID)
return SUCCESS;
else
return FAIL;
}
async command error_t GlobalTime.local2Global(uint32_t *time)
{
*time += offsetAverage + (int32_t)(skew * (int32_t)(*time - localAverage));
return is_synced();
}
async command error_t GlobalTime.global2Local(uint32_t *time)
{
uint32_t approxLocalTime = *time - offsetAverage;
*time = approxLocalTime - (int32_t)(skew * (int32_t)(approxLocalTime - localAverage));
return is_synced();
}
void calculateConversion()
{
float newSkew = skew;
uint32_t newLocalAverage;
int32_t newOffsetAverage;
int64_t localSum;
int64_t offsetSum;
int8_t i;
for(i = 0; i < MAX_ENTRIES && table[i].state != ENTRY_FULL; ++i)
;
if( i >= MAX_ENTRIES ) // table is empty
return;
/*
We use a rough approximation first to avoid time overflow errors. The idea
is that all times in the table should be relatively close to each other.
*/
newLocalAverage = table[i].localTime;
newOffsetAverage = table[i].timeOffset;
localSum = 0;
offsetSum = 0;
while( ++i < MAX_ENTRIES )
if( table[i].state == ENTRY_FULL ) {
localSum += (int32_t)(table[i].localTime - newLocalAverage) / tableEntries;
offsetSum += (int32_t)(table[i].timeOffset - newOffsetAverage) / tableEntries;
}
newLocalAverage += localSum;
newOffsetAverage += offsetSum;
localSum = offsetSum = 0;
for(i = 0; i < MAX_ENTRIES; ++i)
if( table[i].state == ENTRY_FULL ) {
int32_t a = table[i].localTime - newLocalAverage;
int32_t b = table[i].timeOffset - newOffsetAverage;
localSum += (int64_t)a * a;
offsetSum += (int64_t)a * b;
}
if( localSum != 0 )
newSkew = (float)offsetSum / (float)localSum;
atomic
{
skew = newSkew;
offsetAverage = newOffsetAverage;
localAverage = newLocalAverage;
numEntries = tableEntries;
}
}
void clearTable()
{
int8_t i;
for(i = 0; i < MAX_ENTRIES; ++i)
table[i].state = ENTRY_EMPTY;
atomic numEntries = 0;
}
uint8_t numErrors=0;
void addNewEntry(TimeSyncMsg *msg)
{
int8_t i, freeItem = -1, oldestItem = 0;
uint32_t age, oldestTime = 0;
int32_t timeError;
tableEntries = 0;
// clear table if the received entry's been inconsistent for some time
timeError = msg->localTime;
call GlobalTime.local2Global(&timeError);
timeError -= msg->globalTime;
if( (is_synced() == SUCCESS) &&
(timeError > ENTRY_THROWOUT_LIMIT || timeError < -ENTRY_THROWOUT_LIMIT))
{
if (++numErrors>3)
clearTable();
}
else
numErrors = 0;
for(i = 0; i < MAX_ENTRIES; ++i) {
age = msg->localTime - table[i].localTime;
//logical time error compensation
if( age >= 0x7FFFFFFFL )
table[i].state = ENTRY_EMPTY;
if( table[i].state == ENTRY_EMPTY )
freeItem = i;
else
++tableEntries;
if( age >= oldestTime ) {
oldestTime = age;
oldestItem = i;
}
}
if( freeItem < 0 )
freeItem = oldestItem;
else
++tableEntries;
table[freeItem].state = ENTRY_FULL;
table[freeItem].localTime = msg->localTime;
table[freeItem].timeOffset = msg->globalTime - msg->localTime;
}
void task processMsg()
{
TimeSyncMsg* msg = (TimeSyncMsg*)(processedMsg->data);
if( msg->rootID < outgoingMsg->rootID &&
// jw: after becoming the root ignore other roots messages (in send period)
~(heartBeats < IGNORE_ROOT_MSG && outgoingMsg->rootID == TOS_NODE_ID) ){
outgoingMsg->rootID = msg->rootID;
outgoingMsg->seqNum = msg->seqNum;
}
else if( outgoingMsg->rootID == msg->rootID && (int8_t)(msg->seqNum - outgoingMsg->seqNum) > 0 ) {
outgoingMsg->seqNum = msg->seqNum;
}
else
goto exit;
call Leds.led0Toggle();
if( outgoingMsg->rootID < TOS_NODE_ID )
heartBeats = 0;
addNewEntry(msg);
calculateConversion();
signal TimeSyncNotify.msg_received();
exit:
state &= ~STATE_PROCESSING;
}
event message_t* Receive.receive(message_t* msg, void* payload, uint8_t len)
{
#ifdef TIMESYNC_DEBUG // this code can be used to simulate multiple hopsf
uint8_t incomingID = (uint8_t)((TimeSyncMsg*)payload)->nodeID;
int8_t diff = (incomingID & 0x0F) - (TOS_NODE_ID & 0x0F);
if( diff < -1 || diff > 1 )
return msg;
diff = (incomingID & 0xF0) - (TOS_NODE_ID & 0xF0);
if( diff < -16 || diff > 16 )
return msg;
#endif
if( (state & STATE_PROCESSING) == 0 ) {
message_t* old = processedMsg;
processedMsg = msg;
((TimeSyncMsg*)(processedMsg->data))->localTime = call TimeSyncPacket.eventTime(msg);
state |= STATE_PROCESSING;
post processMsg();
return old;
}
return msg;
}
task void sendMsg()
{
uint32_t localTime, globalTime;
globalTime = localTime = call GlobalTime.getLocalTime();
call GlobalTime.local2Global(&globalTime);
// we need to periodically update the reference point for the root
// to avoid wrapping the 32-bit (localTime - localAverage) value
if( outgoingMsg->rootID == TOS_NODE_ID ) {
if( (int32_t)(localTime - localAverage) >= 0x20000000 )
{
atomic
{
localAverage = localTime;
offsetAverage = globalTime - localTime;
}
}
}
else if( heartBeats >= ROOT_TIMEOUT ) {
heartBeats = 0; //to allow ROOT_SWITCH_IGNORE to work
outgoingMsg->rootID = TOS_NODE_ID;
++(outgoingMsg->seqNum); // maybe set it to zero?
}
outgoingMsg->globalTime = globalTime;
// we don't send time sync msg, if we don't have enough data
if( numEntries < ENTRY_SEND_LIMIT && outgoingMsg->rootID != TOS_NODE_ID ){
++heartBeats;
state &= ~STATE_SENDING;
}
else if( call Send.send(AM_BROADCAST_ADDR, &outgoingMsgBuffer, TIMESYNCMSG_LEN, localTime ) != SUCCESS ){
state &= ~STATE_SENDING;
signal TimeSyncNotify.msg_sent();
}
}
event void Send.sendDone(message_t* ptr, error_t error)
{
if (ptr != &outgoingMsgBuffer)
return;
if(error == SUCCESS)
{
++heartBeats;
call Leds.led1Toggle();
if( outgoingMsg->rootID == TOS_NODE_ID )
++(outgoingMsg->seqNum);
}
state &= ~STATE_SENDING;
signal TimeSyncNotify.msg_sent();
}
void timeSyncMsgSend()
{
if( outgoingMsg->rootID == 0xFFFF && ++heartBeats >= ROOT_TIMEOUT ) {
outgoingMsg->seqNum = 0;
outgoingMsg->rootID = TOS_NODE_ID;
}
if( outgoingMsg->rootID != 0xFFFF && (state & STATE_SENDING) == 0 ) {
state |= STATE_SENDING;
post sendMsg();
}
}
event void Timer.fired()
{
if (mode == TS_TIMER_MODE) {
timeSyncMsgSend();
}
else
call Timer.stop();
}
command error_t TimeSyncMode.setMode(uint8_t mode_){
if (mode == mode_)
return SUCCESS;
if (mode_ == TS_USER_MODE){
call Timer.startPeriodic((uint32_t)1000 * BEACON_RATE);
}
else
call Timer.stop();
mode = mode_;
return SUCCESS;
}
command uint8_t TimeSyncMode.getMode(){
return mode;
}
command error_t TimeSyncMode.send(){
if (mode == TS_USER_MODE){
timeSyncMsgSend();
return SUCCESS;
}
return FAIL;
}
command error_t Init.init()
{
atomic{
skew = 0.0;
localAverage = 0;
offsetAverage = 0;
};
clearTable();
atomic outgoingMsg = (TimeSyncMsg*)call Send.getPayload(&outgoingMsgBuffer, sizeof(TimeSyncMsg));
outgoingMsg->rootID = 0xFFFF;
processedMsg = &processedMsgBuffer;
state = STATE_INIT;
return SUCCESS;
}
event void Boot.booted()
{
call RadioControl.start();
call StdControl.start();
}
command error_t StdControl.start()
{
mode = TS_TIMER_MODE;
heartBeats = 0;
outgoingMsg->nodeID = TOS_NODE_ID;
call Timer.startPeriodic((uint32_t)1000 * BEACON_RATE);
return SUCCESS;
}
command error_t StdControl.stop()
{
call Timer.stop();
return SUCCESS;
}
async command float TimeSyncInfo.getSkew() { return skew; }
async command uint32_t TimeSyncInfo.getOffset() { return offsetAverage; }
async command uint32_t TimeSyncInfo.getSyncPoint() { return localAverage; }
async command uint16_t TimeSyncInfo.getRootID() { return outgoingMsg->rootID; }
async command uint8_t TimeSyncInfo.getSeqNum() { return outgoingMsg->seqNum; }
async command uint8_t TimeSyncInfo.getNumEntries() { return numEntries; }
async command uint8_t TimeSyncInfo.getHeartBeats() { return heartBeats; }
default event void TimeSyncNotify.msg_received(){}
default event void TimeSyncNotify.msg_sent(){}
event void RadioControl.startDone(error_t error){}
event void RadioControl.stopDone(error_t error){}
}
More information about the Tinyos-2-commits
mailing list