diff --git a/Unosquare.RaspberryIO/Camera/CameraColor.cs b/Unosquare.RaspberryIO/Camera/CameraColor.cs
index 6fb0c9c..25431bb 100644
--- a/Unosquare.RaspberryIO/Camera/CameraColor.cs
+++ b/Unosquare.RaspberryIO/Camera/CameraColor.cs
@@ -1,134 +1,140 @@
-namespace Unosquare.RaspberryIO.Camera
-{
- using Swan;
- using System;
- using System.Linq;
-
+using Unosquare.Swan;
+using System;
+using System.Linq;
+
+namespace Unosquare.RaspberryIO.Camera {
+ ///
+ /// A simple RGB color class to represent colors in RGB and YUV colorspaces.
+ ///
+ public class CameraColor {
///
- /// A simple RGB color class to represent colors in RGB and YUV colorspaces.
+ /// Initializes a new instance of the class.
///
- public class CameraColor
- {
- ///
- /// Initializes a new instance of the class.
- ///
- /// The red.
- /// The green.
- /// The blue.
- public CameraColor(int r, int g, int b)
- : this(r, g, b, string.Empty)
- {
- }
-
- ///
- /// Initializes a new instance of the class.
- ///
- /// The red.
- /// The green.
- /// The blue.
- /// The well-known color name.
- public CameraColor(int r, int g, int b, string name)
- {
- RGB = new[] { Convert.ToByte(r.Clamp(0, 255)), Convert.ToByte(g.Clamp(0, 255)), Convert.ToByte(b.Clamp(0, 255)) };
-
- var y = (R * .299000f) + (G * .587000f) + (B * .114000f);
- var u = (R * -.168736f) + (G * -.331264f) + (B * .500000f) + 128f;
- var v = (R * .500000f) + (G * -.418688f) + (B * -.081312f) + 128f;
-
- YUV = new byte[] { (byte)y.Clamp(0, 255), (byte)u.Clamp(0, 255), (byte)v.Clamp(0, 255) };
- Name = name;
- }
-
- #region Static Definitions
-
- ///
- /// Gets the predefined white color.
- ///
- public static CameraColor White => new CameraColor(255, 255, 255, nameof(White));
-
- ///
- /// Gets the predefined red color.
- ///
- public static CameraColor Red => new CameraColor(255, 0, 0, nameof(Red));
-
- ///
- /// Gets the predefined green color.
- ///
- public static CameraColor Green => new CameraColor(0, 255, 0, nameof(Green));
-
- ///
- /// Gets the predefined blue color.
- ///
- public static CameraColor Blue => new CameraColor(0, 0, 255, nameof(Blue));
-
- ///
- /// Gets the predefined black color.
- ///
- public static CameraColor Black => new CameraColor(0, 0, 0, nameof(Black));
-
- #endregion
-
- ///
- /// Gets the well-known color name.
- ///
- public string Name { get; }
-
- ///
- /// Gets the red byte.
- ///
- public byte R => RGB[0];
-
- ///
- /// Gets the green byte.
- ///
- public byte G => RGB[1];
-
- ///
- /// Gets the blue byte.
- ///
- public byte B => RGB[2];
-
- ///
- /// Gets the RGB byte array (3 bytes).
- ///
- public byte[] RGB { get; }
-
- ///
- /// Gets the YUV byte array (3 bytes).
- ///
- public byte[] YUV { get; }
-
- ///
- /// Returns a hexadecimal representation of the RGB byte array.
- /// Preceded by 0x and all in lowercase
- ///
- /// if set to true [reverse].
- /// A string
- public string ToRgbHex(bool reverse)
- {
- var data = RGB.ToArray();
- if (reverse) Array.Reverse(data);
- return ToHex(data);
- }
-
- ///
- /// Returns a hexadecimal representation of the YUV byte array.
- /// Preceded by 0x and all in lowercase
- ///
- /// if set to true [reverse].
- /// A string
- public string ToYuvHex(bool reverse)
- {
- var data = YUV.ToArray();
- if (reverse) Array.Reverse(data);
- return ToHex(data);
- }
-
- ///
- /// Returns a hexadecimal representation of the data byte array
- ///
- /// The data.
- /// A string
- private static string ToHex(byte[] data) => $"0x{BitConverter.ToString(data).Replace("-", string.Empty).ToLowerInvariant()}";
- }
+ /// The red.
+ /// The green.
+ /// The blue.
+ public CameraColor(Int32 r, Int32 g, Int32 b)
+ : this(r, g, b, String.Empty) {
+ }
+
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ /// The red.
+ /// The green.
+ /// The blue.
+ /// The well-known color name.
+ public CameraColor(Int32 r, Int32 g, Int32 b, String name) {
+ this.RGB = new[] { Convert.ToByte(r.Clamp(0, 255)), Convert.ToByte(g.Clamp(0, 255)), Convert.ToByte(b.Clamp(0, 255)) };
+
+ Single y = this.R * .299000f + this.G * .587000f + this.B * .114000f;
+ Single u = this.R * -.168736f + this.G * -.331264f + this.B * .500000f + 128f;
+ Single v = this.R * .500000f + this.G * -.418688f + this.B * -.081312f + 128f;
+
+ this.YUV = new Byte[] { (Byte)y.Clamp(0, 255), (Byte)u.Clamp(0, 255), (Byte)v.Clamp(0, 255) };
+ this.Name = name;
+ }
+
+ #region Static Definitions
+
+ ///
+ /// Gets the predefined white color.
+ ///
+ public static CameraColor White => new CameraColor(255, 255, 255, nameof(White));
+
+ ///
+ /// Gets the predefined red color.
+ ///
+ public static CameraColor Red => new CameraColor(255, 0, 0, nameof(Red));
+
+ ///
+ /// Gets the predefined green color.
+ ///
+ public static CameraColor Green => new CameraColor(0, 255, 0, nameof(Green));
+
+ ///
+ /// Gets the predefined blue color.
+ ///
+ public static CameraColor Blue => new CameraColor(0, 0, 255, nameof(Blue));
+
+ ///
+ /// Gets the predefined black color.
+ ///
+ public static CameraColor Black => new CameraColor(0, 0, 0, nameof(Black));
+
+ #endregion
+
+ ///
+ /// Gets the well-known color name.
+ ///
+ public String Name {
+ get;
+ }
+
+ ///
+ /// Gets the red byte.
+ ///
+ public Byte R => this.RGB[0];
+
+ ///
+ /// Gets the green byte.
+ ///
+ public Byte G => this.RGB[1];
+
+ ///
+ /// Gets the blue byte.
+ ///
+ public Byte B => this.RGB[2];
+
+ ///
+ /// Gets the RGB byte array (3 bytes).
+ ///
+ public Byte[] RGB {
+ get;
+ }
+
+ ///
+ /// Gets the YUV byte array (3 bytes).
+ ///
+ public Byte[] YUV {
+ get;
+ }
+
+ ///
+ /// Returns a hexadecimal representation of the RGB byte array.
+ /// Preceded by 0x and all in lowercase
+ ///
+ /// if set to true [reverse].
+ /// A string
+ public String ToRgbHex(Boolean reverse) {
+ Byte[] data = this.RGB.ToArray();
+ if(reverse) {
+ Array.Reverse(data);
+ }
+
+ return ToHex(data);
+ }
+
+ ///
+ /// Returns a hexadecimal representation of the YUV byte array.
+ /// Preceded by 0x and all in lowercase
+ ///
+ /// if set to true [reverse].
+ /// A string
+ public String ToYuvHex(Boolean reverse) {
+ Byte[] data = this.YUV.ToArray();
+ if(reverse) {
+ Array.Reverse(data);
+ }
+
+ return ToHex(data);
+ }
+
+ ///
+ /// Returns a hexadecimal representation of the data byte array
+ ///
+ /// The data.
+ /// A string
+ private static String ToHex(Byte[] data) => $"0x{BitConverter.ToString(data).Replace("-", String.Empty).ToLowerInvariant()}";
+ }
}
\ No newline at end of file
diff --git a/Unosquare.RaspberryIO/Camera/CameraController.cs b/Unosquare.RaspberryIO/Camera/CameraController.cs
index ce42d68..e7db20a 100644
--- a/Unosquare.RaspberryIO/Camera/CameraController.cs
+++ b/Unosquare.RaspberryIO/Camera/CameraController.cs
@@ -1,216 +1,190 @@
-namespace Unosquare.RaspberryIO.Camera
-{
- using Swan.Abstractions;
- using System;
- using Swan.Components;
- using System.IO;
- using System.Threading;
- using System.Threading.Tasks;
-
+using Unosquare.Swan.Abstractions;
+using System;
+using Unosquare.Swan.Components;
+using System.IO;
+using System.Threading;
+using System.Threading.Tasks;
+
+namespace Unosquare.RaspberryIO.Camera {
+ ///
+ /// The Raspberry Pi's camera controller wrapping raspistill and raspivid programs.
+ /// This class is a singleton
+ ///
+ public class CameraController : SingletonBase {
+ #region Private Declarations
+
+ private static readonly ManualResetEventSlim OperationDone = new ManualResetEventSlim(true);
+ private static readonly Object SyncRoot = new Object();
+ private static CancellationTokenSource _videoTokenSource = new CancellationTokenSource();
+ private static Task _videoStreamTask;
+
+ #endregion
+
+ #region Properties
+
///
- /// The Raspberry Pi's camera controller wrapping raspistill and raspivid programs.
- /// This class is a singleton
+ /// Gets a value indicating whether the camera module is busy.
///
- public class CameraController : SingletonBase
- {
- #region Private Declarations
-
- private static readonly ManualResetEventSlim OperationDone = new ManualResetEventSlim(true);
- private static readonly object SyncRoot = new object();
- private static CancellationTokenSource _videoTokenSource = new CancellationTokenSource();
- private static Task _videoStreamTask;
-
- #endregion
-
- #region Properties
-
- ///
- /// Gets a value indicating whether the camera module is busy.
- ///
- ///
- /// true if this instance is busy; otherwise, false.
- ///
- public bool IsBusy => OperationDone.IsSet == false;
-
- #endregion
-
- #region Image Capture Methods
-
- ///
- /// Captures an image asynchronously.
- ///
- /// The settings.
- /// The ct.
- /// The image bytes
- /// Cannot use camera module because it is currently busy.
- public async Task CaptureImageAsync(CameraStillSettings settings, CancellationToken ct = default)
- {
- if (Instance.IsBusy)
- throw new InvalidOperationException("Cannot use camera module because it is currently busy.");
-
- if (settings.CaptureTimeoutMilliseconds <= 0)
- throw new ArgumentException($"{nameof(settings.CaptureTimeoutMilliseconds)} needs to be greater than 0");
-
- try
- {
- OperationDone.Reset();
-
- var output = new MemoryStream();
- var exitCode = await ProcessRunner.RunProcessAsync(
- settings.CommandName,
- settings.CreateProcessArguments(),
- (data, proc) =>
- {
- output.Write(data, 0, data.Length);
- },
- null,
- true,
- ct);
-
- return exitCode != 0 ? new byte[] { } : output.ToArray();
- }
- finally
- {
- OperationDone.Set();
- }
- }
-
- ///
- /// Captures an image.
- ///
- /// The settings.
- /// The image bytes
- public byte[] CaptureImage(CameraStillSettings settings)
- {
- return CaptureImageAsync(settings).GetAwaiter().GetResult();
- }
-
- ///
- /// Captures a JPEG encoded image asynchronously at 90% quality.
- ///
- /// The width.
- /// The height.
- /// The ct.
- /// The image bytes
- public Task CaptureImageJpegAsync(int width, int height, CancellationToken ct = default)
- {
- var settings = new CameraStillSettings
- {
- CaptureWidth = width,
- CaptureHeight = height,
- CaptureJpegQuality = 90,
- CaptureTimeoutMilliseconds = 300,
- };
-
- return CaptureImageAsync(settings, ct);
- }
-
- ///
- /// Captures a JPEG encoded image at 90% quality.
- ///
- /// The width.
- /// The height.
- /// The image bytes
- public byte[] CaptureImageJpeg(int width, int height) => CaptureImageJpegAsync(width, height).GetAwaiter().GetResult();
-
- #endregion
-
- #region Video Capture Methods
-
- ///
- /// Opens the video stream with a timeout of 0 (running indefinitely) at 1080p resolution, variable bitrate and 25 FPS.
- /// No preview is shown
- ///
- /// The on data callback.
- /// The on exit callback.
- public void OpenVideoStream(Action onDataCallback, Action onExitCallback = null)
- {
- var settings = new CameraVideoSettings
- {
- CaptureTimeoutMilliseconds = 0,
- CaptureDisplayPreview = false,
- CaptureWidth = 1920,
- CaptureHeight = 1080
- };
-
- OpenVideoStream(settings, onDataCallback, onExitCallback);
- }
-
- ///
- /// Opens the video stream with the supplied settings. Capture Timeout Milliseconds has to be 0 or greater
- ///
- /// The settings.
- /// The on data callback.
- /// The on exit callback.
- /// Cannot use camera module because it is currently busy.
- /// CaptureTimeoutMilliseconds
- public void OpenVideoStream(CameraVideoSettings settings, Action onDataCallback, Action onExitCallback)
- {
- if (Instance.IsBusy)
- throw new InvalidOperationException("Cannot use camera module because it is currently busy.");
-
- if (settings.CaptureTimeoutMilliseconds < 0)
- throw new ArgumentException($"{nameof(settings.CaptureTimeoutMilliseconds)} needs to be greater than or equal to 0");
-
- try
- {
- OperationDone.Reset();
- _videoStreamTask = Task.Factory.StartNew(() => VideoWorkerDoWork(settings, onDataCallback, onExitCallback), _videoTokenSource.Token);
- }
- catch
- {
- OperationDone.Set();
- throw;
- }
- }
-
- ///
- /// Closes the video stream of a video stream is open.
- ///
- public void CloseVideoStream()
- {
- lock (SyncRoot)
- {
- if (IsBusy == false)
- return;
- }
-
- if (_videoTokenSource.IsCancellationRequested == false)
- {
- _videoTokenSource.Cancel();
- _videoStreamTask.Wait();
- }
-
- _videoTokenSource = new CancellationTokenSource();
- }
-
- private static async Task VideoWorkerDoWork(
- CameraVideoSettings settings,
- Action onDataCallback,
- Action onExitCallback)
- {
- try
- {
- await ProcessRunner.RunProcessAsync(
- settings.CommandName,
- settings.CreateProcessArguments(),
- (data, proc) => onDataCallback?.Invoke(data),
- null,
- true,
- _videoTokenSource.Token);
-
- onExitCallback?.Invoke();
- }
- catch
- {
- // swallow
- }
- finally
- {
- Instance.CloseVideoStream();
- OperationDone.Set();
- }
- }
- #endregion
- }
+ ///
+ /// true if this instance is busy; otherwise, false.
+ ///
+ public Boolean IsBusy => OperationDone.IsSet == false;
+
+ #endregion
+
+ #region Image Capture Methods
+
+ ///
+ /// Captures an image asynchronously.
+ ///
+ /// The settings.
+ /// The ct.
+ /// The image bytes
+ /// Cannot use camera module because it is currently busy.
+ [System.Diagnostics.CodeAnalysis.SuppressMessage("Codequalität", "IDE0067:Objekte verwerfen, bevor Bereich verloren geht", Justification = "")]
+ public async Task CaptureImageAsync(CameraStillSettings settings, CancellationToken ct = default) {
+ if(Instance.IsBusy) {
+ throw new InvalidOperationException("Cannot use camera module because it is currently busy.");
+ }
+
+ if(settings.CaptureTimeoutMilliseconds <= 0) {
+ throw new ArgumentException($"{nameof(settings.CaptureTimeoutMilliseconds)} needs to be greater than 0");
+ }
+
+ try {
+ OperationDone.Reset();
+
+ MemoryStream output = new MemoryStream();
+ Int32 exitCode = await ProcessRunner.RunProcessAsync(
+ settings.CommandName,
+ settings.CreateProcessArguments(),
+ (data, proc) => output.Write(data, 0, data.Length),
+ null,
+ true,
+ ct);
+
+ return exitCode != 0 ? new Byte[] { } : output.ToArray();
+ } finally {
+ OperationDone.Set();
+ }
+ }
+
+ ///
+ /// Captures an image.
+ ///
+ /// The settings.
+ /// The image bytes
+ public Byte[] CaptureImage(CameraStillSettings settings) => this.CaptureImageAsync(settings).GetAwaiter().GetResult();
+
+ ///
+ /// Captures a JPEG encoded image asynchronously at 90% quality.
+ ///
+ /// The width.
+ /// The height.
+ /// The ct.
+ /// The image bytes
+ public Task CaptureImageJpegAsync(Int32 width, Int32 height, CancellationToken ct = default) {
+ CameraStillSettings settings = new CameraStillSettings {
+ CaptureWidth = width,
+ CaptureHeight = height,
+ CaptureJpegQuality = 90,
+ CaptureTimeoutMilliseconds = 300,
+ };
+
+ return this.CaptureImageAsync(settings, ct);
+ }
+
+ ///
+ /// Captures a JPEG encoded image at 90% quality.
+ ///
+ /// The width.
+ /// The height.
+ /// The image bytes
+ public Byte[] CaptureImageJpeg(Int32 width, Int32 height) => this.CaptureImageJpegAsync(width, height).GetAwaiter().GetResult();
+
+ #endregion
+
+ #region Video Capture Methods
+
+ ///
+ /// Opens the video stream with a timeout of 0 (running indefinitely) at 1080p resolution, variable bitrate and 25 FPS.
+ /// No preview is shown
+ ///
+ /// The on data callback.
+ /// The on exit callback.
+ public void OpenVideoStream(Action onDataCallback, Action onExitCallback = null) {
+ CameraVideoSettings settings = new CameraVideoSettings {
+ CaptureTimeoutMilliseconds = 0,
+ CaptureDisplayPreview = false,
+ CaptureWidth = 1920,
+ CaptureHeight = 1080
+ };
+
+ this.OpenVideoStream(settings, onDataCallback, onExitCallback);
+ }
+
+ ///
+ /// Opens the video stream with the supplied settings. Capture Timeout Milliseconds has to be 0 or greater
+ ///
+ /// The settings.
+ /// The on data callback.
+ /// The on exit callback.
+ /// Cannot use camera module because it is currently busy.
+ /// CaptureTimeoutMilliseconds
+ public void OpenVideoStream(CameraVideoSettings settings, Action onDataCallback, Action onExitCallback) {
+ if(Instance.IsBusy) {
+ throw new InvalidOperationException("Cannot use camera module because it is currently busy.");
+ }
+
+ if(settings.CaptureTimeoutMilliseconds < 0) {
+ throw new ArgumentException($"{nameof(settings.CaptureTimeoutMilliseconds)} needs to be greater than or equal to 0");
+ }
+
+ try {
+ OperationDone.Reset();
+ _videoStreamTask = Task.Factory.StartNew(() => VideoWorkerDoWork(settings, onDataCallback, onExitCallback), _videoTokenSource.Token);
+ } catch {
+ OperationDone.Set();
+ throw;
+ }
+ }
+
+ ///
+ /// Closes the video stream of a video stream is open.
+ ///
+ public void CloseVideoStream() {
+ lock(SyncRoot) {
+ if(this.IsBusy == false) {
+ return;
+ }
+ }
+
+ if(_videoTokenSource.IsCancellationRequested == false) {
+ _videoTokenSource.Cancel();
+ _videoStreamTask.Wait();
+ }
+
+ _videoTokenSource = new CancellationTokenSource();
+ }
+
+ private static async Task VideoWorkerDoWork(CameraVideoSettings settings, Action onDataCallback, Action onExitCallback) {
+ try {
+ await ProcessRunner.RunProcessAsync(
+ settings.CommandName,
+ settings.CreateProcessArguments(),
+ (data, proc) => onDataCallback?.Invoke(data),
+ null,
+ true,
+ _videoTokenSource.Token);
+
+ onExitCallback?.Invoke();
+ } catch {
+ // swallow
+ } finally {
+ Instance.CloseVideoStream();
+ OperationDone.Set();
+ }
+ }
+ #endregion
+ }
}
\ No newline at end of file
diff --git a/Unosquare.RaspberryIO/Camera/CameraRect.cs b/Unosquare.RaspberryIO/Camera/CameraRect.cs
index b793081..bb5e5f1 100644
--- a/Unosquare.RaspberryIO/Camera/CameraRect.cs
+++ b/Unosquare.RaspberryIO/Camera/CameraRect.cs
@@ -1,82 +1,86 @@
-namespace Unosquare.RaspberryIO.Camera
-{
- using Swan;
- using System.Globalization;
-
+using Unosquare.Swan;
+using System;
+using System.Globalization;
+
+namespace Unosquare.RaspberryIO.Camera {
+ ///
+ /// Defines the Raspberry Pi camera's sensor ROI (Region of Interest)
+ ///
+ public struct CameraRect {
///
- /// Defines the Raspberry Pi camera's sensor ROI (Region of Interest)
+ /// The default ROI which is the entire area.
///
- public struct CameraRect
- {
- ///
- /// The default ROI which is the entire area.
- ///
- public static readonly CameraRect Default = new CameraRect { X = 0M, Y = 0M, W = 1.0M, H = 1.0M };
-
- ///
- /// Gets or sets the x in relative coordinates. (0.0 to 1.0)
- ///
- ///
- /// The x.
- ///
- public decimal X { get; set; }
-
- ///
- /// Gets or sets the y location in relative coordinates. (0.0 to 1.0)
- ///
- ///
- /// The y.
- ///
- public decimal Y { get; set; }
-
- ///
- /// Gets or sets the width in relative coordinates. (0.0 to 1.0)
- ///
- ///
- /// The w.
- ///
- public decimal W { get; set; }
-
- ///
- /// Gets or sets the height in relative coordinates. (0.0 to 1.0)
- ///
- ///
- /// The h.
- ///
- public decimal H { get; set; }
-
- ///
- /// Gets a value indicating whether this instance is equal to the default (The entire area).
- ///
- ///
- /// true if this instance is default; otherwise, false.
- ///
- public bool IsDefault
- {
- get
- {
- Clamp();
- return X == Default.X && Y == Default.Y && W == Default.W && H == Default.H;
- }
- }
-
- ///
- /// Clamps the members of this ROI to their minimum and maximum values
- ///
- public void Clamp()
- {
- X = X.Clamp(0M, 1M);
- Y = Y.Clamp(0M, 1M);
- W = W.Clamp(0M, 1M - X);
- H = H.Clamp(0M, 1M - Y);
- }
-
- ///
- /// Returns a that represents this instance.
- ///
- ///
- /// A that represents this instance.
- ///
- public override string ToString() => $"{X.ToString(CultureInfo.InvariantCulture)},{Y.ToString(CultureInfo.InvariantCulture)},{W.ToString(CultureInfo.InvariantCulture)},{H.ToString(CultureInfo.InvariantCulture)}";
- }
+ public static readonly CameraRect Default = new CameraRect { X = 0M, Y = 0M, W = 1.0M, H = 1.0M };
+
+ ///
+ /// Gets or sets the x in relative coordinates. (0.0 to 1.0)
+ ///
+ ///
+ /// The x.
+ ///
+ public Decimal X {
+ get; set;
+ }
+
+ ///
+ /// Gets or sets the y location in relative coordinates. (0.0 to 1.0)
+ ///
+ ///
+ /// The y.
+ ///
+ public Decimal Y {
+ get; set;
+ }
+
+ ///
+ /// Gets or sets the width in relative coordinates. (0.0 to 1.0)
+ ///
+ ///
+ /// The w.
+ ///
+ public Decimal W {
+ get; set;
+ }
+
+ ///
+ /// Gets or sets the height in relative coordinates. (0.0 to 1.0)
+ ///
+ ///
+ /// The h.
+ ///
+ public Decimal H {
+ get; set;
+ }
+
+ ///
+ /// Gets a value indicating whether this instance is equal to the default (The entire area).
+ ///
+ ///
+ /// true if this instance is default; otherwise, false.
+ ///
+ public Boolean IsDefault {
+ get {
+ this.Clamp();
+ return this.X == Default.X && this.Y == Default.Y && this.W == Default.W && this.H == Default.H;
+ }
+ }
+
+ ///
+ /// Clamps the members of this ROI to their minimum and maximum values
+ ///
+ public void Clamp() {
+ this.X = this.X.Clamp(0M, 1M);
+ this.Y = this.Y.Clamp(0M, 1M);
+ this.W = this.W.Clamp(0M, 1M - this.X);
+ this.H = this.H.Clamp(0M, 1M - this.Y);
+ }
+
+ ///
+ /// Returns a that represents this instance.
+ ///
+ ///
+ /// A that represents this instance.
+ ///
+ public override String ToString() => $"{this.X.ToString(CultureInfo.InvariantCulture)},{this.Y.ToString(CultureInfo.InvariantCulture)},{this.W.ToString(CultureInfo.InvariantCulture)},{this.H.ToString(CultureInfo.InvariantCulture)}";
+ }
}
diff --git a/Unosquare.RaspberryIO/Camera/CameraSettingsBase.cs b/Unosquare.RaspberryIO/Camera/CameraSettingsBase.cs
index fcc27b2..605b989 100644
--- a/Unosquare.RaspberryIO/Camera/CameraSettingsBase.cs
+++ b/Unosquare.RaspberryIO/Camera/CameraSettingsBase.cs
@@ -1,340 +1,361 @@
-namespace Unosquare.RaspberryIO.Camera
-{
- using Swan;
- using System.Globalization;
- using System.Text;
-
+using Unosquare.Swan;
+using System.Globalization;
+using System.Text;
+using System;
+
+namespace Unosquare.RaspberryIO.Camera {
+ ///
+ /// A base class to implement raspistill and raspivid wrappers
+ /// Full documentation available at
+ /// https://www.raspberrypi.org/documentation/raspbian/applications/camera.md
+ ///
+ public abstract class CameraSettingsBase {
///
- /// A base class to implement raspistill and raspivid wrappers
- /// Full documentation available at
- /// https://www.raspberrypi.org/documentation/raspbian/applications/camera.md
+ /// The Invariant Culture shorthand
///
- public abstract class CameraSettingsBase
- {
- ///
- /// The Invariant Culture shorthand
- ///
- protected static readonly CultureInfo Ci = CultureInfo.InvariantCulture;
-
- #region Capture Settings
-
- ///
- /// Gets or sets the timeout milliseconds.
- /// Default value is 5000
- /// Recommended value is at least 300 in order to let the light collectors open
- ///
- public int CaptureTimeoutMilliseconds { get; set; } = 5000;
-
- ///
- /// Gets or sets a value indicating whether or not to show a preview window on the screen
- ///
- public bool CaptureDisplayPreview { get; set; } = false;
-
- ///
- /// Gets or sets a value indicating whether a preview window is shown in full screen mode if enabled
- ///
- public bool CaptureDisplayPreviewInFullScreen { get; set; } = true;
-
- ///
- /// Gets or sets a value indicating whether video stabilization should be enabled.
- ///
- public bool CaptureVideoStabilizationEnabled { get; set; } = false;
-
- ///
- /// Gets or sets the display preview opacity only if the display preview property is enabled.
- ///
- public byte CaptureDisplayPreviewOpacity { get; set; } = 255;
-
- ///
- /// Gets or sets the capture sensor region of interest in relative coordinates.
- ///
- public CameraRect CaptureSensorRoi { get; set; } = CameraRect.Default;
-
- ///
- /// Gets or sets the capture shutter speed in microseconds.
- /// Default -1, Range 0 to 6000000 (equivalent to 6 seconds)
- ///
- public int CaptureShutterSpeedMicroseconds { get; set; } = -1;
-
- ///
- /// Gets or sets the exposure mode.
- ///
- public CameraExposureMode CaptureExposure { get; set; } = CameraExposureMode.Auto;
-
- ///
- /// Gets or sets the picture EV compensation. Default is 0, Range is -10 to 10
- /// Camera exposure compensation is commonly stated in terms of EV units;
- /// 1 EV is equal to one exposure step (or stop), corresponding to a doubling of exposure.
- /// Exposure can be adjusted by changing either the lens f-number or the exposure time;
- /// which one is changed usually depends on the camera's exposure mode.
- ///
- public int CaptureExposureCompensation { get; set; } = 0;
-
- ///
- /// Gets or sets the capture metering mode.
- ///
- public CameraMeteringMode CaptureMeteringMode { get; set; } = CameraMeteringMode.Average;
-
- ///
- /// Gets or sets the automatic white balance mode. By default it is set to Auto
- ///
- public CameraWhiteBalanceMode CaptureWhiteBalanceControl { get; set; } = CameraWhiteBalanceMode.Auto;
-
- ///
- /// Gets or sets the capture white balance gain on the blue channel. Example: 1.25
- /// Only takes effect if White balance control is set to off.
- /// Default is 0
- ///
- public decimal CaptureWhiteBalanceGainBlue { get; set; } = 0M;
-
- ///
- /// Gets or sets the capture white balance gain on the red channel. Example: 1.75
- /// Only takes effect if White balance control is set to off.
- /// Default is 0
- ///
- public decimal CaptureWhiteBalanceGainRed { get; set; } = 0M;
-
- ///
- /// Gets or sets the dynamic range compensation.
- /// DRC changes the images by increasing the range of dark areas, and decreasing the brighter areas. This can improve the image in low light areas.
- ///
- public CameraDynamicRangeCompensation CaptureDynamicRangeCompensation { get; set; } =
- CameraDynamicRangeCompensation.Off;
-
- #endregion
-
- #region Image Properties
-
- ///
- /// Gets or sets the width of the picture to take.
- /// Less than or equal to 0 in either width or height means maximum resolution available.
- ///
- public int CaptureWidth { get; set; } = 640;
-
- ///
- /// Gets or sets the height of the picture to take.
- /// Less than or equal to 0 in either width or height means maximum resolution available.
- ///
- public int CaptureHeight { get; set; } = 480;
-
- ///
- /// Gets or sets the picture sharpness. Default is 0, Range form -100 to 100
- ///
- public int ImageSharpness { get; set; } = 0;
-
- ///
- /// Gets or sets the picture contrast. Default is 0, Range form -100 to 100
- ///
- public int ImageContrast { get; set; } = 0;
-
- ///
- /// Gets or sets the picture brightness. Default is 50, Range form 0 to 100
- ///
- public int ImageBrightness { get; set; } = 50; // from 0 to 100
-
- ///
- /// Gets or sets the picture saturation. Default is 0, Range form -100 to 100
- ///
- public int ImageSaturation { get; set; } = 0;
-
- ///
- /// Gets or sets the picture ISO. Default is -1 Range is 100 to 800
- /// The higher the value, the more light the sensor absorbs
- ///
- public int ImageIso { get; set; } = -1;
-
- ///
- /// Gets or sets the image capture effect to be applied.
- ///
- public CameraImageEffect ImageEffect { get; set; } = CameraImageEffect.None;
-
- ///
- /// Gets or sets the color effect U coordinates.
- /// Default is -1, Range is 0 to 255
- /// 128:128 should be effectively a monochrome image.
- ///
- public int ImageColorEffectU { get; set; } = -1; // 0 to 255
-
- ///
- /// Gets or sets the color effect V coordinates.
- /// Default is -1, Range is 0 to 255
- /// 128:128 should be effectively a monochrome image.
- ///
- public int ImageColorEffectV { get; set; } = -1; // 0 to 255
-
- ///
- /// Gets or sets the image rotation. Default is no rotation
- ///
- public CameraImageRotation ImageRotation { get; set; } = CameraImageRotation.None;
-
- ///
- /// Gets or sets a value indicating whether the image should be flipped horizontally.
- ///
- public bool ImageFlipHorizontally { get; set; }
-
- ///
- /// Gets or sets a value indicating whether the image should be flipped vertically.
- ///
- public bool ImageFlipVertically { get; set; }
-
- ///
- /// Gets or sets the image annotations using a bitmask (or flags) notation.
- /// Apply a bitwise OR to the enumeration to include multiple annotations
- ///
- public CameraAnnotation ImageAnnotations { get; set; } = CameraAnnotation.None;
-
- ///
- /// Gets or sets the image annotations text.
- /// Text may include date/time placeholders by using the '%' character, as used by strftime.
- /// Example: ABC %Y-%m-%d %X will output ABC 2015-10-28 20:09:33
- ///
- public string ImageAnnotationsText { get; set; } = string.Empty;
-
- ///
- /// Gets or sets the font size of the text annotations
- /// Default is -1, range is 6 to 160
- ///
- public int ImageAnnotationFontSize { get; set; } = -1;
-
- ///
- /// Gets or sets the color of the text annotations.
- ///
- ///
- /// The color of the image annotation font.
- ///
- public CameraColor ImageAnnotationFontColor { get; set; } = null;
-
- ///
- /// Gets or sets the background color for text annotations.
- ///
- ///
- /// The image annotation background.
- ///
- public CameraColor ImageAnnotationBackground { get; set; } = null;
-
- #endregion
-
- #region Interface
-
- ///
- /// Gets the command file executable.
- ///
- public abstract string CommandName { get; }
-
- ///
- /// Creates the process arguments.
- ///
- /// The string that represents the process arguments
- public virtual string CreateProcessArguments()
- {
- var sb = new StringBuilder();
- sb.Append("-o -"); // output to standard output as opposed to a file.
- sb.Append($" -t {(CaptureTimeoutMilliseconds < 0 ? "0" : CaptureTimeoutMilliseconds.ToString(Ci))}");
-
- // Basic Width and height
- if (CaptureWidth > 0 && CaptureHeight > 0)
- {
- sb.Append($" -w {CaptureWidth.ToString(Ci)}");
- sb.Append($" -h {CaptureHeight.ToString(Ci)}");
- }
-
- // Display Preview
- if (CaptureDisplayPreview)
- {
- if (CaptureDisplayPreviewInFullScreen)
- sb.Append(" -f");
-
- if (CaptureDisplayPreviewOpacity != byte.MaxValue)
- sb.Append($" -op {CaptureDisplayPreviewOpacity.ToString(Ci)}");
- }
- else
- {
- sb.Append(" -n"); // no preview
- }
-
- // Picture Settings
- if (ImageSharpness != 0)
- sb.Append($" -sh {ImageSharpness.Clamp(-100, 100).ToString(Ci)}");
-
- if (ImageContrast != 0)
- sb.Append($" -co {ImageContrast.Clamp(-100, 100).ToString(Ci)}");
-
- if (ImageBrightness != 50)
- sb.Append($" -br {ImageBrightness.Clamp(0, 100).ToString(Ci)}");
-
- if (ImageSaturation != 0)
- sb.Append($" -sa {ImageSaturation.Clamp(-100, 100).ToString(Ci)}");
-
- if (ImageIso >= 100)
- sb.Append($" -ISO {ImageIso.Clamp(100, 800).ToString(Ci)}");
-
- if (CaptureVideoStabilizationEnabled)
- sb.Append(" -vs");
-
- if (CaptureExposureCompensation != 0)
- sb.Append($" -ev {CaptureExposureCompensation.Clamp(-10, 10).ToString(Ci)}");
-
- if (CaptureExposure != CameraExposureMode.Auto)
- sb.Append($" -ex {CaptureExposure.ToString().ToLowerInvariant()}");
-
- if (CaptureWhiteBalanceControl != CameraWhiteBalanceMode.Auto)
- sb.Append($" -awb {CaptureWhiteBalanceControl.ToString().ToLowerInvariant()}");
-
- if (ImageEffect != CameraImageEffect.None)
- sb.Append($" -ifx {ImageEffect.ToString().ToLowerInvariant()}");
-
- if (ImageColorEffectU >= 0 && ImageColorEffectV >= 0)
- {
- sb.Append(
- $" -cfx {ImageColorEffectU.Clamp(0, 255).ToString(Ci)}:{ImageColorEffectV.Clamp(0, 255).ToString(Ci)}");
- }
-
- if (CaptureMeteringMode != CameraMeteringMode.Average)
- sb.Append($" -mm {CaptureMeteringMode.ToString().ToLowerInvariant()}");
-
- if (ImageRotation != CameraImageRotation.None)
- sb.Append($" -rot {((int)ImageRotation).ToString(Ci)}");
-
- if (ImageFlipHorizontally)
- sb.Append(" -hf");
-
- if (ImageFlipVertically)
- sb.Append(" -vf");
-
- if (CaptureSensorRoi.IsDefault == false)
- sb.Append($" -roi {CaptureSensorRoi}");
-
- if (CaptureShutterSpeedMicroseconds > 0)
- sb.Append($" -ss {CaptureShutterSpeedMicroseconds.Clamp(0, 6000000).ToString(Ci)}");
-
- if (CaptureDynamicRangeCompensation != CameraDynamicRangeCompensation.Off)
- sb.Append($" -drc {CaptureDynamicRangeCompensation.ToString().ToLowerInvariant()}");
-
- if (CaptureWhiteBalanceControl == CameraWhiteBalanceMode.Off &&
- (CaptureWhiteBalanceGainBlue != 0M || CaptureWhiteBalanceGainRed != 0M))
- sb.Append($" -awbg {CaptureWhiteBalanceGainBlue.ToString(Ci)},{CaptureWhiteBalanceGainRed.ToString(Ci)}");
-
- if (ImageAnnotationFontSize > 0)
- {
- sb.Append($" -ae {ImageAnnotationFontSize.Clamp(6, 160).ToString(Ci)}");
- sb.Append($",{(ImageAnnotationFontColor == null ? "0xff" : ImageAnnotationFontColor.ToYuvHex(true))}");
-
- if (ImageAnnotationBackground != null)
- {
- ImageAnnotations |= CameraAnnotation.SolidBackground;
- sb.Append($",{ImageAnnotationBackground.ToYuvHex(true)}");
- }
- }
-
- if (ImageAnnotations != CameraAnnotation.None)
- sb.Append($" -a {((int)ImageAnnotations).ToString(Ci)}");
-
- if (string.IsNullOrWhiteSpace(ImageAnnotationsText) == false)
- sb.Append($" -a \"{ImageAnnotationsText.Replace("\"", "'")}\"");
-
- return sb.ToString();
- }
-
- #endregion
- }
+ protected static readonly CultureInfo Ci = CultureInfo.InvariantCulture;
+
+ #region Capture Settings
+
+ ///
+ /// Gets or sets the timeout milliseconds.
+ /// Default value is 5000
+ /// Recommended value is at least 300 in order to let the light collectors open
+ ///
+ public Int32 CaptureTimeoutMilliseconds { get; set; } = 5000;
+
+ ///
+ /// Gets or sets a value indicating whether or not to show a preview window on the screen
+ ///
+ public Boolean CaptureDisplayPreview { get; set; } = false;
+
+ ///
+ /// Gets or sets a value indicating whether a preview window is shown in full screen mode if enabled
+ ///
+ public Boolean CaptureDisplayPreviewInFullScreen { get; set; } = true;
+
+ ///
+ /// Gets or sets a value indicating whether video stabilization should be enabled.
+ ///
+ public Boolean CaptureVideoStabilizationEnabled { get; set; } = false;
+
+ ///
+ /// Gets or sets the display preview opacity only if the display preview property is enabled.
+ ///
+ public Byte CaptureDisplayPreviewOpacity { get; set; } = 255;
+
+ ///
+ /// Gets or sets the capture sensor region of interest in relative coordinates.
+ ///
+ public CameraRect CaptureSensorRoi { get; set; } = CameraRect.Default;
+
+ ///
+ /// Gets or sets the capture shutter speed in microseconds.
+ /// Default -1, Range 0 to 6000000 (equivalent to 6 seconds)
+ ///
+ public Int32 CaptureShutterSpeedMicroseconds { get; set; } = -1;
+
+ ///
+ /// Gets or sets the exposure mode.
+ ///
+ public CameraExposureMode CaptureExposure { get; set; } = CameraExposureMode.Auto;
+
+ ///
+ /// Gets or sets the picture EV compensation. Default is 0, Range is -10 to 10
+ /// Camera exposure compensation is commonly stated in terms of EV units;
+ /// 1 EV is equal to one exposure step (or stop), corresponding to a doubling of exposure.
+ /// Exposure can be adjusted by changing either the lens f-number or the exposure time;
+ /// which one is changed usually depends on the camera's exposure mode.
+ ///
+ public Int32 CaptureExposureCompensation { get; set; } = 0;
+
+ ///
+ /// Gets or sets the capture metering mode.
+ ///
+ public CameraMeteringMode CaptureMeteringMode { get; set; } = CameraMeteringMode.Average;
+
+ ///
+ /// Gets or sets the automatic white balance mode. By default it is set to Auto
+ ///
+ public CameraWhiteBalanceMode CaptureWhiteBalanceControl { get; set; } = CameraWhiteBalanceMode.Auto;
+
+ ///
+ /// Gets or sets the capture white balance gain on the blue channel. Example: 1.25
+ /// Only takes effect if White balance control is set to off.
+ /// Default is 0
+ ///
+ public Decimal CaptureWhiteBalanceGainBlue { get; set; } = 0M;
+
+ ///
+ /// Gets or sets the capture white balance gain on the red channel. Example: 1.75
+ /// Only takes effect if White balance control is set to off.
+ /// Default is 0
+ ///
+ public Decimal CaptureWhiteBalanceGainRed { get; set; } = 0M;
+
+ ///
+ /// Gets or sets the dynamic range compensation.
+ /// DRC changes the images by increasing the range of dark areas, and decreasing the brighter areas. This can improve the image in low light areas.
+ ///
+ public CameraDynamicRangeCompensation CaptureDynamicRangeCompensation {
+ get; set;
+ } =
+ CameraDynamicRangeCompensation.Off;
+
+ #endregion
+
+ #region Image Properties
+
+ ///
+ /// Gets or sets the width of the picture to take.
+ /// Less than or equal to 0 in either width or height means maximum resolution available.
+ ///
+ public Int32 CaptureWidth { get; set; } = 640;
+
+ ///
+ /// Gets or sets the height of the picture to take.
+ /// Less than or equal to 0 in either width or height means maximum resolution available.
+ ///
+ public Int32 CaptureHeight { get; set; } = 480;
+
+ ///
+ /// Gets or sets the picture sharpness. Default is 0, Range form -100 to 100
+ ///
+ public Int32 ImageSharpness { get; set; } = 0;
+
+ ///
+ /// Gets or sets the picture contrast. Default is 0, Range form -100 to 100
+ ///
+ public Int32 ImageContrast { get; set; } = 0;
+
+ ///
+ /// Gets or sets the picture brightness. Default is 50, Range form 0 to 100
+ ///
+ public Int32 ImageBrightness { get; set; } = 50; // from 0 to 100
+
+ ///
+ /// Gets or sets the picture saturation. Default is 0, Range form -100 to 100
+ ///
+ public Int32 ImageSaturation { get; set; } = 0;
+
+ ///
+ /// Gets or sets the picture ISO. Default is -1 Range is 100 to 800
+ /// The higher the value, the more light the sensor absorbs
+ ///
+ public Int32 ImageIso { get; set; } = -1;
+
+ ///
+ /// Gets or sets the image capture effect to be applied.
+ ///
+ public CameraImageEffect ImageEffect { get; set; } = CameraImageEffect.None;
+
+ ///
+ /// Gets or sets the color effect U coordinates.
+ /// Default is -1, Range is 0 to 255
+ /// 128:128 should be effectively a monochrome image.
+ ///
+ public Int32 ImageColorEffectU { get; set; } = -1; // 0 to 255
+
+ ///
+ /// Gets or sets the color effect V coordinates.
+ /// Default is -1, Range is 0 to 255
+ /// 128:128 should be effectively a monochrome image.
+ ///
+ public Int32 ImageColorEffectV { get; set; } = -1; // 0 to 255
+
+ ///
+ /// Gets or sets the image rotation. Default is no rotation
+ ///
+ public CameraImageRotation ImageRotation { get; set; } = CameraImageRotation.None;
+
+ ///
+ /// Gets or sets a value indicating whether the image should be flipped horizontally.
+ ///
+ public Boolean ImageFlipHorizontally {
+ get; set;
+ }
+
+ ///
+ /// Gets or sets a value indicating whether the image should be flipped vertically.
+ ///
+ public Boolean ImageFlipVertically {
+ get; set;
+ }
+
+ ///
+ /// Gets or sets the image annotations using a bitmask (or flags) notation.
+ /// Apply a bitwise OR to the enumeration to include multiple annotations
+ ///
+ public CameraAnnotation ImageAnnotations { get; set; } = CameraAnnotation.None;
+
+ ///
+ /// Gets or sets the image annotations text.
+ /// Text may include date/time placeholders by using the '%' character, as used by strftime.
+ /// Example: ABC %Y-%m-%d %X will output ABC 2015-10-28 20:09:33
+ ///
+ public String ImageAnnotationsText { get; set; } = String.Empty;
+
+ ///
+ /// Gets or sets the font size of the text annotations
+ /// Default is -1, range is 6 to 160
+ ///
+ public Int32 ImageAnnotationFontSize { get; set; } = -1;
+
+ ///
+ /// Gets or sets the color of the text annotations.
+ ///
+ ///
+ /// The color of the image annotation font.
+ ///
+ public CameraColor ImageAnnotationFontColor { get; set; } = null;
+
+ ///
+ /// Gets or sets the background color for text annotations.
+ ///
+ ///
+ /// The image annotation background.
+ ///
+ public CameraColor ImageAnnotationBackground { get; set; } = null;
+
+ #endregion
+
+ #region Interface
+
+ ///
+ /// Gets the command file executable.
+ ///
+ public abstract String CommandName {
+ get;
+ }
+
+ ///
+ /// Creates the process arguments.
+ ///
+ /// The string that represents the process arguments
+ public virtual String CreateProcessArguments() {
+ StringBuilder sb = new StringBuilder();
+ _ = sb.Append("-o -"); // output to standard output as opposed to a file.
+ _ = sb.Append($" -t {(this.CaptureTimeoutMilliseconds < 0 ? "0" : this.CaptureTimeoutMilliseconds.ToString(Ci))}");
+
+ // Basic Width and height
+ if(this.CaptureWidth > 0 && this.CaptureHeight > 0) {
+ _ = sb.Append($" -w {this.CaptureWidth.ToString(Ci)}");
+ _ = sb.Append($" -h {this.CaptureHeight.ToString(Ci)}");
+ }
+
+ // Display Preview
+ if(this.CaptureDisplayPreview) {
+ if(this.CaptureDisplayPreviewInFullScreen) {
+ _ = sb.Append(" -f");
+ }
+
+ if(this.CaptureDisplayPreviewOpacity != Byte.MaxValue) {
+ _ = sb.Append($" -op {this.CaptureDisplayPreviewOpacity.ToString(Ci)}");
+ }
+ } else {
+ _ = sb.Append(" -n"); // no preview
+ }
+
+ // Picture Settings
+ if(this.ImageSharpness != 0) {
+ _ = sb.Append($" -sh {this.ImageSharpness.Clamp(-100, 100).ToString(Ci)}");
+ }
+
+ if(this.ImageContrast != 0) {
+ _ = sb.Append($" -co {this.ImageContrast.Clamp(-100, 100).ToString(Ci)}");
+ }
+
+ if(this.ImageBrightness != 50) {
+ _ = sb.Append($" -br {this.ImageBrightness.Clamp(0, 100).ToString(Ci)}");
+ }
+
+ if(this.ImageSaturation != 0) {
+ _ = sb.Append($" -sa {this.ImageSaturation.Clamp(-100, 100).ToString(Ci)}");
+ }
+
+ if(this.ImageIso >= 100) {
+ _ = sb.Append($" -ISO {this.ImageIso.Clamp(100, 800).ToString(Ci)}");
+ }
+
+ if(this.CaptureVideoStabilizationEnabled) {
+ _ = sb.Append(" -vs");
+ }
+
+ if(this.CaptureExposureCompensation != 0) {
+ _ = sb.Append($" -ev {this.CaptureExposureCompensation.Clamp(-10, 10).ToString(Ci)}");
+ }
+
+ if(this.CaptureExposure != CameraExposureMode.Auto) {
+ _ = sb.Append($" -ex {this.CaptureExposure.ToString().ToLowerInvariant()}");
+ }
+
+ if(this.CaptureWhiteBalanceControl != CameraWhiteBalanceMode.Auto) {
+ _ = sb.Append($" -awb {this.CaptureWhiteBalanceControl.ToString().ToLowerInvariant()}");
+ }
+
+ if(this.ImageEffect != CameraImageEffect.None) {
+ _ = sb.Append($" -ifx {this.ImageEffect.ToString().ToLowerInvariant()}");
+ }
+
+ if(this.ImageColorEffectU >= 0 && this.ImageColorEffectV >= 0) {
+ _ = sb.Append(
+ $" -cfx {this.ImageColorEffectU.Clamp(0, 255).ToString(Ci)}:{this.ImageColorEffectV.Clamp(0, 255).ToString(Ci)}");
+ }
+
+ if(this.CaptureMeteringMode != CameraMeteringMode.Average) {
+ _ = sb.Append($" -mm {this.CaptureMeteringMode.ToString().ToLowerInvariant()}");
+ }
+
+ if(this.ImageRotation != CameraImageRotation.None) {
+ _ = sb.Append($" -rot {((Int32)this.ImageRotation).ToString(Ci)}");
+ }
+
+ if(this.ImageFlipHorizontally) {
+ _ = sb.Append(" -hf");
+ }
+
+ if(this.ImageFlipVertically) {
+ _ = sb.Append(" -vf");
+ }
+
+ if(this.CaptureSensorRoi.IsDefault == false) {
+ _ = sb.Append($" -roi {this.CaptureSensorRoi}");
+ }
+
+ if(this.CaptureShutterSpeedMicroseconds > 0) {
+ _ = sb.Append($" -ss {this.CaptureShutterSpeedMicroseconds.Clamp(0, 6000000).ToString(Ci)}");
+ }
+
+ if(this.CaptureDynamicRangeCompensation != CameraDynamicRangeCompensation.Off) {
+ _ = sb.Append($" -drc {this.CaptureDynamicRangeCompensation.ToString().ToLowerInvariant()}");
+ }
+
+ if(this.CaptureWhiteBalanceControl == CameraWhiteBalanceMode.Off &&
+ (this.CaptureWhiteBalanceGainBlue != 0M || this.CaptureWhiteBalanceGainRed != 0M)) {
+ _ = sb.Append($" -awbg {this.CaptureWhiteBalanceGainBlue.ToString(Ci)},{this.CaptureWhiteBalanceGainRed.ToString(Ci)}");
+ }
+
+ if(this.ImageAnnotationFontSize > 0) {
+ _ = sb.Append($" -ae {this.ImageAnnotationFontSize.Clamp(6, 160).ToString(Ci)}");
+ _ = sb.Append($",{(this.ImageAnnotationFontColor == null ? "0xff" : this.ImageAnnotationFontColor.ToYuvHex(true))}");
+
+ if(this.ImageAnnotationBackground != null) {
+ this.ImageAnnotations |= CameraAnnotation.SolidBackground;
+ _ = sb.Append($",{this.ImageAnnotationBackground.ToYuvHex(true)}");
+ }
+ }
+
+ if(this.ImageAnnotations != CameraAnnotation.None) {
+ _ = sb.Append($" -a {((Int32)this.ImageAnnotations).ToString(Ci)}");
+ }
+
+ if(String.IsNullOrWhiteSpace(this.ImageAnnotationsText) == false) {
+ _ = sb.Append($" -a \"{this.ImageAnnotationsText.Replace("\"", "'")}\"");
+ }
+
+ return sb.ToString();
+ }
+
+ #endregion
+ }
}
\ No newline at end of file
diff --git a/Unosquare.RaspberryIO/Camera/CameraStillSettings.cs b/Unosquare.RaspberryIO/Camera/CameraStillSettings.cs
index 3deac71..c1e2edf 100644
--- a/Unosquare.RaspberryIO/Camera/CameraStillSettings.cs
+++ b/Unosquare.RaspberryIO/Camera/CameraStillSettings.cs
@@ -1,120 +1,121 @@
-namespace Unosquare.RaspberryIO.Camera
-{
- using Swan;
- using System;
- using System.Collections.Generic;
- using System.Text;
-
+using Unosquare.Swan;
+using System;
+using System.Collections.Generic;
+using System.Text;
+
+namespace Unosquare.RaspberryIO.Camera {
+ ///
+ /// Defines a wrapper for the raspistill program and its settings (command-line arguments)
+ ///
+ ///
+ public class CameraStillSettings : CameraSettingsBase {
+ private Int32 _rotate;
+
+ ///
+ public override String CommandName => "raspistill";
+
///
- /// Defines a wrapper for the raspistill program and its settings (command-line arguments)
+ /// Gets or sets a value indicating whether the preview window (if enabled) uses native capture resolution
+ /// This may slow down preview FPS
///
- ///
- public class CameraStillSettings : CameraSettingsBase
- {
- private int _rotate;
-
- ///
- public override string CommandName => "raspistill";
-
- ///
- /// Gets or sets a value indicating whether the preview window (if enabled) uses native capture resolution
- /// This may slow down preview FPS
- ///
- public bool CaptureDisplayPreviewAtResolution { get; set; } = false;
-
- ///
- /// Gets or sets the encoding format the hardware will use for the output.
- ///
- public CameraImageEncodingFormat CaptureEncoding { get; set; } = CameraImageEncodingFormat.Jpg;
-
- ///
- /// Gets or sets the quality for JPEG only encoding mode.
- /// Value ranges from 0 to 100
- ///
- public int CaptureJpegQuality { get; set; } = 90;
-
- ///
- /// Gets or sets a value indicating whether the JPEG encoder should add raw bayer metadata.
- ///
- public bool CaptureJpegIncludeRawBayerMetadata { get; set; } = false;
-
- ///
- /// JPEG EXIF data
- /// Keys and values must be already properly escaped. Otherwise the command will fail.
- ///
- public Dictionary CaptureJpegExtendedInfo { get; } = new Dictionary();
-
- ///
- /// Gets or sets a value indicating whether [horizontal flip].
- ///
- ///
- /// true if [horizontal flip]; otherwise, false.
- ///
- public bool HorizontalFlip { get; set; } = false;
-
- ///
- /// Gets or sets a value indicating whether [vertical flip].
- ///
- ///
- /// true if [vertical flip]; otherwise, false.
- ///
- public bool VerticalFlip { get; set; } = false;
-
- ///
- /// Gets or sets the rotation.
- ///
- /// Valid range 0-359
- public int Rotation
- {
- get => _rotate;
- set
- {
- if (value < 0 || value > 359)
- {
- throw new ArgumentOutOfRangeException(nameof(value), "Valid range 0-359");
- }
-
- _rotate = value;
- }
- }
-
- ///
- public override string CreateProcessArguments()
- {
- var sb = new StringBuilder(base.CreateProcessArguments());
- sb.Append($" -e {CaptureEncoding.ToString().ToLowerInvariant()}");
-
- // JPEG Encoder specific arguments
- if (CaptureEncoding == CameraImageEncodingFormat.Jpg)
- {
- sb.Append($" -q {CaptureJpegQuality.Clamp(0, 100).ToString(Ci)}");
-
- if (CaptureJpegIncludeRawBayerMetadata)
- sb.Append(" -r");
-
- // JPEG EXIF data
- if (CaptureJpegExtendedInfo.Count > 0)
- {
- foreach (var kvp in CaptureJpegExtendedInfo)
- {
- if (string.IsNullOrWhiteSpace(kvp.Key) || string.IsNullOrWhiteSpace(kvp.Value))
- continue;
-
- sb.Append($" -x \"{kvp.Key.Replace("\"", "'")}={kvp.Value.Replace("\"", "'")}\"");
- }
- }
- }
-
- // Display preview settings
- if (CaptureDisplayPreview && CaptureDisplayPreviewAtResolution) sb.Append(" -fp");
-
- if (Rotation != 0) sb.Append($" -rot {Rotation}");
-
- if (HorizontalFlip) sb.Append(" -hf");
-
- if (VerticalFlip) sb.Append(" -vf");
-
- return sb.ToString();
- }
- }
+ public Boolean CaptureDisplayPreviewAtResolution { get; set; } = false;
+
+ ///
+ /// Gets or sets the encoding format the hardware will use for the output.
+ ///
+ public CameraImageEncodingFormat CaptureEncoding { get; set; } = CameraImageEncodingFormat.Jpg;
+
+ ///
+ /// Gets or sets the quality for JPEG only encoding mode.
+ /// Value ranges from 0 to 100
+ ///
+ public Int32 CaptureJpegQuality { get; set; } = 90;
+
+ ///
+ /// Gets or sets a value indicating whether the JPEG encoder should add raw bayer metadata.
+ ///
+ public Boolean CaptureJpegIncludeRawBayerMetadata { get; set; } = false;
+
+ ///
+ /// JPEG EXIF data
+ /// Keys and values must be already properly escaped. Otherwise the command will fail.
+ ///
+ public Dictionary CaptureJpegExtendedInfo { get; } = new Dictionary();
+
+ ///
+ /// Gets or sets a value indicating whether [horizontal flip].
+ ///
+ ///
+ /// true if [horizontal flip]; otherwise, false.
+ ///
+ public Boolean HorizontalFlip { get; set; } = false;
+
+ ///
+ /// Gets or sets a value indicating whether [vertical flip].
+ ///
+ ///
+ /// true if [vertical flip]; otherwise, false.
+ ///
+ public Boolean VerticalFlip { get; set; } = false;
+
+ ///
+ /// Gets or sets the rotation.
+ ///
+ /// Valid range 0-359
+ public Int32 Rotation {
+ get => this._rotate;
+ set {
+ if(value < 0 || value > 359) {
+ throw new ArgumentOutOfRangeException(nameof(value), "Valid range 0-359");
+ }
+
+ this._rotate = value;
+ }
+ }
+
+ ///
+ public override String CreateProcessArguments() {
+ StringBuilder sb = new StringBuilder(base.CreateProcessArguments());
+ _ = sb.Append($" -e {this.CaptureEncoding.ToString().ToLowerInvariant()}");
+
+ // JPEG Encoder specific arguments
+ if(this.CaptureEncoding == CameraImageEncodingFormat.Jpg) {
+ _ = sb.Append($" -q {this.CaptureJpegQuality.Clamp(0, 100).ToString(Ci)}");
+
+ if(this.CaptureJpegIncludeRawBayerMetadata) {
+ _ = sb.Append(" -r");
+ }
+
+ // JPEG EXIF data
+ if(this.CaptureJpegExtendedInfo.Count > 0) {
+ foreach(KeyValuePair kvp in this.CaptureJpegExtendedInfo) {
+ if(String.IsNullOrWhiteSpace(kvp.Key) || String.IsNullOrWhiteSpace(kvp.Value)) {
+ continue;
+ }
+
+ _ = sb.Append($" -x \"{kvp.Key.Replace("\"", "'")}={kvp.Value.Replace("\"", "'")}\"");
+ }
+ }
+ }
+
+ // Display preview settings
+ if(this.CaptureDisplayPreview && this.CaptureDisplayPreviewAtResolution) {
+ _ = sb.Append(" -fp");
+ }
+
+ if(this.Rotation != 0) {
+ _ = sb.Append($" -rot {this.Rotation}");
+ }
+
+ if(this.HorizontalFlip) {
+ _ = sb.Append(" -hf");
+ }
+
+ if(this.VerticalFlip) {
+ _ = sb.Append(" -vf");
+ }
+
+ return sb.ToString();
+ }
+ }
}
\ No newline at end of file
diff --git a/Unosquare.RaspberryIO/Camera/CameraVideoSettings.cs b/Unosquare.RaspberryIO/Camera/CameraVideoSettings.cs
index f2470d8..58c10ec 100644
--- a/Unosquare.RaspberryIO/Camera/CameraVideoSettings.cs
+++ b/Unosquare.RaspberryIO/Camera/CameraVideoSettings.cs
@@ -1,94 +1,98 @@
-namespace Unosquare.RaspberryIO.Camera
-{
- using Swan;
- using System.Text;
-
+using Unosquare.Swan;
+using System;
+using System.Text;
+
+namespace Unosquare.RaspberryIO.Camera {
+ ///
+ /// Represents the raspivid camera settings for video capture functionality
+ ///
+ ///
+ public class CameraVideoSettings : CameraSettingsBase {
+ ///
+ public override String CommandName => "raspivid";
+
///
- /// Represents the raspivid camera settings for video capture functionality
+ /// Use bits per second, so 10Mbits/s would be -b 10000000. For H264, 1080p30 a high quality bitrate would be 15Mbits/s or more.
+ /// Maximum bitrate is 25Mbits/s (-b 25000000), but much over 17Mbits/s won't show noticeable improvement at 1080p30.
+ /// Default -1
///
- ///
- public class CameraVideoSettings : CameraSettingsBase
- {
- ///
- public override string CommandName => "raspivid";
-
- ///
- /// Use bits per second, so 10Mbits/s would be -b 10000000. For H264, 1080p30 a high quality bitrate would be 15Mbits/s or more.
- /// Maximum bitrate is 25Mbits/s (-b 25000000), but much over 17Mbits/s won't show noticeable improvement at 1080p30.
- /// Default -1
- ///
- public int CaptureBitrate { get; set; } = -1;
-
- ///
- /// Gets or sets the framerate.
- /// Default 25, range 2 to 30
- ///
- public int CaptureFramerate { get; set; } = 25;
-
- ///
- /// Sets the intra refresh period (GoP) rate for the recorded video. H264 video uses a complete frame (I-frame) every intra
- /// refresh period, from which subsequent frames are based. This option specifies the number of frames between each I-frame.
- /// Larger numbers here will reduce the size of the resulting video, and smaller numbers make the stream less error-prone.
- ///
- public int CaptureKeyframeRate { get; set; } = 25;
-
- ///
- /// Sets the initial quantisation parameter for the stream. Varies from approximately 10 to 40, and will greatly affect
- /// the quality of the recording. Higher values reduce quality and decrease file size. Combine this setting with a
- /// bitrate of 0 to set a completely variable bitrate.
- ///
- public int CaptureQuantisation { get; set; } = 23;
-
- ///
- /// Gets or sets the profile.
- /// Sets the H264 profile to be used for the encoding.
- /// Default is Main mode
- ///
- public CameraH264Profile CaptureProfile { get; set; } = CameraH264Profile.Main;
-
- ///
- /// Forces the stream to include PPS and SPS headers on every I-frame. Needed for certain streaming cases
- /// e.g. Apple HLS. These headers are small, so don't greatly increase the file size.
- ///
- ///
- /// true if [interleave headers]; otherwise, false.
- ///
- public bool CaptureInterleaveHeaders { get; set; } = true;
-
- ///
- /// Switch on an option to display the preview after compression. This will show any compression artefacts in the preview window. In normal operation,
- /// the preview will show the camera output prior to being compressed. This option is not guaranteed to work in future releases.
- ///
- ///
- /// true if [capture display preview encoded]; otherwise, false.
- ///
- public bool CaptureDisplayPreviewEncoded { get; set; } = false;
-
- ///
- public override string CreateProcessArguments()
- {
- var sb = new StringBuilder(base.CreateProcessArguments());
-
- sb.Append($" -pf {CaptureProfile.ToString().ToLowerInvariant()}");
- if (CaptureBitrate < 0)
- sb.Append($" -b {CaptureBitrate.Clamp(0, 25000000).ToString(Ci)}");
-
- if (CaptureFramerate >= 2)
- sb.Append($" -fps {CaptureFramerate.Clamp(2, 30).ToString(Ci)}");
-
- if (CaptureDisplayPreview && CaptureDisplayPreviewEncoded)
- sb.Append(" -e");
-
- if (CaptureKeyframeRate > 0)
- sb.Append($" -g {CaptureKeyframeRate.ToString(Ci)}");
-
- if (CaptureQuantisation >= 0)
- sb.Append($" -qp {CaptureQuantisation.Clamp(0, 40).ToString(Ci)}");
-
- if (CaptureInterleaveHeaders)
- sb.Append(" -ih");
-
- return sb.ToString();
- }
- }
+ public Int32 CaptureBitrate { get; set; } = -1;
+
+ ///
+ /// Gets or sets the framerate.
+ /// Default 25, range 2 to 30
+ ///
+ public Int32 CaptureFramerate { get; set; } = 25;
+
+ ///
+ /// Sets the intra refresh period (GoP) rate for the recorded video. H264 video uses a complete frame (I-frame) every intra
+ /// refresh period, from which subsequent frames are based. This option specifies the number of frames between each I-frame.
+ /// Larger numbers here will reduce the size of the resulting video, and smaller numbers make the stream less error-prone.
+ ///
+ public Int32 CaptureKeyframeRate { get; set; } = 25;
+
+ ///
+ /// Sets the initial quantisation parameter for the stream. Varies from approximately 10 to 40, and will greatly affect
+ /// the quality of the recording. Higher values reduce quality and decrease file size. Combine this setting with a
+ /// bitrate of 0 to set a completely variable bitrate.
+ ///
+ public Int32 CaptureQuantisation { get; set; } = 23;
+
+ ///
+ /// Gets or sets the profile.
+ /// Sets the H264 profile to be used for the encoding.
+ /// Default is Main mode
+ ///
+ public CameraH264Profile CaptureProfile { get; set; } = CameraH264Profile.Main;
+
+ ///
+ /// Forces the stream to include PPS and SPS headers on every I-frame. Needed for certain streaming cases
+ /// e.g. Apple HLS. These headers are small, so don't greatly increase the file size.
+ ///
+ ///
+ /// true if [interleave headers]; otherwise, false.
+ ///
+ public Boolean CaptureInterleaveHeaders { get; set; } = true;
+
+ ///
+ /// Switch on an option to display the preview after compression. This will show any compression artefacts in the preview window. In normal operation,
+ /// the preview will show the camera output prior to being compressed. This option is not guaranteed to work in future releases.
+ ///
+ ///
+ /// true if [capture display preview encoded]; otherwise, false.
+ ///
+ public Boolean CaptureDisplayPreviewEncoded { get; set; } = false;
+
+ ///
+ public override String CreateProcessArguments() {
+ StringBuilder sb = new StringBuilder(base.CreateProcessArguments());
+
+ _ = sb.Append($" -pf {this.CaptureProfile.ToString().ToLowerInvariant()}");
+ if(this.CaptureBitrate < 0) {
+ _ = sb.Append($" -b {this.CaptureBitrate.Clamp(0, 25000000).ToString(Ci)}");
+ }
+
+ if(this.CaptureFramerate >= 2) {
+ _ = sb.Append($" -fps {this.CaptureFramerate.Clamp(2, 30).ToString(Ci)}");
+ }
+
+ if(this.CaptureDisplayPreview && this.CaptureDisplayPreviewEncoded) {
+ _ = sb.Append(" -e");
+ }
+
+ if(this.CaptureKeyframeRate > 0) {
+ _ = sb.Append($" -g {this.CaptureKeyframeRate.ToString(Ci)}");
+ }
+
+ if(this.CaptureQuantisation >= 0) {
+ _ = sb.Append($" -qp {this.CaptureQuantisation.Clamp(0, 40).ToString(Ci)}");
+ }
+
+ if(this.CaptureInterleaveHeaders) {
+ _ = sb.Append(" -ih");
+ }
+
+ return sb.ToString();
+ }
+ }
}
\ No newline at end of file
diff --git a/Unosquare.RaspberryIO/Camera/Enums.cs b/Unosquare.RaspberryIO/Camera/Enums.cs
index 9473147..d9d5200 100644
--- a/Unosquare.RaspberryIO/Camera/Enums.cs
+++ b/Unosquare.RaspberryIO/Camera/Enums.cs
@@ -1,423 +1,413 @@
-namespace Unosquare.RaspberryIO.Camera
-{
- using System;
-
+using System;
+
+namespace Unosquare.RaspberryIO.Camera {
+ ///
+ /// Defines the available encoding formats for the Raspberry Pi camera module
+ ///
+ public enum CameraImageEncodingFormat {
///
- /// Defines the available encoding formats for the Raspberry Pi camera module
+ /// The JPG
///
- public enum CameraImageEncodingFormat
- {
- ///
- /// The JPG
- ///
- Jpg,
-
- ///
- /// The BMP
- ///
- Bmp,
-
- ///
- /// The GIF
- ///
- Gif,
-
- ///
- /// The PNG
- ///
- Png,
- }
-
+ Jpg,
+
///
- /// Defines the different exposure modes for the Raspberry Pi's camera module
+ /// The BMP
///
- public enum CameraExposureMode
- {
- ///
- /// The automatic
- ///
- Auto,
-
- ///
- /// The night
- ///
- Night,
-
- ///
- /// The night preview
- ///
- NightPreview,
-
- ///
- /// The backlight
- ///
- Backlight,
-
- ///
- /// The spotlight
- ///
- Spotlight,
-
- ///
- /// The sports
- ///
- Sports,
-
- ///
- /// The snow
- ///
- Snow,
-
- ///
- /// The beach
- ///
- Beach,
-
- ///
- /// The very long
- ///
- VeryLong,
-
- ///
- /// The fixed FPS
- ///
- FixedFps,
-
- ///
- /// The anti shake
- ///
- AntiShake,
-
- ///
- /// The fireworks
- ///
- Fireworks
- }
-
+ Bmp,
+
///
- /// Defines the different AWB (Auto White Balance) modes for the Raspberry Pi's camera module
+ /// The GIF
///
- public enum CameraWhiteBalanceMode
- {
- ///
- /// No white balance
- ///
- Off,
-
- ///
- /// The automatic
- ///
- Auto,
-
- ///
- /// The sun
- ///
- Sun,
-
- ///
- /// The cloud
- ///
- Cloud,
-
- ///
- /// The shade
- ///
- Shade,
-
- ///
- /// The tungsten
- ///
- Tungsten,
-
- ///
- /// The fluorescent
- ///
- Fluorescent,
-
- ///
- /// The incandescent
- ///
- Incandescent,
-
- ///
- /// The flash
- ///
- Flash,
-
- ///
- /// The horizon
- ///
- Horizon
- }
-
+ Gif,
+
///
- /// Defines the available image effects for the Raspberry Pi's camera module
+ /// The PNG
///
- public enum CameraImageEffect
- {
- ///
- /// No effect
- ///
- None,
-
- ///
- /// The negative
- ///
- Negative,
-
- ///
- /// The solarise
- ///
- Solarise,
-
- ///
- /// The whiteboard
- ///
- Whiteboard,
-
- ///
- /// The blackboard
- ///
- Blackboard,
-
- ///
- /// The sketch
- ///
- Sketch,
-
- ///
- /// The denoise
- ///
- Denoise,
-
- ///
- /// The emboss
- ///
- Emboss,
-
- ///
- /// The oil paint
- ///
- OilPaint,
-
- ///
- /// The hatch
- ///
- Hatch,
-
- ///
- /// Graphite Pen
- ///
- GPen,
-
- ///
- /// The pastel
- ///
- Pastel,
-
- ///
- /// The water colour
- ///
- WaterColour,
-
- ///
- /// The film
- ///
- Film,
-
- ///
- /// The blur
- ///
- Blur,
-
- ///
- /// The saturation
- ///
- Saturation,
-
- ///
- /// The solour swap
- ///
- SolourSwap,
-
- ///
- /// The washed out
- ///
- WashedOut,
-
- ///
- /// The colour point
- ///
- ColourPoint,
-
- ///
- /// The colour balance
- ///
- ColourBalance,
-
- ///
- /// The cartoon
- ///
- Cartoon
- }
-
+ Png,
+ }
+
+ ///
+ /// Defines the different exposure modes for the Raspberry Pi's camera module
+ ///
+ public enum CameraExposureMode {
///
- /// Defines the different metering modes for the Raspberry Pi's camera module
+ /// The automatic
///
- public enum CameraMeteringMode
- {
- ///
- /// The average
- ///
- Average,
-
- ///
- /// The spot
- ///
- Spot,
-
- ///
- /// The backlit
- ///
- Backlit,
-
- ///
- /// The matrix
- ///
- Matrix,
- }
-
+ Auto,
+
///
- /// Defines the different image rotation modes for the Raspberry Pi's camera module
+ /// The night
///
- public enum CameraImageRotation
- {
- ///
- /// No rerotation
- ///
- None = 0,
-
- ///
- /// 90 Degrees
- ///
- Degrees90 = 90,
-
- ///
- /// 180 Degrees
- ///
- Degrees180 = 180,
-
- ///
- /// 270 degrees
- ///
- Degrees270 = 270
- }
-
+ Night,
+
///
- /// Defines the different DRC (Dynamic Range Compensation) modes for the Raspberry Pi's camera module
- /// Helpful for low light photos
+ /// The night preview
///
- public enum CameraDynamicRangeCompensation
- {
- ///
- /// The off setting
- ///
- Off,
-
- ///
- /// The low
- ///
- Low,
-
- ///
- /// The medium
- ///
- Medium,
-
- ///
- /// The high
- ///
- High
- }
-
+ NightPreview,
+
///
- /// Defines the bit-wise mask flags for the available annotation elements for the Raspberry Pi's camera module
+ /// The backlight
///
- [Flags]
- public enum CameraAnnotation
- {
- ///
- /// The none
- ///
- None = 0,
-
- ///
- /// The time
- ///
- Time = 4,
-
- ///
- /// The date
- ///
- Date = 8,
-
- ///
- /// The shutter settings
- ///
- ShutterSettings = 16,
-
- ///
- /// The caf settings
- ///
- CafSettings = 32,
-
- ///
- /// The gain settings
- ///
- GainSettings = 64,
-
- ///
- /// The lens settings
- ///
- LensSettings = 128,
-
- ///
- /// The motion settings
- ///
- MotionSettings = 256,
-
- ///
- /// The frame number
- ///
- FrameNumber = 512,
-
- ///
- /// The solid background
- ///
- SolidBackground = 1024,
- }
-
+ Backlight,
+
///
- /// Defines the different H.264 encoding profiles to be used when capturing video.
+ /// The spotlight
///
- public enum CameraH264Profile
- {
- ///
- /// BP: Primarily for lower-cost applications with limited computing resources,
- /// this profile is used widely in videoconferencing and mobile applications.
- ///
- Baseline,
-
- ///
- /// MP: Originally intended as the mainstream consumer profile for broadcast
- /// and storage applications, the importance of this profile faded when the High profile was developed for those applications.
- ///
- Main,
-
- ///
- /// HiP: The primary profile for broadcast and disc storage applications, particularly
- /// for high-definition television applications (this is the profile adopted into HD DVD and Blu-ray Disc, for example).
- ///
- High
- }
+ Spotlight,
+
+ ///
+ /// The sports
+ ///
+ Sports,
+
+ ///
+ /// The snow
+ ///
+ Snow,
+
+ ///
+ /// The beach
+ ///
+ Beach,
+
+ ///
+ /// The very long
+ ///
+ VeryLong,
+
+ ///
+ /// The fixed FPS
+ ///
+ FixedFps,
+
+ ///
+ /// The anti shake
+ ///
+ AntiShake,
+
+ ///
+ /// The fireworks
+ ///
+ Fireworks
+ }
+
+ ///
+ /// Defines the different AWB (Auto White Balance) modes for the Raspberry Pi's camera module
+ ///
+ public enum CameraWhiteBalanceMode {
+ ///
+ /// No white balance
+ ///
+ Off,
+
+ ///
+ /// The automatic
+ ///
+ Auto,
+
+ ///
+ /// The sun
+ ///
+ Sun,
+
+ ///
+ /// The cloud
+ ///
+ Cloud,
+
+ ///
+ /// The shade
+ ///
+ Shade,
+
+ ///
+ /// The tungsten
+ ///
+ Tungsten,
+
+ ///
+ /// The fluorescent
+ ///
+ Fluorescent,
+
+ ///
+ /// The incandescent
+ ///
+ Incandescent,
+
+ ///
+ /// The flash
+ ///
+ Flash,
+
+ ///
+ /// The horizon
+ ///
+ Horizon
+ }
+
+ ///
+ /// Defines the available image effects for the Raspberry Pi's camera module
+ ///
+ public enum CameraImageEffect {
+ ///
+ /// No effect
+ ///
+ None,
+
+ ///
+ /// The negative
+ ///
+ Negative,
+
+ ///
+ /// The solarise
+ ///
+ Solarise,
+
+ ///
+ /// The whiteboard
+ ///
+ Whiteboard,
+
+ ///
+ /// The blackboard
+ ///
+ Blackboard,
+
+ ///
+ /// The sketch
+ ///
+ Sketch,
+
+ ///
+ /// The denoise
+ ///
+ Denoise,
+
+ ///
+ /// The emboss
+ ///
+ Emboss,
+
+ ///
+ /// The oil paint
+ ///
+ OilPaint,
+
+ ///
+ /// The hatch
+ ///
+ Hatch,
+
+ ///
+ /// Graphite Pen
+ ///
+ GPen,
+
+ ///
+ /// The pastel
+ ///
+ Pastel,
+
+ ///
+ /// The water colour
+ ///
+ WaterColour,
+
+ ///
+ /// The film
+ ///
+ Film,
+
+ ///
+ /// The blur
+ ///
+ Blur,
+
+ ///
+ /// The saturation
+ ///
+ Saturation,
+
+ ///
+ /// The solour swap
+ ///
+ SolourSwap,
+
+ ///
+ /// The washed out
+ ///
+ WashedOut,
+
+ ///
+ /// The colour point
+ ///
+ ColourPoint,
+
+ ///
+ /// The colour balance
+ ///
+ ColourBalance,
+
+ ///
+ /// The cartoon
+ ///
+ Cartoon
+ }
+
+ ///
+ /// Defines the different metering modes for the Raspberry Pi's camera module
+ ///
+ public enum CameraMeteringMode {
+ ///
+ /// The average
+ ///
+ Average,
+
+ ///
+ /// The spot
+ ///
+ Spot,
+
+ ///
+ /// The backlit
+ ///
+ Backlit,
+
+ ///
+ /// The matrix
+ ///
+ Matrix,
+ }
+
+ ///
+ /// Defines the different image rotation modes for the Raspberry Pi's camera module
+ ///
+ public enum CameraImageRotation {
+ ///
+ /// No rerotation
+ ///
+ None = 0,
+
+ ///
+ /// 90 Degrees
+ ///
+ Degrees90 = 90,
+
+ ///
+ /// 180 Degrees
+ ///
+ Degrees180 = 180,
+
+ ///
+ /// 270 degrees
+ ///
+ Degrees270 = 270
+ }
+
+ ///
+ /// Defines the different DRC (Dynamic Range Compensation) modes for the Raspberry Pi's camera module
+ /// Helpful for low light photos
+ ///
+ public enum CameraDynamicRangeCompensation {
+ ///
+ /// The off setting
+ ///
+ Off,
+
+ ///
+ /// The low
+ ///
+ Low,
+
+ ///
+ /// The medium
+ ///
+ Medium,
+
+ ///
+ /// The high
+ ///
+ High
+ }
+
+ ///
+ /// Defines the bit-wise mask flags for the available annotation elements for the Raspberry Pi's camera module
+ ///
+ [Flags]
+ public enum CameraAnnotation {
+ ///
+ /// The none
+ ///
+ None = 0,
+
+ ///
+ /// The time
+ ///
+ Time = 4,
+
+ ///
+ /// The date
+ ///
+ Date = 8,
+
+ ///
+ /// The shutter settings
+ ///
+ ShutterSettings = 16,
+
+ ///
+ /// The caf settings
+ ///
+ CafSettings = 32,
+
+ ///
+ /// The gain settings
+ ///
+ GainSettings = 64,
+
+ ///
+ /// The lens settings
+ ///
+ LensSettings = 128,
+
+ ///
+ /// The motion settings
+ ///
+ MotionSettings = 256,
+
+ ///
+ /// The frame number
+ ///
+ FrameNumber = 512,
+
+ ///
+ /// The solid background
+ ///
+ SolidBackground = 1024,
+ }
+
+ ///
+ /// Defines the different H.264 encoding profiles to be used when capturing video.
+ ///
+ public enum CameraH264Profile {
+ ///
+ /// BP: Primarily for lower-cost applications with limited computing resources,
+ /// this profile is used widely in videoconferencing and mobile applications.
+ ///
+ Baseline,
+
+ ///
+ /// MP: Originally intended as the mainstream consumer profile for broadcast
+ /// and storage applications, the importance of this profile faded when the High profile was developed for those applications.
+ ///
+ Main,
+
+ ///
+ /// HiP: The primary profile for broadcast and disc storage applications, particularly
+ /// for high-definition television applications (this is the profile adopted into HD DVD and Blu-ray Disc, for example).
+ ///
+ High
+ }
}
diff --git a/Unosquare.RaspberryIO/Computer/DsiDisplay.cs b/Unosquare.RaspberryIO/Computer/DsiDisplay.cs
index aff143f..418f0c2 100644
--- a/Unosquare.RaspberryIO/Computer/DsiDisplay.cs
+++ b/Unosquare.RaspberryIO/Computer/DsiDisplay.cs
@@ -1,80 +1,66 @@
-namespace Unosquare.RaspberryIO.Computer
-{
- using Swan.Abstractions;
- using System.Globalization;
- using System.IO;
-
+using Unosquare.Swan.Abstractions;
+using System.Globalization;
+using System.IO;
+using System;
+
+namespace Unosquare.RaspberryIO.Computer {
+ ///
+ /// The Official Raspberry Pi 7-inch touch display from the foundation
+ /// Some docs available here:
+ /// http://forums.pimoroni.com/t/official-7-raspberry-pi-touch-screen-faq/959
+ ///
+ public class DsiDisplay : SingletonBase {
+ private const String BacklightFilename = "/sys/class/backlight/rpi_backlight/bl_power";
+ private const String BrightnessFilename = "/sys/class/backlight/rpi_backlight/brightness";
+
///
- /// The Official Raspberry Pi 7-inch touch display from the foundation
- /// Some docs available here:
- /// http://forums.pimoroni.com/t/official-7-raspberry-pi-touch-screen-faq/959
+ /// Prevents a default instance of the class from being created.
///
- public class DsiDisplay : SingletonBase
- {
- private const string BacklightFilename = "/sys/class/backlight/rpi_backlight/bl_power";
- private const string BrightnessFilename = "/sys/class/backlight/rpi_backlight/brightness";
-
- ///
- /// Prevents a default instance of the class from being created.
- ///
- private DsiDisplay()
- {
- // placeholder
- }
-
- ///
- /// Gets a value indicating whether the Pi Foundation Display files are present.
- ///
- ///
- /// true if this instance is present; otherwise, false.
- ///
- public bool IsPresent => File.Exists(BrightnessFilename);
-
- ///
- /// Gets or sets the brightness of the DSI display via filesystem.
- ///
- ///
- /// The brightness.
- ///
- public byte Brightness
- {
- get
- {
- if (IsPresent == false) return 0;
-
- return byte.TryParse(File.ReadAllText(BrightnessFilename).Trim(), out var brightness) ? brightness : (byte)0;
- }
- set
- {
- if (IsPresent == false) return;
- File.WriteAllText(BrightnessFilename, value.ToString(CultureInfo.InvariantCulture));
- }
- }
-
- ///
- /// Gets or sets a value indicating whether the backlight of the DSI display on.
- /// This operation is performed via the file system
- ///
- ///
- /// true if this instance is backlight on; otherwise, false.
- ///
- public bool IsBacklightOn
- {
- get
- {
- if (IsPresent == false) return false;
-
- if (int.TryParse(File.ReadAllText(BacklightFilename).Trim(), out var backlight))
- return backlight == 0;
-
- return false;
- }
- set
- {
- if (IsPresent == false) return;
-
- File.WriteAllText(BacklightFilename, value ? "0" : "1");
- }
- }
- }
+ private DsiDisplay() {
+ // placeholder
+ }
+
+ ///
+ /// Gets a value indicating whether the Pi Foundation Display files are present.
+ ///
+ ///
+ /// true if this instance is present; otherwise, false.
+ ///
+ public Boolean IsPresent => File.Exists(BrightnessFilename);
+
+ ///
+ /// Gets or sets the brightness of the DSI display via filesystem.
+ ///
+ ///
+ /// The brightness.
+ ///
+ public Byte Brightness {
+ get => this.IsPresent == false ? (Byte)0 : Byte.TryParse(File.ReadAllText(BrightnessFilename).Trim(), out Byte brightness) ? brightness : (Byte)0;
+ set {
+ if(this.IsPresent == false) {
+ return;
+ }
+
+ File.WriteAllText(BrightnessFilename, value.ToString(CultureInfo.InvariantCulture));
+ }
+ }
+
+ ///
+ /// Gets or sets a value indicating whether the backlight of the DSI display on.
+ /// This operation is performed via the file system
+ ///
+ ///
+ /// true if this instance is backlight on; otherwise, false.
+ ///
+ public Boolean IsBacklightOn {
+ get => this.IsPresent == false ? false : Int32.TryParse(File.ReadAllText(BacklightFilename).Trim(), out Int32 backlight) ? backlight == 0 : false;
+ set {
+ if(this.IsPresent == false) {
+ return;
+ }
+
+ File.WriteAllText(BacklightFilename, value ? "0" : "1");
+ }
+ }
+ }
}
diff --git a/Unosquare.RaspberryIO/Computer/NetworkAdapterInfo.cs b/Unosquare.RaspberryIO/Computer/NetworkAdapterInfo.cs
index d90ba47..a63c8eb 100644
--- a/Unosquare.RaspberryIO/Computer/NetworkAdapterInfo.cs
+++ b/Unosquare.RaspberryIO/Computer/NetworkAdapterInfo.cs
@@ -1,40 +1,51 @@
-namespace Unosquare.RaspberryIO.Computer
-{
- using System.Net;
-
+using System;
+using System.Net;
+
+namespace Unosquare.RaspberryIO.Computer {
+ ///
+ /// Represents a Network Adapter
+ ///
+ public class NetworkAdapterInfo {
///
- /// Represents a Network Adapter
+ /// Gets the name.
///
- public class NetworkAdapterInfo
- {
- ///
- /// Gets the name.
- ///
- public string Name { get; internal set; }
-
- ///
- /// Gets the IP V4 address.
- ///
- public IPAddress IPv4 { get; internal set; }
-
- ///
- /// Gets the IP V6 address.
- ///
- public IPAddress IPv6 { get; internal set; }
-
- ///
- /// Gets the name of the access point.
- ///
- public string AccessPointName { get; internal set; }
-
- ///
- /// Gets the MAC (Physical) address.
- ///
- public string MacAddress { get; internal set; }
-
- ///
- /// Gets a value indicating whether this instance is wireless.
- ///
- public bool IsWireless { get; internal set; }
- }
+ public String Name {
+ get; internal set;
+ }
+
+ ///
+ /// Gets the IP V4 address.
+ ///
+ public IPAddress IPv4 {
+ get; internal set;
+ }
+
+ ///
+ /// Gets the IP V6 address.
+ ///
+ public IPAddress IPv6 {
+ get; internal set;
+ }
+
+ ///
+ /// Gets the name of the access point.
+ ///
+ public String AccessPointName {
+ get; internal set;
+ }
+
+ ///
+ /// Gets the MAC (Physical) address.
+ ///
+ public String MacAddress {
+ get; internal set;
+ }
+
+ ///
+ /// Gets a value indicating whether this instance is wireless.
+ ///
+ public Boolean IsWireless {
+ get; internal set;
+ }
+ }
}
diff --git a/Unosquare.RaspberryIO/Computer/NetworkSettings.cs b/Unosquare.RaspberryIO/Computer/NetworkSettings.cs
index 6d03de0..d8e690f 100644
--- a/Unosquare.RaspberryIO/Computer/NetworkSettings.cs
+++ b/Unosquare.RaspberryIO/Computer/NetworkSettings.cs
@@ -1,266 +1,252 @@
-namespace Unosquare.RaspberryIO.Computer
-{
- using Swan;
- using Swan.Abstractions;
- using Swan.Components;
- using System;
- using System.Collections.Generic;
- using System.IO;
- using System.Linq;
- using System.Net;
- using System.Text;
-
+using Unosquare.Swan;
+using Unosquare.Swan.Abstractions;
+using Unosquare.Swan.Components;
+using System;
+using System.Collections.Generic;
+using System.IO;
+using System.Linq;
+using System.Net;
+using System.Text;
+
+namespace Unosquare.RaspberryIO.Computer {
+ ///
+ /// Represents the network information
+ ///
+ public class NetworkSettings : SingletonBase {
+ private const String EssidTag = "ESSID:";
+
///
- /// Represents the network information
+ /// Gets the local machine Host Name.
///
- public class NetworkSettings : SingletonBase
- {
- private const string EssidTag = "ESSID:";
-
- ///
- /// Gets the local machine Host Name.
- ///
- public string HostName => Network.HostName;
-
- ///
- /// Retrieves the wireless networks.
- ///
- /// The adapter.
- /// A list of WiFi networks
- public List RetrieveWirelessNetworks(string adapter) => RetrieveWirelessNetworks(new[] { adapter });
-
- ///
- /// Retrieves the wireless networks.
- ///
- /// The adapters.
- /// A list of WiFi networks
- public List RetrieveWirelessNetworks(string[] adapters = null)
- {
- var result = new List();
-
- foreach (var networkAdapter in adapters ?? RetrieveAdapters().Where(x => x.IsWireless).Select(x => x.Name))
- {
- var wirelessOutput = ProcessRunner.GetProcessOutputAsync("iwlist", $"{networkAdapter} scanning").Result;
- var outputLines =
- wirelessOutput.Split('\n')
- .Select(x => x.Trim())
- .Where(x => string.IsNullOrWhiteSpace(x) == false)
- .ToArray();
-
- for (var i = 0; i < outputLines.Length; i++)
- {
- var line = outputLines[i];
-
- if (line.StartsWith(EssidTag) == false) continue;
-
- var network = new WirelessNetworkInfo()
- {
- Name = line.Replace(EssidTag, string.Empty).Replace("\"", string.Empty)
- };
-
- while (true)
- {
- if (i + 1 >= outputLines.Length) break;
-
- // should look for two lines before the ESSID acording to the scan
- line = outputLines[i - 2];
-
- if (line.StartsWith("Quality="))
- {
- network.Quality = line.Replace("Quality=", string.Empty);
- break;
- }
- }
-
- while (true)
- {
- if (i + 1 >= outputLines.Length) break;
-
- // should look for a line before the ESSID acording to the scan
- line = outputLines[i - 1];
-
- if (line.StartsWith("Encryption key:"))
- {
- network.IsEncrypted = line.Replace("Encryption key:", string.Empty).Trim() == "on";
- break;
- }
- }
-
- if (result.Any(x => x.Name == network.Name) == false)
- result.Add(network);
- }
- }
-
- return result.OrderBy(x => x.Name).ToList();
- }
-
- ///
- /// Setups the wireless network.
- ///
- /// Name of the adapter.
- /// The network ssid.
- /// The password.
- /// The 2-letter country code in uppercase. Default is US.
- /// True if successful. Otherwise, false.
- public bool SetupWirelessNetwork(string adapterName, string networkSsid, string password = null, string countryCode = "US")
- {
- // TODO: Get the country where the device is located to set 'country' param in payload var
- var payload = $"country={countryCode}\nctrl_interface=DIR=/var/run/wpa_supplicant GROUP=netdev\nupdate_config=1\n";
- payload += string.IsNullOrEmpty(password)
- ? $"network={{\n\tssid=\"{networkSsid}\"\n\t}}\n"
- : $"network={{\n\tssid=\"{networkSsid}\"\n\tpsk=\"{password}\"\n\t}}\n";
- try
- {
- File.WriteAllText("/etc/wpa_supplicant/wpa_supplicant.conf", payload);
- ProcessRunner.GetProcessOutputAsync("pkill", "-f wpa_supplicant").Wait();
- ProcessRunner.GetProcessOutputAsync("ifdown", adapterName).Wait();
- ProcessRunner.GetProcessOutputAsync("ifup", adapterName).Wait();
- }
- catch (Exception ex)
- {
- ex.Log(nameof(NetworkSettings));
- return false;
- }
-
- return true;
- }
-
- ///
- /// Retrieves the network adapters.
- ///
- /// A list of network adapters.
- public List RetrieveAdapters()
- {
- const string hWaddr = "HWaddr ";
- const string ether = "ether ";
-
- var result = new List();
- var interfacesOutput = ProcessRunner.GetProcessOutputAsync("ifconfig").Result;
- var wlanOutput = ProcessRunner.GetProcessOutputAsync("iwconfig")
- .Result.Split('\n')
- .Where(x => x.Contains("no wireless extensions.") == false)
- .ToArray();
-
- var outputLines = interfacesOutput.Split('\n').Where(x => string.IsNullOrWhiteSpace(x) == false).ToArray();
-
- for (var i = 0; i < outputLines.Length; i++)
- {
- // grab the current line
- var line = outputLines[i];
-
- // skip if the line is indented
- if (char.IsLetterOrDigit(line[0]) == false)
- continue;
-
- // Read the line as an adatper
- var adapter = new NetworkAdapterInfo
- {
- Name = line.Substring(0, line.IndexOf(' ')).TrimEnd(':')
- };
-
- // Parse the MAC address in old version of ifconfig; it comes in the first line
- if (line.IndexOf(hWaddr) >= 0)
- {
- var startIndexHwd = line.IndexOf(hWaddr) + hWaddr.Length;
- adapter.MacAddress = line.Substring(startIndexHwd, 17).Trim();
- }
-
- // Parse the info in lines other than the first
- for (var j = i + 1; j < outputLines.Length; j++)
- {
- // Get the contents of the indented line
- var indentedLine = outputLines[j];
-
- // We have hit the next adapter info
- if (char.IsLetterOrDigit(indentedLine[0]))
- {
- i = j - 1;
- break;
- }
-
- // Parse the MAC address in new versions of ifconfig; it no longer comes in the first line
- if (indentedLine.IndexOf(ether) >= 0 && string.IsNullOrWhiteSpace(adapter.MacAddress))
- {
- var startIndexHwd = indentedLine.IndexOf(ether) + ether.Length;
- adapter.MacAddress = indentedLine.Substring(startIndexHwd, 17).Trim();
- }
-
- // Parse the IPv4 Address
- {
- var addressText = ParseOutputTagFromLine(indentedLine, "inet addr:") ?? ParseOutputTagFromLine(indentedLine, "inet ");
-
- if (addressText != null)
- {
- if (IPAddress.TryParse(addressText, out var outValue))
- adapter.IPv4 = outValue;
- }
- }
-
- // Parse the IPv6 Address
- {
- var addressText = ParseOutputTagFromLine(indentedLine, "inet6 addr:") ?? ParseOutputTagFromLine(indentedLine, "inet6 ");
-
- if (addressText != null)
- {
- if (IPAddress.TryParse(addressText, out var outValue))
- adapter.IPv6 = outValue;
- }
- }
-
- // we have hit the end of the output in an indented line
- if (j >= outputLines.Length - 1)
- i = outputLines.Length;
- }
-
- // Retrieve the wireless LAN info
- var wlanInfo = wlanOutput.FirstOrDefault(x => x.StartsWith(adapter.Name));
-
- if (wlanInfo != null)
- {
- adapter.IsWireless = true;
- var essidParts = wlanInfo.Split(new[] { EssidTag }, StringSplitOptions.RemoveEmptyEntries);
- if (essidParts.Length >= 2)
- {
- adapter.AccessPointName = essidParts[1].Replace("\"", string.Empty).Trim();
- }
- }
-
- // Add the current adapter to the result
- result.Add(adapter);
- }
-
- return result.OrderBy(x => x.Name).ToList();
- }
-
- ///
- /// Retrieves current wireless connected network name.
- ///
- /// The connected network name.
- public string GetWirelessNetworkName() => ProcessRunner.GetProcessOutputAsync("iwgetid", "-r").Result;
-
- ///
- /// Parses the output tag from the given line.
- ///
- /// The indented line.
- /// Name of the tag.
- /// The value after the tag identifier
- private static string ParseOutputTagFromLine(string indentedLine, string tagName)
- {
- if (indentedLine.IndexOf(tagName) < 0)
- return null;
-
- var startIndex = indentedLine.IndexOf(tagName) + tagName.Length;
- var builder = new StringBuilder(1024);
- for (var c = startIndex; c < indentedLine.Length; c++)
- {
- var currentChar = indentedLine[c];
- if (!char.IsPunctuation(currentChar) && !char.IsLetterOrDigit(currentChar))
- break;
-
- builder.Append(currentChar);
- }
-
- return builder.ToString();
- }
- }
+ public String HostName => Network.HostName;
+
+ ///
+ /// Retrieves the wireless networks.
+ ///
+ /// The adapter.
+ /// A list of WiFi networks
+ public List RetrieveWirelessNetworks(String adapter) => this.RetrieveWirelessNetworks(new[] { adapter });
+
+ ///
+ /// Retrieves the wireless networks.
+ ///
+ /// The adapters.
+ /// A list of WiFi networks
+ public List RetrieveWirelessNetworks(String[] adapters = null) {
+ List result = new List();
+
+ foreach(String networkAdapter in adapters ?? this.RetrieveAdapters().Where(x => x.IsWireless).Select(x => x.Name)) {
+ String wirelessOutput = ProcessRunner.GetProcessOutputAsync("iwlist", $"{networkAdapter} scanning").Result;
+ String[] outputLines =
+ wirelessOutput.Split('\n')
+ .Select(x => x.Trim())
+ .Where(x => String.IsNullOrWhiteSpace(x) == false)
+ .ToArray();
+
+ for(Int32 i = 0; i < outputLines.Length; i++) {
+ String line = outputLines[i];
+
+ if(line.StartsWith(EssidTag) == false) {
+ continue;
+ }
+
+ WirelessNetworkInfo network = new WirelessNetworkInfo() {
+ Name = line.Replace(EssidTag, String.Empty).Replace("\"", String.Empty)
+ };
+
+ while(true) {
+ if(i + 1 >= outputLines.Length) {
+ break;
+ }
+
+ // should look for two lines before the ESSID acording to the scan
+ line = outputLines[i - 2];
+
+ if(line.StartsWith("Quality=")) {
+ network.Quality = line.Replace("Quality=", String.Empty);
+ break;
+ }
+ }
+
+ while(true) {
+ if(i + 1 >= outputLines.Length) {
+ break;
+ }
+
+ // should look for a line before the ESSID acording to the scan
+ line = outputLines[i - 1];
+
+ if(line.StartsWith("Encryption key:")) {
+ network.IsEncrypted = line.Replace("Encryption key:", String.Empty).Trim() == "on";
+ break;
+ }
+ }
+
+ if(result.Any(x => x.Name == network.Name) == false) {
+ result.Add(network);
+ }
+ }
+ }
+
+ return result.OrderBy(x => x.Name).ToList();
+ }
+
+ ///
+ /// Setups the wireless network.
+ ///
+ /// Name of the adapter.
+ /// The network ssid.
+ /// The password.
+ /// The 2-letter country code in uppercase. Default is US.
+ /// True if successful. Otherwise, false.
+ public Boolean SetupWirelessNetwork(String adapterName, String networkSsid, String password = null, String countryCode = "US") {
+ // TODO: Get the country where the device is located to set 'country' param in payload var
+ String payload = $"country={countryCode}\nctrl_interface=DIR=/var/run/wpa_supplicant GROUP=netdev\nupdate_config=1\n";
+ payload += String.IsNullOrEmpty(password)
+ ? $"network={{\n\tssid=\"{networkSsid}\"\n\t}}\n"
+ : $"network={{\n\tssid=\"{networkSsid}\"\n\tpsk=\"{password}\"\n\t}}\n";
+ try {
+ File.WriteAllText("/etc/wpa_supplicant/wpa_supplicant.conf", payload);
+ ProcessRunner.GetProcessOutputAsync("pkill", "-f wpa_supplicant").Wait();
+ ProcessRunner.GetProcessOutputAsync("ifdown", adapterName).Wait();
+ ProcessRunner.GetProcessOutputAsync("ifup", adapterName).Wait();
+ } catch(Exception ex) {
+ ex.Log(nameof(NetworkSettings));
+ return false;
+ }
+
+ return true;
+ }
+
+ ///
+ /// Retrieves the network adapters.
+ ///
+ /// A list of network adapters.
+ public List RetrieveAdapters() {
+ const String hWaddr = "HWaddr ";
+ const String ether = "ether ";
+
+ List result = new List();
+ String interfacesOutput = ProcessRunner.GetProcessOutputAsync("ifconfig").Result;
+ String[] wlanOutput = ProcessRunner.GetProcessOutputAsync("iwconfig")
+ .Result.Split('\n')
+ .Where(x => x.Contains("no wireless extensions.") == false)
+ .ToArray();
+
+ String[] outputLines = interfacesOutput.Split('\n').Where(x => String.IsNullOrWhiteSpace(x) == false).ToArray();
+
+ for(Int32 i = 0; i < outputLines.Length; i++) {
+ // grab the current line
+ String line = outputLines[i];
+
+ // skip if the line is indented
+ if(Char.IsLetterOrDigit(line[0]) == false) {
+ continue;
+ }
+
+ // Read the line as an adatper
+ NetworkAdapterInfo adapter = new NetworkAdapterInfo {
+ Name = line.Substring(0, line.IndexOf(' ')).TrimEnd(':')
+ };
+
+ // Parse the MAC address in old version of ifconfig; it comes in the first line
+ if(line.IndexOf(hWaddr) >= 0) {
+ Int32 startIndexHwd = line.IndexOf(hWaddr) + hWaddr.Length;
+ adapter.MacAddress = line.Substring(startIndexHwd, 17).Trim();
+ }
+
+ // Parse the info in lines other than the first
+ for(Int32 j = i + 1; j < outputLines.Length; j++) {
+ // Get the contents of the indented line
+ String indentedLine = outputLines[j];
+
+ // We have hit the next adapter info
+ if(Char.IsLetterOrDigit(indentedLine[0])) {
+ i = j - 1;
+ break;
+ }
+
+ // Parse the MAC address in new versions of ifconfig; it no longer comes in the first line
+ if(indentedLine.IndexOf(ether) >= 0 && String.IsNullOrWhiteSpace(adapter.MacAddress)) {
+ Int32 startIndexHwd = indentedLine.IndexOf(ether) + ether.Length;
+ adapter.MacAddress = indentedLine.Substring(startIndexHwd, 17).Trim();
+ }
+
+ // Parse the IPv4 Address
+ {
+ String addressText = ParseOutputTagFromLine(indentedLine, "inet addr:") ?? ParseOutputTagFromLine(indentedLine, "inet ");
+
+ if(addressText != null) {
+ if(IPAddress.TryParse(addressText, out IPAddress outValue)) {
+ adapter.IPv4 = outValue;
+ }
+ }
+ }
+
+ // Parse the IPv6 Address
+ {
+ String addressText = ParseOutputTagFromLine(indentedLine, "inet6 addr:") ?? ParseOutputTagFromLine(indentedLine, "inet6 ");
+
+ if(addressText != null) {
+ if(IPAddress.TryParse(addressText, out IPAddress outValue)) {
+ adapter.IPv6 = outValue;
+ }
+ }
+ }
+
+ // we have hit the end of the output in an indented line
+ if(j >= outputLines.Length - 1) {
+ i = outputLines.Length;
+ }
+ }
+
+ // Retrieve the wireless LAN info
+ String wlanInfo = wlanOutput.FirstOrDefault(x => x.StartsWith(adapter.Name));
+
+ if(wlanInfo != null) {
+ adapter.IsWireless = true;
+ String[] essidParts = wlanInfo.Split(new[] { EssidTag }, StringSplitOptions.RemoveEmptyEntries);
+ if(essidParts.Length >= 2) {
+ adapter.AccessPointName = essidParts[1].Replace("\"", String.Empty).Trim();
+ }
+ }
+
+ // Add the current adapter to the result
+ result.Add(adapter);
+ }
+
+ return result.OrderBy(x => x.Name).ToList();
+ }
+
+ ///
+ /// Retrieves current wireless connected network name.
+ ///
+ /// The connected network name.
+ public String GetWirelessNetworkName() => ProcessRunner.GetProcessOutputAsync("iwgetid", "-r").Result;
+
+ ///
+ /// Parses the output tag from the given line.
+ ///
+ /// The indented line.
+ /// Name of the tag.
+ /// The value after the tag identifier
+ private static String ParseOutputTagFromLine(String indentedLine, String tagName) {
+ if(indentedLine.IndexOf(tagName) < 0) {
+ return null;
+ }
+
+ Int32 startIndex = indentedLine.IndexOf(tagName) + tagName.Length;
+ StringBuilder builder = new StringBuilder(1024);
+ for(Int32 c = startIndex; c < indentedLine.Length; c++) {
+ Char currentChar = indentedLine[c];
+ if(!Char.IsPunctuation(currentChar) && !Char.IsLetterOrDigit(currentChar)) {
+ break;
+ }
+
+ _ = builder.Append(currentChar);
+ }
+
+ return builder.ToString();
+ }
+ }
}
diff --git a/Unosquare.RaspberryIO/Computer/OsInfo.cs b/Unosquare.RaspberryIO/Computer/OsInfo.cs
index 80ecfde..104ba17 100644
--- a/Unosquare.RaspberryIO/Computer/OsInfo.cs
+++ b/Unosquare.RaspberryIO/Computer/OsInfo.cs
@@ -1,46 +1,58 @@
-namespace Unosquare.RaspberryIO.Computer
-{
+using System;
+
+namespace Unosquare.RaspberryIO.Computer {
+ ///
+ /// Represents the OS Information
+ ///
+ public class OsInfo {
///
- /// Represents the OS Information
+ /// System name
///
- public class OsInfo
- {
- ///
- /// System name
- ///
- public string SysName { get; set; }
-
- ///
- /// Node name
- ///
- public string NodeName { get; set; }
-
- ///
- /// Release level
- ///
- public string Release { get; set; }
-
- ///
- /// Version level
- ///
- public string Version { get; set; }
-
- ///
- /// Hardware level
- ///
- public string Machine { get; set; }
-
- ///
- /// Domain name
- ///
- public string DomainName { get; set; }
-
- ///
- /// Returns a that represents this instance.
- ///
- ///
- /// A that represents this instance.
- ///
- public override string ToString() => $"{SysName} {Release} {Version}";
- }
+ public String SysName {
+ get; set;
+ }
+
+ ///
+ /// Node name
+ ///
+ public String NodeName {
+ get; set;
+ }
+
+ ///
+ /// Release level
+ ///
+ public String Release {
+ get; set;
+ }
+
+ ///
+ /// Version level
+ ///
+ public String Version {
+ get; set;
+ }
+
+ ///
+ /// Hardware level
+ ///
+ public String Machine {
+ get; set;
+ }
+
+ ///
+ /// Domain name
+ ///
+ public String DomainName {
+ get; set;
+ }
+
+ ///
+ /// Returns a that represents this instance.
+ ///
+ ///
+ /// A that represents this instance.
+ ///
+ public override String ToString() => $"{this.SysName} {this.Release} {this.Version}";
+ }
}
diff --git a/Unosquare.RaspberryIO/Computer/PiVersion.cs b/Unosquare.RaspberryIO/Computer/PiVersion.cs
index a6af028..15d86fe 100644
--- a/Unosquare.RaspberryIO/Computer/PiVersion.cs
+++ b/Unosquare.RaspberryIO/Computer/PiVersion.cs
@@ -1,134 +1,132 @@
-namespace Unosquare.RaspberryIO.Computer
-{
+namespace Unosquare.RaspberryIO.Computer {
+ ///
+ /// Defines the board revision codes of the different versions of the Raspberry Pi
+ /// http://www.raspberrypi-spy.co.uk/2012/09/checking-your-raspberry-pi-board-version/
+ ///
+ public enum PiVersion {
///
- /// Defines the board revision codes of the different versions of the Raspberry Pi
- /// http://www.raspberrypi-spy.co.uk/2012/09/checking-your-raspberry-pi-board-version/
+ /// The unknown version
///
- public enum PiVersion
- {
- ///
- /// The unknown version
- ///
- Unknown = 0,
-
- ///
- /// The model b rev1
- ///
- ModelBRev1 = 0x0002,
-
- ///
- /// The model b rev1 ec N0001
- ///
- ModelBRev1ECN0001 = 0x0003,
-
- ///
- /// The model b rev2x04
- ///
- ModelBRev2x04 = 0x0004,
-
- ///
- /// The model b rev2x05
- ///
- ModelBRev2x05 = 0x0005,
-
- ///
- /// The model b rev2x06
- ///
- ModelBRev2x06 = 0x0006,
-
- ///
- /// The model ax07
- ///
- ModelAx07 = 0x0007,
-
- ///
- /// The model ax08
- ///
- ModelAx08 = 0x0008,
-
- ///
- /// The model ax09
- ///
- ModelAx09 = 0x0009,
-
- ///
- /// The model b rev2x0d
- ///
- ModelBRev2x0d,
-
- ///
- /// The model b rev2x0e
- ///
- ModelBRev2x0e,
-
- ///
- /// The model b rev2x0f
- ///
- ModelBRev2x0f = 0x000f,
-
- ///
- /// The model b plus0x10
- ///
- ModelBPlus0x10 = 0x0010,
-
- ///
- /// The model b plus0x13
- ///
- ModelBPlus0x13 = 0x0013,
-
- ///
- /// The compute module0x11
- ///
- ComputeModule0x11 = 0x0011,
-
- ///
- /// The compute module0x14
- ///
- ComputeModule0x14 = 0x0014,
-
- ///
- /// The model a plus0x12
- ///
- ModelAPlus0x12 = 0x0012,
-
- ///
- /// The model a plus0x15
- ///
- ModelAPlus0x15 = 0x0015,
-
- ///
- /// The pi2 model B1V1 sony
- ///
- Pi2ModelB1v1Sony = 0xa01041,
-
- ///
- /// The pi2 model B1V1 embest
- ///
- Pi2ModelB1v1Embest = 0xa21041,
-
- ///
- /// The pi2 model B1V2
- ///
- Pi2ModelB1v2 = 0xa22042,
-
- ///
- /// The pi zero1v2
- ///
- PiZero1v2 = 0x900092,
-
- ///
- /// The pi zero1v3
- ///
- PiZero1v3 = 0x900093,
-
- ///
- /// The pi3 model b sony
- ///
- Pi3ModelBSony = 0xa02082,
-
- ///
- /// The pi3 model b embest
- ///
- Pi3ModelBEmbest = 0xa22082
- }
+ Unknown = 0,
+
+ ///
+ /// The model b rev1
+ ///
+ ModelBRev1 = 0x0002,
+
+ ///
+ /// The model b rev1 ec N0001
+ ///
+ ModelBRev1ECN0001 = 0x0003,
+
+ ///
+ /// The model b rev2x04
+ ///
+ ModelBRev2x04 = 0x0004,
+
+ ///
+ /// The model b rev2x05
+ ///
+ ModelBRev2x05 = 0x0005,
+
+ ///
+ /// The model b rev2x06
+ ///
+ ModelBRev2x06 = 0x0006,
+
+ ///
+ /// The model ax07
+ ///
+ ModelAx07 = 0x0007,
+
+ ///
+ /// The model ax08
+ ///
+ ModelAx08 = 0x0008,
+
+ ///
+ /// The model ax09
+ ///
+ ModelAx09 = 0x0009,
+
+ ///
+ /// The model b rev2x0d
+ ///
+ ModelBRev2x0d,
+
+ ///
+ /// The model b rev2x0e
+ ///
+ ModelBRev2x0e,
+
+ ///
+ /// The model b rev2x0f
+ ///
+ ModelBRev2x0f = 0x000f,
+
+ ///
+ /// The model b plus0x10
+ ///
+ ModelBPlus0x10 = 0x0010,
+
+ ///
+ /// The model b plus0x13
+ ///
+ ModelBPlus0x13 = 0x0013,
+
+ ///
+ /// The compute module0x11
+ ///
+ ComputeModule0x11 = 0x0011,
+
+ ///
+ /// The compute module0x14
+ ///
+ ComputeModule0x14 = 0x0014,
+
+ ///
+ /// The model a plus0x12
+ ///
+ ModelAPlus0x12 = 0x0012,
+
+ ///
+ /// The model a plus0x15
+ ///
+ ModelAPlus0x15 = 0x0015,
+
+ ///
+ /// The pi2 model B1V1 sony
+ ///
+ Pi2ModelB1v1Sony = 0xa01041,
+
+ ///
+ /// The pi2 model B1V1 embest
+ ///
+ Pi2ModelB1v1Embest = 0xa21041,
+
+ ///
+ /// The pi2 model B1V2
+ ///
+ Pi2ModelB1v2 = 0xa22042,
+
+ ///
+ /// The pi zero1v2
+ ///
+ PiZero1v2 = 0x900092,
+
+ ///
+ /// The pi zero1v3
+ ///
+ PiZero1v3 = 0x900093,
+
+ ///
+ /// The pi3 model b sony
+ ///
+ Pi3ModelBSony = 0xa02082,
+
+ ///
+ /// The pi3 model b embest
+ ///
+ Pi3ModelBEmbest = 0xa22082
+ }
}
\ No newline at end of file
diff --git a/Unosquare.RaspberryIO/Computer/SystemInfo.cs b/Unosquare.RaspberryIO/Computer/SystemInfo.cs
index fad1ec0..6fa9ebc 100644
--- a/Unosquare.RaspberryIO/Computer/SystemInfo.cs
+++ b/Unosquare.RaspberryIO/Computer/SystemInfo.cs
@@ -1,344 +1,343 @@
-namespace Unosquare.RaspberryIO.Computer
-{
- using Native;
- using Swan.Abstractions;
- using System;
- using System.Collections.Generic;
- using System.Globalization;
- using System.IO;
- using System.Linq;
- using System.Reflection;
-
+using Unosquare.RaspberryIO.Native;
+using Unosquare.Swan.Abstractions;
+using System;
+using System.Collections.Generic;
+using System.Globalization;
+using System.IO;
+using System.Linq;
+using System.Reflection;
+
+namespace Unosquare.RaspberryIO.Computer {
+ ///
+ /// http://raspberry-pi-guide.readthedocs.io/en/latest/system.html
+ ///
+ public sealed class SystemInfo : SingletonBase {
+ private const String CpuInfoFilePath = "/proc/cpuinfo";
+ private const String MemInfoFilePath = "/proc/meminfo";
+ private const String UptimeFilePath = "/proc/uptime";
+ private static readonly StringComparer StringComparer = StringComparer.InvariantCultureIgnoreCase;
+ [System.Diagnostics.CodeAnalysis.SuppressMessage("Codequalität", "IDE0052:Ungelesene private Member entfernen", Justification = "")]
+ private static readonly Object SyncRoot = new Object();
+
///
- /// http://raspberry-pi-guide.readthedocs.io/en/latest/system.html
+ /// Prevents a default instance of the class from being created.
///
- public sealed class SystemInfo : SingletonBase
- {
- private const string CpuInfoFilePath = "/proc/cpuinfo";
- private const string MemInfoFilePath = "/proc/meminfo";
- private const string UptimeFilePath = "/proc/uptime";
- private static readonly StringComparer StringComparer = StringComparer.InvariantCultureIgnoreCase;
-
- private static readonly object SyncRoot = new object();
-
- ///
- /// Prevents a default instance of the class from being created.
- ///
- /// Could not initialize the GPIO controller
- private SystemInfo()
- {
- #region Obtain and format a property dictionary
-
- var properties =
- typeof(SystemInfo).GetTypeInfo()
- .GetProperties(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic)
- .Where(
- p =>
- p.CanWrite && p.CanRead &&
- (p.PropertyType == typeof(string) || p.PropertyType == typeof(string[])))
- .ToArray();
- var propDictionary = new Dictionary(StringComparer);
-
- foreach (var prop in properties)
- {
- propDictionary[prop.Name.Replace(" ", string.Empty).ToLowerInvariant().Trim()] = prop;
- }
-
- #endregion
-
- #region Extract CPU information
-
- if (File.Exists(CpuInfoFilePath))
- {
- var cpuInfoLines = File.ReadAllLines(CpuInfoFilePath);
-
- foreach (var line in cpuInfoLines)
- {
- var lineParts = line.Split(new[] { ':' }, 2);
- if (lineParts.Length != 2)
- continue;
-
- var propertyKey = lineParts[0].Trim().Replace(" ", string.Empty);
- var propertyStringValue = lineParts[1].Trim();
-
- if (!propDictionary.ContainsKey(propertyKey)) continue;
-
- var property = propDictionary[propertyKey];
- if (property.PropertyType == typeof(string))
- {
- property.SetValue(this, propertyStringValue);
- }
- else if (property.PropertyType == typeof(string[]))
- {
- var propertyArrayAvalue = propertyStringValue.Split(' ');
- property.SetValue(this, propertyArrayAvalue);
- }
- }
- }
-
- #endregion
-
- #region Extract Memory Information
-
- if (File.Exists(MemInfoFilePath))
- {
- var memInfoLines = File.ReadAllLines(MemInfoFilePath);
- foreach (var line in memInfoLines)
- {
- var lineParts = line.Split(new[] { ':' }, 2);
- if (lineParts.Length != 2)
- continue;
-
- if (lineParts[0].ToLowerInvariant().Trim().Equals("memtotal") == false)
- continue;
-
- var memKb = lineParts[1].ToLowerInvariant().Trim().Replace("kb", string.Empty).Trim();
-
- if (int.TryParse(memKb, out var parsedMem))
- {
- InstalledRam = parsedMem * 1024;
- break;
- }
- }
- }
-
- #endregion
-
- #region Board Version and Form Factor
-
- try
- {
- if (string.IsNullOrWhiteSpace(Revision) == false &&
- int.TryParse(
- Revision.ToUpperInvariant(),
- NumberStyles.HexNumber,
- CultureInfo.InvariantCulture,
- out var boardVersion))
- {
- RaspberryPiVersion = PiVersion.Unknown;
- if (Enum.GetValues(typeof(PiVersion)).Cast().Contains(boardVersion))
- {
- RaspberryPiVersion = (PiVersion)boardVersion;
- }
- }
-
- WiringPiBoardRevision = WiringPi.PiBoardRev();
- }
- catch
- {
- /* Ignore */
- }
-
- #endregion
-
- #region Version Information
-
- {
- var libParts = WiringPi.WiringPiLibrary.Split('.');
- var major = int.Parse(libParts[libParts.Length - 2]);
- var minor = int.Parse(libParts[libParts.Length - 1]);
- var version = new Version(major, minor);
- WiringPiVersion = version;
- }
-
- #endregion
-
- #region Extract OS Info
-
- try
- {
- Standard.Uname(out var unameInfo);
- OperatingSystem = new OsInfo
- {
- DomainName = unameInfo.DomainName,
- Machine = unameInfo.Machine,
- NodeName = unameInfo.NodeName,
- Release = unameInfo.Release,
- SysName = unameInfo.SysName,
- Version = unameInfo.Version
- };
- }
- catch
- {
- OperatingSystem = new OsInfo();
- }
-
- #endregion
- }
-
- ///
- /// Gets the wiring pi library version.
- ///
- public Version WiringPiVersion { get; }
-
- ///
- /// Gets the OS information.
- ///
- ///
- /// The os information.
- ///
- public OsInfo OperatingSystem { get; }
-
- ///
- /// Gets the Raspberry Pi version.
- ///
- public PiVersion RaspberryPiVersion { get; }
-
- ///
- /// Gets the Wiring Pi board revision (1 or 2).
- ///
- ///
- /// The wiring pi board revision.
- ///
- public int WiringPiBoardRevision { get; }
-
- ///
- /// Gets the number of processor cores.
- ///
- public int ProcessorCount
- {
- get
- {
- if (int.TryParse(Processor, out var outIndex))
- {
- return outIndex + 1;
- }
-
- return 0;
- }
- }
-
- ///
- /// Gets the installed ram in bytes.
- ///
- public int InstalledRam { get; }
-
- ///
- /// Gets a value indicating whether this CPU is little endian.
- ///
- public bool IsLittleEndian => BitConverter.IsLittleEndian;
-
- ///
- /// Gets the CPU model name.
- ///
- public string ModelName { get; private set; }
-
- ///
- /// Gets a list of supported CPU features.
- ///
- public string[] Features { get; private set; }
-
- ///
- /// Gets the CPU implementer hex code.
- ///
- public string CpuImplementer { get; private set; }
-
- ///
- /// Gets the CPU architecture code.
- ///
- public string CpuArchitecture { get; private set; }
-
- ///
- /// Gets the CPU variant code.
- ///
- public string CpuVariant { get; private set; }
-
- ///
- /// Gets the CPU part code.
- ///
- public string CpuPart { get; private set; }
-
- ///
- /// Gets the CPU revision code.
- ///
- public string CpuRevision { get; private set; }
-
- ///
- /// Gets the hardware model number.
- ///
- public string Hardware { get; private set; }
-
- ///
- /// Gets the hardware revision number.
- ///
- public string Revision { get; private set; }
-
- ///
- /// Gets the serial number.
- ///
- public string Serial { get; private set; }
-
- ///
- /// Gets the system uptime (in seconds).
- ///
- public double Uptime
- {
- get
- {
- try
- {
- if (File.Exists(UptimeFilePath) == false) return 0;
- var parts = File.ReadAllText(UptimeFilePath).Trim().Split(new[] { ' ' }, StringSplitOptions.RemoveEmptyEntries);
- if (parts.Length >= 1 && float.TryParse(parts[0], out var result))
- return result;
- }
- catch
- {
- /* Ignore */
- }
-
- return 0;
- }
- }
-
- ///
- /// Gets the uptime in TimeSpan.
- ///
- public TimeSpan UptimeTimeSpan => TimeSpan.FromSeconds(Uptime);
-
- ///
- /// Placeholder for processor index
- ///
- private string Processor { get; set; }
-
- ///
- /// Returns a that represents this instance.
- ///
- ///
- /// A that represents this instance.
- ///
- public override string ToString()
- {
- var properties = typeof(SystemInfo).GetTypeInfo().GetProperties(BindingFlags.Instance | BindingFlags.Public)
- .Where(p => p.CanRead && (
- p.PropertyType == typeof(string) ||
- p.PropertyType == typeof(string[]) ||
- p.PropertyType == typeof(int) ||
- p.PropertyType == typeof(bool) ||
- p.PropertyType == typeof(TimeSpan)))
- .ToArray();
-
- var properyValues = new List
- {
+ /// Could not initialize the GPIO controller
+ private SystemInfo() {
+ #region Obtain and format a property dictionary
+
+ PropertyInfo[] properties =
+ typeof(SystemInfo).GetTypeInfo()
+ .GetProperties(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic)
+ .Where(
+ p =>
+ p.CanWrite && p.CanRead &&
+ (p.PropertyType == typeof(String) || p.PropertyType == typeof(String[])))
+ .ToArray();
+ Dictionary propDictionary = new Dictionary(StringComparer);
+
+ foreach(PropertyInfo prop in properties) {
+ propDictionary[prop.Name.Replace(" ", String.Empty).ToLowerInvariant().Trim()] = prop;
+ }
+
+ #endregion
+
+ #region Extract CPU information
+
+ if(File.Exists(CpuInfoFilePath)) {
+ String[] cpuInfoLines = File.ReadAllLines(CpuInfoFilePath);
+
+ foreach(String line in cpuInfoLines) {
+ String[] lineParts = line.Split(new[] { ':' }, 2);
+ if(lineParts.Length != 2) {
+ continue;
+ }
+
+ String propertyKey = lineParts[0].Trim().Replace(" ", String.Empty);
+ String propertyStringValue = lineParts[1].Trim();
+
+ if(!propDictionary.ContainsKey(propertyKey)) {
+ continue;
+ }
+
+ PropertyInfo property = propDictionary[propertyKey];
+ if(property.PropertyType == typeof(String)) {
+ property.SetValue(this, propertyStringValue);
+ } else if(property.PropertyType == typeof(String[])) {
+ String[] propertyArrayAvalue = propertyStringValue.Split(' ');
+ property.SetValue(this, propertyArrayAvalue);
+ }
+ }
+ }
+
+ #endregion
+
+ #region Extract Memory Information
+
+ if(File.Exists(MemInfoFilePath)) {
+ String[] memInfoLines = File.ReadAllLines(MemInfoFilePath);
+ foreach(String line in memInfoLines) {
+ String[] lineParts = line.Split(new[] { ':' }, 2);
+ if(lineParts.Length != 2) {
+ continue;
+ }
+
+ if(lineParts[0].ToLowerInvariant().Trim().Equals("memtotal") == false) {
+ continue;
+ }
+
+ String memKb = lineParts[1].ToLowerInvariant().Trim().Replace("kb", String.Empty).Trim();
+
+ if(Int32.TryParse(memKb, out Int32 parsedMem)) {
+ this.InstalledRam = parsedMem * 1024;
+ break;
+ }
+ }
+ }
+
+ #endregion
+
+ #region Board Version and Form Factor
+
+ try {
+ if(String.IsNullOrWhiteSpace(this.Revision) == false &&
+ Int32.TryParse(
+ this.Revision.ToUpperInvariant(),
+ NumberStyles.HexNumber,
+ CultureInfo.InvariantCulture,
+ out Int32 boardVersion)) {
+ this.RaspberryPiVersion = PiVersion.Unknown;
+ if(Enum.GetValues(typeof(PiVersion)).Cast().Contains(boardVersion)) {
+ this.RaspberryPiVersion = (PiVersion)boardVersion;
+ }
+ }
+
+ this.WiringPiBoardRevision = WiringPi.PiBoardRev();
+ } catch {
+ /* Ignore */
+ }
+
+ #endregion
+
+ #region Version Information
+
+ {
+ String[] libParts = WiringPi.WiringPiLibrary.Split('.');
+ Int32 major = Int32.Parse(libParts[libParts.Length - 2]);
+ Int32 minor = Int32.Parse(libParts[libParts.Length - 1]);
+ Version version = new Version(major, minor);
+ this.WiringPiVersion = version;
+ }
+
+ #endregion
+
+ #region Extract OS Info
+
+ try {
+ _ = Standard.Uname(out SystemName unameInfo);
+ this.OperatingSystem = new OsInfo {
+ DomainName = unameInfo.DomainName,
+ Machine = unameInfo.Machine,
+ NodeName = unameInfo.NodeName,
+ Release = unameInfo.Release,
+ SysName = unameInfo.SysName,
+ Version = unameInfo.Version
+ };
+ } catch {
+ this.OperatingSystem = new OsInfo();
+ }
+
+ #endregion
+ }
+
+ ///
+ /// Gets the wiring pi library version.
+ ///
+ public Version WiringPiVersion {
+ get;
+ }
+
+ ///
+ /// Gets the OS information.
+ ///
+ ///
+ /// The os information.
+ ///
+ public OsInfo OperatingSystem {
+ get;
+ }
+
+ ///
+ /// Gets the Raspberry Pi version.
+ ///
+ public PiVersion RaspberryPiVersion {
+ get;
+ }
+
+ ///
+ /// Gets the Wiring Pi board revision (1 or 2).
+ ///
+ ///
+ /// The wiring pi board revision.
+ ///
+ public Int32 WiringPiBoardRevision {
+ get;
+ }
+
+ ///
+ /// Gets the number of processor cores.
+ ///
+ public Int32 ProcessorCount => Int32.TryParse(this.Processor, out Int32 outIndex) ? outIndex + 1 : 0;
+
+ ///
+ /// Gets the installed ram in bytes.
+ ///
+ public Int32 InstalledRam {
+ get;
+ }
+
+ ///
+ /// Gets a value indicating whether this CPU is little endian.
+ ///
+ public Boolean IsLittleEndian => BitConverter.IsLittleEndian;
+
+ ///
+ /// Gets the CPU model name.
+ ///
+ public String ModelName {
+ get; private set;
+ }
+
+ ///
+ /// Gets a list of supported CPU features.
+ ///
+ public String[] Features {
+ get; private set;
+ }
+
+ ///
+ /// Gets the CPU implementer hex code.
+ ///
+ public String CpuImplementer {
+ get; private set;
+ }
+
+ ///
+ /// Gets the CPU architecture code.
+ ///
+ public String CpuArchitecture {
+ get; private set;
+ }
+
+ ///
+ /// Gets the CPU variant code.
+ ///
+ public String CpuVariant {
+ get; private set;
+ }
+
+ ///
+ /// Gets the CPU part code.
+ ///
+ public String CpuPart {
+ get; private set;
+ }
+
+ ///
+ /// Gets the CPU revision code.
+ ///
+ public String CpuRevision {
+ get; private set;
+ }
+
+ ///
+ /// Gets the hardware model number.
+ ///
+ public String Hardware {
+ get; private set;
+ }
+
+ ///
+ /// Gets the hardware revision number.
+ ///
+ public String Revision {
+ get; private set;
+ }
+
+ ///
+ /// Gets the serial number.
+ ///
+ public String Serial {
+ get; private set;
+ }
+
+ ///
+ /// Gets the system uptime (in seconds).
+ ///
+ public Double Uptime {
+ get {
+ try {
+ if(File.Exists(UptimeFilePath) == false) {
+ return 0;
+ }
+
+ String[] parts = File.ReadAllText(UptimeFilePath).Trim().Split(new[] { ' ' }, StringSplitOptions.RemoveEmptyEntries);
+ if(parts.Length >= 1 && Single.TryParse(parts[0], out Single result)) {
+ return result;
+ }
+ } catch {
+ /* Ignore */
+ }
+
+ return 0;
+ }
+ }
+
+ ///
+ /// Gets the uptime in TimeSpan.
+ ///
+ public TimeSpan UptimeTimeSpan => TimeSpan.FromSeconds(this.Uptime);
+
+ ///
+ /// Placeholder for processor index
+ ///
+ private String Processor {
+ get; set;
+ }
+
+ ///
+ /// Returns a that represents this instance.
+ ///
+ ///
+ /// A that represents this instance.
+ ///
+ public override String ToString() {
+ PropertyInfo[] properties = typeof(SystemInfo).GetTypeInfo().GetProperties(BindingFlags.Instance | BindingFlags.Public)
+ .Where(p => p.CanRead && (
+ p.PropertyType == typeof(String) ||
+ p.PropertyType == typeof(String[]) ||
+ p.PropertyType == typeof(Int32) ||
+ p.PropertyType == typeof(Boolean) ||
+ p.PropertyType == typeof(TimeSpan)))
+ .ToArray();
+
+ List properyValues = new List
+ {
"System Information",
- $"\t{nameof(WiringPiVersion),-22}: {WiringPiVersion}",
- $"\t{nameof(RaspberryPiVersion),-22}: {RaspberryPiVersion}"
- };
-
- foreach (var property in properties)
- {
- if (property.PropertyType != typeof(string[]))
- {
- properyValues.Add($"\t{property.Name,-22}: {property.GetValue(this)}");
- }
- else if (property.GetValue(this) is string[] allValues)
- {
- var concatValues = string.Join(" ", allValues);
- properyValues.Add($"\t{property.Name,-22}: {concatValues}");
- }
- }
-
- return string.Join(Environment.NewLine, properyValues.ToArray());
- }
- }
+ $"\t{nameof(this.WiringPiVersion),-22}: {this.WiringPiVersion}",
+ $"\t{nameof(this.RaspberryPiVersion),-22}: {this.RaspberryPiVersion}"
+ };
+
+ foreach(PropertyInfo property in properties) {
+ if(property.PropertyType != typeof(String[])) {
+ properyValues.Add($"\t{property.Name,-22}: {property.GetValue(this)}");
+ } else if(property.GetValue(this) is String[] allValues) {
+ String concatValues = String.Join(" ", allValues);
+ properyValues.Add($"\t{property.Name,-22}: {concatValues}");
+ }
+ }
+
+ return String.Join(Environment.NewLine, properyValues.ToArray());
+ }
+ }
}
\ No newline at end of file
diff --git a/Unosquare.RaspberryIO/Computer/WirelessNetworkInfo.cs b/Unosquare.RaspberryIO/Computer/WirelessNetworkInfo.cs
index 71d0cb9..f820698 100644
--- a/Unosquare.RaspberryIO/Computer/WirelessNetworkInfo.cs
+++ b/Unosquare.RaspberryIO/Computer/WirelessNetworkInfo.cs
@@ -1,23 +1,29 @@
-namespace Unosquare.RaspberryIO.Computer
-{
+using System;
+
+namespace Unosquare.RaspberryIO.Computer {
+ ///
+ /// Represents a wireless network information
+ ///
+ public class WirelessNetworkInfo {
///
- /// Represents a wireless network information
+ /// Gets the ESSID of the Wireless network.
///
- public class WirelessNetworkInfo
- {
- ///
- /// Gets the ESSID of the Wireless network.
- ///
- public string Name { get; internal set; }
-
- ///
- /// Gets the network quality.
- ///
- public string Quality { get; internal set; }
-
- ///
- /// Gets a value indicating whether this instance is encrypted.
- ///
- public bool IsEncrypted { get; internal set; }
- }
+ public String Name {
+ get; internal set;
+ }
+
+ ///
+ /// Gets the network quality.
+ ///
+ public String Quality {
+ get; internal set;
+ }
+
+ ///
+ /// Gets a value indicating whether this instance is encrypted.
+ ///
+ public Boolean IsEncrypted {
+ get; internal set;
+ }
+ }
}
diff --git a/Unosquare.RaspberryIO/Gpio/Enums.cs b/Unosquare.RaspberryIO/Gpio/Enums.cs
index 95e0032..5f7a7e7 100644
--- a/Unosquare.RaspberryIO/Gpio/Enums.cs
+++ b/Unosquare.RaspberryIO/Gpio/Enums.cs
@@ -1,579 +1,566 @@
-namespace Unosquare.RaspberryIO.Gpio
-{
+namespace Unosquare.RaspberryIO.Gpio {
+ ///
+ /// Defines the different drive modes of a GPIO pin
+ ///
+ public enum GpioPinDriveMode {
///
- /// Defines the different drive modes of a GPIO pin
+ /// Input drive mode (perform reads)
///
- public enum GpioPinDriveMode
- {
- ///
- /// Input drive mode (perform reads)
- ///
- Input = 0,
-
- ///
- /// Output drive mode (perform writes)
- ///
- Output = 1,
-
- ///
- /// PWM output mode (only certain pins support this -- 2 of them at the moment)
- ///
- PwmOutput = 2,
-
- ///
- /// GPIO Clock output mode (only a pin supports this at this time)
- ///
- GpioClock = 3
- }
-
+ Input = 0,
+
///
- /// The GPIO pin resistor mode. This is used on input pins so that their
- /// lines are not floating
+ /// Output drive mode (perform writes)
///
- public enum GpioPinResistorPullMode
- {
- ///
- /// Pull resistor not active. Line floating
- ///
- Off = 0,
-
- ///
- /// Pull resistor sets a default value of 0 on no-connects
- ///
- PullDown = 1,
-
- ///
- /// Pull resistor sets a default value of 1 on no-connects
- ///
- PullUp = 2,
- }
-
+ Output = 1,
+
///
- /// The PWM mode.
+ /// PWM output mode (only certain pins support this -- 2 of them at the moment)
///
- public enum PwmMode
- {
- ///
- /// PWM pulses are sent using mark-sign patterns (old school)
- ///
- MarkSign = 0,
-
- ///
- /// PWM pulses are sent as a balanced signal (default, newer mode)
- ///
- Balanced = 1,
- }
-
+ PwmOutput = 2,
+
///
- /// Defines the different edge detection modes for pin interrupts
+ /// GPIO Clock output mode (only a pin supports this at this time)
///
- public enum EdgeDetection
- {
- ///
- /// Assumes edge detection was already setup externally
- ///
- ExternalSetup = 0,
-
- ///
- /// Falling Edge
- ///
- FallingEdge = 1,
-
- ///
- /// Rising edge
- ///
- RisingEdge = 2,
-
- ///
- /// Both, rising and falling edges
- ///
- RisingAndFallingEdges = 3
- }
-
+ GpioClock = 3
+ }
+
+ ///
+ /// The GPIO pin resistor mode. This is used on input pins so that their
+ /// lines are not floating
+ ///
+ public enum GpioPinResistorPullMode {
///
- /// Defines the GPIO Pin values 0 for low, 1 for High
+ /// Pull resistor not active. Line floating
///
- public enum GpioPinValue
- {
- ///
- /// Digital high
- ///
- High = 1,
-
- ///
- /// Digital low
- ///
- Low = 0
- }
-
+ Off = 0,
+
///
- /// Defines the Header connectors available
+ /// Pull resistor sets a default value of 0 on no-connects
///
- public enum GpioHeader
- {
- ///
- /// Not defined
- ///
- None,
-
- ///
- /// The P1 connector (main connector)
- ///
- P1,
-
- ///
- /// The P5 connector (auxiliary, not commonly used)
- ///
- P5,
- }
-
+ PullDown = 1,
+
///
- /// Defines all the available Wiring Pi Pin Numbers
+ /// Pull resistor sets a default value of 1 on no-connects
///
- public enum WiringPiPin
- {
- ///
- /// The unknown
- ///
- Unknown = -1,
-
- ///
- /// The pin00
- ///
- Pin00 = 0,
-
- ///
- /// The pin01
- ///
- Pin01 = 1,
-
- ///
- /// The pin02
- ///
- Pin02 = 2,
-
- ///
- /// The pin03
- ///
- Pin03 = 3,
-
- ///
- /// The pin04
- ///
- Pin04 = 4,
-
- ///
- /// The pin05
- ///
- Pin05 = 5,
-
- ///
- /// The pin06
- ///
- Pin06 = 6,
-
- ///
- /// The pin07
- ///
- Pin07 = 7,
-
- ///
- /// The pin08
- ///
- Pin08 = 8,
-
- ///
- /// The pin09
- ///
- Pin09 = 9,
-
- ///
- /// The pin10
- ///
- Pin10 = 10,
-
- ///
- /// The pin11
- ///
- Pin11 = 11,
-
- ///
- /// The pin12
- ///
- Pin12 = 12,
-
- ///
- /// The pin13
- ///
- Pin13 = 13,
-
- ///
- /// The pin14
- ///
- Pin14 = 14,
-
- ///
- /// The pin15
- ///
- Pin15 = 15,
-
- ///
- /// The pin16
- ///
- Pin16 = 16,
-
- ///
- /// The pin17
- ///
- Pin17 = 17,
-
- ///
- /// The pin18
- ///
- Pin18 = 18,
-
- ///
- /// The pin19
- ///
- Pin19 = 19,
-
- ///
- /// The pin20
- ///
- Pin20 = 20,
-
- ///
- /// The pin21
- ///
- Pin21 = 21,
-
- ///
- /// The pin22
- ///
- Pin22 = 22,
-
- ///
- /// The pin23
- ///
- Pin23 = 23,
-
- ///
- /// The pin24
- ///
- Pin24 = 24,
-
- ///
- /// The pin25
- ///
- Pin25 = 25,
-
- ///
- /// The pin26
- ///
- Pin26 = 26,
-
- ///
- /// The pin27
- ///
- Pin27 = 27,
-
- ///
- /// The pin28
- ///
- Pin28 = 28,
-
- ///
- /// The pin29
- ///
- Pin29 = 29,
-
- ///
- /// The pin30
- ///
- Pin30 = 30,
-
- ///
- /// The pin31
- ///
- Pin31 = 31,
- }
-
+ PullUp = 2,
+ }
+
+ ///
+ /// The PWM mode.
+ ///
+ public enum PwmMode {
///
- /// Enumerates the different pins on the P1 Header
- /// as commonly referenced by Raspberry Pi Documentation.
- /// Enumeration values correspond to the physical pin number.
+ /// PWM pulses are sent using mark-sign patterns (old school)
///
- public enum P1
- {
- ///
- /// Header P1, GPIO Pin 02
- ///
- Gpio02 = 3,
-
- ///
- /// Header P1, GPIO Pin 03
- ///
- Gpio03 = 5,
-
- ///
- /// Header P1, GPIO Pin 04
- ///
- Gpio04 = 7,
-
- ///
- /// Header P1, GPIO Pin 17
- ///
- Gpio17 = 11,
-
- ///
- /// Header P1, GPIO Pin 27
- ///
- Gpio27 = 13,
-
- ///
- /// Header P1, GPIO Pin 22
- ///
- Gpio22 = 15,
-
- ///
- /// Header P1, GPIO Pin 10
- ///
- Gpio10 = 19,
-
- ///
- /// Header P1, GPIO Pin 09
- ///
- Gpio09 = 21,
-
- ///
- /// Header P1, GPIO Pin 11
- ///
- Gpio11 = 23,
-
- ///
- /// Header P1, GPIO Pin 05
- ///
- Gpio05 = 29,
-
- ///
- /// Header P1, GPIO Pin 06
- ///
- Gpio06 = 31,
-
- ///
- /// Header P1, GPIO Pin 13
- ///
- Gpio13 = 33,
-
- ///
- /// Header P1, GPIO Pin 19
- ///
- Gpio19 = 35,
-
- ///
- /// Header P1, GPIO Pin 26
- ///
- Gpio26 = 37,
-
- ///
- /// Header P1, GPIO Pin 14
- ///
- Gpio14 = 8,
-
- ///
- /// Header P1, GPIO Pin 15
- ///
- Gpio15 = 10,
-
- ///
- /// Header P1, GPIO Pin 18
- ///
- Gpio18 = 12,
-
- ///
- /// Header P1, GPIO Pin 23
- ///
- Gpio23 = 16,
-
- ///
- /// Header P1, GPIO Pin 24
- ///
- Gpio24 = 18,
-
- ///
- /// Header P1, GPIO Pin 25
- ///
- Gpio25 = 22,
-
- ///
- /// Header P1, GPIO Pin 08
- ///
- Gpio08 = 24,
-
- ///
- /// Header P1, GPIO Pin 07
- ///
- Gpio07 = 26,
-
- ///
- /// Header P1, GPIO Pin 12
- ///
- Gpio12 = 32,
-
- ///
- /// Header P1, GPIO Pin 16
- ///
- Gpio16 = 36,
-
- ///
- /// Header P1, GPIO Pin 20
- ///
- Gpio20 = 38,
-
- ///
- /// Header P1, GPIO Pin 21
- ///
- Gpio21 = 40
- }
-
+ MarkSign = 0,
+
///
- /// Enumerates the different pins on the P5 Header
- /// as commonly referenced by Raspberry Pi documentation.
- /// Enumeration values correspond to the physical pin number.
+ /// PWM pulses are sent as a balanced signal (default, newer mode)
///
- public enum P5
- {
- ///
- /// Header P5, GPIO Pin 28
- ///
- Gpio28 = 3,
-
- ///
- /// Header P5, GPIO Pin 29
- ///
- Gpio29 = 4,
-
- ///
- /// Header P5, GPIO Pin 30
- ///
- Gpio30 = 5,
-
- ///
- /// Header P5, GPIO Pin 31
- ///
- Gpio31 = 6
- }
-
+ Balanced = 1,
+ }
+
+ ///
+ /// Defines the different edge detection modes for pin interrupts
+ ///
+ public enum EdgeDetection {
///
- /// Defines the different pin capabilities
+ /// Assumes edge detection was already setup externally
///
- public enum PinCapability
- {
- ///
- /// General Purpose capability: Digital and Analog Read/Write
- ///
- GP,
-
- ///
- /// General Purpose Clock (not PWM)
- ///
- GPCLK,
-
- ///
- /// i2c data channel
- ///
- I2CSDA,
-
- ///
- /// i2c clock channel
- ///
- I2CSCL,
-
- ///
- /// SPI Master Out, Slave In channel
- ///
- SPIMOSI,
-
- ///
- /// SPI Master In, Slave Out channel
- ///
- SPIMISO,
-
- ///
- /// SPI Clock channel
- ///
- SPICLK,
-
- ///
- /// SPI Chip Select Channel
- ///
- SPICS,
-
- ///
- /// UART Request to Send Channel
- ///
- UARTRTS,
-
- ///
- /// UART Transmit Channel
- ///
- UARTTXD,
-
- ///
- /// UART Receive Channel
- ///
- UARTRXD,
-
- ///
- /// Hardware Pule Width Modulation
- ///
- PWM
- }
-
+ ExternalSetup = 0,
+
///
- /// Defines the SPI channel numbers
+ /// Falling Edge
///
- internal enum SpiChannelNumber
- {
- ///
- /// The channel 0
- ///
- Channel0 = 0,
-
- ///
- /// The channel 1
- ///
- Channel1 = 1,
- }
-
+ FallingEdge = 1,
+
///
- /// Defines GPIO controller initialization modes
+ /// Rising edge
///
- internal enum ControllerMode
- {
- ///
- /// The not initialized
- ///
- NotInitialized,
-
- ///
- /// The direct with wiring pi pins
- ///
- DirectWithWiringPiPins,
-
- ///
- /// The direct with BCM pins
- ///
- DirectWithBcmPins,
-
- ///
- /// The direct with header pins
- ///
- DirectWithHeaderPins,
-
- ///
- /// The file stream with hardware pins
- ///
- FileStreamWithHardwarePins,
- }
+ RisingEdge = 2,
+
+ ///
+ /// Both, rising and falling edges
+ ///
+ RisingAndFallingEdges = 3
+ }
+
+ ///
+ /// Defines the GPIO Pin values 0 for low, 1 for High
+ ///
+ public enum GpioPinValue {
+ ///
+ /// Digital high
+ ///
+ High = 1,
+
+ ///
+ /// Digital low
+ ///
+ Low = 0
+ }
+
+ ///
+ /// Defines the Header connectors available
+ ///
+ public enum GpioHeader {
+ ///
+ /// Not defined
+ ///
+ None,
+
+ ///
+ /// The P1 connector (main connector)
+ ///
+ P1,
+
+ ///
+ /// The P5 connector (auxiliary, not commonly used)
+ ///
+ P5,
+ }
+
+ ///
+ /// Defines all the available Wiring Pi Pin Numbers
+ ///
+ public enum WiringPiPin {
+ ///
+ /// The unknown
+ ///
+ Unknown = -1,
+
+ ///
+ /// The pin00
+ ///
+ Pin00 = 0,
+
+ ///
+ /// The pin01
+ ///
+ Pin01 = 1,
+
+ ///
+ /// The pin02
+ ///
+ Pin02 = 2,
+
+ ///
+ /// The pin03
+ ///
+ Pin03 = 3,
+
+ ///
+ /// The pin04
+ ///
+ Pin04 = 4,
+
+ ///
+ /// The pin05
+ ///
+ Pin05 = 5,
+
+ ///
+ /// The pin06
+ ///
+ Pin06 = 6,
+
+ ///
+ /// The pin07
+ ///
+ Pin07 = 7,
+
+ ///
+ /// The pin08
+ ///
+ Pin08 = 8,
+
+ ///
+ /// The pin09
+ ///
+ Pin09 = 9,
+
+ ///
+ /// The pin10
+ ///
+ Pin10 = 10,
+
+ ///
+ /// The pin11
+ ///
+ Pin11 = 11,
+
+ ///
+ /// The pin12
+ ///
+ Pin12 = 12,
+
+ ///
+ /// The pin13
+ ///
+ Pin13 = 13,
+
+ ///
+ /// The pin14
+ ///
+ Pin14 = 14,
+
+ ///
+ /// The pin15
+ ///
+ Pin15 = 15,
+
+ ///
+ /// The pin16
+ ///
+ Pin16 = 16,
+
+ ///
+ /// The pin17
+ ///
+ Pin17 = 17,
+
+ ///
+ /// The pin18
+ ///
+ Pin18 = 18,
+
+ ///
+ /// The pin19
+ ///
+ Pin19 = 19,
+
+ ///
+ /// The pin20
+ ///
+ Pin20 = 20,
+
+ ///
+ /// The pin21
+ ///
+ Pin21 = 21,
+
+ ///
+ /// The pin22
+ ///
+ Pin22 = 22,
+
+ ///
+ /// The pin23
+ ///
+ Pin23 = 23,
+
+ ///
+ /// The pin24
+ ///
+ Pin24 = 24,
+
+ ///
+ /// The pin25
+ ///
+ Pin25 = 25,
+
+ ///
+ /// The pin26
+ ///
+ Pin26 = 26,
+
+ ///
+ /// The pin27
+ ///
+ Pin27 = 27,
+
+ ///
+ /// The pin28
+ ///
+ Pin28 = 28,
+
+ ///
+ /// The pin29
+ ///
+ Pin29 = 29,
+
+ ///
+ /// The pin30
+ ///
+ Pin30 = 30,
+
+ ///
+ /// The pin31
+ ///
+ Pin31 = 31,
+ }
+
+ ///
+ /// Enumerates the different pins on the P1 Header
+ /// as commonly referenced by Raspberry Pi Documentation.
+ /// Enumeration values correspond to the physical pin number.
+ ///
+ public enum P1 {
+ ///
+ /// Header P1, GPIO Pin 02
+ ///
+ Gpio02 = 3,
+
+ ///
+ /// Header P1, GPIO Pin 03
+ ///
+ Gpio03 = 5,
+
+ ///
+ /// Header P1, GPIO Pin 04
+ ///
+ Gpio04 = 7,
+
+ ///
+ /// Header P1, GPIO Pin 17
+ ///
+ Gpio17 = 11,
+
+ ///
+ /// Header P1, GPIO Pin 27
+ ///
+ Gpio27 = 13,
+
+ ///
+ /// Header P1, GPIO Pin 22
+ ///
+ Gpio22 = 15,
+
+ ///
+ /// Header P1, GPIO Pin 10
+ ///
+ Gpio10 = 19,
+
+ ///
+ /// Header P1, GPIO Pin 09
+ ///
+ Gpio09 = 21,
+
+ ///
+ /// Header P1, GPIO Pin 11
+ ///
+ Gpio11 = 23,
+
+ ///
+ /// Header P1, GPIO Pin 05
+ ///
+ Gpio05 = 29,
+
+ ///
+ /// Header P1, GPIO Pin 06
+ ///
+ Gpio06 = 31,
+
+ ///
+ /// Header P1, GPIO Pin 13
+ ///
+ Gpio13 = 33,
+
+ ///
+ /// Header P1, GPIO Pin 19
+ ///
+ Gpio19 = 35,
+
+ ///
+ /// Header P1, GPIO Pin 26
+ ///
+ Gpio26 = 37,
+
+ ///
+ /// Header P1, GPIO Pin 14
+ ///
+ Gpio14 = 8,
+
+ ///
+ /// Header P1, GPIO Pin 15
+ ///
+ Gpio15 = 10,
+
+ ///
+ /// Header P1, GPIO Pin 18
+ ///
+ Gpio18 = 12,
+
+ ///
+ /// Header P1, GPIO Pin 23
+ ///
+ Gpio23 = 16,
+
+ ///
+ /// Header P1, GPIO Pin 24
+ ///
+ Gpio24 = 18,
+
+ ///
+ /// Header P1, GPIO Pin 25
+ ///
+ Gpio25 = 22,
+
+ ///
+ /// Header P1, GPIO Pin 08
+ ///
+ Gpio08 = 24,
+
+ ///
+ /// Header P1, GPIO Pin 07
+ ///
+ Gpio07 = 26,
+
+ ///
+ /// Header P1, GPIO Pin 12
+ ///
+ Gpio12 = 32,
+
+ ///
+ /// Header P1, GPIO Pin 16
+ ///
+ Gpio16 = 36,
+
+ ///
+ /// Header P1, GPIO Pin 20
+ ///
+ Gpio20 = 38,
+
+ ///
+ /// Header P1, GPIO Pin 21
+ ///
+ Gpio21 = 40
+ }
+
+ ///
+ /// Enumerates the different pins on the P5 Header
+ /// as commonly referenced by Raspberry Pi documentation.
+ /// Enumeration values correspond to the physical pin number.
+ ///
+ public enum P5 {
+ ///
+ /// Header P5, GPIO Pin 28
+ ///
+ Gpio28 = 3,
+
+ ///
+ /// Header P5, GPIO Pin 29
+ ///
+ Gpio29 = 4,
+
+ ///
+ /// Header P5, GPIO Pin 30
+ ///
+ Gpio30 = 5,
+
+ ///
+ /// Header P5, GPIO Pin 31
+ ///
+ Gpio31 = 6
+ }
+
+ ///
+ /// Defines the different pin capabilities
+ ///
+ public enum PinCapability {
+ ///
+ /// General Purpose capability: Digital and Analog Read/Write
+ ///
+ GP,
+
+ ///
+ /// General Purpose Clock (not PWM)
+ ///
+ GPCLK,
+
+ ///
+ /// i2c data channel
+ ///
+ I2CSDA,
+
+ ///
+ /// i2c clock channel
+ ///
+ I2CSCL,
+
+ ///
+ /// SPI Master Out, Slave In channel
+ ///
+ SPIMOSI,
+
+ ///
+ /// SPI Master In, Slave Out channel
+ ///
+ SPIMISO,
+
+ ///
+ /// SPI Clock channel
+ ///
+ SPICLK,
+
+ ///
+ /// SPI Chip Select Channel
+ ///
+ SPICS,
+
+ ///
+ /// UART Request to Send Channel
+ ///
+ UARTRTS,
+
+ ///
+ /// UART Transmit Channel
+ ///
+ UARTTXD,
+
+ ///
+ /// UART Receive Channel
+ ///
+ UARTRXD,
+
+ ///
+ /// Hardware Pule Width Modulation
+ ///
+ PWM
+ }
+
+ ///
+ /// Defines the SPI channel numbers
+ ///
+ internal enum SpiChannelNumber {
+ ///
+ /// The channel 0
+ ///
+ Channel0 = 0,
+
+ ///
+ /// The channel 1
+ ///
+ Channel1 = 1,
+ }
+
+ ///
+ /// Defines GPIO controller initialization modes
+ ///
+ internal enum ControllerMode {
+ ///
+ /// The not initialized
+ ///
+ NotInitialized,
+
+ ///
+ /// The direct with wiring pi pins
+ ///
+ DirectWithWiringPiPins,
+
+ ///
+ /// The direct with BCM pins
+ ///
+ DirectWithBcmPins,
+
+ ///
+ /// The direct with header pins
+ ///
+ DirectWithHeaderPins,
+
+ ///
+ /// The file stream with hardware pins
+ ///
+ FileStreamWithHardwarePins,
+ }
}
\ No newline at end of file
diff --git a/Unosquare.RaspberryIO/Gpio/GpioController.cs b/Unosquare.RaspberryIO/Gpio/GpioController.cs
index 48e6a7e..99f6d09 100644
--- a/Unosquare.RaspberryIO/Gpio/GpioController.cs
+++ b/Unosquare.RaspberryIO/Gpio/GpioController.cs
@@ -1,594 +1,572 @@
-namespace Unosquare.RaspberryIO.Gpio
-{
- using Native;
- using Swan;
- using Swan.Abstractions;
- using System;
- using System.Collections;
- using System.Collections.Generic;
- using System.Collections.ObjectModel;
- using System.Linq;
- using System.Threading.Tasks;
-
+using Unosquare.RaspberryIO.Native;
+using Unosquare.Swan;
+using Unosquare.Swan.Abstractions;
+using System;
+using System.Collections;
+using System.Collections.Generic;
+using System.Collections.ObjectModel;
+using System.Linq;
+using System.Threading.Tasks;
+
+namespace Unosquare.RaspberryIO.Gpio {
+ ///
+ /// Represents a singleton of the Raspberry Pi GPIO controller
+ /// as an IReadOnlyCollection of GpioPins
+ /// Low level operations are accomplished by using the Wiring Pi library.
+ /// Use the Instance property to access the singleton's instance
+ ///
+ public sealed class GpioController : SingletonBase, IReadOnlyCollection {
+ #region Private Declarations
+
+ private const String WiringPiCodesEnvironmentVariable = "WIRINGPI_CODES";
+ private static readonly Object SyncRoot = new Object();
+ private readonly Dictionary _pinsByWiringPiPinNumber = new Dictionary();
+
+ #endregion
+
+ #region Constructors and Initialization
+
///
- /// Represents a singleton of the Raspberry Pi GPIO controller
- /// as an IReadOnlyCollection of GpioPins
- /// Low level operations are accomplished by using the Wiring Pi library.
- /// Use the Instance property to access the singleton's instance
+ /// Prevents a default instance of the class from being created.
+ /// It in turn initializes the controller and registers the pin -- in that order.
///
- public sealed class GpioController : SingletonBase, IReadOnlyCollection
- {
- #region Private Declarations
-
- private const string WiringPiCodesEnvironmentVariable = "WIRINGPI_CODES";
- private static readonly object SyncRoot = new object();
- private readonly ReadOnlyCollection _pinCollection;
- private readonly ReadOnlyDictionary _headerP1Pins;
- private readonly ReadOnlyDictionary _headerP5Pins;
- private readonly Dictionary _pinsByWiringPiPinNumber = new Dictionary();
-
- #endregion
-
- #region Constructors and Initialization
-
- ///
- /// Prevents a default instance of the class from being created.
- /// It in turn initializes the controller and registers the pin -- in that order.
- ///
- /// Unable to initialize the GPIO controller.
- private GpioController()
- {
- if (_pinCollection != null)
- return;
-
- if (IsInitialized == false)
- {
- var initResult = Initialize(ControllerMode.DirectWithWiringPiPins);
- if (initResult == false)
- throw new Exception("Unable to initialize the GPIO controller.");
- }
-
- #region Pin Registration (32 WiringPi Pins)
-
- RegisterPin(GpioPin.Pin00.Value);
- RegisterPin(GpioPin.Pin01.Value);
- RegisterPin(GpioPin.Pin02.Value);
- RegisterPin(GpioPin.Pin03.Value);
- RegisterPin(GpioPin.Pin04.Value);
- RegisterPin(GpioPin.Pin05.Value);
- RegisterPin(GpioPin.Pin06.Value);
- RegisterPin(GpioPin.Pin07.Value);
- RegisterPin(GpioPin.Pin08.Value);
- RegisterPin(GpioPin.Pin09.Value);
- RegisterPin(GpioPin.Pin10.Value);
- RegisterPin(GpioPin.Pin11.Value);
- RegisterPin(GpioPin.Pin12.Value);
- RegisterPin(GpioPin.Pin13.Value);
- RegisterPin(GpioPin.Pin14.Value);
- RegisterPin(GpioPin.Pin15.Value);
- RegisterPin(GpioPin.Pin16.Value);
- RegisterPin(GpioPin.Pin17.Value);
- RegisterPin(GpioPin.Pin18.Value);
- RegisterPin(GpioPin.Pin19.Value);
- RegisterPin(GpioPin.Pin20.Value);
- RegisterPin(GpioPin.Pin21.Value);
- RegisterPin(GpioPin.Pin22.Value);
- RegisterPin(GpioPin.Pin23.Value);
- RegisterPin(GpioPin.Pin24.Value);
- RegisterPin(GpioPin.Pin25.Value);
- RegisterPin(GpioPin.Pin26.Value);
- RegisterPin(GpioPin.Pin27.Value);
- RegisterPin(GpioPin.Pin28.Value);
- RegisterPin(GpioPin.Pin29.Value);
- RegisterPin(GpioPin.Pin30.Value);
- RegisterPin(GpioPin.Pin31.Value);
-
- #endregion
-
- _pinCollection = new ReadOnlyCollection(_pinsByWiringPiPinNumber.Values.ToArray());
- var headerP1 = new Dictionary(_pinCollection.Count);
- var headerP5 = new Dictionary(_pinCollection.Count);
- foreach (var pin in _pinCollection)
- {
- var target = pin.Header == GpioHeader.P1 ? headerP1 : headerP5;
- target[pin.HeaderPinNumber] = pin;
- }
-
- _headerP1Pins = new ReadOnlyDictionary(headerP1);
- _headerP5Pins = new ReadOnlyDictionary(headerP5);
- }
-
- ///
- /// Determines if the underlying GPIO controller has been initialized properly.
- ///
- ///
- /// true if the controller is properly initialized; otherwise, false.
- ///
- public static bool IsInitialized
- {
- get
- {
- lock (SyncRoot)
- {
- return Mode != ControllerMode.NotInitialized;
- }
- }
- }
-
- ///
- /// Gets the number of registered pins in the controller.
- ///
- public int Count => _pinCollection.Count;
-
- #endregion
-
- #region Pin Addressing
-
- ///
- /// Gets the PWM base frequency (in Hz).
- ///
- public int PwmBaseFrequency => 19200000;
-
- ///
- /// Gets a red-only collection of all registered pins.
- ///
- public ReadOnlyCollection Pins => _pinCollection;
-
- ///
- /// Provides all the pins on Header P1 of the Pi as a lookup by physical header pin number.
- /// This header is the main header and it is the one commonly used.
- ///
- public ReadOnlyDictionary HeaderP1 => _headerP1Pins;
-
- ///
- /// Provides all the pins on Header P5 of the Pi as a lookup by physical header pin number.
- /// This header is the secondary header and it is rarely used.
- ///
- public ReadOnlyDictionary HeaderP5 => _headerP5Pins;
-
- #endregion
-
- #region Individual Pin Properties
-
- ///
- /// Provides direct access to Pin known to Wiring Pi (not the pin header number) as Pin 00.
- ///
- public GpioPin Pin00 => GpioPin.Pin00.Value;
-
- ///
- /// Provides direct access to Pin known to Wiring Pi (not the pin header number) as Pin 01.
- ///
- public GpioPin Pin01 => GpioPin.Pin01.Value;
-
- ///
- /// Provides direct access to Pin known to Wiring Pi (not the pin header number) as Pin 02.
- ///
- public GpioPin Pin02 => GpioPin.Pin02.Value;
-
- ///
- /// Provides direct access to Pin known to Wiring Pi (not the pin header number) as Pin 03.
- ///
- public GpioPin Pin03 => GpioPin.Pin03.Value;
-
- ///
- /// Provides direct access to Pin known to Wiring Pi (not the pin header number) as Pin 04.
- ///
- public GpioPin Pin04 => GpioPin.Pin04.Value;
-
- ///
- /// Provides direct access to Pin known to Wiring Pi (not the pin header number) as Pin 05.
- ///
- public GpioPin Pin05 => GpioPin.Pin05.Value;
-
- ///
- /// Provides direct access to Pin known to Wiring Pi (not the pin header number) as Pin 06.
- ///
- public GpioPin Pin06 => GpioPin.Pin06.Value;
-
- ///
- /// Provides direct access to Pin known to Wiring Pi (not the pin header number) as Pin 07.
- ///
- public GpioPin Pin07 => GpioPin.Pin07.Value;
-
- ///
- /// Provides direct access to Pin known to Wiring Pi (not the pin header number) as Pin 08.
- ///
- public GpioPin Pin08 => GpioPin.Pin08.Value;
-
- ///
- /// Provides direct access to Pin known to Wiring Pi (not the pin header number) as Pin 09.
- ///
- public GpioPin Pin09 => GpioPin.Pin09.Value;
-
- ///
- /// Provides direct access to Pin known to Wiring Pi (not the pin header number) as Pin 10.
- ///
- public GpioPin Pin10 => GpioPin.Pin10.Value;
-
- ///
- /// Provides direct access to Pin known to Wiring Pi (not the pin header number) as Pin 11.
- ///
- public GpioPin Pin11 => GpioPin.Pin11.Value;
-
- ///
- /// Provides direct access to Pin known to Wiring Pi (not the pin header number) as Pin 12.
- ///
- public GpioPin Pin12 => GpioPin.Pin12.Value;
-
- ///
- /// Provides direct access to Pin known to Wiring Pi (not the pin header number) as Pin 13.
- ///
- public GpioPin Pin13 => GpioPin.Pin13.Value;
-
- ///
- /// Provides direct access to Pin known to Wiring Pi (not the pin header number) as Pin 14.
- ///
- public GpioPin Pin14 => GpioPin.Pin14.Value;
-
- ///
- /// Provides direct access to Pin known to Wiring Pi (not the pin header number) as Pin 15.
- ///
- public GpioPin Pin15 => GpioPin.Pin15.Value;
-
- ///
- /// Provides direct access to Pin known to Wiring Pi (not the pin header number) as Pin 16.
- ///
- public GpioPin Pin16 => GpioPin.Pin16.Value;
-
- ///
- /// Provides direct access to Pin known to Wiring Pi (not the pin header number) as Pin 17.
- ///
- public GpioPin Pin17 => GpioPin.Pin17.Value;
-
- ///
- /// Provides direct access to Pin known to Wiring Pi (not the pin header number) as Pin 18.
- ///
- public GpioPin Pin18 => GpioPin.Pin18.Value;
-
- ///
- /// Provides direct access to Pin known to Wiring Pi (not the pin header number) as Pin 19.
- ///
- public GpioPin Pin19 => GpioPin.Pin19.Value;
-
- ///
- /// Provides direct access to Pin known to Wiring Pi (not the pin header number) as Pin 20.
- ///
- public GpioPin Pin20 => GpioPin.Pin20.Value;
-
- ///
- /// Provides direct access to Pin known to Wiring Pi (not the pin header number) as Pin 21.
- ///
- public GpioPin Pin21 => GpioPin.Pin21.Value;
-
- ///
- /// Provides direct access to Pin known to Wiring Pi (not the pin header number) as Pin 22.
- ///
- public GpioPin Pin22 => GpioPin.Pin22.Value;
-
- ///
- /// Provides direct access to Pin known to Wiring Pi (not the pin header number) as Pin 23.
- ///
- public GpioPin Pin23 => GpioPin.Pin23.Value;
-
- ///
- /// Provides direct access to Pin known to Wiring Pi (not the pin header number) as Pin 24.
- ///
- public GpioPin Pin24 => GpioPin.Pin24.Value;
-
- ///
- /// Provides direct access to Pin known to Wiring Pi (not the pin header number) as Pin 25.
- ///
- public GpioPin Pin25 => GpioPin.Pin25.Value;
-
- ///
- /// Provides direct access to Pin known to Wiring Pi (not the pin header number) as Pin 26.
- ///
- public GpioPin Pin26 => GpioPin.Pin26.Value;
-
- ///
- /// Provides direct access to Pin known to Wiring Pi (not the pin header number) as Pin 27.
- ///
- public GpioPin Pin27 => GpioPin.Pin27.Value;
-
- ///
- /// Provides direct access to Pin known to Wiring Pi (not the pin header number) as Pin 28.
- ///
- public GpioPin Pin28 => GpioPin.Pin28.Value;
-
- ///
- /// Provides direct access to Pin known to Wiring Pi (not the pin header number) as Pin 29.
- ///
- public GpioPin Pin29 => GpioPin.Pin29.Value;
-
- ///
- /// Provides direct access to Pin known to Wiring Pi (not the pin header number) as Pin 30.
- ///
- public GpioPin Pin30 => GpioPin.Pin30.Value;
-
- ///
- /// Provides direct access to Pin known to Wiring Pi (not the pin header number) as Pin 31.
- ///
- public GpioPin Pin31 => GpioPin.Pin31.Value;
-
- #endregion
-
- #region Indexers
-
- ///
- /// Gets or sets the initialization mode.
- ///
- private static ControllerMode Mode { get; set; } = ControllerMode.NotInitialized;
-
- ///
- /// Gets the with the specified Wiring Pi pin number.
- ///
- ///
- /// The .
- ///
- /// The pin number.
- /// A reference to the GPIO pin
- public GpioPin this[WiringPiPin pinNumber] => _pinsByWiringPiPinNumber[pinNumber];
-
- ///
- /// Gets the with the specified pin number.
- ///
- ///
- /// The .
- ///
- /// The pin number.
- /// A reference to the GPIO pin
- public GpioPin this[P1 pinNumber] => HeaderP1[(int)pinNumber];
-
- ///
- /// Gets the with the specified pin number.
- ///
- ///
- /// The .
- ///
- /// The pin number.
- /// A reference to the GPIO pin
- public GpioPin this[P5 pinNumber] => HeaderP5[(int)pinNumber];
-
- ///
- /// Gets the with the specified Wiring Pi pin number.
- /// Use the HeaderP1 and HeaderP5 lookups if you would like to retrieve pins by physical pin number.
- ///
- ///
- /// The .
- ///
- /// The pin number as defined by Wiring Pi. This is not the header pin number as pin number in headers are obvoisly repeating.
- /// A reference to the GPIO pin
- /// When the pin index is not found
- public GpioPin this[int wiringPiPinNumber]
- {
- get
- {
- if (Enum.IsDefined(typeof(WiringPiPin), wiringPiPinNumber) == false)
- throw new IndexOutOfRangeException($"Pin {wiringPiPinNumber} is not registered in the GPIO controller.");
-
- return _pinsByWiringPiPinNumber[(WiringPiPin)wiringPiPinNumber];
- }
- }
-
- #endregion
-
- #region Pin Group Methods (Read, Write, Pad Drive)
-
- ///
- /// This sets the “strength” of the pad drivers for a particular group of pins.
- /// There are 3 groups of pins and the drive strength is from 0 to 7.
- /// Do not use this unless you know what you are doing.
- ///
- /// The group.
- /// The value.
- public void SetPadDrive(int group, int value)
- {
- lock (SyncRoot)
- {
- WiringPi.SetPadDrive(group, value);
- }
- }
-
- ///
- /// This sets the “strength” of the pad drivers for a particular group of pins.
- /// There are 3 groups of pins and the drive strength is from 0 to 7.
- /// Do not use this unless you know what you are doing.
- ///
- /// The group.
- /// The value.
- /// The awaitable task
- public Task SetPadDriveAsync(int group, int value) => Task.Run(() => { SetPadDrive(group, value); });
-
- ///
- /// This writes the 8-bit byte supplied to the first 8 GPIO pins.
- /// It’s the fastest way to set all 8 bits at once to a particular value,
- /// although it still takes two write operations to the Pi’s GPIO hardware.
- ///
- /// The value.
- /// PinMode
- public void WriteByte(byte value)
- {
- lock (SyncRoot)
- {
- if (this.Skip(0).Take(8).Any(p => p.PinMode != GpioPinDriveMode.Output))
- {
- throw new InvalidOperationException(
- $"All firts 8 pins (0 to 7) need their {nameof(GpioPin.PinMode)} to be set to {GpioPinDriveMode.Output}");
- }
-
- WiringPi.DigitalWriteByte(value);
- }
- }
-
- ///
- /// This writes the 8-bit byte supplied to the first 8 GPIO pins.
- /// It’s the fastest way to set all 8 bits at once to a particular value,
- /// although it still takes two write operations to the Pi’s GPIO hardware.
- ///
- /// The value.
- /// The awaitable task
- public Task WriteByteAsync(byte value) => Task.Run(() => { WriteByte(value); });
-
- ///
- /// This reads the 8-bit byte supplied to the first 8 GPIO pins.
- /// It’s the fastest way to get all 8 bits at once to a particular value.
- /// Please note this function is undocumented and unsopported
- ///
- /// A byte from the GPIO
- /// PinMode
- public byte ReadByte()
- {
- lock (SyncRoot)
- {
- if (this.Skip(0).Take(8).Any(p =>
- p.PinMode != GpioPinDriveMode.Input && p.PinMode != GpioPinDriveMode.Output))
- {
- throw new InvalidOperationException(
- $"All firts 8 pins (0 to 7) need their {nameof(GpioPin.PinMode)} to be set to {GpioPinDriveMode.Input} or {GpioPinDriveMode.Output}");
- }
-
- return (byte)WiringPi.DigitalReadByte();
- }
- }
-
- ///
- /// This reads the 8-bit byte supplied to the first 8 GPIO pins.
- /// It’s the fastest way to get all 8 bits at once to a particular value.
- /// Please note this function is undocumented and unsopported
- ///
- /// A byte from the GPIO
- public Task ReadByteAsync() => Task.Run(() => ReadByte());
-
- #endregion
-
- #region IReadOnlyCollection Implementation
-
- ///
- /// Returns an enumerator that iterates through the collection.
- ///
- ///
- /// A that can be used to iterate through the collection.
- ///
- public IEnumerator GetEnumerator() => _pinCollection.GetEnumerator();
-
- ///
- /// Returns an enumerator that iterates through the collection.
- ///
- ///
- /// An object that can be used to iterate through the collection.
- ///
- IEnumerator IEnumerable.GetEnumerator() => _pinCollection.GetEnumerator();
-
- #endregion
-
- #region Helper and Init Methods
-
- ///
- /// Gets the GPIO pin by BCM pin number.
- ///
- /// The BCM pin number.
- /// The GPIO pin
- public GpioPin GetGpioPinByBcmPinNumber(int bcmPinNumber) => this.First(pin => pin.BcmPinNumber == bcmPinNumber);
-
- ///
- /// Converts the Wirings Pi pin number to the BCM pin number.
- ///
- /// The wiring pi pin number.
- /// The converted pin
- internal static int WiringPiToBcmPinNumber(int wiringPiPinNumber)
- {
- lock (SyncRoot)
- {
- return WiringPi.WpiPinToGpio(wiringPiPinNumber);
- }
- }
-
- ///
- /// Converts the Physical (Header) pin number to BCM pin number.
- ///
- /// The header pin number.
- /// The converted pin
- internal static int HaderToBcmPinNumber(int headerPinNumber)
- {
- lock (SyncRoot)
- {
- return WiringPi.PhysPinToGpio(headerPinNumber);
- }
- }
-
- ///
- /// Short-hand method of registering pins
- ///
- /// The pin.
- private void RegisterPin(GpioPin pin)
- {
- if (_pinsByWiringPiPinNumber.ContainsKey(pin.WiringPiPinNumber) == false)
- _pinsByWiringPiPinNumber[pin.WiringPiPinNumber] = pin;
- else
- throw new InvalidOperationException($"Pin {pin.WiringPiPinNumber} has been registered");
- }
-
- ///
- /// Initializes the controller given the initialization mode and pin numbering scheme
- ///
- /// The mode.
- /// True when successful.
- ///
- /// This library does not support the platform
- ///
- /// Library was already Initialized
- /// The init mode is invalid
- private bool Initialize(ControllerMode mode)
- {
- if (Runtime.OS != Swan.OperatingSystem.Unix)
- throw new PlatformNotSupportedException("This library does not support the platform");
-
- lock (SyncRoot)
- {
- if (IsInitialized)
- throw new InvalidOperationException($"Cannot call {nameof(Initialize)} more than once.");
-
- Environment.SetEnvironmentVariable(WiringPiCodesEnvironmentVariable, "1", EnvironmentVariableTarget.Process);
- int setpuResult;
-
- switch (mode)
- {
- case ControllerMode.DirectWithWiringPiPins:
- {
- setpuResult = WiringPi.WiringPiSetup();
- break;
- }
-
- case ControllerMode.DirectWithBcmPins:
- {
- setpuResult = WiringPi.WiringPiSetupGpio();
- break;
- }
-
- case ControllerMode.DirectWithHeaderPins:
- {
- setpuResult = WiringPi.WiringPiSetupPhys();
- break;
- }
-
- case ControllerMode.FileStreamWithHardwarePins:
- {
- setpuResult = WiringPi.WiringPiSetupSys();
- break;
- }
-
- default:
- {
- throw new ArgumentException($"'{mode}' is not a valid initialization mode.");
- }
- }
-
- Mode = setpuResult == 0 ? mode : ControllerMode.NotInitialized;
- return IsInitialized;
- }
- }
-
- #endregion
-
- }
+ /// Unable to initialize the GPIO controller.
+ private GpioController() {
+ if(this.Pins != null) {
+ return;
+ }
+
+ if(IsInitialized == false) {
+ Boolean initResult = this.Initialize(ControllerMode.DirectWithWiringPiPins);
+ if(initResult == false) {
+ throw new Exception("Unable to initialize the GPIO controller.");
+ }
+ }
+
+ #region Pin Registration (32 WiringPi Pins)
+
+ this.RegisterPin(GpioPin.Pin00.Value);
+ this.RegisterPin(GpioPin.Pin01.Value);
+ this.RegisterPin(GpioPin.Pin02.Value);
+ this.RegisterPin(GpioPin.Pin03.Value);
+ this.RegisterPin(GpioPin.Pin04.Value);
+ this.RegisterPin(GpioPin.Pin05.Value);
+ this.RegisterPin(GpioPin.Pin06.Value);
+ this.RegisterPin(GpioPin.Pin07.Value);
+ this.RegisterPin(GpioPin.Pin08.Value);
+ this.RegisterPin(GpioPin.Pin09.Value);
+ this.RegisterPin(GpioPin.Pin10.Value);
+ this.RegisterPin(GpioPin.Pin11.Value);
+ this.RegisterPin(GpioPin.Pin12.Value);
+ this.RegisterPin(GpioPin.Pin13.Value);
+ this.RegisterPin(GpioPin.Pin14.Value);
+ this.RegisterPin(GpioPin.Pin15.Value);
+ this.RegisterPin(GpioPin.Pin16.Value);
+ this.RegisterPin(GpioPin.Pin17.Value);
+ this.RegisterPin(GpioPin.Pin18.Value);
+ this.RegisterPin(GpioPin.Pin19.Value);
+ this.RegisterPin(GpioPin.Pin20.Value);
+ this.RegisterPin(GpioPin.Pin21.Value);
+ this.RegisterPin(GpioPin.Pin22.Value);
+ this.RegisterPin(GpioPin.Pin23.Value);
+ this.RegisterPin(GpioPin.Pin24.Value);
+ this.RegisterPin(GpioPin.Pin25.Value);
+ this.RegisterPin(GpioPin.Pin26.Value);
+ this.RegisterPin(GpioPin.Pin27.Value);
+ this.RegisterPin(GpioPin.Pin28.Value);
+ this.RegisterPin(GpioPin.Pin29.Value);
+ this.RegisterPin(GpioPin.Pin30.Value);
+ this.RegisterPin(GpioPin.Pin31.Value);
+
+ #endregion
+
+ this.Pins = new ReadOnlyCollection(this._pinsByWiringPiPinNumber.Values.ToArray());
+ Dictionary headerP1 = new Dictionary(this.Pins.Count);
+ Dictionary headerP5 = new Dictionary(this.Pins.Count);
+ foreach(GpioPin pin in this.Pins) {
+ Dictionary target = pin.Header == GpioHeader.P1 ? headerP1 : headerP5;
+ target[pin.HeaderPinNumber] = pin;
+ }
+
+ this.HeaderP1 = new ReadOnlyDictionary(headerP1);
+ this.HeaderP5 = new ReadOnlyDictionary(headerP5);
+ }
+
+ ///
+ /// Determines if the underlying GPIO controller has been initialized properly.
+ ///
+ ///
+ /// true if the controller is properly initialized; otherwise, false.
+ ///
+ public static Boolean IsInitialized {
+ get {
+ lock(SyncRoot) {
+ return Mode != ControllerMode.NotInitialized;
+ }
+ }
+ }
+
+ ///
+ /// Gets the number of registered pins in the controller.
+ ///
+ public Int32 Count => this.Pins.Count;
+
+ #endregion
+
+ #region Pin Addressing
+
+ ///
+ /// Gets the PWM base frequency (in Hz).
+ ///
+ public Int32 PwmBaseFrequency => 19200000;
+
+ ///
+ /// Gets a red-only collection of all registered pins.
+ ///
+ public ReadOnlyCollection Pins {
+ get;
+ }
+
+ ///
+ /// Provides all the pins on Header P1 of the Pi as a lookup by physical header pin number.
+ /// This header is the main header and it is the one commonly used.
+ ///
+ public ReadOnlyDictionary HeaderP1 {
+ get;
+ }
+
+ ///
+ /// Provides all the pins on Header P5 of the Pi as a lookup by physical header pin number.
+ /// This header is the secondary header and it is rarely used.
+ ///
+ public ReadOnlyDictionary HeaderP5 {
+ get;
+ }
+
+ #endregion
+
+ #region Individual Pin Properties
+
+ ///
+ /// Provides direct access to Pin known to Wiring Pi (not the pin header number) as Pin 00.
+ ///
+ public GpioPin Pin00 => GpioPin.Pin00.Value;
+
+ ///
+ /// Provides direct access to Pin known to Wiring Pi (not the pin header number) as Pin 01.
+ ///
+ public GpioPin Pin01 => GpioPin.Pin01.Value;
+
+ ///
+ /// Provides direct access to Pin known to Wiring Pi (not the pin header number) as Pin 02.
+ ///
+ public GpioPin Pin02 => GpioPin.Pin02.Value;
+
+ ///
+ /// Provides direct access to Pin known to Wiring Pi (not the pin header number) as Pin 03.
+ ///
+ public GpioPin Pin03 => GpioPin.Pin03.Value;
+
+ ///
+ /// Provides direct access to Pin known to Wiring Pi (not the pin header number) as Pin 04.
+ ///
+ public GpioPin Pin04 => GpioPin.Pin04.Value;
+
+ ///
+ /// Provides direct access to Pin known to Wiring Pi (not the pin header number) as Pin 05.
+ ///
+ public GpioPin Pin05 => GpioPin.Pin05.Value;
+
+ ///
+ /// Provides direct access to Pin known to Wiring Pi (not the pin header number) as Pin 06.
+ ///
+ public GpioPin Pin06 => GpioPin.Pin06.Value;
+
+ ///
+ /// Provides direct access to Pin known to Wiring Pi (not the pin header number) as Pin 07.
+ ///
+ public GpioPin Pin07 => GpioPin.Pin07.Value;
+
+ ///
+ /// Provides direct access to Pin known to Wiring Pi (not the pin header number) as Pin 08.
+ ///
+ public GpioPin Pin08 => GpioPin.Pin08.Value;
+
+ ///
+ /// Provides direct access to Pin known to Wiring Pi (not the pin header number) as Pin 09.
+ ///
+ public GpioPin Pin09 => GpioPin.Pin09.Value;
+
+ ///
+ /// Provides direct access to Pin known to Wiring Pi (not the pin header number) as Pin 10.
+ ///
+ public GpioPin Pin10 => GpioPin.Pin10.Value;
+
+ ///
+ /// Provides direct access to Pin known to Wiring Pi (not the pin header number) as Pin 11.
+ ///
+ public GpioPin Pin11 => GpioPin.Pin11.Value;
+
+ ///
+ /// Provides direct access to Pin known to Wiring Pi (not the pin header number) as Pin 12.
+ ///
+ public GpioPin Pin12 => GpioPin.Pin12.Value;
+
+ ///
+ /// Provides direct access to Pin known to Wiring Pi (not the pin header number) as Pin 13.
+ ///
+ public GpioPin Pin13 => GpioPin.Pin13.Value;
+
+ ///
+ /// Provides direct access to Pin known to Wiring Pi (not the pin header number) as Pin 14.
+ ///
+ public GpioPin Pin14 => GpioPin.Pin14.Value;
+
+ ///
+ /// Provides direct access to Pin known to Wiring Pi (not the pin header number) as Pin 15.
+ ///
+ public GpioPin Pin15 => GpioPin.Pin15.Value;
+
+ ///
+ /// Provides direct access to Pin known to Wiring Pi (not the pin header number) as Pin 16.
+ ///
+ public GpioPin Pin16 => GpioPin.Pin16.Value;
+
+ ///
+ /// Provides direct access to Pin known to Wiring Pi (not the pin header number) as Pin 17.
+ ///
+ public GpioPin Pin17 => GpioPin.Pin17.Value;
+
+ ///
+ /// Provides direct access to Pin known to Wiring Pi (not the pin header number) as Pin 18.
+ ///
+ public GpioPin Pin18 => GpioPin.Pin18.Value;
+
+ ///
+ /// Provides direct access to Pin known to Wiring Pi (not the pin header number) as Pin 19.
+ ///
+ public GpioPin Pin19 => GpioPin.Pin19.Value;
+
+ ///
+ /// Provides direct access to Pin known to Wiring Pi (not the pin header number) as Pin 20.
+ ///
+ public GpioPin Pin20 => GpioPin.Pin20.Value;
+
+ ///
+ /// Provides direct access to Pin known to Wiring Pi (not the pin header number) as Pin 21.
+ ///
+ public GpioPin Pin21 => GpioPin.Pin21.Value;
+
+ ///
+ /// Provides direct access to Pin known to Wiring Pi (not the pin header number) as Pin 22.
+ ///
+ public GpioPin Pin22 => GpioPin.Pin22.Value;
+
+ ///
+ /// Provides direct access to Pin known to Wiring Pi (not the pin header number) as Pin 23.
+ ///
+ public GpioPin Pin23 => GpioPin.Pin23.Value;
+
+ ///
+ /// Provides direct access to Pin known to Wiring Pi (not the pin header number) as Pin 24.
+ ///
+ public GpioPin Pin24 => GpioPin.Pin24.Value;
+
+ ///
+ /// Provides direct access to Pin known to Wiring Pi (not the pin header number) as Pin 25.
+ ///
+ public GpioPin Pin25 => GpioPin.Pin25.Value;
+
+ ///
+ /// Provides direct access to Pin known to Wiring Pi (not the pin header number) as Pin 26.
+ ///
+ public GpioPin Pin26 => GpioPin.Pin26.Value;
+
+ ///
+ /// Provides direct access to Pin known to Wiring Pi (not the pin header number) as Pin 27.
+ ///
+ public GpioPin Pin27 => GpioPin.Pin27.Value;
+
+ ///
+ /// Provides direct access to Pin known to Wiring Pi (not the pin header number) as Pin 28.
+ ///
+ public GpioPin Pin28 => GpioPin.Pin28.Value;
+
+ ///
+ /// Provides direct access to Pin known to Wiring Pi (not the pin header number) as Pin 29.
+ ///
+ public GpioPin Pin29 => GpioPin.Pin29.Value;
+
+ ///
+ /// Provides direct access to Pin known to Wiring Pi (not the pin header number) as Pin 30.
+ ///
+ public GpioPin Pin30 => GpioPin.Pin30.Value;
+
+ ///
+ /// Provides direct access to Pin known to Wiring Pi (not the pin header number) as Pin 31.
+ ///
+ public GpioPin Pin31 => GpioPin.Pin31.Value;
+
+ #endregion
+
+ #region Indexers
+
+ ///
+ /// Gets or sets the initialization mode.
+ ///
+ private static ControllerMode Mode { get; set; } = ControllerMode.NotInitialized;
+
+ ///
+ /// Gets the with the specified Wiring Pi pin number.
+ ///
+ ///
+ /// The .
+ ///
+ /// The pin number.
+ /// A reference to the GPIO pin
+ public GpioPin this[WiringPiPin pinNumber] => this._pinsByWiringPiPinNumber[pinNumber];
+
+ ///
+ /// Gets the with the specified pin number.
+ ///
+ ///
+ /// The .
+ ///
+ /// The pin number.
+ /// A reference to the GPIO pin
+ public GpioPin this[P1 pinNumber] => this.HeaderP1[(Int32)pinNumber];
+
+ ///
+ /// Gets the with the specified pin number.
+ ///
+ ///
+ /// The .
+ ///
+ /// The pin number.
+ /// A reference to the GPIO pin
+ public GpioPin this[P5 pinNumber] => this.HeaderP5[(Int32)pinNumber];
+
+ ///
+ /// Gets the with the specified Wiring Pi pin number.
+ /// Use the HeaderP1 and HeaderP5 lookups if you would like to retrieve pins by physical pin number.
+ ///
+ ///
+ /// The .
+ ///
+ /// The pin number as defined by Wiring Pi. This is not the header pin number as pin number in headers are obvoisly repeating.
+ /// A reference to the GPIO pin
+ /// When the pin index is not found
+ public GpioPin this[Int32 wiringPiPinNumber] {
+ get {
+ if(Enum.IsDefined(typeof(WiringPiPin), wiringPiPinNumber) == false) {
+ throw new IndexOutOfRangeException($"Pin {wiringPiPinNumber} is not registered in the GPIO controller.");
+ }
+
+ return this._pinsByWiringPiPinNumber[(WiringPiPin)wiringPiPinNumber];
+ }
+ }
+
+ #endregion
+
+ #region Pin Group Methods (Read, Write, Pad Drive)
+
+ ///
+ /// This sets the “strength” of the pad drivers for a particular group of pins.
+ /// There are 3 groups of pins and the drive strength is from 0 to 7.
+ /// Do not use this unless you know what you are doing.
+ ///
+ /// The group.
+ /// The value.
+ public void SetPadDrive(Int32 group, Int32 value) {
+ lock(SyncRoot) {
+ _ = WiringPi.SetPadDrive(group, value);
+ }
+ }
+
+ ///
+ /// This sets the “strength” of the pad drivers for a particular group of pins.
+ /// There are 3 groups of pins and the drive strength is from 0 to 7.
+ /// Do not use this unless you know what you are doing.
+ ///
+ /// The group.
+ /// The value.
+ /// The awaitable task
+ public Task SetPadDriveAsync(Int32 group, Int32 value) => Task.Run(() => this.SetPadDrive(group, value));
+
+ ///
+ /// This writes the 8-bit byte supplied to the first 8 GPIO pins.
+ /// It’s the fastest way to set all 8 bits at once to a particular value,
+ /// although it still takes two write operations to the Pi’s GPIO hardware.
+ ///
+ /// The value.
+ /// PinMode
+ public void WriteByte(Byte value) {
+ lock(SyncRoot) {
+ if(this.Skip(0).Take(8).Any(p => p.PinMode != GpioPinDriveMode.Output)) {
+ throw new InvalidOperationException(
+ $"All firts 8 pins (0 to 7) need their {nameof(GpioPin.PinMode)} to be set to {GpioPinDriveMode.Output}");
+ }
+
+ WiringPi.DigitalWriteByte(value);
+ }
+ }
+
+ ///
+ /// This writes the 8-bit byte supplied to the first 8 GPIO pins.
+ /// It’s the fastest way to set all 8 bits at once to a particular value,
+ /// although it still takes two write operations to the Pi’s GPIO hardware.
+ ///
+ /// The value.
+ /// The awaitable task
+ public Task WriteByteAsync(Byte value) => Task.Run(() => this.WriteByte(value));
+
+ ///
+ /// This reads the 8-bit byte supplied to the first 8 GPIO pins.
+ /// It’s the fastest way to get all 8 bits at once to a particular value.
+ /// Please note this function is undocumented and unsopported
+ ///
+ /// A byte from the GPIO
+ /// PinMode
+ public Byte ReadByte() {
+ lock(SyncRoot) {
+ if(this.Skip(0).Take(8).Any(p =>
+ p.PinMode != GpioPinDriveMode.Input && p.PinMode != GpioPinDriveMode.Output)) {
+ throw new InvalidOperationException(
+ $"All firts 8 pins (0 to 7) need their {nameof(GpioPin.PinMode)} to be set to {GpioPinDriveMode.Input} or {GpioPinDriveMode.Output}");
+ }
+
+ return (Byte)WiringPi.DigitalReadByte();
+ }
+ }
+
+ ///
+ /// This reads the 8-bit byte supplied to the first 8 GPIO pins.
+ /// It’s the fastest way to get all 8 bits at once to a particular value.
+ /// Please note this function is undocumented and unsopported
+ ///
+ /// A byte from the GPIO
+ public Task ReadByteAsync() => Task.Run(() => this.ReadByte());
+
+ #endregion
+
+ #region IReadOnlyCollection Implementation
+
+ ///
+ /// Returns an enumerator that iterates through the collection.
+ ///
+ ///
+ /// A that can be used to iterate through the collection.
+ ///
+ public IEnumerator GetEnumerator() => this.Pins.GetEnumerator();
+
+ ///
+ /// Returns an enumerator that iterates through the collection.
+ ///
+ ///
+ /// An object that can be used to iterate through the collection.
+ ///
+ IEnumerator IEnumerable.GetEnumerator() => this.Pins.GetEnumerator();
+
+ #endregion
+
+ #region Helper and Init Methods
+
+ ///
+ /// Gets the GPIO pin by BCM pin number.
+ ///
+ /// The BCM pin number.
+ /// The GPIO pin
+ public GpioPin GetGpioPinByBcmPinNumber(Int32 bcmPinNumber) => this.First(pin => pin.BcmPinNumber == bcmPinNumber);
+
+ ///
+ /// Converts the Wirings Pi pin number to the BCM pin number.
+ ///
+ /// The wiring pi pin number.
+ /// The converted pin
+ internal static Int32 WiringPiToBcmPinNumber(Int32 wiringPiPinNumber) {
+ lock(SyncRoot) {
+ return WiringPi.WpiPinToGpio(wiringPiPinNumber);
+ }
+ }
+
+ ///
+ /// Converts the Physical (Header) pin number to BCM pin number.
+ ///
+ /// The header pin number.
+ /// The converted pin
+ internal static Int32 HaderToBcmPinNumber(Int32 headerPinNumber) {
+ lock(SyncRoot) {
+ return WiringPi.PhysPinToGpio(headerPinNumber);
+ }
+ }
+
+ ///
+ /// Short-hand method of registering pins
+ ///
+ /// The pin.
+ private void RegisterPin(GpioPin pin) {
+ if(this._pinsByWiringPiPinNumber.ContainsKey(pin.WiringPiPinNumber) == false) {
+ this._pinsByWiringPiPinNumber[pin.WiringPiPinNumber] = pin;
+ } else {
+ throw new InvalidOperationException($"Pin {pin.WiringPiPinNumber} has been registered");
+ }
+ }
+
+ ///
+ /// Initializes the controller given the initialization mode and pin numbering scheme
+ ///
+ /// The mode.
+ /// True when successful.
+ ///
+ /// This library does not support the platform
+ ///
+ /// Library was already Initialized
+ /// The init mode is invalid
+ private Boolean Initialize(ControllerMode mode) {
+ if(Runtime.OS != Swan.OperatingSystem.Unix) {
+ throw new PlatformNotSupportedException("This library does not support the platform");
+ }
+
+ lock(SyncRoot) {
+ if(IsInitialized) {
+ throw new InvalidOperationException($"Cannot call {nameof(Initialize)} more than once.");
+ }
+
+ Environment.SetEnvironmentVariable(WiringPiCodesEnvironmentVariable, "1", EnvironmentVariableTarget.Process);
+ Int32 setpuResult;
+
+ switch(mode) {
+ case ControllerMode.DirectWithWiringPiPins: {
+ setpuResult = WiringPi.WiringPiSetup();
+ break;
+ }
+
+ case ControllerMode.DirectWithBcmPins: {
+ setpuResult = WiringPi.WiringPiSetupGpio();
+ break;
+ }
+
+ case ControllerMode.DirectWithHeaderPins: {
+ setpuResult = WiringPi.WiringPiSetupPhys();
+ break;
+ }
+
+ case ControllerMode.FileStreamWithHardwarePins: {
+ setpuResult = WiringPi.WiringPiSetupSys();
+ break;
+ }
+
+ default: {
+ throw new ArgumentException($"'{mode}' is not a valid initialization mode.");
+ }
+ }
+
+ Mode = setpuResult == 0 ? mode : ControllerMode.NotInitialized;
+ return IsInitialized;
+ }
+ }
+
+ #endregion
+
+ }
}
\ No newline at end of file
diff --git a/Unosquare.RaspberryIO/Gpio/GpioPin.Factory.cs b/Unosquare.RaspberryIO/Gpio/GpioPin.Factory.cs
index f4a9d6a..f865253 100644
--- a/Unosquare.RaspberryIO/Gpio/GpioPin.Factory.cs
+++ b/Unosquare.RaspberryIO/Gpio/GpioPin.Factory.cs
@@ -1,201 +1,167 @@
-namespace Unosquare.RaspberryIO.Gpio
-{
- using System;
-
- public partial class GpioPin
- {
- #region Static Pin Definitions
-
- internal static readonly Lazy Pin08 = new Lazy(() => new GpioPin(WiringPiPin.Pin08, 3)
- {
- Capabilities = new[] { PinCapability.GP, PinCapability.I2CSDA },
- Name = "BCM 2 (SDA)"
- });
-
- internal static readonly Lazy Pin09 = new Lazy(() => new GpioPin(WiringPiPin.Pin09, 5)
- {
- Capabilities = new[] { PinCapability.GP, PinCapability.I2CSCL },
- Name = "BCM 3 (SCL)"
- });
-
- internal static readonly Lazy Pin07 = new Lazy(() => new GpioPin(WiringPiPin.Pin07, 7)
- {
- Capabilities = new[] { PinCapability.GP, PinCapability.GPCLK },
- Name = "BCM 4 (GPCLK0)"
- });
-
- internal static readonly Lazy Pin00 = new Lazy(() => new GpioPin(WiringPiPin.Pin00, 11)
- {
- Capabilities = new[] { PinCapability.GP, PinCapability.UARTRTS },
- Name = "BCM 17"
- });
-
- internal static readonly Lazy Pin02 = new Lazy(() => new GpioPin(WiringPiPin.Pin02, 13)
- {
- Capabilities = new[] { PinCapability.GP },
- Name = "BCM 27"
- });
-
- internal static readonly Lazy Pin03 = new Lazy(() => new GpioPin(WiringPiPin.Pin03, 15)
- {
- Capabilities = new[] { PinCapability.GP },
- Name = "BCM 22"
- });
-
- internal static readonly Lazy Pin12 = new Lazy(() => new GpioPin(WiringPiPin.Pin12, 19)
- {
- Capabilities = new[] { PinCapability.GP, PinCapability.SPIMOSI },
- Name = "BCM 10 (MOSI)"
- });
-
- internal static readonly Lazy Pin13 = new Lazy(() => new GpioPin(WiringPiPin.Pin13, 21)
- {
- Capabilities = new[] { PinCapability.GP, PinCapability.SPIMISO },
- Name = "BCM 9 (MISO)"
- });
-
- internal static readonly Lazy Pin14 = new Lazy(() => new GpioPin(WiringPiPin.Pin14, 23)
- {
- Capabilities = new[] { PinCapability.GP, PinCapability.SPICLK },
- Name = "BCM 11 (SCLCK)"
- });
-
- internal static readonly Lazy Pin30 = new Lazy(() => new GpioPin(WiringPiPin.Pin30, 27)
- {
- Capabilities = new[] { PinCapability.I2CSDA },
- Name = "BCM 0 (ID_SD)"
- });
-
- internal static readonly Lazy Pin31 = new Lazy(() => new GpioPin(WiringPiPin.Pin31, 28)
- {
- Capabilities = new[] { PinCapability.I2CSCL },
- Name = "BCM 1 (ID_SC)"
- });
-
- internal static readonly Lazy Pin11 = new Lazy(() => new GpioPin(WiringPiPin.Pin11, 26)
- {
- Capabilities = new[] { PinCapability.GP, PinCapability.SPICS },
- Name = "BCM 7 (CE1)"
- });
-
- internal static readonly Lazy Pin10 = new Lazy(() => new GpioPin(WiringPiPin.Pin10, 24)
- {
- Capabilities = new[] { PinCapability.GP, PinCapability.SPICS },
- Name = "BCM 8 (CE0)"
- });
-
- internal static readonly Lazy Pin06 = new Lazy(() => new GpioPin(WiringPiPin.Pin06, 22)
- {
- Capabilities = new[] { PinCapability.GP },
- Name = "BCM 25"
- });
- internal static readonly Lazy Pin05 = new Lazy(() => new GpioPin(WiringPiPin.Pin05, 18)
- {
- Capabilities = new[] { PinCapability.GP },
- Name = "BCM 24"
- });
-
- internal static readonly Lazy Pin04 = new Lazy(() => new GpioPin(WiringPiPin.Pin04, 16)
- {
- Capabilities = new[] { PinCapability.GP },
- Name = "BCM 23"
- });
-
- internal static readonly Lazy Pin01 = new Lazy(() => new GpioPin(WiringPiPin.Pin01, 12)
- {
- Capabilities = new[] { PinCapability.GP, PinCapability.PWM },
- Name = "BCM 18 (PWM0)"
- });
-
- internal static readonly Lazy Pin16 = new Lazy(() => new GpioPin(WiringPiPin.Pin16, 10)
- {
- Capabilities = new[] { PinCapability.UARTRXD },
- Name = "BCM 15 (RXD)"
- });
-
- internal static readonly Lazy Pin15 = new Lazy(() => new GpioPin(WiringPiPin.Pin15, 8)
- {
- Capabilities = new[] { PinCapability.UARTTXD },
- Name = "BCM 14 (TXD)"
- });
-
- internal static readonly Lazy Pin21 = new Lazy(() => new GpioPin(WiringPiPin.Pin21, 29)
- {
- Capabilities = new[] { PinCapability.GP },
- Name = "BCM 5"
- });
-
- internal static readonly Lazy Pin22 = new Lazy(() => new GpioPin(WiringPiPin.Pin22, 31)
- {
- Capabilities = new[] { PinCapability.GP },
- Name = "BCM 6"
- });
-
- internal static readonly Lazy Pin23 = new Lazy(() => new GpioPin(WiringPiPin.Pin23, 33)
- {
- Capabilities = new[] { PinCapability.GP, PinCapability.PWM },
- Name = "BCM 13 (PWM1)"
- });
-
- internal static readonly Lazy Pin24 = new Lazy(() => new GpioPin(WiringPiPin.Pin24, 35)
- {
- Capabilities = new[] { PinCapability.GP, PinCapability.SPIMISO },
- Name = "BCM 19 (MISO)"
- });
-
- internal static readonly Lazy Pin25 = new Lazy(() => new GpioPin(WiringPiPin.Pin25, 37)
- {
- Capabilities = new[] { PinCapability.GP },
- Name = "BCM 26"
- });
-
- internal static readonly Lazy Pin29 = new Lazy(() => new GpioPin(WiringPiPin.Pin29, 40)
- {
- Capabilities = new[] { PinCapability.GP, PinCapability.SPICLK },
- Name = "BCM 21 (SCLK)"
- });
-
- internal static readonly Lazy Pin28 = new Lazy(() => new GpioPin(WiringPiPin.Pin28, 38)
- {
- Capabilities = new[] { PinCapability.GP, PinCapability.SPIMOSI },
- Name = "BCM 20 (MOSI)"
- });
-
- internal static readonly Lazy Pin27 = new Lazy(() => new GpioPin(WiringPiPin.Pin27, 36)
- {
- Capabilities = new[] { PinCapability.GP },
- Name = "BCM 16"
- });
- internal static readonly Lazy Pin26 = new Lazy(() => new GpioPin(WiringPiPin.Pin26, 32)
- {
- Capabilities = new[] { PinCapability.GP },
- Name = "BCM 12 (PWM0)"
- });
-
- internal static readonly Lazy Pin17 = new Lazy(() => new GpioPin(WiringPiPin.Pin17, 3)
- {
- Capabilities = new[] { PinCapability.GP, PinCapability.I2CSDA },
- Name = "BCM 28 (SDA)"
- });
-
- internal static readonly Lazy Pin18 = new Lazy(() => new GpioPin(WiringPiPin.Pin18, 4)
- {
- Capabilities = new[] { PinCapability.GP, PinCapability.I2CSCL },
- Name = "BCM 29 (SCL)"
- });
-
- internal static readonly Lazy Pin19 = new Lazy(() => new GpioPin(WiringPiPin.Pin19, 5)
- {
- Capabilities = new[] { PinCapability.GP },
- Name = "BCM 30"
- });
-
- internal static readonly Lazy Pin20 = new Lazy(() => new GpioPin(WiringPiPin.Pin20, 6)
- {
- Capabilities = new[] { PinCapability.GP },
- Name = "BCM 31"
- });
-
- #endregion
- }
+using System;
+
+namespace Unosquare.RaspberryIO.Gpio {
+ public partial class GpioPin {
+ #region Static Pin Definitions
+
+ internal static readonly Lazy Pin08 = new Lazy(() => new GpioPin(WiringPiPin.Pin08, 3) {
+ Capabilities = new[] { PinCapability.GP, PinCapability.I2CSDA },
+ Name = "BCM 2 (SDA)"
+ });
+
+ internal static readonly Lazy Pin09 = new Lazy(() => new GpioPin(WiringPiPin.Pin09, 5) {
+ Capabilities = new[] { PinCapability.GP, PinCapability.I2CSCL },
+ Name = "BCM 3 (SCL)"
+ });
+
+ internal static readonly Lazy Pin07 = new Lazy(() => new GpioPin(WiringPiPin.Pin07, 7) {
+ Capabilities = new[] { PinCapability.GP, PinCapability.GPCLK },
+ Name = "BCM 4 (GPCLK0)"
+ });
+
+ internal static readonly Lazy Pin00 = new Lazy(() => new GpioPin(WiringPiPin.Pin00, 11) {
+ Capabilities = new[] { PinCapability.GP, PinCapability.UARTRTS },
+ Name = "BCM 17"
+ });
+
+ internal static readonly Lazy Pin02 = new Lazy(() => new GpioPin(WiringPiPin.Pin02, 13) {
+ Capabilities = new[] { PinCapability.GP },
+ Name = "BCM 27"
+ });
+
+ internal static readonly Lazy Pin03 = new Lazy(() => new GpioPin(WiringPiPin.Pin03, 15) {
+ Capabilities = new[] { PinCapability.GP },
+ Name = "BCM 22"
+ });
+
+ internal static readonly Lazy Pin12 = new Lazy(() => new GpioPin(WiringPiPin.Pin12, 19) {
+ Capabilities = new[] { PinCapability.GP, PinCapability.SPIMOSI },
+ Name = "BCM 10 (MOSI)"
+ });
+
+ internal static readonly Lazy Pin13 = new Lazy(() => new GpioPin(WiringPiPin.Pin13, 21) {
+ Capabilities = new[] { PinCapability.GP, PinCapability.SPIMISO },
+ Name = "BCM 9 (MISO)"
+ });
+
+ internal static readonly Lazy Pin14 = new Lazy(() => new GpioPin(WiringPiPin.Pin14, 23) {
+ Capabilities = new[] { PinCapability.GP, PinCapability.SPICLK },
+ Name = "BCM 11 (SCLCK)"
+ });
+
+ internal static readonly Lazy Pin30 = new Lazy(() => new GpioPin(WiringPiPin.Pin30, 27) {
+ Capabilities = new[] { PinCapability.I2CSDA },
+ Name = "BCM 0 (ID_SD)"
+ });
+
+ internal static readonly Lazy Pin31 = new Lazy(() => new GpioPin(WiringPiPin.Pin31, 28) {
+ Capabilities = new[] { PinCapability.I2CSCL },
+ Name = "BCM 1 (ID_SC)"
+ });
+
+ internal static readonly Lazy Pin11 = new Lazy(() => new GpioPin(WiringPiPin.Pin11, 26) {
+ Capabilities = new[] { PinCapability.GP, PinCapability.SPICS },
+ Name = "BCM 7 (CE1)"
+ });
+
+ internal static readonly Lazy Pin10 = new Lazy(() => new GpioPin(WiringPiPin.Pin10, 24) {
+ Capabilities = new[] { PinCapability.GP, PinCapability.SPICS },
+ Name = "BCM 8 (CE0)"
+ });
+
+ internal static readonly Lazy Pin06 = new Lazy(() => new GpioPin(WiringPiPin.Pin06, 22) {
+ Capabilities = new[] { PinCapability.GP },
+ Name = "BCM 25"
+ });
+ internal static readonly Lazy Pin05 = new Lazy(() => new GpioPin(WiringPiPin.Pin05, 18) {
+ Capabilities = new[] { PinCapability.GP },
+ Name = "BCM 24"
+ });
+
+ internal static readonly Lazy Pin04 = new Lazy(() => new GpioPin(WiringPiPin.Pin04, 16) {
+ Capabilities = new[] { PinCapability.GP },
+ Name = "BCM 23"
+ });
+
+ internal static readonly Lazy Pin01 = new Lazy(() => new GpioPin(WiringPiPin.Pin01, 12) {
+ Capabilities = new[] { PinCapability.GP, PinCapability.PWM },
+ Name = "BCM 18 (PWM0)"
+ });
+
+ internal static readonly Lazy Pin16 = new Lazy(() => new GpioPin(WiringPiPin.Pin16, 10) {
+ Capabilities = new[] { PinCapability.UARTRXD },
+ Name = "BCM 15 (RXD)"
+ });
+
+ internal static readonly Lazy Pin15 = new Lazy(() => new GpioPin(WiringPiPin.Pin15, 8) {
+ Capabilities = new[] { PinCapability.UARTTXD },
+ Name = "BCM 14 (TXD)"
+ });
+
+ internal static readonly Lazy Pin21 = new Lazy(() => new GpioPin(WiringPiPin.Pin21, 29) {
+ Capabilities = new[] { PinCapability.GP },
+ Name = "BCM 5"
+ });
+
+ internal static readonly Lazy Pin22 = new Lazy(() => new GpioPin(WiringPiPin.Pin22, 31) {
+ Capabilities = new[] { PinCapability.GP },
+ Name = "BCM 6"
+ });
+
+ internal static readonly Lazy Pin23 = new Lazy(() => new GpioPin(WiringPiPin.Pin23, 33) {
+ Capabilities = new[] { PinCapability.GP, PinCapability.PWM },
+ Name = "BCM 13 (PWM1)"
+ });
+
+ internal static readonly Lazy Pin24 = new Lazy(() => new GpioPin(WiringPiPin.Pin24, 35) {
+ Capabilities = new[] { PinCapability.GP, PinCapability.SPIMISO },
+ Name = "BCM 19 (MISO)"
+ });
+
+ internal static readonly Lazy Pin25 = new Lazy(() => new GpioPin(WiringPiPin.Pin25, 37) {
+ Capabilities = new[] { PinCapability.GP },
+ Name = "BCM 26"
+ });
+
+ internal static readonly Lazy Pin29 = new Lazy(() => new GpioPin(WiringPiPin.Pin29, 40) {
+ Capabilities = new[] { PinCapability.GP, PinCapability.SPICLK },
+ Name = "BCM 21 (SCLK)"
+ });
+
+ internal static readonly Lazy Pin28 = new Lazy(() => new GpioPin(WiringPiPin.Pin28, 38) {
+ Capabilities = new[] { PinCapability.GP, PinCapability.SPIMOSI },
+ Name = "BCM 20 (MOSI)"
+ });
+
+ internal static readonly Lazy Pin27 = new Lazy(() => new GpioPin(WiringPiPin.Pin27, 36) {
+ Capabilities = new[] { PinCapability.GP },
+ Name = "BCM 16"
+ });
+ internal static readonly Lazy Pin26 = new Lazy(() => new GpioPin(WiringPiPin.Pin26, 32) {
+ Capabilities = new[] { PinCapability.GP },
+ Name = "BCM 12 (PWM0)"
+ });
+
+ internal static readonly Lazy Pin17 = new Lazy(() => new GpioPin(WiringPiPin.Pin17, 3) {
+ Capabilities = new[] { PinCapability.GP, PinCapability.I2CSDA },
+ Name = "BCM 28 (SDA)"
+ });
+
+ internal static readonly Lazy Pin18 = new Lazy(() => new GpioPin(WiringPiPin.Pin18, 4) {
+ Capabilities = new[] { PinCapability.GP, PinCapability.I2CSCL },
+ Name = "BCM 29 (SCL)"
+ });
+
+ internal static readonly Lazy Pin19 = new Lazy(() => new GpioPin(WiringPiPin.Pin19, 5) {
+ Capabilities = new[] { PinCapability.GP },
+ Name = "BCM 30"
+ });
+
+ internal static readonly Lazy Pin20 = new Lazy(() => new GpioPin(WiringPiPin.Pin20, 6) {
+ Capabilities = new[] { PinCapability.GP },
+ Name = "BCM 31"
+ });
+
+ #endregion
+ }
}
diff --git a/Unosquare.RaspberryIO/Gpio/GpioPin.cs b/Unosquare.RaspberryIO/Gpio/GpioPin.cs
index ec4f6db..951dc79 100644
--- a/Unosquare.RaspberryIO/Gpio/GpioPin.cs
+++ b/Unosquare.RaspberryIO/Gpio/GpioPin.cs
@@ -1,648 +1,605 @@
-namespace Unosquare.RaspberryIO.Gpio
-{
- using Native;
- using Swan;
- using System;
- using System.Linq;
- using System.Threading.Tasks;
-
+using Unosquare.RaspberryIO.Native;
+using Unosquare.Swan;
+using System;
+using System.Linq;
+using System.Threading.Tasks;
+
+namespace Unosquare.RaspberryIO.Gpio {
+ ///
+ /// Represents a GPIO Pin, its location and its capabilities.
+ /// Full pin reference available here:
+ /// http://pinout.xyz/pinout/pin31_gpio6 and http://wiringpi.com/pins/
+ ///
+ public sealed partial class GpioPin {
+ #region Property Backing
+
+ private readonly Object _syncLock = new Object();
+ private GpioPinDriveMode m_PinMode;
+ private GpioPinResistorPullMode m_ResistorPullMode;
+ private Int32 m_PwmRegister;
+ private PwmMode m_PwmMode = PwmMode.Balanced;
+ private UInt32 m_PwmRange = 1024;
+ private Int32 m_PwmClockDivisor = 1;
+ private Int32 m_SoftPwmValue = -1;
+ private Int32 m_SoftToneFrequency = -1;
+
+ #endregion
+
+ #region Constructor
+
///
- /// Represents a GPIO Pin, its location and its capabilities.
- /// Full pin reference available here:
- /// http://pinout.xyz/pinout/pin31_gpio6 and http://wiringpi.com/pins/
+ /// Initializes a new instance of the class.
///
- public sealed partial class GpioPin
- {
- #region Property Backing
-
- private readonly object _syncLock = new object();
- private GpioPinDriveMode m_PinMode;
- private GpioPinResistorPullMode m_ResistorPullMode;
- private int m_PwmRegister;
- private PwmMode m_PwmMode = PwmMode.Balanced;
- private uint m_PwmRange = 1024;
- private int m_PwmClockDivisor = 1;
- private int m_SoftPwmValue = -1;
- private int m_SoftToneFrequency = -1;
-
- #endregion
-
- #region Constructor
-
- ///
- /// Initializes a new instance of the class.
- ///
- /// The wiring pi pin number.
- /// The header pin number.
- private GpioPin(WiringPiPin wiringPiPinNumber, int headerPinNumber)
- {
- PinNumber = (int)wiringPiPinNumber;
- WiringPiPinNumber = wiringPiPinNumber;
- BcmPinNumber = GpioController.WiringPiToBcmPinNumber((int)wiringPiPinNumber);
- HeaderPinNumber = headerPinNumber;
- Header = (PinNumber >= 17 && PinNumber <= 20) ? GpioHeader.P5 : GpioHeader.P1;
- }
-
- #endregion
-
- #region Pin Properties
-
- ///
- /// Gets or sets the Wiring Pi pin number as an integer.
- ///
- public int PinNumber { get; }
-
- ///
- /// Gets the WiringPi Pin number
- ///
- public WiringPiPin WiringPiPinNumber { get; }
-
- ///
- /// Gets the BCM chip (hardware) pin number.
- ///
- public int BcmPinNumber { get; }
-
- ///
- /// Gets or the physical header (physical board) pin number.
- ///
- public int HeaderPinNumber { get; }
-
- ///
- /// Gets the pin's header (physical board) location.
- ///
- public GpioHeader Header { get; }
-
- ///
- /// Gets the friendly name of the pin.
- ///
- public string Name { get; private set; }
-
- ///
- /// Gets the hardware mode capabilities of this pin.
- ///
- public PinCapability[] Capabilities { get; private set; }
-
- #endregion
-
- #region Hardware-Specific Properties
-
- ///
- /// Gets or sets the pin operating mode.
- ///
- ///
- /// The pin mode.
- ///
- /// Thrown when a pin does not support the given operation mode.
- public GpioPinDriveMode PinMode
- {
- get => m_PinMode;
-
- set
- {
- lock (_syncLock)
- {
- var mode = value;
- if ((mode == GpioPinDriveMode.GpioClock && Capabilities.Contains(PinCapability.GPCLK) == false) ||
- (mode == GpioPinDriveMode.PwmOutput && Capabilities.Contains(PinCapability.PWM) == false) ||
- (mode == GpioPinDriveMode.Input && Capabilities.Contains(PinCapability.GP) == false) ||
- (mode == GpioPinDriveMode.Output && Capabilities.Contains(PinCapability.GP) == false))
- {
- throw new NotSupportedException(
- $"Pin {WiringPiPinNumber} '{Name}' does not support mode '{mode}'. Pin capabilities are limited to: {string.Join(", ", Capabilities)}");
- }
-
- WiringPi.PinMode(PinNumber, (int)mode);
- m_PinMode = mode;
- }
- }
- }
-
- ///
- /// Gets the interrupt callback. Returns null if no interrupt
- /// has been registered.
- ///
- public InterruptServiceRoutineCallback InterruptCallback { get; private set; }
-
- ///
- /// Gets the interrupt edge detection mode.
- ///
- public EdgeDetection InterruptEdgeDetection { get; private set; } = EdgeDetection.ExternalSetup;
-
- #endregion
-
- #region Hardware PWM Members
-
- ///
- /// This sets or gets the pull-up or pull-down resistor mode on the pin, which should be set as an input.
- /// Unlike the Arduino, the BCM2835 has both pull-up an down internal resistors.
- /// The parameter pud should be; PUD_OFF, (no pull up/down), PUD_DOWN (pull to ground) or PUD_UP (pull to 3.3v)
- /// The internal pull up/down resistors have a value of approximately 50KΩ on the Raspberry Pi.
- ///
- public GpioPinResistorPullMode InputPullMode
- {
- get => PinMode == GpioPinDriveMode.Input ? m_ResistorPullMode : GpioPinResistorPullMode.Off;
-
- set
- {
- lock (_syncLock)
- {
- if (PinMode != GpioPinDriveMode.Input)
- {
- m_ResistorPullMode = GpioPinResistorPullMode.Off;
- throw new InvalidOperationException(
- $"Unable to set the {nameof(InputPullMode)} for pin {PinNumber} because operating mode is {PinMode}."
- + $" Setting the {nameof(InputPullMode)} is only allowed if {nameof(PinMode)} is set to {GpioPinDriveMode.Input}");
- }
-
- WiringPi.PullUpDnControl(PinNumber, (int)value);
- m_ResistorPullMode = value;
- }
- }
- }
-
- ///
- /// Gets or sets the PWM register. Values should be between 0 and 1024
- ///
- ///
- /// The PWM register.
- ///
- public int PwmRegister
- {
- get => m_PwmRegister;
-
- set
- {
- lock (_syncLock)
- {
- if (PinMode != GpioPinDriveMode.PwmOutput)
- {
- m_PwmRegister = 0;
-
- throw new InvalidOperationException(
- $"Unable to write PWM register for pin {PinNumber} because operating mode is {PinMode}."
- + $" Writing the PWM register is only allowed if {nameof(PinMode)} is set to {GpioPinDriveMode.PwmOutput}");
- }
-
- var val = value.Clamp(0, 1024);
-
- WiringPi.PwmWrite(PinNumber, val);
- m_PwmRegister = val;
- }
- }
- }
-
- ///
- /// The PWM generator can run in 2 modes – “balanced” and “mark:space”. The mark:space mode is traditional,
- /// however the default mode in the Pi is “balanced”.
- ///
- ///
- /// The PWM mode.
- ///
- /// When pin mode is not set a Pwn output
- public PwmMode PwmMode
- {
- get => PinMode == GpioPinDriveMode.PwmOutput ? m_PwmMode : PwmMode.Balanced;
-
- set
- {
- lock (_syncLock)
- {
- if (PinMode != GpioPinDriveMode.PwmOutput)
- {
- m_PwmMode = PwmMode.Balanced;
-
- throw new InvalidOperationException(
- $"Unable to set PWM mode for pin {PinNumber} because operating mode is {PinMode}."
- + $" Setting the PWM mode is only allowed if {nameof(PinMode)} is set to {GpioPinDriveMode.PwmOutput}");
- }
-
- WiringPi.PwmSetMode((int)value);
- m_PwmMode = value;
- }
- }
- }
-
- ///
- /// This sets the range register in the PWM generator. The default is 1024.
- ///
- ///
- /// The PWM range.
- ///
- /// When pin mode is not set to PWM output
- public uint PwmRange
- {
- get => PinMode == GpioPinDriveMode.PwmOutput ? m_PwmRange : 0;
-
- set
- {
- lock (_syncLock)
- {
- if (PinMode != GpioPinDriveMode.PwmOutput)
- {
- m_PwmRange = 1024;
-
- throw new InvalidOperationException(
- $"Unable to set PWM range for pin {PinNumber} because operating mode is {PinMode}."
- + $" Setting the PWM range is only allowed if {nameof(PinMode)} is set to {GpioPinDriveMode.PwmOutput}");
- }
-
- WiringPi.PwmSetRange(value);
- m_PwmRange = value;
- }
- }
- }
-
- ///
- /// Gets or sets the PWM clock divisor.
- ///
- ///
- /// The PWM clock divisor.
- ///
- /// When pin mode is not set to PWM output
- public int PwmClockDivisor
- {
- get => PinMode == GpioPinDriveMode.PwmOutput ? m_PwmClockDivisor : 0;
-
- set
- {
- lock (_syncLock)
- {
- if (PinMode != GpioPinDriveMode.PwmOutput)
- {
- m_PwmClockDivisor = 1;
-
- throw new InvalidOperationException(
- $"Unable to set PWM range for pin {PinNumber} because operating mode is {PinMode}."
- + $" Setting the PWM range is only allowed if {nameof(PinMode)} is set to {GpioPinDriveMode.PwmOutput}");
- }
-
- WiringPi.PwmSetClock(value);
- m_PwmClockDivisor = value;
- }
- }
- }
-
- #endregion
-
- #region Software Tone Members
-
- ///
- /// Gets a value indicating whether this instance is in software based tone generator mode.
- ///
- ///
- /// true if this instance is in soft tone mode; otherwise, false.
- ///
- public bool IsInSoftToneMode => m_SoftToneFrequency >= 0;
-
- ///
- /// Gets or sets the soft tone frequency. 0 to 5000 Hz is typical
- ///
- ///
- /// The soft tone frequency.
- ///
- /// When soft tones cannot be initialized on the pin
- public int SoftToneFrequency
- {
- get => m_SoftToneFrequency;
-
- set
- {
- lock (_syncLock)
- {
- if (IsInSoftToneMode == false)
- {
- var setupResult = WiringPi.SoftToneCreate(PinNumber);
- if (setupResult != 0)
- {
- throw new InvalidOperationException(
- $"Unable to initialize soft tone on pin {PinNumber}. Error Code: {setupResult}");
- }
- }
-
- WiringPi.SoftToneWrite(PinNumber, value);
- m_SoftToneFrequency = value;
- }
- }
- }
-
- #endregion
-
- #region Software PWM Members
-
- ///
- /// Gets a value indicating whether this pin is in software based PWM mode.
- ///
- ///
- /// true if this instance is in soft PWM mode; otherwise, false.
- ///
- public bool IsInSoftPwmMode => m_SoftPwmValue >= 0;
-
- ///
- /// Gets or sets the software PWM value on the pin.
- ///
- ///
- /// The soft PWM value.
- ///
- /// StartSoftPwm
- public int SoftPwmValue
- {
- get => m_SoftPwmValue;
-
- set
- {
- lock (_syncLock)
- {
- if (IsInSoftPwmMode && value >= 0)
- {
- WiringPi.SoftPwmWrite(PinNumber, value);
- m_SoftPwmValue = value;
- }
- else
- {
- throw new InvalidOperationException($"Software PWM requires a call to {nameof(StartSoftPwm)}.");
- }
- }
- }
- }
-
- ///
- /// Gets the software PWM range used upon starting the PWM.
- ///
- public int SoftPwmRange { get; private set; } = -1;
-
- ///
- /// Starts the software based PWM on this pin.
- ///
- /// The value.
- /// The range.
- /// When the pin does not suppoert PWM
- /// StartSoftPwm
- /// or
- public void StartSoftPwm(int value, int range)
- {
- lock (_syncLock)
- {
- if (Capabilities.Contains(PinCapability.GP) == false)
- throw new NotSupportedException($"Pin {PinNumber} does not support software PWM");
-
- if (IsInSoftPwmMode)
- throw new InvalidOperationException($"{nameof(StartSoftPwm)} has already been called.");
-
- var startResult = WiringPi.SoftPwmCreate(PinNumber, value, range);
-
- if (startResult == 0)
- {
- m_SoftPwmValue = value;
- SoftPwmRange = range;
- }
- else
- {
- throw new InvalidOperationException(
- $"Could not start software based PWM on pin {PinNumber}. Error code: {startResult}");
- }
- }
- }
-
- #endregion
-
- #region Output Mode (Write) Members
-
- ///
- /// Writes the specified pin value.
- /// This method performs a digital write
- ///
- /// The value.
- public void Write(GpioPinValue value)
- {
- lock (_syncLock)
- {
- if (PinMode != GpioPinDriveMode.Output)
- {
- throw new InvalidOperationException(
- $"Unable to write to pin {PinNumber} because operating mode is {PinMode}."
- + $" Writes are only allowed if {nameof(PinMode)} is set to {GpioPinDriveMode.Output}");
- }
-
- WiringPi.DigitalWrite(PinNumber, (int)value);
- }
- }
-
- ///
- /// Writes the value asynchronously.
- ///
- /// The value.
- /// The awaitable task
- public Task WriteAsync(GpioPinValue value) => Task.Run(() => { Write(value); });
-
- ///
- /// Writes the specified bit value.
- /// This method performs a digital write
- ///
- /// if set to true [value].
- public void Write(bool value)
- => Write(value ? GpioPinValue.High : GpioPinValue.Low);
-
- ///
- /// Writes the specified bit value.
- /// This method performs a digital write
- ///
- /// The value.
- ///
- /// The awaitable task
- ///
- public Task WriteAsync(bool value) => Task.Run(() => { Write(value); });
-
- ///
- /// Writes the specified value. 0 for low, any other value for high
- /// This method performs a digital write
- ///
- /// The value.
- public void Write(int value) => Write(value != 0 ? GpioPinValue.High : GpioPinValue.Low);
-
- ///
- /// Writes the specified value. 0 for low, any other value for high
- /// This method performs a digital write
- ///
- /// The value.
- /// The awaitable task
- public Task WriteAsync(int value) => Task.Run(() => { Write(value); });
-
- ///
- /// Writes the specified value as an analog level.
- /// You will need to register additional analog modules to enable this function for devices such as the Gertboard.
- ///
- /// The value.
- public void WriteLevel(int value)
- {
- lock (_syncLock)
- {
- if (PinMode != GpioPinDriveMode.Output)
- {
- throw new InvalidOperationException(
- $"Unable to write to pin {PinNumber} because operating mode is {PinMode}."
- + $" Writes are only allowed if {nameof(PinMode)} is set to {GpioPinDriveMode.Output}");
- }
-
- WiringPi.AnalogWrite(PinNumber, value);
- }
- }
-
- ///
- /// Writes the specified value as an analog level.
- /// You will need to register additional analog modules to enable this function for devices such as the Gertboard.
- ///
- /// The value.
- /// The awaitable task
- public Task WriteLevelAsync(int value) => Task.Run(() => { WriteLevel(value); });
-
- #endregion
-
- #region Input Mode (Read) Members
-
- ///
- /// Wait for specific pin status
- ///
- /// status to check
- /// timeout to reach status
- /// true/false
- public bool WaitForValue(GpioPinValue status, int timeOutMillisecond)
- {
- if (PinMode != GpioPinDriveMode.Input)
- {
- throw new InvalidOperationException(
- $"Unable to read from pin {PinNumber} because operating mode is {PinMode}."
- + $" Reads are only allowed if {nameof(PinMode)} is set to {GpioPinDriveMode.Input}");
- }
-
- var hrt = new HighResolutionTimer();
- hrt.Start();
- do
- {
- if (ReadValue() == status)
- return true;
-
- Pi.Timing.SleepMicroseconds(101); // 101 uses nanosleep as opposed to a loop.
- }
- while (hrt.ElapsedMilliseconds <= timeOutMillisecond);
-
- return false;
- }
-
- ///
- /// Reads the digital value on the pin as a boolean value.
- ///
- /// The state of the pin
- public bool Read()
- {
- lock (_syncLock)
- {
- if (PinMode != GpioPinDriveMode.Input && PinMode != GpioPinDriveMode.Output)
- {
- throw new InvalidOperationException(
- $"Unable to read from pin {PinNumber} because operating mode is {PinMode}."
- + $" Reads are only allowed if {nameof(PinMode)} is set to {GpioPinDriveMode.Input} or {GpioPinDriveMode.Output}");
- }
-
- return WiringPi.DigitalRead(PinNumber) != 0;
- }
- }
-
- ///
- /// Reads the digital value on the pin as a boolean value.
- ///
- /// The state of the pin
- public Task ReadAsync() => Task.Run(() => Read());
-
- ///
- /// Reads the digital value on the pin as a High or Low value.
- ///
- /// The state of the pin
- public GpioPinValue ReadValue()
- => Read() ? GpioPinValue.High : GpioPinValue.Low;
-
- ///
- /// Reads the digital value on the pin as a High or Low value.
- ///
- /// The state of the pin
- public Task ReadValueAsync() => Task.Run(() => ReadValue());
-
- ///
- /// Reads the analog value on the pin.
- /// This returns the value read on the supplied analog input pin. You will need to register
- /// additional analog modules to enable this function for devices such as the Gertboard,
- /// quick2Wire analog board, etc.
- ///
- /// The analog level
- /// When the pin mode is not configured as an input.
- public int ReadLevel()
- {
- lock (_syncLock)
- {
- if (PinMode != GpioPinDriveMode.Input)
- {
- throw new InvalidOperationException(
- $"Unable to read from pin {PinNumber} because operating mode is {PinMode}."
- + $" Reads are only allowed if {nameof(PinMode)} is set to {GpioPinDriveMode.Input}");
- }
-
- return WiringPi.AnalogRead(PinNumber);
- }
- }
-
- ///
- /// Reads the analog value on the pin.
- /// This returns the value read on the supplied analog input pin. You will need to register
- /// additional analog modules to enable this function for devices such as the Gertboard,
- /// quick2Wire analog board, etc.
- ///
- /// The analog level
- public Task ReadLevelAsync() => Task.Run(() => ReadLevel());
-
- #endregion
-
- #region Interrupts
-
- ///
- /// Registers the interrupt callback on the pin. Pin mode has to be set to Input.
- ///
- /// The edge detection.
- /// The callback.
- /// callback
- ///
- /// An interrupt callback was already registered.
- /// or
- /// RegisterInterruptCallback
- ///
- public void RegisterInterruptCallback(EdgeDetection edgeDetection, InterruptServiceRoutineCallback callback)
- {
- if (callback == null)
- throw new ArgumentException($"{nameof(callback)} cannot be null");
-
- if (InterruptCallback != null)
- throw new InvalidOperationException("An interrupt callback was already registered.");
-
- if (PinMode != GpioPinDriveMode.Input)
- {
- throw new InvalidOperationException(
- $"Unable to {nameof(RegisterInterruptCallback)} for pin {PinNumber} because operating mode is {PinMode}."
- + $" Calling {nameof(RegisterInterruptCallback)} is only allowed if {nameof(PinMode)} is set to {GpioPinDriveMode.Input}");
- }
-
- lock (_syncLock)
- {
- var registerResult = WiringPi.WiringPiISR(PinNumber, (int)edgeDetection, callback);
- if (registerResult == 0)
- {
- InterruptEdgeDetection = edgeDetection;
- InterruptCallback = callback;
- }
- else
- {
- HardwareException.Throw(nameof(GpioPin), nameof(RegisterInterruptCallback));
- }
- }
- }
-
- #endregion
- }
+ /// The wiring pi pin number.
+ /// The header pin number.
+ private GpioPin(WiringPiPin wiringPiPinNumber, Int32 headerPinNumber) {
+ this.PinNumber = (Int32)wiringPiPinNumber;
+ this.WiringPiPinNumber = wiringPiPinNumber;
+ this.BcmPinNumber = GpioController.WiringPiToBcmPinNumber((Int32)wiringPiPinNumber);
+ this.HeaderPinNumber = headerPinNumber;
+ this.Header = (this.PinNumber >= 17 && this.PinNumber <= 20) ? GpioHeader.P5 : GpioHeader.P1;
+ }
+
+ #endregion
+
+ #region Pin Properties
+
+ ///
+ /// Gets or sets the Wiring Pi pin number as an integer.
+ ///
+ public Int32 PinNumber {
+ get;
+ }
+
+ ///
+ /// Gets the WiringPi Pin number
+ ///
+ public WiringPiPin WiringPiPinNumber {
+ get;
+ }
+
+ ///
+ /// Gets the BCM chip (hardware) pin number.
+ ///
+ public Int32 BcmPinNumber {
+ get;
+ }
+
+ ///
+ /// Gets or the physical header (physical board) pin number.
+ ///
+ public Int32 HeaderPinNumber {
+ get;
+ }
+
+ ///
+ /// Gets the pin's header (physical board) location.
+ ///
+ public GpioHeader Header {
+ get;
+ }
+
+ ///
+ /// Gets the friendly name of the pin.
+ ///
+ public String Name {
+ get; private set;
+ }
+
+ ///
+ /// Gets the hardware mode capabilities of this pin.
+ ///
+ public PinCapability[] Capabilities {
+ get; private set;
+ }
+
+ #endregion
+
+ #region Hardware-Specific Properties
+
+ ///
+ /// Gets or sets the pin operating mode.
+ ///
+ ///
+ /// The pin mode.
+ ///
+ /// Thrown when a pin does not support the given operation mode.
+ public GpioPinDriveMode PinMode {
+ get => this.m_PinMode;
+
+ set {
+ lock(this._syncLock) {
+ GpioPinDriveMode mode = value;
+ if(mode == GpioPinDriveMode.GpioClock && this.Capabilities.Contains(PinCapability.GPCLK) == false ||
+ mode == GpioPinDriveMode.PwmOutput && this.Capabilities.Contains(PinCapability.PWM) == false ||
+ mode == GpioPinDriveMode.Input && this.Capabilities.Contains(PinCapability.GP) == false ||
+ mode == GpioPinDriveMode.Output && this.Capabilities.Contains(PinCapability.GP) == false) {
+ throw new NotSupportedException(
+ $"Pin {this.WiringPiPinNumber} '{this.Name}' does not support mode '{mode}'. Pin capabilities are limited to: {String.Join(", ", this.Capabilities)}");
+ }
+
+ WiringPi.PinMode(this.PinNumber, (Int32)mode);
+ this.m_PinMode = mode;
+ }
+ }
+ }
+
+ ///
+ /// Gets the interrupt callback. Returns null if no interrupt
+ /// has been registered.
+ ///
+ public InterruptServiceRoutineCallback InterruptCallback {
+ get; private set;
+ }
+
+ ///
+ /// Gets the interrupt edge detection mode.
+ ///
+ public EdgeDetection InterruptEdgeDetection { get; private set; } = EdgeDetection.ExternalSetup;
+
+ #endregion
+
+ #region Hardware PWM Members
+
+ ///
+ /// This sets or gets the pull-up or pull-down resistor mode on the pin, which should be set as an input.
+ /// Unlike the Arduino, the BCM2835 has both pull-up an down internal resistors.
+ /// The parameter pud should be; PUD_OFF, (no pull up/down), PUD_DOWN (pull to ground) or PUD_UP (pull to 3.3v)
+ /// The internal pull up/down resistors have a value of approximately 50KΩ on the Raspberry Pi.
+ ///
+ public GpioPinResistorPullMode InputPullMode {
+ get => this.PinMode == GpioPinDriveMode.Input ? this.m_ResistorPullMode : GpioPinResistorPullMode.Off;
+
+ set {
+ lock(this._syncLock) {
+ if(this.PinMode != GpioPinDriveMode.Input) {
+ this.m_ResistorPullMode = GpioPinResistorPullMode.Off;
+ throw new InvalidOperationException(
+ $"Unable to set the {nameof(this.InputPullMode)} for pin {this.PinNumber} because operating mode is {this.PinMode}."
+ + $" Setting the {nameof(this.InputPullMode)} is only allowed if {nameof(this.PinMode)} is set to {GpioPinDriveMode.Input}");
+ }
+
+ WiringPi.PullUpDnControl(this.PinNumber, (Int32)value);
+ this.m_ResistorPullMode = value;
+ }
+ }
+ }
+
+ ///
+ /// Gets or sets the PWM register. Values should be between 0 and 1024
+ ///
+ ///
+ /// The PWM register.
+ ///
+ public Int32 PwmRegister {
+ get => this.m_PwmRegister;
+
+ set {
+ lock(this._syncLock) {
+ if(this.PinMode != GpioPinDriveMode.PwmOutput) {
+ this.m_PwmRegister = 0;
+
+ throw new InvalidOperationException(
+ $"Unable to write PWM register for pin {this.PinNumber} because operating mode is {this.PinMode}."
+ + $" Writing the PWM register is only allowed if {nameof(this.PinMode)} is set to {GpioPinDriveMode.PwmOutput}");
+ }
+
+ Int32 val = value.Clamp(0, 1024);
+
+ WiringPi.PwmWrite(this.PinNumber, val);
+ this.m_PwmRegister = val;
+ }
+ }
+ }
+
+ ///
+ /// The PWM generator can run in 2 modes – “balanced” and “mark:space”. The mark:space mode is traditional,
+ /// however the default mode in the Pi is “balanced”.
+ ///
+ ///
+ /// The PWM mode.
+ ///
+ /// When pin mode is not set a Pwn output
+ public PwmMode PwmMode {
+ get => this.PinMode == GpioPinDriveMode.PwmOutput ? this.m_PwmMode : PwmMode.Balanced;
+
+ set {
+ lock(this._syncLock) {
+ if(this.PinMode != GpioPinDriveMode.PwmOutput) {
+ this.m_PwmMode = PwmMode.Balanced;
+
+ throw new InvalidOperationException(
+ $"Unable to set PWM mode for pin {this.PinNumber} because operating mode is {this.PinMode}."
+ + $" Setting the PWM mode is only allowed if {nameof(this.PinMode)} is set to {GpioPinDriveMode.PwmOutput}");
+ }
+
+ WiringPi.PwmSetMode((Int32)value);
+ this.m_PwmMode = value;
+ }
+ }
+ }
+
+ ///
+ /// This sets the range register in the PWM generator. The default is 1024.
+ ///
+ ///
+ /// The PWM range.
+ ///
+ /// When pin mode is not set to PWM output
+ public UInt32 PwmRange {
+ get => this.PinMode == GpioPinDriveMode.PwmOutput ? this.m_PwmRange : 0;
+
+ set {
+ lock(this._syncLock) {
+ if(this.PinMode != GpioPinDriveMode.PwmOutput) {
+ this.m_PwmRange = 1024;
+
+ throw new InvalidOperationException(
+ $"Unable to set PWM range for pin {this.PinNumber} because operating mode is {this.PinMode}."
+ + $" Setting the PWM range is only allowed if {nameof(this.PinMode)} is set to {GpioPinDriveMode.PwmOutput}");
+ }
+
+ WiringPi.PwmSetRange(value);
+ this.m_PwmRange = value;
+ }
+ }
+ }
+
+ ///
+ /// Gets or sets the PWM clock divisor.
+ ///
+ ///
+ /// The PWM clock divisor.
+ ///
+ /// When pin mode is not set to PWM output
+ public Int32 PwmClockDivisor {
+ get => this.PinMode == GpioPinDriveMode.PwmOutput ? this.m_PwmClockDivisor : 0;
+
+ set {
+ lock(this._syncLock) {
+ if(this.PinMode != GpioPinDriveMode.PwmOutput) {
+ this.m_PwmClockDivisor = 1;
+
+ throw new InvalidOperationException(
+ $"Unable to set PWM range for pin {this.PinNumber} because operating mode is {this.PinMode}."
+ + $" Setting the PWM range is only allowed if {nameof(this.PinMode)} is set to {GpioPinDriveMode.PwmOutput}");
+ }
+
+ WiringPi.PwmSetClock(value);
+ this.m_PwmClockDivisor = value;
+ }
+ }
+ }
+
+ #endregion
+
+ #region Software Tone Members
+
+ ///
+ /// Gets a value indicating whether this instance is in software based tone generator mode.
+ ///
+ ///
+ /// true if this instance is in soft tone mode; otherwise, false.
+ ///
+ public Boolean IsInSoftToneMode => this.m_SoftToneFrequency >= 0;
+
+ ///
+ /// Gets or sets the soft tone frequency. 0 to 5000 Hz is typical
+ ///
+ ///
+ /// The soft tone frequency.
+ ///
+ /// When soft tones cannot be initialized on the pin
+ public Int32 SoftToneFrequency {
+ get => this.m_SoftToneFrequency;
+
+ set {
+ lock(this._syncLock) {
+ if(this.IsInSoftToneMode == false) {
+ Int32 setupResult = WiringPi.SoftToneCreate(this.PinNumber);
+ if(setupResult != 0) {
+ throw new InvalidOperationException(
+ $"Unable to initialize soft tone on pin {this.PinNumber}. Error Code: {setupResult}");
+ }
+ }
+
+ WiringPi.SoftToneWrite(this.PinNumber, value);
+ this.m_SoftToneFrequency = value;
+ }
+ }
+ }
+
+ #endregion
+
+ #region Software PWM Members
+
+ ///
+ /// Gets a value indicating whether this pin is in software based PWM mode.
+ ///
+ ///
+ /// true if this instance is in soft PWM mode; otherwise, false.
+ ///
+ public Boolean IsInSoftPwmMode => this.m_SoftPwmValue >= 0;
+
+ ///
+ /// Gets or sets the software PWM value on the pin.
+ ///
+ ///
+ /// The soft PWM value.
+ ///
+ /// StartSoftPwm
+ public Int32 SoftPwmValue {
+ get => this.m_SoftPwmValue;
+
+ set {
+ lock(this._syncLock) {
+ if(this.IsInSoftPwmMode && value >= 0) {
+ WiringPi.SoftPwmWrite(this.PinNumber, value);
+ this.m_SoftPwmValue = value;
+ } else {
+ throw new InvalidOperationException($"Software PWM requires a call to {nameof(StartSoftPwm)}.");
+ }
+ }
+ }
+ }
+
+ ///
+ /// Gets the software PWM range used upon starting the PWM.
+ ///
+ public Int32 SoftPwmRange { get; private set; } = -1;
+
+ ///
+ /// Starts the software based PWM on this pin.
+ ///
+ /// The value.
+ /// The range.
+ /// When the pin does not suppoert PWM
+ /// StartSoftPwm
+ /// or
+ public void StartSoftPwm(Int32 value, Int32 range) {
+ lock(this._syncLock) {
+ if(this.Capabilities.Contains(PinCapability.GP) == false) {
+ throw new NotSupportedException($"Pin {this.PinNumber} does not support software PWM");
+ }
+
+ if(this.IsInSoftPwmMode) {
+ throw new InvalidOperationException($"{nameof(StartSoftPwm)} has already been called.");
+ }
+
+ Int32 startResult = WiringPi.SoftPwmCreate(this.PinNumber, value, range);
+
+ if(startResult == 0) {
+ this.m_SoftPwmValue = value;
+ this.SoftPwmRange = range;
+ } else {
+ throw new InvalidOperationException(
+ $"Could not start software based PWM on pin {this.PinNumber}. Error code: {startResult}");
+ }
+ }
+ }
+
+ #endregion
+
+ #region Output Mode (Write) Members
+
+ ///
+ /// Writes the specified pin value.
+ /// This method performs a digital write
+ ///
+ /// The value.
+ public void Write(GpioPinValue value) {
+ lock(this._syncLock) {
+ if(this.PinMode != GpioPinDriveMode.Output) {
+ throw new InvalidOperationException(
+ $"Unable to write to pin {this.PinNumber} because operating mode is {this.PinMode}."
+ + $" Writes are only allowed if {nameof(this.PinMode)} is set to {GpioPinDriveMode.Output}");
+ }
+
+ WiringPi.DigitalWrite(this.PinNumber, (Int32)value);
+ }
+ }
+
+ ///
+ /// Writes the value asynchronously.
+ ///
+ /// The value.
+ /// The awaitable task
+ public Task WriteAsync(GpioPinValue value) => Task.Run(() => this.Write(value));
+
+ ///
+ /// Writes the specified bit value.
+ /// This method performs a digital write
+ ///
+ /// if set to true [value].
+ public void Write(Boolean value)
+ => this.Write(value ? GpioPinValue.High : GpioPinValue.Low);
+
+ ///
+ /// Writes the specified bit value.
+ /// This method performs a digital write
+ ///
+ /// The value.
+ ///
+ /// The awaitable task
+ ///
+ public Task WriteAsync(Boolean value) => Task.Run(() => this.Write(value));
+
+ ///
+ /// Writes the specified value. 0 for low, any other value for high
+ /// This method performs a digital write
+ ///
+ /// The value.
+ public void Write(Int32 value) => this.Write(value != 0 ? GpioPinValue.High : GpioPinValue.Low);
+
+ ///
+ /// Writes the specified value. 0 for low, any other value for high
+ /// This method performs a digital write
+ ///
+ /// The value.
+ /// The awaitable task
+ public Task WriteAsync(Int32 value) => Task.Run(() => this.Write(value));
+
+ ///
+ /// Writes the specified value as an analog level.
+ /// You will need to register additional analog modules to enable this function for devices such as the Gertboard.
+ ///
+ /// The value.
+ public void WriteLevel(Int32 value) {
+ lock(this._syncLock) {
+ if(this.PinMode != GpioPinDriveMode.Output) {
+ throw new InvalidOperationException(
+ $"Unable to write to pin {this.PinNumber} because operating mode is {this.PinMode}."
+ + $" Writes are only allowed if {nameof(this.PinMode)} is set to {GpioPinDriveMode.Output}");
+ }
+
+ WiringPi.AnalogWrite(this.PinNumber, value);
+ }
+ }
+
+ ///
+ /// Writes the specified value as an analog level.
+ /// You will need to register additional analog modules to enable this function for devices such as the Gertboard.
+ ///
+ /// The value.
+ /// The awaitable task
+ public Task WriteLevelAsync(Int32 value) => Task.Run(() => this.WriteLevel(value));
+
+ #endregion
+
+ #region Input Mode (Read) Members
+
+ ///
+ /// Wait for specific pin status
+ ///
+ /// status to check
+ /// timeout to reach status
+ /// true/false
+ public Boolean WaitForValue(GpioPinValue status, Int32 timeOutMillisecond) {
+ if(this.PinMode != GpioPinDriveMode.Input) {
+ throw new InvalidOperationException(
+ $"Unable to read from pin {this.PinNumber} because operating mode is {this.PinMode}."
+ + $" Reads are only allowed if {nameof(this.PinMode)} is set to {GpioPinDriveMode.Input}");
+ }
+
+ HighResolutionTimer hrt = new HighResolutionTimer();
+ hrt.Start();
+ do {
+ if(this.ReadValue() == status) {
+ return true;
+ }
+
+ Pi.Timing.SleepMicroseconds(101); // 101 uses nanosleep as opposed to a loop.
+ }
+ while(hrt.ElapsedMilliseconds <= timeOutMillisecond);
+
+ return false;
+ }
+
+ ///
+ /// Reads the digital value on the pin as a boolean value.
+ ///
+ /// The state of the pin
+ public Boolean Read() {
+ lock(this._syncLock) {
+ if(this.PinMode != GpioPinDriveMode.Input && this.PinMode != GpioPinDriveMode.Output) {
+ throw new InvalidOperationException(
+ $"Unable to read from pin {this.PinNumber} because operating mode is {this.PinMode}."
+ + $" Reads are only allowed if {nameof(this.PinMode)} is set to {GpioPinDriveMode.Input} or {GpioPinDriveMode.Output}");
+ }
+
+ return WiringPi.DigitalRead(this.PinNumber) != 0;
+ }
+ }
+
+ ///
+ /// Reads the digital value on the pin as a boolean value.
+ ///
+ /// The state of the pin
+ public Task ReadAsync() => Task.Run(() => this.Read());
+
+ ///
+ /// Reads the digital value on the pin as a High or Low value.
+ ///
+ /// The state of the pin
+ public GpioPinValue ReadValue()
+ => this.Read() ? GpioPinValue.High : GpioPinValue.Low;
+
+ ///
+ /// Reads the digital value on the pin as a High or Low value.
+ ///
+ /// The state of the pin
+ public Task ReadValueAsync() => Task.Run(() => this.ReadValue());
+
+ ///
+ /// Reads the analog value on the pin.
+ /// This returns the value read on the supplied analog input pin. You will need to register
+ /// additional analog modules to enable this function for devices such as the Gertboard,
+ /// quick2Wire analog board, etc.
+ ///
+ /// The analog level
+ /// When the pin mode is not configured as an input.
+ public Int32 ReadLevel() {
+ lock(this._syncLock) {
+ if(this.PinMode != GpioPinDriveMode.Input) {
+ throw new InvalidOperationException(
+ $"Unable to read from pin {this.PinNumber} because operating mode is {this.PinMode}."
+ + $" Reads are only allowed if {nameof(this.PinMode)} is set to {GpioPinDriveMode.Input}");
+ }
+
+ return WiringPi.AnalogRead(this.PinNumber);
+ }
+ }
+
+ ///
+ /// Reads the analog value on the pin.
+ /// This returns the value read on the supplied analog input pin. You will need to register
+ /// additional analog modules to enable this function for devices such as the Gertboard,
+ /// quick2Wire analog board, etc.
+ ///
+ /// The analog level
+ public Task ReadLevelAsync() => Task.Run(() => this.ReadLevel());
+
+ #endregion
+
+ #region Interrupts
+
+ ///
+ /// Registers the interrupt callback on the pin. Pin mode has to be set to Input.
+ ///
+ /// The edge detection.
+ /// The callback.
+ /// callback
+ ///
+ /// An interrupt callback was already registered.
+ /// or
+ /// RegisterInterruptCallback
+ ///
+ public void RegisterInterruptCallback(EdgeDetection edgeDetection, InterruptServiceRoutineCallback callback) {
+ if(callback == null) {
+ throw new ArgumentException($"{nameof(callback)} cannot be null");
+ }
+
+ if(this.InterruptCallback != null) {
+ throw new InvalidOperationException("An interrupt callback was already registered.");
+ }
+
+ if(this.PinMode != GpioPinDriveMode.Input) {
+ throw new InvalidOperationException(
+ $"Unable to {nameof(RegisterInterruptCallback)} for pin {this.PinNumber} because operating mode is {this.PinMode}."
+ + $" Calling {nameof(RegisterInterruptCallback)} is only allowed if {nameof(this.PinMode)} is set to {GpioPinDriveMode.Input}");
+ }
+
+ lock(this._syncLock) {
+ Int32 registerResult = WiringPi.WiringPiISR(this.PinNumber, (Int32)edgeDetection, callback);
+ if(registerResult == 0) {
+ this.InterruptEdgeDetection = edgeDetection;
+ this.InterruptCallback = callback;
+ } else {
+ HardwareException.Throw(nameof(GpioPin), nameof(RegisterInterruptCallback));
+ }
+ }
+ }
+
+ #endregion
+ }
}
diff --git a/Unosquare.RaspberryIO/Gpio/I2CBus.cs b/Unosquare.RaspberryIO/Gpio/I2CBus.cs
index cbecc3c..0f530c6 100644
--- a/Unosquare.RaspberryIO/Gpio/I2CBus.cs
+++ b/Unosquare.RaspberryIO/Gpio/I2CBus.cs
@@ -1,93 +1,87 @@
-namespace Unosquare.RaspberryIO.Gpio
-{
- using Native;
- using Swan.Abstractions;
- using System.Collections.Generic;
- using System.Collections.ObjectModel;
- using System.Linq;
-
- ///
- /// 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(_devices.Values.ToArray());
-
- ///
- /// Gets the with the specified device identifier.
- ///
- ///
- /// The .
- ///
- /// The device identifier.
- /// A reference to an I2C device
- public I2CDevice this[int deviceId] => GetDeviceById(deviceId);
-
- ///
- /// Gets the device by identifier.
- ///
- /// The device identifier.
- /// The device reference
- public I2CDevice GetDeviceById(int deviceId)
- {
- lock (SyncRoot)
- {
- return _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(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;
- }
- }
-
- ///
- /// 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 int SetupFileDescriptor(int deviceId)
- {
- lock (SyncRoot)
- {
- return WiringPi.WiringPiI2CSetup(deviceId);
- }
- }
- }
-}
+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);
+ }
+ }
+ }
+}
diff --git a/Unosquare.RaspberryIO/Gpio/I2CDevice.cs b/Unosquare.RaspberryIO/Gpio/I2CDevice.cs
index b9d42bf..ffefc24 100644
--- a/Unosquare.RaspberryIO/Gpio/I2CDevice.cs
+++ b/Unosquare.RaspberryIO/Gpio/I2CDevice.cs
@@ -1,195 +1,193 @@
-namespace Unosquare.RaspberryIO.Gpio
-{
- using System;
- using System.Threading.Tasks;
- using Native;
-
- ///
- /// 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(int deviceId, int fileDescriptor)
- {
- DeviceId = deviceId;
- FileDescriptor = fileDescriptor;
- }
-
- ///
- /// Gets the device identifier.
- ///
- ///
- /// The device identifier.
- ///
- public int DeviceId { get; }
-
- ///
- /// Gets the standard POSIX file descriptor.
- ///
- ///
- /// The file descriptor.
- ///
- public int FileDescriptor { get; }
-
- ///
- /// Reads a byte from the specified file descriptor
- ///
- /// The byte from device
- public byte Read()
- {
- lock (_syncLock)
- {
- var result = WiringPi.WiringPiI2CRead(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(() => Read());
-
- ///
- /// Reads a buffer of the specified length, one byte at a time
- ///
- /// The length.
- /// The byte array from device
- public byte[] Read(int length)
- {
- lock (_syncLock)
- {
- var buffer = new byte[length];
- for (var i = 0; i < length; i++)
- {
- var result = WiringPi.WiringPiI2CRead(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(int length) => Task.Run(() => Read(length));
-
- ///
- /// Writes a byte of data the specified file descriptor.
- ///
- /// The data.
- public void Write(byte data)
- {
- lock (_syncLock)
- {
- var result = WiringPi.WiringPiI2CWrite(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(() => { Write(data); });
-
- ///
- /// Writes a set of bytes to the specified file descriptor.
- ///
- /// The data.
- public void Write(byte[] data)
- {
- lock (_syncLock)
- {
- foreach (var b in data)
- {
- var result = WiringPi.WiringPiI2CWrite(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)
- {
- return Task.Run(() => { Write(data); });
- }
-
- ///
- /// These write an 8 or 16-bit data value into the device register indicated.
- ///
- /// The register.
- /// The data.
- public void WriteAddressByte(int address, byte data)
- {
- lock (_syncLock)
- {
- var result = WiringPi.WiringPiI2CWriteReg8(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(int address, ushort data)
- {
- lock (_syncLock)
- {
- var result = WiringPi.WiringPiI2CWriteReg16(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(int address)
- {
- lock (_syncLock)
- {
- var result = WiringPi.WiringPiI2CReadReg8(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 ushort ReadAddressWord(int address)
- {
- lock (_syncLock)
- {
- var result = WiringPi.WiringPiI2CReadReg16(FileDescriptor, address);
- if (result < 0) HardwareException.Throw(nameof(I2CDevice), nameof(ReadAddressWord));
-
- return Convert.ToUInt16(result);
- }
- }
- }
-}
+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);
+ }
+ }
+ }
+}
diff --git a/Unosquare.RaspberryIO/Gpio/SpiBus.cs b/Unosquare.RaspberryIO/Gpio/SpiBus.cs
index ba9ebc6..7ca7a73 100644
--- a/Unosquare.RaspberryIO/Gpio/SpiBus.cs
+++ b/Unosquare.RaspberryIO/Gpio/SpiBus.cs
@@ -1,72 +1,72 @@
-namespace Unosquare.RaspberryIO.Gpio
-{
- using Swan.Abstractions;
-
+using System;
+using Unosquare.Swan.Abstractions;
+
+namespace Unosquare.RaspberryIO.Gpio {
+ ///
+ /// The SPI Bus containing the 2 SPI channels
+ ///
+ public class SpiBus : SingletonBase {
///
- /// The SPI Bus containing the 2 SPI channels
+ /// Prevents a default instance of the class from being created.
///
- public class SpiBus : SingletonBase
- {
- ///
- /// Prevents a default instance of the class from being created.
- ///
- private SpiBus()
- {
- // placeholder
- }
-
- #region SPI Access
-
- ///
- /// Gets or sets the channel 0 frequency in Hz.
- ///
- ///
- /// The channel0 frequency.
- ///
- public int Channel0Frequency { get; set; }
-
- ///
- /// Gets the SPI bus on channel 1.
- ///
- ///
- /// The channel0.
- ///
- public SpiChannel Channel0
- {
- get
- {
- if (Channel0Frequency == 0)
- Channel0Frequency = SpiChannel.DefaultFrequency;
-
- return SpiChannel.Retrieve(SpiChannelNumber.Channel0, Channel0Frequency);
- }
- }
-
- ///
- /// Gets or sets the channel 1 frequency in Hz
- ///
- ///
- /// The channel1 frequency.
- ///
- public int Channel1Frequency { get; set; }
-
- ///
- /// Gets the SPI bus on channel 1.
- ///
- ///
- /// The channel1.
- ///
- public SpiChannel Channel1
- {
- get
- {
- if (Channel1Frequency == 0)
- Channel1Frequency = SpiChannel.DefaultFrequency;
-
- return SpiChannel.Retrieve(SpiChannelNumber.Channel1, Channel1Frequency);
- }
- }
-
- #endregion
- }
+ private SpiBus() {
+ // placeholder
+ }
+
+ #region SPI Access
+
+ ///
+ /// Gets or sets the channel 0 frequency in Hz.
+ ///
+ ///
+ /// The channel0 frequency.
+ ///
+ public Int32 Channel0Frequency {
+ get; set;
+ }
+
+ ///
+ /// Gets the SPI bus on channel 1.
+ ///
+ ///
+ /// The channel0.
+ ///
+ public SpiChannel Channel0 {
+ get {
+ if(this.Channel0Frequency == 0) {
+ this.Channel0Frequency = SpiChannel.DefaultFrequency;
+ }
+
+ return SpiChannel.Retrieve(SpiChannelNumber.Channel0, this.Channel0Frequency);
+ }
+ }
+
+ ///
+ /// Gets or sets the channel 1 frequency in Hz
+ ///
+ ///
+ /// The channel1 frequency.
+ ///
+ public Int32 Channel1Frequency {
+ get; set;
+ }
+
+ ///
+ /// Gets the SPI bus on channel 1.
+ ///
+ ///
+ /// The channel1.
+ ///
+ public SpiChannel Channel1 {
+ get {
+ if(this.Channel1Frequency == 0) {
+ this.Channel1Frequency = SpiChannel.DefaultFrequency;
+ }
+
+ return SpiChannel.Retrieve(SpiChannelNumber.Channel1, this.Channel1Frequency);
+ }
+ }
+
+ #endregion
+ }
}
diff --git a/Unosquare.RaspberryIO/Gpio/SpiChannel.cs b/Unosquare.RaspberryIO/Gpio/SpiChannel.cs
index 8e5f90e..eadfdeb 100644
--- a/Unosquare.RaspberryIO/Gpio/SpiChannel.cs
+++ b/Unosquare.RaspberryIO/Gpio/SpiChannel.cs
@@ -1,154 +1,154 @@
-namespace Unosquare.RaspberryIO.Gpio
-{
- using Native;
- using Swan;
- using System;
- using System.Collections.Generic;
- using System.Threading.Tasks;
-
+using Unosquare.RaspberryIO.Native;
+using Unosquare.Swan;
+using System;
+using System.Collections.Generic;
+using System.Threading.Tasks;
+
+namespace Unosquare.RaspberryIO.Gpio {
+ ///
+ /// Provides access to using the SPI buses on the GPIO.
+ /// SPI is a bus that works like a ring shift register
+ /// The number of bytes pushed is equal to the number of bytes received.
+ ///
+ public sealed class SpiChannel {
///
- /// Provides access to using the SPI buses on the GPIO.
- /// SPI is a bus that works like a ring shift register
- /// The number of bytes pushed is equal to the number of bytes received.
+ /// The minimum frequency of an SPI Channel
///
- public sealed class SpiChannel
- {
- ///
- /// The minimum frequency of an SPI Channel
- ///
- public const int MinFrequency = 500000;
-
- ///
- /// The maximum frequency of an SPI channel
- ///
- public const int MaxFrequency = 32000000;
-
- ///
- /// The default frequency of SPI channels
- /// This is set to 8 Mhz wich is typical in modern hardware.
- ///
- public const int DefaultFrequency = 8000000;
-
- private static readonly object SyncRoot = new object();
- private static readonly Dictionary Buses = new Dictionary();
- private readonly object _syncLock = new object();
-
- ///
- /// Initializes a new instance of the class.
- ///
- /// The channel.
- /// The frequency.
- private SpiChannel(SpiChannelNumber channel, int frequency)
- {
- lock (SyncRoot)
- {
- Frequency = frequency.Clamp(MinFrequency, MaxFrequency);
- Channel = (int)channel;
- FileDescriptor = WiringPi.WiringPiSPISetup((int)channel, Frequency);
-
- if (FileDescriptor < 0)
- {
- HardwareException.Throw(nameof(SpiChannel), channel.ToString());
- }
- }
- }
-
- ///
- /// Gets the standard initialization file descriptor.
- /// anything negative means error.
- ///
- ///
- /// The file descriptor.
- ///
- public int FileDescriptor { get; }
-
- ///
- /// Gets the channel.
- ///
- public int Channel { get; }
-
- ///
- /// Gets the frequency.
- ///
- public int Frequency { get; }
-
- ///
- /// Sends data and simultaneously receives the data in the return buffer
- ///
- /// The buffer.
- /// The read bytes from the ring-style bus
- public byte[] SendReceive(byte[] buffer)
- {
- if (buffer == null || buffer.Length == 0)
- return null;
-
- lock (_syncLock)
- {
- var spiBuffer = new byte[buffer.Length];
- Array.Copy(buffer, spiBuffer, buffer.Length);
-
- var result = WiringPi.WiringPiSPIDataRW(Channel, spiBuffer, spiBuffer.Length);
- if (result < 0) HardwareException.Throw(nameof(SpiChannel), nameof(SendReceive));
-
- return spiBuffer;
- }
- }
-
- ///
- /// Sends data and simultaneously receives the data in the return buffer
- ///
- /// The buffer.
- ///
- /// The read bytes from the ring-style bus
- ///
- public Task SendReceiveAsync(byte[] buffer) => Task.Run(() => SendReceive(buffer));
-
- ///
- /// Writes the specified buffer the the underlying FileDescriptor.
- /// Do not use this method if you expect data back.
- /// This method is efficient if used in a fire-and-forget scenario
- /// like sending data over to those long RGB LED strips
- ///
- /// The buffer.
- public void Write(byte[] buffer)
- {
- lock (_syncLock)
- {
- var result = Standard.Write(FileDescriptor, buffer, buffer.Length);
-
- if (result < 0)
- HardwareException.Throw(nameof(SpiChannel), nameof(Write));
- }
- }
-
- ///
- /// Writes the specified buffer the the underlying FileDescriptor.
- /// Do not use this method if you expect data back.
- /// This method is efficient if used in a fire-and-forget scenario
- /// like sending data over to those long RGB LED strips
- ///
- /// The buffer.
- /// The awaitable task
- public Task WriteAsync(byte[] buffer) => Task.Run(() => { Write(buffer); });
-
- ///
- /// Retrieves the spi bus. If the bus channel is not registered it sets it up automatically.
- /// If it had been previously registered, then the bus is simply returned.
- ///
- /// The channel.
- /// The frequency.
- /// The usable SPI channel
- internal static SpiChannel Retrieve(SpiChannelNumber channel, int frequency)
- {
- lock (SyncRoot)
- {
- if (Buses.ContainsKey(channel))
- return Buses[channel];
-
- var newBus = new SpiChannel(channel, frequency);
- Buses[channel] = newBus;
- return newBus;
- }
- }
- }
+ public const Int32 MinFrequency = 500000;
+
+ ///
+ /// The maximum frequency of an SPI channel
+ ///
+ public const Int32 MaxFrequency = 32000000;
+
+ ///
+ /// The default frequency of SPI channels
+ /// This is set to 8 Mhz wich is typical in modern hardware.
+ ///
+ public const Int32 DefaultFrequency = 8000000;
+
+ private static readonly Object SyncRoot = new Object();
+ private static readonly Dictionary Buses = new Dictionary();
+ private readonly Object _syncLock = new Object();
+
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ /// The channel.
+ /// The frequency.
+ private SpiChannel(SpiChannelNumber channel, Int32 frequency) {
+ lock(SyncRoot) {
+ this.Frequency = frequency.Clamp(MinFrequency, MaxFrequency);
+ this.Channel = (Int32)channel;
+ this.FileDescriptor = WiringPi.WiringPiSPISetup((Int32)channel, this.Frequency);
+
+ if(this.FileDescriptor < 0) {
+ HardwareException.Throw(nameof(SpiChannel), channel.ToString());
+ }
+ }
+ }
+
+ ///
+ /// Gets the standard initialization file descriptor.
+ /// anything negative means error.
+ ///
+ ///
+ /// The file descriptor.
+ ///
+ public Int32 FileDescriptor {
+ get;
+ }
+
+ ///
+ /// Gets the channel.
+ ///
+ public Int32 Channel {
+ get;
+ }
+
+ ///
+ /// Gets the frequency.
+ ///
+ public Int32 Frequency {
+ get;
+ }
+
+ ///
+ /// Sends data and simultaneously receives the data in the return buffer
+ ///
+ /// The buffer.
+ /// The read bytes from the ring-style bus
+ public Byte[] SendReceive(Byte[] buffer) {
+ if(buffer == null || buffer.Length == 0) {
+ return null;
+ }
+
+ lock(this._syncLock) {
+ Byte[] spiBuffer = new Byte[buffer.Length];
+ Array.Copy(buffer, spiBuffer, buffer.Length);
+
+ Int32 result = WiringPi.WiringPiSPIDataRW(this.Channel, spiBuffer, spiBuffer.Length);
+ if(result < 0) {
+ HardwareException.Throw(nameof(SpiChannel), nameof(SendReceive));
+ }
+
+ return spiBuffer;
+ }
+ }
+
+ ///
+ /// Sends data and simultaneously receives the data in the return buffer
+ ///
+ /// The buffer.
+ ///
+ /// The read bytes from the ring-style bus
+ ///
+ public Task SendReceiveAsync(Byte[] buffer) => Task.Run(() => this.SendReceive(buffer));
+
+ ///
+ /// Writes the specified buffer the the underlying FileDescriptor.
+ /// Do not use this method if you expect data back.
+ /// This method is efficient if used in a fire-and-forget scenario
+ /// like sending data over to those long RGB LED strips
+ ///
+ /// The buffer.
+ public void Write(Byte[] buffer) {
+ lock(this._syncLock) {
+ Int32 result = Standard.Write(this.FileDescriptor, buffer, buffer.Length);
+
+ if(result < 0) {
+ HardwareException.Throw(nameof(SpiChannel), nameof(Write));
+ }
+ }
+ }
+
+ ///
+ /// Writes the specified buffer the the underlying FileDescriptor.
+ /// Do not use this method if you expect data back.
+ /// This method is efficient if used in a fire-and-forget scenario
+ /// like sending data over to those long RGB LED strips
+ ///
+ /// The buffer.
+ /// The awaitable task
+ public Task WriteAsync(Byte[] buffer) => Task.Run(() => this.Write(buffer));
+
+ ///
+ /// Retrieves the spi bus. If the bus channel is not registered it sets it up automatically.
+ /// If it had been previously registered, then the bus is simply returned.
+ ///
+ /// The channel.
+ /// The frequency.
+ /// The usable SPI channel
+ internal static SpiChannel Retrieve(SpiChannelNumber channel, Int32 frequency) {
+ lock(SyncRoot) {
+ if(Buses.ContainsKey(channel)) {
+ return Buses[channel];
+ }
+
+ SpiChannel newBus = new SpiChannel(channel, frequency);
+ Buses[channel] = newBus;
+ return newBus;
+ }
+ }
+ }
}
diff --git a/Unosquare.RaspberryIO/Native/Delegates.cs b/Unosquare.RaspberryIO/Native/Delegates.cs
index 6b0cbbd..c270a13 100644
--- a/Unosquare.RaspberryIO/Native/Delegates.cs
+++ b/Unosquare.RaspberryIO/Native/Delegates.cs
@@ -1,12 +1,11 @@
-namespace Unosquare.RaspberryIO.Native
-{
- ///
- /// A delegate defining a callback for an Interrupt Service Routine
- ///
- public delegate void InterruptServiceRoutineCallback();
-
- ///
- /// Defines the body of a thread worker
- ///
- public delegate void ThreadWorker();
+namespace Unosquare.RaspberryIO.Native {
+ ///
+ /// A delegate defining a callback for an Interrupt Service Routine
+ ///
+ public delegate void InterruptServiceRoutineCallback();
+
+ ///
+ /// Defines the body of a thread worker
+ ///
+ public delegate void ThreadWorker();
}
diff --git a/Unosquare.RaspberryIO/Native/HardwareException.cs b/Unosquare.RaspberryIO/Native/HardwareException.cs
index 3ac43b2..fbfda58 100644
--- a/Unosquare.RaspberryIO/Native/HardwareException.cs
+++ b/Unosquare.RaspberryIO/Native/HardwareException.cs
@@ -1,73 +1,73 @@
-namespace Unosquare.RaspberryIO.Native
-{
- using Swan;
- using System;
- using System.Runtime.InteropServices;
-
+using Unosquare.Swan;
+using System;
+using System.Runtime.InteropServices;
+
+namespace Unosquare.RaspberryIO.Native {
+ ///
+ /// Represents a low-level exception, typically thrown when return codes from a
+ /// low-level operation is non-zero or in some cases when it is less than zero.
+ ///
+ ///
+ public class HardwareException : Exception {
///
- /// Represents a low-level exception, typically thrown when return codes from a
- /// low-level operation is non-zero or in some cases when it is less than zero.
+ /// Initializes a new instance of the class.
///
- ///
- public class HardwareException : Exception
- {
- ///
- /// Initializes a new instance of the class.
- ///
- /// The error code.
- /// The component.
- public HardwareException(int errorCode, string component)
- : base($"A hardware exception occurred. Error Code: {errorCode}")
- {
- ExtendedMessage = null;
-
- try
- {
- ExtendedMessage = Standard.Strerror(errorCode);
- }
- catch
- {
- // TODO: strerror not working great...
- $"Could not retrieve native error description using {nameof(Standard.Strerror)}".Error(Pi.LoggerSource);
- }
-
- ErrorCode = errorCode;
- Component = component;
- }
-
- ///
- /// Gets the error code.
- ///
- ///
- /// The error code.
- ///
- public int ErrorCode { get; }
-
- ///
- /// Gets the component.
- ///
- ///
- /// The component.
- ///
- public string Component { get; }
-
- ///
- /// Gets the extended message (could be null).
- ///
- ///
- /// The extended message.
- ///
- public string ExtendedMessage { get; }
-
- ///
- /// Throws a new instance of a hardware error by retrieving the last error number (errno).
- ///
- /// Name of the class.
- /// Name of the method.
- /// When an error thrown by an API call occurs
- public static void Throw(string className, string methodName) => throw new HardwareException(Marshal.GetLastWin32Error(), $"{className}.{methodName}");
-
- ///
- public override string ToString() => $"{GetType()}{(string.IsNullOrWhiteSpace(Component) ? string.Empty : $" on {Component}")}: ({ErrorCode}) - {Message}";
- }
+ /// The error code.
+ /// The component.
+ public HardwareException(Int32 errorCode, String component)
+ : base($"A hardware exception occurred. Error Code: {errorCode}") {
+ this.ExtendedMessage = null;
+
+ try {
+ this.ExtendedMessage = Standard.Strerror(errorCode);
+ } catch {
+ // TODO: strerror not working great...
+ $"Could not retrieve native error description using {nameof(Standard.Strerror)}".Error(Pi.LoggerSource);
+ }
+
+ this.ErrorCode = errorCode;
+ this.Component = component;
+ }
+
+ ///
+ /// Gets the error code.
+ ///
+ ///
+ /// The error code.
+ ///
+ public Int32 ErrorCode {
+ get;
+ }
+
+ ///
+ /// Gets the component.
+ ///
+ ///
+ /// The component.
+ ///
+ public String Component {
+ get;
+ }
+
+ ///
+ /// Gets the extended message (could be null).
+ ///
+ ///
+ /// The extended message.
+ ///
+ public String ExtendedMessage {
+ get;
+ }
+
+ ///
+ /// Throws a new instance of a hardware error by retrieving the last error number (errno).
+ ///
+ /// Name of the class.
+ /// Name of the method.
+ /// When an error thrown by an API call occurs
+ public static void Throw(String className, String methodName) => throw new HardwareException(Marshal.GetLastWin32Error(), $"{className}.{methodName}");
+
+ ///
+ public override String ToString() => $"{this.GetType()}{(String.IsNullOrWhiteSpace(this.Component) ? String.Empty : $" on {this.Component}")}: ({this.ErrorCode}) - {this.Message}";
+ }
}
diff --git a/Unosquare.RaspberryIO/Native/HighResolutionTimer.cs b/Unosquare.RaspberryIO/Native/HighResolutionTimer.cs
index dd8e624..d96257c 100644
--- a/Unosquare.RaspberryIO/Native/HighResolutionTimer.cs
+++ b/Unosquare.RaspberryIO/Native/HighResolutionTimer.cs
@@ -1,32 +1,30 @@
-namespace Unosquare.RaspberryIO.Native
-{
- using System;
- using System.Diagnostics;
-
+using System;
+using System.Diagnostics;
+
+namespace Unosquare.RaspberryIO.Native {
+ ///
+ /// Provides access to a high- esolution, time measuring device.
+ ///
+ ///
+ public class HighResolutionTimer : Stopwatch {
///
- /// Provides access to a high- esolution, time measuring device.
+ /// Initializes a new instance of the class.
///
- ///
- public class HighResolutionTimer : Stopwatch
- {
- ///
- /// Initializes a new instance of the class.
- ///
- /// High-resolution timer not available
- public HighResolutionTimer()
- {
- if (!IsHighResolution)
- throw new NotSupportedException("High-resolution timer not available");
- }
-
- ///
- /// Gets the numer of microseconds per timer tick.
- ///
- public static double MicrosecondsPerTick { get; } = 1000000d / Frequency;
-
- ///
- /// Gets the elapsed microseconds.
- ///
- public long ElapsedMicroseconds => (long)(ElapsedTicks * MicrosecondsPerTick);
- }
+ /// High-resolution timer not available
+ public HighResolutionTimer() {
+ if(!IsHighResolution) {
+ throw new NotSupportedException("High-resolution timer not available");
+ }
+ }
+
+ ///
+ /// Gets the numer of microseconds per timer tick.
+ ///
+ public static Double MicrosecondsPerTick { get; } = 1000000d / Frequency;
+
+ ///
+ /// Gets the elapsed microseconds.
+ ///
+ public Int64 ElapsedMicroseconds => (Int64)(this.ElapsedTicks * MicrosecondsPerTick);
+ }
}
diff --git a/Unosquare.RaspberryIO/Native/Standard.cs b/Unosquare.RaspberryIO/Native/Standard.cs
index 4ce2ac1..b4b6e79 100644
--- a/Unosquare.RaspberryIO/Native/Standard.cs
+++ b/Unosquare.RaspberryIO/Native/Standard.cs
@@ -1,84 +1,80 @@
-namespace Unosquare.RaspberryIO.Native
-{
- using Swan;
- using System;
- using System.Runtime.InteropServices;
- using System.Text;
-
+using Unosquare.Swan;
+using System;
+using System.Runtime.InteropServices;
+using System.Text;
+
+namespace Unosquare.RaspberryIO.Native {
+ ///
+ /// Provides standard libc calls using platform-invoke
+ ///
+ internal static class Standard {
+ internal const String LibCLibrary = "libc";
+
+ #region LibC Calls
+
///
- /// Provides standard libc calls using platform-invoke
+ /// Strerrors the specified error.
///
- internal static class Standard
- {
- internal const string LibCLibrary = "libc";
-
- #region LibC Calls
-
- ///
- /// Strerrors the specified error.
- ///
- /// The error.
- ///
- public static string Strerror(int error)
- {
- if (!Runtime.IsUsingMonoRuntime) return StrError(error);
-
- try
- {
- var buffer = new StringBuilder(256);
- var result = Strerror(error, buffer, (ulong)buffer.Capacity);
- return (result != -1) ? buffer.ToString() : null;
- }
- catch (EntryPointNotFoundException)
- {
- return null;
- }
- }
-
- ///
- /// Changes file permissions on a Unix file system
- ///
- /// The filename.
- /// The mode.
- /// The result
- [DllImport(LibCLibrary, EntryPoint = "chmod", SetLastError = true)]
- public static extern int Chmod(string filename, uint mode);
-
- ///
- /// Converts a string to a 32 bit integer. Use endpointer as IntPtr.Zero
- ///
- /// The number string.
- /// The end pointer.
- /// The number base.
- /// The result
- [DllImport(LibCLibrary, EntryPoint = "strtol", SetLastError = true)]
- public static extern int StringToInteger(string numberString, IntPtr endPointer, int numberBase);
-
- ///
- /// The write() function attempts to write nbytes from buffer to the file associated with handle. On text files, it expands each LF to a CR/LF.
- /// The function returns the number of bytes written to the file. A return value of -1 indicates an error, with errno set appropriately.
- ///
- /// The fd.
- /// The buffer.
- /// The count.
- /// The result
- [DllImport(LibCLibrary, EntryPoint = "write", SetLastError = true)]
- public static extern int Write(int fd, byte[] buffer, int count);
-
- ///
- /// Fills in the structure with information about the system.
- ///
- /// The name.
- /// The result
- [DllImport(LibCLibrary, EntryPoint = "uname", SetLastError = true)]
- public static extern int Uname(out SystemName name);
-
- [DllImport(LibCLibrary, EntryPoint = "strerror", SetLastError = true)]
- private static extern string StrError(int errnum);
-
- [DllImport("MonoPosixHelper", EntryPoint = "Mono_Posix_Syscall_strerror_r", SetLastError = true)]
- private static extern int Strerror(int error, [Out] StringBuilder buffer, ulong length);
-
- #endregion
- }
+ /// The error.
+ ///
+ public static String Strerror(Int32 error) {
+ if(!Runtime.IsUsingMonoRuntime) {
+ return StrError(error);
+ }
+
+ try {
+ StringBuilder buffer = new StringBuilder(256);
+ Int32 result = Strerror(error, buffer, (UInt64)buffer.Capacity);
+ return (result != -1) ? buffer.ToString() : null;
+ } catch(EntryPointNotFoundException) {
+ return null;
+ }
+ }
+
+ ///
+ /// Changes file permissions on a Unix file system
+ ///
+ /// The filename.
+ /// The mode.
+ /// The result
+ [DllImport(LibCLibrary, EntryPoint = "chmod", SetLastError = true)]
+ public static extern Int32 Chmod(String filename, UInt32 mode);
+
+ ///
+ /// Converts a string to a 32 bit integer. Use endpointer as IntPtr.Zero
+ ///
+ /// The number string.
+ /// The end pointer.
+ /// The number base.
+ /// The result
+ [DllImport(LibCLibrary, EntryPoint = "strtol", SetLastError = true)]
+ public static extern Int32 StringToInteger(String numberString, IntPtr endPointer, Int32 numberBase);
+
+ ///
+ /// The write() function attempts to write nbytes from buffer to the file associated with handle. On text files, it expands each LF to a CR/LF.
+ /// The function returns the number of bytes written to the file. A return value of -1 indicates an error, with errno set appropriately.
+ ///
+ /// The fd.
+ /// The buffer.
+ /// The count.
+ /// The result
+ [DllImport(LibCLibrary, EntryPoint = "write", SetLastError = true)]
+ public static extern Int32 Write(Int32 fd, Byte[] buffer, Int32 count);
+
+ ///
+ /// Fills in the structure with information about the system.
+ ///
+ /// The name.
+ /// The result
+ [DllImport(LibCLibrary, EntryPoint = "uname", SetLastError = true)]
+ public static extern Int32 Uname(out SystemName name);
+
+ [DllImport(LibCLibrary, EntryPoint = "strerror", SetLastError = true)]
+ private static extern String StrError(Int32 errnum);
+
+ [DllImport("MonoPosixHelper", EntryPoint = "Mono_Posix_Syscall_strerror_r", SetLastError = true)]
+ private static extern Int32 Strerror(Int32 error, [Out] StringBuilder buffer, UInt64 length);
+
+ #endregion
+ }
}
\ No newline at end of file
diff --git a/Unosquare.RaspberryIO/Native/SystemName.cs b/Unosquare.RaspberryIO/Native/SystemName.cs
index 424fe8e..3b9e69f 100644
--- a/Unosquare.RaspberryIO/Native/SystemName.cs
+++ b/Unosquare.RaspberryIO/Native/SystemName.cs
@@ -1,47 +1,46 @@
-namespace Unosquare.RaspberryIO.Native
-{
- using System.Runtime.InteropServices;
-
+using System;
+using System.Runtime.InteropServices;
+
+namespace Unosquare.RaspberryIO.Native {
+ ///
+ /// OS uname structure
+ ///
+ [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi)]
+ internal struct SystemName {
///
- /// OS uname structure
+ /// System name
///
- [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi)]
- internal struct SystemName
- {
- ///
- /// System name
- ///
- [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 65)]
- public string SysName;
-
- ///
- /// Node name
- ///
- [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 65)]
- public string NodeName;
-
- ///
- /// Release level
- ///
- [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 65)]
- public string Release;
-
- ///
- /// Version level
- ///
- [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 65)]
- public string Version;
-
- ///
- /// Hardware level
- ///
- [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 65)]
- public string Machine;
-
- ///
- /// Domain name
- ///
- [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 65)]
- public string DomainName;
- }
+ [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 65)]
+ public String SysName;
+
+ ///
+ /// Node name
+ ///
+ [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 65)]
+ public String NodeName;
+
+ ///
+ /// Release level
+ ///
+ [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 65)]
+ public String Release;
+
+ ///
+ /// Version level
+ ///
+ [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 65)]
+ public String Version;
+
+ ///
+ /// Hardware level
+ ///
+ [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 65)]
+ public String Machine;
+
+ ///
+ /// Domain name
+ ///
+ [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 65)]
+ public String DomainName;
+ }
}
\ No newline at end of file
diff --git a/Unosquare.RaspberryIO/Native/ThreadLockKey.cs b/Unosquare.RaspberryIO/Native/ThreadLockKey.cs
index 52ed4fa..6fcc702 100644
--- a/Unosquare.RaspberryIO/Native/ThreadLockKey.cs
+++ b/Unosquare.RaspberryIO/Native/ThreadLockKey.cs
@@ -1,28 +1,26 @@
-namespace Unosquare.RaspberryIO.Native
-{
+namespace Unosquare.RaspberryIO.Native {
+ ///
+ /// Defines the different threading locking keys
+ ///
+ public enum ThreadLockKey {
///
- /// Defines the different threading locking keys
+ /// The lock 0
///
- public enum ThreadLockKey
- {
- ///
- /// The lock 0
- ///
- Lock0 = 0,
-
- ///
- /// The lock 1
- ///
- Lock1 = 1,
-
- ///
- /// The lock 2
- ///
- Lock2 = 2,
-
- ///
- /// The lock 3
- ///
- Lock3 = 3,
- }
+ Lock0 = 0,
+
+ ///
+ /// The lock 1
+ ///
+ Lock1 = 1,
+
+ ///
+ /// The lock 2
+ ///
+ Lock2 = 2,
+
+ ///
+ /// The lock 3
+ ///
+ Lock3 = 3,
+ }
}
diff --git a/Unosquare.RaspberryIO/Native/Timing.cs b/Unosquare.RaspberryIO/Native/Timing.cs
index b0c91fb..e36df61 100644
--- a/Unosquare.RaspberryIO/Native/Timing.cs
+++ b/Unosquare.RaspberryIO/Native/Timing.cs
@@ -1,108 +1,108 @@
-namespace Unosquare.RaspberryIO.Native
-{
- using Swan;
- using Swan.Abstractions;
- using System;
-
+using Unosquare.Swan;
+using Unosquare.Swan.Abstractions;
+using System;
+
+namespace Unosquare.RaspberryIO.Native {
+ ///
+ /// Provides access to timing and threading properties and methods
+ ///
+ public class Timing : SingletonBase {
///
- /// Provides access to timing and threading properties and methods
+ /// Prevents a default instance of the class from being created.
///
- public class Timing : SingletonBase
- {
- ///
- /// Prevents a default instance of the class from being created.
- ///
- /// Could not initialize the GPIO controller
- private Timing()
- {
- // placeholder
- }
-
- ///
- /// This returns a number representing the number of milliseconds since your program
- /// initialized the GPIO controller.
- /// It returns an unsigned 32-bit number which wraps after 49 days.
- ///
- ///
- /// The milliseconds since setup.
- ///
- public uint MillisecondsSinceSetup => WiringPi.Millis();
-
- ///
- /// This returns a number representing the number of microseconds since your
- /// program initialized the GPIO controller
- /// It returns an unsigned 32-bit number which wraps after approximately 71 minutes.
- ///
- ///
- /// The microseconds since setup.
- ///
- public uint MicrosecondsSinceSetup => WiringPi.Micros();
-
- ///
- /// This causes program execution to pause for at least howLong milliseconds.
- /// Due to the multi-tasking nature of Linux it could be longer.
- /// Note that the maximum delay is an unsigned 32-bit integer or approximately 49 days.
- ///
- /// The value.
- public static void SleepMilliseconds(uint value) => WiringPi.Delay(value);
-
- ///
- /// This causes program execution to pause for at least howLong microseconds.
- /// Due to the multi-tasking nature of Linux it could be longer.
- /// Note that the maximum delay is an unsigned 32-bit integer microseconds or approximately 71 minutes.
- /// Delays under 100 microseconds are timed using a hard-coded loop continually polling the system time,
- /// Delays over 100 microseconds are done using the system nanosleep() function –
- /// You may need to consider the implications of very short delays on the overall performance of the system,
- /// especially if using threads.
- ///
- /// The value.
- public void SleepMicroseconds(uint value) => WiringPi.DelayMicroseconds(value);
-
- ///
- /// This attempts to shift your program (or thread in a multi-threaded program) to a higher priority and
- /// enables a real-time scheduling. The priority parameter should be from 0 (the default) to 99 (the maximum).
- /// This won’t make your program go any faster, but it will give it a bigger slice of time when other programs
- /// are running. The priority parameter works relative to others – so you can make one program priority 1 and
- /// another priority 2 and it will have the same effect as setting one to 10 and the other to 90
- /// (as long as no other programs are running with elevated priorities)
- ///
- /// The priority.
- public void SetThreadPriority(int priority)
- {
- priority = priority.Clamp(0, 99);
- var result = WiringPi.PiHiPri(priority);
- if (result < 0) HardwareException.Throw(nameof(Timing), nameof(SetThreadPriority));
- }
-
- ///
- /// This is really nothing more than a simplified interface to the Posix threads mechanism that Linux supports.
- /// See the manual pages on Posix threads (man pthread) if you need more control over them.
- ///
- /// The worker.
- /// worker
- public void CreateThread(ThreadWorker worker)
- {
- if (worker == null)
- throw new ArgumentNullException(nameof(worker));
-
- var result = WiringPi.PiThreadCreate(worker);
- if (result != 0) HardwareException.Throw(nameof(Timing), nameof(CreateThread));
- }
-
- ///
- /// These allow you to synchronize variable updates from your main program to any threads running in your program.
- /// keyNum is a number from 0 to 3 and represents a “key”. When another process tries to lock the same key,
- /// it will be stalled until the first process has unlocked the same key.
- ///
- /// The key.
- public void Lock(ThreadLockKey key) => WiringPi.PiLock((int)key);
-
- ///
- /// These allow you to synchronize variable updates from your main program to any threads running in your program.
- /// keyNum is a number from 0 to 3 and represents a “key”. When another process tries to lock the same key,
- /// it will be stalled until the first process has unlocked the same key.
- ///
- /// The key.
- public void Unlock(ThreadLockKey key) => WiringPi.PiUnlock((int)key);
- }
+ /// Could not initialize the GPIO controller
+ private Timing() {
+ // placeholder
+ }
+
+ ///
+ /// This returns a number representing the number of milliseconds since your program
+ /// initialized the GPIO controller.
+ /// It returns an unsigned 32-bit number which wraps after 49 days.
+ ///
+ ///
+ /// The milliseconds since setup.
+ ///
+ public UInt32 MillisecondsSinceSetup => WiringPi.Millis();
+
+ ///
+ /// This returns a number representing the number of microseconds since your
+ /// program initialized the GPIO controller
+ /// It returns an unsigned 32-bit number which wraps after approximately 71 minutes.
+ ///
+ ///
+ /// The microseconds since setup.
+ ///
+ public UInt32 MicrosecondsSinceSetup => WiringPi.Micros();
+
+ ///
+ /// This causes program execution to pause for at least howLong milliseconds.
+ /// Due to the multi-tasking nature of Linux it could be longer.
+ /// Note that the maximum delay is an unsigned 32-bit integer or approximately 49 days.
+ ///
+ /// The value.
+ public static void SleepMilliseconds(UInt32 value) => WiringPi.Delay(value);
+
+ ///
+ /// This causes program execution to pause for at least howLong microseconds.
+ /// Due to the multi-tasking nature of Linux it could be longer.
+ /// Note that the maximum delay is an unsigned 32-bit integer microseconds or approximately 71 minutes.
+ /// Delays under 100 microseconds are timed using a hard-coded loop continually polling the system time,
+ /// Delays over 100 microseconds are done using the system nanosleep() function –
+ /// You may need to consider the implications of very short delays on the overall performance of the system,
+ /// especially if using threads.
+ ///
+ /// The value.
+ public void SleepMicroseconds(UInt32 value) => WiringPi.DelayMicroseconds(value);
+
+ ///
+ /// This attempts to shift your program (or thread in a multi-threaded program) to a higher priority and
+ /// enables a real-time scheduling. The priority parameter should be from 0 (the default) to 99 (the maximum).
+ /// This won’t make your program go any faster, but it will give it a bigger slice of time when other programs
+ /// are running. The priority parameter works relative to others – so you can make one program priority 1 and
+ /// another priority 2 and it will have the same effect as setting one to 10 and the other to 90
+ /// (as long as no other programs are running with elevated priorities)
+ ///
+ /// The priority.
+ public void SetThreadPriority(Int32 priority) {
+ priority = priority.Clamp(0, 99);
+ Int32 result = WiringPi.PiHiPri(priority);
+ if(result < 0) {
+ HardwareException.Throw(nameof(Timing), nameof(SetThreadPriority));
+ }
+ }
+
+ ///
+ /// This is really nothing more than a simplified interface to the Posix threads mechanism that Linux supports.
+ /// See the manual pages on Posix threads (man pthread) if you need more control over them.
+ ///
+ /// The worker.
+ /// worker
+ public void CreateThread(ThreadWorker worker) {
+ if(worker == null) {
+ throw new ArgumentNullException(nameof(worker));
+ }
+
+ Int32 result = WiringPi.PiThreadCreate(worker);
+ if(result != 0) {
+ HardwareException.Throw(nameof(Timing), nameof(CreateThread));
+ }
+ }
+
+ ///
+ /// These allow you to synchronize variable updates from your main program to any threads running in your program.
+ /// keyNum is a number from 0 to 3 and represents a “key”. When another process tries to lock the same key,
+ /// it will be stalled until the first process has unlocked the same key.
+ ///
+ /// The key.
+ public void Lock(ThreadLockKey key) => WiringPi.PiLock((Int32)key);
+
+ ///
+ /// These allow you to synchronize variable updates from your main program to any threads running in your program.
+ /// keyNum is a number from 0 to 3 and represents a “key”. When another process tries to lock the same key,
+ /// it will be stalled until the first process has unlocked the same key.
+ ///
+ /// The key.
+ public void Unlock(ThreadLockKey key) => WiringPi.PiUnlock((Int32)key);
+ }
}
diff --git a/Unosquare.RaspberryIO/Native/WiringPi.I2C.cs b/Unosquare.RaspberryIO/Native/WiringPi.I2C.cs
index b0775b9..581cd14 100644
--- a/Unosquare.RaspberryIO/Native/WiringPi.I2C.cs
+++ b/Unosquare.RaspberryIO/Native/WiringPi.I2C.cs
@@ -1,79 +1,78 @@
-namespace Unosquare.RaspberryIO.Native
-{
- using System.Runtime.InteropServices;
-
- public partial class WiringPi
- {
- #region WiringPi - I2C Library Calls
-
- ///
- /// Simple device read. Some devices present data when you read them without having to do any register transactions.
- ///
- /// The fd.
- /// The result
- [DllImport(WiringPiLibrary, EntryPoint = "wiringPiI2CRead", SetLastError = true)]
- public static extern int WiringPiI2CRead(int fd);
-
- ///
- /// These read an 8-bit value from the device register indicated.
- ///
- /// The fd.
- /// The reg.
- /// The result
- [DllImport(WiringPiLibrary, EntryPoint = "wiringPiI2CReadReg8", SetLastError = true)]
- public static extern int WiringPiI2CReadReg8(int fd, int reg);
-
- ///
- /// These read a 16-bit value from the device register indicated.
- ///
- /// The fd.
- /// The reg.
- /// The result
- [DllImport(WiringPiLibrary, EntryPoint = "wiringPiI2CReadReg16", SetLastError = true)]
- public static extern int WiringPiI2CReadReg16(int fd, int reg);
-
- ///
- /// Simple device write. Some devices accept data this way without needing to access any internal registers.
- ///
- /// The fd.
- /// The data.
- /// The result
- [DllImport(WiringPiLibrary, EntryPoint = "wiringPiI2CWrite", SetLastError = true)]
- public static extern int WiringPiI2CWrite(int fd, int data);
-
- ///
- /// These write an 8-bit data value into the device register indicated.
- ///
- /// The fd.
- /// The reg.
- /// The data.
- /// The result
- [DllImport(WiringPiLibrary, EntryPoint = "wiringPiI2CWriteReg8", SetLastError = true)]
- public static extern int WiringPiI2CWriteReg8(int fd, int reg, int data);
-
- ///
- /// These write a 16-bit data value into the device register indicated.
- ///
- /// The fd.
- /// The reg.
- /// The data.
- /// The result
- [DllImport(WiringPiLibrary, EntryPoint = "wiringPiI2CWriteReg16", SetLastError = true)]
- public static extern int WiringPiI2CWriteReg16(int fd, int reg, int data);
-
- ///
- /// This initialises 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.
- /// E.g. the popular MCP23017 GPIO expander is usually device Id 0x20, so this is the number you would pass into wiringPiI2CSetup().
- ///
- /// The dev identifier.
- /// The result
- [DllImport(WiringPiLibrary, EntryPoint = "wiringPiI2CSetup", SetLastError = true)]
- public static extern int WiringPiI2CSetup(int devId);
-
- #endregion
-
- }
+using System;
+using System.Runtime.InteropServices;
+
+namespace Unosquare.RaspberryIO.Native {
+ public partial class WiringPi {
+ #region WiringPi - I2C Library Calls
+
+ ///
+ /// Simple device read. Some devices present data when you read them without having to do any register transactions.
+ ///
+ /// The fd.
+ /// The result
+ [DllImport(WiringPiLibrary, EntryPoint = "wiringPiI2CRead", SetLastError = true)]
+ public static extern Int32 WiringPiI2CRead(Int32 fd);
+
+ ///
+ /// These read an 8-bit value from the device register indicated.
+ ///
+ /// The fd.
+ /// The reg.
+ /// The result
+ [DllImport(WiringPiLibrary, EntryPoint = "wiringPiI2CReadReg8", SetLastError = true)]
+ public static extern Int32 WiringPiI2CReadReg8(Int32 fd, Int32 reg);
+
+ ///
+ /// These read a 16-bit value from the device register indicated.
+ ///
+ /// The fd.
+ /// The reg.
+ /// The result
+ [DllImport(WiringPiLibrary, EntryPoint = "wiringPiI2CReadReg16", SetLastError = true)]
+ public static extern Int32 WiringPiI2CReadReg16(Int32 fd, Int32 reg);
+
+ ///
+ /// Simple device write. Some devices accept data this way without needing to access any internal registers.
+ ///
+ /// The fd.
+ /// The data.
+ /// The result
+ [DllImport(WiringPiLibrary, EntryPoint = "wiringPiI2CWrite", SetLastError = true)]
+ public static extern Int32 WiringPiI2CWrite(Int32 fd, Int32 data);
+
+ ///
+ /// These write an 8-bit data value into the device register indicated.
+ ///
+ /// The fd.
+ /// The reg.
+ /// The data.
+ /// The result
+ [DllImport(WiringPiLibrary, EntryPoint = "wiringPiI2CWriteReg8", SetLastError = true)]
+ public static extern Int32 WiringPiI2CWriteReg8(Int32 fd, Int32 reg, Int32 data);
+
+ ///
+ /// These write a 16-bit data value into the device register indicated.
+ ///
+ /// The fd.
+ /// The reg.
+ /// The data.
+ /// The result
+ [DllImport(WiringPiLibrary, EntryPoint = "wiringPiI2CWriteReg16", SetLastError = true)]
+ public static extern Int32 WiringPiI2CWriteReg16(Int32 fd, Int32 reg, Int32 data);
+
+ ///
+ /// This initialises 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.
+ /// E.g. the popular MCP23017 GPIO expander is usually device Id 0x20, so this is the number you would pass into wiringPiI2CSetup().
+ ///
+ /// The dev identifier.
+ /// The result
+ [DllImport(WiringPiLibrary, EntryPoint = "wiringPiI2CSetup", SetLastError = true)]
+ public static extern Int32 WiringPiI2CSetup(Int32 devId);
+
+ #endregion
+
+ }
}
diff --git a/Unosquare.RaspberryIO/Native/WiringPi.SerialPort.cs b/Unosquare.RaspberryIO/Native/WiringPi.SerialPort.cs
index ea54bd3..7b96005 100644
--- a/Unosquare.RaspberryIO/Native/WiringPi.SerialPort.cs
+++ b/Unosquare.RaspberryIO/Native/WiringPi.SerialPort.cs
@@ -1,73 +1,72 @@
-namespace Unosquare.RaspberryIO.Native
-{
- using System.Runtime.InteropServices;
-
- public partial class WiringPi
- {
- #region WiringPi - Serial Port
-
- ///
- /// This opens and initialises the serial device and sets the baud rate. It sets the port into “raw” mode (character at a time and no translations),
- /// and sets the read timeout to 10 seconds. The return value is the file descriptor or -1 for any error, in which case errno will be set as appropriate.
- /// The wiringSerial library is intended to provide simplified control – suitable for most applications, however if you need advanced control
- /// – e.g. parity control, modem control lines (via a USB adapter, there are none on the Pi’s on-board UART!) and so on,
- /// then you need to do some of this the old fashioned way.
- ///
- /// The device.
- /// The baud.
- /// The result
- [DllImport(WiringPiLibrary, EntryPoint = "serialOpen", SetLastError = true)]
- public static extern int SerialOpen(string device, int baud);
-
- ///
- /// Closes the device identified by the file descriptor given.
- ///
- /// The fd.
- /// The result
- [DllImport(WiringPiLibrary, EntryPoint = "serialClose", SetLastError = true)]
- public static extern int SerialClose(int fd);
-
- ///
- /// Sends the single byte to the serial device identified by the given file descriptor.
- ///
- /// The fd.
- /// The c.
- [DllImport(WiringPiLibrary, EntryPoint = "serialPutchar", SetLastError = true)]
- public static extern void SerialPutchar(int fd, byte c);
-
- ///
- /// Sends the nul-terminated string to the serial device identified by the given file descriptor.
- ///
- /// The fd.
- /// The s.
- [DllImport(WiringPiLibrary, EntryPoint = "serialPuts", SetLastError = true)]
- public static extern void SerialPuts(int fd, string s);
-
- ///
- /// Returns the number of characters available for reading, or -1 for any error condition,
- /// in which case errno will be set appropriately.
- ///
- /// The fd.
- /// The result
- [DllImport(WiringPiLibrary, EntryPoint = "serialDataAvail", SetLastError = true)]
- public static extern int SerialDataAvail(int fd);
-
- ///
- /// Returns the next character available on the serial device.
- /// This call will block for up to 10 seconds if no data is available (when it will return -1)
- ///
- /// The fd.
- /// The result
- [DllImport(WiringPiLibrary, EntryPoint = "serialGetchar", SetLastError = true)]
- public static extern int SerialGetchar(int fd);
-
- ///
- /// This discards all data received, or waiting to be send down the given device.
- ///
- /// The fd.
- [DllImport(WiringPiLibrary, EntryPoint = "serialFlush", SetLastError = true)]
- public static extern void SerialFlush(int fd);
-
- #endregion
- }
+using System;
+using System.Runtime.InteropServices;
+
+namespace Unosquare.RaspberryIO.Native {
+ public partial class WiringPi {
+ #region WiringPi - Serial Port
+
+ ///
+ /// This opens and initialises the serial device and sets the baud rate. It sets the port into “raw” mode (character at a time and no translations),
+ /// and sets the read timeout to 10 seconds. The return value is the file descriptor or -1 for any error, in which case errno will be set as appropriate.
+ /// The wiringSerial library is intended to provide simplified control – suitable for most applications, however if you need advanced control
+ /// – e.g. parity control, modem control lines (via a USB adapter, there are none on the Pi’s on-board UART!) and so on,
+ /// then you need to do some of this the old fashioned way.
+ ///
+ /// The device.
+ /// The baud.
+ /// The result
+ [DllImport(WiringPiLibrary, EntryPoint = "serialOpen", SetLastError = true)]
+ public static extern Int32 SerialOpen(String device, Int32 baud);
+
+ ///
+ /// Closes the device identified by the file descriptor given.
+ ///
+ /// The fd.
+ /// The result
+ [DllImport(WiringPiLibrary, EntryPoint = "serialClose", SetLastError = true)]
+ public static extern Int32 SerialClose(Int32 fd);
+
+ ///
+ /// Sends the single byte to the serial device identified by the given file descriptor.
+ ///
+ /// The fd.
+ /// The c.
+ [DllImport(WiringPiLibrary, EntryPoint = "serialPutchar", SetLastError = true)]
+ public static extern void SerialPutchar(Int32 fd, Byte c);
+
+ ///
+ /// Sends the nul-terminated string to the serial device identified by the given file descriptor.
+ ///
+ /// The fd.
+ /// The s.
+ [DllImport(WiringPiLibrary, EntryPoint = "serialPuts", SetLastError = true)]
+ public static extern void SerialPuts(Int32 fd, String s);
+
+ ///
+ /// Returns the number of characters available for reading, or -1 for any error condition,
+ /// in which case errno will be set appropriately.
+ ///
+ /// The fd.
+ /// The result
+ [DllImport(WiringPiLibrary, EntryPoint = "serialDataAvail", SetLastError = true)]
+ public static extern Int32 SerialDataAvail(Int32 fd);
+
+ ///
+ /// Returns the next character available on the serial device.
+ /// This call will block for up to 10 seconds if no data is available (when it will return -1)
+ ///
+ /// The fd.
+ /// The result
+ [DllImport(WiringPiLibrary, EntryPoint = "serialGetchar", SetLastError = true)]
+ public static extern Int32 SerialGetchar(Int32 fd);
+
+ ///
+ /// This discards all data received, or waiting to be send down the given device.
+ ///
+ /// The fd.
+ [DllImport(WiringPiLibrary, EntryPoint = "serialFlush", SetLastError = true)]
+ public static extern void SerialFlush(Int32 fd);
+
+ #endregion
+ }
}
\ No newline at end of file
diff --git a/Unosquare.RaspberryIO/Native/WiringPi.Shift.cs b/Unosquare.RaspberryIO/Native/WiringPi.Shift.cs
index dfab07f..0808f39 100644
--- a/Unosquare.RaspberryIO/Native/WiringPi.Shift.cs
+++ b/Unosquare.RaspberryIO/Native/WiringPi.Shift.cs
@@ -1,36 +1,35 @@
-namespace Unosquare.RaspberryIO.Native
-{
- using System.Runtime.InteropServices;
-
- public partial class WiringPi
- {
- #region WiringPi - Shift Library
-
- ///
- /// This shifts an 8-bit data value in with the data appearing on the dPin and the clock being sent out on the cPin.
- /// Order is either LSBFIRST or MSBFIRST. The data is sampled after the cPin goes high.
- /// (So cPin high, sample data, cPin low, repeat for 8 bits) The 8-bit value is returned by the function.
- ///
- /// The d pin.
- /// The c pin.
- /// The order.
- /// The result
- [DllImport(WiringPiLibrary, EntryPoint = "shiftIn", SetLastError = true)]
- public static extern byte ShiftIn(byte dPin, byte cPin, byte order);
-
- ///
- /// The shifts an 8-bit data value val out with the data being sent out on dPin and the clock being sent out on the cPin.
- /// order is as above. Data is clocked out on the rising or falling edge – ie. dPin is set, then cPin is taken high then low
- /// – repeated for the 8 bits.
- ///
- /// The d pin.
- /// The c pin.
- /// The order.
- /// The value.
- [DllImport(WiringPiLibrary, EntryPoint = "shiftOut", SetLastError = true)]
- public static extern void ShiftOut(byte dPin, byte cPin, byte order, byte val);
-
- #endregion
-
- }
+using System;
+using System.Runtime.InteropServices;
+
+namespace Unosquare.RaspberryIO.Native {
+ public partial class WiringPi {
+ #region WiringPi - Shift Library
+
+ ///
+ /// This shifts an 8-bit data value in with the data appearing on the dPin and the clock being sent out on the cPin.
+ /// Order is either LSBFIRST or MSBFIRST. The data is sampled after the cPin goes high.
+ /// (So cPin high, sample data, cPin low, repeat for 8 bits) The 8-bit value is returned by the function.
+ ///
+ /// The d pin.
+ /// The c pin.
+ /// The order.
+ /// The result
+ [DllImport(WiringPiLibrary, EntryPoint = "shiftIn", SetLastError = true)]
+ public static extern Byte ShiftIn(Byte dPin, Byte cPin, Byte order);
+
+ ///
+ /// The shifts an 8-bit data value val out with the data being sent out on dPin and the clock being sent out on the cPin.
+ /// order is as above. Data is clocked out on the rising or falling edge – ie. dPin is set, then cPin is taken high then low
+ /// – repeated for the 8 bits.
+ ///
+ /// The d pin.
+ /// The c pin.
+ /// The order.
+ /// The value.
+ [DllImport(WiringPiLibrary, EntryPoint = "shiftOut", SetLastError = true)]
+ public static extern void ShiftOut(Byte dPin, Byte cPin, Byte order, Byte val);
+
+ #endregion
+
+ }
}
diff --git a/Unosquare.RaspberryIO/Native/WiringPi.SoftPwm.cs b/Unosquare.RaspberryIO/Native/WiringPi.SoftPwm.cs
index 30a75b5..19e245b 100644
--- a/Unosquare.RaspberryIO/Native/WiringPi.SoftPwm.cs
+++ b/Unosquare.RaspberryIO/Native/WiringPi.SoftPwm.cs
@@ -1,64 +1,63 @@
-namespace Unosquare.RaspberryIO.Native
-{
- using System.Runtime.InteropServices;
-
- public partial class WiringPi
- {
- #region WiringPi - Soft PWM (https://github.com/WiringPi/WiringPi/blob/master/wiringPi/softPwm.h)
-
- ///
- /// This creates a software controlled PWM pin. You can use any GPIO pin and the pin numbering will be that of the wiringPiSetup()
- /// function you used. Use 100 for the pwmRange, then the value can be anything from 0 (off) to 100 (fully on) for the given pin.
- /// The return value is 0 for success. Anything else and you should check the global errno variable to see what went wrong.
- ///
- /// The pin.
- /// The initial value.
- /// The PWM range.
- /// The result
- [DllImport(WiringPiLibrary, EntryPoint = "softPwmCreate", SetLastError = true)]
- public static extern int SoftPwmCreate(int pin, int initialValue, int pwmRange);
-
- ///
- /// This updates the PWM value on the given pin. The value is checked to be in-range and pins that haven’t previously
- /// been initialized via softPwmCreate will be silently ignored.
- ///
- /// The pin.
- /// The value.
- [DllImport(WiringPiLibrary, EntryPoint = "softPwmWrite", SetLastError = true)]
- public static extern void SoftPwmWrite(int pin, int value);
-
- ///
- /// This function is undocumented
- ///
- /// The pin.
- [DllImport(WiringPiLibrary, EntryPoint = "softPwmStop", SetLastError = true)]
- public static extern void SoftPwmStop(int pin);
-
- ///
- /// This creates a software controlled tone pin. You can use any GPIO pin and the pin numbering will be that of the wiringPiSetup() function you used.
- /// The return value is 0 for success. Anything else and you should check the global errno variable to see what went wrong.
- ///
- /// The pin.
- /// The result
- [DllImport(WiringPiLibrary, EntryPoint = "softToneCreate", SetLastError = true)]
- public static extern int SoftToneCreate(int pin);
-
- ///
- /// This function is undocumented
- ///
- /// The pin.
- [DllImport(WiringPiLibrary, EntryPoint = "softToneStop", SetLastError = true)]
- public static extern void SoftToneStop(int pin);
-
- ///
- /// This updates the tone frequency value on the given pin. The tone will be played until you set the frequency to 0.
- ///
- /// The pin.
- /// The freq.
- [DllImport(WiringPiLibrary, EntryPoint = "softToneWrite", SetLastError = true)]
- public static extern void SoftToneWrite(int pin, int freq);
-
- #endregion
-
- }
+using System;
+using System.Runtime.InteropServices;
+
+namespace Unosquare.RaspberryIO.Native {
+ public partial class WiringPi {
+ #region WiringPi - Soft PWM (https://github.com/WiringPi/WiringPi/blob/master/wiringPi/softPwm.h)
+
+ ///
+ /// This creates a software controlled PWM pin. You can use any GPIO pin and the pin numbering will be that of the wiringPiSetup()
+ /// function you used. Use 100 for the pwmRange, then the value can be anything from 0 (off) to 100 (fully on) for the given pin.
+ /// The return value is 0 for success. Anything else and you should check the global errno variable to see what went wrong.
+ ///
+ /// The pin.
+ /// The initial value.
+ /// The PWM range.
+ /// The result
+ [DllImport(WiringPiLibrary, EntryPoint = "softPwmCreate", SetLastError = true)]
+ public static extern Int32 SoftPwmCreate(Int32 pin, Int32 initialValue, Int32 pwmRange);
+
+ ///
+ /// This updates the PWM value on the given pin. The value is checked to be in-range and pins that haven’t previously
+ /// been initialized via softPwmCreate will be silently ignored.
+ ///
+ /// The pin.
+ /// The value.
+ [DllImport(WiringPiLibrary, EntryPoint = "softPwmWrite", SetLastError = true)]
+ public static extern void SoftPwmWrite(Int32 pin, Int32 value);
+
+ ///
+ /// This function is undocumented
+ ///
+ /// The pin.
+ [DllImport(WiringPiLibrary, EntryPoint = "softPwmStop", SetLastError = true)]
+ public static extern void SoftPwmStop(Int32 pin);
+
+ ///
+ /// This creates a software controlled tone pin. You can use any GPIO pin and the pin numbering will be that of the wiringPiSetup() function you used.
+ /// The return value is 0 for success. Anything else and you should check the global errno variable to see what went wrong.
+ ///
+ /// The pin.
+ /// The result
+ [DllImport(WiringPiLibrary, EntryPoint = "softToneCreate", SetLastError = true)]
+ public static extern Int32 SoftToneCreate(Int32 pin);
+
+ ///
+ /// This function is undocumented
+ ///
+ /// The pin.
+ [DllImport(WiringPiLibrary, EntryPoint = "softToneStop", SetLastError = true)]
+ public static extern void SoftToneStop(Int32 pin);
+
+ ///
+ /// This updates the tone frequency value on the given pin. The tone will be played until you set the frequency to 0.
+ ///
+ /// The pin.
+ /// The freq.
+ [DllImport(WiringPiLibrary, EntryPoint = "softToneWrite", SetLastError = true)]
+ public static extern void SoftToneWrite(Int32 pin, Int32 freq);
+
+ #endregion
+
+ }
}
diff --git a/Unosquare.RaspberryIO/Native/WiringPi.Spi.cs b/Unosquare.RaspberryIO/Native/WiringPi.Spi.cs
index 4a36c97..c53eaae 100644
--- a/Unosquare.RaspberryIO/Native/WiringPi.Spi.cs
+++ b/Unosquare.RaspberryIO/Native/WiringPi.Spi.cs
@@ -1,53 +1,52 @@
-namespace Unosquare.RaspberryIO.Native
-{
- using System.Runtime.InteropServices;
-
- public partial class WiringPi
- {
- #region WiringPi - SPI Library Calls
-
- ///
- /// This function is undocumented
- ///
- /// The channel.
- /// Unknown
- [DllImport(WiringPiLibrary, EntryPoint = "wiringPiSPIGetFd", SetLastError = true)]
- public static extern int WiringPiSPIGetFd(int channel);
-
- ///
- /// This performs a simultaneous write/read transaction over the selected SPI bus. Data that was in your buffer is overwritten by data returned from the SPI bus.
- /// That’s all there is in the helper library. It is possible to do simple read and writes over the SPI bus using the standard read() and write() system calls though –
- /// write() may be better to use for sending data to chains of shift registers, or those LED strings where you send RGB triplets of data.
- /// Devices such as A/D and D/A converters usually need to perform a concurrent write/read transaction to work.
- ///
- /// The channel.
- /// The data.
- /// The length.
- /// The result
- [DllImport(WiringPiLibrary, EntryPoint = "wiringPiSPIDataRW", SetLastError = true)]
- public static extern int WiringPiSPIDataRW(int channel, byte[] data, int len);
-
- ///
- /// This function is undocumented
- ///
- /// The channel.
- /// The speed.
- /// The mode.
- /// Unkown
- [DllImport(WiringPiLibrary, EntryPoint = "wiringPiSPISetupMode", SetLastError = true)]
- public static extern int WiringPiSPISetupMode(int channel, int speed, int mode);
-
- ///
- /// This is the way to initialize a channel (The Pi has 2 channels; 0 and 1). The speed parameter is an integer
- /// in the range 500,000 through 32,000,000 and represents the SPI clock speed in Hz.
- /// The returned value is the Linux file-descriptor for the device, or -1 on error. If an error has happened, you may use the standard errno global variable to see why.
- ///
- /// The channel.
- /// The speed.
- /// The Linux file descriptor for the device or -1 for error
- [DllImport(WiringPiLibrary, EntryPoint = "wiringPiSPISetup", SetLastError = true)]
- public static extern int WiringPiSPISetup(int channel, int speed);
-
- #endregion
- }
+using System;
+using System.Runtime.InteropServices;
+
+namespace Unosquare.RaspberryIO.Native {
+ public partial class WiringPi {
+ #region WiringPi - SPI Library Calls
+
+ ///
+ /// This function is undocumented
+ ///
+ /// The channel.
+ /// Unknown
+ [DllImport(WiringPiLibrary, EntryPoint = "wiringPiSPIGetFd", SetLastError = true)]
+ public static extern Int32 WiringPiSPIGetFd(Int32 channel);
+
+ ///
+ /// This performs a simultaneous write/read transaction over the selected SPI bus. Data that was in your buffer is overwritten by data returned from the SPI bus.
+ /// That’s all there is in the helper library. It is possible to do simple read and writes over the SPI bus using the standard read() and write() system calls though –
+ /// write() may be better to use for sending data to chains of shift registers, or those LED strings where you send RGB triplets of data.
+ /// Devices such as A/D and D/A converters usually need to perform a concurrent write/read transaction to work.
+ ///
+ /// The channel.
+ /// The data.
+ /// The length.
+ /// The result
+ [DllImport(WiringPiLibrary, EntryPoint = "wiringPiSPIDataRW", SetLastError = true)]
+ public static extern Int32 WiringPiSPIDataRW(Int32 channel, Byte[] data, Int32 len);
+
+ ///
+ /// This function is undocumented
+ ///
+ /// The channel.
+ /// The speed.
+ /// The mode.
+ /// Unkown
+ [DllImport(WiringPiLibrary, EntryPoint = "wiringPiSPISetupMode", SetLastError = true)]
+ public static extern Int32 WiringPiSPISetupMode(Int32 channel, Int32 speed, Int32 mode);
+
+ ///
+ /// This is the way to initialize a channel (The Pi has 2 channels; 0 and 1). The speed parameter is an integer
+ /// in the range 500,000 through 32,000,000 and represents the SPI clock speed in Hz.
+ /// The returned value is the Linux file-descriptor for the device, or -1 on error. If an error has happened, you may use the standard errno global variable to see why.
+ ///
+ /// The channel.
+ /// The speed.
+ /// The Linux file descriptor for the device or -1 for error
+ [DllImport(WiringPiLibrary, EntryPoint = "wiringPiSPISetup", SetLastError = true)]
+ public static extern Int32 WiringPiSPISetup(Int32 channel, Int32 speed);
+
+ #endregion
+ }
}
diff --git a/Unosquare.RaspberryIO/Native/WiringPi.cs b/Unosquare.RaspberryIO/Native/WiringPi.cs
index df347e7..4acf1c9 100644
--- a/Unosquare.RaspberryIO/Native/WiringPi.cs
+++ b/Unosquare.RaspberryIO/Native/WiringPi.cs
@@ -1,394 +1,392 @@
-namespace Unosquare.RaspberryIO.Native
-{
- using System;
- using System.Runtime.InteropServices;
-
+using System;
+using System.Runtime.InteropServices;
+
+namespace Unosquare.RaspberryIO.Native {
+ ///
+ /// Provides native C WiringPi Library function call wrappers
+ /// All credit for the native library goes to the author of http://wiringpi.com/
+ /// The wrappers were written based on https://github.com/WiringPi/WiringPi/blob/master/wiringPi/wiringPi.h
+ ///
+ public partial class WiringPi {
+ internal const String WiringPiLibrary = "libwiringPi.so.2.46";
+
+ #region WiringPi - Core Functions (https://github.com/WiringPi/WiringPi/blob/master/wiringPi/wiringPi.h)
+
///
- /// Provides native C WiringPi Library function call wrappers
- /// All credit for the native library goes to the author of http://wiringpi.com/
- /// The wrappers were written based on https://github.com/WiringPi/WiringPi/blob/master/wiringPi/wiringPi.h
+ /// This initialises wiringPi and assumes that the calling program is going to be using the wiringPi pin numbering scheme.
+ /// This is a simplified numbering scheme which provides a mapping from virtual pin numbers 0 through 16 to the real underlying Broadcom GPIO pin numbers.
+ /// See the pins page for a table which maps the wiringPi pin number to the Broadcom GPIO pin number to the physical location on the edge connector.
+ /// This function needs to be called with root privileges.
///
- public partial class WiringPi
- {
- internal const string WiringPiLibrary = "libwiringPi.so.2.46";
-
- #region WiringPi - Core Functions (https://github.com/WiringPi/WiringPi/blob/master/wiringPi/wiringPi.h)
-
- ///
- /// This initialises wiringPi and assumes that the calling program is going to be using the wiringPi pin numbering scheme.
- /// This is a simplified numbering scheme which provides a mapping from virtual pin numbers 0 through 16 to the real underlying Broadcom GPIO pin numbers.
- /// See the pins page for a table which maps the wiringPi pin number to the Broadcom GPIO pin number to the physical location on the edge connector.
- /// This function needs to be called with root privileges.
- ///
- /// The result code
- [DllImport(WiringPiLibrary, EntryPoint = "wiringPiSetup", SetLastError = true)]
- public static extern int WiringPiSetup();
-
- ///
- /// This initialises wiringPi but uses the /sys/class/gpio interface rather than accessing the hardware directly.
- /// This can be called as a non-root user provided the GPIO pins have been exported before-hand using the gpio program.
- /// Pin numbering in this mode is the native Broadcom GPIO numbers – the same as wiringPiSetupGpio() above,
- /// so be aware of the differences between Rev 1 and Rev 2 boards.
- ///
- /// Note: In this mode you can only use the pins which have been exported via the /sys/class/gpio interface before you run your program.
- /// You can do this in a separate shell-script, or by using the system() function from inside your program to call the gpio program.
- /// Also note that some functions have no effect when using this mode as they’re not currently possible to action unless called with root privileges.
- /// (although you can use system() to call gpio to set/change modes if needed)
- ///
- /// The result code
- [DllImport(WiringPiLibrary, EntryPoint = "wiringPiSetupSys", SetLastError = true)]
- public static extern int WiringPiSetupSys();
-
- ///
- /// This is identical to wiringPiSetup, however it allows the calling programs to use the Broadcom GPIO
- /// pin numbers directly with no re-mapping.
- /// As above, this function needs to be called with root privileges, and note that some pins are different
- /// from revision 1 to revision 2 boards.
- ///
- /// The result code
- [DllImport(WiringPiLibrary, EntryPoint = "wiringPiSetupGpio", SetLastError = true)]
- public static extern int WiringPiSetupGpio();
-
- ///
- /// Identical to wiringPiSetup, however it allows the calling programs to use the physical pin numbers on the P1 connector only.
- /// This function needs to be called with root privileges.
- ///
- /// The result code
- [DllImport(WiringPiLibrary, EntryPoint = "wiringPiSetupPhys", SetLastError = true)]
- public static extern int WiringPiSetupPhys();
-
- ///
- /// This function is undocumented
- ///
- /// The pin.
- /// The mode.
- [DllImport(WiringPiLibrary, EntryPoint = "pinModeAlt", SetLastError = true)]
- public static extern void PinModeAlt(int pin, int mode);
-
- ///
- /// This sets the mode of a pin to either INPUT, OUTPUT, PWM_OUTPUT or GPIO_CLOCK.
- /// Note that only wiringPi pin 1 (BCM_GPIO 18) supports PWM output and only wiringPi pin 7 (BCM_GPIO 4)
- /// supports CLOCK output modes.
- ///
- /// This function has no effect when in Sys mode. If you need to change the pin mode, then you can
- /// do it with the gpio program in a script before you start your program.
- ///
- /// The pin.
- /// The mode.
- [DllImport(WiringPiLibrary, EntryPoint = "pinMode", SetLastError = true)]
- public static extern void PinMode(int pin, int mode);
-
- ///
- /// This sets the pull-up or pull-down resistor mode on the given pin, which should be set as an input.
- /// Unlike the Arduino, the BCM2835 has both pull-up an down internal resistors. The parameter pud should be; PUD_OFF,
- /// (no pull up/down), PUD_DOWN (pull to ground) or PUD_UP (pull to 3.3v) The internal pull up/down resistors
- /// have a value of approximately 50KΩ on the Raspberry Pi.
- ///
- /// This function has no effect on the Raspberry Pi’s GPIO pins when in Sys mode.
- /// If you need to activate a pull-up/pull-down, then you can do it with the gpio program in a script before you start your program.
- ///
- /// The pin.
- /// The pud.
- [DllImport(WiringPiLibrary, EntryPoint = "pullUpDnControl", SetLastError = true)]
- public static extern void PullUpDnControl(int pin, int pud);
-
- ///
- /// This function returns the value read at the given pin. It will be HIGH or LOW (1 or 0) depending on the logic level at the pin.
- ///
- /// The pin.
- /// The result code
- [DllImport(WiringPiLibrary, EntryPoint = "digitalRead", SetLastError = true)]
- public static extern int DigitalRead(int pin);
-
- ///
- /// Writes the value HIGH or LOW (1 or 0) to the given pin which must have been previously set as an output.
- /// WiringPi treats any non-zero number as HIGH, however 0 is the only representation of LOW.
- ///
- /// The pin.
- /// The value.
- [DllImport(WiringPiLibrary, EntryPoint = "digitalWrite", SetLastError = true)]
- public static extern void DigitalWrite(int pin, int value);
-
- ///
- /// Writes the value to the PWM register for the given pin. The Raspberry Pi has one
- /// on-board PWM pin, pin 1 (BMC_GPIO 18, Phys 12) and the range is 0-1024.
- /// Other PWM devices may have other PWM ranges.
- /// This function is not able to control the Pi’s on-board PWM when in Sys mode.
- ///
- /// The pin.
- /// The value.
- [DllImport(WiringPiLibrary, EntryPoint = "pwmWrite", SetLastError = true)]
- public static extern void PwmWrite(int pin, int value);
-
- ///
- /// This returns the value read on the supplied analog input pin. You will need to
- /// register additional analog modules to enable this function for devices such as the Gertboard, quick2Wire analog board, etc.
- ///
- /// The pin.
- /// The result code
- [DllImport(WiringPiLibrary, EntryPoint = "analogRead", SetLastError = true)]
- public static extern int AnalogRead(int pin);
-
- ///
- /// This writes the given value to the supplied analog pin. You will need to register additional
- /// analog modules to enable this function for devices such as the Gertboard.
- ///
- /// The pin.
- /// The value.
- [DllImport(WiringPiLibrary, EntryPoint = "analogWrite", SetLastError = true)]
- public static extern void AnalogWrite(int pin, int value);
-
- ///
- /// This returns the board revision of the Raspberry Pi. It will be either 1 or 2. Some of the BCM_GPIO pins changed number and
- /// function when moving from board revision 1 to 2, so if you are using BCM_GPIO pin numbers, then you need to be aware of the differences.
- ///
- /// The result code
- [DllImport(WiringPiLibrary, EntryPoint = "piBoardRev", SetLastError = true)]
- public static extern int PiBoardRev();
-
- ///
- /// This function is undocumented
- ///
- /// The model.
- /// The memory.
- /// The maker.
- /// The over volted.
- /// The result code
- [DllImport(WiringPiLibrary, EntryPoint = "piBoardId", SetLastError = true)]
- public static extern int PiBoardId(ref int model, ref int mem, ref int maker, ref int overVolted);
-
- ///
- /// This returns the BCM_GPIO pin number of the supplied wiringPi pin. It takes the board revision into account.
- ///
- /// The w pi pin.
- /// The result code
- [DllImport(WiringPiLibrary, EntryPoint = "wpiPinToGpio", SetLastError = true)]
- public static extern int WpiPinToGpio(int wPiPin);
-
- ///
- /// This returns the BCM_GPIO pin number of the supplied physical pin on the P1 connector.
- ///
- /// The physical pin.
- /// The result code
- [DllImport(WiringPiLibrary, EntryPoint = "physPinToGpio", SetLastError = true)]
- public static extern int PhysPinToGpio(int physPin);
-
- ///
- /// This sets the “strength” of the pad drivers for a particular group of pins.
- /// There are 3 groups of pins and the drive strength is from 0 to 7. Do not use this unless you know what you are doing.
- ///
- /// The group.
- /// The value.
- /// The result code
- [DllImport(WiringPiLibrary, EntryPoint = "setPadDrive", SetLastError = true)]
- public static extern int SetPadDrive(int group, int value);
-
- ///
- /// Undocumented function
- ///
- /// The pin.
- /// The result code
- [DllImport(WiringPiLibrary, EntryPoint = "getAlt", SetLastError = true)]
- public static extern int GetAlt(int pin);
-
- ///
- /// Undocumented function
- ///
- /// The pin.
- /// The freq.
- /// The result code
- [DllImport(WiringPiLibrary, EntryPoint = "pwmToneWrite", SetLastError = true)]
- public static extern int PwmToneWrite(int pin, int freq);
-
- ///
- /// This writes the 8-bit byte supplied to the first 8 GPIO pins.
- /// It’s the fastest way to set all 8 bits at once to a particular value, although it still takes two write operations to the Pi’s GPIO hardware.
- ///
- /// The value.
- [DllImport(WiringPiLibrary, EntryPoint = "digitalWriteByte", SetLastError = true)]
- public static extern void DigitalWriteByte(int value);
-
- ///
- /// This writes the 8-bit byte supplied to the first 8 GPIO pins.
- /// It’s the fastest way to set all 8 bits at once to a particular value, although it still takes two write operations to the Pi’s GPIO hardware.
- ///
- /// The value.
- [DllImport(WiringPiLibrary, EntryPoint = "digitalWriteByte2", SetLastError = true)]
- public static extern void DigitalWriteByte2(int value);
-
- ///
- /// Undocumented function
- /// This reads the 8-bit byte supplied to the first 8 GPIO pins.
- /// It’s the fastest way to get all 8 bits at once to a particular value.
- ///
- /// The result code
- [DllImport(WiringPiLibrary, EntryPoint = "digitalReadByte", SetLastError = true)]
- public static extern uint DigitalReadByte();
-
- ///
- /// Undocumented function
- /// This reads the 8-bit byte supplied to the first 8 GPIO pins.
- /// It’s the fastest way to get all 8 bits at once to a particular value.
- ///
- /// The result code
- [DllImport(WiringPiLibrary, EntryPoint = "digitalReadByte2", SetLastError = true)]
- public static extern uint DigitalReadByte2();
-
- ///
- /// The PWM generator can run in 2 modes – “balanced” and “mark:space”. The mark:space mode is traditional,
- /// however the default mode in the Pi is “balanced”. You can switch modes by supplying the parameter: PWM_MODE_BAL or PWM_MODE_MS.
- ///
- /// The mode.
- [DllImport(WiringPiLibrary, EntryPoint = "pwmSetMode", SetLastError = true)]
- public static extern void PwmSetMode(int mode);
-
- ///
- /// This sets the range register in the PWM generator. The default is 1024.
- ///
- /// The range.
- [DllImport(WiringPiLibrary, EntryPoint = "pwmSetRange", SetLastError = true)]
- public static extern void PwmSetRange(uint range);
-
- ///
- /// This sets the divisor for the PWM clock.
- /// Note: The PWM control functions can not be used when in Sys mode.
- /// To understand more about the PWM system, you’ll need to read the Broadcom ARM peripherals manual.
- ///
- /// The divisor.
- [DllImport(WiringPiLibrary, EntryPoint = "pwmSetClock", SetLastError = true)]
- public static extern void PwmSetClock(int divisor);
-
- ///
- /// Undocumented function
- ///
- /// The pin.
- /// The freq.
- [DllImport(WiringPiLibrary, EntryPoint = "gpioClockSet", SetLastError = true)]
- public static extern void GpioClockSet(int pin, int freq);
-
- ///
- /// Note: Jan 2013: The waitForInterrupt() function is deprecated – you should use the newer and easier to use wiringPiISR() function below.
- /// When called, it will wait for an interrupt event to happen on that pin and your program will be stalled. The timeOut parameter is given in milliseconds,
- /// or can be -1 which means to wait forever.
- /// The return value is -1 if an error occurred (and errno will be set appropriately), 0 if it timed out, or 1 on a successful interrupt event.
- /// Before you call waitForInterrupt, you must first initialise the GPIO pin and at present the only way to do this is to use the gpio program, either
- /// in a script, or using the system() call from inside your program.
- /// e.g. We want to wait for a falling-edge interrupt on GPIO pin 0, so to setup the hardware, we need to run: gpio edge 0 falling
- /// before running the program.
- ///
- /// The pin.
- /// The timeout.
- /// The result code
- [Obsolete]
- [DllImport(WiringPiLibrary, EntryPoint = "waitForInterrupt", SetLastError = true)]
- public static extern int WaitForInterrupt(int pin, int timeout);
-
- ///
- /// This function registers a function to received interrupts on the specified pin.
- /// The edgeType parameter is either INT_EDGE_FALLING, INT_EDGE_RISING, INT_EDGE_BOTH or INT_EDGE_SETUP.
- /// If it is INT_EDGE_SETUP then no initialisation of the pin will happen – it’s assumed that you have already setup the pin elsewhere
- /// (e.g. with the gpio program), but if you specify one of the other types, then the pin will be exported and initialised as specified.
- /// This is accomplished via a suitable call to the gpio utility program, so it need to be available.
- /// The pin number is supplied in the current mode – native wiringPi, BCM_GPIO, physical or Sys modes.
- /// This function will work in any mode, and does not need root privileges to work.
- /// The function will be called when the interrupt triggers. When it is triggered, it’s cleared in the dispatcher before calling your function,
- /// so if a subsequent interrupt fires before you finish your handler, then it won’t be missed. (However it can only track one more interrupt,
- /// if more than one interrupt fires while one is being handled then they will be ignored)
- /// This function is run at a high priority (if the program is run using sudo, or as root) and executes concurrently with the main program.
- /// It has full access to all the global variables, open file handles and so on.
- ///
- /// The pin.
- /// The mode.
- /// The method.
- /// The result code
- [DllImport(WiringPiLibrary, EntryPoint = "wiringPiISR", SetLastError = true)]
- public static extern int WiringPiISR(int pin, int mode, InterruptServiceRoutineCallback method);
-
- ///
- /// This function creates a thread which is another function in your program previously declared using the PI_THREAD declaration.
- /// This function is then run concurrently with your main program. An example may be to have this function wait for an interrupt while
- /// your program carries on doing other tasks. The thread can indicate an event, or action by using global variables to
- /// communicate back to the main program, or other threads.
- ///
- /// The method.
- /// The result code
- [DllImport(WiringPiLibrary, EntryPoint = "piThreadCreate", SetLastError = true)]
- public static extern int PiThreadCreate(ThreadWorker method);
-
- ///
- /// These allow you to synchronise variable updates from your main program to any threads running in your program. keyNum is a number from 0 to 3 and represents a key.
- /// When another process tries to lock the same key, it will be stalled until the first process has unlocked the same key.
- /// You may need to use these functions to ensure that you get valid data when exchanging data between your main program and a thread
- /// – otherwise it’s possible that the thread could wake-up halfway during your data copy and change the data –
- /// so the data you end up copying is incomplete, or invalid. See the wfi.c program in the examples directory for an example.
- ///
- /// The key.
- [DllImport(WiringPiLibrary, EntryPoint = "piLock", SetLastError = true)]
- public static extern void PiLock(int key);
-
- ///
- /// These allow you to synchronise variable updates from your main program to any threads running in your program. keyNum is a number from 0 to 3 and represents a key.
- /// When another process tries to lock the same key, it will be stalled until the first process has unlocked the same key.
- /// You may need to use these functions to ensure that you get valid data when exchanging data between your main program and a thread
- /// – otherwise it’s possible that the thread could wake-up halfway during your data copy and change the data –
- /// so the data you end up copying is incomplete, or invalid. See the wfi.c program in the examples directory for an example.
- ///
- /// The key.
- [DllImport(WiringPiLibrary, EntryPoint = "piUnlock", SetLastError = true)]
- public static extern void PiUnlock(int key);
-
- ///
- /// This attempts to shift your program (or thread in a multi-threaded program) to a higher priority
- /// and enables a real-time scheduling. The priority parameter should be from 0 (the default) to 99 (the maximum).
- /// This won’t make your program go any faster, but it will give it a bigger slice of time when other programs are running.
- /// The priority parameter works relative to others – so you can make one program priority 1 and another priority 2
- /// and it will have the same effect as setting one to 10 and the other to 90 (as long as no other
- /// programs are running with elevated priorities)
- /// The return value is 0 for success and -1 for error. If an error is returned, the program should then consult the errno global variable, as per the usual conventions.
- /// Note: Only programs running as root can change their priority. If called from a non-root program then nothing happens.
- ///
- /// The priority.
- /// The result code
- [DllImport(WiringPiLibrary, EntryPoint = "piHiPri", SetLastError = true)]
- public static extern int PiHiPri(int priority);
-
- ///
- /// This causes program execution to pause for at least howLong milliseconds.
- /// Due to the multi-tasking nature of Linux it could be longer.
- /// Note that the maximum delay is an unsigned 32-bit integer or approximately 49 days.
- ///
- /// The how long.
- [DllImport(WiringPiLibrary, EntryPoint = "delay", SetLastError = true)]
- public static extern void Delay(uint howLong);
-
- ///
- /// This causes program execution to pause for at least howLong microseconds.
- /// Due to the multi-tasking nature of Linux it could be longer.
- /// Note that the maximum delay is an unsigned 32-bit integer microseconds or approximately 71 minutes.
- /// Delays under 100 microseconds are timed using a hard-coded loop continually polling the system time,
- /// Delays over 100 microseconds are done using the system nanosleep() function – You may need to consider the implications
- /// of very short delays on the overall performance of the system, especially if using threads.
- ///
- /// The how long.
- [DllImport(WiringPiLibrary, EntryPoint = "delayMicroseconds", SetLastError = true)]
- public static extern void DelayMicroseconds(uint howLong);
-
- ///
- /// This returns a number representing the number of milliseconds since your program called one of the wiringPiSetup functions.
- /// It returns an unsigned 32-bit number which wraps after 49 days.
- ///
- /// The result code
- [DllImport(WiringPiLibrary, EntryPoint = "millis", SetLastError = true)]
- public static extern uint Millis();
-
- ///
- /// This returns a number representing the number of microseconds since your program called one of
- /// the wiringPiSetup functions. It returns an unsigned 32-bit number which wraps after approximately 71 minutes.
- ///
- /// The result code
- [DllImport(WiringPiLibrary, EntryPoint = "micros", SetLastError = true)]
- public static extern uint Micros();
-
- #endregion
- }
+ /// The result code
+ [DllImport(WiringPiLibrary, EntryPoint = "wiringPiSetup", SetLastError = true)]
+ public static extern Int32 WiringPiSetup();
+
+ ///
+ /// This initialises wiringPi but uses the /sys/class/gpio interface rather than accessing the hardware directly.
+ /// This can be called as a non-root user provided the GPIO pins have been exported before-hand using the gpio program.
+ /// Pin numbering in this mode is the native Broadcom GPIO numbers – the same as wiringPiSetupGpio() above,
+ /// so be aware of the differences between Rev 1 and Rev 2 boards.
+ ///
+ /// Note: In this mode you can only use the pins which have been exported via the /sys/class/gpio interface before you run your program.
+ /// You can do this in a separate shell-script, or by using the system() function from inside your program to call the gpio program.
+ /// Also note that some functions have no effect when using this mode as they’re not currently possible to action unless called with root privileges.
+ /// (although you can use system() to call gpio to set/change modes if needed)
+ ///
+ /// The result code
+ [DllImport(WiringPiLibrary, EntryPoint = "wiringPiSetupSys", SetLastError = true)]
+ public static extern Int32 WiringPiSetupSys();
+
+ ///
+ /// This is identical to wiringPiSetup, however it allows the calling programs to use the Broadcom GPIO
+ /// pin numbers directly with no re-mapping.
+ /// As above, this function needs to be called with root privileges, and note that some pins are different
+ /// from revision 1 to revision 2 boards.
+ ///
+ /// The result code
+ [DllImport(WiringPiLibrary, EntryPoint = "wiringPiSetupGpio", SetLastError = true)]
+ public static extern Int32 WiringPiSetupGpio();
+
+ ///
+ /// Identical to wiringPiSetup, however it allows the calling programs to use the physical pin numbers on the P1 connector only.
+ /// This function needs to be called with root privileges.
+ ///
+ /// The result code
+ [DllImport(WiringPiLibrary, EntryPoint = "wiringPiSetupPhys", SetLastError = true)]
+ public static extern Int32 WiringPiSetupPhys();
+
+ ///
+ /// This function is undocumented
+ ///
+ /// The pin.
+ /// The mode.
+ [DllImport(WiringPiLibrary, EntryPoint = "pinModeAlt", SetLastError = true)]
+ public static extern void PinModeAlt(Int32 pin, Int32 mode);
+
+ ///
+ /// This sets the mode of a pin to either INPUT, OUTPUT, PWM_OUTPUT or GPIO_CLOCK.
+ /// Note that only wiringPi pin 1 (BCM_GPIO 18) supports PWM output and only wiringPi pin 7 (BCM_GPIO 4)
+ /// supports CLOCK output modes.
+ ///
+ /// This function has no effect when in Sys mode. If you need to change the pin mode, then you can
+ /// do it with the gpio program in a script before you start your program.
+ ///
+ /// The pin.
+ /// The mode.
+ [DllImport(WiringPiLibrary, EntryPoint = "pinMode", SetLastError = true)]
+ public static extern void PinMode(Int32 pin, Int32 mode);
+
+ ///
+ /// This sets the pull-up or pull-down resistor mode on the given pin, which should be set as an input.
+ /// Unlike the Arduino, the BCM2835 has both pull-up an down internal resistors. The parameter pud should be; PUD_OFF,
+ /// (no pull up/down), PUD_DOWN (pull to ground) or PUD_UP (pull to 3.3v) The internal pull up/down resistors
+ /// have a value of approximately 50KΩ on the Raspberry Pi.
+ ///
+ /// This function has no effect on the Raspberry Pi’s GPIO pins when in Sys mode.
+ /// If you need to activate a pull-up/pull-down, then you can do it with the gpio program in a script before you start your program.
+ ///
+ /// The pin.
+ /// The pud.
+ [DllImport(WiringPiLibrary, EntryPoint = "pullUpDnControl", SetLastError = true)]
+ public static extern void PullUpDnControl(Int32 pin, Int32 pud);
+
+ ///
+ /// This function returns the value read at the given pin. It will be HIGH or LOW (1 or 0) depending on the logic level at the pin.
+ ///
+ /// The pin.
+ /// The result code
+ [DllImport(WiringPiLibrary, EntryPoint = "digitalRead", SetLastError = true)]
+ public static extern Int32 DigitalRead(Int32 pin);
+
+ ///
+ /// Writes the value HIGH or LOW (1 or 0) to the given pin which must have been previously set as an output.
+ /// WiringPi treats any non-zero number as HIGH, however 0 is the only representation of LOW.
+ ///
+ /// The pin.
+ /// The value.
+ [DllImport(WiringPiLibrary, EntryPoint = "digitalWrite", SetLastError = true)]
+ public static extern void DigitalWrite(Int32 pin, Int32 value);
+
+ ///
+ /// Writes the value to the PWM register for the given pin. The Raspberry Pi has one
+ /// on-board PWM pin, pin 1 (BMC_GPIO 18, Phys 12) and the range is 0-1024.
+ /// Other PWM devices may have other PWM ranges.
+ /// This function is not able to control the Pi’s on-board PWM when in Sys mode.
+ ///
+ /// The pin.
+ /// The value.
+ [DllImport(WiringPiLibrary, EntryPoint = "pwmWrite", SetLastError = true)]
+ public static extern void PwmWrite(Int32 pin, Int32 value);
+
+ ///
+ /// This returns the value read on the supplied analog input pin. You will need to
+ /// register additional analog modules to enable this function for devices such as the Gertboard, quick2Wire analog board, etc.
+ ///
+ /// The pin.
+ /// The result code
+ [DllImport(WiringPiLibrary, EntryPoint = "analogRead", SetLastError = true)]
+ public static extern Int32 AnalogRead(Int32 pin);
+
+ ///
+ /// This writes the given value to the supplied analog pin. You will need to register additional
+ /// analog modules to enable this function for devices such as the Gertboard.
+ ///
+ /// The pin.
+ /// The value.
+ [DllImport(WiringPiLibrary, EntryPoint = "analogWrite", SetLastError = true)]
+ public static extern void AnalogWrite(Int32 pin, Int32 value);
+
+ ///
+ /// This returns the board revision of the Raspberry Pi. It will be either 1 or 2. Some of the BCM_GPIO pins changed number and
+ /// function when moving from board revision 1 to 2, so if you are using BCM_GPIO pin numbers, then you need to be aware of the differences.
+ ///
+ /// The result code
+ [DllImport(WiringPiLibrary, EntryPoint = "piBoardRev", SetLastError = true)]
+ public static extern Int32 PiBoardRev();
+
+ ///
+ /// This function is undocumented
+ ///
+ /// The model.
+ /// The memory.
+ /// The maker.
+ /// The over volted.
+ /// The result code
+ [DllImport(WiringPiLibrary, EntryPoint = "piBoardId", SetLastError = true)]
+ public static extern Int32 PiBoardId(ref Int32 model, ref Int32 mem, ref Int32 maker, ref Int32 overVolted);
+
+ ///
+ /// This returns the BCM_GPIO pin number of the supplied wiringPi pin. It takes the board revision into account.
+ ///
+ /// The w pi pin.
+ /// The result code
+ [DllImport(WiringPiLibrary, EntryPoint = "wpiPinToGpio", SetLastError = true)]
+ public static extern Int32 WpiPinToGpio(Int32 wPiPin);
+
+ ///
+ /// This returns the BCM_GPIO pin number of the supplied physical pin on the P1 connector.
+ ///
+ /// The physical pin.
+ /// The result code
+ [DllImport(WiringPiLibrary, EntryPoint = "physPinToGpio", SetLastError = true)]
+ public static extern Int32 PhysPinToGpio(Int32 physPin);
+
+ ///
+ /// This sets the “strength” of the pad drivers for a particular group of pins.
+ /// There are 3 groups of pins and the drive strength is from 0 to 7. Do not use this unless you know what you are doing.
+ ///
+ /// The group.
+ /// The value.
+ /// The result code
+ [DllImport(WiringPiLibrary, EntryPoint = "setPadDrive", SetLastError = true)]
+ public static extern Int32 SetPadDrive(Int32 group, Int32 value);
+
+ ///
+ /// Undocumented function
+ ///
+ /// The pin.
+ /// The result code
+ [DllImport(WiringPiLibrary, EntryPoint = "getAlt", SetLastError = true)]
+ public static extern Int32 GetAlt(Int32 pin);
+
+ ///
+ /// Undocumented function
+ ///
+ /// The pin.
+ /// The freq.
+ /// The result code
+ [DllImport(WiringPiLibrary, EntryPoint = "pwmToneWrite", SetLastError = true)]
+ public static extern Int32 PwmToneWrite(Int32 pin, Int32 freq);
+
+ ///
+ /// This writes the 8-bit byte supplied to the first 8 GPIO pins.
+ /// It’s the fastest way to set all 8 bits at once to a particular value, although it still takes two write operations to the Pi’s GPIO hardware.
+ ///
+ /// The value.
+ [DllImport(WiringPiLibrary, EntryPoint = "digitalWriteByte", SetLastError = true)]
+ public static extern void DigitalWriteByte(Int32 value);
+
+ ///
+ /// This writes the 8-bit byte supplied to the first 8 GPIO pins.
+ /// It’s the fastest way to set all 8 bits at once to a particular value, although it still takes two write operations to the Pi’s GPIO hardware.
+ ///
+ /// The value.
+ [DllImport(WiringPiLibrary, EntryPoint = "digitalWriteByte2", SetLastError = true)]
+ public static extern void DigitalWriteByte2(Int32 value);
+
+ ///
+ /// Undocumented function
+ /// This reads the 8-bit byte supplied to the first 8 GPIO pins.
+ /// It’s the fastest way to get all 8 bits at once to a particular value.
+ ///
+ /// The result code
+ [DllImport(WiringPiLibrary, EntryPoint = "digitalReadByte", SetLastError = true)]
+ public static extern UInt32 DigitalReadByte();
+
+ ///
+ /// Undocumented function
+ /// This reads the 8-bit byte supplied to the first 8 GPIO pins.
+ /// It’s the fastest way to get all 8 bits at once to a particular value.
+ ///
+ /// The result code
+ [DllImport(WiringPiLibrary, EntryPoint = "digitalReadByte2", SetLastError = true)]
+ public static extern UInt32 DigitalReadByte2();
+
+ ///
+ /// The PWM generator can run in 2 modes – “balanced” and “mark:space”. The mark:space mode is traditional,
+ /// however the default mode in the Pi is “balanced”. You can switch modes by supplying the parameter: PWM_MODE_BAL or PWM_MODE_MS.
+ ///
+ /// The mode.
+ [DllImport(WiringPiLibrary, EntryPoint = "pwmSetMode", SetLastError = true)]
+ public static extern void PwmSetMode(Int32 mode);
+
+ ///
+ /// This sets the range register in the PWM generator. The default is 1024.
+ ///
+ /// The range.
+ [DllImport(WiringPiLibrary, EntryPoint = "pwmSetRange", SetLastError = true)]
+ public static extern void PwmSetRange(UInt32 range);
+
+ ///
+ /// This sets the divisor for the PWM clock.
+ /// Note: The PWM control functions can not be used when in Sys mode.
+ /// To understand more about the PWM system, you’ll need to read the Broadcom ARM peripherals manual.
+ ///
+ /// The divisor.
+ [DllImport(WiringPiLibrary, EntryPoint = "pwmSetClock", SetLastError = true)]
+ public static extern void PwmSetClock(Int32 divisor);
+
+ ///
+ /// Undocumented function
+ ///
+ /// The pin.
+ /// The freq.
+ [DllImport(WiringPiLibrary, EntryPoint = "gpioClockSet", SetLastError = true)]
+ public static extern void GpioClockSet(Int32 pin, Int32 freq);
+
+ ///
+ /// Note: Jan 2013: The waitForInterrupt() function is deprecated – you should use the newer and easier to use wiringPiISR() function below.
+ /// When called, it will wait for an interrupt event to happen on that pin and your program will be stalled. The timeOut parameter is given in milliseconds,
+ /// or can be -1 which means to wait forever.
+ /// The return value is -1 if an error occurred (and errno will be set appropriately), 0 if it timed out, or 1 on a successful interrupt event.
+ /// Before you call waitForInterrupt, you must first initialise the GPIO pin and at present the only way to do this is to use the gpio program, either
+ /// in a script, or using the system() call from inside your program.
+ /// e.g. We want to wait for a falling-edge interrupt on GPIO pin 0, so to setup the hardware, we need to run: gpio edge 0 falling
+ /// before running the program.
+ ///
+ /// The pin.
+ /// The timeout.
+ /// The result code
+ [Obsolete]
+ [DllImport(WiringPiLibrary, EntryPoint = "waitForInterrupt", SetLastError = true)]
+ public static extern Int32 WaitForInterrupt(Int32 pin, Int32 timeout);
+
+ ///
+ /// This function registers a function to received interrupts on the specified pin.
+ /// The edgeType parameter is either INT_EDGE_FALLING, INT_EDGE_RISING, INT_EDGE_BOTH or INT_EDGE_SETUP.
+ /// If it is INT_EDGE_SETUP then no initialisation of the pin will happen – it’s assumed that you have already setup the pin elsewhere
+ /// (e.g. with the gpio program), but if you specify one of the other types, then the pin will be exported and initialised as specified.
+ /// This is accomplished via a suitable call to the gpio utility program, so it need to be available.
+ /// The pin number is supplied in the current mode – native wiringPi, BCM_GPIO, physical or Sys modes.
+ /// This function will work in any mode, and does not need root privileges to work.
+ /// The function will be called when the interrupt triggers. When it is triggered, it’s cleared in the dispatcher before calling your function,
+ /// so if a subsequent interrupt fires before you finish your handler, then it won’t be missed. (However it can only track one more interrupt,
+ /// if more than one interrupt fires while one is being handled then they will be ignored)
+ /// This function is run at a high priority (if the program is run using sudo, or as root) and executes concurrently with the main program.
+ /// It has full access to all the global variables, open file handles and so on.
+ ///
+ /// The pin.
+ /// The mode.
+ /// The method.
+ /// The result code
+ [DllImport(WiringPiLibrary, EntryPoint = "wiringPiISR", SetLastError = true)]
+ public static extern Int32 WiringPiISR(Int32 pin, Int32 mode, InterruptServiceRoutineCallback method);
+
+ ///
+ /// This function creates a thread which is another function in your program previously declared using the PI_THREAD declaration.
+ /// This function is then run concurrently with your main program. An example may be to have this function wait for an interrupt while
+ /// your program carries on doing other tasks. The thread can indicate an event, or action by using global variables to
+ /// communicate back to the main program, or other threads.
+ ///
+ /// The method.
+ /// The result code
+ [DllImport(WiringPiLibrary, EntryPoint = "piThreadCreate", SetLastError = true)]
+ public static extern Int32 PiThreadCreate(ThreadWorker method);
+
+ ///
+ /// These allow you to synchronise variable updates from your main program to any threads running in your program. keyNum is a number from 0 to 3 and represents a key.
+ /// When another process tries to lock the same key, it will be stalled until the first process has unlocked the same key.
+ /// You may need to use these functions to ensure that you get valid data when exchanging data between your main program and a thread
+ /// – otherwise it’s possible that the thread could wake-up halfway during your data copy and change the data –
+ /// so the data you end up copying is incomplete, or invalid. See the wfi.c program in the examples directory for an example.
+ ///
+ /// The key.
+ [DllImport(WiringPiLibrary, EntryPoint = "piLock", SetLastError = true)]
+ public static extern void PiLock(Int32 key);
+
+ ///
+ /// These allow you to synchronise variable updates from your main program to any threads running in your program. keyNum is a number from 0 to 3 and represents a key.
+ /// When another process tries to lock the same key, it will be stalled until the first process has unlocked the same key.
+ /// You may need to use these functions to ensure that you get valid data when exchanging data between your main program and a thread
+ /// – otherwise it’s possible that the thread could wake-up halfway during your data copy and change the data –
+ /// so the data you end up copying is incomplete, or invalid. See the wfi.c program in the examples directory for an example.
+ ///
+ /// The key.
+ [DllImport(WiringPiLibrary, EntryPoint = "piUnlock", SetLastError = true)]
+ public static extern void PiUnlock(Int32 key);
+
+ ///
+ /// This attempts to shift your program (or thread in a multi-threaded program) to a higher priority
+ /// and enables a real-time scheduling. The priority parameter should be from 0 (the default) to 99 (the maximum).
+ /// This won’t make your program go any faster, but it will give it a bigger slice of time when other programs are running.
+ /// The priority parameter works relative to others – so you can make one program priority 1 and another priority 2
+ /// and it will have the same effect as setting one to 10 and the other to 90 (as long as no other
+ /// programs are running with elevated priorities)
+ /// The return value is 0 for success and -1 for error. If an error is returned, the program should then consult the errno global variable, as per the usual conventions.
+ /// Note: Only programs running as root can change their priority. If called from a non-root program then nothing happens.
+ ///
+ /// The priority.
+ /// The result code
+ [DllImport(WiringPiLibrary, EntryPoint = "piHiPri", SetLastError = true)]
+ public static extern Int32 PiHiPri(Int32 priority);
+
+ ///
+ /// This causes program execution to pause for at least howLong milliseconds.
+ /// Due to the multi-tasking nature of Linux it could be longer.
+ /// Note that the maximum delay is an unsigned 32-bit integer or approximately 49 days.
+ ///
+ /// The how long.
+ [DllImport(WiringPiLibrary, EntryPoint = "delay", SetLastError = true)]
+ public static extern void Delay(UInt32 howLong);
+
+ ///
+ /// This causes program execution to pause for at least howLong microseconds.
+ /// Due to the multi-tasking nature of Linux it could be longer.
+ /// Note that the maximum delay is an unsigned 32-bit integer microseconds or approximately 71 minutes.
+ /// Delays under 100 microseconds are timed using a hard-coded loop continually polling the system time,
+ /// Delays over 100 microseconds are done using the system nanosleep() function – You may need to consider the implications
+ /// of very short delays on the overall performance of the system, especially if using threads.
+ ///
+ /// The how long.
+ [DllImport(WiringPiLibrary, EntryPoint = "delayMicroseconds", SetLastError = true)]
+ public static extern void DelayMicroseconds(UInt32 howLong);
+
+ ///
+ /// This returns a number representing the number of milliseconds since your program called one of the wiringPiSetup functions.
+ /// It returns an unsigned 32-bit number which wraps after 49 days.
+ ///
+ /// The result code
+ [DllImport(WiringPiLibrary, EntryPoint = "millis", SetLastError = true)]
+ public static extern UInt32 Millis();
+
+ ///
+ /// This returns a number representing the number of microseconds since your program called one of
+ /// the wiringPiSetup functions. It returns an unsigned 32-bit number which wraps after approximately 71 minutes.
+ ///
+ /// The result code
+ [DllImport(WiringPiLibrary, EntryPoint = "micros", SetLastError = true)]
+ public static extern UInt32 Micros();
+
+ #endregion
+ }
}
\ No newline at end of file
diff --git a/Unosquare.RaspberryIO/Pi.cs b/Unosquare.RaspberryIO/Pi.cs
index c3bebf0..5f1046e 100644
--- a/Unosquare.RaspberryIO/Pi.cs
+++ b/Unosquare.RaspberryIO/Pi.cs
@@ -1,110 +1,121 @@
-namespace Unosquare.RaspberryIO
-{
- using Camera;
- using Computer;
- using Gpio;
- using Native;
- using System.Threading.Tasks;
- using Swan.Components;
-
- ///
- /// Our main character. Provides access to the Raspberry Pi's GPIO, system and board information and Camera
- ///
- public static class Pi
- {
- private static readonly object SyncLock = new object();
-
- ///
- /// Initializes static members of the class.
- ///
- static Pi()
- {
- lock (SyncLock)
- {
- // Extraction of embedded resources
- Resources.EmbeddedResources.ExtractAll();
-
- // Instance assignments
- Gpio = GpioController.Instance;
- Info = SystemInfo.Instance;
- Timing = Timing.Instance;
- Spi = SpiBus.Instance;
- I2C = I2CBus.Instance;
- Camera = CameraController.Instance;
- PiDisplay = DsiDisplay.Instance;
- }
- }
-
- #region Components
-
- ///
- /// Provides access to the Raspberry Pi's GPIO as a collection of GPIO Pins.
- ///
- public static GpioController Gpio { get; }
-
- ///
- /// Provides information on this Raspberry Pi's CPU and form factor.
- ///
- public static SystemInfo Info { get; }
-
- ///
- /// Provides access to The PI's Timing and threading API
- ///
- public static Timing Timing { get; }
-
- ///
- /// Provides access to the 2-channel SPI bus
- ///
- public static SpiBus Spi { get; }
-
- ///
- /// Provides access to the functionality of the i2c bus.
- ///
- public static I2CBus I2C { get; }
-
- ///
- /// Provides access to the official Raspberry Pi Camera
- ///
- public static CameraController Camera { get; }
-
- ///
- /// Provides access to the official Raspberry Pi 7-inch DSI Display
- ///
- public static DsiDisplay PiDisplay { get; }
-
- ///
- /// Gets the logger source name.
- ///
- internal static string LoggerSource => typeof(Pi).Namespace;
-
- #endregion
-
- #region Methods
-
- ///
- /// Restarts the Pi. Must be running as SU
- ///
- /// The process result
- public static async Task RestartAsync() => await ProcessRunner.GetProcessResultAsync("reboot", null, null);
-
- ///
- /// Restarts the Pi. Must be running as SU
- ///
- /// The process result
- public static ProcessResult Restart() => RestartAsync().GetAwaiter().GetResult();
-
- ///
- /// Halts the Pi. Must be running as SU
- ///
- /// The process result
- public static async Task ShutdownAsync() => await ProcessRunner.GetProcessResultAsync("halt", null, null);
-
- ///
- /// Halts the Pi. Must be running as SU
- ///
- /// The process result
- public static ProcessResult Shutdown() => ShutdownAsync().GetAwaiter().GetResult();
-
- #endregion
- }
-}
+using Unosquare.RaspberryIO.Camera;
+using Unosquare.RaspberryIO.Computer;
+using Unosquare.RaspberryIO.Gpio;
+using Unosquare.RaspberryIO.Native;
+using System.Threading.Tasks;
+using Unosquare.Swan.Components;
+using System;
+
+namespace Unosquare.RaspberryIO {
+ ///
+ /// Our main character. Provides access to the Raspberry Pi's GPIO, system and board information and Camera
+ ///
+ public static class Pi {
+ private static readonly Object SyncLock = new Object();
+
+ ///
+ /// Initializes static members of the class.
+ ///
+ static Pi() {
+ lock(SyncLock) {
+ // Extraction of embedded resources
+ Resources.EmbeddedResources.ExtractAll();
+
+ // Instance assignments
+ Gpio = GpioController.Instance;
+ Info = SystemInfo.Instance;
+ Timing = Timing.Instance;
+ Spi = SpiBus.Instance;
+ I2C = I2CBus.Instance;
+ Camera = CameraController.Instance;
+ PiDisplay = DsiDisplay.Instance;
+ }
+ }
+
+ #region Components
+
+ ///
+ /// Provides access to the Raspberry Pi's GPIO as a collection of GPIO Pins.
+ ///
+ public static GpioController Gpio {
+ get;
+ }
+
+ ///
+ /// Provides information on this Raspberry Pi's CPU and form factor.
+ ///
+ public static SystemInfo Info {
+ get;
+ }
+
+ ///
+ /// Provides access to The PI's Timing and threading API
+ ///
+ public static Timing Timing {
+ get;
+ }
+
+ ///
+ /// Provides access to the 2-channel SPI bus
+ ///
+ public static SpiBus Spi {
+ get;
+ }
+
+ ///
+ /// Provides access to the functionality of the i2c bus.
+ ///
+ public static I2CBus I2C {
+ get;
+ }
+
+ ///
+ /// Provides access to the official Raspberry Pi Camera
+ ///
+ public static CameraController Camera {
+ get;
+ }
+
+ ///
+ /// Provides access to the official Raspberry Pi 7-inch DSI Display
+ ///
+ public static DsiDisplay PiDisplay {
+ get;
+ }
+
+ ///
+ /// Gets the logger source name.
+ ///
+ internal static String LoggerSource => typeof(Pi).Namespace;
+
+ #endregion
+
+ #region Methods
+
+ ///
+ /// Restarts the Pi. Must be running as SU
+ ///
+ /// The process result
+ public static async Task RestartAsync() => await ProcessRunner.GetProcessResultAsync("reboot", null, null);
+
+ ///
+ /// Restarts the Pi. Must be running as SU
+ ///
+ /// The process result
+ public static ProcessResult Restart() => RestartAsync().GetAwaiter().GetResult();
+
+ ///
+ /// Halts the Pi. Must be running as SU
+ ///
+ /// The process result
+ public static async Task ShutdownAsync() => await ProcessRunner.GetProcessResultAsync("halt", null, null);
+
+ ///
+ /// Halts the Pi. Must be running as SU
+ ///
+ /// The process result
+ public static ProcessResult Shutdown() => ShutdownAsync().GetAwaiter().GetResult();
+
+ #endregion
+ }
+}
\ No newline at end of file
diff --git a/Unosquare.RaspberryIO/Resources/EmbeddedResources.cs b/Unosquare.RaspberryIO/Resources/EmbeddedResources.cs
index 7c8c3b9..ff063ef 100644
--- a/Unosquare.RaspberryIO/Resources/EmbeddedResources.cs
+++ b/Unosquare.RaspberryIO/Resources/EmbeddedResources.cs
@@ -1,65 +1,55 @@
-namespace Unosquare.RaspberryIO.Resources
-{
- using Native;
- using Swan;
- using System;
- using System.Collections.ObjectModel;
- using System.IO;
-
+using Unosquare.RaspberryIO.Native;
+using Unosquare.Swan;
+using System;
+using System.Collections.ObjectModel;
+using System.IO;
+
+namespace Unosquare.RaspberryIO.Resources {
+ ///
+ /// Provides access to embedded assembly files
+ ///
+ internal static class EmbeddedResources {
///
- /// Provides access to embedded assembly files
+ /// Initializes static members of the class.
///
- internal static class EmbeddedResources
- {
- ///
- /// Initializes static members of the class.
- ///
- static EmbeddedResources()
- {
- ResourceNames =
- new ReadOnlyCollection(typeof(EmbeddedResources).Assembly().GetManifestResourceNames());
- }
-
- ///
- /// Gets the resource names.
- ///
- ///
- /// The resource names.
- ///
- public static ReadOnlyCollection ResourceNames { get; }
-
- ///
- /// Extracts all the file resources to the specified base path.
- ///
- public static void ExtractAll()
- {
- var basePath = Runtime.EntryAssemblyDirectory;
- var executablePermissions = Standard.StringToInteger("0777", IntPtr.Zero, 8);
-
- foreach (var resourceName in ResourceNames)
- {
- var filename = resourceName.Substring($"{typeof(EmbeddedResources).Namespace}.".Length);
- var targetPath = Path.Combine(basePath, filename);
- if (File.Exists(targetPath)) return;
-
- using (var stream = typeof(EmbeddedResources).Assembly()
- .GetManifestResourceStream($"{typeof(EmbeddedResources).Namespace}.{filename}"))
- {
- using (var outputStream = File.OpenWrite(targetPath))
- {
- stream?.CopyTo(outputStream);
- }
-
- try
- {
- Standard.Chmod(targetPath, (uint)executablePermissions);
- }
- catch
- {
- /* Ignore */
- }
- }
- }
- }
- }
+ static EmbeddedResources() => ResourceNames = new ReadOnlyCollection(typeof(EmbeddedResources).Assembly().GetManifestResourceNames());
+
+ ///
+ /// Gets the resource names.
+ ///
+ ///
+ /// The resource names.
+ ///
+ public static ReadOnlyCollection ResourceNames {
+ get;
+ }
+
+ ///
+ /// Extracts all the file resources to the specified base path.
+ ///
+ public static void ExtractAll() {
+ String basePath = Runtime.EntryAssemblyDirectory;
+ Int32 executablePermissions = Standard.StringToInteger("0777", IntPtr.Zero, 8);
+
+ foreach(String resourceName in ResourceNames) {
+ String filename = resourceName.Substring($"{typeof(EmbeddedResources).Namespace}.".Length);
+ String targetPath = Path.Combine(basePath, filename);
+ if(File.Exists(targetPath)) {
+ return;
+ }
+
+ using(Stream stream = typeof(EmbeddedResources).Assembly().GetManifestResourceStream($"{typeof(EmbeddedResources).Namespace}.{filename}")) {
+ using(FileStream outputStream = File.OpenWrite(targetPath)) {
+ stream?.CopyTo(outputStream);
+ }
+
+ try {
+ _ = Standard.Chmod(targetPath, (UInt32)executablePermissions);
+ } catch {
+ /* Ignore */
+ }
+ }
+ }
+ }
+ }
}
\ No newline at end of file