Packet.Radio.Tait 0.23.0

dotnet add package Packet.Radio.Tait --version 0.23.0
                    
NuGet\Install-Package Packet.Radio.Tait -Version 0.23.0
                    
This command is intended to be used within the Package Manager Console in Visual Studio, as it uses the NuGet module's version of Install-Package.
<PackageReference Include="Packet.Radio.Tait" Version="0.23.0" />
                    
For projects that support PackageReference, copy this XML node into the project file to reference the package.
<PackageVersion Include="Packet.Radio.Tait" Version="0.23.0" />
                    
Directory.Packages.props
<PackageReference Include="Packet.Radio.Tait" />
                    
Project file
For projects that support Central Package Management (CPM), copy this XML node into the solution Directory.Packages.props file to version the package.
paket add Packet.Radio.Tait --version 0.23.0
                    
#r "nuget: Packet.Radio.Tait, 0.23.0"
                    
#r directive can be used in F# Interactive and Polyglot Notebooks. Copy this into the interactive tool or source code of the script to reference the package.
#:package Packet.Radio.Tait@0.23.0
                    
#:package directive can be used in C# file-based apps starting in .NET 10 preview 4. Copy this into a .cs file before any lines of code to reference the package.
#addin nuget:?package=Packet.Radio.Tait&version=0.23.0
                    
Install as a Cake Addin
#tool nuget:?package=Packet.Radio.Tait&version=0.23.0
                    
Install as a Cake Tool

Packet.Radio.Tait

Tait TM8100/TM8200 mobile-radio control over CCDI — the driver that gives the Packet.NET stack RSSI, hardware carrier-sense, PTT, and a radio-native side channel.

A Packet.Radio IRadioControl implementation for Tait TM8100/TM8200 radios over CCDI (the Computer-Controlled Data Interface — the radio's serial command protocol). Wire it to RssiTaggingTransport and RadioCarrierSense (the ICarrierSense bridge the AX.25 stack's native CSMA gate consults) and a bare KISS packet link gains per-frame signal metadata and hardware carrier-sense CSMA. Part of Packet.NET, a .NET amateur-radio / AX.25 packet stack.

Install

dotnet add package Packet.Radio.Tait

