Skip to content

Commit

Permalink
removing gpiozero from gpio backend.
Browse files Browse the repository at this point in the history
  • Loading branch information
mgineer85 committed Nov 4, 2024
1 parent b30a7d4 commit 93d774d
Showing 1 changed file with 50 additions and 23 deletions.
73 changes: 50 additions & 23 deletions wigglecam/services/backends/io/gpio.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,11 @@
import os
import time
from pathlib import Path
from queue import Empty, Queue
from threading import current_thread

import gpiod
from gpiod.line import Bias, Clock, Direction, Edge
from gpiozero import DigitalOutputDevice
from gpiod.line import Bias, Clock, Direction, Edge, Value

from ....utils.stoppablethread import StoppableThread
from ...config.models import ConfigBackendGpio
Expand All @@ -23,8 +23,9 @@ def __init__(self, config: ConfigBackendGpio):
self._config: ConfigBackendGpio = config

# private props
self._gpio_thread: StoppableThread = None
self._trigger_out: DigitalOutputDevice = None
self._gpio_monitor_thread: StoppableThread = None
self._gpio_triggerout_thread: StoppableThread = None
self._queue_trigger_out: Queue[bool] = None

# init private props
pass
Expand All @@ -37,14 +38,16 @@ def start(self):
self._set_hardware_clock(enable=True)
logger.info("generating clock using hardware pwm overlay")

self._trigger_out = DigitalOutputDevice(pin=self._config.trigger_out_pin_name, initial_value=False, active_high=True)
logger.info(f"forward trigger_out on {self._trigger_out}")
self._queue_trigger_out: Queue[bool] = Queue()
self._gpio_triggerout_thread = StoppableThread(name="_gpio_triggerout_thread", target=self._gpio_triggerout_fun, args=(), daemon=True)
self._gpio_triggerout_thread.start()
logger.info(f"forward trigger_out on {self._config.trigger_out_pin_name}")
else:
logger.info("skipped loading primary clockwork service because disabled in config")
logger.info("skipped enabling trigger_out because disabled in config, trigger out should be enabled on primary node usually only.")

self._gpio_thread = StoppableThread(name="_gpio_thread", target=self._gpio_fun, args=(), daemon=True)
self._gpio_thread.start()
self._gpio_monitor_thread = StoppableThread(name="_gpio_monitor_thread", target=self._gpio_monitor_fun, args=(), daemon=True)
self._gpio_monitor_thread.start()

logger.debug(f"{self.__module__} started")

Expand All @@ -54,12 +57,13 @@ def stop(self):
if self._config.is_primary:
self._set_hardware_clock(enable=False)

if self._trigger_out:
self._trigger_out.close()
if self._gpio_monitor_thread and self._gpio_monitor_thread.is_alive():
self._gpio_monitor_thread.stop()
self._gpio_monitor_thread.join()

if self._gpio_thread and self._gpio_thread.is_alive():
self._gpio_thread.stop()
self._gpio_thread.join()
if self._gpio_triggerout_thread and self._gpio_triggerout_thread.is_alive():
self._gpio_triggerout_thread.stop()
self._gpio_triggerout_thread.join()

def derive_nominal_framerate_from_clock(self) -> int:
"""calc the framerate derived by monitoring the clock signal for 11 ticks (means 10 intervals).
Expand Down Expand Up @@ -90,16 +94,12 @@ def derive_nominal_framerate_from_clock(self) -> int:
return fps

def set_trigger_out(self, on: bool):
if not self._trigger_out:
if not self._queue_trigger_out:
logger.debug("trigger requested to forward on this device but disabled in config!")
return

if on:
self._trigger_out.on()
logger.debug("set trigger_out ON")
else:
self._trigger_out.off()
logger.debug("set trigger_out OFF")
logger.debug(f"set trigger_out={on}")
self._queue_trigger_out.put(on)

def _set_hardware_clock(self, enable: bool = True):
"""
Expand Down Expand Up @@ -137,8 +137,35 @@ def _set_hardware_clock(self, enable: bool = True):

logger.info(f"set hw clock sysfs chip {pwm_dir}, period={PERIOD}, duty_cycle={DUTY_CYCLE}, enable={1 if enable else 0}")

def _gpio_fun(self):
logger.debug("starting _gpio_fun")
def _gpio_triggerout_fun(self):
logger.debug("starting _gpio_triggerout_fun")

with gpiod.Chip(self._config.chip) as chip:
try:
_gpiod_trigger_out = chip.line_offset_from_id(self._config.trigger_out_pin_name)
except OSError as exc:
# An OSError is raised if the name is not found.
raise RuntimeError(f"gpio not found: {exc}") from exc

# setup lines
with gpiod.request_lines(
self._config.chip,
consumer="trigger_out",
config={_gpiod_trigger_out: gpiod.LineSettings(direction=Direction.OUTPUT, output_value=Value.INACTIVE)},
) as request:
while not current_thread().stopped():
# timeout to allow the thread to end after 1s if stopped and no events received (read_edge_events would block infinite otherwise)
try:
value = self._queue_trigger_out.get(block=True, timeout=1.0)
except Empty:
pass
else:
request.set_value(_gpiod_trigger_out, value)

logger.debug("_gpio_triggerout_fun left")

def _gpio_monitor_fun(self):
logger.debug("starting _gpio_monitor_fun")

_gpiod_clock_in = None
_gpiod_trigger_in = None
Expand Down Expand Up @@ -193,4 +220,4 @@ def _event_callback(event: gpiod.EdgeEvent):
# print("no events")
pass

logger.info("_gpio_fun left")
logger.info("_gpio_monitor_fun left")

0 comments on commit 93d774d

Please sign in to comment.