I small introduction of the current FlexPacket version on my #hamradio blog. There you will also find the latest AppImage for Linux. And yes, I changed the look and feel. đ
I small introduction of the current FlexPacket version on my #hamradio blog. There you will also find the latest AppImage for Linux. And yes, I changed the look and feel. đ
Hamfest packet radio goodie.
Suspected to be from the former Finnish packet radio network.
1200baud 1200MHz band backhaul link with TAPR TNC-2 clone.
Building an AX.25 Messenger App with C#, a TNC, and a Bit of Madness
1,046 words, 6 minutes read time.
YT MD-UV390 Digital Dual Band VHF UHF DMR Radio Waterproof Dustproof IP67 Walkie TalkieIt started with a simple idea â or at least it seemed simple. I was chatting with AI about ways to send text messages from device to device using nothing but the speakers and microphones already built into our phones or laptops. The idea was to modulate the data into frequencies just outside the human hearing range and transmit them. AI made it sound easy â encode, send, decode. But once I actually started trying to do it, it quickly became clear: it wasnât simple at all. It wasnât even close.
That failure wasnât the end â it was the beginning. Because during that process, I remembered that I already owned something built for this kind of thing: a Mobilinkd TNC3. It connects via Bluetooth or USB, speaks the AX.25 protocol over KISS, and communicates via AFSK. And so, a new plan was born â use existing amateur radio tech to send messages between devices. But I didnât just want to use the TNC â I wanted to understand what it was doing. That meant learning AX.25, digging into KISS, and writing everything from scratch in C#.
The Stack: Tools and Hardware
For this build, I used:
Why AX.25?
The Mobilinkd TNC3 operates using the AX.25 protocol layered over KISS. If you want to send messages through this hardware, you have to understand those protocols. AX.25, originally developed for packet radio in amateur radio use, is efficient, compact, and battle-tested.
I dove into it because the hardware required it â but what I found was something elegant. The structure is simple enough to understand but flexible enough to do real work. That said, actually implementing it in C# was another story.
Writing the AX.25 Messenger
The goal of the app was simple: send and receive short text messages over radio using the Mobilinkd TNC3 and AX.25 protocol.
The project is open source. You can find the code here:
đ GitHub Repository: AX25Messenger
Letâs walk through some of the key components.
1. Encoding an AX.25 Frame
Hereâs what the code looks like when we build the raw AX.25 frame. We start with destination and source callsigns, then add control and protocol fields, and finally append the actual payload.
public byte[] CreateAX25Frame(string destination, string source, byte[] payload){ var frame = new List<byte>(); // Encode callsigns frame.AddRange(EncodeCallsign(destination, false)); frame.AddRange(EncodeCallsign(source, true)); // Control field (0x03 = UI frame) frame.Add(0x03); // Protocol ID (0xF0 = no layer 3 protocol) frame.Add(0xF0); // Add payload frame.AddRange(payload); return frame.ToArray();}
This code constructs the complete AX.25 frame for a UI (Unnumbered Information) packet. The EncodeCallsign
method handles shifting and bit manipulation, making it compatible with the standard.
2. Interfacing with the TNC over KISS
KISS is a framing protocol that wraps the AX.25 data for transmission over a serial port. Hereâs how we encapsulate an AX.25 frame into a KISS frame.
public byte[] WrapKISSFrame(byte[] ax25Frame){ var kissFrame = new List<byte>(); kissFrame.Add(0xC0); // Start delimiter kissFrame.Add(0x00); // Command byte: TNC Data frame foreach (var b in ax25Frame) { if (b == 0xC0) { kissFrame.Add(0xDB); kissFrame.Add(0xDC); } else if (b == 0xDB) { kissFrame.Add(0xDB); kissFrame.Add(0xDD); } else { kissFrame.Add(b); } } kissFrame.Add(0xC0); // End delimiter return kissFrame.ToArray();}
This makes the AX.25 message digestible by the TNC.
3. Sending the Data
Once the KISS frame is ready, itâs sent out the serial port like this:
_serialPort.Write(kissFrame, 0, kissFrame.Length);
Where _serialPort
is an instance of SerialPort
in .NET. Simple, fast, and effective.
The Frustrations of Learning While Building
There were many moments during this project that made me want to throw the whole setup out the window. Trying to learn AX.25 and KISS while building an app around them is painful. The documentation is scattered, and much of whatâs out there is old, inconsistent, or assumes a Linux environment.
It didnât help that most of the time, you canât even tell if your code is broken or if the radio just didnât key up fast enough. Debugging means digging into the bits of a failed frame, then trying again and hoping for a clean transmission.
And then thereâs AI â which was extremely helpful in doing early code research, mocking up skeletons, and pointing me toward technical docs. But it also hallucinated like crazy when it came to niche protocols. AI tends to guess at how it should be coded when it doesnât have enough training data, and this project was definitely in that category. I had to train the AI by teaching it the protocol myself before it became useful.
What Didnât Work
One major limitation of this build: I wasnât able to test incoming AX.25 messages yet. That part of the project is still under construction. The receive pipeline, decoding the AX.25 frame, and confirming messages are cleanly parsed is a work in progress. Itâs the next big hurdle.
Conclusion: A Love Letter to Low-Level Protocols
This whole build was a reminder that sometimes the best learning comes from the weirdest places. I didnât plan to learn how AX.25 worked. I definitely didnât plan to write a whole C# interface to a hardware modem. But here we are.
This was a project of persistence, curiosity, and a refusal to let a good idea die. If youâre into coding, radios, or just learning things the hard way, I canât recommend it enough.
Follow the project on GitHub: AX25Messenger.
And if you enjoyed this write-up or want to follow along as I dive deeper into protocols, microcontrollers, or strange networking ideas, be sure to subscribe to the newsletter.
D. Bryan King
Sources
Disclaimer:
The views and opinions expressed in this post are solely those of the author. The information provided is based on personal research, experience, and understanding of the subject matter at the time of writing. Readers should consult relevant experts or authorities for specific guidance related to their unique situations.
Related Posts
#AFSKModem #AIInRadioProjects #AmateurRadio #amateurRadioTNC #APRSMessaging #AX25 #AX25CCode #AX25Examples #AX25ForProgrammers #AX25LearnByCoding #AX25RawFrames #AX25WithMobilinkd #AX25CMessenger #AX25DigitalMode #AX25Modem #AX25ParserC_ #AX25Protocol #ax25TestSetup #buildingAX25Apps #CAFSKDecoding #CAndKissProtocol #CAndPacketRadio #CAX25 #CHamToolkit #CProjectAX25 #CRadioApp #digitalModeCCode #digitalRadioMessage #hamRadioAndProgramming #hamRadioCExamples #hamRadioCoding #hamRadioCodingTutorial #hamRadioProgramming #hamRadioProtocol #kissAndAfsk #kissCProtocol #kissDecoderTutorial #kissInterface #KISSProtocol #kissProtocolC_ #kissProtocolExample #kissTnc #learnAX25 #learningPacketRadio #MobilinkdTNC3 #packetRadio #packetRadioDev #packetRadioOverAudio #radioMessageApp #radioTextOverAfsk #radioToRadioMessaging #realTimeRadioMessaging #serialRadioCommunication #TNC3AndKiss #TNC3HardwareGuide
A silly protocol idea has been brewing in my mind⊠CoAP over AX.25.
The thinking is this⊠use UI frames to encapsulate CoAP messages in the same manner as UDP and use a URI scheme like coap+ax25://DEST[,DIGI1[,DIGI2âŠ]]/[path]
If DEST has the C/H bit clear, DEST is a "multicast" group, otherwise it's a specific amateur station.
File transfer just uses RFC-7959 [block-wise transfer] (with possibly a small extension inspired by RFC-2090 [TFTP Multicast] to allow Block1 transmissions to a multicast group).
That would allow file transfer and messaging between stations using existing AX.25 packet radio hardware.
- https://datatracker.ietf.org/doc/html/rfc7252 - CoAP RFC
- https://datatracker.ietf.org/doc/html/rfc7959 - Blockwise transfers over CoAP
- https://datatracker.ietf.org/doc/html/rfc2090 - TFTP Multicast
- https://ax25.net/ - AX.25 protocol specs and docs
Are there any ham radio packet BBS systems that I can connect to via the Internet? Ideally East Coast US.
I don't have the ability to connect to packet nodes local to me. My ham shack is down pending remodeling. I'd still like to poke around from a Linux box over SSH or Telnet if I can just to see what it's like.
For all you #PacketRadio folks, checking to see that my whitepages entry is working.
can someone send me a packet message to:
KB8QPT
Thanks!
It looks like APRS has competition in the form of the CATS protocol. https://cats.radio/
Is there a node map, equivalent to aprs.fi for this protocol?
I am mulling over creating a website and a #GeminiCapsule for those interested in getting started in #PacketRadio . I was thinking that it might be cool to be able to post a listing to the #PacketBBS and allow users to request info via packet, but proxy through #Gemini
This should be possible, as my node can play #Zork
with the latest changes, 7Plus works very well with my flexpacket #packetradio terminal. đ„ł
đ Oh joy, another "lightweight" protocol to complicate your life with packet radios! Because what we really needed was yet another GitHub project with a name only a tech hipster would loveâMeshCore. đ€Šââïž But hey, at least you get to "automate any workflow" while drowning in #buzzwords.
https://github.com/ripplebiz/MeshCore #lightweightprotocol #packetradio #MeshCore #automation #HackerNews #ngated
I've add a new feature in Flexpacket. Flexpacket will store chosen mails automatically therefore we can read them later offline. Thats a helpfull feature for very long mails. :-) I've tested it with OpenBCM. If it's not working with your home PBBS, please open an issue and add the whole Mail (include header data). đ #hamradio #packetradio #ax25
In other news, a copy of Jan Axelsonâs âUSB Completeâ 5th edition arrived today. Hoping it can help me make sense of USB Audio 2, so I can make progress on my #RaspberryPiPico project! #PacketRadio #Embedded #HamRadio
I just set up a node too, after 35 years away from #PacketRadio
if you want to try and send a message,my address is:
KB8QPT@KD8FTR.#NEOH.OH.USA.NOAM
thanks!
I think i have a working #HomeBBS on VHF #PacketRadio.
If someone wants to send me a bbs message, that would be awesome. My address is:
KB8QPT@KD8FTR.#NEOH.OH.USA.NOAM
if you post your address, I'll try sending you a message.
thanks!
So, I am finally updating my #GeminiCapsule #Gemlog .
This time, it's about getting my #PacketRadio station put back up for the first time since like 1992. it works!
But this posting makes me wonder about the present state of the #Gemini protocol. More later.
gemini://gemini.sergio101.com/posts/fun-with-packet-radio.gmi
It's back to the future for packet radio. I just reflashed my Kantronics KAM-XL (vintage 2005 or so) with new firmware.
After a few mistakes - Kantronics wasn't expecting a .hex file with Unix line terminators, and there were an awkward few minutes when it would say "upload now" then "upload failed" right after - my TNC now boots up with a version from August 2024.
Who knew they were still doing development?
#hamRadio #packet #tnc #kantronics #packetRadio #AmateurRadio
In 2021, the german #DARC received 179,690⏠from the #ARDC to correct and update the #Linux #AX25 #packetradio #kernel stack.
https://www.ardc.net/apply/grants/2021-grants/grant-fixing-the-linux-kernel-ax-25/
Since that day, NOTHING is available anywhere. The dedicated web site (linux-ax25.org) is non-existant and all about this project (and the money) vanished.
Has anyone any information about the status of this project? Where is the code? Where the money went?
So, I've been learning #GraphDatabases with #Neo4j this week. I think it would be SUPER fun to recursivlely do an mheard on all the #PacketRadio nodes, to help establish paths around the country.
Just casually playing with old #ham #msdos #packetradio software #GraphicPacket, my favorite in the 90's, in a #DosBoxX window.
I'm thrown 30 years back and thrilled to have managed to make it work with a #KISS modem and #TFKISS resident driver (a NordLink TNC2 "TheFirmware" emulator for MSDOS).
Btw, I am preaparing some real hardware (Pentium 233) to make that work on, with a legendary 1200 bauds packet-radio #BayCom modem...