⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 rssifixedthresholdcmp.nc

📁 tinyos-2.x.rar
💻 NC
字号:
/* -*- 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.
 *
 * - Revision -------------------------------------------------------------
 * $Revision: 1.6 $
 * $Date: 2008/08/14 13:14:09 $
 * @author: Kevin Klues (klues@tkn.tu-berlin.de)
 * @author: Philipp Huppertz (huppertz@tkn.tu-berlin.de)
 * @author: Andreas Koepke (koepke@tkn.tu-berlin.de)
 * ========================================================================
 */

includes shellsort;
module RssiFixedThresholdCMP {
    provides {
      interface Init;
      interface StdControl;
      interface ChannelMonitor;
      interface ChannelMonitorControl;
      interface ChannelMonitorData;
      interface BatteryLevel;
    }
    uses {
        interface ReadNow<uint16_t> as Rssi;
        interface Read<uint16_t> as Voltage;
        interface Timer<TMilli> as Timer;
#ifdef RSSI_FIXED_DEBUG
        interface SerialDebug;
#endif
    }
}
implementation
{
#ifdef RSSI_FIXED_DEBUG
    void sdDebug(uint16_t p) {
        call SerialDebug.putPlace(p);
    }
#else
    void sdDebug(uint16_t p) {};
#endif

    /* Measure internal voltage every 20s */
#define VOLTAGE_SAMPLE_INTERVALL 20000

    /* 
     * Number of samples for noisefloor estimation
     * Actually the size of the array for the median
     */
#define NSAMPLES 5
        
    /*
     * If the channel is seen more then DEADLOCK times 
     * in a row busy, update noisefloor nonetheless.
     */
#define DEADLOCK 10
        
    /* 
     * Initital noisefloor from data sheet ca. 350mV 
     * Seems to depend on many things, usually values around
     * 250 mV are observed for the eyesIFXv2 node, but 450 has also 
     * been measured as noise floor. It is also not stable, depending
     * on the placement of the node (USB cable shielding!) 
     */
#define NOISE_FLOOR 480 // raw value compared to 3V

    // mu + 3*sigma -> rare event, outlier? 
#define THREE_SIGMA          145

    // 75 mV measured against 3V Vcc 
#define INITIAL_BUSY_DELTA   100
    
    // 3000/2 mV measured against 2.5V Ref
#define INITIAL_BATTERY_LEVEL 2457 

    /*** calibration stuff *************************/
#define UPDATE_NF_RUNS   10
#define MINIMUM_POSITION 0
#define RSSI_SAMPLE_INTERVALL   20 // it makes no sense to check the channel too often

    /*** variable type definitions ******************/
    typedef enum {
        VOID,
        CALIBRATE, // update noisefloor
        IDLE,      // noisefloor up to date, nothing is currently attempted
        CCA,       // in clear channel assessment
        SNR        // measureing SNR
    } state_t;
    
    /****************  Variables  *******************/
    state_t state;       // what we try to do
    int16_t gradient;    // how to convert mV to dB in mV/dB

    uint16_t noisefloor;       // [raw value against Vcc]
    uint16_t batteryLevel;     // [raw value against 2.5V ref]
    
    /* if the rssi value exceeds noisefloor + busyDelta
     * the channel is busy
     */
    uint16_t busyDelta;    // [raw value against Vcc]
    
    // noise floor estimation
    uint16_t rssisamples[NSAMPLES];
    uint8_t rssiindex;

    // deadlock protection counter
    uint8_t deadlockCounter;

    // last rssi reading
    uint16_t rssi;           // rssi in [mV]
    
    /****************  Tasks  *******************/
    task void UpdateNoiseFloorTask();
    // task void GetChannelStateTask();
    task void SnrReadyTask();
    task void CalibrateNoiseFloorTask();
    // task void GetSnrTask();
    task void CalibrateTask();
    task void GetVoltageTask();

    /***************** Helper function *************/

    int16_t computeSNR(uint16_t r) {
        uint32_t delta;
        uint16_t snr;
        if(r > noisefloor) {
             delta = r - noisefloor;
             // speedily cacluate
             // (2*batteryLevel*2500mV*delta)/(4095*4095*gradient)
             snr = ((((uint32_t)batteryLevel*39)>>5)*delta>>12)/gradient;
        } else {
            snr = 0;
        }
        return snr;
    }
    /**************** Init *******************/
    command error_t Init.init() {
        atomic {
            noisefloor = NOISE_FLOOR;
            rssiindex = 0;
            batteryLevel = INITIAL_BATTERY_LEVEL;
            busyDelta = INITIAL_BUSY_DELTA;
            state = VOID;
            gradient = 14; // gradient of TDA5250
            /* call Led3.makeOutput(); 
               call Led3.clr(); */
        }
#ifdef RSSI_FIXED_DEBUG
        call SerialDebug.putShortDesc("Rssi");
#endif
        return SUCCESS;
    }
    
    /**************** StdControl *******************/   
    command error_t StdControl.start() { 
        return post GetVoltageTask();
    }
   
    command error_t StdControl.stop() {
        call Timer.stop();
        return SUCCESS;
    }
     
    /**************** RSSI *******************/

    inline void addSample(uint16_t data)  {
        if(rssiindex < NSAMPLES) rssisamples[rssiindex++] = data;
        deadlockCounter = 0;
        if(rssiindex >= NSAMPLES) post UpdateNoiseFloorTask();
    }

    error_t rssiRead() {
        return call Rssi.read();
    }
    
    async event void Rssi.readDone(error_t result, uint16_t data) {
        switch(state) {
            case CCA:
                state = IDLE;
                if(data < noisefloor + busyDelta) {
                    signal ChannelMonitor.channelIdle();
                    addSample(data);
                }
                else {
                    signal ChannelMonitor.channelBusy();
                    if(++deadlockCounter >= DEADLOCK) addSample(data);
                }
                break;
            case SNR:
                rssi = data;
                post SnrReadyTask();    
                break;
            case CALIBRATE:
                rssi = data;
                post CalibrateNoiseFloorTask();    
                break;
            default:
                break;
        }
    }
    

    /**************** Voltage *******************/
    void readVoltage() {
        if(call Voltage.read() != SUCCESS) post GetVoltageTask();
    }
    
    task void GetVoltageTask() {
        readVoltage();
    }
    
    event void Voltage.readDone(error_t result, uint16_t data) {
        uint16_t nbl;
        int16_t d;
        uint16_t nbD;
        uint16_t bD;
        if(result == SUCCESS) {
            nbl = (data + batteryLevel)>>1;
            atomic bD = busyDelta;
            d = batteryLevel - nbl;
            sdDebug(10000 + batteryLevel);
            sdDebug(20000 + data);
            sdDebug(30000 + nbl);
            sdDebug(40000U + busyDelta);
            if(d > 75 || d < -75) {
                // recalculate busyDelta,
                // noisefloor already adapted by floating
                nbD = ((uint32_t)batteryLevel*(uint32_t)busyDelta)/(uint32_t)nbl;
                atomic busyDelta = nbD;
                batteryLevel = nbl;
            }
            sdDebug(50000U + busyDelta);
        }
        else {
            post GetVoltageTask();
        }
    }
    
    /**************** ChannelMonitor *******************/  
    async command error_t ChannelMonitor.start() {
        error_t res = FAIL;
        atomic {
            if(state == IDLE) {
                res = rssiRead();
                if(res == SUCCESS) state = CCA;
            }
            else if(state == CCA) {
                res = SUCCESS;
            }
        }
        return res;
    }

    async command void ChannelMonitor.rxSuccess() {
        atomic {
            if((deadlockCounter > 0) && (deadlockCounter < DEADLOCK)) {
                --deadlockCounter;
            }
        }
    }
    
    task void UpdateNoiseFloorTask() {
        shellsort(rssisamples,NSAMPLES);
        atomic { 
            noisefloor = (5*noisefloor + rssisamples[NSAMPLES/2] + 3)/6;
            rssiindex = 0; 
        }
        sdDebug(60000U + noisefloor);
    }

    /**************** ChannelMonitorControl ************/ 

    command async error_t ChannelMonitorControl.updateNoiseFloor() {
        return post CalibrateTask();
    }

    task void CalibrateTask() {
        atomic {
            if((state != IDLE) && (state != VOID)) {
                post CalibrateTask();
            } else {
                state = CALIBRATE;
                deadlockCounter = 0;
                call Timer.stop();
                call Timer.startPeriodic(RSSI_SAMPLE_INTERVALL);
            }
        }
    }

    task void CalibrateNoiseFloorTask() {
        atomic {
            if(rssiindex < NSAMPLES) {
                rssisamples[rssiindex++] = rssi;
            } else { 
                shellsort(rssisamples,NSAMPLES);
                if(rssisamples[MINIMUM_POSITION] < noisefloor + THREE_SIGMA)  {
                    noisefloor = (7*noisefloor + rssisamples[NSAMPLES/2] + 4)/8;
                    ++deadlockCounter;
                }
                else {
                    noisefloor += THREE_SIGMA/8;
                }
                rssiindex = 0; 
            }
            if(deadlockCounter > UPDATE_NF_RUNS) {
                state = IDLE;
                deadlockCounter = 0;
                call Timer.stop();
                call Timer.startPeriodic(VOLTAGE_SAMPLE_INTERVALL);
                signal ChannelMonitorControl.updateNoiseFloorDone();
            }
        }
    }

    event void Timer.fired() {
        state_t s;
        atomic s = state;
        if(s != CALIBRATE) {
            readVoltage();
        } else {
            rssiRead();
        }
    }
    
    /**************** ChannelMonitorData ************/  
    async command void ChannelMonitorData.setGradient(int16_t grad) {
        // needed to convert RSSI into dB
        atomic gradient = grad;
    }
    
    async command int16_t ChannelMonitorData.getGradient() {
        int16_t v;
        atomic v = gradient;
        return v;
    }
    
    async command uint16_t ChannelMonitorData.getNoiseFloor() {
        uint16_t v;
        atomic v = noisefloor;
        return v;
    }

    async command error_t ChannelMonitorData.getSnr() {
        error_t res = FAIL;
        atomic {
            if(state == IDLE) {
                res = rssiRead();
                if(res == SUCCESS) state = SNR;
            }
            else if(state == SNR) {
                res = SUCCESS;
            }
        }
        return res;
    }

    task void SnrReadyTask() {
        int16_t snr;
        state_t s;
        uint16_t r;
        atomic {
            r = rssi;
            s = state;
            if(state == SNR) state = IDLE;
        }
        if(s == SNR) {
            snr = computeSNR(r);
            signal ChannelMonitorData.getSnrDone(snr);
        }
    }

    async command uint16_t ChannelMonitorData.readSnr() {
        uint16_t rval;
        if(rssi > noisefloor) {
            rval = (rssi-noisefloor)>>4;
        } else {
            rval = 3;
        }
        return rval;
    }
    
    default async event void ChannelMonitorData.getSnrDone(int16_t snr) {
    }

    /***** BatteryLevel ***************/
    // get the batterylevel in mV
    async command uint16_t BatteryLevel.getLevel() {
        uint16_t l;
        atomic l = batteryLevel;
        return (uint32_t)(l+3)*6/5;
    }
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -