/* * Catroid: An on-device visual programming system for Android devices * Copyright (C) 2010-2016 The Catrobat Team * (<http://developer.catrobat.org/credits>) * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Affero General Public License as * published by the Free Software Foundation, either version 3 of the * License, or (at your option) any later version. * * An additional term exception under section 7 of the GNU Affero * General Public License, version 3, is available at * http://developer.catrobat.org/license_additional_term * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Affero General Public License for more details. * * You should have received a copy of the GNU Affero General Public License * along with this program. If not, see <http://www.gnu.org/licenses/>. */ package org.catrobat.catroid.devices.mindstorms.nxt.sensors; import android.util.Log; import org.catrobat.catroid.devices.mindstorms.MindstormsConnection; import org.catrobat.catroid.devices.mindstorms.nxt.Command; import org.catrobat.catroid.devices.mindstorms.nxt.CommandByte; import org.catrobat.catroid.devices.mindstorms.nxt.CommandType; import org.catrobat.catroid.devices.mindstorms.nxt.NXTError; import org.catrobat.catroid.devices.mindstorms.nxt.NXTException; import org.catrobat.catroid.devices.mindstorms.nxt.NXTReply; import org.catrobat.catroid.utils.Stopwatch; public abstract class NXTI2CSensor extends NXTSensor { private byte address; private int pendingCommunicationErrorWaitTime; private final int requestTimeout = 500; //in MS private static final byte BYTES_READ_BYTE = 3; private static final String TAG = NXTI2CSensor.class.getSimpleName(); public NXTI2CSensor(byte sensorAddress, NXTSensorType sensorType, MindstormsConnection connection) { super(3, sensorType, NXTSensorMode.RAW, connection); address = sensorAddress; pendingCommunicationErrorWaitTime = 30; } public byte getI2CAddress() { return address; } @Override protected void initialize() { super.initialize(); readRegister(0x00, 0x01); } protected void writeRegister(byte register, byte data, boolean reply) { if (!hasInit) { initialize(); } byte[] command = { address, register, data }; write(command, (byte) 0, reply); } protected byte[] readRegister(int register, int rxLength) { if (!hasInit) { initialize(); } byte[] command = { address, (byte) register }; return writeAndRead(command, (byte) rxLength); } private void waitForBytes(byte numberOfBytes) { Stopwatch stopWatch = new Stopwatch(); byte bytesRead = 0; stopWatch.start(); do { bytesRead = tryGetNumberOfBytesAreReadyToRead(); } while (bytesRead != numberOfBytes && stopWatch.getElapsedMilliseconds() < requestTimeout); if (stopWatch.getElapsedMilliseconds() > requestTimeout) { throw new NXTException("RequestTimeout while waiting on bytes Ready, waited " + stopWatch.getElapsedMilliseconds() + "ms"); } } private byte tryGetNumberOfBytesAreReadyToRead() { try { return getNumberOfBytesAreReadyToRead(); } catch (NXTException e) { if (e.getError() == NXTError.ErrorCode.PendingCommunication) { Log.e(TAG, "Pending Coummunication Error occured, wait for " + pendingCommunicationErrorWaitTime + "ms and try again."); wait(pendingCommunicationErrorWaitTime); return 0; } throw e; } } protected byte[] writeAndRead(byte[] data, byte rxLength) { write(data, rxLength, false); waitForBytes(rxLength); return read(); } protected void write(byte[] txData, byte rxLength, boolean reply) { Command command = new Command(CommandType.DIRECT_COMMAND, CommandByte.LS_WRITE, reply); command.append((byte) port); command.append((byte) txData.length); command.append(rxLength); command.append(txData); if (reply) { NXTReply brickReply = new NXTReply(connection.sendAndReceive(command)); NXTError.checkForError(brickReply, 5); } else { connection.send(command); } } private byte[] read() { Command command = new Command(CommandType.DIRECT_COMMAND, CommandByte.LS_READ, true); command.append((byte) port); NXTReply reply = new NXTReply(connection.sendAndReceive(command)); NXTError.checkForError(reply, 20); byte size = reply.getByte(BYTES_READ_BYTE); return reply.getData(4, size); } private byte getNumberOfBytesAreReadyToRead() { Command command = new Command(CommandType.DIRECT_COMMAND, CommandByte.LS_GET_STATUS, true); command.append((byte) port); NXTReply reply = new NXTReply(connection.sendAndReceive(command)); NXTError.checkForError(reply, 4); return reply.getByte(BYTES_READ_BYTE); } protected void wait(int millis) { try { Thread.sleep(millis); } catch (InterruptedException interruptedException) { Log.w(TAG, "Shouldn't be interrupted", interruptedException); } } }