event based mote interfaces + reimplemented cross level functionality for TR1001

This commit is contained in:
fros4943 2009-05-26 14:33:30 +00:00
parent c59fc91487
commit 1c22bf5151
4 changed files with 135 additions and 192 deletions

View file

@ -26,7 +26,7 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE. * SUCH DAMAGE.
* *
* $Id: SkyByteRadio.java,v 1.11 2009/05/04 15:34:00 fros4943 Exp $ * $Id: SkyByteRadio.java,v 1.12 2009/05/26 14:33:30 fros4943 Exp $
*/ */
package se.sics.cooja.mspmote.interfaces; package se.sics.cooja.mspmote.interfaces;
@ -74,7 +74,6 @@ public class SkyByteRadio extends Radio implements CustomDataRadio {
private boolean isTransmitting = false; private boolean isTransmitting = false;
private boolean isReceiving = false; private boolean isReceiving = false;
// private boolean hasFailedReception = false;
private CC2420RadioByte lastOutgoingByte = null; private CC2420RadioByte lastOutgoingByte = null;
@ -84,10 +83,6 @@ public class SkyByteRadio extends Radio implements CustomDataRadio {
private RadioPacket lastIncomingPacket = null; private RadioPacket lastIncomingPacket = null;
// private int mode;
//TODO: HW on/off
public SkyByteRadio(Mote mote) { public SkyByteRadio(Mote mote) {
this.mote = (SkyMote) mote; this.mote = (SkyMote) mote;
this.cc2420 = this.mote.skyNode.radio; this.cc2420 = this.mote.skyNode.radio;
@ -167,15 +162,14 @@ public class SkyByteRadio extends Radio implements CustomDataRadio {
private byte[] crossBufferedData = null; private byte[] crossBufferedData = null;
private TimeEvent receiveCrosslevelDataEvent = new TimeEvent(0) { private TimeEvent deliverPacketDataEvent = new TimeEvent(0) {
public void execute(long t) { public void execute(long t) {
if (crossBufferedData == null) { if (crossBufferedData == null) {
return; return;
} }
/*logger.info("Radio is now ready to receive the incoming data");*/ /*logger.info("Delivering buffered packet data now: " + mote.getSimulation().getSimulationTime());*/
for (byte b: crossBufferedData) { for (byte b: crossBufferedData) {
cc2420.receivedByte(b); cc2420.receivedByte(b);
} }
@ -185,31 +179,32 @@ public class SkyByteRadio extends Radio implements CustomDataRadio {
private StateListener cc2420StateListener = new StateListener() { private StateListener cc2420StateListener = new StateListener() {
public void newState(RadioState state) { public void newState(RadioState state) {
if (cc2420.getState() == CC2420.RadioState.RX_SFD_SEARCH) { if (cc2420.getState() != CC2420.RadioState.RX_SFD_SEARCH) {
return;
}
cc2420.setStateListener(null); cc2420.setStateListener(null);
if (crossBufferedData == null) { if (crossBufferedData == null) {
return; return;
} }
/* Receive data very soon (just wait for a radio flush) */ /*logger.info("Radio was turned on! Short delay before transmitting buffered data: " + mote.getSimulation().getSimulationTime());*/
mote.getSimulation().scheduleEvent(
receiveCrosslevelDataEvent,
mote.getSimulation().getSimulationTime()+1
);
} /* Deliver data after the radio drivers flush */
mote.getSimulation().scheduleEvent(
deliverPacketDataEvent,
mote.getSimulation().getSimulationTime()+Simulation.MILLISECOND/3
);
} }
}; };
public void setReceivedPacket(RadioPacket packet) { public void setReceivedPacket(RadioPacket packet) {
lastIncomingPacket = packet; lastIncomingPacket = packet;
/* TODO Receiving all bytes at the same time ok? */
byte[] packetData = CC2420RadioPacketConverter.fromCoojaToCC2420(packet); byte[] packetData = CC2420RadioPacketConverter.fromCoojaToCC2420(packet);
if (cc2420.getState() != CC2420.RadioState.RX_SFD_SEARCH) { if (cc2420.getState() != CC2420.RadioState.RX_SFD_SEARCH) {
/*logger.info("Radio is not currently active. Let's wait some...");*/ /*logger.info("Radio is turned off. Buffering data.");*/
crossBufferedData = packetData; crossBufferedData = packetData;
cc2420.setStateListener(cc2420StateListener); cc2420.setStateListener(cc2420StateListener);
@ -218,6 +213,7 @@ public class SkyByteRadio extends Radio implements CustomDataRadio {
return; return;
} }
/* Delivering data immediately */
for (byte b: packetData) { for (byte b: packetData) {
cc2420.receivedByte(b); cc2420.receivedByte(b);
} }

View file

@ -26,7 +26,7 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE. * SUCH DAMAGE.
* *
* $Id: TR1001Radio.java,v 1.12 2009/04/16 14:28:12 fros4943 Exp $ * $Id: TR1001Radio.java,v 1.13 2009/05/26 14:33:30 fros4943 Exp $
*/ */
package se.sics.cooja.mspmote.interfaces; package se.sics.cooja.mspmote.interfaces;
@ -52,19 +52,23 @@ import se.sics.cooja.mspmote.ESBMote;
* @author Fredrik Osterlind * @author Fredrik Osterlind
*/ */
@ClassDescription("TR1001 Radio") @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); private static Logger logger = Logger.getLogger(TR1001Radio.class);
/** /**
* Minimum delay in CPU cycles between each byte fed to USART. * Delay used when feeding packet data to radio chip (us). 416us corresponds
* to 19200 bit/s with encoding.
*/ */
public static final long CYCLES_BETWEEN_BYTES = 1200; /* ~19.200 bps */ public static final long DELAY_BETWEEN_BYTES = 3 * 416;
private ESBMote mote; private ESBMote mote;
private boolean radioOn = true; private boolean radioOn = true;
private boolean transmitting = false; private boolean isTransmitting = false;
private boolean isReceiving = false;
private boolean isInterfered = false; private boolean isInterfered = false;
@ -74,7 +78,7 @@ public class TR1001Radio extends Radio implements USARTListener, CustomDataRadio
private USART radioUSART = null; private USART radioUSART = null;
private RadioPacket packetToMote = null; private RadioPacket lastIncomingPacket = null;
private RadioPacket packetFromMote = null; private RadioPacket packetFromMote = null;
@ -83,27 +87,15 @@ public class TR1001Radio extends Radio implements USARTListener, CustomDataRadio
private int outgoingDataLength = 0; private int outgoingDataLength = 0;
private int ticksSinceLastSend = -1; private int millisSinceLastSend = -1;
/* Incoming byte-to-packet data buffer */
private Vector<Byte> bufferedBytes = new Vector<Byte>();
private Vector<Long> bufferedByteDelays = new Vector<Long>();
/* Outgoing byte data buffer */ /* Outgoing byte data buffer */
private TR1001RadioByte tr1001ByteFromMote = null; private TR1001RadioByte tr1001ByteFromMote = null;
private TR1001RadioByte tr1001ByteToMote = null; private TR1001RadioByte lastIncomingByte = null;
private long transmissionStartCycles = -1; private long transmissionStartCycles = -1;
/* Incoming byte data buffer */
private byte lastDeliveredByte = -1;
private long lastDeliveredByteTimestamp = -1;
private long lastDeliveredByteDelay = -1;
private TR1001RadioPacketConverter tr1001PacketConverter = null; private TR1001RadioPacketConverter tr1001PacketConverter = null;
private double signalStrength = 0; private double signalStrength = 0;
@ -133,28 +125,34 @@ public class TR1001Radio extends Radio implements USARTListener, CustomDataRadio
} }
public RadioPacket getLastPacketReceived() { public RadioPacket getLastPacketReceived() {
return packetToMote; return lastIncomingPacket;
} }
public void setReceivedPacket(RadioPacket packet) { public void setReceivedPacket(RadioPacket packet) {
packetToMote = packet; lastIncomingPacket = packet;
if (packetToMote.getPacketData() == null || packetToMote.getPacketData().length == 0) {
logger.fatal("Received null packet");
return;
}
if (isInterfered) {
logger.fatal("Received packet when interfered");
return;
}
/* Convert to TR1001 packet data */ /* Convert to TR1001 packet data */
TR1001RadioByte[] tr1001bytes = TR1001RadioPacketConverter.fromCoojaToTR1001(packetToMote); TR1001RadioByte[] byteArr = TR1001RadioPacketConverter.fromCoojaToTR1001(packet);
final ArrayList<TR1001RadioByte> byteList = new ArrayList<TR1001RadioByte>();
/* Feed to the CPU "slowly" */ for (TR1001RadioByte b : byteArr) {
for (TR1001RadioByte b : tr1001bytes) { byteList.add(b);
receiveCustomData(b);
} }
/* Feed incoming bytes to radio "slowly" via time events */
TimeEvent receiveCrosslevelDataEvent = new TimeEvent(0) {
public void execute(long t) {
/* Stop receiving data when buffer is empty */
if (byteList.isEmpty() || isInterfered) {
return;
}
TR1001RadioByte b = byteList.remove(0);
radioUSART.byteReceived(b.getByte());
mote.getSimulation().scheduleEvent(this, t + DELAY_BETWEEN_BYTES);
}
};
receiveCrosslevelDataEvent.execute(mote.getSimulation().getSimulationTime());
} }
/* Custom data radio support */ /* Custom data radio support */
@ -163,84 +161,32 @@ public class TR1001Radio extends Radio implements USARTListener, CustomDataRadio
} }
public Object getLastCustomDataReceived() { public Object getLastCustomDataReceived() {
return tr1001ByteToMote; return lastIncomingByte;
} }
public void receiveCustomData(Object data) { public void receiveCustomData(Object data) {
if (data instanceof TR1001RadioByte) { if (data instanceof TR1001RadioByte) {
tr1001ByteToMote = ((TR1001RadioByte) data); lastIncomingByte = ((TR1001RadioByte) data);
bufferedBytes.add(tr1001ByteToMote.getByte());
bufferedByteDelays.add(tr1001ByteToMote.getDelay());
}
}
/**
* @return True if undelivered bytes exist.
*/
public boolean hasPendingBytes() {
return bufferedBytes.size() > 0;
}
/**
* If non-delivered bytes exist, tries to deliver one byte to the CPU by
* checking USART receive flag.
*
* @param cycles
* Current CPU cycles
*/
public void tryDeliverNextByte(long cycles) {
// Check that pending bytes exist
if (!hasPendingBytes()) {
return;
}
// Check if time to deliver byte
long nextByteDelay = bufferedByteDelays.firstElement();
if (cycles - lastDeliveredByteDelay < nextByteDelay) {
return;
}
lastDeliveredByte = bufferedBytes.firstElement();
bufferedBytes.remove(0);
bufferedByteDelays.remove(0);
if (radioUSART.isReceiveFlagCleared()) { if (radioUSART.isReceiveFlagCleared()) {
//logger.info(nextByteDelay + " < " /*logger.info("----- TR1001 RECEIVED BYTE -----");*/
// + (cycles - receptionStartedCycles) radioUSART.byteReceived(lastIncomingByte.getByte());
// + ":\tDelivering 0x" + Utils.hex8(lastDeliveredByte) + " (TODO="
// + bufferedBytes.size() + ")");
radioUSART.byteReceived(lastDeliveredByte);
} else { } else {
/*logger.fatal(nextByteDelay + " < " logger.warn("----- TR1001 RECEIVED BYTE DROPPED -----");
+ (cycles - receptionStartedCycles) }
+ ":\tDROPPING 0x" + Utils.hex8(lastDeliveredByte) + " (TODO="
+ bufferedBytes.size() + ")");*/
} }
lastDeliveredByteDelay = cycles;
// /* TODO BUG: Resends last byte, interrupt lost somewhere? */
// else if (cycles > lastDeliveredByteTimestamp + CYCLES_BETWEEN_BYTES) {
// logger.warn("0x" + Utils.hex16((int) cycles) + ":\tRedelivering 0x"
// + Utils.hex8(lastDeliveredByte) + " (TODO=" + bufferedBytes.size()
// + ")");
// radioUSART.byteReceived(lastDeliveredByte);
// lastDeliveredByteTimestamp = cycles;
// }
} }
/* USART listener support */ /* USART listener support */
public void dataReceived(USART source, int data) { public void dataReceived(USART source, int data) {
if (outgoingDataLength == 0 && !isTransmitting()) { if (outgoingDataLength == 0 && !isTransmitting()) {
/* New transmission discovered */ /* New transmission discovered */
/*logger.debug("----- NEW TR1001 TRANSMISSION DETECTED -----");*/ /*logger.info("----- NEW TR1001 TRANSMISSION DETECTED -----");*/
tr1001PacketConverter = new TR1001RadioPacketConverter(); tr1001PacketConverter = new TR1001RadioPacketConverter();
transmitting = true; isTransmitting = true;
transmissionStartCycles = mote.getCPU().cycles; transmissionStartCycles = mote.getCPU().cycles;
lastDeliveredByteTimestamp = transmissionStartCycles;
lastEvent = RadioEvent.TRANSMISSION_STARTED; lastEvent = RadioEvent.TRANSMISSION_STARTED;
lastEventTime = mote.getSimulation().getSimulationTime(); lastEventTime = mote.getSimulation().getSimulationTime();
@ -249,33 +195,35 @@ public class TR1001Radio extends Radio implements USARTListener, CustomDataRadio
} }
// Remember recent radio activity // Remember recent radio activity
ticksSinceLastSend = 0; millisSinceLastSend = 0;
mote.getSimulation().scheduleEvent(followupTransmissionEvent, mote.getSimulation().getSimulationTime()+1); mote.getSimulation().scheduleEvent(
followupTransmissionEvent,
mote.getSimulation().getSimulationTime() + Simulation.MILLISECOND);
if (outgoingDataLength >= outgoingData.length) { if (outgoingDataLength >= outgoingData.length) {
logger.fatal("Ignoring byte due to buffer overflow"); logger.warn("----- TR1001 DROPPING OUTGOING BYTE (buffer overflow) -----");
return; return;
} }
// Deliver byte to radio medium as custom data // Deliver byte to radio medium as custom data
/*logger.debug("----- TR1001 DELIVERED BYTE -----");*/ /* logger.debug("----- TR1001 SENT BYTE -----"); */
lastEvent = RadioEvent.CUSTOM_DATA_TRANSMITTED; lastEvent = RadioEvent.CUSTOM_DATA_TRANSMITTED;
tr1001ByteFromMote = new TR1001RadioByte((byte) data, mote.getCPU().cycles - lastDeliveredByteTimestamp); tr1001ByteFromMote = new TR1001RadioByte((byte) data);
this.setChanged(); this.setChanged();
this.notifyObservers(); this.notifyObservers();
lastDeliveredByteTimestamp = mote.getCPU().cycles;
outgoingData[outgoingDataLength++] = tr1001ByteFromMote; outgoingData[outgoingDataLength++] = tr1001ByteFromMote;
// Feed to application level immediately // Feed to application level immediately
boolean finished = tr1001PacketConverter.fromTR1001ToCoojaAccumulated(tr1001ByteFromMote); boolean finished = tr1001PacketConverter
.fromTR1001ToCoojaAccumulated(tr1001ByteFromMote);
if (finished) { if (finished) {
/* Transmission finished - deliver packet immediately */ /* Transmission finished - deliver packet immediately */
if (tr1001PacketConverter.accumulatedConversionIsOk()) { if (tr1001PacketConverter.accumulatedConversionIsOk()) {
packetFromMote = tr1001PacketConverter.getAccumulatedConvertedCoojaPacket(); packetFromMote = tr1001PacketConverter.getAccumulatedConvertedCoojaPacket();
/* Notify observers of new prepared packet */ /* Notify observers of new prepared packet */
/*logger.debug("----- TR1001 DELIVERED PACKET -----");*/ /* logger.info("----- TR1001 DELIVERED PACKET -----"); */
lastEvent = RadioEvent.PACKET_TRANSMITTED; lastEvent = RadioEvent.PACKET_TRANSMITTED;
this.setChanged(); this.setChanged();
this.notifyObservers(); this.notifyObservers();
@ -283,15 +231,15 @@ public class TR1001Radio extends Radio implements USARTListener, CustomDataRadio
// Reset counters and wait for next packet // Reset counters and wait for next packet
outgoingDataLength = 0; outgoingDataLength = 0;
ticksSinceLastSend = -1; millisSinceLastSend = -1;
// Signal we are done transmitting // Signal we are done transmitting
transmitting = false; isTransmitting = false;
lastEvent = RadioEvent.TRANSMISSION_FINISHED; lastEvent = RadioEvent.TRANSMISSION_FINISHED;
this.setChanged(); this.setChanged();
this.notifyObservers(); this.notifyObservers();
/*logger.debug("----- TR1001 TRANSMISSION ENDED -----");*/ /* logger.info("----- TR1001 TRANSMISSION ENDED -----"); */
} }
} }
@ -300,11 +248,11 @@ public class TR1001Radio extends Radio implements USARTListener, CustomDataRadio
/* General radio support */ /* General radio support */
public boolean isTransmitting() { public boolean isTransmitting() {
return transmitting; return isTransmitting;
} }
public boolean isReceiving() { public boolean isReceiving() {
return hasPendingBytes(); return isReceiving;
} }
public boolean isInterfered() { public boolean isInterfered() {
@ -317,18 +265,14 @@ public class TR1001Radio extends Radio implements USARTListener, CustomDataRadio
public void signalReceptionStart() { public void signalReceptionStart() {
lastEvent = RadioEvent.RECEPTION_STARTED; lastEvent = RadioEvent.RECEPTION_STARTED;
/*receptionStartedCycles = mspMote.getCPU().cycles;*/ isReceiving = true;
this.setChanged(); this.setChanged();
this.notifyObservers(); this.notifyObservers();
} }
public void signalReceptionEnd() { public void signalReceptionEnd() {
// TODO Should be done according to serial port instead
// TODO Compare times with OS abstraction level
if (isInterfered()) {
isInterfered = false; isInterfered = false;
return; isReceiving = false;
}
lastEvent = RadioEvent.RECEPTION_FINISHED; lastEvent = RadioEvent.RECEPTION_FINISHED;
this.setChanged(); this.setChanged();
this.notifyObservers(); this.notifyObservers();
@ -341,12 +285,11 @@ public class TR1001Radio extends Radio implements USARTListener, CustomDataRadio
public void interfereAnyReception() { public void interfereAnyReception() {
if (!isInterfered()) { if (!isInterfered()) {
isInterfered = true; isInterfered = true;
lastIncomingPacket = null;
bufferedBytes.clear();
bufferedByteDelays.clear();
lastEvent = RadioEvent.RECEPTION_INTERFERED;
lastEventTime = mote.getSimulation().getSimulationTime(); lastEventTime = mote.getSimulation().getSimulationTime();
lastEvent = RadioEvent.RECEPTION_INTERFERED;
/*logger.info("----- TR1001 RECEPTION INTERFERED -----");*/
this.setChanged(); this.setChanged();
this.notifyObservers(); this.notifyObservers();
} }
@ -382,19 +325,19 @@ public class TR1001Radio extends Radio implements USARTListener, CustomDataRadio
public void execute(long t) { public void execute(long t) {
if (isTransmitting()) { if (isTransmitting()) {
ticksSinceLastSend++; millisSinceLastSend++;
// Detect transmission end due to inactivity // Detect transmission end due to inactivity
if (ticksSinceLastSend > 4) { if (millisSinceLastSend > 5) {
/* Dropping packet due to inactivity */ /* Dropping packet due to inactivity */
packetFromMote = null; packetFromMote = null;
/* Reset counters and wait for next packet */ /* Reset counters and wait for next packet */
outgoingDataLength = 0; outgoingDataLength = 0;
ticksSinceLastSend = -1; millisSinceLastSend = -1;
/* Signal we are done transmitting */ /* Signal we are done transmitting */
transmitting = false; isTransmitting = false;
lastEvent = RadioEvent.TRANSMISSION_FINISHED; lastEvent = RadioEvent.TRANSMISSION_FINISHED;
TR1001Radio.this.setChanged(); TR1001Radio.this.setChanged();
TR1001Radio.this.notifyObservers(); TR1001Radio.this.notifyObservers();
@ -403,7 +346,7 @@ public class TR1001Radio extends Radio implements USARTListener, CustomDataRadio
} }
/* Reschedule as long as node is transmitting */ /* Reschedule as long as node is transmitting */
mote.getSimulation().scheduleEvent(this, t+1); mote.getSimulation().scheduleEvent(this, t + Simulation.MILLISECOND);
} }
} }
}; };
@ -440,7 +383,9 @@ public class TR1001Radio extends Radio implements USARTListener, CustomDataRadio
updateButton.addActionListener(new ActionListener() { updateButton.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) { public void actionPerformed(ActionEvent e) {
powerLabel.setText(getCurrentOutputPower() + " dBm (indicator=" + getCurrentOutputPowerIndicator() + "/" + getOutputPowerIndicatorMax() + ")"); powerLabel.setText(getCurrentOutputPower() + " dBm (indicator="
+ getCurrentOutputPowerIndicator() + "/"
+ getOutputPowerIndicatorMax() + ")");
ssLabel.setText(getCurrentSignalStrength() + " dBm"); ssLabel.setText(getCurrentSignalStrength() + " dBm");
} }
}); });
@ -460,7 +405,9 @@ public class TR1001Radio extends Radio implements USARTListener, CustomDataRadio
lastEventLabel.setText(lastEvent + " @ time=" + lastEventTime); lastEventLabel.setText(lastEvent + " @ time=" + lastEventTime);
powerLabel.setText(getCurrentOutputPower() + " dBm (indicator=" + getCurrentOutputPowerIndicator() + "/" + getOutputPowerIndicatorMax() + ")"); powerLabel.setText(getCurrentOutputPower() + " dBm (indicator="
+ getCurrentOutputPowerIndicator() + "/"
+ getOutputPowerIndicatorMax() + ")");
ssLabel.setText(getCurrentSignalStrength() + " dBm"); ssLabel.setText(getCurrentSignalStrength() + " dBm");
} }
}); });

View file

@ -26,7 +26,7 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE. * SUCH DAMAGE.
* *
* $Id: TR1001RadioByte.java,v 1.1 2008/03/18 13:08:26 fros4943 Exp $ * $Id: TR1001RadioByte.java,v 1.2 2009/05/26 14:33:30 fros4943 Exp $
*/ */
package se.sics.cooja.mspmote.interfaces; package se.sics.cooja.mspmote.interfaces;
@ -40,14 +40,11 @@ public class TR1001RadioByte {
private byte b; private byte b;
private long delay;
/** /**
* Creates new TR1001 radio byte * Creates new TR1001 radio byte
*/ */
public TR1001RadioByte(byte b, long delay) { public TR1001RadioByte(byte b) {
this.b = b; this.b = b;
this.delay = delay;
} }
/** /**
@ -57,11 +54,4 @@ public class TR1001RadioByte {
return b; return b;
} }
/**
* @return Cycle delay since previous byte
*/
public long getDelay() {
return delay;
}
} }

View file

@ -26,14 +26,16 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE. * SUCH DAMAGE.
* *
* $Id: TR1001RadioPacketConverter.java,v 1.3 2008/03/18 16:55:44 fros4943 Exp $ * $Id: TR1001RadioPacketConverter.java,v 1.4 2009/05/26 14:33:30 fros4943 Exp $
*/ */
package se.sics.cooja.mspmote.interfaces; package se.sics.cooja.mspmote.interfaces;
import java.util.ArrayList;
import org.apache.log4j.Logger; import org.apache.log4j.Logger;
import se.sics.cooja.COOJARadioPacket; import se.sics.cooja.COOJARadioPacket;
import se.sics.cooja.ConvertedRadioPacket;
import se.sics.cooja.RadioPacket; import se.sics.cooja.RadioPacket;
/** /**
@ -66,6 +68,7 @@ public class TR1001RadioPacketConverter {
final static int ESB_FOOTER_LENGTH = 2; final static int ESB_FOOTER_LENGTH = 2;
private ArrayList<TR1001RadioByte> originalData = new ArrayList<TR1001RadioByte>();
private enum AccumulatedConversionState { private enum AccumulatedConversionState {
TR1001_PREAMBLE, TR1001_SYNCH, ESB_LEN1, ESB_LEN2, ESB_DATA, ESB_CRC1, ESB_CRC2, ESB_POST, TR1001_PREAMBLE, TR1001_SYNCH, ESB_LEN1, ESB_LEN2, ESB_DATA, ESB_CRC1, ESB_CRC2, ESB_POST,
@ -141,7 +144,7 @@ public class TR1001RadioPacketConverter {
TR1001RadioByte[] tr1001Bytes = new TR1001RadioByte[tr1001Frame.length]; TR1001RadioByte[] tr1001Bytes = new TR1001RadioByte[tr1001Frame.length];
for (int i=0; i < tr1001Frame.length; i++) { for (int i=0; i < tr1001Frame.length; i++) {
tr1001Bytes[i] = new TR1001RadioByte(tr1001Frame[i], TR1001Radio.CYCLES_BETWEEN_BYTES); tr1001Bytes[i] = new TR1001RadioByte(tr1001Frame[i]);
} }
return tr1001Bytes; return tr1001Bytes;
} }
@ -160,7 +163,7 @@ public class TR1001RadioPacketConverter {
* @param tr1001DataLength TR1001 specified packet length * @param tr1001DataLength TR1001 specified packet length
* @return COOJA radio packet * @return COOJA radio packet
*/ */
public static RadioPacket fromTR1001ToCooja(TR1001RadioByte[] tr1001Bytes, int tr1001DataLength) { public static ConvertedRadioPacket fromTR1001ToCooja(TR1001RadioByte[] tr1001Bytes, int tr1001DataLength) {
byte[] tr1001Data = new byte[tr1001Bytes.length]; byte[] tr1001Data = new byte[tr1001Bytes.length];
for (int i=0; i < tr1001Bytes.length; i++) { for (int i=0; i < tr1001Bytes.length; i++) {
@ -192,11 +195,11 @@ public class TR1001RadioPacketConverter {
System.arraycopy(decodedData, ESB_HEADER_LENGTH, packetData, 0, System.arraycopy(decodedData, ESB_HEADER_LENGTH, packetData, 0,
dataLength); dataLength);
return new COOJARadioPacket(packetData); return new ConvertedRadioPacket(packetData, tr1001Data);
} }
logger.fatal("Error when converting emulated to application level, returning null packet"); logger.warn("No cross-level conversion available: TR1001 GCR decoding failed");
return null; return new ConvertedRadioPacket(new byte[0], tr1001Data);
} }
/** /**
@ -241,6 +244,7 @@ public class TR1001RadioPacketConverter {
*/ */
public boolean fromTR1001ToCoojaAccumulated(TR1001RadioByte tr1001Byte) { public boolean fromTR1001ToCoojaAccumulated(TR1001RadioByte tr1001Byte) {
byte b = tr1001Byte.getByte(); byte b = tr1001Byte.getByte();
originalData.add(tr1001Byte);
if (accumulatedConversionState == AccumulatedConversionState.TR1001_PREAMBLE) { if (accumulatedConversionState == AccumulatedConversionState.TR1001_PREAMBLE) {
if (b == (byte) 0xaa || b == (byte) 0xff) { if (b == (byte) 0xaa || b == (byte) 0xff) {
@ -311,12 +315,18 @@ public class TR1001RadioPacketConverter {
/** /**
* @return Converted data (application level) * @return Converted data (application level)
*/ */
public RadioPacket getAccumulatedConvertedCoojaPacket() { public ConvertedRadioPacket getAccumulatedConvertedCoojaPacket() {
byte[] dataArrayByte = new byte[accumulatedConversionDataArray.length]; byte[] dataArrayByte = new byte[accumulatedConversionDataArray.length];
for (int i = 0; i < accumulatedConversionDataArray.length; i++) { for (int i=0; i < accumulatedConversionDataArray.length; i++) {
dataArrayByte[i] = (byte) accumulatedConversionDataArray[i]; dataArrayByte[i] = (byte) accumulatedConversionDataArray[i];
} }
return new COOJARadioPacket(dataArrayByte);
byte[] originalArr = new byte[originalData.size()];
for (int i=0; i < originalArr.length; i++) {
originalArr[i] = (byte) originalData.get(i).getByte();
}
return new ConvertedRadioPacket(dataArrayByte, originalArr);
} }
/** /**