/** * Sound class. Usage: SoundSensor.playTone(500, 1000); * * @author <a href="mailto:[email protected]">Brian Bagnall</a> */ public class Sound { private static final NXTCommand nxtCommand = NXTCommandConnector.getSingletonOpen(); // Make sure no one tries to instantiate this. private Sound() {} public static int playTone(int frequency, int duration) { try { return nxtCommand.playTone(frequency, duration); } catch (IOException ioe) { System.out.println(ioe.getMessage()); return -1; } } /** * Plays a sound file from the NXT. SoundSensor files use the .rso extension. The filename is not * case sensitive. Filenames on the NXT Bricks display do now show the filename extension. * * @param fileName e.g. "Woops.rso" * @param repeat true = repeat, false = play once. * @return If you receive a non-zero number, the filename is probably wrong or the file is not * uploaded to the NXT brick. */ public static byte playSoundFile(String fileName, boolean repeat) { try { return nxtCommand.playSoundFile(fileName, repeat); } catch (IOException ioe) { System.out.println(ioe.getMessage()); return -1; } } /** * Plays a sound file once from the NXT. SoundSensor files use the .rso extension. The filename is * not case sensitive. Filenames on the NXT Bricks display do now show the filename extension. * * @param fileName e.g. "Woops.rso" * @return If you receive a non-zero number, the filename is probably wrong or the file is not * uploaded to the NXT brick. */ public static byte playSoundFile(String fileName) { return Sound.playSoundFile(fileName, false); } /** * Stops a sound file that has been playing/repeating. * * @return Error code. */ public static int stopSoundPlayback() { try { return nxtCommand.stopSoundPlayback(); } catch (IOException ioe) { System.out.println(ioe.getMessage()); return -1; } } }
/** * A sensor wrapper to allow easy access to I2C sensors, like the ultrasonic sensor. * * <p>This version of this class supports remote execution of I2C. * * @author Brian Bagnall and Lawrie Griffiths */ public class I2CSensor implements SensorConstants { private static final NXTCommand nxtCommand = NXTCommandConnector.getSingletonOpen(); protected byte address = 0x02; // the default I2C address for a port. You can change address of compass sensor (see // docs) and then communicate with multiple sensors on same physical port. protected static byte STOP = 0x00; // Commands don't seem to use this? protected static String BLANK = " "; // Port information (constants) /** Returns the version number of the sensor. e.g. "V1.0" Reply length = 8. */ protected static byte VERSION = 0x00; /** Returns the product ID of the sensor. e.g. "LEGO" Reply length = 8. */ protected static byte PRODUCT_ID = 0x08; /** Returns the sensor type. e.g. "Sonar" Reply length = 8. */ protected static byte SENSOR_TYPE = 0x10; /** Returns the "zero position" set at the factory for this sensor. e.g. 0 Reply length = 1. */ byte port; /** @param s A sensor. e.g. Port.S1 */ public I2CSensor(I2CPort s, byte sensorType) { port = (byte) s.getId(); s.setTypeAndMode(sensorType, NXTProtocol.RAWMODE); // Flushes out any existing data try { nxtCommand.LSGetStatus(this.port); nxtCommand.LSRead(this.port); } catch (IOException ioe) { System.out.println(ioe.getMessage()); } } public I2CSensor(I2CPort s) { this(s, NXTProtocol.LOWSPEED); } public int getId() { return port; } /** * Method for retrieving data values from the sensor. BYTE0 ( is usually the primary data value * for the sensor. Data is read from registers in the sensor, usually starting at 0x00 and ending * around 0x49. Just supply the register to start reading at, and the length of bytes to read (16 * maximum). NOTE: The NXT supplies UBYTE (unsigned byte) values but Java converts them into * signed bytes (probably more practical to return short/int?) * * @param register e.g. FACTORY_SCALE_DIVISOR, BYTE0, etc.... * @param length Length of data to read (minimum 1, maximum 16) * @return the status */ public int getData(int register, byte[] buf, int length) { byte[] txData = {address, (byte) register}; try { nxtCommand.LSWrite(port, txData, (byte) length); } catch (IOException ioe) { System.out.println(ioe.getMessage()); } byte[] status = null; do { try { status = nxtCommand.LSGetStatus(port); } catch (IOException ioe) { System.out.println(ioe.getMessage()); return -1; } } while (status[0] == ErrorMessages.PENDING_COMMUNICATION_TRANSACTION_IN_PROGRESS | status[0] == ErrorMessages.SPECIFIED_CHANNEL_CONNECTION_NOT_CONFIGURED_OR_BUSY); try { byte[] ret = nxtCommand.LSRead(port); if (ret != null) System.arraycopy(ret, 0, buf, 0, ret.length); } catch (IOException ioe) { System.out.println(ioe.getMessage()); return -1; } return status[0]; } /** * Helper method to return a single register byte. * * @param register * @return the byte of data */ public int getData(int register) { byte[] buf1 = new byte[1]; return getData(register, buf1, 1); } /** * Sets a single byte in the I2C sensor. * * @param register A data register in the I2C sensor. e.g. ACTUAL_ZERO * @param value The data value. */ public int sendData(int register, byte value) { byte[] txData = {address, (byte) register, value}; try { int ret = nxtCommand.LSWrite(this.port, txData, (byte) 0); return ret; } catch (IOException ioe) { System.out.println(ioe.getMessage()); return -1; } } /** * Send data top the sensor * * @param register A data register in the I2C sensor. * @param data The byte to send. * @param length the number of bytes */ public int sendData(int register, byte[] data, int length) { byte[] txData = {address, (byte) register}; byte[] sendData = new byte[length + 2]; System.arraycopy(txData, 0, sendData, 0, 2); System.arraycopy(data, 0, sendData, 2, length); try { return nxtCommand.LSWrite(this.port, sendData, (byte) 0); } catch (IOException ioe) { System.out.println(ioe.getMessage()); return -1; } } /** * Returns the version number of the sensor hardware. NOTE: A little unreliable at the moment due * to a bug in firmware. Keep trying if it doesn't get it the first time. * * @return The version number. e.g. "V1.0" */ public String getVersion() { return fetchString(VERSION, 8); } /** * Returns the Product ID as a string. NOTE: A little unreliable at the moment due to a bug in * firmware. Keep trying if it doesn't get it the first time. * * @return The product ID. e.g. "LEGO" */ public String getProductID() { return fetchString(PRODUCT_ID, 8); } /** * Returns the type of sensor as a string. NOTE: A little unreliable at the moment due to a bug in * firmware. Keep trying if it doesn't get it the first time. * * @return The sensor type. e.g. "Sonar" */ public String getSensorType() { return fetchString(SENSOR_TYPE, 8); } /** * Helper method for retrieving string constants using I2C protocol. * * @param constantEnumeration e.g. I2CProtocol.VERSION * @param rxLength * @return the string */ protected String fetchString(int constantEnumeration, int rxLength) { byte[] stringBytes = new byte[rxLength]; getData(constantEnumeration, stringBytes, rxLength); // Get rid of everything after 0. int zeroPos = 0; for (zeroPos = 0; zeroPos < rxLength; zeroPos++) { if (stringBytes[zeroPos] == 0) break; } String s = new String(stringBytes).substring(0, zeroPos); return s; } /** * Set the address of the port Note that addresses are from 0x01 to 0x7F not even numbers from * 0x02 to 0xFE as given in some I2C device specifications. They are 7-bit addresses not 8-bit * addresses. * * @param addr 1 to 0x7F */ public void setAddress(int addr) { address = (byte) (addr << 1); } }