defmodule Modbus.Float do @moduledoc """ IEEE754 float converter Based on https://www.h-schmidt.net/FloatConverter/Float.html. """ @doc """ Converts a list of 2n 16-bit registers to a list of IEEE754 big endian floats. ## Example ```elixir [+5.0] = Float.from_be([0x40a0, 0x0000]) [-5.0, +5.0] = Float.from_be([0xc0a0, 0x0000, 0x40a0, 0x0000]) ``` """ def from_be(list_of_regs), do: from(list_of_regs, :be) @doc """ Converts a list of 2n 16-bit registers to a list of IEEE754 little endian floats. ## Example ```elixir [+5.0] = Float.from_le([0x0000, 0x40a0]) [-5.0, +5.0] = Float.from_le([0x0000, 0xc0a0, 0x0000, 0x40a0]) ``` """ def from_le(list_of_regs), do: from(list_of_regs, :le) @doc """ Converts a list of IEEE754 big endian floats to a list of 2n 16-bit registers. ## Example ```elixir [0x40a0, 0x0000] = Float.to_be([+5.0]) [0xc0a0, 0x0000, 0x40a0, 0x0000] = Float.to_be([-5.0, +5.0]) ``` """ def to_be(list_of_floats), do: to(list_of_floats, :be) @doc """ Converts a list of IEEE754 little endian floats to a list of 2n 16-bit registers. ## Example ```elixir [0x0000, 0x40a0] = Float.to_le([+5.0]) [0x0000, 0xc0a0, 0x0000, 0x40a0] = Float.to_le([-5.0, +5.0]) ``` """ def to_le(list_of_floats), do: to(list_of_floats, :le) defp from([], _), do: [] defp from([w0, w1 | tail], endianness) do [from(w0, w1, endianness) | from(tail, endianness)] end defp from(w0, w1, :be) do <> = <> value end defp from(w0, w1, :le) do <> = <> value end defp to([], _), do: [] defp to([f | tail], endianness) do [w0, w1] = to(f, endianness) [w0, w1 | to(tail, endianness)] end defp to(f, :be) do <> = <> [w0, w1] end defp to(f, :le) do <> = <> [w1, w0] end end