Skip to content

Instantly share code, notes, and snippets.

@loeschg
Created March 21, 2017 22:32
Show Gist options
  • Save loeschg/65621b2e3e699754cfff4b13bd748add to your computer and use it in GitHub Desktop.
Save loeschg/65621b2e3e699754cfff4b13bd748add to your computer and use it in GitHub Desktop.
Fake gpio implementation for ElixirAle
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