]> oss.titaniummirror.com Git - tinyos-2.x.git/blobdiff - tos/chips/tda5250/mac/RedMacP.nc
fix exotic backoff bug, check validity of duplicate supression table first
[tinyos-2.x.git] / tos / chips / tda5250 / mac / RedMacP.nc
index 789a479723725ec62f262f32e4b26e497403e73a..164813de6f9177edbfd9c03c41b5e4f14d969271 100644 (file)
@@ -47,7 +47,7 @@ module RedMacP {
         interface MacReceive;
         interface Packet;
         interface LocalTime<T32khz> as LocalTime32khz;
-        interface SleepTime;
+        interface Sleeptime;
         interface Teamgeist;
         interface ChannelCongestion;
     }
@@ -74,9 +74,19 @@ module RedMacP {
         interface Alarm<T32khz, uint16_t> as SampleTimer;
         interface Counter<T32khz,uint16_t> as Counter32khz16;
         async command am_addr_t amAddress();
+/*
+        interface GeneralIO as Led0;
+        interface GeneralIO as Led1;
+        interface GeneralIO as Led2;
+        interface GeneralIO as Led3;        
+*/  
 #ifdef REDMAC_DEBUG
         interface SerialDebug;
 #endif
+#ifdef REDMAC_PERFORMANCE
+        interface Performance;
+#endif
+
     }
 }
 implementation
@@ -103,52 +113,46 @@ implementation
     void sdDebug(uint16_t p) {
         call SerialDebug.putPlace(p);
     }
+    uint8_t repCounter;
 #else
     void sdDebug(uint16_t p) {};
 #endif
     
+#ifdef REDMAC_PERFORMANCE
+    macTxStat_t txStat;
+    macRxStat_t rxStat;
+#endif
+
     /**************** Module Global Constants  *****************/
     enum {
-/*
-        BYTE_TIME=13,                // byte at 38400 kBit/s, 4b6b encoded
-        PREAMBLE_BYTE_TIME=9,        // byte at 38400 kBit/s, no coding
-        PHY_HEADER_TIME=51,          // 6 Phy Preamble at 38400
-*/
-        BYTE_TIME=10,                // byte at 49000 kBit/s, 4b6b encoded
-        PREAMBLE_BYTE_TIME=7,        // byte at 49000 kBit/s, no coding
-        PHY_HEADER_TIME=40,          // 6 Phy Preamble at 49000
 
-/*
-        BYTE_TIME=12,                // byte at 40960 kBit/s, 4b6b encoded
-        PREAMBLE_BYTE_TIME=8,        // byte at 40960 kBit/s, no coding
-        PHY_HEADER_TIME=48,          // 6 Phy Preamble at 40960
-*/
-        SUB_HEADER_TIME=PHY_HEADER_TIME + sizeof(tda5250_header_t)*BYTE_TIME,
+        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=9750,
         DEFAULT_SLEEP_TIME=16384,
+        // DEFAULT_SLEEP_TIME=32768U,
         DATA_DETECT_TIME=17,
-        RX_SETUP_TIME=111,    // time to set up receiver
-        TX_SETUP_TIME=69,     // time to set up transmitter
-        ADDED_DELAY = PREAMBLE_BYTE_TIME,
-        RX_ACK_TIMEOUT = RX_SETUP_TIME + PHY_HEADER_TIME + 2*ADDED_DELAY + 19,
-        TX_GAP_TIME=RX_ACK_TIMEOUT + TX_SETUP_TIME + 11,
+        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=7,
-        MAX_LONG_RETRY=2,
+        MAX_SHORT_RETRY=9,
+        MAX_LONG_RETRY=3,
         MAX_AGE=2*MAX_LONG_RETRY*MAX_SHORT_RETRY,
         MSG_TABLE_ENTRIES=20,
         TOKEN_ACK_FLAG = 64,
         TOKEN_ACK_MASK = 0x3f,
-        /* correct the difference between the transmittedSFD and the receivedSFD
-           that appears due to buffering, measured value on an osci is 320us, so this
-           value is actually 10.48576
-        */
-        TIME_CORRECTION = 10,
         INVALID_SNR = 0xffff,
         // PREAMBLE_LONG = 5,
         // PREAMBLE_SHORT = 2,
@@ -186,27 +190,28 @@ implementation
     } knownMessage_t;
     
     knownMessage_t knownMsgTable[MSG_TABLE_ENTRIES];
