requesting mote wakeup when receiving radio data + code cleanup (faster code)

This commit is contained in:
fros4943 2009-12-02 16:39:42 +00:00
parent 51f210b37f
commit 36d09eaa69
3 changed files with 112 additions and 201 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: 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; package se.sics.cooja.mspmote.interfaces;
@ -47,6 +47,7 @@ import javax.swing.JPanel;
import org.apache.log4j.Logger; import org.apache.log4j.Logger;
import org.jdom.Element; import org.jdom.Element;
import se.sics.cooja.COOJARadioPacket;
import se.sics.cooja.ClassDescription; import se.sics.cooja.ClassDescription;
import se.sics.cooja.Mote; import se.sics.cooja.Mote;
import se.sics.cooja.MoteTimeEvent; import se.sics.cooja.MoteTimeEvent;
@ -62,109 +63,96 @@ import se.sics.mspsim.core.USART;
import se.sics.mspsim.core.USARTListener; import se.sics.mspsim.core.USARTListener;
/** /**
* TR1001 radio interface on ESB platform. Assumes driver specifics such as * TR1001 radio interface on ESB platform.
* preambles, synchbytes, GCR coding, CRC16. * Assumes Contiki driver specifics such as preambles, synchbytes, GCR coding, CRC16.
* *
* @author Fredrik Osterlind * @author Fredrik Osterlind
*/ */
@ClassDescription("TR1001 Radio") @ClassDescription("TR1001 Radio")
public class TR1001Radio extends Radio implements USARTListener, public class TR1001Radio extends Radio implements USARTListener, CustomDataRadio {
CustomDataRadio {
private static Logger logger = Logger.getLogger(TR1001Radio.class); private static Logger logger = Logger.getLogger(TR1001Radio.class);
/** /**
* Delay used when feeding packet data to radio chip (us). 416us corresponds * Cross-level:
* to 19200 bit/s with encoding. * 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 ESBMote mote;
private boolean radioOn = true;
private boolean isTransmitting = false; private boolean isTransmitting = false;
private boolean isReceiving = false; private boolean isReceiving = false;
private boolean isInterfered = false; private boolean isInterfered = false;
private RadioEvent lastEvent = RadioEvent.UNKNOWN; private RadioEvent lastEvent = RadioEvent.UNKNOWN;
private long lastEventTime = 0; private long lastEventTime = 0;
private USART radioUSART = null; private USART radioUSART = null;
private RadioPacket lastIncomingPacket = null; private RadioPacket receivedPacket = null;
private RadioPacket sentPacket = null;
private RadioPacket packetFromMote = null; private byte receivedByte, sentByte;
/* 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 TR1001RadioPacketConverter tr1001PacketConverter = null; 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. * Creates an interface to the TR1001 radio at mote.
* *
* @param mote * @param mote Mote
* Radio's mote.
* @see Mote
* @see se.sics.cooja.MoteInterfaceHandler
*/ */
public TR1001Radio(Mote mote) { public TR1001Radio(Mote mote) {
this.mote = (ESBMote) mote; this.mote = (ESBMote) mote;
/* Start listening to CPU's USART */ /* Start listening to CPU's USART */
IOUnit usart = this.mote.getCPU().getIOUnit("USART 0"); IOUnit usart = this.mote.getCPU().getIOUnit("USART 0");
if (usart instanceof USART) { if (usart != null && usart instanceof USART) {
radioUSART = (USART) usart; radioUSART = (USART) usart;
radioUSART.setUSARTListener(this); radioUSART.setUSARTListener(this);
} else {
throw new RuntimeException("Bad TR1001 IO: " + usart);
} }
} }
/* Packet radio support */ /* Packet radio support */
public RadioPacket getLastPacketTransmitted() { public RadioPacket getLastPacketTransmitted() {
return packetFromMote; return sentPacket;
} }
public RadioPacket getLastPacketReceived() { public RadioPacket getLastPacketReceived() {
return lastIncomingPacket; return receivedPacket;
} }
public void setReceivedPacket(RadioPacket packet) { public void setReceivedPacket(RadioPacket packet) {
lastIncomingPacket = packet; receivedPacket = packet;
/* Convert to TR1001 packet data */ /* Convert to TR1001 packet data */
TR1001RadioByte[] byteArr = TR1001RadioPacketConverter.fromCoojaToTR1001(packet); byte[] arr = TR1001RadioPacketConverter.fromCoojaToTR1001(packet);
final ArrayDeque<TR1001RadioByte> byteList = new ArrayDeque<TR1001RadioByte>(); final ArrayDeque<Byte> data = new ArrayDeque<Byte>();
for (TR1001RadioByte b : byteArr) { for (Byte b : arr) {
byteList.addLast(b); data.addLast(b);
} }
/* Feed incoming bytes to radio "slowly" via time events */ /* Feed incoming bytes to radio "slowly" via time events */
TimeEvent receiveCrosslevelDataEvent = new MoteTimeEvent(mote, 0) { TimeEvent receiveCrosslevelDataEvent = new MoteTimeEvent(mote, 0) {
public void execute(long t) { public void execute(long t) {
/* Stop receiving data when buffer is empty */ /* Stop receiving data when buffer is empty */
if (byteList.isEmpty() || isInterfered) { if (data.isEmpty()) {
byteList.clear();
return; return;
} }
TR1001RadioByte b = byteList.pop(); byte b = data.pop();
radioUSART.byteReceived(b.getByte()); if (isInterfered) {
radioUSART.byteReceived(0xFF); /* Corrupted data */
} else {
radioUSART.byteReceived(b);
}
mote.requestImmediateWakeup();
mote.getSimulation().scheduleEvent(this, t + DELAY_BETWEEN_BYTES); mote.getSimulation().scheduleEvent(this, t + DELAY_BETWEEN_BYTES);
} }
@ -174,90 +162,83 @@ public class TR1001Radio extends Radio implements USARTListener,
/* Custom data radio support */ /* Custom data radio support */
public Object getLastCustomDataTransmitted() { public Object getLastCustomDataTransmitted() {
return tr1001ByteFromMote; return sentByte;
} }
public Object getLastCustomDataReceived() { public Object getLastCustomDataReceived() {
return lastIncomingByte; return receivedByte;
} }
public void receiveCustomData(Object data) { public void receiveCustomData(Object data) {
if (data instanceof TR1001RadioByte) { if (!(data instanceof Byte)) {
lastIncomingByte = ((TR1001RadioByte) data); logger.fatal("Received bad custom data: " + data);
return;
}
receivedByte = (Byte) data;
mote.requestImmediateWakeup();
if (radioUSART.isReceiveFlagCleared()) { if (radioUSART.isReceiveFlagCleared()) {
/*logger.info("----- TR1001 RECEIVED BYTE -----");*/ /*logger.info("----- TR1001 RECEIVED BYTE -----");*/
radioUSART.byteReceived(lastIncomingByte.getByte()); if (isInterfered) {
radioUSART.byteReceived(0xFF); /* Corrupted data */
} else { } else {
logger.warn("----- TR1001 RECEIVED BYTE DROPPED -----"); radioUSART.byteReceived(receivedByte);
} }
} else {
logger.warn(mote.getSimulation().getSimulationTime() + ": ----- TR1001 RECEIVED BYTE DROPPED -----");
} }
} }
/* 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 (!isTransmitting()) {
/* New transmission discovered */ /* New transmission discovered */
/*logger.info("----- NEW TR1001 TRANSMISSION DETECTED -----");*/ /*logger.info("----- NEW TR1001 TRANSMISSION DETECTED -----");*/
tr1001PacketConverter = new TR1001RadioPacketConverter(); tr1001PacketConverter = new TR1001RadioPacketConverter();
isTransmitting = true;
transmissionStartCycles = mote.getCPU().cycles;
lastEvent = RadioEvent.TRANSMISSION_STARTED; lastEvent = RadioEvent.TRANSMISSION_STARTED;
lastEventTime = mote.getSimulation().getSimulationTime(); lastEventTime = mote.getSimulation().getSimulationTime();
isTransmitting = true;
this.setChanged(); this.setChanged();
this.notifyObservers(); this.notifyObservers();
}
// Remember recent radio activity /* Timeout transmission after some time */
millisSinceLastSend = 0; if (timeoutTransmission.isScheduled()) {
if (!followupTransmissionEvent.isScheduled()) { logger.warn("Timeout TX event already scheduled");
timeoutTransmission.remove();
}
mote.getSimulation().scheduleEvent( mote.getSimulation().scheduleEvent(
followupTransmissionEvent, timeoutTransmission,
mote.getSimulation().getSimulationTime() + Simulation.MILLISECOND); mote.getSimulation().getSimulationTime() + 40*Simulation.MILLISECOND
);
} }
if (outgoingDataLength >= outgoingData.length) { /* Deliver custom data byte */
logger.warn("----- TR1001 DROPPING OUTGOING BYTE (buffer overflow) -----");
return;
}
// Deliver byte to radio medium as custom data
/* logger.debug("----- TR1001 SENT BYTE -----"); */
lastEvent = RadioEvent.CUSTOM_DATA_TRANSMITTED; lastEvent = RadioEvent.CUSTOM_DATA_TRANSMITTED;
tr1001ByteFromMote = new TR1001RadioByte((byte) data); sentByte = (byte) data;
this.setChanged(); this.setChanged();
this.notifyObservers(); this.notifyObservers();
outgoingData[outgoingDataLength++] = tr1001ByteFromMote; /* Detect full packet */
boolean finished = tr1001PacketConverter.fromTR1001ToCoojaAccumulated(sentByte);
// Feed to application level immediately
boolean finished = tr1001PacketConverter
.fromTR1001ToCoojaAccumulated(tr1001ByteFromMote);
if (finished) { if (finished) {
timeoutTransmission.remove();
/* Transmission finished - deliver packet immediately */ /* Transmission finished - deliver packet immediately */
if (tr1001PacketConverter.accumulatedConversionIsOk()) { if (tr1001PacketConverter.accumulatedConversionIsOk()) {
packetFromMote = tr1001PacketConverter.getAccumulatedConvertedCoojaPacket(); /* Deliver packet */
/* Notify observers of new prepared packet */
/* logger.info("----- TR1001 DELIVERED PACKET -----"); */ /* logger.info("----- TR1001 DELIVERED PACKET -----"); */
sentPacket = tr1001PacketConverter.getAccumulatedConvertedCoojaPacket();
lastEvent = RadioEvent.PACKET_TRANSMITTED; lastEvent = RadioEvent.PACKET_TRANSMITTED;
this.setChanged(); this.setChanged();
this.notifyObservers(); this.notifyObservers();
} }
// Reset counters and wait for next packet /* Finish transmission */
outgoingDataLength = 0;
millisSinceLastSend = -1;
// Signal we are done transmitting
isTransmitting = false; isTransmitting = false;
lastEvent = RadioEvent.TRANSMISSION_FINISHED; lastEvent = RadioEvent.TRANSMISSION_FINISHED;
this.setChanged(); TR1001Radio.this.setChanged();
this.notifyObservers(); TR1001Radio.this.notifyObservers();
/* logger.info("----- TR1001 TRANSMISSION ENDED -----"); */ /* logger.info("----- TR1001 TRANSMISSION ENDED -----"); */
} }
} }
@ -279,12 +260,14 @@ public class TR1001Radio extends Radio implements USARTListener,
} }
public int getChannel() { public int getChannel() {
/* TODO Implement */
return -1; return -1;
} }
public void signalReceptionStart() { public void signalReceptionStart() {
lastEvent = RadioEvent.RECEPTION_STARTED; lastEvent = RadioEvent.RECEPTION_STARTED;
isReceiving = true; isReceiving = true;
isInterfered = false;
this.setChanged(); this.setChanged();
this.notifyObservers(); this.notifyObservers();
} }
@ -304,7 +287,7 @@ public class TR1001Radio extends Radio implements USARTListener,
public void interfereAnyReception() { public void interfereAnyReception() {
if (!isInterfered()) { if (!isInterfered()) {
isInterfered = true; isInterfered = true;
lastIncomingPacket = null; receivedPacket = null;
lastEventTime = mote.getSimulation().getSimulationTime(); lastEventTime = mote.getSimulation().getSimulationTime();
lastEvent = RadioEvent.RECEPTION_INTERFERED; lastEvent = RadioEvent.RECEPTION_INTERFERED;
@ -340,33 +323,25 @@ public class TR1001Radio extends Radio implements USARTListener,
return mote.getInterfaces().getPosition(); return mote.getInterfaces().getPosition();
} }
private TimeEvent followupTransmissionEvent = new MoteTimeEvent(mote, 0) { private TimeEvent timeoutTransmission = new MoteTimeEvent(mote, 0) {
public void execute(long t) { public void execute(long t) {
if (!isTransmitting()) {
/* Nothing to do */
return;
}
if (isTransmitting()) { logger.warn("TR1001 transmission timed out, delivering empty packet");
millisSinceLastSend++;
// Detect transmission end due to inactivity /* XXX Timeout: We may need to deliver an empty radio packet here */
if (millisSinceLastSend > 5) { sentPacket = new COOJARadioPacket(new byte[0]);
/* Dropping packet due to inactivity */ lastEvent = RadioEvent.PACKET_TRANSMITTED;
packetFromMote = null; TR1001Radio.this.setChanged();
TR1001Radio.this.notifyObservers();
/* Reset counters and wait for next packet */
outgoingDataLength = 0;
millisSinceLastSend = -1;
/* Signal we are done transmitting */
isTransmitting = false; isTransmitting = false;
lastEvent = RadioEvent.TRANSMISSION_FINISHED; lastEvent = RadioEvent.TRANSMISSION_FINISHED;
TR1001Radio.this.setChanged(); TR1001Radio.this.setChanged();
TR1001Radio.this.notifyObservers(); TR1001Radio.this.notifyObservers();
/*logger.debug("----- NULL TRANSMISSION ENDED -----");*/
}
/* Reschedule as long as node is transmitting */
mote.getSimulation().scheduleEvent(this, t + Simulation.MILLISECOND);
}
} }
}; };

View file

@ -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;
}
}

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: 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; package se.sics.cooja.mspmote.interfaces;
@ -68,7 +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 ArrayList<Byte> originalData = new ArrayList<Byte>();
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,
@ -106,11 +106,10 @@ public class TR1001RadioPacketConverter {
* The returned array typically needs to be feeded to the emulated "slowly", * The returned array typically needs to be feeded to the emulated "slowly",
* i.e. one by one and using interrupts. * i.e. one by one and using interrupts.
* *
* @param coojaPacket * @param coojaPacket COOJA radio packet
* COOJA radio packet
* @return TR1001 radio packet * @return TR1001 radio packet
*/ */
public static TR1001RadioByte[] fromCoojaToTR1001(RadioPacket coojaPacket) { public static byte[] fromCoojaToTR1001(RadioPacket coojaPacket) {
byte[] coojaPacketData = coojaPacket.getPacketData(); 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 + 2] = (byte) 0x33;
tr1001Frame[TR1001_HEADER_LENGTH + encodedData.length + 3] = (byte) 0xcc; tr1001Frame[TR1001_HEADER_LENGTH + encodedData.length + 3] = (byte) 0xcc;
TR1001RadioByte[] tr1001Bytes = new TR1001RadioByte[tr1001Frame.length]; byte[] tr1001Bytes = new byte[tr1001Frame.length];
for (int i=0; i < tr1001Frame.length; i++) { System.arraycopy(tr1001Frame, 0, tr1001Bytes, 0, tr1001Frame.length);
tr1001Bytes[i] = new TR1001RadioByte(tr1001Frame[i]);
}
return tr1001Bytes; return tr1001Bytes;
} }
@ -159,25 +156,22 @@ public class TR1001RadioPacketConverter {
* - Read length header * - Read length header
* - Remove both length header and CRC footer * - Remove both length header and CRC footer
* *
* @param tr1001Bytes TR1001 bytes * @param tr1001xxBytes TR1001 bytes
* @param tr1001DataLength TR1001 specified packet length * @param tr1001DataLength TR1001 specified packet length
* @return COOJA radio packet * @return COOJA radio packet
*/ */
public static ConvertedRadioPacket fromTR1001ToCooja(TR1001RadioByte[] tr1001Bytes, int tr1001DataLength) { public static ConvertedRadioPacket fromTR1001ToCooja(byte[] data, int tr1001DataLength) {
byte[] tr1001Data = new byte[tr1001Bytes.length];
for (int i=0; i < tr1001Bytes.length; i++) {
tr1001Data[i] = tr1001Bytes[i].getByte();
}
/* Remove TR1001 specifics: preamble, synch and trail bytes */ /* Remove TR1001 specifics: preamble, synch and trail bytes */
System.arraycopy(tr1001Data, TR1001_HEADER_LENGTH, tr1001Data, 0, tr1001DataLength -= (TR1001_HEADER_LENGTH + TR1001_FOOTER_LENGTH);
tr1001DataLength - TR1001_HEADER_LENGTH - TR1001_FOOTER_LENGTH); System.arraycopy(
tr1001DataLength = tr1001DataLength - TR1001_HEADER_LENGTH data, TR1001_HEADER_LENGTH,
- TR1001_FOOTER_LENGTH; data, 0,
tr1001DataLength
);
/* GCR decode */ /* GCR decode */
byte[] decodedData = gcrCoder.gcrDecode(tr1001Data, tr1001DataLength); byte[] decodedData = gcrCoder.gcrDecode(data, tr1001DataLength);
if (decodedData != null) { if (decodedData != null) {
/* Decoding succeded, fetch length from the two first bytes */ /* Decoding succeded, fetch length from the two first bytes */
@ -195,11 +189,11 @@ public class TR1001RadioPacketConverter {
System.arraycopy(decodedData, ESB_HEADER_LENGTH, packetData, 0, System.arraycopy(decodedData, ESB_HEADER_LENGTH, packetData, 0,
dataLength); dataLength);
return new ConvertedRadioPacket(packetData, tr1001Data); return new ConvertedRadioPacket(packetData, data);
} }
logger.warn("No cross-level conversion available: TR1001 GCR decoding failed"); 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 * @param tr1001Byte New TR1001 packet data byte
* @return True if conversion finished (either successful of failed) * @return True if conversion finished (either successful of failed)
*/ */
public boolean fromTR1001ToCoojaAccumulated(TR1001RadioByte tr1001Byte) { public boolean fromTR1001ToCoojaAccumulated(byte b) {
byte b = tr1001Byte.getByte(); originalData.add(b);
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) {
@ -323,7 +316,7 @@ public class TR1001RadioPacketConverter {
byte[] originalArr = new byte[originalData.size()]; byte[] originalArr = new byte[originalData.size()];
for (int i=0; i < originalArr.length; i++) { 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); return new ConvertedRadioPacket(dataArrayByte, originalArr);