ht1621b 0.2.0

Platform-agnostic embedded-hal driver for the HT1621B LCD controller (3-wire bit-bang)
Documentation
# ht1621b

Platform-agnostic [`embedded-hal`] 1.0 driver for the **HT1621B** LCD
controller, driven over its custom 3‑ or 4‑wire serial interface.

| Type | Pins | Capabilities |
|------|------|-------------|
| `Ht1621b` | CS, WR, DA | Write commands + RAM data |
| `Ht1621bRW` | CS, WR, **RD**, DA | Write + read + read‑modify‑write |

Both are aliases for the generic `Driver<B>`, which wraps a bus
implementation (`Ht1621bBus` / `Ht1621bBusRW`). Generic over any
`embedded-hal` 1.0 `OutputPin` (+ `FlexPin` for DA on the 4‑wire variant)
and `DelayNs`; the power-on initialisation (`Ht1621b::new`) is `async` and
borrows an [`embedded-hal-async`] `DelayNs` for its millisecond-scale waits.

## Features

| feature | default | effect |
|---------|---------|--------|
| `read`  | off     | Enables `Ht1621bRW` / `Ht1621bBusRW` (RAM read + read‑modify‑write) and pulls in the `embedded-flex-pin` dependency for the bidirectional DA pin. |

The default build is write-only (3-wire) and does not depend on
`embedded-flex-pin`. Enable read support with:

```toml
ht1621b = { version = "0.2", features = ["read"] }
```


## Example

```ignore
use ht1621b::{Config, Ht1621b};

let mut lcd = Ht1621b::new(cs, wr, da, delay, &mut async_delay, Config::default()).await;
lcd.write_byte(arbitrary_int::u6::new(0x00), 0xEF); // display a digit
```

## Resource-constrained MCUs (e.g. Cortex-M0+)

This driver targets extremely small parts (tested against budgets like
**3 KB SRAM / 20 KB flash**). It uses no heap, no `static` buffers, and the
struct is only the moved pin/delay fields, so its RAM footprint is a handful of
bytes. The dominant cost is flash, which is overwhelmingly decided by your
**application's** release profile.

Add this to your binary crate's `Cargo.toml`:

```toml
[profile.release]
opt-level = "z"     # optimise for size
lto = true
codegen-units = 1
panic = "abort"     # drop unwind tables / landing pads
strip = true
```

`panic = "abort"` is usually the single biggest flash win at this level, as it
removes the unwinding machinery entirely.

### Cortex-M0+ notes (`thumbv6m-none-eabi`)

- The M0+ has **no hardware divide** and **no atomic compare-and-swap**. This
  driver contains neither division nor atomics, so it maps cleanly onto the
  `thumbv6m` instruction set.
- When constructing RAM addresses, prefer `arbitrary_int::u6::new_masked(x)`
  over `u6::new(x)`: `new()` panics on out-of-range input, which pulls the
  `core::fmt` panic-formatting machinery into flash. `new_masked()` truncates
  instead and keeps that code path out of your binary.

### Measuring size

An example harness is included that instantiates the full driver (including the
`async` `new`) on bare metal so you can profile it:

```sh
cargo size --example size_m0 --release --target thumbv6m-none-eabi -- -A
```

Measured on `thumbv6m-none-eabi` (driver + minimal `cortex-m-rt` runtime; the
`size_m0` harness exercises `new`, `clear`, `write_byte`, and `set_config`).
Two profiles compared — stock `release` (`opt-level = 3`, no LTO) vs. the size
profile above:

| profile               | `.text` | `.rodata` / `.data` / `.bss` |
|-----------------------|---------|------------------------------|
| stock `release`       | 124 B   | 0 / 0 / 0                    |
| recommended size opts | 384 B   | 0 / 0 / 0                    |

(`.text` here excludes the 192 B `.vector_table`, which is Cortex-M runtime, not
the driver. Stock `release` inlines the no-op harness pins away more
aggressively, hence the smaller number; both are tiny.)

Key takeaways: `.rodata`/`.data`/`.bss` are all **0** — no `core::fmt`
panic-formatting machinery, libcalls, or static buffers are linked, and the
driver's static RAM footprint is zero. Unused features cost nothing: methods are
generic over the pins/delay, so any command you never call (e.g. tone or
time-base/WDT) is dropped entirely by dead-code elimination.

[`embedded-hal`]: https://crates.io/crates/embedded-hal
[`embedded-hal-async`]: https://crates.io/crates/embedded-hal-async