Current section

Files

Jump to
elixir_mlx90640 lib mlx90640.ex
Raw

lib/mlx90640.ex

defmodule Mlx90640 do
use Bitwise
use GenServer
defmodule State do
@moduledoc false
defstruct port: nil, receiver: nil
end
defmodule Frame do
@moduledoc false
defstruct data: []
end
def start_link(receiver, mlx_opts \\ [], opts \\ []) do
frame_rate = Keyword.get(mlx_opts, :frame_rate, 2)
if Enum.member?([1, 2, 4, 8, 16, 32, 64], frame_rate) do
GenServer.start_link(__MODULE__, [receiver, frame_rate], opts)
else
{ :error, "frame rate #{frame_rate} not supported" }
end
end
def stop(pid) do
GenServer.cast(pid, :stop)
end
def init([receiver, frame_rate]) do
executable = :code.priv_dir(:elixir_mlx90640) ++ '/mlx90640'
port = Port.open({:spawn_executable, executable}, [
{:args, ["#{frame_rate}"]},
{:packet, 2},
:use_stdio,
:binary,
:exit_status
])
{:ok, %State{ port: port, receiver: receiver }}
end
def handle_info({port, {:data, data}}, state = %State{ port: port, receiver: receiver }) do
send(receiver, %Frame{ data: decode(data) })
{ :noreply, state }
end
def handle_cast(:stop, state) do
{ :stop, :normal, state }
end
defp decode(data, decoded \\ []) do
case data do
<<>> -> decoded |> Enum.reverse |> Enum.chunk_every(32)
<< a, b, rest :: binary >> -> decode(rest, [decode_bytes(a, b) | decoded])
_ -> nil
end
end
defp decode_bytes(a, b) do
sign = if bsr(band(b, 0b10000000), 7) == 1, do: -1, else: 1
fractional = band(b, 0b01111111)
(a * sign) + (fractional / 100.0)
end
end