User Tools

Site Tools



The N9600A is a USB interfaced multi bitrate USB KISS TNC, supporting modulations suitable for all bands and both FM and SSB. The NinoTNC is designed by Nino KK4HEJ for use in Amateur Radio packet data networks. The 2400 baud DPSK modem supports many microphone-audio transceivers, and 4800 baud GFSK is great for use in data-radio/9600 transceivers which don't quite cut it for 9600 baud. On top of that, it supports both AX.25 for compatability with legacy TNCs, and a new link-layer encoding scheme called IL2P which is a Forward Error Correction equipped protocol designed to be more efficient than AX.25, recently with added CRC for better error rejection.

The N9600A NinoTNC provides a USB serial interface at 57600 baud.

More information mailing list

Group Buys

OARC has run two successful UK/EI group buys, with around 250 kits distributed across two rounds.

There are no current plans for another group buy, however never say never.

Board + CPU sets are available in the UK, see below.

Here is information on ordering a set of components to build up a NinoTNC. It's fast and easy.

UK Stock

By arrangement, Tom M0LTE will be holding stock of PCB + microcontroller only kits in the UK starting mid August. This will be on an ongoing basis. These will be available with circa 2 day shipping from Two sets of components from Mouser takes you over their free shipping threshold.

Operating modes

Current modes as of firmware release 3.3.1:

Mode Baud bps Mod Protocol Intended mode BW Typical use
0010 9600 9600 GFSK IL2P+CRC FM 25k Current recommended mode for new 70cm (25kHz) links where both ends are compatible
0100 4800 4800 GFSK IL2P+CRC FM 12.5k Current recommended mode for new 2m (12.5kHz) links where both ends are compatible
0101 2400 2400 DPSK IL2P FM 12.5k For situations where only a speaker/mic connection is available but > 1200 baud is desired
1011 1200 2400 QPSK IL2P+CRC SSB/FM 2.4kHz HF - quadrature version of 1200 BPSK, twice the throughput for +3dB SNR.
1010 1200 1200 BPSK IL2P+CRC SSB/FM 2.4kHz HF - use for circuits where wider transmission is acceptable.
1001 300 600 QPSK IL2P+CRC SSB 500Hz HF - quadrature version of 300 BPSK, twice the throughput for +3dB SNR
1000 300 300 BPSK IL2P+CRC SSB 500Hz HF - slowest but best performing mode. ~7dB better than classic 300 baud FSK AX.25
1110 300 300 AFSK IL2P+CRC SSB 500Hz CRC improvement of IL2P 300 baud AX.25. Recommended if you can't do BPSK / QPSK on HF.

Superseded (but still supported) modes:

Mode Baud bps Mod Protocol Superseded by Intended mode BW Typical use
0000 9600 9600 GFSK AX.25 9600 GFSK IL2P FM 25k Backwards compatibility with legacy G3RUH modems
0001 9600 9600 GFSK IL2P 9600 GFSK IL2P+CRC FM 25k Backwards compatibility. Obsoleted by 9600 GFSK IL2P+CRC
0011 4800 4800 GFSK IL2P 4800 GFSK IL2P+CRC FM 12.5k Debugging against 4800 GFSK IL2P+CRC in case of issues with the CRC mode
1111 1200 1200 BPSK IL2P 1200 BPSK IL2P+CRC SSB/FM 2.4kHz Backwards compatibility
0111 1200 1200 AFSK IL2P 4800 GFSK IL2P+CRC FM 12.5k Improvement over 1200 AFSK IL2P, where none of the GFSK modes are possible
0110 1200 1200 AFSK AX.25 1200 AFSK IL2P FM 12.5k VHF APRS, backwards compatibility with classic / legacy TNCs like PK232
1100 300 300 AFSK AX.25 300 AFSK IL2P SSB 500Hz Backwards compatibility with legacy HF packet modems. Modulation invented c. 1962!
1101 300 300 AFSK IL2P 300 AFSK IL2P+CRC SSB 500Hz IL2P improvement of AFSK 300 baud AX.25.


  • IL2P+CRC > IL2P > IL2P > AX.25
  • SSB > FM

