]> oss.titaniummirror.com Git - tinyos-2.x.git/commitdiff
added SpeckMac
authorandreaskoepke <andreaskoepke>
Mon, 1 Oct 2007 15:48:58 +0000 (15:48 +0000)
committerandreaskoepke <andreaskoepke>
Mon, 1 Oct 2007 15:48:58 +0000 (15:48 +0000)
refactor MAC protocols:
- separate duplicate suppression component
- separate LocalTime component

12 files changed:
tos/chips/tda5250/mac/CsmaMacC.nc
tos/chips/tda5250/mac/CsmaMacP.nc
tos/chips/tda5250/mac/Duplicate.h [new file with mode: 0644]
tos/chips/tda5250/mac/Duplicate.nc [new file with mode: 0644]
tos/chips/tda5250/mac/DuplicateC.nc [new file with mode: 0644]
tos/chips/tda5250/mac/DuplicateP.nc [new file with mode: 0644]
tos/chips/tda5250/mac/RedMacC.nc
tos/chips/tda5250/mac/RedMacP.nc
tos/chips/tda5250/mac/SpeckMacDC.nc [new file with mode: 0644]
tos/chips/tda5250/mac/SpeckMacDP.nc [new file with mode: 0644]
tos/platforms/eyesIFX/LocalTimeC.nc [new file with mode: 0644]
tos/platforms/eyesIFX/LocalTimeP.nc [new file with mode: 0644]

index 499f3b78052849986dc8b0689fed22b973a85601..9966cf8b87a71441ba7857d41dfcc1f2cb0df4d6 100644 (file)
@@ -59,6 +59,7 @@ implementation {
       RssiFixedThresholdCMC as Cca,
       new Alarm32khz16C() as Timer,
       new TimerMilliC() as ReRxTimer,
+      DuplicateC,
       RandomLfsrC
 #ifdef MAC_DEBUG
       ,PlatformLedsC
@@ -96,6 +97,8 @@ implementation {
     CsmaMacP.Timer -> Timer;
 
     CsmaMacP.ReRxTimer -> ReRxTimer;
+
+    CsmaMacP.Duplicate -> DuplicateC;
     
 #ifdef MAC_DEBUG
     CsmaMacP.Led0 -> PlatformLedsC.Led0;
index bba168f6c382dee51c4b1fba0c4fe7d509e2d900..46c19d3f00ade28edadea12a44a6d46a3bf95847 100644 (file)
@@ -71,6 +71,7 @@ module CsmaMacP {
         interface Random;
 
         interface Timer<TMilli> as ReRxTimer;
+        interface Duplicate;
         
         interface Alarm<T32khz, uint16_t> as Timer;
         async command am_addr_t amAddress();
@@ -106,9 +107,7 @@ implementation
         MIN_PREAMBLE_BYTES=2,
         TOKEN_ACK_FLAG = 64,
         TOKEN_ACK_MASK = 0x3f,
-        INVALID_SNR = 0xffff,
-        MSG_TABLE_ENTRIES=16,
-        MAX_AGE=0xff
+        INVALID_SNR = 0xffff
     };
     
 /**************** Module Global Variables  *****************/
@@ -154,24 +153,8 @@ implementation
     
     uint16_t restLaufzeit;
 
-    /* duplicate suppression */
-    typedef struct knownMessage_t {
-        am_addr_t src;
-        uint8_t token;
-        uint8_t age;
-    } knownMessage_t;
+    uint16_t rssiValue = 0;
     
-    knownMessage_t knownMsgTable[MSG_TABLE_ENTRIES];
-
-    task void ageMsgsTask() {
-        unsigned i;
-        atomic {
-            for(i = 0; i < MSG_TABLE_ENTRIES; i++) {
-                if(knownMsgTable[i].age < MAX_AGE) ++knownMsgTable[i].age;
-            }
-        }
-    }
-
     /****** debug vars & defs & functions  ***********************/
 #ifdef MACM_DEBUG
 #define HISTORY_ENTRIES 100
@@ -274,6 +257,7 @@ implementation
     }
     
     void setRxMode() {
+        rssiValue = INVALID_SNR;
         if(call RadioModes.RxMode() == FAIL) {
             post SetRxModeTask();
         }
@@ -336,7 +320,21 @@ implementation
             setFlag(&flags, RESUME_BACKOFF);
         }
     }
-    
+
+    void storeStrength(message_t *m) {
+        if(rssiValue != INVALID_SNR) {
+            (getMetadata(m))->strength = rssiValue;
+        }
+        else {
+            if(call RssiAdcResource.isOwner()) {
+                (getMetadata(m))->strength = call ChannelMonitorData.readSnr();
+            }
+            else {
+                (getMetadata(m))->strength = 1;
+            }
+        }
+    }
+
     void signalSendDone(error_t error) {
         message_t *m;
         error_t e = error;
@@ -349,6 +347,7 @@ implementation
             if(isFlagSet(&flags, CANCEL_SEND)) {
                 e = ECANCEL;
             }
+            storeStrength(m);
             clearFlag(&flags, CANCEL_SEND);
         }
         signal MacSend.sendDone(m, e);
