Skip to content

Instantly share code, notes, and snippets.

@ericek111
Last active October 29, 2025 14:34
Show Gist options
  • Select an option

  • Save ericek111/d2325c55921853a4592e46962dfe37f2 to your computer and use it in GitHub Desktop.

Select an option

Save ericek111/d2325c55921853a4592e46962dfe37f2 to your computer and use it in GitHub Desktop.
Contesting with N1MM on Linux: a tutorial for the adventurous

Contesting with N1MM on Linux

N1MM+ has been the go-to contest logger for many hams and, thanks to its networking features, also clubs. Sadly, it's only for Windows, it's closed-source and the bugs (whether in N1MM or Wine) don't make it any more fun.

Setting up Wine

  1. Install any decently recent flavour of Wine. Usually the one provided by your distro's package manager is fine.
  2. Install winetricks.
  3. Set the required environment variables. To work inside this wineprefix (which is, in short, a self-contained "fake" "Windows" "installation"), you need to specify its path inside every newly opened terminal window.
export WINEPREFIX=~/.wine_n1mm
export WINEARCH=win32

Tip

You only need to specify $WINEARCH the first time when creating the wineprefix.

  1. Use winetricks to install .NET, which N1MM uses to run:
wine wineboot
winetricks win7
winetricks dotnet46
  1. Download and install N1MM+ (in the same terminal window, wine ~/Downloads/N1MM-Logger....exe).

Patching N1MM

... is no longer necessary since 1.0.10476 thanks to the N1MM team! You can read the instructions in an earlier revision of this text. Nevertheless, the cause of the issue is still present -- a bug in Wine (audio enumeration is not fully implemented), which breaks the voice line recording feature (e. g. in the QTC config window). Playback works perfectly fine. Just use (i. e.) Audacity to make the recordings.

Using CAT inside N1MM

Through FLrig

I personally prefer to run every ham program with FLrig, if possible. N1MM does not natively support it, but with a useful utility in hamlib called rigctlcom, we can simulate a Kenwood TS-2000 radio.

Due to some bug, FLrig does not save the quite long file path of my radio's USB serial converter correctly. One workaround is to set up FLrig, save the config, make a copy, fix the xcvr_serial_port path, and then just overwrite the corrupted config with my good one on every launch. This is the command my desktop icon runs:

bash -c "cp ~/.flrig3000/FTdx3000.prefs.good ~/.flrig3000/FTdx3000.prefs ; flrig --config-dir ~/.flrig3000"

There is an open issue to allow rigctlcom to work over TCP saving us these next two commands. But until that's implemented, we need to create a virtual serial port:

sudo socat pty,raw,link=/dev/vspin0,group-late=uucp,mode=660 pty,raw,link=/dev/vsp0,group-late=uucp,mode=660

Tip

Your user must be a member of the uucp group. You can also use mode=666.

Then, "bridge" the virtual serial port onto a TCP port.

socat TCP-LISTEN:10501,fork,reuseaddr,nodelay FILE:/dev/vsp0,raw,echo=0

Finally, start rigctlcom to translate the TS-2000 commands into something FLrig can speak.

rigctlcom -vvvv -m 4 -R /dev/vspin0

Tip

If FLrig gets stuck/closed and your CAT suddenly stops working, the culprit is most likely rigctlcom. Just kill it with Ctrl+C and start it again. N1MM should recover. With the -vvvv flags, you'll see "IO error" printed in the console.

In N1MM in menu Config > Configure Ports, Mode Control, Winkey... select Port: TCP, Radio: TS-2000, and fill in your IP and port: 127.0.0.1:10501. Click the Set button and enable PTT via Radio Command, if you want to use N1MM to play back prerecorded CQ calls, for example.

I want to use my radio directly.

You can. In that case, it's just this one command. Your radio must be supported by N1MM and it's not the most stable way, in my experience.

socat TCP-LISTEN:10501,fork,reuseaddr,nodelay FILE:/dev/serial/by-id/usb-Silicon_Labs_CP2105_Dual_USB_to_UART_Bridge_Controller_AH046H4J230099-if00-port0,raw,echo=0,cs8,crtscts=1,b38400,cstopb=1

Note

cstopb can be 0 (one stopbit) or 1 (two stopbits).

Routing audio

Along with PipeWire (link to its docs on virtual devices and their configuration), which is now the default audio server in most popular distributions, I use these great tools:

  • Calf Studio Gear for DSP audio filters with a very nice and easily understandable interface.
  • The RaySession family (mostly Patchance) for routing audio around the system and to/from the individual filter blocks. It's very easy to use and makes audio on Linux so much fun. Alternatives are qpwgraph, Helvum, Carla, or doing it manually (see below).
  • Pavucontrol -- should be available in the repositories of your distro, maybe it's even pre-installed.

Automating it

Setting up the Calf plugins from scratch every single time is tedious. RaySession makes this EXTREMELY easy. Simply create a new session, add the Calf JACK Host application from the menu, add whatever plugins you want, route their inputs/outputs and click the "Save" button on the left. This will make RaySession remember the exact routing and settings of each Calf filter. Upon loading the session later, it'll route and start everything automatically. It truly is an amazing piece of software.