Baud is symbols per second, bps is bits per second. Where baud=bps, that means each symbol carries 1 bit (i.e. a symbol can have two states, 0 or 1). Where baud is 2x bps, that means each symbol carries 2 bits (i.e. a symbol can have four states: 00, 01, 10, 11).

Signals settings

Cheat sheet

  • Switch 1 is TX audio range selection - on/up is high level for louder transmitted audio, off/down is for quieter transmitted audio
  • Switch 2 is RX audio sensitivity - on/up is low sensitivity for loud radios, off/down is high sensitivity for quiet radios
  • Switch 3 is AC/DC coupling - normally should be off/down apart from specific radios
  • Switch 4 is external carrier detect - normally should be off/down unless you need it for a specific purpose
Radio Signals Notes
Yaesu FT-450D 0000 Requires low level TX audio - the FT-450D is very sensitive.
RX audio setting probably doesn't matter, control with appropriate RF gain / AGC, but off/down works.
Tait TM8100 / 8200 1100 Requires high level TX audio, else the transmitted audio is too quiet in the range of the pot.
Requires low level RX audio, else CRC is always lit.
Requires AC coupling to block the DC which is present on the TX audio pin.
Tait T2010 1100
Yaesu FTM-300D 1100 Tested up to Modes 0100 4800 GFSK IL2P+CRC
Kenwood TK-90 0100 TX audio is pretty sensitive, works better in mic range.

Switch 1 - Transmit audio range selection - DATA/MIC

The data / on / up position increases the TXA level so the TX-LEVEL potentiometer adjustment is in the range needed by the Data radio.

The mic / off / down position reduces transmit audio to the range needed by a microphone-level-input radio.

Switch 2 - Receive audio sensitivity - 1x/11x

The on / up / 1x position is about the right level for a speaker output, and is also appropriate for a data radio output.

The off / down / 11x position is used for radios which have a very low level of receive audio, e.g. perhaps when taken from a speaker mic connection.

Switch 3 - Transmit audio coupling control - DC/AC

Leave in the off / down / AC position unless you have a rare case where having the voltage into the modulator track the TNC’s output, exactly, is required (DC coupling).

Switch 4 - External carrier detect - EN/CD

Leave in the off / down / CD position unless you want to provide external transmit inhibit using pin 2 of the DB9 connector.

Some content courtesy


  • DPSK - Differential Audio Phase Shift Keying - works through mic / speaker connections
  • BPSK - Binary Phase Shift Keying (1 bit per symbol) - new, good for HF (SSB)
  • QPSK - Quadrature Phase Shift Keying (2 bits per symbol) - new, good for HF (SSB)
  • AFSK - Audio Frequency Shift Keying - typical for VHF
  • G3RUH - Classic 9600 baud modem design, described here
  • GFSK - Gaussian Frequency Shift Keying - as utilised in G3RUH 9600 baud classic mode, often used on UHF for many years, but also implemented in other modes.
  • AX.25 - Basic over-the-air protocol utilised for packet radio
  • IL2P - Improved Layer 2 Protocol - effectively implements AX.25 but with some over-the-air improvements, transparent to the host software at both ends.
  • IL2P+CRC - IL2P with added checksum. Co-developed by Nino KK4HEJ and Jonathan G4KLX to resolve corruption found with IL2P in practice.
  • BW - in this context, for FM: channel spacing, and for SSB: audio bandwidth.
  • Baud - symbols per second
  • bps - bits per second. Effective throughput. For modes with 1 bit per symbol, baud == bps. For modes with 2 bits per symbol, effective throughput is 2x the baud rate.

Experimental new modes

Packet radio on HF is typically 300 baud (and bits/sec), using the Bell 103 modem standard. This was released by AT&T Corporation in 1962. It is extremely susceptible to interference and performs poorly with weak signals common in amateur radio.

61 years later, we have far more processing power at our disposal, which means it is possible to achieve much better performance using the same RF bandwidth. While there are some interesting projects around, e.g. FreeDV / Codec2, nothing so far has been found which is easily accessible for amateurs to deploy in a packet radio setting.

Until now.

Nino, KK4HEJ, has been developing a number of new modes which can be added to the NinoTNC with a simple firmware upgrade. Instead of frequency-shift keying (i.e. tone changing in pitch), the new modes are based on phase-shift keying (i.e. phase of a continuous sine wave changing). BPSK (binary phase shift keying) devices modulate input signals by 0° and 180° phase shifts. QPSK (quadrature phase shift keying) devices modulate input signals by 0°, 90°, 180°, and 270° phase shifts, thus in QPSK mode, each symbol can have one of four values, meaning it is possible to transmit two bits of data in each symbol as opposed to just one, doubling the effective throughput in the same bandwidth, at the expense of requiring a bit more signal-to-noise ratio.

The great news is that these modes are now present in the latest firmware.

These new modes are then selectable using the Signals DIP switch. The software node / client settings can be left as-is - the modulation is completely transparent to them, and this can be used for any kind of packet radio traffic. However, given these are new modes, which may perform quite differently (likely better!) than Bell 103, new values for other parameters such as maxframe, frack, paclen may need to be found, but the Network 105 recommendation of paclen=60, maxframe=1, frack=5000 are probably a good starting point until more is known about how these modes perform in the wild.

Until we know more, suitable BPQ port settings might be:


Obviously, there is no cross- or backwards-compatibility with any old modes or indeed any other model of modem or software out there at this point. You switch exclusively to this on-air scheme using the Signals DIP switch on the NinoTNC.

Some notes from Nino:

The speeds refer to gross bit rate, not including IL2P overhead. The baud rates are 300 for the narrow modes and 1200 for the wide modes. Net bit rate will obviously be slightly less.

Precise tuning will always be an advantage on SSB, but these have more inherent frequency mismatch tolerance than AFSK. 300 can deal with up to about 50 Hz. 1200 should work up to about 100 Hz. The QPSK modes are slightly less, respectively.

In addition, the wideband PSK modes should work better than AFSK over FM, e.g. on 2m. I also expect these to work through mic/speaker connections or direct modulator/discriminator connections. Data port not required, but also not an obstacle.

The old 2400 bps audio mode at 0100 and 0101 will go away. It wasn't based on any widely-used standard and 2400 QPSK is far superior.

Performing the firmware update is easy- follow the instructions here on Windows or Linux. Be sure to take the precautions mentioned on that page.

Once you have updated, you can set your signals switch to one of the new modes as per the table above.

To switch back to the previous mode, just change your signals switch settings. You don't even need to restart your software - the change is immediate and totally transparent to the software running on the PC.

Given these are new modes, it is at the very least good manners that we ID regularly in a well-known mode. To that end, this firmware IDs every 9 minutes in BPSK/QPSK modes, modulated in 1600/1800 AFSK AX.25.

On transmit, like any data mode, it's important to make sure that your signal is linear, i.e. clean. My recommendation is to turn your rig power up fairly high, turn your TX DEV pot on the TNC down to zero, hold down the TX TEST button on the NinoTNC until it goes into transmit test mode where it repeatedly transmits frames, let go of the button, then turn up the TX DEV pot on the TNC until you are transmitting the desired power level. Press and hold the TX TEST button for a moment and the TNC will come out of TX test mode.

Usage and testing in any scenario is encouraged:

  • between nodes
  • accessing a node
  • keyboard to keyboard, e.g. using QtTermTCP at both ends
  • on QO-100
  • even HF APRS! (Maybe someone will put up a BPSK or QPSK iGate?!)

Don't use this on established FSK packet channels - this will be QRM to anyone else on frequency - pick a clear channel anywhere in All Modes / Data sections of bands.

Please be sure to feed back your experiences to Nino and others via OARC Discord.

Usage with QtSoundModem

The user must:

  • choose “IL2P Mode”→“IL2P RX+TX” or “IL2P Only” under the Settings→Setup Modems menu in QTSM
  • and ensure the center frequency in QTSM is set to 1500.

Surface-mount versions

There are a few known SMD variants of NinoTNC in various stages of development:

  1. Nigel M0ZFJ
  2. A friend of G0NZO

Please update this section if you know more about any of these.

NinoTNC 3D printed cases

Here are some of the case models we've been able to locate:

NinoTNC A4 Housing - the “official” case

Nino TNC Case - Modified case with a tighter fit (and relocated LEDs) by: Jez - M0JXW

NinoTNC standoff - a simple open standoff frame with split pins
The pins just fell off mine straight away - print settings probably need some work.

NinoTNC mounting plate - a basic standoff mounting plate for the A2, A3, and A4. Uses M3 hardware. Has two countersunk holes for wood screws etc.

More forgiving case by Matt M0MFZ - a case with some clever features to allow for ‘less than perfect’ kit builds

LEDs in a line - modified by Jeremy M0JXW


Credit Nino:

The NinoTNC firmware honors the SLOTTIME and PERSIST settings sent from the host through KISS commands. Since version 27, It also honors TXDELAY if the hardware TX_DELAY potentiometer is set to minimum.

Those settings are used to implement the Carrier Sense Multiple Access (CSMA) scheme described here: Scroll down to “6. Persistence”.

PERSIST is the probability that the TNC will transmit immediately when the channel is clear. SLOTTIME is the time the TNC will wait if it decides not to transmit. The KISS PERSIST command setting is expressed as an 8-bit value, where higher values reflect higher probabilities. A PERSIST setting of 255 means the probability of transmit is 100%, when the channel is clear. SLOTTIME is also expressed as an 8-bit value, in units of 10mS.

The CSMA algorithm in the TNC generates an 8-bit pseudorandom number and compares it to the PERSIST value. If the number is greater than PERSIST, then the TNC waits SLOTTIME before transmit.

I made a slight revision to my implementation of the CSMA algorithm in firmware version 3.31/4.31. In 31 and later, the TNC computes the CSMA lottery while the channel is busy. So you probably won't see a SLOTTIME delay on a dead channel with firmware 31 or 32. In earlier versions, the TNC computed the CSMA lottery every time it was about to start a transmission. So you probably would see some SLOTTIME delays on a dead channel in earlier versions. I made the change to simplify what had become a very complicated logic tree for starting transmissions. I'm not sure which is more correct… or if it matters much.

Other small but measurable time delays you'll see between received and sent packets probably have to do with demodulation processing, serial host communication, host processing, packet assembly, etc.

If you want to see the effect of SLOTTIME and PERSIST, try setting high SLOTTIME and low PERSIST. Repeat your send-and-reply experiments with the storage oscilloscope. You should start to see SLOTTIME delays appearing before replies.

Tuning NinoTNC Deviation

Tuning NinoTNC Deviation

This video demonstrates how to set the transmit deviation for an N9600A TNC using the built-in 999Hz tuning tone and a cheap USB SDR.

In the test setup, an N9600A2 TNC is connected to a TAIT TM8105 radio set to transmit on 145.510 MHz. Software is SDR Console v3.0.14 on a Windows 10 PC. Receive bandwidth on the SDR software is set to 250kHz, AGC on, WFM.

The TX DEV potentiometer on the TNC is at minimum at first, then slowly increased while holding the TEST TX button. Proper deviation is reached when the center spike in the spectrum display is dipped to minimum. This takes advantage of the first “Bessel Null”, which happens when FM deviation is 2.405 times the frequency of the transmitted tone (999Hz in this case). 2.4kHz provides minimum-shift deviation for 9600 baud transmitted data.

After this video was taken, the setup was tested against an IFR 1200 service monitor to verify transmit deviation. The monitor showed 2.42kHz, which is perfect for 9600 or 1200 baud data.

Random excerpt from conversations on the subject

Link to conversation on Discord

IL2P 1200 radio is 25kHz channel - that generates a 1248 Hz tone with the test button, you set 3kHz deviation

If you want to calibrate for a 12kHz channel, set the TNC to a 4800 baud mode, like 0011. That will generate a 500 Hz tone with the test button, which will dip the first null at 1.2kHz deviation, which will work with a 12kHz channel.

