Author/Contact: 
	branislav.kusy@vanderbilt.edu (Branislav Kusy, ISIS, Vanderbilt)
	miklos.maroti@vanderbilt.edu (Miklos Maroti, ISIS, Vanderbilt)

DESCRIPTION:

The TimeSync component provides global time synchronization in the network. All of the nodes
in the network run the same algorithm, they choose the root of network and the global time of
the network is then determined based on the internal clock of the root. To keep synchronized, 
TimeSync msgs are periodically broadcasted by each node. This may possibly be switched off for
a certain amount of time without harming the algorithm (eg. by using RadioSuspend :D). Each 
node keeps a certain number of msgs in a table and (re)calculates the skew and offset of his
local clock vs global time each time a new TimeSync msg comes. We assume that the local time 
of node A is linear function of local time of node B, so we can use linear regression. The 
algorithm works multi-hop with an approximate error +-2 jiffies (1/32k secs) per hop - see the
analysis for more complete results. See the requirements to correctly update tos system files 
with our modified versions. The most recent algorithm was only used with MICA2's however it 
should also work with MICA's.

TimeSyncMsg:
	Used to synchronize the network through the radio. Contains the sender address (2 bytes),
	the root address (2 bytes), the sequence number of the last root TimeSyncMsg (1 byte), 
	the global time when the message was sent (4 bytes) and the local time when the message 
	was received. To achieve this we were forced to set the sendingTime and arrivalTime in 
	the radio stack. To decrease the computation needed in the radio stack, we compute the 
	offset (global-local time) in the TimeSync and radio stack only adds local time at 
	synchronization point. The timesync does not fill out arrivalTime field of the msg, 
	this is taken care of by radio stack at the receiver side.

Phases of algorithm:
- INIT phase: triggered by switching the mote on
	The node which is joining the network first listens to the radio for certain amount of 
	time. If it does not receive TimeSync message from any other node in the network, it 
	declares itself the root of the network. The length of this initial period is defined
	by ROOT_ALONE_TIMEOUT value = the number of Timer.fired() events (currently Timer fires
	each 30 secs and ROOT_ALONE_TIMEOUT is 7, so the node waits 30*7 = 210 secs).

- SENDING phase: triggered by Timer.fired() event
	Each node is periodically broadcasting TimeSync msgs. BEACON_RATE (in secs) specifies
	the period of this broadcast. Eventually we would like the node with the smallest addr
	to get the root of the network (the root is the only one who can increase the seq number
	of the time sync msg). However we do not want to force all the network to change its 
	global time by large amount each time the new node with smaller ID appears. Therefore 
	we are waiting for certain period of time (ROOT_SWITCH_TIMEOUT), during which we determine
	the skew and the offset of the global time and only after then we announce ourselves being 
	the root (after this our skew and offset won't change until someone else gets root, 
	we might want to keep the skew to be 0 to decrease the error in arithmetic). A node also 
	declares itself the root if he did not here any time sync msg for ROOT_SWITCH_TIMEOUT 
	Timer events.

- PROCESSING phase: triggered by TimeSync msg.receive() event
	each time a new TimeSync msg comes, we need to store it in our table of messages and 
	recalculate the skew and offset of our local time with respect to global time. The msg
	is considered to be new only if it has higher sequence number than the last heard msg.
	Only the root has chance to increase the sequence number. The calculation of skew and
	offset in calculateConversion task is sensitive on the difference between the current
	local time and the avg local time (avg of times stored in the table). So if the root
	dies and does not increase the sequence number of time sync msg, tables of all the 
	other nodes won't get updated and the value of local time - avg time can grow what
	introduces an arithmetic error in the computation. To avoid this we use (as desc above)
	ROOT_SWITCH_TIMEOUT and declare some other node being root.

PARAMETERS:

The TimeSync component can be configured by changing the following values in 
TimeSyncMsg.h/TimeSyncM.nc:

AM_TIMESYNCMSG: the active message id used 
MAX_ENTREES: the number of time sync msg entrees each mote keeps in its table
BEACON_RATE: the period (secs) of broadcasting the time sync msgs
ROOT_ALONE_TIMEOUT: (in Timer events) how long should the mote wait for the time sync msgs
	in the initial phase before declaring itself the root when no msgs came
ROOT_SWITCH_TIMEOUT: 
	1. how long the mote with smaller ID than the root should listen to time sync msgs before
		declaring itself root
	2. the same as ROOT_ALONE_TIMEOUT when not in initialization phase

REQUIRED SYSTEM FILES:

  update the following files from minitasks/02/vu cvs:
	both MICA&MICA2:
	 tos/system/LocalTime.nc
	 tos/system/Timer.h
	 tos/system/Timer.nc
	 tos/system/TimerC.nc
	 tos/system/TimerM.nc
	 tos/system/ClockC.nc
	 
	MICA:
	 tos/platform/mica/Clock.h
	 tos/platform/mica/ClockM.nc
	 tos/platform/mica/ClockM2.nc
	 tos/platform/mica/MicaHighSpeedRadioM.nc
	 tos/platform/mica/RadioCRCPacket.nc

	MICA2:
	 tos/platform/mica2/Clock.h
	 tos/platform/mica2/ClockM.nc
	 tos/platform/mica2/CC1000RadioC.nc
	 tos/platform/mica2/CC1000RadioIntM.nc
	
USING TIMESYNC:
	(see examples TestTimeSyncC, TestTimeSyncSuspC )
	 - get the cvs version of TimeSync (minitasks/02/vu/tos/lib/TimeSync directory)
	 - copy all required system files to the dir of your application (or corresponding tos dirs)
	 - wire StdControl of TimeSyncC to the MAIN component
	 - wire GlobalTime interface to your application
	 - add flags to Makefile:
		 PFLAGS=-DVANDY_TIME_SYNC when using just time sync
				-DVANDY_TIME_SYNC_POLLER if using TimeSyncDebugger, to allow TimeSyncPoll msgs
				 to be updated

TESTING & RESULTS:
	
	- see apps/TestTimeSync
