Skip to content

Commit

Permalink
pwm: fix naming of channel->chip, pin->channel
Browse files Browse the repository at this point in the history
resolves #24, resolves #26
  • Loading branch information
vsergeev committed Oct 24, 2019
1 parent a096870 commit ae79407
Show file tree
Hide file tree
Showing 4 changed files with 65 additions and 65 deletions.
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -73,7 +73,7 @@ led1.close()
``` python
from periphery import PWM

# Open PWM channel 0, pin 10
# Open PWM chip 0, channel 10
pwm = PWM(0, 10)

# Set frequency to 1 kHz
Expand Down
2 changes: 1 addition & 1 deletion docs/pwm.rst
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ Code Example
from periphery import PWM
# Open PWM channel 0, pin 10
# Open PWM chip 0, channel 10
pwm = PWM(0, 10)
# Set frequency to 1 kHz
Expand Down
100 changes: 50 additions & 50 deletions periphery/pwm.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,40 +15,40 @@ class PWM(object):

# Sysfs paths
_sysfs_path = "/sys/class/pwm/"
_channel_path = "pwmchip{}"
_chip_path = "pwmchip{}"

# Channel paths
_export_path = "export"
_pin_path = "pwm{}"
_channel_path = "pwm{}"

# Pin attribute paths
_pin_period_path = "period"
_pin_duty_cycle_path = "duty_cycle"
_pin_polarity_path = "polarity"
_pin_enable_path = "enable"
# Channel attribute paths
_channel_period_path = "period"
_channel_duty_cycle_path = "duty_cycle"
_channel_polarity_path = "polarity"
_channel_enable_path = "enable"

def __init__(self, channel, pin):
def __init__(self, chip, channel):
"""Instantiate a PWM object and open the sysfs PWM corresponding to the
specified channel and pin.
specified chip and channel.
Args:
channel (int): Linux channel number.
pin (int): Linux pin number.
chip (int): PWM chip number.
channel (int): PWM channel number.
Returns:
PWM: PWM object.
Raises:
PWMError: if an I/O or OS error occurs.
TypeError: if `channel` or `pin` types are invalid.
ValueError: if PWM channel does not exist.
TypeError: if `chip` or `channel` types are invalid.
LookupError: if PWM chip does not exist.
TimeoutError: if waiting for PWM export times out.
"""

self._chip = None
self._channel = None
self._pin = None
self._open(channel, pin)
self._open(chip, channel)

def __del__(self):
self.close()
Expand All @@ -59,64 +59,64 @@ def __enter__(self):
def __exit__(self, t, value, traceback):
self.close()

def _open(self, channel, pin):
def _open(self, chip, channel):
if not isinstance(chip, int):
raise TypeError("Invalid chip type, should be integer.")
if not isinstance(channel, int):
raise TypeError("Invalid channel type, should be integer.")
if not isinstance(pin, int):
raise TypeError("Invalid pin type, should be integer.")

channel_path = os.path.join(self._sysfs_path, self._channel_path.format(channel))
if not os.path.isdir(channel_path):
raise ValueError("PWM channel does not exist, check that the required modules are loaded.")
chip_path = os.path.join(self._sysfs_path, self._chip_path.format(chip))
if not os.path.isdir(chip_path):
raise LookupError("PWM chip does not exist, check that the required modules are loaded.")

pin_path = os.path.join(channel_path, self._pin_path.format(pin))
channel_path = os.path.join(chip_path, self._channel_path.format(channel))

if not os.path.isdir(pin_path):
if not os.path.isdir(channel_path):
# Export the PWM
try:
with open(os.path.join(channel_path, self._export_path), "w") as f_export:
f_export.write("%d\n" % pin)
with open(os.path.join(chip_path, self._export_path), "w") as f_export:
f_export.write("%d\n" % channel)
except IOError as e:
raise PWMError(e.errno, "Exporting PWM pin: " + e.strerror)
raise PWMError(e.errno, "Exporting PWM channel: " + e.strerror)

# Loop until PWM is exported
exported = False
for i in range(PWM.PWM_STAT_RETRIES):
if os.path.isdir(pin_path):
if os.path.isdir(channel_path):
exported = True
break

time.sleep(PWM.PWM_STAT_DELAY)

if not exported:
raise TimeoutError("Exporting PWM: waiting for '%s' timed out" % pin_path)
raise TimeoutError("Exporting PWM: waiting for '%s' timed out" % channel_path)

self._chip = chip
self._channel = channel
self._pin = pin

# Look up the period, for fast duty cycle updates
self._period = self._get_period()

def close(self):
"""Close the sysfs PWM."""
self._chip = None
self._channel = None
self._pin = None

def _write_pin_attr(self, attr, value):
def _write_channel_attr(self, attr, value):
path = os.path.join(
self._sysfs_path,
self._chip_path.format(self._chip),
self._channel_path.format(self._channel),
self._pin_path.format(self._pin),
attr)

with open(path, 'w') as f_attr:
f_attr.write(value + "\n")

def _read_pin_attr(self, attr):
def _read_channel_attr(self, attr):
path = os.path.join(
self._sysfs_path,
self._chip_path.format(self._chip),
self._channel_path.format(self._channel),
self._pin_path.format(self._pin),
attr)

with open(path, 'r') as f_attr:
Expand All @@ -135,26 +135,26 @@ def disable(self):
# Immutable properties

@property
def channel(self):
"""Get the sysfs PWM channel number.
def chip(self):
"""Get the sysfs PWM chip number.
:type: int
"""
return self._channel
return self._chip

@property
def pin(self):
"""Get the sysfs PWM pin number.
def channel(self):
"""Get the sysfs PWM channel number.
:type: int
"""
return self._pin
return self._channel

# Mutable properties

def _get_period(self):
try:
period_ns = int(self._read_pin_attr(self._pin_period_path))
period_ns = int(self._read_channel_attr(self._channel_period_path))
except ValueError:
raise PWMError(None, "Unknown period value: \"%s\"" % period_ns)

Expand All @@ -173,7 +173,7 @@ def _set_period(self, period):
# Convert period from seconds to integer nanoseconds
period_ns = int(period * 1e9)

self._write_pin_attr(self._pin_period_path, "{}".format(period_ns))
self._write_channel_attr(self._channel_period_path, "{}".format(period_ns))

# Update our cached period
self._period = float(period)
Expand All @@ -190,7 +190,7 @@ def _set_period(self, period):

def _get_duty_cycle(self):
try:
duty_cycle_ns = int(self._read_pin_attr(self._pin_duty_cycle_path))
duty_cycle_ns = int(self._read_channel_attr(self._channel_duty_cycle_path))
except ValueError:
raise PWMError(None, "Unknown duty cycle value: \"%s\"" % duty_cycle_ns)

Expand All @@ -214,7 +214,7 @@ def _set_duty_cycle(self, duty_cycle):
# Convert duty cycle from seconds to integer nanoseconds
duty_cycle_ns = int(duty_cycle * 1e9)

self._write_pin_attr(self._pin_duty_cycle_path, "{}".format(duty_cycle_ns))
self._write_channel_attr(self._channel_duty_cycle_path, "{}".format(duty_cycle_ns))

duty_cycle = property(_get_duty_cycle, _set_duty_cycle)
"""Get or set the PWM's output duty cycle as a ratio from 0.0 to 1.0.
Expand Down Expand Up @@ -247,15 +247,15 @@ def _set_frequency(self, frequency):
"""

def _get_polarity(self):
return self._read_pin_attr(self._pin_polarity_path)
return self._read_channel_attr(self._channel_polarity_path)

def _set_polarity(self, polarity):
if not isinstance(polarity, str):
raise TypeError("Invalid polarity type, should be str.")
elif polarity.lower() not in ["normal", "inversed"]:
raise ValueError("Invalid polarity, can be: \"normal\" or \"inversed\".")

self._write_pin_attr(self._pin_polarity_path, polarity.lower())
self._write_channel_attr(self._channel_polarity_path, polarity.lower())

polarity = property(_get_polarity, _set_polarity)
"""Get or set the PWM's output polarity. Can be "normal" or "inversed".
Expand All @@ -269,7 +269,7 @@ def _set_polarity(self, polarity):
"""

def _get_enabled(self):
enabled = self._read_pin_attr(self._pin_enable_path)
enabled = self._read_channel_attr(self._channel_enable_path)

if enabled == "1":
return True
Expand All @@ -282,7 +282,7 @@ def _set_enabled(self, value):
if not isinstance(value, bool):
raise TypeError("Invalid enabled type, should be string.")

self._write_pin_attr(self._pin_enable_path, "1" if value else "0")
self._write_channel_attr(self._channel_enable_path, "1" if value else "0")

enabled = property(_get_enabled, _set_enabled)
"""Get or set the PWM's output enabled state.
Expand All @@ -297,6 +297,6 @@ def _set_enabled(self, value):
# String representation

def __str__(self):
return "PWM%d, pin %d (period=%f sec, duty_cycle=%f%%, polarity=%s, enabled=%s)" % \
(self._channel, self._pin, self.period, self.duty_cycle * 100,
return "PWM %d, chip %d (period=%f sec, duty_cycle=%f%%, polarity=%s, enabled=%s)" % \
(self._channel, self._chip, self.period, self.duty_cycle * 100,
self.polarity, str(self.enabled))
26 changes: 13 additions & 13 deletions tests/test_pwm.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,8 @@
if sys.version_info[0] == 3:
raw_input = input

pwm_chip = None
pwm_channel = None
pwm_pin = None


def test_arguments():
Expand All @@ -25,18 +25,18 @@ def test_arguments():
def test_open_close():
print("Starting open/close test...")

# Open non-existent PWM channel
with AssertRaises(ValueError):
periphery.PWM(9999, pwm_pin)
# Open non-existent PWM chip
with AssertRaises(LookupError):
periphery.PWM(9999, pwm_channel)

# Open non-existent PWM pin
# Open non-existent PWM channel
with AssertRaises(periphery.PWMError):
periphery.PWM(pwm_channel, 9999)
periphery.PWM(pwm_chip, 9999)

# Open legitimate PWM channel/pin
pwm = periphery.PWM(pwm_channel, pwm_pin)
# Open legitimate PWM chip/channel
pwm = periphery.PWM(pwm_chip, pwm_channel)
assert pwm.chip == pwm_chip
assert pwm.channel == pwm_channel
assert pwm.pin == pwm_pin

# Set period, check period and frequency
pwm.period = 1e-3
Expand Down Expand Up @@ -87,7 +87,7 @@ def test_open_close():
def test_interactive():
print("Starting interactive test...")

pwm = periphery.PWM(pwm_channel, pwm_pin)
pwm = periphery.PWM(pwm_chip, pwm_channel)

print("Starting interactive test. Get out your oscilloscope, buddy!")
raw_input("Press enter to continue...")
Expand Down Expand Up @@ -132,7 +132,7 @@ def test_interactive():
sys.exit(0)

if len(sys.argv) < 3:
print("Usage: python -m tests.test_pwm <PWM channel> <PWM pin number>")
print("Usage: python -m tests.test_pwm <PWM chip> <PWM channel>")
print("")
print("[1/4] Arguments test: No requirements.")
print("[2/4] Open/close test: PWM device should be real.")
Expand All @@ -150,8 +150,8 @@ def test_interactive():

sys.exit(1)

pwm_channel = int(sys.argv[1])
pwm_pin = int(sys.argv[2])
pwm_chip = int(sys.argv[1])
pwm_channel = int(sys.argv[2])

print("Starting PMW tests...")

Expand Down

0 comments on commit ae79407

Please sign in to comment.