-    uint8_t flags;
-    uint8_t checkCounter;
-    uint8_t shortRetryCounter;
-    uint8_t longRetryCounter;
-    uint16_t sleepTime;
-    uint16_t rssiValue;
-    uint32_t restLaufzeit;
-    
-    message_t *txBufPtr;
-    uint16_t txLen;
-    red_mac_header_t *txMacHdr;
+    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;
 
-    uint16_t seqNo;
-    message_t ackMsg;
+    uint16_t counter2sec = 127;
+    uint32_t rxTime = 0;
 
-    uint16_t counter2sec;
-    uint32_t rxTime;
+    am_id_t teamgeistType = 0;
 
-    am_id_t teamgeistType;
+    uint8_t congestionLevel = 0;
+    
+    message_t *txBufPtr = NULL;
+    uint16_t txLen = 0;
+    red_mac_header_t *txMacHdr = NULL;
+    uint16_t seqNo;
+    message_t ackMsg;
 
-    uint8_t congestionLevel;
     uint16_t MIN_BACKOFF_MASK;
     
     /****** Secure switching of radio modes ***/
@@ -241,6 +246,11 @@ implementation
         if(call RadioModes.RxMode() == FAIL) {
             post SetRxModeTask();
         }
+        else {
+#ifdef REDMAC_PERFORMANCE
+            call Performance.macRxMode();
+#endif
+        }
         requestAdc();
     }
     
@@ -258,6 +268,11 @@ implementation
         if(call RadioModes.SleepMode() == FAIL) {
             post SetSleepModeTask();
         }
