Skip to content

Manual: AX25 Java Soundcard Modem

Jose Ricardo de Oliveira Damico edited this page May 30, 2021 · 1 revision

Sivan Toledo, February 2012

Introduction

I wrote the Java soundcard modem mostly because the previous soundcard modem I was using for APRS, called soundmodem, failed to parse packets from some station/receiver combinations. I recorded these stations using the receiver that caused soundmodem problems and I was able to decode them using a Matlab code that I developed. I decided to transform the Matlab algorithm into Java and this software is the result. The code generates good packets and it decodes packets from all the local stations I can receive. It also receives packets from the ISS. The demodulator seems to work very well. I tested it on Stephen Smith’s APRS test CD (http://wa8lmf.net/TNCtest/index.htm). At a 11025 kHz sample rate, it decodes 958 packets from track 1 (discriminator audio) and 943 from track 2 (de-emphasized audio, similar to the audio from the speaker output of radios). At 44100 kHz, it decodes a bit more, 964 and 960, respectively. Rob Marshall KI4MCW used the test CD to evaluate several AX25 modems (including his own). He found out that soundmodem can decode only 412 packets from track 2, AGWPE can decode 500, multimon only 130, and various microcontroller based modems (some with a modem chip, the mx614, and some DSP-based) can decode 729-871 packets. Rob fed the audio to the modems by playing the CD and feeding the audio to the modems, whereas I ran my Java code directly on the audio file from the CD, so a direct comparison might not be fair, but this does give an indication that my code decodes better than the other three soundcard modems and at a level that is at least comparable to the microcontroller-based modems. (The main difference between the two methods is the setting of the audio level; in my method, the modem always gets the 16 bits of audio that were recorded for each sample; in Rob’s method, the audio level might saturate the modem’s ADC if it is set too high or might not give the full precision if it is set too low.)

Code Structure

The code consists of two main components and two external interfaces. One component is the modem itself, which consists of a modulator class (Afsk1200Modulator) and a demodulator class (Afsk1200MultiDemodulator), as well as several utility classes. The modem does not deal directly with the soundcard; instead, it expects to receive samples of received audio from some other part of the code and to send samples back for transmission. The demodulator also has carrier detect functionality (mostly to aid in CSMA channel access), but I have not tested it much yet. The second major component is the soundcard interface, in the class Soundcard. It is responsible for moving samples between the computer’s audio system and the modem.

Both of these components should work at several sample rates, including 9600 samples/s, 11025, 22050, 24000, 44100, and 48000. The computational overhead is lower, of course, at lower sample rates: at 9600 kHz, the modem runs at about 5% CPU utilization on a 1.6GHz Intel Atom computer; at 48000, it runs at about 30% CPU utilization. The modem performs well even at 9600 samples/s, so there is little reason to run it at higher sampling rates. The default is 9600. On one radio packets sent at 9600 kHz were not always decoded; switching to 12000 kHz cured the problem. I have not investigated the issue in detail, but if you experience a similar problem you may want to switch to 12000. On the same Intel Atom computer, running the code at 12000 kHz leads to a 10% CPU utilization; still tolerable. The modem also supports 8000 samples/s, which it interpolated to 16000 samples/s. The computational overhead is larger than at 9600, 11025, and 12000, so use 8000 samples/s only if this is the only rate available (e.g., Bluetooth audio). Another small module keys the transmitter using a serial port signal, either RTS or DTR. There are three external interfaces in the code. One is the javAPRSsrvr interface. To javAPRSsrvr, the software modem looks like a TNC interface. Another is a Java program that can be used to test the modem and to adjust audio levels. The last one is an AGWPE emulator that client programs (e.g., APRSISCE) connect to through a TCP connection. These interfaces are documented below.

The Test Program

The code includes a test program. You invoke it from the command line using a command like

java -cp bin 
     -Drate=48000 -Dinput="Conexant HD Audio input" 
     -Daudio-level 
     sivantoledo.ax25test.Test

(the command should appear on one line, but is broken here into lines for clarity). In this particular invocation, the program will listen for packets coming in through the named input device. It will also print the audio levels once a second; these are always between 1 and 100, where values close to 100 indicate possible saturation. If the reported audio levels are near 100, you need to reduce the audio input levels, either though adjusting the gain in the radio or your sound-card interface, or by adjusting the audio level using the software mixers in your operating system.

In this mode, the program prints out packets that the modem managed to decode. Here is a typical output:

[4Z1PF-3>APRS,4Z5LA-3,WIDE2-2:!3200.59N/03447.82E#Holon 144.800 MHz Digi]

To see which audio devices are available, use the -Denumerate option to the program. On Windows, it will output something like

Available sound devices (On Windows):

  • output: Primary Sound Driver
  • output: Conexant HD Audio output
  • output: Virtual Cable 1
  • input : Primary Sound Capture Driver
  • input : Conexant HD Audio input
  • input : Virtual Cable 1
  • output: Java Sound Audio Engine

Available sound devices (On Linux):

  • output: NVidia [plughw:0,0]
  • input : NVidia [plughw:0,0]
  • output: NVidia [plughw:0,1]
  • output: NVidia [plughw:0,3]
  • output: External [plughw:1,0]
  • input : External [plughw:1,0]
  • output: Java Sound Audio Engine

To adjust transmit audio levels, you can tell the program to send flags (the AX25 idle signal) for a specified number of seconds,

java -cp bin 
     -Drate=48000 
     -Doutput="Conexant HD Audio output" 
     -Dflags=7 
     sivantoledo.ax25test.Test

To transmit a test packet, give it an output device and a callsign,

java -cp bin 
     -Drate=48000 -Doutput="Conexant HD Audio output" 
     -Dcallsign=YOURCALL 
     sivantoledo.ax25test.Test

The program does not key the transmitter. The examples above assume that you use VOX to key the transmitter. If your transceiver requires an explicit activation (PTT), you will need to connect a signal of a serial port to the transceiver’s PTT line. The code that communicates with the serial port is the RXTX library, which consists of a Java component and a native library. You will need to install it. On Windows, assuming that the RXTX libraries are in the current directory, the relevant options are

java -cp bin:RXTXcomm.jar 
     -Dptt-port=COM20 –Dptt-signal=RTS
     ... 

On Linux, the options are simiar, but you also need to tell the Java environment where the native library is; the names of serial ports are also different.

java -cp bin;RXTXcomm.jar
     -Djava.library.path=.
     -Dptt-port=/dev/ttyUSB0 –Dptt-signal=RTS
     ... 

The program also has several options that are mostly used by me (the developer). One writes the samples of a test packet to a text file. Another processes audio from a file:

java -cp bin 
     -Drate=44100 
     -Dfile-input=TNC_Test_Ver-1.1.track2.wav 
     sivantoledo.ax25test.Test

This produces the following output (slightly edited) , Trying to decode packets from <e_Test_Ver-1.1.track2.wav>

Audio rate is 44100, 2 channels, 4 bytes per frame, 16 bits per sample

  1. [WA6YLB-4>APRS,N6EX-5:$ULTW00000000----...000\x0d\x0a]
  2. [KD6FVP-2>APS224,N6EX-1,WIDE1:...We know most of your faults!!!\x0d]
  3. [KD6FVP-2>APS224,N6EX-1,WIDE1:...We know most of your faults!!!\x0d]
  4. [WA6YLB>APRX46,WA6YLB-7,W6SCE-10:>081839z wa6ylb@theworks.com\x0d]
  5. [KC6HUR-1>S4QVYV,W6SCE-10:'.4&l-/k/]"7q}\x0d]
  6. [N6XQY-12>GPSLJ,N6EX-4:$GPRMC,013641.06,A,3348.1607,N,...,E*73\x0d]

The javAPRSsrvr interface

To use the program with javAPRSsrvr, you need to add its classes to the Java class path that is used when javAPRSsrvr runs, and to configure javAPRSsrvr to use it. The configuration in javaprssrvr.cfg should look something like

TNCModule=SoundcardInterface
SoundcardName=NVidia [plughw:0,0]
SoundcardSampleRate=48000
SoundcardLatency=10
PTTPort=/dev/ttyUSB0
PTTSignal=RTS

The first line tells javAPRSsrvr to use the soundcard modem. The second tells the modem which sound card to use (you can use SoundcardInputName and SoundcardOutputName if they are not the same). The third tells the modem what sample rate to use, and the last tells it to attempt to delay processing by no more than 10ms. The modem cannot guarantee this latency; it merely tries to achieve it. A long latency improves somewhat the efficiency of the software and reduces the chances of dropped audio, which can cause bad packets to be transmitted and failure to decode incoming packets (I have not seen such failures, but they are possible in principle, especially to heavily loaded computers and short latencies). On the other hand, long latencies introduce a delay in processing incoming packets. This has two negative effects. One is that the data-carrier detection is delayed, so the modem might start transmitting at the same time another station is transmitting, simply because it is still queuing the audio of the incoming packets. The second is a longer delay between receiving a packet and digipeating it. The last two lines tell the modem how to key the transmitter: which signal (RTS or DTR) in which serial port is activates the transceiver’s PTT.

The modem also honors the KISS parameters KISSTXDelay, KISSPersist, and KISSSlotTime, but I really have not tested this at all.

The AGWPE Emulator Program

Another command-line program emulates AGWPE.

java -cp bin 
     -Drate=48000
     -Dinput="Conexant HD Audio input" 
     -Dinput="Conexant HD Audio output" 
     -Daudio-level 
     sivantoledo.agwpe.TNC

The only other option that the program currently supports is -Dport, which tells the program on which TCP port to listen to client connection requests. The default is 8000, which is also the default of AGWPE.