]> oss.titaniummirror.com Git - tinyos-2.x.git/commitdiff
added rf230 test applications for the IRIS mote
authorsallai <sallai>
Tue, 6 Nov 2007 19:41:28 +0000 (19:41 +0000)
committersallai <sallai>
Tue, 6 Nov 2007 19:41:28 +0000 (19:41 +0000)
14 files changed:
apps/tests/rf230/RF230Sniffer/Makefile [new file with mode: 0644]
apps/tests/rf230/RF230Sniffer/RF230Config.nc [new file with mode: 0644]
apps/tests/rf230/RF230Sniffer/RF230LayerC.nc [new file with mode: 0644]
apps/tests/rf230/RF230Sniffer/RF230LayerP.nc [new file with mode: 0644]
apps/tests/rf230/RF230Sniffer/RF230SnifferC.nc [new file with mode: 0644]
apps/tests/rf230/RF230Sniffer/RF230SnifferP.nc [new file with mode: 0644]
apps/tests/rf230/RF230Sniffer/RadioWait.nc [new file with mode: 0644]
apps/tests/rf230/RF230Test/Makefile [new file with mode: 0644]
apps/tests/rf230/RF230Test/RF230TestC.nc [new file with mode: 0644]
apps/tests/rf230/RF230Test/RF230TestM.nc [new file with mode: 0644]
apps/tests/rf230/TestMac/Makefile [new file with mode: 0644]
apps/tests/rf230/TestMac/TestMac.h [new file with mode: 0644]
apps/tests/rf230/TestMac/TestMacC.nc [new file with mode: 0644]
apps/tests/rf230/TestMac/TestMacP.nc [new file with mode: 0644]

diff --git a/apps/tests/rf230/RF230Sniffer/Makefile b/apps/tests/rf230/RF230Sniffer/Makefile
new file mode 100644 (file)
index 0000000..5ce24c2
--- /dev/null
@@ -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 (file)
index 0000000..eaf5511
--- /dev/null
@@ -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 (file)
index 0000000..8aca409
--- /dev/null
@@ -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 (file)
index 0000000..4f5aa7e
--- /dev/null
@@ -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 <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();
+       }
+}
diff --git a/apps/tests/rf230/RF230Sniffer/RF230SnifferC.nc b/apps/tests/rf230/RF230Sniffer/RF230SnifferC.nc
new file mode 100644 (file)
index 0000000..cf22b7d
--- /dev/null
@@ -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 (file)
index 0000000..1aebc3d
--- /dev/null
@@ -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 <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;
+       }
+}
diff --git a/apps/tests/rf230/RF230Sniffer/RadioWait.nc b/apps/tests/rf230/RF230Sniffer/RadioWait.nc
new file mode 100644 (file)
index 0000000..3191bde
--- /dev/null
@@ -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 <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();
+}
diff --git a/apps/tests/rf230/RF230Test/Makefile b/apps/tests/rf230/RF230Test/Makefile
new file mode 100644 (file)
index 0000000..4cb2f0b
--- /dev/null
@@ -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 (file)
index 0000000..9bdc578
--- /dev/null
@@ -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 (file)
index 0000000..3fa947f
--- /dev/null
@@ -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 <Tasklet.h>
+
+module RF230TestM
+{
+       uses
+       {
+               interface Leds;
+               interface Boot;
+               interface DiagMsg;
+               interface SplitControl;
+               interface Timer<TMilli> 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 (file)
index 0000000..380940b
--- /dev/null
@@ -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 (file)
index 0000000..4045887
--- /dev/null
@@ -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 (file)
index 0000000..584c05f
--- /dev/null
@@ -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 (file)
index 0000000..2a88f49
--- /dev/null
@@ -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<TMilli> as SendTimer;
+               interface Timer<TMilli> 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);
+       }
+}