📄 redmacp.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"#ifdef DELTATIMEDEBUG#include "DeltaTrace.h"#endifmodule RedMacP { provides { interface Init; interface SplitControl; interface MacSend; interface MacReceive; interface Packet; interface Sleeptime; interface Teamgeist; 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 REDMAC_DEBUG interface SerialDebug;#endif#ifdef REDMAC_PERFORMANCE interface Performance;#endif#ifdef DELTATIMEDEBUG interface DeltaTrace;#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 REDMAC_DEBUG void sdDebug(uint16_t p) { call SerialDebug.putPlace(p); } uint8_t repCounter;#else void sdDebug(uint16_t p) {};#endif #ifdef REDMAC_PERFORMANCE PfmTxMsg_t txStat; PfmRxMsg_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=2048, // DEFAULT_SLEEP_TIME=4096, // 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=3, MAX_LONG_RETRY=7, ADD_NAV = 2, 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 };#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#ifdef DELTATIMEDEBUG DeltaTrace_t dTrace;#endif /**************** Module Global Variables *****************/ /* flags */ typedef enum { SWITCHING = 1, RSSI_STABLE = 2, UNHANDLED_PACKET = 4, MESSAGE_PREPARED = 8, RESUME_BACKOFF = 16, CANCEL_SEND = 32, ACTION_DETECTED = 64, TEAMGEIST_ACTIVE=128 } 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; am_id_t teamgeistType = 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 REDMAC_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 REDMAC_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 REDMAC_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; 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, uint8_t *level) { bool rVal = FALSE; am_addr_t dest = getHeader(msg)->dest; uint8_t token; uint16_t snr = 1; if(dest < AM_BROADCAST_ADDR) { if(dest < RELIABLE_MCAST_MIN_ADDR) { token = getHeader(msg)->token; if(isFlagSet(&token, ACK_REQUESTED)) { rVal = TRUE; } } else { if(isFlagSet(&flags, TEAMGEIST_ACTIVE) && (getHeader(msg)->type == teamgeistType)) { if(rssiValue != INVALID_SNR) snr = rssiValue; *level = 2; rVal = signal Teamgeist.needsAck(msg, getHeader(msg)->src, getHeader(msg)->dest, snr); } } } 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 + TX_GAP_TIME) + 1; atomic { if((longRetryCounter > 1) && isFlagSet(&flags, TEAMGEIST_ACTIVE) && (getHeader(msg)->type == teamgeistType)) { getHeader(msg)->dest = signal Teamgeist.getDestination(msg, longRetryCounter - 1); } 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 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; } } 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; } } } 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;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -