Code gardening.

* Rename and extract a bunch of modules into their own files to make it easier to navigate the repository.
* Remove fake versions of `ElixirALE` and `Circuits` from `test/support`.
* Create wrapper modules for `ElixirALE` and `Circuits` modules using `defdelegate` instead.
* Use Elixir 1.10's new `@compile {:no_warn_undefined ...}` directive to inhibit compiler warnings for our optional dependencies.
This commit is contained in:
James Harton 2020-01-08 10:18:38 +13:00
parent 8f4bca1e58
commit 4b27f5441f
42 changed files with 388 additions and 337 deletions

View file

@ -50,7 +50,7 @@ end
I've included stub implementations of the parts of `ElixirALE` and `Circuits`
that are interacted with by this project, so the tests should run and pass on
machines without physical hardware interfaces. If you have a Raspberry Pi with
a Pi Sense Hat connected you can run the tests with the `FAKE_DRIVERS=false`
a Pi Sense Hat connected you can run the tests with the `SENSE_HAT_PRESENT=true`
environment variable set and it will perform integration tests with two of the
sensors on this device.

View file

@ -8,8 +8,8 @@ defmodule Wafer.Application do
def start(_type, _args) do
children = [
{Registry, [keys: :duplicate, name: Wafer.InterruptRegistry]},
Wafer.Driver.ElixirALEGPIODispatcher,
Wafer.Driver.CircuitsGPIODispatcher
Wafer.Driver.ElixirALE.GPIO.Dispatcher,
Wafer.Driver.Circuits.GPIO.Dispatcher
]
# See https://hexdocs.pm/elixir/Supervisor.html

View file

@ -46,7 +46,7 @@ defprotocol Wafer.Chip do
## Example
iex> {:ok, conn} = ElixirALEI2C.acquire(bus: "i2c-1", address: 0x68)
iex> {:ok, conn} = ElixirALE.I2C.acquire(bus: "i2c-1", address: 0x68)
...> Chip.read_register(conn, 0, 1)
{:ok, <<0>>}
"""
@ -65,7 +65,7 @@ defprotocol Wafer.Chip do
## Example
iex> {:ok, conn} = ElixirALEI2C.acquire(bus: "i2c", address: 0x68)
iex> {:ok, conn} = ElixirALE.I2C.acquire(bus: "i2c", address: 0x68)
...> Chip.write_register(conn, 0, <<0>>)
{:ok, conn}
"""
@ -90,7 +90,7 @@ defprotocol Wafer.Chip do
## Example
iex> {:ok, conn} = ElixirALEI2C.acquire(bus: "i2c", address: 0x68)
iex> {:ok, conn} = ElixirALE.I2C.acquire(bus: "i2c", address: 0x68)
...> Chip.swap_register(conn, 0, <<1>>)
{:ok, <<0>>, conn}
"""

View file

@ -12,7 +12,7 @@ defmodule Wafer.Conn do
```elixir
defmodule HTS221 do
defstruct ~w[conn]a
alias Wafer.Drivers.CircuitsI2C, as: Driver
alias Wafer.Drivers.Circuits.I2C, as: Driver
@behaviour Wafer.Conn
@default_bus "i2c-1"
@default_address 0x5F

View file

@ -1,7 +1,7 @@
defmodule Wafer.Driver.CircuitsGPIO do
defmodule Wafer.Driver.Circuits.GPIO do
defstruct ~w[direction pin ref]a
@behaviour Wafer.Conn
alias Circuits.GPIO, as: Driver
alias Wafer.Driver.Circuits.GPIO.Wrapper
alias Wafer.GPIO
import Wafer.Guards
@ -29,7 +29,7 @@ defmodule Wafer.Driver.CircuitsGPIO do
with {:ok, pin} when is_pin_number(pin) <- Keyword.fetch(opts, :pin),
direction when is_pin_direction(direction) <- Keyword.get(opts, :direction, :out),
pin_dir <- String.to_atom(Enum.join([direction, "put"], "")),
{:ok, ref} <- Driver.open(pin, pin_dir, Keyword.drop(opts, ~w[pin direction]a)) do
{:ok, ref} <- Wrapper.open(pin, pin_dir, Keyword.drop(opts, ~w[pin direction]a)) do
{:ok, %__MODULE__{ref: ref, pin: pin, direction: direction}}
else
:error -> {:error, "Circuits.GPIO requires a `pin` option."}
@ -43,23 +43,23 @@ defmodule Wafer.Driver.CircuitsGPIO do
Note that other connections may still be using the pin.
"""
@spec release(t) :: :ok | {:error, reason :: any}
def release(%__MODULE__{ref: ref} = _conn) when is_reference(ref), do: Driver.close(ref)
def release(%__MODULE__{ref: ref} = _conn) when is_reference(ref), do: Wrapper.close(ref)
end
defimpl Wafer.GPIO, for: Wafer.Driver.CircuitsGPIO do
alias Wafer.Driver.CircuitsGPIODispatcher
alias Circuits.GPIO, as: Driver
defimpl Wafer.GPIO, for: Wafer.Driver.Circuits.GPIO do
alias Wafer.Driver.Circuits.GPIO.Dispatcher
alias Wafer.Driver.Circuits.GPIO.Wrapper
import Wafer.Guards
def read(%{ref: ref}) when is_reference(ref) do
case(Driver.read(ref)) do
case(Wrapper.read(ref)) do
value when is_pin_value(value) -> {:ok, value}
{:error, reason} -> {:error, reason}
end
end
def write(%{ref: ref} = conn, value) when is_reference(ref) and is_pin_value(value) do
case(Driver.write(ref, value)) do
case(Wrapper.write(ref, value)) do
:ok -> {:ok, conn}
{:error, reason} -> {:error, reason}
end
@ -72,7 +72,7 @@ defimpl Wafer.GPIO, for: Wafer.Driver.CircuitsGPIO do
when is_reference(ref) and is_pin_direction(direction) do
pin_dir = String.to_atom(Enum.join([direction, "put"], ""))
case(Driver.set_direction(ref, pin_dir)) do
case(Wrapper.set_direction(ref, pin_dir)) do
:ok -> {:ok, %{conn | direction: direction}}
{:error, reason} -> {:error, reason}
end
@ -80,21 +80,21 @@ defimpl Wafer.GPIO, for: Wafer.Driver.CircuitsGPIO do
def enable_interrupt(conn, pin_condition, metadata \\ nil)
when is_pin_condition(pin_condition) do
with :ok <- CircuitsGPIODispatcher.enable(conn, pin_condition, metadata), do: {:ok, conn}
with :ok <- Dispatcher.enable(conn, pin_condition, metadata), do: {:ok, conn}
end
def disable_interrupt(conn, pin_condition) when is_pin_condition(pin_condition) do
with :ok <- CircuitsGPIODispatcher.disable(conn, pin_condition), do: {:ok, conn}
with :ok <- Dispatcher.disable(conn, pin_condition), do: {:ok, conn}
end
def pull_mode(%{ref: ref} = conn, mode) when is_reference(ref) and is_pin_pull_mode(mode) do
case Driver.set_pull_mode(ref, mode) do
case Wrapper.set_pull_mode(ref, mode) do
:ok -> {:ok, conn}
{:error, reason} -> {:error, reason}
end
end
end
defimpl Wafer.DeviceID, for: Wafer.Driver.CircuitsGPIO do
def id(%{pin: pin}), do: {Wafer.Driver.CircuitsGPIO, pin}
defimpl Wafer.DeviceID, for: Wafer.Driver.Circuits.GPIO do
def id(%{pin: pin}), do: {Wafer.Driver.Circuits.GPIO, pin}
end

View file

