esb/tr1001 interface

This commit is contained in:
fros4943 2008-02-07 14:55:35 +00:00
parent 749c0aa639
commit 70dd3218f3
2 changed files with 806 additions and 0 deletions

View file

@ -0,0 +1,485 @@
/*
* 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: TR1001Radio.java,v 1.1 2008/02/07 14:55:35 fros4943 Exp $
*/
package se.sics.cooja.mspmote.interfaces;
import java.util.*;
import javax.swing.*;
import java.awt.event.*;
import org.apache.log4j.Logger;
import org.jdom.Element;
import se.sics.mspsim.core.*;
import se.sics.cooja.*;
import se.sics.cooja.interfaces.*;
import se.sics.cooja.mspmote.ESBMote;
/**
* TR1001 radio interface on ESB platform. Assumes driver specifics such as
* preambles, synchbytes, GCR coding, CRC16.
*
* @author Fredrik Osterlind
*/
@ClassDescription("TR1001 Radio")
public class TR1001Radio extends Radio implements USARTListener, ByteRadio {
private static Logger logger = Logger.getLogger(TR1001Radio.class);
/**
* Minimum delay in CPU cycles between each byte fed to USART.
*/
private static final long CYCLES_BETWEEN_BYTES = 1200; /* ~19.200 bps */
private ESBMote mspMote;
private boolean radioOn = true;
private boolean transmitting = false;
private boolean isInterfered = false;
private RadioEvent lastEvent = RadioEvent.UNKNOWN;
private int lastEventTime = 0;
private USART radioUSART = null;
private byte[] packetToMote = null;
private byte[] packetFromMote = null;
/* Outgoing packet data buffer */
private byte[] outgoingData = new byte[1024]; // TODO Decrease max size
private int outgoingDataLength = 0;
private int ticksSinceLastSend = -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 */
private byte byteFromMote = -1;
private long transmissionStartCycles = -1;
private long byteFromMoteDelay = -1;
/* Incoming byte data buffer */
private byte byteToMote = -1;
private byte lastDeliveredByte = -1;
private long lastDeliveredByteTimestamp = -1;
private long lastDeliveredByteDelay = -1;
private TR1001RadioPacketConverter tr1001PacketConverter = null;
/**
* Creates an interface to the TR1001 radio at mote.
*
* @param mote
* Radio's mote.
* @see Mote
* @see se.sics.cooja.MoteInterfaceHandler
*/
public TR1001Radio(ESBMote mote) {
mspMote = mote;
/* Start listening to CPU's USART */
IOUnit usart = mote.getCPU().getIOUnit("USART 0");
if (usart instanceof USART) {
radioUSART = (USART) usart;
radioUSART.setUSARTListener(this);
}
}
/* Packet radio support */
public byte[] getLastPacketTransmitted() {
return packetFromMote;
}
public byte[] getLastPacketReceived() {
return packetToMote;
}
public void setReceivedPacket(byte[] p) {
packetToMote = p;
if (packetToMote == null || packetToMote.length == 0) {
logger.fatal("Received null packet");
return;
}
if (isInterfered) {
logger.fatal("Received packet when interfered");
return;
}
/* Convert to TR1001 packet data */
byte[] tr1001Frame = TR1001RadioPacketConverter.fromCoojaToTR1001(p);
/* Feed to the CPU "slowly" */
for (byte element : tr1001Frame) {
receiveByte(element, CYCLES_BETWEEN_BYTES);
}
}
/* Byte radio support */
public byte getLastByteTransmitted() {
return byteFromMote;
}
public long getLastByteTransmittedDelay() {
return byteFromMoteDelay;
}
public byte getLastByteReceived() {
return byteToMote;
}
public void receiveByte(byte b, long delay) {
byteToMote = b;
bufferedBytes.add(b);
bufferedByteDelays.add(delay);
}
/**
* @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()) {
//logger.info(nextByteDelay + " < "
// + (cycles - receptionStartedCycles)
// + ":\tDelivering 0x" + Utils.hex8(lastDeliveredByte) + " (TODO="
// + bufferedBytes.size() + ")");
radioUSART.byteReceived(lastDeliveredByte);
} else {
/*logger.fatal(nextByteDelay + " < "
+ (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 */
public void dataReceived(USART source, int data) {
if (outgoingDataLength == 0 && !isTransmitting()) {
/* New transmission discovered */
//logger.debug("----- NEW MSP TRANSMISSION DETECTED -----");
tr1001PacketConverter = new TR1001RadioPacketConverter();
transmitting = true;
lastEventTime = mspMote.getSimulation().getSimulationTime();
lastEvent = RadioEvent.TRANSMISSION_STARTED;
transmissionStartCycles = mspMote.getCPU().cycles;
lastDeliveredByteTimestamp = transmissionStartCycles;
this.setChanged();
this.notifyObservers();
}
// Remember recent radio activity
ticksSinceLastSend = 0;
if (outgoingDataLength >= outgoingData.length) {
logger.fatal("Ignoring byte due to buffer overflow");
return;
}
// Store packet data
outgoingData[outgoingDataLength++] = (byte) data;
// Deliver byte to radio medium
lastEvent = RadioEvent.BYTE_TRANSMITTED;
byteFromMote = (byte) data;
byteFromMoteDelay = mspMote.getCPU().cycles - lastDeliveredByteTimestamp;
lastDeliveredByteTimestamp = mspMote.getCPU().cycles;
if (byteFromMoteDelay < 0) {
byteFromMoteDelay = 0;
}
this.setChanged();
this.notifyObservers();
// Feed to application level immediately
boolean finished = tr1001PacketConverter.fromTR1001ToCoojaAccumulated(byteFromMote);
if (finished) {
/* Transmission finished - deliver packet immediately */
if (tr1001PacketConverter.accumulatedConversionIsOk()) {
packetFromMote = tr1001PacketConverter.getAccumulatedConvertedData();
} else {
packetFromMote = new byte[0];
}
/* Notify observers of new prepared packet */
/*logger.debug("----- MSP DELIVERED PACKET -----");*/
lastEvent = RadioEvent.PACKET_TRANSMITTED;
this.setChanged();
this.notifyObservers();
// Reset counters and wait for next packet
outgoingDataLength = 0;
ticksSinceLastSend = -1;
// Signal we are done transmitting
transmitting = false;
lastEvent = RadioEvent.TRANSMISSION_FINISHED;
this.setChanged();
this.notifyObservers();
/*logger.debug("----- MSP TRANSMISSION ENDED -----");*/
}
}
/* General radio support */
public boolean isTransmitting() {
return transmitting;
}
public boolean isReceiving() {
return hasPendingBytes();
}
public boolean isInterfered() {
return isInterfered;
}
public int getChannel() {
// TODO Implement support for channels
return 1;
}
public void signalReceptionStart() {
lastEvent = RadioEvent.RECEPTION_STARTED;
/*receptionStartedCycles = mspMote.getCPU().cycles;*/
this.setChanged();
this.notifyObservers();
}
public void signalReceptionEnd() {
// TODO Should be done according to serial port instead
// TODO Compare times with OS abstraction level
if (isInterfered()) {
isInterfered = false;
return;
}
lastEvent = RadioEvent.RECEPTION_FINISHED;
this.setChanged();
this.notifyObservers();
}
public RadioEvent getLastEvent() {
return lastEvent;
}
public void interfereAnyReception() {
if (!isInterfered()) {
isInterfered = true;
bufferedBytes.clear();
bufferedByteDelays.clear();
lastEvent = RadioEvent.RECEPTION_INTERFERED;
lastEventTime = mspMote.getSimulation().getSimulationTime();
this.setChanged();
this.notifyObservers();
}
}
public double getCurrentOutputPower() {
// TODO Implement method
return 1.5;
}
public int getCurrentOutputPowerIndicator() {
// TODO Implement output power indicator
return 100;
}
public double getCurrentSignalStrength() {
// TODO Implement signal strength
return 100;
}
public void setCurrentSignalStrength(double signalStrength) {
// TODO Implement signal strength
// logger.warn("Not implemented");
}
public Position getPosition() {
return mspMote.getInterfaces().getPosition();
}
public void doActionsBeforeTick() {
}
public void doActionsAfterTick() {
// Detect transmission end due to inactivity
if (isTransmitting() && ticksSinceLastSend > 4) {
/* Dropping packet due to inactivity */
packetFromMote = new byte[0];
/* Notify observers of new empty packet */
logger.warn("----- DELIVERED MSP NULL PACKET -----");
lastEvent = RadioEvent.PACKET_TRANSMITTED;
this.setChanged();
this.notifyObservers();
// Reset counters and wait for next packet
outgoingDataLength = 0;
ticksSinceLastSend = -1;
// Signal we are done transmitting
transmitting = false;
lastEvent = RadioEvent.TRANSMISSION_FINISHED;
this.setChanged();
this.notifyObservers();
//logger.debug("----- NULL TRANSMISSION ENDED -----");
} else if (isTransmitting() && ticksSinceLastSend >= 0) {
// Increase counter to detect when transmission ends
ticksSinceLastSend++;
}
}
public JPanel getInterfaceVisualizer() {
// Location
JPanel panel = new JPanel();
panel.setLayout(new BoxLayout(panel, BoxLayout.Y_AXIS));
final JLabel statusLabel = new JLabel("");
final JLabel lastEventLabel = new JLabel("");
final JLabel ssLabel = new JLabel("");
final JButton updateButton = new JButton("Update SS");
panel.add(statusLabel);
panel.add(lastEventLabel);
panel.add(ssLabel);
panel.add(updateButton);
updateButton.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
ssLabel.setText("Signal strength (not auto-updated): "
+ getCurrentSignalStrength() + " dBm");
}
});
Observer observer;
this.addObserver(observer = new Observer() {
public void update(Observable obs, Object obj) {
if (isTransmitting()) {
statusLabel.setText("Transmitting packet now!");
} else if (isReceiving()) {
statusLabel.setText("Receiving packet now!");
} else if (radioOn) {
statusLabel.setText("Listening...");
} else {
statusLabel.setText("HW turned off");
}
lastEventLabel.setText("Last event (time=" + lastEventTime + "): "
+ lastEvent);
ssLabel.setText("Signal strength (not auto-updated): "
+ getCurrentSignalStrength() + " dBm");
}
});
observer.update(null, null);
// Saving observer reference for releaseInterfaceVisualizer
panel.putClientProperty("intf_obs", observer);
return panel;
}
public void releaseInterfaceVisualizer(JPanel panel) {
Observer observer = (Observer) panel.getClientProperty("intf_obs");
if (observer == null) {
logger.fatal("Error when releasing panel, observer is null");
return;
}
this.deleteObserver(observer);
}
public double energyConsumptionPerTick() {
return 0;
}
public Collection<Element> getConfigXML() {
return null;
}
public void setConfigXML(Collection<Element> configXML, boolean visAvailable) {
}
public Mote getMote() {
return mspMote;
}
}

View file

@ -0,0 +1,321 @@
/*
* 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: TR1001RadioPacketConverter.java,v 1.1 2008/02/07 14:55:35 fros4943 Exp $
*/
package se.sics.cooja.mspmote.interfaces;
import org.apache.log4j.Logger;
/**
* Converts radio packets between TR1001/ESB and COOJA.
* Some functionality, such as GCR coding, is ESB TR1001 driver specific.
*
* @author Fredrik Osterlind
*/
public class TR1001RadioPacketConverter {
private static Logger logger = Logger.getLogger(TR1001RadioPacketConverter.class);
private static GCRCoder gcrCoder = new GCRCoder();
/* TR1001 packet: PREAMBLE(20) _ SYNCH(1+4+1) _ GCR(ESBDATA(?)) _ TRAIL(4) */
final static int TR1001_PREAMBLE_LENGTH = 20;
final static int TR1001_NR_SYNCHBYTES = 4;
final static byte TR1001_SYNCH1 = 0x3c;
final static byte TR1001_SYNCH2 = 0x03;
final static int TR1001_HEADER_LENGTH = TR1001_PREAMBLE_LENGTH + 1
+ TR1001_NR_SYNCHBYTES + 1;
final static int TR1001_FOOTER_LENGTH = 4;
/* "ESB" packet: LENGTH(2) _ APPDATA(?) _ CRC(2) */
final static int ESB_HEADER_LENGTH = 2;
final static int ESB_FOOTER_LENGTH = 2;
private enum AccumulatedConversionState {
TR1001_PREAMBLE, TR1001_SYNCH, ESB_LEN1, ESB_LEN2, ESB_DATA, ESB_CRC1, ESB_CRC2, ESB_POST,
}
private AccumulatedConversionState accumulatedConversionState = AccumulatedConversionState.TR1001_PREAMBLE;
private boolean accumulatedConversionOK = true;
private int[] accumulatedConversionDataLengthArray = new int[2];
private int[] accumulatedConversionDataArray = null;
private int[] accumulatedConversionCRCArray = new int[2];
private int accumulatedConversionDataCounter = 0;
private int accumulatedConversionDataLength = 0;
private int accumulatedConversionFooterLength = 0;
private GCRCoder AccumulatedConversionGCRCoder = new GCRCoder();
/**
* Converts radio packet data from COOJA to TR1001. This
* implementation is ESB platform and TR1001 driver specific.
*
* It consists of (in sequential order):
* - Adding 2-byte length header
* - Calculating and adding 2-byte CRC16 footer
* - GCR encoding data
* - Add TR1001 header: preamble and synch bytes
* - Add TR1001 footer: 4 trail bytes
*
* 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
* @return TR1001 radio packet
*/
public static byte[] fromCoojaToTR1001(byte[] coojaPacket) {
/* Create "ESB" packet: add length header and CRC16 footer */
byte[] esbPacket = addLengthAndCRC(coojaPacket);
/* GCR encode radio frame */
byte[] encodedData = gcrCoder.gcrEncode(esbPacket, esbPacket.length);
/* Create TR1001 header (preamble and synchbytes) */
byte[] tr1001Frame = new byte[TR1001_HEADER_LENGTH + encodedData.length
+ TR1001_FOOTER_LENGTH];
for (int i = 0; i < TR1001_PREAMBLE_LENGTH; i++) {
tr1001Frame[i] = (byte) 0xaa;
}
tr1001Frame[TR1001_PREAMBLE_LENGTH] = (byte) 0xff;
for (int i = 0; i < TR1001_NR_SYNCHBYTES; i++) {
tr1001Frame[TR1001_PREAMBLE_LENGTH + 1 + i] = TR1001_SYNCH1;
}
tr1001Frame[TR1001_PREAMBLE_LENGTH + 1 + TR1001_NR_SYNCHBYTES] = TR1001_SYNCH2;
/* Add encoded data */
System.arraycopy(encodedData, 0, tr1001Frame, TR1001_HEADER_LENGTH,
encodedData.length);
/* Add TR1001 footer (trail bytes) */
tr1001Frame[TR1001_HEADER_LENGTH + encodedData.length] = (byte) 0x33;
tr1001Frame[TR1001_HEADER_LENGTH + encodedData.length + 1] = (byte) 0xcc;
tr1001Frame[TR1001_HEADER_LENGTH + encodedData.length + 2] = (byte) 0x33;
tr1001Frame[TR1001_HEADER_LENGTH + encodedData.length + 3] = (byte) 0xcc;
return tr1001Frame;
}
/**
* Converts radio packet data from TR1001 to COOJA. This
* implementation is ESB platform and TR1001 driver specific.
*
* It consists of (in sequential order):
* - Removing TR1001 header and footer
* - GCR decode data
* - Read length header
* - Remove both length header and CRC footer
*
* @param tr1001Data
* TR1001 packet data
* @param tr1001DataLength
* TR1001 packet data length
* @return COOJA radio packet
*/
public static byte[] fromTR1001ToCooja(byte[] tr1001Data,
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;
/* GCR decode */
byte[] decodedData = gcrCoder.gcrDecode(tr1001Data, tr1001DataLength);
if (decodedData != null) {
/* Decoding succeded, fetch length from the two first bytes */
int dataLength = ((decodedData[0] & 0xff) << 8) + (decodedData[1] & 0xff);
if (dataLength + ESB_HEADER_LENGTH + ESB_HEADER_LENGTH > decodedData.length) {
logger.fatal("Decoded data is smaller than specified data length: "
+ (dataLength + ESB_HEADER_LENGTH + ESB_HEADER_LENGTH) + " vs "
+ decodedData.length);
return new byte[0];
}
/* Remove ESB header and CRC footer */
byte[] packetData = new byte[dataLength];
System.arraycopy(decodedData, ESB_HEADER_LENGTH, packetData, 0,
dataLength);
return packetData;
}
logger
.fatal("Error when converting emulated to application level, returning empty: "
+ tr1001DataLength);
return new byte[0];
}
/**
* Adds length header and CRC16 footer to given data.
*
* @param packetData
* Packet data
* @return Packet data with length header and CRC16 footer
*/
private static byte[] addLengthAndCRC(byte[] packetData) {
short accumulatedCRC = (short) 0xffff;
byte[] radioFrame = new byte[ESB_HEADER_LENGTH + packetData.length
+ ESB_FOOTER_LENGTH];
/* Add length */
radioFrame[0] = (byte) ((packetData.length >> 8) & 0xff);
accumulatedCRC = CRCCoder.crc16Add(radioFrame[0], accumulatedCRC);
radioFrame[1] = (byte) (packetData.length & 0xff);
accumulatedCRC = CRCCoder.crc16Add(radioFrame[1], accumulatedCRC);
/* Add data */
System.arraycopy(packetData, 0, radioFrame, ESB_HEADER_LENGTH,
packetData.length);
/* Calculate CRC */
for (byte element : packetData) {
accumulatedCRC = CRCCoder.crc16Add(element, accumulatedCRC);
}
/* Add CRC */
radioFrame[ESB_HEADER_LENGTH + packetData.length] = (byte) ((accumulatedCRC >> 8) & 0xff);
radioFrame[ESB_HEADER_LENGTH + packetData.length + 1] = (byte) (accumulatedCRC & 0xff);
return radioFrame;
}
/**
* Adds another another byte to the accumulated conversion from TR1001
* to Cooja.
*
* @see #accumulatedConversionIsOk()
* @param b
* Byte
* @return True if conversion finished (either successful of failed).
*/
public boolean fromTR1001ToCoojaAccumulated(byte b) {
if (accumulatedConversionState == AccumulatedConversionState.TR1001_PREAMBLE) {
if (b == (byte) 0xaa || b == (byte) 0xff) {
return false;
} else if (b == (byte) 0x3c) {
accumulatedConversionState = AccumulatedConversionState.TR1001_SYNCH;
return false;
} else {
accumulatedConversionOK = false;
return true;
}
} else if (accumulatedConversionState == AccumulatedConversionState.TR1001_SYNCH) {
if (b == TR1001_SYNCH1) {
return false;
} else if (b == TR1001_SYNCH2) {
accumulatedConversionState = AccumulatedConversionState.ESB_LEN1;
AccumulatedConversionGCRCoder.gcr_init();
return false;
} else {
accumulatedConversionOK = false;
return true;
}
} else if (accumulatedConversionState == AccumulatedConversionState.ESB_LEN1) {
AccumulatedConversionGCRCoder.gcr_decode(0xff & b);
if (AccumulatedConversionGCRCoder.gcr_get_decoded(accumulatedConversionDataLengthArray, 0)) {
accumulatedConversionState = AccumulatedConversionState.ESB_LEN2;
}
return false;
} else if (accumulatedConversionState == AccumulatedConversionState.ESB_LEN2) {
AccumulatedConversionGCRCoder.gcr_decode(0xff & b);
if (AccumulatedConversionGCRCoder.gcr_get_decoded(accumulatedConversionDataLengthArray, 1)) {
accumulatedConversionState = AccumulatedConversionState.ESB_DATA;
accumulatedConversionDataLength = (accumulatedConversionDataLengthArray[0] & 0xff) << 8;
accumulatedConversionDataLength = (accumulatedConversionDataLengthArray[1] & 0xff);
accumulatedConversionDataArray = new int[accumulatedConversionDataLength];
}
return false;
} else if (accumulatedConversionState == AccumulatedConversionState.ESB_DATA) {
AccumulatedConversionGCRCoder.gcr_decode(0xff & b);
if (AccumulatedConversionGCRCoder.gcr_get_decoded(accumulatedConversionDataArray, accumulatedConversionDataCounter)) {
accumulatedConversionDataCounter++;
if (accumulatedConversionDataCounter >= accumulatedConversionDataArray.length) {
accumulatedConversionState = AccumulatedConversionState.ESB_CRC1;
}
}
return false;
} else if (accumulatedConversionState == AccumulatedConversionState.ESB_CRC1) {
AccumulatedConversionGCRCoder.gcr_decode(0xff & b);
if (AccumulatedConversionGCRCoder.gcr_get_decoded(accumulatedConversionCRCArray, 0)) {
accumulatedConversionState = AccumulatedConversionState.ESB_CRC2;
}
return false;
} else if (accumulatedConversionState == AccumulatedConversionState.ESB_CRC2) {
AccumulatedConversionGCRCoder.gcr_decode(0xff & b);
if (AccumulatedConversionGCRCoder.gcr_get_decoded(accumulatedConversionCRCArray, 1)) {
accumulatedConversionState = AccumulatedConversionState.ESB_POST;
}
return false;
} else if (accumulatedConversionState == AccumulatedConversionState.ESB_POST) {
accumulatedConversionFooterLength++;
return accumulatedConversionFooterLength >= 4;
} else {
accumulatedConversionOK = false;
return true;
}
}
/**
* @return Converted data (application level)
*/
public byte[] getAccumulatedConvertedData() {
byte[] dataArrayByte = new byte[accumulatedConversionDataArray.length];
for (int i = 0; i < accumulatedConversionDataArray.length; i++) {
dataArrayByte[i] = (byte) accumulatedConversionDataArray[i];
}
return dataArrayByte;
}
/**
* Returns status from accumulated conversion.
*
* @return True if ok, false if error occurred.
*/
public boolean accumulatedConversionIsOk() {
return accumulatedConversionOK;
}
}