Skip to content
78 changes: 76 additions & 2 deletions doc/configuration.rst
Original file line number Diff line number Diff line change
Expand Up @@ -556,9 +556,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`_
Expand All @@ -577,6 +579,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.
Expand All @@ -585,6 +588,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`_
Expand Down Expand Up @@ -2213,6 +2217,72 @@ Implements:
Arguments:
- delay (float, default=2.0): delay in seconds between off and on

ManualButtonDriver
~~~~~~~~~~~~~~~~~~
A :any:`ManualButtonDriver` requires the user to control the taget button.
This is required if a strategy is used with the target, but no automatic
button control is available.

The driver's name will be displayed during interaction.

Binds to:
- None

Implements:
- :any:`ButtonProtocol`

.. code-block:: yaml

ManualButtonDriver:
name: 'example-board'

Arguments:
- None

ExternalButtonDriver
~~~~~~~~~~~~~~~~~~~~
An :any:`ExternalButtonDriver` is used to control a target button via an
external command.

Binds to:
- None

Implements:
- :any:`ButtonProtocol`

.. code-block:: yaml

ExternalButtonDriver:
cmd_press: 'example_command press and hold'
cmd_release: 'example_command release'
cmd_press_for: 'example_command press_for'
delay: 2.0

Arguments:
- cmd_press (str): command to press and hold the button on the board
- cmd_release (str): command to release the button on the board
- cmd_press_for (str): command to press, pause, and release the button on the board
- delay (float, default=1.0): delay in seconds when calling press_for

DigitalOutputButtonDriver
~~~~~~~~~~~~~~~~~~~~~~~~~
A :any:`DigitalOutputButtonDriver` is used to control a target button via a
DigitalOutputDriver

Binds to:
- :any:`DigitalOutputProtocol`

Implements:
- :any:`ButtonProtocol`

.. code-block:: yaml

DigitalOutputButtonDriver:
delay: 2.0

Arguments:
- delay (float, default=1.0): delay in seconds when calling press_for

GpioDigitalOutputDriver
~~~~~~~~~~~~~~~~~~~~~~~
The :any:`GpioDigitalOutputDriver` writes a digital signal to a GPIO line.
Expand All @@ -2228,13 +2298,17 @@ Binds to:

Implements:
- :any:`DigitalOutputProtocol`
- :any:`ResetProtocol`
- :any:`PowerProtocol`
- :any:`ButtonProtocol`

.. code-block:: yaml

GpioDigitalOutputDriver: {}
GpioDigitalOutputDriver:
delay: 2.0

Arguments:
- None
- delay (float, default=1.0): delay in seconds between off and on for a power cycle or between states for button press_for

SerialPortDigitalOutputDriver
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Expand Down
3 changes: 2 additions & 1 deletion examples/sysfsgpio/export-gpio.yaml
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
desk:
GpioDigitalOutputDriver:
SysfsGPIO:
index: 60
invert: False
2 changes: 0 additions & 2 deletions examples/sysfsgpio/import-gpio.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -5,5 +5,3 @@ targets:
name: gpio
drivers:
GpioDigitalOutputDriver: {}
options:
coordinator_address: 'labgrid:20408'
34 changes: 33 additions & 1 deletion examples/sysfsgpio/sysfsgpio.py
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand All @@ -26,3 +27,34 @@
time.sleep(2)
p.set(True)
print(p.get())
time.sleep(2)
p.invert()
print(p.get())
time.sleep(2)
p.invert()
print(p.get())
time.sleep(2)

print("Testing Power")
p.off()
print(p.get())
time.sleep(2)
p.on()
print(p.get())
time.sleep(2)
p.cycle()
print(p.get())
time.sleep(2)

print("Testing Button")
p.release()
print(p.get())
time.sleep(2)
p.press()
print(p.get())
time.sleep(2)
p.release()
print(p.get())
time.sleep(2)
p.press_for()
print(p.get())
32 changes: 32 additions & 0 deletions examples/sysfsgpio/sysfsgpio_remote.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@

p = t.get_driver("DigitalOutputProtocol")
print(t.resources)
print("Testing IO")
p.set(True)
print(p.get())
time.sleep(2)
Expand All @@ -23,3 +24,34 @@
time.sleep(2)
p.set(True)
print(p.get())
time.sleep(2)
p.invert()
print(p.get())
time.sleep(2)
p.invert()
print(p.get())
time.sleep(2)

print("Testing Power")
p.off()
print(p.get())
time.sleep(2)
p.on()
print(p.get())
time.sleep(2)
p.cycle()
print(p.get())
time.sleep(2)

print("Testing Button")
p.release()
print(p.get())
time.sleep(2)
p.press()
print(p.get())
time.sleep(2)
p.release()
print(p.get())
time.sleep(2)
p.press_for()
print(p.get())
2 changes: 2 additions & 0 deletions labgrid/driver/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,8 @@
DigitalOutputPowerDriver, YKUSHPowerDriver, \
USBPowerDriver, SiSPMPowerDriver, NetworkPowerDriver, \
PDUDaemonDriver
from .buttondriver import ManualButtonDriver, ExternalButtonDriver, \
DigitalOutputButtonDriver
from .usbloader import MXSUSBDriver, IMXUSBDriver, BDIMXUSBDriver, RKUSBDriver, UUUDriver
from .usbsdmuxdriver import USBSDMuxDriver
from .usbsdwiredriver import USBSDWireDriver
Expand Down
107 changes: 107 additions & 0 deletions labgrid/driver/buttondriver.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,107 @@
import shlex
import time
import math
from importlib import import_module

import attr

from ..factory import target_factory
from ..protocol import ButtonProtocol, DigitalOutputProtocol
from ..step import step
from ..util.proxy import proxymanager
from ..util.helper import processwrapper
from .common import Driver
from .exception import ExecutionError


@target_factory.reg_driver
@attr.s(eq=False)
class ManualButtonDriver(Driver, ButtonProtocol):
"""ManualButtonDriver - Driver to tell the user to control a target's button"""

@Driver.check_active
@step()
def press(self):
self.target.interact(
f"Press and hold the button on target {self.target.name} and press enter"
)

@Driver.check_active
@step()
def release(self):
self.target.interact(
f"Release the button on the target {self.target.name} press enter"
)

@Driver.check_active
@step()
def press_for(self):
self.target.interact(
f"Press and then Release the button on target {self.target.name} for {self.delay} seconds and press enter"
)

@target_factory.reg_driver
@attr.s(eq=False)
class ExternalButtonDriver(Driver, ButtonProtocol):
"""ExternalButtonDriver - Driver using an external command to control a target's button"""
cmd_press = attr.ib(validator=attr.validators.instance_of(str))
cmd_release = attr.ib(validator=attr.validators.instance_of(str))
cmd_press_for = attr.ib(validator=attr.validators.instance_of(str))
delay = attr.ib(default=1.0, validator=attr.validators.instance_of(float))

@Driver.check_active
@step()
def press(self):
cmd = shlex.split(self.cmd_press)
processwrapper.check_output(cmd)

@Driver.check_active
@step()
def release(self):
cmd = shlex.split(self.cmd_release)
processwrapper.check_output(cmd)

@Driver.check_active
@step()
def press_for(self):
if self.cmd_press_for is not None:
cmd = shlex.split(self.cmd_press_for)
processwrapper.check_output(cmd)
else:
self.press()
time.sleep(self.delay)
self.release()

@target_factory.reg_driver
@attr.s(eq=False)
class DigitalOutputButtonDriver(Driver, ButtonProtocol):
"""
DigitalOutputButtonDriver uses a DigitalOutput to control a button
"""
bindings = {"output": DigitalOutputProtocol, }
delay = attr.ib(default=1.0, validator=attr.validators.instance_of(float))

def __attrs_post_init__(self):
super().__attrs_post_init__()

@Driver.check_active
@step()
def press(self):
self.output.set(True)

@Driver.check_active
@step()
def release(self):
self.output.set(False)

@Driver.check_active
@step()
def press_for(self):
self.press()
time.sleep(self.delay)
self.release()

@Driver.check_active
@step()
def get(self):
return self.output.get()
Loading