未验证 提交 254244cc 编写于 作者: K Krzysztof Wicher 提交者: GitHub

Enable SA1204 (#1444)

上级 96fd9f1d
......@@ -74,7 +74,7 @@
<Rule Id="SA1201" Action="None" /> <!--Enum should not follow a class -->
<Rule Id="SA1202" Action="None" />
<Rule Id="SA1203" Action="Error" />
<Rule Id="SA1204" Action="None" />
<Rule Id="SA1204" Action="Error" />
<Rule Id="SA1205" Action="Error" />
<Rule Id="SA1206" Action="Error" />
<Rule Id="SA1207" Action="Error" />
......@@ -85,6 +85,7 @@
<Rule Id="SA1212" Action="Error" />
<Rule Id="SA1213" Action="Error" />
<Rule Id="SA1214" Action="Error" />
<Rule Id="SA1215" Action="Error" />
<Rule Id="SA1216" Action="Error" />
<Rule Id="SA1217" Action="Error" /> <!-- Using statements should be ordered by alphabet -->
<Rule Id="SA1300" Action="Error" />
......
......@@ -28,9 +28,10 @@ namespace System.Device.Gpio.Drivers
private const string DeviceTreeRanges = "/proc/device-tree/soc/ranges";
private const string ModelFilePath = "/proc/device-tree/model";
private static readonly object s_initializationLock = new object();
private readonly PinState?[] _pinModes;
private RegisterView* _registerViewPointer = null;
private static readonly object s_initializationLock = new object();
private UnixDriver? _interruptDriver = null;
......
......@@ -21,10 +21,12 @@ namespace System.Device.Gpio.Drivers
private const string GpioContoller = "pinctrl";
private const string GpioOffsetBase = "/base";
private const int PollingTimeout = 50;
private static readonly int s_pinOffset = ReadOffset();
private readonly CancellationTokenSource _eventThreadCancellationTokenSource;
private readonly List<int> _exportedPins = new List<int>();
private readonly Dictionary<int, UnixDriverDevicePin> _devicePins = new Dictionary<int, UnixDriverDevicePin>();
private static readonly int s_pinOffset = ReadOffset();
private TimeSpan _statusUpdateSleepTime = TimeSpan.FromMilliseconds(1);
private int _pollFileDescriptor = -1;
private Thread? _eventDetectionThread;
......
......@@ -11,20 +11,16 @@ namespace System.Device.Gpio.Drivers
{
internal sealed class LibGpiodDriverEventHandler : IDisposable
{
public event PinChangeEventHandler? ValueRising;
private static string s_consumerName = Process.GetCurrentProcess().ProcessName;
public event PinChangeEventHandler? ValueRising;
public event PinChangeEventHandler? ValueFalling;
private int _pinNumber;
public CancellationTokenSource CancellationTokenSource;
private Task _task;
private bool _disposing = false;
private static string s_consumerName = Process.GetCurrentProcess().ProcessName;
public LibGpiodDriverEventHandler(int pinNumber, SafeLineHandle safeLineHandle)
{
_pinNumber = pinNumber;
......
......@@ -14,6 +14,23 @@ namespace System.Device.I2c
/// </summary>
public abstract I2cConnectionSettings ConnectionSettings { get; }
/// <summary>
/// Creates a communications channel to a device on an I2C bus running on the current platform
/// </summary>
/// <param name="settings">The connection settings of a device on an I2C bus.</param>
/// <returns>A communications channel to a device on an I2C bus running on Windows 10 IoT.</returns>
public static I2cDevice Create(I2cConnectionSettings settings)
{
if (Environment.OSVersion.Platform == PlatformID.Win32NT)
{
return CreateWindows10I2cDevice(settings);
}
else
{
return new UnixI2cDevice(UnixI2cBus.Create(settings.BusId), settings.DeviceAddress, shouldDisposeBus: true);
}
}
/// <summary>
/// Reads a byte from the I2C device.
/// </summary>
......@@ -57,23 +74,6 @@ namespace System.Device.I2c
/// </param>
public abstract void WriteRead(ReadOnlySpan<byte> writeBuffer, Span<byte> readBuffer);
/// <summary>
/// Creates a communications channel to a device on an I2C bus running on the current platform
/// </summary>
/// <param name="settings">The connection settings of a device on an I2C bus.</param>
/// <returns>A communications channel to a device on an I2C bus running on Windows 10 IoT.</returns>
public static I2cDevice Create(I2cConnectionSettings settings)
{
if (Environment.OSVersion.Platform == PlatformID.Win32NT)
{
return CreateWindows10I2cDevice(settings);
}
else
{
return new UnixI2cDevice(UnixI2cBus.Create(settings.BusId), settings.DeviceAddress, shouldDisposeBus: true);
}
}
/// <inheritdoc cref="IDisposable.Dispose"/>
public void Dispose()
{
......
......@@ -104,6 +104,11 @@ namespace System.Device.Pwm.Channels
return (int)((1.0 / frequency) * 1_000_000_000);
}
private static int GetDutyCycleOnTimeNs(int pwmPeriodNs, double dutyCycle)
{
return (int)(pwmPeriodNs * dutyCycle);
}
private void SetFrequency(int frequency, double newDutyCycle, int? dutyCycleOnTimeNs = null)
{
if (frequency < 0)
......@@ -162,11 +167,6 @@ namespace System.Device.Pwm.Channels
_dutyCycle = dutyCycle;
}
private static int GetDutyCycleOnTimeNs(int pwmPeriodNs, double dutyCycle)
{
return (int)(pwmPeriodNs * dutyCycle);
}
/// <summary>
/// Verifies the specified chip and channel are available.
/// </summary>
......
......@@ -8,6 +8,23 @@ namespace System.Device.Spi
/// </summary>
public abstract partial class SpiDevice : IDisposable
{
/// <summary>
/// Creates a communications channel to a device on a SPI bus running on the current hardware
/// </summary>
/// <param name="settings">The connection settings of a device on a SPI bus.</param>
/// <returns>A communications channel to a device on a SPI bus.</returns>
public static SpiDevice Create(SpiConnectionSettings settings)
{
if (Environment.OSVersion.Platform == PlatformID.Win32NT)
{
return CreateWindows10SpiDevice(settings);
}
else
{
return new UnixSpiDevice(settings);
}
}
/// <summary>
/// The connection settings of a device on a SPI bus. The connection settings are immutable after the device is created
/// so the object returned will be a clone of the settings object.
......@@ -50,23 +67,6 @@ namespace System.Device.Spi
/// <param name="readBuffer">The buffer to read the data from the SPI device.</param>
public abstract void TransferFullDuplex(ReadOnlySpan<byte> writeBuffer, Span<byte> readBuffer);
/// <summary>
/// Creates a communications channel to a device on a SPI bus running on the current hardware
/// </summary>
/// <param name="settings">The connection settings of a device on a SPI bus.</param>
/// <returns>A communications channel to a device on a SPI bus.</returns>
public static SpiDevice Create(SpiConnectionSettings settings)
{
if (Environment.OSVersion.Platform == PlatformID.Win32NT)
{
return CreateWindows10SpiDevice(settings);
}
else
{
return new UnixSpiDevice(settings);
}
}
/// <inheritdoc cref="IDisposable.Dispose"/>
public void Dispose()
{
......
......@@ -24,6 +24,11 @@ namespace Iot.Device.Bmxx80
public class Bme680 : Bmxx80Base
{
private static readonly Temperature DefaultAmbientTemperature = Temperature.FromDegreesCelsius(20);
private static readonly byte[] s_osToMeasCycles = { 0, 1, 2, 4, 8, 16 };
private static readonly byte[] s_osToSwitchCount = { 0, 1, 1, 1, 1, 1 };
private static readonly double[] s_k1Lookup = { 0.0, 0.0, 0.0, 0.0, 0.0, -1.0, 0.0, -0.8, 0.0, 0.0, -0.2, -0.5, 0.0, -1.0, 0.0, 0.0 };
private static readonly double[] s_k2Lookup = { 0.0, 0.0, 0.0, 0.0, 0.1, 0.7, 0.0, -0.8, -0.1, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0 };
private readonly Temperature _ambientTemperatureUserDefault;
/// <summary>
......@@ -57,11 +62,6 @@ namespace Iot.Device.Bmxx80
private Bme680FilteringMode _filterMode;
private Sampling _humiditySampling;
private static readonly byte[] s_osToMeasCycles = { 0, 1, 2, 4, 8, 16 };
private static readonly byte[] s_osToSwitchCount = { 0, 1, 1, 1, 1, 1 };
private static readonly double[] s_k1Lookup = { 0.0, 0.0, 0.0, 0.0, 0.0, -1.0, 0.0, -0.8, 0.0, 0.0, -0.2, -0.5, 0.0, -1.0, 0.0, 0.0 };
private static readonly double[] s_k2Lookup = { 0.0, 0.0, 0.0, 0.0, 0.1, 0.7, 0.0, -0.8, -0.1, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0 };
/// <summary>
/// Initialize a new instance of the <see cref="Bme680"/> class.
/// </summary>
......
......@@ -78,19 +78,6 @@ namespace Iot.Device.BoardLed
#endif
}
/// <summary>
/// Get all triggers of current LED.
/// </summary>
/// <returns>The name of triggers.</returns>
public IEnumerable<string> EnumerateTriggers()
{
_triggerReader.BaseStream.Position = 0;
// Remove selected chars
return Regex.Replace(_triggerReader.ReadToEnd(), @"\[|\]", string.Empty)
.Split(' ');
}
/// <summary>
/// Get all BoardLed instances of on-board LEDs.
/// </summary>
......@@ -105,6 +92,19 @@ namespace Iot.Device.BoardLed
.Select(x => new BoardLed(x.Name));
}
/// <summary>
/// Get all triggers of current LED.
/// </summary>
/// <returns>The name of triggers.</returns>
public IEnumerable<string> EnumerateTriggers()
{
_triggerReader.BaseStream.Position = 0;
// Remove selected chars
return Regex.Replace(_triggerReader.ReadToEnd(), @"\[|\]", string.Empty)
.Split(' ');
}
private int GetBrightness()
{
_brightnessReader.BaseStream.Position = 0;
......
......@@ -13,8 +13,6 @@ namespace Iot.Device.Card.Mifare
/// </summary>
public class MifareCard
{
// This is the actual RFID reader
private CardTransceiver _rfid;
private static readonly byte[] Mifare1KBlock1 = new byte[] { 0x14, 0x01, 0x03, 0xE1, 0x03, 0xE1, 0x03, 0xE1, 0x03, 0xE1, 0x03, 0xE1, 0x03, 0xE1, 0x03, 0xE1 };
private static readonly byte[] Mifare1KBlock2 = new byte[] { 0x03, 0xE1, 0x03, 0xE1, 0x03, 0xE1, 0x03, 0xE1, 0x03, 0xE1, 0x03, 0xE1, 0x03, 0xE1, 0x03, 0xE1 };
private static readonly byte[] Mifare1KBlock4 = new byte[] { 0x03, 0x00, 0xFE, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
......@@ -26,6 +24,9 @@ namespace Iot.Device.Card.Mifare
private static readonly byte[] StaticDefaultFirstBlockNdefKeyA = new byte[6] { 0xA0, 0xA1, 0xA2, 0xA3, 0xA4, 0xA5 };
private static readonly byte[] StaticDefaultBlocksNdefKeyA = new byte[6] { 0xD3, 0xF7, 0xD3, 0xF7, 0xD3, 0xF7 };
// This is the actual RFID reader
private CardTransceiver _rfid;
/// <summary>
/// Default Key A
/// </summary>
......
......@@ -15,6 +15,42 @@ namespace Iot.Device.CharacterLcd
{
private bool _disposed;
/// <summary>
/// Creates a GPIO based interface for the LCD.
/// </summary>
/// <param name="registerSelectPin">The pin that controls the register select.</param>
/// <param name="enablePin">The pin that controls the enable switch.</param>
/// <param name="dataPins">Collection of pins holding the data that will be printed on the screen.</param>
/// <param name="backlightPin">The optional pin that controls the backlight of the display.</param>
/// <param name="backlightBrightness">The brightness of the backlight. 0.0 for off, 1.0 for on.</param>
/// <param name="readWritePin">The optional pin that controls the read and write switch.</param>
/// <param name="controller">The controller to use with the LCD. If not specified, uses the platform default.</param>
/// <param name="shouldDispose">True to dispose the Gpio Controller</param>
public static LcdInterface CreateGpio(int registerSelectPin, int enablePin, int[] dataPins, int backlightPin = -1, float backlightBrightness = 1.0f, int readWritePin = -1, GpioController? controller = null, bool shouldDispose = true)
{
return new Gpio(registerSelectPin, enablePin, dataPins, backlightPin, backlightBrightness, readWritePin, controller, shouldDispose);
}
/// <summary>
/// Create an integrated I2c based interface for the LCD.
/// </summary>
/// <remarks>
/// This is for on-chip I2c support. For connecting via I2c GPIO expanders, use the GPIO interface <see cref="CreateGpio(int, int, int[], int, float, int, GpioController, bool)"/>.
/// </remarks>
/// <param name="device">The I2c device for the LCD.</param>
/// <param name="uses8Bit">True if the device uses 8 Bit commands, false if it handles only 4 bit commands.</param>
public static LcdInterface CreateI2c(I2cDevice device, bool uses8Bit = true)
{
if (uses8Bit)
{
return new I2c(device);
}
else
{
return new I2c4Bit(device);
}
}
/// <summary>
/// Sends byte to LCD device
/// </summary>
......@@ -109,41 +145,5 @@ namespace Iot.Device.CharacterLcd
_disposed = true;
}
}
/// <summary>
/// Creates a GPIO based interface for the LCD.
/// </summary>
/// <param name="registerSelectPin">The pin that controls the register select.</param>
/// <param name="enablePin">The pin that controls the enable switch.</param>
/// <param name="dataPins">Collection of pins holding the data that will be printed on the screen.</param>
/// <param name="backlightPin">The optional pin that controls the backlight of the display.</param>
/// <param name="backlightBrightness">The brightness of the backlight. 0.0 for off, 1.0 for on.</param>
/// <param name="readWritePin">The optional pin that controls the read and write switch.</param>
/// <param name="controller">The controller to use with the LCD. If not specified, uses the platform default.</param>
/// <param name="shouldDispose">True to dispose the Gpio Controller</param>
public static LcdInterface CreateGpio(int registerSelectPin, int enablePin, int[] dataPins, int backlightPin = -1, float backlightBrightness = 1.0f, int readWritePin = -1, GpioController? controller = null, bool shouldDispose = true)
{
return new Gpio(registerSelectPin, enablePin, dataPins, backlightPin, backlightBrightness, readWritePin, controller, shouldDispose);
}
/// <summary>
/// Create an integrated I2c based interface for the LCD.
/// </summary>
/// <remarks>
/// This is for on-chip I2c support. For connecting via I2c GPIO expanders, use the GPIO interface <see cref="CreateGpio(int, int, int[], int, float, int, GpioController, bool)"/>.
/// </remarks>
/// <param name="device">The I2c device for the LCD.</param>
/// <param name="uses8Bit">True if the device uses 8 Bit commands, false if it handles only 4 bit commands.</param>
public static LcdInterface CreateI2c(I2cDevice device, bool uses8Bit = true)
{
if (uses8Bit)
{
return new I2c(device);
}
else
{
return new I2c4Bit(device);
}
}
}
}
......@@ -72,6 +72,57 @@ namespace Iot.Device.Multiplexing
/// </summary>
public int NodeCount => _nodeCount;
/// <summary>
/// Provides the set of Charlie nodes given the set of pins and the count provided.
/// If count = 0, then the Charlieplex maximum is used for the pins provided (n^2-n).
/// </summary>
/// <param name="pins">The pins to use for the segment.</param>
/// <param name="nodeCount">The number of nodes to use. Default is the Charlieplex maximum.</param>
public static CharlieplexSegmentNode[] GetNodes(int[] pins, int nodeCount = 0)
{
int pinCount = pins.Length;
if (nodeCount == 0)
{
nodeCount = (int)Math.Pow(pinCount, 2) - pinCount;
}
CharlieplexSegmentNode[] nodes = new CharlieplexSegmentNode[nodeCount];
int pin = 0;
int pinJump = 1;
int resetCount = pinCount - 1;
bool firstLeg = false;
for (int i = 0; i < nodeCount; i++)
{
if ((pin > 0 && pin % resetCount == 0) || pin + pinJump > resetCount)
{
pin = 0;
pinJump++;
}
CharlieplexSegmentNode node = new CharlieplexSegmentNode();
if (!firstLeg)
{
node.Anode = pins[pin];
node.Cathode = pins[pin + pinJump];
firstLeg = true;
}
else
{
node.Anode = pins[pin + pinJump];
node.Cathode = pins[pin];
firstLeg = false;
pin++;
}
nodes[i] = node;
}
return nodes;
}
/// <summary>
/// Write a PinValue to a node, to update Charlieplex segment.
/// Address scheme is 0-based. Given 8 nodes, addresses would be 0-7.
......@@ -146,57 +197,6 @@ namespace Iot.Device.Multiplexing
while (watch.Elapsed < duration);
}
/// <summary>
/// Provides the set of Charlie nodes given the set of pins and the count provided.
/// If count = 0, then the Charlieplex maximum is used for the pins provided (n^2-n).
/// </summary>
/// <param name="pins">The pins to use for the segment.</param>
/// <param name="nodeCount">The number of nodes to use. Default is the Charlieplex maximum.</param>
public static CharlieplexSegmentNode[] GetNodes(int[] pins, int nodeCount = 0)
{
int pinCount = pins.Length;
if (nodeCount == 0)
{
nodeCount = (int)Math.Pow(pinCount, 2) - pinCount;
}
CharlieplexSegmentNode[] nodes = new CharlieplexSegmentNode[nodeCount];
int pin = 0;
int pinJump = 1;
int resetCount = pinCount - 1;
bool firstLeg = false;
for (int i = 0; i < nodeCount; i++)
{
if ((pin > 0 && pin % resetCount == 0) || pin + pinJump > resetCount)
{
pin = 0;
pinJump++;
}
CharlieplexSegmentNode node = new CharlieplexSegmentNode();
if (!firstLeg)
{
node.Anode = pins[pin];
node.Cathode = pins[pin + pinJump];
firstLeg = true;
}
else
{
node.Anode = pins[pin + pinJump];
node.Cathode = pins[pin];
firstLeg = false;
pin++;
}
nodes[i] = node;
}
return nodes;
}
/// <summary>
/// Cleanup.
/// Failing to dispose this class, especially when callbacks are active, may lead to undefined behavior.
......
......@@ -118,6 +118,55 @@ namespace Iot.Device.Graphics
return font;
}
private static int ReadNextDecimalNumber(ref ReadOnlySpan<char> span)
{
span = span.Trim();
int sign = 1;
if (span.Length > 0 && span[0] == '-')
{
sign = -1;
span = span.Slice(1);
}
int number = 0;
while (span.Length > 0 && ((uint)(span[0] - '0')) <= 9)
{
number = number * 10 + (span[0] - '0');
span = span.Slice(1);
}
return number * sign;
}
private static int ReadNextHexaDecimalNumber(ref ReadOnlySpan<char> span)
{
span = span.Trim();
int number = 0;
while (span.Length > 0)
{
if ((uint)(span[0] - '0') <= 9)
{
number = number * 16 + (span[0] - '0');
span = span.Slice(1);
continue;
}
else if ((uint)(Char.ToLowerInvariant(span[0]) - 'a') <= ((uint)('f' - 'a')))
{
number = number * 16 + (Char.ToLowerInvariant(span[0]) - 'a') + 10;
span = span.Slice(1);
continue;
}
else
{
break;
}
}
return number;
}
/// <summary>
/// Get character data or data for default character
/// </summary>
......@@ -275,54 +324,5 @@ namespace Iot.Device.Graphics
}
}
}
private static int ReadNextDecimalNumber(ref ReadOnlySpan<char> span)
{
span = span.Trim();
int sign = 1;
if (span.Length > 0 && span[0] == '-')
{
sign = -1;
span = span.Slice(1);
}
int number = 0;
while (span.Length > 0 && ((uint)(span[0] - '0')) <= 9)
{
number = number * 10 + (span[0] - '0');
span = span.Slice(1);
}
return number * sign;
}
private static int ReadNextHexaDecimalNumber(ref ReadOnlySpan<char> span)
{
span = span.Trim();
int number = 0;
while (span.Length > 0)
{
if ((uint)(span[0] - '0') <= 9)
{
number = number * 16 + (span[0] - '0');
span = span.Slice(1);
continue;
}
else if ((uint)(Char.ToLowerInvariant(span[0]) - 'a') <= ((uint)('f' - 'a')))
{
number = number * 16 + (Char.ToLowerInvariant(span[0]) - 'a') + 10;
span = span.Slice(1);
continue;
}
else
{
break;
}
}
return number;
}
}
}
......@@ -38,18 +38,6 @@ namespace Iot.Device.DCMotor
/// </summary>
protected GpioController Controller { get; set; }
/// <summary>
/// Releases the resources used by the <see cref="DCMotor"/> instance.
/// </summary>
public virtual void Dispose()
{
if (_shouldDispose)
{
Controller?.Dispose();
Controller = null!;
}
}
/// <summary>
/// Creates <see cref="DCMotor"/> instance using only one pin which allows to control speed in one direction.
/// </summary>
......@@ -269,5 +257,17 @@ namespace Iot.Device.DCMotor
controller,
shouldDispose);
}
/// <summary>
/// Releases the resources used by the <see cref="DCMotor"/> instance.
/// </summary>
public virtual void Dispose()
{
if (_shouldDispose)
{
Controller?.Dispose();
Controller = null!;
}
}
}
}
......@@ -12,6 +12,11 @@ namespace Iot.Device.GoPiGo3.Sensors
/// </summary>
public class AnalogSensor : ISensor
{
/// <summary>
/// List the supported Grove ports for the sensor
/// </summary>
public static List<GrovePort> SupportedPorts => new List<GrovePort>() { GrovePort.Grove1, GrovePort.Grove2 };
internal readonly GrovePort _mode;
internal GoPiGo _goPiGo;
......@@ -59,15 +64,9 @@ namespace Iot.Device.GoPiGo3.Sensors
/// </summary>
public GrovePort Port { get; internal set; }
/// <summary>
/// List the supported Grove ports for the sensor
/// </summary>
public static List<GrovePort> SupportedPorts => new List<GrovePort>() { GrovePort.Grove1, GrovePort.Grove2 };
/// <summary>
/// Get the sensor name "Analog Sensor"
/// </summary>
public string SensorName => "Analog Sensor";
}
}
......@@ -12,6 +12,11 @@ namespace Iot.Device.GoPiGo3.Sensors
/// </summary>
public class DigitalInput : ISensor
{
/// <summary>
/// List the supported Grove ports for the sensor
/// </summary>
public static List<GrovePort> SupportedPorts => new List<GrovePort>() { GrovePort.Grove1, GrovePort.Grove2 };
internal readonly GrovePort _mode;
internal GoPiGo _goPiGo;
......@@ -53,10 +58,5 @@ namespace Iot.Device.GoPiGo3.Sensors
/// Grove port
/// </summary>
public GrovePort Port { get; internal set; }
/// <summary>
/// List the supported Grove ports for the sensor
/// </summary>
public static List<GrovePort> SupportedPorts => new List<GrovePort>() { GrovePort.Grove1, GrovePort.Grove2 };
}
}
......@@ -12,6 +12,11 @@ namespace Iot.Device.GoPiGo3.Sensors
/// </summary>
public class DigitalOutput : ISensor
{
/// <summary>
/// List the supported Grove ports for the sensor
/// </summary>
public static List<GrovePort> SupportedPorts => new List<GrovePort>() { GrovePort.Grove1, GrovePort.Grove2 };
internal readonly GrovePort _mode;
internal GoPiGo _goPiGo;
internal bool _value;
......@@ -67,10 +72,5 @@ namespace Iot.Device.GoPiGo3.Sensors
/// Grove port
/// </summary>
public GrovePort Port { get; internal set; }
/// <summary>
/// List the supported Grove ports for the sensor
/// </summary>
public static List<GrovePort> SupportedPorts => new List<GrovePort>() { GrovePort.Grove1, GrovePort.Grove2 };
}
}
......@@ -23,11 +23,13 @@ namespace Iot.Device.Gpio.Drivers
public unsafe class SunxiDriver : SysFsDriver
{
private const string GpioMemoryFilePath = "/dev/mem";
private IDictionary<int, PinState> _pinModes = new Dictionary<int, PinState>();
// final_address = mapped_address + (target_address & map_mask) https://stackoverflow.com/a/37922968
private static readonly int _mapMask = Environment.SystemPageSize - 1;
private static readonly object s_initializationLock = new object();
private IDictionary<int, PinState> _pinModes = new Dictionary<int, PinState>();
private IntPtr _cpuxPointer = IntPtr.Zero;
private IntPtr _cpusPointer = IntPtr.Zero;
......
......@@ -13,6 +13,16 @@ namespace Iot.Device.GrovePiDevice.Sensors
/// </summary>
public class AnalogSensor
{
/// <summary>
/// Only Analogic ports are supported
/// </summary>
public static List<GrovePort> SupportedPorts => new List<GrovePort>()
{
GrovePort.AnalogPin0,
GrovePort.AnalogPin1,
GrovePort.AnalogPin2
};
internal GrovePi _grovePi;
/// <summary>
......@@ -62,15 +72,5 @@ namespace Iot.Device.GrovePiDevice.Sensors
/// Get the namme Analog Sensor
/// </summary>
public string SensorName => "Analog Sensor";
/// <summary>
/// Only Analogic ports are supported
/// </summary>
public static List<GrovePort> SupportedPorts => new List<GrovePort>()
{
GrovePort.AnalogPin0,
GrovePort.AnalogPin1,
GrovePort.AnalogPin2
};
}
}
......@@ -13,6 +13,23 @@ namespace Iot.Device.GrovePiDevice.Sensors
/// </summary>
public class DhtSensor
{
/// <summary>
/// Only Digital ports including the analogic sensors (A0 = D14, A1 = D15, A2 = D16)
/// </summary>
public static List<GrovePort> SupportedPorts => new List<GrovePort>()
{
GrovePort.DigitalPin2,
GrovePort.DigitalPin3,
GrovePort.DigitalPin4,
GrovePort.DigitalPin5,
GrovePort.DigitalPin6,
GrovePort.DigitalPin7,
GrovePort.DigitalPin8,
GrovePort.DigitalPin14,
GrovePort.DigitalPin15,
GrovePort.DigitalPin16
};
private readonly double[] _lastTemHum = new double[2] { double.NaN, double.NaN };
private GrovePi _grovePi;
......@@ -106,22 +123,5 @@ namespace Iot.Device.GrovePiDevice.Sensors
/// Get the name of the DHT sensor
/// </summary>
public string SensorName => $"{DhtType} Temperature and Humidity Sensor";
/// <summary>
/// Only Digital ports including the analogic sensors (A0 = D14, A1 = D15, A2 = D16)
/// </summary>
public static List<GrovePort> SupportedPorts => new List<GrovePort>()
{
GrovePort.DigitalPin2,
GrovePort.DigitalPin3,
GrovePort.DigitalPin4,
GrovePort.DigitalPin5,
GrovePort.DigitalPin6,
GrovePort.DigitalPin7,
GrovePort.DigitalPin8,
GrovePort.DigitalPin14,
GrovePort.DigitalPin15,
GrovePort.DigitalPin16
};
}
}
......@@ -13,6 +13,23 @@ namespace Iot.Device.GrovePiDevice.Sensors
/// </summary>
public class DigitalInput
{
/// <summary>
/// Only Digital ports including the analog sensors (A0 = D14, A1 = D15, A2 = D16)
/// </summary>
public static List<GrovePort> SupportedPorts => new List<GrovePort>()
{
GrovePort.DigitalPin2,
GrovePort.DigitalPin3,
GrovePort.DigitalPin4,
GrovePort.DigitalPin5,
GrovePort.DigitalPin6,
GrovePort.DigitalPin7,
GrovePort.DigitalPin8,
GrovePort.DigitalPin14,
GrovePort.DigitalPin15,
GrovePort.DigitalPin16
};
internal GrovePi _grovePi;
/// <summary>
......@@ -52,22 +69,5 @@ namespace Iot.Device.GrovePiDevice.Sensors
/// grove sensor port
/// </summary>
public GrovePort Port { get; internal set; }
/// <summary>
/// Only Digital ports including the analog sensors (A0 = D14, A1 = D15, A2 = D16)
/// </summary>
public static List<GrovePort> SupportedPorts => new List<GrovePort>()
{
GrovePort.DigitalPin2,
GrovePort.DigitalPin3,
GrovePort.DigitalPin4,
GrovePort.DigitalPin5,
GrovePort.DigitalPin6,
GrovePort.DigitalPin7,
GrovePort.DigitalPin8,
GrovePort.DigitalPin14,
GrovePort.DigitalPin15,
GrovePort.DigitalPin16
};
}
}
......@@ -13,6 +13,23 @@ namespace Iot.Device.GrovePiDevice.Sensors
/// </summary>
public class DigitalOutput
{
/// <summary>
/// Only Digital ports including the analogic sensors (A0 = D14, A1 = D15, A2 = D16)
/// </summary>
public static List<GrovePort> SupportedPorts => new List<GrovePort>()
{
GrovePort.DigitalPin2,
GrovePort.DigitalPin3,
GrovePort.DigitalPin4,
GrovePort.DigitalPin5,
GrovePort.DigitalPin6,
GrovePort.DigitalPin7,
GrovePort.DigitalPin8,
GrovePort.DigitalPin14,
GrovePort.DigitalPin15,
GrovePort.DigitalPin16
};
internal GrovePi _grovePi;
internal PinValue _value;
......@@ -66,22 +83,5 @@ namespace Iot.Device.GrovePiDevice.Sensors
/// Get the name Digital Output
/// </summary>
public string SensorName => "Digital Output";
/// <summary>
/// Only Digital ports including the analogic sensors (A0 = D14, A1 = D15, A2 = D16)
/// </summary>
public static List<GrovePort> SupportedPorts => new List<GrovePort>()
{
GrovePort.DigitalPin2,
GrovePort.DigitalPin3,
GrovePort.DigitalPin4,
GrovePort.DigitalPin5,
GrovePort.DigitalPin6,
GrovePort.DigitalPin7,
GrovePort.DigitalPin8,
GrovePort.DigitalPin14,
GrovePort.DigitalPin15,
GrovePort.DigitalPin16
};
}
}
......@@ -24,6 +24,21 @@ namespace Iot.Device.GrovePiDevice.Sensors
/// </summary>
public class LedBar
{
/// <summary>
/// Only Digital ports only but you can't create more than 4 bars as each bar is using 2 Pins
/// So you have to have at least 1 Grove Port empty between 2 bars
/// </summary>
public static List<GrovePort> SupportedPorts => new List<GrovePort>()
{
GrovePort.DigitalPin2,
GrovePort.DigitalPin3,
GrovePort.DigitalPin4,
GrovePort.DigitalPin5,
GrovePort.DigitalPin6,
GrovePort.DigitalPin7,
GrovePort.DigitalPin8,
};
private GrovePi _grovePi;
private byte _level;
private LedBarOrientation _orientation;
......@@ -166,20 +181,5 @@ namespace Iot.Device.GrovePiDevice.Sensors
/// Get the name Led Bar
/// </summary>
public string SensorName => "Led Bar";
/// <summary>
/// Only Digital ports only but you can't create more than 4 bars as each bar is using 2 Pins
/// So you have to have at least 1 Grove Port empty between 2 bars
/// </summary>
public static List<GrovePort> SupportedPorts => new List<GrovePort>()
{
GrovePort.DigitalPin2,
GrovePort.DigitalPin3,
GrovePort.DigitalPin4,
GrovePort.DigitalPin5,
GrovePort.DigitalPin6,
GrovePort.DigitalPin7,
GrovePort.DigitalPin8,
};
}
}
......@@ -13,6 +13,16 @@ namespace Iot.Device.GrovePiDevice.Sensors
/// </summary>
public class PwmOutput
{
/// <summary>
/// Only Digital PWM are supported
/// </summary>
public static List<GrovePort> SupportedPorts => new List<GrovePort>()
{
GrovePort.DigitalPin3,
GrovePort.DigitalPin5,
GrovePort.DigitalPin6
};
internal GrovePi _grovePi;
internal byte _duty;
......@@ -106,15 +116,5 @@ namespace Iot.Device.GrovePiDevice.Sensors
/// Get the name PWM Output
/// </summary>
public string SensorName => "PWM Output";
/// <summary>
/// Only Digital PWM are supported
/// </summary>
public static List<GrovePort> SupportedPorts => new List<GrovePort>()
{
GrovePort.DigitalPin3,
GrovePort.DigitalPin5,
GrovePort.DigitalPin6
};
}
}
......@@ -14,6 +14,23 @@ namespace Iot.Device.GrovePiDevice.Sensors
/// </summary>
public class UltrasonicSensor
{
/// <summary>
/// Only Digital ports including the analogic sensors (A0 = D14, A1 = D15, A2 = D16)
/// </summary>
public static List<GrovePort> SupportedPorts => new List<GrovePort>()
{
GrovePort.DigitalPin2,
GrovePort.DigitalPin3,
GrovePort.DigitalPin4,
GrovePort.DigitalPin5,
GrovePort.DigitalPin6,
GrovePort.DigitalPin7,
GrovePort.DigitalPin8,
GrovePort.DigitalPin14,
GrovePort.DigitalPin15,
GrovePort.DigitalPin16
};
private GrovePi _grovePi;
/// <summary>
......@@ -64,22 +81,5 @@ namespace Iot.Device.GrovePiDevice.Sensors
/// Get the name Ultrasonic Sensor
/// </summary>
public string SensorName => "Ultrasonic Sensor";
/// <summary>
/// Only Digital ports including the analogic sensors (A0 = D14, A1 = D15, A2 = D16)
/// </summary>
public static List<GrovePort> SupportedPorts => new List<GrovePort>()
{
GrovePort.DigitalPin2,
GrovePort.DigitalPin3,
GrovePort.DigitalPin4,
GrovePort.DigitalPin5,
GrovePort.DigitalPin6,
GrovePort.DigitalPin7,
GrovePort.DigitalPin8,
GrovePort.DigitalPin14,
GrovePort.DigitalPin15,
GrovePort.DigitalPin16
};
}
}
......@@ -52,6 +52,13 @@ namespace Iot.Device.Hts221
[Telemetry]
public RelativeHumidity Humidity => GetActualHumidity(ReadInt16(Register.Humidity));
private static float Lerp(float x, float x0, float x1, float y0, float y1)
{
float xrange = x1 - x0;
float yrange = y1 - y0;
return y0 + (x - x0) * yrange / xrange;
}
private void WriteByte(Register register, byte data)
{
Span<byte> buff = stackalloc byte[2]
......@@ -100,13 +107,6 @@ namespace Iot.Device.Hts221
return RelativeHumidity.FromPercent(Lerp(humidityRaw, h0raw, h1raw, h0x2rH / 2.0f, h1x2rH / 2.0f));
}
private static float Lerp(float x, float x0, float x1, float y0, float y1)
{
float xrange = x1 - x0;
float yrange = y1 - y0;
return y0 + (x - x0) * yrange / xrange;
}
private (ushort T0x8, ushort T1x8) GetTemperatureCalibrationPointsCelsius()
{
Span<byte> t0t1Lsb = stackalloc byte[2];
......
......@@ -24,13 +24,6 @@ namespace Iot.Device.Adc
[Interface("INA219 Bidirectional Current/Power monitor")]
public class Ina219 : IDisposable
{
private I2cDevice _i2cDevice;
private bool _disposeI2cDevice = false;
private ushort _calibrationValue;
private Ina219AdcResolutionOrSamples _busAdcResSamp;
private Ina219AdcResolutionOrSamples _shuntAdcResSamp;
private float _currentLsb;
// These values are the datasheet defined delays in micro seconds between requesting a Current or Power value from the INA219 and the ADC sampling having completed
// along with any conversions.
private static readonly Dictionary<Ina219AdcResolutionOrSamples, int> s_readDelays = new()
......@@ -48,6 +41,13 @@ namespace Iot.Device.Adc
{ Ina219AdcResolutionOrSamples.Adc128Sample, 68100 }
};
private I2cDevice _i2cDevice;
private bool _disposeI2cDevice = false;
private ushort _calibrationValue;
private Ina219AdcResolutionOrSamples _busAdcResSamp;
private Ina219AdcResolutionOrSamples _shuntAdcResSamp;
private float _currentLsb;
/// <summary>
/// Construct an Ina219 device using an I2cDevice
/// </summary>
......
......@@ -54,17 +54,6 @@ namespace Iot.Device.Lps25h
[Telemetry]
public Pressure Pressure => Pressure.FromHectopascals(ReadInt24(Register.Pressure) / 4096.0);
private void WriteByte(Register register, byte data)
{
Span<byte> buff = stackalloc byte[2]
{
(byte)register,
data
};
_i2c.Write(buff);
}
private static int ReadInt24LittleEndian(ReadOnlySpan<byte> buff)
{
Debug.Assert(buff.Length == 3, "Buffer must be 3 bytes long");
......@@ -81,6 +70,17 @@ namespace Iot.Device.Lps25h
return BinaryPrimitives.ReadInt32LittleEndian(b);
}
private void WriteByte(Register register, byte data)
{
Span<byte> buff = stackalloc byte[2]
{
(byte)register,
data
};
_i2c.Write(buff);
}
private int ReadInt24(Register register)
{
Span<byte> val = stackalloc byte[3];
......
......@@ -22,6 +22,15 @@ namespace Iot.Device.Adc
{
}
/// <summary>
/// Convert a signed value with a sign bit at a particular location to an int.
/// </summary>
/// <param name="signedValue">Signed value with a sign bit at a particular location</param>
/// <param name="signingBit">Bit number that contains the sign bit</param>
/// <returns>A value corresponding to the signed value sign extended into an int</returns>
// if the sign bit is set then extend the signing bit to create a signed integer
public static int SignExtend(int signedValue, int signingBit) => (signedValue >> signingBit) == 0 ? signedValue : signedValue - (2 << signingBit);
/// <summary>
/// Reads a value from the device using pseudo-differential inputs
/// </summary>
......@@ -70,14 +79,5 @@ namespace Iot.Device.Adc
return retval;
}
/// <summary>
/// Convert a signed value with a sign bit at a particular location to an int.
/// </summary>
/// <param name="signedValue">Signed value with a sign bit at a particular location</param>
/// <param name="signingBit">Bit number that contains the sign bit</param>
/// <returns>A value corresponding to the signed value sign extended into an int</returns>
// if the sign bit is set then extend the signing bit to create a signed integer
public static int SignExtend(int signedValue, int signingBit) => (signedValue >> signingBit) == 0 ? signedValue : signedValue - (2 << signingBit);
}
}
......@@ -16,16 +16,16 @@ namespace Iot.Device.Media
/// </summary>
internal class UnixSoundDevice : SoundDevice
{
private static readonly object s_playbackInitializationLock = new object();
private static readonly object s_recordingInitializationLock = new object();
private static readonly object s_mixerInitializationLock = new object();
private IntPtr _playbackPcm;
private IntPtr _recordingPcm;
private IntPtr _mixer;
private IntPtr _elem;
private int _errorNum;
private static readonly object s_playbackInitializationLock = new object();
private static readonly object s_recordingInitializationLock = new object();
private static readonly object s_mixerInitializationLock = new object();
private uint _recordingTotalTimeSeconds;
private bool _record;
private Thread? _recordingThread;
......
......@@ -16,9 +16,11 @@ namespace Iot.Device.Media
{
private const string DefaultDevicePath = "/dev/video";
private const int BufferCount = 4;
private int _deviceFileDescriptor = -1;
private static readonly object s_initializationLock = new object();
private int _deviceFileDescriptor = -1;
/// <summary>
/// Path to video resources located on the platform.
/// </summary>
......@@ -39,6 +41,15 @@ namespace Iot.Device.Media
DevicePath = DefaultDevicePath;
}
private static unsafe void UnmappingFrameBuffers(V4l2FrameBuffer* buffers)
{
// Unmapping the applied buffer to user space
for (uint i = 0; i < BufferCount; i++)
{
Interop.munmap(buffers[i].Start, (int)buffers[i].Length);
}
}
/// <summary>
/// Capture a picture from the video device.
/// </summary>
......@@ -249,15 +260,6 @@ namespace Iot.Device.Media
return buffers;
}
private static unsafe void UnmappingFrameBuffers(V4l2FrameBuffer* buffers)
{
// Unmapping the applied buffer to user space
for (uint i = 0; i < BufferCount; i++)
{
Interop.munmap(buffers[i].Start, (int)buffers[i].Length);
}
}
private unsafe void SetVideoConnectionSettings()
{
FillVideoConnectionSettings();
......
......@@ -70,14 +70,14 @@ namespace CameraIoT
}
/// <summary>
/// Timezone to use for the time stamp
/// Get the camera instance
/// </summary>
public int Timezone { get; set; } = 0;
public static Camera Instance => _instance;
/// <summary>
/// Get the camera instance
/// Timezone to use for the time stamp
/// </summary>
public static Camera Instance => _instance;
public int Timezone { get; set; } = 0;
/// <summary>
/// The last image
......
......@@ -10,18 +10,6 @@ namespace Iot.Device.OneWire
{
public partial class OneWireThermometerDevice : OneWireDevice
{
private async Task<Temperature> ReadTemperatureInternalAsync()
{
var data = await File.ReadAllTextAsync(Path.Combine(OneWireBus.SysfsDevicesPath, BusId, DeviceId, "w1_slave"));
return ParseTemperature(data);
}
private Temperature ReadTemperatureInternal()
{
var data = File.ReadAllText(Path.Combine(OneWireBus.SysfsDevicesPath, BusId, DeviceId, "w1_slave"));
return ParseTemperature(data);
}
private static Temperature ParseTemperature(string data)
{
// Expected data format:
......@@ -40,5 +28,17 @@ namespace Iot.Device.OneWire
return Temperature.FromDegreesCelsius(temp * 0.001);
}
private async Task<Temperature> ReadTemperatureInternalAsync()
{
var data = await File.ReadAllTextAsync(Path.Combine(OneWireBus.SysfsDevicesPath, BusId, DeviceId, "w1_slave"));
return ParseTemperature(data);
}
private Temperature ReadTemperatureInternal()
{
var data = File.ReadAllText(Path.Combine(OneWireBus.SysfsDevicesPath, BusId, DeviceId, "w1_slave"));
return ParseTemperature(data);
}
}
}
......@@ -48,7 +48,7 @@ namespace Iot.Device.Pca95x4
data &= (byte)~(1 << bitNumber);
}
private void SetBit(ref byte data, int bitNumber)
private static void SetBit(ref byte data, int bitNumber)
{
ValidateBitNumber(bitNumber);
data |= (byte)(1 << bitNumber);
......
......@@ -125,6 +125,65 @@ namespace Iot.Device.Pwm
DelayHelper.DelayMicroseconds(500, allowThreadYield: true);
}
private static (ushort On, ushort Off) DutyCycleToOnOff(double dutyCycle)
{
Debug.Assert(dutyCycle >= 0.0 && dutyCycle <= 1.0, "Duty cycle must be between 0 and 1");
// there are actually 4097 values in the set but we can do edge values
// using 13th bit which overrides to always on/off
ushort dutyCycleSampled = (ushort)Math.Round(dutyCycle * 4096);
if (dutyCycleSampled == 0)
{
return (0, 1 << 12);
}
else if (dutyCycleSampled == 4096)
{
return (1 << 12, 0);
}
else
{
return (0, dutyCycleSampled);
}
}
private static double OnOffToDutyCycle(ushort on, ushort off)
{
ushort OnOffToDutyCycleSampled(ushort onCycles, ushort offCycles)
{
const ushort Max = (ushort)(1 << 12);
if (onCycles == 0)
{
return (offCycles == Max) ? (ushort)0 : offCycles;
}
else if (onCycles == Max && offCycles == 0)
{
return 4096;
}
// we didn't set this value anywhere in the code
throw new InvalidOperationException($"Unexpected value of duty cycle ({onCycles}, {offCycles})");
}
return OnOffToDutyCycleSampled(on, off) / 4096.0;
}
private static void CheckDutyCycle(double dutyCycle)
{
if (dutyCycle < 0.0 || dutyCycle > 1.0)
{
throw new ArgumentOutOfRangeException(nameof(dutyCycle), dutyCycle, "Value must be between 0.0 and 1.0.");
}
}
private static void CheckChannel(int channel)
{
if (channel < 0 || channel >= 16)
{
throw new ArgumentOutOfRangeException(nameof(channel), channel, "Channel must be a value from 0 to 15.");
}
}
/// <summary>
/// Sets duty cycle on specified channel.
/// </summary>
......@@ -310,64 +369,5 @@ namespace Iot.Device.Pwm
BinaryPrimitives.WriteUInt16LittleEndian(bytes.Slice(1), value);
_device.Write(bytes);
}
private static (ushort On, ushort Off) DutyCycleToOnOff(double dutyCycle)
{
Debug.Assert(dutyCycle >= 0.0 && dutyCycle <= 1.0, "Duty cycle must be between 0 and 1");
// there are actually 4097 values in the set but we can do edge values
// using 13th bit which overrides to always on/off
ushort dutyCycleSampled = (ushort)Math.Round(dutyCycle * 4096);
if (dutyCycleSampled == 0)
{
return (0, 1 << 12);
}
else if (dutyCycleSampled == 4096)
{
return (1 << 12, 0);
}
else
{
return (0, dutyCycleSampled);
}
}
private static double OnOffToDutyCycle(ushort on, ushort off)
{
ushort OnOffToDutyCycleSampled(ushort onCycles, ushort offCycles)
{
const ushort Max = (ushort)(1 << 12);
if (onCycles == 0)
{
return (offCycles == Max) ? (ushort)0 : offCycles;
}
else if (onCycles == Max && offCycles == 0)
{
return 4096;
}
// we didn't set this value anywhere in the code
throw new InvalidOperationException($"Unexpected value of duty cycle ({onCycles}, {offCycles})");
}
return OnOffToDutyCycleSampled(on, off) / 4096.0;
}
private static void CheckDutyCycle(double dutyCycle)
{
if (dutyCycle < 0.0 || dutyCycle > 1.0)
{
throw new ArgumentOutOfRangeException(nameof(dutyCycle), dutyCycle, "Value must be between 0.0 and 1.0.");
}
}
private static void CheckChannel(int channel)
{
if (channel < 0 || channel >= 16)
{
throw new ArgumentOutOfRangeException(nameof(channel), channel, "Channel must be a value from 0 to 15.");
}
}
}
}
......@@ -25,14 +25,14 @@ namespace Iot.Device.Pn5180
{
private const int TimeoutWaitingMilliseconds = 2_000;
private static List<SelectedPiccInformation> _activeSelected = new List<SelectedPiccInformation>();
private readonly SpiDevice _spiDevice;
private readonly GpioController _gpioController;
private bool _shouldDispose;
private int _pinBusy;
private int _pinNss;
private static List<SelectedPiccInformation> _activeSelected = new List<SelectedPiccInformation>();
/// <summary>
/// A radio Frequency configuration element size is 5 bytes
/// Byte 1 = Register Address
......
......@@ -39,26 +39,6 @@ namespace Iot.Device.SenseHat
{
}
/// <summary>
/// Write colors to the device
/// </summary>
/// <param name="colors">Array of colors</param>
public abstract void Write(ReadOnlySpan<Color> colors);
/// <summary>
/// Fill LED matrix with a specific color
/// </summary>
/// <param name="color">Color to fill the device with</param>
public abstract void Fill(Color color = default(Color));
/// <summary>
/// Sets color on specific position of the LED matrix
/// </summary>
/// <param name="x">X coordinate</param>
/// <param name="y">Y coordinate</param>
/// <param name="color">Color to be set in the specified position</param>
public abstract void SetPixel(int x, int y, Color color);
/// <summary>
/// Translates position in the buffer to X, Y coordinates
/// </summary>
......@@ -97,6 +77,26 @@ namespace Iot.Device.SenseHat
return x + y * NumberOfPixelsPerRow;
}
/// <summary>
/// Write colors to the device
/// </summary>
/// <param name="colors">Array of colors</param>
public abstract void Write(ReadOnlySpan<Color> colors);
/// <summary>
/// Fill LED matrix with a specific color
/// </summary>
/// <param name="color">Color to fill the device with</param>
public abstract void Fill(Color color = default(Color));
/// <summary>
/// Sets color on specific position of the LED matrix
/// </summary>
/// <param name="x">X coordinate</param>
/// <param name="y">Y coordinate</param>
/// <param name="color">Color to be set in the specified position</param>
public abstract void SetPixel(int x, int y, Color color);
/// <inheritdoc/>
public abstract void Dispose();
}
......
......@@ -38,6 +38,20 @@ namespace Iot.Device.SenseHat
Fill(Color.Black);
}
private static string? GetSenseHatDevice()
{
foreach (string dev in Directory.EnumerateFileSystemEntries("/sys/class/graphics/", "fb*"))
{
string devName = Path.Combine(dev, "name");
if (File.Exists(devName) && File.ReadAllText(devName).Trim() == SenseHatDeviceName)
{
return Path.Combine("/dev/", Path.GetFileName(dev));
}
}
return null;
}
/// <inheritdoc/>
public override void Write(ReadOnlySpan<Color> colors)
{
......@@ -116,20 +130,6 @@ namespace Iot.Device.SenseHat
_deviceFile.Write(encoded);
}
private static string? GetSenseHatDevice()
{
foreach (string dev in Directory.EnumerateFileSystemEntries("/sys/class/graphics/", "fb*"))
{
string devName = Path.Combine(dev, "name");
if (File.Exists(devName) && File.ReadAllText(devName).Trim() == SenseHatDeviceName)
{
return Path.Combine("/dev/", Path.GetFileName(dev));
}
}
return null;
}
/// <inheritdoc/>
public override void Dispose()
{
......
......@@ -48,6 +48,71 @@ namespace Iot.Device.Shtc3
/// </summary>
internal Status Status => _status;
private static Register GetMeasurementCmd(bool lowPower, bool clockStretching)
{
if (lowPower)
{
if (clockStretching)
{
return Register.SHTC3_MEAS_T_RH_CLOCKSTR_LPM;
}
else
{
return Register.SHTC3_MEAS_T_RH_POLLING_LPM;
}
}
else
{
if (clockStretching)
{
return Register.SHTC3_MEAS_T_RH_CLOCKSTR_NPM;
}
else
{
return Register.SHTC3_MEAS_T_RH_POLLING_NPM;
}
}
}
/// <summary>
/// Check the match to the SHTC3 product code
/// Table 15 while bits 11 and 5:0 contain the SHTC3 specific product code 0b_0000_1000_0000_0111
/// </summary>
/// <param name="id">Id to test</param>
/// <returns></returns>
private static bool ValidShtc3Id(int id) =>
(id & 0b_0000_1000_0011_1111) == 0b_0000_1000_0000_0111;
/// <summary>
/// 8-bit CRC Checksum Calculation
/// </summary>
/// <param name="data">Raw Data</param>
/// <param name="crc8">Raw CRC8</param>
/// <returns>Checksum is true or false</returns>
private static bool CheckCrc8(ReadOnlySpan<byte> data, byte crc8)
{
// Details in the Datasheet table 16 P9
byte crc = CRC_INIT;
for (int i = 0; i < 2; i++)
{
crc ^= data[i];
for (int j = 8; j > 0; j--)
{
if ((crc & 0x80) != 0)
{
crc = (byte)((crc << 1) ^ CRC_POLYNOMIAL);
}
else
{
crc = (byte)(crc << 1);
}
}
}
return crc == crc8;
}
/// <summary>
/// Try read Temperature and Humidity
/// </summary>
......@@ -105,32 +170,6 @@ namespace Iot.Device.Shtc3
return true;
}
private static Register GetMeasurementCmd(bool lowPower, bool clockStretching)
{
if (lowPower)
{
if (clockStretching)
{
return Register.SHTC3_MEAS_T_RH_CLOCKSTR_LPM;
}
else
{
return Register.SHTC3_MEAS_T_RH_POLLING_LPM;
}
}
else
{
if (clockStretching)
{
return Register.SHTC3_MEAS_T_RH_CLOCKSTR_NPM;
}
else
{
return Register.SHTC3_MEAS_T_RH_POLLING_NPM;
}
}
}
/// <summary>
/// SHTC3 Sleep
/// </summary>
......@@ -200,45 +239,6 @@ namespace Iot.Device.Shtc3
return id;
}
/// <summary>
/// Check the match to the SHTC3 product code
/// Table 15 while bits 11 and 5:0 contain the SHTC3 specific product code 0b_0000_1000_0000_0111
/// </summary>
/// <param name="id">Id to test</param>
/// <returns></returns>
private static bool ValidShtc3Id(int id) =>
(id & 0b_0000_1000_0011_1111) == 0b_0000_1000_0000_0111;
/// <summary>
/// 8-bit CRC Checksum Calculation
/// </summary>
/// <param name="data">Raw Data</param>
/// <param name="crc8">Raw CRC8</param>
/// <returns>Checksum is true or false</returns>
private static bool CheckCrc8(ReadOnlySpan<byte> data, byte crc8)
{
// Details in the Datasheet table 16 P9
byte crc = CRC_INIT;
for (int i = 0; i < 2; i++)
{
crc ^= data[i];
for (int j = 8; j > 0; j--)
{
if ((crc & 0x80) != 0)
{
crc = (byte)((crc << 1) ^ CRC_POLYNOMIAL);
}
else
{
crc = (byte)(crc << 1);
}
}
}
return crc == crc8;
}
private void Write(Register register)
{
Span<byte> writeBuff = stackalloc byte[2];
......
......@@ -15,23 +15,6 @@ namespace Iot.Device.Uln2003
/// </summary>
private const long StepperMotorDefaultDelay = 1000;
private int _pin1;
private int _pin2;
private int _pin3;
private int _pin4;
private int _steps = 0;
private int _engineStep = 0;
private int _currentStep = 0;
private int _stepsToRotate = 4096;
private int _stepsToRotateInMode = 4096;
private StepperMode _mode = StepperMode.HalfStep;
private bool[,] _currentSwitchingSequence = _halfStepSequence;
private bool _isClockwise = true;
private GpioController _controller;
private bool _shouldDispose;
private Stopwatch _stopwatch = new Stopwatch();
private long _stepMicrosecondsDelay;
private static bool[,] _halfStepSequence = new bool[4, 8]
{
{ true, true, false, false, false, false, false, true },
......@@ -56,6 +39,23 @@ namespace Iot.Device.Uln2003
{ false, false, true, true, false, false, true, true }
};
private int _pin1;
private int _pin2;
private int _pin3;
private int _pin4;
private int _steps = 0;
private int _engineStep = 0;
private int _currentStep = 0;
private int _stepsToRotate = 4096;
private int _stepsToRotateInMode = 4096;
private StepperMode _mode = StepperMode.HalfStep;
private bool[,] _currentSwitchingSequence = _halfStepSequence;
private bool _isClockwise = true;
private GpioController _controller;
private bool _shouldDispose;
private Stopwatch _stopwatch = new Stopwatch();
private long _stepMicrosecondsDelay;
/// <summary>
/// Initialize a Uln2003 class.
/// </summary>
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册