M0LTE.Tait.Codeplug
0.8.0
dotnet add package M0LTE.Tait.Codeplug --version 0.8.0
NuGet\Install-Package M0LTE.Tait.Codeplug -Version 0.8.0
<PackageReference Include="M0LTE.Tait.Codeplug" Version="0.8.0" />
<PackageVersion Include="M0LTE.Tait.Codeplug" Version="0.8.0" />
<PackageReference Include="M0LTE.Tait.Codeplug" />
paket add M0LTE.Tait.Codeplug --version 0.8.0
#r "nuget: M0LTE.Tait.Codeplug, 0.8.0"
#:package M0LTE.Tait.Codeplug@0.8.0
#addin nuget:?package=M0LTE.Tait.Codeplug&version=0.8.0
#tool nuget:?package=M0LTE.Tait.Codeplug&version=0.8.0
M0LTE.Tait.Codeplug
A Tait TM8100/TM8200 codeplug library, reverse-engineered from Free Serial Analyzer captures of the Windows CPS. It reads and writes the codeplug over the serial programming interface without the CPS, exposes a typed, version-pinned field map for the whole CPS Data form and the channel table, and applies the Packet.NET (PDN) upgrade profiles. The read + write path is hardware-validated against a real TM8100.
The CLI front-end that ships from the same repo, tait-codeplug, is a thin layer over this library:
see github.com/M0LTE/tait-codeplug for prebuilt binaries.
The protocol, in short
- ASCII-hex, line-oriented, CR-terminated, strictly lock-step (every command gets one
>prompt before the next). - Records share the
.m8pframing<addr:4hex><len:2hex><data><checksum:2hex>; checksum is the CCDI-family negated sum over the decoded bytes (whole record sums to 0 mod 256).addris(section << 8) | index. - Session:
^(reset →v),#(enter programming →>),ld→{C05},d00→{C01}. Read a section:r<section>. Write:b,i<arg>, a run ofw<record>,e. Teardown:^. - Baud opens at 9600, switches to 19200 for the transfer.
The full write-up is in docs/research/tait-codeplug-protocol.md
and the programming brief it came from is docs/research/tait-codeplug-programming-brief.md,
both in the packet.net repo where this code started life.
What is here
CodeplugChecksum/CodeplugRecord/CodeplugImage- the record model, checksum, and .m8p load/save + section map. Fully offline and unit-tested.Fields/- the typed, version-pinned field map (CodeplugFields,CodeplugEnums,ChannelBits): channels (frequency, bandwidth, power, split-TX, CTCSS/DCS), the whole CPS Data form (its General, Serial Communications, RF Modems, SDM and TOTAL Transparent Mode tabs live in the one data/signalling record; the GPS and Customer Data tabs are separate records; plus the unit data identity), and audio taps. Each field is pinned by a test.FieldConsole- name/value access used by thedump/get/setCLI verbs.CodeplugFields.ApplyPdnBasic()/ApplyPdnExtra()- the two PDN upgrade profiles (see below).ISerialLine/SerialPortLine- the byte seam (mirrorsPacket.Radio.Tait.ISerialIo); tests substitute a scripted mock radio.TaitProgrammer- the lock-step transport state machine (connect, interrogate, read, write).
Using it
using M0LTE.Tait.Codeplug;
// Offline: load a CPS .m8p save and read a field.
CodeplugImage image = CodeplugImage.LoadM8p(File.ReadAllText("radio.m8p"));
CodeplugFields fields = CodeplugFields.Open(image);
Console.WriteLine(FieldConsole.Get(fields, "ch0.bandwidth"));
// Live: read the codeplug off a radio latched into programming mode (power-cycle it as you connect).
using var programmer = new TaitProgrammer(new SerialPortLine("/dev/ttyUSB0"));
CodeplugImage live = programmer.ReadImage();
PDN upgrade profiles
Two composable patches that upgrade a radio to the Packet.NET feature set without touching its RF config (channels, frequencies, power), so they layer safely onto a radio already provisioned for its environment. They change only the data record (0x09). For a radio arriving from a foreign application, prefer a clean flash of a full codeplug first, then apply a profile.
pdn-basicenables the CCDI command channel that carriesPacket.Radio.Tait's telemetry and control: averaged/instantaneous RSSI, forward/reverse power, PA temperature, status/identity, transmitter keying, and the PROGRESS stream for carrier-sense (DCD) and external-PTT edges. It sets CCDI-mode-allowed on, power-up state to Command (so the radio is always CCDI-reachable), progress messages on, and the command baud to 28800.pdn-extraincludespdn-basicand adds the TNC-less internal FFSK packet modem plus the SDM side channel used for mode signalling: transparent mode on, ignore-escape-sequence off (so the transport can escape back to command mode - without this the radio wedges), ignore-subaudible on the data path, the transparent terminal baud (28800) and over-air FFSK baud (2400), and SDM + CCDI SDM output. The over-air baud must match at both ends; adjust the bauds and the data port for your setup.
Status and safety
The read + write path is hardware-validated against a real TM8100 (a same-image write round-tripped every writable record byte-identical), and the field map is validated field-by-field against real-radio CPS saves. Field writes are byte-identical to the CPS's own saves. Safety rails:
- Snapshot the current codeplug before writing (the CLI's
patchverb does this automatically). - Codeplug region only - this never writes firmware.
- Version-pin: the write path refuses a radio whose database version is not in its validated set (currently 0094 / 0095); the field offsets are version-specific.
- The field map enforces the CPS's own input rules (value ranges, character sets, and the "only available if ..." availability dependencies), so the library will not write a state the CPS rejects.
- Bench on a sacrificial radio first, and re-read (after a power-cycle) to verify a write.
A single-record write is acked but not committed by the radio, so a live field change writes the whole codeplug; that is the validated write path.
Licence
AGPL-3.0-or-later. See LICENSE.
| 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
- System.IO.Ports (>= 10.0.11)
NuGet packages
This package is not used by any NuGet packages.
GitHub repositories
This package is not used by any popular GitHub repositories.