diff --git a/doc/configuration.rst b/doc/configuration.rst index d93e58c90..7f0535ce6 100644 --- a/doc/configuration.rst +++ b/doc/configuration.rst @@ -610,9 +610,11 @@ A :any:`SysfsGPIO` resource describes a GPIO line. SysfsGPIO: index: 12 + invert: False Arguments: - index (int): index of the GPIO line + - invert (bool, default=False): optional, whether the logic level is inverted(active-low) Used by: - `GpioDigitalOutputDriver`_ @@ -636,6 +638,7 @@ USB based gpiochips. '@SUBSYSTEM': 'usb' '@ID_SERIAL_SHORT': 'D38EJ8LF' pin: 0 + invert: False The example would search for a USB gpiochip with the key `ID_SERIAL_SHORT` and the value `D38EJ8LF` and use the pin 0 of this device. @@ -644,6 +647,7 @@ The `ID_SERIAL_SHORT` property is set by the usb_id builtin helper program. Arguments: - match (dict): key and value pairs for a udev match, see `udev Matching`_ - pin (int): gpio pin number within the matched gpiochip. + - invert (bool, default=False): optional, whether the logic level is inverted (active-low) Used by: - `GpioDigitalOutputDriver`_ diff --git a/examples/sysfsgpio/export-gpio.yaml b/examples/sysfsgpio/export-gpio.yaml index 489befd16..808a82c2a 100644 --- a/examples/sysfsgpio/export-gpio.yaml +++ b/examples/sysfsgpio/export-gpio.yaml @@ -1,3 +1,4 @@ desk: - GpioDigitalOutputDriver: + SysfsGPIO: index: 60 + invert: False diff --git a/examples/sysfsgpio/import-gpio.yaml b/examples/sysfsgpio/import-gpio.yaml index 4ba7b223f..40954a448 100644 --- a/examples/sysfsgpio/import-gpio.yaml +++ b/examples/sysfsgpio/import-gpio.yaml @@ -5,5 +5,3 @@ targets: name: gpio drivers: GpioDigitalOutputDriver: {} -options: - coordinator_address: 'labgrid:20408' diff --git a/examples/sysfsgpio/sysfsgpio.py b/examples/sysfsgpio/sysfsgpio.py index 98acf0ac1..3a09ad90c 100644 --- a/examples/sysfsgpio/sysfsgpio.py +++ b/examples/sysfsgpio/sysfsgpio.py @@ -13,11 +13,12 @@ StepLogger.start() t = Target("main") -r = SysfsGPIO(t, name=None, index=60) +r = SysfsGPIO(t, name=None, index=60, invert=True) d = GpioDigitalOutputDriver(t, name=None) p = t.get_driver("DigitalOutputProtocol") print(t.resources) +print("Testing IO") p.set(True) print(p.get()) time.sleep(2) diff --git a/examples/sysfsgpio/sysfsgpio_remote.py b/examples/sysfsgpio/sysfsgpio_remote.py index 4b16b8466..37976b673 100644 --- a/examples/sysfsgpio/sysfsgpio_remote.py +++ b/examples/sysfsgpio/sysfsgpio_remote.py @@ -15,6 +15,7 @@ p = t.get_driver("DigitalOutputProtocol") print(t.resources) +print("Testing IO") p.set(True) print(p.get()) time.sleep(2) diff --git a/labgrid/driver/gpiodriver.py b/labgrid/driver/gpiodriver.py index 1d987761a..0fc046092 100644 --- a/labgrid/driver/gpiodriver.py +++ b/labgrid/driver/gpiodriver.py @@ -37,9 +37,9 @@ def on_deactivate(self): @Driver.check_active @step(args=['status']) def set(self, status): - self.proxy.set(self.gpio.index, status) + self.proxy.set(self.gpio.index, self.gpio.invert, status) @Driver.check_active @step(result=True) def get(self): - return self.proxy.get(self.gpio.index) + return self.proxy.get(self.gpio.index, self.gpio.invert) diff --git a/labgrid/remote/exporter.py b/labgrid/remote/exporter.py index d3b406503..136381db5 100755 --- a/labgrid/remote/exporter.py +++ b/labgrid/remote/exporter.py @@ -642,16 +642,19 @@ def _get_params(self): return { "host": self.host, "index": self.local.index, + "invert": self.local.invert, } def _get_start_params(self): return { "index": self.local.index, + "invert": self.local.invert, } def _start(self, start_params): """Start a GPIO export to userspace""" index = start_params["index"] + invert = start_params["invert"] # pylint: disable=unused-variable if self.export_path.exists(): self.system_exported = True diff --git a/labgrid/resource/base.py b/labgrid/resource/base.py index d8cdb984c..0df31a8f1 100644 --- a/labgrid/resource/base.py +++ b/labgrid/resource/base.py @@ -42,5 +42,7 @@ class SysfsGPIO(Resource): """The basic SysfsGPIO contains an index Args: - index (int): index of target gpio line.""" + index (int): index of target gpio line. + invert (bool) : optional, whether the logic level is inverted (active-low)""" index = attr.ib(default=None, validator=attr.validators.instance_of(int)) + invert = attr.ib(default=False, validator=attr.validators.instance_of(bool)) diff --git a/labgrid/resource/remote.py b/labgrid/resource/remote.py index a29e58ee8..6ab0f51d4 100644 --- a/labgrid/resource/remote.py +++ b/labgrid/resource/remote.py @@ -340,6 +340,7 @@ class NetworkSysfsGPIO(NetworkResource, ManagedResource): """The NetworkSysfsGPIO describes a remotely accessible gpio line""" index = attr.ib(validator=attr.validators.optional(attr.validators.instance_of(int))) + invert = attr.ib(default=False, validator=attr.validators.instance_of(bool)) def __attrs_post_init__(self): self.timeout = 10.0 super().__attrs_post_init__() diff --git a/labgrid/resource/udev.py b/labgrid/resource/udev.py index 3dcd2ae72..2879b0dbb 100644 --- a/labgrid/resource/udev.py +++ b/labgrid/resource/udev.py @@ -778,8 +778,10 @@ class MatchedSysfsGPIO(USBResource): """The MatchedSysfsGPIO described a SysfsGPIO matched by Udev Args: - pin (int): gpio pin number within the matched gpiochip.""" + pin (int): gpio pin number within the matched gpiochip. + invert (bool): optional, whether the logic level is inverted (active-low)""" pin = attr.ib(default=None, validator=attr.validators.instance_of(int)) + invert = attr.ib(default=False, validator=attr.validators.instance_of(bool)) index = None def __attrs_post_init__(self): diff --git a/labgrid/util/agents/sysfsgpio.py b/labgrid/util/agents/sysfsgpio.py index e62736750..580b77f0e 100644 --- a/labgrid/util/agents/sysfsgpio.py +++ b/labgrid/util/agents/sysfsgpio.py @@ -2,6 +2,7 @@ This module implements switching GPIOs via sysfs GPIO kernel interface. Takes an integer property 'index' which refers to the already exported GPIO device. +Takes a boolean property 'invert' which inverts logical values if set to True (active-low) """ import logging @@ -23,7 +24,7 @@ def _assert_gpio_line_is_exported(index): if not os.path.exists(gpio_sysfs_path): raise ValueError("Device not found") - def __init__(self, index): + def __init__(self, index, invert): self.gpio_sysfs_value_fd = None self._logger = logging.getLogger("Device: ") GpioDigitalOutput._assert_gpio_line_is_exported(index) @@ -41,6 +42,10 @@ def __init__(self, index): gpio_sysfs_value_path = os.path.join(gpio_sysfs_path, 'value') self.gpio_sysfs_value_fd = os.open(gpio_sysfs_value_path, flags=(os.O_RDWR | os.O_SYNC)) + gpio_sysfs_active_low_path = os.path.join(gpio_sysfs_path, 'active_low') + with open(gpio_sysfs_active_low_path, 'w') as active_low_fd: + active_low_fd.write(str(int(invert))) + def __del__(self): if self.gpio_sysfs_value_fd: os.close(self.gpio_sysfs_value_fd) @@ -68,24 +73,22 @@ def set(self, status): os.write(self.gpio_sysfs_value_fd, binary_value) - _gpios = {} -def _get_gpio_line(index): +def _get_gpio_line(index, invert): if index not in _gpios: - _gpios[index] = GpioDigitalOutput(index=index) + _gpios[index] = GpioDigitalOutput(index=index, invert=invert) return _gpios[index] -def handle_set(index, status): - gpio_line = _get_gpio_line(index) +def handle_set(index, invert, status): + gpio_line = _get_gpio_line(index, invert) gpio_line.set(status) -def handle_get(index): - gpio_line = _get_gpio_line(index) +def handle_get(index, invert): + gpio_line = _get_gpio_line(index, invert) return gpio_line.get() - methods = { 'set': handle_set, 'get': handle_get, diff --git a/tests/test_sysfsgpioagent.py b/tests/test_sysfsgpioagent.py index bd212ef2b..1f70bc198 100644 --- a/tests/test_sysfsgpioagent.py +++ b/tests/test_sysfsgpioagent.py @@ -36,11 +36,11 @@ def set(self, val): super().set(val) def test_instantiation(self): - gpio_line = TestGpioAgent.GpioDigitalOutputMock(index=13) + gpio_line = TestGpioAgent.GpioDigitalOutputMock(index=13, invert=False) assert isinstance(gpio_line, GpioDigitalOutput) def test_set(self): - gpio_line = TestGpioAgent.GpioDigitalOutputMock(index=13) + gpio_line = TestGpioAgent.GpioDigitalOutputMock(index=13, invert=False) for val in [True, False, True, False]: gpio_line.set(val) assert gpio_line.get() == val