In a 25kHz channel, 3kHz works great

If you set a 9k6 mode on the TNC, you'll get a 999 Hz test tone. That's aimed to set deviation at 2.4kHz with the first null, which gives “minimum shift keying” at 9k6. Though it will work at 3kHz deviation as well.

It's also useful to measure the peak-to-peak voltage of the transmit audio signal fed to the radio after proper deviation is set, using an oscilloscope. In this case it was 690mV. This will serve as a “good enough” deviation setting in the future for this particular radio, and likely for similar radios of the same model.

The FM modes tones are as follows:

0000, 0001: 999 Hz tone for 2.4kHz deviation
0010, 0011: 500 Hz tone for 1.2kHz deviation
0110, 0111: 1248 Hz tone for 3.0kHz deviation
0101: 2079 Hz tone for 5.0kHz deviation

Misc Linux Notes

For convenience, udev can be used to create a symlink with a consistent unique name in /dev for each of your NinoTNCs:

# Create a handy symlink to make refering to NinoTNC's easier
SUBSYSTEM=="tty", ATTRS{idVendor}=="04d8", ATTRS{idProduct}=="00dd", SYMLINK+="NinoTNC-%s{serial}"

After creating said file, run udevadm trigger for it to take effect without rebooting.

If this doesn't work immediately, it may be the NinoTNC is not configured to expose its serial number. This can be enabled using the tool at

git clone

sudo python3 ./ enum-serial 1

If preferred, the same tool can be used to specify a serial number for the device.

sudo python3 ./ set-serial 0123456789

Then rerun the udevadm trigger command above.

Auto mode switch


With Raspberry Pi GPIO, put /usr/bin in the crontab path, and add the following to /etc/crontab:

# 1000 - BPSK300
0 *     * * *   root    raspi-gpio set 5 op dh && raspi-gpio set 6 op dl && raspi-gpio set 13 op dl && raspi-gpio set 19 op dl

# 1001 - QPSK600
30 *    * * *   root    raspi-gpio set 5 op dh && raspi-gpio set 6 op dl && raspi-gpio set 13 op dl && raspi-gpio set 19 op dh

dl = drive low, dh = drive high.

Wire the numbered GPIO pins to the bottom of the MODE DIP switch, turn all the switches off, and it'll mode-switch automatically. I've gone for BPSK300 for the first half of each hour, and QPSK600 for the second half.

I picked GPIOs 5, 6, 13 and 19 (consecutive physical pins) to map to the DIP switch pins from left to right as you look at the PCB.


The MCP2221A USB chip has four GPIOs which can be used to control the mode, instead of the DIP switches. This can be useful particularly on a remote site, and removes the need for a second cable (and works with a machine without its own GPIO interface).

This is experimental and is likely to change. See for up to date info. Thanks to Dan for working on this.

General steps:

git clone

Install python3.

then, once (persistent):

sudo python3 ./ setup-gpio

this will configure the GPIO pins as outputs, and make them all low at power on.

then, when required (non-persistent):

sudo python3 ./ set-gpio 1111

where 1111 is the state of the four switches, left to right.

Wiring as follows. NOTE - you MUST either remove the DIP switch or leave all four switches set permanently off with the jumpers in place.


Note: this is the BACK / SOLDER side of the PLUG.


To upgrade the firmware, see


# save a headache
sudo systemctl disable linbpq
sudo reboot

# then...
sudo apt install -y python3 python3-pip python3-serial git
git clone
cd flashtnc
python3 N9600A-v3-35.hex /dev/ttyACM0

# don't forget to...
sudo systemctl enable linbpq
sudo systemctl start linbpq

Use v3 firmware unless you know you have a 512kb chip, which is none of the OARC UK kits (i.e. ignore the v4 firmware - it's the same, but for the bigger chip).

If you get dire warnings about bricked TNCs, know is this highly unlikely. Unplug TNC, reboot system, plug TNC, try again.

packet/ninotnc.txt · Last modified: 2024/05/13 17:48 by m0lte