using System;
using System.Threading.Tasks;
using Unosquare.RaspberryIO.Native;
namespace Unosquare.RaspberryIO.Gpio {
///
/// Represents a device on the I2C Bus
///
public class I2CDevice {
private readonly Object _syncLock = new Object();
///
/// Initializes a new instance of the class.
///
/// The device identifier.
/// The file descriptor.
internal I2CDevice(Int32 deviceId, Int32 fileDescriptor) {
this.DeviceId = deviceId;
this.FileDescriptor = fileDescriptor;
}
///
/// Gets the device identifier.
///
///
/// The device identifier.
///
public Int32 DeviceId {
get;
}
///
/// Gets the standard POSIX file descriptor.
///
///
/// The file descriptor.
///
public Int32 FileDescriptor {
get;
}
///
/// Reads a byte from the specified file descriptor
///
/// The byte from device
public Byte Read() {
lock(this._syncLock) {
Int32 result = WiringPi.WiringPiI2CRead(this.FileDescriptor);
if(result < 0) {
HardwareException.Throw(nameof(I2CDevice), nameof(Read));
}
return (Byte)result;
}
}
///
/// Reads a byte from the specified file descriptor
///
/// The byte from device
public Task ReadAsync() => Task.Run(() => this.Read());
///
/// Reads a buffer of the specified length, one byte at a time
///
/// The length.
/// The byte array from device
public Byte[] Read(Int32 length) {
lock(this._syncLock) {
Byte[] buffer = new Byte[length];
for(Int32 i = 0; i < length; i++) {
Int32 result = WiringPi.WiringPiI2CRead(this.FileDescriptor);
if(result < 0) {
HardwareException.Throw(nameof(I2CDevice), nameof(Read));
}
buffer[i] = (Byte)result;
}
return buffer;
}
}
///
/// Reads a buffer of the specified length, one byte at a time
///
/// The length.
/// The byte array from device
public Task ReadAsync(Int32 length) => Task.Run(() => this.Read(length));
///
/// Writes a byte of data the specified file descriptor.
///
/// The data.
public void Write(Byte data) {
lock(this._syncLock) {
Int32 result = WiringPi.WiringPiI2CWrite(this.FileDescriptor, data);
if(result < 0) {
HardwareException.Throw(nameof(I2CDevice), nameof(Write));
}
}
}
///
/// Writes a byte of data the specified file descriptor.
///
/// The data.
/// The awaitable task
public Task WriteAsync(Byte data) => Task.Run(() => this.Write(data));
///
/// Writes a set of bytes to the specified file descriptor.
///
/// The data.
public void Write(Byte[] data) {
lock(this._syncLock) {
foreach(Byte b in data) {
Int32 result = WiringPi.WiringPiI2CWrite(this.FileDescriptor, b);
if(result < 0) {
HardwareException.Throw(nameof(I2CDevice), nameof(Write));
}
}
}
}
///
/// Writes a set of bytes to the specified file descriptor.
///
/// The data.
/// The awaitable task
public Task WriteAsync(Byte[] data) => Task.Run(() => this.Write(data));
///
/// These write an 8 or 16-bit data value into the device register indicated.
///
/// The register.
/// The data.
public void WriteAddressByte(Int32 address, Byte data) {
lock(this._syncLock) {
Int32 result = WiringPi.WiringPiI2CWriteReg8(this.FileDescriptor, address, data);
if(result < 0) {
HardwareException.Throw(nameof(I2CDevice), nameof(WriteAddressByte));
}
}
}
///
/// These write an 8 or 16-bit data value into the device register indicated.
///
/// The register.
/// The data.
public void WriteAddressWord(Int32 address, UInt16 data) {
lock(this._syncLock) {
Int32 result = WiringPi.WiringPiI2CWriteReg16(this.FileDescriptor, address, data);
if(result < 0) {
HardwareException.Throw(nameof(I2CDevice), nameof(WriteAddressWord));
}
}
}
///
/// These read an 8 or 16-bit value from the device register indicated.
///
/// The register.
/// The address byte from device
public Byte ReadAddressByte(Int32 address) {
lock(this._syncLock) {
Int32 result = WiringPi.WiringPiI2CReadReg8(this.FileDescriptor, address);
if(result < 0) {
HardwareException.Throw(nameof(I2CDevice), nameof(ReadAddressByte));
}
return (Byte)result;
}
}
///
/// These read an 8 or 16-bit value from the device register indicated.
///
/// The register.
/// The address word from device
public UInt16 ReadAddressWord(Int32 address) {
lock(this._syncLock) {
Int32 result = WiringPi.WiringPiI2CReadReg16(this.FileDescriptor, address);
if(result < 0) {
HardwareException.Throw(nameof(I2CDevice), nameof(ReadAddressWord));
}
return Convert.ToUInt16(result);
}
}
}
}