未验证 提交 db790317 编写于 作者: J John Tasler 提交者: GitHub

Initial implementation of the Windows PWM driver (#65)

上级 560732a7
......@@ -2,9 +2,6 @@
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
using System.Collections.Generic;
using System.IO;
namespace System.Device.Pwm.Drivers
{
public class UnixPwmDriver : PwmDriver
......
......@@ -6,29 +6,16 @@ namespace System.Device.Pwm.Drivers
{
public class Windows10PwmDriver : PwmDriver
{
protected internal override void ChangeDutyCycle(int pwmChip, int pwmChannel, double dutyCycleInNanoSeconds)
{
throw new NotImplementedException();
}
public Windows10PwmDriver() => throw new PlatformNotSupportedException($"The {GetType().Name} class is not available on Linux.");
protected internal override void CloseChannel(int pwmChip, int pwmChannel)
{
throw new NotImplementedException();
}
protected internal override void OpenChannel(int pwmChip, int pwmChannel) => throw new PlatformNotSupportedException();
protected internal override void OpenChannel(int pwmChip, int pwmChannel)
{
throw new NotImplementedException();
}
protected internal override void CloseChannel(int pwmChip, int pwmChannel) => throw new PlatformNotSupportedException();
protected internal override void StartWriting(int pwmChip, int pwmChannel, double frequencyInHertz, double dutyCycleInNanoSeconds)
{
throw new NotImplementedException();
}
protected internal override void ChangeDutyCycle(int pwmChip, int pwmChannel, double dutyCycleInNanoSeconds) => throw new PlatformNotSupportedException();
protected internal override void StopWriting(int pwmChip, int pwmChannel)
{
throw new NotImplementedException();
}
protected internal override void StartWriting(int pwmChip, int pwmChannel, double frequencyInHertz, double dutyCycleInNanoSeconds) => throw new PlatformNotSupportedException();
protected internal override void StopWriting(int pwmChip, int pwmChannel) => throw new PlatformNotSupportedException();
}
}
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
using System.Collections.Generic;
namespace System.Device.Pwm.Drivers
{
internal class Windows10PwmDriver : PwmDriver
{
private readonly Dictionary<int, Windows10PwmDriverChip> _chipMap = new Dictionary<int, Windows10PwmDriverChip>();
protected internal override void OpenChannel(int chipIndex, int channelIndex)
{
if (!_chipMap.TryGetValue(chipIndex, out Windows10PwmDriverChip chip))
{
chip = new Windows10PwmDriverChip(chipIndex);
_chipMap[chipIndex] = chip;
}
chip.OpenChannel(channelIndex);
}
protected internal override void CloseChannel(int chipIndex, int channelIndex)
{
// This assumes that PwmController has ensured that the chip is already open
Windows10PwmDriverChip chip = _chipMap[chipIndex];
if (chip.CloseChannel(channelIndex))
{
_chipMap.Remove(channelIndex);
}
}
protected internal override void ChangeDutyCycle(int chipIndex, int channelIndex, double dutyCyclePercentage)
{
this.LookupOpenChip(chipIndex).ChangeDutyCycle(channelIndex, dutyCyclePercentage);
}
protected internal override void StartWriting(int chipIndex, int channelIndex, double frequencyInHertz, double dutyCyclePercentage)
{
this.LookupOpenChip(chipIndex).Start(channelIndex, frequencyInHertz, dutyCyclePercentage);
}
protected internal override void StopWriting(int chipIndex, int channelIndex)
{
this.LookupOpenChip(chipIndex).Stop(channelIndex);
}
protected override void Dispose(bool disposing)
{
foreach (Windows10PwmDriverChip chip in _chipMap.Values)
{
chip.Dispose();
}
_chipMap.Clear();
base.Dispose(disposing);
}
private Windows10PwmDriverChip LookupOpenChip(int chipIndex)
{
// This assumes that PwmController has ensured that the chip is already open
return _chipMap[chipIndex];
}
}
}
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
using WinPwm = Windows.Devices.Pwm;
namespace System.Device.Pwm.Drivers
{
internal class Windows10PwmDriverChannel : IDisposable
{
private WinPwm.PwmPin _winPin;
public Windows10PwmDriverChannel(WinPwm.PwmController winController, int channelIndex)
{
_winPin = winController.OpenPin(channelIndex);
if (_winPin == null)
{
throw new ArgumentOutOfRangeException($"The PWM chip is unable to open a channel at index {channelIndex}.", nameof(channelIndex));
}
}
public void ChangeDutyCycle(double dutyCyclePercentage)
{
_winPin?.SetActiveDutyCyclePercentage(dutyCyclePercentage / 100.0);
}
public void Start(double dutyCyclePercentage)
{
this.ChangeDutyCycle(dutyCyclePercentage);
_winPin?.Start();
}
public void Stop()
{
_winPin?.Stop();
}
public void Dispose()
{
this.Stop();
_winPin?.Dispose();
_winPin = null;
}
}
}
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
using System.Collections.Generic;
using Windows.Devices.Enumeration;
using WinPwm = Windows.Devices.Pwm;
namespace System.Device.Pwm.Drivers
{
public class Windows10PwmDriverChip : IDisposable
{
private WinPwm.PwmController _winController;
private readonly Dictionary<int, Windows10PwmDriverChannel> _channelMap = new Dictionary<int, Windows10PwmDriverChannel>();
public Windows10PwmDriverChip(int chipIndex)
{
// Open the Windows PWM controller for the specified PWM chip
string controllerFriendlyName = $"PWM{chipIndex}";
string deviceSelector = WinPwm.PwmController.GetDeviceSelector(controllerFriendlyName);
DeviceInformationCollection deviceInformationCollection = DeviceInformation.FindAllAsync(deviceSelector).WaitForCompletion();
if (deviceInformationCollection.Count == 0)
{
throw new ArgumentException($"No PWM device exists for PWM chip at index {chipIndex}", $"{nameof(chipIndex)}");
}
string deviceId = deviceInformationCollection[0].Id;
_winController = WinPwm.PwmController.FromIdAsync(deviceId).WaitForCompletion();
}
public void OpenChannel(int channelIndex)
{
if (!_channelMap.TryGetValue(channelIndex, out Windows10PwmDriverChannel channel))
{
channel = new Windows10PwmDriverChannel(_winController, channelIndex);
_channelMap.Add(channelIndex, channel);
}
}
/// <summary>
/// Closes the channel.
/// </summary>
/// <param name="channelIndex">The PWM channel to close.</param>
/// <returns><see langword="true" /> if the chip has no more open channels open upon exiting; <see langword="false" /> otherwise.</returns>
public bool CloseChannel(int channelIndex)
{
// This assumes that PwmController has ensured that the channel is already open
Windows10PwmDriverChannel channel = _channelMap[channelIndex];
channel.Dispose();
_channelMap.Remove(channelIndex);
return _channelMap.Count == 0;
}
public void ChangeDutyCycle(int channelIndex, double dutyCyclePercentage)
{
// This assumes that PwmController has ensured that the channel is already open
Windows10PwmDriverChannel channel = _channelMap[channelIndex];
channel.ChangeDutyCycle(dutyCyclePercentage);
}
public void Start(int channelIndex, double frequencyInHertz, double dutyCyclePercentage)
{
// This assumes that PwmController has ensured that the channel is already open
Windows10PwmDriverChannel channel = _channelMap[channelIndex];
_winController.SetDesiredFrequency(frequencyInHertz);
channel.Start(dutyCyclePercentage);
}
public void Stop(int channelIndex)
{
// This assumes that PwmController has ensured that the channel is already open
Windows10PwmDriverChannel channel = _channelMap[channelIndex];
channel.Stop();
}
public void Dispose()
{
_winController = null;
foreach (Windows10PwmDriverChannel channel in _channelMap.Values)
{
channel.Dispose();
}
_channelMap.Clear();
}
}
}
......@@ -13,7 +13,7 @@ namespace System.Device.Pwm
/// <summary>
/// This collection will hold all of the channels that are currently opened by this controller.
/// </summary>
private HashSet<(int, int)> _openChannels;
private readonly HashSet<(int, int)> _openChannels;
public PwmController(PwmDriver driver)
{
......@@ -41,8 +41,16 @@ namespace System.Device.Pwm
_driver.CloseChannel(pwmChip, pwmChannel);
_openChannels.Remove((pwmChip, pwmChannel));
}
}
/// <summary>
/// Changes the duty cycle.
/// </summary>
/// <param name="pwmChip">The PWM chip.</param>
/// <param name="pwmChannel">The PWM channel.</param>
/// <param name="dutyCyclePercentage">The duty cycle percentage, from 0.0 to 100.</param>
/// <exception cref="InvalidOperationException">Can not change dutycycle to a pwm channel that is not yet opened.</exception>
/// <exception cref="ArgumentException">Duty cycle must be a percentage in the range of 0.0 - 100.0 - dutyCyclePercentage</exception>
public void ChangeDutyCycle(int pwmChip, int pwmChannel, double dutyCyclePercentage)
{
if (!_openChannels.Contains((pwmChip, pwmChannel)))
......@@ -54,8 +62,18 @@ namespace System.Device.Pwm
throw new ArgumentException("Duty cycle must be a percentage in the range of 0.0 - 100.0", nameof(dutyCyclePercentage));
}
_driver.ChangeDutyCycle(pwmChip, pwmChannel, dutyCyclePercentage);
}
}
/// <summary>
/// Starts the writing.
/// </summary>
/// <param name="pwmChip">The PWM chip.</param>
/// <param name="pwmChannel">The PWM channel.</param>
/// <param name="frequencyInHertz">The frequency in hertz.</param>
/// <param name="dutyCyclePercentage">The duty cycle percentage.</param>
/// <exception cref="InvalidOperationException">Can not start writing to a pwm channel that is not yet opened.</exception>
/// <exception cref="ArgumentException">Duty cycle must be a percentage in the range of 0.0 - 100.0 - dutyCyclePercentage</exception>
/// TODO Edit XML Comment Template for StartWriting
public void StartWriting(int pwmChip, int pwmChannel, double frequencyInHertz, double dutyCyclePercentage)
{
if (!_openChannels.Contains((pwmChip, pwmChannel)))
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册