Skip to content

Commit c9c9b23

Browse files
committed
Add MPSSE backend
1 parent 1adc9c0 commit c9c9b23

File tree

3 files changed

+125
-7
lines changed

3 files changed

+125
-7
lines changed

examples/backends/mpsse.ex

Lines changed: 114 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,114 @@
1+
defmodule Circuits.I2C.MPSSE do
2+
@moduledoc """
3+
Circuits.I2C backend for USB devices that use the FTDI MPSSE protocol
4+
5+
Devices that speak MPSSE:
6+
7+
* [Adafruit FT232H Breakout](https://www.adafruit.com/product/2264)
8+
9+
Example use:
10+
11+
```elixir
12+
iex> {:ok, i2c} = Circuits.I2C.MPSSE.open("anything", [])
13+
{:ok, %Circuits.I2C.MPSSE{mpsse: #Reference<0.3204948360.1742602257.8675>}}
14+
iex> Circuits.I2C.detect_devices(i2c)
15+
'P'
16+
# This is also [0x50]. 0x50 is the address of an I2C EEPROM. Read the beginning.
17+
iex> Circuits.I2C.write_read(i2c, 0x50, <<0>>, 16)
18+
{:ok, <<34, 51, 68, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255>>}
19+
iex> Circuits.I2C.close(i2c)
20+
:ok
21+
```
22+
"""
23+
@behaviour Circuits.I2C.Backend
24+
25+
alias Circuits.I2C.Backend
26+
alias Circuits.I2C.Bus
27+
28+
defstruct [:mpsse]
29+
30+
@doc """
31+
Return the I2C bus names on this system
32+
33+
No supported options
34+
"""
35+
@impl Backend
36+
def bus_names(_options) do
37+
# TODO
38+
["i2c-1"]
39+
end
40+
41+
@doc """
42+
Open an I2C bus
43+
"""
44+
@impl Backend
45+
def open(_bus_name, _options) do
46+
with {:ok, mpsse} <- MPSSE.find_and_open(:i2c) do
47+
{:ok, %__MODULE__{mpsse: mpsse}}
48+
end
49+
end
50+
51+
@doc """
52+
Return information about this backend
53+
"""
54+
@impl Backend
55+
def info() do
56+
%{backend: __MODULE__}
57+
end
58+
59+
defimpl Bus do
60+
@impl Bus
61+
def read(%Circuits.I2C.MPSSE{mpsse: mpsse}, address, count, _options) do
62+
address_rd = Bitwise.bsl(address, 1) + 1
63+
64+
with :ok <- MPSSE.start(mpsse),
65+
:ok <- MPSSE.write(mpsse, <<address_rd>>),
66+
:ack <- MPSSE.get_ack(mpsse),
67+
{:ok, result} <- MPSSE.read(mpsse, count) do
68+
MPSSE.stop(mpsse)
69+
{:ok, result}
70+
end
71+
end
72+
73+
@impl Bus
74+
def write(%Circuits.I2C.MPSSE{mpsse: mpsse}, address, data, _options) do
75+
address_wr = Bitwise.bsl(address, 1)
76+
77+
with :ok <- MPSSE.start(mpsse),
78+
:ok <- MPSSE.write(mpsse, [address_wr, data]),
79+
:ack <- MPSSE.get_ack(mpsse) do
80+
MPSSE.stop(mpsse)
81+
:ok
82+
end
83+
end
84+
85+
@impl Bus
86+
def write_read(
87+
%Circuits.I2C.MPSSE{mpsse: mpsse},
88+
address,
89+
write_data,
90+
read_count,
91+
_options
92+
) do
93+
address_wr = Bitwise.bsl(address, 1)
94+
address_rd = address_wr + 1
95+
96+
with :ok <- MPSSE.start(mpsse),
97+
:ok <- MPSSE.write(mpsse, [address_wr, write_data]),
98+
:ack <- MPSSE.get_ack(mpsse),
99+
:ok <- MPSSE.start(mpsse),
100+
:ok <- MPSSE.write(mpsse, <<address_rd>>),
101+
:ack <- MPSSE.get_ack(mpsse),
102+
{:ok, result} <- MPSSE.read(mpsse, read_count) do
103+
MPSSE.stop(mpsse)
104+
{:ok, result}
105+
end
106+
end
107+
108+
@impl Bus
109+
def close(%Circuits.I2C.MPSSE{mpsse: mpsse}) do
110+
MPSSE.close(mpsse)
111+
:ok
112+
end
113+
end
114+
end

mix.exs

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,9 @@ defmodule Circuits.I2C.MixProject do
3232
]
3333
end
3434

35-
defp elixirc_paths(env) when env in [:test, :dev], do: ["lib", "examples/circuits_sim"]
35+
defp elixirc_paths(:mpsse),
36+
do: ["lib", "examples/backends/mpsse_backend.ex"]
37+
3638
defp elixirc_paths(_env), do: ["lib"]
3739

3840
def application do
@@ -66,7 +68,8 @@ defmodule Circuits.I2C.MixProject do
6668
{:credo, "~> 1.6", only: :dev, runtime: false},
6769
{:credo_binary_patterns, "~> 0.2.2", only: :dev, runtime: false},
6870
{:dialyxir, "~> 1.2", only: :dev, runtime: false},
69-
{:elixir_make, "~> 0.6", runtime: false}
71+
{:elixir_make, "~> 0.6", runtime: false},
72+
{:mpsse, github: "fhunleth/mpsse", submodules: true, only: :mpsse}
7073
]
7174
end
7275

mix.lock

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,17 @@
11
%{
22
"bunt": {:hex, :bunt, "1.0.0", "081c2c665f086849e6d57900292b3a161727ab40431219529f13c4ddcf3e7a44", [:mix], [], "hexpm", "dc5f86aa08a5f6fa6b8096f0735c4e76d54ae5c9fa2c143e5a1fc7c1cd9bb6b5"},
3-
"credo": {:hex, :credo, "1.7.3", "05bb11eaf2f2b8db370ecaa6a6bda2ec49b2acd5e0418bc106b73b07128c0436", [:mix], [{:bunt, "~> 0.2.1 or ~> 1.0", [hex: :bunt, repo: "hexpm", optional: false]}, {:file_system, "~> 0.2 or ~> 1.0", [hex: :file_system, repo: "hexpm", optional: false]}, {:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: false]}], "hexpm", "35ea675a094c934c22fb1dca3696f3c31f2728ae6ef5a53b5d648c11180a4535"},
3+
"credo": {:hex, :credo, "1.7.5", "643213503b1c766ec0496d828c90c424471ea54da77c8a168c725686377b9545", [:mix], [{:bunt, "~> 0.2.1 or ~> 1.0", [hex: :bunt, repo: "hexpm", optional: false]}, {:file_system, "~> 0.2 or ~> 1.0", [hex: :file_system, repo: "hexpm", optional: false]}, {:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: false]}], "hexpm", "f799e9b5cd1891577d8c773d245668aa74a2fcd15eb277f51a0131690ebfb3fd"},
44
"credo_binary_patterns": {:hex, :credo_binary_patterns, "0.2.3", "0dabadbe3cfd8db14b69ff346c112bfadde9bf65dc7aea19c39743c8d2ed07fa", [:mix], [{:credo, "~> 1.6", [hex: :credo, repo: "hexpm", optional: false]}], "hexpm", "3c333a564ed3e27f5c9f69985a921b88ef90f131bf722d085957cc4b25b7a085"},
55
"dialyxir": {:hex, :dialyxir, "1.4.3", "edd0124f358f0b9e95bfe53a9fcf806d615d8f838e2202a9f430d59566b6b53b", [:mix], [{:erlex, ">= 0.2.6", [hex: :erlex, repo: "hexpm", optional: false]}], "hexpm", "bf2cfb75cd5c5006bec30141b131663299c661a864ec7fbbc72dfa557487a986"},
66
"earmark_parser": {:hex, :earmark_parser, "1.4.39", "424642f8335b05bb9eb611aa1564c148a8ee35c9c8a8bba6e129d51a3e3c6769", [:mix], [], "hexpm", "06553a88d1f1846da9ef066b87b57c6f605552cfbe40d20bd8d59cc6bde41944"},
7-
"elixir_make": {:hex, :elixir_make, "0.7.8", "505026f266552ee5aabca0b9f9c229cbb496c689537c9f922f3eb5431157efc7", [:mix], [{:castore, "~> 0.1 or ~> 1.0", [hex: :castore, repo: "hexpm", optional: true]}, {:certifi, "~> 2.0", [hex: :certifi, repo: "hexpm", optional: true]}], "hexpm", "7a71945b913d37ea89b06966e1342c85cfe549b15e6d6d081e8081c493062c07"},
7+
"elixir_make": {:hex, :elixir_make, "0.8.3", "d38d7ee1578d722d89b4d452a3e36bcfdc644c618f0d063b874661876e708683", [:mix], [{:castore, "~> 0.1 or ~> 1.0", [hex: :castore, repo: "hexpm", optional: true]}, {:certifi, "~> 2.0", [hex: :certifi, repo: "hexpm", optional: true]}], "hexpm", "5c99a18571a756d4af7a4d89ca75c28ac899e6103af6f223982f09ce44942cc9"},
88
"erlex": {:hex, :erlex, "0.2.6", "c7987d15e899c7a2f34f5420d2a2ea0d659682c06ac607572df55a43753aa12e", [:mix], [], "hexpm", "2ed2e25711feb44d52b17d2780eabf998452f6efda104877a3881c2f8c0c0c75"},
9-
"ex_doc": {:hex, :ex_doc, "0.31.1", "8a2355ac42b1cc7b2379da9e40243f2670143721dd50748bf6c3b1184dae2089", [:mix], [{:earmark_parser, "~> 1.4.39", [hex: :earmark_parser, repo: "hexpm", optional: false]}, {:makeup_c, ">= 0.1.1", [hex: :makeup_c, repo: "hexpm", optional: true]}, {:makeup_elixir, "~> 0.14", [hex: :makeup_elixir, repo: "hexpm", optional: false]}, {:makeup_erlang, "~> 0.1", [hex: :makeup_erlang, repo: "hexpm", optional: false]}], "hexpm", "3178c3a407c557d8343479e1ff117a96fd31bafe52a039079593fb0524ef61b0"},
9+
"ex_doc": {:hex, :ex_doc, "0.32.0", "896afb57b1e00030f6ec8b2e19d3ca99a197afb23858d49d94aea673dc222f12", [:mix], [{:earmark_parser, "~> 1.4.39", [hex: :earmark_parser, repo: "hexpm", optional: false]}, {:makeup_c, ">= 0.1.1", [hex: :makeup_c, repo: "hexpm", optional: true]}, {:makeup_elixir, "~> 0.14", [hex: :makeup_elixir, repo: "hexpm", optional: false]}, {:makeup_erlang, "~> 0.1", [hex: :makeup_erlang, repo: "hexpm", optional: false]}], "hexpm", "ed2c3e42c558f49bda3ff37e05713432006e1719a6c4a3320c7e4735787374e7"},
1010
"file_system": {:hex, :file_system, "1.0.0", "b689cc7dcee665f774de94b5a832e578bd7963c8e637ef940cd44327db7de2cd", [:mix], [], "hexpm", "6752092d66aec5a10e662aefeed8ddb9531d79db0bc145bb8c40325ca1d8536d"},
1111
"jason": {:hex, :jason, "1.4.1", "af1504e35f629ddcdd6addb3513c3853991f694921b1b9368b0bd32beb9f1b63", [:mix], [{:decimal, "~> 1.0 or ~> 2.0", [hex: :decimal, repo: "hexpm", optional: true]}], "hexpm", "fbb01ecdfd565b56261302f7e1fcc27c4fb8f32d56eab74db621fc154604a7a1"},
1212
"makeup": {:hex, :makeup, "1.1.1", "fa0bc768698053b2b3869fa8a62616501ff9d11a562f3ce39580d60860c3a55e", [:mix], [{:nimble_parsec, "~> 1.2.2 or ~> 1.3", [hex: :nimble_parsec, repo: "hexpm", optional: false]}], "hexpm", "5dc62fbdd0de44de194898b6710692490be74baa02d9d108bc29f007783b0b48"},
13-
"makeup_elixir": {:hex, :makeup_elixir, "0.16.1", "cc9e3ca312f1cfeccc572b37a09980287e243648108384b97ff2b76e505c3555", [:mix], [{:makeup, "~> 1.0", [hex: :makeup, repo: "hexpm", optional: false]}, {:nimble_parsec, "~> 1.2.3 or ~> 1.3", [hex: :nimble_parsec, repo: "hexpm", optional: false]}], "hexpm", "e127a341ad1b209bd80f7bd1620a15693a9908ed780c3b763bccf7d200c767c6"},
14-
"makeup_erlang": {:hex, :makeup_erlang, "0.1.3", "d684f4bac8690e70b06eb52dad65d26de2eefa44cd19d64a8095e1417df7c8fd", [:mix], [{:makeup, "~> 1.0", [hex: :makeup, repo: "hexpm", optional: false]}], "hexpm", "b78dc853d2e670ff6390b605d807263bf606da3c82be37f9d7f68635bd886fc9"},
13+
"makeup_elixir": {:hex, :makeup_elixir, "0.16.2", "627e84b8e8bf22e60a2579dad15067c755531fea049ae26ef1020cad58fe9578", [:mix], [{:makeup, "~> 1.0", [hex: :makeup, repo: "hexpm", optional: false]}, {:nimble_parsec, "~> 1.2.3 or ~> 1.3", [hex: :nimble_parsec, repo: "hexpm", optional: false]}], "hexpm", "41193978704763f6bbe6cc2758b84909e62984c7752b3784bd3c218bb341706b"},
14+
"makeup_erlang": {:hex, :makeup_erlang, "0.1.5", "e0ff5a7c708dda34311f7522a8758e23bfcd7d8d8068dc312b5eb41c6fd76eba", [:mix], [{:makeup, "~> 1.0", [hex: :makeup, repo: "hexpm", optional: false]}], "hexpm", "94d2e986428585a21516d7d7149781480013c56e30c6a233534bedf38867a59a"},
15+
"mpsse": {:git, "https://github.com/fhunleth/mpsse.git", "f49977a4d2a691fd8a1b0ab023f8ca276726bf9c", [submodules: true]},
1516
"nimble_parsec": {:hex, :nimble_parsec, "1.4.0", "51f9b613ea62cfa97b25ccc2c1b4216e81df970acd8e16e8d1bdc58fef21370d", [:mix], [], "hexpm", "9c565862810fb383e9838c1dd2d7d2c437b3d13b267414ba6af33e50d2d1cf28"},
1617
}

0 commit comments

Comments
 (0)