2024-09-15-22-35.png

Automating it, but manually

If you want to skip using a session manager (or do it via CLI for any reason), you can save the preset in calfjackhost in File > Save. To recall it, start the program with -l (path to the preset file). Then, to route the audio streams between the filters, use pw-link with the names of the ports, like so, ending with your radio's sound card:

# List all ports: pw-link --output --input
# Link two: pw-link {{output_port_name}} {{input_port_name}}
# Unlink two: pw-link --disconnect {{output_port_name}} {{input_port_name}}

set -m
calfjackhost -l ham_ssb_emph &
sleep 1
pw-link "Calf Studio Gear:Emphasis Out #1" "Calf Studio Gear:Compressor In #1"
pw-link "Calf Studio Gear:Emphasis Out #2" "Calf Studio Gear:Compressor In #2"
pw-link "Calf Studio Gear:Compressor Out #1" "Calf Studio Gear:Equalizer 5 Band In #1"
pw-link "Calf Studio Gear:Compressor Out #2" "Calf Studio Gear:Equalizer 5 Band In #2"
pw-link "Calf Studio Gear:Equalizer 5 Band Out #1" "alsa_output.usb-Burr-Brown_from_TI_USB_Audio_CODEC-00.analog-stereo:playback_FL"
pw-link "Calf Studio Gear:Equalizer 5 Band Out #2" "alsa_output.usb-Burr-Brown_from_TI_USB_Audio_CODEC-00.analog-stereo:playback_FR"
fg

Remote operation

Audio

The only other proprietary part of my setup, apart from N1MM+, is TeamSpeak 3. Before the era of Discord, it was the go-to communicator for gamers (and some value its simplicity and stability even today). It's low latency (UDP) and uses the CELT codec (with configurable quality). You need a server. I recommend self-hosting your own, for full control and the lowest possible latency. Simply use Patchance to route the audio from your radio into TS3's input and vice versa.

PTT

I've made a simple Node.js script that triggers the radio's PTT line when there's a client speaking in the TS3 channel: https://git.lixko.eu/ericek111/ts3_remote_ham.

I have configured TS3 to only transmit my voice when I hold down the left Shift key. This has a side effect in Linux -- your num-pad will behave as if you had Num Lock off. This can be easily disabled, in my environment (MATE), it's under Keyboard > Layouts > Options > Compatibility options > Numeric keypad always enters digits (as in macOS).

Remote desktop

Any app for remote desktop is fine. I found VNC to be too slow and other alternatives for gamers (such as Steam Remote Play or Moonlight) too much hassle. In the end, I've settled with NoMachine and it's served me well over the years. It's multi-platform, free (as in beer, sadly), and pretty low latency. It uses H.264 and supports hardware accelerated encoding. The audio support is (probably still) broken on Linux/PipeWire. It, like TS3, also requires a direct connection to the machine, necessitating a VPN software such as WireGuard or OpenVPN.

AnyDesk was also mostly usable -- it does not need a direct connection and audio works fine, but for me, sometimes the image would start falling behind, growing the latency to several seconds, and only a reconnect would fix it.

@recri
Copy link

recri commented Feb 28, 2025

Hi Erick -

I followed your instructions. it immediately failed because Ubuntu 24.10 installed wine win64 but n1mm required win32. So I followed the instructions to enable win32. Everything thereafter produced nothing but error messages. At the end I installed n1mm and discovered that you give no instructions that run n1mm. I found no permutation of "wine n1mm*" that succeeded so I deleted everything. I thought it would be funny to send you the transcript of installs and error messages, but it was so long that xterm started choking on the size of the selection I was asking for. Any suggestions?

Not really trolling you, I would like to see n1mm running, but this was a wasted few hours, and my Ubuntu now suggests that I can uninstall a whole list of things that I know I should not uninstall, so the net result has been to bork my system configuration to boot.

-- [email protected] --

@recri
Copy link

recri commented Feb 28, 2025

Okay, try again, here are the errors to the end of the first .net installation. So we created a directory, then we start failing. Any ideas what's wrong?

-- rec --

