Packet.Radio.Tait
0.18.0
See the version list below for details.
dotnet add package Packet.Radio.Tait --version 0.18.0
NuGet\Install-Package Packet.Radio.Tait -Version 0.18.0
<PackageReference Include="Packet.Radio.Tait" Version="0.18.0" />
<PackageVersion Include="Packet.Radio.Tait" Version="0.18.0" />
<PackageReference Include="Packet.Radio.Tait" />
paket add Packet.Radio.Tait --version 0.18.0
#r "nuget: Packet.Radio.Tait, 0.18.0"
#:package Packet.Radio.Tait@0.18.0
#addin nuget:?package=Packet.Radio.Tait&version=0.18.0
#tool nuget:?package=Packet.Radio.Tait&version=0.18.0
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
RssiTaggingTransportto stamp per-frame RSSI/SNR onto received AX.25 frames. - Hardware carrier-sense — unsolicited PROGRESS "receiver busy / not busy" messages become
CarrierSenseChangedevents + aChannelBusyproperty (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
TaitRadioHealthMonitorthat 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.
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.
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
- Source & issues
Packet.Radio— theIRadioControlcontract this implementsPacket.Tune.Core— link-tuning + mode coordination over the SDM side channel
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 | Versions 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. |
-
net10.0
- Packet.Ax25.Sdl (>= 0.10.0)
- Packet.Ax25.Transport.Abstractions (>= 0.18.0)
- Packet.Kiss (>= 0.18.0)
- Packet.Radio (>= 0.18.0)
- System.IO.Ports (>= 10.0.0)
NuGet packages (1)
Showing the top 1 NuGet packages that depend on Packet.Radio.Tait:
| Package | Downloads |
|---|---|
|
pdn-soundmodem
Headless soundcard packet modem core: IL2P/AX.25 framing and FEC now; demodulators, KISS TCP and DCD to follow. |
GitHub repositories
This package is not used by any popular GitHub repositories.
| Version | Downloads | Last Updated |
|---|---|---|
| 0.33.0 | 206 | 9/3/2026 |
| 0.32.0 | 104 | 9/3/2026 |
| 0.31.0 | 107 | 9/2/2026 |
| 0.30.0 | 115 | 8/23/2026 |
| 0.29.0 | 115 | 8/22/2026 |
| 0.28.0 | 112 | 8/22/2026 |
| 0.27.0 | 121 | 8/17/2026 |
| 0.26.0 | 136 | 8/17/2026 |
| 0.25.0 | 133 | 8/3/2026 |
| 0.24.0 | 128 | 7/20/2026 |
| 0.23.0 | 116 | 7/14/2026 |
| 0.22.0 | 122 | 7/14/2026 |
| 0.21.0 | 122 | 7/9/2026 |
| 0.20.0 | 127 | 7/5/2026 |
| 0.19.0 | 127 | 7/5/2026 |
| 0.18.0 | 137 | 7/5/2026 |