@@ -386,36 +385,11 @@ implementation
     }
 
     bool isNewMsg(message_t* msg) {
-        uint8_t i;
-        for(i=0; i < MSG_TABLE_ENTRIES; i++) {
-            if((getHeader(msg)->src == knownMsgTable[i].src) &&
-               (((getHeader(msg)->token) & TOKEN_ACK_MASK) == knownMsgTable[i].token) &&
-               (knownMsgTable[i].age < MAX_AGE)) {
-                knownMsgTable[i].age = 0;
-                return FALSE;
-            }
-        }
-        return TRUE;
-    }
-
-    unsigned findOldest() {
-        unsigned i;
-        unsigned oldIndex = 0;
-        unsigned age = knownMsgTable[oldIndex].age;
-        for(i = 1; i < MSG_TABLE_ENTRIES; i++) {
-            if(age < knownMsgTable[i].age) {
-                oldIndex = i;
-                age = knownMsgTable[i].age;
-            }
-        }
-        return oldIndex;
+        return call Duplicate.isNew(getHeader(msg)->src, (getHeader(msg)->token) & TOKEN_ACK_MASK);
     }
     
     void rememberMsg(message_t* msg) {
-        unsigned oldest = findOldest();
-        knownMsgTable[oldest].src = getHeader(msg)->src;
-        knownMsgTable[oldest].token = (getHeader(msg)->token) & TOKEN_ACK_MASK;
-        knownMsgTable[oldest].age = 0;
+        call Duplicate.remember(getHeader(msg)->src, (getHeader(msg)->token) & TOKEN_ACK_MASK);
     }
     
     void checkSend() {
@@ -483,7 +457,6 @@ implementation
     /**************** Init ************************/
     
     command error_t Init.init(){
-        unsigned i;
         atomic {
             txBufPtr = NULL;
             macState = INIT;
@@ -491,9 +464,6 @@ implementation
             shortRetryCounter = 0;
             longRetryCounter = 0;
             flags = 0;
-            for(i = 0; i < MSG_TABLE_ENTRIES; i++) {
-                knownMsgTable[i].age = MAX_AGE;
-            }
 #ifdef MACM_DEBUG
             histIndex = 0;
 #endif
@@ -687,19 +657,18 @@ implementation
     
     /****** PacketSerializer events **********************/
     async event void PacketReceive.receiveDetected() {
+        rssiValue = INVALID_SNR;
         if(macState <= RX_ACK) {
             storeOldState(60);
             interruptBackoffTimer();
             if(macState == CCA) computeBackoff();
         }
         if(macState <= RX) {
-          post ReleaseAdcTask();  
-          storeOldState(61);
+            storeOldState(61);
             macState = RX_P;
             signalMacState();
         }
         else if(macState <= RX_ACK) {
-            post ReleaseAdcTask();
             storeOldState(62);
             macState = RX_ACK_P;
             signalMacState();
@@ -720,12 +689,11 @@ implementation
         macState_t action = RX;
         if(macState == RX_P) {
             if(error == SUCCESS) {
-                post ageMsgsTask();
                 storeOldState(82);
                 isCnt = isControl(msg);
                 if(msgIsForMe(msg)) {
                     if(!isCnt) {
-                        (getMetadata(m))->strength = 10;
+                        storeStrength(msg);
                         if(isNewMsg(m)) {
                             m = signal MacReceive.receiveDone(msg);
                             rememberMsg(m);   
@@ -753,7 +721,6 @@ implementation
             if(error == SUCCESS) {
                 if(ackIsForMe(msg)) {
                     storeOldState(92);
-                    (getMetadata(txBufPtr))->strength = 10;
                     (getMetadata(txBufPtr))->ack = WAS_ACKED;
                     signalSendDone(SUCCESS);
                 }
@@ -956,6 +923,8 @@ implementation
     /***** ChannelMonitorData events ******************/
     
     async event void ChannelMonitorData.getSnrDone(int16_t data) {
+        atomic if((macState == RX_P) || (macState == RX_ACK_P)) rssiValue = data;
+        post ReleaseAdcTask();  
     }
     
     /***** unused Radio Modes events **************************/
@@ -982,6 +951,7 @@ implementation
     
     /***** abused TimeStamping events **************************/
     async event void RadioTimeStamping.receivedSFD( uint16_t time ) {
+        if(call RssiAdcResource.isOwner()) call ChannelMonitorData.getSnr();
         if(macState == RX_P) call ChannelMonitor.rxSuccess();
     }
     
diff --git a/tos/chips/tda5250/mac/Duplicate.h b/tos/chips/tda5250/mac/Duplicate.h
new file mode 100644 (file)
index 0000000..00c853d
--- /dev/null
@@ -0,0 +1,49 @@
+/* -*- mode:c++; indent-tabs-mode: nil -*-
+ * Copyright (c) 2007, Technische Universitaet Berlin
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * - Redistributions of source code must retain the above copyright notice,
+ *   this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright
+ *   notice, this list of conditions and the following disclaimer in the
+ *   documentation and/or other materials provided with the distribution.
+ * - Neither the name of the Technische Universitaet Berlin nor the names
+ *   of its contributors may be used to endorse or promote products derived
+ *   from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+ * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES {} LOSS OF USE, DATA,
+ * OR PROFITS {} OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
+ * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+/**
+ * constants and definitions for duplicate detector
+ * @author: Andreas Koepke (koepke@tkn.tu-berlin.de)
+ */
+
+#ifndef DUPLICATE_H
+#define DUPLICATE_H
+
+typedef struct known_t {
+    am_addr_t src;
+    uint8_t seqno;
+    uint8_t age;
+} known_t;
+
+enum {
+    TABLE_ENTRIES=16,
+    MAX_AGE=0xff,
+    AGE_INTERVALL = 1024, // every second increase the age of the messages
+};
+
+#endif
diff --git a/tos/chips/tda5250/mac/Duplicate.nc b/tos/chips/tda5250/mac/Duplicate.nc
new file mode 100644 (file)
index 0000000..2b3a19c
--- /dev/null
@@ -0,0 +1,43 @@
+/* -*- mode:c++; indent-tabs-mode: nil -*-
+ * Copyright (c) 2007, Technische Universitaet Berlin
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * - Redistributions of source code must retain the above copyright notice,
+ *   this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright
+ *   notice, this list of conditions and the following disclaimer in the
+ *   documentation and/or other materials provided with the distribution.
+ * - Neither the name of the Technische Universitaet Berlin nor the names
+ *   of its contributors may be used to endorse or promote products derived
+ *   from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+ * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
+ * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
+ * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+/**
+ * Keep information for the MAC protocols to suppress duplicates.
+ * @author Andreas Koepke (koepke at tkn.tu-berlin.de)
+ */
+
+interface Duplicate {
+    /** check whether this message is a new message, does not store anything */
+    async command bool isNew(am_addr_t src, uint8_t seqno);
+
+    /** remember the fingerprint of this message, stores/updates the information */
+    async command void remember(am_addr_t src, uint8_t seqno);
+}
+
diff --git a/tos/chips/tda5250/mac/DuplicateC.nc b/tos/chips/tda5250/mac/DuplicateC.nc
new file mode 100644 (file)
index 0000000..b57c166
--- /dev/null
@@ -0,0 +1,50 @@
+/* -*- mode:c++; indent-tabs-mode:nil -*- 
+ * Copyright (c) 2007, Technische Universitaet Berlin
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without 
+ * modification, are permitted provided that the following conditions 
+ * are met:
+ * - Redistributions of source code must retain the above copyright notice,
+ *   this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright 
+ *   notice, this list of conditions and the following disclaimer in the 
+ *   documentation and/or other materials provided with the distribution.
+ * - Neither the name of the Technische Universitaet Berlin nor the names 
+ *   of its contributors may be used to endorse or promote products derived
+ *   from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED 
+ * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, 
+ * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY 
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE 
+ * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+/**
+ * Helper component for MAC protocols to suppress duplicates
+ * To do: turn it into a generic?
+ * @author: Andreas Koepke (koepke@tkn.tu-berlin.de)
+ */
+
+#include "Duplicate.h"
+
+configuration DuplicateC {
+  provides {
+      interface Duplicate;
+  }
+}
+implementation {
+    components MainC;
+    components new TimerMilliC() as Timer;
+    components DuplicateP;
+
+    Duplicate = DuplicateP;
+    DuplicateP.Timer -> Timer;        // make information soft state
+    MainC.SoftwareInit -> DuplicateP; 
+}
diff --git a/tos/chips/tda5250/mac/DuplicateP.nc b/tos/chips/tda5250/mac/DuplicateP.nc
new file mode 100644 (file)
index 0000000..b07b568
--- /dev/null
@@ -0,0 +1,109 @@
+/* -*- mode:c++; indent-tabs-mode:nil -*- 
+ * Copyright (c) 2007, Technische Universitaet Berlin
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without 
+ * modification, are permitted provided that the following conditions 
+ * are met:
+ * - Redistributions of source code must retain the above copyright notice,
+ *   this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright 
+ *   notice, this list of conditions and the following disclaimer in the 
+ *   documentation and/or other materials provided with the distribution.
+ * - Neither the name of the Technische Universitaet Berlin nor the names 
+ *   of its contributors may be used to endorse or promote products derived
+ *   from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED 
+ * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, 
+ * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY 
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE 
+ * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+/**
+ * Helper component for MAC protocols to suppress duplicates
+ * To do: turn it into a generic?
+ * @author: Andreas Koepke (koepke@tkn.tu-berlin.de)
+ */
+
+module DuplicateP {
+  provides {
+      interface Duplicate;
+      interface Init;
+  }
+  uses {
+      interface Timer<TMilli> as Timer;
+  }
+}
+implementation {    
+    known_t knownTable[TABLE_ENTRIES];
+
+    /** helper functions */
+    task void ageMsgsTask() {
+        unsigned i;
+        for(i = 0; i < TABLE_ENTRIES; i++) {
+            atomic {
+                if(knownTable[i].age < MAX_AGE) ++knownTable[i].age;
+            }
+        }
+    }
+    
+    unsigned findOldest() {
+        unsigned i;
+        unsigned oldIndex = 0;
+        unsigned age = knownTable[oldIndex].age;
+        for(i = 1; i < TABLE_ENTRIES; i++) {
+            if(age < knownTable[i].age) {
+                oldIndex = i;
+                age = knownTable[i].age;
+            }
+        }
+        return oldIndex;
+    }
+
+    /*** duplicate interface */
+    async command bool Duplicate.isNew(am_addr_t src, uint8_t seqno) {
+        bool rVal = TRUE;
+        unsigned i;
+        for(i=0; i < TABLE_ENTRIES; i++) {
+            if((knownTable[i].age < MAX_AGE) &&
+               (src == knownTable[i].src) &&
+               (seqno == knownTable[i].seqno)) {
+                knownTable[i].age = 0;
+                rVal = FALSE;
+                break;
+            }
+        }
+        return rVal;
+    }
+    
+    async command void Duplicate.remember(am_addr_t src, uint8_t seqno) {
+        unsigned oldest = findOldest();
+        knownTable[oldest].src = src;
+        knownTable[oldest].seqno = seqno;
+        knownTable[oldest].age = 0;
+    }
+
+    /** helper interfaces */
+    event void Timer.fired() {
+        post ageMsgsTask();
+    }
+
+    command error_t Init.init(){
+        uint8_t i;
+        for(i = 0; i < TABLE_ENTRIES; i++) {
+            atomic {
+                    knownTable[i].age = MAX_AGE;
+            }
+        }
+        call Timer.startPeriodic(AGE_INTERVALL);
+        return SUCCESS;
+    }
+}
+
index 469fe5ce431e612f256471973fd93b5d3b44cff0..3421fe920cc7c9bf1e8fc1082b8cb325223649d4 100644 (file)
@@ -45,7 +45,6 @@ configuration RedMacC {
     interface MacSend;
     interface MacReceive;
     interface Packet;
-    interface LocalTime<T32khz> as LocalTime;
     interface Sleeptime;
     interface ChannelCongestion;
   }
@@ -64,8 +63,7 @@ implementation {
         RssiFixedThresholdCMC as Cca,
         new Alarm32khz16C() as Timer,
         new Alarm32khz16C() as SampleTimer,
-        RandomLfsrC,
-        Counter32khz16C as Counter;
+        RandomLfsrC, LocalTimeC, DuplicateC;
     
     components ActiveMessageAddressC;
     RedMacP.amAddress -> ActiveMessageAddressC;
@@ -78,7 +76,6 @@ implementation {
     Tda5250Control = RedMacP;
     UartPhyControl = RedMacP;
     RadioTimeStamping = RedMacP;
-    LocalTime = RedMacP;
     ChannelCongestion = RedMacP;
     
     RedMacP = PacketSend;
@@ -98,7 +95,9 @@ implementation {
 
     RedMacP.Timer -> Timer;
     RedMacP.SampleTimer -> SampleTimer;
-    RedMacP.Counter32khz16 -> Counter;
+    RedMacP.LocalTime32kHz -> LocalTimeC;
+
+    RedMacP.Duplicate -> DuplicateC;
     
 /*    components PlatformLedsC;
     RedMacP.Led0 -> PlatformLedsC.Led0;
index 5ea29ebe7fc0b0c57216910f974454944dc40b80..41739aa300136fbeb28e6e7e8bd67967c4d7fb5f 100644 (file)
@@ -46,7 +46,6 @@ module RedMacP {
         interface MacSend;
         interface MacReceive;
         interface Packet;
-        interface LocalTime<T32khz> as LocalTime32khz;
         interface Sleeptime;
         interface Teamgeist;
         interface ChannelCongestion;
@@ -72,7 +71,10 @@ module RedMacP {
         
         interface Alarm<T32khz, uint16_t> as Timer;
         interface Alarm<T32khz, uint16_t> as SampleTimer;
-        interface Counter<T32khz,uint16_t> as Counter32khz16;
+        interface LocalTime<T32khz> as LocalTime32kHz;
+
+        interface Duplicate;
+        
         async command am_addr_t amAddress();
 /*
         interface GeneralIO as Led0;
@@ -137,8 +139,8 @@ implementation
         // DEFAULT_SLEEP_TIME=3250,
         // DEFAULT_SLEEP_TIME=6500,
         // DEFAULT_SLEEP_TIME=8192,
-        DEFAULT_SLEEP_TIME=16384,
-        // DEFAULT_SLEEP_TIME=32768U,
+        // DEFAULT_SLEEP_TIME=16384,
+        DEFAULT_SLEEP_TIME=32768U,
         // DEFAULT_SLEEP_TIME=65535U,
         DATA_DETECT_TIME=17,
         RX_SETUP_TIME=102,    // time to set up receiver
@@ -150,8 +152,6 @@ implementation
         ACK_DURATION = SUB_HEADER_TIME + SUB_FOOTER_TIME,
         MAX_SHORT_RETRY=9,
         MAX_LONG_RETRY=3,
-        MAX_AGE=0xff,
-        MSG_TABLE_ENTRIES=16,
         TOKEN_ACK_FLAG = 64,
         TOKEN_ACK_MASK = 0x3f,
         INVALID_SNR = 0xffff,
@@ -162,15 +162,6 @@ implementation
     };
     
     /**************** Module Global Variables  *****************/
-    typedef union 
-    {
-        uint32_t op;
-        struct {
-            uint16_t lo;
-            uint16_t hi;
-        };
-    } ui32parts_t;
-    
     /* flags */
     typedef enum {
         SWITCHING = 1,
@@ -183,14 +174,6 @@ implementation
         TEAMGEIST_ACTIVE=128
     } flags_t;
 
-        /* duplicate suppression */
-    typedef struct knownMessage_t {
-        am_addr_t src;
-        uint8_t token;
-        uint8_t age;
-    } knownMessage_t;
-    
-    knownMessage_t knownMsgTable[MSG_TABLE_ENTRIES];
     uint8_t flags = 0;
     uint8_t checkCounter = 0;
     uint8_t shortRetryCounter = 0;
@@ -199,8 +182,7 @@ implementation
     uint16_t localSleeptime = DEFAULT_SLEEP_TIME;
     uint16_t rssiValue = 0;
     uint32_t restLaufzeit = 0;
-
-    uint16_t counter2sec = 127;
+    
     uint32_t rxTime = 0;
 
     am_id_t teamgeistType = 0;
@@ -215,23 +197,6 @@ implementation
 
     uint16_t MIN_BACKOFF_MASK;
 
-#ifdef REDMAC_DEBUG
-    uint8_t dupOldest;
-    task void dumpLast() {
-        knownMessage_t mem;
-        unsigned i;
-        atomic {
-            i = dupOldest;
-            mem = knownMsgTable[i];
-        }
-        sdDebug(5000);
-        sdDebug(i);
-        sdDebug(mem.src);
-        sdDebug(mem.token);
-        sdDebug(mem.age);
-    }
-#endif
-    
     /****** Secure switching of radio modes ***/
     void interruptBackoffTimer();
     
@@ -319,16 +284,7 @@ implementation
         }
     }
 
-    /**************** Helper functions ************************/
-    task void ageMsgsTask() {
-        unsigned i;
-        atomic {
-            for(i = 0; i < MSG_TABLE_ENTRIES; i++) {
-                if(knownMsgTable[i].age < MAX_AGE) ++knownMsgTable[i].age;
-            }
-        }
-    }
-    
+    /**************** Helper functions ************************/    
     void computeBackoff();
     
     void checkSend() {
@@ -402,7 +358,7 @@ implementation
             sT = networkSleeptime;
         }
         if(msg == NULL) return;
-        macHdr = (red_mac_header_t *)call SubPacket.getPayload(msg, NULL);
+        macHdr = (red_mac_header_t *)call SubPacket.getPayload(msg, sizeof(red_mac_header_t) + length);
         macHdr->repetitionCounter = sT/(length * BYTE_TIME + SUB_HEADER_TIME + SUB_FOOTER_TIME + 
                                         TX_GAP_TIME) + 1;
         atomic {
@@ -435,6 +391,20 @@ implementation
         }
     }
 
+    void storeStrength(message_t *m) {
+        if(rssiValue != INVALID_SNR) {
+            (getMetadata(txBufPtr))->strength = rssiValue;
+        }
+        else {
+            if(call RssiAdcResource.isOwner()) {
+                (getMetadata(txBufPtr))->strength = call ChannelMonitorData.readSnr();
+            }
+            else {
+                (getMetadata(txBufPtr))->strength = 1;
+            }
+        }
+    }
+
     bool prepareRepetition() {
         bool repeat;
         atomic {
@@ -448,7 +418,7 @@ implementation
         }
         return repeat;
     }
-
+    
     void signalSendDone(error_t error) {
         message_t *m;
         error_t e = error;
@@ -464,12 +434,7 @@ implementation
 #endif
             longRetryCounter = 0;
             shortRetryCounter = 0;
-            if(rssiValue != INVALID_SNR) {
-                (getMetadata(m))->strength = rssiValue;
-            }
-            else {
-                (getMetadata(m))->strength = call ChannelMonitorData.readSnr();
-            }
+            storeStrength(m);
             if(isFlagSet(&flags, CANCEL_SEND)) {
                 e = ECANCEL;
             }
@@ -559,42 +524,11 @@ implementation
     }
     
     bool isNewMsg(message_t* msg) {
-        bool rVal = TRUE;
-        uint8_t i;
-        for(i=0; i < MSG_TABLE_ENTRIES; i++) {
-            if((knownMsgTable[i].age < MAX_AGE) &&
-               (getHeader(msg)->src == knownMsgTable[i].src) &&
-               (((getHeader(msg)->token) & TOKEN_ACK_MASK) == knownMsgTable[i].token)) {
-                knownMsgTable[i].age = 0;
-                rVal = FALSE;
-                break;
-            }
-        }
-        return rVal;
-    }
-
-    unsigned findOldest() {
-        unsigned i;
-        unsigned oldIndex = 0;
-        unsigned age = knownMsgTable[oldIndex].age;
-        for(i = 1; i < MSG_TABLE_ENTRIES; i++) {
-            if(age < knownMsgTable[i].age) {
-                oldIndex = i;
-                age = knownMsgTable[i].age;
-            }
-        }
-        return oldIndex;
-    }
+        return call Duplicate.isNew(getHeader(msg)->src, (getHeader(msg)->token) & TOKEN_ACK_MASK);
+   }
 
     void rememberMsg(message_t* msg) {
-        unsigned oldest = findOldest();
-        knownMsgTable[oldest].src = getHeader(msg)->src;
-        knownMsgTable[oldest].token = (getHeader(msg)->token) & TOKEN_ACK_MASK;
-        knownMsgTable[oldest].age = 0;
-#ifdef REDMAC_DEBUG
-        dupOldest = oldest;
-        post dumpLast();
-#endif
+        call Duplicate.remember(getHeader(msg)->src, (getHeader(msg)->token) & TOKEN_ACK_MASK);
     }
 
     void prepareAck(message_t* msg) {
@@ -605,24 +539,20 @@ implementation
         getHeader(&ackMsg)->dest = getHeader(msg)->src;
         getHeader(&ackMsg)->type = getHeader(msg)->type;
 #ifdef REDMAC_DEBUG
-        repCounter = ((red_mac_header_t *)call SubPacket.getPayload(msg, NULL))->repetitionCounter;
+        repCounter = ((red_mac_header_t *)
+                      call SubPacket.getPayload(msg, sizeof(red_mac_header_t)))->repetitionCounter;
 #endif
     }
     
     uint32_t calcGeneratedTime(red_mac_header_t *m) {
         return rxTime - m->time - TIME_CORRECTION;
     }
-    
     /**************** Init ************************/
     
     command error_t Init.init(){
-        uint8_t i;
         atomic {
             macState = INIT;
             seqNo = call Random.rand16() % TOKEN_ACK_FLAG;
-            for(i = 0; i < MSG_TABLE_ENTRIES; i++) {
-                knownMsgTable[i].age = MAX_AGE;
-            }
             for(MIN_BACKOFF_MASK = 1; MIN_BACKOFF_MASK < networkSleeptime; ) {
                 MIN_BACKOFF_MASK = (MIN_BACKOFF_MASK << 1) + 1;
             }
@@ -698,11 +628,8 @@ implementation
         return call SubPacket.maxPayloadLength() - sizeof(red_mac_header_t);
     }
     
-    command void* Packet.getPayload(message_t* msg, uint8_t* len) {
-        nx_uint8_t *payload = (nx_uint8_t *)call SubPacket.getPayload(msg, len);
-        if (len != NULL) {
-            *len -= sizeof(red_mac_header_t);
-        }
+    command void* Packet.getPayload(message_t* msg, uint8_t len) {
+        nx_uint8_t *payload = (nx_uint8_t *)call SubPacket.getPayload(msg, len + sizeof(red_mac_header_t));
         return (void*)(payload + sizeof(red_mac_header_t));
     }
     
@@ -828,7 +755,7 @@ implementation
                 if(seqNo >= TOKEN_ACK_FLAG) seqNo = 1;
 #ifdef REDMAC_PERFORMANCE
                 txStat.payloadLength = txLen;
-                txStat.interfaceTime = call LocalTime32khz.get();
+                txStat.interfaceTime = call LocalTime32kHz.get();
 #endif
             }
             else {
@@ -907,7 +834,6 @@ implementation
         if(macState == RX_P) {
             // sdDebug(191);
             if(error == SUCCESS) {
-                post ageMsgsTask();
                 // sdDebug(192);
                 isCnt = isControl(msg);
                 if(msgIsForMe(msg)) {
@@ -918,17 +844,7 @@ implementation
                             rxStat.duplicate = PERF_NEW_MSG;
 #endif
                             // sdDebug(194);
-                            if(rssiValue != INVALID_SNR) {
-                                (getMetadata(m))->strength = rssiValue;
-                            }
-                            else {
-                                if(call RssiAdcResource.isOwner()) {
-                                    (getMetadata(m))->strength = call ChannelMonitorData.readSnr();
-                                }
-                                else {
-                                    (getMetadata(m))->strength = 1;
-                                }
-                            }
+                            storeStrength(msg);
                             getMetadata(msg)->time = calcGeneratedTime((red_mac_header_t*) payload);
                             getMetadata(msg)->ack = WAS_NOT_ACKED;
                             m = signal MacReceive.receiveDone(msg);
@@ -989,17 +905,6 @@ implementation
             if(error == SUCCESS) {
                 if(ackIsForMe(msg)) {
                     // sdDebug(202);
-                    if(rssiValue != INVALID_SNR) {
-                        (getMetadata(txBufPtr))->strength = rssiValue;
-                    }
-                    else {
-                        if(call RssiAdcResource.isOwner()) {
-                            (getMetadata(txBufPtr))->strength = call ChannelMonitorData.readSnr();
-                        }
-                        else {
-                            (getMetadata(txBufPtr))->strength = 1;
-                        }
-                    }
                     getMetadata(txBufPtr)->ack = WAS_ACKED;
                     getMetadata(txBufPtr)->repetitions = txMacHdr->repetitionCounter;
                     if(isFlagSet(&flags, TEAMGEIST_ACTIVE) &&
@@ -1112,7 +1017,7 @@ implementation
     async event void RadioTimeStamping.receivedSFD( uint16_t time ) {
         if(call RssiAdcResource.isOwner()) call ChannelMonitorData.getSnr();
         if(macState == RX_P) {
-            rxTime = call LocalTime32khz.get();
+            rxTime = call LocalTime32kHz.get();
             call ChannelMonitor.rxSuccess();
         }
     }
@@ -1121,7 +1026,7 @@ implementation
         uint32_t now;
         uint32_t mTime;
         if((macState == TX) && (p_msg == txBufPtr)) {
-            now = call LocalTime32khz.get();
+            now = call LocalTime32kHz.get();
             mTime = getMetadata(p_msg)->time;
             if(now >= mTime) {
                 txMacHdr->time = now - mTime;
@@ -1133,21 +1038,6 @@ implementation
         }
     }
     
-    async command uint32_t LocalTime32khz.get() {
-        ui32parts_t time;
-        atomic {
-            time.lo = call Counter32khz16.get();
-            time.hi = counter2sec;
-            if(call Counter32khz16.isOverflowPending()) ++time.hi;
-        }
-        return time.op;
-    }
-    
-    async event void Counter32khz16.overflow() {
-        ++counter2sec;
-    }
-
-
     /****** Timer ******************************/
 
     void checkOnBusy() {
@@ -1194,7 +1084,7 @@ implementation
                 setTxMode();
 #ifdef REDMAC_PERFORMANCE
                 call Performance.macIdleOnCca();
-                txStat.txModeTime = call LocalTime32khz.get();
+                txStat.txModeTime = call LocalTime32kHz.get();
 #endif
             }
         }
@@ -1294,7 +1184,6 @@ implementation
             setRxMode();
             call Timer.stop();
         }
-        post ageMsgsTask();
     }
 
     /***** Sleeptime **********************************/
diff --git a/tos/chips/tda5250/mac/SpeckMacDC.nc b/tos/chips/tda5250/mac/SpeckMacDC.nc
new file mode 100644 (file)
index 0000000..77b9bc8
--- /dev/null
@@ -0,0 +1,120 @@
+/* -*- mode:c++; indent-tabs-mode:nil -*- 
+ * Copyright (c) 2006, Technische Universitaet Berlin
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without 
+ * modification, are permitted provided that the following conditions 
+ * are met:
+ * - Redistributions of source code must retain the above copyright notice,
+ *   this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright 
+ *   notice, this list of conditions and the following disclaimer in the 
+ *   documentation and/or other materials provided with the distribution.
+ * - Neither the name of the Technische Universitaet Berlin nor the names 
+ *   of its contributors may be used to endorse or promote products derived
+ *   from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED 
+ * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, 
+ * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY 
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE 
+ * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * - Description ---------------------------------------------------------
+ * low power nonpersistent CSMA MAC, rendez-vous via redundantly sent packets
+ * - Author --------------------------------------------------------------
+ * @author: Andreas Koepke (koepke@tkn.tu-berlin.de)
+ * ========================================================================
+ */
+
+// #define SPECKMAC_DEBUG
+
+#ifdef SPECKMAC_PERFORMANCE
+#include <Performance.h>
+#endif
+
+configuration SpeckMacDC {
+  provides {
+    interface SplitControl;
+    interface MacSend;
+    interface MacReceive;
+    interface Packet;
+    interface Sleeptime;
+    interface ChannelCongestion;
+  }
+  uses {
+    interface PhySend as PacketSend;
+    interface PhyReceive as PacketReceive;
+    interface Packet as SubPacket;
+    interface Tda5250Control;  
+    interface UartPhyControl;
+    interface RadioTimeStamping;
+  }
+}
+implementation {
+    components  MainC,
+        SpeckMacDP,
+        RssiFixedThresholdCMC as Cca,
+        new Alarm32khz16C() as Timer,
+        new Alarm32khz16C() as SampleTimer,
+        RandomLfsrC,
+        LocalTimeC, DuplicateC;
+    
+    components ActiveMessageAddressC;
+    SpeckMacDP.amAddress -> ActiveMessageAddressC;
+
+    MainC.SoftwareInit -> SpeckMacDP;
+              
+    SplitControl = SpeckMacDP;
+    MacSend = SpeckMacDP;
+    MacReceive = SpeckMacDP;
+    Tda5250Control = SpeckMacDP;
+    UartPhyControl = SpeckMacDP;
+    RadioTimeStamping = SpeckMacDP;
+
+    ChannelCongestion = SpeckMacDP;
+    
+    SpeckMacDP = PacketSend;
+    SpeckMacDP = PacketReceive;
+    SpeckMacDP = SubPacket;
+    SpeckMacDP = Packet;
+    SpeckMacDP = Sleeptime;
+    
+    SpeckMacDP.CcaStdControl -> Cca.StdControl;
+    SpeckMacDP.ChannelMonitor -> Cca.ChannelMonitor;
+    SpeckMacDP.ChannelMonitorData -> Cca.ChannelMonitorData;
+    SpeckMacDP.ChannelMonitorControl -> Cca.ChannelMonitorControl;
+    SpeckMacDP.RssiAdcResource -> Cca.RssiAdcResource;
+    
+    MainC.SoftwareInit -> RandomLfsrC;
+    SpeckMacDP.Random -> RandomLfsrC;
+
+    SpeckMacDP.Timer -> Timer;
+    SpeckMacDP.SampleTimer -> SampleTimer;
+    SpeckMacDP.LocalTime32kHz -> LocalTimeC;
+
+    SpeckMacDP.Duplicate -> DuplicateC;
+    
+/*    components PlatformLedsC;
+    SpeckMacDP.Led0 -> PlatformLedsC.Led0;
+    SpeckMacDP.Led1 -> PlatformLedsC.Led1;
+    SpeckMacDP.Led2 -> PlatformLedsC.Led2;
+    SpeckMacDP.Led3 -> PlatformLedsC.Led3;
+*/
+#ifdef SPECKMAC_DEBUG
+    components new SerialDebugC() as SD;
+    SpeckMacDP.SerialDebug -> SD;
+#endif
+
+#ifdef SPECKMAC_PERFORMANCE
+    components new PerformanceC() as Perf;
+    SpeckMacDP.Performance -> Perf;
+#endif
+}
+
diff --git a/tos/chips/tda5250/mac/SpeckMacDP.nc b/tos/chips/tda5250/mac/SpeckMacDP.nc
new file mode 100644 (file)
index 0000000..271cdd5
--- /dev/null
@@ -0,0 +1,1229 @@
+/* -*- mode:c++; indent-tabs-mode: nil -*-
+ * Copyright (c) 2006, Technische Universitaet Berlin
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * - Redistributions of source code must retain the above copyright notice,
+ *   this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright
+ *   notice, this list of conditions and the following disclaimer in the
+ *   documentation and/or other materials provided with the distribution.
+ * - Neither the name of the Technische Universitaet Berlin nor the names
+ *   of its contributors may be used to endorse or promote products derived
+ *   from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+ * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
+ * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
+ * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * - Description ---------------------------------------------------------
+ * low power nonpersistent CSMA MAC, rendez-vous via redundantly sent packets
+ * - Author --------------------------------------------------------------
+ * @author: Andreas Koepke (koepke@tkn.tu-berlin.de)
+ * ========================================================================
+ */
+
+
+#include "radiopacketfunctions.h"
+#include "flagfunctions.h"
+#include "PacketAck.h"
+#include "RedMac.h"
+
+module SpeckMacDP {
+    provides {
+        interface Init;
+        interface SplitControl;
+        interface MacSend;
+        interface MacReceive;
+        interface Packet;
+        interface Sleeptime;
+        interface ChannelCongestion;
+    }
+    uses {
+        interface StdControl as CcaStdControl;
+        interface PhySend as PacketSend;
+        interface PhyReceive as PacketReceive;
+        interface RadioTimeStamping;
+
+        interface Tda5250Control as RadioModes;  
+
+        interface UartPhyControl;
+      
+        interface ChannelMonitor;
+        interface ChannelMonitorControl;  
+        interface ChannelMonitorData;
+        interface Resource as RssiAdcResource;
+
+        interface Random;
+
+        interface Packet as SubPacket;
+        
+        interface Alarm<T32khz, uint16_t> as Timer;
+        interface Alarm<T32khz, uint16_t> as SampleTimer;
+        interface LocalTime<T32khz> as LocalTime32kHz;
+
+        interface Duplicate;
+
+        async command am_addr_t amAddress();
+/*
+        interface GeneralIO as Led0;
+        interface GeneralIO as Led1;
+        interface GeneralIO as Led2;
+        interface GeneralIO as Led3;        
+*/  
+#ifdef SPECKMAC_DEBUG
+        interface SerialDebug;
+#endif
+#ifdef SPECKMAC_PERFORMANCE
+        interface Performance;
+#endif
+
+    }
+}
+implementation
+{
+    /****** MAC State machine *********************************/
+    typedef enum {
+        RX,
+        RX_ACK,
+        CCA,
+        CCA_ACK,
+        RX_P,
+        RX_ACK_P,
+        SLEEP,
+        TX,
+        TX_ACK,
+        INIT,
+        STOP
+    } macState_t;
+
+    macState_t macState;
+
+    /****** debug vars & defs & functions  ***********************/
+#ifdef SPECKMAC_DEBUG
+    void sdDebug(uint16_t p) {
+        call SerialDebug.putPlace(p);
+    }
+    uint8_t repCounter;
+#else
+    void sdDebug(uint16_t p) {};
+#endif
+    
+#ifdef SPECKMAC_PERFORMANCE
+    macTxStat_t txStat;
+    macRxStat_t rxStat;
+#endif
+
+    /**************** Module Global Constants  *****************/
+    enum {
+
+        BYTE_TIME=21,                 // byte at 23405 kBit/s, 4b6b encoded
+        PREAMBLE_BYTE_TIME=14,        // byte at 23405 kBit/s, no coding
+        PHY_HEADER_TIME=84,           // 6 Phy Preamble at 23405 bits/s
+        TIME_CORRECTION=16,           // difference between txSFD and rxSFD: 475us
+                
+        SUB_HEADER_TIME=PHY_HEADER_TIME + sizeof(message_header_t)*BYTE_TIME,
+        SUB_FOOTER_TIME=2*BYTE_TIME, // 2 bytes crc 
+        // DEFAULT_SLEEP_TIME=1625,
+        // DEFAULT_SLEEP_TIME=3250,
+        // DEFAULT_SLEEP_TIME=6500,
+        // DEFAULT_SLEEP_TIME=8192,
+        // DEFAULT_SLEEP_TIME=16384,
+        DEFAULT_SLEEP_TIME=32768U,
+        // DEFAULT_SLEEP_TIME=65535U,
+        DATA_DETECT_TIME=17,
+        RX_SETUP_TIME=102,    // time to set up receiver
+        TX_SETUP_TIME=58,     // time to set up transmitter
+        ADDED_DELAY = 30,
+        RX_ACK_TIMEOUT = RX_SETUP_TIME + PHY_HEADER_TIME + ADDED_DELAY + 30,
+        TX_GAP_TIME = RX_ACK_TIMEOUT + TX_SETUP_TIME + 33,
+        // the duration of a send ACK
+        ACK_DURATION = SUB_HEADER_TIME + SUB_FOOTER_TIME,
+        MAX_SHORT_RETRY=9,
+        MAX_LONG_RETRY=3,
+        TOKEN_ACK_FLAG = 64,
+        TOKEN_ACK_MASK = 0x3f,
+        INVALID_SNR = 0xffff,
+        // PREAMBLE_LONG = 5,
+        // PREAMBLE_SHORT = 2,
+        // reduced minimal backoff
+        ZERO_BACKOFF_MASK = 0xff
+    };
+    
+    /**************** Module Global Variables  *****************/
+    typedef union 
+    {
+        uint32_t op;
+        struct {
+            uint16_t lo;
+            uint16_t hi;
+        };
+    } ui32parts_t;
+    
+    /* flags */
+    typedef enum {
+        SWITCHING = 1,
+        RSSI_STABLE = 2,
+        UNHANDLED_PACKET = 4,
+        MESSAGE_PREPARED = 8,
+        RESUME_BACKOFF = 16,
+        CANCEL_SEND = 32,
+        ACTION_DETECTED = 64,
+    } flags_t;
+
+    uint8_t flags = 0;
+    uint8_t checkCounter = 0;
+    uint8_t shortRetryCounter = 0;
+    uint8_t longRetryCounter = 0;
+    uint16_t networkSleeptime = DEFAULT_SLEEP_TIME;
+    uint16_t localSleeptime = DEFAULT_SLEEP_TIME;
+    uint16_t rssiValue = 0;
+    uint32_t restLaufzeit = 0;
+    
+    uint32_t rxTime = 0;
+
+    uint8_t congestionLevel = 0;
+    
+    message_t *txBufPtr = NULL;
+    uint16_t txLen = 0;
+    red_mac_header_t *txMacHdr = NULL;
+    uint16_t seqNo;
+    message_t ackMsg;
+
+    uint16_t MIN_BACKOFF_MASK;
+    
+    /****** Secure switching of radio modes ***/
+    void interruptBackoffTimer();
+    
+    task void SetRxModeTask();
+    task void SetTxModeTask();
+    task void SetSleepModeTask();
+
+    task void ReleaseAdcTask() {
+        bool release = FALSE;
+        atomic {
+            if((macState >= SLEEP) &&  call RssiAdcResource.isOwner())  {
+                release = TRUE;
+            }
+        }
+        if(release) call RssiAdcResource.release(); 
+    }
+
+    void requestAdc() {
+        if(!call RssiAdcResource.isOwner()) {
+            call RssiAdcResource.immediateRequest();
+        }
+    }
+
+    void setRxMode() {
+        setFlag(&flags, SWITCHING);
+        clearFlag(&flags, RSSI_STABLE);
+        // sdDebug(10);
+        checkCounter = 0;
+        rssiValue = INVALID_SNR;
+        if(call RadioModes.RxMode() == FAIL) {
+            post SetRxModeTask();
+        }
+        else {
+#ifdef SPECKMAC_PERFORMANCE
+            call Performance.macRxMode();
+#endif
+        }
+        requestAdc();
+    }
+    
+    task void SetRxModeTask() {
+        atomic {
+            if(isFlagSet(&flags, SWITCHING) && ((macState <= CCA) || (macState == INIT))) setRxMode();
+        }
+    }
+
+    void setSleepMode() {
+        // sdDebug(20);
+        clearFlag(&flags, RSSI_STABLE);
+        post ReleaseAdcTask();
+        setFlag(&flags, SWITCHING);
+        if(call RadioModes.SleepMode() == FAIL) {
+            post SetSleepModeTask();
+        }
+        else {
+#ifdef SPECKMAC_PERFORMANCE
+            call Performance.macSleepMode();
+#endif
+        }
+    }
+    
+    task void SetSleepModeTask() {
+        atomic if(isFlagSet(&flags, SWITCHING) && ((macState == SLEEP) || (macState == STOP))) setSleepMode();
+    }
+
+
+    void setTxMode() {
+        post ReleaseAdcTask();
+        // sdDebug(30);
+        clearFlag(&flags, RSSI_STABLE);
+        setFlag(&flags, SWITCHING);
+        if(call RadioModes.TxMode() == FAIL) {
+            post SetTxModeTask();
+        }
+        else {
+#ifdef SPECKMAC_PERFORMANCE
+            call Performance.macTxMode();
+#endif
+        }
+    }
+
+    task void SetTxModeTask() {
+        atomic {
+            if(isFlagSet(&flags, SWITCHING) && ((macState == TX) || (macState == TX_ACK))) setTxMode();
+        }
+    }
+
+    /**************** Helper functions ************************/
+    void computeBackoff();
+    
+    void checkSend() {
+        if((shortRetryCounter) && (txBufPtr != NULL) && (isFlagSet(&flags, MESSAGE_PREPARED)) && 
+           (macState == SLEEP) && (!isFlagSet(&flags, RESUME_BACKOFF)) && (!call Timer.isRunning())) {
+            // sdDebug(40);
+            macState = CCA;
+            checkCounter = 0;
+            setRxMode();
+        }
+/*        else {
+            if(txBufPtr) // sdDebug(41);
+            if(shortRetryCounter) // sdDebug(42);
+            if(isFlagSet(&flags, MESSAGE_PREPARED)) // sdDebug(43);
+            if(txBufPtr) {
+                if(macState == SLEEP) // sdDebug(44);
+                if(!isFlagSet(&flags, RESUME_BACKOFF)) // sdDebug(45);
+                if(!call Timer.isRunning()) // sdDebug(46);
+            }
+        }
+*/
+    }
+
+    uint32_t backoff(uint8_t counter) {
+        uint32_t rVal = call Random.rand16() &  MIN_BACKOFF_MASK;
+        return (rVal << counter) + ZERO_BACKOFF_MASK;
+    }
+    
+    bool needsAckTx(message_t* msg) {
+        bool rVal = FALSE;
+        if(getHeader(msg)->dest < AM_BROADCAST_ADDR) {
+            if(getMetadata(msg)->ack != NO_ACK_REQUESTED) {
+                rVal = TRUE;
+            }
+        }
+        return rVal;
+    }
+    
+    bool needsAckRx(message_t* msg) {
+        bool rVal = FALSE;
+        am_addr_t dest = getHeader(msg)->dest;
+        uint8_t token;
+        if(dest < AM_BROADCAST_ADDR) {
+            token = getHeader(msg)->token;
+            if(isFlagSet(&token, ACK_REQUESTED)) {
+                rVal = TRUE;
+            }
+        }
+        return rVal;
+    }
+
+    task void PrepareMsgTask() {
+        message_t *msg;
+        uint8_t length;
+        red_mac_header_t *macHdr;
+        uint16_t sT;
+        atomic {
+            msg = txBufPtr;
+            length = txLen;
+            sT = networkSleeptime;
+        }
+        if(msg == NULL) return;
+        macHdr = (red_mac_header_t *)call SubPacket.getPayload(msg, sizeof(red_mac_header_t) + length);
+        macHdr->repetitionCounter = sT/(length * BYTE_TIME + SUB_HEADER_TIME + SUB_FOOTER_TIME) + 1;
+        atomic {
+            getHeader(msg)->token = seqNo;
+            if(needsAckTx(msg)) getHeader(msg)->token |= ACK_REQUESTED;
+            txMacHdr = macHdr;
+            setFlag(&flags, MESSAGE_PREPARED);
+            if((macState == SLEEP) && (!call Timer.isRunning()) && (!isFlagSet(&flags, RESUME_BACKOFF))) {
+                if((longRetryCounter == 1) &&
+                   (getHeader(msg)->dest != AM_BROADCAST_ADDR)) {
+                    call Timer.start((call Random.rand16() >> 3) & ZERO_BACKOFF_MASK);
+                }
+                else {
+                    call Timer.start(backoff(longRetryCounter));
+                }
+            }
+#ifdef SPECKMAC_PERFORMANCE
+            txStat.type = getHeader(msg)->type;
+            txStat.to = getHeader(msg)->dest;
+            txStat.token = getHeader(msg)->token;
+            txStat.maxRepCounter = macHdr->repetitionCounter;
+            txStat.creationTime =  getMetadata(msg)->time;
+#endif
+            getMetadata(msg)->maxRepetitions = macHdr->repetitionCounter;
+        }
+    }
+
+    void storeStrength(message_t *m) {
+        if(rssiValue != INVALID_SNR) {
+            (getMetadata(txBufPtr))->strength = rssiValue;
+        }
+        else {
+            if(call RssiAdcResource.isOwner()) {
+                (getMetadata(txBufPtr))->strength = call ChannelMonitorData.readSnr();
+            }
+            else {
+                (getMetadata(txBufPtr))->strength = 1;
+            }
+        }
+    }
+
+
+    bool prepareRepetition() {
+        bool repeat;
+        atomic {
+            if(isFlagSet(&flags, CANCEL_SEND)) {
+                repeat = txMacHdr->repetitionCounter = 0;
+            }
+            else {
+                repeat = txMacHdr->repetitionCounter;
+                txMacHdr->repetitionCounter--;
+            }
+        }
+        return repeat;
+    }
+
+    void signalSendDone(error_t error) {
+        message_t *m;
+        error_t e = error;
+        // sdDebug(50);
+        atomic {
+            m = txBufPtr;
+            txBufPtr = NULL;
+            txLen  = 0;
+#ifdef SPECKMAC_PERFORMANCE
+            txStat.repCounter = txMacHdr->repetitionCounter;
+            txStat.longRetry = longRetryCounter;
+            txStat.shortRetry = shortRetryCounter;
+#endif
+            longRetryCounter = 0;
+            shortRetryCounter = 0;
+            storeStrength(m);
+            if(isFlagSet(&flags, CANCEL_SEND)) {
+                e = ECANCEL;
+            }
+            clearFlag(&flags, MESSAGE_PREPARED);
+            clearFlag(&flags, CANCEL_SEND);
+        }
+        // sdDebug(3000 + e);
+        // sdDebug(4000 + getHeader(m)->type);
+        signal MacSend.sendDone(m, e);
+#ifdef SPECKMAC_PERFORMANCE
+        txStat.success = e;
+        txStat.strength = getMetadata(m)->strength;
+        call Performance.macTxMsgStats(&txStat);
+#endif
+    }
+    
+    void updateRetryCounters() {
+        shortRetryCounter++;
+        if(shortRetryCounter > MAX_SHORT_RETRY) {
+            longRetryCounter++;
+            shortRetryCounter = 1;
+            if(longRetryCounter > MAX_LONG_RETRY) {
+                // sdDebug(60);
+                signalSendDone(FAIL);
+            }
+        }
+    }
+
+    void updateLongRetryCounters() {
+        atomic {
+            clearFlag(&flags, MESSAGE_PREPARED);
+            longRetryCounter++;
+            shortRetryCounter = 1;
+            if(longRetryCounter > MAX_LONG_RETRY) {
+                // sdDebug(70);
+                signalSendDone(FAIL);
+            } else {
+                post PrepareMsgTask();
+            }
+        }
+    }
+
+    bool ackIsForMe(message_t* msg) {
+        uint8_t localToken = seqNo;
+        setFlag(&localToken, TOKEN_ACK_FLAG);
+        if((getHeader(msg)->dest == call amAddress()) && (localToken == getHeader(msg)->token)) return TRUE;
+        return FALSE;
+    }
+
+    void interruptBackoffTimer() {
+        uint16_t now;
+        if(call Timer.isRunning()) {
+            restLaufzeit = call Timer.getAlarm();
+            call Timer.stop(); 
+            now = call Timer.getNow(); 
+            if(restLaufzeit >= now) {
+                restLaufzeit = restLaufzeit - now;
+            }
+            else {
+                restLaufzeit =  (uint16_t)(-1) - restLaufzeit + now;
+            }
+            if(restLaufzeit > MIN_BACKOFF_MASK << MAX_LONG_RETRY) {
+                restLaufzeit = call Random.rand16() & ZERO_BACKOFF_MASK;
+            }
+            setFlag(&flags, RESUME_BACKOFF);
+        }
+    }
+
+    void computeBackoff() {
+        if(!isFlagSet(&flags, RESUME_BACKOFF)) {
+            setFlag(&flags, RESUME_BACKOFF);
+            restLaufzeit = backoff(longRetryCounter);
+            updateRetryCounters();
+        }
+    }
+
+    bool msgIsForMe(message_t* msg) {
+        if(getHeader(msg)->dest == AM_BROADCAST_ADDR) return TRUE;
+        if(getHeader(msg)->dest == call amAddress()) return TRUE;
+        if(getHeader(msg)->dest >= RELIABLE_MCAST_MIN_ADDR) return TRUE;
+        return FALSE;
+    }
+
+    bool isControl(message_t* m) {
+        uint8_t token = getHeader(m)->token;
+        return isFlagSet(&token, TOKEN_ACK_FLAG);
+    }
+    
+    bool isNewMsg(message_t* msg) {
+        return call Duplicate.isNew(getHeader(msg)->src, (getHeader(msg)->token) & TOKEN_ACK_MASK);
+    }
+    
+    void rememberMsg(message_t* msg) {
+        call Duplicate.remember(getHeader(msg)->src, (getHeader(msg)->token) & TOKEN_ACK_MASK);
+    }
+
+    void prepareAck(message_t* msg) {
+        uint8_t rToken = getHeader(msg)->token & TOKEN_ACK_MASK;
+        setFlag(&rToken, TOKEN_ACK_FLAG);
+        getHeader(&ackMsg)->token = rToken;
+        getHeader(&ackMsg)->src = call amAddress();
+        getHeader(&ackMsg)->dest = getHeader(msg)->src;
+        getHeader(&ackMsg)->type = getHeader(msg)->type;
+#ifdef SPECKMAC_DEBUG
+        repCounter = ((red_mac_header_t *)
+                      call SubPacket.getPayload(msg, sizeof(red_mac_header_t)))->repetitionCounter;
+#endif
+    }
+    
+    uint32_t calcGeneratedTime(red_mac_header_t *m) {
+        return rxTime - m->time - TIME_CORRECTION;
+    }
+    
+    /**************** Init ************************/
+    
+    command error_t Init.init(){
+        atomic {
+            macState = INIT;
+            seqNo = call Random.rand16() % TOKEN_ACK_FLAG;
+            for(MIN_BACKOFF_MASK = 1; MIN_BACKOFF_MASK < networkSleeptime; ) {
+                MIN_BACKOFF_MASK = (MIN_BACKOFF_MASK << 1) + 1;
+            }
+            MIN_BACKOFF_MASK >>= 2;
+        }
+#ifdef SPECKMAC_DEBUG
+        call SerialDebug.putShortDesc("SpeckMacP");
+#endif
+        return SUCCESS;
+    }
+
+    /****************  SplitControl  *****************/
+
+    task void StartDoneTask() {
+        // sdDebug(90);
+        atomic  {
+            call SampleTimer.start(localSleeptime);
+            macState = SLEEP;
+        }
+        signal SplitControl.startDone(SUCCESS);        
+    }
+    
+    command error_t SplitControl.start() {
+        call CcaStdControl.start();
+        atomic {
+            macState = INIT;
+            setRxMode();
+            // sdDebug(100);
+        }
+        return SUCCESS;
+    }
+    
+    task void StopDoneTask() {
+        call Init.init();
+        // sdDebug(110);
+        signal SplitControl.stopDone(SUCCESS);        
+    }
+    
+    command error_t SplitControl.stop() {
+        call CcaStdControl.stop();
+        call Timer.stop();
+        call SampleTimer.stop();
+        atomic {
+            if((macState == SLEEP) && isFlagSet(&flags, SWITCHING)) {
+                macState = STOP;
+                // sdDebug(120);
+            }
+            else {
+                macState = STOP;
+                setSleepMode();
+                // sdDebug(121);
+            }
+        }
+        return SUCCESS;
+    }
+
+    /****** Packet interface ********************/
+    command void Packet.clear(message_t* msg) {
+        call SubPacket.clear(msg);
+    }
+    
+    command uint8_t Packet.payloadLength(message_t* msg) {
+        return call SubPacket.payloadLength(msg) - sizeof(red_mac_header_t);
+    }
+    
+    command void Packet.setPayloadLength(message_t* msg, uint8_t len) {
+        call SubPacket.setPayloadLength(msg,len + sizeof(red_mac_header_t));
+    }
+    
+    command uint8_t Packet.maxPayloadLength() {
+        return call SubPacket.maxPayloadLength() - sizeof(red_mac_header_t);
+    }
+    
+    command void* Packet.getPayload(message_t* msg, uint8_t len) {
+        nx_uint8_t *payload = (nx_uint8_t *)call SubPacket.getPayload(msg, len + sizeof(red_mac_header_t));
+        return (void*)(payload + sizeof(red_mac_header_t));
+    }
+    
+    /****** Radio(Mode) events *************************/
+    async event void RadioModes.RssiStable() {
+        setFlag(&flags, RSSI_STABLE);
+        if((macState == RX) || (macState == CCA)) {
+            call Timer.start(DATA_DETECT_TIME);
+            // sdDebug(130);
+        }
+        else if(macState == RX_P) {
+            // sdDebug(131);
+            if(call RssiAdcResource.isOwner()) call ChannelMonitorData.getSnr();
+        }
+        else if(macState == RX_ACK) {
+            // if(call RssiAdcResource.isOwner()) call ChannelMonitor.start();
+            // sdDebug(132);
+        }
+        else if(macState == RX_ACK_P) {
+        }
+        else if(macState == INIT) {
+            // sdDebug(133);
+            if(call RssiAdcResource.isOwner()) {
+                call ChannelMonitorControl.updateNoiseFloor();
+            } else {
+                call RssiAdcResource.request();
+            }
+        }
+        else if(macState == STOP) {
+            // sdDebug(134);
+        }
+        else {
+            // sdDebug(135);
+        }
+    }
+    
+    async event void RadioModes.RxModeDone() {
+        atomic {
+            clearFlag(&flags, SWITCHING);
+            if((macState == RX) || (macState == RX_ACK) || (macState == CCA) ||
+               (macState == INIT) || (macState == STOP)) {
+                // sdDebug(140);
+                if(macState != RX_ACK) requestAdc();
+            }
+            else {
+                // sdDebug(141);
+            }
+        }
+    }
+    
+    async event void RadioModes.TxModeDone() {
+        // sdDebug(150);
+        atomic {
+            clearFlag(&flags, SWITCHING);
+            if(macState == TX) {
+                setFlag(&flags, ACTION_DETECTED);
+                if(call PacketSend.send(txBufPtr, txLen) == SUCCESS) {
+                    // sdDebug(151);
+                }
+                else {
+                    // sdDebug(152);
+                }
+            }
+            else if(macState == TX_ACK) {
+                if(call PacketSend.send(&ackMsg, 0) == SUCCESS) {
+                    // sdDebug(153);
+                } else {
+                    // sdDebug(154);
+                }
+            }
+            else {
+                // sdDebug(155);
+            }
+        }
+    }
+
+    async event void RadioModes.SleepModeDone() {
+        // sdDebug(160);
+        atomic {
+            clearFlag(&flags, SWITCHING);
+            if(isFlagSet(&flags, ACTION_DETECTED)) {
+                if(congestionLevel < 5) congestionLevel++;
+            } else {
+                if(congestionLevel > 0) congestionLevel--;
+            }
+            // if(congestionLevel > 3) // sdDebug(2000 + congestionLevel);
+            if(macState == SLEEP) {
+                // sdDebug(161);
+                if(!call Timer.isRunning()) {
+                    // sdDebug(162);
+                    if(isFlagSet(&flags, RESUME_BACKOFF)) {
+                        // sdDebug(164);
+                        clearFlag(&flags, RESUME_BACKOFF);
+                        call Timer.start(restLaufzeit);
+                        restLaufzeit = 0;
+                    }
+                    else {
+                        // sdDebug(165);
+                        checkSend();
+                    }
+                }
+            }
+            else if(macState == STOP) {
+                // sdDebug(168);
+                post StopDoneTask();
+            }
+            signal ChannelCongestion.congestionEvent(congestionLevel);
+        }
+    }
+    
+    /****** MacSend events *************************/    
+    async command error_t MacSend.send(message_t* msg, uint8_t len) {
+        error_t err = SUCCESS;
+        atomic {
+            if((shortRetryCounter == 0) && (txBufPtr == NULL)) {
+                clearFlag(&flags, MESSAGE_PREPARED);
+                // sdDebug(5000 + getHeader(msg)->type);
+                shortRetryCounter = 1;
+                longRetryCounter = 1;
+                txBufPtr = msg;
+                txLen = len + sizeof(red_mac_header_t);
+                seqNo++;
+                if(seqNo >= TOKEN_ACK_FLAG) seqNo = 1;
+#ifdef SPECKMAC_PERFORMANCE
+                txStat.payloadLength = txLen;
+                txStat.interfaceTime = call LocalTime32kHz.get();
+#endif
+            }
+            else {
+                // sdDebug(171);
+                err = EBUSY;
+            }
+        }
+        if(err == SUCCESS) {
+            post PrepareMsgTask();
+        }
+        return err;
+    }
+
+    async command error_t MacSend.cancel(message_t* msg) {
+        error_t err = FAIL;
+        atomic {
+            if(msg == txBufPtr) {
+                // sdDebug(320);
+                setFlag(&flags, CANCEL_SEND);
+                shortRetryCounter = MAX_SHORT_RETRY + 2;
+                longRetryCounter  = MAX_LONG_RETRY + 2;
+                if(macState == SLEEP) {
+                    // sdDebug(321);
+                    signalSendDone(ECANCEL);
+                }
+                else {
+                    // sdDebug(322);
+                }
+                // sdDebug(1000 + macState);
+                err = SUCCESS;
+            }
+            else {
+                // sdDebug(323);
+                // sdDebug(1100 + macState);
+            }
+        }
+        return err;
+    }
+    
+    /****** PacketSerializer events **********************/
+    
+    async event void PacketReceive.receiveDetected() {
+        rssiValue = INVALID_SNR;
+        setFlag(&flags, ACTION_DETECTED);
+        call ChannelMonitor.rxSuccess();
+        if(macState <= CCA_ACK) {
+            if(macState == CCA) {
+                computeBackoff();
+#ifdef SPECKMAC_PERFORMANCE
+                call Performance.macDetectedOnCca();
+#endif
+            }
+            if(macState != RX_ACK) {
+                macState = RX_P;
+            } else {
+                macState = RX_ACK_P;
+            }
+        }
+        else if(macState == INIT) {
+            // sdDebug(180);
+            setFlag(&flags, UNHANDLED_PACKET);
+        }
+    }
+    
+    async event message_t* PacketReceive.receiveDone(message_t* msg, void* payload, uint8_t len, error_t error) {
+        message_t *m = msg;
+        macState_t action = STOP;
+        uint32_t nav = 0;
+        bool isCnt;
+#ifdef SPECKMAC_PERFORMANCE
+        rxStat.duplicate = PERF_UNKNOWN;
+        rxStat.repCounter = 0xff;
+#endif
+        // sdDebug(190);
+        if(macState == RX_P) {
+            // sdDebug(191);
+            if(error == SUCCESS) {
+                // sdDebug(192);
+                isCnt = isControl(msg);
+                if(msgIsForMe(msg)) {
+                    if(!isCnt) {
+                        // sdDebug(193);
+                        if(isNewMsg(msg)) {
+#ifdef SPECKMAC_PERFORMANCE
+                            rxStat.duplicate = PERF_NEW_MSG;
+#endif
+                            storeStrength(msg);
+                            getMetadata(msg)->time = calcGeneratedTime((red_mac_header_t*) payload);
+                            getMetadata(msg)->ack = WAS_NOT_ACKED;
+                            m = signal MacReceive.receiveDone(msg);
+                            // assume a buffer swap -- if buffer is not swapped, assume that the
+                            // message was not successfully delivered to upper layers
+                            if(m != msg) {
+                                // sdDebug(195);
+                                rememberMsg(msg);
+                            } else {
+                                // sdDebug(196);
+                                action = RX;
+#ifdef SPECKMAC_PERFORMANCE
+                                call Performance.macQueueFull();
+#endif
+                            }
+                        }
+#ifdef SPECKMAC_PERFORMANCE
+                        else {
+                            rxStat.duplicate = PERF_REPEATED_MSG;
+                        }
+#endif                  
+                        if(needsAckRx(msg) && (action != RX)) {
+                            // sdDebug(197);
+                            if(((red_mac_header_t*)payload)->repetitionCounter == 0) {
+                                action = CCA_ACK;
+                            }
+                            else {
+                                action = RX;
+                            }
+                        }
+                        else {
+                            // sdDebug(198);
+                            if(action != RX) {
+                                nav = ((red_mac_header_t*)payload)->repetitionCounter *
+                                    (SUB_HEADER_TIME + getHeader(msg)->length*BYTE_TIME +
+                                     SUB_FOOTER_TIME) + RX_ACK_TIMEOUT + TX_SETUP_TIME + ACK_DURATION;
+                                action = SLEEP;
+                            }
+                        }
+                    }
+                    else {
+                        // sdDebug(199);
+                        action = RX;
+                    }
+                }
+                else {
+                    // sdDebug(200);
+                    action = SLEEP;
+                    if(!isCnt) {
+                        nav = ((red_mac_header_t*)payload)->repetitionCounter *
+                            (SUB_HEADER_TIME + getHeader(msg)->length*BYTE_TIME +
+                             SUB_FOOTER_TIME) + RX_ACK_TIMEOUT + TX_SETUP_TIME + ACK_DURATION;
+                    }
+                }
+            }
+            else {
+                // sdDebug(201);
+                action = SLEEP;
+            }
+        }
+        else if(macState == RX_ACK_P) {
+            if(error == SUCCESS) {
+                if(ackIsForMe(msg)) {
+                    // sdDebug(202);
+                    storeStrength(msg);
+                    getMetadata(txBufPtr)->ack = WAS_ACKED;
+                    getMetadata(txBufPtr)->repetitions = txMacHdr->repetitionCounter;
+                    // sdDebug(203);
+                    signalSendDone(SUCCESS);
+                    // sdDebug(30000 + getHeader(msg)->src);
+                    action = SLEEP;
+                }
+                else {
+                    // sdDebug(203);
+                    updateLongRetryCounters(); // this will eventually schedule the right backoff
+                    macState = SLEEP;          // so much traffic is going on -- take a nap
+                    setSleepMode();
+                    action = INIT;             // a difficult way to say: do nothing
+                }
+            }
+            else {
+                if(call Timer.isRunning()) {
+                    // sdDebug(204);
+                    action = RX_ACK;
+                }
+                else {
+                    // sdDebug(205);
+                    updateLongRetryCounters();
+                    action = RX;
+                }
+            }
+        }
+        else {
+            // sdDebug(206);
+            action = INIT;
+        }
+        if(action == CCA_ACK) {
+            macState = TX_ACK;
+            call Timer.start(RX_SETUP_TIME - TX_SETUP_TIME + 16);
+            prepareAck(msg);
+        }
+        else if(action == RX_ACK) {
+            macState = RX_ACK;
+        }
+        else if(action == RX) {
+            macState = RX;
+            checkCounter = 0;
+            call Timer.start(DATA_DETECT_TIME);
+        }
+        else if(action == SLEEP) {
+            macState = SLEEP;
+            if(isFlagSet(&flags, RESUME_BACKOFF)) {
+                if(nav > restLaufzeit) restLaufzeit += nav;
+            }
+            else {
+                setFlag(&flags, RESUME_BACKOFF);
+                restLaufzeit = call Random.rand16() & ZERO_BACKOFF_MASK;
+            }
+            setSleepMode();
+        }
+        else if(action == INIT) {
+            clearFlag(&flags, UNHANDLED_PACKET);
+        }
+        else {
+            // sdDebug(207);
+        }
+#ifdef SPECKMAC_PERFORMANCE
+        if(error == SUCCESS) {
+            rxStat.type = getHeader(msg)->type;
+            rxStat.from = getHeader(msg)->src;
+            rxStat.to = getHeader(msg)->dest;
+            rxStat.token = getHeader(msg)->token;
+            if(!isControl(msg)) rxStat.repCounter  = ((red_mac_header_t*)payload)->repetitionCounter;
+            rxStat.payloadLength = len;
+            rxStat.strength = rssiValue;
+            rxStat.creationTime = getMetadata(msg)->time;
+            call Performance.macRxStats(&rxStat);
+        }
+#endif
+        return m;
+    }
+
+    async event void PacketSend.sendDone(message_t* msg, error_t error) {
+        if(macState == TX) {
+            if(prepareRepetition()) {
+                call PacketSend.send(txBufPtr, txLen);
+            }
+            else {
+                macState = RX_ACK;
+                setRxMode();
+                call Timer.start(RX_ACK_TIMEOUT);
+                // sdDebug(220);
+                checkCounter = 0;
+            }
+        }
+        else if(macState == TX_ACK) {
+            checkCounter = 0;
+            macState = RX;
+            setRxMode();
+            // sdDebug(221);
+#ifdef SPECKMAC_DEBUG            
+            // sdDebug(40000U + repCounter);
+#endif
+        }
+    }
+    
+    /***** TimeStamping stuff **************************/
+    async event void RadioTimeStamping.receivedSFD( uint16_t time ) {
+        if(call RssiAdcResource.isOwner()) call ChannelMonitorData.getSnr();
+        if(macState == RX_P) {
+            rxTime = call LocalTime32kHz.get();
+            call ChannelMonitor.rxSuccess();
+        }
+    }
+    
+    async event void RadioTimeStamping.transmittedSFD( uint16_t time, message_t* p_msg ) {
+        uint32_t now;
+        uint32_t mTime;
+        if((macState == TX) && (p_msg == txBufPtr)) {
+            now = call LocalTime32kHz.get();
+            mTime = getMetadata(p_msg)->time;
+            if(now >= mTime) {
+                txMacHdr->time = now - mTime;
+            }
+            else {
+                // assume a clock wrap here
+                txMacHdr->time = (uint32_t)(-1) - mTime + now;
+            }
+        }
+    }
+    
+    /****** Timer ******************************/
+
+    void checkOnBusy() {
+        setFlag(&flags, ACTION_DETECTED);
+        if((macState == RX) || (macState == CCA) || (macState == CCA_ACK)) {
+            if(macState == CCA) {
+                computeBackoff();
+#ifdef SPECKMAC_PERFORMANCE
+                call Performance.macBusyOnCca();
+#endif
+            }
+            requestAdc();
+            // sdDebug(230);
+            macState = RX;
+            checkCounter = 0;
+            call Timer.start(TX_GAP_TIME>>1);
+        }
+    }
+
+    void checkOnIdle()  {
+        if(macState == RX) {
+            // sdDebug(240);
+            macState = SLEEP;
+            setSleepMode();
+        }
+        else if(macState == CCA) {
+            checkCounter++;
+            if(checkCounter < 3) {
+                // sdDebug(242);                
+                call Timer.start(TX_GAP_TIME >> 1);
+                requestAdc();
+            }
+            else {
+                // sdDebug(243);
+                macState = TX;
+                setTxMode();
+#ifdef SPECKMAC_PERFORMANCE
+                call Performance.macIdleOnCca();
+                txStat.txModeTime = call LocalTime32kHz.get();
+#endif
+            }
+        }
+    }
+    
+    async event void Timer.fired() {
+        // sdDebug(250);
+        if((macState == RX) || (macState == CCA) || (macState == CCA_ACK)) {
+            if((!call RssiAdcResource.isOwner()) || (call ChannelMonitor.start() != SUCCESS)) {
+                if(call UartPhyControl.isBusy()) {
+                    // sdDebug(251);
+                    checkOnBusy();
+                }
+                else {
+                    // sdDebug(252);
+                    checkOnIdle();
+                }
+            }
+        }
+        else if(macState == RX_ACK) {
+            if(needsAckTx(txBufPtr)) {
+                // sdDebug(254);
+#ifdef SPECKMAC_PERFORMANCE
+                call Performance.macAckTimeout();
+#endif
+                updateLongRetryCounters();
+            }
+            else {
+                // sdDebug(255);
+                signalSendDone(SUCCESS);
+            }
+            macState = SLEEP;
+            setSleepMode();
+        }
+        else if(macState == TX_ACK) {
+            setTxMode();
+            // sdDebug(10000 + getHeader(&ackMsg)->dest);
+        }
+        else if(macState == SLEEP) {
+             if(isFlagSet(&flags, SWITCHING)) {
+                 // sdDebug(256);
+                 call Timer.start(call Random.rand16() & 0x0f);
+             }
+             else {
+                 if(isFlagSet(&flags, RESUME_BACKOFF)) {
+                     // sdDebug(261);
+                     clearFlag(&flags, RESUME_BACKOFF);
+                     call Timer.start(restLaufzeit);
+                     restLaufzeit = 0;
+                 }
+                 else {
+                     // sdDebug(262);
+                     checkSend();
+                 }
+             }
+        }
+        else if((macState == RX_ACK_P) || (macState == RX_P)) {
+            // sdDebug(258);
+        }
+        else if(macState == INIT) {
+            // sdDebug(259);
+            post StartDoneTask();
+        }
+        else {
+            // sdDebug(260);
+        }
+    }
+
+    /****** SampleTimer ******************************/
+
+    async event void SampleTimer.fired() {
+        call SampleTimer.start(localSleeptime);
+        // sdDebug(270);
+        if((macState == SLEEP) && (!isFlagSet(&flags, SWITCHING))) {
+            clearFlag(&flags, ACTION_DETECTED);
+            interruptBackoffTimer();
+            macState = RX;
+            // sdDebug(271);
+            setRxMode();
+            call Timer.stop();
+        }
+    }
+
+    /***** Sleeptime **********************************/
+    async command void Sleeptime.setLocalSleeptime(uint16_t sT) {
+        atomic localSleeptime = sT;
+    }
+
+    async command uint16_t Sleeptime.getLocalSleeptime() {
+        uint16_t st;
+        atomic st = localSleeptime;
+        return st;        
+    }
+
+    async command void Sleeptime.setNetworkSleeptime(uint16_t sT) {
+        atomic {
+            networkSleeptime = sT;
+            for(MIN_BACKOFF_MASK = 1; MIN_BACKOFF_MASK < sT; ) {
+                MIN_BACKOFF_MASK = (MIN_BACKOFF_MASK << 1) + 1;
+            }
+            MIN_BACKOFF_MASK >>= 3;
+        }
+    }
+    
+    async command uint16_t Sleeptime.getNetworkSleeptime() {
+        uint16_t st;
+        atomic st = networkSleeptime;
+        return st;
+    }
+
+    /****** ChannelMonitor events *********************/
+
+    async event void ChannelMonitor.channelBusy() {
+        // sdDebug(280);
+        checkOnBusy();
+    }
+
+    async event void ChannelMonitor.channelIdle() {
+        // sdDebug(281);
+        checkOnIdle();
+    }
+
+    /****** ChannelMonitorControl events **************/
+    
+    event void ChannelMonitorControl.updateNoiseFloorDone() {
+        if(macState == INIT) {
+            // sdDebug(290);
+            call Timer.start(call Random.rand16() % localSleeptime);
+            setSleepMode();
+        } else {
+            // sdDebug(291);
+        }
+    }
+
+    /***** ChannelMonitorData events ******************/
+    
+    async event void ChannelMonitorData.getSnrDone(int16_t data) {
+        atomic if((macState == RX_P) || (macState == RX_ACK_P)) rssiValue = data;
+    }
+    
+    /***** Rssi Resource events ******************/
+    event void RssiAdcResource.granted() {
+        macState_t ms;
+        atomic ms = macState;
+        if(ms < SLEEP) {
+            // sdDebug(300);
+        }
+        else if(ms == INIT) {
+            // sdDebug(301);
+            call ChannelMonitorControl.updateNoiseFloor();            
+        }
+        else {
+            // sdDebug(302);
+            post ReleaseAdcTask();
+        }
+    }
+    
+    default async event void ChannelCongestion.congestionEvent(uint8_t level) {}
+
+    /***** unused Radio Modes events **************************/
+    
+    async event void RadioModes.TimerModeDone() {}
+    async event void RadioModes.SelfPollingModeDone() {}
+    async event void RadioModes.PWDDDInterrupt() {}
+}
+
diff --git a/tos/platforms/eyesIFX/LocalTimeC.nc b/tos/platforms/eyesIFX/LocalTimeC.nc
new file mode 100644 (file)
index 0000000..97be68b
--- /dev/null
@@ -0,0 +1,40 @@
+/* -*- mode:c++; indent-tabs-mode:nil -*- 
+ * Copyright (c) 2007, Technische Universitaet Berlin
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without 
+ * modification, are permitted provided that the following conditions 
+ * are met:
+ * - Redistributions of source code must retain the above copyright notice,
+ *   this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright 
+ *   notice, this list of conditions and the following disclaimer in the 
+ *   documentation and/or other materials provided with the distribution.
+ * - Neither the name of the Technische Universitaet Berlin nor the names 
+ *   of its contributors may be used to endorse or promote products derived
+ *   from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED 
+ * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, 
+ * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY 
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE 
+ * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+configuration LocalTimeC {
+    provides {  
+        interface LocalTime<T32khz> as LocalTime;
+    }
+}
+implementation  {
+    components LocalTimeP, Counter32khz16C as Counter;
+    LocalTime = LocalTimeP;
+    LocalTimeP.Counter32khz16 -> Counter;
+}
+
diff --git a/tos/platforms/eyesIFX/LocalTimeP.nc b/tos/platforms/eyesIFX/LocalTimeP.nc
new file mode 100644 (file)
index 0000000..8778422
--- /dev/null
@@ -0,0 +1,64 @@
+/* -*- mode:c++; indent-tabs-mode:nil -*- 
+ * Copyright (c) 2007, Technische Universitaet Berlin
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without 
+ * modification, are permitted provided that the following conditions 
+ * are met:
+ * - Redistributions of source code must retain the above copyright notice,
+ *   this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright 
+ *   notice, this list of conditions and the following disclaimer in the 
+ *   documentation and/or other materials provided with the distribution.
+ * - Neither the name of the Technische Universitaet Berlin nor the names 
+ *   of its contributors may be used to endorse or promote products derived
+ *   from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED 
+ * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, 
+ * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY 
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE 
+ * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+module LocalTimeP {
+    provides {  
+        interface LocalTime<T32khz> as LocalTime32kHz;
+    }
+    uses {
+        interface Counter<T32khz,uint16_t> as Counter32khz16;
+    }
+}
+implementation  {
+    typedef union 
+    {
+        uint32_t op;
+        struct {
+            uint16_t lo;
+            uint16_t hi;
+        };
+    } ui32parts_t;
+    
+    uint16_t counter2sec = 127;
+
+    async command uint32_t LocalTime32kHz.get() {
+        ui32parts_t time;
+        atomic {
+            time.lo = call Counter32khz16.get();
+            time.hi = counter2sec;
+            if(call Counter32khz16.isOverflowPending()) ++time.hi;
+        }
+        return time.op;
+    }
+
+    async event void Counter32khz16.overflow() {
+        ++counter2sec;
+    }
+}
+