farmbot_os/farmbot_os/platform/target/gpio/circuits_gpio_handler.ex

57 lines
1.7 KiB
Elixir
Raw Normal View History

2019-03-05 12:35:09 -07:00
defmodule FarmbotOS.Platform.Target.PinBindingWorker.CircuitsGPIOHandler do
2018-11-30 13:40:57 -07:00
@moduledoc "Circuits gpio handler for PinBindings"
2019-03-05 12:35:09 -07:00
@behaviour FarmbotCore.AssetWorker.FarmbotCore.Asset.PinBinding
require Logger
use GenServer
2018-11-30 13:40:57 -07:00
alias Circuits.GPIO
@debounce_timeout_ms 1000
def start_link(pin_number, fun) do
GenServer.start_link(__MODULE__, [pin_number, fun], name: name(pin_number))
end
def terminate(reason, state) do
2020-01-17 08:58:53 -07:00
Logger.warn(
"CircuitsGPIOHandler #{state.pin_number} crash: #{inspect(reason)}"
)
end
def init([pin_number, fun]) do
Logger.info("CircuitsGPIOHandler #{pin_number} init")
2018-11-30 13:40:57 -07:00
{:ok, pin} = GPIO.open(pin_number, :input)
:ok = GPIO.set_interrupts(pin, :rising)
2020-04-09 08:21:14 -06:00
# this has been checked on v1.3 and v1.5 hardware
# and it seems to be fine.
:ok = GPIO.set_pull_mode(pin, :pulldown)
{:ok, %{pin_number: pin_number, pin: pin, fun: fun, debounce: nil}}
end
def handle_info(:timeout, state) do
2018-11-30 13:40:57 -07:00
Logger.info("CircuitsGPIOHandler #{state.pin_number} debounce cleared")
{:noreply, %{state | debounce: nil}}
end
2020-01-17 08:58:53 -07:00
def handle_info(
{:circuits_gpio, pin, _timestamp, _},
%{debounce: timer} = state
)
when is_reference(timer) do
left = Process.read_timer(timer)
2018-11-30 13:40:57 -07:00
Logger.info("CircuitsGPIOHandler #{pin} still debounced for #{left} ms")
{:noreply, state}
end
def handle_info({:circuits_gpio, pin, _timestamp, _signal}, state) do
Logger.debug("CircuitsGPIOHandler #{pin} triggered")
state.fun.()
{:noreply, %{state | debounce: debounce_timer()}}
end
def name(pin_number), do: :"#{__MODULE__}.#{pin_number}"
2020-01-17 08:58:53 -07:00
defp debounce_timer,
do: Process.send_after(self(), :timeout, @debounce_timeout_ms)
end