defmodule Modbus.IEEE754 do @moduledoc """ IEEE754 float helper Based on https://www.h-schmidt.net/FloatConverter/IEEE754.html. """ @doc """ Converts a couple of 16-bit registers to IEEE754 float. ## Example ```elixir +5.0 = IEEE754.from_2_regs(0x40a0, 0x0000, :be) ``` """ def from_2_regs(w0, w1, :be) do <> = <> value end def from_2_regs(w0, w1, :le) do <> = <> value end @doc """ Converts a couple of 16-bit registers to IEEE754 float. ## Example ```elixir +5.0 = IEEE754.from_2_regs(0x40a0, 0x0000, :be) ``` """ def from_2_regs([w0, w1], :be) do <> = <> f end def from_2_regs([w0, w1], :le) do <> = <> f end @doc """ Converts a list of 2n 16-bit registers to a IEEE754 floats list. ## Example ```elixir [-5.0, +5.0] = IEEE754.from_2n_regs([0xc0a0, 0x0000, 0x40a0, 0x0000], :be) ``` """ def from_2n_regs([], _), do: [] def from_2n_regs([w0, w1 | tail], endianness) do [from_2_regs(w0, w1, endianness) | from_2n_regs(tail, endianness)] end @doc """ Converts a IEEE754 float to a couple of 16-bit registers. ## Example ```elixir [0xc0a0, 0x0000] = IEEE754.to_2_regs(-5.0) ``` """ def to_2_regs(f, :be) do <> = <> [w0, w1] end def to_2_regs(f, :le) do <> = <> [w1, w0] end @doc """ Converts a list of IEEE754 floats to a list of 2n 16-bit registers. ## Example ```elixir [0xc0a0, 0x0000, 0x40a0, 0x0000] = IEEE754.to_2n_regs([-5.0, +5.0]) ``` """ def to_2n_regs([], _), do: [] def to_2n_regs([f | tail], endianness) do [w0, w1] = to_2_regs(f, endianness) [w0, w1 | to_2n_regs(tail, endianness)] end end