speckmacdp.nc
来自「tinyos-2.x.rar」· NC 代码 · 共 1,172 行 · 第 1/3 页
NC
1,172 行
/* -*- 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
#ifndef DEFAULT_SLEEP_TIME
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,
#endif
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));
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 + =
减小字号Ctrl + -
显示快捷键?