📄 randomcollisionlayerp.nc
字号:
/* * Copyright (c) 2007, Vanderbilt University * 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 following * two paragraphs and the author appear in all copies of this software. * * IN NO EVENT SHALL THE VANDERBILT UNIVERSITY BE LIABLE TO ANY PARTY FOR * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT * OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF THE VANDERBILT * UNIVERSITY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * THE VANDERBILT UNIVERSITY SPECIFICALLY DISCLAIMS ANY WARRANTIES, * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY * AND FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS * ON AN "AS IS" BASIS, AND THE VANDERBILT UNIVERSITY HAS NO OBLIGATION TO * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS. * * Author: Miklos Maroti */#include <Tasklet.h>#include <RadioAssert.h>module RandomCollisionLayerP{ provides { interface RadioSend; interface RadioReceive; } uses { interface RadioSend as SubSend; interface RadioReceive as SubReceive; interface RadioAlarm; interface Random; interface RandomCollisionConfig as Config; }}implementation{ tasklet_norace uint8_t state; enum { STATE_READY = 0, STATE_TX_PENDING_FIRST = 1, STATE_TX_PENDING_SECOND = 2, STATE_TX_SENDING = 3, STATE_BARRIER = 0x80, }; tasklet_norace message_t *txMsg; tasklet_norace uint16_t txBarrier; tasklet_async event void SubSend.ready() { if( state == STATE_READY && call RadioAlarm.isFree() ) signal RadioSend.ready(); } uint16_t nextRandom; task void calcNextRandom() { uint16_t a = call Random.rand16(); atomic nextRandom = a; } uint16_t getBackoff(uint16_t maxBackoff) { uint16_t a; atomic { a = nextRandom; nextRandom += 273; } post calcNextRandom(); return (a % maxBackoff) + call Config.getMinimumBackoff(); } tasklet_async command error_t RadioSend.send(message_t* msg) { if( state != STATE_READY || ! call RadioAlarm.isFree() ) return EBUSY; txMsg = msg; state = STATE_TX_PENDING_FIRST; call RadioAlarm.wait(getBackoff(call Config.getInitialBackoff(msg))); return SUCCESS; } tasklet_async event void RadioAlarm.fired() { error_t error; int16_t delay; ASSERT( state != STATE_READY ); delay = (int16_t)txBarrier - call RadioAlarm.getNow(); if( state == STATE_BARRIER ) { state = STATE_READY; signal RadioSend.ready(); return; } else if( (state & STATE_BARRIER) && delay > 0 ) error = EBUSY; else error = call SubSend.send(txMsg); if( error != SUCCESS ) { if( (state & ~STATE_BARRIER) == STATE_TX_PENDING_FIRST ) { state = (state & STATE_BARRIER) | STATE_TX_PENDING_SECOND; call RadioAlarm.wait(getBackoff(call Config.getCongestionBackoff(txMsg))); } else { if( (state & STATE_BARRIER) && delay > 0 ) { state = STATE_BARRIER; call RadioAlarm.wait(delay); } else state = STATE_READY; signal RadioSend.sendDone(error); } } else state = STATE_TX_SENDING; } tasklet_async event void SubSend.sendDone(error_t error) { ASSERT( state == STATE_TX_SENDING ); state = STATE_READY; signal RadioSend.sendDone(error); } tasklet_async event bool SubReceive.header(message_t* msg) { return signal RadioReceive.header(msg); } tasklet_async event message_t* SubReceive.receive(message_t* msg) { int16_t delay; txBarrier = call Config.getTransmitBarrier(msg); delay = txBarrier - call RadioAlarm.getNow(); if( delay > 0 ) { if( state == STATE_READY ) { call RadioAlarm.wait(delay); state = STATE_BARRIER; } else state |= STATE_BARRIER; } return signal RadioReceive.receive(msg); }}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -