All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.tinkerforge.BrickletCANV2 Maven / Gradle / Ivy

/* ***********************************************************
 * This file was automatically generated on 2019-11-25.      *
 *                                                           *
 * Java Bindings Version 2.1.25                              *
 *                                                           *
 * If you have a bugfix for this file and want to commit it, *
 * please fix the bug in the generator. You can find a link  *
 * to the generators git repository on tinkerforge.com       *
 *************************************************************/

package com.tinkerforge;

import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import java.util.concurrent.CopyOnWriteArrayList;
import java.util.Arrays;
import java.util.List;

/**
 * Communicates with CAN bus devices
 */
public class BrickletCANV2 extends Device {
	public final static int DEVICE_IDENTIFIER = 2107;
	public final static String DEVICE_DISPLAY_NAME = "CAN Bricklet 2.0";

	public final static byte FUNCTION_WRITE_FRAME_LOW_LEVEL = (byte)1;
	public final static byte FUNCTION_READ_FRAME_LOW_LEVEL = (byte)2;
	public final static byte FUNCTION_SET_FRAME_READ_CALLBACK_CONFIGURATION = (byte)3;
	public final static byte FUNCTION_GET_FRAME_READ_CALLBACK_CONFIGURATION = (byte)4;
	public final static byte FUNCTION_SET_TRANSCEIVER_CONFIGURATION = (byte)5;
	public final static byte FUNCTION_GET_TRANSCEIVER_CONFIGURATION = (byte)6;
	public final static byte FUNCTION_SET_QUEUE_CONFIGURATION_LOW_LEVEL = (byte)7;
	public final static byte FUNCTION_GET_QUEUE_CONFIGURATION_LOW_LEVEL = (byte)8;
	public final static byte FUNCTION_SET_READ_FILTER_CONFIGURATION = (byte)9;
	public final static byte FUNCTION_GET_READ_FILTER_CONFIGURATION = (byte)10;
	public final static byte FUNCTION_GET_ERROR_LOG_LOW_LEVEL = (byte)11;
	public final static byte FUNCTION_SET_COMMUNICATION_LED_CONFIG = (byte)12;
	public final static byte FUNCTION_GET_COMMUNICATION_LED_CONFIG = (byte)13;
	public final static byte FUNCTION_SET_ERROR_LED_CONFIG = (byte)14;
	public final static byte FUNCTION_GET_ERROR_LED_CONFIG = (byte)15;
	public final static byte FUNCTION_GET_SPITFP_ERROR_COUNT = (byte)234;
	public final static byte FUNCTION_SET_BOOTLOADER_MODE = (byte)235;
	public final static byte FUNCTION_GET_BOOTLOADER_MODE = (byte)236;
	public final static byte FUNCTION_SET_WRITE_FIRMWARE_POINTER = (byte)237;
	public final static byte FUNCTION_WRITE_FIRMWARE = (byte)238;
	public final static byte FUNCTION_SET_STATUS_LED_CONFIG = (byte)239;
	public final static byte FUNCTION_GET_STATUS_LED_CONFIG = (byte)240;
	public final static byte FUNCTION_GET_CHIP_TEMPERATURE = (byte)242;
	public final static byte FUNCTION_RESET = (byte)243;
	public final static byte FUNCTION_WRITE_UID = (byte)248;
	public final static byte FUNCTION_READ_UID = (byte)249;
	public final static byte FUNCTION_GET_IDENTITY = (byte)255;
	private final static int CALLBACK_FRAME_READ_LOW_LEVEL = 16;
	private final static int CALLBACK_FRAME_READ = -16;

	public final static int FRAME_TYPE_STANDARD_DATA = 0;
	public final static int FRAME_TYPE_STANDARD_REMOTE = 1;
	public final static int FRAME_TYPE_EXTENDED_DATA = 2;
	public final static int FRAME_TYPE_EXTENDED_REMOTE = 3;
	public final static int TRANSCEIVER_MODE_NORMAL = 0;
	public final static int TRANSCEIVER_MODE_LOOPBACK = 1;
	public final static int TRANSCEIVER_MODE_READ_ONLY = 2;
	public final static int FILTER_MODE_ACCEPT_ALL = 0;
	public final static int FILTER_MODE_MATCH_STANDARD_ONLY = 1;
	public final static int FILTER_MODE_MATCH_EXTENDED_ONLY = 2;
	public final static int FILTER_MODE_MATCH_STANDARD_AND_EXTENDED = 3;
	public final static int TRANSCEIVER_STATE_ACTIVE = 0;
	public final static int TRANSCEIVER_STATE_PASSIVE = 1;
	public final static int TRANSCEIVER_STATE_DISABLED = 2;
	public final static int COMMUNICATION_LED_CONFIG_OFF = 0;
	public final static int COMMUNICATION_LED_CONFIG_ON = 1;
	public final static int COMMUNICATION_LED_CONFIG_SHOW_HEARTBEAT = 2;
	public final static int COMMUNICATION_LED_CONFIG_SHOW_COMMUNICATION = 3;
	public final static int ERROR_LED_CONFIG_OFF = 0;
	public final static int ERROR_LED_CONFIG_ON = 1;
	public final static int ERROR_LED_CONFIG_SHOW_HEARTBEAT = 2;
	public final static int ERROR_LED_CONFIG_SHOW_TRANSCEIVER_STATE = 3;
	public final static int ERROR_LED_CONFIG_SHOW_ERROR = 4;
	public final static int BOOTLOADER_MODE_BOOTLOADER = 0;
	public final static int BOOTLOADER_MODE_FIRMWARE = 1;
	public final static int BOOTLOADER_MODE_BOOTLOADER_WAIT_FOR_REBOOT = 2;
	public final static int BOOTLOADER_MODE_FIRMWARE_WAIT_FOR_REBOOT = 3;
	public final static int BOOTLOADER_MODE_FIRMWARE_WAIT_FOR_ERASE_AND_REBOOT = 4;
	public final static int BOOTLOADER_STATUS_OK = 0;
	public final static int BOOTLOADER_STATUS_INVALID_MODE = 1;
	public final static int BOOTLOADER_STATUS_NO_CHANGE = 2;
	public final static int BOOTLOADER_STATUS_ENTRY_FUNCTION_NOT_PRESENT = 3;
	public final static int BOOTLOADER_STATUS_DEVICE_IDENTIFIER_INCORRECT = 4;
	public final static int BOOTLOADER_STATUS_CRC_MISMATCH = 5;
	public final static int STATUS_LED_CONFIG_OFF = 0;
	public final static int STATUS_LED_CONFIG_ON = 1;
	public final static int STATUS_LED_CONFIG_SHOW_HEARTBEAT = 2;
	public final static int STATUS_LED_CONFIG_SHOW_STATUS = 3;

	private List listenerFrameReadLowLevel = new CopyOnWriteArrayList();
	private List listenerFrameRead = new CopyOnWriteArrayList();

	public class ReadFrameLowLevel {
		public boolean success;
		public int frameType;
		public long identifier;
		public int dataLength;
		public int[] dataData = new int[15];

		public String toString() {
			return "[" + "success = " + success + ", " + "frameType = " + frameType + ", " + "identifier = " + identifier + ", " + "dataLength = " + dataLength + ", " + "dataData = " + Arrays.toString(dataData) + "]";
		}
	}

	public class TransceiverConfiguration {
		public long baudRate;
		public int samplePoint;
		public int transceiverMode;

		public String toString() {
			return "[" + "baudRate = " + baudRate + ", " + "samplePoint = " + samplePoint + ", " + "transceiverMode = " + transceiverMode + "]";
		}
	}

	public class QueueConfigurationLowLevel {
		public int writeBufferSize;
		public int writeBufferTimeout;
		public int writeBacklogSize;
		public int readBufferSizesLength;
		public int[] readBufferSizesData = new int[32];
		public int readBacklogSize;

		public String toString() {
			return "[" + "writeBufferSize = " + writeBufferSize + ", " + "writeBufferTimeout = " + writeBufferTimeout + ", " + "writeBacklogSize = " + writeBacklogSize + ", " + "readBufferSizesLength = " + readBufferSizesLength + ", " + "readBufferSizesData = " + Arrays.toString(readBufferSizesData) + ", " + "readBacklogSize = " + readBacklogSize + "]";
		}
	}

	public class ReadFilterConfiguration {
		public int filterMode;
		public long filterMask;
		public long filterIdentifier;

		public String toString() {
			return "[" + "filterMode = " + filterMode + ", " + "filterMask = " + filterMask + ", " + "filterIdentifier = " + filterIdentifier + "]";
		}
	}