rec@x13:~$ export WINEPREFIX=~/.wine_n1mm
export WINEARCH=win32
rec@x13:~$ 
rec@x13:~$ wine wineboot
winetricks win7
winetricks dotnet46
wine: created the configuration directory '/home/rec/.wine_n1mm'
0054:err:ole:StdMarshalImpl_MarshalInterface Failed to create ifstub, hr 0x80004002
0054:err:ole:CoMarshalInterface Failed to marshal the interface {6d5140c1-7436-11ce-8034-00aa006009fa}, hr 0x80004002
0054:err:ole:apartment_get_local_server_stream Failed: 0x80004002
0054:err:ole:start_rpcss Failed to open RpcSs service
004c:err:ole:StdMarshalImpl_MarshalInterface Failed to create ifstub, hr 0x80004002
004c:err:ole:CoMarshalInterface Failed to marshal the interface {6d5140c1-7436-11ce-8034-00aa006009fa}, hr 0x80004002
004c:err:ole:apartment_get_local_server_stream Failed: 0x80004002
wine: configuration in L"/home/rec/.wine_n1mm" has been updated.
Executing cd /usr/bin
Using winetricks 20240105 - sha256sum: dd9a0453769c7ca7198812373ecab6d1d2c561416eafba00026a487007f3039f with wine-9.0 (Ubuntu 9.0~repack-4build3) and WINEARCH=win32
Executing w_do_call win7
Executing load_win7 
Executing wine winecfg -v win7
------------------------------------------------------
warning: Running /usr/bin/wineserver -w. This will hang until all wine processes in prefix=/home/rec/.wine_n1mm terminate
------------------------------------------------------
Executing cd /usr/bin
Using winetricks 20240105 - sha256sum: dd9a0453769c7ca7198812373ecab6d1d2c561416eafba00026a487007f3039f with wine-9.0 (Ubuntu 9.0~repack-4build3) and WINEARCH=win32
Executing w_do_call dotnet46
Executing load_dotnet46 
Executing w_do_call remove_mono internal
Executing load_remove_mono internal
Executing w_do_call dotnet45
Executing load_dotnet45 
Executing w_do_call remove_mono internal
Executing load_remove_mono internal
Executing w_do_call dotnet40
Executing load_dotnet40 
------------------------------------------------------
warning: dotnet40 does not yet fully work or install on wine.  Caveat emptor.
------------------------------------------------------
Executing w_do_call remove_mono internal
Executing load_remove_mono internal
win7
Executing w_do_call winxp
Executing load_winxp 
Executing wine winecfg -v winxp
------------------------------------------------------
warning: Running /usr/bin/wineserver -w. This will hang until all wine processes in prefix=/home/rec/.wine_n1mm terminate
------------------------------------------------------
Executing cd /home/rec/.cache/winetricks/dotnet40
Executing wine dotNetFx40_Full_x86_x64.exe
0118:err:winediag:ntlm_check_version ntlm_auth was not found. Make sure that ntlm_auth >= 3.0.25 is in your path. Usually, you can find it in the winbind package of your distribution.
0118:err:ntlm:ntlm_LsaApInitializePackage no NTLM support, expect problems
02d0:err:ole:CoGetContextToken apartment not initialised
0280:err:ole:CoReleaseMarshalData StdMarshal ReleaseMarshalData failed with error 0x8001011d
0338:err:ole:CoGetContextToken apartment not initialised
0348:err:ole:CoGetContextToken apartment not initialised
02f0:err:ole:CoReleaseMarshalData StdMarshal ReleaseMarshalData failed with error 0x8001011d
02d8:err:ole:CoReleaseMarshalData StdMarshal ReleaseMarshalData failed with error 0x8001011d
03a0:err:ole:CoGetContextToken apartment not initialised
[ ... truncated ... ]

@ericek111
Copy link
Author

Hi. I've set up a new Incus instance of Ubuntu 24.10 (as I use Ubuntu MATE 24.04 on this PC). Make sure you're running X.org, not Wayland. I don't know whether it makes any difference, but it's worth sticking to the tried and tested. Then I just copy-pasted the commands above and it worked. This is literally all I needed to run.

The errors you can ignore. Maybe install winbind if you're intending to run N1MM networked (like we do in the radioclub).

# This is just the container setup on my PC to get the same environment as you. Skip it.
incus launch images:ubuntu/oracular/cloud roger --profile default --profile gui --storage cont 
incus exec roger bash
# Now we're in Ubuntu 24.10, install Wine
apt install wget
dpkg --add-architecture i386 
mkdir -pm755 /etc/apt/keyrings
wget -O /etc/apt/keyrings/winehq-archive.key https://dl.winehq.org/wine-builds/winehq.key
wget -NP /etc/apt/sources.list.d/ https://dl.winehq.org/wine-builds/ubuntu/dists/noble/winehq-noble.sources
apt install --install-recommends winehq-stable winetricks
su - ubuntu
export WINEPREFIX=~/.wine_n1mm
export WINEARCH=win32
wine wineboot
winetricks win7
winetricks dotnet46
wine ~/N1MM-Logger-FullInstaller-1.0.10386.exe
wine ~/N1MM-Logger-Update-1.0.10628.exe

@recri
Copy link

recri commented Feb 28, 2025 via email

@barf
Copy link

barf commented Sep 20, 2025

wine doesn't work on ARM. Is there any solution for Raspberry Pi / ARM users? Thanks.

@ericek111
Copy link
Author

@barf, Wine works fine under Box86. I had N1MM running on my phone a few years ago.

@barf
Copy link

barf commented Sep 21, 2025

Thanks @ericek111 I'm new to amateur radio and contesting but no stranger to virtualisation and running a whole Windows VM is not really a solution for a Raspberry Pi with 4GB RAM, and the appropriate Windows Server license cost for a VM is over NZD$800 (you read that right).

QLog here on GitHub seems to be the best choice for ARM/Pi users but lacks the contesting features, ohwell, thanks again anyway!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment