culvert
Typed access to the HDMI 2.1 SCDC register map.
culvert sits on top of [hdmi_hal::scdc::ScdcTransport] and gives raw SCDC register
bytes meaning: named structs, typed enums, and one method per register group for
scrambling control, FRL training primitives, version negotiation, update flags, and
Character Error Detection. It is the SCDC layer that [plumbob]'s link training state
machine drives, and is equally usable without it.
Sequencing of register operations — rate selection, timeout handling, retry logic — is out of scope. Culvert provides the typed primitives; the caller decides when to call them.
Usage
[]
= "0.1"
Wrap your transport in Scdc and call typed methods:
use ;
let mut scdc = new;
// Version negotiation
let sink_ver = scdc.read_sink_version?;
scdc.write_source_version?;
// Enable TMDS scrambling
scdc.write_tmds_config?;
// Request an FRL rate
scdc.write_frl_config?;
// Poll for training readiness
let flags = scdc.read_status_flags?;
if flags.flt_ready
// Read per-lane character error counts
let ced = scdc.read_ced?;
if let Some = ced.lane0
To use culvert as the SCDC backend for plumbob's link training state machine, enable
the plumbob feature:
[]
= { = "0.1", = ["plumbob"] }
= "0.1"
Scdc<T> then implements plumbob::ScdcClient automatically.
Register coverage
| Register group | Addresses | Methods |
|---|---|---|
| Version | 0x01–0x02 | read_sink_version, write_source_version |
| Update flags | 0x10–0x11 | read_update_flags, clear_update_flags |
| TMDS / scrambling | 0x20–0x21 | write_tmds_config, read_scrambler_status |
| FRL config | 0x30 | write_frl_config |
| FRL status | 0x40–0x41 | read_status_flags |
| Character Error Detection | 0x50–0x57 | read_ced |
Registers not yet covered (RS Correction counters, DSC status, manufacturer
identification) are documented in doc/roadmap.md.
Features
| Feature | Default | Description |
|---|---|---|
plumbob |
no | Implements plumbob::ScdcClient for Scdc<T> |
no_std
culvert is #![no_std] throughout. All output types are stack-allocated; no allocator
is required in any configuration.
Stack position
flowchart LR
dt["display-types"]
hal["hdmi-hal"]
culvert["culvert"]
plumbob["plumbob"]
integration["integration layer"]
dt --> culvert
hal --> culvert
culvert -->|"implements ScdcClient"| plumbob
plumbob -->|"implements LinkTrainer"| integration
culvert does not depend on plumbob. The relationship runs the other way: enabling the
plumbob feature makes Scdc<T> implement plumbob::ScdcClient. Any crate that
implements ScdcClient is substitutable.
Out of scope
- Async API — an async variant will live in a separate
culvert-asynccrate. - Link training state machine — the sequencing of FRL training (rate selection, polling, fallback to TMDS) belongs in the link training crate. Culvert provides the register operations; the state machine decides when to call them.
- PHY configuration —
HdmiPhyoperations are the link training layer's concern. - I²C / DDC transport — platform backends implement
ScdcTransportfromhdmi-hal. Culvert never touches I²C directly.
Documentation
doc/setup.md— build, test, and coverage commandsdoc/testing.md— testing strategy, transport harness, and CI expectationsdoc/architecture.md— role, scope, register map, type reference, design principles, and the culvert / link training boundarydoc/roadmap.md— SCDC registers deferred to future releases
License
Licensed under the Mozilla Public License 2.0.