After the challenges I had with finding a bluetooth solution for APRS, I more or less gave up on using existing TNC solutions.

During my last installment, I started looking into the Arduino Uno R4 WiFi. It occurred to me that it has an ADC, so I started looking into whether or not anyone had used it as a TNC before. It looked like it had been tried – but with little success.

Since I was vibe-coding (I’ll admit- AI can write better code than me), I challenged ChatGPT with the project. I started back in December 2025 with a pretty broad scope, and it didn’t work well at all. I did get a few things working, such as packet generation (transmitting) and the BLE connection. Since I couldn’t get receive working, I started to get a little frustrated. I eventually tore the setup down – needed to finish my masters and all. I knew once I got moved, I could give it another shot.

A couple months later, I started picking the project back up.

One thing I learned during development of RevLogger was the need for a detailed software requirements as a part of the prompt. Before I started any hardware work, I began fleshing out the software requirements specification (SRS). As I found more and more features that I thought were important, I added as much detail as I could imagine.

After a bit, I reconnected the hardware, and began breaking down my biggest issues. Since receive was the biggest challenge, that’s what I started with. I intentionally broke the project down to JUST a receive development, while dumping other ideas into the SRS.

To satisfy the ADC, I used a couple 10k resistors to create a voltage divider between 5V and 0V, with the ADC input riding at 2.5V. I then coupled my computer audio output through a 100uF non-polarized cap into the ADC input.

One thing I did was start playing with the LED matrix to turn on an LED when a signal is present at the ADC input, and later on, a second light during packet decodes. Both of these were infinitely valuable during troubleshooting. While I was at it, I created a boot-image on the LEDs… hint.. it’s a squirrel.

because I’m using GPT, it took a lot of troubleshooting, and commands like “improve noise performance”, but eventually, i found a solution. the biggest issue was timing within the framing and decode string.

I eventually made a huge breakthrough when I could get some longer packets reliably decoded – this was a HUGE step in the right direction!

Once “we” got decide working, then it became a matter of messing with the framing and timing to get it to be reliable.

Next, it was time to re-tackle Bluetooth. One of my goals was to use this device with IOS and APRS.FI. The kiss over (BLE) protocol is very specific. I had it connected once… and it was time to recreate that.

Once I pulled my old code in and tweaked the service values, it connected! Then there was a need to get the two processors to pass traffic. There were a LOT of incremental builds to grow this capability, but it started working, and APRS.FI would display raw incoming packets.

