/*
* 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;
import android.util.Log;
import org.catrobat.catroid.devices.mindstorms.MindstormsConnection;
import org.catrobat.catroid.devices.mindstorms.MindstormsException;
import org.catrobat.catroid.devices.mindstorms.MindstormsMotor;
public class NXTMotor implements MindstormsMotor {
private static final String TAG = NXTMotor.class.getSimpleName();
private int port;
private MindstormsConnection connection;
public NXTMotor(int port, MindstormsConnection connection) {
this.port = port;
this.connection = connection;
}
@Override
public void stop() {
OutputState state = new OutputState();
state.setSpeed(0);
state.mode = MotorMode.BREAK | MotorMode.ON | MotorMode.REGULATED;
state.regulation = MotorRegulation.SPEED;
state.turnRatio = 100;
state.runState = MotorRunState.RUNNING;
state.tachoLimit = 0;
setOutputState(state, false);
}
private void setOutputState(OutputState state, boolean reply) {
try {
trySetOutputState(state, reply);
} catch (MindstormsException e) {
Log.e(TAG, e.getMessage());
}
}
private void trySetOutputState(OutputState state, boolean reply) {
Command command = new Command(CommandType.DIRECT_COMMAND, CommandByte.SET_OUTPUT_STATE, false);
command.append((byte) port);
command.append(state.getSpeed());
command.append(state.mode);
command.append(state.regulation.getByte());
command.append(state.turnRatio);
command.append(state.runState.getByte());
command.append(state.tachoLimit);
command.append((byte) 0x00);
if (reply) {
connection.sendAndReceive(command);
} else {
connection.send(command);
}
}
@Override
public void move(int speed) {
move(speed, 0, false);
}
@Override
public void move(int speed, int degrees) {
move(speed, degrees, false);
}
@Override
public void move(int speed, int degrees, boolean reply) {
OutputState state = new OutputState();
state.setSpeed(speed);
state.mode = MotorMode.BREAK | MotorMode.ON | MotorMode.REGULATED;
state.regulation = MotorRegulation.SPEED;
state.turnRatio = 100;
state.runState = MotorRunState.RUNNING;
state.tachoLimit = degrees;
setOutputState(state, reply);
}
private static class OutputState {
private byte speed;
public byte mode;
public MotorRegulation regulation;
public byte turnRatio;
public MotorRunState runState;
public int tachoLimit; //Current limit on a movement in progress, if any
public void setSpeed(int speed) {
if (speed > 100) {
this.speed = (byte) 100;
} else if (speed < -100) {
this.speed = (byte) -100;
} else if (turnRatio > 100) {
turnRatio = (byte) 100;
} else if (turnRatio < -100) {
this.turnRatio = (byte) 100;
} else {
this.speed = (byte) speed;
}
}
public byte getSpeed() {
return this.speed;
}
}
public static class MotorMode {
public static final byte ON = 0x01;
public static final byte BREAK = 0x02;
public static final byte REGULATED = 0x04;
}
public enum MotorRegulation {
IDLE(0x00), SPEED(0x01), SYNC(0x02);
private int motorRegulationValue;
private MotorRegulation(int motorRegulationValue) {
this.motorRegulationValue = motorRegulationValue;
}
public byte getByte() {
return (byte) motorRegulationValue;
}
}
public enum MotorRunState {
IDLE(0x00), RAMP_UP(0x10), RUNNING(0x20), RAMP_DOWN(0x40);
private int motorRunStateValue;
private MotorRunState(int motorRunStateValue) {
this.motorRunStateValue = motorRunStateValue;
}
public byte getByte() {
return (byte) motorRunStateValue;
}
}
}