-
Notifications
You must be signed in to change notification settings - Fork 582
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Adding GpioPin #1895
Adding GpioPin #1895
Changes from all commits
16a35c4
37de849
1342816
357820c
252c227
5cd6c35
811730d
b524ed4
8ca6aac
08f52d9
9e61fbb
2b21a22
1f4272c
e667d8e
b2c00e1
04a50cb
f627a91
57fb407
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,83 @@ | ||
// Licensed to the .NET Foundation under one or more agreements. | ||
// The .NET Foundation licenses this file to you under the MIT license. | ||
|
||
using System; | ||
using System.Collections.Generic; | ||
using System.Text; | ||
using Moq; | ||
using Xunit; | ||
|
||
namespace System.Device.Gpio.Tests | ||
{ | ||
public class GpioPinTests : IDisposable | ||
{ | ||
private const int PinNumber = 2; | ||
private Mock<MockableGpioDriver> _mockedGpioDriver; | ||
|
||
public GpioPinTests() | ||
{ | ||
_mockedGpioDriver = new Mock<MockableGpioDriver>(MockBehavior.Default); | ||
_mockedGpioDriver.CallBase = true; | ||
} | ||
|
||
public void Dispose() | ||
{ | ||
_mockedGpioDriver.VerifyAll(); | ||
} | ||
|
||
[Fact] | ||
public void TestOpenPin() | ||
{ | ||
// Arrange | ||
_mockedGpioDriver.Setup(x => x.OpenPinEx(PinNumber)); | ||
_mockedGpioDriver.Setup(x => x.IsPinModeSupportedEx(PinNumber, It.IsAny<PinMode>())).Returns(true); | ||
_mockedGpioDriver.Setup(x => x.SetPinModeEx(PinNumber, It.IsAny<PinMode>())); | ||
_mockedGpioDriver.Setup(x => x.GetPinModeEx(PinNumber)).Returns(PinMode.Input); | ||
var ctrl = new GpioController(PinNumberingScheme.Logical, _mockedGpioDriver.Object); | ||
// Act | ||
GpioPin pin = ctrl.OpenPin(PinNumber, PinMode.Input); | ||
// Assert | ||
Assert.Equal(pin.PinNumber, PinNumber); | ||
Assert.Equal(PinMode.Input, pin.GetPinMode()); | ||
} | ||
|
||
[Fact] | ||
public void TestClosePin() | ||
{ | ||
// Arrange | ||
_mockedGpioDriver.Setup(x => x.OpenPinEx(PinNumber)); | ||
_mockedGpioDriver.Setup(x => x.IsPinModeSupportedEx(PinNumber, It.IsAny<PinMode>())).Returns(true); | ||
_mockedGpioDriver.Setup(x => x.SetPinModeEx(PinNumber, It.IsAny<PinMode>())); | ||
var ctrl = new GpioController(PinNumberingScheme.Logical, _mockedGpioDriver.Object); | ||
// Act | ||
GpioPin pin = ctrl.OpenPin(PinNumber, PinMode.Input); | ||
ctrl.ClosePin(PinNumber); | ||
// Assert | ||
// This should work even if the pin is closed in the controller as the driver has no idea | ||
// Of the controller behavior. | ||
var ret = pin.Read(); | ||
} | ||
|
||
[Fact] | ||
public void TestToggleReadWrite() | ||
{ | ||
// Arrange | ||
PinValue pinValue = PinValue.High; | ||
_mockedGpioDriver.Setup(x => x.OpenPinEx(PinNumber)); | ||
_mockedGpioDriver.Setup(x => x.IsPinModeSupportedEx(PinNumber, It.IsAny<PinMode>())).Returns(true); | ||
_mockedGpioDriver.Setup(x => x.SetPinModeEx(PinNumber, It.IsAny<PinMode>())); | ||
_mockedGpioDriver.Setup(x => x.ReadEx(PinNumber)).Returns(pinValue); | ||
var ctrl = new GpioController(PinNumberingScheme.Logical, _mockedGpioDriver.Object); | ||
// Act | ||
GpioPin pin = ctrl.OpenPin(PinNumber, PinMode.Input); | ||
pin.Write(pinValue); | ||
// Assert | ||
Assert.Equal(pinValue, pin.Read()); | ||
pin.Toggle(); | ||
// Make sure we setup the drive properly | ||
pinValue = !pinValue; | ||
_mockedGpioDriver.Setup(x => x.ReadEx(PinNumber)).Returns(pinValue); | ||
Assert.Equal(pinValue, pin.Read()); | ||
} | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -14,6 +14,7 @@ public class Windows10Driver : GpioDriver | |
{ | ||
private static readonly WinGpio.GpioController s_winGpioController = WinGpio.GpioController.GetDefault(); | ||
private readonly Dictionary<int, Windows10DriverPin> _openPins = new Dictionary<int, Windows10DriverPin>(); | ||
private readonly Dictionary<int, PinValue> _pinValues = new Dictionary<int, PinValue>(); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. why does LibGpiodDriver need ConcurrentDictionary while this one is ok with regular Dictionary? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. (it's an existing issue anyway so don't worry about this in this PR) |
||
|
||
/// <summary> | ||
/// Initializes a new instance of the <see cref="Windows10Driver"/> class. | ||
|
@@ -68,6 +69,7 @@ protected internal override void ClosePin(int pinNumber) | |
{ | ||
pin.ClosePin(); | ||
_openPins.Remove(pinNumber); | ||
_pinValues.Remove(pinNumber); | ||
} | ||
} | ||
|
||
|
@@ -113,14 +115,24 @@ protected internal override void OpenPin(int pinNumber) | |
|
||
WinGpio.GpioPin windowsPin = s_winGpioController.OpenPin(pinNumber, WinGpio.GpioSharingMode.Exclusive); | ||
_openPins[pinNumber] = new Windows10DriverPin(this, windowsPin); | ||
// Default value, override by the set pin mode with another default value | ||
_pinValues[pinNumber] = PinValue.Low; | ||
} | ||
|
||
/// <summary> | ||
/// Reads the current value of a pin. | ||
/// </summary> | ||
/// <param name="pinNumber">The pin number in the driver's logical numbering scheme.</param> | ||
/// <returns>The value of the pin.</returns> | ||
protected internal override PinValue Read(int pinNumber) => LookupOpenPin(pinNumber).Read(); | ||
protected internal override PinValue Read(int pinNumber) | ||
{ | ||
var value = LookupOpenPin(pinNumber).Read(); | ||
_pinValues[pinNumber] = value; | ||
return value; | ||
} | ||
|
||
/// <inheritdoc/> | ||
protected internal override void Toggle(int pinNumber) => Write(pinNumber, !_pinValues[pinNumber]); | ||
|
||
/// <summary> | ||
/// Removes a handler for a pin value changed event. | ||
|
@@ -152,7 +164,11 @@ protected internal override WaitForEventResult WaitForEvent(int pinNumber, PinEv | |
/// </summary> | ||
/// <param name="pinNumber">The pin number in the driver's logical numbering scheme.</param> | ||
/// <param name="value">The value to be written to the pin.</param> | ||
protected internal override void Write(int pinNumber, PinValue value) => LookupOpenPin(pinNumber).Write(value); | ||
protected internal override void Write(int pinNumber, PinValue value) | ||
{ | ||
LookupOpenPin(pinNumber).Write(value); | ||
_pinValues[pinNumber] = value; | ||
} | ||
|
||
/// <summary> | ||
/// Lookups an open pin in the driver. | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm looking at this and wondering - perhaps GpioDriver could have virtual
CreateGpioPin
with default implementation - then in here you'd returnLibGpiodPin
and moveCurrentPinValue
,EventHandler
,SafeLineHandle
toLibGpiodPin
- this way you could have just oneConcurrentDictionary
here and using pin directly would have advantage of not touching ConcurrentDictionaryThere was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
we talked offline and we can do this as a separate change most likely without any API changes (only addition suggested here)