From 36d09eaa6913295d07e85435eedfb46fd27c7105 Mon Sep 17 00:00:00 2001 From: fros4943 Date: Wed, 2 Dec 2009 16:39:42 +0000 Subject: [PATCH] requesting mote wakeup when receiving radio data + code cleanup (faster code) --- .../cooja/mspmote/interfaces/TR1001Radio.java | 209 ++++++++---------- .../mspmote/interfaces/TR1001RadioByte.java | 57 ----- .../TR1001RadioPacketConverter.java | 47 ++-- 3 files changed, 112 insertions(+), 201 deletions(-) delete mode 100644 tools/cooja/apps/mspsim/src/se/sics/cooja/mspmote/interfaces/TR1001RadioByte.java diff --git a/tools/cooja/apps/mspsim/src/se/sics/cooja/mspmote/interfaces/TR1001Radio.java b/tools/cooja/apps/mspsim/src/se/sics/cooja/mspmote/interfaces/TR1001Radio.java index d2563e649..34d60e913 100644 --- a/tools/cooja/apps/mspsim/src/se/sics/cooja/mspmote/interfaces/TR1001Radio.java +++ b/tools/cooja/apps/mspsim/src/se/sics/cooja/mspmote/interfaces/TR1001Radio.java @@ -26,7 +26,7 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * $Id: TR1001Radio.java,v 1.15 2009/10/28 15:58:43 fros4943 Exp $ + * $Id: TR1001Radio.java,v 1.16 2009/12/02 16:39:42 fros4943 Exp $ */ package se.sics.cooja.mspmote.interfaces; @@ -47,6 +47,7 @@ import javax.swing.JPanel; import org.apache.log4j.Logger; import org.jdom.Element; +import se.sics.cooja.COOJARadioPacket; import se.sics.cooja.ClassDescription; import se.sics.cooja.Mote; import se.sics.cooja.MoteTimeEvent; @@ -62,109 +63,96 @@ import se.sics.mspsim.core.USART; import se.sics.mspsim.core.USARTListener; /** - * TR1001 radio interface on ESB platform. Assumes driver specifics such as - * preambles, synchbytes, GCR coding, CRC16. + * TR1001 radio interface on ESB platform. + * Assumes Contiki driver specifics such as preambles, synchbytes, GCR coding, CRC16. * * @author Fredrik Osterlind */ @ClassDescription("TR1001 Radio") -public class TR1001Radio extends Radio implements USARTListener, - CustomDataRadio { +public class TR1001Radio extends Radio implements USARTListener, CustomDataRadio { private static Logger logger = Logger.getLogger(TR1001Radio.class); /** - * Delay used when feeding packet data to radio chip (us). 416us corresponds - * to 19200 bit/s with encoding. + * Cross-level: + * Delay used when feeding packet data to radio chip (us). + * 416us corresponds to 19200 bit/s with encoding. */ - public static final long DELAY_BETWEEN_BYTES = 3 * 416; + public static final long DELAY_BETWEEN_BYTES = 416; private ESBMote mote; - private boolean radioOn = true; - private boolean isTransmitting = false; - private boolean isReceiving = false; - private boolean isInterfered = false; private RadioEvent lastEvent = RadioEvent.UNKNOWN; - private long lastEventTime = 0; private USART radioUSART = null; - private RadioPacket lastIncomingPacket = null; + private RadioPacket receivedPacket = null; + private RadioPacket sentPacket = null; - private RadioPacket packetFromMote = null; - - /* Outgoing packet data buffer */ - private TR1001RadioByte[] outgoingData = new TR1001RadioByte[128]; /* TODO Adaptive max size */ - - private int outgoingDataLength = 0; - - private int millisSinceLastSend = -1; - - /* Outgoing byte data buffer */ - private TR1001RadioByte tr1001ByteFromMote = null; - - private TR1001RadioByte lastIncomingByte = null; - - private long transmissionStartCycles = -1; + private byte receivedByte, sentByte; private TR1001RadioPacketConverter tr1001PacketConverter = null; - private double signalStrength = 0; - + private boolean radioOn = true; /* TODO MSPSim: Not implemented */ + private double signalStrength = 0; /* TODO MSPSim: Not implemented */ + + /** * Creates an interface to the TR1001 radio at mote. * - * @param mote - * Radio's mote. - * @see Mote - * @see se.sics.cooja.MoteInterfaceHandler + * @param mote Mote */ public TR1001Radio(Mote mote) { this.mote = (ESBMote) mote; /* Start listening to CPU's USART */ IOUnit usart = this.mote.getCPU().getIOUnit("USART 0"); - if (usart instanceof USART) { + if (usart != null && usart instanceof USART) { radioUSART = (USART) usart; radioUSART.setUSARTListener(this); + } else { + throw new RuntimeException("Bad TR1001 IO: " + usart); } } /* Packet radio support */ public RadioPacket getLastPacketTransmitted() { - return packetFromMote; + return sentPacket; } public RadioPacket getLastPacketReceived() { - return lastIncomingPacket; + return receivedPacket; } public void setReceivedPacket(RadioPacket packet) { - lastIncomingPacket = packet; + receivedPacket = packet; /* Convert to TR1001 packet data */ - TR1001RadioByte[] byteArr = TR1001RadioPacketConverter.fromCoojaToTR1001(packet); - final ArrayDeque byteList = new ArrayDeque(); - for (TR1001RadioByte b : byteArr) { - byteList.addLast(b); + byte[] arr = TR1001RadioPacketConverter.fromCoojaToTR1001(packet); + final ArrayDeque data = new ArrayDeque(); + for (Byte b : arr) { + data.addLast(b); } /* Feed incoming bytes to radio "slowly" via time events */ TimeEvent receiveCrosslevelDataEvent = new MoteTimeEvent(mote, 0) { public void execute(long t) { /* Stop receiving data when buffer is empty */ - if (byteList.isEmpty() || isInterfered) { - byteList.clear(); + if (data.isEmpty()) { return; } - TR1001RadioByte b = byteList.pop(); - radioUSART.byteReceived(b.getByte()); + byte b = data.pop(); + if (isInterfered) { + radioUSART.byteReceived(0xFF); /* Corrupted data */ + } else { + radioUSART.byteReceived(b); + } + mote.requestImmediateWakeup(); mote.getSimulation().scheduleEvent(this, t + DELAY_BETWEEN_BYTES); } @@ -174,90 +162,83 @@ public class TR1001Radio extends Radio implements USARTListener, /* Custom data radio support */ public Object getLastCustomDataTransmitted() { - return tr1001ByteFromMote; + return sentByte; } public Object getLastCustomDataReceived() { - return lastIncomingByte; + return receivedByte; } public void receiveCustomData(Object data) { - if (data instanceof TR1001RadioByte) { - lastIncomingByte = ((TR1001RadioByte) data); + if (!(data instanceof Byte)) { + logger.fatal("Received bad custom data: " + data); + return; + } + receivedByte = (Byte) data; - if (radioUSART.isReceiveFlagCleared()) { - /*logger.info("----- TR1001 RECEIVED BYTE -----");*/ - radioUSART.byteReceived(lastIncomingByte.getByte()); + mote.requestImmediateWakeup(); + if (radioUSART.isReceiveFlagCleared()) { + /*logger.info("----- TR1001 RECEIVED BYTE -----");*/ + if (isInterfered) { + radioUSART.byteReceived(0xFF); /* Corrupted data */ } else { - logger.warn("----- TR1001 RECEIVED BYTE DROPPED -----"); + radioUSART.byteReceived(receivedByte); } + } else { + logger.warn(mote.getSimulation().getSimulationTime() + ": ----- TR1001 RECEIVED BYTE DROPPED -----"); } } /* USART listener support */ public void dataReceived(USART source, int data) { - if (outgoingDataLength == 0 && !isTransmitting()) { + if (!isTransmitting()) { /* New transmission discovered */ /*logger.info("----- NEW TR1001 TRANSMISSION DETECTED -----");*/ tr1001PacketConverter = new TR1001RadioPacketConverter(); - - isTransmitting = true; - - transmissionStartCycles = mote.getCPU().cycles; - + lastEvent = RadioEvent.TRANSMISSION_STARTED; lastEventTime = mote.getSimulation().getSimulationTime(); + isTransmitting = true; this.setChanged(); this.notifyObservers(); - } - // Remember recent radio activity - millisSinceLastSend = 0; - if (!followupTransmissionEvent.isScheduled()) { + /* Timeout transmission after some time */ + if (timeoutTransmission.isScheduled()) { + logger.warn("Timeout TX event already scheduled"); + timeoutTransmission.remove(); + } mote.getSimulation().scheduleEvent( - followupTransmissionEvent, - mote.getSimulation().getSimulationTime() + Simulation.MILLISECOND); + timeoutTransmission, + mote.getSimulation().getSimulationTime() + 40*Simulation.MILLISECOND + ); } - if (outgoingDataLength >= outgoingData.length) { - logger.warn("----- TR1001 DROPPING OUTGOING BYTE (buffer overflow) -----"); - return; - } - - // Deliver byte to radio medium as custom data - /* logger.debug("----- TR1001 SENT BYTE -----"); */ + /* Deliver custom data byte */ lastEvent = RadioEvent.CUSTOM_DATA_TRANSMITTED; - tr1001ByteFromMote = new TR1001RadioByte((byte) data); + sentByte = (byte) data; this.setChanged(); this.notifyObservers(); - outgoingData[outgoingDataLength++] = tr1001ByteFromMote; - - // Feed to application level immediately - boolean finished = tr1001PacketConverter - .fromTR1001ToCoojaAccumulated(tr1001ByteFromMote); + /* Detect full packet */ + boolean finished = tr1001PacketConverter.fromTR1001ToCoojaAccumulated(sentByte); if (finished) { + timeoutTransmission.remove(); + /* Transmission finished - deliver packet immediately */ if (tr1001PacketConverter.accumulatedConversionIsOk()) { - packetFromMote = tr1001PacketConverter.getAccumulatedConvertedCoojaPacket(); - - /* Notify observers of new prepared packet */ + /* Deliver packet */ /* logger.info("----- TR1001 DELIVERED PACKET -----"); */ + sentPacket = tr1001PacketConverter.getAccumulatedConvertedCoojaPacket(); lastEvent = RadioEvent.PACKET_TRANSMITTED; this.setChanged(); this.notifyObservers(); } - // Reset counters and wait for next packet - outgoingDataLength = 0; - millisSinceLastSend = -1; - - // Signal we are done transmitting + /* Finish transmission */ isTransmitting = false; lastEvent = RadioEvent.TRANSMISSION_FINISHED; - this.setChanged(); - this.notifyObservers(); - + TR1001Radio.this.setChanged(); + TR1001Radio.this.notifyObservers(); /* logger.info("----- TR1001 TRANSMISSION ENDED -----"); */ } } @@ -279,12 +260,14 @@ public class TR1001Radio extends Radio implements USARTListener, } public int getChannel() { + /* TODO Implement */ return -1; } public void signalReceptionStart() { lastEvent = RadioEvent.RECEPTION_STARTED; isReceiving = true; + isInterfered = false; this.setChanged(); this.notifyObservers(); } @@ -304,7 +287,7 @@ public class TR1001Radio extends Radio implements USARTListener, public void interfereAnyReception() { if (!isInterfered()) { isInterfered = true; - lastIncomingPacket = null; + receivedPacket = null; lastEventTime = mote.getSimulation().getSimulationTime(); lastEvent = RadioEvent.RECEPTION_INTERFERED; @@ -340,33 +323,25 @@ public class TR1001Radio extends Radio implements USARTListener, return mote.getInterfaces().getPosition(); } - private TimeEvent followupTransmissionEvent = new MoteTimeEvent(mote, 0) { + private TimeEvent timeoutTransmission = new MoteTimeEvent(mote, 0) { public void execute(long t) { - - if (isTransmitting()) { - millisSinceLastSend++; - - // Detect transmission end due to inactivity - if (millisSinceLastSend > 5) { - /* Dropping packet due to inactivity */ - packetFromMote = null; - - /* Reset counters and wait for next packet */ - outgoingDataLength = 0; - millisSinceLastSend = -1; - - /* Signal we are done transmitting */ - isTransmitting = false; - lastEvent = RadioEvent.TRANSMISSION_FINISHED; - TR1001Radio.this.setChanged(); - TR1001Radio.this.notifyObservers(); - - /*logger.debug("----- NULL TRANSMISSION ENDED -----");*/ - } - - /* Reschedule as long as node is transmitting */ - mote.getSimulation().scheduleEvent(this, t + Simulation.MILLISECOND); + if (!isTransmitting()) { + /* Nothing to do */ + return; } + + logger.warn("TR1001 transmission timed out, delivering empty packet"); + + /* XXX Timeout: We may need to deliver an empty radio packet here */ + sentPacket = new COOJARadioPacket(new byte[0]); + lastEvent = RadioEvent.PACKET_TRANSMITTED; + TR1001Radio.this.setChanged(); + TR1001Radio.this.notifyObservers(); + + isTransmitting = false; + lastEvent = RadioEvent.TRANSMISSION_FINISHED; + TR1001Radio.this.setChanged(); + TR1001Radio.this.notifyObservers(); } }; diff --git a/tools/cooja/apps/mspsim/src/se/sics/cooja/mspmote/interfaces/TR1001RadioByte.java b/tools/cooja/apps/mspsim/src/se/sics/cooja/mspmote/interfaces/TR1001RadioByte.java deleted file mode 100644 index a1e77e0cb..000000000 --- a/tools/cooja/apps/mspsim/src/se/sics/cooja/mspmote/interfaces/TR1001RadioByte.java +++ /dev/null @@ -1,57 +0,0 @@ -/* - * Copyright (c) 2007, Swedish Institute of Computer Science. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. Neither the name of the Institute nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - * - * $Id: TR1001RadioByte.java,v 1.2 2009/05/26 14:33:30 fros4943 Exp $ - */ - -package se.sics.cooja.mspmote.interfaces; - -/** - * TR1001 radio byte. - * - * @author Fredrik Osterlind - */ -public class TR1001RadioByte { - - private byte b; - - /** - * Creates new TR1001 radio byte - */ - public TR1001RadioByte(byte b) { - this.b = b; - } - - /** - * @return Byte - */ - public byte getByte() { - return b; - } - -} diff --git a/tools/cooja/apps/mspsim/src/se/sics/cooja/mspmote/interfaces/TR1001RadioPacketConverter.java b/tools/cooja/apps/mspsim/src/se/sics/cooja/mspmote/interfaces/TR1001RadioPacketConverter.java index 8c8dd3817..db97703f6 100644 --- a/tools/cooja/apps/mspsim/src/se/sics/cooja/mspmote/interfaces/TR1001RadioPacketConverter.java +++ b/tools/cooja/apps/mspsim/src/se/sics/cooja/mspmote/interfaces/TR1001RadioPacketConverter.java @@ -26,7 +26,7 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * $Id: TR1001RadioPacketConverter.java,v 1.4 2009/05/26 14:33:30 fros4943 Exp $ + * $Id: TR1001RadioPacketConverter.java,v 1.5 2009/12/02 16:39:42 fros4943 Exp $ */ package se.sics.cooja.mspmote.interfaces; @@ -68,7 +68,7 @@ public class TR1001RadioPacketConverter { final static int ESB_FOOTER_LENGTH = 2; - private ArrayList originalData = new ArrayList(); + private ArrayList originalData = new ArrayList(); private enum AccumulatedConversionState { TR1001_PREAMBLE, TR1001_SYNCH, ESB_LEN1, ESB_LEN2, ESB_DATA, ESB_CRC1, ESB_CRC2, ESB_POST, @@ -106,11 +106,10 @@ public class TR1001RadioPacketConverter { * The returned array typically needs to be feeded to the emulated "slowly", * i.e. one by one and using interrupts. * - * @param coojaPacket - * COOJA radio packet + * @param coojaPacket COOJA radio packet * @return TR1001 radio packet */ - public static TR1001RadioByte[] fromCoojaToTR1001(RadioPacket coojaPacket) { + public static byte[] fromCoojaToTR1001(RadioPacket coojaPacket) { byte[] coojaPacketData = coojaPacket.getPacketData(); @@ -142,10 +141,8 @@ public class TR1001RadioPacketConverter { tr1001Frame[TR1001_HEADER_LENGTH + encodedData.length + 2] = (byte) 0x33; tr1001Frame[TR1001_HEADER_LENGTH + encodedData.length + 3] = (byte) 0xcc; - TR1001RadioByte[] tr1001Bytes = new TR1001RadioByte[tr1001Frame.length]; - for (int i=0; i < tr1001Frame.length; i++) { - tr1001Bytes[i] = new TR1001RadioByte(tr1001Frame[i]); - } + byte[] tr1001Bytes = new byte[tr1001Frame.length]; + System.arraycopy(tr1001Frame, 0, tr1001Bytes, 0, tr1001Frame.length); return tr1001Bytes; } @@ -159,25 +156,22 @@ public class TR1001RadioPacketConverter { * - Read length header * - Remove both length header and CRC footer * - * @param tr1001Bytes TR1001 bytes + * @param tr1001xxBytes TR1001 bytes * @param tr1001DataLength TR1001 specified packet length * @return COOJA radio packet */ - public static ConvertedRadioPacket fromTR1001ToCooja(TR1001RadioByte[] tr1001Bytes, int tr1001DataLength) { - - byte[] tr1001Data = new byte[tr1001Bytes.length]; - for (int i=0; i < tr1001Bytes.length; i++) { - tr1001Data[i] = tr1001Bytes[i].getByte(); - } + public static ConvertedRadioPacket fromTR1001ToCooja(byte[] data, int tr1001DataLength) { /* Remove TR1001 specifics: preamble, synch and trail bytes */ - System.arraycopy(tr1001Data, TR1001_HEADER_LENGTH, tr1001Data, 0, - tr1001DataLength - TR1001_HEADER_LENGTH - TR1001_FOOTER_LENGTH); - tr1001DataLength = tr1001DataLength - TR1001_HEADER_LENGTH - - TR1001_FOOTER_LENGTH; + tr1001DataLength -= (TR1001_HEADER_LENGTH + TR1001_FOOTER_LENGTH); + System.arraycopy( + data, TR1001_HEADER_LENGTH, + data, 0, + tr1001DataLength + ); /* GCR decode */ - byte[] decodedData = gcrCoder.gcrDecode(tr1001Data, tr1001DataLength); + byte[] decodedData = gcrCoder.gcrDecode(data, tr1001DataLength); if (decodedData != null) { /* Decoding succeded, fetch length from the two first bytes */ @@ -195,11 +189,11 @@ public class TR1001RadioPacketConverter { System.arraycopy(decodedData, ESB_HEADER_LENGTH, packetData, 0, dataLength); - return new ConvertedRadioPacket(packetData, tr1001Data); + return new ConvertedRadioPacket(packetData, data); } logger.warn("No cross-level conversion available: TR1001 GCR decoding failed"); - return new ConvertedRadioPacket(new byte[0], tr1001Data); + return new ConvertedRadioPacket(new byte[0], data); } /** @@ -242,9 +236,8 @@ public class TR1001RadioPacketConverter { * @param tr1001Byte New TR1001 packet data byte * @return True if conversion finished (either successful of failed) */ - public boolean fromTR1001ToCoojaAccumulated(TR1001RadioByte tr1001Byte) { - byte b = tr1001Byte.getByte(); - originalData.add(tr1001Byte); + public boolean fromTR1001ToCoojaAccumulated(byte b) { + originalData.add(b); if (accumulatedConversionState == AccumulatedConversionState.TR1001_PREAMBLE) { if (b == (byte) 0xaa || b == (byte) 0xff) { @@ -323,7 +316,7 @@ public class TR1001RadioPacketConverter { byte[] originalArr = new byte[originalData.size()]; for (int i=0; i < originalArr.length; i++) { - originalArr[i] = (byte) originalData.get(i).getByte(); + originalArr[i] = originalData.get(i); } return new ConvertedRadioPacket(dataArrayByte, originalArr);