+        else {
+#ifdef REDMAC_PERFORMANCE
+            call Performance.macSleepMode();
+#endif
+        }
     }
     
     task void SetSleepModeTask() {
@@ -273,6 +288,11 @@ implementation
         if(call RadioModes.TxMode() == FAIL) {
             post SetTxModeTask();
         }
+        else {
+#ifdef REDMAC_PERFORMANCE
+            call Performance.macTxMode();
+#endif
+        }
     }
 
     task void SetTxModeTask() {
@@ -287,19 +307,22 @@ implementation
     void checkSend() {
         if((shortRetryCounter) && (txBufPtr != NULL) && (isFlagSet(&flags, MESSAGE_PREPARED)) && 
            (macState == SLEEP) && (!isFlagSet(&flags, RESUME_BACKOFF)) && (!call Timer.isRunning())) {
-            sdDebug(40);
+            // sdDebug(40);
             macState = CCA;
             checkCounter = 0;
             setRxMode();
         }
-        else {
-            if(txBufPtr) sdDebug(41);
-            if(shortRetryCounter) sdDebug(42);
-            if(isFlagSet(&flags, MESSAGE_PREPARED)) sdDebug(43);
-            if(!call Timer.isRunning()) sdDebug(44);
-            if(!isFlagSet(&flags, RESUME_BACKOFF)) sdDebug(45);
-            if(macState == SLEEP) sdDebug(46);
+/*        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) {
@@ -349,7 +372,7 @@ implementation
         atomic {
             msg = txBufPtr;
             length = txLen;
-            sT = sleepTime;
+            sT = networkSleeptime;
         }
         if(msg == NULL) return;
         macHdr = (red_mac_header_t *)call SubPacket.getPayload(msg, NULL);
@@ -374,15 +397,27 @@ implementation
                     call Timer.start(backoff(longRetryCounter));
                 }
             }
+#ifdef REDMAC_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;
         }
     }
 
     bool prepareRepetition() {
         bool repeat;
         atomic {
-            if(isFlagSet(&flags, CANCEL_SEND)) txMacHdr->repetitionCounter = 0;
-            repeat = (txMacHdr->repetitionCounter >= 1);
-            txMacHdr->repetitionCounter--;
+            if(isFlagSet(&flags, CANCEL_SEND)) {
+                repeat = txMacHdr->repetitionCounter = 0;
+            }
+            else {
+                repeat = txMacHdr->repetitionCounter;
+                txMacHdr->repetitionCounter--;
+            }
         }
         return repeat;
     }
@@ -395,6 +430,11 @@ implementation
             m = txBufPtr;
             txBufPtr = NULL;
             txLen  = 0;
+#ifdef REDMAC_PERFORMANCE
+            txStat.repCounter = txMacHdr->repetitionCounter;
+            txStat.longRetry = longRetryCounter;
+            txStat.shortRetry = shortRetryCounter;
+#endif
             longRetryCounter = 0;
             shortRetryCounter = 0;
             if(rssiValue != INVALID_SNR) {
@@ -409,8 +449,14 @@ implementation
             clearFlag(&flags, MESSAGE_PREPARED);
             clearFlag(&flags, CANCEL_SEND);
         }
-        sdDebug(3000 + e);
+        // sdDebug(3000 + e);
+        // sdDebug(4000 + getHeader(m)->type);
         signal MacSend.sendDone(m, e);
+#ifdef REDMAC_PERFORMANCE
+        txStat.success = e;
+        txStat.strength = getMetadata(m)->strength;
+        call Performance.macTxMsgStats(&txStat);
+#endif
     }
     
     void updateRetryCounters() {
@@ -419,7 +465,7 @@ implementation
             longRetryCounter++;
             shortRetryCounter = 1;
             if(longRetryCounter > MAX_LONG_RETRY) {
-                sdDebug(60);
+                // sdDebug(60);
                 signalSendDone(FAIL);
             }
         }
@@ -431,7 +477,7 @@ implementation
             longRetryCounter++;
             shortRetryCounter = 1;
             if(longRetryCounter > MAX_LONG_RETRY) {
-                sdDebug(70);
+                // sdDebug(70);
                 signalSendDone(FAIL);
             } else {
                 post PrepareMsgTask();
@@ -450,8 +496,8 @@ implementation
         uint16_t now;
         if(call Timer.isRunning()) {
             restLaufzeit = call Timer.getAlarm();
-            call Timer.stop();
-            now = call Timer.getNow();
+            call Timer.stop(); 
+            now = call Timer.getNow(); 
             if(restLaufzeit >= now) {
                 restLaufzeit = restLaufzeit - now;
             }
@@ -461,8 +507,6 @@ implementation
             if(restLaufzeit > MIN_BACKOFF_MASK << MAX_LONG_RETRY) {
                 restLaufzeit = call Random.rand16() & ZERO_BACKOFF_MASK;
             }
-            sdDebug(1000);
-            sdDebug(restLaufzeit);
             setFlag(&flags, RESUME_BACKOFF);
         }
     }
@@ -472,8 +516,6 @@ implementation
             setFlag(&flags, RESUME_BACKOFF);
             restLaufzeit = backoff(longRetryCounter);
             updateRetryCounters();
-            sdDebug(80);
-            sdDebug(restLaufzeit);
         }
     }
 
@@ -493,9 +535,9 @@ implementation
         bool rVal = TRUE;
         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)) {
+            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;
@@ -531,6 +573,9 @@ implementation
         getHeader(&ackMsg)->src = call amAddress();
         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;
+#endif
     }
     
     uint32_t calcGeneratedTime(red_mac_header_t *m) {
@@ -543,27 +588,14 @@ implementation
         uint8_t i;
         atomic {
             macState = INIT;
-            flags = 0;
-            checkCounter = 0;
-            rssiValue = 0;
-            restLaufzeit = 0;
             seqNo = call Random.rand16() % TOKEN_ACK_FLAG;
-            txBufPtr = NULL;
-            txLen = 0;
-            txMacHdr = NULL;
-            sleepTime = DEFAULT_SLEEP_TIME;
             for(i = 0; i < MSG_TABLE_ENTRIES; i++) {
                 knownMsgTable[i].age = MAX_AGE;
             }
-            for(MIN_BACKOFF_MASK = 1; MIN_BACKOFF_MASK < sleepTime; ) {
+            for(MIN_BACKOFF_MASK = 1; MIN_BACKOFF_MASK < networkSleeptime; ) {
                 MIN_BACKOFF_MASK = (MIN_BACKOFF_MASK << 1) + 1;
             }
             MIN_BACKOFF_MASK >>= 2;
-            shortRetryCounter = 0;
-            longRetryCounter = 0;
-            counter2sec = 127;
-            rxTime = 0;
-            teamgeistType = 0;
         }
 #ifdef REDMAC_DEBUG
         call SerialDebug.putShortDesc("RedMacP");
@@ -576,7 +608,7 @@ implementation
     task void StartDoneTask() {
         // sdDebug(90);
         atomic  {
-            call SampleTimer.start(sleepTime);
+            call SampleTimer.start(localSleeptime);
             macState = SLEEP;
             setFlag(&flags, TEAMGEIST_ACTIVE);
             teamgeistType = signal Teamgeist.observedAMType();
@@ -697,10 +729,10 @@ implementation
             if(macState == TX) {
                 setFlag(&flags, ACTION_DETECTED);
                 if(call PacketSend.send(txBufPtr, txLen) == SUCCESS) {
-                    sdDebug(151);
+                    // sdDebug(151);
                 }
                 else {
-                    sdDebug(152);
+                    // sdDebug(152);
                 }
             }
             else if(macState == TX_ACK) {
@@ -725,27 +757,23 @@ implementation
             } else {
                 if(congestionLevel > 0) congestionLevel--;
             }
-            if(congestionLevel > 3) sdDebug(2000 + 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);
+                        // sdDebug(164);
                         clearFlag(&flags, RESUME_BACKOFF);
                         call Timer.start(restLaufzeit);
                         restLaufzeit = 0;
                     }
                     else {
-                        sdDebug(165);
+                        // sdDebug(165);
                         checkSend();
                     }
                 }
             }
-            else if(macState == INIT) {
-                // sdDebug(167);
-                post StartDoneTask();
-            }
             else if(macState == STOP) {
                 // sdDebug(168);
                 post StopDoneTask();
@@ -760,13 +788,17 @@ implementation
         atomic {
             if((shortRetryCounter == 0) && (txBufPtr == NULL)) {
                 clearFlag(&flags, MESSAGE_PREPARED);
-                sdDebug(170);
+                // 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 REDMAC_PERFORMANCE
+                txStat.payloadLength = txLen;
+                txStat.interfaceTime = call LocalTime32khz.get();
+#endif
             }
             else {
                 // sdDebug(171);
@@ -783,15 +815,24 @@ implementation
         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(320);
+                    // sdDebug(321);
                     signalSendDone(ECANCEL);
                 }
+                else {
+                    // sdDebug(322);
+                }
+                // sdDebug(1000 + macState);
                 err = SUCCESS;
             }
+            else {
+                // sdDebug(323);
+                // sdDebug(1100 + macState);
+            }
         }
         return err;
     }
@@ -801,8 +842,14 @@ implementation
     async event void PacketReceive.receiveDetected() {
         rssiValue = INVALID_SNR;
         setFlag(&flags, ACTION_DETECTED);
+        call ChannelMonitor.rxSuccess();
         if(macState <= CCA_ACK) {
-            if(macState == CCA) computeBackoff();
+            if(macState == CCA) {
+                computeBackoff();
+#ifdef REDMAC_PERFORMANCE
+                call Performance.macDetectedOnCca();
+#endif
+            }
             if(macState != RX_ACK) {
                 macState = RX_P;
             } else {
@@ -821,7 +868,10 @@ implementation
         uint32_t nav = 0;
         uint8_t level = 0;
         bool isCnt;
-        
+#ifdef REDMAC_PERFORMANCE
+        rxStat.duplicate = PERF_UNKNOWN;
+        rxStat.repCounter = 0xff;
+#endif
         // sdDebug(190);
         if(macState == RX_P) {
             // sdDebug(191);
@@ -832,6 +882,9 @@ implementation
                     if(!isCnt) {
                         // sdDebug(193);
                         if(isNewMsg(msg)) {
+#ifdef REDMAC_PERFORMANCE
+                            rxStat.duplicate = PERF_NEW_MSG;
+#endif
                             // sdDebug(194);
                             if(rssiValue != INVALID_SNR) {
                                 (getMetadata(m))->strength = rssiValue;
@@ -844,7 +897,8 @@ implementation
                                     (getMetadata(m))->strength = 1;
                                 }
                             }
-                            (getMetadata(msg))->time = calcGeneratedTime((red_mac_header_t*) payload);
+                            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
@@ -854,8 +908,16 @@ implementation
                             } else {
                                 // sdDebug(196);
                                 action = RX;
+#ifdef REDMAC_PERFORMANCE
+                                call Performance.macQueueFull();
+#endif
                             }
                         }
+#ifdef REDMAC_PERFORMANCE
+                        else {
+                            rxStat.duplicate = PERF_REPEATED_MSG;
+                        }
+#endif                  
                         if(needsAckRx(msg, &level) && (action != RX)) {
                             // sdDebug(197);
                             action = CCA_ACK;
@@ -906,27 +968,34 @@ implementation
                             (getMetadata(txBufPtr))->strength = 1;
                         }
                     }
-                    (getMetadata(txBufPtr))->ack = WAS_ACKED;
-                    if(isFlagSet(&flags, TEAMGEIST_ACTIVE) && (getHeader(txBufPtr)->type == teamgeistType)) {
+                    getMetadata(txBufPtr)->ack = WAS_ACKED;
+                    getMetadata(txBufPtr)->repetitions = txMacHdr->repetitionCounter;
+                    if(isFlagSet(&flags, TEAMGEIST_ACTIVE) &&
+                       (getHeader(txBufPtr)->type == teamgeistType))
+                    {
                         signal Teamgeist.gotAck(txBufPtr, getHeader(msg)->src,
                                                 getMetadata(txBufPtr)->strength);
                     }
-                    sdDebug(203);
+                    // sdDebug(203);
                     signalSendDone(SUCCESS);
+                    // sdDebug(30000 + getHeader(msg)->src);
                     action = SLEEP;
                 }
                 else {
-                    updateLongRetryCounters();
-                    action = RX;
+                    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);
+                    sdDebug(204);
                     action = RX_ACK;
                 }
                 else {
-                    // sdDebug(205);
+                    sdDebug(205);
                     updateLongRetryCounters();
                     action = RX;
                 }
@@ -937,9 +1006,15 @@ implementation
             action = INIT;
         }
         if(action == CCA_ACK) {
-            prepareAck(msg);
             macState = CCA_ACK;
-            call Timer.start(RX_SETUP_TIME - TX_SETUP_TIME + (ADDED_DELAY>>level));
+            if(call Random.rand16() & 2) {
+                call Timer.start(RX_SETUP_TIME - TX_SETUP_TIME + 16 - level*8 + ADDED_DELAY);
+            }
+            else {
+                macState = TX_ACK;
+                call Timer.start(RX_SETUP_TIME - TX_SETUP_TIME + 16);
+            }
+            prepareAck(msg);
         }
         else if(action == RX_ACK) {
             macState = RX_ACK;
@@ -956,7 +1031,7 @@ implementation
             }
             else {
                 setFlag(&flags, RESUME_BACKOFF);
-                restLaufzeit = nav + backoff(longRetryCounter);
+                restLaufzeit = call Random.rand16() & ZERO_BACKOFF_MASK;
             }
             setSleepMode();
         }
@@ -966,21 +1041,38 @@ implementation
         else {
             // sdDebug(207);
         }
+#ifdef REDMAC_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) {
-            sdDebug(220);
             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 REDMAC_DEBUG            
+            // sdDebug(40000U + repCounter);
+#endif
         }
     }
     
@@ -1031,6 +1123,9 @@ implementation
         if((macState == RX) || (macState == CCA) || (macState == CCA_ACK)) {
             if(macState == CCA) {
                 computeBackoff();
+#ifdef REDMAC_PERFORMANCE
+                call Performance.macBusyOnCca();
+#endif
             }
             requestAdc();
             // sdDebug(230);
@@ -1065,12 +1160,22 @@ implementation
                 // sdDebug(243);
                 macState = TX;
                 setTxMode();
+#ifdef REDMAC_PERFORMANCE
+                call Performance.macIdleOnCca();
+                txStat.txModeTime = call LocalTime32khz.get();
+#endif
             }
         }
         else if(macState == CCA_ACK) {
             // sdDebug(244);
             macState = TX_ACK;
             setTxMode();
+            // sdDebug(20000 + getHeader(&ackMsg)->dest);
+#ifdef REDMAC_PERFORMANCE
+            call Performance.macTxAckStats(getHeader(&ackMsg)->type,
+                                          getHeader(&ackMsg)->dest,
+                                          getHeader(&ackMsg)->token);
+#endif
         }
     }
     
@@ -1097,24 +1202,39 @@ implementation
             else {
                 if(needsAckTx(txBufPtr)) {
                     // sdDebug(254);
+#ifdef REDMAC_PERFORMANCE
+                    call Performance.macAckTimeout();
+#endif
                     updateLongRetryCounters();
                 }
                 else {
-                    sdDebug(255);
+                    // 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 {
-                 sdDebug(257);
-                 checkSend();
+                 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)) {
@@ -1141,7 +1261,7 @@ implementation
     }
     
     async event void SampleTimer.fired() {
-        call SampleTimer.start(sleepTime);
+        call SampleTimer.start(localSleeptime);
         // sdDebug(270);
         if((macState == SLEEP) && (!isFlagSet(&flags, SWITCHING))) {
             clearFlag(&flags, ACTION_DETECTED);
@@ -1154,10 +1274,20 @@ implementation
         post ageMsgsTask();
     }
 
-    /***** SleepTime **********************************/
-    async command void SleepTime.setSleepTime(uint16_t sT) {
+    /***** 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 {
-            sleepTime = sT;
+            networkSleeptime = sT;
             for(MIN_BACKOFF_MASK = 1; MIN_BACKOFF_MASK < sT; ) {
                 MIN_BACKOFF_MASK = (MIN_BACKOFF_MASK << 1) + 1;
             }
@@ -1165,9 +1295,9 @@ implementation
         }
     }
     
-    async command uint16_t SleepTime.getSleepTime() {
+    async command uint16_t Sleeptime.getNetworkSleeptime() {
         uint16_t st;
-        atomic st = sleepTime;
+        atomic st = networkSleeptime;
         return st;
     }
 
@@ -1188,7 +1318,7 @@ implementation
     event void ChannelMonitorControl.updateNoiseFloorDone() {
         if(macState == INIT) {
             // sdDebug(290);
-            call Timer.start(call Random.rand16() % DEFAULT_SLEEP_TIME);
+            call Timer.start(call Random.rand16() % localSleeptime);
             setSleepMode();
         } else {
             // sdDebug(291);
@@ -1242,7 +1372,7 @@ implementation
     }
     
     default async event void ChannelCongestion.congestionEvent(uint8_t level) {}
-    
+
     /***** unused Radio Modes events **************************/
     
     async event void RadioModes.TimerModeDone() {}