package lejos.nxt; /** * Abstract class that implements common methods for all I2C sensors. * * Extend this class to implement new I2C sensors. * * @author Lawrie Griffiths (lawrie.griffiths@ntlworld.com). * */ public class I2CSensor implements SensorConstants { /** * 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; I2CPort port; int address = 1; String version = null; String productID = null; String sensorType = null; byte [] byteBuff = new byte[8]; byte [] buf1 = new byte[1]; public I2CSensor(I2CPort port, int mode) { this.port = port; port.i2cEnable(mode); port.setType(TYPE_LOWSPEED); } public I2CSensor(I2CPort port) { this(port, I2CPort.LEGO_MODE); } /** * Executes an I2C read transaction and waits for the result. * * @param register I2C register, e.g 0x41 * @param buf Buffer to return data * @param len Length of the return data * @return status == 0 success, != 0 failure */ public int getData(int register, byte [] buf, int len) { int ret = port.i2cStart(address, register, 1, null, len, 0); if (ret != 0) return ret; while (port.i2cBusy() != 0) { Thread.yield(); } ret = port.i2cComplete(buf, len); return (ret < 0 ? ret : (ret == len ? 0 : -1)); } /** * Executes an I2C write transaction. * * @param register I2C register, e.g 0x42 * @param buf Buffer containing data to send * @param len Length of data to send * @return status zero=success, non-zero=failure */ public int sendData(int register, byte [] buf, int len) { int ret = port.i2cStart(address, register, 1, buf, len, 1); if (ret != 0) return ret; while (port.i2cBusy() != 0) { Thread.yield(); } return port.i2cComplete(null, 0); } /** * Executes an I2C write transaction. * * @param register I2C register, e.g 0x42 * @param value single byte to send * @return status zero=success, non-zero=failure */ public int sendData(int register, byte value) { buf1[0] = value; return sendData(register, buf1, 1); } /** * Return the sensor version number. * * @return 8-byte string */ public String getVersion() { return fetchString(VERSION, 8); } /** * Return the sensor product identifier. * * @return 8-byte string */ public String getProductID() { return fetchString(PRODUCT_ID, 8); } /** * Return the sensor type. * * @return 8-byte string */ public String getSensorType() { return fetchString(SENSOR_TYPE, 8); } /** * Internal helper function, read a string from the device * @param register * @param len The length of the space padded reply. * @return the requested string */ protected String fetchString(int register, int len) { int ret = getData(register, byteBuff, 8); char [] charBuff = new char[len]; for(int i=0;i<len;i++) charBuff[i] = (byteBuff[i] == 0 ? ' ' : (char)byteBuff[i]); return new String(charBuff, 0, len); } /** * 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 = addr; } /** * Get the port that the sensor is attached to * @return the I2CPort */ public I2CPort getPort() { return port; } }