@ -1,7 +1,7 @@
defmodule Wafer.Driver.CircuitsGPIODispatcher do
defmodule Wafer.Driver.Circuits.GPIO.Dispatcher do
use GenServer
alias __MODULE__
alias Circuits.GPIO, as: Driver
alias Wafer.Driver.Circuits.GPIO.Wrapper
alias Wafer.{Conn, GPIO, InterruptRegistry}
import Wafer.Guards
@ -15,21 +15,22 @@ defmodule Wafer.Driver.CircuitsGPIODispatcher do
"""
@doc false
def start_link(opts), do: GenServer.start_link(__MODULE__, [opts], name: CircuitsGPIODispatcher)
def start_link(opts),
do: GenServer.start_link(__MODULE__, [opts], name: Dispatcher)
@doc """
Enable interrupts for this connection using the specified pin_condition.
"""
@spec enable(Conn.t(), GPIO.pin_condition(), any) :: {:ok, Conn.t()} | {:error, reason :: any}
def enable(conn, pin_condition, metadata \\ nil) when is_pin_condition(pin_condition),
do: GenServer.call(CircuitsGPIODispatcher, {:enable, conn, pin_condition, metadata, self()})
do: GenServer.call(Dispatcher, {:enable, conn, pin_condition, metadata, self()})
@doc """
Disable interrupts for this connection using the specified pin_condition.
"""
@spec disable(Conn.t(), GPIO.pin_condition()) :: {:ok, Conn.t()} | {:error, reason :: any}
def disable(conn, pin_condition) when is_pin_condition(pin_condition),
do: GenServer.call(CircuitsGPIODispatcher, {:disable, conn, pin_condition})
do: GenServer.call(Dispatcher, {:disable, conn, pin_condition})
@impl true
def init(_opts) do
@ -44,7 +45,7 @@ defmodule Wafer.Driver.CircuitsGPIODispatcher do
)
when is_pin_condition(pin_condition) and is_pid(receiver) and is_reference(ref) and
is_pin_number(pin) do
with :ok <- Driver.set_interrupts(ref, pin_condition),
with :ok <- Wrapper.set_interrupts(ref, pin_condition),
:ok <- InterruptRegistry.subscribe(key(pin), pin_condition, conn, metadata, receiver) do
{:reply, {:ok, conn}, state}
else

View file

@ -0,0 +1,30 @@
defmodule Wafer.Driver.Circuits.GPIO.Wrapper do
@moduledoc false
@compile {:no_warn_undefined, Circuits.GPIO}
defdelegate close(gpio), to: Circuits.GPIO
@compile {:no_warn_undefined, Circuits.GPIO}
defdelegate info(), to: Circuits.GPIO
@compile {:no_warn_undefined, Circuits.GPIO}
defdelegate open(pin_number, pin_direction, options \\ []), to: Circuits.GPIO
@compile {:no_warn_undefined, Circuits.GPIO}
defdelegate pin(gpio), to: Circuits.GPIO
@compile {:no_warn_undefined, Circuits.GPIO}
defdelegate read(gpio), to: Circuits.GPIO
@compile {:no_warn_undefined, Circuits.GPIO}
defdelegate set_direction(gpio, pin_direction), to: Circuits.GPIO
@compile {:no_warn_undefined, Circuits.GPIO}
defdelegate set_interrupts(gpio, trigger, opts \\ []), to: Circuits.GPIO
@compile {:no_warn_undefined, Circuits.GPIO}
defdelegate set_pull_mode(gpio, pull_mode), to: Circuits.GPIO
@compile {:no_warn_undefined, Circuits.GPIO}
defdelegate write(gpio, value), to: Circuits.GPIO
end

View file

@ -1,7 +1,7 @@
defmodule Wafer.Driver.CircuitsI2C do
defmodule Wafer.Driver.Circuits.I2C do
defstruct ~w[address bus ref]a
@behaviour Wafer.Conn
alias Circuits.I2C, as: Driver
alias Wafer.Driver.Circuits.I2C.Wrapper
alias Wafer.I2C
import Wafer.Guards
@ -23,8 +23,8 @@ defmodule Wafer.Driver.CircuitsI2C do
def acquire(opts) when is_list(opts) do
with {:ok, bus} when is_binary(bus) <- Keyword.fetch(opts, :bus_name),
{:ok, address} when is_i2c_address(address) <- Keyword.fetch(opts, :address),
{:ok, ref} when is_reference(ref) <- Driver.open(bus),
devices when is_list(devices) <- Driver.detect_devices(ref),
{:ok, ref} when is_reference(ref) <- Wrapper.open(bus),
devices when is_list(devices) <- Wrapper.detect_devices(ref),
true <- Keyword.get(opts, :force, false) || Enum.member?(devices, address) do
{:ok, %__MODULE__{bus: bus, address: address, ref: ref}}
else
@ -40,24 +40,24 @@ defmodule Wafer.Driver.CircuitsI2C do
end
@spec release(t) :: :ok | {:error, reason :: any}
def release(%__MODULE__{ref: ref} = _conn), do: Driver.close(ref)
def release(%__MODULE__{ref: ref} = _conn), do: Wrapper.close(ref)
end
defimpl Wafer.Chip, for: Wafer.Driver.CircuitsI2C do
alias Circuits.I2C, as: Driver
defimpl Wafer.Chip, for: Wafer.Driver.Circuits.I2C do
alias Wafer.Driver.Circuits.I2C.Wrapper
import Wafer.Guards
def read_register(%{ref: ref, address: address}, register_address, bytes)
when is_reference(ref) and is_i2c_address(address) and is_register_address(register_address) and
is_byte_size(bytes),
do: Driver.write_read(ref, address, <<register_address>>, bytes)
do: Wrapper.write_read(ref, address, <<register_address>>, bytes)
def read_register(_conn, _register_address, _bytes), do: {:error, "Invalid argument"}
def write_register(%{ref: ref, address: address} = conn, register_address, data)
when is_reference(ref) and is_i2c_address(address) and is_register_address(register_address) and
is_binary(data) do
case Driver.write(ref, address, <<register_address, data::binary>>) do
case Wrapper.write(ref, address, <<register_address, data::binary>>) do
:ok -> {:ok, conn}
{:error, reason} -> {:error, reason}
end
@ -76,18 +76,18 @@ defimpl Wafer.Chip, for: Wafer.Driver.CircuitsI2C do
def swap_register(_conn, _register_address, _data), do: {:error, "Invalid argument"}
end
defimpl Wafer.I2C, for: Wafer.Driver.CircuitsI2C do
defimpl Wafer.I2C, for: Wafer.Driver.Circuits.I2C do
import Wafer.Guards
alias Circuits.I2C, as: Driver
alias Wafer.Driver.Circuits.I2C.Wrapper
def read(%{ref: ref, address: address}, bytes, options \\ [])
when is_reference(ref) and is_i2c_address(address) and is_byte_size(bytes) and
is_list(options),
do: Driver.read(ref, address, bytes, options)
do: Wrapper.read(ref, address, bytes, options)
def write(%{ref: ref, address: address} = conn, data, options \\ [])
when is_reference(ref) and is_i2c_address(address) and is_binary(data) and is_list(options) do
case Driver.write(ref, address, data, options) do
case Wrapper.write(ref, address, data, options) do
:ok -> {:ok, conn}
{:error, reason} -> {:error, reason}
end
@ -96,20 +96,20 @@ defimpl Wafer.I2C, for: Wafer.Driver.CircuitsI2C do
def write_read(%{ref: ref, address: address} = conn, data, bytes, options \\ [])
when is_reference(ref) and is_i2c_address(address) and is_binary(data) and
is_byte_size(bytes) and is_list(options) do
case Driver.write_read(ref, address, data, bytes, options) do
case Wrapper.write_read(ref, address, data, bytes, options) do
{:ok, data} -> {:ok, data, conn}
{:error, reason} -> {:error, reason}
end
end
def detect_devices(%{ref: ref}) when is_reference(ref) do
case Driver.detect_devices(ref) do
case Wrapper.detect_devices(ref) do
devices when is_list(devices) -> {:ok, devices}
{:error, reason} -> {:error, reason}
end
end
end
defimpl Wafer.DeviceID, for: Wafer.Driver.CircuitsI2C do
def id(%{address: address, bus: bus}), do: {Wafer.Driver.CircuitsI2C, bus, address}
defimpl Wafer.DeviceID, for: Wafer.Driver.Circuits.I2C do
def id(%{address: address, bus: bus}), do: {Wafer.Driver.Circuits.I2C, bus, address}
end

View file

@ -0,0 +1,41 @@
defmodule Wafer.Driver.Circuits.I2C.Wrapper do
@moduledoc false
@compile {:no_warn_undefined, Circuits.I2C}
defdelegate bus_names(), to: Circuits.I2C
@compile {:no_warn_undefined, Circuits.I2C}
defdelegate close(i2c_bus), to: Circuits.I2C
@compile {:no_warn_undefined, Circuits.I2C}
defdelegate detect_devices(), to: Circuits.I2C
@compile {:no_warn_undefined, Circuits.I2C}
defdelegate detect_devices(i2c_bus), to: Circuits.I2C
@compile {:no_warn_undefined, Circuits.I2C}
defdelegate info(), to: Circuits.I2C
@compile {:no_warn_undefined, Circuits.I2C}
defdelegate open(bus_name), to: Circuits.I2C
@compile {:no_warn_undefined, Circuits.I2C}
defdelegate read(i2c_bus, address, bytes_to_read, opts \\ []), to: Circuits.I2C
@compile {:no_warn_undefined, Circuits.I2C}
defdelegate read!(i2c_bus, address, bytes_to_read, opts \\ []), to: Circuits.I2C
@compile {:no_warn_undefined, Circuits.I2C}
defdelegate write(i2c_bus, address, data, opts \\ []), to: Circuits.I2C
@compile {:no_warn_undefined, Circuits.I2C}
defdelegate write!(i2c_bus, address, data, opts \\ []), to: Circuits.I2C
@compile {:no_warn_undefined, Circuits.I2C}
defdelegate write_read(i2c_bus, address, write_data, bytes_to_read, opts \\ []),
to: Circuits.I2C
@compile {:no_warn_undefined, Circuits.I2C}
defdelegate write_read!(i2c_bus, address, write_data, bytes_to_read, opts \\ []),
to: Circuits.I2C
end

View file

@ -1,7 +1,7 @@
defmodule Wafer.Driver.CircuitsSPI do
defmodule Wafer.Driver.Circuits.SPI do
defstruct ~w[bus ref]a
@behaviour Wafer.Conn
alias Circuits.SPI, as: Driver
alias Wafer.Driver.Circuits.SPI.Wrapper
@moduledoc """
A connection to a chip via Circuits's SPI driver.
@ -27,7 +27,7 @@ defmodule Wafer.Driver.CircuitsSPI do
@spec acquire(options) :: {:ok, t} | {:error, reason :: any}
def acquire(opts) when is_list(opts) do
with {:ok, bus} when is_binary(bus) <- Keyword.fetch(opts, :bus_name),
{:ok, ref} when is_reference(ref) <- Driver.open(bus, Keyword.delete(opts, :bus_name)) do
{:ok, ref} when is_reference(ref) <- Wrapper.open(bus, Keyword.delete(opts, :bus_name)) do
{:ok, %__MODULE__{bus: bus, ref: ref}}
else
:error -> {:error, "Circuits.SPI requires a `bus_name` option"}
@ -39,20 +39,20 @@ defmodule Wafer.Driver.CircuitsSPI do
Close the SPI bus connection.
"""
@spec release(t) :: :ok | {:error, reason :: any}
def release(%__MODULE__{ref: ref} = _conn) when is_reference(ref), do: Driver.close(ref)
def release(%__MODULE__{ref: ref} = _conn) when is_reference(ref), do: Wrapper.close(ref)
end
defimpl Wafer.SPI, for: Wafer.Driver.CircuitsSPI do
alias Circuits.SPI, as: Driver
defimpl Wafer.SPI, for: Wafer.Driver.Circuits.SPI do
alias Wafer.Driver.Circuits.SPI.Wrapper
def transfer(%{ref: ref} = conn, data) when is_reference(ref) and is_binary(data) do
case Driver.transfer(ref, data) do
case Wrapper.transfer(ref, data) do
{:ok, data} -> {:ok, data, conn}
{:error, reason} -> {:error, reason}
end
end
end
defimpl Wafer.DeviceID, for: Wafer.Driver.CircuitsSPI do
def id(%{bus: bus}), do: {Wafer.Driver.CircuitsSPI, bus}
defimpl Wafer.DeviceID, for: Wafer.Driver.Circuits.SPI do
def id(%{bus: bus}), do: {Wafer.Driver.Circuits.SPI, bus}
end

View file

@ -0,0 +1,18 @@
defmodule Wafer.Driver.Circuits.SPI.Wrapper do
@moduledoc false
@compile {:no_warn_undefined, Circuits.SPI}
defdelegate bus_names(), to: Circuits.SPI
@compile {:no_warn_undefined, Circuits.SPI}
defdelegate close(spi_bus), to: Circuits.SPI
@compile {:no_warn_undefined, Circuits.SPI}
defdelegate info(), to: Circuits.SPI
@compile {:no_warn_undefined, Circuits.SPI}
defdelegate open(bus_name, options \\ []), to: Circuits.SPI
@compile {:no_warn_undefined, Circuits.SPI}
defdelegate transfer(spi_bus, data), to: Circuits.SPI
end

View file

@ -1,7 +1,7 @@
defmodule Wafer.Driver.ElixirALEGPIO do
defmodule Wafer.Driver.ElixirALE.GPIO do
defstruct ~w[direction pid pin]a
@behaviour Wafer.Conn
alias ElixirALE.GPIO, as: Driver
alias Wafer.Driver.ElixirALE.GPIO.Wrapper
alias Wafer.GPIO
import Wafer.Guards
@ -28,7 +28,7 @@ defmodule Wafer.Driver.ElixirALEGPIO do
def acquire(opts) when is_list(opts) do
with {:ok, pin} when is_pin_number(pin) <- Keyword.fetch(opts, :pin),
direction when direction in [:in, :out] <- Keyword.get(opts, :direction, :out),
{:ok, pid} <- Driver.start_link(pin, direction, Keyword.drop(opts, ~w[pin direction]a)) do
{:ok, pid} <- Wrapper.start_link(pin, direction, Keyword.drop(opts, ~w[pin direction]a)) do
{:ok, %__MODULE__{pid: pid, pin: pin, direction: direction}}
else
:error -> {:error, "ElixirALE.GPIO requires a `pin` option."}
@ -42,22 +42,22 @@ defmodule Wafer.Driver.ElixirALEGPIO do
Note that other connections may still be using the pin.
"""
@spec release(t) :: :ok | {:error, reason :: any}
def release(%__MODULE__{pid: pid} = _conn), do: Driver.release(pid)
def release(%__MODULE__{pid: pid} = _conn), do: Wrapper.release(pid)
end
defimpl Wafer.GPIO, for: Wafer.Driver.ElixirALEGPIO do
alias ElixirALE.GPIO, as: Driver
alias Wafer.Driver.ElixirALEGPIODispatcher
defimpl Wafer.GPIO, for: Wafer.Driver.ElixirALE.GPIO do
alias Wafer.Driver.ElixirALE.GPIO.Wrapper
alias Wafer.Driver.ElixirALE.GPIO.Dispatcher
def read(%{pid: pid} = _conn) do
case Driver.read(pid) do
case Wrapper.read(pid) do
value when value in [0, 1] -> {:ok, value}
{:error, reason} -> {:error, reason}
end
end
def write(%{pid: pid} = conn, value) when value in [0, 1] do
case Driver.write(pid, value) do
case Wrapper.write(pid, value) do
:ok -> {:ok, conn}
{:error, reason} -> {:error, reason}
end
@ -66,14 +66,14 @@ defimpl Wafer.GPIO, for: Wafer.Driver.ElixirALEGPIO do
def direction(_conn, _direction), do: {:error, :not_supported}
def enable_interrupt(conn, pin_condition, metadata \\ nil),
do: ElixirALEGPIODispatcher.enable(conn, pin_condition, metadata)
do: Dispatcher.enable(conn, pin_condition, metadata)
def disable_interrupt(conn, pin_condition),
do: ElixirALEGPIODispatcher.disable(conn, pin_condition)
do: Dispatcher.disable(conn, pin_condition)
def pull_mode(_conn, _pull_mode), do: {:error, :not_supported}
end
defimpl Wafer.DeviceID, for: Wafer.Driver.ElixirALEGPIO do
def id(%{pin: pin}), do: {Wafer.Driver.ElixirALEGPIO, pin}
defimpl Wafer.DeviceID, for: Wafer.Driver.ElixirALE.GPIO do
def id(%{pin: pin}), do: {Wafer.Driver.ElixirALE.GPIO, pin}
end

