]> oss.titaniummirror.com Git - tinyos-2.x.git/commitdiff
updated TimeSyncMessage implementation
authormmaroti <mmaroti>
Wed, 12 Mar 2008 19:42:56 +0000 (19:42 +0000)
committermmaroti <mmaroti>
Wed, 12 Mar 2008 19:42:56 +0000 (19:42 +0000)
14 files changed:
tos/chips/rf230/DefaultMac.h [deleted file]
tos/chips/rf230/DefaultMacC.nc
tos/chips/rf230/DefaultPacket.h
tos/chips/rf230/DefaultPacketC.nc
tos/chips/rf230/DefaultPacketP.nc
tos/chips/rf230/PacketLastTouch.nc [new file with mode: 0644]
tos/chips/rf230/RF230LayerC.nc
tos/chips/rf230/RF230LayerP.nc
tos/chips/rf230/TimeSyncMessageC.nc [new file with mode: 0644]
tos/chips/rf230/TimeSyncMessageP.nc [new file with mode: 0644]
tos/chips/rf230/TimeSyncPacket.nc [new file with mode: 0644]
tos/chips/rf230/TimeSyncSend.nc [new file with mode: 0644]
tos/chips/rf230/notes.txt [deleted file]
tos/platforms/iris/chips/rf230/HplRF230C.nc

diff --git a/tos/chips/rf230/DefaultMac.h b/tos/chips/rf230/DefaultMac.h
deleted file mode 100644 (file)
index 3547bde..0000000
+++ /dev/null
@@ -1,54 +0,0 @@
-/*
- * Copyright (c) 2007, Vanderbilt University
- * All rights reserved.
- *
- * Permission to use, copy, modify, and distribute this software and its
- * documentation for any purpose, without fee, and without written agreement is
- * hereby granted, provided that the above copyright notice, the following
- * two paragraphs and the author appear in all copies of this software.
- * 
- * IN NO EVENT SHALL THE VANDERBILT UNIVERSITY BE LIABLE TO ANY PARTY FOR
- * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT
- * OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF THE VANDERBILT
- * UNIVERSITY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- * 
- * THE VANDERBILT UNIVERSITY SPECIFICALLY DISCLAIMS ANY WARRANTIES,
- * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
- * AND FITNESS FOR A PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS
- * ON AN "AS IS" BASIS, AND THE VANDERBILT UNIVERSITY HAS NO OBLIGATION TO
- * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
- *
- * Author: Miklos Maroti
- */
-
-#ifndef __DEFAULTMAC_H__
-#define __DEFAULTMAC_H__
-
-#include <IEEE154Packet.h>
-
-typedef ieee154_header_t defaultmac_header_t;
-
-typedef nx_struct defaultmac_metadata_t
-{
-       nx_uint8_t flags;
-       nx_uint8_t lqi;
-       nx_uint16_t timestamp;
-} defaultmac_metadata_t;
-
-enum defaultmac_metadata_flags
-{
-       DEFAULTMAC_WAS_ACKED = 0x01,
-       DEFAULTMAC_SCHEDULED_TX = 0x02,
-};
-
-/* This is the default value of the TX_PWR field of the PHY_TX_PWR register. */
-#ifndef RF230_DEF_RFPOWER
-#define RF230_DEF_RFPOWER      0
-#endif
-
-/* This is the default value of the CHANNEL field of the PHY_CC_CCA register. */
-#ifndef RF230_DEF_CHANNEL
-#define RF230_DEF_CHANNEL      11
-#endif
-
-#endif//__DEFAULTMAC_H__
index 2f6ca524e15c5fc93a66e60db8d469664851fdcc..2143adc35a34ce0f7825140b587098f0ac2815eb 100644 (file)
@@ -39,7 +39,6 @@ configuration DefaultMacC
 
                interface PacketField<uint8_t> as PacketLinkQuality;
                interface PacketTimeStamp<TRF230, uint16_t>;
-               interface PacketTimeSynch<TRF230, uint16_t>;
        }
 }
 
@@ -60,7 +59,6 @@ implementation
        PacketAcknowledgements = DefaultPacketC;
        PacketLinkQuality = DefaultPacketC.PacketLinkQuality;
        PacketTimeStamp = DefaultPacketC.PacketTimeStamp;
-       PacketTimeSynch = DefaultPacketC.PacketTimeSynch;
 
        components ActiveMessageLayerC;
        components MessageBufferLayerC;
@@ -112,6 +110,5 @@ implementation
        RF230LayerC.RF230Config -> DefaultMacP;
        RF230LayerC.PacketLinkQuality -> DefaultPacketC.PacketLinkQuality;
        RF230LayerC.PacketTransmitPower -> DefaultPacketC.PacketTransmitPower;
-       RF230LayerC.PacketTimeStamping -> DefaultPacketC.PacketTimeStamping;
-       RF230LayerC.PacketTimeSynchron -> DefaultPacketC.PacketTimeSynchron;
+       RF230LayerC.PacketTimeStamp -> DefaultPacketC.PacketTimeStamp;
 }
index 819b5bd48d82aa466844868ad9dc4a6ec9939fa7..dcf62d3c6ff74b775e44ef0869016ae44c21792f 100644 (file)
@@ -43,15 +43,4 @@ enum defpacket_metadata_flags
        DEFPACKET_CLEAR_METADATA = 0x00,
 };
 
-typedef nx_struct defpacket_footer_t
-{
-       nx_uint16_t timeoffset;
-} defpacket_footer_t;
-
-enum defpacket_footer_enum
-{
-       // just to signal missing time offsets
-       DEFPACKET_INVALID_TIMEOFFSET = 0x7317,
-};
-
 #endif//__DEFAULTPACKET_H__
