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 + -
显示快捷键?