[Tinyos-2-commits] CVS: tinyos-2.x/apps/tests/rf230/RF230Sniffer
Makefile, NONE, 1.1 RF230Config.nc, NONE, 1.1 RF230LayerC.nc,
NONE, 1.1 RF230LayerP.nc, NONE, 1.1 RF230SnifferC.nc, NONE,
1.1 RF230SnifferP.nc, NONE, 1.1 RadioWait.nc, NONE, 1.1
Janos Sallai
sallai at users.sourceforge.net
Tue Nov 6 11:41:30 PST 2007
Update of /cvsroot/tinyos/tinyos-2.x/apps/tests/rf230/RF230Sniffer
In directory sc8-pr-cvs10.sourceforge.net:/tmp/cvs-serv27196/RF230Sniffer
Added Files:
Makefile RF230Config.nc RF230LayerC.nc RF230LayerP.nc
RF230SnifferC.nc RF230SnifferP.nc RadioWait.nc
Log Message:
added rf230 test applications for the IRIS mote
--- NEW FILE: Makefile ---
COMPONENT=RF230SnifferC
IEEE154_CHANNEL ?= 11
CFLAGS += -DCC240_DEF_CHANNEL=$(IEEE154_CHANNEL)
CFLAGS += -DRF230_DEF_CHANNEL=$(IEEE154_CHANNEL)
CFLAGS += -I$(TOSDIR)/lib/diagmsg
CFLAGS += -DTASKLET_IS_TASK
CFLAGS += -DDIAGMSG_RECORDED_MSGS=60
include $(MAKERULES)
--- NEW FILE: RF230Config.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
*/
/**
* This interface needs to be implemented by the MAC to control the behaviour
* of the RF230LayerC component.
*/
interface RF230Config
{
/**
* Returns the length of the PHY payload (including the FCF field).
* This value must be in the range [3, 127].
*/
async command uint8_t getLength(message_t* msg);
/**
* Sets the length of the PHY payload.
*/
async command void setLength(message_t* msg, uint8_t len);
/**
* Returns a pointer to the start of the PHY payload that contains
* getLength()-2 number of bytes. The FCF field (CRC-16) is not stored,
* but automatically appended / verified.
*/
async command uint8_t* getPayload(message_t* msg);
/**
* Sets the timestamp (when the message was sent or received)
*/
async command void setTimestamp(message_t* msg, uint16_t time);
/**
* Sets the link quality indicator field for the received message
*/
async command void setLinkQuality(message_t* msg, uint8_t lqi);
/**
* Gets the number of bytes we should read before the RadioReceive.header
* event is fired. If the length of the packet is less than this amount,
* then that event is fired earlier.
*/
async command uint8_t getHeaderLength();
/**
* Returns the maximum PHY length that can be set via the setLength command
*/
async command uint8_t getMaxLength();
/**
* Returns the transmit power for the given message, this must be a value
* in the range [0, 15] which will be stored in the PHY_TX_PWR register.
*/
async command uint8_t getTransmitPower(message_t* msg);
/**
* This command is used at power up to set the default channel.
* The default CC2420 channel is 26.
*/
async command uint8_t getDefaultChannel();
}
--- NEW FILE: RF230LayerC.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
*/
configuration RF230LayerC
{
provides
{
interface Init as PlatformInit @exactlyonce();
interface RadioState;
interface RadioSend;
interface RadioReceive;
interface RadioCCA;
interface RadioWait;
interface Tasklet as RadioTasklet;
}
uses
{
interface RF230Config;
}
}
implementation
{
components RF230LayerP, HplRF230C, BusyWaitMicroC, TaskletC, MainC;
PlatformInit = RF230LayerP.PlatformInit;
RadioState = RF230LayerP;
RadioSend = RF230LayerP;
RadioReceive = RF230LayerP;
RadioCCA = RF230LayerP;
RadioWait = RF230LayerP;
RadioTasklet = RF230LayerP;
RF230Config = RF230LayerP;
RF230LayerP.SELN -> HplRF230C.SELN;
RF230LayerP.SpiResource -> HplRF230C.SpiResource;
RF230LayerP.SpiByte -> HplRF230C;
RF230LayerP.HplRF230 -> HplRF230C;
RF230LayerP.SLP_TR -> HplRF230C.SLP_TR;
RF230LayerP.RSTN -> HplRF230C.RSTN;
RF230LayerP.IRQ -> HplRF230C.IRQ;
RF230LayerP.Alarm -> HplRF230C.Alarm;
RF230LayerP.Tasklet -> TaskletC;
RF230LayerP.BusyWait -> BusyWaitMicroC;
components DiagMsgC, AssertC;
RF230LayerP.DiagMsg -> DiagMsgC;
MainC.SoftwareInit -> RF230LayerP.SoftwareInit;
}
--- NEW FILE: RF230LayerP.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 <RF230.h>
#include <HplRF230.h>
#include <Tasklet.h>
#include <RadioAssert.h>
module RF230LayerP
{
provides
{
interface Init as PlatformInit;
interface Init as SoftwareInit;
interface RadioState;
interface RadioSend;
interface RadioReceive;
interface RadioCCA;
interface RadioWait;
interface Tasklet as RadioTasklet;
}
uses
{
interface GeneralIO as SELN;
interface Resource as SpiResource;
interface SpiByte;
interface HplRF230;
interface GeneralIO as SLP_TR;
interface GeneralIO as RSTN;
interface GpioCapture as IRQ;
interface Alarm<TRF230, uint16_t>;
interface BusyWait<TMicro, uint16_t>;
interface RF230Config;
interface Tasklet;
interface DiagMsg;
}
}
implementation
{
/*----------------- STATE -----------------*/
tasklet_norace uint8_t state;
enum
{
STATE_P_ON = 0,
STATE_SLEEP = 1,
STATE_SLEEP_2_TRX_OFF = 2,
STATE_TRX_OFF = 3,
STATE_TRX_OFF_2_RX_ON = 4,
STATE_RX_ON = 5,
STATE_BUSY_TX_2_RX_ON = 6,
};
tasklet_norace uint8_t cmd;
enum
{
CMD_NONE = 0, // the state machine has stopped
CMD_WAIT = 1, // RadioWait timeout is irqs
CMD_TURNOFF = 2, // goto SLEEP state
CMD_STANDBY = 3, // goto TRX_OFF state
CMD_TURNON = 4, // goto RX_ON state
CMD_TRANSMIT = 5, // currently transmitting a message
CMD_RECEIVE = 6, // currently receiving a message
CMD_CCA = 7, // performing clear chanel assesment
CMD_CHANNEL = 8, // changing the channel
CMD_SIGNAL_DONE = 9, // signal the end of the state transition
CMD_DOWNLOAD = 10, // download the received message
};
uint8_t interrupts;
enum
{
IRQ_ALARM = 0x01,
IRQ_RADIO = 0x02,
};
inline uint8_t getInterrupts()
{
uint8_t s;
atomic s = interrupts;
return s;
}
tasklet_norace uint8_t txPower;
tasklet_norace uint8_t channel;
tasklet_norace message_t* rxMsg;
message_t rxMsgBuffer;
uint16_t capturedTime; // the current time when the last interrupt has occured
/*----------------- REGISTER -----------------*/
inline void writeRegister(uint8_t reg, uint8_t value)
{
ASSERT( call SpiResource.isOwner() );
reg = RF230_CMD_REGISTER_WRITE | (reg & RF230_CMD_REGISTER_MASK);
call SELN.clr();
call HplRF230.spiWrite(reg);
call HplRF230.spiWrite(value);
call SELN.set();
}
inline uint8_t readRegister(uint8_t reg)
{
ASSERT( call SpiResource.isOwner() );
reg = RF230_CMD_REGISTER_READ | (reg & RF230_CMD_REGISTER_MASK);
call SELN.clr();
call HplRF230.spiWrite(reg);
reg = call HplRF230.spiWrite(0);
call SELN.set();
return reg;
}
/*----------------- ALARM -----------------*/
enum
{
SLEEP_WAKEUP_TIME = (uint16_t)(880 * RF230_ALARM_MICROSEC),
CCA_REQUEST_TIME = (uint16_t)(140 * RF230_ALARM_MICROSEC),
TX_SFD_DELAY = (uint16_t)(176 * RF230_ALARM_MICROSEC),
RX_SFD_DELAY = (uint16_t)(8 * RF230_ALARM_MICROSEC),
};
void startAlarm(uint16_t time)
{
call Alarm.start(time);
}
async event void Alarm.fired()
{
ASSERT( ! (getInterrupts() & IRQ_ALARM) );
atomic interrupts |= IRQ_ALARM;
call Tasklet.schedule();
}
inline void serviceAlarm()
{
if( state == STATE_SLEEP_2_TRX_OFF )
state = STATE_TRX_OFF;
else if( cmd == CMD_CCA )
{
uint8_t cca;
ASSERT( state == STATE_RX_ON );
cmd = CMD_NONE;
cca = readRegister(RF230_TRX_STATUS);
signal RadioCCA.done( (cca & RF230_CCA_DONE) ? ((cca & RF230_CCA_STATUS) ? SUCCESS : EBUSY) : FAIL );
}
else if( cmd == CMD_WAIT )
{
ASSERT( state == STATE_RX_ON || state == STATE_TRX_OFF || state == STATE_SLEEP );
cmd = CMD_NONE;
signal RadioWait.fired();
}
}
/*----------------- WAIT -----------------*/
void cancelUserWait()
{
if( cmd == CMD_WAIT )
{
call Alarm.stop();
atomic interrupts &= ~IRQ_ALARM;
cmd = CMD_NONE;
}
}
async command uint16_t RadioWait.getNow()
{
return call Alarm.getNow();
}
tasklet_async command void RadioWait.cancel()
{
}
tasklet_async command error_t RadioWait.wait(uint16_t time)
{
if( cmd > CMD_WAIT )
return EBUSY;
else if( cmd == CMD_WAIT )
call Alarm.stop();
atomic interrupts &= ~IRQ_ALARM;
call Alarm.start(time);
cmd = CMD_WAIT;
return SUCCESS;
}
default tasklet_async event void RadioWait.fired()
{
}
/*----------------- INIT -----------------*/
command error_t PlatformInit.init()
{
call SELN.makeOutput();
call SELN.set();
call SLP_TR.makeOutput();
call SLP_TR.clr();
call RSTN.makeOutput();
call RSTN.set();
rxMsg = &rxMsgBuffer;
return SUCCESS;
}
command error_t SoftwareInit.init()
{
return call SpiResource.request();
}
void initRadio()
{
if( call DiagMsg.record() )
{
call DiagMsg.str("power on");
call DiagMsg.send();
}
call BusyWait.wait(510);
call RSTN.clr();
call SLP_TR.clr();
call BusyWait.wait(6);
call RSTN.set();
writeRegister(RF230_TRX_CTRL_0, RF230_TRX_CTRL_0_VALUE);
writeRegister(RF230_TRX_STATE, RF230_TRX_OFF);
call BusyWait.wait(510);
writeRegister(RF230_IRQ_MASK, RF230_IRQ_TRX_UR | RF230_IRQ_PLL_UNLOCK | RF230_IRQ_PLL_LOCK | RF230_IRQ_TRX_END | RF230_IRQ_RX_START);
writeRegister(RF230_CCA_THRES, RF230_CCA_THRES_VALUE);
writeRegister(RF230_PHY_TX_PWR, RF230_TX_AUTO_CRC_ON | RF230_TX_PWR_DEFAULT);
txPower = RF230_TX_PWR_DEFAULT;
channel = call RF230Config.getDefaultChannel() & RF230_CHANNEL_MASK;
writeRegister(RF230_PHY_CC_CCA, RF230_CCA_MODE_VALUE | channel);
// writeRegister(RF230_XOSC_CTRL, RF230_XTAL_MODE_INTERNAL | 15);
call SLP_TR.set();
state = STATE_SLEEP;
}
/*----------------- SPI -----------------*/
event void SpiResource.granted()
{
// TODO: this should not be here, see my comment in HplRF230C.nc
call SELN.set();
if( state == STATE_P_ON )
{
initRadio();
call SpiResource.release();
}
else
call Tasklet.schedule();
}
bool isSpiAcquired()
{
if( call SpiResource.isOwner() )
return TRUE;
if( call SpiResource.immediateRequest() == SUCCESS )
{
// TODO: this should not be here, see my comment in HplRF230C.nc
call SELN.set();
return TRUE;
}
call SpiResource.request();
return FALSE;
}
/*----------------- CHANNEL -----------------*/
tasklet_async command error_t RadioState.setChannel(uint8_t c)
{
c &= RF230_CHANNEL_MASK;
if( cmd > CMD_WAIT )
return EBUSY;
else if( channel == c )
return EALREADY;
cancelUserWait();
channel = c;
cmd = CMD_CHANNEL;
call Tasklet.schedule();
return SUCCESS;
}
inline void changeChannel()
{
ASSERT( cmd == CMD_CHANNEL );
ASSERT( state == STATE_SLEEP || state == STATE_TRX_OFF || state == STATE_RX_ON );
if( isSpiAcquired() )
{
writeRegister(RF230_PHY_CC_CCA, RF230_CCA_MODE_VALUE | channel);
if( state == STATE_RX_ON )
state = STATE_TRX_OFF_2_RX_ON;
else
cmd = CMD_SIGNAL_DONE;
}
}
/*----------------- TURN ON/OFF -----------------*/
inline void changeState()
{
if( (cmd == CMD_STANDBY || cmd == CMD_TURNON)
&& state == STATE_SLEEP )
{
call SLP_TR.clr();
startAlarm(SLEEP_WAKEUP_TIME);
state = STATE_SLEEP_2_TRX_OFF;
}
else if( cmd == CMD_TURNON && state == STATE_TRX_OFF && isSpiAcquired() )
{
call IRQ.captureRisingEdge();
writeRegister(RF230_TRX_STATE, RF230_RX_ON);
state = STATE_TRX_OFF_2_RX_ON;
}
else if( (cmd == CMD_TURNOFF || cmd == CMD_STANDBY)
&& state == STATE_RX_ON && isSpiAcquired() )
{
call IRQ.disable();
writeRegister(RF230_TRX_STATE, RF230_FORCE_TRX_OFF);
state = STATE_TRX_OFF;
}
if( cmd == CMD_TURNOFF && state == STATE_TRX_OFF )
{
call SLP_TR.set();
state = STATE_SLEEP;
cmd = CMD_SIGNAL_DONE;
}
else if( cmd == CMD_STANDBY && state == STATE_TRX_OFF )
cmd = CMD_SIGNAL_DONE;
}
tasklet_async command error_t RadioState.turnOff()
{
if( cmd > CMD_WAIT )
return EBUSY;
else if( state == STATE_SLEEP )
return EALREADY;
cancelUserWait();
cmd = CMD_TURNOFF;
call Tasklet.schedule();
return SUCCESS;
}
tasklet_async command error_t RadioState.standby()
{
if( cmd > CMD_WAIT )
return EBUSY;
else if( state == STATE_TRX_OFF )
return EALREADY;
cancelUserWait();
cmd = CMD_STANDBY;
call Tasklet.schedule();
return SUCCESS;
}
tasklet_async command error_t RadioState.turnOn()
{
if( cmd > CMD_WAIT )
return EBUSY;
else if( state == STATE_RX_ON )
return EALREADY;
cancelUserWait();
cmd = CMD_TURNON;
call Tasklet.schedule();
return SUCCESS;
}
default tasklet_async event void RadioState.done()
{
}
/*----------------- TRANSMIT -----------------*/
tasklet_async command error_t RadioSend.send(message_t* msg)
{
uint16_t time;
uint8_t length;
uint8_t* data;
if( cmd > CMD_WAIT || state != STATE_RX_ON || ! isSpiAcquired() )
return EBUSY;
length = call RF230Config.getTransmitPower(msg) & RF230_TX_PWR_MASK;
if( length != txPower )
{
txPower = length;
writeRegister(RF230_PHY_TX_PWR, RF230_TX_AUTO_CRC_ON | txPower);
}
writeRegister(RF230_TRX_STATE, RF230_PLL_ON);
// wait a little for the command to complete
length = call RF230Config.getLength(msg);
data = call RF230Config.getPayload(msg);
// maybe we are currently receiving a message
if( (readRegister(RF230_TRX_STATUS) & RF230_TRX_STATUS_MASK) != RF230_PLL_ON )
{
writeRegister(RF230_TRX_STATE, RF230_RX_ON);
return EBUSY;
}
cancelUserWait();
if( call DiagMsg.record() )
{
call DiagMsg.str("tx");
call DiagMsg.uint8(length);
call DiagMsg.hex8s(data, length - 2);
call DiagMsg.send();
}
atomic
{
call SLP_TR.set();
time = call Alarm.getNow();
}
call SLP_TR.clr();
// write the length first to buy some time
call SELN.clr();
call HplRF230.spiWrite(RF230_CMD_FRAME_WRITE);
// length | data[0] ... data[length-3] | automatically generated FCS
call HplRF230.spiWrite(length);
// the FCF is atomatically generated
length -= 2;
do
{
// TODO: we could do this faster with split access like for download
call HplRF230.spiWrite(*(data++));
}
while( --length != 0 );
call SELN.set();
// wait for the TRX_END interrupt
time += TX_SFD_DELAY;
call RF230Config.setTimestamp(msg, time);
// go back to RX_ON state when finished
writeRegister(RF230_TRX_STATE, RF230_RX_ON);
state = STATE_BUSY_TX_2_RX_ON;
cmd = CMD_TRANSMIT;
return SUCCESS;
}
default tasklet_async event void RadioSend.sendDone(error_t error)
{
}
/*----------------- CCA -----------------*/
tasklet_async command error_t RadioCCA.request()
{
if( cmd > CMD_WAIT || state != STATE_RX_ON || ! isSpiAcquired() )
return EBUSY;
cancelUserWait();
// see Errata B7 of the datasheet
// writeRegister(RF230_TRX_STATE, RF230_PLL_ON);
// writeRegister(RF230_TRX_STATE, RF230_RX_ON);
writeRegister(RF230_PHY_CC_CCA, RF230_CCA_REQUEST | RF230_CCA_MODE_VALUE | channel);
startAlarm(CCA_REQUEST_TIME);
cmd = CMD_CCA;
return SUCCESS;
}
default tasklet_async event void RadioCCA.done(error_t error)
{
}
/*----------------- RECEIVE -----------------*/
tasklet_norace uint16_t rx_start_time;
tasklet_norace uint16_t trx_end_time;
inline void downloadMessage()
{
uint8_t length;
uint16_t crc;
call SELN.clr();
call HplRF230.spiWrite(RF230_CMD_FRAME_READ);
// read the length byte
length = call HplRF230.spiWrite(0);
// if correct length
if( length >= 3 && length <= call RF230Config.getMaxLength() )
{
uint8_t read;
uint8_t* data;
// initiate the reading
call HplRF230.spiSplitWrite(0);
call RF230Config.setLength(rxMsg, length);
data = call RF230Config.getPayload(rxMsg);
crc = 0;
// we do not store the CRC field
length -= 2;
read = call RF230Config.getHeaderLength();
if( length < read )
read = length;
length -= read;
while( read-- != 0 )
crc = call HplRF230.crcByte(crc, *(data++) = call HplRF230.spiSplitReadWrite(0));
if( signal RadioReceive.header(rxMsg) )
{
while( length-- != 0 )
crc = call HplRF230.crcByte(crc, *(data++) = call HplRF230.spiSplitReadWrite(0));
crc = call HplRF230.crcByte(crc, call HplRF230.spiSplitReadWrite(0));
crc = call HplRF230.crcByte(crc, call HplRF230.spiSplitReadWrite(0));
call RF230Config.setLinkQuality(rxMsg, call HplRF230.spiSplitRead());
}
else
crc = 1;
}
else
crc = 1;
call SELN.set();
state = STATE_RX_ON;
if( call DiagMsg.record() )
{
length = call RF230Config.getLength(rxMsg);
call DiagMsg.uint16(rx_start_time);
call DiagMsg.uint16(trx_end_time);
call DiagMsg.uint8(length);
call DiagMsg.uint8(crc != 0);
call DiagMsg.hex8s(call RF230Config.getPayload(rxMsg), length - 2);
call DiagMsg.send();
}
cmd = CMD_NONE;
// signal only if it has passed the CRC check
if( crc == 0 )
rxMsg = signal RadioReceive.receive(rxMsg);
}
/*----------------- IRQ -----------------*/
async event void IRQ.captured(uint16_t time)
{
ASSERT( ! (getInterrupts() & IRQ_RADIO) );
atomic
{
capturedTime = time;
interrupts |= IRQ_RADIO;
}
call Tasklet.schedule();
}
void serviceRadio()
{
if( isSpiAcquired() )
{
uint16_t time;
uint8_t radioIrq;
atomic time = capturedTime;
radioIrq = readRegister(RF230_IRQ_STATUS);
// TODO: handle this interrupt
ASSERT( ! (radioIrq & RF230_IRQ_TRX_UR) );
// TODO: handle this interrupt
ASSERT( ! (radioIrq & RF230_IRQ_PLL_UNLOCK) );
if( radioIrq & RF230_IRQ_PLL_LOCK )
{
if( cmd == CMD_TURNON || cmd == CMD_CHANNEL )
{
ASSERT( state == STATE_TRX_OFF_2_RX_ON );
state = STATE_RX_ON;
cmd = CMD_SIGNAL_DONE;
}
else if( cmd == CMD_TRANSMIT )
{
ASSERT( state == STATE_BUSY_TX_2_RX_ON );
}
else
ASSERT(FALSE);
}
if( radioIrq & RF230_IRQ_RX_START )
{
if( cmd == CMD_CCA )
{
signal RadioCCA.done(FAIL);
cmd = CMD_NONE;
}
if( cmd == CMD_NONE )
{
rx_start_time = time;
/*
* The timestamp corresponds to the first event which could not
* have been a PLL_LOCK because then cmd != CMD_NONE, so we must
* have received a message (and could also have received the
* TRX_END interrupt in the mean time, but that is fine. Also,
* we could not be after a transmission, because then cmd =
* CMD_TRANSMIT.
*/
call RF230Config.setTimestamp(rxMsg, time - RX_SFD_DELAY);
cmd = CMD_RECEIVE;
}
}
if( radioIrq & RF230_IRQ_TRX_END )
{
if( cmd == CMD_TRANSMIT )
{
state = STATE_RX_ON;
cmd = CMD_NONE;
signal RadioSend.sendDone(SUCCESS);
// TODO: we could have missed a received message
ASSERT( ! (radioIrq & RF230_IRQ_RX_START) );
}
else if( cmd == CMD_RECEIVE )
{
trx_end_time = time;
cmd = CMD_DOWNLOAD;
}
else
ASSERT(FALSE);
}
}
else
atomic interrupts |= IRQ_RADIO;
}
default tasklet_async event bool RadioReceive.header(message_t* msg)
{
return TRUE;
}
default tasklet_async event message_t* RadioReceive.receive(message_t* msg)
{
return msg;
}
/*----------------- TASKLET -----------------*/
inline async command void RadioTasklet.schedule()
{
call Tasklet.schedule();
}
inline command void RadioTasklet.suspend()
{
call Tasklet.suspend();
}
inline command void RadioTasklet.resume()
{
call Tasklet.resume();
}
default tasklet_async event void RadioTasklet.run()
{
}
tasklet_async event void Tasklet.run()
{
uint8_t irqs;
atomic
{
irqs = interrupts;
interrupts = 0;
}
if( irqs != 0 )
{
if( irqs & IRQ_RADIO )
serviceRadio();
else if( irqs & IRQ_ALARM )
serviceAlarm();
}
if( cmd != CMD_NONE )
{
if( CMD_TURNOFF <= cmd && cmd <= CMD_TURNON )
changeState();
else if( cmd == CMD_CHANNEL )
changeChannel();
else if( cmd == CMD_DOWNLOAD )
downloadMessage();
if( cmd == CMD_SIGNAL_DONE )
{
cmd = CMD_NONE;
signal RadioState.done();
}
}
if( cmd == CMD_NONE )
signal RadioTasklet.run();
if( cmd == CMD_NONE )
call SpiResource.release();
}
}
--- NEW FILE: RF230SnifferC.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
*/
configuration RF230SnifferC
{
}
implementation
{
components RF230SnifferP, MainC, SerialActiveMessageC, RF230LayerC, IEEE154PacketC;
RF230SnifferP.Boot -> MainC;
RF230SnifferP.SplitControl -> SerialActiveMessageC;
RF230SnifferP.RadioState -> RF230LayerC;
RF230SnifferP.IEEE154Packet -> IEEE154PacketC;
RF230LayerC.RF230Config -> RF230SnifferP;
}
--- NEW FILE: RF230SnifferP.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 <DefaultMac.h>
#include <message.h>
module RF230SnifferP
{
uses
{
interface Boot;
interface SplitControl;
interface RadioState;
interface IEEE154Packet;
}
provides
{
interface RF230Config;
}
}
implementation
{
task void serialPowerUp()
{
if( call SplitControl.start() != SUCCESS )
post serialPowerUp();
}
event void SplitControl.startDone(error_t error)
{
if( error != SUCCESS )
post serialPowerUp();
else
call RadioState.turnOn();
}
event void SplitControl.stopDone(error_t error)
{
}
event void Boot.booted()
{
post serialPowerUp();
}
tasklet_async event void RadioState.done()
{
}
async command uint8_t RF230Config.getLength(message_t* msg)
{
return call IEEE154Packet.getLength(msg);
}
async command void RF230Config.setLength(message_t* msg, uint8_t len)
{
call IEEE154Packet.setLength(msg, len);
}
async command uint8_t* RF230Config.getPayload(message_t* msg)
{
return ((uint8_t*)(call IEEE154Packet.getHeader(msg))) + 1;
}
inline defaultmac_metadata_t* getMeta(message_t* msg)
{
return (defaultmac_metadata_t*)(msg->metadata);
}
async command void RF230Config.setTimestamp(message_t* msg, uint16_t time)
{
getMeta(msg)->timestamp = time;
}
async command void RF230Config.setLinkQuality(message_t* msg, uint8_t lqi)
{
getMeta(msg)->lqi = lqi;
}
async command uint8_t RF230Config.getHeaderLength()
{
// we need the fcf, dsn, destpan and dest
return 7;
}
async command uint8_t RF230Config.getMaxLength()
{
// note, that the ieee154_footer_t is not stored, but we should include it here
return sizeof(defaultmac_header_t) - 1 + TOSH_DATA_LENGTH + sizeof(ieee154_footer_t);
}
async command uint8_t RF230Config.getTransmitPower(message_t* msg)
{
return 0;
}
async command uint8_t RF230Config.getDefaultChannel()
{
return RF230_DEF_CHANNEL;
}
}
--- NEW FILE: RadioWait.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>
interface RadioWait
{
/**
* Cancels all pending waits and waits till the specified timeout period
* expires. Returns FAIL if another event will surely be fired.
*/
tasklet_async command error_t wait(uint16_t timeout);
/**
* Cancels the running alarm
*/
tasklet_async command void cancel();
/**
* This event is fired when the specified timeout period expires. For
*/
tasklet_async event void fired();
/**
* Returns the current time as measured by the radio stack.
*/
async command uint16_t getNow();
}
More information about the Tinyos-2-commits
mailing list