index f02f3e6543a76ce5e627d34c07c71979b7c86d71..3c32ee332561af81aa669fbb526356e20938c611 100644 (file)
@@ -32,11 +32,8 @@ configuration DefaultPacketC
                interface PacketAcknowledgements;
                interface PacketField<uint8_t> as PacketLinkQuality;
                interface PacketField<uint8_t> as PacketTransmitPower;
-               interface PacketField<uint16_t> as PacketTimeStamping;
-               interface PacketField<uint16_t> as PacketTimeSynchron;
 
                interface PacketTimeStamp<TRF230, uint16_t>;
-               interface PacketTimeSynch<TRF230, uint16_t>;
        }
 }
 
@@ -51,9 +48,5 @@ implementation
        PacketAcknowledgements = DefaultPacketP;
        PacketLinkQuality = DefaultPacketP.PacketLinkQuality;
        PacketTransmitPower = DefaultPacketP.PacketTransmitPower;
-       PacketTimeStamping = DefaultPacketP.PacketTimeStamping;
-       PacketTimeSynchron = DefaultPacketP.PacketTimeSynchron;
-
        PacketTimeStamp = DefaultPacketP.PacketTimeStamp;
-       PacketTimeSynch = DefaultPacketP.PacketTimeSynch;
 }
index 1c2358df89a56bf737e481d5cb751c8b6303c6d2..a0cb16f36623ddaa520e80d94b8e64879879f3af 100644 (file)
@@ -31,11 +31,8 @@ module DefaultPacketP
                interface Packet;
                interface PacketField<uint8_t> as PacketLinkQuality;
                interface PacketField<uint8_t> as PacketTransmitPower;
-               interface PacketField<uint16_t> as PacketTimeStamping;
-               interface PacketField<uint16_t> as PacketTimeSynchron;
 
                interface PacketTimeStamp<TRF230, uint16_t>;
-               interface PacketTimeSynch<TRF230, uint16_t>;
        }
 
        uses
@@ -46,38 +43,18 @@ module DefaultPacketP
 
 implementation
 {
-/*----------------- Async Packet -----------------*/
-
-#define PACKET_OVERHEAD ((sizeof(ieee154_header_t) - 1) + sizeof(defpacket_footer_t) + sizeof(ieee154_footer_t))
-
-       // async Packet.payloadLength
-       inline uint8_t getPayloadLength(message_t* msg)
-       {
-               //      sizeof(ieee154_header_t) - 1 : the ieee154 header minus the length field
-               //      sizeof(defpacket_footer_t) : footer containing the embedded time offset
-               //      sizeof(ieee154_footer_t) : the size of the CRC (not transmitted)
-
-               return call IEEE154Packet.getLength(msg) - PACKET_OVERHEAD;
-       }
-
-       // async Pakcet.maxPayloadLength
-       inline uint8_t getMaxPayloadLength()
+       enum
        {
-               return TOSH_DATA_LENGTH;
-       }
-
-/*----------------- Accessors -----------------*/
+               PACKET_LENGTH_INCREASE = 
+                       sizeof(defpacket_header_t) - 1  // the 8-bit length field is not counted
+                       + sizeof(ieee154_footer_t),             // the CRC is not stored in memory
+       };
 
        inline defpacket_metadata_t* getMeta(message_t* msg)
        {
                return (defpacket_metadata_t*)(msg->metadata);
        }
 
-       inline defpacket_footer_t* getFooter(message_t* msg)
-       {
-               return (defpacket_footer_t*)(msg->data + getPayloadLength(msg));
-       }
-
 /*----------------- Packet -----------------*/
 
        command void Packet.clear(message_t* msg) 
@@ -90,22 +67,24 @@ implementation
 
                getMeta(msg)->flags = DEFPACKET_CLEAR_METADATA;
        }
-  
+
        inline command void Packet.setPayloadLength(message_t* msg, uint8_t len) 
        {
-               call IEEE154Packet.setLength(msg, len + PACKET_OVERHEAD);
+               call IEEE154Packet.setLength(msg, len + PACKET_LENGTH_INCREASE);
        }
-  
+
+       // TODO: make Packet.payloadLength async
        inline command uint8_t Packet.payloadLength(message_t* msg) 
        {
-               return getPayloadLength(msg);
+               return call IEEE154Packet.getLength(msg) - PACKET_LENGTH_INCREASE;
        }
-  
+
+       // TODO: make Packet.maxPayloadLength async
        inline command uint8_t Packet.maxPayloadLength()
        {
-               return getMaxPayloadLength();
+               return TOSH_DATA_LENGTH;
        }
