Skip to content

tune: SDM tuning link (SdmTuningLink) over the CCDI driver - #62

Merged
M0LTE merged 2 commits into
mainfrom
feat/sdm-tuning-link
Jul 12, 2026
Merged

tune: SDM tuning link (SdmTuningLink) over the CCDI driver#62
M0LTE merged 2 commits into
mainfrom
feat/sdm-tuning-link

Conversation

@M0LTE

@M0LTE M0LTE commented Jul 12, 2026

Copy link
Copy Markdown
Collaborator

Completes the SDM "side channel" pick (D) — the codec shipped in #59; this adds the link. Ports SdmTuningLink + SdmTuningLinkOptions from Packet.Tune.Core: send a TuningTelegram as a CCDI SDM datagram with retry + sequence-dedupe. Receipt-tolerant by default (wait_for_delivery_receipt=false) — returns on radio acceptance, retries only on a radio reject, and a delivered send with no over-air receipt is NOT an error (the TM8110 SDM auto-ack refractory suppresses receipts). Also adds the driver's a/s/q1 SDM send/read commands. Fixed-capacity dedupe ring, integer-only, no alloc-maps. +17 tests; clippy/no_std/fw-build all green.

🤖 Generated with Claude Code

Tom Fanning and others added 2 commits July 12, 2026 19:55
Add the CCDI Short Data Message commands the SDM tuning link rides on:
- send_sdm / send_extended_sdm — SEND_ADAPTABLE_SDM (`a`, GFI 2 / SFI 00|04),
  completing on the radio's prompt (acceptance); a reject surfaces as
  TaitError::Ccdi. The over-air delivery receipt (PROGRESS 1D) stays an
  unsolicited drain_events() event, deliberately not awaited.
- read_buffered_sdm_into — GET_SDM via QUERY type 1 (`q1`), zero-alloc copy into
  a caller buffer; empty buffer maps to None.

Mirrors TaitCcdiRadio.{SendSdmAsync,SendExtendedSdmAsync,ReadBufferedSdmAsync}
+ SendAdaptableSdmAsync's {leadIn:X2}{gfi}{sfi}{id}{msg} parameter layout.

Co-Authored-By: Claude Code <noreply@anthropic.com>
Port Packet.Tune.Core.SdmTuningLink (+ SdmTuningLinkOptions) onto the Tait
CCDI driver's new SDM commands. A TuningTelegram is compact-encoded to fit one
plain SDM and sent as a CCDI `a` datagram; the send retries only on a radio
command *reject* (fresh attempt, same sequence — the responder dedupes), and
the receive path dedupes inbound telegrams on their sequence number via a fixed
[i32; 64] evict-oldest ring (no HashSet, no alloc-map).

Critical default mirrored exactly: SdmTuningLinkOptions.wait_for_delivery_receipt
defaults FALSE — receipt-tolerant. A send completes as soon as the radio ACCEPTS
the datagram; a delivered send with no over-air delivery receipt is NOT an error
(the TM8110 auto-ack refractory suppresses the receipt for close bidirectional
SDM). WaitForDeliveryReceipt=true opt-in consults the receipt the driver demuxed.

no_std posture (matching the driver): the core is clock-free; only the
inter-attempt backoff is awaited through a tiny LinkDelay seam (fw = embassy,
host tests = no-op). The other duration knobs are carried faithfully but consumed
by the fw timing layer. Inbound is pull-based (poll_receive), not a channel.

Host tests over the driver's MemStream seam (+ a per-read ScriptStream for the
multi-attempt retry cases): successful send, retry-on-reject, exhaustion,
receipt-tolerant default, sequence dedupe, over-budget rejection, extended SDM,
option defaults, and the dedupe ring's evict-oldest. 12 tests.

Co-Authored-By: Claude Code <noreply@anthropic.com>
@M0LTE
M0LTE merged commit 4066fbe into main Jul 12, 2026
M0LTE added a commit that referenced this pull request Jul 12, 2026
docs(roadmap): reflect the XID/MDL + SDM-link wave (#62/#63)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant