001package com.pi4j.io.i2c.impl; 002 003/* 004 * #%L 005 * ********************************************************************** 006 * ORGANIZATION : Pi4J 007 * PROJECT : Pi4J :: Java Library (Core) 008 * FILENAME : I2CDeviceImpl.java 009 * 010 * This file is part of the Pi4J project. More information about 011 * this project can be found here: https://www.pi4j.com/ 012 * ********************************************************************** 013 * %% 014 * Copyright (C) 2012 - 2021 Pi4J 015 * %% 016 * This program is free software: you can redistribute it and/or modify 017 * it under the terms of the GNU Lesser General Public License as 018 * published by the Free Software Foundation, either version 3 of the 019 * License, or (at your option) any later version. 020 * 021 * This program is distributed in the hope that it will be useful, 022 * but WITHOUT ANY WARRANTY; without even the implied warranty of 023 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 024 * GNU General Lesser Public License for more details. 025 * 026 * You should have received a copy of the GNU General Lesser Public 027 * License along with this program. If not, see 028 * <http://www.gnu.org/licenses/lgpl-3.0.html>. 029 * #L% 030 */ 031 032import java.io.IOException; 033import java.nio.ByteBuffer; 034import java.nio.IntBuffer; 035 036import com.pi4j.io.i2c.I2CDevice; 037 038/** 039 * Implementation of i2c device. This class only holds reference to i2c bus (so it can use its handle) and device address. 040 * 041 * @author Daniel Sendula, refactored by <a href="http://raspelikan.blogspot.co.at">RasPelikan</a> 042 * 043 */ 044public class I2CDeviceImpl implements I2CDevice { 045 /** 046 * Reference to i2c bus 047 */ 048 private I2CBusImpl bus; 049 050 /** 051 * I2c device address 052 */ 053 private int deviceAddress; 054 055 /** 056 * @return The address for which this instance is constructed for. 057 */ 058 @Override 059 public int getAddress() { 060 return deviceAddress; 061 } 062 063 /** 064 * Constructor. 065 * 066 * @param bus i2c bus 067 * @param address i2c device address 068 */ 069 public I2CDeviceImpl(I2CBusImpl bus, int address) { 070 this.bus = bus; 071 this.deviceAddress = address; 072 } 073 074 /** 075 * Used by WriteRunnables and ReadRunnables. 076 * 077 * @return The bus associated with this I2CDeviceImpl instance. 078 */ 079 I2CBusImpl getBus() { 080 return bus; 081 } 082 083 /** 084 * This method writes one byte to i2c device. 085 * 086 * @param data byte to be written 087 * 088 * @throws IOException thrown in case byte cannot be written to the i2c device or i2c bus 089 */ 090 @Override 091 public void write(final byte data) throws IOException { 092 getBus().writeByteDirect(this, data); 093 } 094 095 /** 096 * This method writes several bytes to the i2c device from given buffer at given offset. 097 * 098 * @param data buffer of data to be written to the i2c device in one go 099 * @param offset offset in buffer 100 * @param size number of bytes to be written 101 * 102 * @throws IOException thrown in case byte cannot be written to the i2c device or i2c bus 103 */ 104 @Override 105 public void write(final byte[] data, final int offset, final int size) throws IOException { 106 getBus().writeBytesDirect(this, size, offset, data); 107 } 108 109 /** 110 * This method writes all bytes included in the given buffer directly to the i2c device. 111 * 112 * @param buffer buffer of data to be written to the i2c device in one go 113 * 114 * @throws IOException thrown in case byte cannot be written to the i2c device or i2c bus 115 */ 116 @Override 117 public void write(byte[] buffer) throws IOException { 118 write(buffer, 0, buffer.length); 119 } 120 121 /** 122 * This method writes one byte to i2c device. 123 * 124 * @param address local address in the i2c device 125 * @param data byte to be written 126 * 127 * @throws IOException thrown in case byte cannot be written to the i2c device or i2c bus 128 */ 129 @Override 130 public void write(final int address, final byte data) throws IOException { 131 getBus().writeByte(this, address, data); 132 } 133 134 /** 135 * This method writes several bytes to the i2c device from given buffer at given offset. 136 * 137 * @param address local address in the i2c device 138 * @param data buffer of data to be written to the i2c device in one go 139 * @param offset offset in buffer 140 * @param size number of bytes to be written 141 * 142 * @throws IOException thrown in case byte cannot be written to the i2c device or i2c bus 143 */ 144 @Override 145 public void write(final int address, final byte[] data, final int offset, final int size) throws IOException { 146 getBus().writeBytes(this, address, size, offset, data); 147 } 148 149 /** 150 * This method writes all bytes included in the given buffer directoy to the register address on the i2c device 151 * 152 * @param address local address in the i2c device 153 * @param buffer buffer of data to be written to the i2c device in one go 154 * 155 * @throws IOException thrown in case byte cannot be written to the i2c device or i2c bus 156 */ 157 public void write(int address, byte[] buffer) throws IOException { 158 write(address, buffer, 0, buffer.length); 159 } 160 161 /** 162 * This method reads one byte from the i2c device. Result is between 0 and 255 if read operation was successful, else a negative number for an error. 163 * 164 * @return byte value read: positive number (or zero) to 255 if read was successful. Negative number if reading failed. 165 * 166 * @throws IOException thrown in case byte cannot be read from the i2c device or i2c bus 167 */ 168 @Override 169 public int read() throws IOException { 170 return getBus().readByteDirect(this); 171 } 172 173 /** 174 * <p> 175 * This method reads bytes from the i2c device to given buffer at asked offset. 176 * </p> 177 * 178 * <p> 179 * Note: Current implementation calls {@link #read(int)}. That means for each read byte i2c bus will send (next) address to i2c device. 180 * </p> 181 * 182 * @param data buffer of data to be read from the i2c device in one go 183 * @param offset offset in buffer 184 * @param size number of bytes to be read 185 * 186 * @return number of bytes read 187 * 188 * @throws IOException thrown in case byte cannot be read from the i2c device or i2c bus 189 */ 190 @Override 191 public int read(final byte[] data, final int offset, final int size) throws IOException { 192 return getBus().readBytesDirect(this, size, offset, data); 193 } 194 195 /** 196 * This method reads one byte from the i2c device. Result is between 0 and 255 if read operation was successful, else a negative number for an error. 197 * 198 * @param address local address in the i2c device 199 * @return byte value read: positive number (or zero) to 255 if read was successful. Negative number if reading failed. 200 * 201 * @throws IOException thrown in case byte cannot be read from the i2c device or i2c bus 202 */ 203 @Override 204 public int read(final int address) throws IOException { 205 return getBus().readByte(this, address); 206 } 207 208 /** 209 * <p> 210 * This method reads bytes from the i2c device to given buffer at asked offset. 211 * </p> 212 * 213 * <p> 214 * Note: Current implementation calls {@link #read(int)}. That means for each read byte i2c bus will send (next) address to i2c device. 215 * </p> 216 * 217 * @param address local address in the i2c device 218 * @param data buffer of data to be read from the i2c device in one go 219 * @param offset offset in buffer 220 * @param size number of bytes to be read 221 * 222 * @return number of bytes read 223 * 224 * @throws IOException thrown in case byte cannot be read from the i2c device or i2c bus 225 */ 226 @Override 227 public int read(final int address, final byte[] data, final int offset, final int size) throws IOException { 228 return getBus().readBytes(this, address, size, offset, data); 229 } 230 231 /** 232 * @see com.pi4j.io.file.LinuxFile#ioctl(long, int) 233 */ 234 @Override 235 public void ioctl(long command, int value) throws IOException { 236 getBus().ioctl(this, command, value); 237 } 238 239 /** 240 * @see com.pi4j.io.file.LinuxFile#ioctl(long, ByteBuffer, IntBuffer) 241 */ 242 @Override 243 public void ioctl(long command, ByteBuffer data, IntBuffer offsets) throws IOException { 244 getBus().ioctl(this, command, data, offsets); 245 } 246 247 /** 248 * This method writes and reads bytes to/from the i2c device in a single method call 249 * 250 * @param writeData buffer of data to be written to the i2c device in one go 251 * @param writeOffset offset in write buffer 252 * @param writeSize number of bytes to be written from buffer 253 * @param readData buffer of data to be read from the i2c device in one go 254 * @param readOffset offset in read buffer 255 * @param readSize number of bytes to be read 256 * 257 * @return number of bytes read 258 * 259 * @throws IOException thrown in case byte cannot be read from the i2c device or i2c bus 260 */ 261 @Override 262 public int read(final byte[] writeData, final int writeOffset, final int writeSize, final byte[] readData, final int readOffset, final int readSize) throws IOException { 263 return getBus().writeAndReadBytesDirect(this, writeSize, writeOffset, writeData, readSize, readOffset, readData); 264 } 265 266 /** 267 * This helper method creates a string describing bus file name and device address (in hex). 268 * 269 * @return string with all details 270 */ 271 protected String makeDescription() { 272 return "I2CDevice on " + bus + " at address 0x" + Integer.toHexString(deviceAddress); 273 } 274 275 /** 276 * This helper method creates a string describing bus file name, device address (in hex) and local i2c address. 277 * 278 * @param address local address in i2c device 279 * @return string with all details 280 */ 281 protected String makeDescription(int address) { 282 return "I2CDevice on " + bus + " at address 0x" + Integer.toHexString(deviceAddress) + " to address 0x" + Integer.toHexString(address); 283 } 284}