📄 speckmacdp.nc
字号:
/* -*- 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;#ifdef MAC_EVAL interface MacEval;#endif } uses { interface StdControl as CcaStdControl; interface PhySend as PacketSend; interface PhyReceive as PacketReceive; interface RadioTimeStamping; interface Tda5250Control as RadioModes; interface UartPhyControl; interface ChannelMonitor; interface ChannelMonitorControl; interface ChannelMonitorData; interface Resource as RssiAdcResource; interface Random; interface Packet as SubPacket; interface Alarm<T32khz, uint16_t> as Timer; interface Alarm<T32khz, uint16_t> as SampleTimer; interface LocalTime<T32khz> as LocalTime32kHz; interface Duplicate; interface TimeDiff16; interface TimeDiff32; 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=ENCODED_32KHZ_BYTE_TIME, // phy encoded PREAMBLE_BYTE_TIME=TDA5250_32KHZ_BYTE_TIME, // no coding PHY_HEADER_TIME=6*PREAMBLE_BYTE_TIME, // 6 Phy Preamble TIME_CORRECTION=TDA5250_32KHZ_BYTE_TIME+2, // difference between txSFD and rxSFD 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, NAV_FACTOR = 4,#ifndef MAC_EVAL MAX_SHORT_RETRY=9, MAX_LONG_RETRY=3, ADD_NAV = 4, INCREASE_BACKOFF = TRUE,#endif 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 *****************/#ifdef MAC_EVAL uint8_t MAX_SHORT_RETRY = 9; uint8_t MAX_LONG_RETRY = 3; uint8_t ADD_NAV = 4; bool INCREASE_BACKOFF = TRUE;#endif /* 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); 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() { 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(); 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())) { macState = CCA; checkCounter = 0; setRxMode(); } } uint32_t backoff(uint8_t counter) { uint32_t rVal = call Random.rand16() & MIN_BACKOFF_MASK; if(!INCREASE_BACKOFF) counter = 1; 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) { } else { } if(!call Timer.isRunning()) { } else { } if(!isFlagSet(&flags, RESUME_BACKOFF)) { } else { } 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(m))->strength = rssiValue; } else {
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -