namespace Unosquare.RaspberryIO.Gpio { using System; using System.Threading.Tasks; using Native; /// /// 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(int deviceId, int fileDescriptor) { DeviceId = deviceId; FileDescriptor = fileDescriptor; } /// /// Gets the device identifier. /// /// /// The device identifier. /// public int DeviceId { get; } /// /// Gets the standard POSIX file descriptor. /// /// /// The file descriptor. /// public int FileDescriptor { get; } /// /// Reads a byte from the specified file descriptor /// /// The byte from device public byte Read() { lock (_syncLock) { var result = WiringPi.WiringPiI2CRead(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(() => Read()); /// /// Reads a buffer of the specified length, one byte at a time /// /// The length. /// The byte array from device public byte[] Read(int length) { lock (_syncLock) { var buffer = new byte[length]; for (var i = 0; i < length; i++) { var result = WiringPi.WiringPiI2CRead(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(int length) => Task.Run(() => Read(length)); /// /// Writes a byte of data the specified file descriptor. /// /// The data. public void Write(byte data) { lock (_syncLock) { var result = WiringPi.WiringPiI2CWrite(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(() => { Write(data); }); /// /// Writes a set of bytes to the specified file descriptor. /// /// The data. public void Write(byte[] data) { lock (_syncLock) { foreach (var b in data) { var result = WiringPi.WiringPiI2CWrite(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) { return Task.Run(() => { Write(data); }); } /// /// These write an 8 or 16-bit data value into the device register indicated. /// /// The register. /// The data. public void WriteAddressByte(int address, byte data) { lock (_syncLock) { var result = WiringPi.WiringPiI2CWriteReg8(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(int address, ushort data) { lock (_syncLock) { var result = WiringPi.WiringPiI2CWriteReg16(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(int address) { lock (_syncLock) { var result = WiringPi.WiringPiI2CReadReg8(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 ushort ReadAddressWord(int address) { lock (_syncLock) { var result = WiringPi.WiringPiI2CReadReg16(FileDescriptor, address); if (result < 0) HardwareException.Throw(nameof(I2CDevice), nameof(ReadAddressWord)); return Convert.ToUInt16(result); } } } }