# `ExDlt645.BCD`
[🔗](https://github.com/Ultraluv/ex_dlt645/blob/v0.1.0/lib/ex_dlt645/bcd.ex#L1)

Binary Coded Decimal (BCD) encoding and decoding helpers for DL/T 645 protocols.

In DL/T 645, meter addresses, numeric values (energy, voltage, current, etc.),
and timestamps are represented in BCD format, typically transmitted with the
least significant byte first (little-endian byte order).

# `address_match?`

```elixir
@spec address_match?(String.t(), String.t()) :: boolean()
```

Checks if a slave address matches a target address.
Supports broadcast address `AAAAAAAAAAAA`, `999999999999`, and per-nibble wildcard `A`.

# `bcd_to_int`

```elixir
@spec bcd_to_int(byte()) :: 0..99
```

Converts a single BCD byte (0x00..0x99) to an integer (0..99).

# `decode_address`

```elixir
@spec decode_address(binary()) :: String.t()
```

Decodes 6 BCD bytes (little-endian) into a 12-character address string.

## Examples

    iex> ExDlt645.BCD.decode_address(<<0x12, 0x90, 0x78, 0x56, 0x34, 0x12>>)
    "123456789012"

# `decode_datetime`

```elixir
@spec decode_datetime(binary()) :: {:ok, NaiveDateTime.t()} | {:error, term()}
```

Decodes a 6-byte BCD timestamp `YYMMDDhhmmss` (transmitted order: ss, mm, hh, DD, MM, YY).
Returns `{:ok, %NaiveDateTime{}}` or `{:error, reason}`.

# `decode_datetime_min`

```elixir
@spec decode_datetime_min(binary()) :: {:ok, NaiveDateTime.t()} | {:error, term()}
```

Decodes a 5-byte BCD date-minute `YYMMDDhhmm` (transmitted order: mm, hh, DD, MM, YY).
Returns `{:ok, %NaiveDateTime{}}` with seconds set to 0.

# `decode_float`

```elixir
@spec decode_float(binary(), non_neg_integer(), :little | :big) :: float()
```

Decodes a BCD binary into a float or integer representing a fixed-point decimal.
For example, with `decimals: 2` and bytes `<<0x45, 0x23, 0x01, 0x00>>` (little-endian), returns `123.45`.

# `decode_integer`

```elixir
@spec decode_integer(binary(), :little | :big) :: integer()
```

Decodes a BCD binary into an integer.
By default, `endianness: :little` (least significant byte first).

# `decode_time`

```elixir
@spec decode_time(binary()) :: {:ok, Time.t()} | {:error, term()}
```

Decodes a 3-byte BCD time `hhmmss` (transmitted order: ss, mm, hh).
Returns `{:ok, %Time{}}`.

# `encode_address`

```elixir
@spec encode_address(String.t()) :: binary()
```

Encodes a 12-digit meter address string into 6 BCD bytes (little-endian, low byte first).

## Examples

    iex> ExDlt645.BCD.encode_address("123456789012")
    <<0x12, 0x90, 0x78, 0x56, 0x34, 0x12>>

    iex> ExDlt645.BCD.encode_address("AAAAAAAAAAAA")
    <<0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA>>

# `encode_datetime`

```elixir
@spec encode_datetime(NaiveDateTime.t() | DateTime.t()) :: binary()
```

Encodes a `NaiveDateTime` or `DateTime` struct into 6-byte BCD `YYMMDDhhmmss` (ss, mm, hh, DD, MM, YY).

# `encode_datetime_min`

```elixir
@spec encode_datetime_min(NaiveDateTime.t() | DateTime.t()) :: binary()
```

Encodes a `NaiveDateTime` or `DateTime` struct into 5-byte BCD `YYMMDDhhmm` (mm, hh, DD, MM, YY).

# `encode_float`

```elixir
@spec encode_float(number(), non_neg_integer(), non_neg_integer(), :little | :big) ::
  binary()
```

Encodes a float or numeric value into a fixed-point BCD binary.

# `encode_integer`

```elixir
@spec encode_integer(integer(), non_neg_integer(), :little | :big) :: binary()
```

Encodes an integer into BCD binary with the specified byte size and endianness.

# `encode_time`

```elixir
@spec encode_time(Time.t()) :: binary()
```

Encodes a `Time` into 3-byte BCD `hhmmss` (ss, mm, hh).

# `int_to_bcd`

```elixir
@spec int_to_bcd(0..99) :: byte()
```

Converts an integer (0..99) to a single BCD byte.

---

*Consult [api-reference.md](api-reference.md) for complete listing*