View file

@ -1,7 +1,7 @@
defmodule Wafer.Driver.ElixirALEGPIODispatcher do
defmodule Wafer.Driver.ElixirALE.GPIO.Dispatcher do
use GenServer
alias __MODULE__
alias ElixirALE.GPIO, as: Driver
alias Wafer.Driver.ElixirALE.GPIO.Wrapper
alias Wafer.{Conn, GPIO, InterruptRegistry}
@allowed_pin_conditions ~w[rising falling both]a
@ -13,21 +13,21 @@ defmodule Wafer.Driver.ElixirALEGPIODispatcher do
@doc false
def start_link(opts),
do: GenServer.start_link(__MODULE__, [opts], name: ElixirALEGPIODispatcher)
do: GenServer.start_link(__MODULE__, [opts], name: Dispatcher)
@doc """
Enable interrupts for this connection using the specified pin_condition.
"""
@spec enable(Conn.t(), GPIO.pin_condition(), any) :: {:ok, Conn.t()} | {:error, reason :: any}
def enable(conn, pin_condition, metadata) when pin_condition in @allowed_pin_conditions,
do: GenServer.call(ElixirALEGPIODispatcher, {:enable, conn, pin_condition, metadata, self()})
do: GenServer.call(Dispatcher, {:enable, conn, pin_condition, metadata, self()})
@doc """
Disable interrupts for this connection on the specified pin_condition.
"""
@spec disable(Conn.t(), GPIO.pin_condition()) :: {:ok, Conn.t()} | {:error, reason :: any}
def disable(conn, pin_condition) when pin_condition in @allowed_pin_conditions,
do: GenServer.call(ElixirALEGPIODispatcher, {:disable, conn, pin_condition})
do: GenServer.call(Dispatcher, {:disable, conn, pin_condition})
@impl true
def init(_opts) do
@ -41,7 +41,7 @@ defmodule Wafer.Driver.ElixirALEGPIODispatcher do
state
)
when pin_condition in @allowed_pin_conditions do
with :ok <- Driver.set_int(pid, pin_condition),
with :ok <- Wrapper.set_int(pid, pin_condition),
:ok <- InterruptRegistry.subscribe(key(pin), pin_condition, conn, metadata, receiver) do
{:reply, {:ok, conn}, state}
else

View file

@ -0,0 +1,27 @@
defmodule Wafer.Driver.ElixirALE.GPIO.Wrapper do
@moduledoc false
@compile {:no_warn_undefined, ElixirALE.GPIO}
defdelegate child_spec(arg), to: ElixirALE.GPIO
@compile {:no_warn_undefined, ElixirALE.GPIO}
defdelegate init(list), to: ElixirALE.GPIO
@compile {:no_warn_undefined, ElixirALE.GPIO}
defdelegate pin(pid), to: ElixirALE.GPIO
@compile {:no_warn_undefined, ElixirALE.GPIO}
defdelegate read(pid), to: ElixirALE.GPIO
@compile {:no_warn_undefined, ElixirALE.GPIO}
defdelegate release(pid), to: ElixirALE.GPIO
@compile {:no_warn_undefined, ElixirALE.GPIO}
defdelegate set_int(pid, direction), to: ElixirALE.GPIO
@compile {:no_warn_undefined, ElixirALE.GPIO}
defdelegate start_link(pin, pin_direction, opts \\ []), to: ElixirALE.GPIO
@compile {:no_warn_undefined, ElixirALE.GPIO}
defdelegate write(pid, value), to: ElixirALE.GPIO
end

View file

@ -1,7 +1,6 @@
defmodule Wafer.Driver.ElixirALEI2C do
defmodule Wafer.Driver.ElixirALE.I2C do
defstruct ~w[address bus pid]a
@behaviour Wafer.Conn
alias ElixirALE.I2C, as: Driver
alias Wafer.Driver.ElixirALE.I2C.Wrapper
alias Wafer.I2C
import Wafer.Guards
@ -24,8 +23,8 @@ defmodule Wafer.Driver.ElixirALEI2C do
def acquire(opts) when is_list(opts) do
with {:ok, bus} when is_binary(bus) <- Keyword.fetch(opts, :bus_name),
{:ok, address} when is_i2c_address(address) <- Keyword.fetch(opts, :address),
{:ok, pid} <- Driver.start_link(bus, address),
devices when is_list(devices) <- Driver.detect_devices(pid),
{:ok, pid} <- Wrapper.start_link(bus, address),
devices when is_list(devices) <- Wrapper.detect_devices(pid),
true <- Keyword.get(opts, :force, false) || Enum.member?(devices, address) do
{:ok, %__MODULE__{bus: bus, address: address, pid: pid}}
else
@ -41,16 +40,16 @@ defmodule Wafer.Driver.ElixirALEI2C do
end
@spec release(t) :: :ok | {:error, reason :: any}
def release(%__MODULE__{pid: pid} = _conn) when is_pid(pid), do: ElixirALE.I2C.release(pid)
def release(%__MODULE__{pid: pid} = _conn) when is_pid(pid), do: Wrapper.release(pid)
end
defimpl Wafer.Chip, for: Wafer.Driver.ElixirALEI2C do
alias ElixirALE.I2C, as: Driver
defimpl Wafer.Chip, for: Wafer.Driver.ElixirALE.I2C do
alias Wafer.Driver.ElixirALE.I2C.Wrapper
import Wafer.Guards
def read_register(%{pid: pid}, register_address, bytes)
when is_pid(pid) and is_register_address(register_address) and is_byte_size(bytes) do
case Driver.write_read(pid, <<register_address>>, bytes) do
case Wrapper.write_read(pid, <<register_address>>, bytes) do
data when is_binary(data) -> {:ok, data}
{:error, reason} -> {:error, reason}
end
@ -60,7 +59,7 @@ defimpl Wafer.Chip, for: Wafer.Driver.ElixirALEI2C do
def write_register(%{pid: pid} = conn, register_address, data)
when is_pid(pid) and is_register_address(register_address) and is_binary(data) do
case Driver.write(pid, <<register_address, data::binary>>) do
case Wrapper.write(pid, <<register_address, data::binary>>) do
:ok -> {:ok, conn}
{:error, reason} -> {:error, reason}
end
@ -79,13 +78,13 @@ defimpl Wafer.Chip, for: Wafer.Driver.ElixirALEI2C do
def swap_register(_conn, _register_address, _data), do: {:error, "Invalid argument"}
end
defimpl Wafer.I2C, for: Wafer.Driver.ElixirALEI2C do
defimpl Wafer.I2C, for: Wafer.Driver.ElixirALE.I2C do
import Wafer.Guards
alias ElixirALE.I2C, as: Driver
alias Wafer.Driver.ElixirALE.I2C.Wrapper
def read(%{pid: pid}, bytes, options \\ [])
when is_pid(pid) and is_byte_size(bytes) and is_list(options) do
case Driver.read(pid, bytes) do
case Wrapper.read(pid, bytes) do
data when is_binary(data) -> {:ok, data}
{:error, reason} -> {:error, reason}
end
@ -93,7 +92,7 @@ defimpl Wafer.I2C, for: Wafer.Driver.ElixirALEI2C do
def write(%{pid: pid} = conn, data, options \\ [])
when is_pid(pid) and is_binary(data) and is_list(options) do
case Driver.write(pid, data) do
case Wrapper.write(pid, data) do
:ok -> {:ok, conn}
{:error, reason} -> {:error, reason}
end
@ -101,20 +100,20 @@ defimpl Wafer.I2C, for: Wafer.Driver.ElixirALEI2C do
def write_read(%{pid: pid} = conn, data, bytes, options \\ [])
when is_pid(pid) and is_binary(data) and is_byte_size(bytes) and is_list(options) do
case Driver.write_read(pid, data, bytes) do
case Wrapper.write_read(pid, data, bytes) do
data when is_binary(data) -> {:ok, data, conn}
{:error, reason} -> {:error, reason}
end
end
def detect_devices(%{pid: pid}) do
case Driver.detect_devices(pid) do
case Wrapper.detect_devices(pid) do
devices when is_list(devices) -> {:ok, devices}
{:error, reason} -> {:error, reason}
end
end
end
defimpl Wafer.DeviceID, for: Wafer.Driver.ElixirALEI2C do
def id(%{address: address, bus: bus}), do: {Wafer.Driver.ElixirALEI2C, bus, address}
defimpl Wafer.DeviceID, for: Wafer.Driver.ElixirALE.I2C do
def id(%{address: address, bus: bus}), do: {Wafer.Driver.ElixirALE.I2C, bus, address}
end

View file

@ -0,0 +1,39 @@
defmodule Wafer.Driver.ElixirALE.I2C.Wrapper do
@moduledoc false
@compile {:no_warn_undefined, ElixirALE.I2C}
defdelegate child_spec(arg), to: ElixirALE.I2C
@compile {:no_warn_undefined, ElixirALE.I2C}
defdelegate detect_devices(pid_or_devname), to: ElixirALE.I2C
@compile {:no_warn_undefined, ElixirALE.I2C}
defdelegate device_names(), to: ElixirALE.I2C
@compile {:no_warn_undefined, ElixirALE.I2C}
defdelegate init(list), to: ElixirALE.I2C
@compile {:no_warn_undefined, ElixirALE.I2C}
defdelegate read(pid, count), to: ElixirALE.I2C
@compile {:no_warn_undefined, ElixirALE.I2C}
defdelegate read_device(pid, address, count), to: ElixirALE.I2C
@compile {:no_warn_undefined, ElixirALE.I2C}
defdelegate release(pid), to: ElixirALE.I2C
@compile {:no_warn_undefined, ElixirALE.I2C}
defdelegate start_link(devname, address, opts \\ []), to: ElixirALE.I2C
@compile {:no_warn_undefined, ElixirALE.I2C}
defdelegate write(pid, data), to: ElixirALE.I2C
@compile {:no_warn_undefined, ElixirALE.I2C}
defdelegate write_device(pid, address, data), to: ElixirALE.I2C
@compile {:no_warn_undefined, ElixirALE.I2C}
defdelegate write_read(pid, write_data, read_count), to: ElixirALE.I2C
@compile {:no_warn_undefined, ElixirALE.I2C}
defdelegate write_read_device(pid, address, write_data, read_count), to: ElixirALE
end

View file

@ -1,7 +1,7 @@
defmodule Wafer.Driver.ElixirALESPI do
defmodule Wafer.Driver.ElixirALE.SPI do
defstruct ~w[bus pid]a
@behaviour Wafer.Conn
alias ElixirALE.SPI, as: Driver
alias Wafer.Driver.ElixirALE.SPI.Wrapper
@moduledoc """
A connection to a chip via ElixirALE's SPI driver.
@ -28,7 +28,7 @@ defmodule Wafer.Driver.ElixirALESPI do
def acquire(opts) when is_list(opts) do
with {:ok, bus} when is_binary(bus) <- Keyword.fetch(opts, :bus_name),
{:ok, pid} when is_pid(pid) <-
Driver.start_link(bus, Keyword.delete(opts, :bus_name), []) do
Wrapper.start_link(bus, Keyword.delete(opts, :bus_name), []) do
{:ok, %__MODULE__{bus: bus, pid: pid}}
else
:error -> {:error, "ElixirALE.SPI requires a `bus_name` option"}
@ -40,20 +40,20 @@ defmodule Wafer.Driver.ElixirALESPI do
Close the SPI bus connection.
"""
@spec release(t) :: :ok | {:error, reason :: any}
def release(%__MODULE__{pid: pid} = _conn) when is_pid(pid), do: Driver.release(pid)
def release(%__MODULE__{pid: pid} = _conn) when is_pid(pid), do: Wrapper.release(pid)
end
defimpl Wafer.SPI, for: Wafer.Driver.ElixirALESPI do
alias ElixirALE.SPI, as: Driver
defimpl Wafer.SPI, for: Wafer.Driver.ElixirALE.SPI do
alias Wafer.Driver.ElixirALE.SPI.Wrapper
def transfer(%{pid: pid} = conn, data) when is_pid(pid) and is_binary(data) do
case Driver.transfer(pid, data) do
case Wrapper.transfer(pid, data) do
data when is_binary(data) -> {:ok, data, conn}
{:error, reason} -> {:error, reason}
end
end
end
defimpl Wafer.DeviceID, for: Wafer.Driver.ElixirALESPI do
def id(%{bus: bus}), do: {Wafer.Driver.ElixirALESPI, bus}
defimpl Wafer.DeviceID, for: Wafer.Driver.ElixirALE.SPI do
def id(%{bus: bus}), do: {Wafer.Driver.ElixirALE.SPI, bus}
end

View file

@ -0,0 +1,21 @@
defmodule Wafer.Driver.ElixirALE.SPI.Wrapper do
@moduledoc false
@compile {:no_warn_undefined, ElixirALE.SPI}
defdelegate child_spec(arg), to: ElixirALE.SPI
@compile {:no_warn_undefined, ElixirALE.SPI}
defdelegate device_names(), to: ElixirALE.SPI
@compile {:no_warn_undefined, ElixirALE.SPI}
defdelegate init(arg), to: ElixirALE.SPI
@compile {:no_warn_undefined, ElixirALE.SPI}
defdelegate release(pid), to: ElixirALE.SPI
@compile {:no_warn_undefined, ElixirALE.SPI}
defdelegate start_link(devname, spi_opts \\ [], opts \\ []), to: ElixirALE.SPI
@compile {:no_warn_undefined, ElixirALE.SPI}
defdelegate transfer(pid, data), to: ElixirALE.SPI
end

View file

@ -73,7 +73,7 @@ defprotocol Wafer.GPIO do
`Wafer` starts it's own `Registry` named `Wafer.InterruptRegistry` which you
can use to publish your interrupts to using the above format. The registry
key is set as follows: `{PublishingModule, pin, pin_condition}`. You can see
examples in the `CircuitsGPIODispatcher` and `ElixirALEGPIODispatcher`
examples in the `Circuits.GPIO.Dispatcher` and `ElixirALE.GPIO.Dispatcher`
modules.
"""
@spec enable_interrupt(Conn.t(), pin_condition, any) ::

View file

@ -7,8 +7,8 @@ defmodule Wafer.InterruptRegistry do
This module provides Wafer's interrupt registry. This allows multiple
subscribers to be subscribed to interrupts from many different pins.
It is used by `Driver.CircuitsGPIODispatcher` and
`Driver.ElixirALEGPIODispatcher` and you should probably use it if you're
It is used by `Driver.Circuits.GPIO.Dispatcher` and
`Driver.ElixirALE.GPIO.Dispatcher` and you should probably use it if you're
writing your own driver which supports sending interrupts to subscribers.
"""

11
mix.exs
View file

@ -13,7 +13,6 @@ defmodule Wafer.MixProject do
app: :wafer,
version: @version,
elixir: "~> 1.9",
elixirc_paths: elixirc_paths(Mix.env()),
start_permanent: Mix.env() == :prod,
package: package(),
description: @description,
@ -53,14 +52,4 @@ defmodule Wafer.MixProject do
{:circuits_spi, "~> 0.1", optional: true}
]
end
# Load fake versions of the Circuits and ElixirALE modules unless explicitly
# told not to.
defp elixirc_paths(:test) do
if System.get_env("FAKE_DRIVERS") == "false",
do: elixirc_paths(nil),
else: ["test/support" | elixirc_paths(nil)]
end
defp elixirc_paths(_), do: ["lib"]
end

View file

@ -1,9 +1,9 @@
defmodule WaferAcceptanceCircuitsI2CDeviceTest do
defmodule WaferAcceptanceCircuits.I2CDeviceTest do
use ExUnit.Case, async: true
# Only run acceptance tests if the fake drivers are not loaded.
if System.get_env("FAKE_DRIVERS") == "false" do
alias Wafer.Driver.CircuitsI2C, as: Driver
if System.get_env("SENSE_HAT_PRESENT") == "true" do
alias Wafer.Driver.Circuits.I2C, as: Driver
defmodule HTS221 do
use Wafer.Registers

View file

@ -1,9 +1,9 @@
defmodule WaferAcceptanceElixirALEI2CDeviceTest do
defmodule WaferAcceptanceElixirALE.I2CDeviceTest do
use ExUnit.Case, async: true
# Only run acceptance tests if the fake drivers are not loaded.
if System.get_env("FAKE_DRIVERS") == "false" do
alias Wafer.Driver.ElixirALEI2C, as: Driver
if System.get_env("SENSE_HAT_PRESENT") == "true" do
alias Wafer.Driver.ElixirALE.I2C, as: Driver
defmodule LPS25H do
use Wafer.Registers

View file

@ -1,8 +1,8 @@
defmodule WaferChipTest do
use ExUnit.Case, async: true
alias Wafer.Chip
alias Wafer.Chip.Wafer.Driver.CircuitsI2C, as: Impl
alias Wafer.Driver.CircuitsI2C, as: Driver
alias Wafer.Chip.Wafer.Driver.Circuits.I2C, as: Impl
alias Wafer.Driver.Circuits.I2C, as: Driver
import Mimic
Code.require_file("test/support/test_utils.exs")
@moduledoc false

View file

