From f139d40721e23194dd9e8f84e3652212ac990e36 Mon Sep 17 00:00:00 2001 From: andreaskoepke Date: Mon, 1 Oct 2007 15:48:58 +0000 Subject: [PATCH] added SpeckMac refactor MAC protocols: - separate duplicate suppression component - separate LocalTime component --- tos/chips/tda5250/mac/CsmaMacC.nc | 3 + tos/chips/tda5250/mac/CsmaMacP.nc | 86 +- tos/chips/tda5250/mac/Duplicate.h | 49 ++ tos/chips/tda5250/mac/Duplicate.nc | 43 + tos/chips/tda5250/mac/DuplicateC.nc | 50 ++ tos/chips/tda5250/mac/DuplicateP.nc | 109 +++ tos/chips/tda5250/mac/RedMacC.nc | 9 +- tos/chips/tda5250/mac/RedMacP.nc | 185 +--- tos/chips/tda5250/mac/SpeckMacDC.nc | 120 +++ tos/chips/tda5250/mac/SpeckMacDP.nc | 1229 +++++++++++++++++++++++++++ tos/platforms/eyesIFX/LocalTimeC.nc | 40 + tos/platforms/eyesIFX/LocalTimeP.nc | 64 ++ 12 files changed, 1776 insertions(+), 211 deletions(-) create mode 100644 tos/chips/tda5250/mac/Duplicate.h create mode 100644 tos/chips/tda5250/mac/Duplicate.nc create mode 100644 tos/chips/tda5250/mac/DuplicateC.nc create mode 100644 tos/chips/tda5250/mac/DuplicateP.nc create mode 100644 tos/chips/tda5250/mac/SpeckMacDC.nc create mode 100644 tos/chips/tda5250/mac/SpeckMacDP.nc create mode 100644 tos/platforms/eyesIFX/LocalTimeC.nc create mode 100644 tos/platforms/eyesIFX/LocalTimeP.nc diff --git a/tos/chips/tda5250/mac/CsmaMacC.nc b/tos/chips/tda5250/mac/CsmaMacC.nc index 499f3b78..9966cf8b 100644 --- a/tos/chips/tda5250/mac/CsmaMacC.nc +++ b/tos/chips/tda5250/mac/CsmaMacC.nc @@ -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; diff --git a/tos/chips/tda5250/mac/CsmaMacP.nc b/tos/chips/tda5250/mac/CsmaMacP.nc index bba168f6..46c19d3f 100644 --- a/tos/chips/tda5250/mac/CsmaMacP.nc +++ b/tos/chips/tda5250/mac/CsmaMacP.nc @@ -71,6 +71,7 @@ module CsmaMacP { interface Random; interface Timer as ReRxTimer; + interface Duplicate; interface Alarm 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 index 00000000..00c853d6 --- /dev/null +++ b/tos/chips/tda5250/mac/Duplicate.h @@ -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 index 00000000..2b3a19c1 --- /dev/null +++ b/tos/chips/tda5250/mac/Duplicate.nc @@ -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 index 00000000..b57c166b --- /dev/null +++ b/tos/chips/tda5250/mac/DuplicateC.nc @@ -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 index 00000000..b07b5686 --- /dev/null +++ b/tos/chips/tda5250/mac/DuplicateP.nc @@ -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 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; + } +} + diff --git a/tos/chips/tda5250/mac/RedMacC.nc b/tos/chips/tda5250/mac/RedMacC.nc index 469fe5ce..3421fe92 100644 --- a/tos/chips/tda5250/mac/RedMacC.nc +++ b/tos/chips/tda5250/mac/RedMacC.nc @@ -45,7 +45,6 @@ configuration RedMacC { interface MacSend; interface MacReceive; interface Packet; - interface LocalTime 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; diff --git a/tos/chips/tda5250/mac/RedMacP.nc b/tos/chips/tda5250/mac/RedMacP.nc index 5ea29ebe..41739aa3 100644 --- a/tos/chips/tda5250/mac/RedMacP.nc +++ b/tos/chips/tda5250/mac/RedMacP.nc @@ -46,7 +46,6 @@ module RedMacP { interface MacSend; interface MacReceive; interface Packet; - interface LocalTime as LocalTime32khz; interface Sleeptime; interface Teamgeist; interface ChannelCongestion; @@ -72,7 +71,10 @@ module RedMacP { interface Alarm as Timer; interface Alarm as SampleTimer; - interface Counter as Counter32khz16; + interface LocalTime 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 index 00000000..77b9bc83 --- /dev/null +++ b/tos/chips/tda5250/mac/SpeckMacDC.nc @@ -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 +#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 index 00000000..271cdd51 --- /dev/null +++ b/tos/chips/tda5250/mac/SpeckMacDP.nc @@ -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 as Timer; + interface Alarm as SampleTimer; + interface LocalTime 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 index 00000000..97be68bf --- /dev/null +++ b/tos/platforms/eyesIFX/LocalTimeC.nc @@ -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 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 index 00000000..87784227 --- /dev/null +++ b/tos/platforms/eyesIFX/LocalTimeP.nc @@ -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 as LocalTime32kHz; + } + uses { + interface Counter 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; + } +} + -- 2.39.2