	public class ErrorLogLowLevel {
		public int transceiverState;
		public int transceiverWriteErrorLevel;
		public int transceiverReadErrorLevel;
		public long transceiverStuffingErrorCount;
		public long transceiverFormatErrorCount;
		public long transceiverACKErrorCount;
		public long transceiverBit1ErrorCount;
		public long transceiverBit0ErrorCount;
		public long transceiverCRCErrorCount;
		public long writeBufferTimeoutErrorCount;
		public long readBufferOverflowErrorCount;
		public int readBufferOverflowErrorOccurredLength;
		public boolean[] readBufferOverflowErrorOccurredData = new boolean[32];
		public long readBacklogOverflowErrorCount;

		public String toString() {
			return "[" + "transceiverState = " + transceiverState + ", " + "transceiverWriteErrorLevel = " + transceiverWriteErrorLevel + ", " + "transceiverReadErrorLevel = " + transceiverReadErrorLevel + ", " + "transceiverStuffingErrorCount = " + transceiverStuffingErrorCount + ", " + "transceiverFormatErrorCount = " + transceiverFormatErrorCount + ", " + "transceiverACKErrorCount = " + transceiverACKErrorCount + ", " + "transceiverBit1ErrorCount = " + transceiverBit1ErrorCount + ", " + "transceiverBit0ErrorCount = " + transceiverBit0ErrorCount + ", " + "transceiverCRCErrorCount = " + transceiverCRCErrorCount + ", " + "writeBufferTimeoutErrorCount = " + writeBufferTimeoutErrorCount + ", " + "readBufferOverflowErrorCount = " + readBufferOverflowErrorCount + ", " + "readBufferOverflowErrorOccurredLength = " + readBufferOverflowErrorOccurredLength + ", " + "readBufferOverflowErrorOccurredData = " + Arrays.toString(readBufferOverflowErrorOccurredData) + ", " + "readBacklogOverflowErrorCount = " + readBacklogOverflowErrorCount + "]";
		}
	}

	public class SPITFPErrorCount {
		public long errorCountAckChecksum;
		public long errorCountMessageChecksum;
		public long errorCountFrame;
		public long errorCountOverflow;

		public String toString() {
			return "[" + "errorCountAckChecksum = " + errorCountAckChecksum + ", " + "errorCountMessageChecksum = " + errorCountMessageChecksum + ", " + "errorCountFrame = " + errorCountFrame + ", " + "errorCountOverflow = " + errorCountOverflow + "]";
		}
	}

	public class ReadFrame {
		public boolean success;
		public int frameType;
		public long identifier;
		public int[] data;

		public ReadFrame(boolean success, int frameType, long identifier, int[] data) {
			this.success = success;
			this.frameType = frameType;
			this.identifier = identifier;
			this.data = data;
		}

		public String toString() {
			return "[" + "success = " + success + ", " + "frameType = " + frameType + ", " + "identifier = " + identifier + ", " + "data = " + Arrays.toString(data) + "]";
		}
	}

	public class QueueConfiguration {
		public int writeBufferSize;
		public int writeBufferTimeout;
		public int writeBacklogSize;
		public int[] readBufferSizes;
		public int readBacklogSize;

		public QueueConfiguration(int writeBufferSize, int writeBufferTimeout, int writeBacklogSize, int[] readBufferSizes, int readBacklogSize) {
			this.writeBufferSize = writeBufferSize;
			this.writeBufferTimeout = writeBufferTimeout;
			this.writeBacklogSize = writeBacklogSize;
			this.readBufferSizes = readBufferSizes;
			this.readBacklogSize = readBacklogSize;
		}

		public String toString() {
			return "[" + "writeBufferSize = " + writeBufferSize + ", " + "writeBufferTimeout = " + writeBufferTimeout + ", " + "writeBacklogSize = " + writeBacklogSize + ", " + "readBufferSizes = " + Arrays.toString(readBufferSizes) + ", " + "readBacklogSize = " + readBacklogSize + "]";
		}
	}

	public class ErrorLog {
		public int transceiverState;
		public int transceiverWriteErrorLevel;
		public int transceiverReadErrorLevel;
		public long transceiverStuffingErrorCount;
		public long transceiverFormatErrorCount;
		public long transceiverACKErrorCount;
		public long transceiverBit1ErrorCount;
		public long transceiverBit0ErrorCount;
		public long transceiverCRCErrorCount;
		public long writeBufferTimeoutErrorCount;
		public long readBufferOverflowErrorCount;
		public boolean[] readBufferOverflowErrorOccurred;
		public long readBacklogOverflowErrorCount;

		public ErrorLog(int transceiverState, int transceiverWriteErrorLevel, int transceiverReadErrorLevel, long transceiverStuffingErrorCount, long transceiverFormatErrorCount, long transceiverACKErrorCount, long transceiverBit1ErrorCount, long transceiverBit0ErrorCount, long transceiverCRCErrorCount, long writeBufferTimeoutErrorCount, long readBufferOverflowErrorCount, boolean[] readBufferOverflowErrorOccurred, long readBacklogOverflowErrorCount) {
			this.transceiverState = transceiverState;
			this.transceiverWriteErrorLevel = transceiverWriteErrorLevel;
			this.transceiverReadErrorLevel = transceiverReadErrorLevel;
			this.transceiverStuffingErrorCount = transceiverStuffingErrorCount;
			this.transceiverFormatErrorCount = transceiverFormatErrorCount;
			this.transceiverACKErrorCount = transceiverACKErrorCount;
			this.transceiverBit1ErrorCount = transceiverBit1ErrorCount;
			this.transceiverBit0ErrorCount = transceiverBit0ErrorCount;
			this.transceiverCRCErrorCount = transceiverCRCErrorCount;
			this.writeBufferTimeoutErrorCount = writeBufferTimeoutErrorCount;
			this.readBufferOverflowErrorCount = readBufferOverflowErrorCount;
			this.readBufferOverflowErrorOccurred = readBufferOverflowErrorOccurred;
			this.readBacklogOverflowErrorCount = readBacklogOverflowErrorCount;
		}

		public String toString() {
			return "[" + "transceiverState = " + transceiverState + ", " + "transceiverWriteErrorLevel = " + transceiverWriteErrorLevel + ", " + "transceiverReadErrorLevel = " + transceiverReadErrorLevel + ", " + "transceiverStuffingErrorCount = " + transceiverStuffingErrorCount + ", " + "transceiverFormatErrorCount = " + transceiverFormatErrorCount + ", " + "transceiverACKErrorCount = " + transceiverACKErrorCount + ", " + "transceiverBit1ErrorCount = " + transceiverBit1ErrorCount + ", " + "transceiverBit0ErrorCount = " + transceiverBit0ErrorCount + ", " + "transceiverCRCErrorCount = " + transceiverCRCErrorCount + ", " + "writeBufferTimeoutErrorCount = " + writeBufferTimeoutErrorCount + ", " + "readBufferOverflowErrorCount = " + readBufferOverflowErrorCount + ", " + "readBufferOverflowErrorOccurred = " + Arrays.toString(readBufferOverflowErrorOccurred) + ", " + "readBacklogOverflowErrorCount = " + readBacklogOverflowErrorCount + "]";
		}
	}

	/**
	 * @see FrameReadListener
	 */
	public interface FrameReadLowLevelListener extends DeviceListener {
		public void frameReadLowLevel(int frameType, long identifier, int dataLength, int[] dataData);
	}

	/**
	 * This listener is triggered if a data or remote frame was received by the CAN
	 * transceiver.
	 * 
	 * The ``identifier`` return value follows the identifier format described for
	 * {@link BrickletCANV2#writeFrame(int, long, int[])}.
	 * 
	 * For details on the ``data`` return value see {@link BrickletCANV2#readFrame()}.
	 * 
	 * A configurable read filter can be used to define which frames should be
	 * received by the CAN transceiver and put into the read queue (see
	 * {@link BrickletCANV2#setQueueConfiguration(int, int, int, int[], int)}).
	 * 
	 * To enable this listener, use {@link BrickletCANV2#setFrameReadCallbackConfiguration(boolean)}.
	 * 
	 * \note
	 *  If reconstructing the value fails, the listener is triggered with null for data.
	 */
	public interface FrameReadListener extends DeviceListener {
		public void frameRead(int frameType, long identifier, int[] data);
	}

	/**
	 * Creates an object with the unique device ID \c uid. and adds it to
	 * the IP Connection \c ipcon.
	 */
	public BrickletCANV2(String uid, IPConnection ipcon) {
		super(uid, ipcon);

		apiVersion[0] = 2;
		apiVersion[1] = 0;
		apiVersion[2] = 0;
		responseExpected[IPConnection.unsignedByte(FUNCTION_WRITE_FRAME_LOW_LEVEL)] = RESPONSE_EXPECTED_FLAG_ALWAYS_TRUE;
		responseExpected[IPConnection.unsignedByte(FUNCTION_READ_FRAME_LOW_LEVEL)] = RESPONSE_EXPECTED_FLAG_ALWAYS_TRUE;
		responseExpected[IPConnection.unsignedByte(FUNCTION_SET_FRAME_READ_CALLBACK_CONFIGURATION)] = RESPONSE_EXPECTED_FLAG_TRUE;
		responseExpected[IPConnection.unsignedByte(FUNCTION_GET_FRAME_READ_CALLBACK_CONFIGURATION)] = RESPONSE_EXPECTED_FLAG_ALWAYS_TRUE;
		responseExpected[IPConnection.unsignedByte(FUNCTION_SET_TRANSCEIVER_CONFIGURATION)] = RESPONSE_EXPECTED_FLAG_FALSE;
		responseExpected[IPConnection.unsignedByte(FUNCTION_GET_TRANSCEIVER_CONFIGURATION)] = RESPONSE_EXPECTED_FLAG_ALWAYS_TRUE;
		responseExpected[IPConnection.unsignedByte(FUNCTION_SET_QUEUE_CONFIGURATION_LOW_LEVEL)] = RESPONSE_EXPECTED_FLAG_TRUE;
		responseExpected[IPConnection.unsignedByte(FUNCTION_GET_QUEUE_CONFIGURATION_LOW_LEVEL)] = RESPONSE_EXPECTED_FLAG_ALWAYS_TRUE;
		responseExpected[IPConnection.unsignedByte(FUNCTION_SET_READ_FILTER_CONFIGURATION)] = RESPONSE_EXPECTED_FLAG_FALSE;
		responseExpected[IPConnection.unsignedByte(FUNCTION_GET_READ_FILTER_CONFIGURATION)] = RESPONSE_EXPECTED_FLAG_ALWAYS_TRUE;
		responseExpected[IPConnection.unsignedByte(FUNCTION_GET_ERROR_LOG_LOW_LEVEL)] = RESPONSE_EXPECTED_FLAG_ALWAYS_TRUE;
		responseExpected[IPConnection.unsignedByte(FUNCTION_SET_COMMUNICATION_LED_CONFIG)] = RESPONSE_EXPECTED_FLAG_FALSE;
		responseExpected[IPConnection.unsignedByte(FUNCTION_GET_COMMUNICATION_LED_CONFIG)] = RESPONSE_EXPECTED_FLAG_ALWAYS_TRUE;
		responseExpected[IPConnection.unsignedByte(FUNCTION_SET_ERROR_LED_CONFIG)] = RESPONSE_EXPECTED_FLAG_FALSE;
		responseExpected[IPConnection.unsignedByte(FUNCTION_GET_ERROR_LED_CONFIG)] = RESPONSE_EXPECTED_FLAG_ALWAYS_TRUE;
		responseExpected[IPConnection.unsignedByte(FUNCTION_GET_SPITFP_ERROR_COUNT)] = RESPONSE_EXPECTED_FLAG_ALWAYS_TRUE;
		responseExpected[IPConnection.unsignedByte(FUNCTION_SET_BOOTLOADER_MODE)] = RESPONSE_EXPECTED_FLAG_ALWAYS_TRUE;
		responseExpected[IPConnection.unsignedByte(FUNCTION_GET_BOOTLOADER_MODE)] = RESPONSE_EXPECTED_FLAG_ALWAYS_TRUE;
		responseExpected[IPConnection.unsignedByte(FUNCTION_SET_WRITE_FIRMWARE_POINTER)] = RESPONSE_EXPECTED_FLAG_FALSE;
		responseExpected[IPConnection.unsignedByte(FUNCTION_WRITE_FIRMWARE)] = RESPONSE_EXPECTED_FLAG_ALWAYS_TRUE;
		responseExpected[IPConnection.unsignedByte(FUNCTION_SET_STATUS_LED_CONFIG)] = RESPONSE_EXPECTED_FLAG_FALSE;
		responseExpected[IPConnection.unsignedByte(FUNCTION_GET_STATUS_LED_CONFIG)] = RESPONSE_EXPECTED_FLAG_ALWAYS_TRUE;
		responseExpected[IPConnection.unsignedByte(FUNCTION_GET_CHIP_TEMPERATURE)] = RESPONSE_EXPECTED_FLAG_ALWAYS_TRUE;
		responseExpected[IPConnection.unsignedByte(FUNCTION_RESET)] = RESPONSE_EXPECTED_FLAG_FALSE;
		responseExpected[IPConnection.unsignedByte(FUNCTION_WRITE_UID)] = RESPONSE_EXPECTED_FLAG_FALSE;
		responseExpected[IPConnection.unsignedByte(FUNCTION_READ_UID)] = RESPONSE_EXPECTED_FLAG_ALWAYS_TRUE;
		responseExpected[IPConnection.unsignedByte(FUNCTION_GET_IDENTITY)] = RESPONSE_EXPECTED_FLAG_ALWAYS_TRUE;

		highLevelCallbacks[-CALLBACK_FRAME_READ] = new IPConnection.DeviceHighLevelCallback();
		callbacks[CALLBACK_FRAME_READ_LOW_LEVEL] = new IPConnection.DeviceCallbackListener() {
			public void callback(byte[] packet) {
				ByteBuffer bb = ByteBuffer.wrap(packet, 8, packet.length - 8);
				bb.order(ByteOrder.LITTLE_ENDIAN);

				int frameType = IPConnection.unsignedByte(bb.get());
				long identifier = IPConnection.unsignedInt(bb.getInt());
				int dataLength = IPConnection.unsignedByte(bb.get());
				int[] dataData = new int[15];
				for (int i = 0; i < 15; i++) {
					dataData[i] = IPConnection.unsignedByte(bb.get());
				}

				int[] data = new int[dataLength];

				System.arraycopy(dataData, 0, data, 0, dataLength);

				for (FrameReadListener listener: listenerFrameRead) {
					listener.frameRead(frameType, identifier, data);
				}

				for (FrameReadLowLevelListener listener: listenerFrameReadLowLevel) {
					listener.frameReadLowLevel(frameType, identifier, dataLength, dataData);
				}
			}
		};
	}

	/**
	 * Writes a data or remote frame to the write queue to be transmitted over the
	 * CAN transceiver.
	 * 
	 * The Bricklet supports the standard 11-bit (CAN 2.0A) and the additional extended
	 * 29-bit (CAN 2.0B) identifiers. For standard frames the Bricklet uses bit 0 to 10
	 * from the ``identifier`` parameter as standard 11-bit identifier. For extended
	 * frames the Bricklet uses bit 0 to 28 from the ``identifier`` parameter as
	 * extended 29-bit identifier.
	 * 
	 * The ``data`` parameter can be up to 15 bytes long. For data frames up to 8 bytes
	 * will be used as the actual data. The length (DLC) field in the data or remote
	 * frame will be set to the actual length of the ``data`` parameter. This allows
	 * to transmit data and remote frames with excess length. For remote frames only
	 * the length of the ``data`` parameter is used. The actual ``data`` bytes are
	 * ignored.
	 * 
	 * Returns *true* if the frame was successfully added to the write queue. Returns
	 * *false* if the frame could not be added because write queue is already full or
	 * because the write buffer or the write backlog are configured with a size of
	 * zero (see {@link BrickletCANV2#setQueueConfiguration(int, int, int, int[], int)}).
	 * 
	 * The write queue can overflow if frames are written to it at a higher rate
	 * than the Bricklet can transmitted them over the CAN transceiver. This may
	 * happen if the CAN transceiver is configured as read-only or is using a low baud
	 * rate (see {@link BrickletCANV2#setTransceiverConfiguration(long, int, int)}). It can also happen if the CAN
	 * bus is congested and the frame cannot be transmitted because it constantly loses
	 * arbitration or because the CAN transceiver is currently disabled due to a high
	 * write error level (see {@link BrickletCANV2#getErrorLog()}).
	 */
	public boolean writeFrameLowLevel(int frameType, long identifier, int dataLength, int[] dataData) throws TinkerforgeException {
		ByteBuffer bb = ipcon.createRequestPacket((byte)29, FUNCTION_WRITE_FRAME_LOW_LEVEL, this);

		bb.put((byte)frameType);
		bb.putInt((int)identifier);
		bb.put((byte)dataLength);
		for (int i = 0; i < 15; i++) {
			bb.put((byte)dataData[i]);
		}

		byte[] response = sendRequest(bb.array());

		bb = ByteBuffer.wrap(response, 8, response.length - 8);
		bb.order(ByteOrder.LITTLE_ENDIAN);

		boolean success = (bb.get()) != 0;

		return success;
	}

	/**
	 * Tries to read the next data or remote frame from the read queue and returns it.
	 * If a frame was successfully read, then the ``success`` return value is set to
	 * *true* and the other return values contain the frame. If the read queue is
	 * empty and no frame could be read, then the ``success`` return value is set to
	 * *false* and the other return values contain invalid data.
	 * 
	 * The ``identifier`` return value follows the identifier format described for
	 * {@link BrickletCANV2#writeFrame(int, long, int[])}.
	 * 
	 * The ``data`` return value can be up to 15 bytes long. For data frames up to the
	 * first 8 bytes are the actual received data. All bytes after the 8th byte are
	 * always zero and only there to indicate the length of a data or remote frame
	 * with excess length. For remote frames the length of the ``data`` return value
	 * represents the requested length. The actual ``data`` bytes are always zero.
	 * 
	 * A configurable read filter can be used to define which frames should be
	 * received by the CAN transceiver and put into the read queue (see
	 * {@link BrickletCANV2#setReadFilterConfiguration(int, int, long, long)}).
	 * 
	 * Instead of polling with this function, you can also use listeners. See the
	 * {@link BrickletCANV2#setFrameReadCallbackConfiguration(boolean)} function and the {@link BrickletCANV2.FrameReadListener}
	 * callback.
	 */
	public ReadFrameLowLevel readFrameLowLevel() throws TinkerforgeException {
		ByteBuffer bb = ipcon.createRequestPacket((byte)8, FUNCTION_READ_FRAME_LOW_LEVEL, this);


		byte[] response = sendRequest(bb.array());

		bb = ByteBuffer.wrap(response, 8, response.length - 8);
		bb.order(ByteOrder.LITTLE_ENDIAN);

		ReadFrameLowLevel obj = new ReadFrameLowLevel();
		obj.success = (bb.get()) != 0;
		obj.frameType = IPConnection.unsignedByte(bb.get());
		obj.identifier = IPConnection.unsignedInt(bb.getInt());
		obj.dataLength = IPConnection.unsignedByte(bb.get());
		for (int i = 0; i < 15; i++) {
			obj.dataData[i] = IPConnection.unsignedByte(bb.get());
		}

		return obj;
	}

	/**
	 * Enables and disables the {@link BrickletCANV2.FrameReadListener} listener.
	 * 
	 * By default the listener is disabled.
	 */
	public void setFrameReadCallbackConfiguration(boolean enabled) throws TinkerforgeException {
		ByteBuffer bb = ipcon.createRequestPacket((byte)9, FUNCTION_SET_FRAME_READ_CALLBACK_CONFIGURATION, this);

		bb.put((byte)(enabled ? 1 : 0));

		sendRequest(bb.array());
	}

	/**
	 * Returns *true* if the {@link BrickletCANV2.FrameReadListener} listener is enabled, *false* otherwise.
	 */
	public boolean getFrameReadCallbackConfiguration() throws TinkerforgeException {
		ByteBuffer bb = ipcon.createRequestPacket((byte)8, FUNCTION_GET_FRAME_READ_CALLBACK_CONFIGURATION, this);


		byte[] response = sendRequest(bb.array());

		bb = ByteBuffer.wrap(response, 8, response.length - 8);
		bb.order(ByteOrder.LITTLE_ENDIAN);

		boolean enabled = (bb.get()) != 0;

		return enabled;
	}

	/**
	 * Sets the transceiver configuration for the CAN bus communication.
	 * 
	 * The CAN transceiver has three different modes:
	 * 
	 * * Normal: Reads from and writes to the CAN bus and performs active bus
	 *   error detection and acknowledgement.
	 * * Loopback: All reads and writes are performed internally. The transceiver
	 *   is disconnected from the actual CAN bus.
	 * * Read-Only: Only reads from the CAN bus, but does neither active bus error
	 *   detection nor acknowledgement. Only the receiving part of the transceiver
	 *   is connected to the CAN bus.
	 */
	public void setTransceiverConfiguration(long baudRate, int samplePoint, int transceiverMode) throws TinkerforgeException {
		ByteBuffer bb = ipcon.createRequestPacket((byte)15, FUNCTION_SET_TRANSCEIVER_CONFIGURATION, this);

		bb.putInt((int)baudRate);
		bb.putShort((short)samplePoint);
		bb.put((byte)transceiverMode);

		sendRequest(bb.array());
	}

	/**
	 * Returns the configuration as set by {@link BrickletCANV2#setTransceiverConfiguration(long, int, int)}.
	 */
	public TransceiverConfiguration getTransceiverConfiguration() throws TinkerforgeException {
		ByteBuffer bb = ipcon.createRequestPacket((byte)8, FUNCTION_GET_TRANSCEIVER_CONFIGURATION, this);


		byte[] response = sendRequest(bb.array());

		bb = ByteBuffer.wrap(response, 8, response.length - 8);
		bb.order(ByteOrder.LITTLE_ENDIAN);

		TransceiverConfiguration obj = new TransceiverConfiguration();
		obj.baudRate = IPConnection.unsignedInt(bb.getInt());
		obj.samplePoint = IPConnection.unsignedShort(bb.getShort());
		obj.transceiverMode = IPConnection.unsignedByte(bb.get());

		return obj;
	}

	/**
	 * Sets the write and read queue configuration.
	 * 
	 * The CAN transceiver has 32 buffers in total in hardware for transmitting and
	 * receiving frames. Additionally, the Bricklet has a backlog for 768 frames in
	 * total in software. The buffers and the backlog can be freely assigned to the
	 * write and read queues.
	 * 
	 * {@link BrickletCANV2#writeFrame(int, long, int[])} writes a frame into the write backlog. The Bricklet moves
	 * the frame from the backlog into a free write buffer. The CAN transceiver then
	 * transmits the frame from the write buffer to the CAN bus. If there are no
	 * write buffers (``write_buffer_size`` is zero) or there is no write backlog
	 * (``write_backlog_size`` is zero) then no frames can be transmitted and
	 * {@link BrickletCANV2#writeFrame(int, long, int[])} returns always *false*.
	 * 
	 * The CAN transceiver receives a frame from the CAN bus and stores it into a
	 * free read buffer. The Bricklet moves the frame from the read buffer into the
	 * read backlog. {@link BrickletCANV2#readFrame()} reads the frame from the read backlog and
	 * returns it. If there are no read buffers (``read_buffer_sizes`` is empty) or
	 * there is no read backlog (``read_backlog_size`` is zero) then no frames can be
	 * received and {@link BrickletCANV2#readFrame()} returns always *false*.
	 * 
	 * There can be multiple read buffers, because the CAN transceiver cannot receive
	 * data and remote frames into the same read buffer. A positive read buffer size
	 * represents a data frame read buffer and a negative read buffer size represents
	 * a remote frame read buffer. A read buffer size of zero is not allowed. By
	 * default the first read buffer is configured for data frames and the second read
	 * buffer is configured for remote frame. There can be up to 32 different read
	 * buffers, assuming that no write buffer is used. Each read buffer has its own
	 * filter configuration (see {@link BrickletCANV2#setReadFilterConfiguration(int, int, long, long)}).
	 * 
	 * A valid queue configuration fulfills these conditions::
	 * 
	 *  write_buffer_size + abs(read_buffer_size_0) + abs(read_buffer_size_1) + ... + abs(read_buffer_size_31) <= 32
	 *  write_backlog_size + read_backlog_size <= 768
	 * 
	 * The write buffer timeout has three different modes that define how a failed
	 * frame transmission should be handled:
	 * 
	 * * Single-Shot (< 0): Only one transmission attempt will be made. If the
	 *   transmission fails then the frame is discarded.
	 * * Infinite (= 0): Infinite transmission attempts will be made. The frame will
	 *   never be discarded.
	 * * Milliseconds (> 0): A limited number of transmission attempts will be made.
	 *   If the frame could not be transmitted successfully after the configured
	 *   number of milliseconds then the frame is discarded.
	 * 
	 * The current content of the queues is lost when this function is called.
	 */
	public void setQueueConfigurationLowLevel(int writeBufferSize, int writeBufferTimeout, int writeBacklogSize, int readBufferSizesLength, int[] readBufferSizesData, int readBacklogSize) throws TinkerforgeException {
		ByteBuffer bb = ipcon.createRequestPacket((byte)50, FUNCTION_SET_QUEUE_CONFIGURATION_LOW_LEVEL, this);

		bb.put((byte)writeBufferSize);
		bb.putInt(writeBufferTimeout);
		bb.putShort((short)writeBacklogSize);
		bb.put((byte)readBufferSizesLength);
		for (int i = 0; i < 32; i++) {
			bb.put((byte)readBufferSizesData[i]);
		}
		bb.putShort((short)readBacklogSize);

		sendRequest(bb.array());
	}

	/**
	 * Returns the queue configuration as set by {@link BrickletCANV2#setQueueConfiguration(int, int, int, int[], int)}.
	 */
	public QueueConfigurationLowLevel getQueueConfigurationLowLevel() throws TinkerforgeException {
		ByteBuffer bb = ipcon.createRequestPacket((byte)8, FUNCTION_GET_QUEUE_CONFIGURATION_LOW_LEVEL, this);


		byte[] response = sendRequest(bb.array());

		bb = ByteBuffer.wrap(response, 8, response.length - 8);
		bb.order(ByteOrder.LITTLE_ENDIAN);

		QueueConfigurationLowLevel obj = new QueueConfigurationLowLevel();
		obj.writeBufferSize = IPConnection.unsignedByte(bb.get());
		obj.writeBufferTimeout = (bb.getInt());
		obj.writeBacklogSize = IPConnection.unsignedShort(bb.getShort());
		obj.readBufferSizesLength = IPConnection.unsignedByte(bb.get());
		for (int i = 0; i < 32; i++) {
			obj.readBufferSizesData[i] = (bb.get());
		}
		obj.readBacklogSize = IPConnection.unsignedShort(bb.getShort());

		return obj;
	}

	/**
	 * Set the read filter configuration for the given read buffer index. This can be
	 * used to define which frames should be received by the CAN transceiver and put
	 * into the read buffer.
	 * 
	 * The read filter has four different modes that define if and how the filter mask
	 * and the filter identifier are applied:
	 * 
	 * * Accept-All: All frames are received.
	 * * Match-Standard-Only: Only standard frames with a matching identifier are
	 *   received.
	 * * Match-Extended-Only: Only extended frames with a matching identifier are
	 *   received.
	 * * Match-Standard-And-Extended: Standard and extended frames with a matching
	 *   identifier are received.
	 * 
	 * The filter mask and filter identifier are used as bit masks. Their usage
	 * depends on the mode:
	 * 
	 * * Accept-All: Mask and identifier are ignored.
	 * * Match-Standard-Only: Bit 0 to 10 (11 bits) of filter mask and filter
	 *   identifier are used to match the 11-bit identifier of standard frames.
	 * * Match-Extended-Only: Bit 0 to 28 (29 bits) of filter mask and filter
	 *   identifier are used to match the 29-bit identifier of extended frames.
	 * * Match-Standard-And-Extended: Bit 18 to 28 (11 bits) of filter mask and filter
	 *   identifier are used to match the 11-bit identifier of standard frames, bit 0
	 *   to 17 (18 bits) are ignored in this case. Bit 0 to 28 (29 bits) of filter
	 *   mask and filter identifier are used to match the 29-bit identifier of extended
	 *   frames.
	 * 
	 * The filter mask and filter identifier are applied in this way: The filter mask
	 * is used to select the frame identifier bits that should be compared to the
	 * corresponding filter identifier bits. All unselected bits are automatically
	 * accepted. All selected bits have to match the filter identifier to be accepted.
	 * If all bits for the selected mode are accepted then the frame is accepted and
	 * is added to the read buffer.
	 * 
	 * \verbatim
	 *  "Filter Mask Bit", "Filter Identifier Bit", "Frame Identifier Bit", "Result"
	 * 
	 *  0, X, X, Accept
	 *  1, 0, 0, Accept
	 *  1, 0, 1, Reject
	 *  1, 1, 0, Reject
	 *  1, 1, 1, Accept
	 * \endverbatim
	 * 
	 * For example, to receive standard frames with identifier 0x123 only, the mode
	 * can be set to Match-Standard-Only with 0x7FF as mask and 0x123 as identifier.
	 * The mask of 0x7FF selects all 11 identifier bits for matching so that the
	 * identifier has to be exactly 0x123 to be accepted.
	 * 
	 * To accept identifier 0x123 and identifier 0x456 at the same time, just set
	 * filter 2 to 0x456 and keep mask and filter 1 unchanged.
	 * 
	 * There can be up to 32 different read filters configured at the same time,
	 * because there can be up to 32 read buffer (see {@link BrickletCANV2#setQueueConfiguration(int, int, int, int[], int)}).
	 * 
	 * The default mode is accept-all for all read buffers.
	 */
	public void setReadFilterConfiguration(int bufferIndex, int filterMode, long filterMask, long filterIdentifier) throws TinkerforgeException {
		ByteBuffer bb = ipcon.createRequestPacket((byte)18, FUNCTION_SET_READ_FILTER_CONFIGURATION, this);

		bb.put((byte)bufferIndex);
		bb.put((byte)filterMode);
		bb.putInt((int)filterMask);
		bb.putInt((int)filterIdentifier);

		sendRequest(bb.array());
	}

	/**
	 * Returns the read filter configuration as set by {@link BrickletCANV2#setReadFilterConfiguration(int, int, long, long)}.
	 */
	public ReadFilterConfiguration getReadFilterConfiguration(int bufferIndex) throws TinkerforgeException {
		ByteBuffer bb = ipcon.createRequestPacket((byte)9, FUNCTION_GET_READ_FILTER_CONFIGURATION, this);

		bb.put((byte)bufferIndex);

		byte[] response = sendRequest(bb.array());

		bb = ByteBuffer.wrap(response, 8, response.length - 8);
		bb.order(ByteOrder.LITTLE_ENDIAN);

		ReadFilterConfiguration obj = new ReadFilterConfiguration();
		obj.filterMode = IPConnection.unsignedByte(bb.get());
		obj.filterMask = IPConnection.unsignedInt(bb.getInt());
		obj.filterIdentifier = IPConnection.unsignedInt(bb.getInt());

		return obj;
	}

	/**
	 * Returns information about different kinds of errors.
	 * 
	 * The write and read error levels indicate the current level of stuffing, form,
	 * acknowledgement, bit and checksum errors during CAN bus write and read
	 * operations. For each of this error kinds there is also an individual counter.
	 * 
	 * When the write error level extends 255 then the CAN transceiver gets disabled
	 * and no frames can be transmitted or received anymore. The CAN transceiver will
	 * automatically be activated again after the CAN bus is idle for a while.
	 * 
	 * The write buffer timeout, read buffer and backlog overflow counts represents the
	 * number of these errors:
	 * 
	 * * A write buffer timeout occurs if a frame could not be transmitted before the
	 *   configured write buffer timeout expired (see {@link BrickletCANV2#setQueueConfiguration(int, int, int, int[], int)}).
	 * * A read buffer overflow occurs if a read buffer of the CAN transceiver
	 *   still contains the last received frame when the next frame arrives. In this
	 *   case the last received frame is lost. This happens if the CAN transceiver
	 *   receives more frames than the Bricklet can handle. Using the read filter
	 *   (see {@link BrickletCANV2#setReadFilterConfiguration(int, int, long, long)}) can help to reduce the amount of
	 *   received frames. This count is not exact, but a lower bound, because the
	 *   Bricklet might not able detect all overflows if they occur in rapid succession.
	 * * A read backlog overflow occurs if the read backlog of the Bricklet is already
	 *   full when the next frame should be read from a read buffer of the CAN
	 *   transceiver. In this case the frame in the read buffer is lost. This
	 *   happens if the CAN transceiver receives more frames to be added to the read
	 *   backlog than are removed from the read backlog using the {@link BrickletCANV2#readFrame()}
	 *   function. Using the {@link BrickletCANV2.FrameReadListener} listener ensures that the read backlog
	 *   can not overflow.
	 * 
	 * The read buffer overflow counter counts the overflows of all configured read
	 * buffers. Which read buffer exactly suffered from an overflow can be figured
	 * out from the read buffer overflow occurrence list
	 * (``read_buffer_overflow_error_occurred``).
	 */
	public ErrorLogLowLevel getErrorLogLowLevel() throws TinkerforgeException {
		ByteBuffer bb = ipcon.createRequestPacket((byte)8, FUNCTION_GET_ERROR_LOG_LOW_LEVEL, this);


		byte[] response = sendRequest(bb.array());

		bb = ByteBuffer.wrap(response, 8, response.length - 8);
		bb.order(ByteOrder.LITTLE_ENDIAN);

		ErrorLogLowLevel obj = new ErrorLogLowLevel();
		obj.transceiverState = IPConnection.unsignedByte(bb.get());
		obj.transceiverWriteErrorLevel = IPConnection.unsignedByte(bb.get());
		obj.transceiverReadErrorLevel = IPConnection.unsignedByte(bb.get());
		obj.transceiverStuffingErrorCount = IPConnection.unsignedInt(bb.getInt());
		obj.transceiverFormatErrorCount = IPConnection.unsignedInt(bb.getInt());
		obj.transceiverACKErrorCount = IPConnection.unsignedInt(bb.getInt());
		obj.transceiverBit1ErrorCount = IPConnection.unsignedInt(bb.getInt());
		obj.transceiverBit0ErrorCount = IPConnection.unsignedInt(bb.getInt());
		obj.transceiverCRCErrorCount = IPConnection.unsignedInt(bb.getInt());
		obj.writeBufferTimeoutErrorCount = IPConnection.unsignedInt(bb.getInt());
		obj.readBufferOverflowErrorCount = IPConnection.unsignedInt(bb.getInt());
		obj.readBufferOverflowErrorOccurredLength = IPConnection.unsignedByte(bb.get());
		byte[] readBufferOverflowErrorOccurredDataBits = new byte[4];
		bb.get(readBufferOverflowErrorOccurredDataBits);
		for (int i = 0; i < 32; i++) {
			obj.readBufferOverflowErrorOccurredData[i] = (readBufferOverflowErrorOccurredDataBits[i / 8] & (1 << (i % 8))) != 0;
		}

		obj.readBacklogOverflowErrorCount = IPConnection.unsignedInt(bb.getInt());

		return obj;
	}

	/**
	 * Sets the communication LED configuration. By default the LED shows
	 * CAN-Bus traffic, it flickers once for every 40 transmitted or received frames.
	 * 
	 * You can also turn the LED permanently on/off or show a heartbeat.
	 * 
	 * If the Bricklet is in bootloader mode, the LED is off.
	 */
	public void setCommunicationLEDConfig(int config) throws TinkerforgeException {
		ByteBuffer bb = ipcon.createRequestPacket((byte)9, FUNCTION_SET_COMMUNICATION_LED_CONFIG, this);

		bb.put((byte)config);

		sendRequest(bb.array());
	}

	/**
	 * Returns the configuration as set by {@link BrickletCANV2#setCommunicationLEDConfig(int)}
	 */
	public int getCommunicationLEDConfig() throws TinkerforgeException {
		ByteBuffer bb = ipcon.createRequestPacket((byte)8, FUNCTION_GET_COMMUNICATION_LED_CONFIG, this);


		byte[] response = sendRequest(bb.array());

		bb = ByteBuffer.wrap(response, 8, response.length - 8);
		bb.order(ByteOrder.LITTLE_ENDIAN);

		int config = IPConnection.unsignedByte(bb.get());

		return config;
	}

	/**
	 * Sets the error LED configuration.
	 * 
	 * By default (show-transceiver-state) the error LED turns on if the CAN
	 * transceiver is passive or disabled state (see {@link BrickletCANV2#getErrorLog()}). If
	 * the CAN transceiver is in active state the LED turns off.
	 * 
	 * If the LED is configured as show-error then the error LED turns on if any error
	 * occurs. If you call this function with the show-error option again, the LED will
	 * turn off until the next error occurs.
	 * 
	 * You can also turn the LED permanently on/off or show a heartbeat.
	 * 
	 * If the Bricklet is in bootloader mode, the LED is off.
	 */
	public void setErrorLEDConfig(int config) throws TinkerforgeException {
		ByteBuffer bb = ipcon.createRequestPacket((byte)9, FUNCTION_SET_ERROR_LED_CONFIG, this);

		bb.put((byte)config);

		sendRequest(bb.array());
	}

	/**
	 * Returns the configuration as set by {@link BrickletCANV2#setErrorLEDConfig(int)}.
	 */
	public int getErrorLEDConfig() throws TinkerforgeException {
		ByteBuffer bb = ipcon.createRequestPacket((byte)8, FUNCTION_GET_ERROR_LED_CONFIG, this);


		byte[] response = sendRequest(bb.array());

		bb = ByteBuffer.wrap(response, 8, response.length - 8);
		bb.order(ByteOrder.LITTLE_ENDIAN);

		int config = IPConnection.unsignedByte(bb.get());

		return config;
	}

	/**
	 * Returns the error count for the communication between Brick and Bricklet.
	 * 
	 * The errors are divided into
	 * 
	 * * ACK checksum errors,
	 * * message checksum errors,
	 * * framing errors and
	 * * overflow errors.
	 * 
	 * The errors counts are for errors that occur on the Bricklet side. All
	 * Bricks have a similar function that returns the errors on the Brick side.
	 */
	public SPITFPErrorCount getSPITFPErrorCount() throws TinkerforgeException {
		ByteBuffer bb = ipcon.createRequestPacket((byte)8, FUNCTION_GET_SPITFP_ERROR_COUNT, this);


		byte[] response = sendRequest(bb.array());

		bb = ByteBuffer.wrap(response, 8, response.length - 8);
		bb.order(ByteOrder.LITTLE_ENDIAN);

		SPITFPErrorCount obj = new SPITFPErrorCount();
		obj.errorCountAckChecksum = IPConnection.unsignedInt(bb.getInt());
		obj.errorCountMessageChecksum = IPConnection.unsignedInt(bb.getInt());
		obj.errorCountFrame = IPConnection.unsignedInt(bb.getInt());
		obj.errorCountOverflow = IPConnection.unsignedInt(bb.getInt());

		return obj;
	}

	/**
	 * Sets the bootloader mode and returns the status after the requested
	 * mode change was instigated.
	 * 
	 * You can change from bootloader mode to firmware mode and vice versa. A change
	 * from bootloader mode to firmware mode will only take place if the entry function,
	 * device identifier and CRC are present and correct.
	 * 
	 * This function is used by Brick Viewer during flashing. It should not be
	 * necessary to call it in a normal user program.
	 */
	public int setBootloaderMode(int mode) throws TinkerforgeException {
		ByteBuffer bb = ipcon.createRequestPacket((byte)9, FUNCTION_SET_BOOTLOADER_MODE, this);

		bb.put((byte)mode);

		byte[] response = sendRequest(bb.array());

		bb = ByteBuffer.wrap(response, 8, response.length - 8);
		bb.order(ByteOrder.LITTLE_ENDIAN);

		int status = IPConnection.unsignedByte(bb.get());

		return status;
	}

	/**
	 * Returns the current bootloader mode, see {@link BrickletCANV2#setBootloaderMode(int)}.
	 */
	public int getBootloaderMode() throws TinkerforgeException {
		ByteBuffer bb = ipcon.createRequestPacket((byte)8, FUNCTION_GET_BOOTLOADER_MODE, this);


		byte[] response = sendRequest(bb.array());

		bb = ByteBuffer.wrap(response, 8, response.length - 8);
		bb.order(ByteOrder.LITTLE_ENDIAN);

		int mode = IPConnection.unsignedByte(bb.get());

		return mode;
	}

	/**
	 * Sets the firmware pointer for {@link BrickletCANV2#writeFirmware(int[])}. The pointer has
	 * to be increased by chunks of size 64. The data is written to flash
	 * every 4 chunks (which equals to one page of size 256).
	 * 
	 * This function is used by Brick Viewer during flashing. It should not be
	 * necessary to call it in a normal user program.
	 */
	public void setWriteFirmwarePointer(long pointer) throws TinkerforgeException {
		ByteBuffer bb = ipcon.createRequestPacket((byte)12, FUNCTION_SET_WRITE_FIRMWARE_POINTER, this);

		bb.putInt((int)pointer);

		sendRequest(bb.array());
	}

	/**
	 * Writes 64 Bytes of firmware at the position as written by
	 * {@link BrickletCANV2#setWriteFirmwarePointer(long)} before. The firmware is written
	 * to flash every 4 chunks.
	 * 
	 * You can only write firmware in bootloader mode.
	 * 
	 * This function is used by Brick Viewer during flashing. It should not be
	 * necessary to call it in a normal user program.
	 */
	public int writeFirmware(int[] data) throws TinkerforgeException {
		ByteBuffer bb = ipcon.createRequestPacket((byte)72, FUNCTION_WRITE_FIRMWARE, this);

		for (int i = 0; i < 64; i++) {
			bb.put((byte)data[i]);
		}

		byte[] response = sendRequest(bb.array());

		bb = ByteBuffer.wrap(response, 8, response.length - 8);
		bb.order(ByteOrder.LITTLE_ENDIAN);

		int status = IPConnection.unsignedByte(bb.get());

		return status;
	}

