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 @@
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 * ** * @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:- * 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 *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: *
- * 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. *
* *- * 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: *
*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 @@ *
*- * 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: *
*
* 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:
*
@@ -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.
*
- * 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.
*
* 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.
*
* 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 @@
*
* 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 ConsumermeasurementListener; @@ -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 @@ /** *- Datasheet
+ *- Datasheet
*- Application * notes
*- SparkFun * C++ implementation
- *- Pololu + *
- Pololu * C++ implementation
- *- Adafruit Python - * implementation
+ *- Adafruit + * Python implementation
** 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 @@ @@ -100,6 +106,10 @@picocli ${picocli.version} ++ org.yaml +snakeyaml +${snakeyaml.version} +info.picocli picocli ++ org.yaml +snakeyaml +@@ -108,7 +118,6 @@ org.apache.maven.plugins maven-shade-plugin -3.4.1 false