What it surfaces that a bare KISS modem cannot

  • RSSI in dBm (CCTM queries 063/064, 0.1 dB resolution) — feed RssiTaggingTransport to stamp per-frame RSSI/SNR onto received AX.25 frames.
  • Hardware carrier-sense — unsolicited PROGRESS "receiver busy / not busy" messages become CarrierSenseChanged events + a ChannelBusy property (a true RF-level DCD).
  • Transmitter keying (SetTransmitterAsync) — CCDI-forced TX ignores the radio's TX timer, so the driver unkeys on dispose if you left it keyed through it.
  • Telemetry + health — PA temperature (CCTM 047), forward/reverse power detector readings (CCTM 318/319, an antenna-health proxy while transmitting), and a periodic TaitRadioHealthMonitor that trends them: idle-offset-corrected fwd/rev + ratio (a TREND, never VSWR — the detectors are raw √P-scaled millivolts per Tait's service docs), typed sample events + rolling min/median/max summaries.
  • Identity — model/tier, CCDI version, serial number, firmware/hardware version inventory.
  • An escape hatch (TransactRawAsync) for CCDI commands the driver doesn't model yet — framing and checksumming handled, responses returned decoded.
  • A station-control view (TaitRigControl) — re-presents the radio through the Packet.Rig IRigControl abstraction (the same seam the hamlib/rigctld and flrig backends implement), advertising the slice CCDI can honestly serve: PTT set/get and a relative RF-power meter (the CCTM 318 forward detector over its full scale). Frequency, mode, SWR and watts are deliberately unadvertised — the tuned frequency isn't CCDI-readable, the radio has no mode concept, and the power detectors are raw √P-scaled millivolts, not calibrated units. Cross-backend rig consumers feature-probe RigCapabilities and get exactly what's real.

Usage

await using var radio = TaitCcdiRadio.Open("/dev/ttyUSB0"); // 28800 8N1 default
await radio.SetProgressMessagesAsync(true);                 // per-session: enables DCD events

var id = await radio.QueryIdentityAsync();                  // e.g. "Tait TM8110", serial, versions
float rssi = await radio.ReadRssiDbmAsync();                // e.g. -90.3
radio.CarrierSenseChanged += (_, e) => Console.WriteLine($"DCD {(e.Busy ? "up" : "down")} at {e.At:O}");

The radio must be programmed with its data port in Command mode (the power-up state) at the matching baud rate. (For the TNC-less FFSK link, TaitTransparentTransport drives the Transparent-mode enter/escape for you — see below.)

TNC-less AX.25: the FFSK Transparent transport

TaitTransparentTransport is an IAx25Transport whose modem is the radio — no external TNC. It puts the radio into Transparent mode (the radio's own FFSK modem as an 8-bit-clean byte pipe), frames AX.25 with KISS SLIP framing over that pipe, and de-frames the inbound byte stream back into whole AX.25 frames (the radio fragments/reassembles ≤46-byte over-air blocks itself). Because the transport owns the transmission it times it directly: a TxTiming event and ITxCompletionTransport give per-frame on-air start/end, and inbound frames carry ReceivedAt + RadioMetadata.EstimatedAirtime.

await using var link = await TaitTransparentTransport.OpenAsync("/dev/ttyUSB0");
await link.SendAsync(ax25FrameBody);            // SLIP-framed over the FFSK pipe
await foreach (var f in link.ReceiveAsync(ct))  // whole AX.25 frames, ReceivedAt + airtime stamped
    Handle(f.Ax25, f.ReceivedAt, f.Radio?.EstimatedAirtime);
// DisposeAsync escapes Transparent (+++) and restores Command mode.

The inherent trade-off vs the RssiTaggingTransport (NinoTNC modem + CCDI control channel) arrangement: one device, no audio wiring, but no signal telemetry — RSSI/SNR/noise-floor/DCD are unavailable while the CCDI channel is a byte pipe (those RadioMetadata fields stay null; only airtime is known). ⚠ If the radio is programmed with "Ignore Escape Sequence" on, the +++ exit cannot succeed and recovery is a power cycle — program the escape sequence honoured before running it unattended.

Beyond telemetry

The driver models the rest of the documented surface: channel report/change (QueryCurrentChannelAsync / GoToChannelAsync), CANCEL / DIAL, and SDM short-data messages — radio-to-radio, no TNC: plain 32-character (SendSdmAsync) and extended 128-character (SendExtendedSdmAsync), requiring SDMs enabled in the radio's programming. TaitSdmSideChannel exposes SDMs as a Packet.Radio.IRadioSideChannel, the mode-agnostic coordination plane the tuning / mode-negotiation stack rides. Also: display query, Transparent mode (the radio's own FFSK/THSD modem as a byte pipe), a keep-alive watchdog (ConnectionState + events; probes on link silence, self-heals on recovery), port auto-detection (TaitRadioPortDiscovery — probes candidate ports with a MODEL query and identifies radios by CCDI serial number), and the whole CCR mode (TaitCcrSession, TM8100 only): run-time RX/TX frequency in Hz, TX power, bandwidth, CTCSS/DCS, Selcall encode/decode events, volume, and the pulse ping.

⚠ SDM delivery receipts are unreliable for close bidirectional traffic

The over-air SDM delivery receipt (CCDI PROGRESS 1D, para 1=ack / 0=nak) is not a dependable delivery signal when two radios exchange SDMs back-and-forth within a few seconds — as a coordination protocol does. Bench-characterised on 2× TM8110 (CCDI 03.02): a radio captures its send's receipt only if it has not transmitted an SDM auto-acknowledge since its previous send and ≥~9 s have elapsed since its last auto-ack; otherwise it reports NAK after the ~6 s timeout. Crucially the SDM payload is delivered every time regardless — only the receipt is lost. Full characterisation and proof: docs/research/tm8110-sdm-autoack-refractory.md.

Guidance: treat the receipt as an optimistic fast-path only — never fail delivery on its absence. For reliability, confirm at the application layer (the peer's reply). Auto-ack itself is a codeplug (programming-application) setting, not a runtime toggle — there is no f-command to disable it; a radio you own can have "SDM Auto Acknowledge" turned off in its codeplug to remove the effect and save the ack airtime, but you cannot assume that on radios you don't program.

CCR-over-SDM ⚠ experimental / unsafe

UnsafeSendCcrOverSdmAsync transmits a CCR command into another radio over the air — remote control that can retune, re-power, or key the target, with no consent handshake in the protocol. It is [Experimental] (PKTTAIT001) and carries the Unsafe prefix deliberately: a radio not already in CCR mode simply ignores it (immune), but any real deployment needs an application-layer consent/auth gate first — keep it to bench tooling and radios you own. See the CCDI spike doc.

See also

Verified on hardware: 2× TM8110 (TMAB12-B100, CCDI 03.02, firmware 02.18.00.00). On that firmware the CCDI-side TX-power set (FUNCTION 0/7) answers "unsupported command" — but the CCR-mode power command works, so power control lives on TaitCcrSession.

Status: experimental, spike-born (plan §5.10 Phase 10). Protocol reference: Tait MMA-00038-06 "TM8100/TM8200 CCDI Protocol Manual".

Product Compatible and additional computed target framework versions.
.NET net10.0 is compatible.  net10.0-android was computed.  net10.0-browser was computed.  net10.0-ios was computed.  net10.0-maccatalyst was computed.  net10.0-macos was computed.  net10.0-tvos was computed.  net10.0-windows was computed. 
Compatible target framework(s)
Included target framework(s) (in package)
Learn more about Target Frameworks and .NET Standard.

NuGet packages (1)

Showing the top 1 NuGet packages that depend on Packet.Radio.Tait:

Package Downloads
Packet.Tune.Core

Coordination primitives for tuning a NinoTNC + radio pair with the two ends apart: the tuning-telegram protocol (ITuningLink), an SDM flavour riding the radio's own side channel (Packet.Radio.IRadioSideChannel; Tait CCDI short data messages — radio-native FFSK, independent of the TNC mode/pot under tune), a WebSocket flavour with a PIN-rendezvous relay, the shared meter/tuned assistant loop, a mode-coordination protocol (propose/confirm/commit a TNC mode + radio channel switch, probe-verify, revert-to-home on failure), and a capability doctor for the whole TNC↔radio stack. Source: github.com/packet-net/packet.net.

GitHub repositories

This package is not used by any popular GitHub repositories.

Version Downloads Last Updated
0.23.0 57 7/14/2026
0.22.0 88 7/14/2026
0.21.0 99 7/9/2026
0.20.0 107 7/5/2026
0.19.0 105 7/5/2026
0.18.0 112 7/5/2026