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