csmamacp.nc
来自「tinyos-2.x.rar」· NC 代码 · 共 999 行 · 第 1/2 页
NC
999 行
/* -*- mode:c++; indent-tabs-mode: nil -*-
* Copyright (c) 2004-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.
*
*/
#include "radiopacketfunctions.h"
#include "flagfunctions.h"
#include "PacketAck.h"
/**
* An implementation of a Csma Mac.
*
* @author: Andreas Koepke (koepke@tkn.tu-berlin.de)
* @author: Kevin Klues (klues@tkn.tu-berlin.de)
* @author Philipp Huppertz (huppertz@tkn.tu-berlin.de)
*/
// #define MACM_DEBUG // debug...
module CsmaMacP {
provides {
interface Init;
interface SplitControl;
interface MacSend;
interface MacReceive;
interface Packet;
}
uses {
interface StdControl as CcaStdControl;
interface PhySend as PacketSend;
interface PhyReceive as PacketReceive;
interface RadioTimeStamping;
interface Tda5250Control as RadioModes;
interface ResourceRequested as RadioResourceRequested;
interface UartPhyControl;
interface Packet as SubPacket;
interface ChannelMonitor;
interface ChannelMonitorControl;
interface ChannelMonitorData;
interface Resource as RssiAdcResource;
interface Random;
interface Timer<TMilli> as ReRxTimer;
interface Duplicate;
interface TimeDiff16;
interface Alarm<T32khz, uint16_t> as Timer;
async command am_addr_t amAddress();
interface LocalTime<T32khz> as LocalTime32kHz;
#ifdef MACM_DEBUG
interface GeneralIO as Led0;
interface GeneralIO as Led1;
interface GeneralIO as Led2;
interface GeneralIO as Led3;
#endif
}
}
implementation
{
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(tda5250_header_t)*BYTE_TIME,
SUB_FOOTER_TIME=2*BYTE_TIME, // 2 bytes crc
MAXTIMERVALUE=0xFFFF, // helps to compute backoff
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 + 2*ADDED_DELAY,
TX_GAP_TIME=RX_ACK_TIMEOUT + TX_SETUP_TIME + 33,
MAX_SHORT_RETRY=7,
MAX_LONG_RETRY=4,
BACKOFF_MASK=0xFFF, // minimum time around one packet time
MIN_PREAMBLE_BYTES=2,
TOKEN_ACK_FLAG = 64,
TOKEN_ACK_MASK = 0x3f,
INVALID_SNR = 0xffff
};
/**************** Module Global Variables *****************/
/* state vars & defs */
typedef enum {
CCA, // clear channel assessment
CCA_ACK,
SW_RX, // switch to receive
RX, // rx mode done, listening & waiting for packet
SW_RX_ACK,
RX_ACK,
RX_ACK_P,
RX_P,
SW_TX,
TX,
SW_TX_ACK,
TX_ACK,
INIT
} macState_t;
/* flags */
typedef enum {
RSSI_STABLE = 1,
RESUME_BACKOFF = 2,
CANCEL_SEND = 4,
CCA_PENDING = 8
} flags_t;
/* Packet vars */
message_t* txBufPtr;
message_t ackMsg;
uint8_t txLen;
uint8_t shortRetryCounter;
uint8_t longRetryCounter;
unsigned checkCounter;
macState_t macState;
uint8_t flags;
uint8_t seqNo;
uint16_t restLaufzeit;
uint16_t rssiValue = 0;
uint32_t rxTime = 0;
/****** debug vars & defs & functions ***********************/
#ifdef MACM_DEBUG
#define HISTORY_ENTRIES 100
typedef struct {
int index;
macState_t state;
int place;
} history_t;
history_t history[HISTORY_ENTRIES];
unsigned histIndex;
void storeOldState(int p) {
atomic {
history[histIndex].index = histIndex;
history[histIndex].state = macState;
history[histIndex].place = p;
histIndex++;
if(histIndex >= HISTORY_ENTRIES) histIndex = 0;
}
}
#else
void storeOldState(int p) {};
#endif
void signalFailure(uint8_t place) {
#ifdef MACM_DEBUG
unsigned long i;
atomic {
for(;;) {
call Led0.set();
call Led1.clr();
call Led2.clr();
call Led3.clr();
for(i = 0; i < 1000000; i++) {
;
}
(place & 1) ? call Led0.set() : call Led0.clr();
(place & 2) ? call Led1.set() : call Led1.clr();
(place & 4) ? call Led2.set() : call Led2.clr();
(place & 8) ? call Led3.set() : call Led3.clr();
for(i = 0; i < 1000000; i++) {
;
}
(macState & 1) ? call Led0.set() : call Led0.clr();
(macState & 2) ? call Led1.set() : call Led1.clr();
(macState & 4) ? call Led2.set() : call Led2.clr();
(macState & 8) ? call Led3.set() : call Led3.clr();
for(i = 0; i < 1000000; i++) {
;
}
}
}
#endif
}
void signalMacState() {
#ifdef MACM_DEBUG
/*
(macState & 1) ? call Led0.set() : call Led0.clr();
(macState & 2) ? call Led1.set() : call Led1.clr();
(macState & 4) ? call Led2.set() : call Led2.clr();
(macState & 8) ? call Led3.set() : call Led3.clr();
*/
#endif
}
/****** Secure switching of radio modes ***/
task void SetRxModeTask();
task void SetTxModeTask();
task void ReleaseAdcTask() {
macState_t ms;
atomic ms = macState;
if(isFlagSet(&flags, CCA_PENDING)) {
post ReleaseAdcTask();
}
else {
if((ms > CCA) && (ms != INIT) && call RssiAdcResource.isOwner()) {
call RssiAdcResource.release();
}
}
}
void setRxMode();
void setTxMode();
void requestAdc() {
if(macState != INIT) {
call RssiAdcResource.immediateRequest();
}
else {
call RssiAdcResource.request();
}
}
void setRxMode() {
rssiValue = INVALID_SNR;
if(call RadioModes.RxMode() == FAIL) {
post SetRxModeTask();
}
if(macState == INIT) {
requestAdc();
} else {
post ReleaseAdcTask();
}
}
task void SetRxModeTask() {
atomic {
if((macState == SW_RX) ||
(macState == SW_RX_ACK) ||
(macState == INIT)) setRxMode();
}
}
void setTxMode() {
clearFlag(&flags, RSSI_STABLE);
if(call RadioModes.TxMode() == FAIL) {
post SetTxModeTask();
}
post ReleaseAdcTask();
}
task void SetTxModeTask() {
atomic {
if((macState == SW_TX) ||
(macState == SW_TX_ACK)) setTxMode();
}
}
/**************** Helper functions ********/
task void postponeReRx() {
call ReRxTimer.startOneShot(5000);
}
uint16_t backoff(uint8_t counter) {
uint16_t mask = BACKOFF_MASK >> (MAX_LONG_RETRY - counter);
return (call Random.rand16() & mask);
}
void interruptBackoffTimer() {
if(call Timer.isRunning()) {
restLaufzeit = call TimeDiff16.computeDelta(call Timer.getAlarm(), call Timer.getNow());
call Timer.stop();
if(restLaufzeit > BACKOFF_MASK) {
restLaufzeit = call Random.rand16() & 0xFF;
}
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;
atomic {
m = txBufPtr;
txBufPtr = 0;
txLen = 0;
longRetryCounter = 0;
shortRetryCounter = 0;
if(isFlagSet(&flags, CANCEL_SEND)) {
e = ECANCEL;
}
storeStrength(m);
clearFlag(&flags, CANCEL_SEND);
}
signal MacSend.sendDone(m, e);
}
void updateLongRetryCounters() {
longRetryCounter++;
shortRetryCounter = 1;
if(longRetryCounter > MAX_LONG_RETRY) {
storeOldState(13);
getMetadata(txBufPtr)->ack = WAS_NOT_ACKED;
signalSendDone(FAIL);
}
}
void updateRetryCounters() {
shortRetryCounter++;
if(shortRetryCounter > MAX_SHORT_RETRY) {
longRetryCounter++;
shortRetryCounter = 1;
if(longRetryCounter > MAX_LONG_RETRY) {
getMetadata(txBufPtr)->ack = WAS_NOT_ACKED;
signalSendDone(FAIL);
}
}
}
void computeBackoff() {
if(!isFlagSet(&flags, RESUME_BACKOFF)) {
setFlag(&flags, RESUME_BACKOFF);
restLaufzeit = backoff(longRetryCounter);
updateRetryCounters();
storeOldState(92);
}
}
bool isNewMsg(message_t* msg) {
return call Duplicate.isNew(getHeader(msg)->src, getHeader(msg)->dest,
(getHeader(msg)->token) & TOKEN_ACK_MASK);
}
void rememberMsg(message_t* msg) {
call Duplicate.remember(getHeader(msg)->src, getHeader(msg)->dest,
(getHeader(msg)->token) & TOKEN_ACK_MASK);
}
void checkSend() {
if((txBufPtr != NULL) && (macState == RX) && (!call Timer.isRunning())) {
macState = CCA;
signalMacState();
checkCounter = 0;
requestAdc();
call Timer.start(DATA_DETECT_TIME);
storeOldState(170);
}
else {
storeOldState(171);
post ReleaseAdcTask();
}
}
bool needsAckRx(message_t* msg) {
bool rVal = FALSE;
uint8_t token;
if(getHeader(msg)->dest < AM_BROADCAST_ADDR) {
token = getHeader(msg)->token;
if(isFlagSet(&token, ACK_REQUESTED)) rVal = TRUE;
}
return rVal;
}
bool needsAckTx(message_t* msg) {
bool rVal = FALSE;
if(getHeader(msg)->dest < AM_BROADCAST_ADDR) {
if((getMetadata(msg)->ack == ACK_REQUESTED) || (getMetadata(msg)->ack != NO_ACK_REQUESTED)) {
rVal = TRUE;
}
}
return rVal;
}
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;
}
bool msgIsForMe(message_t* msg) {
if(getHeader(msg)->dest == AM_BROADCAST_ADDR) return TRUE;
if(getHeader(msg)->dest == call amAddress()) return TRUE;
return FALSE;
}
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;
}
bool isControl(message_t* m) {
uint8_t token = getHeader(m)->token;
return isFlagSet(&token, TOKEN_ACK_FLAG);
}
/**************** Init ************************/
command error_t Init.init(){
atomic {
txBufPtr = NULL;
macState = INIT;
signalMacState();
shortRetryCounter = 0;
longRetryCounter = 0;
flags = 0;
#ifdef MACM_DEBUG
histIndex = 0;
#endif
}
return SUCCESS;
}
/**************** SplitControl *****************/
task void StartDoneTask() {
atomic {
macState = RX;
signalMacState();
call UartPhyControl.setNumPreambles(MIN_PREAMBLE_BYTES);
}
post ReleaseAdcTask();
signal SplitControl.startDone(SUCCESS);
}
command error_t SplitControl.start() {
call CcaStdControl.start();
atomic {
macState = INIT;
signalMacState();
setRxMode();
storeOldState(1);
}
return SUCCESS;
}
task void StopDone() {
atomic {
if (macState != RX) {
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?