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

📄 xe1205csmap.nc

📁 tinyos-2.x.rar
💻 NC
字号:
/* Copyright (c) 2007 Shockfish SA
*  All rights reserved.
*
*  Permission to use, copy, modify, and distribute this software and its
*  documentation for any purpose, without fee, and without written
*  agreement is hereby granted, provided that the above copyright
*  notice, the (updated) modification history and the author appear in
*  all copies of this source code.
*
*  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 HOLDERS OR CONTRIBUTORS
*  BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
*  CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, LOSS OF USE, DATA,
*  OR PROFITS) 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.
*/

/**
 * @author Maxime Muller
 *
 */

#include "XE1205.h"
#include "XE1205LowPowerListening.h"

#define MAX(X,Y) X>Y ? X:Y

module XE1205CsmaP {

    provides {
	interface Init @atleastonce();
	interface SplitControl @atleastonce();
	interface Send;
	interface Receive;
	interface CsmaControl;
	interface LPLControl;
	interface CsmaBackoff[am_id_t amId];
    }
    uses {
	interface SplitControl as SubControl;
	interface Receive as SubReceive;
	interface Send as SubSend;
	interface XE1205PhyRssi as Rssi;
	interface XE1205PhyConf as RadioConf;
	interface Timer<TMilli> as BackoffTimer;
	interface Random;
    }
}
implementation {

    enum {
	RADIO_DISABLED,
	RADIO_IDLE,
	RADIO_RX,
	RADIO_TX,
    };

    uint8_t rState;
    uint8_t rxRssi;
    uint8_t clrRssi;
    norace uint8_t rssiSampleCnt;
    bool enableCCA;

    message_t * txMsg;
    uint8_t txLen;
    enum {
	RSSI_RX = 0,
	RSSI_CLR = 1,
    };
    uint16_t MA_LENGTH = 8;
    uint8_t MAX_RSSI_SAMPLE = 4;
    norace float RSSI_RX_MA;
    norace float RSSI_CLR_MA;
    
    /*
     * function prototypes
     */

    task void readRssi();
    task void send();
    
    command error_t Init.init() {
	rssiSampleCnt=0;
	rState = RADIO_DISABLED;
	RSSI_RX_MA = RSSI_ABOVE_85;
	RSSI_CLR_MA = RSSI_90_TO_85;
	return SUCCESS;
    }
    
    command error_t SplitControl.start() {
	return call SubControl.start();
    }

    event void SubControl.startDone(error_t err) {
	if (err!=SUCCESS) {
	    atomic {
	    if (rState == RADIO_TX)
		signal Send.sendDone(txMsg,FAIL);
	    else 
		signal SplitControl.startDone(err);
	    }
	} else {
	    atomic {
		if (rState == RADIO_TX) {
		    if(enableCCA==TRUE) {
			if(SUCCESS != post readRssi()) {
			    signal Send.sendDone(txMsg,FAIL);
			}
			return;
		    }
		    else {
			post send();
			return;
			if (SUCCESS != post send()) {
			    signal Send.sendDone(txMsg,FAIL);
			    return;
			}
		    }
		}
		signal SplitControl.startDone(err);
	    }
	}
    }

    command error_t SplitControl.stop() { 

	return call SubControl.stop();
    }

    event void SubControl.stopDone(error_t err) {
	atomic {
	if (rState == RADIO_RX) // LPL: shutdown if no activity
	    if (err==SUCCESS)
		 rState = RADIO_IDLE;
	}
	signal SplitControl.stopDone(err);
    }



    void updateRssiMA(uint8_t maType, uint8_t value) {

	switch (maType) {
	case RSSI_CLR:
	    if((float)value < MAX(RSSI_RX_MA,RSSI_CLR_MA))
		RSSI_CLR_MA = (RSSI_CLR_MA*(MA_LENGTH - 1)+ value )/(MA_LENGTH);
	    break;
	    
	case RSSI_RX:
	    RSSI_RX_MA  = (RSSI_RX_MA*(MA_LENGTH - 1)+ value )/(MA_LENGTH);
	    break;

	default:
	    break;
	}
    }

    event message_t *SubReceive.receive(message_t* msg, void* payload, uint8_t len){
	
	uint8_t strgth = ((xe1205_metadata_t*)((uint8_t*)msg->footer + sizeof(xe1205_footer_t)))->strength;
	updateRssiMA(RSSI_RX, strgth);
	return signal Receive.receive(msg, payload, len);
    }

    command error_t Send.send(message_t* msg, uint8_t len) {
	error_t err;
	atomic {
	    switch (rState) {

	    case RADIO_DISABLED:
		return EOFF;

	    default:
	
		rState = RADIO_TX;
		atomic txMsg = msg;
		atomic txLen = len;
		err = call SubControl.start();
		return err;
	    }
	}
    }
    
    task void send() {
	if (SUCCESS != call SubSend.send(txMsg, txLen)) {
	    atomic rState = RADIO_IDLE;
	    signal Send.sendDone(txMsg, FAIL);	 
	}
    }

    event void SubSend.sendDone(message_t *msg, error_t err) {
	atomic rState = RADIO_IDLE;
	signal Send.sendDone(msg, err);
    }

    command void* Send.getPayload(message_t* m,uint8_t len) {
	return m->data;
    }

    command uint8_t Send.maxPayloadLength() {
	return TOSH_DATA_LENGTH;
    }

    command error_t Send.cancel( message_t* p_msg ) {
	return FAIL;
    }

    task void readRssi() {
	if(SUCCESS!=call Rssi.getRssi()) {
	 
	    atomic {
	    if (rState == RADIO_TX) {    
		signal Send.sendDone(txMsg, FAIL);
	    } else {
		signal SplitControl.startDone(FAIL);
	    }
	    }
	}
    }


    event void BackoffTimer.fired() {
	rssiSampleCnt = 0;
	if(SUCCESS != post send()) {
	    atomic rState = RADIO_IDLE;
	    signal Send.sendDone(txMsg,FAIL);
	}
    }
    async event void Rssi.rssiDone(uint8_t val) {
	
	updateRssiMA(RSSI_CLR, val);
	atomic {
	    if (rState == RADIO_DISABLED) {
		rState = RADIO_IDLE;
		signal SplitControl.startDone(SUCCESS);
		return;
	    }
	}

	// RX for LPL only
	atomic {
	if (rState == RADIO_RX) {
	    if (RSSI_CLR_MA >= (float)val) { // go back to sleep
		call SubControl.stop();
		return;
	    } else
		// tell lpl layer we have some activity
		signal SplitControl.startDone(SUCCESS);
	}
	
	// TX
	if (rState == RADIO_TX) {
	    rssiSampleCnt++;
	    if ( RSSI_RX_MA >= (float)val || RSSI_CLR_MA >= (float)val || !enableCCA) { // it's a go
		if (enableCCA) {
		    call BackoffTimer.startOneShot(signal CsmaBackoff.initial[((xe1205_header_t*)(txMsg->data -  sizeof(xe1205_header_t)))->type](txMsg));
		} else
		    post send();
		return;
	    }
	    else 
		if (enableCCA && rssiSampleCnt < MAX_RSSI_SAMPLE) {
		    post readRssi();
		} else {
		    call BackoffTimer.startOneShot(signal CsmaBackoff.congestion[((xe1205_header_t*)(txMsg->data -  sizeof(xe1205_header_t)))->type](txMsg));
		}
	    }
	}
    }
    
    async command void LPLControl.setMode(uint8_t mode) {
	switch (mode) {

	case RX:
	    atomic {
		if(rState!=RADIO_TX)
		    rState = RADIO_RX;
	    }
	    break;

	case IDLE:
	    atomic rState = RADIO_IDLE;

	default:
	    return;
	}
    }
    
    async command void CsmaControl.enableCca() {
	atomic enableCCA = TRUE;
    }
    
    async command void CsmaControl.disableCca() {
	atomic enableCCA = FALSE;
    }

 default async event uint16_t CsmaBackoff.initial[am_id_t amId](message_t *m) { 
     return (call Random.rand16() & 0x07) + 1;
 }
 
 default async event uint16_t CsmaBackoff.congestion[am_id_t amId](message_t *m) { 
     return (call Random.rand16() & 0xF) + 1;
 }

}

⌨️ 快捷键说明

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