-  
+
        command void* Packet.getPayload(message_t* msg, uint8_t len)
        {
                if( len > TOSH_DATA_LENGTH )
@@ -158,101 +137,27 @@ implementation
 
 /*----------------- PacketTimeStamp -----------------*/
 
-       async command bool PacketTimeStamping.isSet(message_t* msg)
+       async command bool PacketTimeStamp.isSet(message_t* msg)
        {
                return getMeta(msg)->flags & DEFPACKET_TIMESTAMP;
        }
 
-       async command uint16_t PacketTimeStamping.get(message_t* msg)
+       async command uint16_t PacketTimeStamp.get(message_t* msg)
        {
                return getMeta(msg)->timestamp;
        }
 
-       async command void PacketTimeStamping.clear(message_t* msg)
+       async command void PacketTimeStamp.clear(message_t* msg)
        {
                getMeta(msg)->flags &= ~DEFPACKET_TIMESTAMP;
        }
 
-       async command void PacketTimeStamping.set(message_t* msg, uint16_t value)
+       async command void PacketTimeStamp.set(message_t* msg, uint16_t value)
        {
                getMeta(msg)->flags |= DEFPACKET_TIMESTAMP;
                getMeta(msg)->timestamp = value;
        }
 
-       inline async command bool PacketTimeStamp.isSet(message_t* msg)
-       {
-               return call PacketTimeStamping.isSet(msg);
-       }
-
-       inline async command uint16_t PacketTimeStamp.get(message_t* msg)
-       {
-               return call PacketTimeStamping.get(msg);
-       }
-
-       inline async command void PacketTimeStamp.clear(message_t* msg)
-       {
-               call PacketTimeStamping.clear(msg);
-       }
-
-       inline async command void PacketTimeStamp.set(message_t* msg, uint16_t value)
-       {
-               call PacketTimeStamping.set(msg, value);
-       }
-
-/*----------------- PacketTimeSynch -----------------*/
-
-       async command bool PacketTimeSynchron.isSet(message_t* msg)
-       {
-               // just sanity check if the length is not initialized
-               if( getPayloadLength(msg) > getMaxPayloadLength() )
-                       return FALSE;
-
-               return getFooter(msg)->timeoffset != DEFPACKET_INVALID_TIMEOFFSET;
-       }
-
-       async command uint16_t PacketTimeSynchron.get(message_t* msg)
-       {
-               return getFooter(msg)->timeoffset;
-       }
-
-       async command void PacketTimeSynchron.clear(message_t* msg)
-       {
-               // just sanity check if the length is not initialized
-               if( getPayloadLength(msg) <= getMaxPayloadLength() )
-                       getFooter(msg)->timeoffset = DEFPACKET_INVALID_TIMEOFFSET;
-       }
-
-       async command void PacketTimeSynchron.set(message_t* msg, uint16_t value)
-       {
-               if( getPayloadLength(msg) > getMaxPayloadLength() )
-                       return;
-
-               if( value == DEFPACKET_INVALID_TIMEOFFSET )
-                       ++value;
-
-               getFooter(msg)->timeoffset = value;
-       }
-
-       inline async command bool PacketTimeSynch.isSet(message_t* msg)
-       {
-               return call PacketTimeSynchron.isSet(msg);
-       }
-
-       inline async command uint16_t PacketTimeSynch.get(message_t* msg)
-       {
-               return call PacketTimeSynchron.get(msg);
-       }
-
-       inline async command void PacketTimeSynch.clear(message_t* msg)
-       {
-               call PacketTimeSynchron.clear(msg);
-       }
-
-       inline async command void PacketTimeSynch.set(message_t* msg, uint16_t value)
-       {
-               call PacketTimeSynchron.set(msg, value);
-       }
-
 /*----------------- Global fields -----------------*/
 
        uint8_t flags;
diff --git a/tos/chips/rf230/PacketLastTouch.nc b/tos/chips/rf230/PacketLastTouch.nc
new file mode 100644 (file)
index 0000000..af51caf
--- /dev/null
@@ -0,0 +1,45 @@
+/*
+ * Copyright (c) 2007, Vanderbilt University
+ * All rights reserved.
+ *
+ * Permission to use, copy, modify, and distribute this software and its
+ * documentation for any purpose, without fee, and without written agreement is
+ * hereby granted, provided that the above copyright notice, the following
+ * two paragraphs and the author appear in all copies of this software.
+ * 
+ * IN NO EVENT SHALL THE VANDERBILT UNIVERSITY BE LIABLE TO ANY PARTY FOR
+ * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT
+ * OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF THE VANDERBILT
+ * UNIVERSITY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ * 
+ * THE VANDERBILT UNIVERSITY SPECIFICALLY DISCLAIMS ANY WARRANTIES,
+ * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
+ * AND FITNESS FOR A PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS
+ * ON AN "AS IS" BASIS, AND THE VANDERBILT UNIVERSITY HAS NO OBLIGATION TO
+ * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
+ *
+ * Author: Miklos Maroti
+ */
+
+interface PacketLastTouch
+{
+       /**
+        * Requests the touch event to be called back just before the message
+        * transmission starts.
+        */
+       async command void request(message_t* msg);
+
+       /**
+        * Cancels any pending requests.
+        */
+       async command void cancel(message_t* msg);
+
+       /**
+        * This event is called by the MAC layer when the tranmission of the
+        * message starts (the SFD byte is already transmitted and the packet
+        * is already time stamped). In this method the packet payload can be
+        * updated. This method MUST do absolutely minimal processing, and 
+        * should complete in 1-2 microseconds.
+        */
+       async event void touch(message_t* msg);
+}
index 596928a685096253e35c655e0cbd18af6bbed6cc..7e12df94004b4c060e133d8ee3b9451aa769399f 100644 (file)
@@ -36,8 +36,7 @@ configuration RF230LayerC
                interface RF230Config;
                interface PacketField<uint8_t> as PacketLinkQuality;
                interface PacketField<uint8_t> as PacketTransmitPower;
-               interface PacketField<uint16_t> as PacketTimeStamping;
-               interface PacketField<uint16_t> as PacketTimeSynchron;
+               interface PacketTimeStamp<TRF230, uint16_t>;
        }
 }
 
@@ -53,8 +52,7 @@ implementation
        RF230Config = RF230LayerP;
        PacketLinkQuality = RF230LayerP.PacketLinkQuality;
        PacketTransmitPower = RF230LayerP.PacketTransmitPower;
-       PacketTimeStamping = RF230LayerP.PacketTimeStamping;
-       PacketTimeSynchron = RF230LayerP.PacketTimeSynchron;
+       PacketTimeStamp = RF230LayerP.PacketTimeStamp;
 
        RF230LayerP.RadioAlarm -> RadioAlarmC.RadioAlarm[unique("RadioAlarm")];
        RadioAlarmC.Alarm -> HplRF230C.Alarm;
index c11a1729631847a2bc5ef02b1f35e3645897c528..2796fd4e17a1f213be99b5375a87fad66ecebb87 100644 (file)
@@ -56,9 +56,8 @@ module RF230LayerP
 
                interface RF230Config;
                interface PacketField<uint8_t> as PacketLinkQuality;
-               interface PacketField<uint16_t> as PacketTimeStamping;
-               interface PacketField<uint16_t> as PacketTimeSynchron;
                interface PacketField<uint8_t> as PacketTransmitPower;
+               interface PacketTimeStamp<TRF230, uint16_t>;
                interface Tasklet;
                interface RadioAlarm;
 
@@ -431,10 +430,6 @@ implementation
                // the FCS is atomatically generated
                length -= 2;
 
-               // calculate and embed the time offset
-               if( call PacketTimeSynchron.isSet(msg) )
-                       call PacketTimeSynchron.set(msg, call PacketTimeSynchron.get(msg) - time);
-
                do {
                        call HplRF230.spiSplitReadWrite(*(data++));
                }
@@ -476,11 +471,7 @@ implementation
                        return FAIL;
                }
 
-               // TODO: be nicer for retransmissions
-               // clear the embedded time stamp field
-               call PacketTimeSynchron.clear(msg);
-
-               call PacketTimeStamping.set(msg, time);
+               call PacketTimeStamp.set(msg, time);
 
                // wait for the TRX_END interrupt
                state = STATE_BUSY_TX_2_RX_ON;
@@ -569,10 +560,6 @@ implementation
                state = STATE_RX_ON;
                cmd = CMD_NONE;
 
-               // we need a correct time stamp of the message
-               if( call PacketTimeSynchron.isSet(rxMsg) && call PacketTimeStamping.isSet(rxMsg) )
-                       call PacketTimeSynchron.set(rxMsg, call PacketTimeSynchron.get(rxMsg) + call PacketTimeStamping.get(rxMsg));
-
                // signal only if it has passed the CRC check
                if( crc == 0 )
                        rxMsg = signal RadioReceive.receive(rxMsg);
@@ -664,9 +651,9 @@ implementation
                                         * CMD_TRANSMIT.
                                         */
                                        if( irq == RF230_IRQ_RX_START ) // just to be cautious
-                                               call PacketTimeStamping.set(rxMsg, time - RX_SFD_DELAY);
+                                               call PacketTimeStamp.set(rxMsg, time - RX_SFD_DELAY);
                                        else
-                                               call PacketTimeStamping.clear(rxMsg);
+                                               call PacketTimeStamp.clear(rxMsg);
 
                                        cmd = CMD_RECEIVE;
                                }
