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); } } } }