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 - 2013 Pi4J 015 * %% 016 * Licensed under the Apache License, Version 2.0 (the "License"); 017 * you may not use this file except in compliance with the License. 018 * You may obtain a copy of the License at 019 * 020 * http://www.apache.org/licenses/LICENSE-2.0 021 * 022 * Unless required by applicable law or agreed to in writing, software 023 * distributed under the License is distributed on an "AS IS" BASIS, 024 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 025 * See the License for the specific language governing permissions and 026 * limitations under the License. 027 * #L% 028 */ 029 030import java.io.IOException; 031 032import com.pi4j.io.i2c.I2CDevice; 033import com.pi4j.jni.I2C; 034 035/** 036 * Implementation of i2c device. This class only holds reference to i2c bus (so it can use its handle) and 037 * device address. 038 * 039 * @author Daniel Sendula 040 * 041 */ 042public class I2CDeviceImpl implements I2CDevice { 043 044 /** Reference to i2c bus */ 045 private I2CBusImpl bus; 046 047 /** I2c device address */ 048 private int deviceAddress; 049 050 /** 051 * Constructor. 052 * 053 * @param bus i2c bus 054 * @param address i2c device address 055 */ 056 public I2CDeviceImpl(I2CBusImpl bus, int address) { 057 this.bus = bus; 058 this.deviceAddress = address; 059 } 060 061 /** 062 * This method writes one byte to i2c device. 063 * 064 * @param b byte to be written 065 * 066 * @throws IOException thrown in case byte cannot be written to the i2c device or i2c bus 067 */ 068 @Override 069 public void write(byte data) throws IOException { 070 int ret = I2C.i2cWriteByteDirect(bus.fd, deviceAddress, data); 071 if (ret < 0) { 072 throw new IOException("Error writing to " + makeDescription() + ". Got " + ret + "."); 073 } 074 } 075 076 /** 077 * This method writes several bytes to the i2c device from given buffer at given offset. 078 * 079 * @param buffer buffer of data to be written to the i2c device in one go 080 * @param offset offset in buffer 081 * @param size number of bytes to be written 082 * 083 * @throws IOException thrown in case byte cannot be written to the i2c device or i2c bus 084 */ 085 @Override 086 public void write(byte[] buffer, int offset, int size) throws IOException { 087 088 int ret = I2C.i2cWriteBytesDirect(bus.fd, deviceAddress, size, offset, buffer); 089 if (ret < 0) { 090 throw new IOException("Error writing to " + makeDescription() + ". Got " + ret + "."); 091 } 092 } 093 094 /** 095 * This method writes one byte to i2c device. 096 * 097 * @param address local address in the i2c device 098 * @param b byte to be written 099 * 100 * @throws IOException thrown in case byte cannot be written to the i2c device or i2c bus 101 */ 102 @Override 103 public void write(int address, byte data) throws IOException { 104 int ret = I2C.i2cWriteByte(bus.fd, deviceAddress, address, data); 105 if (ret < 0) { 106 throw new IOException("Error writing to " + makeDescription(address) + ". Got " + ret + "."); 107 } 108 } 109 110 /** 111 * This method writes several bytes to the i2c device from given buffer at given offset. 112 * 113 * @param address local address in the i2c device 114 * @param buffer buffer of data to be written to the i2c device in one go 115 * @param offset offset in buffer 116 * @param size number of bytes to be written 117 * 118 * @throws IOException thrown in case byte cannot be written to the i2c device or i2c bus 119 */ 120 @Override 121 public void write(int address, byte[] buffer, int offset, int size) throws IOException { 122 123 int ret = I2C.i2cWriteBytes(bus.fd, deviceAddress, address, size, offset, buffer); 124 if (ret < 0) { 125 throw new IOException("Error writing to " + makeDescription(address) + ". Got " + ret + "."); 126 } 127 } 128 129 /** 130 * This method reads one byte from the i2c device. Result is between -128 and 127. 131 * 132 * @return 133 * 134 * @throws IOException thrown in case byte cannot be read from the i2c device or i2c bus 135 */ 136 @Override 137 public int read() throws IOException { 138 int ret = I2C.i2cReadByteDirect(bus.fd, deviceAddress); 139 if (ret < 0) { 140 throw new IOException("Error reading from " + makeDescription() + ". Got " + ret + "."); 141 } 142 return ret; 143 } 144 145 /** 146 * <p>This method reads bytes from the i2c device to given buffer at asked offset. </p> 147 * 148 * <p>Note: Current implementation calls {@link #read(int)}. That means for each read byte 149 * i2c bus will send (next) address to i2c device. 150 * </p> 151 * 152 * @param buffer buffer of data to be read from the i2c device in one go 153 * @param offset offset in buffer 154 * @param size number of bytes to be read 155 * 156 * @return number of bytes read 157 * 158 * @throws IOException thrown in case byte cannot be read from the i2c device or i2c bus 159 */ 160 @Override 161 public int read(byte[] buffer, int offset, int size) throws IOException { 162 // It doesn't work for some reason. 163 int ret = I2C.i2cReadBytesDirect(bus.fd, deviceAddress, size, offset, buffer); 164 if (ret < 0) { 165 throw new IOException("Error reading from " + makeDescription() + ". Got " + ret + "."); 166 } 167 return ret; 168 } 169 170 /** 171 * This method reads one byte from the i2c device. Result is between -128 and 127. 172 * 173 * @param address local address in the i2c device 174 * @return 175 * 176 * @throws IOException thrown in case byte cannot be read from the i2c device or i2c bus 177 */ 178 @Override 179 public int read(int address) throws IOException { 180 int ret = I2C.i2cReadByte(bus.fd, deviceAddress, address); 181 if (ret < 0) { 182 throw new IOException("Error reading from " + makeDescription(address) + ". Got " + ret + "."); 183 } 184 return ret; 185 } 186 187 /** 188 * <p>This method reads bytes from the i2c device to given buffer at asked offset. </p> 189 * 190 * <p>Note: Current implementation calls {@link #read(int)}. That means for each read byte 191 * i2c bus will send (next) address to i2c device. 192 * </p> 193 * 194 * @param address local address in the i2c device 195 * @param buffer buffer of data to be read from the i2c device in one go 196 * @param offset offset in buffer 197 * @param size number of bytes to be read 198 * 199 * @return number of bytes read 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(int address, byte[] buffer, int offset, int size) throws IOException { 205 // It doesn't work for some reason. 206 int ret = I2C.i2cReadBytes(bus.fd, deviceAddress, address, size, offset, buffer); 207 if (ret < 0) { 208 throw new IOException("Error reading from " + makeDescription(address) + ". Got " + ret + "."); 209 } 210 return ret; 211 } 212 213 /** 214 * This helper method creates a string describing bus file name and device address (in hex). 215 * 216 * @return string with all details 217 */ 218 protected String makeDescription() { 219 return bus.filename + " at address 0x" + Integer.toHexString(deviceAddress); 220 } 221 222 /** 223 * This helper method creates a string describing bus file name, device address (in hex) 224 * and local i2c address. 225 * 226 * @param address local address in i2c device 227 * @return string with all details 228 */ 229 protected String makeDescription(int address) { 230 return bus.filename + " at address 0x" + Integer.toHexString(deviceAddress) 231 + " to address 0x" + Integer.toHexString(address); 232 } 233 234}