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: http://www.pi4j.com/ 012 * ********************************************************************** 013 * %% 014 * Copyright (C) 2012 - 2016 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; 033 034import com.pi4j.io.i2c.I2CDevice; 035 036/** 037 * Implementation of i2c device. This class only holds reference to i2c bus (so it can use its handle) and device address. 038 * 039 * @author Daniel Sendula, refactored by <a href="http://raspelikan.blogspot.co.at">RasPelikan</a> 040 * 041 */ 042public class I2CDeviceImpl implements I2CDevice { 043 044 /** 045 * Reference to i2c bus 046 */ 047 private I2CBusImpl bus; 048 049 /** 050 * I2c device address 051 */ 052 private int deviceAddress; 053 054 /** 055 * @return The address for which this instance is constructed for. 056 */ 057 @Override 058 public int getAddress() { 059 return deviceAddress; 060 } 061 062 /** 063 * Constructor. 064 * 065 * @param bus i2c bus 066 * @param address i2c device address 067 */ 068 public I2CDeviceImpl(I2CBusImpl bus, int address) { 069 this.bus = bus; 070 this.deviceAddress = address; 071 } 072 073 /** 074 * Used by WriteRunnables and ReadRunnables. 075 * 076 * @return The bus associated with this I2CDeviceImpl instance. 077 */ 078 I2CBusImpl getBus() { 079 return bus; 080 } 081 082 /** 083 * This method writes one byte to i2c device. 084 * 085 * @param data byte to be written 086 * 087 * @throws IOException thrown in case byte cannot be written to the i2c device or i2c bus 088 */ 089 @Override 090 public void write(final byte data) throws IOException { 091 int ret = getBus().writeByteDirect(this, data); 092 if (ret < 0) { 093 throw new IOException("Error writing to " + makeDescription() + ". Got '" + ret + "'."); 094 095 } 096 } 097 098 /** 099 * This method writes several bytes to the i2c device from given buffer at given offset. 100 * 101 * @param data buffer of data to be written to the i2c device in one go 102 * @param offset offset in buffer 103 * @param size number of bytes to be written 104 * 105 * @throws IOException thrown in case byte cannot be written to the i2c device or i2c bus 106 */ 107 @Override 108 public void write(final byte[] data, final int offset, final int size) throws IOException { 109 int ret = getBus().writeBytesDirect(this, size, offset, data); 110 if (ret < 0) { 111 throw new IOException("Error writing to " + makeDescription() + ". Got '" + ret + "'."); 112 } 113 } 114 115 /** 116 * This method writes all bytes included in the given buffer directly to the i2c device. 117 * 118 * @param buffer buffer of data to be written to the i2c device in one go 119 * 120 * @throws IOException thrown in case byte cannot be written to the i2c device or i2c bus 121 */ 122 @Override 123 public void write(byte[] buffer) throws IOException { 124 write(buffer, 0, buffer.length); 125 } 126 127 /** 128 * This method writes one byte to i2c device. 129 * 130 * @param address local address in the i2c device 131 * @param data byte to be written 132 * 133 * @throws IOException thrown in case byte cannot be written to the i2c device or i2c bus 134 */ 135 @Override 136 public void write(final int address, final byte data) throws IOException { 137 int ret = getBus().writeByte(this, address, data); 138 if (ret < 0) { 139 throw new IOException("Error writing to " + makeDescription(address) + ". Got '" + ret + "'."); 140 } 141 } 142 143 /** 144 * This method writes several bytes to the i2c device from given buffer at given offset. 145 * 146 * @param address local address in the i2c device 147 * @param data buffer of data to be written to the i2c device in one go 148 * @param offset offset in buffer 149 * @param size number of bytes to be written 150 * 151 * @throws IOException thrown in case byte cannot be written to the i2c device or i2c bus 152 */ 153 @Override 154 public void write(final int address, final byte[] data, final int offset, final int size) throws IOException { 155 int ret = getBus().writeBytes(this, address, size, offset, data); 156 if (ret < 0) { 157 throw new IOException("Error writing to " + makeDescription(address) + ". Got '" + ret + "'."); 158 } 159 } 160 161 /** 162 * This method writes all bytes included in the given buffer directoy to the register address on the i2c device 163 * 164 * @param address local address in the i2c device 165 * @param buffer buffer of data to be written to the i2c device in one go 166 * 167 * @throws IOException thrown in case byte cannot be written to the i2c device or i2c bus 168 */ 169 public void write(int address, byte[] buffer) throws IOException { 170 write(address, buffer, 0, buffer.length); 171 } 172 173 /** 174 * 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. 175 * 176 * @return byte value read: positive number (or zero) to 255 if read was successful. Negative number if reading failed. 177 * 178 * @throws IOException thrown in case byte cannot be read from the i2c device or i2c bus 179 */ 180 @Override 181 public int read() throws IOException { 182 int ret = getBus().readByteDirect(this); 183 if (ret < 0) { 184 throw new IOException("Error reading from " + makeDescription() + ". Got '" + ret + "'."); 185 } 186 return ret; 187 } 188 189 /** 190 * <p> 191 * This method reads bytes from the i2c device to given buffer at asked offset. 192 * </p> 193 * 194 * <p> 195 * Note: Current implementation calls {@link #read(int)}. That means for each read byte i2c bus will send (next) address to i2c device. 196 * </p> 197 * 198 * @param data buffer of data to be read from the i2c device in one go 199 * @param offset offset in buffer 200 * @param size number of bytes to be read 201 * 202 * @return number of bytes read 203 * 204 * @throws IOException thrown in case byte cannot be read from the i2c device or i2c bus 205 */ 206 @Override 207 public int read(final byte[] data, final int offset, final int size) throws IOException { 208 int ret = getBus().readBytesDirect(this, size, offset, data); 209 if (ret < 0) { 210 throw new IOException("Error reading from " + makeDescription() + ". Got '" + ret + "'."); 211 } 212 return ret; 213 } 214 215 /** 216 * 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. 217 * 218 * @param address local address in the i2c device 219 * @return byte value read: positive number (or zero) to 255 if read was successful. Negative number if reading failed. 220 * 221 * @throws IOException thrown in case byte cannot be read from the i2c device or i2c bus 222 */ 223 @Override 224 public int read(final int address) throws IOException { 225 int ret = getBus().readByte(this, address); 226 if (ret < 0) { 227 throw new IOException("Error reading from " + makeDescription(address) + ". Got '" + ret + "'."); 228 } 229 return ret; 230 } 231 232 /** 233 * <p> 234 * This method reads bytes from the i2c device to given buffer at asked offset. 235 * </p> 236 * 237 * <p> 238 * Note: Current implementation calls {@link #read(int)}. That means for each read byte i2c bus will send (next) address to i2c device. 239 * </p> 240 * 241 * @param address local address in the i2c device 242 * @param data buffer of data to be read from the i2c device in one go 243 * @param offset offset in buffer 244 * @param size number of bytes to be read 245 * 246 * @return number of bytes read 247 * 248 * @throws IOException thrown in case byte cannot be read from the i2c device or i2c bus 249 */ 250 @Override 251 public int read(final int address, final byte[] data, final int offset, final int size) throws IOException { 252 int ret = getBus().readBytes(this, address, size, offset, data); 253 if (ret < 0) { 254 throw new IOException("Error reading from " + makeDescription(address) + ". Got '" + ret + "'."); 255 } 256 return ret; 257 } 258 259 /** 260 * This method writes and reads bytes to/from the i2c device in a single method call 261 * 262 * @param writeData buffer of data to be written to the i2c device in one go 263 * @param writeOffset offset in write buffer 264 * @param writeSize number of bytes to be written from buffer 265 * @param readData buffer of data to be read from the i2c device in one go 266 * @param readOffset offset in read buffer 267 * @param readSize number of bytes to be read 268 * 269 * @return number of bytes read 270 * 271 * @throws IOException thrown in case byte cannot be read from the i2c device or i2c bus 272 */ 273 @Override 274 public int read(final byte[] writeData, final int writeOffset, final int writeSize, final byte[] readData, final int readOffset, final int readSize) throws IOException { 275 int ret = getBus().writeAndReadBytesDirect(this, writeSize, writeOffset, writeData, readSize, readOffset, readData); 276 if (ret < 0) { 277 throw new IOException("Error reading from " + makeDescription() + ". Got '" + ret + "'."); 278 } 279 return ret; 280 } 281 282 /** 283 * This helper method creates a string describing bus file name and device address (in hex). 284 * 285 * @return string with all details 286 */ 287 protected String makeDescription() { 288 return "I2CDevice on " + bus + " at address 0x" + Integer.toHexString(deviceAddress); 289 } 290 291 /** 292 * This helper method creates a string describing bus file name, device address (in hex) and local i2c address. 293 * 294 * @param address local address in i2c device 295 * @return string with all details 296 */ 297 protected String makeDescription(int address) { 298 return "I2CDevice on " + bus + " at address 0x" + Integer.toHexString(deviceAddress) + " to address 0x" + Integer.toHexString(address); 299 } 300}