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