All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.pi4j.plugin.linuxfs.provider.i2c.LinuxFsI2C Maven / Gradle / Ivy

There is a newer version: 2.7.0
Show newest version
package com.pi4j.plugin.linuxfs.provider.i2c;

/*-
 * #%L
 * **********************************************************************
 * ORGANIZATION  :  Pi4J
 * PROJECT       :  Pi4J :: PLUGIN   :: LinuxFS I/O Providers
 * FILENAME      :  PiGpioI2C.java
 *
 * This file is part of the Pi4J project. More information about
 * this project can be found here:  https://pi4j.com/
 * **********************************************************************
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Lesser General Public License as
 * published by the Free Software Foundation, either version 3 of the
 * License, or (at your option) any later version.*
 *
 * You should have received a copy of the GNU General Lesser Public
 * License along with this program.  If not, see
 * .
 * #L%
 */

import java.io.RandomAccessFile;
import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import java.nio.IntBuffer;
import java.util.Objects;

import com.pi4j.io.i2c.I2C;
import com.pi4j.io.i2c.I2CBase;
import com.pi4j.io.i2c.I2CConfig;
import com.pi4j.io.i2c.I2CProvider;

import  com.pi4j.plugin.linuxfs.util.SystemUtil;

/**
 * 

PiGpioI2C class.

* * @author Robert Savage (http://www.savagehomeautomation.com) * @version $Id: $Id */ public class LinuxFsI2C extends I2CBase implements I2C { private final LinuxFsI2CBus i2CBus; /** *

Constructor for PiGpioI2C.

* * @param provider * a {@link I2CProvider} object. * @param config * a {@link I2CConfig} object. */ public LinuxFsI2C(LinuxFsI2CBus i2CBus, I2CProvider provider, I2CConfig config) { super(provider, config); this.i2CBus = i2CBus; } // ------------------------------------------------------------------- // RAW DEVICE WRITE FUNCTIONS // ------------------------------------------------------------------- /** * {@inheritDoc} */ @Override public int write(byte b) { return this.i2CBus.execute(this, file -> { file.write(b); return 1; }); } /** * {@inheritDoc} */ @Override public int write(byte[] data, int offset, int length) { Objects.checkFromIndexSize(offset, length, data.length); return this.i2CBus.execute(this, file -> { file.write(data, offset, length); return length; }); } // ------------------------------------------------------------------- // RAW DEVICE READ FUNCTIONS // ------------------------------------------------------------------- /** * {@inheritDoc} */ @Override public int read() { return this.i2CBus.execute(this, RandomAccessFile::read); } /** * {@inheritDoc} */ @Override public int read(byte[] buffer, int offset, int length) { Objects.checkFromIndexSize(offset, length, buffer.length); return this.i2CBus.execute(this, file -> file.read(buffer, offset, length)); } // ------------------------------------------------------------------- // DEVICE REGISTER WRITE FUNCTIONS // ------------------------------------------------------------------- /** * {@inheritDoc} */ @Override public int writeRegister(int register, byte b) { return write((byte) register, b); } /** * {@inheritDoc} */ @Override public int writeRegister(int register, byte[] data, int offset, int length) { Objects.checkFromIndexSize(offset, length, data.length); byte[] tmp = new byte[length + 1]; tmp[0] = (byte) register; System.arraycopy(data, offset, tmp, 1, length); return write(tmp); } /** * {@inheritDoc} */ @Override public int writeRegister(byte[] register, byte[] data, int offset, int length) { Objects.checkFromIndexSize(offset, length, data.length); byte[] tmp = new byte[length + register.length]; System.arraycopy(register,0, tmp, 0, length); System.arraycopy(data, offset, tmp, register.length, length); int rc = write(tmp); return (rc - register.length); // do not include the register bytes as what was written... } // ------------------------------------------------------------------- // DEVICE REGISTER READ FUNCTIONS // ------------------------------------------------------------------- /** * {@inheritDoc} */ @Override public int readRegister(int register) { return this.i2CBus.execute(this, file -> { file.write(register); return file.read(); }); } /** * {@inheritDoc} */ @Override public int readRegister(int register, byte[] buffer, int offset, int length) { Objects.checkFromIndexSize(offset, length, buffer.length); return this.i2CBus.execute(this, file -> { file.write(register); return file.read(buffer, offset, length); }); } /** * {@inheritDoc} * *

This function uses the IOCTL interface to the LinuxFS. This * is required so the I2C transaction uses an I2C RESTART. * The following details explain creating the ByteBuffers used * to create the 'C" structures for the IOCTL.

*

i2c_msg: The space *buf will be used to set a pointer to the data buffer. * This pointer must be aligned to the machines 4 or 8 byte alignment. *

*

* This alignment is accomplished when the pointer is 'put' into the * ByteBuffer *

* *
    *
  • struct i2c_msg {
  • *
  • __u16 addr;
  • *
  • __u16 flags;
  • *
  • __u16 len;
  • *
  • __u8 *buf; wordSize
  • *
  • u8 buffer
  • *
  • };
  • *
*

* The ioctl command is I2CConstants.I2C_RDWR, this command requires * two i2c_msg entries. *

*

The following describes the ByteBuffer, ioctlData, contents:

* *
    *
  • two byte address entry one
  • *
  • two byte len entry one
  • *
  • Possible padding for alignment
  • *
  • word size area for pointer to write data buffer
  • *
  • two byte address entry two
  • *
  • two byte flags entry two
  • *
  • two byte len entry two
  • *
  • Possible padding for alignment
  • *
  • word size area for pointer to read data buffer
  • *
  • Bytes required to contain write buffer contents
  • *
  • Bytes required to contain read data buffer
  • *
* *

There is a second byte buffer, offsets, this specifies the * ByteBuffer offset of any pointer paired with the ByteBuffer offset * of the data pointed to.

* * This ByteBuffer contents *
    *
  • ByteBuffer position start of pointer to write data buffer
  • *
  • ByteBuffer position start of write buffer contents
  • *
  • ByteBuffer position start of pointer to read data buffer
  • *
  • ByteBuffer position start of read buffer contents
  • *
* */ @Override public int readRegister(byte[] register, byte[] buffer, int offset, int length) { Objects.checkFromIndexSize(offset, length, buffer.length); // command I2C_RDWR long command = I2CConstants.I2C_RDWR; // create byte buffer containing the i2c messages // address,flags, number of bytes data, pointer // First message to write device register short deviceAddr = (short) (this.config.device()& 0xff); short writeFlags = (short) (I2CConstants.I2C_SMBUS_WRITE & 0xff); short writeLength = (short) register.length; // two pointers will be used so 2 pairs of offset entries IntBuffer offsets = IntBuffer.allocate(4); // create ByteBuffer, load with write details ByteBuffer ioctlData = ByteBuffer.allocate(500); // Ensures Pi BCM little_endian ioctlData.order(ByteOrder.nativeOrder()); ioctlData.putShort(deviceAddr); ioctlData.putShort(writeFlags); ioctlData.putShort(writeLength); // Before creating the pointer entry space, see if we are properly aligned int wrtAlignValue = ioctlData.position()%SystemUtil.getWordSize(); // test if current position is less than word size, if less move position to word boundary // If greater than word size set position to next word boundary if(ioctlData.position() { writeRegisterWord(register, word); return readRegisterWord(register); }); } }




© 2015 - 2025 Weber Informatics LLC | Privacy Policy