@ -1,7 +1,7 @@
defmodule WaferDriverCircuitsGPIODispatcherTest do
defmodule WaferDriverCircuits.GPIO.DispatcherTest do
use ExUnit.Case, async: true
alias Circuits.GPIO, as: Driver
alias Wafer.Driver.CircuitsGPIODispatcher, as: Dispatcher
alias Wafer.Driver.Circuits.GPIO.Wrapper
alias Wafer.Driver.Circuits.GPIO.Dispatcher, as: Dispatcher
alias Wafer.InterruptRegistry, as: IR
import Mimic
@moduledoc false
@ -10,7 +10,7 @@ defmodule WaferDriverCircuitsGPIODispatcherTest do
test "enabling rising interrupts" do
conn = conn()
Driver
Wrapper
|> expect(:set_interrupts, 1, fn ref, pin_condition ->
assert ref == conn.ref
assert pin_condition == :rising
@ -26,7 +26,7 @@ defmodule WaferDriverCircuitsGPIODispatcherTest do
test "enabling falling interrupts" do
conn = conn()
Driver
Wrapper
|> expect(:set_interrupts, 1, fn ref, pin_condition ->
assert ref == conn.ref
assert pin_condition == :falling
@ -42,7 +42,7 @@ defmodule WaferDriverCircuitsGPIODispatcherTest do
test "enabling both interrupts" do
conn = conn()
Driver
Wrapper
|> expect(:set_interrupts, 1, fn ref, pin_condition ->
assert ref == conn.ref
assert pin_condition == :both
@ -58,7 +58,7 @@ defmodule WaferDriverCircuitsGPIODispatcherTest do
test "disabling rising interrupts" do
conn = conn()
Driver
Wrapper
|> stub(:set_interrupts, fn _, _ -> :ok end)
Dispatcher.handle_call({:enable, conn, :rising, :metadata, self()}, nil, state())
@ -72,7 +72,7 @@ defmodule WaferDriverCircuitsGPIODispatcherTest do
test "disabling falling interrupts" do
conn = conn()
Driver
Wrapper
|> stub(:set_interrupts, fn _, _ -> :ok end)
Dispatcher.handle_call({:enable, conn, :falling, :metadta, self()}, nil, state())
@ -86,7 +86,7 @@ defmodule WaferDriverCircuitsGPIODispatcherTest do
test "disabling both interrupts" do
conn = conn()
Driver
Wrapper
|> stub(:set_interrupts, fn _, _ -> :ok end)
Dispatcher.handle_call({:enable, conn, :both, :metadata, self()}, nil, state())
@ -100,7 +100,7 @@ defmodule WaferDriverCircuitsGPIODispatcherTest do
describe "handle_info/2" do
test "publishing interrupts when the value was previously unknown" do
Driver
Wrapper
|> stub(:set_interrupts, fn _, _ -> :ok end)
{:reply, {:ok, conn}, state} =
@ -112,7 +112,7 @@ defmodule WaferDriverCircuitsGPIODispatcherTest do
end
test "publishing interrupts when the value rises" do
Driver
Wrapper
|> stub(:set_interrupts, fn _, _ -> :ok end)
state = state(values: %{1 => 0})
@ -126,7 +126,7 @@ defmodule WaferDriverCircuitsGPIODispatcherTest do
end
test "publishing interrupts when the value falls" do
Driver
Wrapper
|> stub(:set_interrupts, fn _, _ -> :ok end)
state = state(values: %{1 => 1})
@ -140,7 +140,7 @@ defmodule WaferDriverCircuitsGPIODispatcherTest do
end
test "ignoring interrupts when the value stays high" do
Driver
Wrapper
|> stub(:set_interrupts, fn _, _ -> :ok end)
state = state(values: %{1 => 1})
@ -154,7 +154,7 @@ defmodule WaferDriverCircuitsGPIODispatcherTest do
end
test "ignoring interrupts when the value stays low" do
Driver
Wrapper
|> stub(:set_interrupts, fn _, _ -> :ok end)
state = state(values: %{1 => 0})

View file

@ -1,15 +1,15 @@
defmodule WaferDriverCircuitsGPIOTest do
defmodule WaferDriverCircuits.GPIOTest do
use ExUnit.Case, async: true
use Mimic
alias Circuits.GPIO, as: Driver
alias Wafer.Driver.CircuitsGPIO, as: Subject
alias Wafer.Driver.CircuitsGPIODispatcher, as: Dispatcher
alias Wafer.Driver.Circuits.GPIO.Wrapper
alias Wafer.Driver.Circuits.GPIO, as: Subject
alias Wafer.Driver.Circuits.GPIO.Dispatcher, as: Dispatcher
alias Wafer.GPIO, as: GPIO
@moduledoc false
describe "acquire/1" do
test "opens the pin and creates the conn" do
Driver
Wrapper
|> expect(:open, 1, fn pin, direction, opts ->
assert pin == 1
assert direction == :output
@ -29,7 +29,7 @@ defmodule WaferDriverCircuitsGPIOTest do
test "closes the pin" do
conn = conn()
Driver
Wrapper
|> expect(:close, 1, fn ref ->
assert ref == conn.ref
:ok
@ -43,7 +43,7 @@ defmodule WaferDriverCircuitsGPIOTest do
test "can read the pin value" do
conn = conn()
Driver
Wrapper
|> expect(:read, 1, fn ref ->
assert ref == conn.ref
0
@ -57,7 +57,7 @@ defmodule WaferDriverCircuitsGPIOTest do
test "can set the pin value" do
conn = conn()
Driver
Wrapper
|> expect(:write, 1, fn ref, value ->
assert ref == conn.ref
assert value == 1
@ -70,7 +70,7 @@ defmodule WaferDriverCircuitsGPIOTest do
describe "GPIO.direction/2" do
test "when the direction isn't changing" do
Driver
Wrapper
|> reject(:set_direction, 2)
assert {:ok, %Subject{} = conn} = Subject.acquire(pin: 1, direction: :out)
@ -80,7 +80,7 @@ defmodule WaferDriverCircuitsGPIOTest do
test "when the direction is changing" do
assert {:ok, %Subject{} = conn} = Subject.acquire(pin: 1, direction: :out)
Driver
Wrapper
|> expect(:set_direction, 1, fn ref, direction ->
assert ref == conn.ref
assert direction == :input
@ -125,7 +125,7 @@ defmodule WaferDriverCircuitsGPIOTest do
test "sets the specified pull mode on the connection" do
conn = conn()
Driver
Wrapper
|> expect(:set_pull_mode, 1, fn ref, mode ->
assert ref == conn.ref
assert mode == :pull_up

View file

@ -1,9 +1,9 @@
defmodule WaferCircuitsI2CTest do
defmodule WaferCircuits.I2CTest do
use ExUnit.Case, async: true
use Mimic
alias Circuits.I2C, as: Driver
alias Wafer.Driver.Circuits.I2C.Wrapper
alias Wafer.Chip
alias Wafer.Driver.CircuitsI2C, as: Subject
alias Wafer.Driver.Circuits.I2C, as: Subject
alias Wafer.I2C
@moduledoc false
@ -13,7 +13,7 @@ defmodule WaferCircuitsI2CTest do
busname = "i2c-1"
address = 0x13
Driver
Wrapper
|> expect(:open, 1, fn bus ->
assert bus == busname
{:ok, busref}
@ -31,7 +31,7 @@ defmodule WaferCircuitsI2CTest do
busname = "i2c-1"
address = 0x13
Driver
Wrapper
|> expect(:open, 1, fn bus ->
assert bus == busname
{:ok, busref}
@ -49,7 +49,7 @@ defmodule WaferCircuitsI2CTest do
busname = "i2c-1"
address = 0x13
Driver
Wrapper
|> expect(:open, 1, fn bus ->
assert bus == busname
{:ok, busref}
@ -76,7 +76,7 @@ defmodule WaferCircuitsI2CTest do
test "closes the bus connection" do
conn = conn()
Driver
Wrapper
|> expect(:close, 1, fn ref ->
assert ref == conn.ref
:ok
@ -90,7 +90,7 @@ defmodule WaferCircuitsI2CTest do
test "reads from the device's register" do
conn = conn()
Driver
Wrapper
|> expect(:write_read, 1, fn ref, addr, data, bytes ->
assert ref == conn.ref
assert addr == conn.address
@ -107,7 +107,7 @@ defmodule WaferCircuitsI2CTest do
test "writes to the device's register" do
conn = conn()
Driver
Wrapper
|> expect(:write, 1, fn ref, addr, data ->
assert ref == conn.ref
assert addr == conn.address
@ -123,7 +123,7 @@ defmodule WaferCircuitsI2CTest do
test "swaps the device's register value for a new value, returning the old value" do
conn = conn()
Driver
Wrapper
|> expect(:write_read, 1, fn ref, addr, data, bytes ->
assert ref == conn.ref
assert addr == conn.address
@ -132,7 +132,7 @@ defmodule WaferCircuitsI2CTest do
{:ok, <<0, 0>>}
end)
Driver
Wrapper
|> expect(:write, 1, fn ref, addr, data ->
assert ref == conn.ref
assert addr == conn.address
@ -148,7 +148,7 @@ defmodule WaferCircuitsI2CTest do
test "reads from the device" do
conn = conn()
Driver
Wrapper
|> expect(:read, 1, fn ref, addr, bytes, opts ->
assert ref == conn.ref
assert addr == conn.address
@ -165,7 +165,7 @@ defmodule WaferCircuitsI2CTest do
test "it writes to the device" do
conn = conn()
Driver
Wrapper
|> expect(:write, 1, fn ref, addr, data, opts ->
assert ref == conn.ref
assert addr == conn.address
@ -182,7 +182,7 @@ defmodule WaferCircuitsI2CTest do
test "it writes to then reads from the device" do
conn = conn()
Driver
Wrapper
|> expect(:write_read, 1, fn ref, addr, data, bytes, opts ->
assert ref == conn.ref
assert addr == conn.address
@ -201,7 +201,7 @@ defmodule WaferCircuitsI2CTest do
test "it detects devices" do
conn = conn()
Driver
Wrapper
|> expect(:detect_devices, 1, fn ref ->
assert conn.ref == ref
[conn.address]

View file

@ -1,14 +1,14 @@
defmodule WaferCircuitsSPITest do
defmodule WaferCircuits.SPITest do
use ExUnit.Case, async: true
use Mimic
alias Circuits.SPI, as: Driver
alias Wafer.Driver.CircuitsSPI, as: Subject
alias Wafer.Driver.Circuits.SPI.Wrapper
alias Wafer.Driver.Circuits.SPI, as: Subject
alias Wafer.SPI
@moduledoc false
describe "acquire/1" do
test "opens the bus" do
Driver
Wrapper
|> expect(:open, 1, fn bus, opts ->
assert bus == "spidev0.0"
assert opts == []
@ -27,7 +27,7 @@ defmodule WaferCircuitsSPITest do
test "closes the bus connection" do
conn = conn()
Driver
Wrapper
|> expect(:close, 1, fn ref ->
assert ref == conn.ref
:ok
@ -41,7 +41,7 @@ defmodule WaferCircuitsSPITest do
test "transfers data to and from the bus" do
conn = conn()
Driver
Wrapper
|> expect(:transfer, 1, fn ref, data ->
assert ref == conn.ref
assert data == <<0, 0>>

View file

@ -1,7 +1,7 @@
defmodule WaferDriverElixirALEGPIODispatcherTest do
defmodule WaferDriverElixirALE.GPIO.DispatcherTest do
use ExUnit.Case, async: true
alias ElixirALE.GPIO, as: Driver
alias Wafer.Driver.ElixirALEGPIODispatcher, as: Dispatcher
alias Wafer.Driver.ElixirALE.GPIO.Wrapper
alias Wafer.Driver.ElixirALE.GPIO.Dispatcher, as: Dispatcher
alias Wafer.InterruptRegistry, as: IR
import Mimic
@moduledoc false
@ -10,7 +10,7 @@ defmodule WaferDriverElixirALEGPIODispatcherTest do
test "enabling rising interrupts" do
conn = conn()
Driver
Wrapper
|> expect(:set_int, 1, fn pid, pin_condition ->
assert pid == conn.pid
assert pin_condition == :rising
@ -26,7 +26,7 @@ defmodule WaferDriverElixirALEGPIODispatcherTest do
test "enabling falling interrupts" do
conn = conn()
Driver
Wrapper
|> expect(:set_int, 1, fn pid, pin_condition ->
assert pid == conn.pid
assert pin_condition == :falling
@ -42,7 +42,7 @@ defmodule WaferDriverElixirALEGPIODispatcherTest do
test "enabling both interrupts" do
conn = conn()
Driver
Wrapper
|> expect(:set_int, 1, fn pid, pin_condition ->
assert pid == conn.pid
assert pin_condition == :both
@ -58,7 +58,7 @@ defmodule WaferDriverElixirALEGPIODispatcherTest do
test "disabling rising interrupts" do
conn = conn()
Driver
Wrapper
|> stub(:set_int, fn _, _ -> :ok end)
Dispatcher.handle_call({:enable, conn, :rising, :metadata, self()}, nil, state())
@ -72,7 +72,7 @@ defmodule WaferDriverElixirALEGPIODispatcherTest do
test "disabling falling interrupts" do
conn = conn()
Driver
Wrapper
|> stub(:set_int, fn _, _ -> :ok end)
Dispatcher.handle_call({:enable, conn, :falling, :metadata, self()}, nil, state())
@ -86,7 +86,7 @@ defmodule WaferDriverElixirALEGPIODispatcherTest do
test "disabling both interrupts" do
conn = conn()
Driver
Wrapper
|> stub(:set_int, fn _, _ -> :ok end)
Dispatcher.handle_call({:enable, conn, :both, :metadata, self()}, nil, state())
@ -100,7 +100,7 @@ defmodule WaferDriverElixirALEGPIODispatcherTest do
describe "handle_info/2" do
test "publishing rising interrupts" do
Driver
Wrapper
|> stub(:set_int, fn _, _ -> :ok end)
{:reply, {:ok, conn}, state} =
@ -112,7 +112,7 @@ defmodule WaferDriverElixirALEGPIODispatcherTest do
end
test "publishing falling interrupts" do
Driver
Wrapper
|> stub(:set_int, fn _, _ -> :ok end)
{:reply, {:ok, conn}, state} =

View file

@ -1,15 +1,15 @@
defmodule WaferDriverElixirALEGPIOTest do
defmodule WaferDriverElixirALE.GPIOTest do
use ExUnit.Case, async: true
use Mimic
alias ElixirALE.GPIO, as: Driver
alias Wafer.Driver.ElixirALEGPIO, as: Subject
alias Wafer.Driver.ElixirALEGPIODispatcher, as: Dispatcher
alias Wafer.Driver.ElixirALE.GPIO.Wrapper
alias Wafer.Driver.ElixirALE.GPIO, as: Subject
alias Wafer.Driver.ElixirALE.GPIO.Dispatcher, as: Dispatcher
alias Wafer.GPIO, as: GPIO
@moduledoc false
describe "acquire/1" do
test "opens the pin and creates the conn" do
Driver
Wrapper
|> expect(:start_link, 1, fn pin, direction, opts ->
assert pin == 1
assert direction == :out
@ -29,7 +29,7 @@ defmodule WaferDriverElixirALEGPIOTest do
test "closes the pin" do
conn = conn()
Driver
Wrapper
|> expect(:release, 1, fn pid ->
assert pid == conn.pid
:ok
@ -43,7 +43,7 @@ defmodule WaferDriverElixirALEGPIOTest do
test "can read the pin value" do
conn = conn()
Driver
Wrapper
|> expect(:read, 1, fn pid ->
assert pid == conn.pid
0
@ -57,7 +57,7 @@ defmodule WaferDriverElixirALEGPIOTest do
test "can set the pin value" do
conn = conn()
Driver
Wrapper
|> expect(:write, 1, fn pid, value ->
assert pid == conn.pid
assert value == 1

View file

@ -1,9 +1,9 @@
defmodule WaferElixirALEI2CTest do
defmodule WaferElixirALE.I2CTest do
use ExUnit.Case, async: true
use Mimic
alias ElixirALE.I2C, as: Driver
alias Wafer.Driver.ElixirALE.I2C.Wrapper
alias Wafer.Chip
alias Wafer.Driver.ElixirALEI2C, as: Subject
alias Wafer.Driver.ElixirALE.I2C, as: Subject
alias Wafer.I2C
@moduledoc false
@ -13,7 +13,7 @@ defmodule WaferElixirALEI2CTest do
busname = "i2c-1"
address = 0x13
Driver
Wrapper
|> expect(:start_link, 1, fn bus, address ->
assert bus == busname
assert address == 0x13
@ -32,7 +32,7 @@ defmodule WaferElixirALEI2CTest do
busname = "i2c-1"
address = 0x13
Driver
Wrapper
|> expect(:start_link, 1, fn bus, address ->
assert bus == busname
assert address == 0x13
@ -51,7 +51,7 @@ defmodule WaferElixirALEI2CTest do
busname = "i2c-1"
address = 0x13
Driver
Wrapper
|> expect(:start_link, 1, fn bus, address ->
assert bus == busname
assert address == 0x13
@ -79,7 +79,7 @@ defmodule WaferElixirALEI2CTest do
test "closes the bus connection" do
conn = conn()
Driver
Wrapper
|> expect(:release, 1, fn pid ->
assert pid == conn.pid
:ok
@ -93,7 +93,7 @@ defmodule WaferElixirALEI2CTest do
test "reads from the device's register" do
conn = conn()
Driver
Wrapper
|> expect(:write_read, 1, fn pid, data, bytes ->
assert pid == conn.pid
assert data == <<0>>
@ -109,7 +109,7 @@ defmodule WaferElixirALEI2CTest do
test "writes to the device's register" do
conn = conn()
Driver
Wrapper
|> expect(:write, 1, fn pid, data ->
assert pid == conn.pid
assert data == <<1, 2, 3>>
@ -124,7 +124,7 @@ defmodule WaferElixirALEI2CTest do
test "swaps the device's register value for a new value, returning the old value" do
conn = conn()
Driver
Wrapper
|> expect(:write_read, 1, fn pid, data, bytes ->
assert pid == conn.pid
assert data == <<0>>
@ -132,7 +132,7 @@ defmodule WaferElixirALEI2CTest do
<<0, 0>>
end)
Driver
Wrapper
|> expect(:write, 1, fn pid, data ->
assert pid == conn.pid
assert data == <<0, 1, 1>>
@ -147,7 +147,7 @@ defmodule WaferElixirALEI2CTest do
test "reads from the device" do
conn = conn()
Driver
Wrapper
|> expect(:read, 1, fn pid, bytes ->
assert pid == conn.pid
assert bytes == 2
@ -162,7 +162,7 @@ defmodule WaferElixirALEI2CTest do
test "it writes to the device" do
conn = conn()
Driver
Wrapper
|> expect(:write, 1, fn pid, data ->
assert pid == conn.pid
assert data == <<0, 0>>
@ -177,7 +177,7 @@ defmodule WaferElixirALEI2CTest do
test "it writes to then reads from the device" do
conn = conn()
Driver
Wrapper
|> expect(:write_read, 1, fn pid, data, bytes ->
assert pid == conn.pid
assert data == <<1>>
@ -194,7 +194,7 @@ defmodule WaferElixirALEI2CTest do
test "it detects devices" do
conn = conn()
Driver
Wrapper
|> expect(:detect_devices, 1, fn pid ->
assert conn.pid == pid
[conn.address]

View file

@ -1,14 +1,14 @@
defmodule WaferElixirALESPITest do
defmodule WaferElixirALE.SPITest do
use ExUnit.Case, async: true
use Mimic
alias ElixirALE.SPI, as: Driver
alias Wafer.Driver.ElixirALESPI, as: Subject
alias Wafer.Driver.ElixirALE.SPI.Wrapper
alias Wafer.Driver.ElixirALE.SPI, as: Subject
alias Wafer.SPI
@moduledoc false
describe "acquire/1" do
test "opens the bus" do
Driver
Wrapper
|> expect(:start_link, 1, fn bus, spi_opts, opts ->
assert bus == "spidev0.0"
assert spi_opts == []
@ -28,7 +28,7 @@ defmodule WaferElixirALESPITest do
test "closes the bus connection" do
conn = conn()
Driver
Wrapper
|> expect(:release, 1, fn pid ->
assert pid == conn.pid
:ok
@ -42,7 +42,7 @@ defmodule WaferElixirALESPITest do
test "transfers data to and from the bus" do
conn = conn()
Driver
Wrapper
|> expect(:transfer, 1, fn pid, data ->
assert pid == conn.pid
assert data == <<0, 0>>

View file

@ -1,8 +1,8 @@
defmodule WaferGPIOTest do
use ExUnit.Case, async: true
alias Wafer.Driver.CircuitsGPIO, as: Driver
alias Wafer.Driver.Circuits.GPIO, as: Driver
alias Wafer.GPIO
alias Wafer.GPIO.Wafer.Driver.CircuitsGPIO, as: Impl
alias Wafer.GPIO.Wafer.Driver.Circuits.GPIO, as: Impl
import Mimic
Code.require_file("test/support/test_utils.exs")
@moduledoc false

View file

@ -1,8 +1,8 @@
defmodule WaferI2CTest do
use ExUnit.Case, async: true
alias Wafer.Driver.CircuitsI2C, as: Driver
alias Wafer.Driver.Circuits.I2C, as: Driver
alias Wafer.I2C
alias Wafer.I2C.Wafer.Driver.CircuitsI2C, as: Impl
alias Wafer.I2C.Wafer.Driver.Circuits.I2C, as: Impl
import Mimic
Code.require_file("test/support/test_utils.exs")
@moduledoc false

View file

@ -1,8 +1,8 @@
defmodule WaferSPITest do
use ExUnit.Case, async: true
alias Wafer.Driver.CircuitsSPI, as: Driver
alias Wafer.Driver.Circuits.SPI, as: Driver
alias Wafer.SPI
alias Wafer.SPI.Wafer.Driver.CircuitsSPI, as: Impl
alias Wafer.SPI.Wafer.Driver.Circuits.SPI, as: Impl
import Mimic
Code.require_file("test/support/test_utils.exs")
@moduledoc false

View file

@ -1,21 +0,0 @@
defmodule Circuits.GPIO do
import Wafer.Guards
@moduledoc false
def set_interrupts(ref, pin_condition, opts \\ [])
when is_reference(ref) and is_pin_condition(pin_condition) and is_list(opts),
do: :ok
def open(pin_number, pin_direction, options \\ [])
when is_pin_number(pin_number) and pin_direction in ~w[input output]a and is_list(options),
do: {:ok, :erlang.make_ref()}
def close(ref) when is_reference(ref), do: :ok
def read(ref) when is_reference(ref), do: 0
def write(ref, value) when is_reference(ref) and is_pin_value(value), do: :ok
def set_direction(ref, direction) when is_reference(ref) and is_pin_direction(direction),
do: :ok
def set_pull_mode(ref, mode) when is_reference(ref) and is_pin_pull_mode(mode), do: :ok
end

View file

@ -1,26 +0,0 @@
defmodule Circuits.I2C do
import Wafer.Guards
@moduledoc false
def read(ref, address, bytes, opts \\ [])
when is_reference(ref) and is_i2c_address(address) and is_byte_size(bytes) and is_list(opts) do
bits = bytes * 8
{:ok, <<0::unsigned-integer-size(bits)>>}
end
def write_read(ref, address, data, bytes, opts \\ [])
when is_reference(ref) and is_i2c_address(address) and is_binary(data) and
is_byte_size(bytes) and is_list(opts) do
bits = bytes * 8
{:ok, <<0::unsigned-integer-size(bits)>>}
end
def write(ref, address, data, opts \\ [])
when is_reference(ref) and is_i2c_address(address) and is_binary(data) and is_list(opts),
do: :ok
def open(name) when is_binary(name), do: {:ok, :erlang.make_ref()}
def close(ref) when is_reference(ref), do: :ok
def detect_devices(bus) when is_reference(bus) or is_binary(bus), do: []
end

View file

@ -1,13 +0,0 @@
defmodule Circuits.SPI do
@moduledoc false
def open(name, opts \\ [])
when is_binary(name) and is_list(opts),
do: {:ok, self()}
def close(ref) when is_reference(ref), do: :ok
def transfer(ref, data) when is_reference(ref) and is_binary(data) do
bits = bit_size(data)
{:ok, <<0::unsigned-integer-size(bits)>>}
end
end

View file

@ -1,15 +0,0 @@
defmodule ElixirALE.GPIO do
@moduledoc false
def set_int(pid, condition) when is_pid(pid) and condition in [:rising, :falling, :both],
do: :ok
def start_link(pin, direction, _opts \\ [])
when is_integer(pin) and pin >= 0 and direction in [:in, :out],
do: {:ok, self()}
def release(pid) when is_pid(pid), do: :ok
def read(pid) when is_pid(pid), do: 0
def write(pid, value) when is_pid(pid) and value in [0, 1], do: :ok
end

View file

@ -1,27 +0,0 @@
defmodule ElixirALE.I2C do
import Wafer.Guards
@moduledoc false
def read(pid, bytes, options \\ [])
when is_pid(pid) and is_byte_size(bytes) and is_list(options) do
bits = bytes * 8
<<0::unsigned-integer-size(bits)>>
end
def write(pid, data, options \\ []) when is_pid(pid) and is_binary(data) and is_list(options),
do: :ok
def write_read(pid, data, bytes, options \\ [])
when is_pid(pid) and is_binary(data) and is_byte_size(bytes) and is_list(options) do
bits = bytes * 8
<<0::unsigned-integer-size(bits)>>
end
def start_link(name, address, opts \\ [])
when is_binary(name) and is_i2c_address(address) and is_list(opts),
do: {:ok, self()}
def release(pid) when is_pid(pid), do: :ok
def detect_devices(bus) when is_binary(bus) or is_pid(bus), do: []
end

View file

@ -1,13 +0,0 @@
defmodule ElixirALE.SPI do
@moduledoc false
def start_link(name, spi_opts \\ [], opts \\ [])
when is_binary(name) and is_list(spi_opts) and is_list(opts),
do: {:ok, self()}
def release(pid) when is_pid(pid), do: :ok
def transfer(pid, data) when is_pid(pid) and is_binary(data) do
bits = bit_size(data)
<<0::unsigned-integer-size(bits)>>
end
end

View file

@ -1,10 +1,11 @@
Mimic.copy(Circuits.GPIO)
Mimic.copy(Circuits.I2C)
Mimic.copy(Circuits.SPI)
Mimic.copy(ElixirALE.GPIO)
Mimic.copy(ElixirALE.I2C)
Mimic.copy(ElixirALE.SPI)
Mimic.copy(Wafer.Chip)
Mimic.copy(Wafer.Driver.CircuitsGPIODispatcher)
Mimic.copy(Wafer.Driver.ElixirALEGPIODispatcher)
Mimic.copy(Wafer.Driver.Circuits.GPIO.Wrapper)
Mimic.copy(Wafer.Driver.Circuits.GPIO.Dispatcher)
Mimic.copy(Wafer.Driver.Circuits.I2C.Wrapper)
Mimic.copy(Wafer.Driver.Circuits.SPI.Wrapper)
Mimic.copy(Wafer.Driver.ElixirALE.GPIO.Wrapper)
Mimic.copy(Wafer.Driver.ElixirALE.GPIO.Dispatcher)
Mimic.copy(Wafer.Driver.ElixirALE.I2C.Wrapper)
Mimic.copy(Wafer.Driver.ElixirALE.SPI.Wrapper)
ExUnit.start()