Created
March 21, 2017 22:32
-
-
Save loeschg/65621b2e3e699754cfff4b13bd748add to your computer and use it in GitHub Desktop.
Fake gpio implementation for ElixirAle
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
defmodule FakeAle.Gpio do | |
use GenServer | |
@moduledoc """ | |
This is a fake Elixir interface to ElixirALE.GPIO. | |
Each "GPIO" is an independent GenServer. | |
""" | |
defmodule State do | |
@moduledoc false | |
defstruct pin: 0, | |
direction: nil, | |
value: 0, | |
callbacks: %{} | |
end | |
def start_link(pin, pin_direction, ops \\ []) do | |
GenServer.start_link(__MODULE__, [pin, pin_direction], ops) | |
end | |
def release(pid), do: GenServer.cast(pid, :release) | |
def write(pid, value) when is_integer(value) do | |
GenServer.call pid, {:write, value} | |
end | |
def write(pid, true), do: write(pid, 1) | |
def write(pid, false), do: write(pid, 0) | |
def read(pid), do: GenServer.call(pid, :read) | |
def set_int(pid, direction) when direction == :both or direction == :rising or direction == :falling or direction == :none do | |
GenServer.call(pid, {:set_int, direction, self()}) | |
end | |
def fake_rise(pid), do: GenServer.cast(pid, {:trigger, :rising}) | |
def fake_fall(pid), do: GenServer.cast(pid, {:trigger, :falling}) | |
def init([pin, pin_direction]) do | |
state = %State{pin: pin, direction: pin_direction, value: 0} | |
{:ok, state} | |
end | |
def handle_call({:write, value}, _from, state) do | |
{:reply, :ok, %{state | value: value}} | |
end | |
def handle_call(:read, _from, state) do | |
{:reply, state.value, state} | |
end | |
def handle_call({:set_int, direction, requestor}, _from, state) do | |
new_callbacks = add_or_remove_callback(requestor, direction, state) | |
state = %{state | callbacks: new_callbacks} | |
{:reply, :ok, state} | |
end | |
defp add_or_remove_callback(pid, :none, state), do: Map.delete(state.callbacks, pid) | |
defp add_or_remove_callback(pid, direction, state), do: Map.put(state.callbacks, pid, direction) | |
def handle_cast(:release, state) do | |
{:stop, :normal, state} | |
end | |
def handle_cast({:trigger, trigger_direction}, state) do | |
state.callbacks | |
|> Enum.filter(fn({_pid, callback_direction}) -> callback_direction == :both || trigger_direction == callback_direction end) | |
|> Enum.each(fn({pid, _}) -> send(pid, {:gpio_interrupt, state.pin, trigger_direction}) end) | |
{:noreply, state} | |
end | |
end |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment