diff --git a/README.md b/README.md index ecb6dc9e..43ca3362 100644 --- a/README.md +++ b/README.md @@ -1,3 +1,6 @@ +--- +author: "Matthew Lewis" +--- # diozero - a Java Device I/O wrapper for GPIO / I2C / SPI control [![Maven CI Build](https://github.com/mattjlewis/diozero/actions/workflows/build.yml/badge.svg)](https://github.com/mattjlewis/diozero/actions/workflows/build.yml) diff --git a/diozero-bom/pom.xml b/diozero-bom/pom.xml index 20cc62de..a71f66ce 100644 --- a/diozero-bom/pom.xml +++ b/diozero-bom/pom.xml @@ -62,15 +62,15 @@ 11 - 3.12.1 - 3.7.0 + 3.13.0 + 3.7.1 3.6.3 3.3.0 3.5.2 3.3.0 3.1.1 3.1.1 - 3.2.0 + 3.2.2 3.0.1 3.2.5 @@ -87,7 +87,7 @@ 1.2.5 2.10.1 3.25.2 - 4.1.107.Final + 4.1.108.Final 1.62.2 5.10.2 5.11.0 diff --git a/diozero-core/src/main/java/com/diozero/api/I2CDevice.java b/diozero-core/src/main/java/com/diozero/api/I2CDevice.java index 106dd6e3..eda328cc 100644 --- a/diozero-core/src/main/java/com/diozero/api/I2CDevice.java +++ b/diozero-core/src/main/java/com/diozero/api/I2CDevice.java @@ -31,7 +31,6 @@ * #L% */ -import java.nio.ByteBuffer; import java.nio.ByteOrder; import org.tinylog.Logger; @@ -39,15 +38,15 @@ import com.diozero.internal.spi.I2CDeviceFactoryInterface; import com.diozero.internal.spi.InternalI2CDeviceInterface; import com.diozero.sbc.DeviceFactoryHelper; -import com.diozero.util.BitManipulation; /** * Utility class for interfacing with to I2C devices. * - * @see I2C Bus - * Specification + * @see I2C Bus Specification */ public class I2CDevice implements I2CDeviceInterface { + public static final int DEFAULT_CONTROLLER = I2CConstants.CONTROLLER_1; + public enum ProbeMode { QUICK, READ, AUTO; } @@ -65,7 +64,7 @@ public static class Builder { public static final ByteOrder DEFAULT_BYTE_ORDER = ByteOrder.BIG_ENDIAN; private I2CDeviceFactoryInterface factory; - private int controller = I2CConstants.CONTROLLER_1; + private int controller = DEFAULT_CONTROLLER; private int address; private I2CConstants.AddressSize addressSize = I2CConstants.AddressSize.SIZE_7; private ByteOrder byteOrder = DEFAULT_BYTE_ORDER; @@ -77,8 +76,7 @@ protected Builder(int address) { /** * Set the I2C device factory to use for provisioning I2C device instances * - * @param factory the I2C device factory to use for provisioning I2C device - * instances + * @param factory the I2C device factory to use for provisioning I2C device instances * @return this builder instance */ public Builder setDeviceFactory(I2CDeviceFactoryInterface factory) { @@ -112,8 +110,7 @@ public Builder setAddress(int address) { /** * Set the I2C device {@link I2CConstants.AddressSize address size} * - * @param addressSize the I2C device {@link I2CConstants.AddressSize address - * size} + * @param addressSize the I2C device {@link I2CConstants.AddressSize address size} * @return this builder instance */ public Builder setAddressSize(I2CConstants.AddressSize addressSize) { @@ -124,8 +121,8 @@ public Builder setAddressSize(I2CConstants.AddressSize addressSize) { /** * Set the Default {@link ByteOrder byte order} for this device * - * @param byteOrder the {@link ByteOrder byte order} that is only used in the - * additional non-SMBus I2C device utility methods + * @param byteOrder the {@link ByteOrder byte order} that is only used in the additional + * non-SMBus I2C device utility methods * @return this builder instance */ public Builder setByteOrder(ByteOrder byteOrder) { @@ -161,11 +158,10 @@ public static Builder builder(int address) { private ByteOrder byteOrder; /** - * Use the default {@link I2CConstants.AddressSize#SIZE_7 7-bit} address size - * and {@link Builder#DEFAULT_BYTE_ORDER default} {@link ByteOrder byte order} + * Use the default {@link I2CConstants.AddressSize#SIZE_7 7-bit} address size and + * {@link Builder#DEFAULT_BYTE_ORDER default} {@link ByteOrder byte order} * - * @see I2C Bus - * Specification + * @see I2C Bus Specification * * @param controller I2C bus controller number * @param address I2C device address @@ -179,13 +175,12 @@ public I2CDevice(int controller, int address) throws RuntimeIOException { /** * Use the default {@link I2CConstants.AddressSize#SIZE_7 7-bit} address size * - * @see I2C Bus - * Specification + * @see I2C Bus Specification * * @param controller I2C bus controller number * @param address I2C device address - * @param byteOrder The {@link ByteOrder byte order} that is only used in the - * additional non-SMBus I2C device utility methods + * @param byteOrder The {@link ByteOrder byte order} that is only used in the additional + * non-SMBus I2C device utility methods * @throws RuntimeIOException If an I/O error occurred */ public I2CDevice(int controller, int address, ByteOrder byteOrder) throws RuntimeIOException { @@ -194,11 +189,9 @@ public I2CDevice(int controller, int address, ByteOrder byteOrder) throws Runtim } /** - * Use the {@link Builder#DEFAULT_BYTE_ORDER default} {@link ByteOrder byte - * order} + * Use the {@link Builder#DEFAULT_BYTE_ORDER default} {@link ByteOrder byte order} * - * @see I2C Bus - * Specification + * @see I2C Bus Specification * * @param controller I2C bus controller number * @param address I2C device address @@ -213,14 +206,13 @@ public I2CDevice(int controller, int address, I2CConstants.AddressSize addressSi /** * Use the default native device factory * - * @see I2C Bus - * Specification + * @see I2C Bus Specification * * @param controller I2C bus controller number * @param address I2C device address * @param addressSize I2C device address size. Can be 7 or 10 - * @param byteOrder the {@link ByteOrder byte order} that is only used in the - * additional non-SMBus I2C device utility methods + * @param byteOrder the {@link ByteOrder byte order} that is only used in the additional + * non-SMBus I2C device utility methods * @throws RuntimeIOException If an I/O error occurred. */ public I2CDevice(int controller, int address, I2CConstants.AddressSize addressSize, ByteOrder byteOrder) @@ -229,19 +221,18 @@ public I2CDevice(int controller, int address, I2CConstants.AddressSize addressSi } /** - * Construct an I2C device using the specified I2C bus / controller, device - * address, address size and byte order. Note that the {@link ByteOrder byte - * order} is only used in the utility methods. + * Construct an I2C device using the specified I2C bus / controller, device address, + * address size and byte order. Note that the {@link ByteOrder byte order} is only used in + * the utility methods. * - * @see I2C Bus - * Specification + * @see I2C Bus Specification * * @param deviceFactory Device factory to use to provision this device * @param controller I2C bus controller number * @param address I2C device address * @param addressSize I2C device address size. Can be 7 or 10 - * @param byteOrder the {@link ByteOrder byte order} that is only used in - * the additional non-SMBus I2C device utility methods + * @param byteOrder the {@link ByteOrder byte order} that is only used in the + * additional non-SMBus I2C device utility methods * @throws RuntimeIOException If an I/O error occurred */ public I2CDevice(I2CDeviceFactoryInterface deviceFactory, int controller, int address, @@ -258,6 +249,7 @@ public int getController() { return controller; } + @Override public int getAddress() { return address; } @@ -266,6 +258,7 @@ public I2CConstants.AddressSize getAddressSize() { return addressSize; } + @Override public ByteOrder getByteOrder() { return byteOrder; } @@ -358,10 +351,9 @@ public short readWordData(int register) throws RuntimeIOException { /** * {@inheritDoc} * - * Note that the {@link ByteOrder byte order} for the input - * value is {@link ByteOrder#LITTLE_ENDIAN Little Endian} as per the SMBus - * specification, regardless of the {@link ByteOrder byte order} specified in - * the constructor + * Note that the {@link ByteOrder byte order} for the input value is + * {@link ByteOrder#LITTLE_ENDIAN Little Endian} as per the SMBus specification, + * regardless of the {@link ByteOrder byte order} specified in the constructor */ @Override public void writeWordData(int register, short value) throws RuntimeIOException { @@ -374,8 +366,8 @@ public void writeWordData(int register, short value) throws RuntimeIOException { * {@inheritDoc} * * Note that the byte order for the returned word data is - * {@link ByteOrder#BIG_ENDIAN Big Endian}, regardless of the {@link ByteOrder - * byte order} specified in the constructor + * {@link ByteOrder#BIG_ENDIAN Big Endian}, regardless of the {@link ByteOrder byte order} + * specified in the constructor */ @Override public short readWordSwapped(int register) throws RuntimeIOException { @@ -387,9 +379,9 @@ public short readWordSwapped(int register) throws RuntimeIOException { /** * {@inheritDoc} * - * Note that the {@link ByteOrder byte order} for the input - * value is {@link ByteOrder#BIG_ENDIAN Big Endian}, regardless of the - * {@link ByteOrder byte order} specified in the constructor + * Note that the {@link ByteOrder byte order} for the input value is + * {@link ByteOrder#BIG_ENDIAN Big Endian}, regardless of the {@link ByteOrder byte order} + * specified in the constructor */ @Override public void writeWordSwapped(int register, short value) throws RuntimeIOException { @@ -492,269 +484,4 @@ public void readWrite(I2CMessage[] messages, byte[] buffer) { delegate.readWrite(messages, buffer); } } - - // - // I2CDevice utility methods - // - - /** - * Utility method that simply casts the int data parameter to byte and calls - * {@link I2CDevice#writeByteData(int, byte)} - * - * @see I2CDevice#writeByteData(int, byte) - * - * @param register the register to write to - * @param data value to write - * @throws RuntimeIOException if an I/O error occurs - */ - public void writeByteData(int register, int data) throws RuntimeIOException { - writeByteData(register, (byte) data); - } - - /** - * Utility method that simply converts the response from - * {@link I2CDevice#readByteData(int)} to an unsigned byte. A short is returned - * to ensure that the returned value is unsigned - * - * @see I2CDevice#readByteData(int) - * - * @param register the register to read from - * @return byte data returned converted to unsigned byte (represented as a - * short) - * @throws RuntimeIOException if an I/O error occurs - */ - public short readUByte(int register) throws RuntimeIOException { - return (short) (readByteData(register) & 0xff); - } - - /** - * Utility method that wraps the response from {@link I2CDevice#readBytes(int)} - * in a {@link ByteBuffer} that is configured to use the {@link ByteOrder byte - * order} specified in the constructor. - * - * @see I2CDevice#readBytes(int) - * @see ByteBuffer#wrap(byte[]) - * - * @param length number of bytes to read - * @return A {@link ByteBuffer} containing the bytes read using the byte order - * specified in the constructor - * @throws RuntimeIOException if an I/O error occurs - */ - public ByteBuffer readBytesAsByteBuffer(int length) throws RuntimeIOException { - ByteBuffer buffer = ByteBuffer.wrap(readBytes(length)); - buffer.order(byteOrder); - return buffer; - } - - /** - * Utility method that wraps {@link I2CDevice#writeBytes(byte[])} to write the - * available bytes in the specified {@link ByteBuffer ByteBuffer}. The byte - * order of data in the ByteBuffer is unchanged. - * - * @see I2CDevice#writeBytes(byte[]) - * @see ByteBuffer#put(byte[]) - * - * @param buffer the {@link ByteBuffer} containing the data to write - * @throws RuntimeIOException if an I/O error occurs - */ - public void writeBytes(ByteBuffer buffer) throws RuntimeIOException { - byte[] tx_buf = new byte[buffer.remaining()]; - buffer.get(tx_buf); - writeBytes(tx_buf); - } - - /** - * Utility method that wraps {@link I2CDevice#readI2CBlockData(int, byte[])} to - * read the specified number of bytes and return as a new byte array. - * - * @see I2CDevice#readI2CBlockData(int, byte[]) - * - * @param register the register to read from - * @param length the number of bytes to read - * @return the data read - * @throws RuntimeIOException if an I/O error occurs - */ - public byte[] readI2CBlockDataByteArray(int register, int length) throws RuntimeIOException { - byte[] data = new byte[length]; - int read = readI2CBlockData(register, data); - if (read == length) { - return data; - } - - // Shrink the byte array to the size of data actually read - byte[] rx_data = new byte[read]; - System.arraycopy(data, 0, rx_data, 0, read); - return rx_data; - } - - /** - * Utility method that wraps {@link I2CDevice#readI2CBlockData(int, byte[])} to - * read the specified number of bytes and return as a {@link ByteBuffer} using - * the {@link ByteOrder byte order} specified in the device constructor. - * - * @see I2CDevice#readI2CBlockData(int, byte[]) - * @see ByteBuffer#wrap(byte[]) - * - * @param register the register to read from - * @param length the number of bytes to read - * @return the data read - * @throws RuntimeIOException if an I/O error occurs - */ - public ByteBuffer readI2CBlockDataByteBuffer(int register, int length) throws RuntimeIOException { - byte[] data = new byte[length]; - - readI2CBlockData(register, data); - ByteBuffer buffer = ByteBuffer.wrap(data); - buffer.order(byteOrder); - - return buffer; - } - - /** - * Utility method that invokes either {@link I2CDevice#readWordData(int)} or - * {@link I2CDevice#readWordSwapped(int)} to read a signed short value from the - * requested register in the {@link ByteOrder byte order} specified in the - * constructor. - * - * @see I2CDevice#readWordData(int) - * @see I2CDevice#readWordSwapped(int) - * - * @param register register to read from - * @return the signed short value read - * @throws RuntimeIOException if an I/O error occurs - */ - public short readShort(int register) throws RuntimeIOException { - if (byteOrder == ByteOrder.LITTLE_ENDIAN) { - return readWordData(register); - } - return readWordSwapped(register); - } - - /** - * Utility method that wraps {@link I2CDevice#readShort(int)} to read an - * unsigned short value from the requested register using the {@link ByteOrder - * byte order} specified in the constructor. - * - * @see I2CDevice#readShort(int) - * - * @param register register to read from - * @return the unsigned short value read - * @throws RuntimeIOException if an I/O error occurs - */ - public int readUShort(int register) throws RuntimeIOException { - return readShort(register) & 0xffff; - } - - /** - * Utility method that wraps - * {@link I2CDevice#readI2CBlockDataByteBuffer(int, int)} to read a signed int - * value from the requested register using the {@link ByteOrder byte order} - * specified in the constructor. - * - * @see I2CDevice#readI2CBlockDataByteBuffer(int, int) - * - * @param register register to read from - * @return the signed int value read - * @throws RuntimeIOException if an I/O error occurs - */ - public int readInt(int register) throws RuntimeIOException { - return readI2CBlockDataByteBuffer(register, 4).getInt(); - } - - /** - * Utility method that wraps {@link I2CDevice#readInt(int)} to read an unsigned - * int value from the requested register using the {@link ByteOrder byte order} - * specified in the constructor. - * - * @see I2CDevice#readInt(int) - * - * @param register register to read from - * @return the unsigned int value read - * @throws RuntimeIOException if an I/O error occurs - */ - public long readUInt(int register) throws RuntimeIOException { - return readInt(register) & 0xffffffffL; - } - - /** - * Utility method that wraps - * {@link I2CDevice#readI2CBlockDataByteArray(int, int)} to read an unsigned int - * value on the specified length from the requested register using the - * {@link ByteOrder byte order} specified in the constructor. - * - * @see I2CDevice#readI2CBlockDataByteArray(int, int) - * - * @param register register to read from - * @param numBytes number of bytes to read (1..4) - * @return the unsigned int value read - * @throws RuntimeIOException if an I/O error occurs - */ - public long readUInt(int register, int numBytes) throws RuntimeIOException { - if (numBytes < 1 || numBytes > 4) { - throw new IllegalArgumentException("Maximum int length is 4 bytes - you requested " + numBytes); - } - - if (numBytes == 4) { - return readUInt(address); - } - - byte[] data = readI2CBlockDataByteArray(register, numBytes); - - long val = 0; - for (int i = 0; i < numBytes; i++) { - val |= (data[byteOrder == ByteOrder.LITTLE_ENDIAN ? numBytes - i - 1 : i] & 0xff) << (8 - * (numBytes - i - 1)); - } - - return val; - } - - /** - * Utility method that wraps {@link I2CDevice#readBytes(byte[])} to read the - * specified number of bytes. - * - * @see I2CDevice#readBytes(byte[]) - * - * @param length the number of bytes to read - * @return the bytes read from the device - * @throws RuntimeIOException if an I/O error occurs - */ - public byte[] readBytes(int length) throws RuntimeIOException { - byte[] buffer = new byte[length]; - readBytes(buffer); - return buffer; - } - - /** - * Utility method that wraps {@link I2CDevice#readByteData(int)} to check if the - * specified bit number is set. - * - * @see BitManipulation#isBitSet(byte, int) - * @see I2CDevice#readByteData(int) - * - * @param register the register to read - * @param bit the bit number to check - * @return true if the specified bit number is set - * @throws RuntimeIOException if an I/O error occurs - */ - public boolean readBit(int register, int bit) throws RuntimeIOException { - return BitManipulation.isBitSet(readByteData(register), bit); - } - - /** - * Utility method that wraps {@link I2CDevice#readByteData(int)} and - * {@link I2CDevice#writeByteData(int, byte)} to update the specified bit number - * - * @see I2CDevice#readByteData(int) - * @see BitManipulation#setBitValue(byte, int, boolean) - * - * @param register the register to update - * @param bit the bit number to set - * @param value the value to set the bit to - * @throws RuntimeIOException if an I/O error occurs - */ - public void writeBit(int register, int bit, boolean value) throws RuntimeIOException { - byte cur_val = readByteData(register); - writeByteData(register, BitManipulation.setBitValue(cur_val, bit, value)); - } } diff --git a/diozero-core/src/main/java/com/diozero/api/I2CDeviceInterface.java b/diozero-core/src/main/java/com/diozero/api/I2CDeviceInterface.java index 613bcb39..9c58bbd8 100644 --- a/diozero-core/src/main/java/com/diozero/api/I2CDeviceInterface.java +++ b/diozero-core/src/main/java/com/diozero/api/I2CDeviceInterface.java @@ -33,6 +33,8 @@ import java.io.ByteArrayOutputStream; import java.io.IOException; +import java.nio.ByteBuffer; +import java.nio.ByteOrder; import java.util.ArrayList; import java.util.List; import java.util.Optional; @@ -62,6 +64,41 @@ public interface I2CDeviceInterface extends I2CSMBusInterface { */ int readBytes(byte[] buffer) throws RuntimeIOException; + /** + * Utility method that wraps the response from {@link I2CDevice#readBytes(int)} + * in a {@link ByteBuffer} that is configured to use the {@link ByteOrder byte + * order} specified in the constructor. + * + * @see I2CDevice#readBytes(int) + * @see ByteBuffer#wrap(byte[]) + * + * @param length number of bytes to read + * @return A {@link ByteBuffer} containing the bytes read using the byte order + * specified in the constructor + * @throws RuntimeIOException if an I/O error occurs + */ + default ByteBuffer readBytesAsByteBuffer(int length) throws RuntimeIOException { + ByteBuffer buffer = ByteBuffer.wrap(readBytes(length)); + buffer.order(getByteOrder()); + return buffer; + } + + /** + * Utility method that wraps {@link I2CDeviceInterface#readBytes(byte[])} to + * read the specified number of bytes. + * + * @see I2CDevice#readBytes(byte[]) + * + * @param length the number of bytes to read + * @return the bytes read from the device + * @throws RuntimeIOException if an I/O error occurs + */ + default byte[] readBytes(int length) throws RuntimeIOException { + byte[] buffer = new byte[length]; + readBytes(buffer); + return buffer; + } + /** * Write the specified byte array to the device without the 32 byte limit * imposed by SMBus. @@ -77,6 +114,23 @@ public interface I2CDeviceInterface extends I2CSMBusInterface { */ void writeBytes(byte... data) throws RuntimeIOException; + /** + * Utility method that wraps {@link I2CDevice#writeBytes(byte[])} to write the + * available bytes in the specified {@link ByteBuffer ByteBuffer}. The byte + * order of data in the ByteBuffer is unchanged. + * + * @see I2CDevice#writeBytes(byte[]) + * @see ByteBuffer#put(byte[]) + * + * @param buffer the {@link ByteBuffer} containing the data to write + * @throws RuntimeIOException if an I/O error occurs + */ + default void writeBytes(ByteBuffer buffer) throws RuntimeIOException { + byte[] tx_buf = new byte[buffer.remaining()]; + buffer.get(tx_buf); + writeBytes(tx_buf); + } + /** * Utility method to simplify the {@link #readWrite(I2CMessage[], byte[])} * method at the cost of a bit of performance. diff --git a/diozero-core/src/main/java/com/diozero/api/I2CSMBusInterface.java b/diozero-core/src/main/java/com/diozero/api/I2CSMBusInterface.java index c9fe06e8..998e25b6 100644 --- a/diozero-core/src/main/java/com/diozero/api/I2CSMBusInterface.java +++ b/diozero-core/src/main/java/com/diozero/api/I2CSMBusInterface.java @@ -31,23 +31,24 @@ * #L% */ +import java.nio.ByteBuffer; +import java.nio.ByteOrder; + +import com.diozero.util.BitManipulation; + /** * I2C device interface - * Linux - * SMBus interface + * Linux SMBus + * interface */ public interface I2CSMBusInterface extends DeviceInterface { int MAX_I2C_BLOCK_SIZE = 32; - /** - * Probe this I2C device using {@link I2CDevice.ProbeMode#AUTO Auto} probe mode - * - * @return True if the probe is successful - * @throws RuntimeIOException if an I/O error occurs - */ - default boolean probe() throws RuntimeIOException { - return probe(I2CDevice.ProbeMode.AUTO); - } + int getController(); + + int getAddress(); + + ByteOrder getByteOrder(); /** * Probe this I2C device to see if it is connected @@ -80,18 +81,16 @@ default boolean probe() throws RuntimeIOException { * SMBus Receive Byte: i2c_smbus_read_byte() *

*

- * This reads a single byte from a device, without specifying a device register. - * Some devices are so simple that this interface is enough; for others, it is a - * shorthand if you want to read the same register as in the previous SMBus - * command. + * This reads a single byte from a device, without specifying a device register. Some + * devices are so simple that this interface is enough; for others, it is a shorthand if + * you want to read the same register as in the previous SMBus command. *

* *
 	 * S Addr Rd [A] [Data] NA P
 	 * 