I used the packet audio cd file (http://www.wa8lmf.net/TNCtest/) to see how it would do. Since this has a 45 minute recording of real world APRS, it was perfect. It wasn’t long before I was not only seeing packets, but able to watch them populate my map!

I was curious how it was really doing compared to commercial solutions, so I contacted NV4B to ask if he could run the CD against some old TNCs because Chris collects stuff. Ingot a response:

First, I needed a way to track decodes, so I added it. The TNC would now count decoded packets. Then I ran the entire 45 minute track. 845+ successful decodes. Wow!!

After this, I started adding a lot more commands to make this device command compatible with kantronics products. I’ve also been working the overall system architecture.

To save code space, the following system architecture is planned:

  • Hardware UART reserved for PC connection (like a kantronics)
  • I2C will be used to connect a real time clock
  • I2C will connect to a “I2C to UART” board, which will connect to a GPS module. This board will host 2 UARTs (though one will be unused for the moment) to allow for expansion, whether it be a weather station or another peripheral. I’ll also need to add firmware support for the weather stuff.

The biggest challenge is the SRAM limitation to avoid duplication (so we don’t digipeat something we already digipeated. I think we got that worked out.

As of now, I’m searching for another TNC to do some live testing with. I’ve decoded packets with an SDR on another computer, but that’s a sketchy setup.

I’m a bit concerned with how the WiFi / web UIs will pan out, but they should be simple enough. There’s also some functionality planned for the other features (foxhunt controller).

I’m also limiting GPS support to GGA, RMC, and one other sentence just to save space, and because these provide the position, time, and constellation data I am interested in.

As of now, here’s how the firmware has evolved to this point:

  • v0.1a — First integrated Bell-202 RX/TX core with AX.25/HDLC framing and the known-good transmit path.
  • v0.1b — Improved receive TRACK recovery after timing lock was lost.
  • v0.1c — Added a parallel fixed-phase safety decoder alongside the tracked decoder.
  • v0.1d — Added rolling Bell-202 occupancy logic to improve TRACK retention.
  • v0.1e — Added separate development indicators for software channel activity and actual packet/timing detection.
  • v0.1f — Fixed compile/scope problems introduced with quiet receive output.
  • v0.1g — Changed RX to decode continuously instead of gating the modem from the software carrier detector.
  • v0.1h — Ran all 8 fixed timing phases continuously and improved packet-acquisition quality.
  • v0.1i — Added 8 confidence-weighted soft/voted receive decoders; initial build exceeded available SRAM.
  • v0.1j — Recovered SRAM by shrinking diagnostic snapshots while preserving all 8 receive paths.
  • v0.1k — Hardened the software carrier/activity detector against noise without changing or gating the proven decoder; this became the practical RX baseline.
  • v0.2a — Added persistent configuration using versioned dual-slot EEPROM storage with CRC protection.
  • v0.2b — Added the first framed RA4↔ESP32 IPC framework.
  • v0.2c — Fixed Arduino auto-prototype/compiler problems in the IPC implementation.
  • v0.2d — Moved IPC onto the internal RA4↔ESP UART path and reduced diagnostic RAM usage enough for reliable compile/runtime.
  • v0.2e — Added 
    IPC_RX_FRAME
    , forwarding each unique CRC-valid AX.25 receive frame to the ESP32 without altering the modem.

ESP32-S3 bridge revisions

  • v0.1 — First attempt at adding TreeRat IPC functionality to the Arduino UNO R4 WiFi USB bridge.
  • v0.2 — Improved patch placement and bridge integration, but source matching was still fragile.
  • v0.3 — Changed the patcher to regex-based matching; exposed a missing Python 
    re
     import.
  • v0.4 — Fixed the Python patcher issue, but the build process still masked underlying compile failures.
  • v0.5 — Changed the builder to fail immediately on compiler errors, exposing corruption of the Arduino bridge source.
  • v0.6 — Rebuilt the patching process around a clean upstream Arduino bridge checkout and successfully preserved normal USB/programming operation.
  • v0.7 — Corrected the physical RA4↔ESP IPC UART to ESP GPIO6/GPIO5 / Serial1 and disabled the conflicting stock AT task.
  • v0.8 — Added reception and human-readable diagnostic display of 
    IPC_RX_FRAME
     packets from the RA4.

Major functionality now proven

At this point we have demonstrated:

  • Bell-202 1200-baud receive on A1.
  • Bell-202 transmit on A0.
  • AX.25 HDLC framing, bit stuffing, NRZI, and FCS handling.
  • Real over-the-air TX decoding by another receiver.
  • Real-world RX decoding of multiple live/noisy packet frames.
  • Continuous 8-phase receive decoding with confidence-weighted paths.
  • Software carrier/activity detection separated from actual modem decoding.
  • Configurable 
    CORSENS
    .
  • Persistent configuration surviving power cycles.
  • MYCALL, destination, paths, TX delay/tail, persistence, slot time, full-duplex, carrier settings, and COS settings stored in EEPROM.
  • Framed RA4↔ESP IPC with CRC and sequence numbers.
  • HELLO / heartbeat / CONFIG_GET / CONFIG_SNAPSHOT exchange.
  • Normal UNO R4 USB programming and terminal operation preserved while running custom ESP firmware.
  • Correct physical RA4↔ESP communication over the board’s internal GPIO6/5 UART.
  • Raw CRC-valid AX.25 frames transported successfully from RA4 to ESP.
  • Multiple consecutive 
    IPC_RX_FRAME
     packets received intact by the ESP.
  • ESP AX.25 diagnostic formatting including digipeater 
    *
    /H-bit information.
0.2eProven RA4 baseline: Bell-202 RX/TX, HDLC, AX.25, FCS, IPC RX forwarding
v0.2fEarly IPC TX-frame support
v0.2hAdded 
RXCOUNT
 / 
RXCOUNT RESET
v0.3a–bExpanded KPC-style command shell
v0.3cFunctional CSMA/p-persistence TX scheduling
v0.3dCompile fixes
v0.3eSRAM fix by reducing large debug snapshot usage
v0.3fFinalized/froze 
CORTUNE
 / 
CORSENS
 behavior
v0.3gFunctional 
BEACON
BCNOW
BTEXT
UNPROTO
 beacon path
v0.3hAdded 
COR PACKET
 / 
COR SQUELCH
 behavior for 
BEACON AFTER
v0.3iFunctional UI digipeater: 
DIGIPEAT
UIDIGI
UIDUPE
UIDWAIT
UIFLOOD
UITRACE
v0.3jAdded 
DIGITEST
; enlarged duplicate cache to 64 compact entries
v0.3kMemory housekeeping: removed deep modem-development RAM usage, reduced TX buffer, moved LUT out of SRAM
v0.3lI²C/RTC/UART-bridge foundation branch — shelved pending hardware
v0.3mFirst functional AX.25 connected-mode engine
v0.3nConnected-mode compile fix
v0.3oFixed 15-byte AX.25 control-frame TX; connected-mode synthetic tests passed
v0.3pKPC-style 
MONITOR
MCOM
MCON
, converse/monitor formatting
v0.3qReal 
ECHO ON/OFF
; duplicate-I handling, RNR/REJ robustness
v0.3r
PACLEN
SENDPAC
, held-packet logic, VIA-path reversal/test
v0.3sAdded 
CMD
 / 
COMMAND
 escape for Arduino Serial Monitor; synthetic 
CONNTEST ACK
v0.3tFixed printable SENDPAC handling with Arduino CR/LF; cleaned buffer-full behavior
v0.3uFunctional 
MHEARD
MHCLEAR
MSTAMP
MHEADER
MRPT
, plus real-RF heard-list tracking

Leave a Reply