RaspberryIO/Unosquare.RaspberryIO/Gpio/I2CBus.cs

94 lines
3.6 KiB
C#
Raw Normal View History

2019-02-17 14:08:57 +01:00
namespace Unosquare.RaspberryIO.Gpio
{
using Native;
using Swan.Abstractions;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Linq;
/// <summary>
/// A simple wrapper for the I2c bus on the Raspberry Pi
/// </summary>
public class I2CBus : SingletonBase<I2CBus>
{
// TODO: It would be nice to integrate i2c device detection.
private static readonly object SyncRoot = new object();
private readonly Dictionary<int, I2CDevice> _devices = new Dictionary<int, I2CDevice>();
/// <summary>
/// Prevents a default instance of the <see cref="I2CBus"/> class from being created.
/// </summary>
private I2CBus()
{
// placeholder
}
/// <summary>
/// Gets the registered devices as a read only collection.
/// </summary>
public ReadOnlyCollection<I2CDevice> Devices => new ReadOnlyCollection<I2CDevice>(_devices.Values.ToArray());
/// <summary>
/// Gets the <see cref="I2CDevice"/> with the specified device identifier.
/// </summary>
/// <value>
/// The <see cref="I2CDevice"/>.
/// </value>
/// <param name="deviceId">The device identifier.</param>
/// <returns>A reference to an I2C device</returns>
public I2CDevice this[int deviceId] => GetDeviceById(deviceId);
/// <summary>
/// Gets the device by identifier.
/// </summary>
/// <param name="deviceId">The device identifier.</param>
/// <returns>The device reference</returns>
public I2CDevice GetDeviceById(int deviceId)
{
lock (SyncRoot)
{
return _devices[deviceId];
}
}
/// <summary>
/// Adds a device to the bus by its Id. If the device is already registered it simply returns the existing device.
/// </summary>
/// <param name="deviceId">The device identifier.</param>
/// <returns>The device reference</returns>
/// <exception cref="KeyNotFoundException">When the device file descriptor is not found</exception>
public I2CDevice AddDevice(int deviceId)
{
lock (SyncRoot)
{
if (_devices.ContainsKey(deviceId))
return _devices[deviceId];
var fileDescriptor = SetupFileDescriptor(deviceId);
if (fileDescriptor < 0)
throw new KeyNotFoundException($"Device with id {deviceId} could not be registered with the I2C bus. Error Code: {fileDescriptor}.");
var device = new I2CDevice(deviceId, fileDescriptor);
_devices[deviceId] = device;
return device;
}
}
/// <summary>
/// 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.
/// </summary>
/// <param name="deviceId">The device identifier.</param>
/// <returns>The Linux file handle</returns>
private static int SetupFileDescriptor(int deviceId)
{
lock (SyncRoot)
{
return WiringPi.WiringPiI2CSetup(deviceId);
}
}
}
}