From: sallai Date: Tue, 6 Nov 2007 19:41:28 +0000 (+0000) Subject: added rf230 test applications for the IRIS mote X-Git-Tag: release_tinyos_2_1_0_0~667 X-Git-Url: https://oss.titaniummirror.com/gitweb/?p=tinyos-2.x.git;a=commitdiff_plain;h=ce269017dc4056d92b6ba42d4f903cef8286a96c added rf230 test applications for the IRIS mote --- diff --git a/apps/tests/rf230/RF230Sniffer/Makefile b/apps/tests/rf230/RF230Sniffer/Makefile new file mode 100644 index 00000000..5ce24c25 --- /dev/null +++ b/apps/tests/rf230/RF230Sniffer/Makefile @@ -0,0 +1,8 @@ +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) diff --git a/apps/tests/rf230/RF230Sniffer/RF230Config.nc b/apps/tests/rf230/RF230Sniffer/RF230Config.nc new file mode 100644 index 00000000..eaf55118 --- /dev/null +++ b/apps/tests/rf230/RF230Sniffer/RF230Config.nc @@ -0,0 +1,81 @@ +/* + * 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(); +} diff --git a/apps/tests/rf230/RF230Sniffer/RF230LayerC.nc b/apps/tests/rf230/RF230Sniffer/RF230LayerC.nc new file mode 100644 index 00000000..8aca4096 --- /dev/null +++ b/apps/tests/rf230/RF230Sniffer/RF230LayerC.nc @@ -0,0 +1,76 @@ +/* + * 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; +} diff --git a/apps/tests/rf230/RF230Sniffer/RF230LayerP.nc b/apps/tests/rf230/RF230Sniffer/RF230LayerP.nc new file mode 100644 index 00000000..4f5aa7e1 --- /dev/null +++ b/apps/tests/rf230/RF230Sniffer/RF230LayerP.nc @@ -0,0 +1,800 @@ +/* + * 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 +#include +#include +#include + +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; + + interface BusyWait; + + 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(); + } +} diff --git a/apps/tests/rf230/RF230Sniffer/RF230SnifferC.nc b/apps/tests/rf230/RF230Sniffer/RF230SnifferC.nc new file mode 100644 index 00000000..cf22b7dc --- /dev/null +++ b/apps/tests/rf230/RF230Sniffer/RF230SnifferC.nc @@ -0,0 +1,38 @@ +/* + * 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; +} diff --git a/apps/tests/rf230/RF230Sniffer/RF230SnifferP.nc b/apps/tests/rf230/RF230Sniffer/RF230SnifferP.nc new file mode 100644 index 00000000..1aebc3db --- /dev/null +++ b/apps/tests/rf230/RF230Sniffer/RF230SnifferP.nc @@ -0,0 +1,125 @@ +/* + * 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 +#include +#include + +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; + } +} diff --git a/apps/tests/rf230/RF230Sniffer/RadioWait.nc b/apps/tests/rf230/RF230Sniffer/RadioWait.nc new file mode 100644 index 00000000..3191bdea --- /dev/null +++ b/apps/tests/rf230/RF230Sniffer/RadioWait.nc @@ -0,0 +1,48 @@ +/* + * 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 + +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(); +} diff --git a/apps/tests/rf230/RF230Test/Makefile b/apps/tests/rf230/RF230Test/Makefile new file mode 100644 index 00000000..4cb2f0b2 --- /dev/null +++ b/apps/tests/rf230/RF230Test/Makefile @@ -0,0 +1,3 @@ +COMPONENT=RF230TestC +CFLAGS += -I$(TOSDIR)/lib/diagmsg +include $(MAKERULES) diff --git a/apps/tests/rf230/RF230Test/RF230TestC.nc b/apps/tests/rf230/RF230Test/RF230TestC.nc new file mode 100644 index 00000000..9bdc578f --- /dev/null +++ b/apps/tests/rf230/RF230Test/RF230TestC.nc @@ -0,0 +1,44 @@ +/* + * 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 RF230TestC +{ +} + +implementation +{ + components MainC, RF230TestM, LedsC; + components DiagMsgC, SerialActiveMessageC; + components new TimerMilliC(); + + RF230TestM.Boot -> MainC; + RF230TestM.Leds -> LedsC; + RF230TestM.DiagMsg -> DiagMsgC; + RF230TestM.SplitControl -> SerialActiveMessageC; + RF230TestM.Timer -> TimerMilliC; + + components RF230LayerC, DefaultMacC; + + RF230TestM.RadioState -> RF230LayerC; + RF230TestM.AMSend -> DefaultMacC; +} diff --git a/apps/tests/rf230/RF230Test/RF230TestM.nc b/apps/tests/rf230/RF230Test/RF230TestM.nc new file mode 100644 index 00000000..3fa947fb --- /dev/null +++ b/apps/tests/rf230/RF230Test/RF230TestM.nc @@ -0,0 +1,137 @@ +/* + * 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 + +module RF230TestM +{ + uses + { + interface Leds; + interface Boot; + interface DiagMsg; + interface SplitControl; + interface Timer as Timer; + + interface RadioState; + interface AMSend[am_id_t id]; + } +} + +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 Timer.startPeriodic(1000); + } + + event void SplitControl.stopDone(error_t error) + { + } + + event void Boot.booted() + { + call Leds.led0On(); + post serialPowerUp(); + } + + message_t testMsg; + + void testStateTransitions(uint8_t seqNo) + { + seqNo &= 15; + + if( seqNo == 1 ) + call RadioState.standby(); + else if( seqNo == 2 ) + call RadioState.turnOff(); + else if( seqNo == 3 ) + call RadioState.standby(); + else if( seqNo == 4 ) + call RadioState.turnOn(); + else if( seqNo == 5 ) + call RadioState.turnOff(); + else if( seqNo == 6 ) + call RadioState.turnOn(); + else if( seqNo == 7 ) + { + *(uint16_t*)(call AMSend.getPayload[111](&testMsg)) = seqNo; + call AMSend.send[111](0xFFFF, &testMsg, 2); + } + } + + void testTransmission(uint8_t seqNo) + { + uint8_t seqMod = seqNo & 15; + + if( seqMod == 1 ) + call RadioState.turnOn(); + else if( 2 <= seqMod && seqMod <= 14 ) + { + *(uint16_t*)(call AMSend.getPayload[111](&testMsg)) = seqNo; + call AMSend.send[111](0xFFFF, &testMsg, 2); + } + else if( seqMod == 15 ) + call RadioState.turnOff(); + } + + tasklet_async event void RadioState.done() + { + } + + event void AMSend.sendDone[am_id_t id](message_t* msg, error_t error) + { + } + + norace uint8_t payload[3]; + norace uint8_t receiveLength; + norace uint8_t receiveData[10]; + norace error_t receiveError; + + task void reportReceive() + { + if( call DiagMsg.record() ) + { + call DiagMsg.hex8s(receiveData, receiveLength); + call DiagMsg.uint8(receiveError); + call DiagMsg.send(); + } + } + + uint8_t seqNo; + event void Timer.fired() + { + ++seqNo; +// testStateTransitions(seqNo); + testTransmission(seqNo); + } +} diff --git a/apps/tests/rf230/TestMac/Makefile b/apps/tests/rf230/TestMac/Makefile new file mode 100644 index 00000000..380940b1 --- /dev/null +++ b/apps/tests/rf230/TestMac/Makefile @@ -0,0 +1,7 @@ +COMPONENT=TestMacC +CFLAGS += -I$(TOSDIR)/lib/diagmsg +IEEE154_CHANNEL ?= 11 +CFLAGS += -DCC240_DEF_CHANNEL=$(IEEE154_CHANNEL) +CFLAGS += -DRF230_DEF_CHANNEL=$(IEEE154_CHANNEL) +CFLAGS += -DRF230_DEBUG +include $(MAKERULES) diff --git a/apps/tests/rf230/TestMac/TestMac.h b/apps/tests/rf230/TestMac/TestMac.h new file mode 100644 index 00000000..40458873 --- /dev/null +++ b/apps/tests/rf230/TestMac/TestMac.h @@ -0,0 +1,87 @@ +/* + * 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 + */ + +#ifndef __TESTMAC_H__ +#define __TESTMAC_H__ + +/** + * SEND_RATE the rate in milliseconds a source message should be sent out, + * if this value is 0, then the message is sent from a task as fast as it can. + * Set this value to -1 for turning off source messages. + * + * SEND_SOURCE the id of the source message. Each ping message contains a source + * identifier and a sequence number. + * + * SEND_TARGET the active message address of the source messages sent out by + * this node. Use AM_BROADCAST_ADDR to broadcast the message. + * + * SEND_ACK if it is set to 1, then packet acknowledgements are requested, + * otherwise set it to 0 + * + * SOURCE_COUNT the number of data sources in the network whose progress we + * need to monitor. + */ + +// everybody transmit as fast as we can for up to five nodes with IDs 0 through 4 +#if TESTCASE == 0 +#define SOURCE_COUNT 5 +#define SEND_TARGET AM_BROADCAST_ADDR +#define SEND_SOURCE TOS_NODE_ID +#define SEND_RATE 0 +#define SEND_ACK 1 + +// one node sending message to another as fast as it can +#elif TESTCASE == 1 +#define SOURCE_COUNT 2 +#define SEND_TARGET 1 +#define SEND_SOURCE (TOS_NODE_ID == 0 ? 0 : -1) +#define SEND_RATE (TOS_NODE_ID == 0 ? 0 : -1) +#define SEND_ACK 1 + +// two nodes sending messages to one another 200 msgs per second +#elif TESTCASE == 2 +#define SOURCE_COUNT 2 +#define SEND_TARGET ((TOS_NODE_ID+1) % SOURCE_COUNT) +#define SEND_SOURCE TOS_NODE_ID +#define SEND_RATE 5 +#define SEND_ACK 1 + +// two nodes sending messages to one another as fast as they can +#elif TESTCASE == 3 +#define SOURCE_COUNT 2 +#define SEND_TARGET ((TOS_NODE_ID+1) % SOURCE_COUNT) +#define SEND_SOURCE TOS_NODE_ID +#define SEND_RATE 0 +#define SEND_ACK 1 + +// three nodes sending messages to one another as fast as they can +#elif TESTCASE == 4 +#define SOURCE_COUNT 3 +#define SEND_TARGET ((TOS_NODE_ID+1) % SOURCE_COUNT) +#define SEND_SOURCE TOS_NODE_ID +#define SEND_RATE 0 +#define SEND_ACK 1 + +#endif + +#endif//__TESTMAC_H__ diff --git a/apps/tests/rf230/TestMac/TestMacC.nc b/apps/tests/rf230/TestMac/TestMacC.nc new file mode 100644 index 00000000..584c05f3 --- /dev/null +++ b/apps/tests/rf230/TestMac/TestMacC.nc @@ -0,0 +1,47 @@ +/* + * 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 TestMacC +{ +} + +implementation +{ + components MainC, TestMacP, DiagMsgC; + components ActiveMessageC, SerialActiveMessageC; + components new TimerMilliC() as SendTimerC; + components new TimerMilliC() as ReportTimerC; + + TestMacP.Boot -> MainC; + TestMacP.DiagMsg -> DiagMsgC; + TestMacP.SendTimer -> SendTimerC; + TestMacP.ReportTimer -> ReportTimerC; + + TestMacP.SerialControl -> SerialActiveMessageC; + TestMacP.RadioControl -> ActiveMessageC; + + TestMacP.PacketAcknowledgements -> ActiveMessageC; + TestMacP.AMSend -> ActiveMessageC.AMSend[0x17]; + TestMacP.Receive -> ActiveMessageC.Receive[0x17]; + TestMacP.Snoop -> ActiveMessageC.Snoop[0x17]; +} diff --git a/apps/tests/rf230/TestMac/TestMacP.nc b/apps/tests/rf230/TestMac/TestMacP.nc new file mode 100644 index 00000000..2a88f49b --- /dev/null +++ b/apps/tests/rf230/TestMac/TestMacP.nc @@ -0,0 +1,209 @@ +/* + * 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 "TestMac.h" + +module TestMacP +{ + uses + { + interface Boot; + interface DiagMsg; + + interface Timer as SendTimer; + interface Timer as ReportTimer; + + interface Receive; + interface Receive as Snoop; + interface AMSend; + interface PacketAcknowledgements; + + interface SplitControl as SerialControl; + interface SplitControl as RadioControl; + } +} + +implementation +{ + task void serialPowerUp() + { + if( call SerialControl.start() != SUCCESS ) + post serialPowerUp(); + } + + event void Boot.booted() + { + post serialPowerUp(); + } + + task void radioPowerUp() + { + if( call RadioControl.start() != SUCCESS ) + post radioPowerUp(); + } + + event void SerialControl.startDone(error_t error) + { + if( error != SUCCESS ) + post serialPowerUp(); + else + post radioPowerUp(); + } + + void send(); + + task void sendTask() + { + send(); + } + + event void RadioControl.startDone(error_t error) + { + if( error != SUCCESS ) + post radioPowerUp(); + else + { + if( SEND_RATE > 0 ) + call SendTimer.startPeriodic(SEND_RATE); + else if( SEND_RATE == 0 ) + post sendTask(); + + call ReportTimer.startPeriodic(1000); + } + } + + event void SendTimer.fired() + { + send(); + } + + event void RadioControl.stopDone(error_t error) { } + event void SerialControl.stopDone(error_t error) { } + + typedef struct source_t + { + uint16_t sequence; + uint16_t failures; + uint16_t errors; + } source_t; + + source_t sources[SOURCE_COUNT]; + + message_t txMsg; + + typedef struct source_msg_t + { + uint8_t source; + uint16_t sequence; + uint8_t failures; + uint8_t errors; + uint8_t stuff[23]; + } source_msg_t; + + void send() + { + source_msg_t* data = (source_msg_t*)txMsg.data; + data->source = SEND_SOURCE; + data->sequence = sources[SEND_SOURCE].sequence; + data->failures = sources[SEND_SOURCE].failures; + data->errors = sources[SEND_SOURCE].errors; + + if( SEND_ACK ) + call PacketAcknowledgements.requestAck(&txMsg); + else + call PacketAcknowledgements.noAck(&txMsg); + + if( call AMSend.send(SEND_TARGET, &txMsg, sizeof(source_msg_t)) != SUCCESS ) + post sendTask(); + } + + event void AMSend.sendDone(message_t* msg, error_t error) + { + if( error != SUCCESS ) + { + sources[SEND_SOURCE].errors += 1; + post sendTask(); + } + else + { + if( SEND_ACK ) + { + if( ! call PacketAcknowledgements.wasAcked(msg) ) + sources[SEND_SOURCE].failures += 1; + } + + sources[SEND_SOURCE].sequence += 1; + + if( SEND_RATE == 0 ) + post sendTask(); + } + } + + event void ReportTimer.fired() + { + if( call DiagMsg.record() ) + { + uint8_t i; + + call DiagMsg.uint8(TOS_NODE_ID); + + for(i = 0; i < SOURCE_COUNT; ++i) + { + call DiagMsg.uint16(sources[i].sequence); + call DiagMsg.uint16(sources[i].failures); + call DiagMsg.uint16(sources[i].errors); + } + + call DiagMsg.send(); + } + } + + message_t* receive(message_t* msg) + { + source_msg_t* data = (source_msg_t*)(msg->data); + + if( data->source < SOURCE_COUNT && data->source != SEND_SOURCE ) + { + uint8_t source = data->source; + + if( sources[source].sequence == data->sequence ) + sources[source].errors += 1; + else + sources[source].failures += (uint16_t)(data->sequence - sources[source].sequence - 1); + + sources[source].sequence = data->sequence; + } + + return msg; + } + + event message_t* Receive.receive(message_t* msg, void* payload, uint8_t len) + { + return receive(msg); + } + + event message_t* Snoop.receive(message_t* msg, void* payload, uint8_t len) + { + return receive(msg); + } +}