	/**
	 * Sets the status LED configuration. By default the LED shows
	 * communication traffic between Brick and Bricklet, it flickers once
	 * for every 10 received data packets.
	 * 
	 * You can also turn the LED permanently on/off or show a heartbeat.
	 * 
	 * If the Bricklet is in bootloader mode, the LED is will show heartbeat by default.
	 */
	public void setStatusLEDConfig(int config) throws TinkerforgeException {
		ByteBuffer bb = ipcon.createRequestPacket((byte)9, FUNCTION_SET_STATUS_LED_CONFIG, this);

		bb.put((byte)config);

		sendRequest(bb.array());
	}

	/**
	 * Returns the configuration as set by {@link BrickletCANV2#setStatusLEDConfig(int)}
	 */
	public int getStatusLEDConfig() throws TinkerforgeException {
		ByteBuffer bb = ipcon.createRequestPacket((byte)8, FUNCTION_GET_STATUS_LED_CONFIG, this);


		byte[] response = sendRequest(bb.array());

		bb = ByteBuffer.wrap(response, 8, response.length - 8);
		bb.order(ByteOrder.LITTLE_ENDIAN);

		int config = IPConnection.unsignedByte(bb.get());

		return config;
	}

	/**
	 * Returns the temperature in °C as measured inside the microcontroller. The
	 * value returned is not the ambient temperature!
	 * 
	 * The temperature is only proportional to the real temperature and it has bad
	 * accuracy. Practically it is only useful as an indicator for
	 * temperature changes.
	 */
	public int getChipTemperature() throws TinkerforgeException {
		ByteBuffer bb = ipcon.createRequestPacket((byte)8, FUNCTION_GET_CHIP_TEMPERATURE, this);


		byte[] response = sendRequest(bb.array());

		bb = ByteBuffer.wrap(response, 8, response.length - 8);
		bb.order(ByteOrder.LITTLE_ENDIAN);

		int temperature = (bb.getShort());

		return temperature;
	}

	/**
	 * Calling this function will reset the Bricklet. All configurations
	 * will be lost.
	 * 
	 * After a reset you have to create new device objects,
	 * calling functions on the existing ones will result in
	 * undefined behavior!
	 */
	public void reset() throws TinkerforgeException {
		ByteBuffer bb = ipcon.createRequestPacket((byte)8, FUNCTION_RESET, this);


		sendRequest(bb.array());
	}

	/**
	 * Writes a new UID into flash. If you want to set a new UID
	 * you have to decode the Base58 encoded UID string into an
	 * integer first.
	 * 
	 * We recommend that you use Brick Viewer to change the UID.
	 */
	public void writeUID(long uid) throws TinkerforgeException {
		ByteBuffer bb = ipcon.createRequestPacket((byte)12, FUNCTION_WRITE_UID, this);

		bb.putInt((int)uid);

		sendRequest(bb.array());
	}

	/**
	 * Returns the current UID as an integer. Encode as
	 * Base58 to get the usual string version.
	 */
	public long readUID() throws TinkerforgeException {
		ByteBuffer bb = ipcon.createRequestPacket((byte)8, FUNCTION_READ_UID, this);


		byte[] response = sendRequest(bb.array());

		bb = ByteBuffer.wrap(response, 8, response.length - 8);
		bb.order(ByteOrder.LITTLE_ENDIAN);

		long uid = IPConnection.unsignedInt(bb.getInt());

		return uid;
	}

	/**
	 * Returns the UID, the UID where the Bricklet is connected to,
	 * the position, the hardware and firmware version as well as the
	 * device identifier.
	 * 
	 * The position can be 'a', 'b', 'c' or 'd'.
	 * 
	 * The device identifier numbers can be found :ref:`here <device_identifier>`.
	 * |device_identifier_constant|
	 */
	public Identity getIdentity() throws TinkerforgeException {
		ByteBuffer bb = ipcon.createRequestPacket((byte)8, FUNCTION_GET_IDENTITY, this);


		byte[] response = sendRequest(bb.array());

		bb = ByteBuffer.wrap(response, 8, response.length - 8);
		bb.order(ByteOrder.LITTLE_ENDIAN);

		Identity obj = new Identity();
		obj.uid = IPConnection.string(bb, 8);
		obj.connectedUid = IPConnection.string(bb, 8);
		obj.position = (char)(bb.get());
		for (int i = 0; i < 3; i++) {
			obj.hardwareVersion[i] = IPConnection.unsignedByte(bb.get());
		}
		for (int i = 0; i < 3; i++) {
			obj.firmwareVersion[i] = IPConnection.unsignedByte(bb.get());
		}
		obj.deviceIdentifier = IPConnection.unsignedShort(bb.getShort());

		return obj;
	}

	/**
	 * Writes a data or remote frame to the write queue to be transmitted over the
	 * CAN transceiver.
	 * 
	 * The Bricklet supports the standard 11-bit (CAN 2.0A) and the additional extended
	 * 29-bit (CAN 2.0B) identifiers. For standard frames the Bricklet uses bit 0 to 10
	 * from the ``identifier`` parameter as standard 11-bit identifier. For extended
	 * frames the Bricklet uses bit 0 to 28 from the ``identifier`` parameter as
	 * extended 29-bit identifier.
	 * 
	 * The ``data`` parameter can be up to 15 bytes long. For data frames up to 8 bytes
	 * will be used as the actual data. The length (DLC) field in the data or remote
	 * frame will be set to the actual length of the ``data`` parameter. This allows
	 * to transmit data and remote frames with excess length. For remote frames only
	 * the length of the ``data`` parameter is used. The actual ``data`` bytes are
	 * ignored.
	 * 
	 * Returns *true* if the frame was successfully added to the write queue. Returns
	 * *false* if the frame could not be added because write queue is already full or
	 * because the write buffer or the write backlog are configured with a size of
	 * zero (see {@link BrickletCANV2#setQueueConfiguration(int, int, int, int[], int)}).
	 * 
	 * The write queue can overflow if frames are written to it at a higher rate
	 * than the Bricklet can transmitted them over the CAN transceiver. This may
	 * happen if the CAN transceiver is configured as read-only or is using a low baud
	 * rate (see {@link BrickletCANV2#setTransceiverConfiguration(long, int, int)}). It can also happen if the CAN
	 * bus is congested and the frame cannot be transmitted because it constantly loses
	 * arbitration or because the CAN transceiver is currently disabled due to a high
	 * write error level (see {@link BrickletCANV2#getErrorLog()}).
	 */
	public boolean writeFrame(int frameType, long identifier, int[] data) throws TinkerforgeException {
		if (data.length > 15) {
			throw new IllegalArgumentException("Data can be at most 15 items long");
		}

		int dataLength = data.length;
		int[] dataData = new int[15];
		boolean ret;

		System.arraycopy(data, 0, dataData, 0, dataLength);
		Arrays.fill(dataData, dataLength, 15, 0);

		ret = writeFrameLowLevel(frameType, identifier, dataLength, dataData);

		return ret;
	}

	/**
	 * Tries to read the next data or remote frame from the read queue and returns it.
	 * If a frame was successfully read, then the ``success`` return value is set to
	 * *true* and the other return values contain the frame. If the read queue is
	 * empty and no frame could be read, then the ``success`` return value is set to
	 * *false* and the other return values contain invalid data.
	 * 
	 * The ``identifier`` return value follows the identifier format described for
	 * {@link BrickletCANV2#writeFrame(int, long, int[])}.
	 * 
	 * The ``data`` return value can be up to 15 bytes long. For data frames up to the
	 * first 8 bytes are the actual received data. All bytes after the 8th byte are
	 * always zero and only there to indicate the length of a data or remote frame
	 * with excess length. For remote frames the length of the ``data`` return value
	 * represents the requested length. The actual ``data`` bytes are always zero.
	 * 
	 * A configurable read filter can be used to define which frames should be
	 * received by the CAN transceiver and put into the read queue (see
	 * {@link BrickletCANV2#setReadFilterConfiguration(int, int, long, long)}).
	 * 
	 * Instead of polling with this function, you can also use listeners. See the
	 * {@link BrickletCANV2#setFrameReadCallbackConfiguration(boolean)} function and the {@link BrickletCANV2.FrameReadListener}
	 * callback.
	 */
	public ReadFrame readFrame() throws TinkerforgeException {
		ReadFrameLowLevel ret = readFrameLowLevel();
		int[] data = new int[ret.dataLength];

		System.arraycopy(ret.dataData, 0, data, 0, ret.dataLength);

		return new ReadFrame(ret.success, ret.frameType, ret.identifier, data);
	}

	/**
	 * Sets the write and read queue configuration.
	 * 
	 * The CAN transceiver has 32 buffers in total in hardware for transmitting and
	 * receiving frames. Additionally, the Bricklet has a backlog for 768 frames in
	 * total in software. The buffers and the backlog can be freely assigned to the
	 * write and read queues.
	 * 
	 * {@link BrickletCANV2#writeFrame(int, long, int[])} writes a frame into the write backlog. The Bricklet moves
	 * the frame from the backlog into a free write buffer. The CAN transceiver then
	 * transmits the frame from the write buffer to the CAN bus. If there are no
	 * write buffers (``write_buffer_size`` is zero) or there is no write backlog
	 * (``write_backlog_size`` is zero) then no frames can be transmitted and
	 * {@link BrickletCANV2#writeFrame(int, long, int[])} returns always *false*.
	 * 
	 * The CAN transceiver receives a frame from the CAN bus and stores it into a
	 * free read buffer. The Bricklet moves the frame from the read buffer into the
	 * read backlog. {@link BrickletCANV2#readFrame()} reads the frame from the read backlog and
	 * returns it. If there are no read buffers (``read_buffer_sizes`` is empty) or
	 * there is no read backlog (``read_backlog_size`` is zero) then no frames can be
	 * received and {@link BrickletCANV2#readFrame()} returns always *false*.
	 * 
	 * There can be multiple read buffers, because the CAN transceiver cannot receive
	 * data and remote frames into the same read buffer. A positive read buffer size
	 * represents a data frame read buffer and a negative read buffer size represents
	 * a remote frame read buffer. A read buffer size of zero is not allowed. By
	 * default the first read buffer is configured for data frames and the second read
	 * buffer is configured for remote frame. There can be up to 32 different read
	 * buffers, assuming that no write buffer is used. Each read buffer has its own
	 * filter configuration (see {@link BrickletCANV2#setReadFilterConfiguration(int, int, long, long)}).
	 * 
	 * A valid queue configuration fulfills these conditions::
	 * 
	 *  write_buffer_size + abs(read_buffer_size_0) + abs(read_buffer_size_1) + ... + abs(read_buffer_size_31) <= 32
	 *  write_backlog_size + read_backlog_size <= 768
	 * 
	 * The write buffer timeout has three different modes that define how a failed
	 * frame transmission should be handled:
	 * 
	 * * Single-Shot (< 0): Only one transmission attempt will be made. If the
	 *   transmission fails then the frame is discarded.
	 * * Infinite (= 0): Infinite transmission attempts will be made. The frame will
	 *   never be discarded.
	 * * Milliseconds (> 0): A limited number of transmission attempts will be made.
	 *   If the frame could not be transmitted successfully after the configured
	 *   number of milliseconds then the frame is discarded.
	 * 
	 * The current content of the queues is lost when this function is called.
	 */
	public void setQueueConfiguration(int writeBufferSize, int writeBufferTimeout, int writeBacklogSize, int[] readBufferSizes, int readBacklogSize) throws TinkerforgeException {
		if (readBufferSizes.length > 32) {
			throw new IllegalArgumentException("Read Buffer Sizes can be at most 32 items long");
		}

		int readBufferSizesLength = readBufferSizes.length;
		int[] readBufferSizesData = new int[32];

		System.arraycopy(readBufferSizes, 0, readBufferSizesData, 0, readBufferSizesLength);
		Arrays.fill(readBufferSizesData, readBufferSizesLength, 32, 0);

		setQueueConfigurationLowLevel(writeBufferSize, writeBufferTimeout, writeBacklogSize, readBufferSizesLength, readBufferSizesData, readBacklogSize);
	}

	/**
	 * Returns the queue configuration as set by {@link BrickletCANV2#setQueueConfiguration(int, int, int, int[], int)}.
	 */
	public QueueConfiguration getQueueConfiguration() throws TinkerforgeException {
		QueueConfigurationLowLevel ret = getQueueConfigurationLowLevel();
		int[] readBufferSizes = new int[ret.readBufferSizesLength];

		System.arraycopy(ret.readBufferSizesData, 0, readBufferSizes, 0, ret.readBufferSizesLength);

		return new QueueConfiguration(ret.writeBufferSize, ret.writeBufferTimeout, ret.writeBacklogSize, readBufferSizes, ret.readBacklogSize);
	}

	/**
	 * Returns information about different kinds of errors.
	 * 
	 * The write and read error levels indicate the current level of stuffing, form,
	 * acknowledgement, bit and checksum errors during CAN bus write and read
	 * operations. For each of this error kinds there is also an individual counter.
	 * 
	 * When the write error level extends 255 then the CAN transceiver gets disabled
	 * and no frames can be transmitted or received anymore. The CAN transceiver will
	 * automatically be activated again after the CAN bus is idle for a while.
	 * 
	 * The write buffer timeout, read buffer and backlog overflow counts represents the
	 * number of these errors:
	 * 
	 * * A write buffer timeout occurs if a frame could not be transmitted before the
	 *   configured write buffer timeout expired (see {@link BrickletCANV2#setQueueConfiguration(int, int, int, int[], int)}).
	 * * A read buffer overflow occurs if a read buffer of the CAN transceiver
	 *   still contains the last received frame when the next frame arrives. In this
	 *   case the last received frame is lost. This happens if the CAN transceiver
	 *   receives more frames than the Bricklet can handle. Using the read filter
	 *   (see {@link BrickletCANV2#setReadFilterConfiguration(int, int, long, long)}) can help to reduce the amount of
	 *   received frames. This count is not exact, but a lower bound, because the
	 *   Bricklet might not able detect all overflows if they occur in rapid succession.
	 * * A read backlog overflow occurs if the read backlog of the Bricklet is already
	 *   full when the next frame should be read from a read buffer of the CAN
	 *   transceiver. In this case the frame in the read buffer is lost. This
	 *   happens if the CAN transceiver receives more frames to be added to the read
	 *   backlog than are removed from the read backlog using the {@link BrickletCANV2#readFrame()}
	 *   function. Using the {@link BrickletCANV2.FrameReadListener} listener ensures that the read backlog
	 *   can not overflow.
	 * 
	 * The read buffer overflow counter counts the overflows of all configured read
	 * buffers. Which read buffer exactly suffered from an overflow can be figured
	 * out from the read buffer overflow occurrence list
	 * (``read_buffer_overflow_error_occurred``).
	 */
	public ErrorLog getErrorLog() throws TinkerforgeException {
		ErrorLogLowLevel ret = getErrorLogLowLevel();
		boolean[] readBufferOverflowErrorOccurred = new boolean[ret.readBufferOverflowErrorOccurredLength];

		System.arraycopy(ret.readBufferOverflowErrorOccurredData, 0, readBufferOverflowErrorOccurred, 0, ret.readBufferOverflowErrorOccurredLength);

		return new ErrorLog(ret.transceiverState, ret.transceiverWriteErrorLevel, ret.transceiverReadErrorLevel, ret.transceiverStuffingErrorCount, ret.transceiverFormatErrorCount, ret.transceiverACKErrorCount, ret.transceiverBit1ErrorCount, ret.transceiverBit0ErrorCount, ret.transceiverCRCErrorCount, ret.writeBufferTimeoutErrorCount, ret.readBufferOverflowErrorCount, readBufferOverflowErrorOccurred, ret.readBacklogOverflowErrorCount);
	}

	/**
	 * Adds a FrameReadLowLevel listener.
	 */
	public void addFrameReadLowLevelListener(FrameReadLowLevelListener listener) {
		listenerFrameReadLowLevel.add(listener);
	}

	/**
	 * Removes a FrameReadLowLevel listener.
	 */
	public void removeFrameReadLowLevelListener(FrameReadLowLevelListener listener) {
		listenerFrameReadLowLevel.remove(listener);
	}

	/**
	 * Adds a FrameRead listener.
	 */
	public void addFrameReadListener(FrameReadListener listener) {
		listenerFrameRead.add(listener);
	}

	/**
	 * Removes a FrameRead listener.
	 */
	public void removeFrameReadListener(FrameReadListener listener) {
		listenerFrameRead.remove(listener);
	}
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy