Last active
June 6, 2019 04:11
-
-
Save kurtnelle/7368de27537d07296af7fab8854d83a8 to your computer and use it in GitHub Desktop.
PocketBeagle PWM Controller
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
using System; | |
using System.Collections.Generic; | |
using System.IO; | |
public class PocketBeaglePWMController : BBBandVariantsPWMController | |
{ | |
public PWMChannel ChipZeroChannelZero | |
{ | |
get | |
{ | |
return this["pwmchip0"][0]; | |
} | |
} | |
public PWMChannel ChipZeroChannelOne | |
{ | |
get | |
{ | |
return this["pwmchip0"][1]; | |
} | |
} | |
public PWMChannel ChipTwoChannelZero | |
{ | |
get | |
{ | |
return this["pwmchip2"][0]; | |
} | |
} | |
public PWMChannel ChipTwoChannelOne | |
{ | |
get | |
{ | |
return this["pwmchip2"][1]; | |
} | |
} | |
public PWMChannel ChipFourChannelZero | |
{ | |
get | |
{ | |
return this["pwmchip4"][0]; | |
} | |
} | |
public PWMChannel ChipFourChannelOne | |
{ | |
get | |
{ | |
return this["pwmchip4"][1]; | |
} | |
} | |
} | |
public class BBBandVariantsPWMController : Dictionary<string, PWMChip> | |
{ | |
const string PWM_ROOT = "/sys/class/pwm"; | |
public BBBandVariantsPWMController() | |
{ | |
var _chips = new List<PWMChip>(); | |
foreach (var dir in Directory.GetDirectories(PWM_ROOT, "pwmchip*")) | |
{ | |
var _chip = new PWMChip(dir); | |
Add(_chip.ChipName, _chip); | |
} | |
} | |
} | |
public class PWMChip : List<PWMChannel> | |
{ | |
public int ChipNumber | |
{ | |
get; | |
private set; | |
} | |
public string ChipPath | |
{ | |
get; | |
private set; | |
} | |
public string ChipName | |
{ | |
get; | |
private set; | |
} | |
public PWMChip(string chipPath) | |
{ | |
ChipPath = chipPath; | |
ChipNumber = int.Parse(chipPath.Substring(chipPath.Length - 1, 1)); | |
ChipName = chipPath.Substring(chipPath.LastIndexOf("/") + 1); | |
var _channelCount = int.Parse(File.ReadAllText($"{chipPath}/npwm")); | |
for(var i = 0; i < _channelCount; i++) | |
{ | |
Add(new PWMChannel($"{chipPath}/pwm-{ChipNumber}:{i}")); | |
} | |
} | |
} | |
public class PWMChannel | |
{ | |
const string ONE_VALUE = "1"; | |
const string ZERO_VALUE = "0"; | |
const string NORMAL_VALUE = "normal"; | |
const string INVERSED_VALUE = "inversed"; | |
string enablePath = "{0}/enable"; | |
string periodPath = "{0}/period"; | |
string dutyCyclePath = "{0}/duty_cycle"; | |
string polarityPath = "{0}/polarity"; | |
public string ChannelPath | |
{ | |
get; | |
private set; | |
} | |
public PWMChannel Enable() | |
{ | |
IsEnabled = true; | |
return this; | |
} | |
public PWMChannel Disable() | |
{ | |
IsEnabled = false; | |
return this; | |
} | |
public bool IsEnabled | |
{ | |
get | |
{ | |
return File.ReadAllText(enablePath) == ONE_VALUE; | |
} | |
set | |
{ | |
File.WriteAllText(enablePath, value ? ONE_VALUE : ZERO_VALUE); | |
} | |
} | |
/// <summary> | |
/// The active time of the PWM signal (read/write). Value is in nanoseconds and must be less than the period. | |
/// </summary> | |
public UInt64 DutyCycle | |
{ | |
get | |
{ | |
return UInt64.Parse(File.ReadAllText(dutyCyclePath)); | |
} | |
set | |
{ | |
File.WriteAllText(dutyCyclePath, value.ToString()); | |
} | |
} | |
/// <summary> | |
/// The active time of the PWM signal as a ratio of the period value must be greater than 0 and less than 1 | |
/// </summary> | |
/// <param name="dutyCycle"></param> | |
/// <returns></returns> | |
public PWMChannel SetDutyCycle(double dutyCycle) | |
{ | |
if(dutyCycle >= 1 || dutyCycle <=0) | |
{ | |
throw new ArgumentException("This method only accepts values that represent a ratio of the period e.g. 0.5 = 50%"); | |
} | |
var period = Period; | |
if (period == 0) | |
{ | |
throw new ArgumentException("The period must not be 0 for the duty cycle to be set"); | |
} | |
else | |
{ | |
DutyCycle = (UInt64)(period * dutyCycle); | |
} | |
return this; | |
} | |
/// <summary> | |
/// The total period of the PWM signal (read/write). Value is in nanoseconds and is the sum of the active and inactive time of the PWM. | |
/// </summary> | |
public UInt64 Period | |
{ | |
get | |
{ | |
return UInt64.Parse(File.ReadAllText(periodPath)); | |
} | |
set | |
{ | |
if (DutyCycle != 0) | |
{ | |
if ((value / DutyCycle) <= 0) | |
{ | |
DutyCycle = 0; | |
} | |
} | |
File.WriteAllText(periodPath, value.ToString()); | |
} | |
} | |
/// <summary> | |
/// The total period of the PWM signal (read/write). Value is in nanoseconds and is the sum of the active and inactive time of the PWM. | |
/// </summary> | |
/// <param name="period">number of nano seconds per cycle</param> | |
/// <returns></returns> | |
public PWMChannel SetPeriod(UInt64 period) | |
{ | |
try | |
{ | |
Period = period; | |
} | |
catch (IOException ioEx) | |
{ | |
throw new ArgumentException($"Invalid value when setting period \"{period}\"", ioEx); | |
} | |
return this; | |
} | |
public bool Polarity | |
{ | |
get | |
{ | |
return File.ReadAllText(polarityPath) == NORMAL_VALUE; | |
} | |
set | |
{ | |
IsEnabled = false; | |
File.WriteAllText(polarityPath, value ? NORMAL_VALUE : INVERSED_VALUE); | |
} | |
} | |
public PWMChannel SetPolarity(bool normal) | |
{ | |
Polarity = normal; | |
return this; | |
} | |
public PWMChannel(string channelPath) | |
{ | |
enablePath = string.Format(enablePath, channelPath); | |
dutyCyclePath = string.Format(dutyCyclePath, channelPath); | |
periodPath = string.Format(periodPath, channelPath); | |
polarityPath = string.Format(polarityPath, channelPath); | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Test by connecting Scope to Pin labeled PWM1A on silk screen.