diff --git a/tos/chips/rf230/TimeSyncMessageC.nc b/tos/chips/rf230/TimeSyncMessageC.nc
new file mode 100644 (file)
index 0000000..5876b0c
--- /dev/null
@@ -0,0 +1,71 @@
+/*
+ * Copyright (c) 2007, Vanderbilt University
+ * All rights reserved.
+ *
+ * Permission to use, copy, modify, and distribute this software and its
+ * documentation for any purpose, without fee, and without written agreement is
+ * hereby granted, provided that the above copyright notice, the following
+ * two paragraphs and the author appear in all copies of this software.
+ * 
+ * IN NO EVENT SHALL THE VANDERBILT UNIVERSITY BE LIABLE TO ANY PARTY FOR
+ * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT
+ * OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF THE VANDERBILT
+ * UNIVERSITY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ * 
+ * THE VANDERBILT UNIVERSITY SPECIFICALLY DISCLAIMS ANY WARRANTIES,
+ * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
+ * AND FITNESS FOR A PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS
+ * ON AN "AS IS" BASIS, AND THE VANDERBILT UNIVERSITY HAS NO OBLIGATION TO
+ * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
+ *
+ * Author: Miklos Maroti
+ */
+
+#include <Timer.h>
+#include <AM.h>
+
+configuration TimeSyncMessageC
+{
+       provides
+       {
+               interface TimeSyncSend<TMicro> as TimeSyncSendMicro[am_id_t id];
+               interface TimeSyncPacket<TMicro> as TimeSyncPacketMicro;
+               interface LocalTime<TMicro> as LocalTimeMicro;
+
+               interface TimeSyncSend<TMilli> as TimeSyncSendMilli[am_id_t id];
+               interface TimeSyncPacket<TMilli> as TimeSyncPacketMilli;
+               interface LocalTime<TMilli> as LocalTimeMilli;
+
+               interface SplitControl;
+               interface Receive[uint8_t id];
+               interface Receive as Snoop[am_id_t id];
+               interface Packet;
+               interface AMPacket;
+               interface PacketAcknowledgements;
+       }
+}
+
+implementation
+{
+       components TimeSyncMessageP, ActiveMessageC, LocalTimeMilliC;
+
+       TimeSyncSendMicro = TimeSyncMessageP;
+       TimeSyncPacketMicro = TimeSyncMessageP;
+       LocalTimeMicro = ActiveMessageC;
+
+       TimeSyncSendMilli = TimeSyncMessageP;
+       TimeSyncPacketMilli = TimeSyncMessageP;
+       LocalTimeMilli = LocalTimeMilliC;
+
+       Packet = TimeSyncMessageP;
+       TimeSyncMessageP.SubSend -> ActiveMessageC.AMSend;
+       TimeSyncMessageP.SubPacket -> ActiveMessageC.Packet;
+
+       TimeSyncMessageP.LocalTimeMilli -> LocalTimeMilliC;
+
+       SplitControl = ActiveMessageC;
+       Receive = ActiveMessageC.Receive;
+       Snoop = ActiveMessageC.Snoop;
+       AMPacket = ActiveMessageC;
+       PacketAcknowledgements = ActiveMessageC;
+}
diff --git a/tos/chips/rf230/TimeSyncMessageP.nc b/tos/chips/rf230/TimeSyncMessageP.nc
new file mode 100644 (file)
index 0000000..8b99ccc
--- /dev/null
@@ -0,0 +1,229 @@
+/*
+ * Copyright (c) 2007, Vanderbilt University
+ * All rights reserved.
+ *
+ * Permission to use, copy, modify, and distribute this software and its
+ * documentation for any purpose, without fee, and without written agreement is
+ * hereby granted, provided that the above copyright notice, the following
+ * two paragraphs and the author appear in all copies of this software.
+ * 
+ * IN NO EVENT SHALL THE VANDERBILT UNIVERSITY BE LIABLE TO ANY PARTY FOR
+ * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT
+ * OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF THE VANDERBILT
+ * UNIVERSITY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ * 
+ * THE VANDERBILT UNIVERSITY SPECIFICALLY DISCLAIMS ANY WARRANTIES,
+ * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
+ * AND FITNESS FOR A PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS
+ * ON AN "AS IS" BASIS, AND THE VANDERBILT UNIVERSITY HAS NO OBLIGATION TO
+ * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
+ *
+ * Author: Miklos Maroti
+ */
+
+module TimeSyncMessageP
+{
+       provides
+       {
+               interface TimeSyncSend<TMicro> as TimeSyncSendMicro[uint8_t id];
+               interface TimeSyncSend<TMilli> as TimeSyncSendMilli[uint8_t id];
+               interface Packet;
+               interface TimeSyncPacket<TMicro> as TimeSyncPacketMicro;
+               interface TimeSyncPacket<TMilli> as TimeSyncPacketMilli;
+       }
+
+       uses
+       {
+               interface AMSend as SubSend[uint8_t id];
+               interface Packet as SubPacket;
+               interface PacketTimeStamp<TMicro,uint32_t>;
+               interface PacketLastTouch;
+
+               interface LocalTime<TMicro> as LocalTimeMicro;
+               interface LocalTime<TMilli> as LocalTimeMilli;
+       }
+}
+
+implementation
+{
+/*----------------- Packet -----------------*/
+
+       typedef nx_struct timesync_footer_t
+       {
+               nx_uint32_t time_offset;        // in micorsec
+       } timesync_footer_t;
+
+       typedef struct timesync_local_t
+       {
+               uint32_t event_time;            // in microsec
+       } timesync_local_t;
+
+       inline timesync_footer_t* getFooter(message_t* msg)
+       {
+               return (timesync_footer_t*)(msg->data + call SubPacket.payloadLength(msg) - sizeof(timesync_footer_t));
+       }
+
+       inline timesync_local_t* getLocal(message_t* msg)
+       {
+               return (timesync_local_t*)(msg->data + call SubPacket.maxPayloadLength() - sizeof(timesync_local_t));
+       }
+
+       command void Packet.clear(message_t* msg) 
+       {
+               call SubPacket.clear(msg);
+               call PacketLastTouch.cancel(msg);       // TODO: check if we need to do this
+       }
+
+       command void Packet.setPayloadLength(message_t* msg, uint8_t len) 
+       {
+               call SubPacket.setPayloadLength(msg, len + sizeof(timesync_footer_t));
+       }
+
+       command uint8_t Packet.payloadLength(message_t* msg) 
+       {
+               return call SubPacket.payloadLength(msg) - sizeof(timesync_footer_t);
+       }
+
+       command uint8_t Packet.maxPayloadLength()
+       {
+               return call SubPacket.maxPayloadLength() - sizeof(timesync_footer_t) - sizeof(timesync_local_t);
+       }
+
+       command void* Packet.getPayload(message_t* msg, uint8_t len)
+       {
+               return call SubPacket.getPayload(msg, len + sizeof(timesync_footer_t) + sizeof(timesync_local_t));
+       }
+
+/*----------------- TimeSyncSendMicro -----------------*/
+
+       command error_t TimeSyncSendMicro.send[am_id_t id](uint32_t event_time, am_addr_t addr, message_t* msg, uint8_t len)
+       {
+               timesync_local_t* local = getLocal(msg);
+
+               local->event_time = event_time;
+
+               call PacketLastTouch.request(msg);
+
+               return call SubSend.send[id](addr, msg, len);
+       }
+
+       command error_t TimeSyncSendMicro.cancel[am_id_t id](message_t* msg)
+       {
+               call PacketLastTouch.cancel(msg);
+               return call SubSend.cancel[id](msg);
+       }
+
+       default event void TimeSyncSendMicro.sendDone[am_id_t id](message_t* msg, error_t error)
+       {
+       }
+
+       command uint8_t TimeSyncSendMicro.maxPayloadLength[am_id_t id]()
+       {
+               return call SubSend.maxPayloadLength[id]() - sizeof(timesync_footer_t);
+       }
+
+       command void* TimeSyncSendMicro.getPayload[am_id_t id](message_t* msg, uint8_t len)
+       {
+               return call SubSend.getPayload[id](msg, len + sizeof(timesync_footer_t));
+       }
+
+/*----------------- TimeSyncSendMilli -----------------*/
+
+       command error_t TimeSyncSendMilli.send[am_id_t id](uint32_t event_time, am_addr_t addr, message_t* msg, uint8_t len)
+       {
+               timesync_local_t* local = getLocal(msg);
+
+               // compute elapsed time in millisecond
+               event_time = ((event_time - call LocalTimeMilli.get()) << 10) + call LocalTimeMicro.get();
+
+               local->event_time = event_time;
+
+               call PacketLastTouch.request(msg);
+
+               return call SubSend.send[id](addr, msg, len);
+       }
+
+       command error_t TimeSyncSendMilli.cancel[am_id_t id](message_t* msg)
+       {
+               return call SubSend.cancel[id](msg);
+       }
+
+       default event void TimeSyncSendMilli.sendDone[am_id_t id](message_t* msg, error_t error)
+       {
+       }
+
+       command uint8_t TimeSyncSendMilli.maxPayloadLength[am_id_t id]()
+       {
+               return call SubSend.maxPayloadLength[id]() - sizeof(timesync_footer_t);
+       }
+
+       command void* TimeSyncSendMilli.getPayload[am_id_t id](message_t* msg, uint8_t len)
+       {
+               return call SubSend.getPayload[id](msg, len + sizeof(timesync_footer_t));
+       }
+
+       /*----------------- SubSend.sendDone -------------------*/
+
+       event void SubSend.sendDone[am_id_t id](message_t* msg, error_t error)
+       {
+               signal TimeSyncSendMicro.sendDone[id](msg, error);
+               signal TimeSyncSendMilli.sendDone[id](msg, error);
+       }
+
+       /*----------------- PacketLastTouch.touch -------------------*/
+
+       enum
+       {
+               TIMESYNC_INVALID_STAMP = 0x80000000L,
+       };
+
+       async event void PacketLastTouch.touch(message_t* msg)
+       {
+               timesync_footer_t* footer = footer = getFooter(msg);
+               timesync_local_t* local;
+
+               if( call PacketTimeStamp.isSet(msg) )
+               {
+                       local = getLocal(msg);
+
+                       footer->time_offset = local->event_time - call PacketTimeStamp.get(msg);
+               }
+               else
+                       footer->time_offset = TIMESYNC_INVALID_STAMP;
+       }
+
+       /*----------------- TimeSyncPacketMicro -----------------*/
+
+       async command bool TimeSyncPacketMicro.hasValidTime(message_t* msg)
+       {
+               timesync_footer_t* footer = getFooter(msg);
+
+               return call PacketTimeStamp.isSet(msg) && footer->time_offset != TIMESYNC_INVALID_STAMP;
+       }
+
+       async command uint32_t TimeSyncPacketMicro.getEventTime(message_t* msg)
+       {
+               timesync_footer_t* footer = getFooter(msg);
+
+               return (uint32_t)(footer->time_offset) + call PacketTimeStamp.get(msg);
+       }
+
+       /*----------------- TimeSyncPacketMilli -----------------*/
+
+       async command bool TimeSyncPacketMilli.hasValidTime(message_t* msg)
+       {
+               timesync_footer_t* footer = getFooter(msg);
+
+               return call PacketTimeStamp.isSet(msg) && footer->time_offset != TIMESYNC_INVALID_STAMP;
+       }
+
+       async command uint32_t TimeSyncPacketMilli.getEventTime(message_t* msg)
+       {
+               timesync_footer_t* footer = getFooter(msg);
+
+               // time offset compared to now in microsec, important that this is signed
+               int32_t elapsed = (uint32_t)(footer->time_offset) + call PacketTimeStamp.get(msg) - call LocalTimeMicro.get();
+
+               return (elapsed >> 10) + call LocalTimeMilli.get();
+       }
+}
diff --git a/tos/chips/rf230/TimeSyncPacket.nc b/tos/chips/rf230/TimeSyncPacket.nc
new file mode 100644 (file)
index 0000000..7264ecb
--- /dev/null
@@ -0,0 +1,43 @@
+/*
+ * Copyright (c) 2007, Vanderbilt University
+ * All rights reserved.
+ *
+ * Permission to use, copy, modify, and distribute this software and its
+ * documentation for any purpose, without fee, and without written agreement is
+ * hereby granted, provided that the above copyright notice, the following
+ * two paragraphs and the author appear in all copies of this software.
+ * 
+ * IN NO EVENT SHALL THE VANDERBILT UNIVERSITY BE LIABLE TO ANY PARTY FOR
+ * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT
+ * OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF THE VANDERBILT
+ * UNIVERSITY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ * 
+ * THE VANDERBILT UNIVERSITY SPECIFICALLY DISCLAIMS ANY WARRANTIES,
+ * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
+ * AND FITNESS FOR A PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS
+ * ON AN "AS IS" BASIS, AND THE VANDERBILT UNIVERSITY HAS NO OBLIGATION TO
+ * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
+ *
+ * Author: Miklos Maroti
+ */
+
+interface TimeSyncPacket<precision_tag>
+{
+       /**
+        * Returns TRUE if the value returned by <tt>getTime</tt> can be trusted.
+        * Under certain circumstances the received message cannot be properly 
+        * time stamped, so the sender-receiver synchronization cannot be finished
+        * on the receiver side. In this case, this command returns FALSE.
+        * This command MUST BE called only on the receiver side and only for 
+        * messages transmitted via the TimeSyncSend interface.
+        */
+       async command bool hasValidTime(message_t* msg);
+
+       /**
+        * This command should be called by the receiver of a message. The time 
+        * of the synchronization event is returned as expressed in the local
+        * clock of the caller. This command MUST BE called only on the receiver
+        * side and only for messages transmitted via the TimeSyncSend interface.
+        */
+       async command uint32_t getEventTime(message_t* msg);
+}
diff --git a/tos/chips/rf230/TimeSyncSend.nc b/tos/chips/rf230/TimeSyncSend.nc
new file mode 100644 (file)
index 0000000..267d555
--- /dev/null
@@ -0,0 +1,104 @@
+/*
+ * Copyright (c) 2007, Vanderbilt University
+ * All rights reserved.
+ *
+ * Permission to use, copy, modify, and distribute this software and its
+ * documentation for any purpose, without fee, and without written agreement is
+ * hereby granted, provided that the above copyright notice, the following
+ * two paragraphs and the author appear in all copies of this software.
+ * 
+ * IN NO EVENT SHALL THE VANDERBILT UNIVERSITY BE LIABLE TO ANY PARTY FOR
+ * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT
+ * OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF THE VANDERBILT
+ * UNIVERSITY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ * 
+ * THE VANDERBILT UNIVERSITY SPECIFICALLY DISCLAIMS ANY WARRANTIES,
+ * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
+ * AND FITNESS FOR A PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS
+ * ON AN "AS IS" BASIS, AND THE VANDERBILT UNIVERSITY HAS NO OBLIGATION TO
+ * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
+ */
+
+/**
+  * @author Philip Levis
+  * @author Miklos Maroti
+  *
+  * @see TimeSyncPacket
+  */ 
+
+#include <TinyError.h>
+#include <message.h>
+#include <AM.h>
+
+interface TimeSyncSend<precision_tag>
+{
+       /**
+       * This command sends a regular message just like <tt>AMSend.send</tt>, but 
+       * it also performs sender-receiver time synchronization. The <tt>event_time</tt>
+       * parameter holds the time of some event as expressed in the local clock of 
+       * the sender. The receiver can obtain the time of this event (expressed in its
+       * own local time) via the <tt>TimeSyncPacket</tt> interface.
+       *
+       * @param addr   address to which to send the packet
+       * @param msg    the packet
+       * @param len    the length of the data in the packet payload
+       * @param time   the synchronization point to be transfered with the message
+       * @return       SUCCESS if the request to send succeeded and a
+       *               sendDone will be signaled later, EBUSY if the
+       *               abstraction cannot send now but will be able to
+       *               later, or FAIL if the communication layer is not
+       *               in a state that can send (e.g., off).
+    * @see          sendDone
+       */ 
+       command error_t send(uint32_t event_time, am_addr_t addr, message_t* msg, uint8_t len);
+
+       /**
+       * Cancel a requested transmission. Returns SUCCESS if the 
+       * transmission was canceled properly (not sent in its
+       * entirety). Note that the component may not know
+       * if the send was successfully canceled, if the radio is
+       * handling much of the logic; in this case, a component
+       * should be conservative and return an appropriate error code.
+       * A successful call to cancel must always result in a 
+       * sendFailed event, and never a sendSucceeded event.
+       * 
+       * @param  msg     the packet whose transmission should be cancelled.
+       * @return SUCCESS if the transmission was cancelled, FAIL otherwise.
+       * @see    sendDone
+       */
+       command error_t cancel(message_t* msg);
+
+       /** 
+       * Signaled in response to an accepted send request. <tt>msg</tt> is
+       * the message buffer sent, and <tt>error</tt> indicates whether
+       * the send was successful.
+       *
+       * @param  msg   the packet which was submitted as a send request
+       * @param  error SUCCESS if it was sent successfully, FAIL if it was not,
+       *               ECANCEL if it was cancelled
+       * @see send
+       * @see cancel
+       */ 
+       event void sendDone(message_t* msg, error_t error);
+
+       /**
+       * Return the maximum payload length that this communication layer
+       * can provide. This command behaves identically to
+       * <tt>Packet.maxPayloadLength</tt> and is included in this
+       * interface as a convenience.
+       *
+       * @return the maximum payload length
+       */
+       command uint8_t maxPayloadLength();
+
+       /**
+       * Return a pointer to a protocol's payload region in a packet.
+       * This command behaves identically to <tt>Packet.getPayload</tt>
+       * (minus the length parameter) and is included in this interface
+       * as a convenience.
+       *
+       * @param  msg    the packet
+       * @return        the payload of the packet
+       */
+       command void* getPayload(message_t* msg, uint8_t len);
+}
diff --git a/tos/chips/rf230/notes.txt b/tos/chips/rf230/notes.txt
deleted file mode 100644 (file)
index b5bdd65..0000000
+++ /dev/null
@@ -1,113 +0,0 @@
-
-1. to support multiple sends through the ascynronous radio send interface 
-the send() must return error_t to indicate it cannot service more
-
-2. to have guaranteed timing we need guaranteed access to the send interface, 
-so we cannot have multiple sends through the radio send interface.
-
-3. time critical tasks:
-       CCA -> TX-DATA
-       RX-DATA -> TX-ACK
-       TX-DATA -> RX-ACK
-
-4. after the CCA we need to send data, but then TX-DATA cannot wait for the
-completion of a receieved packet (maybe we should), so maybe we should not
-have concurrent receives with everything else, enable receive only when 
-needed
-
-5. if there are no multiple sends in the radio send interface, then to have 
-robustness, the separate interfaces should record the requests until they are 
-ready to service them 
-
-6. to support receiving messages in the TX-DATA -> RX-ACK gap that need to be 
-acknowledged we must have a TX-ACK queue (we do not want to saturate the 
-channel while waiting for ACK). If this gap is large, then many messages 
-could accumulate that have not been acked, which can get out of control
-
-7. for low power listeing the TX-DATA -> RX-ACK -> TX-DATA gap should be 
-minimal to have the best duty cycle possible (maybe with a pair of CCA 
-checks it is possible to cover the gap).
-
-8. if only single requests are serviced by the radio send interface, then
-there is no need for the message pointer in the sendDone event.
-
-9. the receive buffer cannot service the higher layer via the asynchronous
-radio receive interface (or there should be another buffering down the road)
-that is pumped with a task. Also, the sendDone event must be fired from a
-task too.
-
-10. if a valid packet is received in the TX-DATA -> RX-ACK gap, then we could
-fail the TX-DATA but accept the RX-DATA. This requires two events to be 
-fiered: sendDone(FAIL) and receive(msg). We cannot fire the sendDone first
-because then our component does not become ready, and the higher layer might
-want to transmit again instead of listening (needs buffering) 
-
-11. four ways to handle the receive data while waiting for ACK problem 
-  a) drop these packets, 
-  b) drop only those that need acknowledgements, 
-  c) buffer them at the acked send layer (needs message_t) and deliver them
-     when receiving is allowed again
-  d) deliver them before signaling the sendDone(FAIL), but then we have to 
-     allow concurrent receives with sends
-
-12. It is very problematic to receive unexpected packets, what to do with 
-these? They could occur in the following gaps
-  a) CCA -> TX-DATA
-  b) RX-DATA -> TX-ACK
-  c) TX-DATA -> RX-ACK
-
-13. The hidden terminal problem can occur at 12b), i.e. NodeA transmits that 
-is received by NodeB but not heard by NodeC, which starts to transmit before 
-NodeB could send an acknowledgment. 
-
-14. with dedicated receive start calls, 
-   a) we could set the channel there, 
-   b) would have no problem with unexpected receives
-   c) could set a timeout parameter
-   d) need cancel command in the asynchronous receive interface
-   e) after receive we could go to PLL_ON state, could always download frame
-
-15. async send done could return an error code to indicate that something 
-went wrong, for example the CCA did not complete or the channel was busy
-
-16. If we want to cancel the receive process, then it is not clear what to do
-in the BUSY_RX case. We could either go with FORCE_TRX_OFF and then PLL_ON, 
-or do a PLL_ON and wait for the completion of the received message. Therefore
-once we are in the RX_ON state, we cannot guarantee to start TX_ON precisely. 
-We need to verify this.
-
-17. We need to transmit and cancel the listening process because of user 
-input. The listening cancelling is not atomic (we might need to receive 
-messages) and then send acknowledgment etc. Either we are always listening
-(conccurent receive / transmit) or call cancel and wait for receive(ECANCEL).
-
-18. The CC2420 has a receive queue, that needs to be flushed. This mean that 
-we might not able to prevent more than one message to arrive when listening.
-So we are either always on, or need purge functionality to receive all 
-messages from the receive queue.
-
-19. The RF230 does not support promisculous mode, so in general we cannot
-use the hardware TX-ACK feature with the RX_AACK command.
-
-20. With software acknowledgements on the RF230 we cannot reply to a RX-DATA
-with a TX-ACK faster than at least 200 microsec, because we need to download
-the full frame, check the CRC and only then we can send the ACK to avoid
-acking corrupted frames. This means that item 13 is a real problem, and we
-should go with item 11 d). Receiving a data packet while waiting for an ACK
-should fail the previous transmission and send an ack for the incoming frame.
-
-21. We cannot receive a message while a transmission is in progress because
-what would an ack layer do in this case? It cannot send the acknowledgment
-because a send is in progress. So send should return an error_t and while
-a send is in progress no receive is going to be fired.
-
-22. If we use dedicated receive start calls, then an uxpected message can
-arrive (such as when waiting for ACK but getting some DATA), in which case
-the returned message_t pointer might be something else than the one with
-which the receive command was called. So in this case we need to return
-the message with the messageDone event.
-
-23. What do we do with a received DATA packet while waiting for an ACK
-packet? We cannot signal higher layers that we have received it because
-the receive command was not called, so we have to buffer it, which can
-be problematic.
index 113d47cd7030e53747e70d313afa0b0a4a30b055..65459b40c9aab4bdc5bb11712a4a76a129c375e7 100644 (file)
@@ -36,6 +36,7 @@ configuration HplRF230C
 
                interface GpioCapture as IRQ;
                interface Alarm<TRF230, uint16_t> as Alarm;
+               interface LocalTime<TRF230>;
 
                interface HplRF230;
        }
@@ -70,4 +71,12 @@ implementation
 
        components RealMainP;
        RealMainP.PlatformInit -> HplRF230P.PlatformInit;
+
+       components CounterOne16C;
+       components new TransformCounterC(TRF230, uint32_t, TRF230, uint16_t, 0, uint32_t);
+       components new CounterToLocalTimeC(TRF230);
+
+       LocalTime = CounterToLocalTimeC;
+       CounterToLocalTimeC.Counter -> TransformCounterC;
+       TransformCounterC.CounterFrom -> CounterOne16C;
 }