using Unosquare.RaspberryIO.Native; using Unosquare.Swan.Abstractions; using System.Collections.Generic; using System.Collections.ObjectModel; using System.Linq; using System; namespace Unosquare.RaspberryIO.Gpio { /// /// A simple wrapper for the I2c bus on the Raspberry Pi /// public class I2CBus : SingletonBase { // TODO: It would be nice to integrate i2c device detection. private static readonly Object SyncRoot = new Object(); private readonly Dictionary _devices = new Dictionary(); /// /// Prevents a default instance of the class from being created. /// private I2CBus() { // placeholder } /// /// Gets the registered devices as a read only collection. /// public ReadOnlyCollection Devices => new ReadOnlyCollection(this._devices.Values.ToArray()); /// /// Gets the with the specified device identifier. /// /// /// The . /// /// The device identifier. /// A reference to an I2C device public I2CDevice this[Int32 deviceId] => this.GetDeviceById(deviceId); /// /// Gets the device by identifier. /// /// The device identifier. /// The device reference public I2CDevice GetDeviceById(Int32 deviceId) { lock(SyncRoot) { return this._devices[deviceId]; } } /// /// Adds a device to the bus by its Id. If the device is already registered it simply returns the existing device. /// /// The device identifier. /// The device reference /// When the device file descriptor is not found public I2CDevice AddDevice(Int32 deviceId) { lock(SyncRoot) { if(this._devices.ContainsKey(deviceId)) { return this._devices[deviceId]; } Int32 fileDescriptor = SetupFileDescriptor(deviceId); if(fileDescriptor < 0) { throw new KeyNotFoundException($"Device with id {deviceId} could not be registered with the I2C bus. Error Code: {fileDescriptor}."); } I2CDevice device = new I2CDevice(deviceId, fileDescriptor); this._devices[deviceId] = device; return device; } } /// /// This initializes the I2C system with your given device identifier. /// The ID is the I2C number of the device and you can use the i2cdetect program to find this out. /// wiringPiI2CSetup() will work out which revision Raspberry Pi you have and open the appropriate device in /dev. /// The return value is the standard Linux filehandle, or -1 if any error – in which case, you can consult errno as usual. /// /// The device identifier. /// The Linux file handle private static Int32 SetupFileDescriptor(Int32 deviceId) { lock(SyncRoot) { return WiringPi.WiringPiI2CSetup(deviceId); } } } }