Modify the API to be more sensible, and add test coverage.
This commit is contained in:
parent
37432189c4
commit
1342ba7952
56
.gitlab-ci.yml
Normal file
56
.gitlab-ci.yml
Normal file
|
@ -0,0 +1,56 @@
|
|||
image: elixir:latest
|
||||
|
||||
cache:
|
||||
key: "$CI_JOB_NAME"
|
||||
paths:
|
||||
- deps
|
||||
- _build
|
||||
- /root/.mix
|
||||
|
||||
variables:
|
||||
MIX_ENV: "test"
|
||||
|
||||
before_script:
|
||||
- mix local.hex --force
|
||||
- mix local.rebar --force
|
||||
- mix deps.get --only test
|
||||
|
||||
test:
|
||||
stage: test
|
||||
script:
|
||||
- mix test
|
||||
|
||||
credo:
|
||||
stage: test
|
||||
script:
|
||||
- mix credo
|
||||
|
||||
audit:
|
||||
stage: test
|
||||
script:
|
||||
- mix hex.audit
|
||||
|
||||
format:
|
||||
stage: test
|
||||
script:
|
||||
- mix format --check-formatted
|
||||
|
||||
pages:
|
||||
stage: deploy
|
||||
script:
|
||||
- mix docs -o public
|
||||
artifacts:
|
||||
paths:
|
||||
- public
|
||||
only:
|
||||
- master
|
||||
|
||||
package:
|
||||
stage: deploy
|
||||
only:
|
||||
- /^v[0-9]+\.[0-9]+\.[0-9]+$/
|
||||
script:
|
||||
- mix hex.build
|
||||
artifacts:
|
||||
paths:
|
||||
- "pca9641-*.tar"
|
461
lib/pca9641.ex
461
lib/pca9641.ex
|
@ -2,15 +2,33 @@ defmodule PCA9641 do
|
|||
@derive [Wafer.Chip, Wafer.DeviceID]
|
||||
defstruct ~w[conn int_pin state]a
|
||||
@behaviour Wafer.Conn
|
||||
alias Wafer.Conn
|
||||
alias PCA9641.Registers
|
||||
alias Wafer.Conn
|
||||
import Wafer.Twiddles
|
||||
|
||||
@moduledoc """
|
||||
PCA9641 Driver for Elixir using Wafer.
|
||||
|
||||
The PCA9641 I2C bus arbiter allows two I2C masters (eg Raspberry Pis) to be
|
||||
connected to the same downstream I2C bus. The chip decides which master has
|
||||
access to the bus based on it's own internal state machine.
|
||||
|
||||
The device also contains an interrupt input pin which can be used for
|
||||
downstream devices to signal interrupts and be passed to the two interrupt
|
||||
outputs connected to the two masters.
|
||||
|
||||
## Examples
|
||||
|
||||
Connecting to the device using Elixir Circuits.
|
||||
|
||||
iex> {:ok, i2c_conn} = Wafer.Driver.Circuits.I2C.acquire(bus_name: "i2c-1", address: 0x70)
|
||||
...> {:ok, int_conn} = Wafer.Driver.Circuits.GPIO.acquire(pin: 7, direction: :in)
|
||||
...> {:ok, conn} = PCA9641.acquire(conn: i2c_conn, int_pin: int_conn)
|
||||
|
||||
|
||||
"""
|
||||
|
||||
@interrupts %{
|
||||
@interrupts_fwd %{
|
||||
bus_hung: 6,
|
||||
mbox_full: 5,
|
||||
mbox_empty: 4,
|
||||
|
@ -19,6 +37,7 @@ defmodule PCA9641 do
|
|||
bus_lost: 1,
|
||||
int_in: 0
|
||||
}
|
||||
@interrupts_bkwd @interrupts_fwd |> Enum.map(fn {k, v} -> {v, k} end) |> Enum.into(%{})
|
||||
|
||||
@type interrupt_name ::
|
||||
:bus_hung | :mbox_full | :mbox_empty | :test_int | :lock_grant | :bus_lost | :int_in
|
||||
|
@ -54,9 +73,13 @@ defmodule PCA9641 do
|
|||
|
||||
It should match the expected value of `#{@pca9641_id}`.
|
||||
"""
|
||||
@spec verify_identify(t) :: {:ok, t} | {:error, reason :: any}
|
||||
def verify_identify(%PCA9641{conn: conn}) do
|
||||
with {:ok, <<@pca9641_id>>} <- Registers.read_id(conn), do: {:ok, conn}
|
||||
@spec verify_identity(t) :: {:ok, t} | {:error, reason :: any}
|
||||
def verify_identity(%PCA9641{conn: conn}) do
|
||||
case Registers.read_id(conn) do
|
||||
{:ok, <<@pca9641_id>>} -> {:ok, conn}
|
||||
{:ok, <<id>>} -> {:error, "Found incorrect ID #{inspect(id)}"}
|
||||
{:error, reason} -> {:error, reason}
|
||||
end
|
||||
end
|
||||
|
||||
@doc """
|
||||
|
@ -65,8 +88,8 @@ defmodule PCA9641 do
|
|||
@spec request_downstream_bus(t) :: {:ok, t} | {:error, reason :: any}
|
||||
def request_downstream_bus(%PCA9641{conn: conn} = dev) do
|
||||
with {:ok, conn} <- Registers.write_control(conn, 0x1),
|
||||
{:ok, conn} <- wait_for_bus_init(conn) do
|
||||
{:ok, %{dev | conn: conn}}
|
||||
{:ok, dev} <- wait_for_bus_init(%{dev | conn: conn}) do
|
||||
{:ok, dev}
|
||||
end
|
||||
end
|
||||
|
||||
|
@ -78,8 +101,8 @@ defmodule PCA9641 do
|
|||
"""
|
||||
@spec priority?(t) :: boolean
|
||||
def priority?(conn) do
|
||||
with {:ok, conn} <- Registers.read_control(conn),
|
||||
true <- get_bool(conn, 7),
|
||||
with {:ok, data} <- Registers.read_control(conn),
|
||||
true <- get_bool(data, 7),
|
||||
do: true,
|
||||
else: (_ -> false)
|
||||
end
|
||||
|
@ -91,8 +114,8 @@ defmodule PCA9641 do
|
|||
masters request the downstream bus at the same time.
|
||||
"""
|
||||
@spec priority(t, boolean) :: {:ok, t} | {:error, reason :: any}
|
||||
def priority(%PCA9641{conn: conn} = dev, true) do
|
||||
with {:ok, conn} <- Registers.update_control(conn, &set_bit(&1, 7)),
|
||||
def priority(%PCA9641{conn: conn} = dev, value) do
|
||||
with {:ok, conn} <- Registers.update_control(conn, &set_bit(&1, 7, value)),
|
||||
do: {:ok, %{dev | conn: conn}}
|
||||
end
|
||||
|
||||
|
@ -108,8 +131,8 @@ defmodule PCA9641 do
|
|||
"""
|
||||
@spec downstream_disconnect_on_timeout?(t) :: boolean
|
||||
def downstream_disconnect_on_timeout?(%PCA9641{conn: conn}) do
|
||||
with {:ok, conn} <- Registers.read_control(conn),
|
||||
true <- get_bool(conn, 6),
|
||||
with {:ok, data} <- Registers.read_control(conn),
|
||||
true <- get_bool(data, 6),
|
||||
do: true,
|
||||
else: (_ -> false)
|
||||
end
|
||||
|
@ -145,8 +168,8 @@ defmodule PCA9641 do
|
|||
"""
|
||||
@spec idle_timer_disconnect?(t) :: boolean
|
||||
def idle_timer_disconnect?(%PCA9641{conn: conn}) do
|
||||
with {:ok, conn} <- Registers.read_control(conn),
|
||||
true <- get_bool(conn, 5),
|
||||
with {:ok, data} <- Registers.read_control(conn),
|
||||
true <- get_bool(data, 5),
|
||||
do: true,
|
||||
else: (_ -> false)
|
||||
end
|
||||
|
@ -182,8 +205,8 @@ defmodule PCA9641 do
|
|||
"""
|
||||
@spec smbus_software_reset?(t) :: boolean
|
||||
def smbus_software_reset?(%PCA9641{conn: conn}) do
|
||||
with {:ok, conn} <- Registers.read_control(conn),
|
||||
true <- get_bool(conn, 4),
|
||||
with {:ok, data} <- Registers.read_control(conn),
|
||||
true <- get_bool(data, 4),
|
||||
do: true,
|
||||
else: (_ -> false)
|
||||
end
|
||||
|
@ -219,8 +242,8 @@ defmodule PCA9641 do
|
|||
"""
|
||||
@spec bus_init?(t) :: boolean
|
||||
def bus_init?(%PCA9641{conn: conn}) do
|
||||
with {:ok, conn} <- Registers.read_control(conn),
|
||||
true <- get_bool(conn, 3),
|
||||
with {:ok, data} <- Registers.read_control(conn),
|
||||
true <- get_bool(data, 3),
|
||||
do: true,
|
||||
else: (_ -> false)
|
||||
end
|
||||
|
@ -255,8 +278,8 @@ defmodule PCA9641 do
|
|||
"""
|
||||
@spec bus_connect?(t) :: boolean
|
||||
def bus_connect?(%PCA9641{conn: conn}) do
|
||||
with {:ok, conn} <- Registers.read_control(conn),
|
||||
true <- get_bool(conn, 2),
|
||||
with {:ok, data} <- Registers.read_control(conn),
|
||||
true <- get_bool(data, 2),
|
||||
do: true,
|
||||
else: (_ -> false)
|
||||
end
|
||||
|
@ -289,8 +312,8 @@ defmodule PCA9641 do
|
|||
"""
|
||||
@spec lock_grant?(t) :: boolean
|
||||
def lock_grant?(%PCA9641{conn: conn}) do
|
||||
with {:ok, conn} <- Registers.read_control(conn),
|
||||
true <- get_bool(conn, 1),
|
||||
with {:ok, data} <- Registers.read_control(conn),
|
||||
true <- get_bool(data, 1),
|
||||
do: true,
|
||||
else: (_ -> false)
|
||||
end
|
||||
|
@ -310,8 +333,8 @@ defmodule PCA9641 do
|
|||
"""
|
||||
@spec lock_request?(t) :: boolean
|
||||
def lock_request?(%PCA9641{conn: conn}) do
|
||||
with {:ok, conn} <- Registers.read_control(conn),
|
||||
true <- get_bool(conn, 0),
|
||||
with {:ok, data} <- Registers.read_control(conn),
|
||||
true <- get_bool(data, 0),
|
||||
do: true,
|
||||
else: (_ -> false)
|
||||
end
|
||||
|
@ -352,8 +375,8 @@ defmodule PCA9641 do
|
|||
"""
|
||||
@spec sda_becomes_io?(t) :: boolean
|
||||
def sda_becomes_io?(%PCA9641{conn: conn}) do
|
||||
with {:ok, conn} <- Registers.read_status(conn),
|
||||
true <- get_bool(conn, 7),
|
||||
with {:ok, data} <- Registers.read_status(conn),
|
||||
true <- get_bool(data, 7),
|
||||
do: true,
|
||||
else: (_ -> false)
|
||||
end
|
||||
|
@ -396,8 +419,8 @@ defmodule PCA9641 do
|
|||
"""
|
||||
@spec scl_becomes_io?(t) :: boolean
|
||||
def scl_becomes_io?(%PCA9641{conn: conn}) do
|
||||
with {:ok, conn} <- Registers.read_status(conn),
|
||||
true <- get_bool(conn, 6),
|
||||
with {:ok, data} <- Registers.read_status(conn),
|
||||
true <- get_bool(data, 6),
|
||||
do: true,
|
||||
else: (_ -> false)
|
||||
end
|
||||
|
@ -431,6 +454,27 @@ defmodule PCA9641 do
|
|||
clear this interrupt, master must write ‘1’ to TEST_INT_INT in Interrupt
|
||||
Status register.
|
||||
|
||||
- `false` -> Normal operation.
|
||||
- `true` -> Causes PCA9641 INT pin to go LOW if not masked by TEST_INT_INT in
|
||||
Interrupt Mask register. Allows this master to invoke its Interrupt Service
|
||||
Routine to handle housekeeping tasks.
|
||||
"""
|
||||
@spec test_interrupt_pin?(t) :: boolean
|
||||
def test_interrupt_pin?(%PCA9641{conn: conn}) do
|
||||
with {:ok, data} <- Registers.read_status(conn),
|
||||
true <- get_bool(data, 5),
|
||||
do: true,
|
||||
else: (_ -> false)
|
||||
end
|
||||
|
||||
@doc """
|
||||
TEST_INT
|
||||
|
||||
Test interrupt output pin; a master can send an interrupt to itself by writing
|
||||
‘1’ to this register bit. Writing ‘0’ to this register bit has no effect. To
|
||||
clear this interrupt, master must write ‘1’ to TEST_INT_INT in Interrupt
|
||||
Status register.
|
||||
|
||||
- `false` -> Normal operation.
|
||||
- `true` -> Causes PCA9641 INT pin to go LOW if not masked by TEST_INT_INT in
|
||||
Interrupt Mask register. Allows this master to invoke its Interrupt Service
|
||||
|
@ -454,8 +498,8 @@ defmodule PCA9641 do
|
|||
"""
|
||||
@spec mailbox_full?(t) :: boolean
|
||||
def mailbox_full?(%PCA9641{conn: conn}) do
|
||||
with {:ok, conn} <- Registers.read_status(conn),
|
||||
true <- get_bool(conn, 4),
|
||||
with {:ok, data} <- Registers.read_status(conn),
|
||||
true <- get_bool(data, 4),
|
||||
do: true,
|
||||
else: (_ -> false)
|
||||
end
|
||||
|
@ -475,8 +519,8 @@ defmodule PCA9641 do
|
|||
"""
|
||||
@spec mailbox_empty?(t) :: boolean
|
||||
def mailbox_empty?(%PCA9641{conn: conn}) do
|
||||
with {:ok, conn} <- Registers.read_status(conn),
|
||||
true <- get_bool(conn, 3),
|
||||
with {:ok, data} <- Registers.read_status(conn),
|
||||
true <- get_bool(data, 3),
|
||||
do: true,
|
||||
else: (_ -> false)
|
||||
end
|
||||
|
@ -495,8 +539,8 @@ defmodule PCA9641 do
|
|||
"""
|
||||
@spec bus_hung?(t) :: boolean
|
||||
def bus_hung?(%PCA9641{conn: conn}) do
|
||||
with {:ok, conn} <- Registers.read_status(conn),
|
||||
true <- get_bool(conn, 2),
|
||||
with {:ok, data} <- Registers.read_status(conn),
|
||||
true <- get_bool(data, 2),
|
||||
do: true,
|
||||
else: (_ -> false)
|
||||
end
|
||||
|
@ -515,8 +559,8 @@ defmodule PCA9641 do
|
|||
"""
|
||||
@spec bus_initialisation_failed?(t) :: boolean
|
||||
def bus_initialisation_failed?(%PCA9641{conn: conn}) do
|
||||
with {:ok, conn} <- Registers.read_status(conn),
|
||||
true <- get_bool(conn, 1),
|
||||
with {:ok, data} <- Registers.read_status(conn),
|
||||
true <- get_bool(data, 1),
|
||||
do: true,
|
||||
else: (_ -> false)
|
||||
end
|
||||
|
@ -534,8 +578,8 @@ defmodule PCA9641 do
|
|||
"""
|
||||
@spec other_lock?(t) :: boolean
|
||||
def other_lock?(%PCA9641{conn: conn}) do
|
||||
with {:ok, conn} <- Registers.read_status(conn),
|
||||
true <- get_bool(conn, 0),
|
||||
with {:ok, data} <- Registers.read_status(conn),
|
||||
true <- get_bool(data, 0),
|
||||
do: true,
|
||||
else: (_ -> false)
|
||||
end
|
||||
|
@ -575,7 +619,7 @@ defmodule PCA9641 do
|
|||
def interrupt_reason(%PCA9641{conn: conn}) do
|
||||
with {:ok, <<value>>} <- Registers.read_interrupt_status(conn) do
|
||||
reasons =
|
||||
@interrupts
|
||||
@interrupts_fwd
|
||||
|> Enum.reduce([], fn {name, idx}, interrupts ->
|
||||
if get_bit(value, idx) == 1,
|
||||
do: [name | interrupts],
|
||||
|
@ -587,11 +631,26 @@ defmodule PCA9641 do
|
|||
end
|
||||
|
||||
@doc """
|
||||
Clears the interrupt status register.
|
||||
Clear specific interrupts from the interrupt status register
|
||||
"""
|
||||
@spec interrupt_clear(t) :: {:ok, t} | {:error, term}
|
||||
def interrupt_clear(%PCA9641{conn: conn} = dev) do
|
||||
with {:ok, conn} <- Registers.write_interrupt_status(conn, 0x7F),
|
||||
@spec interrupt_clear(t, :all | [interrupt_name()]) :: {:ok, t} | {:error, term}
|
||||
def interrupt_clear(%PCA9641{conn: conn} = dev, :all) do
|
||||
with {:ok, conn} <- Registers.write_interrupt_status(conn, <<0x7F>>),
|
||||
do: {:ok, %{dev | conn: conn}}
|
||||
end
|
||||
|
||||
def interrupt_clear(%PCA9641{conn: conn} = dev, interrupt_names)
|
||||
when is_list(interrupt_names) do
|
||||
clear_mask =
|
||||
interrupt_names
|
||||
|> Enum.reduce(<<0>>, fn name, mask ->
|
||||
case Map.fetch(@interrupts_fwd, name) do
|
||||
{:ok, i} -> set_bit(mask, i)
|
||||
_ -> mask
|
||||
end
|
||||
end)
|
||||
|
||||
with {:ok, conn} <- Registers.write_interrupt_status(conn, clear_mask),
|
||||
do: {:ok, %{dev | conn: conn}}
|
||||
end
|
||||
|
||||
|
@ -600,23 +659,45 @@ defmodule PCA9641 do
|
|||
"""
|
||||
@spec interrupt_enable(t, :all | :none | [interrupt_name()]) :: {:ok, t} | {:error, term}
|
||||
def interrupt_enable(%PCA9641{conn: conn} = dev, :all) do
|
||||
with {:ok, conn} <- Registers.write_interrupt_mask(conn, 0), do: {:ok, %{dev | conn: conn}}
|
||||
with {:ok, conn} <- Registers.write_interrupt_mask(conn, <<0>>),
|
||||
do: {:ok, %{dev | conn: conn}}
|
||||
end
|
||||
|
||||
def interrupt_enable(%PCA9641{conn: conn} = dev, :none) do
|
||||
with {:ok, conn} <- Registers.write_interrupt_mask(conn, 0x7F), do: {:ok, %{dev | conn: conn}}
|
||||
with {:ok, conn} <- Registers.write_interrupt_mask(conn, <<0x7F>>),
|
||||
do: {:ok, %{dev | conn: conn}}
|
||||
end
|
||||
|
||||
def interrupt_enable(%PCA9641{conn: conn} = dev, interrupts) do
|
||||
mask =
|
||||
@interrupts
|
||||
|> Enum.reduce(0x7F, fn {name, idx}, result ->
|
||||
if Enum.member?(interrupts, name),
|
||||
do: clear_bit(result, idx),
|
||||
else: result
|
||||
end)
|
||||
with {:ok, conn} <-
|
||||
Registers.update_interrupt_mask(conn, fn data ->
|
||||
interrupts
|
||||
|> Enum.reduce(data, fn interrupt_name, data ->
|
||||
bit = Map.fetch!(@interrupts_fwd, interrupt_name)
|
||||
clear_bit(data, bit)
|
||||
end)
|
||||
end),
|
||||
do: {:ok, %{dev | conn: conn}}
|
||||
end
|
||||
|
||||
with {:ok, conn} <- Registers.write_interrupt_mask(conn, mask), do: {:ok, %{dev | conn: conn}}
|
||||
@doc """
|
||||
Returns a list of atoms containing the
|
||||
"""
|
||||
@spec interrupt_enabled(t) :: {:ok, [interrupt_name()]} | {:error, term}
|
||||
def interrupt_enabled(%PCA9641{conn: conn}) do
|
||||
with {:ok, data} <- Registers.read_interrupt_mask(conn) do
|
||||
interrupts =
|
||||
data
|
||||
|> find_zeroes()
|
||||
|> Enum.reduce([], fn i, interrupts ->
|
||||
case Map.fetch(@interrupts_bkwd, i) do
|
||||
{:ok, name} -> [name | interrupts]
|
||||
_ -> interrupts
|
||||
end
|
||||
end)
|
||||
|
||||
{:ok, interrupts}
|
||||
end
|
||||
end
|
||||
|
||||
@doc """
|
||||
|
@ -632,29 +713,12 @@ defmodule PCA9641 do
|
|||
"""
|
||||
@spec bus_hung_interrupt?(t) :: boolean
|
||||
def bus_hung_interrupt?(%PCA9641{conn: conn}) do
|
||||
with {:ok, conn} <- Registers.read_interrupt_status(conn),
|
||||
true <- get_bool(conn, 6),
|
||||
with {:ok, data} <- Registers.read_interrupt_status(conn),
|
||||
true <- get_bool(data, 6),
|
||||
do: true,
|
||||
else: (_ -> false)
|
||||
end
|
||||
|
||||
@doc """
|
||||
BUS_HUNG_INT
|
||||
|
||||
Indicates to both masters that SDA signal is LOW and SCL signal does not
|
||||
toggle for more than 500 ms or SCL is LOW for 500 ms.
|
||||
|
||||
- `false` -> No interrupt generated; normal operation.
|
||||
- `true` -> Interrupt generated; downstream bus cannot recover; when SDA
|
||||
signal is LOW and SCL signal does not toggle for more than 500 ms or SCL is
|
||||
LOW for 500 ms,
|
||||
"""
|
||||
@spec bus_hung_interrupt(t, boolean) :: {:ok, t} | {:error, term}
|
||||
def bus_hung_interrupt(%PCA9641{conn: conn} = dev, value) when is_boolean(value) do
|
||||
with {:ok, conn} <- Registers.update_interrupt_status(conn, &set_bit(&1, 6, value)),
|
||||
do: {:ok, %{dev | conn: conn}}
|
||||
end
|
||||
|
||||
@doc """
|
||||
MBOX_FULL_INT
|
||||
|
||||
|
@ -665,26 +729,12 @@ defmodule PCA9641 do
|
|||
"""
|
||||
@spec mailbox_full_interrupt?(t) :: boolean
|
||||
def mailbox_full_interrupt?(%PCA9641{conn: conn}) do
|
||||
with {:ok, conn} <- Registers.read_interrupt_status(conn),
|
||||
true <- get_bool(conn, 5),
|
||||
with {:ok, data} <- Registers.read_interrupt_status(conn),
|
||||
true <- get_bool(data, 5),
|
||||
do: true,
|
||||
else: (_ -> false)
|
||||
end
|
||||
|
||||
@doc """
|
||||
MBOX_FULL_INT
|
||||
|
||||
Indicates the mailbox has new mail.
|
||||
|
||||
- `false` -> No interrupt generated; mailbox is not full.
|
||||
- `true` -> Interrupt generated; mailbox full.
|
||||
"""
|
||||
@spec mailbox_full_interrupt(t, boolean) :: {:ok, t} | {:error, term}
|
||||
def mailbox_full_interrupt(%PCA9641{conn: conn} = dev, value) when is_boolean(value) do
|
||||
with {:ok, conn} <- Registers.update_interrupt_status(conn, &set_bit(&1, 5, value)),
|
||||
do: {:ok, %{dev | conn: conn}}
|
||||
end
|
||||
|
||||
@doc """
|
||||
MBOX_EMPTY_INT
|
||||
|
||||
|
@ -695,26 +745,12 @@ defmodule PCA9641 do
|
|||
"""
|
||||
@spec mailbox_empty_interrupt?(t) :: boolean
|
||||
def mailbox_empty_interrupt?(%PCA9641{conn: conn}) do
|
||||
with {:ok, conn} <- Registers.read_interrupt_status(conn),
|
||||
true <- get_bool(conn, 4),
|
||||
with {:ok, data} <- Registers.read_interrupt_status(conn),
|
||||
true <- get_bool(data, 4),
|
||||
do: true,
|
||||
else: (_ -> false)
|
||||
end
|
||||
|
||||
@doc """
|
||||
MBOX_EMPTY_INT
|
||||
|
||||
Indicates the sent mail is empty, other master has read the mail.
|
||||
|
||||
- `false` -> No interrupt generated; sent mail is not empty.
|
||||
- `true` -> Interrupt generated; mailbox is empty.
|
||||
"""
|
||||
@spec mailbox_empty_interrupt(t, boolean) :: {:ok, t} | {:error, term}
|
||||
def mailbox_empty_interrupt(%PCA9641{conn: conn} = dev, value) when is_boolean(value) do
|
||||
with {:ok, conn} <- Registers.update_interrupt_status(conn, &set_bit(&1, 4, value)),
|
||||
do: {:ok, %{dev | conn: conn}}
|
||||
end
|
||||
|
||||
@doc """
|
||||
TEST_INT_INT
|
||||
|
||||
|
@ -727,28 +763,12 @@ defmodule PCA9641 do
|
|||
"""
|
||||
@spec test_interrupt_pin_interrupt?(t) :: boolean
|
||||
def test_interrupt_pin_interrupt?(%PCA9641{conn: conn}) do
|
||||
with {:ok, conn} <- Registers.read_interrupt_status(conn),
|
||||
true <- get_bool(conn, 3),
|
||||
with {:ok, data} <- Registers.read_interrupt_status(conn),
|
||||
true <- get_bool(data, 3),
|
||||
do: true,
|
||||
else: (_ -> false)
|
||||
end
|
||||
|
||||
@doc """
|
||||
TEST_INT_INT
|
||||
|
||||
Indicates this master has sent an interrupt to itself.
|
||||
|
||||
- `false` -> No interrupt generated; master has not set the TEST_INT bit in
|
||||
STATUS register.
|
||||
- `true` -> Interrupt generated; master activates its interrupt pin via the
|
||||
TEST_INT bit in STATUS register.
|
||||
"""
|
||||
@spec test_interrupt_pin_interrupt(t, true) :: {:ok, t} | {:error, term}
|
||||
def test_interrupt_pin_interrupt(%PCA9641{conn: conn} = dev, value) when is_boolean(value) do
|
||||
with {:ok, conn} <- Registers.update_interrupt_status(conn, &set_bit(&1, 3, value)),
|
||||
do: {:ok, %{dev | conn: conn}}
|
||||
end
|
||||
|
||||
@doc """
|
||||
LOCK_GRANT_INT
|
||||
|
||||
|
@ -760,27 +780,12 @@ defmodule PCA9641 do
|
|||
"""
|
||||
@spec lock_grant_interrupt?(pid) :: boolean
|
||||
def lock_grant_interrupt?(%PCA9641{conn: conn}) do
|
||||
with {:ok, conn} <- Registers.read_interrupt_status(conn),
|
||||
true <- get_bool(conn, 2),
|
||||
with {:ok, data} <- Registers.read_interrupt_status(conn),
|
||||
true <- get_bool(data, 2),
|
||||
do: true,
|
||||
else: (_ -> false)
|
||||
end
|
||||
|
||||
@doc """
|
||||
LOCK_GRANT_INT
|
||||
|
||||
Indicates the master has a lock (ownership) on the downstream bus.
|
||||
|
||||
- `false` -> No interrupt generated; this master does not have a lock on the
|
||||
downstream bus.
|
||||
- `true` -> Interrupt generated; this master has a lock on the downstream bus.
|
||||
"""
|
||||
@spec lock_grant_interrupt(t, boolean) :: {:ok, t} | {:error, term}
|
||||
def lock_grant_interrupt(%PCA9641{conn: conn} = dev, value) when is_boolean(value) do
|
||||
with {:ok, conn} <- Registers.update_interrupt_status(conn, &set_bit(&1, 2, value)),
|
||||
do: {:ok, %{dev | conn: conn}}
|
||||
end
|
||||
|
||||
@doc """
|
||||
BUS_LOST_INT
|
||||
|
||||
|
@ -794,29 +799,12 @@ defmodule PCA9641 do
|
|||
"""
|
||||
@spec bus_lost_interrupt?(t) :: boolean
|
||||
def bus_lost_interrupt?(%PCA9641{conn: conn}) do
|
||||
with {:ok, conn} <- Registers.read_interrupt_status(conn),
|
||||
true <- get_bool(conn, 1),
|
||||
with {:ok, data} <- Registers.read_interrupt_status(conn),
|
||||
true <- get_bool(data, 1),
|
||||
do: true,
|
||||
else: (_ -> false)
|
||||
end
|
||||
|
||||
@doc """
|
||||
BUS_LOST_INT
|
||||
|
||||
Indicates the master has involuntarily lost the ownership of the downstream
|
||||
bus.
|
||||
|
||||
- `false` -> No interrupt generated; this master is controlling the downstream
|
||||
bus.
|
||||
- `true` -> Interrupt generated; this master has involuntarily lost the
|
||||
control of the downstream bus.
|
||||
"""
|
||||
@spec bus_lost_interrupt(t, boolean) :: {:ok, t} | {:error, term}
|
||||
def bus_lost_interrupt(%PCA9641{conn: conn} = dev, value) when is_boolean(value) do
|
||||
with {:ok, conn} <- Registers.update_interrupt_status(conn, &set_bit(&1, 1, value)),
|
||||
do: {:ok, %{dev | conn: conn}}
|
||||
end
|
||||
|
||||
@doc """
|
||||
INT_IN_INT
|
||||
|
||||
|
@ -828,37 +816,22 @@ defmodule PCA9641 do
|
|||
"""
|
||||
@spec interupt_in_interrupt?(t) :: boolean
|
||||
def interupt_in_interrupt?(%PCA9641{conn: conn}) do
|
||||
with {:ok, conn} <- Registers.read_interrupt_status(conn),
|
||||
true <- get_bool(conn, 0),
|
||||
with {:ok, data} <- Registers.read_interrupt_status(conn),
|
||||
true <- get_bool(data, 0),
|
||||
do: true,
|
||||
else: (_ -> false)
|
||||
end
|
||||
|
||||
@doc """
|
||||
INT_IN_INT
|
||||
|
||||
Indicates that there is an interrupt from the downstream bus to both the
|
||||
granted and non-granted masters.
|
||||
|
||||
- `false` -> No interrupt on interrupt input pin INT_IN.
|
||||
- `true` -> Interrupt on interrupt input pin INT_IN.
|
||||
"""
|
||||
@spec interupt_in_interrupt(pid, boolean) :: {:ok, t} | {:error, term}
|
||||
def interupt_in_interrupt(%PCA9641{conn: conn} = dev, value) when is_boolean(value) do
|
||||
with {:ok, conn} <- Registers.update_interrupt_status(conn, &set_bit(&1, 0, value)),
|
||||
do: {:ok, %{dev | conn: conn}}
|
||||
end
|
||||
|
||||
@doc """
|
||||
BUS_HUNG_MSK
|
||||
|
||||
- `false` -> Enable output interrupt when BUS_HUNG function is set.
|
||||
- `true` -> Disable output interrupt when BUS_HUNG function is set.
|
||||
"""
|
||||
@spec bus_hung_mask?(t) :: boolean
|
||||
def bus_hung_mask?(%PCA9641{conn: conn}) do
|
||||
with {:ok, conn} <- Registers.read_interrupt_mask(conn),
|
||||
true <- get_bool(conn, 6),
|
||||
@spec bus_hung_interrupt_enabled?(t) :: boolean
|
||||
def bus_hung_interrupt_enabled?(%PCA9641{conn: conn}) do
|
||||
with {:ok, data} <- Registers.read_interrupt_mask(conn),
|
||||
false <- get_bool(data, 6),
|
||||
do: true,
|
||||
else: (_ -> false)
|
||||
end
|
||||
|
@ -869,36 +842,10 @@ defmodule PCA9641 do
|
|||
- `false` -> Enable output interrupt when MBOX_FULL function is set.
|
||||
- `true` -> Disable output interrupt when MBOX_FULL function is set.
|
||||
"""
|
||||
@spec mailbox_full_mask?(t) :: boolean
|
||||
def mailbox_full_mask?(%PCA9641{conn: conn}) do
|
||||
with {:ok, conn} <- Registers.read_interrupt_mask(conn),
|
||||
true <- get_bool(conn, 5),
|
||||
do: true,
|
||||
else: (_ -> false)
|
||||
end
|
||||
|
||||
@doc """
|
||||
MBOX_FULL_MSK
|
||||
|
||||
- `false` -> Enable output interrupt when MBOX_FULL function is set.
|
||||
- `true` -> Disable output interrupt when MBOX_FULL function is set.
|
||||
"""
|
||||
@spec mailbox_full_mask(pid, boolean) :: {:ok, t} | {:error, term}
|
||||
def mailbox_full_mask(%PCA9641{conn: conn} = dev, value) when is_boolean(value) do
|
||||
with {:ok, conn} <- Registers.update_interrupt_mask(conn, &set_bit(&1, 5, value)),
|
||||
do: {:ok, %{dev | conn: conn}}
|
||||
end
|
||||
|
||||
@doc """
|
||||
MBOX_EMPTY_MSK
|
||||
|
||||
- `false` -> Enable output interrupt when MBOX_EMPTY function is set.
|
||||
- `true` -> Disable output interrupt when MBOX_EMPTY function is set.
|
||||
"""
|
||||
@spec mailbox_empty_mask?(t) :: boolean
|
||||
def mailbox_empty_mask?(%PCA9641{conn: conn}) do
|
||||
with {:ok, conn} <- Registers.read_interrupt_mask(conn),
|
||||
true <- get_bool(conn, 4),
|
||||
@spec mailbox_full_interrupt_enabled?(t) :: boolean
|
||||
def mailbox_full_interrupt_enabled?(%PCA9641{conn: conn}) do
|
||||
with {:ok, data} <- Registers.read_interrupt_mask(conn),
|
||||
false <- get_bool(data, 5),
|
||||
do: true,
|
||||
else: (_ -> false)
|
||||
end
|
||||
|
@ -909,22 +856,10 @@ defmodule PCA9641 do
|
|||
- `false` -> Enable output interrupt when MBOX_EMPTY function is set.
|
||||
- `true` -> Disable output interrupt when MBOX_EMPTY function is set.
|
||||
"""
|
||||
@spec mailbox_empty_mask(t, boolean) :: {:ok, t} | {:error, term}
|
||||
def mailbox_empty_mask(%PCA9641{conn: conn} = dev, value) when is_boolean(value) do
|
||||
with {:ok, conn} <- Registers.update_interrupt_mask(conn, &set_bit(&1, 4, value)),
|
||||
do: {:ok, %{dev | conn: conn}}
|
||||
end
|
||||
|
||||
@doc """
|
||||
TEST_INT_MSK
|
||||
|
||||
- `false` -> Enable output interrupt when TEST_INT function is set.
|
||||
- `true` -> Disable output interrupt when TEST_INT function is set.
|
||||
"""
|
||||
@spec test_interrupt_mask?(t) :: boolean
|
||||
def test_interrupt_mask?(%PCA9641{conn: conn}) do
|
||||
with {:ok, conn} <- Registers.read_interrupt_mask(conn),
|
||||
true <- get_bool(conn, 3),
|
||||
@spec mailbox_empty_interrupt_enabled?(t) :: boolean
|
||||
def mailbox_empty_interrupt_enabled?(%PCA9641{conn: conn}) do
|
||||
with {:ok, data} <- Registers.read_interrupt_mask(conn),
|
||||
false <- get_bool(data, 4),
|
||||
do: true,
|
||||
else: (_ -> false)
|
||||
end
|
||||
|
@ -935,22 +870,10 @@ defmodule PCA9641 do
|
|||
- `false` -> Enable output interrupt when TEST_INT function is set.
|
||||
- `true` -> Disable output interrupt when TEST_INT function is set.
|
||||
"""
|
||||
@spec test_interrupt_mask(t, boolean) :: {:ok, t} | {:error, term}
|
||||
def test_interrupt_mask(%PCA9641{conn: conn} = dev, value) when is_boolean(value) do
|
||||
with {:ok, conn} <- Registers.update_interrupt_mask(conn, &set_bit(&1, 3, value)),
|
||||
do: {:ok, %{dev | conn: conn}}
|
||||
end
|
||||
|
||||
@doc """
|
||||
LOCK_GRANT_MSK
|
||||
|
||||
- `false` -> Enable output interrupt when LOCK_GRANT function is set.
|
||||
- `true` -> Disable output interrupt when LOCK_GRANT function is set.
|
||||
"""
|
||||
@spec lock_grant_mask?(t) :: boolean
|
||||
def lock_grant_mask?(%PCA9641{conn: conn}) do
|
||||
with {:ok, conn} <- Registers.read_interrupt_mask(conn),
|
||||
true <- get_bool(conn, 2),
|
||||
@spec test_interrupt_interrupt_enabled?(t) :: boolean
|
||||
def test_interrupt_interrupt_enabled?(%PCA9641{conn: conn}) do
|
||||
with {:ok, data} <- Registers.read_interrupt_mask(conn),
|
||||
false <- get_bool(data, 3),
|
||||
do: true,
|
||||
else: (_ -> false)
|
||||
end
|
||||
|
@ -961,22 +884,10 @@ defmodule PCA9641 do
|
|||
- `false` -> Enable output interrupt when LOCK_GRANT function is set.
|
||||
- `true` -> Disable output interrupt when LOCK_GRANT function is set.
|
||||
"""
|
||||
@spec lock_grant_mask(t, boolean) :: {:ok, t} | {:error, term}
|
||||
def lock_grant_mask(%PCA9641{conn: conn} = dev, value) when is_boolean(value) do
|
||||
with {:ok, conn} <- Registers.update_interrupt_mask(conn, &set_bit(&1, 2, value)),
|
||||
do: {:ok, %{dev | conn: conn}}
|
||||
end
|
||||
|
||||
@doc """
|
||||
BUS_LOST_MSK
|
||||
|
||||
- `false` -> Enable output interrupt when BUS_LOST function is set.
|
||||
- `true` -> Disable output interrupt when BUS_LOST function is set.
|
||||
"""
|
||||
@spec bus_lost_mask?(t) :: boolean
|
||||
def bus_lost_mask?(%PCA9641{conn: conn}) do
|
||||
with {:ok, conn} <- Registers.read_interrupt_mask(conn),
|
||||
true <- get_bool(conn, 1),
|
||||
@spec lock_grant_interrupt_enabled?(t) :: boolean
|
||||
def lock_grant_interrupt_enabled?(%PCA9641{conn: conn}) do
|
||||
with {:ok, data} <- Registers.read_interrupt_mask(conn),
|
||||
false <- get_bool(data, 2),
|
||||
do: true,
|
||||
else: (_ -> false)
|
||||
end
|
||||
|
@ -987,22 +898,10 @@ defmodule PCA9641 do
|
|||
- `false` -> Enable output interrupt when BUS_LOST function is set.
|
||||
- `true` -> Disable output interrupt when BUS_LOST function is set.
|
||||
"""
|
||||
@spec bus_lost_mask(t, boolean) :: {:ok, t} | {:error, term}
|
||||
def bus_lost_mask(%PCA9641{conn: conn} = dev, value) when is_boolean(value) do
|
||||
with {:ok, conn} <- Registers.update_interrupt_mask(conn, &set_bit(&1, 1, value)),
|
||||
do: {:ok, %{dev | conn: conn}}
|
||||
end
|
||||
|
||||
@doc """
|
||||
INT_IN_MSK
|
||||
|
||||
- `false` -> Enable output interrupt when INT_IN function is set.
|
||||
- `true` -> Disable output interrupt when INT_IN function is set.
|
||||
"""
|
||||
@spec int_in_mask?(t) :: boolean
|
||||
def int_in_mask?(%PCA9641{conn: conn}) do
|
||||
with {:ok, conn} <- Registers.read_interrupt_mask(conn),
|
||||
true <- get_bool(conn, 0),
|
||||
@spec bus_lost_interrupt_enabled?(t) :: boolean
|
||||
def bus_lost_interrupt_enabled?(%PCA9641{conn: conn}) do
|
||||
with {:ok, data} <- Registers.read_interrupt_mask(conn),
|
||||
false <- get_bool(data, 1),
|
||||
do: true,
|
||||
else: (_ -> false)
|
||||
end
|
||||
|
@ -1013,10 +912,12 @@ defmodule PCA9641 do
|
|||
- `false` -> Enable output interrupt when INT_IN function is set.
|
||||
- `true` -> Disable output interrupt when INT_IN function is set.
|
||||
"""
|
||||
@spec int_in_mask(pid, boolean) :: {:ok, t} | {:error, term}
|
||||
def int_in_mask(%PCA9641{conn: conn} = dev, value) when is_boolean(value) do
|
||||
with {:ok, conn} <- Registers.update_interrupt_mask(conn, &set_bit(&1, 0, value)),
|
||||
do: {:ok, %{dev | conn: conn}}
|
||||
@spec interrupt_in_interrupt_enabled?(t) :: boolean
|
||||
def interrupt_in_interrupt_enabled?(%PCA9641{conn: conn}) do
|
||||
with {:ok, data} <- Registers.read_interrupt_mask(conn),
|
||||
false <- get_bool(data, 0),
|
||||
do: true,
|
||||
else: (_ -> false)
|
||||
end
|
||||
|
||||
@doc """
|
||||
|
@ -1040,7 +941,7 @@ defmodule PCA9641 do
|
|||
"""
|
||||
@spec abandon_downstream_bus(t) :: {:ok, t} | {:error, term}
|
||||
def abandon_downstream_bus(%PCA9641{conn: conn} = dev) do
|
||||
with {:ok, conn} <- Registers.write_control(conn, 0), do: {:ok, %{dev | conn: conn}}
|
||||
with {:ok, conn} <- Registers.write_control(conn, <<0>>), do: {:ok, %{dev | conn: conn}}
|
||||
end
|
||||
|
||||
defp wait_for_bus_init(conn), do: wait_for_bus_init(conn, 0)
|
||||
|
@ -1053,7 +954,7 @@ defmodule PCA9641 do
|
|||
else
|
||||
if bus_initialisation_failed?(conn),
|
||||
do: {:error, :bus_init_fail},
|
||||
else: :ok
|
||||
else: {:ok, conn}
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
11
mix.exs
11
mix.exs
|
@ -33,11 +33,14 @@ defmodule PCA9641.MixProject do
|
|||
# Run "mix help deps" to learn about dependencies.
|
||||
defp deps do
|
||||
[
|
||||
{:elixir_ale, "~> 1.2", optional: true},
|
||||
{:circuits_i2c, "~> 0.3", optional: true},
|
||||
{:circuits_gpio, "~> 0.4", optional: true},
|
||||
{:wafer, git: "https://gitlab.com/jimsy/wafer"},
|
||||
{:ex_doc, ">= 0.0.0", only: :dev, runtime: false}
|
||||
{:circuits_i2c, "~> 0.3", optional: true},
|
||||
{:credo, "~> 1.1", only: [:dev, :test], runtime: false},
|
||||
{:earmark, ">= 0.0.0", only: [:dev, :test]},
|
||||
{:elixir_ale, "~> 1.2", optional: true},
|
||||
{:ex_doc, ">= 0.0.0", only: [:dev, :test]},
|
||||
{:mimic, "~> 1.1", only: :test},
|
||||
{:wafer, git: "https://gitlab.com/jimsy/wafer"}
|
||||
]
|
||||
end
|
||||
end
|
||||
|
|
12
mix.lock
12
mix.lock
|
@ -1,12 +1,16 @@
|
|||
%{
|
||||
"bunt": {:hex, :bunt, "0.2.0", "951c6e801e8b1d2cbe58ebbd3e616a869061ddadcc4863d0a2182541acae9a38", [:mix], [], "hexpm"},
|
||||
"circuits_gpio": {:hex, :circuits_gpio, "0.4.4", "09823645b82d84177549c9520e822ffb87d228413527f8a3134f4f436be16efe", [:make, :mix], [{:elixir_make, "~> 0.6", [hex: :elixir_make, repo: "hexpm", optional: false]}], "hexpm"},
|
||||
"circuits_i2c": {:hex, :circuits_i2c, "0.3.5", "43e043d7efc3aead364061f8a7ed627f81ff7cef52bfa47cb629d8a68ca56a9f", [:make, :mix], [{:elixir_make, "~> 0.6", [hex: :elixir_make, repo: "hexpm", optional: false]}], "hexpm"},
|
||||
"earmark": {:hex, :earmark, "1.4.1", "07bb382826ee8d08d575a1981f971ed41bd5d7e86b917fd012a93c51b5d28727", [:mix], [], "hexpm"},
|
||||
"circuits_i2c": {:hex, :circuits_i2c, "0.3.6", "348b8de3cf1ade6c4b92ad7c9de7068df1af0d441df341d7d126d53671924f64", [:make, :mix], [{:elixir_make, "~> 0.6", [hex: :elixir_make, repo: "hexpm", optional: false]}], "hexpm"},
|
||||
"credo": {:hex, :credo, "1.1.5", "caec7a3cadd2e58609d7ee25b3931b129e739e070539ad1a0cd7efeeb47014f4", [:mix], [{:bunt, "~> 0.2.0", [hex: :bunt, repo: "hexpm", optional: false]}, {:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: false]}], "hexpm"},
|
||||
"earmark": {:hex, :earmark, "1.4.3", "364ca2e9710f6bff494117dbbd53880d84bebb692dafc3a78eb50aa3183f2bfd", [:mix], [], "hexpm"},
|
||||
"elixir_ale": {:hex, :elixir_ale, "1.2.1", "07ac2f17a0191b8bd3b0df6b526c7f699a3a4d690c9def573fcb5824eef24d98", [:make, :mix], [{:elixir_make, "~> 0.4", [hex: :elixir_make, repo: "hexpm", optional: false]}], "hexpm"},
|
||||
"elixir_make": {:hex, :elixir_make, "0.6.0", "38349f3e29aff4864352084fc736fa7fa0f2995a819a737554f7ebd28b85aaab", [:mix], [], "hexpm"},
|
||||
"ex_doc": {:hex, :ex_doc, "0.21.2", "caca5bc28ed7b3bdc0b662f8afe2bee1eedb5c3cf7b322feeeb7c6ebbde089d6", [:mix], [{:earmark, "~> 1.3.3 or ~> 1.4", [hex: :earmark, repo: "hexpm", optional: false]}, {:makeup_elixir, "~> 0.14", [hex: :makeup_elixir, repo: "hexpm", optional: false]}], "hexpm"},
|
||||
"jason": {:hex, :jason, "1.1.2", "b03dedea67a99223a2eaf9f1264ce37154564de899fd3d8b9a21b1a6fd64afe7", [:mix], [{:decimal, "~> 1.0", [hex: :decimal, repo: "hexpm", optional: true]}], "hexpm"},
|
||||
"makeup": {:hex, :makeup, "1.0.0", "671df94cf5a594b739ce03b0d0316aa64312cee2574b6a44becb83cd90fb05dc", [:mix], [{:nimble_parsec, "~> 0.5.0", [hex: :nimble_parsec, repo: "hexpm", optional: false]}], "hexpm"},
|
||||
"makeup_elixir": {:hex, :makeup_elixir, "0.14.0", "cf8b7c66ad1cff4c14679698d532f0b5d45a3968ffbcbfd590339cb57742f1ae", [:mix], [{:makeup, "~> 1.0", [hex: :makeup, repo: "hexpm", optional: false]}], "hexpm"},
|
||||
"nimble_parsec": {:hex, :nimble_parsec, "0.5.1", "c90796ecee0289dbb5ad16d3ad06f957b0cd1199769641c961cfe0b97db190e0", [:mix], [], "hexpm"},
|
||||
"wafer": {:git, "https://gitlab.com/jimsy/wafer", "cac08bc5f037bc0fb544330e2262478b9e916747", []},
|
||||
"mimic": {:hex, :mimic, "1.1.3", "3bad83d5271b4faa7bbfef587417a6605cbbc802a353395d446a1e5f46fe7115", [:mix], [], "hexpm"},
|
||||
"nimble_parsec": {:hex, :nimble_parsec, "0.5.3", "def21c10a9ed70ce22754fdeea0810dafd53c2db3219a0cd54cf5526377af1c6", [:mix], [], "hexpm"},
|
||||
"wafer": {:git, "https://gitlab.com/jimsy/wafer", "edb85a48b75215dede060016f46d783d9da67672", []},
|
||||
}
|
||||
|
|
930
test/pca9641_test.exs
Normal file
930
test/pca9641_test.exs
Normal file
|
@ -0,0 +1,930 @@
|
|||
defmodule PCA9641Test do
|
||||
use ExUnit.Case, async: true
|
||||
use Mimic
|
||||
use Bitwise
|
||||
alias PCA9641.Registers, as: Registers
|
||||
alias Wafer.Driver.Fake, as: Driver
|
||||
|
||||
describe "acquire/1" do
|
||||
test "fails when called without a connection" do
|
||||
assert {:error, _} = PCA9641.acquire([])
|
||||
end
|
||||
|
||||
test "returns a device struct" do
|
||||
assert {:ok, %PCA9641{}} = PCA9641.acquire(conn: Driver.acquire([]))
|
||||
end
|
||||
end
|
||||
|
||||
describe "verify_identity/1" do
|
||||
test "succeeds when the register contains the correct value" do
|
||||
Registers
|
||||
|> expect(:read_id, 1, fn _conn -> {:ok, <<0x38>>} end)
|
||||
|
||||
assert {:ok, _conn} = PCA9641.verify_identity(conn())
|
||||
end
|
||||
|
||||
test "fails when the register contains an incorrect value" do
|
||||
Registers
|
||||
|> expect(:read_id, 1, fn _conn -> {:ok, <<0x13>>} end)
|
||||
|
||||
assert {:error, _} = PCA9641.verify_identity(conn())
|
||||
end
|
||||
end
|
||||
|
||||
describe "request_downstream_bus/1" do
|
||||
test "writes to the control register and then polls until bus init is true" do
|
||||
Registers
|
||||
|> expect(:write_control, 1, fn conn, command ->
|
||||
assert command == 0x1
|
||||
{:ok, conn}
|
||||
end)
|
||||
|> expect(:read_control, 1, fn _conn ->
|
||||
{:ok, <<0b1000>>}
|
||||
end)
|
||||
|> expect(:read_status, 1, fn _conn ->
|
||||
{:ok, <<0b00>>}
|
||||
end)
|
||||
|
||||
assert {:ok, _conn} = PCA9641.request_downstream_bus(conn())
|
||||
end
|
||||
end
|
||||
|
||||
describe "priority?/1" do
|
||||
test "reads byte 7 of CONTROL" do
|
||||
Registers
|
||||
|> expect(:read_control, 1, fn _conn -> {:ok, 0b10000000} end)
|
||||
|
||||
assert PCA9641.priority?(conn())
|
||||
|
||||
Registers
|
||||
|> expect(:read_control, 1, fn _conn -> {:ok, 0} end)
|
||||
|
||||
refute PCA9641.priority?(conn())
|
||||
end
|
||||
end
|
||||
|
||||
describe "priority/2" do
|
||||
test "writes to bit 7 of CONTROL" do
|
||||
Registers
|
||||
|> expect(:update_control, 1, fn conn, callback ->
|
||||
assert <<0b10000000>> = callback.(<<0>>)
|
||||
{:ok, conn}
|
||||
end)
|
||||
|
||||
PCA9641.priority(conn(), true)
|
||||
end
|
||||
end
|
||||
|
||||
describe "downstream_disconnect_on_timeout?/1" do
|
||||
test "reads bit 6 from CONTROL" do
|
||||
Registers
|
||||
|> expect(:read_control, 1, fn _conn -> {:ok, 0b01000000} end)
|
||||
|
||||
assert PCA9641.downstream_disconnect_on_timeout?(conn())
|
||||
|
||||
Registers
|
||||
|> expect(:read_control, 1, fn _conn -> {:ok, 0} end)
|
||||
|
||||
refute PCA9641.downstream_disconnect_on_timeout?(conn())
|
||||
end
|
||||
end
|
||||
|
||||
describe "downstream_disconnect_on_timeout/2" do
|
||||
test "writes to bit 6 of CONTROL" do
|
||||
Registers
|
||||
|> expect(:update_control, 1, fn conn, callback ->
|
||||
assert <<0b01000000>> = callback.(<<0>>)
|
||||
{:ok, conn}
|
||||
end)
|
||||
|
||||
PCA9641.downstream_disconnect_on_timeout(conn(), true)
|
||||
end
|
||||
end
|
||||
|
||||
describe "idle_timer_disconnect?/1" do
|
||||
test "reads bit 6 from CONTROL" do
|
||||
Registers
|
||||
|> expect(:read_control, 1, fn _conn -> {:ok, 0b00100000} end)
|
||||
|
||||
assert PCA9641.idle_timer_disconnect?(conn())
|
||||
|
||||
Registers
|
||||
|> expect(:read_control, 1, fn _conn -> {:ok, 0} end)
|
||||
|
||||
refute PCA9641.idle_timer_disconnect?(conn())
|
||||
end
|
||||
end
|
||||
|
||||
describe "idle_timer_disconnect/2" do
|
||||
test "writes to bit 5 of CONTROL" do
|
||||
Registers
|
||||
|> expect(:update_control, 1, fn conn, callback ->
|
||||
assert <<0b00100000>> = callback.(<<0>>)
|
||||
{:ok, conn}
|
||||
end)
|
||||
|
||||
PCA9641.idle_timer_disconnect(conn(), true)
|
||||
end
|
||||
end
|
||||
|
||||
describe "smbus_software_reset?/1" do
|
||||
test "reads bit 4 from CONTROL" do
|
||||
Registers
|
||||
|> expect(:read_control, 1, fn _conn -> {:ok, 0b00010000} end)
|
||||
|
||||
assert PCA9641.smbus_software_reset?(conn())
|
||||
|
||||
Registers
|
||||
|> expect(:read_control, 1, fn _conn -> {:ok, 0} end)
|
||||
|
||||
refute PCA9641.smbus_software_reset?(conn())
|
||||
end
|
||||
end
|
||||
|
||||
describe "smbus_software_reset/2" do
|
||||
test "writes to bit 4 of CONTROL" do
|
||||
Registers
|
||||
|> expect(:update_control, 1, fn conn, callback ->
|
||||
assert <<0b00010000>> = callback.(<<0>>)
|
||||
{:ok, conn}
|
||||
end)
|
||||
|
||||
PCA9641.smbus_software_reset(conn(), true)
|
||||
end
|
||||
end
|
||||
|
||||
describe "bus_init?/1" do
|
||||
test "reads bit 3 from CONTROL" do
|
||||
Registers
|
||||
|> expect(:read_control, 1, fn _conn -> {:ok, 0b00001000} end)
|
||||
|
||||
assert PCA9641.bus_init?(conn())
|
||||
|
||||
Registers
|
||||
|> expect(:read_control, 1, fn _conn -> {:ok, 0} end)
|
||||
|
||||
refute PCA9641.bus_init?(conn())
|
||||
end
|
||||
end
|
||||
|
||||
describe "bus_init/2" do
|
||||
test "writes to bit 3 of CONTROL" do
|
||||
Registers
|
||||
|> expect(:update_control, 1, fn conn, callback ->
|
||||
assert <<0b00001000>> = callback.(<<0>>)
|
||||
{:ok, conn}
|
||||
end)
|
||||
|
||||
PCA9641.bus_init(conn(), true)
|
||||
end
|
||||
end
|
||||
|
||||
describe "bus_connect?/1" do
|
||||
test "reads bit 2 from CONTROL" do
|
||||
Registers
|
||||
|> expect(:read_control, 1, fn _conn -> {:ok, 0b00000100} end)
|
||||
|
||||
assert PCA9641.bus_connect?(conn())
|
||||
|
||||
Registers
|
||||
|> expect(:read_control, 1, fn _conn -> {:ok, 0} end)
|
||||
|
||||
refute PCA9641.bus_connect?(conn())
|
||||
end
|
||||
end
|
||||
|
||||
describe "bus_connect/2" do
|
||||
test "writes to bit 2 of CONTROL" do
|
||||
Registers
|
||||
|> expect(:update_control, 1, fn conn, callback ->
|
||||
assert <<0b00000100>> = callback.(<<0>>)
|
||||
{:ok, conn}
|
||||
end)
|
||||
|
||||
PCA9641.bus_connect(conn(), true)
|
||||
end
|
||||
end
|
||||
|
||||
describe "lock_grant?/1" do
|
||||
test "reads bit 1 from CONTROL" do
|
||||
Registers
|
||||
|> expect(:read_control, 1, fn _conn -> {:ok, 0b00000010} end)
|
||||
|
||||
assert PCA9641.lock_grant?(conn())
|
||||
|
||||
Registers
|
||||
|> expect(:read_control, 1, fn _conn -> {:ok, 0} end)
|
||||
|
||||
refute PCA9641.lock_grant?(conn())
|
||||
end
|
||||
end
|
||||
|
||||
describe "lock_request?/1" do
|
||||
test "reads bit 0 from CONTROL" do
|
||||
Registers
|
||||
|> expect(:read_control, 1, fn _conn -> {:ok, 0b00000001} end)
|
||||
|
||||
assert PCA9641.lock_request?(conn())
|
||||
|
||||
Registers
|
||||
|> expect(:read_control, 1, fn _conn -> {:ok, 0} end)
|
||||
|
||||
refute PCA9641.lock_request?(conn())
|
||||
end
|
||||
end
|
||||
|
||||
describe "lock_request/2" do
|
||||
test "writes to bit 0 of CONTROL" do
|
||||
Registers
|
||||
|> expect(:update_control, 1, fn conn, callback ->
|
||||
assert <<0b00000001>> = callback.(<<0>>)
|
||||
{:ok, conn}
|
||||
end)
|
||||
|
||||
PCA9641.lock_request(conn(), true)
|
||||
end
|
||||
end
|
||||
|
||||
describe "sda_becomes_io?/1" do
|
||||
test "reads bit 7 of STATUS" do
|
||||
Registers
|
||||
|> expect(:read_status, 1, fn _conn -> {:ok, 0b10000000} end)
|
||||
|
||||
assert PCA9641.sda_becomes_io?(conn())
|
||||
|
||||
Registers
|
||||
|> expect(:read_status, 1, fn _conn -> {:ok, 0} end)
|
||||
|
||||
refute PCA9641.sda_becomes_io?(conn())
|
||||
end
|
||||
end
|
||||
|
||||
describe "sda_becomes_io/2" do
|
||||
test "writes to bit 7 of STATUS" do
|
||||
Registers
|
||||
|> expect(:update_status, 1, fn conn, callback ->
|
||||
assert <<0b10000000>> = callback.(<<0>>)
|
||||
{:ok, conn}
|
||||
end)
|
||||
|
||||
PCA9641.sda_becomes_io(conn(), true)
|
||||
end
|
||||
end
|
||||
|
||||
describe "scl_becomes_io?/1" do
|
||||
test "reads bit 6 of STATUS" do
|
||||
Registers
|
||||
|> expect(:read_status, 1, fn _conn -> {:ok, 0b01000000} end)
|
||||
|
||||
assert PCA9641.scl_becomes_io?(conn())
|
||||
|
||||
Registers
|
||||
|> expect(:read_status, 1, fn _conn -> {:ok, 0} end)
|
||||
|
||||
refute PCA9641.scl_becomes_io?(conn())
|
||||
end
|
||||
end
|
||||
|
||||
describe "scl_becomes_io/2" do
|
||||
test "writes to bit 6 of STATUS" do
|
||||
Registers
|
||||
|> expect(:update_status, 1, fn conn, callback ->
|
||||
assert <<0b01000000>> = callback.(<<0>>)
|
||||
{:ok, conn}
|
||||
end)
|
||||
|
||||
PCA9641.scl_becomes_io(conn(), true)
|
||||
end
|
||||
end
|
||||
|
||||
describe "test_interrupt_pin?/1" do
|
||||
test "reads bit 5 of STATUS" do
|
||||
Registers
|
||||
|> expect(:read_status, 1, fn _conn -> {:ok, 0b00100000} end)
|
||||
|
||||
assert PCA9641.test_interrupt_pin?(conn())
|
||||
|
||||
Registers
|
||||
|> expect(:read_status, 1, fn _conn -> {:ok, 0} end)
|
||||
|
||||
refute PCA9641.test_interrupt_pin?(conn())
|
||||
end
|
||||
end
|
||||
|
||||
describe "test_interrupt_pin/2" do
|
||||
test "writes to bit 5 of STATUS" do
|
||||
Registers
|
||||
|> expect(:update_status, 1, fn conn, callback ->
|
||||
assert <<0b00100000>> = callback.(<<0>>)
|
||||
{:ok, conn}
|
||||
end)
|
||||
|
||||
PCA9641.test_interrupt_pin(conn(), true)
|
||||
end
|
||||
end
|
||||
|
||||
describe "mailbox_full?/1" do
|
||||
test "reads bit 4 of STATUS" do
|
||||
Registers
|
||||
|> expect(:read_status, 1, fn _conn -> {:ok, 0b00010000} end)
|
||||
|
||||
assert PCA9641.mailbox_full?(conn())
|
||||
|
||||
Registers
|
||||
|> expect(:read_status, 1, fn _conn -> {:ok, 0} end)
|
||||
|
||||
refute PCA9641.mailbox_full?(conn())
|
||||
end
|
||||
end
|
||||
|
||||
describe "mailbox_empty?/1" do
|
||||
test "reads bit 3 of STATUS" do
|
||||
Registers
|
||||
|> expect(:read_status, 1, fn _conn -> {:ok, 0b00001000} end)
|
||||
|
||||
assert PCA9641.mailbox_empty?(conn())
|
||||
|
||||
Registers
|
||||
|> expect(:read_status, 1, fn _conn -> {:ok, 0} end)
|
||||
|
||||
refute PCA9641.mailbox_empty?(conn())
|
||||
end
|
||||
end
|
||||
|
||||
describe "bus_hung?/1" do
|
||||
test "reads bit 2 of STATUS" do
|
||||
Registers
|
||||
|> expect(:read_status, 1, fn _conn -> {:ok, 0b00000100} end)
|
||||
|
||||
assert PCA9641.bus_hung?(conn())
|
||||
|
||||
Registers
|
||||
|> expect(:read_status, 1, fn _conn -> {:ok, 0} end)
|
||||
|
||||
refute PCA9641.bus_hung?(conn())
|
||||
end
|
||||
end
|
||||
|
||||
describe "bus_initialisation_failed?/1" do
|
||||
test "reads bit 1 of STATUS" do
|
||||
Registers
|
||||
|> expect(:read_status, 1, fn _conn -> {:ok, 0b00000010} end)
|
||||
|
||||
assert PCA9641.bus_initialisation_failed?(conn())
|
||||
|
||||
Registers
|
||||
|> expect(:read_status, 1, fn _conn -> {:ok, 0} end)
|
||||
|
||||
refute PCA9641.bus_initialisation_failed?(conn())
|
||||
end
|
||||
end
|
||||
|
||||
describe "other_lock?/1" do
|
||||
test "reads bit 0 of STATUS" do
|
||||
Registers
|
||||
|> expect(:read_status, 1, fn _conn -> {:ok, 0b00000001} end)
|
||||
|
||||
assert PCA9641.other_lock?(conn())
|
||||
|
||||
Registers
|
||||
|> expect(:read_status, 1, fn _conn -> {:ok, 0} end)
|
||||
|
||||
refute PCA9641.other_lock?(conn())
|
||||
end
|
||||
end
|
||||
|
||||
describe "reserve_time/1" do
|
||||
test "returns the contents of the RESERVE_TIME register" do
|
||||
Registers
|
||||
|> expect(:read_reserve_time, 1, fn _conn ->
|
||||
{:ok, <<123>>}
|
||||
end)
|
||||
|
||||
assert {:ok, 123, _conn} = PCA9641.reserve_time(conn())
|
||||
end
|
||||
end
|
||||
|
||||
describe "reserve_time/2" do
|
||||
test "sets the contents of the RESERVE_TIME register" do
|
||||
Registers
|
||||
|> expect(:write_reserve_time, 1, fn conn, ms ->
|
||||
assert ms == 123
|
||||
{:ok, conn}
|
||||
end)
|
||||
|
||||
assert {:ok, _conn} = PCA9641.reserve_time(conn(), 123)
|
||||
end
|
||||
end
|
||||
|
||||
describe "interrupt_reason/1" do
|
||||
test "returns :bus_hung when bit 6 of INTERRUPT_STATUS is high" do
|
||||
Registers
|
||||
|> expect(:read_interrupt_status, 1, fn _conn ->
|
||||
{:ok, <<0b01000000>>}
|
||||
end)
|
||||
|
||||
assert {:ok, [:bus_hung]} = PCA9641.interrupt_reason(conn())
|
||||
end
|
||||
|
||||
test "returns :mbox_full when bit 5 of INTERRUPT_STATUS is high" do
|
||||
Registers
|
||||
|> expect(:read_interrupt_status, 1, fn _conn ->
|
||||
{:ok, <<0b00100000>>}
|
||||
end)
|
||||
|
||||
assert {:ok, [:mbox_full]} = PCA9641.interrupt_reason(conn())
|
||||
end
|
||||
|
||||
test "returns :mbox_empty when bit 4 of INTERRUPT_STATUS is high" do
|
||||
Registers
|
||||
|> expect(:read_interrupt_status, 1, fn _conn ->
|
||||
{:ok, <<0b00010000>>}
|
||||
end)
|
||||
|
||||
assert {:ok, [:mbox_empty]} = PCA9641.interrupt_reason(conn())
|
||||
end
|
||||
|
||||
test "returns :test_int when bit 3 of INTERRUPT_STATUS is high" do
|
||||
Registers
|
||||
|> expect(:read_interrupt_status, 1, fn _conn ->
|
||||
{:ok, <<0b00001000>>}
|
||||
end)
|
||||
|
||||
assert {:ok, [:test_int]} = PCA9641.interrupt_reason(conn())
|
||||
end
|
||||
|
||||
test "returns :lock_grant when bit 2 of INTERRUPT_STATUS is high" do
|
||||
Registers
|
||||
|> expect(:read_interrupt_status, 1, fn _conn ->
|
||||
{:ok, <<0b00000100>>}
|
||||
end)
|
||||
|
||||
assert {:ok, [:lock_grant]} = PCA9641.interrupt_reason(conn())
|
||||
end
|
||||
|
||||
test "returns :bus_lost when bit 1 of INTERRUPT_STATUS is high" do
|
||||
Registers
|
||||
|> expect(:read_interrupt_status, 1, fn _conn ->
|
||||
{:ok, <<0b00000010>>}
|
||||
end)
|
||||
|
||||
assert {:ok, [:bus_lost]} = PCA9641.interrupt_reason(conn())
|
||||
end
|
||||
|
||||
test "returns :int_in when bit 0 of INTERRUPT_STATUS is high" do
|
||||
Registers
|
||||
|> expect(:read_interrupt_status, 1, fn _conn ->
|
||||
{:ok, <<0b00000001>>}
|
||||
end)
|
||||
|
||||
assert {:ok, [:int_in]} = PCA9641.interrupt_reason(conn())
|
||||
end
|
||||
end
|
||||
|
||||
describe "interrupt_clear/2" do
|
||||
test "writes all ones to INTERRUPT_STATUS when passed `:all`" do
|
||||
Registers
|
||||
|> expect(:write_interrupt_status, 1, fn conn, <<data>> ->
|
||||
assert data == 0b01111111
|
||||
{:ok, conn}
|
||||
end)
|
||||
|
||||
PCA9641.interrupt_clear(conn(), :all)
|
||||
end
|
||||
|
||||
test "writes INTERRUPT_STATUS bit 5 high when passed `[:mbox_full]`" do
|
||||
Registers
|
||||
|> expect(:write_interrupt_status, 1, fn conn, <<data>> ->
|
||||
assert data == 0b00100000
|
||||
{:ok, conn}
|
||||
end)
|
||||
|
||||
PCA9641.interrupt_clear(conn(), [:mbox_full])
|
||||
end
|
||||
|
||||
test "writes INTERRUPT_STATUS bit 4 high when passed `[:mbox_empty]`" do
|
||||
Registers
|
||||
|> expect(:write_interrupt_status, 1, fn conn, <<data>> ->
|
||||
assert data == 0b00010000
|
||||
{:ok, conn}
|
||||
end)
|
||||
|
||||
PCA9641.interrupt_clear(conn(), [:mbox_empty])
|
||||
end
|
||||
|
||||
test "writes INTERRUPT_STATUS bit 3 high when passed `[:test_int]`" do
|
||||
Registers
|
||||
|> expect(:write_interrupt_status, 1, fn conn, <<data>> ->
|
||||
assert data == 0b00001000
|
||||
{:ok, conn}
|
||||
end)
|
||||
|
||||
PCA9641.interrupt_clear(conn(), [:test_int])
|
||||
end
|
||||
|
||||
test "writes INTERRUPT_STATUS bit 2 high when passed `[:lock_grant]`" do
|
||||
Registers
|
||||
|> expect(:write_interrupt_status, 1, fn conn, <<data>> ->
|
||||
assert data == 0b00000100
|
||||
{:ok, conn}
|
||||
end)
|
||||
|
||||
PCA9641.interrupt_clear(conn(), [:lock_grant])
|
||||
end
|
||||
|
||||
test "writes INTERRUPT_STATUS bit 1 high when passed `[:bus_lost]`" do
|
||||
Registers
|
||||
|> expect(:write_interrupt_status, 1, fn conn, <<data>> ->
|
||||
assert data == 0b00000010
|
||||
{:ok, conn}
|
||||
end)
|
||||
|
||||
PCA9641.interrupt_clear(conn(), [:bus_lost])
|
||||
end
|
||||
|
||||
test "writes INTERRUPT_STATUS bit 0 high when passed `[:int_in]`" do
|
||||
Registers
|
||||
|> expect(:write_interrupt_status, 1, fn conn, <<data>> ->
|
||||
assert data == 0b00000001
|
||||
{:ok, conn}
|
||||
end)
|
||||
|
||||
PCA9641.interrupt_clear(conn(), [:int_in])
|
||||
end
|
||||
end
|
||||
|
||||
describe "interrupt_enable/2" do
|
||||
test "writes all zeroes when called with `:all`" do
|
||||
Registers
|
||||
|> expect(:write_interrupt_mask, 1, fn conn, <<data>> ->
|
||||
assert data == 0
|
||||
{:ok, conn}
|
||||
end)
|
||||
|
||||
PCA9641.interrupt_enable(conn(), :all)
|
||||
end
|
||||
|
||||
test "writes all ones when called with `:none`" do
|
||||
Registers
|
||||
|> expect(:write_interrupt_mask, 1, fn conn, <<data>> ->
|
||||
assert data == 0b01111111
|
||||
{:ok, conn}
|
||||
end)
|
||||
|
||||
PCA9641.interrupt_enable(conn(), :none)
|
||||
end
|
||||
|
||||
test "writes INTERRUPT_MASK bit 6 low when called with [:bus_hung]" do
|
||||
Registers
|
||||
|> expect(:update_interrupt_mask, 1, fn conn, callback ->
|
||||
assert <<0b10111111>> = callback.(<<0xFF>>)
|
||||
{:ok, conn}
|
||||
end)
|
||||
|
||||
PCA9641.interrupt_enable(conn(), [:bus_hung])
|
||||
end
|
||||
|
||||
test "writes INTERRUPT_MASK bit 5 low when called with [:mbox_full]" do
|
||||
Registers
|
||||
|> expect(:update_interrupt_mask, 1, fn conn, callback ->
|
||||
assert <<0b11011111>> = callback.(<<0xFF>>)
|
||||
{:ok, conn}
|
||||
end)
|
||||
|
||||
PCA9641.interrupt_enable(conn(), [:mbox_full])
|
||||
end
|
||||
|
||||
test "writes INTERRUPT_MASK bit 4 low when called with [:mbox_empty]" do
|
||||
Registers
|
||||
|> expect(:update_interrupt_mask, 1, fn conn, callback ->
|
||||
assert <<0b11101111>> = callback.(<<0xFF>>)
|
||||
{:ok, conn}
|
||||
end)
|
||||
|
||||
PCA9641.interrupt_enable(conn(), [:mbox_empty])
|
||||
end
|
||||
|
||||
test "writes INTERRUPT_MASK bit 3 low when called with [:test_int]" do
|
||||
Registers
|
||||
|> expect(:update_interrupt_mask, 1, fn conn, callback ->
|
||||
assert <<0b11110111>> = callback.(<<0xFF>>)
|
||||
{:ok, conn}
|
||||
end)
|
||||
|
||||
PCA9641.interrupt_enable(conn(), [:test_int])
|
||||
end
|
||||
|
||||
test "writes INTERRUPT_MASK bit 2 low when called with [:lock_grant]" do
|
||||
Registers
|
||||
|> expect(:update_interrupt_mask, 1, fn conn, callback ->
|
||||
assert <<0b11111011>> = callback.(<<0xFF>>)
|
||||
{:ok, conn}
|
||||
end)
|
||||
|
||||
PCA9641.interrupt_enable(conn(), [:lock_grant])
|
||||
end
|
||||
|
||||
test "writes INTERRUPT_MASK bit 1 low when called with [:bus_lost]" do
|
||||
Registers
|
||||
|> expect(:update_interrupt_mask, 1, fn conn, callback ->
|
||||
assert <<0b11111101>> = callback.(<<0xFF>>)
|
||||
{:ok, conn}
|
||||
end)
|
||||
|
||||
PCA9641.interrupt_enable(conn(), [:bus_lost])
|
||||
end
|
||||
|
||||
test "writes INTERRUPT_MASK bit 0 low when called with [:int_in]" do
|
||||
Registers
|
||||
|> expect(:update_interrupt_mask, 1, fn conn, callback ->
|
||||
assert <<0b11111110>> = callback.(<<0xFF>>)
|
||||
{:ok, conn}
|
||||
end)
|
||||
|
||||
PCA9641.interrupt_enable(conn(), [:int_in])
|
||||
end
|
||||
end
|
||||
|
||||
describe "interrupt_enabled/1" do
|
||||
test "returns [:bus_hung] when INTERRUPT_MASK bit 6 is low" do
|
||||
Registers
|
||||
|> expect(:read_interrupt_mask, 1, fn _conn ->
|
||||
{:ok, 0b10111111}
|
||||
end)
|
||||
|
||||
assert {:ok, [:bus_hung]} = PCA9641.interrupt_enabled(conn())
|
||||
end
|
||||
|
||||
test "returns [:mbox_full] when INTERRUPT_MASK bit 5 is low" do
|
||||
Registers
|
||||
|> expect(:read_interrupt_mask, 1, fn _conn ->
|
||||
{:ok, 0b11011111}
|
||||
end)
|
||||
|
||||
assert {:ok, [:mbox_full]} = PCA9641.interrupt_enabled(conn())
|
||||
end
|
||||
|
||||
test "returns [:mbox_empty] when INTERRUPT_MASK bit 4 is low" do
|
||||
Registers
|
||||
|> expect(:read_interrupt_mask, 1, fn _conn ->
|
||||
{:ok, 0b11101111}
|
||||
end)
|
||||
|
||||
assert {:ok, [:mbox_empty]} = PCA9641.interrupt_enabled(conn())
|
||||
end
|
||||
|
||||
test "returns [:test_int] when INTERRUPT_MASK bit 3 is low" do
|
||||
Registers
|
||||
|> expect(:read_interrupt_mask, 1, fn _conn ->
|
||||
{:ok, 0b11110111}
|
||||
end)
|
||||
|
||||
assert {:ok, [:test_int]} = PCA9641.interrupt_enabled(conn())
|
||||
end
|
||||
|
||||
test "returns [:lock_grant] when INTERRUPT_MASK bit 2 is low" do
|
||||
Registers
|
||||
|> expect(:read_interrupt_mask, 1, fn _conn ->
|
||||
{:ok, 0b11111011}
|
||||
end)
|
||||
|
||||
assert {:ok, [:lock_grant]} = PCA9641.interrupt_enabled(conn())
|
||||
end
|
||||
|
||||
test "returns [:bus_lost] when INTERRUPT_MASK bit 1 is low" do
|
||||
Registers
|
||||
|> expect(:read_interrupt_mask, 1, fn _conn ->
|
||||
{:ok, 0b11111101}
|
||||
end)
|
||||
|
||||
assert {:ok, [:bus_lost]} = PCA9641.interrupt_enabled(conn())
|
||||
end
|
||||
|
||||
test "returns [:int_in] when INTERRUPT_MASK bit 0 is low" do
|
||||
Registers
|
||||
|> expect(:read_interrupt_mask, 1, fn _conn ->
|
||||
{:ok, 0b11111110}
|
||||
end)
|
||||
|
||||
assert {:ok, [:int_in]} = PCA9641.interrupt_enabled(conn())
|
||||
end
|
||||
|
||||
test "returns all interrupts when all INTERRUPT_MASK bits are low" do
|
||||
Registers
|
||||
|> expect(:read_interrupt_mask, 1, fn _conn ->
|
||||
{:ok, 0}
|
||||
end)
|
||||
|
||||
assert {:ok, interrupts} = PCA9641.interrupt_enabled(conn())
|
||||
assert :bus_hung in interrupts
|
||||
assert :mbox_full in interrupts
|
||||
assert :mbox_empty in interrupts
|
||||
assert :test_int in interrupts
|
||||
assert :lock_grant in interrupts
|
||||
assert :bus_lost in interrupts
|
||||
assert :int_in in interrupts
|
||||
end
|
||||
|
||||
test "returns no interrupts when all INTERRUPT_MASK bits are high" do
|
||||
Registers
|
||||
|> expect(:read_interrupt_mask, 1, fn _conn ->
|
||||
{:ok, 0x7F}
|
||||
end)
|
||||
|
||||
assert {:ok, []} = PCA9641.interrupt_enabled(conn())
|
||||
end
|
||||
end
|
||||
|
||||
describe "bus_hung_interrupt?/1" do
|
||||
test "returns `true` when INTERRUPT_STATUS bit 6 is high" do
|
||||
Registers
|
||||
|> expect(:read_interrupt_status, 1, fn _conn ->
|
||||
{:ok, 0b01000000}
|
||||
end)
|
||||
|
||||
assert PCA9641.bus_hung_interrupt?(conn())
|
||||
end
|
||||
end
|
||||
|
||||
describe "mailbox_full_interrupt?/1" do
|
||||
test "returns `true` when INTERRUPT_STATUS bit 5 is high" do
|
||||
Registers
|
||||
|> expect(:read_interrupt_status, 1, fn _conn ->
|
||||
{:ok, 0b00100000}
|
||||
end)
|
||||
|
||||
assert PCA9641.mailbox_full_interrupt?(conn())
|
||||
end
|
||||
end
|
||||
|
||||
describe "mailbox_empty_interrupt?/1" do
|
||||
test "returns `true` when INTERRUPT_STATUS bit 4 is high" do
|
||||
Registers
|
||||
|> expect(:read_interrupt_status, 1, fn _conn ->
|
||||
{:ok, 0b00010000}
|
||||
end)
|
||||
|
||||
assert PCA9641.mailbox_empty_interrupt?(conn())
|
||||
end
|
||||
end
|
||||
|
||||
describe "test_interrupt_pin_interrupt?/1" do
|
||||
test "returns `true` when INTERRUPT_STATUS bit 3 is high" do
|
||||
Registers
|
||||
|> expect(:read_interrupt_status, 1, fn _conn ->
|
||||
{:ok, 0b00001000}
|
||||
end)
|
||||
|
||||
assert PCA9641.test_interrupt_pin_interrupt?(conn())
|
||||
end
|
||||
end
|
||||
|
||||
describe "lock_grant_interrupt?/1" do
|
||||
test "returns `true` when INTERRUPT_STATUS bit 2 is high" do
|
||||
Registers
|
||||
|> expect(:read_interrupt_status, 1, fn _conn ->
|
||||
{:ok, 0b00000100}
|
||||
end)
|
||||
|
||||
assert PCA9641.lock_grant_interrupt?(conn())
|
||||
end
|
||||
end
|
||||
|
||||
describe "bus_lost_interrupt?/1" do
|
||||
test "returns `true` when INTERRUPT_STATUS bit 1 is high" do
|
||||
Registers
|
||||
|> expect(:read_interrupt_status, 1, fn _conn ->
|
||||
{:ok, 0b00000010}
|
||||
end)
|
||||
|
||||
assert PCA9641.bus_lost_interrupt?(conn())
|
||||
end
|
||||
end
|
||||
|
||||
describe "interupt_in_interrupt?/1" do
|
||||
test "returns `true` when INTERRUPT_STATUS bit 0 is high" do
|
||||
Registers
|
||||
|> expect(:read_interrupt_status, 1, fn _conn ->
|
||||
{:ok, 0b00000001}
|
||||
end)
|
||||
|
||||
assert PCA9641.interupt_in_interrupt?(conn())
|
||||
end
|
||||
end
|
||||
|
||||
describe "bus_hung_interrupt_enabled?/1" do
|
||||
test "returns `true` when INTERRUPT_MASK bit 6 is low" do
|
||||
Registers
|
||||
|> expect(:read_interrupt_mask, 1, fn _conn ->
|
||||
{:ok, 0b10111111}
|
||||
end)
|
||||
|
||||
assert PCA9641.bus_hung_interrupt_enabled?(conn())
|
||||
end
|
||||
end
|
||||
|
||||
describe "mailbox_full_interrupt_enabled?/1" do
|
||||
test "returns `true` when INTERRUPT_MASK bit 5 is low" do
|
||||
Registers
|
||||
|> expect(:read_interrupt_mask, 1, fn _conn ->
|
||||
{:ok, 0b11011111}
|
||||
end)
|
||||
|
||||
assert PCA9641.mailbox_full_interrupt_enabled?(conn())
|
||||
end
|
||||
end
|
||||
|
||||
describe "mailbox_empty_interrupt_enabled?/1" do
|
||||
test "returns `true` when INTERRUPT_MASK bit 4 is low" do
|
||||
Registers
|
||||
|> expect(:read_interrupt_mask, 1, fn _conn ->
|
||||
{:ok, 0b11101111}
|
||||
end)
|
||||
|
||||
assert PCA9641.mailbox_empty_interrupt_enabled?(conn())
|
||||
end
|
||||
end
|
||||
|
||||
describe "test_interrupt_interrupt_enabled?/1" do
|
||||
test "returns `true` when INTERRUPT_MASK bit 3 is low" do
|
||||
Registers
|
||||
|> expect(:read_interrupt_mask, 1, fn _conn ->
|
||||
{:ok, 0b11110111}
|
||||
end)
|
||||
|
||||
assert PCA9641.test_interrupt_interrupt_enabled?(conn())
|
||||
end
|
||||
end
|
||||
|
||||
describe "lock_grant_interrupt_enabled?/1" do
|
||||
test "returns `true` when INTERRUPT_MASK bit 2 is low" do
|
||||
Registers
|
||||
|> expect(:read_interrupt_mask, 1, fn _conn ->
|
||||
{:ok, 0b11111011}
|
||||
end)
|
||||
|
||||
assert PCA9641.lock_grant_interrupt_enabled?(conn())
|
||||
end
|
||||
end
|
||||
|
||||
describe "bus_lost_interrupt_enabled?/1" do
|
||||
test "returns `true` when INTERRUPT_MASK bit 1 is low" do
|
||||
Registers
|
||||
|> expect(:read_interrupt_mask, 1, fn _conn ->
|
||||
{:ok, 0b11111101}
|
||||
end)
|
||||
|
||||
assert PCA9641.bus_lost_interrupt_enabled?(conn())
|
||||
end
|
||||
end
|
||||
|
||||
describe "interrupt_in_interrupt_enabled?/1" do
|
||||
test "returns `true` when INTERRUPT_MASK bit 0 is low" do
|
||||
Registers
|
||||
|> expect(:read_interrupt_mask, 1, fn _conn ->
|
||||
{:ok, 0b11111110}
|
||||
end)
|
||||
|
||||
assert PCA9641.interrupt_in_interrupt_enabled?(conn())
|
||||
end
|
||||
end
|
||||
|
||||
describe "read_mailbox/1" do
|
||||
test "returns the contents of the MAILBOX register" do
|
||||
Registers
|
||||
|> expect(:read_mailbox, 1, fn _conn ->
|
||||
{:ok, <<0x1, 0x2>>}
|
||||
end)
|
||||
|
||||
assert {:ok, <<0x1, 0x2>>, _conn} = PCA9641.read_mailbox(conn())
|
||||
end
|
||||
end
|
||||
|
||||
describe "write_mailbox/2" do
|
||||
test "writes the contents of the MAILBOX register" do
|
||||
Registers
|
||||
|> expect(:write_mailbox, 1, fn conn, data ->
|
||||
assert <<0x1, 0x2>> == data
|
||||
{:ok, conn}
|
||||
end)
|
||||
|
||||
assert {:ok, _conn} = PCA9641.write_mailbox(conn(), <<0x1, 0x2>>)
|
||||
end
|
||||
end
|
||||
|
||||
describe "abandon_downstream_bus/1" do
|
||||
test "writes the CONTROL register to zero" do
|
||||
Registers
|
||||
|> expect(:write_control, 1, fn conn, data ->
|
||||
assert <<0>> == data
|
||||
{:ok, conn}
|
||||
end)
|
||||
|
||||
assert {:ok, conn} = PCA9641.abandon_downstream_bus(conn())
|
||||
end
|
||||
end
|
||||
|
||||
defp conn do
|
||||
with {:ok, conn} <- Driver.acquire([]), {:ok, conn} <- PCA9641.acquire(conn: conn), do: conn
|
||||
end
|
||||
end
|
|
@ -1 +1,2 @@
|
|||
Mimic.copy(PCA9641.Registers)
|
||||
ExUnit.start()
|
||||
|
|
Loading…
Reference in a new issue