* - * @return The byte data read (note caller needs to handle conversion to - * unsigned) + * @return The byte data read (note caller needs to handle conversion to unsigned) * @throws RuntimeIOException if an I/O error occurs */ byte readByte() throws RuntimeIOException; @@ -101,8 +100,8 @@ default boolean probe() throws RuntimeIOException { * SMBus Send Byte: i2c_smbus_write_byte() *

*

- * This operation is the reverse of Receive Byte: it sends a single byte to a - * device. See Receive Byte for more information. + * This operation is the reverse of Receive Byte: it sends a single byte to a device. See + * Receive Byte for more information. *

* *
@@ -119,8 +118,8 @@ default boolean probe() throws RuntimeIOException {
 	 * SMBus Read Byte: i2c_smbus_read_byte_data()
 	 * 

*

- * This reads a single byte from a device, from a designated register. The - * register is specified through the Comm byte. + * This reads a single byte from a device, from a designated register. The register is + * specified through the Comm byte. *

* *
@@ -128,8 +127,7 @@ default boolean probe() throws RuntimeIOException {
 	 * 
* * @param register the register to read from - * @return data read as byte (note caller needs to handle conversion to - * unsigned) + * @return data read as byte (note caller needs to handle conversion to unsigned) * @throws RuntimeIOException if an I/O error occurs */ byte readByteData(int register) throws RuntimeIOException; @@ -139,9 +137,8 @@ default boolean probe() throws RuntimeIOException { * SMBus Write Byte: i2c_smbus_write_byte_data() *

*

- * This writes a single byte to a device, to a designated register. The register - * is specified through the Comm byte. This is the opposite of the Read Byte - * operation. + * This writes a single byte to a device, to a designated register. The register is + * specified through the Comm byte. This is the opposite of the Read Byte operation. *

* *
@@ -159,11 +156,10 @@ default boolean probe() throws RuntimeIOException {
 	 * SMBus Read Word: i2c_smbus_read_word_data()
 	 * 

*

- * This operation is very like Read Byte; again, data is read from a device, - * from a designated register that is specified through the Comm byte. But this - * time, the data is a complete word (16 bits) in - * {@link java.nio.ByteOrder#LITTLE_ENDIAN Little Endian} order as per the SMBus - * specification. + * This operation is very like Read Byte; again, data is read from a device, from a + * designated register that is specified through the Comm byte. But this time, the data is + * a complete word (16 bits) in {@link java.nio.ByteOrder#LITTLE_ENDIAN Little Endian} + * order as per the SMBus specification. *

* *
@@ -171,8 +167,8 @@ default boolean probe() throws RuntimeIOException {
 	 * 
* * @param register the register to read from - * @return data read as a signed short in - * {@link java.nio.ByteOrder#LITTLE_ENDIAN Little Endian} byte order + * @return data read as a signed short in {@link java.nio.ByteOrder#LITTLE_ENDIAN Little + * Endian} byte order * @throws RuntimeIOException if an I/O error occurs */ short readWordData(int register) throws RuntimeIOException; @@ -182,11 +178,10 @@ default boolean probe() throws RuntimeIOException { * SMBus Write Word: i2c_smbus_write_word_data() *

*

- * This is the opposite of the Read Word operation. 16 bits of data is written - * to a device, to the designated register that is specified through the Comm - * byte. Note that the data is written in - * {@link java.nio.ByteOrder#LITTLE_ENDIAN Little Endian} byte order as per the - * SMBus specification. + * This is the opposite of the Read Word operation. 16 bits of data is written to a + * device, to the designated register that is specified through the Comm byte. Note that + * the data is written in {@link java.nio.ByteOrder#LITTLE_ENDIAN Little Endian} byte + * order as per the SMBus specification. *

* *
@@ -194,70 +189,19 @@ default boolean probe() throws RuntimeIOException {
 	 * 
* * @param register the register to write to - * @param data value to write in {@link java.nio.ByteOrder#LITTLE_ENDIAN - * Little Endian} byte order - * @throws RuntimeIOException if an I/O error occurs - */ - void writeWordData(int register, short data) throws RuntimeIOException; - - /** - *

- * SMBus Read Word Swapped: i2c_smbus_read_word_swapped() - *

- *

- * This operation is very like Read Byte; again, data is read from a device, - * from a designated register that is specified through the Comm byte. But this - * time, the data is a complete word (16 bits). Note this is the convenience - * function for reads where the two data bytes are the other way around (not - * SMBus compliant, but very popular.) - *

- * - *
-	 * S Addr Wr [A] Comm [A] S Addr Rd [A] [DataHigh] A [DataLow] NA P
-	 * 
- * - * @param register the register to read from - * @return data read as a signed short in {@link java.nio.ByteOrder#BIG_ENDIAN - * Big Endian} byte order - * @throws RuntimeIOException if an I/O error occurs - */ - default short readWordSwapped(int register) throws RuntimeIOException { - short value = readWordData(register); - return (short) (((value & 0x00ff) << 8) | ((value & 0xff00) >> 8)); - } - - /** - *

- * SMBus Write Word Swapped: i2c_smbus_write_word_swapped() - *

- *

- * This is the opposite of the Read Word operation. 16 bits of data is written - * to a device, to the designated register that is specified through the Comm - * byte. Note that this is the convenience function for writes where the two - * data bytes are the other way around (not SMBus compliant, but very popular.) - *

- * - *
-	 * S Addr Wr [A] Comm [A] DataHigh [A] DataLow [A] P
-	 * 
- * - * @param register the register to write to - * @param data value to write in {@link java.nio.ByteOrder#BIG_ENDIAN Big + * @param data value to write in {@link java.nio.ByteOrder#LITTLE_ENDIAN Little * Endian} byte order * @throws RuntimeIOException if an I/O error occurs */ - default void writeWordSwapped(int register, short data) throws RuntimeIOException { - short swapped = (short) (((data & 0x00ff) << 8) | ((data & 0xff00) >> 8)); - writeWordData(register, swapped); - } + void writeWordData(int register, short data) throws RuntimeIOException; /** *

* SMBus Process Call *

*

- * This command selects a device register (through the Comm byte), sends 16 bits - * of data to it, and reads 16 bits of data in return. + * This command selects a device register (through the Comm byte), sends 16 bits of data + * to it, and reads 16 bits of data in return. *

* *
@@ -277,9 +221,9 @@ default void writeWordSwapped(int register, short data) throws RuntimeIOExceptio
 	 * SMBus Block Read: i2c_smbus_read_block_data()
 	 * 

*

- * This command reads a block of up to 32 bytes from a device, from a designated - * register that is specified through the Comm byte. The amount of data is - * specified by the device in the Count byte. + * This command reads a block of up to 32 bytes from a device, from a designated register + * that is specified through the Comm byte. The amount of data is specified by the device + * in the Count byte. *

* *
@@ -298,9 +242,9 @@ default void writeWordSwapped(int register, short data) throws RuntimeIOExceptio
 	 * SMBus Block Write: i2c_smbus_write_block_data()
 	 * 

*

- * The opposite of the Block Read command, this writes up to 32 bytes to a - * device, to a designated register that is specified through the Comm byte. The - * amount of data is specified in the Count byte. + * The opposite of the Block Read command, this writes up to 32 bytes to a device, to a + * designated register that is specified through the Comm byte. The amount of data is + * specified in the Count byte. *

* *
@@ -318,10 +262,10 @@ default void writeWordSwapped(int register, short data) throws RuntimeIOExceptio
 	 * SMBus Block Write - Block Read Process Call
 	 * 

*

- * SMBus Block Write - Block Read Process Call was introduced in Revision 2.0 of - * the specification.
- * This command selects a device register (through the Comm byte), sends 1 to 31 - * bytes of data to it, and reads 1 to 31 bytes of data in return. + * SMBus Block Write - Block Read Process Call was introduced in Revision 2.0 of the + * specification.
+ * This command selects a device register (through the Comm byte), sends 1 to 31 bytes of + * data to it, and reads 1 to 31 bytes of data in return. *

* *
@@ -330,8 +274,7 @@ default void writeWordSwapped(int register, short data) throws RuntimeIOExceptio
 	 * 
* * @param register the register to write to and read from - * @param txData the byte array from which the data is written (up to 32 - * bytes) + * @param txData the byte array from which the data is written (up to 32 bytes) * @return the data read (up to 32 bytes) * @throws RuntimeIOException if an I/O error occurs */ @@ -351,8 +294,8 @@ default void writeWordSwapped(int register, short data) throws RuntimeIOExceptio * I2C Block Read: i2c_smbus_read_i2c_block_data() *

*

- * This command reads a block of up to 32 bytes from a device, using the - * specified register address. + * This command reads a block of up to 32 bytes from a device, using the specified + * register address. *

* * I2C commands: @@ -363,8 +306,8 @@ default void writeWordSwapped(int register, short data) throws RuntimeIOExceptio *
* * @param register the register to read from - * @param buffer the buffer to read the data into, the buffer length specifies - * the number of bytes to read up to a maximum of 32 bytes + * @param buffer the buffer to read the data into, the buffer length specifies the + * number of bytes to read up to a maximum of 32 bytes * @return the number of bytes actually read * @throws RuntimeIOException if an I/O error occurs */ @@ -375,8 +318,8 @@ default void writeWordSwapped(int register, short data) throws RuntimeIOExceptio * I2C Block Write: i2c_smbus_write_i2c_block_data() *

*

- * The opposite of the Block Read command, this writes up to 32 bytes of data to - * a device, to the specified register address. + * The opposite of the Block Read command, this writes up to 32 bytes of data to a device, + * to the specified register address. *

* * @@ -394,4 +337,273 @@ default void writeWordSwapped(int register, short data) throws RuntimeIOExceptio * @throws RuntimeIOException if an I/O error occurs */ void writeI2CBlockData(int register, byte... data) throws RuntimeIOException; + + // + // Utility methods + // + + /** + * Probe this I2C device using {@link I2CDevice.ProbeMode#AUTO Auto} probe mode + * + * @return True if the probe is successful + * @throws RuntimeIOException if an I/O error occurs + */ + default boolean probe() throws RuntimeIOException { + return probe(I2CDevice.ProbeMode.AUTO); + } + + /** + *

+ * SMBus Read Word Swapped: i2c_smbus_read_word_swapped() + *

+ *

+ * This operation is very like Read Byte; again, data is read from a device, from a + * designated register that is specified through the Comm byte. But this time, the data is + * a complete word (16 bits). Note this is the convenience function for reads where the + * two data bytes are the other way around (not SMBus compliant, but very popular.) + *

+ * + *
+	 * S Addr Wr [A] Comm [A] S Addr Rd [A] [DataHigh] A [DataLow] NA P
+	 * 
+ * + * @param register the register to read from + * @return data read as a signed short in {@link java.nio.ByteOrder#BIG_ENDIAN Big Endian} + * byte order + * @throws RuntimeIOException if an I/O error occurs + */ + default short readWordSwapped(int register) throws RuntimeIOException { + short value = readWordData(register); + return (short) (((value & 0x00ff) << 8) | ((value & 0xff00) >> 8)); + } + + /** + *

+ * SMBus Write Word Swapped: i2c_smbus_write_word_swapped() + *

+ *

+ * This is the opposite of the Read Word operation. 16 bits of data is written to a + * device, to the designated register that is specified through the Comm byte. Note that + * this is the convenience function for writes where the two data bytes are the other way + * around (not SMBus compliant, but very popular.) + *

+ * + *
+	 * S Addr Wr [A] Comm [A] DataHigh [A] DataLow [A] P
+	 * 
+ * + * @param register the register to write to + * @param data value to write in {@link java.nio.ByteOrder#BIG_ENDIAN Big Endian} byte + * order + * @throws RuntimeIOException if an I/O error occurs + */ + default void writeWordSwapped(int register, short data) throws RuntimeIOException { + short swapped = (short) (((data & 0x00ff) << 8) | ((data & 0xff00) >> 8)); + writeWordData(register, swapped); + } + + /** + * Utility method that simply casts the int data parameter to byte and calls + * {@link I2CDevice#writeByteData(int, byte)} + * + * @see I2CDevice#writeByteData(int, byte) + * + * @param register the register to write to + * @param data value to write + * @throws RuntimeIOException if an I/O error occurs + */ + default void writeByteData(int register, int data) throws RuntimeIOException { + writeByteData(register, (byte) data); + } + + /** + * Utility method that simply converts the response from + * {@link I2CDevice#readByteData(int)} to an unsigned byte. A short is returned to ensure + * that the returned value is unsigned + * + * @see I2CDevice#readByteData(int) + * + * @param register the register to read from + * @return byte data returned converted to unsigned byte (represented as a short) + * @throws RuntimeIOException if an I/O error occurs + */ + default short readUByte(int register) throws RuntimeIOException { + return (short) (readByteData(register) & 0xff); + } + + /** + * Utility method that wraps {@link I2CDevice#readI2CBlockData(int, byte[])} to read the + * specified number of bytes and return as a new byte array. + * + * @see I2CDevice#readI2CBlockData(int, byte[]) + * + * @param register the register to read from + * @param length the number of bytes to read + * @return the data read + * @throws RuntimeIOException if an I/O error occurs + */ + default byte[] readI2CBlockDataByteArray(int register, int length) throws RuntimeIOException { + byte[] data = new byte[length]; + int read = readI2CBlockData(register, data); + if (read == length) { + return data; + } + + // Shrink the byte array to the size of data actually read + byte[] rx_data = new byte[read]; + System.arraycopy(data, 0, rx_data, 0, read); + return rx_data; + } + + /** + * Utility method that wraps {@link I2CDevice#readI2CBlockData(int, byte[])} to read the + * specified number of bytes and return as a {@link ByteBuffer} using the {@link ByteOrder + * byte order} specified in the device constructor. + * + * @see I2CDevice#readI2CBlockData(int, byte[]) + * @see ByteBuffer#wrap(byte[]) + * + * @param register the register to read from + * @param length the number of bytes to read + * @return the data read + * @throws RuntimeIOException if an I/O error occurs + */ + default ByteBuffer readI2CBlockDataByteBuffer(int register, int length) throws RuntimeIOException { + byte[] data = new byte[length]; + + readI2CBlockData(register, data); + ByteBuffer buffer = ByteBuffer.wrap(data); + buffer.order(getByteOrder()); + + return buffer; + } + + /** + * Utility method that invokes either {@link I2CDevice#readWordData(int)} or + * {@link I2CDevice#readWordSwapped(int)} to read a signed short value from the requested + * register in the {@link ByteOrder byte order} specified in the constructor. + * + * @see I2CDevice#readWordData(int) + * @see I2CDevice#readWordSwapped(int) + * + * @param register register to read from + * @return the signed short value read + * @throws RuntimeIOException if an I/O error occurs + */ + default short readShort(int register) throws RuntimeIOException { + if (getByteOrder().equals(ByteOrder.LITTLE_ENDIAN)) { + return readWordData(register); + } + return readWordSwapped(register); + } + + /** + * Utility method that wraps {@link I2CDevice#readShort(int)} to read an unsigned short + * value from the requested register using the {@link ByteOrder byte order} specified in + * the constructor. + * + * @see I2CDevice#readShort(int) + * + * @param register register to read from + * @return the unsigned short value read + * @throws RuntimeIOException if an I/O error occurs + */ + default int readUShort(int register) throws RuntimeIOException { + return readShort(register) & 0xffff; + } + + /** + * Utility method that wraps {@link I2CDevice#readI2CBlockDataByteBuffer(int, int)} to + * read a signed int value from the requested register using the {@link ByteOrder byte + * order} specified in the constructor. + * + * @see I2CDevice#readI2CBlockDataByteBuffer(int, int) + * + * @param register register to read from + * @return the signed int value read + * @throws RuntimeIOException if an I/O error occurs + */ + default int readInt(int register) throws RuntimeIOException { + return readI2CBlockDataByteBuffer(register, 4).getInt(); + } + + /** + * Utility method that wraps {@link I2CDevice#readInt(int)} to read an unsigned int value + * from the requested register using the {@link ByteOrder byte order} specified in the + * constructor. + * + * @see I2CDevice#readInt(int) + * + * @param register register to read from + * @return the unsigned int value read + * @throws RuntimeIOException if an I/O error occurs + */ + default long readUInt(int register) throws RuntimeIOException { + return readInt(register) & 0xffffffffL; + } + + /** + * Utility method that wraps {@link I2CDevice#readI2CBlockDataByteArray(int, int)} to read + * an unsigned int value on the specified length from the requested register using the + * {@link ByteOrder byte order} specified in the constructor. + * + * @see I2CDevice#readI2CBlockDataByteArray(int, int) + * + * @param register register to read from + * @param numBytes number of bytes to read (1..4) + * @return the unsigned int value read + * @throws RuntimeIOException if an I/O error occurs + */ + default long readUInt(int register, int numBytes) throws RuntimeIOException { + if (numBytes < 1 || numBytes > 4) { + throw new IllegalArgumentException("Maximum int length is 4 bytes - you requested " + numBytes); + } + + if (numBytes == 4) { + return readUInt(getAddress()); + } + + byte[] data = readI2CBlockDataByteArray(register, numBytes); + + long val = 0; + for (int i = 0; i < numBytes; i++) { + val |= (data[getByteOrder().equals(ByteOrder.LITTLE_ENDIAN) ? numBytes - i - 1 : i] & 0xff) << (8 + * (numBytes - i - 1)); + } + + return val; + } + + /** + * Utility method that wraps {@link I2CDevice#readByteData(int)} to check if the specified + * bit number is set. + * + * @see BitManipulation#isBitSet(byte, int) + * @see I2CDevice#readByteData(int) + * + * @param register the register to read + * @param bit the bit number to check + * @return true if the specified bit number is set + * @throws RuntimeIOException if an I/O error occurs + */ + default boolean readBit(int register, int bit) throws RuntimeIOException { + return BitManipulation.isBitSet(readByteData(register), bit); + } + + /** + * Utility method that wraps {@link I2CDevice#readByteData(int)} and + * {@link I2CDevice#writeByteData(int, byte)} to update the specified bit number + * + * @see I2CDevice#readByteData(int) + * @see BitManipulation#setBitValue(byte, int, boolean) + * + * @param register the register to update + * @param bit the bit number to set + * @param value the value to set the bit to + * @throws RuntimeIOException if an I/O error occurs + */ + default void writeBit(int register, int bit, boolean value) throws RuntimeIOException { + byte cur_val = readByteData(register); + writeByteData(register, BitManipulation.setBitValue(cur_val, bit, value)); + } } diff --git a/diozero-core/src/main/java/com/diozero/api/SpiDevice.java b/diozero-core/src/main/java/com/diozero/api/SpiDevice.java index a21b9540..94f22385 100644 --- a/diozero-core/src/main/java/com/diozero/api/SpiDevice.java +++ b/diozero-core/src/main/java/com/diozero/api/SpiDevice.java @@ -121,14 +121,13 @@ public Builder setLsbFirst(boolean lsbFirst) { * * @return a new SPI device instance */ - public SpiDevice build() { + public SpiDeviceInterface build() { return new SpiDevice(controller, chipSelect, frequency, clockMode, lsbFirst); } } /** - * Construct a new SPI device builder instance using the specified chip select - * value + * Construct a new SPI device builder instance using the specified chip select value * * @param chipSelect SPI chip select * @return SPI device builder diff --git a/diozero-core/src/main/java/com/diozero/devices/Ads112C04.java b/diozero-core/src/main/java/com/diozero/devices/Ads112C04.java index fc95efef..cb46c4a9 100644 --- a/diozero-core/src/main/java/com/diozero/devices/Ads112C04.java +++ b/diozero-core/src/main/java/com/diozero/devices/Ads112C04.java @@ -85,10 +85,10 @@ public class Ads112C04 extends AbstractDeviceFactory implements AnalogInputDevic private static final int NUM_CHANNELS = 4; /** - * The ADS112C04 has two address pins: A0 and A1. Each address pin can be tied - * to either DGND, DVDD, SDA, or SCL, providing 16 possible unique addresses. - * This configuration allows up to 16 different ADS112C04 devices to be present - * on the same I2C bus. Name format is A1_A0 + * The ADS112C04 has two address pins: A0 and A1. Each address pin can be tied to either + * DGND, DVDD, SDA, or SCL, providing 16 possible unique addresses. This configuration + * allows up to 16 different ADS112C04 devices to be present on the same I2C bus. Name + * format is A1_A0 */ public enum Address { GND_GND(0b01000000), GND_VDD(0b01000001), GND_SDA(0b01000010), GND_SCL(0b01000011), // @@ -393,10 +393,10 @@ public boolean isCompareToAvss() { } /* - * The device has four 8-bit configuration registers that are accessible through - * the I2C interface using the RREG and WREG commands. After power-up or reset, - * all registers are set to the default values (which are all 0). All register - * values are retained during power-down mode. + * The device has four 8-bit configuration registers that are accessible through the I2C + * interface using the RREG and WREG commands. After power-up or reset, all registers are + * set to the default values (which are all 0). All register values are retained during + * power-down mode. */ public enum ConfigRegister { _0(0b00), _1(0b01), _2(0b10), _3(0b11); @@ -583,7 +583,7 @@ public static Builder builder(Address address) { } private BoardPinInfo boardPinInfo; - private I2CDevice device; + private I2CDeviceInterface device; private GainConfig gainConfig; private Pga pga; private DataRate dataRate; @@ -924,8 +924,8 @@ public void setSingleShotMode() { } /** - * Disable continuous readings and take a single-shot reading on the specified - * ADC number (non-differential reads). + * Disable continuous readings and take a single-shot reading on the specified ADC number + * (non-differential reads). * * @param adcNumber The ADC number to read from * @return The current raw Analog reading @@ -935,11 +935,10 @@ public short getSingleShotReadingNonDifferential(int adcNumber) { } /** - * Disable continuous readings and take a single-shot reading on the specified - * ADC number. + * Disable continuous readings and take a single-shot reading on the specified ADC number. * - * For settings where AINN = AVSS, the PGA must be disabled (PGA_BYPASS = 1) and - * only gains 1, 2, and 4 can be used. + * For settings where AINN = AVSS, the PGA must be disabled (PGA_BYPASS = 1) and only + * gains 1, 2, and 4 can be used. * * @param inputMultiplexerConfig the input multiplexer configuration * @return The current raw Analog reading @@ -962,9 +961,8 @@ public short getSingleShotReading(InputMultiplexerConfig inputMultiplexerConfig) } /** - * Enable continuous read mode for the specified ADC number (AINp = - * AIN{adcNumber}, AINn = AVSS). Note the PGA must be disabled and only gains 1, - * 2, and 4 can be used. + * Enable continuous read mode for the specified ADC number (AINp = AIN{adcNumber}, AINn = + * AVSS). Note the PGA must be disabled and only gains 1, 2, and 4 can be used. * * @param adcNumber The ADC to continuously read from (non-differential mode) */ @@ -973,9 +971,8 @@ public void setContinuousModeNonDifferential(int adcNumber) { } /** - * Enable continuous read mode for the specified input multiplexer value. For - * settings where AINN = AVSS, the PGA must be disabled and only gains 1, 2, and - * 4 can be used. + * Enable continuous read mode for the specified input multiplexer value. For settings + * where AINN = AVSS, the PGA must be disabled and only gains 1, 2, and 4 can be used. * * @param inputMultiplexerConfig The input multiplexer configuration */ diff --git a/diozero-core/src/main/java/com/diozero/devices/Ads1x15.java b/diozero-core/src/main/java/com/diozero/devices/Ads1x15.java index aa48e193..d43a452c 100644 --- a/diozero-core/src/main/java/com/diozero/devices/Ads1x15.java +++ b/diozero-core/src/main/java/com/diozero/devices/Ads1x15.java @@ -41,6 +41,7 @@ import com.diozero.api.DigitalInputDevice; import com.diozero.api.I2CConstants; import com.diozero.api.I2CDevice; +import com.diozero.api.I2CDeviceInterface; import com.diozero.api.PinInfo; import com.diozero.api.RuntimeIOException; import com.diozero.api.function.FloatConsumer; @@ -53,8 +54,8 @@ import com.diozero.util.SleepUtil; /** - * ADS1115 Datasheet: https://www.ti.com/lit/ds/symlink/ads1115.pdf ADS1015 - * Datasheet: https://www.ti.com/lit/ds/symlink/ads1015.pdf + * ADS1115 Datasheet: https://www.ti.com/lit/ds/symlink/ads1115.pdf ADS1015 Datasheet: + * https://www.ti.com/lit/ds/symlink/ads1015.pdf * *
  * Device  | Resolution | Max Sample Rate | # Channels | Interface | Features
@@ -72,11 +73,11 @@
  * A3 | A2 | A1 | A0 | ALERT | ADDR | SDA | SCL | G | V
  * 
* - * ADDR (In) - I2C slave address select ALERT (Out) - Comparator output or - * conversion ready (ADS1114 and ADS1115 only) + * ADDR (In) - I2C slave address select ALERT (Out) - Comparator output or conversion + * ready (ADS1114 and ADS1115 only) * - * ADDR - can be connected to GND, VDD, SDA, or SCL, allowing for four different - * addresses to be selected + * ADDR - can be connected to GND, VDD, SDA, or SCL, allowing for four different addresses + * to be selected * *
  * GND | 0b01001000 (0x48)
@@ -166,8 +167,8 @@ public byte getMask() {
 	}
 
 	/**
-	 * Programmable Gain Amplifier configuration. Ensure that ADC input voltage does
-	 * not exceed this value
+	 * Programmable Gain Amplifier configuration. Ensure that ADC input voltage does not
+	 * exceed this value
 	 */
 	public static enum PgaConfig {
 		_6144MV(6.144f, 0b000), _4096MV(4.096f, 0b001), _2048MV(2.048f, 0b010), _1024MV(1.024f, 0b011),
@@ -295,7 +296,7 @@ public byte getMask() {
 	// lowest address currently asserting the ALERT/RDY bus line.
 	private static final int CONFIG_LSB_COMP_LATCHING = 1 << 2;
 
-	private I2CDevice device;
+	private I2CDeviceInterface device;
 	private Model model;
 	private BoardPinInfo boardPinInfo;
 	private PgaConfig pgaConfig;
@@ -316,9 +317,8 @@ public byte getMask() {
 
 	/**
 	 * 
-	 * @param pgaConfig Programmable Gain Amplifier configuration - make sure this
-	 *                  is set correctly and that the ADC input voltage does not
-	 *                  exceed this value
+	 * @param pgaConfig Programmable Gain Amplifier configuration - make sure this is set
+	 *                  correctly and that the ADC input voltage does not exceed this value
 	 * @param dataRate  Data read frequency (Hz)
 	 */
 	public Ads1x15(PgaConfig pgaConfig, Ads1115DataRate dataRate) {
diff --git a/diozero-core/src/main/java/com/diozero/devices/BH1750.java b/diozero-core/src/main/java/com/diozero/devices/BH1750.java
index a184eb3c..eff28b56 100644
--- a/diozero-core/src/main/java/com/diozero/devices/BH1750.java
+++ b/diozero-core/src/main/java/com/diozero/devices/BH1750.java
@@ -32,14 +32,14 @@
  */
 
 import com.diozero.api.I2CDevice;
+import com.diozero.api.I2CDeviceInterface;
 import com.diozero.api.RuntimeIOException;
 import com.diozero.util.SleepUtil;
 
 /**
  * BH1750 Luminosity sensor
  * Datasheet
- * Python
- * code
+ * Python code
  * 
  * Pins:
  * 
@@ -102,7 +102,7 @@ public int getMeasurementTimeMs() {
 
 	private static final Mode DEFAULT_MODE = Mode.CONTINUOUS_HIGH_RES_MODE;
 
-	private I2CDevice device;
+	private I2CDeviceInterface device;
 	private Mode mode;
 
 	public BH1750(int controller) {
diff --git a/diozero-core/src/main/java/com/diozero/devices/BME680.java b/diozero-core/src/main/java/com/diozero/devices/BME680.java
index 446a5c51..b6a712f5 100644
--- a/diozero-core/src/main/java/com/diozero/devices/BME680.java
+++ b/diozero-core/src/main/java/com/diozero/devices/BME680.java
@@ -38,12 +38,13 @@
 
 import com.diozero.api.I2CConstants;
 import com.diozero.api.I2CDevice;
+import com.diozero.api.I2CDeviceInterface;
 import com.diozero.util.SleepUtil;
 
 /**
- * Indoor air quality (IAQ) output. In principle, this output is in an index
- * that can have values between 0 and 500 with a resolution of 1 to indicate or
- * quantify the quality of the air available in the surrounding.
+ * Indoor air quality (IAQ) output. In principle, this output is in an index that can have
+ * values between 0 and 500 with a resolution of 1 to indicate or quantify the quality of
+ * the air available in the surrounding.
  *
  * Operational Range: Temperature: -40C-85C Humidity: 10-95 %r.H. IAQ: 0-500
  *
@@ -304,20 +305,21 @@ public enum HeaterProfile {
 	private static final int RESET_PERIOD_MILLISECONDS = 10;
 	private static final int POLL_PERIOD_MILLISECONDS = 10;
 
-	private I2CDevice device;
-	// Raw temperature data
-	private int temperatureFine;
-
 	// Look up tables for the possible gas range values
-	final long GAS_RANGE_LOOKUP_TABLE_1[] = { 2147483647L, 2147483647L, 2147483647L, 2147483647L, 2147483647L,
-			2126008810L, 2147483647L, 2130303777L, 2147483647L, 2147483647L, 2143188679L, 2136746228L, 2147483647L,
-			2126008810L, 2147483647L, 2147483647L };
+	private static final long GAS_RANGE_LOOKUP_TABLE_1[] = { 2147483647L, 2147483647L, 2147483647L, 2147483647L,
+			2147483647L, 2126008810L, 2147483647L, 2130303777L, 2147483647L, 2147483647L, 2143188679L, 2136746228L,
+			2147483647L, 2126008810L, 2147483647L, 2147483647L };
 
-	final long GAS_RANGE_LOOKUP_TABLE_2[] = { 4096000000L, 2048000000L, 1024000000L, 512000000L, 255744255L, 127110228L,
-			64000000L, 32258064L, 16016016L, 8000000L, 4000000L, 2000000L, 1000000L, 500000L, 250000L, 125000L };
+	private static final long GAS_RANGE_LOOKUP_TABLE_2[] = { 4096000000L, 2048000000L, 1024000000L, 512000000L,
+			255744255L, 127110228L, 64000000L, 32258064L, 16016016L, 8000000L, 4000000L, 2000000L, 1000000L, 500000L,
+			250000L, 125000L };
 
 	private static final int DATA_GAS_BURN_IN = 50;
 
+	private I2CDeviceInterface device;
+	// Raw temperature data
+	private int temperatureFine;
+
 	private int chipId;
 	/* ! Ambient temperature in Degree C */
 	private int ambientTemperature;
@@ -623,8 +625,8 @@ public void setGasMeasurementEnabled(final boolean gasMeasurementsEnabled) {
 	}
 
 	/**
-	 * Set temperature offset in celsius. If set, the temperature t_fine will be
-	 * increased by given value in celsius.
+	 * Set temperature offset in celsius. If set, the temperature t_fine will be increased by
+	 * given value in celsius.
 	 *
 	 * @param value temperature offset in Celsius, eg. 4, -8, 1.25
 	 */
diff --git a/diozero-core/src/main/java/com/diozero/devices/BME68x.java b/diozero-core/src/main/java/com/diozero/devices/BME68x.java
index 26c2f43b..2780f47c 100644
--- a/diozero-core/src/main/java/com/diozero/devices/BME68x.java
+++ b/diozero-core/src/main/java/com/diozero/devices/BME68x.java
@@ -35,6 +35,7 @@
 
 import com.diozero.api.I2CConstants;
 import com.diozero.api.I2CDevice;
+import com.diozero.api.I2CDeviceInterface;
 import com.diozero.util.BitManipulation;
 import com.diozero.util.SleepUtil;
 
@@ -429,6 +430,10 @@ public static Builder builder(final int controller) {
 			return new Builder(controller);
 		}
 
+		public static Builder builder(final I2CDeviceInterface device) {
+			return new Builder(device);
+		}
+
 		/*-
 		 * chipId: 0x61, variantId: 0x1, uniqueId: 0x2c
 		 * Defaults:
@@ -440,17 +445,25 @@ public static Builder builder(final int controller) {
 		 */
 		private int controller;
 		private int address = DEVICE_ADDRESS;
+		private I2CDeviceInterface device;
 		private OversamplingMultiplier humidityOversampling;
 		private OversamplingMultiplier temperatureOversampling;
 		private OversamplingMultiplier pressureOversampling;
 		private IirFilterCoefficient filter;
 		private StandbyDuration standbyDuration;
 
-		public Builder(int controller) {
+		public Builder(final int controller) {
 			this.controller = controller;
 		}
 
+		public Builder(final I2CDeviceInterface device) {
+			this.device = device;
+		}
+
 		public Builder setAddress(int address) {
+			if (device != null) {
+				throw new IllegalArgumentException("I2C device already assigned");
+			}
 			this.address = address;
 			return this;
 		}
@@ -481,12 +494,15 @@ public Builder setDataRate(StandbyDuration standbyDuration) {
 		}
 
 		public BME68x build() {
-			return new BME68x(controller, address, humidityOversampling, temperatureOversampling, pressureOversampling,
-					filter, standbyDuration);
+			if (device == null) {
+				device = I2CDevice.builder(address).setController(controller).build();
+			}
+			return new BME68x(device, humidityOversampling, temperatureOversampling, pressureOversampling, filter,
+					standbyDuration);
 		}
 	}
 
-	private I2CDevice device;
+	private I2CDeviceInterface device;
 	private byte chipId;
 	private byte variantId;
 	private byte uniqueId;
@@ -517,20 +533,53 @@ public BME68x(final int controller) {
 	 * @param address    I2C address of the sensor.
 	 */
 	public BME68x(final int controller, final int address) {
-		this(controller, address, OversamplingMultiplier.X1, OversamplingMultiplier.X1, OversamplingMultiplier.X1,
+		this(I2CDevice.builder(address).setController(controller).build());
+	}
+
+	/**
+	 * Create a new BME680 sensor driver connected on the given bus and address.
+	 *
+	 * @param device I2C device.
+	 */
+	public BME68x(final I2CDeviceInterface device) {
+		this(device, OversamplingMultiplier.X1, OversamplingMultiplier.X1, OversamplingMultiplier.X1,
 				IirFilterCoefficient._7, StandbyDuration._10_MS);
 	}
 
 	/**
 	 * Create a new BME680 sensor driver connected on the given bus and address.
 	 *
-	 * @param controller I2C bus the sensor is connected to.
-	 * @param address    I2C address of the sensor.
+	 * @param controller               I2C bus the sensor is connected to.
+	 * @param address                  I2C address of the sensor.
+	 * @param humidityOversampling     Humidity oversampling.
+	 * @param termperatureOversampling Temperature oversampling.
+	 * @param pressureOversampling     Pressure oversampling.
+	 * @param filter                   Infinite Impulse Response (IIR) filter.
+	 * @param standbyDuration          Standby time between sequential mode
+	 *                                 measurement profiles.
 	 */
 	public BME68x(final int controller, final int address, OversamplingMultiplier humidityOversampling,
 			OversamplingMultiplier temperatureOversampling, OversamplingMultiplier pressureOversampling,
 			IirFilterCoefficient filter, StandbyDuration standbyDuration) {
-		this.device = I2CDevice.builder(address).setController(controller).build();
+		this(I2CDevice.builder(address).setController(controller).build(), humidityOversampling,
+				temperatureOversampling, pressureOversampling, filter, standbyDuration);
+	}
+
+	/**
+	 * Create a new BME680 sensor driver connected on the given bus and address.
+	 *
+	 * @param device                   I2C device.
+	 * @param humidityOversampling     Humidity oversampling.
+	 * @param termperatureOversampling Temperature oversampling.
+	 * @param pressureOversampling     Pressure oversampling.
+	 * @param filter                   Infinite Impulse Response (IIR) filter.
+	 * @param standbyDuration          Standby time between sequential mode
+	 *                                 measurement profiles.
+	 */
+	public BME68x(final I2CDeviceInterface device, OversamplingMultiplier humidityOversampling,
+			OversamplingMultiplier temperatureOversampling, OversamplingMultiplier pressureOversampling,
+			IirFilterCoefficient filter, StandbyDuration standbyDuration) {
+		this.device = device;
 
 		initialise(humidityOversampling, temperatureOversampling, pressureOversampling, filter, standbyDuration);
 	}
diff --git a/diozero-core/src/main/java/com/diozero/devices/BMP180.java b/diozero-core/src/main/java/com/diozero/devices/BMP180.java
index c515047c..39e7fd1c 100644
--- a/diozero-core/src/main/java/com/diozero/devices/BMP180.java
+++ b/diozero-core/src/main/java/com/diozero/devices/BMP180.java
@@ -36,6 +36,7 @@
 
 import com.diozero.api.I2CConstants;
 import com.diozero.api.I2CDevice;
+import com.diozero.api.I2CDeviceInterface;
 import com.diozero.api.RuntimeIOException;
 import com.diozero.util.SleepUtil;
 
@@ -44,9 +45,9 @@
  */
 public class BMP180 implements ThermometerInterface, BarometerInterface {
 	/**
-	 * Relationship between sampling mode and conversion delay (in ms) for each
-	 * sampling mode Ultra low power: 4.5 ms minimum conversion delay Standard: 7.5
-	 * ms High Resolution: 13.5 ms Ultra high Resolution: 25.5 ms
+	 * Relationship between sampling mode and conversion delay (in ms) for each sampling mode
+	 * Ultra low power: 4.5 ms minimum conversion delay Standard: 7.5 ms High Resolution: 13.5
+	 * ms Ultra high Resolution: 25.5 ms
 	 */
 	public static enum Mode {
 		ULTRA_LOW_POWER(0, 5), STANDARD(1, 8), HIGH_RESOLUTION(2, 14), ULTRA_HIGH_RESOLUTION(3, 26);
@@ -143,7 +144,7 @@ int getSamplingMode() {
 
 	// Barometer configuration
 	private Mode mode;
-	private I2CDevice i2cDevice;
+	private I2CDeviceInterface i2cDevice;
 
 	/**
 	 * Constructor
@@ -162,8 +163,8 @@ public BMP180(int controller, Mode mode) throws RuntimeIOException {
 	}
 
 	/**
-	 * This method reads the calibration data common for the Temperature sensor and
-	 * Barometer sensor included in the BMP180
+	 * This method reads the calibration data common for the Temperature sensor and Barometer
+	 * sensor included in the BMP180
 	 * 
 	 * @throws RuntimeIOException if an I/O error occurs
 	 **/
@@ -201,10 +202,10 @@ private int readRawTemperature() throws RuntimeIOException {
 	}
 
 	/**
-	 * Method for reading the temperature. Remember the sensor will provide us with
-	 * raw data, and we need to transform in some analysed value to make sense. All
-	 * the calculations are normally provided by the manufacturer. In our case we
-	 * use the calibration data collected at construction time.
+	 * Method for reading the temperature. Remember the sensor will provide us with raw data,
+	 * and we need to transform in some analysed value to make sense. All the calculations are
+	 * normally provided by the manufacturer. In our case we use the calibration data
+	 * collected at construction time.
 	 *
 	 * @return Temperature in Celsius as a double
 	 * @throws RuntimeIOException If there is an IO error reading the sensor
diff --git a/diozero-core/src/main/java/com/diozero/devices/BMx280.java b/diozero-core/src/main/java/com/diozero/devices/BMx280.java
index ba4cc22f..6b55260d 100644
--- a/diozero-core/src/main/java/com/diozero/devices/BMx280.java
+++ b/diozero-core/src/main/java/com/diozero/devices/BMx280.java
@@ -37,10 +37,12 @@
 import org.tinylog.Logger;
 
 import com.diozero.api.I2CDevice;
+import com.diozero.api.I2CDeviceInterface;
 import com.diozero.api.RuntimeIOException;
 import com.diozero.api.SpiClockMode;
 import com.diozero.api.SpiConstants;
 import com.diozero.api.SpiDevice;
+import com.diozero.api.SpiDeviceInterface;
 import com.diozero.util.SleepUtil;
 
 /*-
@@ -61,9 +63,9 @@
  */
 
 /**
- * Provides access to the Bosch BMx280 pressure and temperature sensor. The
- * BME280 includes an additional humidity sensor. Different constructors support
- * access via I2C or SPI.
+ * Provides access to the Bosch BMx280 pressure and temperature sensor. The BME280
+ * includes an additional humidity sensor. Different constructors support access via I2C
+ * or SPI.
  *
  * All constructors configure the device as follows:
  * 
    @@ -259,8 +261,8 @@ public byte getMask() { } private boolean useI2C; - private I2CDevice deviceI; - private SpiDevice deviceS; + private I2CDeviceInterface deviceI; + private SpiDeviceInterface deviceS; private Model model; // Calibration data private int digT1; @@ -283,12 +285,17 @@ public byte getMask() { private byte digH6; public static class I2CBuilder { - public static I2CBuilder builder(int bus) { - return new I2CBuilder(bus); + public static I2CBuilder builder(int controller) { + return new I2CBuilder(controller); } - private int bus; + public static I2CBuilder builder(I2CDeviceInterface device) { + return new I2CBuilder(device); + } + + private int controller; private int address = DEFAULT_I2C_ADDRESS; + private I2CDeviceInterface device; private TemperatureOversampling temperatureOversampling = TemperatureOversampling._1; private PressureOversampling pressureOversampling = PressureOversampling._1; private HumidityOversampling humidityOversampling = HumidityOversampling._1; @@ -296,11 +303,18 @@ public static I2CBuilder builder(int bus) { private StandbyDuration standbyDuration = StandbyDuration._1_S; private FilterCoefficient filterCoefficient = FilterCoefficient.OFF; - public I2CBuilder(int bus) { - this.bus = bus; + public I2CBuilder(int controller) { + this.controller = controller; + } + + public I2CBuilder(I2CDeviceInterface device) { + this.device = device; } public I2CBuilder setAddress(int address) { + if (device != null) { + throw new IllegalArgumentException("I2C device already assigned"); + } this.address = address; return this; } @@ -336,7 +350,10 @@ public I2CBuilder setFilterCoefficient(FilterCoefficient filterCoefficient) { } public BMx280 build() { - return new BMx280(bus, address, temperatureOversampling, pressureOversampling, humidityOversampling, + if (device == null) { + device = I2CDevice.builder(address).setController(controller).build(); + } + return new BMx280(device, temperatureOversampling, pressureOversampling, humidityOversampling, operatingMode, standbyDuration, filterCoefficient); } } @@ -346,10 +363,15 @@ public static SpiBuilder builder(int chipSelect) { return new SpiBuilder(chipSelect); } + public static SpiBuilder builder(SpiDeviceInterface device) { + return new SpiBuilder(device); + } + private int chipSelect; private int controller = SpiConstants.DEFAULT_SPI_CONTROLLER; private int frequency = SpiConstants.DEFAULT_SPI_CLOCK_FREQUENCY; private SpiClockMode mode = SpiConstants.DEFAULT_SPI_CLOCK_MODE; + private SpiDeviceInterface device; private TemperatureOversampling temperatureOversampling = TemperatureOversampling._1; private PressureOversampling pressureOversampling = PressureOversampling._1; private HumidityOversampling humidityOversampling = HumidityOversampling._1; @@ -361,6 +383,10 @@ public SpiBuilder(int chipSelect) { this.chipSelect = chipSelect; } + public SpiBuilder(SpiDeviceInterface device) { + this.device = device; + } + /** * Set the SPI controller * @@ -368,6 +394,9 @@ public SpiBuilder(int chipSelect) { * @return this builder instance */ public SpiBuilder setController(int controller) { + if (device != null) { + throw new IllegalStateException("SPI device already assigned"); + } this.controller = controller; return this; } @@ -379,6 +408,9 @@ public SpiBuilder setController(int controller) { * @return this builder instance */ public SpiBuilder setChipSelect(int chipSelect) { + if (device != null) { + throw new IllegalStateException("SPI device already assigned"); + } this.chipSelect = chipSelect; return this; } @@ -390,6 +422,9 @@ public SpiBuilder setChipSelect(int chipSelect) { * @return this builder instance */ public SpiBuilder setFrequency(int frequency) { + if (device != null) { + throw new IllegalStateException("SPI device already assigned"); + } this.frequency = frequency; return this; } @@ -401,6 +436,9 @@ public SpiBuilder setFrequency(int frequency) { * @return this builder instance */ public SpiBuilder setClockMode(SpiClockMode mode) { + if (device != null) { + throw new IllegalStateException("SPI device already assigned"); + } this.mode = mode; return this; } @@ -436,31 +474,33 @@ public SpiBuilder setFilterCoefficient(FilterCoefficient filterCoefficient) { } public BMx280 build() { - return new BMx280(controller, chipSelect, frequency, mode, temperatureOversampling, pressureOversampling, - humidityOversampling, operatingMode, standbyDuration, filterCoefficient); + if (device == null) { + device = SpiDevice.builder(chipSelect).setController(controller).setFrequency(frequency) + .setClockMode(mode).build(); + } + return new BMx280(device, temperatureOversampling, pressureOversampling, humidityOversampling, + operatingMode, standbyDuration, filterCoefficient); } } - private BMx280(int bus, int address, TemperatureOversampling temperatureOversampling, + private BMx280(I2CDeviceInterface device, TemperatureOversampling temperatureOversampling, PressureOversampling pressureOversampling, HumidityOversampling humidityOversampling, OperatingMode operatingMode, StandbyDuration standbyDuration, FilterCoefficient filterCoefficient) throws RuntimeIOException { useI2C = true; - deviceI = I2CDevice.builder(address).setController(bus).setByteOrder(ByteOrder.LITTLE_ENDIAN).build(); + deviceI = device; initialise(temperatureOversampling, pressureOversampling, humidityOversampling, operatingMode, standbyDuration, filterCoefficient); } - private BMx280(int controller, int chipSelect, int frequency, SpiClockMode mode, - TemperatureOversampling temperatureOversampling, PressureOversampling pressureOversampling, - HumidityOversampling humidityOversampling, OperatingMode operatingMode, StandbyDuration standbyDuration, - FilterCoefficient filterCoefficient) { + private BMx280(SpiDeviceInterface device, TemperatureOversampling temperatureOversampling, + PressureOversampling pressureOversampling, HumidityOversampling humidityOversampling, + OperatingMode operatingMode, StandbyDuration standbyDuration, FilterCoefficient filterCoefficient) { useI2C = false; - deviceS = SpiDevice.builder(chipSelect).setController(controller).setFrequency(frequency).setClockMode(mode) - .build(); + deviceS = device; initialise(temperatureOversampling, pressureOversampling, humidityOversampling, operatingMode, standbyDuration, filterCoefficient); @@ -591,8 +631,8 @@ public boolean isDataAvailable() { } /** - * Reads the temperature, pressure, and humidity registers; compensates the raw - * values to provide meaningful results. + * Reads the temperature, pressure, and humidity registers; compensates the raw values to + * provide meaningful results. * * @return array in order of: temperature, pressure, humidity */ @@ -653,8 +693,8 @@ public float[] getValues() { } /** - * Reads the temperature, pressure, and humidity registers; compensates the raw - * values to provide meaningful results. + * Reads the temperature, pressure, and humidity registers; compensates the raw values to + * provide meaningful results. * * @return temperature */ @@ -664,8 +704,8 @@ public float getTemperature() { } /** - * Reads the temperature, pressure, and humidity registers; compensates the raw - * values to provide meaningful results. + * Reads the temperature, pressure, and humidity registers; compensates the raw values to + * provide meaningful results. * * @return pressure in hectoPascals (hPa) */ @@ -675,8 +715,8 @@ public float getPressure() { } /** - * Reads the temperature, pressure, and humidity registers; compensates the raw - * values to provide meaningful results. + * Reads the temperature, pressure, and humidity registers; compensates the raw values to + * provide meaningful results. * * @return humidity */ diff --git a/diozero-core/src/main/java/com/diozero/devices/GarminLidarLiteV4.java b/diozero-core/src/main/java/com/diozero/devices/GarminLidarLiteV4.java index 0d3a0da7..3e9707ce 100644 --- a/diozero-core/src/main/java/com/diozero/devices/GarminLidarLiteV4.java +++ b/diozero-core/src/main/java/com/diozero/devices/GarminLidarLiteV4.java @@ -36,6 +36,7 @@ import org.tinylog.Logger; import com.diozero.api.I2CDevice; +import com.diozero.api.I2CDeviceInterface; import com.diozero.api.RuntimeIOException; import com.diozero.api.RuntimeInterruptedException; import com.diozero.util.BitManipulation; @@ -84,18 +85,17 @@ public static HardwareRevision of(int value) { public enum PowerMode { /** - * The coprocessor is always OFF unless a distance measurement is requested or a - * register access is required. + * The coprocessor is always OFF unless a distance measurement is requested or a register + * access is required. */ ASYNCHRONOUS(ASYNC_POWER_MODE), /** - * Distance measurement is tied to the ANT channel period. The coprocessor is - * turned on and off as required. + * Distance measurement is tied to the ANT channel period. The coprocessor is turned on + * and off as required. */ SYNCHRONOUS(SYNC_POWER_MODE), /** - * The coprocessor is not turned off, allowing for the fastest measurements - * possible. + * The coprocessor is not turned off, allowing for the fastest measurements possible. */ ALWAYS_ON(ALWAYS_ON_POWER_MODE); @@ -226,13 +226,11 @@ public static class Status { /** 1: Device is busy taking a measurement or powering on */ public static final byte BUSY_BIT = 0; /** - * 1: Signal data in correlation record has reached the maximum value before - * overflow + * 1: Signal data in correlation record has reached the maximum value before overflow */ public static final byte SIGNAL_OVERFLOW_BIT = 1; /** - * 1: Reference data in correlation record has reached the maximum value before - * overflow + * 1: Reference data in correlation record has reached the maximum value before overflow */ public static final byte REFDATA_OVERFLOW_BIT = 2; /** 1: device is in low power mode */ @@ -264,9 +262,8 @@ public boolean isDeviceBusy() { /** * Signal overflow flag. * - * @return true if the signal data in correlation record has reached the maximum - * value before overflow (this occurs with a strong received signal - * strength) + * @return true if the signal data in correlation record has reached the maximum value + * before overflow (this occurs with a strong received signal strength) */ public boolean isSignalOverflow() { return BitManipulation.isBitSet(value, SIGNAL_OVERFLOW_BIT); @@ -275,9 +272,8 @@ public boolean isSignalOverflow() { /** * Reference overflow flag. * - * @return reue if reference data in correlation record has reached the maximum - * value before overflow (this occurs when taking measurements with - * biasing enabled) + * @return reue if reference data in correlation record has reached the maximum value + * before overflow (this occurs when taking measurements with biasing enabled) */ public boolean isReferenceDataOverflow() { return BitManipulation.isBitSet(value, REFDATA_OVERFLOW_BIT); @@ -289,8 +285,8 @@ public boolean isReferenceDataOverflow() { *
    0
    *
    Device is powered on. I2C commands can be issued at a normal rate.
    *
    1
    - *
    The device is in low power mode. To allow the device to power on and - * perform the I2C command, a 10ms delay after each command is recommended.
    + *
    The device is in low power mode. To allow the device to power on and perform the + * I2C command, a 10ms delay after each command is recommended.
    * * * @return true if the device is in low power mode @@ -305,8 +301,8 @@ public boolean isInLowerPowerMode() { *
    false
    *
    The device is performing automatic DC noise bias corrections.
    *
    true
    - *
    DC noise is within tolerance, and the automatic DC noise bias corrections - * are currently idle.
    + *
    DC noise is within tolerance, and the automatic DC noise bias corrections are + * currently idle.
    * * * @return the data correlation noise bias status @@ -318,8 +314,8 @@ public boolean isDataCorrelationNoiseBiasDone() { /** * Data correlation noise bias error flag. * - * @return true if an error was detected in correcting DC noise bias, and - * distance measurements are expected to be inaccurate + * @return true if an error was detected in correcting DC noise bias, and distance + * measurements are expected to be inaccurate */ public boolean isDataCorrelationNoiseBiasError() { return BitManipulation.isBitSet(value, DC_ERROR_BIT); @@ -333,7 +329,7 @@ public boolean isDataCorrelationNoiseBiasError() { private static final byte FLASH_STORAGE = 0x11; private static final byte HIGH_ACCURACY_MODE_DISABLED = 0x00; - private I2CDevice device; + private I2CDeviceInterface device; public GarminLidarLiteV4() { device = I2CDevice.builder(DEFAULT_ADDRESS).setByteOrder(ByteOrder.LITTLE_ENDIAN).build(); @@ -386,8 +382,8 @@ public String getLibraryVersion() { } /** - * Resets the NVM/Flash storage information back to default settings and - * executes a SoftDevice reset. + * Resets the NVM/Flash storage information back to default settings and executes a + * SoftDevice reset. */ public void factoryReset() { device.writeByteData(FACTORY_RESET, 0x01); @@ -473,19 +469,17 @@ public boolean isFlashStorageEnabled() { * Storage for register settings. *

    *

    - * NOTE: Use caution when enabling flash storage. The total - * number of writes and erases is limited to 10,000. + * NOTE: Use caution when enabling flash storage. The total number of + * writes and erases is limited to 10,000. *

    * *
    *
    Enabled
    - *
    Use RAM storage only. When the device is reset, default values are - * loaded.
    + *
    Use RAM storage only. When the device is reset, default values are loaded.
    *
    Disabled
    - *
    Use FLASH/NVM storage. Any register that supports both read and write - * operations is stored in NVM and persists over power cycles. When the device - * is reset, the values stored in NVM are loaded instead of the default - * values.
    + *
    Use FLASH/NVM storage. Any register that supports both read and write operations is + * stored in NVM and persists over power cycles. When the device is reset, the values + * stored in NVM are loaded instead of the default values.
    *
    * * @param enabled whether or not to use Flash/NVM storage for register settings @@ -495,21 +489,20 @@ public void setFlashStorage(boolean enabled) { } /** - * Get the high accuracy mode. While high accuracy mode is disabled, you can - * adjust the {@link PowerMode} to {@link PowerMode#ASYNCHRONOUS Asynchronous} - * or {@link PowerMode#SYNCHRONOUS Synchronous} if required. + * Get the high accuracy mode. While high accuracy mode is disabled, you can adjust the + * {@link PowerMode} to {@link PowerMode#ASYNCHRONOUS Asynchronous} or + * {@link PowerMode#SYNCHRONOUS Synchronous} if required. * *
    *
    0x00
    *
    High accuracy mode is disabled
    *
    0x01 to 0xFF
    - *
    High accuracy mode is enabled. The value is used as the number of - * distance measurements to accumulate and average before returning them to the - * user.
    + *
    High accuracy mode is enabled. The value is used as the number of distance + * measurements to accumulate and average before returning them to the user.
    *
    * - * @return the number of distance measurements to accumulate and average before - * returning them to the user (0 == disabled) + * @return the number of distance measurements to accumulate and average before returning + * them to the user (0 == disabled) */ public int getHighAccuracyMode() { return device.readByteData(HIGH_ACCURACY_MODE) & 0xff; @@ -525,24 +518,23 @@ public boolean isHighAccuracyModeEnabled() { } /** - * Set the high accuracy mode. While high accuracy mode is disabled, you can - * adjust the {@link PowerMode} to {@link PowerMode#ASYNCHRONOUS Asynchronous} - * or {@link PowerMode#SYNCHRONOUS Synchronous} if required. + * Set the high accuracy mode. While high accuracy mode is disabled, you can adjust the + * {@link PowerMode} to {@link PowerMode#ASYNCHRONOUS Asynchronous} or + * {@link PowerMode#SYNCHRONOUS Synchronous} if required. * *
    *
    0x00
    *
    High accuracy mode is disabled
    *
    0x01 to 0xFF
    - *
    Enable high accuracy mode. The value is used as the number of distance - * measurements to accumulate and average before returning them to the - * user.
    + *
    Enable high accuracy mode. The value is used as the number of distance measurements + * to accumulate and average before returning them to the user.
    *
    * - * Note you must set the {@link PowerMode} to {@link PowerMode#ALWAYS_ON Always - * On} before you adjust to a non-zero value. + * Note you must set the {@link PowerMode} to {@link PowerMode#ALWAYS_ON Always On} before + * you adjust to a non-zero value. * - * @param accuracyMode the number of distance measurements to accumulate and - * average before returning them to the user (0 == disabled) + * @param accuracyMode the number of distance measurements to accumulate and average + * before returning them to the user (0 == disabled) */ public void setHighAccuracyMode(int accuracyMode) { if (accuracyMode < 0 || accuracyMode > 255) { @@ -598,8 +590,8 @@ public void setMaximumAcquisitionCount(int acquisitionCount) { * *
    *
    0x00
    - *
    Use default valid measurement detection algorithm based on the peak - * value, signal strength, and noise in the correlation record.
    + *
    Use default valid measurement detection algorithm based on the peak value, signal + * strength, and noise in the correlation record.
    *
    0x01 to 0xFF
    *
    Set simple threshold for valid measurement detection.
    *
    @@ -620,8 +612,8 @@ public int getDetectionSensitivity() { * *
    *
    0x00
    - *
    Use default valid measurement detection algorithm based on the peak - * value, signal strength, and noise in the correlation record.
    + *
    Use default valid measurement detection algorithm based on the peak value, signal + * strength, and noise in the correlation record.
    *
    0x01 to 0xFF
    *
    Set simple threshold for valid measurement detection.
    *
    @@ -640,9 +632,9 @@ public void setDetectionSensitivity(int detectionSensitivity) { } /** - * Get the status of the quick acquisition termination flag. If enabled the - * device terminates the distance measurement early if it anticipates the signal - * peak in the correlation record will reach the maximum value. + * Get the status of the quick acquisition termination flag. If enabled the device + * terminates the distance measurement early if it anticipates the signal peak in the + * correlation record will reach the maximum value. * * @return acquisition quick termination status */ @@ -655,9 +647,9 @@ public boolean isQuickAcquistionTerminationEnabled() { } /** - * Set the quick acquisition termination flag. If enabled the device terminates - * the distance measurement early if it anticipates the signal peak in the - * correlation record will reach the maximum value. + * Set the quick acquisition termination flag. If enabled the device terminates the + * distance measurement early if it anticipates the signal peak in the correlation record + * will reach the maximum value. * * @param enabled quick acquisition termination value */ @@ -667,20 +659,19 @@ public void setQuickTerminationEnabled(boolean enabled) { /** *

    - * The correlation record used to calculate distance can be read from the - * device. It has a bipolar wave shape, transitioning from a positive going - * portion to a roughly symmetrical negative going pulse. The point where the - * signal crosses zero represents the effective delay for the reference and - * return signals. + * The correlation record used to calculate distance can be read from the device. It has a + * bipolar wave shape, transitioning from a positive going portion to a roughly + * symmetrical negative going pulse. The point where the signal crosses zero represents + * the effective delay for the reference and return signals. *

    *

    * Process: *

    *
      - *
    1. Take a distance reading (there is no correlation record without at least - * one distance reading being taken)
    2. - *
    3. For as many points as you want to read from the record (max is 192) read - * the two byte signed correlation data point.
    4. + *
    5. Take a distance reading (there is no correlation record without at least one + * distance reading being taken)
    6. + *
    7. For as many points as you want to read from the record (max is 192) read the two + * byte signed correlation data point.
    8. *
    * * @param numberOfReadings The number of readings to take up to a maximum of 192 @@ -709,8 +700,7 @@ public void resetCorrelationData() { } /** - * Selects one of several preset configurations as per the Garmin Arduino - * library configure * function. * diff --git a/diozero-core/src/main/java/com/diozero/devices/HTS221.java b/diozero-core/src/main/java/com/diozero/devices/HTS221.java index e6a60201..08ae37f3 100644 --- a/diozero-core/src/main/java/com/diozero/devices/HTS221.java +++ b/diozero-core/src/main/java/com/diozero/devices/HTS221.java @@ -37,11 +37,12 @@ import com.diozero.api.I2CConstants; import com.diozero.api.I2CDevice; +import com.diozero.api.I2CDeviceInterface; import com.diozero.api.RuntimeIOException; /** - * STMicroelectronics HTS221 "ultra compact sensor for relative humidity and - * temperature". Datasheet: http://www2.st.com/content/ccc/resource/technical/document/datasheet/4d/9a/9c/ad/25/07/42/34/DM00116291.pdf/files/DM00116291.pdf/jcr:content/translations/en.DM00116291.pdf */ @SuppressWarnings("unused") @@ -62,9 +63,8 @@ public class HTS221 implements ThermometerInterface, HygrometerInterface { /** Control Register 3 (data ready output signal). */ private static final int CTRL_REG3 = 0x22; /** - * Status register; the content of this register is updated every one-shot - * reading, and after completion of every ODR cycle, regardless of BDU value in - * CTRL_REG1. + * Status register; the content of this register is updated every one-shot reading, and + * after completion of every ODR cycle, regardless of BDU value in CTRL_REG1. */ private static final int STATUS_REG = 0x27; /** Humidity output registers (2s complement, signed short). */ @@ -94,15 +94,13 @@ public class HTS221 implements ThermometerInterface, HygrometerInterface { // Flags for Control Register 1 private static final byte CR1_PD_CONTROL_BIT = 7; /** - * The PD bit is used to turn on the device. The device is in power-down mode - * when PD = ?0? (default value after boot). The device is active when PD is set - * to ?1?. + * The PD bit is used to turn on the device. The device is in power-down mode when PD = + * ?0? (default value after boot). The device is active when PD is set to ?1?. */ private static final byte CR1_PD_CONTROL = (byte) (1 << CR1_PD_CONTROL_BIT); private static final byte CR1_BDU_BIT = 2; /** - * (0: continuous update; 1: output registers not updated until MSB and LSB - * reading) + * (0: continuous update; 1: output registers not updated until MSB and LSB reading) */ private static final byte CR1_BDU = 1 << CR1_BDU_BIT; private static final byte CR1_ODR_ONE_SHOT = 0b00; @@ -111,18 +109,17 @@ public class HTS221 implements ThermometerInterface, HygrometerInterface { private static final byte CR1_ODR_12_5HZ = 0b11; /* - * Flags for Status Register [7:2] Reserved [1] H_DA: Humidity data available. - * Default value: 0 (0: new data for humidity is not yet available; 1: new data - * for humidity is available) [0] T_DA: Temperature data available. Default - * value: 0 (0: new data for temperature is not yet available; 1: new data for - * temperature is available) + * Flags for Status Register [7:2] Reserved [1] H_DA: Humidity data available. Default + * value: 0 (0: new data for humidity is not yet available; 1: new data for humidity is + * available) [0] T_DA: Temperature data available. Default value: 0 (0: new data for + * temperature is not yet available; 1: new data for temperature is available) */ private static final byte SR_H_DA_BIT = 1; private static final byte SR_H_DA = 1 << SR_H_DA_BIT; private static final byte SR_T_DA_BIT = 0; private static final byte SR_T_DA = 1 << SR_T_DA_BIT; - private I2CDevice device; + private I2CDeviceInterface device; private float h0Rh; private float h1Rh; private short h0T0Out; diff --git a/diozero-core/src/main/java/com/diozero/devices/LM73.java b/diozero-core/src/main/java/com/diozero/devices/LM73.java index 893aa993..fcd758b7 100644 --- a/diozero-core/src/main/java/com/diozero/devices/LM73.java +++ b/diozero-core/src/main/java/com/diozero/devices/LM73.java @@ -34,45 +34,41 @@ import org.tinylog.Logger; import com.diozero.api.I2CDevice; +import com.diozero.api.I2CDeviceInterface; import com.diozero.api.RuntimeIOException; import com.diozero.util.BitManipulation; public class LM73 implements ThermometerInterface { public static enum Configuration { - LM73_0_ADDRESS_PIN_FLOAT(0x48), - LM73_0_ADDRESS_PIN_GROUND(0x49), - LM73_0_ADDRESS_PIN_VDD(0x4a), - LM73_1_ADDRESS_PIN_FLOAT(0x4c), - LM73_1_ADDRESS_PIN_GROUND(0x4d), - LM73_1_ADDRESS_PIN_VDD(0x4e); - + LM73_0_ADDRESS_PIN_FLOAT(0x48), LM73_0_ADDRESS_PIN_GROUND(0x49), LM73_0_ADDRESS_PIN_VDD(0x4a), + LM73_1_ADDRESS_PIN_FLOAT(0x4c), LM73_1_ADDRESS_PIN_GROUND(0x4d), LM73_1_ADDRESS_PIN_VDD(0x4e); + private int address; + private Configuration(int address) { this.address = address; } - + public int getAddress() { return address; } } - + // Temperature resolutions public static enum Resolution { - RES_11_BIT(0b00), - RES_12_BIT(0b01), - RES_13_BIT(0b10), - RES_14_BIT(0b11); - + RES_11_BIT(0b00), RES_12_BIT(0b01), RES_13_BIT(0b10), RES_14_BIT(0b11); + private static final byte CLEAR_MASK = (byte) 0b10011111; private byte mask; + private Resolution(int value) { this.mask = (byte) (value << 5); } - + public byte getMask() { return mask; } - + public byte getValue(byte currentValue) { return (byte) ((currentValue &= CLEAR_MASK) | mask); } @@ -85,7 +81,7 @@ public byte getValue(byte currentValue) { private static final int LOWER_LIMIT_TEMP_REG = 0b011; private static final int CTRL_STATUS_REG = 0b100; private static final int ID_REG = 0b111; - + // Control/Status register bits private static final byte CONTROL_DATA_AVAILABLE_BIT = 0; private static final byte TEMP_LOW_BIT = 1; @@ -93,7 +89,7 @@ public byte getValue(byte currentValue) { private static final byte ALERT_STATUS_BIT = 3; private static final byte TIMEOUT_DISABLE_BIT = 7; - //private static final byte LM73_BIT_STATUS = 0x0F; + // private static final byte LM73_BIT_STATUS = 0x0F; // Configuration register bits private static final byte ONE_SHOT_BIT = 2; @@ -101,158 +97,158 @@ public byte getValue(byte currentValue) { private static final byte ALERT_POLARITY_BIT = 4; private static final byte ALERT_ENABLE_BIT = 5; private static final byte POWER_DOWN_BIT = 7; - + private static final int LM73_ID = 0x190; // p19 states that the reset state is 0x08 private static final Resolution DEFAULT_RESOLUTION = Resolution.RES_11_BIT; private static final float RANGE = 128f; - private I2CDevice device; + private I2CDeviceInterface device; private Configuration config; private Resolution resolution; - + public LM73(int controller, Configuration config) { this.config = config; resolution = DEFAULT_RESOLUTION; - + device = I2CDevice.builder(config.getAddress()).setController(controller).build(); int id = device.readUShort(ID_REG); if (id != LM73_ID) { Logger.warn("Expected device id 0x{}, got 0x{}", Integer.toHexString(LM73_ID), Integer.toHexString(id)); } } - + @Override public void close() { device.close(); } - + public Configuration getConfiguration() { return config; } - + public Resolution getResolution() { return resolution; } - + public void setResolution(Resolution resolution) { byte value = device.readByteData(CTRL_STATUS_REG); device.writeByteData(CTRL_STATUS_REG, resolution.getValue(value)); } - + public void setPower(boolean on) { device.writeBit(CONFIG_REG, POWER_DOWN_BIT, !on); // TODO Wait for the specified maximum conversion time } - + public boolean isDataAvailable() { return BitManipulation.isBitSet(device.readByteData(CTRL_STATUS_REG), CONTROL_DATA_AVAILABLE_BIT); } - + @Override public float getTemperature() throws RuntimeIOException { return device.readShort(TEMPERATURE_REG) / RANGE; } - + public float oneShotRead() { // Assumes the device is powered down device.writeBit(CONFIG_REG, ONE_SHOT_BIT, true); - while (! isDataAvailable()) { + while (!isDataAvailable()) { // TODO Wait the required number of ms with a timeout } return getTemperature(); } - + public static void main(String[] args) { // FIXME Remove this temperature conversion test code short raw; float expected, actual; float range = 128f; - + raw = 0x4b00; expected = 150; actual = raw / range; System.out.format("raw: 0x%02x, expected: %.5f, actual: %.5f%n", Integer.valueOf(raw & 0xffff), Float.valueOf(expected), Float.valueOf(actual)); - + raw = 0x0c80; expected = 25; actual = raw / range; System.out.format("raw: 0x%02x, expected: %.5f, actual: %.5f%n", Integer.valueOf(raw & 0xffff), Float.valueOf(expected), Float.valueOf(actual)); - + raw = 0x0080; expected = 1; actual = raw / range; System.out.format("raw: 0x%02x, expected: %.5f, actual: %.5f%n", Integer.valueOf(raw & 0xffff), Float.valueOf(expected), Float.valueOf(actual)); - + raw = 0x0020; expected = 0.25f; actual = raw / range; System.out.format("raw: 0x%02x, expected: %.5f, actual: %.5f%n", Integer.valueOf(raw & 0xffff), Float.valueOf(expected), Float.valueOf(actual)); - + raw = 0x0010; expected = 0.125f; actual = raw / range; System.out.format("raw: 0x%02x, expected: %.5f, actual: %.5f%n", Integer.valueOf(raw & 0xffff), Float.valueOf(expected), Float.valueOf(actual)); - + raw = 0x0008; expected = 0.0625f; actual = raw / range; System.out.format("raw: 0x%02x, expected: %.5f, actual: %.5f%n", Integer.valueOf(raw & 0xffff), Float.valueOf(expected), Float.valueOf(actual)); - + raw = 0x0004; expected = 0.03125f; actual = raw / range; System.out.format("raw: 0x%02x, expected: %.5f, actual: %.5f%n", Integer.valueOf(raw & 0xffff), Float.valueOf(expected), Float.valueOf(actual)); - + raw = 0x0000; expected = 0; actual = raw / range; System.out.format("raw: 0x%02x, expected: %.5f, actual: %.5f%n", Integer.valueOf(raw & 0xffff), Float.valueOf(expected), Float.valueOf(actual)); - + raw = (short) 0xfffc; expected = -0.03125f; actual = raw / range; System.out.format("raw: 0x%02x, expected: %.5f, actual: %.5f%n", Integer.valueOf(raw & 0xffff), Float.valueOf(expected), Float.valueOf(actual)); - + raw = (short) 0xfff8; expected = -0.0625f; actual = raw / range; System.out.format("raw: 0x%02x, expected: %.5f, actual: %.5f%n", Integer.valueOf(raw & 0xffff), Float.valueOf(expected), Float.valueOf(actual)); - + raw = (short) 0xfff0; expected = -0.125f; actual = raw / range; System.out.format("raw: 0x%02x, expected: %.5f, actual: %.5f%n", Integer.valueOf(raw & 0xffff), Float.valueOf(expected), Float.valueOf(actual)); - + raw = (short) 0xffe0; expected = -0.25f; actual = raw / range; System.out.format("raw: 0x%02x, expected: %.5f, actual: %.5f%n", Integer.valueOf(raw & 0xffff), Float.valueOf(expected), Float.valueOf(actual)); - + raw = (short) 0xff80; expected = -1f; actual = raw / range; System.out.format("raw: 0x%02x, expected: %.5f, actual: %.5f%n", Integer.valueOf(raw & 0xffff), Float.valueOf(expected), Float.valueOf(actual)); - + raw = (short) 0xf380; expected = -25; actual = raw / range; System.out.format("raw: 0x%02x, expected: %.5f, actual: %.5f%n", Integer.valueOf(raw & 0xffff), Float.valueOf(expected), Float.valueOf(actual)); - + raw = (short) 0xec00; expected = -40; actual = raw / range; diff --git a/diozero-core/src/main/java/com/diozero/devices/LPS25H.java b/diozero-core/src/main/java/com/diozero/devices/LPS25H.java index cb1eb212..5144c681 100644 --- a/diozero-core/src/main/java/com/diozero/devices/LPS25H.java +++ b/diozero-core/src/main/java/com/diozero/devices/LPS25H.java @@ -31,34 +31,36 @@ * #L% */ - import java.nio.ByteOrder; import org.tinylog.Logger; import com.diozero.api.I2CConstants; import com.diozero.api.I2CDevice; +import com.diozero.api.I2CDeviceInterface; /** - * STMicroelectronics LPS25H "ultra compact absolute piezoresistive pressure sensor". Datasheet: + * STMicroelectronics LPS25H "ultra compact absolute piezoresistive pressure sensor". + * Datasheet: * http://www2.st.com/content/ccc/resource/technical/document/datasheet/58/d2/33/a4/42/89/42/0b/DM00066332.pdf/files/DM00066332.pdf/jcr:content/translations/en.DM00066332.pdf * Example implementation: * https://github.com/richards-tech/RTIMULib/blob/master/RTIMULib/IMUDrivers/RTPressureLPS25H.cpp - * Eclipse Kura implementation: https://github.com/eclipse/kura/tree/develop/kura/examples/org.eclipse.kura.raspberrypi.sensehat/src/main/java/org/eclipse/kura + * Eclipse Kura implementation: + * https://github.com/eclipse/kura/tree/develop/kura/examples/org.eclipse.kura.raspberrypi.sensehat/src/main/java/org/eclipse/kura */ @SuppressWarnings("unused") public class LPS25H implements ThermometerInterface, BarometerInterface { private static final double PRESSURE_SCALE = 4096; - - // LPS25H I2C Slave Addresses + + // LPS25H I2C Slave Addresses private static final int DEFAULT_DEVICE_ADDRESS0 = 0x5c; private static final int DEFAULT_DEVICE_ADDRESS1 = 0x5d; private static final int REG_ID = 0x0f; private static final int ID = 0xbd; /** Set to 1 to read, 0 to write. */ private static final int READ = 0x80; - - // Register map + + // Register map /** Reference pressure, 2s complement, 3-byte signed integer. */ private static final int REF_P_XL = 0x08; private static final int REF_P_L = 0x09; @@ -77,7 +79,10 @@ public class LPS25H implements ThermometerInterface, BarometerInterface { private static final int INTERRUPT_CFG = 0x24; /** Interrupt Source. */ private static final int INT_SOURCE = 0x25; - /** Status register. This register is updated every ODR cycle, regardless of BDU value in CTRL_REG1. */ + /** + * Status register. This register is updated every ODR cycle, regardless of BDU value in + * CTRL_REG1. + */ private static final int STATUS_REG = 0x27; /** Pressure value, 2s complement, 3-byte signed integer. */ private static final int PRESS_OUT_XL = 0x28; @@ -96,8 +101,8 @@ public class LPS25H implements ThermometerInterface, BarometerInterface { /** Pressure offset, 2s-complement signed 2-byte integer. */ private static final int RPDS_L = 0x39; private static final int RPDS_H = 0x3a; - - /* + + /*- * Flags for pressure and temperature resolution configuration. * Bit: 3 2 1 0 * Use: AVGP1 AVGP0 AVGT1 AVGT0 @@ -120,8 +125,8 @@ public class LPS25H implements ThermometerInterface, BarometerInterface { private static final byte RC_TEMP_16_SAMPLES = 0b01; private static final byte RC_TEMP_32_SAMPLES = 0b10; private static final byte RC_TEMP_64_SAMPLES = 0b11; - - /* + + /*- * Flags for Control Register 1 * [7] PD: Power down control (0: power down mode, 1: active mode) * [6:4] ODR2, ODR1, ODR0: output data rate selection @@ -132,33 +137,41 @@ public class LPS25H implements ThermometerInterface, BarometerInterface { * [0] SIM: SPI Serial Interface Mode selection. (0: 4-wire interface; 1: 3-wire interface) */ private static final byte CR1_PD_CONTROL_BIT = 7; - /** The PD bit is used to turn on the device. The device is in power-down mode when - * PD = ?0? (default value after boot). The device is active when PD is set to ?1?. */ + /** + * The PD bit is used to turn on the device. The device is in power-down mode when PD = + * ?0? (default value after boot). The device is active when PD is set to ?1?. + */ private static final byte CR1_PD_CONTROL = (byte) (1 << CR1_PD_CONTROL_BIT); private static final byte CR1_ODR_ONE_SHOT = 0b000 << 4; - private static final byte CR1_ODR_1HZ = 0b001 << 4; - private static final byte CR1_ODR_7HZ = 0b010 << 4; - private static final byte CR1_ODR_12_5HZ = 0b011 << 4; - private static final byte CR1_ODR_25HZ = 0b100 << 4; + private static final byte CR1_ODR_1HZ = 0b001 << 4; + private static final byte CR1_ODR_7HZ = 0b010 << 4; + private static final byte CR1_ODR_12_5HZ = 0b011 << 4; + private static final byte CR1_ODR_25HZ = 0b100 << 4; private static final byte CR1_DIFF_EN_BIT = 3; - /** Used to enable the circuitry for the computing of differential pressure output. - * In default mode (DIFF_EN=?0?) the circuitry is turned off. It is suggested to turn - * on the circuitry only after the configuration of REF_P_x and THS_P_x. */ + /** + * Used to enable the circuitry for the computing of differential pressure output. In + * default mode (DIFF_EN=?0?) the circuitry is turned off. It is suggested to turn on the + * circuitry only after the configuration of REF_P_x and THS_P_x. + */ private static final byte CR1_DIFF_EN = 1 << CR1_DIFF_EN_BIT; private static final byte CR1_BDU_BIT = 2; /** (0: continuous update; 1: output registers not updated until MSB and LSB reading) */ private static final byte CR1_BDU = 1 << CR1_BDU_BIT; private static final byte CR1_RESET_AZ_BIT = 1; - /** Used to Reset AutoZero function. Reset REF_P reg (@0x08..0A) set pressure - * reference to default value RPDS reg(0x39/3A). RESET_AZ is self cleared. */ + /** + * Used to Reset AutoZero function. Reset REF_P reg (@0x08..0A) set pressure reference to + * default value RPDS reg(0x39/3A). RESET_AZ is self cleared. + */ private static final byte CR1_RESET_AZ = 1 << CR1_RESET_AZ_BIT; private static final byte CR1_SIM_BIT = 1; - /** Selects the SPI serial interface mode. + /*- + * Selects the SPI serial interface mode. * 0: (default value) 4-wire SPI interface mode selected. - * 1: 3-wire SPI interface mode selected. */ + * 1: 3-wire SPI interface mode selected. + */ private static final byte CR1_SIM = 1 << CR1_SIM_BIT; - - /* + + /*- * Flags for Control Register 2 * [7] BOOT: Reboot memory content. Default value: 0 * (0: normal mode; 1: reboot memory content) Self-clearing upon completion) @@ -193,8 +206,8 @@ public class LPS25H implements ThermometerInterface, BarometerInterface { private static final byte CR2_AUTOZERO_EN = (byte) (1 << CR2_AUTOZERO_EN_BIT); private static final byte CR2_ONESHOT_EN_BIT = 0; private static final byte CR2_ONESHOT_EN = (byte) (1 << CR2_ONESHOT_EN_BIT); - - /* + + /*- * Flags for Control Register 3 * [7] INT_H_L: Interrupt active high, low. Default value: 0 * (0: active high; 1: active low) @@ -208,8 +221,8 @@ public class LPS25H implements ThermometerInterface, BarometerInterface { * 1 0 Pressure low (P_low) * 1 1 Pressure low OR high */ - - /* + + /*- * Flags for Control Register 4 * [7:4] Reserved: keep these bits at 0 * [3] P1_EMPTY: Empty signal on INT1 pin @@ -217,8 +230,8 @@ public class LPS25H implements ThermometerInterface, BarometerInterface { * [1] P1_OVERRUN: Overrun signal on INT1 pin * [0] P1_DRDY: Data ready signal on INT1 pin */ - - /* + + /*- * Flags for Interrupt Configuration * [7:3] RESERVED * [2] LIR: Latch Interrupt request into INT_SOURCE register. Default value: 0. @@ -230,8 +243,8 @@ public class LPS25H implements ThermometerInterface, BarometerInterface { * (0: disable interrupt request; * 1:enable interrupt request on measured differential pressure value higher than preset threshold) */ - - /* + + /*- * Flags for Interrupt Source * [7:3] Reserved: keep these bits at 0 * [2] IA: Interrupt Active. @@ -241,8 +254,8 @@ public class LPS25H implements ThermometerInterface, BarometerInterface { * [0] PH: Differential pressure High. * (0: no interrupt has been generated; 1: High differential pressure event has occurred) */ - - /* + + /*- * Flags for Status Register * [5] P_OR: Pressure data overrun. Default value: 0 * (0: no overrun has occurred; @@ -262,8 +275,8 @@ public class LPS25H implements ThermometerInterface, BarometerInterface { private static final byte SR_P_DA = 1 << SR_P_DA_BIT; private static final byte SR_T_DA_BIT = 0; private static final byte SR_T_DA = 1 << SR_T_DA_BIT; - - /* + + /*- * Flags for FIFO Control * [7:5] F_MODE2-0: FIFO mode selection. * [4:0] WTM_POINT4-0 : FIFO threshold watermark level setting. @@ -272,28 +285,28 @@ public class LPS25H implements ThermometerInterface, BarometerInterface { private static final byte FC_BYPASS_MODE = 0b000 << 5; /** FIFO MODE. Stops collecting data when full. */ private static final byte FC_FIFO_MODE = 0b001 << 5; - /** STREAM MODE: Keep the newest measurements in the FIFO. */ + /** STREAM MODE: Keep the newest measurements in the FIFO. */ private static final byte FC_STREAM_MODE = 0b010 << 5; /** STREAM MODE until trigger deasserted, then change to FIFO MODE. */ private static final byte FC_STREAM_THEN_FIFO_MODE = 0b011 << 5; /** BYPASS MODE until trigger deasserted, then change to STREAM MODE. */ private static final byte FC_BYPASS_THEN_STREAM_MODE = (byte) (0b100 << 5); - /** FIFO_MEAN MODE: FIFO is used to generate a running average filtered pressure. */ + /** FIFO_MEAN MODE: FIFO is used to generate a running average filtered pressure. */ private static final byte FC_FIFO_MEAN_MODE = (byte) (0b110 << 5); /** BYPASS mode until trigger deasserted, then change to FIFO MODE. */ private static final byte FC_BYPASS_THEN_FIFO_MODE = (byte) (0b111 << 5); /** 2 samples moving average. */ - private static final byte FC_WTM_2_SAMPLES = 0b00001; + private static final byte FC_WTM_2_SAMPLES = 0b00001; /** 4 samples moving average. */ - private static final byte FC_WTM_4_SAMPLES = 0b00011; + private static final byte FC_WTM_4_SAMPLES = 0b00011; /** 8 samples moving average. */ - private static final byte FC_WTM_8_SAMPLES = 0b00111; + private static final byte FC_WTM_8_SAMPLES = 0b00111; /** 16 samples moving average. */ private static final byte FC_WTM_16_SAMPLES = 0b01111; /** 32 samples moving average. */ private static final byte FC_WTM_32_SAMPLES = 0b11111; - - private I2CDevice device; + + private I2CDeviceInterface device; public LPS25H() { this(I2CConstants.CONTROLLER_1, DEFAULT_DEVICE_ADDRESS0); @@ -312,7 +325,7 @@ public LPS25H(int controller, int address) { // Enable the FIFO device.writeByteData(CTRL_REG2, CR2_FIFO_EN); } - + @Override public float getPressure() { byte status = device.readByteData(STATUS_REG); @@ -320,15 +333,15 @@ public float getPressure() { Logger.warn("Pressure data not available"); return -1; } - + byte[] raw_data = new byte[3]; device.readI2CBlockData(PRESS_OUT_XL | READ, raw_data); - + int raw_pressure = raw_data[2] << 16 | (raw_data[1] & 0xff) << 8 | (raw_data[0] & 0xff); - + return (float) (raw_pressure / PRESSURE_SCALE); } - + @Override public float getTemperature() { byte status = device.readByteData(STATUS_REG); @@ -336,9 +349,9 @@ public float getTemperature() { Logger.warn("Temperature data not available"); return -1; } - + short raw_temp = device.readShort(TEMP_OUT_L | READ); - + return (float) (raw_temp / 480.0 + 42.5); } diff --git a/diozero-core/src/main/java/com/diozero/devices/MCP23008.java b/diozero-core/src/main/java/com/diozero/devices/MCP23008.java index 301482e8..42f28f60 100644 --- a/diozero-core/src/main/java/com/diozero/devices/MCP23008.java +++ b/diozero-core/src/main/java/com/diozero/devices/MCP23008.java @@ -33,6 +33,7 @@ import com.diozero.api.I2CConstants; import com.diozero.api.I2CDevice; +import com.diozero.api.I2CDeviceInterface; import com.diozero.api.RuntimeIOException; import com.diozero.devices.mcp23xxx.MCP23x08; @@ -41,7 +42,7 @@ public class MCP23008 extends MCP23x08 { public static final int DEVICE_ADDRESS = 0x20; private static final String DEVICE_NAME = "MCP23008"; - private I2CDevice device; + private I2CDeviceInterface device; public MCP23008() throws RuntimeIOException { this(I2CConstants.CONTROLLER_1, DEVICE_ADDRESS, INTERRUPT_GPIO_NOT_SET, INTERRUPT_GPIO_NOT_SET); @@ -61,12 +62,12 @@ public MCP23008(int controller, int address, int interruptGpio) throws RuntimeIO public MCP23008(int controller, int address, int interruptGpioA, int interruptGpioB) throws RuntimeIOException { super(DEVICE_NAME + "-" + controller + "-" + address, interruptGpioA, interruptGpioB); - + device = I2CDevice.builder(address).setController(controller).build(); - + initialise(); } - + @Override public void close() throws RuntimeIOException { super.close(); diff --git a/diozero-core/src/main/java/com/diozero/devices/MCP23017.java b/diozero-core/src/main/java/com/diozero/devices/MCP23017.java index 21cd5c64..f71cf2fc 100644 --- a/diozero-core/src/main/java/com/diozero/devices/MCP23017.java +++ b/diozero-core/src/main/java/com/diozero/devices/MCP23017.java @@ -33,31 +33,41 @@ import com.diozero.api.I2CConstants; import com.diozero.api.I2CDevice; +import com.diozero.api.I2CDeviceInterface; import com.diozero.api.RuntimeIOException; import com.diozero.devices.mcp23xxx.MCP23x17; /** - * Datasheet: http://ww1.microchip.com/downloads/en/DeviceDoc/21952b.pdf. - *

    The MCP23X17 consists of multiple 8-bit configuration registers for input, output and polarity selection. The - * system master can enable the I/Os as either inputs or outputs by writing the I/O configuration bits (IODIRA/B). - * The data for each input or output is kept in the corresponding input or output register. The polarity of - * the Input Port register can be inverted with the Polarity Inversion register. All registers can be read by the - * system master.

    - *

    The 16-bit I/O port functionally consists of two 8-bit ports (PORTA and PORTB). The MCP23X17 can be - * configured to operate in the 8-bit or 16-bit modes via IOCON.BANK.

    - *

    There are two interrupt GPIOs, INTA and INTB, that can be associated with their respective ports, or can be - * logically OR'ed together so that both GPIOs will activate if either port causes an interrupt. - * A special mode (Byte mode with IOCON.BANK = 0) causes the address pointer to toggle between - * associated A/B register pairs. For example, if the BANK bit is cleared and the Address Pointer is initially set - * to address 12h (GPIOA) or 13h (GPIOB), the pointer will toggle between GPIOA and GPIOB. Note that the - * Address Pointer can initially point to either address in the register pair.

    + * Datasheet: http://ww1.microchip.com/downloads/en/DeviceDoc/21952b.pdf. + *

    + * The MCP23X17 consists of multiple 8-bit configuration registers for input, output and + * polarity selection. The system master can enable the I/Os as either inputs or outputs + * by writing the I/O configuration bits (IODIRA/B). The data for each input or output is + * kept in the corresponding input or output register. The polarity of the Input Port + * register can be inverted with the Polarity Inversion register. All registers can be + * read by the system master. + *

    + *

    + * The 16-bit I/O port functionally consists of two 8-bit ports (PORTA and PORTB). The + * MCP23X17 can be configured to operate in the 8-bit or 16-bit modes via IOCON.BANK. + *

    + *

    + * There are two interrupt GPIOs, INTA and INTB, that can be associated with their + * respective ports, or can be logically OR'ed together so that both GPIOs will activate + * if either port causes an interrupt. A special mode (Byte mode with IOCON.BANK = 0) + * causes the address pointer to toggle between associated A/B register pairs. For + * example, if the BANK bit is cleared and the Address Pointer is initially set to address + * 12h (GPIOA) or 13h (GPIOB), the pointer will toggle between GPIOA and GPIOB. Note that + * the Address Pointer can initially point to either address in the register pair. + *

    */ public class MCP23017 extends MCP23x17 { // Default I2C address public static final int DEVICE_ADDRESS = 0x20; private static final String DEVICE_NAME = "MCP23017"; - private I2CDevice device; + private I2CDeviceInterface device; public MCP23017() throws RuntimeIOException { this(I2CConstants.CONTROLLER_1, DEVICE_ADDRESS, INTERRUPT_GPIO_NOT_SET, INTERRUPT_GPIO_NOT_SET); @@ -77,23 +87,23 @@ public MCP23017(int controller, int address, int interruptGpio) throws RuntimeIO public MCP23017(int controller, int address, int interruptGpioA, int interruptGpioB) throws RuntimeIOException { super(DEVICE_NAME + "-" + controller + "-" + address, interruptGpioA, interruptGpioB); - + device = I2CDevice.builder(address).setController(controller).build(); - + initialise(); } - + @Override public void close() throws RuntimeIOException { super.close(); device.close(); } - + @Override protected byte readByte(int register) { return device.readByteData(register); } - + @Override protected void writeByte(int register, byte value) { device.writeByteData(register, value); diff --git a/diozero-core/src/main/java/com/diozero/devices/MCP23S17.java b/diozero-core/src/main/java/com/diozero/devices/MCP23S17.java index 17258370..61c6ff09 100644 --- a/diozero-core/src/main/java/com/diozero/devices/MCP23S17.java +++ b/diozero-core/src/main/java/com/diozero/devices/MCP23S17.java @@ -35,6 +35,7 @@ import com.diozero.api.SpiConstants; import com.diozero.api.SpiDevice; +import com.diozero.api.SpiDeviceInterface; import com.diozero.devices.mcp23xxx.MCP23x17; /** @@ -44,7 +45,7 @@ public class MCP23S17 extends MCP23x17 { // From P8 of the datasheet, 5MHz for 1.8V – 5.5V and 10MHz for 2.7V – 5.5V public static final int MAX_CLOCK_SPEED = 10_000_000; public static final int DEFAULT_CLOCK_SPEED = SpiConstants.DEFAULT_SPI_CLOCK_FREQUENCY; - + // SPI Address Register 0b[0 1 0 0 A2 A1 A0 R/W] private static final byte ADDRESS_MASK = 0b01000000; // 0x40 [0100 0000] [A2 = 0 | A1 = 0 | A0 = 0] // private static final byte DEFAULT_ADDRESS = 0b00; // [A2 = 0 | A1 = 0 | A0 = @@ -53,27 +54,26 @@ public class MCP23S17 extends MCP23x17 { private static final byte READ_FLAG = 0b00000001; // 0x01 private static final String DEVICE_NAME = "MCP23S17"; - private SpiDevice device; + private SpiDeviceInterface device; private byte boardAddress; public MCP23S17(int boardAddress) throws RuntimeIOException { - this(SpiConstants.DEFAULT_SPI_CONTROLLER, SpiConstants.CE0, boardAddress, - DEFAULT_CLOCK_SPEED, INTERRUPT_GPIO_NOT_SET, INTERRUPT_GPIO_NOT_SET); + this(SpiConstants.DEFAULT_SPI_CONTROLLER, SpiConstants.CE0, boardAddress, DEFAULT_CLOCK_SPEED, + INTERRUPT_GPIO_NOT_SET, INTERRUPT_GPIO_NOT_SET); } public MCP23S17(int boardAddress, int interruptGpio) throws RuntimeIOException { - this(SpiConstants.DEFAULT_SPI_CONTROLLER, SpiConstants.CE0, boardAddress, - DEFAULT_CLOCK_SPEED, interruptGpio, interruptGpio); + this(SpiConstants.DEFAULT_SPI_CONTROLLER, SpiConstants.CE0, boardAddress, DEFAULT_CLOCK_SPEED, interruptGpio, + interruptGpio); } public MCP23S17(int boardAddress, int interruptGpioA, int interruptGpioB) throws RuntimeIOException { - this(SpiConstants.DEFAULT_SPI_CONTROLLER, SpiConstants.CE0, boardAddress, - DEFAULT_CLOCK_SPEED, interruptGpioA, interruptGpioB); + this(SpiConstants.DEFAULT_SPI_CONTROLLER, SpiConstants.CE0, boardAddress, DEFAULT_CLOCK_SPEED, interruptGpioA, + interruptGpioB); } public MCP23S17(int controller, int chipSelect, int boardAddress, int interruptGpio) throws RuntimeIOException { - this(controller, chipSelect, boardAddress, DEFAULT_CLOCK_SPEED, interruptGpio, - interruptGpio); + this(controller, chipSelect, boardAddress, DEFAULT_CLOCK_SPEED, interruptGpio, interruptGpio); } public MCP23S17(int controller, int chipSelect, int address, int frequency, int interruptGpioA, int interruptGpioB) diff --git a/diozero-core/src/main/java/com/diozero/devices/MFRC522.java b/diozero-core/src/main/java/com/diozero/devices/MFRC522.java index 0605a133..37feaa97 100644 --- a/diozero-core/src/main/java/com/diozero/devices/MFRC522.java +++ b/diozero-core/src/main/java/com/diozero/devices/MFRC522.java @@ -41,15 +41,14 @@ import com.diozero.api.DigitalOutputDevice; import com.diozero.api.SpiConstants; import com.diozero.api.SpiDevice; +import com.diozero.api.SpiDeviceInterface; import com.diozero.util.Hex; import com.diozero.util.SleepUtil; /** *

    - * Datasheet
    - * Example + * Datasheet
    + * Example * Python code
    * MiFare Classic Universal toolKit * (MFCUK)
    @@ -70,10 +69,10 @@ *

* *

- * Java port from MFRC522 - * Library to use ARDUINO RFID MODULE KIT 13.56 MHZ WITH TAGS SPI W AND R BY - * COOQROBOT that was created by Miguel Balboa (circuitito.com). + * Java port from + * MFRC522 + * Library to use ARDUINO RFID MODULE KIT 13.56 MHZ WITH TAGS SPI W AND R BY COOQROBOT + * that was created by Miguel Balboa (circuitito.com). *

* *

@@ -81,22 +80,20 @@ *

*
    *
  1. The controller, e.g. Arduino, Raspberry Pi
  2. - *
  3. The PCD (Proximity C oupling Device), e.g. NXP MFRC522 Contactless - * Reader
  4. - *
  5. The PICC (Proximity Integrated Circuit Card): A card or tag using the ISO - * 14443A interface, e.g. Mifare or NTAG203.
  6. + *
  7. The PCD (Proximity C oupling Device), e.g. NXP MFRC522 Contactless Reader
  8. + *
  9. The PICC (Proximity Integrated Circuit Card): A card or tag using the ISO 14443A + * interface, e.g. Mifare or NTAG203.
  10. *
* *

- * The microcontroller and card reader uses SPI for communication. The protocol - * is described in the - * MFRC522 + * The microcontroller and card reader uses SPI for communication. The protocol is + * described in the MFRC522 * datasheet. *

* *

- * The card reader and the tags communicate using a 13.56MHz electromagnetic - * field. The protocol is defined in http://wg8.de/wg8n1496_17n3613_Ballot_FCD14443-3.pdf: *

*
    @@ -110,10 +107,9 @@ *

    * If only the PICC UID is wanted, the above documents have all the information * needed.
    - * To read and write from MIFARE PICCs, the MIFARE protocol is used after the - * PICC has been selected.
    - * The MIFARE Classic and Ultralight chips and protocols are described in the - * datasheets: + * To read and write from MIFARE PICCs, the MIFARE protocol is used after the PICC has + * been selected.
    + * The MIFARE Classic and Ultralight chips and protocols are described in the datasheets: *

    * * @@ -133,8 +127,7 @@ * Has 16 sectors * 4 blocks/sector * 16 bytes/block = 1024 bytes.
    * The blocks are numbered 0-63.
    * Block 3 in each sector is the Sector Trailer. See - * sections 8.6 and - * 8.7: + * sections 8.6 and 8.7: *

    * *
    @@ -152,23 +145,21 @@
      * UID     |BCC|SAK|ATAQ|Manufacturer data
      * 
    *

    - * To access a block, an authentication using a key from the block's sector must - * be performed first.
    - * Example: To read from block 10, first authenticate using a key from sector 3 - * (blocks 8-11).
    + * To access a block, an authentication using a key from the block's sector must be + * performed first.
    + * Example: To read from block 10, first authenticate using a key from sector 3 (blocks + * 8-11).
    * All keys are set to FFFFFFFFFFFFh at chip delivery.
    - * Warning: Please read section 8.7 "Memory Access". It includes this - * text: if the PICC detects a format violation the whole sector is irreversibly - * blocked.
    - * To use a block in "value block" mode (for Increment/Decrement operations) you - * need to change the sector trailer. Use setAccessBits() to calculate the bit - * patterns. + * Warning: Please read section 8.7 "Memory Access". It includes this text: if + * the PICC detects a format violation the whole sector is irreversibly blocked.
    + * To use a block in "value block" mode (for Increment/Decrement operations) you need to + * change the sector trailer. Use setAccessBits() to calculate the bit patterns. *

    * *

    MIFARE Classic 4K (MF1S703x)

    *

    - * Has (32 sectors * 4 blocks/sector + 8 sectors * 16 blocks/sector) * 16 - * bytes/block = 4096 bytes.
    + * Has (32 sectors * 4 blocks/sector + 8 sectors * 16 blocks/sector) * 16 bytes/block = + * 4096 bytes.
    * The blocks are numbered 0-255.
    * The last block in each sector is the Sector Trailer like above. *

    @@ -184,11 +175,10 @@ *

    * Has 16 pages of 4 bytes = 64 bytes.
    * Pages 0 + 1 is used for the 7-byte UID.
    - * Page 2 contains the last check digit for the UID, one byte manufacturer - * internal data, and the lock bytes (see - * http://www.nxp.com/documents/data_sheet/MF0ICU1.pdf section 8.5.2).
    - * Page 3 is OTP, One Time Programmable bits. Once set to 1 they cannot revert - * to 0.
    + * Page 2 contains the last check digit for the UID, one byte manufacturer internal data, + * and the lock bytes (see http://www.nxp.com/documents/data_sheet/MF0ICU1.pdf section + * 8.5.2).
    + * Page 3 is OTP, One Time Programmable bits. Once set to 1 they cannot revert to 0.
    * Pages 4-15 are read/write unless blocked by the lock bytes in page 2. *

    * @@ -196,11 +186,10 @@ *

    * Has 48 pages of 4 bytes = 192 bytes.
    * Pages 0 + 1 is used for the 7-byte UID.
    - * Page 2 contains the last check digit for the UID, one byte manufacturer - * internal data, and the lock bytes (see - * http://www.nxp.com/documents/data_sheet/MF0ICU1.pdf section 8.5.2).
    - * Page 3 is OTP, One Time Programmable bits. Once set to 1 they cannot revert - * to 0.
    + * Page 2 contains the last check digit for the UID, one byte manufacturer internal data, + * and the lock bytes (see http://www.nxp.com/documents/data_sheet/MF0ICU1.pdf section + * 8.5.2).
    + * Page 3 is OTP, One Time Programmable bits. Once set to 1 they cannot revert to 0.
    * Pages 4-39 are read/write unless blocked by the lock bytes in page 2.
    * Page 40 Lock bytes
    * Page 41 16 bit one way counter
    @@ -241,14 +230,14 @@ *

      *
    1. Call ISO_Request() to check to see if a tag is in range and if so get its * ATQA.
    2. - *
    3. Upon success call ISO_Anticollision() which returns the UID of the active - * tag in range.
    4. - *
    5. Upon success call ISO_Select(UID) which selects the active tag in range - * by its UID and returns its SAK.
    6. - *
    7. If the card needs authentication call ISO_Authenticate(blockAddr, keyId, - * key, UID) to authenticate access to a block.
    8. - *
    9. Call ISO_StopCrypto() when you have finished talking to a card which - * requires authentication.
    10. + *
    11. Upon success call ISO_Anticollision() which returns the UID of the active tag in + * range.
    12. + *
    13. Upon success call ISO_Select(UID) which selects the active tag in range by its UID + * and returns its SAK.
    14. + *
    15. If the card needs authentication call ISO_Authenticate(blockAddr, keyId, key, UID) + * to authenticate access to a block.
    16. + *
    17. Call ISO_StopCrypto() when you have finished talking to a card which requires + * authentication.
    18. *
    */ public class MFRC522 implements DeviceInterface { @@ -308,7 +297,7 @@ public class MFRC522 implements DeviceInterface { private static final int SPI_CLOCK_FREQUENCY = 1_000_000; - private final SpiDevice device; + private final SpiDeviceInterface device; private final DigitalOutputDevice resetPin; private boolean logReadsAndWrites = false; @@ -562,11 +551,11 @@ public void init(AntennaGain antennaGain) { /*- writeRegister(T_MODE_REG, (byte) 0x8D); // Tauto=1; f(Timer) = 6.78MHz/TPreScaler writeRegister(T_PRESCALER_REG, (byte) 0x3E); // TModeReg[3..0] + TPrescalerReg - + // 30 writeRegister(T_RELOAD_REG_MSB, (byte) 0); writeRegister(T_RELOAD_REG_LSB, (byte) 0x1E); - + writeRegister(TX_ASK_REG, (byte) 0x40); // 100%ASK writeRegister(MODE_REG, (byte) 0x3D); // CRC Initial value 0x6363 ??? */ @@ -627,8 +616,8 @@ private void reset() { } /** - * Open antennas, each time you start or shut down the natural barrier between - * the transmitter should be at least 1ms interval + * Open antennas, each time you start or shut down the natural barrier between the + * transmitter should be at least 1ms interval * * @param on on/off value */ @@ -644,10 +633,9 @@ public void setAntennaOn(boolean on) { } /** - * Get the current MFRC522 Receiver Gain (RxGain[2:0]) value. See 9.3.3.6 / - * table 98 in http://www.nxp.com/documents/data_sheet/MFRC522.pdf NOTE: Return - * value scrubbed with (0x07<<4)=01110000b as RCFfgReg may use reserved - * bits. + * Get the current MFRC522 Receiver Gain (RxGain[2:0]) value. See 9.3.3.6 / table 98 in + * http://www.nxp.com/documents/data_sheet/MFRC522.pdf NOTE: Return value scrubbed with + * (0x07<<4)=01110000b as RCFfgReg may use reserved bits. * * @return Value of the RxGain, scrubbed to the 3 bits used. */ @@ -656,10 +644,9 @@ public AntennaGain getAntennaGain() { } /** - * Set the MFRC522 Receiver Gain (RxGain) to value specified by given mask. See - * 9.3.3.6 / table 98 in https://www.nxp.com/docs/en/data-sheet/MFRC522.pdf - * NOTE: Given mask is scrubbed with (0x07<<4)=01110000b as RCFfgReg may - * use reserved bits. + * Set the MFRC522 Receiver Gain (RxGain) to value specified by given mask. See 9.3.3.6 / + * table 98 in https://www.nxp.com/docs/en/data-sheet/MFRC522.pdf NOTE: Given mask is + * scrubbed with (0x07<<4)=01110000b as RCFfgReg may use reserved bits. * * @param gain New antenna gain value */ @@ -681,8 +668,7 @@ public void setAntennaGain(AntennaGain gain) { * Performs a self-test of the MFRC522 See 16.1.1 in * http://www.nxp.com/documents/data_sheet/MFRC522.pdf * - * @return Whether or not the test passed. Or false if no firmware reference is - * available. + * @return Whether or not the test passed. Or false if no firmware reference is available. */ public boolean performSelfTest() { Logger.debug("Self test - START"); @@ -779,8 +765,8 @@ public int getVersion() { ///////////////////////////////////////////////////////////////////////////////////// /** - * Executes the Transceive command. CRC validation can only be done if backData - * and backLen are specified. + * Executes the Transceive command. CRC validation can only be done if backData and + * backLen are specified. * * @param sendData Pointer to the data to transfer to the FIFO. * @return STATUS_OK on success, STATUS_??? otherwise. @@ -790,12 +776,12 @@ private Response transceiveData(byte[] sendData) { } /** - * Executes the Transceive command. CRC validation can only be done if backData - * and backLen are specified. + * Executes the Transceive command. CRC validation can only be done if backData and + * backLen are specified. * * @param sendData Pointer to the data to transfer to the FIFO. - * @param rxAlign Defines the bit position in backData[0] for the first bit - * received. Default 0. + * @param rxAlign Defines the bit position in backData[0] for the first bit received. + * Default 0. * @return STATUS_OK on success, STATUS_??? otherwise. */ private Response transceiveData(byte[] sendData, byte rxAlign) { @@ -803,14 +789,13 @@ private Response transceiveData(byte[] sendData, byte rxAlign) { } /** - * Executes the Transceive command. CRC validation can only be done if backData - * and backLen are specified. + * Executes the Transceive command. CRC validation can only be done if backData and + * backLen are specified. * * @param sendData Pointer to the data to transfer to the FIFO. - * @param validBits The number of valid bits in the last byte. 0 for 8 valid - * bits - * @param rxAlign Defines the bit position in backData[0] for the first bit - * received. Default 0. + * @param validBits The number of valid bits in the last byte. 0 for 8 valid bits + * @param rxAlign Defines the bit position in backData[0] for the first bit received. + * Default 0. * @return STATUS_OK on success, STATUS_??? otherwise. */ private Response transceiveData(byte[] sendData, byte validBits, byte rxAlign) { @@ -818,16 +803,15 @@ private Response transceiveData(byte[] sendData, byte validBits, byte rxAlign) { } /** - * Executes the Transceive command. CRC validation can only be done if backData - * and backLen are specified. + * Executes the Transceive command. CRC validation can only be done if backData and + * backLen are specified. * * @param sendData Pointer to the data to transfer to the FIFO. - * @param validBits The number of valid bits in the last byte. 0 for 8 valid - * bits - * @param rxAlign Defines the bit position in backData[0] for the first bit - * received. Default 0. - * @param checkCRC True => The last two bytes of the response is assumed to be - * a CRC_A that must be validated. + * @param validBits The number of valid bits in the last byte. 0 for 8 valid bits + * @param rxAlign Defines the bit position in backData[0] for the first bit received. + * Default 0. + * @param checkCRC True => The last two bytes of the response is assumed to be a CRC_A + * that must be validated. * @return STATUS_OK on success, STATUS_??? otherwise. */ private Response transceiveData(byte[] sendData, byte validBits, byte rxAlign, boolean checkCRC) { @@ -844,20 +828,19 @@ private Response communicateWithPICC(PcdCommand command, byte waitIRq, byte[] se } /** - * Transfers data to the MFRC522 FIFO, executes a command, waits for completion - * and transfers data back from the FIFO. CRC validation can only be done if - * backData and backLen are specified. + * Transfers data to the MFRC522 FIFO, executes a command, waits for completion and + * transfers data back from the FIFO. CRC validation can only be done if backData and + * backLen are specified. * * @param command The command to execute. One of the PCD_Command enums. - * @param waitIRq The bits in the ComIrqReg register that signals successful - * completion of the command. + * @param waitIRq The bits in the ComIrqReg register that signals successful completion + * of the command. * @param sendData Data to transfer to the FIFO. - * @param validBits The number of valid bits in the last byte. 0 for 8 valid - * bits. - * @param rxAlign Defines the bit position in backData[0] for the first bit - * received. Default 0. - * @param checkCRC True => The last two bytes of the response is assumed to be - * a CRC_A that must be validated. + * @param validBits The number of valid bits in the last byte. 0 for 8 valid bits. + * @param rxAlign Defines the bit position in backData[0] for the first bit received. + * Default 0. + * @param checkCRC True => The last two bytes of the response is assumed to be a CRC_A + * that must be validated. * @return response */ private Response communicateWithPICC(PcdCommand command, byte waitIRq, byte[] sendData, byte validBits, @@ -979,10 +962,9 @@ private Response communicateWithPICC(PcdCommand command, byte waitIRq, byte[] se } /** - * Transmits a REQuest command, Type A. Invites PICCs in state IDLE to go to - * READY and prepare for anticollision or selection. 7 bit frame. Beware: When - * two PICCs are in the field at the same time I often get STATUS_TIMEOUT - - * probably due do bad antenna design. + * Transmits a REQuest command, Type A. Invites PICCs in state IDLE to go to READY and + * prepare for anticollision or selection. 7 bit frame. Beware: When two PICCs are in the + * field at the same time I often get STATUS_TIMEOUT - probably due do bad antenna design. * * @param bufferATQA The buffer to store the ATQA (Answer to request) in * @return STATUS_OK on success, STATUS_??? otherwise. @@ -992,10 +974,10 @@ public StatusCode requestA(byte[] bufferATQA) { } /** - * Transmits a Wake-UP command, Type A. Invites PICCs in state IDLE and HALT to - * go to READY(*) and prepare for anticollision or selection. 7 bit frame. - * Beware: When two PICCs are in the field at the same time I often get - * STATUS_TIMEOUT - probably due do bad antenna design. + * Transmits a Wake-UP command, Type A. Invites PICCs in state IDLE and HALT to go to + * READY(*) and prepare for anticollision or selection. 7 bit frame. Beware: When two + * PICCs are in the field at the same time I often get STATUS_TIMEOUT - probably due do + * bad antenna design. * * @param bufferATQA The buffer to store the ATQA (Answer to request) in * @return STATUS_OK on success, STATUS_??? otherwise. @@ -1005,9 +987,8 @@ public StatusCode wakeupA(byte[] bufferATQA) { } /** - * Transmits REQA or WUPA commands. Beware: When two PICCs are in the field at - * the same time I often get STATUS_TIMEOUT - probably due do bad antenna - * design. + * Transmits REQA or WUPA commands. Beware: When two PICCs are in the field at the same + * time I often get STATUS_TIMEOUT - probably due do bad antenna design. * * @param command The command to send - PICC_CMD_REQA or PICC_CMD_WUPA * @param bufferATQA The buffer to store the ATQA (Answer to request) in @@ -1046,21 +1027,20 @@ public UID select() { } /** - * Transmits SELECT/ANTICOLLISION commands to select a single PICC. Before - * calling this function the PICCs must be placed in the READY(*) state by - * calling PICC_RequestA() or PICC_WakeupA(). On success: - The chosen PICC is - * in state ACTIVE(*) and all other PICCs have returned to state IDLE/HALT. - * (Figure 7 of the ISO/IEC 14443-3 draft.) - The UID size and value of the - * chosen PICC is returned in *uid along with the SAK. + * Transmits SELECT/ANTICOLLISION commands to select a single PICC. Before calling this + * function the PICCs must be placed in the READY(*) state by calling PICC_RequestA() or + * PICC_WakeupA(). On success: - The chosen PICC is in state ACTIVE(*) and all other PICCs + * have returned to state IDLE/HALT. (Figure 7 of the ISO/IEC 14443-3 draft.) - The UID + * size and value of the chosen PICC is returned in *uid along with the SAK. * - * A PICC UID consists of 4, 7 or 10 bytes. Only 4 bytes can be specified in a - * SELECT command, so for the longer UIDs two or three iterations are used: UID - * size Number of UID bytes Cascade levels Example of PICC ======== - * =================== ============== =============== single 4 1 MIFARE Classic - * double 7 2 MIFARE Ultralight triple 10 3 Not currently in use? + * A PICC UID consists of 4, 7 or 10 bytes. Only 4 bytes can be specified in a SELECT + * command, so for the longer UIDs two or three iterations are used: UID size Number of + * UID bytes Cascade levels Example of PICC ======== =================== ============== + * =============== single 4 1 MIFARE Classic double 7 2 MIFARE Ultralight triple 10 3 Not + * currently in use? * - * @param validBits The number of known UID bits supplied in *uid. Normally 0. - * If set you must also supply uid->size. + * @param validBits The number of known UID bits supplied in *uid. Normally 0. If set you + * must also supply uid->size. * @return UID object or null if there was an error. */ public UID select(byte validBits) { @@ -1363,24 +1343,22 @@ public StatusCode haltA() { } /** - * Executes the MFRC522 MFAuthent command. This command manages MIFARE - * authentication to enable a secure communication to any MIFARE Mini, MIFARE 1K - * and MIFARE 4K card. The authentication is described in the MFRC522 datasheet - * section 10.3.1.9 and http://www.nxp.com/documents/data_sheet/MF1S503x.pdf - * section 10.1. For use with MIFARE Classic PICCs. The PICC must be selected - - * ie in state ACTIVE(*) - before calling this function. Remember to call - * PCD_StopCrypto1() after communicating with the authenticated PICC - otherwise - * no new communications can start. + * Executes the MFRC522 MFAuthent command. This command manages MIFARE authentication to + * enable a secure communication to any MIFARE Mini, MIFARE 1K and MIFARE 4K card. The + * authentication is described in the MFRC522 datasheet section 10.3.1.9 and + * http://www.nxp.com/documents/data_sheet/MF1S503x.pdf section 10.1. For use with MIFARE + * Classic PICCs. The PICC must be selected - ie in state ACTIVE(*) - before calling this + * function. Remember to call PCD_StopCrypto1() after communicating with the authenticated + * PICC - otherwise no new communications can start. * * All keys are set to FFFFFFFFFFFFh at chip delivery. * * @param authKeyA PICC_CMD_MF_AUTH_KEY_A or PICC_CMD_MF_AUTH_KEY_B - * @param blockAddr The block number. See numbering in the comments in the .h - * file. + * @param blockAddr The block number. See numbering in the comments in the .h file. * @param key Crypto1 key to use (6 bytes) * @param uid Pointer to Uid struct. The first 4 bytes of the UID is used. - * @return STATUS_OK on success, STATUS_??? otherwise. Probably STATUS_TIMEOUT - * if you supply the wrong key. + * @return STATUS_OK on success, STATUS_??? otherwise. Probably STATUS_TIMEOUT if you + * supply the wrong key. */ public StatusCode authenticate(boolean authKeyA, byte blockAddr, byte[] key, UID uid) { Logger.debug("blockAddr: " + blockAddr); @@ -1412,9 +1390,8 @@ public StatusCode authenticate(boolean authKeyA, byte blockAddr, byte[] key, UID } // End PCD_Authenticate() /** - * Used to exit the PCD from its authenticated state. Remember to call this - * function after communicating with an authenticated PICC - otherwise no new - * communications can start. + * Used to exit the PCD from its authenticated state. Remember to call this function after + * communicating with an authenticated PICC - otherwise no new communications can start. */ public void stopCrypto1() { // Clear MFCrypto1On bit @@ -1425,21 +1402,21 @@ public void stopCrypto1() { /** * Reads 16 bytes (+ 2 bytes CRC_A) from the active PICC. * - * For MIFARE Classic the sector containing the block must be authenticated - * before calling this function. + * For MIFARE Classic the sector containing the block must be authenticated before calling + * this function. * - * For MIFARE Ultralight only addresses 00h to 0Fh are decoded. The MF0ICU1 - * returns a NAK for higher addresses. The MF0ICU1 responds to the READ command - * by sending 16 bytes starting from the page address defined by the command - * argument. For example; if blockAddr is 03h then pages 03h, 04h, 05h, 06h are - * returned. A roll-back is implemented: If blockAddr is 0Eh, then the contents - * of pages 0Eh, 0Fh, 00h and 01h are returned. + * For MIFARE Ultralight only addresses 00h to 0Fh are decoded. The MF0ICU1 returns a NAK + * for higher addresses. The MF0ICU1 responds to the READ command by sending 16 bytes + * starting from the page address defined by the command argument. For example; if + * blockAddr is 03h then pages 03h, 04h, 05h, 06h are returned. A roll-back is + * implemented: If blockAddr is 0Eh, then the contents of pages 0Eh, 0Fh, 00h and 01h are + * returned. * - * The buffer must be at least 18 bytes because a CRC_A is also returned. Checks - * the CRC_A before returning STATUS_OK. + * The buffer must be at least 18 bytes because a CRC_A is also returned. Checks the CRC_A + * before returning STATUS_OK. * - * @param blockAddr MIFARE Classic: The block (0-0xff) number. MIFARE - * Ultralight: The first page to return data from. + * @param blockAddr MIFARE Classic: The block (0-0xff) number. MIFARE Ultralight: The + * first page to return data from. * @return STATUS_OK on success, STATUS_??? otherwise. */ public byte[] mifareRead(byte blockAddr) { @@ -1469,16 +1446,16 @@ public byte[] mifareRead(byte blockAddr) { /** * Writes 16 bytes to the active PICC. * - * For MIFARE Classic the sector containing the block must be authenticated - * before calling this function. + * For MIFARE Classic the sector containing the block must be authenticated before calling + * this function. * - * For MIFARE Ultralight the operation is called "COMPATIBILITY WRITE". Even - * though 16 bytes are transferred to the Ultralight PICC, only the least - * significant 4 bytes (bytes 0 to 3) are written to the specified address. It - * is recommended to set the remaining bytes 04h to 0Fh to all logic 0. + * For MIFARE Ultralight the operation is called "COMPATIBILITY WRITE". Even though 16 + * bytes are transferred to the Ultralight PICC, only the least significant 4 bytes (bytes + * 0 to 3) are written to the specified address. It is recommended to set the remaining + * bytes 04h to 0Fh to all logic 0. * - * @param blockAddr MIFARE Classic: The block (0-0xff) number. MIFARE - * Ultralight: The page (2-15) to write to. + * @param blockAddr MIFARE Classic: The block (0-0xff) number. MIFARE Ultralight: The page + * (2-15) to write to. * @param buffer The 16 bytes to write to the PICC * @return STATUS_OK on success, STATUS_??? otherwise. */ @@ -1509,9 +1486,9 @@ public StatusCode mifareWrite(byte blockAddr, byte[] buffer) { */ public StatusCode mifareUltralightWrite(byte page, byte[] buffer) { // Sanity check - //if (buffer == null || buffer.length != 4) { - // return StatusCode.INVALID; - //} + // if (buffer == null || buffer.length != 4) { + // return StatusCode.INVALID; + // } // Build commmand buffer byte[] cmdBuffer = new byte[6]; @@ -1525,11 +1502,11 @@ public StatusCode mifareUltralightWrite(byte page, byte[] buffer) { } // End MIFARE_Ultralight_Write() /** - * MIFARE Decrement subtracts the delta from the value of the addressed block, - * and stores the result in a volatile memory. For MIFARE Classic only. The - * sector containing the block must be authenticated before calling this - * function. Only for blocks in "value block" mode, ie with access bits [C1 C2 - * C3] = [110] or [001]. Use MIFARE_Transfer() to store the result in a block. + * MIFARE Decrement subtracts the delta from the value of the addressed block, and stores + * the result in a volatile memory. For MIFARE Classic only. The sector containing the + * block must be authenticated before calling this function. Only for blocks in "value + * block" mode, ie with access bits [C1 C2 C3] = [110] or [001]. Use MIFARE_Transfer() to + * store the result in a block. * * @param blockAddr The block (0-0xff) number. * @param delta This number is subtracted from the value of block blockAddr. @@ -1540,11 +1517,11 @@ public StatusCode mifareDecrement(byte blockAddr, int delta) { } // End MIFARE_Decrement() /** - * MIFARE Increment adds the delta to the value of the addressed block, and - * stores the result in a volatile memory. For MIFARE Classic only. The sector - * containing the block must be authenticated before calling this function. Only - * for blocks in "value block" mode, ie with access bits [C1 C2 C3] = [110] or - * [001]. Use MIFARE_Transfer() to store the result in a block. + * MIFARE Increment adds the delta to the value of the addressed block, and stores the + * result in a volatile memory. For MIFARE Classic only. The sector containing the block + * must be authenticated before calling this function. Only for blocks in "value block" + * mode, ie with access bits [C1 C2 C3] = [110] or [001]. Use MIFARE_Transfer() to store + * the result in a block. * * @param blockAddr The block (0-0xff) number. * @param delta This number is added to the value of block blockAddr. @@ -1555,11 +1532,10 @@ public StatusCode mifareIncrement(byte blockAddr, int delta) { } // End MIFARE_Increment() /** - * MIFARE Restore copies the value of the addressed block into a volatile - * memory. For MIFARE Classic only. The sector containing the block must be - * authenticated before calling this function. Only for blocks in "value block" - * mode, ie with access bits [C1 C2 C3] = [110] or [001]. Use MIFARE_Transfer() - * to store the result in a block. + * MIFARE Restore copies the value of the addressed block into a volatile memory. For + * MIFARE Classic only. The sector containing the block must be authenticated before + * calling this function. Only for blocks in "value block" mode, ie with access bits [C1 + * C2 C3] = [110] or [001]. Use MIFARE_Transfer() to store the result in a block. * * @param blockAddr The block (0-0xff) number. * @return STATUS_OK on success, STATUS_??? otherwise. @@ -1573,8 +1549,8 @@ public StatusCode mifareRestore(byte blockAddr) { } // End MIFARE_Restore() /** - * Helper function for the two-step MIFARE Classic protocol operations - * Decrement, Increment and Restore. + * Helper function for the two-step MIFARE Classic protocol operations Decrement, + * Increment and Restore. * * @param command The command to use * @param blockAddr The block (0-0xff) number. @@ -1602,10 +1578,10 @@ public StatusCode mifareTwoStepHelper(PiccCommand command, byte blockAddr, int d } // End MIFARE_TwoStepHelper() /** - * MIFARE Transfer writes the value stored in the volatile memory into one - * MIFARE Classic block. For MIFARE Classic only. The sector containing the - * block must be authenticated before calling this function. Only for blocks in - * "value block" mode, ie with access bits [C1 C2 C3] = [110] or [001]. + * MIFARE Transfer writes the value stored in the volatile memory into one MIFARE Classic + * block. For MIFARE Classic only. The sector containing the block must be authenticated + * before calling this function. Only for blocks in "value block" mode, ie with access + * bits [C1 C2 C3] = [110] or [001]. * * @param blockAddr The block (0-0xff) number. * @return STATUS_OK on success, STATUS_??? otherwise. @@ -1619,9 +1595,9 @@ public StatusCode mifareTransfer(byte blockAddr) { /** * Helper routine to read the current value from a Value Block. * - * Only for MIFARE Classic and only for blocks in "value block" mode, that is: - * with access bits [C1 C2 C3] = [110] or [001]. The sector containing the block - * must be authenticated before calling this function. + * Only for MIFARE Classic and only for blocks in "value block" mode, that is: with access + * bits [C1 C2 C3] = [110] or [001]. The sector containing the block must be authenticated + * before calling this function. * * @param blockAddr The block (0x00-0xff) number. * @return Integer value or null if error. @@ -1641,9 +1617,9 @@ public Integer mifareGetValue(byte blockAddr) { /** * Helper routine to write a specific value into a Value Block. * - * Only for MIFARE Classic and only for blocks in "value block" mode, that is: - * with access bits [C1 C2 C3] = [110] or [001]. The sector containing the block - * must be authenticated before calling this function. + * Only for MIFARE Classic and only for blocks in "value block" mode, that is: with access + * bits [C1 C2 C3] = [110] or [001]. The sector containing the block must be authenticated + * before calling this function. * * @param blockAddr The block (0x00-0xff) number. * @param value New value of the Value Block. @@ -1686,35 +1662,35 @@ public StatusCode ntag216Auth(byte[] passWord, byte pACK[]) //Authenticate with { // TODO: Fix cmdBuffer length and rxlength. They really should match. // (Better still, rxlength should not even be necessary.) - + StatusCode result; byte cmdBuffer[18]; // We need room for 16 bytes data and 2 bytes CRC_A. - + cmdBuffer[0] = 0x1B; //Comando de autentificacion - + for (byte i = 0; i<4; i++) cmdBuffer[i+1] = passWord[i]; - + result = PCD_CalculateCRC(cmdBuffer, 5, &cmdBuffer[5]); - + if (result!=STATUS_OK) { return result; } - + // Transceive the data, store the reply in cmdBuffer[] byte waitIRq = 0x30; // RxIRq and IdleIRq //byte cmdBufferSize = sizeof(cmdBuffer); byte validBits = 0; byte rxlength = 5; result = PCD_CommunicateWithPICC(PCD_Transceive, waitIRq, cmdBuffer, 7, cmdBuffer, &rxlength, &validBits); - + pACK[0] = cmdBuffer[0]; pACK[1] = cmdBuffer[1]; - + if (result!=STATUS_OK) { return result; } - + return STATUS_OK; } // End PCD_NTAG216_AUTH() */ @@ -1728,8 +1704,8 @@ public StatusCode mifareTransceive(byte[] sendData) { } /** - * Wrapper for MIFARE protocol communication. Adds CRC_A, executes the - * Transceive command and checks that the response is MF_ACK or a timeout. + * Wrapper for MIFARE protocol communication. Adds CRC_A, executes the Transceive command + * and checks that the response is MF_ACK or a timeout. * * @param sendData Data to transfer to the FIFO. Do NOT include the CRC_A. * @param acceptTimeout A timeout is also success @@ -1737,9 +1713,9 @@ public StatusCode mifareTransceive(byte[] sendData) { */ public StatusCode mifareTransceive(byte[] sendData, boolean acceptTimeout) { // Sanity check - //if (sendData == null || sendData.length != 16) { - // return StatusCode.INVALID; - //} + // if (sendData == null || sendData.length != 16) { + // return StatusCode.INVALID; + // } /*- C++ Code: byte cmdBuffer[18]; // We need room for 16 bytes data and 2 bytes CRC_A. @@ -1798,8 +1774,8 @@ public static PiccType getPiccType(byte sak) { } // End PICC_GetType() /** - * Calculates the bit pattern needed for the specified access bits. In the [C1 - * C2 C3] tuples C1 is MSB (=4) and C3 is LSB (=1). + * Calculates the bit pattern needed for the specified access bits. In the [C1 C2 C3] + * tuples C1 is MSB (=4) and C3 is LSB (=1). */ /*- public void mifareSetAccessBits( byte *accessBitBuffer, ///< Pointer to byte 6, 7 and 8 in the sector trailer. Bytes [0..2] will be set. @@ -1811,7 +1787,7 @@ public void mifareSetAccessBits( byte *accessBitBuffer, ///< Pointer to byte 6, byte c1 = ((g3 & 4) << 1) | ((g2 & 4) << 0) | ((g1 & 4) >> 1) | ((g0 & 4) >> 2); byte c2 = ((g3 & 2) << 2) | ((g2 & 2) << 1) | ((g1 & 2) << 0) | ((g0 & 2) >> 1); byte c3 = ((g3 & 1) << 3) | ((g2 & 1) << 2) | ((g1 & 1) << 1) | ((g0 & 1) << 0); - + accessBitBuffer[0] = (~c2 & 0xF) << 4 | (~c1 & 0xF); accessBitBuffer[1] = c1 << 4 | (~c3 & 0xF); accessBitBuffer[2] = c3 << 4 | c2; @@ -1819,16 +1795,16 @@ public void mifareSetAccessBits( byte *accessBitBuffer, ///< Pointer to byte 6, */ /** - * Performs the "magic sequence" needed to get Chinese UID changeable Mifare - * cards to allow writing to sector 0, where the card UID is stored. + * Performs the "magic sequence" needed to get Chinese UID changeable Mifare cards to + * allow writing to sector 0, where the card UID is stored. * - * Note that you do not need to have selected the card through REQA or WUPA, - * this sequence works immediately when the card is in the reader vicinity. This - * means you can use this method even on "bricked" cards that your reader does - * not recognise anymore (see MFRC522::MIFARE_UnbrickUidSector). + * Note that you do not need to have selected the card through REQA or WUPA, this sequence + * works immediately when the card is in the reader vicinity. This means you can use this + * method even on "bricked" cards that your reader does not recognise anymore (see + * MFRC522::MIFARE_UnbrickUidSector). * - * Of course with non-bricked devices, you're free to select them before calling - * this function. + * Of course with non-bricked devices, you're free to select them before calling this + * function. * * @return Status */ @@ -1845,8 +1821,8 @@ public boolean mifareOpenUidBackdoor() { byte[] cmd = { 0x40 }; byte validBits = 7; /* - * Our command is only 7 bits. After receiving card response, this will contain - * amount of valid response bits. + * Our command is only 7 bits. After receiving card response, this will contain amount of + * valid response bits. */ Response resp = transceiveData(cmd, validBits, (byte) 0, false); // 40 byte[] response = resp.getBackData(); @@ -1886,9 +1862,8 @@ public boolean mifareOpenUidBackdoor() { } // End MIFARE_OpenUidBackdoor() /** - * Reads entire block 0, including all manufacturer data, and overwrites that - * block with the new UID, a freshly calculated BCC, and the original - * manufacturer data. + * Reads entire block 0, including all manufacturer data, and overwrites that block with + * the new UID, a freshly calculated BCC, and the original manufacturer data. * * Make sure to have selected the card before this function is called. * @@ -1940,7 +1915,7 @@ public boolean mifareSetUid(byte[] newUid, UID uid, byte[] authKey) { return false; } - block0_buffer = Arrays.copyOf(block0_buffer, 16); //Remove the CRC_A which is also returned by mifareRead + block0_buffer = Arrays.copyOf(block0_buffer, 16); // Remove the CRC_A which is also returned by mifareRead // Write new UID to the data we just read, and calculate BCC byte byte bcc = 0; @@ -2000,8 +1975,8 @@ public boolean mifareUnbrickUidSector() { ///////////////////////////////////////////////////////////////////////////////////// /** - * Returns true if a PICC responds to PICC_CMD_REQA. Only "new" cards in state - * IDLE are invited. Sleeping cards in state HALT are ignored. + * Returns true if a PICC responds to PICC_CMD_REQA. Only "new" cards in state IDLE are + * invited. Sleeping cards in state HALT are ignored. * * @return bool */ @@ -2018,9 +1993,9 @@ public boolean isNewCardPresent() { } // End PICC_IsNewCardPresent() /** - * Simple wrapper around PICC_Select. Returns the UID of the card if present, - * otherwise null. Remember to call PICC_IsNewCardPresent(), PICC_RequestA() or - * PICC_WakeupA() first. + * Simple wrapper around PICC_Select. Returns the UID of the card if present, otherwise + * null. Remember to call PICC_IsNewCardPresent(), PICC_RequestA() or PICC_WakeupA() + * first. * * @return The UID is a card could be read, otherwise null */ @@ -2031,8 +2006,7 @@ public UID readCardSerial() { // DEBUG METHODS /** - * Dumps debug info about the connected PCD to Serial. Shows all known firmware - * versions + * Dumps debug info about the connected PCD to Serial. Shows all known firmware versions */ public void dumpVersionToConsole() { // Get the MFRC522 firmware version @@ -2063,9 +2037,9 @@ public void dumpVersionToConsole() { } // End PCD_DumpVersionToSerial() /** - * Dumps debug info about the selected PICC to Serial. On success the PICC is - * halted after dumping the data. For MIFARE Classic the factory default key of - * 0xFFFFFFFFFFFF is tried. + * Dumps debug info about the selected PICC to Serial. On success the PICC is halted after + * dumping the data. For MIFARE Classic the factory default key of 0xFFFFFFFFFFFF is + * tried. * * @param uid UID returned from a successful PICC_Select(). * @deprecated Kept for backward compatibility @@ -2130,8 +2104,8 @@ public static void dumpDetailsToConsole(UID uid) { } // End PICC_DumpDetailsToSerial() /** - * Dumps memory contents of a MIFARE Classic PICC. On success the PICC is halted - * after dumping the data. + * Dumps memory contents of a MIFARE Classic PICC. On success the PICC is halted after + * dumping the data. * * @param uid UID returned from a successful PICC_Select(). * @param key Key A used for all sectors. @@ -2171,10 +2145,9 @@ public void dumpMifareClassicToConsole(UID uid, byte[] key) { } // End PICC_DumpMifareClassicToSerial() /** - * Dumps memory contents of a sector of a MIFARE Classic PICC. Uses - * PCD_Authenticate(), MIFARE_Read() and PCD_StopCrypto1. Always uses - * PICC_CMD_MF_AUTH_KEY_A because only Key A can always read the sector trailer - * access bits. + * Dumps memory contents of a sector of a MIFARE Classic PICC. Uses PCD_Authenticate(), + * MIFARE_Read() and PCD_StopCrypto1. Always uses PICC_CMD_MF_AUTH_KEY_A because only Key + * A can always read the sector trailer access bits. * * @param uid UID returned from a successful select(). * @param key Key A for the sector. @@ -2590,8 +2563,7 @@ public static class UID { /** Number of bytes in the UID. 4, 7 or 10. */ private byte[] uidBytes; /** - * The SAK (Select acknowledge) byte returned from the PICC after successful - * selection. + * The SAK (Select acknowledge) byte returned from the PICC after successful selection. */ private byte sak; @@ -2634,15 +2606,19 @@ public int hashCode() { @Override public boolean equals(Object obj) { - if (this == obj) + if (this == obj) { return true; - if (obj == null) + } + if (obj == null) { return false; - if (getClass() != obj.getClass()) + } + if (getClass() != obj.getClass()) { return false; + } UID other = (UID) obj; - if (!Arrays.equals(uidBytes, other.uidBytes)) + if (!Arrays.equals(uidBytes, other.uidBytes)) { return false; + } return true; } diff --git a/diozero-core/src/main/java/com/diozero/devices/McpAdc.java b/diozero-core/src/main/java/com/diozero/devices/McpAdc.java index 5df18d64..f147459f 100644 --- a/diozero-core/src/main/java/com/diozero/devices/McpAdc.java +++ b/diozero-core/src/main/java/com/diozero/devices/McpAdc.java @@ -41,6 +41,7 @@ import com.diozero.api.RuntimeIOException; import com.diozero.api.SpiConstants; import com.diozero.api.SpiDevice; +import com.diozero.api.SpiDeviceInterface; import com.diozero.internal.spi.AbstractDeviceFactory; import com.diozero.internal.spi.AbstractInputDevice; import com.diozero.internal.spi.AnalogInputDeviceFactoryInterface; @@ -49,7 +50,7 @@ public class McpAdc extends AbstractDeviceFactory implements AnalogInputDeviceFactoryInterface, DeviceInterface { private Type type; - private SpiDevice spiDevice; + private SpiDeviceInterface device; private BoardPinInfo boardPinInfo; public McpAdc(Type type, int chipSelect, float vRef) throws RuntimeIOException { @@ -63,7 +64,7 @@ public McpAdc(Type type, int controller, int chipSelect, float vRef) throws Runt boardPinInfo = new McpAdcBoardPinInfo(type, vRef); - spiDevice = SpiDevice.builder(chipSelect).setController(controller).setFrequency(type.getMaxFreq2v7()).build(); + device = SpiDevice.builder(chipSelect).setController(controller).setFrequency(type.getMaxFreq2v7()).build(); } @Override @@ -71,7 +72,7 @@ public void close() throws RuntimeIOException { Logger.trace("close()"); // Close all open pins before closing the SPI device itself super.close(); - spiDevice.close(); + device.close(); } /** @@ -151,7 +152,7 @@ private int getRawValue(int adcPin, boolean differentialRead) throws RuntimeIOEx tx[index++] = (byte) 0; tx[index++] = (byte) 0; - byte[] in = spiDevice.writeAndRead(tx); + byte[] in = device.writeAndRead(tx); // Logger.debug(String.format("0x%x, 0x%x, 0x%x", // Byte.valueOf(in.get(0)), Byte.valueOf(in.get(1)), Byte.valueOf(in.get(2)))); @@ -201,7 +202,7 @@ public AnalogInputDeviceInterface createAnalogInputDevice(String key, PinInfo pi @Override public String getName() { - return type.name() + "-" + spiDevice.getController() + "-" + spiDevice.getChipSelect(); + return type.name() + "-" + device.getController() + "-" + device.getChipSelect(); } @Override @@ -210,21 +211,19 @@ public BoardPinInfo getBoardPinInfo() { } /** - * The MCP3204/3208 devices offer the choice of using the analog input channels - * configured as single-ended inputs or pseudo-differential pairs. When used in - * the pseudo-differential mode, each channel pair (i.e., CH0 and CH1, CH2 and - * CH3 etc.) is programmed to be the IN+ and IN- inputs as part of the command - * string transmitted to the device. The IN+ input can range from IN- to (VREF + - * IN-). The IN- input is limited to ?100 mV from the VSS rail. The IN- input - * can be used to cancel small signal common-mode noise which is present on both - * the IN+ and IN- inputs. When operating in the pseudo-differential mode, if - * the voltage level of IN+ is equal to or less than IN-, the resultant code - * will be 000h. If the voltage at IN+ is equal to or greater than {[VREF + - * (IN-)] - 1 LSB}, then the output code will be FFFh. If the voltage level at - * IN- is more than 1 LSB below VSS, the voltage level at the IN+ input will - * have to go below VSS to see the 000h output code. Conversely, if IN- is more - * than 1 LSB above VSS, then the FFFh code will not be seen unless the IN+ - * input level goes above VREF level. + * The MCP3204/3208 devices offer the choice of using the analog input channels configured + * as single-ended inputs or pseudo-differential pairs. When used in the + * pseudo-differential mode, each channel pair (i.e., CH0 and CH1, CH2 and CH3 etc.) is + * programmed to be the IN+ and IN- inputs as part of the command string transmitted to + * the device. The IN+ input can range from IN- to (VREF + IN-). The IN- input is limited + * to ?100 mV from the VSS rail. The IN- input can be used to cancel small signal + * common-mode noise which is present on both the IN+ and IN- inputs. When operating in + * the pseudo-differential mode, if the voltage level of IN+ is equal to or less than IN-, + * the resultant code will be 000h. If the voltage at IN+ is equal to or greater than + * {[VREF + (IN-)] - 1 LSB}, then the output code will be FFFh. If the voltage level at + * IN- is more than 1 LSB below VSS, the voltage level at the IN+ input will have to go + * below VSS to see the 000h output code. Conversely, if IN- is more than 1 LSB above VSS, + * then the FFFh code will not be seen unless the IN+ input level goes above VREF level. */ public static enum Type { /*- diff --git a/diozero-core/src/main/java/com/diozero/devices/McpEeprom.java b/diozero-core/src/main/java/com/diozero/devices/McpEeprom.java index 5f65f004..b24f4275 100644 --- a/diozero-core/src/main/java/com/diozero/devices/McpEeprom.java +++ b/diozero-core/src/main/java/com/diozero/devices/McpEeprom.java @@ -31,18 +31,21 @@ * #L% */ - import org.tinylog.Logger; import com.diozero.api.DeviceInterface; import com.diozero.api.I2CDevice; +import com.diozero.api.I2CDeviceInterface; import com.diozero.api.RuntimeIOException; import com.diozero.util.SleepUtil; /** - * See the Microchip website. + * See the Microchip + * website. * Datasheet. * Connections: + * *
      *         Notch
      * GND  A0 1  8 Vcc 3v3
    @@ -54,13 +57,13 @@
     public class McpEeprom implements DeviceInterface {
     	public static enum Type {
     		MCP_24xx256(2, 64, 5, 256), MCP_24xx512(2, 128, 5, 512);
    -		
    +
     		private int addressSizeBytes;
     		private int pageSizeBytes;
     		private int writeCycleTimeMillis;
     		private int memorySizeBits;
     		private int memorySizeBytes;
    -		
    +
     		private Type(int addressSizeBytes, int pageSizeBytes, int writeCycleTimeMillis, int memorySizeKibibits) {
     			this.addressSizeBytes = addressSizeBytes;
     			this.pageSizeBytes = pageSizeBytes;
    @@ -89,91 +92,91 @@ public int getMemorySizeBytes() {
     			return memorySizeBytes;
     		}
     	}
    -	
    +
     	public static final int DEFAULT_ADDRESS = 0x50;
    -	
    -	private I2CDevice device;
    +
    +	private I2CDeviceInterface device;
     	private Type type;
    -	
    +
     	public McpEeprom(int controller, Type type) {
     		this(controller, DEFAULT_ADDRESS, type);
     	}
    -	
    +
     	public McpEeprom(int controller, int address, Type type) {
     		this.type = type;
     		device = I2CDevice.builder(address).setController(controller).build();
    -		if (! device.probe()) {
    +		if (!device.probe()) {
     			throw new RuntimeIOException("No such device " + controller + "-0x" + Integer.toHexString(address));
     		}
     	}
    -	
    +
     	public Type getType() {
     		return type;
     	}
    -	
    +
     	public int getMemorySizeByte() {
     		return type.getMemorySizeBytes();
     	}
    -	
    +
     	private byte[] getAddressByteArray(int address) {
     		byte[] address_bytes = new byte[type.getAddressSizeBytes()];
    -		
    -		for (int i=0; i> 8 * (type.getAddressSizeBytes() - (i+1))) & 0xff);
    +
    +		for (int i = 0; i < type.getAddressSizeBytes(); i++) {
    +			address_bytes[i] = (byte) ((address >> 8 * (type.getAddressSizeBytes() - (i + 1))) & 0xff);
     		}
    -		
    +
     		return address_bytes;
     	}
    -	
    +
     	public byte readCurrentAddress() {
     		return device.readByte();
     	}
    -	
    +
     	public byte readByte(int address) {
     		device.writeBytes(getAddressByteArray(address));
     		return device.readByte();
     	}
    -	
    +
     	public byte[] readBytes(int address, int length) {
     		device.writeBytes(getAddressByteArray(address));
     		return device.readBytes(length);
     	}
    -	
    +
     	public void writeByte(int address, int data) {
     		writeByte(address, (byte) data);
     	}
    -	
    +
     	public void writeByte(int address, byte data) {
     		byte[] addr_bytes = getAddressByteArray(address);
    -		byte[] buffer = new byte[addr_bytes.length+1];
    +		byte[] buffer = new byte[addr_bytes.length + 1];
     		System.arraycopy(addr_bytes, 0, buffer, 0, addr_bytes.length);
     		buffer[addr_bytes.length] = data;
     		device.writeBytes(buffer);
     		SleepUtil.sleepMillis(type.getWriteCycleTimeMillis());
     	}
    -	
    +
     	public void writeBytes(int address, byte[] data) {
     		if ((address + data.length) > type.getMemorySizeBytes()) {
     			Logger.error("Attempt to write beyond memory size - no data written");
     			return;
     		}
    -		
    +
     		int page = address / type.getPageSizeBytes();
     		int bytes_remaining = data.length;
     		do {
     			int remaining_page_size = type.getPageSizeBytes() - (address % type.getPageSizeBytes());
     			int bytes_to_write = remaining_page_size < bytes_remaining ? remaining_page_size : bytes_remaining;
    -			
    +
     			byte[] addr_bytes = getAddressByteArray(address);
    -			byte[] buffer = new byte[addr_bytes.length+bytes_to_write];
    +			byte[] buffer = new byte[addr_bytes.length + bytes_to_write];
     			System.arraycopy(addr_bytes, 0, buffer, 0, addr_bytes.length);
     			System.arraycopy(data, data.length - bytes_remaining, buffer, addr_bytes.length, bytes_to_write);
     			device.writeBytes(buffer);
    -			
    +
     			bytes_remaining -= bytes_to_write;
     			page++;
     			address = page * type.getPageSizeBytes();
    -			
    +
     			SleepUtil.sleepMillis(type.getWriteCycleTimeMillis());
     		} while (bytes_remaining > 0);
     	}
    diff --git a/diozero-core/src/main/java/com/diozero/devices/PCA9685.java b/diozero-core/src/main/java/com/diozero/devices/PCA9685.java
    index 2f3ad5fd..2906e3b4 100644
    --- a/diozero-core/src/main/java/com/diozero/devices/PCA9685.java
    +++ b/diozero-core/src/main/java/com/diozero/devices/PCA9685.java
    @@ -40,6 +40,7 @@
     import com.diozero.api.DeviceMode;
     import com.diozero.api.I2CConstants;
     import com.diozero.api.I2CDevice;
    +import com.diozero.api.I2CDeviceInterface;
     import com.diozero.api.PinInfo;
     import com.diozero.api.RuntimeIOException;
     import com.diozero.internal.spi.AbstractDevice;
    @@ -53,8 +54,8 @@
     import com.diozero.util.SleepUtil;
     
     /**
    - * PCA9685 I2C-bus controlled 16-channel 12-bit PWM controller as used in the
    - * popular Adafruit PWM add-on board:
    + * PCA9685 I2C-bus controlled 16-channel 12-bit PWM controller as used in the popular
    + * Adafruit PWM add-on board:
      * Datasheet
      */
     @SuppressWarnings("unused")
    @@ -113,7 +114,7 @@ public class PCA9685 extends AbstractDeviceFactory
     	private static final int MAX_PWM_FREQUENCY = 1000;
     	public static final int DEFAULT_PWM_FREQUENCY = 50;
     
    -	private final I2CDevice i2cDevice;
    +	private final I2CDeviceInterface device;
     	private String keyPrefix;
     	private int boardPwmFrequency = DEFAULT_PWM_FREQUENCY;
     	private double periodUs = 1_000_000.0 / DEFAULT_PWM_FREQUENCY;
    @@ -134,7 +135,7 @@ public PCA9685(int controller, int pwmFrequency) throws RuntimeIOException {
     	public PCA9685(int controller, int address, int pwmFrequency) throws RuntimeIOException {
     		super(DEVICE_NAME + "-" + controller + "-" + address);
     
    -		i2cDevice = I2CDevice.builder(address).setController(controller).setByteOrder(ByteOrder.BIG_ENDIAN).build();
    +		device = I2CDevice.builder(address).setController(controller).setByteOrder(ByteOrder.BIG_ENDIAN).build();
     		boardPinInfo = new PCA9685BoardPinInfo();
     
     		reset();
    @@ -143,15 +144,14 @@ public PCA9685(int controller, int address, int pwmFrequency) throws RuntimeIOEx
     	}
     
     	private void reset() throws RuntimeIOException {
    -		i2cDevice.writeByteData(MODE1, 0); // Normal mode
    -		i2cDevice.writeByteData(MODE2, OUTDRV_MASK); // Set output driver to totem pole mode (rather than open drain)
    +		device.writeByteData(MODE1, 0); // Normal mode
    +		device.writeByteData(MODE2, OUTDRV_MASK); // Set output driver to totem pole mode (rather than open drain)
     	}
     
     	/**
     	 * Sets the PWM frequency
     	 *
    -	 * @param pwmFrequency desired frequency. 40Hz to 1000Hz using internal 25MHz
    -	 *                     oscillator
    +	 * @param pwmFrequency desired frequency. 40Hz to 1000Hz using internal 25MHz oscillator
     	 * @throws RuntimeIOException if an I/O error occurs
     	 */
     	private void setPwmFreq(int pwmFrequency) throws RuntimeIOException {
    @@ -167,26 +167,26 @@ private void setPwmFreq(int pwmFrequency) throws RuntimeIOException {
     		Logger.debug("Setting PWM frequency to {} Hz, float pre-scale: {}, int prescale {}", pwmFrequency,
     				String.format("%.2f", prescale_flt), prescale_int);
     
    -		byte oldmode = i2cDevice.readByteData(MODE1);
    -		i2cDevice.writeByteData(MODE1, (byte) ((oldmode & 0x7F) | SLEEP_MASK)); // Enter low power mode (set the sleep
    +		byte oldmode = device.readByteData(MODE1);
    +		device.writeByteData(MODE1, (byte) ((oldmode & 0x7F) | SLEEP_MASK)); // Enter low power mode (set the sleep
     																				// bit)
    -		i2cDevice.writeByteData(PRESCALE, (byte) (prescale_int));
    +		device.writeByteData(PRESCALE, (byte) (prescale_int));
     		boardPwmFrequency = pwmFrequency;
     		periodUs = 1_000_000.0 / pwmFrequency;
    -		i2cDevice.writeByteData(MODE1, oldmode); // Restore the previous mode1 value
    +		device.writeByteData(MODE1, oldmode); // Restore the previous mode1 value
     		SleepUtil.sleepMillis(1); // Wait min 500us for the oscillator to stabilise
    -		i2cDevice.writeByteData(MODE1, (byte) (oldmode | RESTART_MASK)); // Set restart enabled
    +		device.writeByteData(MODE1, (byte) (oldmode | RESTART_MASK)); // Set restart enabled
     	}
     
     	private int[] getPwm(int channel) throws RuntimeIOException {
     		validateChannel(channel);
     
    -		short on_l = i2cDevice.readUByte(LED0_ON_L + 4 * channel);
    -		short on_h = i2cDevice.readUByte(LED0_ON_H + 4 * channel);
    +		short on_l = device.readUByte(LED0_ON_L + 4 * channel);
    +		short on_h = device.readUByte(LED0_ON_H + 4 * channel);
     		int on = (on_h << 8) | on_l;
     
    -		short off_l = i2cDevice.readUByte(LED0_OFF_L + 4 * channel);
    -		short off_h = i2cDevice.readUByte(LED0_OFF_H + 4 * channel);
    +		short off_l = device.readUByte(LED0_OFF_L + 4 * channel);
    +		short off_h = device.readUByte(LED0_OFF_H + 4 * channel);
     		int off = (off_h << 8) | off_l;
     
     		Logger.debug("channel={}, on={}, off={}", channel, on, off);
    @@ -197,8 +197,8 @@ private int[] getPwm(int channel) throws RuntimeIOException {
     	/**
     	 * Sets a single PWM channel
     	 *
    -	 * Example 1: (assumes that the LED0 output is used and (delay time) + (PWM duty
    -	 * cycle) <= 100 %)
    +	 * Example 1: (assumes that the LED0 output is used and (delay time) + (PWM duty cycle)
    +	 * <= 100 %)
     	 *
     	 * 
     	 * Delay time = 10 %;
    @@ -229,12 +229,12 @@ private void setPwm(int channel, int on, int off) throws RuntimeIOException {
     		// Integer.valueOf(off));
     
     		// TODO Replace with writeWordData()?
    -		// i2cDevice.writeWordData(LED0_ON_L + 4 * channel, (short) on);
    -		// i2cDevice.writeWordData(LED0_OFF_L + 4 * channel, (short) off);
    -		i2cDevice.writeByteData(LED0_ON_L + 4 * channel, on & 0xFF);
    -		i2cDevice.writeByteData(LED0_ON_H + 4 * channel, on >> 8);
    -		i2cDevice.writeByteData(LED0_OFF_L + 4 * channel, off & 0xFF);
    -		i2cDevice.writeByteData(LED0_OFF_H + 4 * channel, off >> 8);
    +		// device.writeWordData(LED0_ON_L + 4 * channel, (short) on);
    +		// device.writeWordData(LED0_OFF_L + 4 * channel, (short) off);
    +		device.writeByteData(LED0_ON_L + 4 * channel, on & 0xFF);
    +		device.writeByteData(LED0_ON_H + 4 * channel, on >> 8);
    +		device.writeByteData(LED0_OFF_L + 4 * channel, off & 0xFF);
    +		device.writeByteData(LED0_OFF_H + 4 * channel, off >> 8);
     		// SleepUtil.sleepMillis(50);
     	}
     
    @@ -272,12 +272,12 @@ private static void validateChannel(int channel) {
     	private void setAllPwm(int on, int off) throws RuntimeIOException {
     		validateOnOff(on, off);
     		// TODO Replace with writeShort()?
    -		// i2cDevice.writeShort(ALL_LED_ON_L, (short)on);
    -		// i2cDevice.writeShort(ALL_LED_OFF_L, (short)off);
    -		i2cDevice.writeByteData(ALL_LED_ON_L, on & 0xFF);
    -		i2cDevice.writeByteData(ALL_LED_ON_H, on >> 8);
    -		i2cDevice.writeByteData(ALL_LED_OFF_L, off & 0xFF);
    -		i2cDevice.writeByteData(ALL_LED_OFF_H, off >> 8);
    +		// device.writeShort(ALL_LED_ON_L, (short)on);
    +		// device.writeShort(ALL_LED_OFF_L, (short)off);
    +		device.writeByteData(ALL_LED_ON_L, on & 0xFF);
    +		device.writeByteData(ALL_LED_ON_H, on >> 8);
    +		device.writeByteData(ALL_LED_OFF_L, off & 0xFF);
    +		device.writeByteData(ALL_LED_OFF_H, off >> 8);
     	}
     
     	@Override
    @@ -294,7 +294,7 @@ public void close() throws RuntimeIOException {
     
     		// Close all open pins before closing the I2C device itself
     		super.close();
    -		i2cDevice.close();
    +		device.close();
     	}
     
     	public void closeChannel(int channel) throws RuntimeIOException {
    @@ -362,10 +362,9 @@ public int getDutyUs(int channel) {
     	}
     
     	/**
    -	 * Set PWM duty cycle output in microseconds for the specified channel. A
    -	 * standard servo has a minimum range of 1-2 milliseconds. The actual range
    -	 * varies between devices. E.g. My TowerPro SG90 has a pulse width range of
    -	 * 500-2,400 us.
    +	 * Set PWM duty cycle output in microseconds for the specified channel. A standard servo
    +	 * has a minimum range of 1-2 milliseconds. The actual range varies between devices. E.g.
    +	 * My TowerPro SG90 has a pulse width range of 500-2,400 us.
     	 *
     	 * @param channel PWM channel
     	 * @param dutyUs  New duty value in microseconds
    diff --git a/diozero-core/src/main/java/com/diozero/devices/PCF8574.java b/diozero-core/src/main/java/com/diozero/devices/PCF8574.java
    index 125481c6..a1ebc769 100644
    --- a/diozero-core/src/main/java/com/diozero/devices/PCF8574.java
    +++ b/diozero-core/src/main/java/com/diozero/devices/PCF8574.java
    @@ -40,6 +40,7 @@
     import com.diozero.api.GpioEventTrigger;
     import com.diozero.api.GpioPullUpDown;
     import com.diozero.api.I2CDevice;
    +import com.diozero.api.I2CDeviceInterface;
     import com.diozero.api.PinInfo;
     import com.diozero.api.RuntimeIOException;
     import com.diozero.internal.spi.AbstractDevice;
    @@ -60,7 +61,7 @@ public class PCF8574 extends AbstractDeviceFactory implements GpioDeviceFactoryI
     
     	private static final int NUM_PINS = 8;
     
    -	private I2CDevice device;
    +	private I2CDeviceInterface device;
     	private MutableByte directions;
     	private BoardPinInfo boardPinInfo;
     
    diff --git a/diozero-core/src/main/java/com/diozero/devices/PCF8591.java b/diozero-core/src/main/java/com/diozero/devices/PCF8591.java
    index c394aaa9..7a550a9f 100644
    --- a/diozero-core/src/main/java/com/diozero/devices/PCF8591.java
    +++ b/diozero-core/src/main/java/com/diozero/devices/PCF8591.java
    @@ -39,6 +39,7 @@
     import com.diozero.api.DeviceInterface;
     import com.diozero.api.I2CConstants;
     import com.diozero.api.I2CDevice;
    +import com.diozero.api.I2CDeviceInterface;
     import com.diozero.api.PinInfo;
     import com.diozero.api.RuntimeIOException;
     import com.diozero.internal.spi.AbstractDevice;
    @@ -61,22 +62,22 @@
      * 

    * Note the raspoid - * driver states there is a known bug when reading digital values from - * PCF8591 if analog output is disabled. + * driver states there is a known bug when reading digital values from PCF8591 if + * analog output is disabled. *

    *

    * Instructions:
    - * The jumpers control whether analog input channels of the IC are connected to - * the analog sources: + * The jumpers control whether analog input channels of the IC are connected to the analog + * sources: *

    *
      - *
    • Jumper P4 for AIN1: The temperature sensed by the R6 thermister is - * provided to the ADC.
    • - *
    • Jumper P5 to AIN0: The R7 photocell voltage (resistance drop) is provided - * to the DAC.
    • - *
    • Jumper P6 to AIN3: The single turn 10K ohm trimpot voltage (resistance - * drop ? brighter light, lower resistance).
    • + *
    • Jumper P4 for AIN1: The temperature sensed by the R6 thermister is provided to the + * ADC.
    • + *
    • Jumper P5 to AIN0: The R7 photocell voltage (resistance drop) is provided to the + * DAC.
    • + *
    • Jumper P6 to AIN3: The single turn 10K ohm trimpot voltage (resistance drop ? + * brighter light, lower resistance).
    • *
    *

    * From my experiments, the inputs / jumpers are configured as follows: @@ -88,8 +89,8 @@ *

  • AIN3: AIN3
  • *
*

- * Removing a jumper allows an input channel to be fed from one of the external - * pins, labelled accordingly. + * Removing a jumper allows an input channel to be fed from one of the external pins, + * labelled accordingly. *

*/ @SuppressWarnings("unused") @@ -108,13 +109,13 @@ public class PCF8591 extends AbstractDeviceFactory // [6] Analog output enable flag (analog output active if 1) // [7] 0 /** - * If the auto-increment flag is set to 1, the channel number is incremented - * automatically after each A/D conversion. + * If the auto-increment flag is set to 1, the channel number is incremented automatically + * after each A/D conversion. */ private static final byte AUTO_INCREMENT_FLAG = 0b0000_0100; // 0x04 private static final byte ANALOG_OUTPUT_ENABLE_MASK = 0b0100_0000; // 0x40 - private I2CDevice device; + private I2CDeviceInterface device; private boolean outputEnabled = false; private InputMode inputMode; private BoardPinInfo boardPinInfo; diff --git a/diozero-core/src/main/java/com/diozero/devices/PiconZero.java b/diozero-core/src/main/java/com/diozero/devices/PiconZero.java index 8ea4d707..a0c37290 100644 --- a/diozero-core/src/main/java/com/diozero/devices/PiconZero.java +++ b/diozero-core/src/main/java/com/diozero/devices/PiconZero.java @@ -46,6 +46,7 @@ import com.diozero.api.GpioPullUpDown; import com.diozero.api.I2CConstants; import com.diozero.api.I2CDevice; +import com.diozero.api.I2CDeviceInterface; import com.diozero.api.PinInfo; import com.diozero.api.RuntimeIOException; import com.diozero.api.function.DeviceEventConsumer; @@ -127,7 +128,7 @@ public int getValue() { public static final int MIN_MOTOR_VALUE = -128; public static final int SERVO_CENTRE = 90; - private I2CDevice device; + private I2CDeviceInterface device; private BoardPinInfo boardPinInfo; private OutputConfig[] outputConfigs = new OutputConfig[NUM_OUTPUT_CHANNELS]; private InputConfig[] inputConfigs = new InputConfig[NUM_INPUT_CHANNELS]; @@ -197,8 +198,7 @@ private void writeBytes(int register, byte[] data) throws RuntimeIOException { /** * Get the board revision details * - * @return revision[0]: Board type (2 == PiconZero); revision[1]: Firmware - * version + * @return revision[0]: Board type (2 == PiconZero); revision[1]: Firmware version */ public byte[] getRevision() { ByteBuffer buffer = device.readI2CBlockDataByteBuffer(REVISION_REG, 2); @@ -224,8 +224,7 @@ public void setInputConfig(int channel, InputConfig config) { * Set configuration of selected output * * @param channel Output channel (0..5) - * @param config Output configuration (0: Digital, 1: PWM, 2: Servo, 3: - * Neopixel WS2812B) + * @param config Output configuration (0: Digital, 1: PWM, 2: Servo, 3: Neopixel WS2812B) */ public void setOutputConfig(int channel, OutputConfig config) { Logger.debug("setOutputConfig({}, {})", Integer.valueOf(channel), config); @@ -337,8 +336,8 @@ public void setPixel(int pixel, int red, int green, int blue, boolean update) { } /** - * Sets all pixels with the selected red, green and blue values (0 to 255) - * [Available from firmware revision 07] + * Sets all pixels with the selected red, green and blue values (0 to 255) [Available from + * firmware revision 07] * * @param red 0..255 * @param green 0..255 diff --git a/diozero-core/src/main/java/com/diozero/devices/SGP30.java b/diozero-core/src/main/java/com/diozero/devices/SGP30.java index eb6c7650..27e5f300 100644 --- a/diozero-core/src/main/java/com/diozero/devices/SGP30.java +++ b/diozero-core/src/main/java/com/diozero/devices/SGP30.java @@ -42,6 +42,7 @@ import com.diozero.api.DeviceInterface; import com.diozero.api.I2CDevice; +import com.diozero.api.I2CDeviceInterface; import com.diozero.api.I2CDeviceInterface.I2CMessage; import com.diozero.util.Crc; import com.diozero.util.DiozeroScheduler; @@ -116,7 +117,7 @@ public class SGP30 implements DeviceInterface, Runnable { private static final short CMD_SET_TVOC_BASELINE = 0x2077; private static final int CMD_SET_TVOC_BASELINE_DELAY_MS = 10; - private I2CDevice device; + private I2CDeviceInterface device; private long startTimeMs; private ScheduledFuture future; private Consumer measurementListener; @@ -127,7 +128,11 @@ public SGP30(int controller) { } public SGP30(int controller, int address) { - device = I2CDevice.builder(address).setController(controller).setByteOrder(ByteOrder.BIG_ENDIAN).build(); + this(I2CDevice.builder(address).setController(controller).setByteOrder(ByteOrder.BIG_ENDIAN).build()); + } + + public SGP30(I2CDeviceInterface device) { + this.device = device; } public void start(Consumer consumer) { diff --git a/diozero-core/src/main/java/com/diozero/devices/TSL2561.java b/diozero-core/src/main/java/com/diozero/devices/TSL2561.java index 4c59b847..5903bceb 100644 --- a/diozero-core/src/main/java/com/diozero/devices/TSL2561.java +++ b/diozero-core/src/main/java/com/diozero/devices/TSL2561.java @@ -35,12 +35,12 @@ import com.diozero.api.I2CConstants; import com.diozero.api.I2CDevice; +import com.diozero.api.I2CDeviceInterface; import com.diozero.api.RuntimeIOException; import com.diozero.util.SleepUtil; /** - * Datasheet - * Pins: + * Datasheet Pins: * *
  * +-----------------------------+
@@ -170,14 +170,14 @@ public static enum TSL2561Package {
 	private int broadband;
 	private int ir;
 	private TSL2561Package tsl2561Package;
-	private I2CDevice i2cDevice;
+	private I2CDeviceInterface device;
 
 	public TSL2561(TSL2561Package tsl2561Package) throws RuntimeIOException {
 		this(I2CConstants.CONTROLLER_1, tsl2561Package);
 	}
 
 	public TSL2561(int controller, TSL2561Package tsl2561Package) throws RuntimeIOException {
-		i2cDevice = I2CDevice.builder(DEVICE_ADDRESS).setController(controller).setByteOrder(ByteOrder.LITTLE_ENDIAN)
+		device = I2CDevice.builder(DEVICE_ADDRESS).setController(controller).setByteOrder(ByteOrder.LITTLE_ENDIAN)
 				.build();
 
 		this.tsl2561Package = tsl2561Package;
@@ -199,7 +199,7 @@ public void setAutoGain(boolean autoGain) {
 	}
 
 	private boolean begin() throws RuntimeIOException {
-		int x = i2cDevice.readByteData(TSL2561_REGISTER_ID);
+		int x = device.readByteData(TSL2561_REGISTER_ID);
 		// if not(x & 0x0A):
 		if ((x & 0x0A) == 0) {
 			return false;
@@ -221,14 +221,14 @@ private boolean begin() throws RuntimeIOException {
 	 * Enables the device
 	 */
 	private void enable() throws RuntimeIOException {
-		i2cDevice.writeByteData(TSL2561_COMMAND_BIT | TSL2561_REGISTER_CONTROL, TSL2561_CONTROL_POWERON);
+		device.writeByteData(TSL2561_COMMAND_BIT | TSL2561_REGISTER_CONTROL, TSL2561_CONTROL_POWERON);
 	}
 
 	/**
 	 * Disables the device (putting it in lower power sleep mode)
 	 */
 	private void disable() throws RuntimeIOException {
-		i2cDevice.writeByteData(TSL2561_COMMAND_BIT | TSL2561_REGISTER_CONTROL, TSL2561_CONTROL_POWEROFF);
+		device.writeByteData(TSL2561_COMMAND_BIT | TSL2561_REGISTER_CONTROL, TSL2561_CONTROL_POWEROFF);
 	}
 
 	/**
@@ -247,10 +247,10 @@ private void getData() throws RuntimeIOException {
 		}
 
 		// Reads a two byte value from channel 0 (visible + infrared)
-		broadband = i2cDevice.readUShort(TSL2561_COMMAND_BIT | TSL2561_WORD_BIT | TSL2561_REGISTER_CHAN0_LOW);
+		broadband = device.readUShort(TSL2561_COMMAND_BIT | TSL2561_WORD_BIT | TSL2561_REGISTER_CHAN0_LOW);
 
 		// Reads a two byte value from channel 1 (infrared)
-		ir = i2cDevice.readUShort(TSL2561_COMMAND_BIT | TSL2561_WORD_BIT | TSL2561_REGISTER_CHAN1_LOW);
+		ir = device.readUShort(TSL2561_COMMAND_BIT | TSL2561_WORD_BIT | TSL2561_REGISTER_CHAN1_LOW);
 
 		// Turn the device off to save power
 		disable();
@@ -261,7 +261,7 @@ void setIntegrationTime(int time) throws RuntimeIOException {
 		enable();
 
 		// Update the timing register
-		i2cDevice.writeByteData(TSL2561_COMMAND_BIT | TSL2561_REGISTER_TIMING, (byte) (time | gain));
+		device.writeByteData(TSL2561_COMMAND_BIT | TSL2561_REGISTER_TIMING, (byte) (time | gain));
 
 		integrationTime = time;
 
@@ -280,7 +280,7 @@ public void setGain(int gain) throws RuntimeIOException {
 		enable();
 
 		// Update the timing register
-		i2cDevice.writeByteData(TSL2561_COMMAND_BIT | TSL2561_REGISTER_TIMING, (byte) (integrationTime | gain));
+		device.writeByteData(TSL2561_COMMAND_BIT | TSL2561_REGISTER_TIMING, (byte) (integrationTime | gain));
 
 		this.gain = gain;
 
@@ -352,8 +352,8 @@ private void getRawLuminosity() throws RuntimeIOException {
 	}
 
 	/**
-	 * Converts the raw sensor values to the standard SI lux equivalent. Returns 0
-	 * if the sensor is saturated and the values are unreliable.
+	 * Converts the raw sensor values to the standard SI lux equivalent. Returns 0 if the
+	 * sensor is saturated and the values are unreliable.
 	 */
 	@Override
 	public float getLuminosity() throws RuntimeIOException {
@@ -483,6 +483,6 @@ public float getLuminosity() throws RuntimeIOException {
 
 	@Override
 	public void close() {
-		i2cDevice.close();
+		device.close();
 	}
 }
diff --git a/diozero-core/src/main/java/com/diozero/devices/sandpit/Max30102.java b/diozero-core/src/main/java/com/diozero/devices/sandpit/Max30102.java
index 96d9bbd5..c8beba33 100644
--- a/diozero-core/src/main/java/com/diozero/devices/sandpit/Max30102.java
+++ b/diozero-core/src/main/java/com/diozero/devices/sandpit/Max30102.java
@@ -50,8 +50,7 @@
 
 /**
  * maxim integrated High-sensitivity Pulse Oximeter and Heart-rate Sensor.
- * Datasheet
+ * Datasheet
  *
  * 
  * INT  IRD  RD   GND
@@ -69,8 +68,8 @@
  * select 1.8v or 3_3v (this terminal contains 3.3V and above)
  * 
* - * The active-low interrupt pin pulls low when an interrupt is triggered. The - * pin is open-drain, meaning it requires a pull-up resistor (min 4.7kOhm). + * The active-low interrupt pin pulls low when an interrupt is triggered. The pin is + * open-drain, meaning it requires a pull-up resistor (min 4.7kOhm). * * Credit to: * https://makersportal.com/blog/2019/6/24/arduino-heart-rate-monitor-using-max30102-and-pulse-oximetry @@ -115,10 +114,9 @@ public class Max30102 implements DeviceInterface { /** * FIFO Almost Full Flag bit mask. * - * In SpO2 and HR modes, this interrupt triggers when the FIFO write pointer has - * a certain number of free spaces remaining. The trigger can be set by the - * FIFO_A_FULL[3:0] register. The interrupt is cleared by reading the Interrupt - * Status 1 register (0x00). + * In SpO2 and HR modes, this interrupt triggers when the FIFO write pointer has a certain + * number of free spaces remaining. The trigger can be set by the FIFO_A_FULL[3:0] + * register. The interrupt is cleared by reading the Interrupt Status 1 register (0x00). */ private static final int INT1_FIFO_ALMOST_FULL_MASK = 1 << INT1_FIFO_ALMOST_FULL_BIT; @@ -126,9 +124,9 @@ public class Max30102 implements DeviceInterface { /** * New FIFO Data Ready bit mask. * - * In SpO2 and HR modes, this interrupt triggers when there is a new sample in - * the data FIFO. The interrupt is cleared by reading the Interrupt Status 1 - * register (0x00), or by reading the FIFO_DATA register. + * In SpO2 and HR modes, this interrupt triggers when there is a new sample in the data + * FIFO. The interrupt is cleared by reading the Interrupt Status 1 register (0x00), or by + * reading the FIFO_DATA register. */ private static final byte INT1_PPG_RDY_DATA_MASK = 1 << INT1_PPG_RDY_BIT; @@ -136,10 +134,10 @@ public class Max30102 implements DeviceInterface { /** * Ambient Light Cancellation Overflow bit mask. * - * Ambient Light Cancellation Overflow This interrupt triggers when the ambient - * light cancellation function of the SpO2/HR photodiode has reached its maximum - * limit, and therefore, ambient light is affecting the output of the ADC. The - * interrupt is cleared by reading the Interrupt Status 1 register (0x00). + * Ambient Light Cancellation Overflow This interrupt triggers when the ambient light + * cancellation function of the SpO2/HR photodiode has reached its maximum limit, and + * therefore, ambient light is affecting the output of the ADC. The interrupt is cleared + * by reading the Interrupt Status 1 register (0x00). */ private static final byte INT1_ALC_OVF_MASK = 1 << INT1_ALC_OVF_BIT; @@ -150,8 +148,8 @@ public class Max30102 implements DeviceInterface { * On power-up a power-ready interrupt is triggered to signal that the module is * powered-up and ready to collect data. * - * Note can only be read from the Interrupt Status 1 register, cannot be written - * to the Interrupt Enable 1 register. + * Note can only be read from the Interrupt Status 1 register, cannot be written to the + * Interrupt Enable 1 register. */ private static final byte INT1_PWR_RDY_MASK = 1 << INT1_PWR_RDY_BIT; @@ -161,17 +159,16 @@ public class Max30102 implements DeviceInterface { /** * Internal Temperature Ready Flag bit mask. * - * When an internal die temperature conversion is finished, this interrupt is - * triggered so the processor can read the temperature data registers. The - * interrupt is cleared by reading either the Interrupt Status 2 register (0x01) - * or the TFRAC register (0x20). + * When an internal die temperature conversion is finished, this interrupt is triggered so + * the processor can read the temperature data registers. The interrupt is cleared by + * reading either the Interrupt Status 2 register (0x01) or the TFRAC register (0x20). */ private static final byte INT2_DIE_TEMP_RDY_MASK = 1 << INT2_DIE_TEMP_RDY_BIT; // FIFO Config (0x08) // Mode Configuration (0x09) - + private static final int MODE_CONFIG_SHUTDOWN_BIT = 7; private static final int MODE_CONFIG_SHUTDOWN_MASK = 1 << MODE_CONFIG_SHUTDOWN_BIT; private static final int MODE_CONFIG_RESET_BIT = 6; @@ -197,18 +194,15 @@ byte getMask() { } /** - * Controls the behaviour of the FIFO when it becomes completely filled with - * data + * Controls the behaviour of the FIFO when it becomes completely filled with data */ public enum FifoRolloverOnFull { /** - * The FIFO address rolls over to zero and the FIFO continues to fill with new - * data + * The FIFO address rolls over to zero and the FIFO continues to fill with new data */ ENABLED(1), /** - * The FIFO is not updated until FIFO_DATA is read or the WRITE/READ positions - * are changed + * The FIFO is not updated until FIFO_DATA is read or the WRITE/READ positions are changed */ DISABLED(0); @@ -324,7 +318,7 @@ public int getAdcResolution() { } } - private I2CDevice device; + private I2CDeviceInterface device; private int revisionId; private Mode mode; private SampleAveraging sampleAveraging; @@ -417,14 +411,12 @@ private byte getPartId() { * * @param sampleAveraging number of samples averaged per FIFO sample * @param fifoRolloverOnFull whether or not the FIFO rolls over when full - * @param fifoAlmostFullValue set the number of data samples remaining in the - * FIFO when the interrupt is issued (range 0..15). - * E.g. if set to 0, the interrupt is issued when - * there are no data samples remaining in the FIFO - * (all 32 FIFO words have unread data, i.e. the FIFO - * is full), if set to 15, the interrupt is issued - * when there are 15 data samples remaining in the - * FIFO (17 unread) + * @param fifoAlmostFullValue set the number of data samples remaining in the FIFO when + * the interrupt is issued (range 0..15). E.g. if set to 0, the + * interrupt is issued when there are no data samples remaining + * in the FIFO (all 32 FIFO words have unread data, i.e. the + * FIFO is full), if set to 15, the interrupt is issued when + * there are 15 data samples remaining in the FIFO (17 unread) * @param mode Operating mode * @param spo2AdcRange SpO2 ADC range * @param spo2SampleRate SpO2 sample rate @@ -604,8 +596,8 @@ public float readTemperatureCelsius() { } /** - * Poll the sensor for new data - call regularly. If new data is available, it - * adds data to the queues + * Poll the sensor for new data - call regularly. If new data is available, it adds data + * to the queues * * @return number of new samples obtained */ @@ -618,8 +610,8 @@ public int pollForData() { SleepUtil.sleepMillis(1); } /* - * The write pointer increments every time a new sample is added to the FIFO. - * The read pointer is incremented every time a sample is read from the FIFO. + * The write pointer increments every time a new sample is added to the FIFO. The read + * pointer is incremented every time a sample is read from the FIFO. */ int fifo_read_ptr = getFifoReadPointer(); int fifo_write_ptr = getFifoWritePointer(); @@ -638,10 +630,9 @@ public int pollForData() { } /* - * The data FIFO consists of a 32-sample memory bank that can store IR and Red - * ADC data. Since each sample consists of two channels of data, there are 6 - * bytes of data for each sample, and therefore 192 total bytes of data can be - * stored in the FIFO. + * The data FIFO consists of a 32-sample memory bank that can store IR and Red ADC data. + * Since each sample consists of two channels of data, there are 6 bytes of data for each + * sample, and therefore 192 total bytes of data can be stored in the FIFO. */ // Heart rate mode activates the Red LED only, SpO2 and Multi-mode activate Red // and IR diff --git a/diozero-core/src/main/java/com/diozero/devices/sandpit/VL6180.java b/diozero-core/src/main/java/com/diozero/devices/sandpit/VL6180.java index f97ebfdd..4edd762a 100644 --- a/diozero-core/src/main/java/com/diozero/devices/sandpit/VL6180.java +++ b/diozero-core/src/main/java/com/diozero/devices/sandpit/VL6180.java @@ -38,6 +38,7 @@ import org.tinylog.Logger; import com.diozero.api.I2CDevice; +import com.diozero.api.I2CDeviceInterface; import com.diozero.api.I2CDeviceInterface.I2CMessage; import com.diozero.api.RuntimeIOException; import com.diozero.devices.DistanceSensorInterface; @@ -46,20 +47,17 @@ /** * References: * */ public class VL6180 implements DistanceSensorInterface { @@ -129,7 +127,7 @@ public class VL6180 implements DistanceSensorInterface { private static final int DEFAULT_ADDRESS = 0x29; public static final byte VL6180_MODEL_ID = (byte) 0xb4; - private I2CDevice device; + private I2CDeviceInterface device; private short modelId; private short modelMajor; private short modelMinor; diff --git a/diozero-core/src/main/java/com/diozero/devices/sandpit/WaveshareEink.java b/diozero-core/src/main/java/com/diozero/devices/sandpit/WaveshareEink.java index c4524fe1..2c705f6e 100644 --- a/diozero-core/src/main/java/com/diozero/devices/sandpit/WaveshareEink.java +++ b/diozero-core/src/main/java/com/diozero/devices/sandpit/WaveshareEink.java @@ -36,19 +36,19 @@ import com.diozero.api.DigitalOutputDevice; import com.diozero.api.RuntimeIOException; import com.diozero.api.SpiDevice; +import com.diozero.api.SpiDeviceInterface; import com.diozero.util.SleepUtil; /** - * 7.5" Datasheet: - * https://www.waveshare.com/wiki/File:7.5inch-e-paper-specification.pdf 7.5" V2 - * Datasheet: + * 7.5" Datasheet: https://www.waveshare.com/wiki/File:7.5inch-e-paper-specification.pdf + * 7.5" V2 Datasheet: * https://www.waveshare.com/w/upload/6/60/7.5inch_e-Paper_V2_Specification.pdf * https://www.waveshare.com/wiki/7.5inch_e-Paper_HAT * * Code: https://github.com/waveshare/e-Paper * - * OTP: One Time Programmable memory, not programmed into registers by the - * driver SW for this controller. LUT: Waveform Look Up Table + * OTP: One Time Programmable memory, not programmed into registers by the driver SW for + * this controller. LUT: Waveform Look Up Table */ public abstract class WaveshareEink implements DeviceInterface { public enum Model { @@ -73,7 +73,7 @@ public int getHeight() { } protected Model model; - protected SpiDevice device; + protected SpiDeviceInterface device; protected DigitalOutputDevice reset; protected DigitalOutputDevice dataOrCommand; protected DigitalInputDevice busy; diff --git a/diozero-core/src/main/java/com/diozero/internal/provider/builtin/i2c/NativeI2CDeviceJavaRaf.java b/diozero-core/src/main/java/com/diozero/internal/provider/builtin/i2c/NativeI2CDeviceJavaRaf.java index 13a9deeb..5747233d 100644 --- a/diozero-core/src/main/java/com/diozero/internal/provider/builtin/i2c/NativeI2CDeviceJavaRaf.java +++ b/diozero-core/src/main/java/com/diozero/internal/provider/builtin/i2c/NativeI2CDeviceJavaRaf.java @@ -48,13 +48,12 @@ /** *

* Native Java implementation of the I2C SMBus commands using a Java - * {@link RandomAccessFile} to read to and write from the device. Makes use of a - * single native method to select the slave address. + * {@link RandomAccessFile} to read to and write from the device. Makes use of a single + * native method to select the slave address. *

* *

- * Reference - * Kernel + * Reference Kernel * I2C dev interface and * SMBus * Protocol. @@ -120,6 +119,16 @@ public boolean probe(I2CDevice.ProbeMode mode) { } } + @Override + public int getController() { + return controller; + } + + @Override + public int getAddress() { + return deviceAddress; + } + @Override public void writeQuick(byte bit) { throw new UnsupportedOperationException("I2C write quick isn't possible via sysfs"); diff --git a/diozero-core/src/main/java/com/diozero/internal/provider/builtin/i2c/NativeI2CDeviceSMBus.java b/diozero-core/src/main/java/com/diozero/internal/provider/builtin/i2c/NativeI2CDeviceSMBus.java index ce5d1801..995df0de 100644 --- a/diozero-core/src/main/java/com/diozero/internal/provider/builtin/i2c/NativeI2CDeviceSMBus.java +++ b/diozero-core/src/main/java/com/diozero/internal/provider/builtin/i2c/NativeI2CDeviceSMBus.java @@ -48,15 +48,14 @@ * JNI wrapper of SMBus interface. *

*

- * Reference - * Kernel + * Reference Kernel * I2C dev interface and * SMBus * Protocol. *

*

- * See i2c-dev + * See + * i2c-dev * for a definition of the in-line functions. *

*/ @@ -105,11 +104,13 @@ public NativeI2CDeviceSMBus(DeviceFactoryInterface deviceFactory, String key, in Logger.debug("I2C_FUNCS for controller {}: 0x{}", Integer.toString(controller), Integer.toHexString(funcs)); } + @Override public int getController() { return controller; } - public int getDeviceAddress() { + @Override + public int getAddress() { return deviceAddress; } @@ -313,7 +314,7 @@ public void writeWordSwapped(int registerAddress, short data) throws I2CExceptio throw new UnsupportedOperationException( "Function I2C_FUNC_SMBUS_WRITE_WORD_DATA isn't supported for device " + getKey()); } - + int rc = EAGAIN; for (int i = 0; i < numRetries && (rc == EAGAIN || rc == ETIMEDOUT); i++) { rc = NativeI2C.writeWordSwapped(fd, registerAddress, data); diff --git a/diozero-core/src/main/java/com/diozero/internal/spi/InternalI2CDeviceInterface.java b/diozero-core/src/main/java/com/diozero/internal/spi/InternalI2CDeviceInterface.java index f254ae3b..b68d0bc1 100644 --- a/diozero-core/src/main/java/com/diozero/internal/spi/InternalI2CDeviceInterface.java +++ b/diozero-core/src/main/java/com/diozero/internal/spi/InternalI2CDeviceInterface.java @@ -1,5 +1,7 @@ package com.diozero.internal.spi; +import java.nio.ByteOrder; + /*- * #%L * Organisation: diozero @@ -34,5 +36,8 @@ import com.diozero.api.I2CDeviceInterface; public interface InternalI2CDeviceInterface extends InternalDeviceInterface, I2CDeviceInterface { - + @Override + default ByteOrder getByteOrder() { + throw new UnsupportedOperationException("Only implemented in com.diozero.api"); + } } diff --git a/diozero-core/src/main/resources/boarddefs/friendlyarm_nanopi-duo2.txt b/diozero-core/src/main/resources/boarddefs/friendlyarm_nanopi-duo2.txt index 89d70eb2..9b1b6cca 100644 --- a/diozero-core/src/main/resources/boarddefs/friendlyarm_nanopi-duo2.txt +++ b/diozero-core/src/main/resources/boarddefs/friendlyarm_nanopi-duo2.txt @@ -20,18 +20,18 @@ General, DEFAULT, 31, EPhySPD General, DEFAULT, 32, MIC_N # GPIOA=0-31, B=32-63, C=64-95, D=96-127, E=128-159, F=160-192, G=192-223, H=224-255,I=256-287, J=288-319, K=320-351, L=352-383 -# GPIO, Header, GPIO#, Name, Physical, Chip, Line, Modes -PWM, DEFAULT, 5, PWM0, 2, 0, 5, 0, 0, DIGITAL_INPUT | DIGITAL_OUTPUT | PWM_OUTPUT # PA5 (5): UART_RXD0 (2) / PWM (3) -GPIO, DEFAULT, 4, PA4, 4, 0, 4, DIGITAL_INPUT | DIGITAL_OUTPUT # PA4 (4): UART_TXD0 (2) -GPIO, DEFAULT, 11, I2C0_SCL, 8, 0, 11, DIGITAL_INPUT | DIGITAL_OUTPUT # PA11 (11): I2C0_SCL (2) -GPIO, DEFAULT, 363, PL11, 9, 1, 11, DIGITAL_INPUT | DIGITAL_OUTPUT # PL11 (363) -GPIO, DEFAULT, 12, I2C0_SDA, 10, 0, 12, DIGITAL_INPUT | DIGITAL_OUTPUT # PA12 (12): I2C0_SDA (2), UART -GPIO, DEFAULT, 203, PG11, 11, 0, 203, DIGITAL_INPUT | DIGITAL_OUTPUT # PG11 (203) -GPIO, DEFAULT, 13, PA13, 12, 0, 13, DIGITAL_INPUT | DIGITAL_OUTPUT # PA13 (13): SPI1_CS (2), UART3_TX (3) -GPIO, DEFAULT, 14, PA14, 14, 0, 14, DIGITAL_INPUT | DIGITAL_OUTPUT # PA14 (14): SPI1_CLK (2), UART3_RX (3) -GPIO, DEFAULT, 15, PA15, 18, 0, 15, DIGITAL_INPUT | DIGITAL_OUTPUT # PA15 (15): SPI1_MISO (2), UART3_CTS (3) -GPIO, DEFAULT, 16, PA16, 16, 0, 16, DIGITAL_INPUT | DIGITAL_OUTPUT # PA16 (16): SPI1_MOSI (2), UART3_RTS (3) -GPIO, DEFAULT, 199, PG7, 20, 0, 199, DIGITAL_INPUT | DIGITAL_OUTPUT # PG7 (199): UART1_RX (2) -GPIO, DEFAULT, 198, PG6, 22, 0, 198, DIGITAL_INPUT | DIGITAL_OUTPUT # PG6 (198): UART1_TX (2) +# GPIO, Header, GPIO#, Name, Physical, Chip, Line, Modes +PWM, DEFAULT, 5, PWM0, 2, 0, 5, 0, 0, DIGITAL_INPUT | DIGITAL_OUTPUT | PWM_OUTPUT # PA5 (5): UART_RXD0 (2) / PWM (3) +GPIO, DEFAULT, 4, PA4, 4, 0, 4, DIGITAL_INPUT | DIGITAL_OUTPUT # PA4 (4): UART_TXD0 (2) +GPIO, DEFAULT, 11, I2C0_SCL, 8, 0, 11, DIGITAL_INPUT | DIGITAL_OUTPUT # PA11 (11): I2C0_SCL (2) +GPIO, DEFAULT, 363, PL11, 9, 1, 11, DIGITAL_INPUT | DIGITAL_OUTPUT # PL11 (363): IRRX? +GPIO, DEFAULT, 12, I2C0_SDA, 10, 0, 12, DIGITAL_INPUT | DIGITAL_OUTPUT # PA12 (12): I2C0_SDA (2), UART +GPIO, DEFAULT, 203, PG11, 11, 0, 203, DIGITAL_INPUT | DIGITAL_OUTPUT # PG11 (203) +GPIO, DEFAULT, 13, PA13, 12, 0, 13, DIGITAL_INPUT | DIGITAL_OUTPUT # PA13 (13): SPI1_CS (2), UART3_TX (3) +GPIO, DEFAULT, 14, PA14, 14, 0, 14, DIGITAL_INPUT | DIGITAL_OUTPUT # PA14 (14): SPI1_CLK (2), UART3_RX (3) +GPIO, DEFAULT, 15, PA15, 18, 0, 15, DIGITAL_INPUT | DIGITAL_OUTPUT # PA15 (15): SPI1_MISO (2), UART3_CTS (3) +GPIO, DEFAULT, 16, PA16, 16, 0, 16, DIGITAL_INPUT | DIGITAL_OUTPUT # PA16 (16): SPI1_MOSI (2), UART3_RTS (3) +GPIO, DEFAULT, 199, PG7, 20, 0, 199, DIGITAL_INPUT | DIGITAL_OUTPUT # PG7 (199): UART1_RX (2) +GPIO, DEFAULT, 198, PG6, 22, 0, 198, DIGITAL_INPUT | DIGITAL_OUTPUT # PG6 (198): UART1_TX (2) # These start at 352 rather than 224 (224+128)... -GPIO, DEFAULT, 355, BUTTON, -1, 1, 3, DIGITAL_INPUT # PL3 (355) +GPIO, DEFAULT, 355, BUTTON, -1, 1, 3, DIGITAL_INPUT # PL3 (355) diff --git a/diozero-core/src/test/java/com/diozero/internal/provider/test/TestI2CDevice.java b/diozero-core/src/test/java/com/diozero/internal/provider/test/TestI2CDevice.java index de5beaa0..b7fc6aa1 100644 --- a/diozero-core/src/test/java/com/diozero/internal/provider/test/TestI2CDevice.java +++ b/diozero-core/src/test/java/com/diozero/internal/provider/test/TestI2CDevice.java @@ -42,9 +42,15 @@ import com.diozero.util.Hex; public class TestI2CDevice extends AbstractDevice implements InternalI2CDeviceInterface { + private int controller; + private int address; + public TestI2CDevice(String key, DeviceFactoryInterface deviceFactory, int controller, int address, I2CConstants.AddressSize addressSize) { super(key, deviceFactory); + + this.controller = controller; + this.address = address; } @Override @@ -57,6 +63,16 @@ public boolean probe(I2CDevice.ProbeMode mode) { return true; } + @Override + public int getController() { + return controller; + } + + @Override + public int getAddress() { + return address; + } + @Override public void writeQuick(byte bit) { // TODO Auto-generated method stub diff --git a/diozero-imu-devices/src/main/java/com/diozero/devices/imu/ADXL345.java b/diozero-imu-devices/src/main/java/com/diozero/devices/imu/ADXL345.java index 7385b077..464ad0d7 100644 --- a/diozero-imu-devices/src/main/java/com/diozero/devices/imu/ADXL345.java +++ b/diozero-imu-devices/src/main/java/com/diozero/devices/imu/ADXL345.java @@ -38,6 +38,7 @@ import com.diozero.api.I2CConstants; import com.diozero.api.I2CDevice; +import com.diozero.api.I2CDeviceInterface; import com.diozero.api.RuntimeIOException; import com.diozero.util.BitManipulation; @@ -120,7 +121,7 @@ public class ADXL345 implements ImuInterface { private static final float FREEFALL_TIME_RANGE = 1280; private static final float FREEFALL_TIME_LSB = FREEFALL_TIME_RANGE / 0xff; - private I2CDevice device; + private I2CDeviceInterface device; public ADXL345() { device = I2CDevice.builder(ADXL345_ADDRESS).setController(I2CConstants.CONTROLLER_1).build(); @@ -222,8 +223,8 @@ public float getTapDuration() { /** * Set the tap duration in mS * - * @param tapDuration The maximum time in ms that an event must be above to - * qualify as a tap event + * @param tapDuration The maximum time in ms that an event must be above to qualify as a + * tap event */ public void setTapDuration(float tapDuration) { if (tapDuration < 0 || tapDuration > TAP_DURATION_MS_RANGE) { @@ -245,9 +246,9 @@ public float getTapLatency() { /** * Set the tap latency in mS * - * @param tapLatency The wait time in mS from the detection of a tap event to - * the start of the time window during which a possible second - * tap event can be detected + * @param tapLatency The wait time in mS from the detection of a tap event to the start of + * the time window during which a possible second tap event can be + * detected */ public void setTapLatency(float tapLatency) { if (tapLatency < 0 || tapLatency > TAP_LATENCY_MS_RANGE) { @@ -269,8 +270,8 @@ public float getTapWindow() { /** * Set the tap window in mS * - * @param tapWindow The amount of time in milliseconds after the expiration of - * the latency time during which a second valid tap can begin + * @param tapWindow The amount of time in milliseconds after the expiration of the latency + * time during which a second valid tap can begin */ public void setTapWindow(float tapWindow) { if (tapWindow < 0 || tapWindow > TAP_WINDOW_MS_RANGE) { @@ -321,9 +322,9 @@ public float getInactivityTime() { /** * Set the inactivity time value in mS * - * @param inactivityTime Value representing the amount of time that acceleration - * must be less than the value in the THRESH_INACT - * register for inactivity to be declared + * @param inactivityTime Value representing the amount of time that acceleration must be + * less than the value in the THRESH_INACT register for inactivity + * to be declared */ public void setInactivityTime(float inactivityTime) { if (inactivityTime < 0 || inactivityTime > INACTIVITY_TIME_RANGE) { @@ -334,25 +335,22 @@ public void setInactivityTime(float inactivityTime) { } /** - * D7 - Activity ac/dc D6 - ACT_X enable D5 - ACT_Y enable D4 - ACT_Z enable D3 - * - Inactivity ac/dc D2 - INACT_X enable D1 - INACT_Y enable D0 - INACT_Z - * enable + * D7 - Activity ac/dc D6 - ACT_X enable D5 - ACT_Y enable D4 - ACT_Z enable D3 - + * Inactivity ac/dc D2 - INACT_X enable D1 - INACT_Y enable D0 - INACT_Z enable * - * A setting of 0 selects dc-coupled operation, and a setting of 1 enables - * ac-coupled operation. In dc-coupled operation, the current acceleration - * magnitude is compared directly with THRESH_ACT and THRESH_INACT to determine - * whether activity or inactivity is detected. In ac-coupled operation for - * activity detection, the acceleration value at the start of activity detection - * is taken as a reference value. New samples of acceleration are then compared - * to this reference value, and if the magnitude of the difference exceeds the - * THRESH_ACT value, the device triggers an activity interrupt. Similarly, in - * ac-coupled operation for inactivity detection, a reference value is used for - * comparison and is updated whenever the device exceeds the inactivity - * threshold. After the reference value is selected, the device compares the - * magnitude of the difference between the reference value and the current - * acceleration with THRESH_INACT. If the difference is less than the value in - * THRESH_INACT for the time in TIME_INACT, the device is considered inactive - * and the inactivity interrupt is triggered. + * A setting of 0 selects dc-coupled operation, and a setting of 1 enables ac-coupled + * operation. In dc-coupled operation, the current acceleration magnitude is compared + * directly with THRESH_ACT and THRESH_INACT to determine whether activity or inactivity + * is detected. In ac-coupled operation for activity detection, the acceleration value at + * the start of activity detection is taken as a reference value. New samples of + * acceleration are then compared to this reference value, and if the magnitude of the + * difference exceeds the THRESH_ACT value, the device triggers an activity interrupt. + * Similarly, in ac-coupled operation for inactivity detection, a reference value is used + * for comparison and is updated whenever the device exceeds the inactivity threshold. + * After the reference value is selected, the device compares the magnitude of the + * difference between the reference value and the current acceleration with THRESH_INACT. + * If the difference is less than the value in THRESH_INACT for the time in TIME_INACT, + * the device is considered inactive and the inactivity interrupt is triggered. * * @return Activity / inativity control flags */ @@ -388,9 +386,8 @@ public float getFreefallTime() { /** * Set the freefall time value in mS * - * @param freefallTime Value representing minimum time that the value of all - * axes must be less than THRESH_FF to generate a freefall - * interrupt + * @param freefallTime Value representing minimum time that the value of all axes must be + * less than THRESH_FF to generate a freefall interrupt */ public void setFreefallTime(float freefallTime) { if (freefallTime < 0 || freefallTime > FREEFALL_TIME_RANGE) { @@ -505,24 +502,22 @@ public void setAccelFsr(int range) { } /** - * D7 D6 | D5 | D4 D3 D2 D1 D0 FIFO_MODE | Trigger | Samples FIFO modes: 0 - * Bypass - FIFO is bypassed 1 FIFO - FIFO collects up to 32 values and then - * stops collecting data, collecting new data only when FIFO is not full 2 - * Stream - FIFO holds the last 32 data values. When FIFO is full, the oldest - * data is overwritten with newer data 3 Trigger - When triggered by the trigger - * bit, FIFO holds the last data samples before the trigger event and then - * continues to collect data until full. New data is collected only when FIFO is - * not full Trigger bit: A value of 0 in the trigger bit links the trigger event - * of trigger mode to INT1, and a value of 1 links the trigger event to INT2 - * Samples: The function of these bits depends on the FIFO mode selected (see - * below). Entering a value of 0 in the samples bits immediately sets the - * watermark status bit in the INT_SOURCE register, regardless of which FIFO - * mode is selected. Undesirable operation may occur if a value of 0 is used for - * the samples bits when trigger mode is used FIFO Mode | Samples Bits Function - * Bypass | None. FIFO | Specifies how many FIFO entries are needed to trigger a - * watermark interrupt. Stream | Specifies how many FIFO entries are needed to - * trigger a watermark interrupt. Trigger | Specifies how many FIFO samples are - * retained in the FIFO buffer before a trigger event. + * D7 D6 | D5 | D4 D3 D2 D1 D0 FIFO_MODE | Trigger | Samples FIFO modes: 0 Bypass - FIFO + * is bypassed 1 FIFO - FIFO collects up to 32 values and then stops collecting data, + * collecting new data only when FIFO is not full 2 Stream - FIFO holds the last 32 data + * values. When FIFO is full, the oldest data is overwritten with newer data 3 Trigger - + * When triggered by the trigger bit, FIFO holds the last data samples before the trigger + * event and then continues to collect data until full. New data is collected only when + * FIFO is not full Trigger bit: A value of 0 in the trigger bit links the trigger event + * of trigger mode to INT1, and a value of 1 links the trigger event to INT2 Samples: The + * function of these bits depends on the FIFO mode selected (see below). Entering a value + * of 0 in the samples bits immediately sets the watermark status bit in the INT_SOURCE + * register, regardless of which FIFO mode is selected. Undesirable operation may occur if + * a value of 0 is used for the samples bits when trigger mode is used FIFO Mode | Samples + * Bits Function Bypass | None. FIFO | Specifies how many FIFO entries are needed to + * trigger a watermark interrupt. Stream | Specifies how many FIFO entries are needed to + * trigger a watermark interrupt. Trigger | Specifies how many FIFO samples are retained + * in the FIFO buffer before a trigger event. * * @return FIFO Control flags */ @@ -535,15 +530,14 @@ public void setFifoControlFlags(byte flags) { } /** - * D7 | D6 | D5 D4 D3 D2 D1 D0 FIFO Trig | 0 | Entries FIFO Trig: A 1 in the - * FIFO_TRIG bit corresponds to a trigger event occurring, and a 0 means that a - * FIFO trigger event has not occurred Entries: These bits report how many data - * values are stored in FIFO. Access to collect the data from FIFO is provided - * through the DATAX, DATAY, and DATAZ registers. FIFO reads must be done in - * burst or multiple-byte mode because each FIFO level is cleared after any read - * (single-or multiple-byte) of FIFO. FIFO stores a maximum of 32 entries, which - * equates to a maximum of 33 entries available at any given time because an - * additional entry is available at the output filter of the device. + * D7 | D6 | D5 D4 D3 D2 D1 D0 FIFO Trig | 0 | Entries FIFO Trig: A 1 in the FIFO_TRIG bit + * corresponds to a trigger event occurring, and a 0 means that a FIFO trigger event has + * not occurred Entries: These bits report how many data values are stored in FIFO. Access + * to collect the data from FIFO is provided through the DATAX, DATAY, and DATAZ + * registers. FIFO reads must be done in burst or multiple-byte mode because each FIFO + * level is cleared after any read (single-or multiple-byte) of FIFO. FIFO stores a + * maximum of 32 entries, which equates to a maximum of 33 entries available at any given + * time because an additional entry is available at the output filter of the device. * * @return FIFO status */ diff --git a/diozero-imu-devices/src/main/java/com/diozero/devices/imu/invensense/AK8975Driver.java b/diozero-imu-devices/src/main/java/com/diozero/devices/imu/invensense/AK8975Driver.java index 5dc2e003..99b45b79 100644 --- a/diozero-imu-devices/src/main/java/com/diozero/devices/imu/invensense/AK8975Driver.java +++ b/diozero-imu-devices/src/main/java/com/diozero/devices/imu/invensense/AK8975Driver.java @@ -33,16 +33,17 @@ import com.diozero.api.DeviceInterface; import com.diozero.api.I2CDevice; +import com.diozero.api.I2CDeviceInterface; import com.diozero.api.RuntimeIOException; import com.diozero.util.SleepUtil; /** - * Output data resolution is 13 bit (0.3 uT per LSB), Full scale measurement - * range is +/-1200 uT + * Output data resolution is 13 bit (0.3 uT per LSB), Full scale measurement range is + * +/-1200 uT */ public class AK8975Driver implements DeviceInterface, AK8975Constants { private short[] mag_sens_adj = new short[3]; - private I2CDevice i2cDevice; + private I2CDeviceInterface i2cDevice; public AK8975Driver(int controller) throws RuntimeIOException { this(controller, AK8975_MAG_ADDRESS); diff --git a/diozero-imu-devices/src/main/java/com/diozero/devices/imu/invensense/MPU9150Driver.java b/diozero-imu-devices/src/main/java/com/diozero/devices/imu/invensense/MPU9150Driver.java index 18eaf148..7ddf9bb6 100644 --- a/diozero-imu-devices/src/main/java/com/diozero/devices/imu/invensense/MPU9150Driver.java +++ b/diozero-imu-devices/src/main/java/com/diozero/devices/imu/invensense/MPU9150Driver.java @@ -38,6 +38,7 @@ import com.diozero.api.DeviceInterface; import com.diozero.api.I2CDevice; +import com.diozero.api.I2CDeviceInterface; import com.diozero.api.RuntimeIOException; import com.diozero.util.SleepUtil; @@ -73,8 +74,8 @@ public class MPU9150Driver implements DeviceInterface, MPU9150Constants, AK8975C /* true if devices on auxiliary I2C bus appear on the primary. */ private Boolean bypass_mode; /* - * true if half-sensitivity. NOTE: This doesn't belong here, but everything else - * in hw_s is const, and this allows us to save some precious RAM. + * true if half-sensitivity. NOTE: This doesn't belong here, but everything else in hw_s + * is const, and this allows us to save some precious RAM. */ private boolean accel_half; /* true if device in low-power accel-only mode. */ @@ -96,7 +97,7 @@ public class MPU9150Driver implements DeviceInterface, MPU9150Constants, AK8975C private int compass_sample_rate; private byte compass_addr; private AK8975Driver magSensor; - private I2CDevice i2cDevice; + private I2CDeviceInterface i2cDevice; /** * Default constructor, uses default I2C address. @@ -129,8 +130,8 @@ public void close() throws RuntimeIOException { } /** - * Enable/disable data ready interrupt. If the DMP is on, the DMP interrupt is - * enabled. Otherwise, the data ready interrupt is used. + * Enable/disable data ready interrupt. If the DMP is on, the DMP interrupt is enabled. + * Otherwise, the data ready interrupt is used. * * @param enable 1 to enable interrupt. * @return success status @@ -168,9 +169,9 @@ public boolean set_int_enable(boolean enable) throws RuntimeIOException { } /** - * Initialize hardware. Initial configuration: Gyro FSR: +/- 2000DPS Accel FSR - * +/- 2G DLPF: 42Hz FIFO rate: 50Hz Clock source: Gyro PLL FIFO: Disabled. Data - * ready interrupt: Disabled, active low, unlatched. + * Initialize hardware. Initial configuration: Gyro FSR: +/- 2000DPS Accel FSR +/- 2G + * DLPF: 42Hz FIFO rate: 50Hz Clock source: Gyro PLL FIFO: Disabled. Data ready interrupt: + * Disabled, active low, unlatched. * * @throws RuntimeIOException if an I/O error occurs */ @@ -222,13 +223,13 @@ public void mpu_init() throws RuntimeIOException { } /** - * Enter low-power accel-only mode. In low-power accel mode, the chip goes to - * sleep and only wakes up to sample the accelerometer at one of the following - * frequencies: MPU6050: 1.25Hz, 5Hz, 20Hz, 40Hz MPU6500: 1.25Hz, 2.5Hz, 5Hz, - * 10Hz, 20Hz, 40Hz, 80Hz, 160Hz, 320Hz, 640Hz If the requested rate is not one - * listed above, the device will be set to the next highest rate. Requesting a - * rate above the maximum supported frequency will result in an error. To select - * a fractional wake-up frequency, round down the value passed to rate. + * Enter low-power accel-only mode. In low-power accel mode, the chip goes to sleep and + * only wakes up to sample the accelerometer at one of the following frequencies: MPU6050: + * 1.25Hz, 5Hz, 20Hz, 40Hz MPU6500: 1.25Hz, 2.5Hz, 5Hz, 10Hz, 20Hz, 40Hz, 80Hz, 160Hz, + * 320Hz, 640Hz If the requested rate is not one listed above, the device will be set to + * the next highest rate. Requesting a rate above the maximum supported frequency will + * result in an error. To select a fractional wake-up frequency, round down the value + * passed to rate. * * @param rate Minimum sampling rate, or zero to disable LP accel mode. * @return true if successful. @@ -249,10 +250,9 @@ public boolean mpu_lp_accel_mode(int rate) throws RuntimeIOException { return true; } /* - * For LP accel, we automatically configure the hardware to produce latched - * interrupts. In LP accel mode, the hardware cycles into sleep mode before it - * gets a chance to deassert the interrupt pin; therefore, we shift this - * responsibility over to the MCU. + * For LP accel, we automatically configure the hardware to produce latched interrupts. In + * LP accel mode, the hardware cycles into sleep mode before it gets a chance to deassert + * the interrupt pin; therefore, we shift this responsibility over to the MCU. * * Any register read will clear the interrupt. */ @@ -301,20 +301,19 @@ public short[] mpu_get_gyro_reg() throws RuntimeIOException { short z = buffer.getShort(); System.out.format("gyro reg values = (%d, %d, %d)%n", Short.valueOf(x), Short.valueOf(y), Short.valueOf(z)); /* - * byte[] data = readBytes(MPU9150_RA_GYRO_XOUT_H, 6) short x = (short)((data[0] - * << 8) | (data[1] & 0xff)); short y = (short)((data[2] << 8) | (data[3] & - * 0xff)); short z = (short)((data[4] << 8) | (data[5] & 0xff)); + * byte[] data = readBytes(MPU9150_RA_GYRO_XOUT_H, 6) short x = (short)((data[0] << 8) | + * (data[1] & 0xff)); short y = (short)((data[2] << 8) | (data[3] & 0xff)); short z = + * (short)((data[4] << 8) | (data[5] & 0xff)); */ return new short[] { x, y, z }; } /** - * Each 16-bit accelerometer measurement has a full scale defined in ACCEL_FS - * (Register 28). For each full scale setting, the accelerometers' sensitivity - * per LSB in ACCEL_xOUT is shown in the table below. AFS_SEL Full Scale Range - * LSB Sensitivity 0 +/-2g 16384 LSB/mg 1 +/-4g 8192 LSB/mg 2 +/-8g 4096 LSB/mg - * 3 +/-16g 2048 LSB/mg + * Each 16-bit accelerometer measurement has a full scale defined in ACCEL_FS (Register + * 28). For each full scale setting, the accelerometers' sensitivity per LSB in ACCEL_xOUT + * is shown in the table below. AFS_SEL Full Scale Range LSB Sensitivity 0 +/-2g 16384 + * LSB/mg 1 +/-4g 8192 LSB/mg 2 +/-8g 4096 LSB/mg 3 +/-16g 2048 LSB/mg * * @return Raw data in hardware units. * @throws RuntimeIOException if an I/O error occurs @@ -340,12 +339,11 @@ public short[] mpu_get_accel_reg() throws RuntimeIOException { } /** - * Read temperature data directly from the registers. The scale factor and - * offset for the temperature sensor are found in the Electrical Specifications - * table in the MPU-9150 Product Specification document. The temperature in - * degrees C for a given register value may be computed as: Temperature in - * degrees C = (TEMP_OUT Register Value as a signed quantity)/340 + 35 Please - * note that the math in the above equation is in decimal. + * Read temperature data directly from the registers. The scale factor and offset for the + * temperature sensor are found in the Electrical Specifications table in the MPU-9150 + * Product Specification document. The temperature in degrees C for a given register value + * may be computed as: Temperature in degrees C = (TEMP_OUT Register Value as a signed + * quantity)/340 + 35 Please note that the math in the above equation is in decimal. * * @return Temperature * @throws RuntimeIOException if an I/O error occurs @@ -364,9 +362,9 @@ public float mpu_get_temperature() throws RuntimeIOException { } /** - * Read biases to the accel bias 6050 registers. This function reads from the - * MPU6050 accel offset cancellations registers. The format are G in +-8G - * format. The register is initialised with OTP factory trim values. + * Read biases to the accel bias 6050 registers. This function reads from the MPU6050 + * accel offset cancellations registers. The format are G in +-8G format. The register is + * initialised with OTP factory trim values. * * @return accel_bias returned structure with the accel bias * @throws RuntimeIOException if an I/O error occurs @@ -375,12 +373,11 @@ public short[] mpu_read_6050_accel_bias() throws RuntimeIOException { short[] accel_bias = new short[3]; /* - * byte[] bias_x_bytes = readBytes(MPU9150_RA_XA_OFFS_H, 2); byte[] bias_y_bytes - * = readBytes(MPU9150_RA_YA_OFFS_H, 2); byte[] bias_z_bytes = + * byte[] bias_x_bytes = readBytes(MPU9150_RA_XA_OFFS_H, 2); byte[] bias_y_bytes = + * readBytes(MPU9150_RA_YA_OFFS_H, 2); byte[] bias_z_bytes = * readBytes(MPU9150_RA_ZA_OFFS_H, 2); accel_bias[0] = (bias_x_bytes[0] << 8) | - * (bias_x_bytes[1] & 0xff); accel_bias[1] = (bias_y_bytes[2] << 8) | - * (bias_y_bytes[3] & 0xff); accel_bias[2] = (bias_z_bytes[4] << 8) | - * (bias_z_bytes[5] & 0xff); + * (bias_x_bytes[1] & 0xff); accel_bias[1] = (bias_y_bytes[2] << 8) | (bias_y_bytes[3] & + * 0xff); accel_bias[2] = (bias_z_bytes[4] << 8) | (bias_z_bytes[5] & 0xff); */ ByteBuffer buffer = i2cDevice.readI2CBlockDataByteBuffer(MPU9150_RA_XA_OFFS_H, 6); accel_bias[0] = buffer.getShort(); @@ -391,9 +388,9 @@ public short[] mpu_read_6050_accel_bias() throws RuntimeIOException { } /** - * Push biases to the gyro bias 6500/6050 registers. This function expects - * biases relative to the current sensor output, and these biases will be added - * to the factory-supplied values. Bias inputs are LSB in +-1000dps format. + * Push biases to the gyro bias 6500/6050 registers. This function expects biases relative + * to the current sensor output, and these biases will be added to the factory-supplied + * values. Bias inputs are LSB in +-1000dps format. * * @param gyro_bias New biases. * @throws RuntimeIOException if an I/O error occurs @@ -403,11 +400,10 @@ public void mpu_set_gyro_bias_reg(short[] gyro_bias) throws RuntimeIOException { gyro_bias[i] = (short) -gyro_bias[i]; } /* - * byte data[] = {0, 0, 0, 0, 0, 0}; data[0] = (byte)((gyro_bias[0] >> 8) & - * 0xff); data[1] = (byte)((gyro_bias[0]) & 0xff); data[2] = - * (byte)((gyro_bias[1] >> 8) & 0xff); data[3] = (byte)((gyro_bias[1]) & 0xff); - * data[4] = (byte)((gyro_bias[2] >> 8) & 0xff); data[5] = (byte)((gyro_bias[2]) - * & 0xff); + * byte data[] = {0, 0, 0, 0, 0, 0}; data[0] = (byte)((gyro_bias[0] >> 8) & 0xff); data[1] + * = (byte)((gyro_bias[0]) & 0xff); data[2] = (byte)((gyro_bias[1] >> 8) & 0xff); data[3] + * = (byte)((gyro_bias[1]) & 0xff); data[4] = (byte)((gyro_bias[2] >> 8) & 0xff); data[5] + * = (byte)((gyro_bias[2]) & 0xff); */ i2cDevice.writeWordData(MPU9150_RA_XG_OFFS_USRH, gyro_bias[0]); i2cDevice.writeWordData(MPU9150_RA_YG_OFFS_USRH, gyro_bias[1]); @@ -415,9 +411,9 @@ public void mpu_set_gyro_bias_reg(short[] gyro_bias) throws RuntimeIOException { } /** - * Push biases to the accel bias 6050 registers. This function expects biases - * relative to the current sensor output, and these biases will be added to the - * factory-supplied values. Bias inputs are LSB in +-16G format. + * Push biases to the accel bias 6050 registers. This function expects biases relative to + * the current sensor output, and these biases will be added to the factory-supplied + * values. Bias inputs are LSB in +-16G format. * * @param accel_bias New biases. * @throws RuntimeIOException if an I/O error occurs @@ -430,11 +426,10 @@ public void mpu_set_accel_bias_6050_reg(short[] accel_bias) throws RuntimeIOExce accel_reg_bias[2] -= (accel_bias[2] & ~1); /* - * byte data[] = {0, 0, 0, 0, 0, 0}; data[0] = (byte)((accel_reg_bias[0] >> 8) & - * 0xff); data[1] = (byte)((accel_reg_bias[0]) & 0xff); data[2] = - * (byte)((accel_reg_bias[1] >> 8) & 0xff); data[3] = (byte)((accel_reg_bias[1]) - * & 0xff); data[4] = (byte)((accel_reg_bias[2] >> 8) & 0xff); data[5] = - * (byte)((accel_reg_bias[2]) & 0xff); + * byte data[] = {0, 0, 0, 0, 0, 0}; data[0] = (byte)((accel_reg_bias[0] >> 8) & 0xff); + * data[1] = (byte)((accel_reg_bias[0]) & 0xff); data[2] = (byte)((accel_reg_bias[1] >> 8) + * & 0xff); data[3] = (byte)((accel_reg_bias[1]) & 0xff); data[4] = + * (byte)((accel_reg_bias[2] >> 8) & 0xff); data[5] = (byte)((accel_reg_bias[2]) & 0xff); */ i2cDevice.writeWordData(MPU9150_RA_XA_OFFS_H, accel_reg_bias[0]); @@ -580,8 +575,8 @@ public LowPassFilter mpu_get_lpf() { } /** - * Set digital low pass filter. The following LPF settings are supported: 188, - * 98, 42, 20, 10, 5. + * Set digital low pass filter. The following LPF settings are supported: 188, 98, 42, 20, + * 10, 5. * * @param frequency Desired LPF setting. * @throws RuntimeIOException if an I/O error occurs @@ -592,8 +587,8 @@ public boolean mpu_set_lpf(int frequency) throws RuntimeIOException { } /** - * Set digital low pass filter. The following LPF settings are supported: 188, - * 98, 42, 20, 10, 5. + * Set digital low pass filter. The following LPF settings are supported: 188, 98, 42, 20, + * 10, 5. * * @param lpf Desired LPF setting. * @throws RuntimeIOException if an I/O error occurs @@ -649,8 +644,8 @@ public boolean mpu_set_sample_rate(int rate) throws RuntimeIOException { } /* - * Requested rate exceeds the allowed frequencies in LP accel mode, switch back - * to full-power mode. + * Requested rate exceeds the allowed frequencies in LP accel mode, switch back to + * full-power mode. */ Logger.debug("Setting lp_accel_mode to 0"); mpu_lp_accel_mode(0); @@ -683,9 +678,9 @@ public int mpu_get_compass_sample_rate() { } /** - * Set compass sampling rate. The compass on the auxiliary I2C bus is read by - * the MPU hardware at a maximum of 100Hz. The actual rate can be set to a - * fraction of the gyro sampling rate. + * Set compass sampling rate. The compass on the auxiliary I2C bus is read by the MPU + * hardware at a maximum of 100Hz. The actual rate can be set to a fraction of the gyro + * sampling rate. * * WARNING: The new rate may be different than what was requested. Call * mpu_get_compass_sample_rate to check the actual setting. @@ -715,9 +710,9 @@ public boolean mpu_set_compass_sample_rate(int rate) throws RuntimeIOException { */ public double mpu_get_gyro_sens() { /* - * float sens; switch (gyro_fsr) { case INV_FSR_250DPS: sens = 131.0f; break; - * case INV_FSR_500DPS: sens = 65.5f; break; case INV_FSR_1000DPS: sens = 32.8f; - * break; case INV_FSR_2000DPS: sens = 16.4f; break; default: sens = -1f; } + * float sens; switch (gyro_fsr) { case INV_FSR_250DPS: sens = 131.0f; break; case + * INV_FSR_500DPS: sens = 65.5f; break; case INV_FSR_1000DPS: sens = 32.8f; break; case + * INV_FSR_2000DPS: sens = 16.4f; break; default: sens = -1f; } * * return sens; */ @@ -732,9 +727,9 @@ public double mpu_get_gyro_sens() { */ public int mpu_get_accel_sens() { /* - * int sens; switch (accel_fsr) { case INV_FSR_2G: sens = 16384; break; case - * INV_FSR_4G: sens = 8192; break; case INV_FSR_8G: sens = 4096; break; case - * INV_FSR_16G: sens = 2048; break; default: return -1; } + * int sens; switch (accel_fsr) { case INV_FSR_2G: sens = 16384; break; case INV_FSR_4G: + * sens = 8192; break; case INV_FSR_8G: sens = 4096; break; case INV_FSR_16G: sens = 2048; + * break; default: return -1; } */ int sens = accel_fsr.getSensitivityScaleFactor(); @@ -746,9 +741,8 @@ public int mpu_get_accel_sens() { } /** - * Get current FIFO configuration. sensors can contain a combination of the - * following flags: INV_X_GYRO, INV_Y_GYRO, INV_Z_GYRO INV_XYZ_GYRO - * INV_XYZ_ACCEL + * Get current FIFO configuration. sensors can contain a combination of the following + * flags: INV_X_GYRO, INV_Y_GYRO, INV_Z_GYRO INV_XYZ_GYRO INV_XYZ_ACCEL * * @return sensors Mask of sensors in FIFO. */ @@ -757,9 +751,8 @@ public byte mpu_get_fifo_config() { } /** - * Select which sensors are pushed to FIFO. sensors can contain a combination of - * the following flags: INV_X_GYRO, INV_Y_GYRO, INV_Z_GYRO INV_XYZ_GYRO - * INV_XYZ_ACCEL + * Select which sensors are pushed to FIFO. sensors can contain a combination of the + * following flags: INV_X_GYRO, INV_Y_GYRO, INV_Z_GYRO INV_XYZ_GYRO INV_XYZ_ACCEL * * @param newSensors Mask of sensors to push to FIFO. * @throws RuntimeIOException if an I/O error occurs @@ -818,9 +811,8 @@ public boolean mpu_get_power_state() { } /** - * Turn specific sensors on/off. sensors can contain a combination of the - * following flags: INV_X_GYRO, INV_Y_GYRO, INV_Z_GYRO INV_XYZ_GYRO - * INV_XYZ_ACCEL INV_XYZ_COMPASS + * Turn specific sensors on/off. sensors can contain a combination of the following flags: + * INV_X_GYRO, INV_Y_GYRO, INV_Z_GYRO INV_XYZ_GYRO INV_XYZ_ACCEL INV_XYZ_COMPASS * * @param newSensors Mask of sensors to wake. * @return true if successful. @@ -921,16 +913,15 @@ public short mpu_get_int_status() throws RuntimeIOException { } /** - * Get one packet from the FIFO. If sensors does not contain a particular - * sensor, disregard the data returned to that pointer. sensors can contain a - * combination of the following flags: INV_X_GYRO, INV_Y_GYRO, INV_Z_GYRO - * INV_XYZ_GYRO INV_XYZ_ACCEL If the FIFO has no new data, sensors will be zero. - * If the FIFO is disabled, sensors will be zero and this function will return a - * non-zero error code. + * Get one packet from the FIFO. If sensors does not contain a particular sensor, + * disregard the data returned to that pointer. sensors can contain a combination of the + * following flags: INV_X_GYRO, INV_Y_GYRO, INV_Z_GYRO INV_XYZ_GYRO INV_XYZ_ACCEL If the + * FIFO has no new data, sensors will be zero. If the FIFO is disabled, sensors will be + * zero and this function will return a non-zero error code. * - * @return FIFOData: gyro Gyro data in hardware units. accel Accel data in - * hardware units. timestamp Timestamp in milliseconds. sensors Mask of - * sensors read from FIFO. more Number of remaining packets. + * @return FIFOData: gyro Gyro data in hardware units. accel Accel data in hardware units. + * timestamp Timestamp in milliseconds. sensors Mask of sensors read from FIFO. + * more Number of remaining packets. * @throws RuntimeIOException if an I/O error occurs */ public MPU9150FIFOData mpu_read_fifo() throws RuntimeIOException { @@ -1024,8 +1015,8 @@ public MPU9150FIFOData mpu_read_fifo() throws RuntimeIOException { } /** - * Get one unparsed packet from the FIFO. This function should be used if the - * packet is to be parsed elsewhere. + * Get one unparsed packet from the FIFO. This function should be used if the packet is to + * be parsed elsewhere. * * @param length Length of one FIFO packet. * @return more Number of remaining packets. @@ -1192,8 +1183,7 @@ public float[] get_accel_prod_shift() throws RuntimeIOException { continue; } /* - * Equivalent to.. st_shift[ii] = 0.34f * powf(0.92f/0.34f, (shift_code[ii]-1) / - * 30.f) + * Equivalent to.. st_shift[ii] = 0.34f * powf(0.92f/0.34f, (shift_code[ii]-1) / 30.f) */ st_shift[ii] = 0.34f; while (--shift_code[ii] != 0) { @@ -1209,8 +1199,8 @@ public void get_st_biases() throws RuntimeIOException { } /** - * Write to the DMP memory. This function prevents I2C writes past the bank - * boundaries. The DMP memory is only accessible when the chip is awake. + * Write to the DMP memory. This function prevents I2C writes past the bank boundaries. + * The DMP memory is only accessible when the chip is awake. * * @param mem_addr Memory location (bank << 8 | start address) * @param data Bytes to write to memory. @@ -1244,8 +1234,8 @@ public void mpu_write_mem(int mem_addr, byte[] data) throws RuntimeIOException { } /** - * Read from the DMP memory. This function prevents I2C reads past the bank - * boundaries. The DMP memory is only accessible when the chip is awake. + * Read from the DMP memory. This function prevents I2C reads past the bank boundaries. + * The DMP memory is only accessible when the chip is awake. * * @param mem_addr Memory location (bank << 8 | start address) * @param length Number of bytes to read. @@ -1387,9 +1377,9 @@ public boolean setup_compass() throws RuntimeIOException { /* Find compass. Possible addresses range from 0x0C to 0x0F. */ byte akm_addr = AK8975Driver.AK8975_MAG_ADDRESS; /* - * Assume it's on 0x0C... for (akm_addr = 0x0C; akm_addr <= 0x0F; akm_addr++) { - * int result; result = read(akm_addr, AKM_REG_WHOAMI, 1, data); if (data[0] == - * AKM_WHOAMI) { break; } } + * Assume it's on 0x0C... for (akm_addr = 0x0C; akm_addr <= 0x0F; akm_addr++) { int + * result; result = read(akm_addr, AKM_REG_WHOAMI, 1, data); if (data[0] == AKM_WHOAMI) { + * break; } } */ if (akm_addr > 0x0F) { @@ -1529,36 +1519,32 @@ public int mpu_get_compass_fsr() { } /** - * Enters LP accel motion interrupt mode. The behaviour of this feature is very - * different between the MPU6050 and the MPU6500. Each chip's version of this - * feature is explained below. + * Enters LP accel motion interrupt mode. The behaviour of this feature is very different + * between the MPU6050 and the MPU6500. Each chip's version of this feature is explained + * below. * - * The hardware motion threshold can be between 32mg and 8160mg in 32mg - * increments. + * The hardware motion threshold can be between 32mg and 8160mg in 32mg increments. * - * Low-power accel mode supports the following frequencies: 1.25Hz, 5Hz, 20Hz, - * 40Hz + * Low-power accel mode supports the following frequencies: 1.25Hz, 5Hz, 20Hz, 40Hz * - * MPU6500: Unlike the MPU6050 version, the hardware does not "lock in" a - * reference sample. The hardware monitors the accel data and detects any large - * change over a short period of time. + * MPU6500: Unlike the MPU6050 version, the hardware does not "lock in" a reference + * sample. The hardware monitors the accel data and detects any large change over a short + * period of time. * - * The hardware motion threshold can be between 4mg and 1020mg in 4mg - * increments. + * The hardware motion threshold can be between 4mg and 1020mg in 4mg increments. * - * MPU6500 Low-power accel mode supports the following frequencies: 1.25Hz, - * 2.5Hz, 5Hz, 10Hz, 20Hz, 40Hz, 80Hz, 160Hz, 320Hz, 640Hz + * MPU6500 Low-power accel mode supports the following frequencies: 1.25Hz, 2.5Hz, 5Hz, + * 10Hz, 20Hz, 40Hz, 80Hz, 160Hz, 320Hz, 640Hz * * NOTES: The driver will round down thresh to the nearest supported value if an - * unsupported threshold is selected. To select a fractional wake-up frequency, - * round down the value passed to lpa_freq. The MPU6500 does not support a delay - * parameter. If this function is used for the MPU6500, the value passed to time - * will be ignored. To disable this mode, set lpa_freq to zero. The driver will - * restore the previous configuration. + * unsupported threshold is selected. To select a fractional wake-up frequency, round down + * the value passed to lpa_freq. The MPU6500 does not support a delay parameter. If this + * function is used for the MPU6500, the value passed to time will be ignored. To disable + * this mode, set lpa_freq to zero. The driver will restore the previous configuration. * * @param thresh Motion threshold in mg. - * @param time Duration in milliseconds that the accel data must exceed - * thresh before motion is reported. + * @param time Duration in milliseconds that the accel data must exceed thresh before + * motion is reported. * @param lpa_freq Minimum sampling rate, or zero to disable. * @throws RuntimeIOException if an I/O error occurs */ diff --git a/diozero-provider-firmata/src/main/java/com/diozero/internal/provider/firmata/FirmataI2CDevice.java b/diozero-provider-firmata/src/main/java/com/diozero/internal/provider/firmata/FirmataI2CDevice.java index 80a8a070..fa1c0b50 100644 --- a/diozero-provider-firmata/src/main/java/com/diozero/internal/provider/firmata/FirmataI2CDevice.java +++ b/diozero-provider-firmata/src/main/java/com/diozero/internal/provider/firmata/FirmataI2CDevice.java @@ -45,8 +45,8 @@ /** *

- * Work In Progress. I am unclear as to how the this Java Firmata I2C - * implementation is supposed to work. + * Work In Progress. I am unclear as to how the this Java Firmata I2C implementation is + * supposed to work. *

*

* Wiring: @@ -63,6 +63,7 @@ public class FirmataI2CDevice extends AbstractDevice implements InternalI2CDevic private static final String I2C_DELAY_PROP = "diozero.firmata.i2cDelay"; private FirmataAdapter adapter; + private int controller; private int address; private boolean autoRestart = false; private boolean addressSize10Bit; @@ -77,10 +78,22 @@ public FirmataI2CDevice(FirmataDeviceFactory deviceFactory, String key, int cont adapter.i2cConfig(PropertyUtil.getIntProperty(I2C_DELAY_PROP, DEFAULT_I2C_DELAY)); } } + // XXX Note multiple controllers supported in Firmata + this.controller = controller; this.address = address; addressSize10Bit = addressSize == I2CConstants.AddressSize.SIZE_10; } + @Override + public int getController() { + return controller; + } + + @Override + public int getAddress() { + return address; + } + @Override public boolean probe(com.diozero.api.I2CDevice.ProbeMode mode) { return readByte() >= 0; diff --git a/diozero-provider-mock/src/main/java/com/diozero/internal/provider/mock/devices/MockPca9685.java b/diozero-provider-mock/src/main/java/com/diozero/internal/provider/mock/devices/MockPca9685.java index 05465d1a..b064124e 100644 --- a/diozero-provider-mock/src/main/java/com/diozero/internal/provider/mock/devices/MockPca9685.java +++ b/diozero-provider-mock/src/main/java/com/diozero/internal/provider/mock/devices/MockPca9685.java @@ -76,6 +76,16 @@ public MockPca9685(String key) { offValues = new int[NUM_CHANNELS]; } + @Override + public int getController() { + return 0; + } + + @Override + public int getAddress() { + return 0; + } + @Override public String getKey() { return key; diff --git a/diozero-provider-pigpio/src/main/java/com/diozero/internal/provider/pigpioj/PigpioJI2CDevice.java b/diozero-provider-pigpio/src/main/java/com/diozero/internal/provider/pigpioj/PigpioJI2CDevice.java index 5cc309cd..f5451fea 100644 --- a/diozero-provider-pigpio/src/main/java/com/diozero/internal/provider/pigpioj/PigpioJI2CDevice.java +++ b/diozero-provider-pigpio/src/main/java/com/diozero/internal/provider/pigpioj/PigpioJI2CDevice.java @@ -71,6 +71,16 @@ public PigpioJI2CDevice(String key, DeviceFactoryInterface deviceFactory, Pigpio Integer.toHexString(address), Integer.valueOf(handle)); } + @Override + public int getController() { + return controller; + } + + @Override + public int getAddress() { + return address; + } + @Override public boolean isOpen() { return handle >= 0; diff --git a/diozero-provider-remote/src/main/java/com/diozero/internal/provider/remote/grpc/GrpcClientI2CDevice.java b/diozero-provider-remote/src/main/java/com/diozero/internal/provider/remote/grpc/GrpcClientI2CDevice.java index b704ebd6..3aefeb0e 100644 --- a/diozero-provider-remote/src/main/java/com/diozero/internal/provider/remote/grpc/GrpcClientI2CDevice.java +++ b/diozero-provider-remote/src/main/java/com/diozero/internal/provider/remote/grpc/GrpcClientI2CDevice.java @@ -80,6 +80,16 @@ public GrpcClientI2CDevice(GrpcClientDeviceFactory deviceFactory, String key, in } } + @Override + public int getController() { + return controller; + } + + @Override + public int getAddress() { + return address; + } + @Override public boolean probe(ProbeMode mode) throws RuntimeIOException { try { diff --git a/diozero-sampleapps/pom.xml b/diozero-sampleapps/pom.xml index f021199c..2e855dfd 100644 --- a/diozero-sampleapps/pom.xml +++ b/diozero-sampleapps/pom.xml @@ -15,6 +15,7 @@ 4.2 2.4.1 4.7.5 + 2.2 @@ -55,6 +56,11 @@ picocli ${picocli.version} + + org.yaml + snakeyaml + ${snakeyaml.version} + @@ -100,6 +106,10 @@ info.picocli picocli + + org.yaml + snakeyaml + @@ -108,7 +118,6 @@ org.apache.maven.plugins maven-shade-plugin - 3.4.1 false