Packages

Wafer is an Elixir library to make writing drivers for i2c and SPI connected peripherals and interacting with GPIO pins easier.

Current section

Files

Jump to
wafer lib wafer drivers elixir_ale spi.ex
Raw

lib/wafer/drivers/elixir_ale/spi.ex

defmodule Wafer.Driver.ElixirALE.SPI do
defstruct ~w[bus pid]a
@behaviour Wafer.Conn
alias Wafer.Driver.ElixirALE.SPI.Wrapper
@moduledoc """
A connection to a chip via ElixirALE's SPI driver.
Implements the `Wafer.Conn` behaviour as well as the `Wafer.SPI` protocol.
"""
@type t :: %__MODULE__{bus: binary, pid: pid}
@type options :: [option | driver_option]
@type option :: {:bus_name, binary}
# These options are passed unchanged to the underlying driver.
@type driver_option ::
{:mode, 0..3}
| {:bits_per_word, 0..16}
| {:speed_hz, pos_integer}
| {:delay_us, non_neg_integer}
@doc """
Acquire a connection to a peripheral using the ElixirALE' SPI driver on the
specified bus and address.
"""
@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, pid} when is_pid(pid) <-
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"}
{:error, reason} -> {:error, reason}
end
end
end
defimpl Wafer.Release, for: Wafer.Driver.ElixirALE.SPI do
alias Wafer.Driver.ElixirALE.SPI.Wrapper
alias Wafer.Driver.ElixirALE.SPI
@doc """
Close the SPI bus connection.
"""
@spec release(SPI.t()) :: :ok | {:error, reason :: any}
def release(%SPI{pid: pid} = _conn) when is_pid(pid), do: Wrapper.release(pid)
end
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 Wrapper.transfer(pid, data) do
read_data when is_binary(read_data) and byte_size(read_data) == byte_size(data) ->
{:ok, read_data, conn}
{:error, reason} ->
{:error, reason}
other ->
{:error, "Invalid response from driver: #{inspect(other)}"}
end
end
end
defimpl Wafer.DeviceID, for: Wafer.Driver.ElixirALE.SPI do
def id(%{bus: bus}), do: {Wafer.Driver.ElixirALE.SPI, bus}
end