WOLF (Weak-signal Operation on Low Frequency) is a proposed new signal format and protocol designed specifically for the LF bands. It can be used for beacons and for two way communication. Unlike existing formats, which are optimized for a particular S/N (and corresponding speed), WOLF can operate over a wide range of signal levels. For example, a WOLF beacon transmits a 15-character message repeatedly. If the received signal would be adequate for conventional CW, copy will be displayed in 24 seconds. At a level barely enough for 0.4 WPM QRSS, copy will appear within two minutes. Even if the signal is another 10 dB weaker, the message can still be received. It will take from 20 minutes to several hours, depending on the stability of the Tx and Rx. Of course, it is also necessary that the propagation path remain open over the required interval.

I hope that WOLF will permit a QSO to be completed in an hour, if one station receives a signal that is 10 dB weaker than would be needed for QRSS, and the other station's signal is 6 dB below the QRSS threshold. I believe that it is also feasible to "hear" a LOWFER beacon across the Atlantic, during an overnight run (very accurate time and frequency control is required).

At this time, I have implemented only a crude "off-line demo". In transmit mode, this command line program writes a .wav file which contains the specified message. A simulation is performed by mixing (using an audio editor) a small amount of this signal with a large amount of noise (recorded off the air or synthetic, as desired). The resulting file is read by the program in receive mode, and attempts to decode the message are made at various intervals. For an on-the-air test, the transmit output file is played (with a media player or editor), feeding the audio into an SSB transmitter. There are also various ways to drive a PSK transmitter. The receiving station records the Rx output as a .wav file, which is then supplied to WOLF for decoding.

There have been a few successful WOLF transmissions; simulated results have also been quite encouraging. I used the procedure developed by Lyle Kohler; see his description and results . Lyle's tests found that conventional CW could be received with the signal attenuated up to 18 dB below the reference noise level. For 0.4 WPM QRSS, the limit was -30 dB. BPSK at MS1000, ET1 was the most robust mode tested, showing intermittent copy after many minutes at -33 dB. WOLF occasionally shows good copy at -45 dB, and seems quite robust at -40.

If you feel that this format holds some promise, please download the software, try it with various kinds of QRN and QRM, and let me know the results. It would be even better if you could test it on the air. I also welcome any suggestions for making the format or protocol more robust.

Of course, to be useful for real communication, audio I/O and a user interface must be added. Unfortunately, I have no experience programming for Windows, so it will take me quite a while to implement these features. If someone with knowledge in this area is willing to participate, I would be glad to set up the project as open source.

How to get WOLF

If you will test WOLF on the air, please note that the signal is not constant envelope, and is relatively wide band (BW at -20 dB is about 40 Hz).

I will not be responsible for any damage to your transmitter, nor for any QRM caused; please examine the audio output before transmitting. Also, do not transmit with higher power than needed for your test.

If you agree with the above, download WOLF here, and unzip it to get wolf.exe .

For testing with simulated data, you will need a file containing suitable noise. I used a file provided by Lyle; you can find a copy here. If your system just plays the noise, right-click the link and select "save target..." or similar. This file is actually an example of conventional CW at -18 dB, but the CW is at 400 Hz and does not seem to affect WOLF, which is nominally at 800 Hz. Of course, it would be better to use an actual noise sample recorded at your QTH.

Wolf can also write a file which can drive an "XOR gate" PSK transmitter via a serial port. However, the baud rate clock in many serial ports is quite inaccurate. A file to help you determine the precise rate of your serial port's clock is here. Right-click the link to save.

How to use the demo version of WOLF

WOLF runs at the command prompt under Windows. However, it is a WIN32 application, and will not run under DOS. I have only tested it with Windows 2000 and 95, but others have run it under Win 98, and I believe it should also run under NT4 or ME. Let me know if you see any problems.

Create a new folder for WOLF; put wolf.exe and noise.wav there. At the command prompt, CD to that folder before running WOLF. In transmit mode, WOLF will write a file called wolfx.wav, and will read wolfr.wav when receiving (except test mode). You can specify alternate file names with the 'q' option.

All files read and written by WOLF must be in Windows .wav format, mono, at a nominal sample rate of 8000 Hz. Samples may be 16 bits or 8 bits linear.

You can "send" a message like this:

C:\wolf>wolf -x "QUICK BROWN FOX"
WOLF version 0.11
Wrote wolfx.wav, 1536044 bytes, at 8000.000 samples/sec., 800.000 Hz


In transmit mode, there are some other options you may wish to use. For example:

C:\wolf>wolf -x "QUICK BROWN FOX" -e -r 7999.876 -f 812.345 -a 0 -t 1
WOLF version 0.53
Wrote wolfx.wav, 768032 bytes, at 7999.875 samples/sec., 812.344 Hz

The 'e' option causes the file to be written with 8 bit samples.
The 'r' option specifies the actual sample rate of the transmitting sound card. This may be needed for on the air testing, because the program expects the bit rates to match within a few PPM.
The 'f' option specifies the center frequency of the output. The program alters the sample rate and/or frequency slightly, so that there are an integral number of samples and carrier cycles in a frame.
The 'a' option (on transmit only) specifies the output level attenuation, in dB, relative to full scale. If not used, the level is -8 dB normally, or 0 dB for '-k' mode.
The 't' option (on transmit only) specifies the transition time for a phase reversal, in bit times. The value must be between zero and one, inclusive. If not used, a transition takes about 0.1 bit times.
Larger 't' values greatly reduce the required spectrum, at some expense in received S/N. For the same PEP, 't 1' is about 1.5 dB worse than 't 0'. The spectra below show 't 0', 't 0.1', and 't 1' respectively.

Once you have created wolfx.wav, there are three ways to test it. The simplest is to use the built-in test mode:

C:\wolf>wolf -a 40
WOLF version 0.11
t:  24 f: 0.598 a:-0.8 dp: 98.3 ci:15 cj:203 UJ*MLL1MHLQKVVQ ?
t:  48 f: 0.598 a:-0.8 dp: 97.8 ci:11 cj:166 B 4OBXBB3AYLV 9 ?
t:  96 f:-0.342 a: 0.8 dp: 98.2 ci: 5 cj:150 JRHFVGK HDYZ45  ?
t: 192 f: 0.039 pm:  73 jm:728               .UBBV13698*COP8 ?
t: 288 f: 0.000 pm: 112 jm:959               A9R.F2RFG3.8H0H ?
t: 384 f: 0.000 pm: 141 jm:959               4NG966Z6PQ/T48  ?
t: 480 f: 0.000 pm: 197 jm:959               QYWZT1FINPUWH/J ?
t: 576 f: 0.000 pm: 219 jm:959               ???H FJ2TMO9FT9 ?
t: 672 f: 0.000 pm: 266 jm:959               QUICK BROWN FOX -
t: 768 f: 0.000 pm: 360 jm:959               QUICK BROWN FOX -

The 'a' option (on receive) turns on test mode. In this case an attenuation of 40 dB is specified. The program reads wolfx.wav, attenuates it, adds in noise.wav, and attempts to decode the result. When it gets to the end of an input file, it loops back to the beginning. It stops after processing 16 frames, or when you hit control-C. Here, we see good copy after 672 simulated seconds (on a 700 MHz P III, processing is about 10 times faster than real time; on an old P100, it's a little faster than real time).

C:\wolf>wolf -a 24
WOLF version 0.11
t:  24 f:-0.002 a:-1.3 dp:106.6 ci: 0 cj:  0 QUICK BROWN FOX -
t:  48 f:-0.002 a:-1.2 dp:105.9 ci: 0 cj:  0 QUICK BROWN FOX -
t:  96 f: 0.000 a: 1.5 dp:106.5 ci: 0 cj:  0 QUICK BROWN FOX -

You can see that a strong signal gives good copy after only 24 seconds.

You can also write wolfr.wav with an audio editor. This allows you to test with simulated impairments beyond simple attenuation, to use time-varying noise sources, etc. If neither -a nor -x is given, WOLF will read wolfr.wav and try to decode it. It stops after end-of-file. Two examples:

WOLF version 0.11
t:  24 f: 0.598 a:-0.8 dp: 98.3 ci:15 cj:203 030CUEHU5G1D58B ?
t:  48 f: 0.598 a:-0.8 dp: 97.7 ci:11 cj:166 FJO/M67UPGZY9YH ?
t:  96 f:-0.342 a: 0.8 dp: 98.2 ci: 5 cj:150 0/RFVGK HDYZ45  ?
t: 192 f: 0.000 pm: 203 jm:959               PPFUMSA1VF8 WL/ -
t: 288 f: 0.000 pm: 361 jm:959               QUICK BROWN FOX -

C:\wolf>wolf -s 12345 -f 800.321 -r 8000.012
WOLF version 0.11
t:  24 f: 0.193 a: 1.4 dp:100.6 ci: 4 cj:361 U9S7ZP7WWS7YPM2 ?
t:  48 f: 0.193 a: 1.5 dp:100.2 ci: 6 cj:272 8MU.2K*XZ34F6GE ?
t:  96 f: 0.194 a: 1.4 dp:100.4 ci: 6 cj:272 RQ/SNDLGH3Q5H8B ?
t: 192 f:-0.322 pm: 153 jm:943               7D93677.GZJC/8U ?
t: 288 f:-0.322 pm: 259 jm:943               QUICK BROWN FO0 ?

In the second case, the 's' option tells WOLF to skip a number of samples from the input file before processing. This allows testing that carrier phase, bit phase, and frame timing is properly recovered. The 'f' and 'r' options are as described for transmit. Decoding was unsuccessful with these parameters.

For an on the air test, play wolfx.wav in loop mode into your SSB transmitter. It is important that there be no gap between the end of one frame and the beginning of the next. The loop playback in Cool Edit meets this requirement. If your playback program does not, create a file with several copies of the frame. At the receiving station, just save the audio from the Rx as wolfr.wav in mono at 8000 Hz, and run wolf on it. Depending on frequency accuracy, you may need to use the 't' option, e.g. -t 2.5 tells WOLF to search +/- 2.5 Hz for the signal. Values from 0.01 to 10.0 are reasonable; the default is 1.0 Hz. Larger values result in reduced sensitivity, and also require more memory.

Driving an "XOR gate" PSK transmitter

Starting with version 0.31, WOLF provides three ways to drive a transmitter which has a logic input to control the carrier phase. One method writes a wolfx.wav file which has a tone present for ones and absent for zeros. You rectify the audio output, filter it with a time constant of about a milliseconds, and use the result to key your Tx. For instance:

C:\wolf>wolf -x "QUICK BROWN FOX" -k -e -r 8000.123 -f 3000
WOLF version 0.31
Wrote wolfx.wav, 768056 bytes, at 8000.125 samples/sec., 3000.000 Hz

With this "keyed" output format, selected with the 'k' option, an output frequency of 3000 Hz was chosen to make filtering easier. You can also adjust for sound card sampling rate error, if needed.

Tx output via serial port

WOLF can write a file (wolfx.txt) for driving an "XOR gate" type of PSK transmitter via a serial port. The file is created by:

C:\wolf>wolf -x "NOW IS THE TIME" -n 100
WOLF version 0.31
Wrote wolfx.txt, 288000 bytes

The 'n' option turns on serial port output mode and specifies the number of frames (up to 1000) to be sent. Three bytes of all zeros or all ones are written for each encoded bit, so one frame is 2880 bytes long. For transmission, set up your serial port for 300 bps, 8 bits data, no parity, no flow control. Under Windows 2000, it should look like this:

C:\wolf>mode com1:

Status for device COM1:
    Baud:            300
    Parity:          None
    Data Bits:       8
    Stop Bits:       1
    Timeout:         OFF
    XON/XOFF:        OFF
    CTS handshaking: OFF
    DSR handshaking: OFF
    DSR sensitivity: OFF
    DTR circuit:     ON
    RTS circuit:     ON

After creating the file and setting up the serial port, use a copy command to start transmission:

C:\wolf>copy wolfx.txt com1:
        1 file(s) copied.

Unfortunately, the program does not currently provide a way to compensate for serial port baud rate clock errors. It is therefore necessary to do that at the receiving end, by lying about the sampling rate of the receiver's sound card. For example, if the serial port at the transmitter is running at 300.0123 bps, the sound card at the receiver has a sample rate of 8000.456 Hz, and the received audio frequency is 800.000 Hz, the command arguments -r 8000.128 and -f 799.967 would be used. By multiplying both rate and frequency arguments by the ratio of the desired and actual serial clock rates, the Tx and Rx will be synchronized.

The file test.txt may help you measure the clock rate of your serial port to within a few ppm. While copying it to COMx, record the output with your sound card. I did this by just connecting an earphone to the TXD line, placing it on the computer's microphone. Every nominal second, there is a burst of pulses which should be easy to spot. Measure the reported time between the start of a burst, and the start of one about 20 seconds later (the file is 25 seconds long). Adjust, if needed, for any sound card sampling error.

Tx output via EEPROM

If you have a BPSK-capable beacon which uses an EEPROM to store its message, WOLF can generate a binary file suitable for programming the device. This mode is activated by supplying a negative argument to the 'n' option:

C:\wolf>wolf -x "KK7KA RENO NV" -n -1
WOLF version 0.31
Wrote wolfx.bin, 961 bytes

The wolfx.bin file has one byte for each bit to be transmitted, followed by a "reset" byte. The data is in the LSB (bit 0), and the reset function is in bit 1. You may need to convert the .bin file to a .hex for some programmers.

Receiving Tools

WOLF requires very stable and accurate transmitters and receivers. Drift of only 3 millihertz per minute is a 3 dB loss; 10 mHz/min. will probably make communication impossible. The 'm' option allows you to measure frequency and drift (of an unmodulated carrier, not a WOLF signal):

C:\wolf>wolf -q xmgr.wav -f 1150 -t 10 -m 96
WOLF version 0.51
t:  96 f: 6.031 a:-0.9 dp: 56.7
t: 192 f: 6.028 a:-0.5 dp: 57.0
t: 288 f: 6.024 a:-2.9 dp: 57.2
t: 384 f: 6.028 a:-0.0 dp: 56.9
t: 480 f: 6.023 a:-2.3 dp: 58.2
t: 576 f: 6.018 a:-1.0 dp: 59.1
t: 672 f: 6.011 a: 2.9 dp: 60.9
t: 768 f: 6.010 a: 3.0 dp: 61.7
t: 864 f: 5.992 a:-2.3 dp: 60.8
t: 960 f: 5.992 a:-1.5 dp: 61.9
t:1056 f: 5.991 a: 0.8 dp: 60.9
t:1152 f: 5.986 a: 0.2 dp: 60.7
t:1248 f: 5.981 a:-2.0 dp: 60.7
t:1344 f: 5.981 a:-0.8 dp: 60.4
t:1440 f: 5.983 a: 0.4 dp: 60.0
t:1536 f: 5.981 a: 2.9 dp: 60.4
t:1632 f: 5.973 a:-1.5 dp: 59.6
t:1728 f: 5.958 a: 1.5 dp: 58.9
t:1824 f: 5.956 a: 1.3 dp: 53.4

In my attempted reception of XMGR on 184.9 kHz, the receiver was tuned to 184.1 USB. There is a carrier which I believe is on 185.250; this should nominally become 1150 Hz audio. The 'm' command displays frequency, angle, and power at the interval specified (from 10 to 100 seconds). You can see that my receiver was about 6 Hz low, and drifted up about 75 mHz in a half hour. First order compensation is provided by the 'w' (slew) option. Units are Hz/second.

C:\wolf>wolf -q xmgr.wav -f 1156 -t 10 -w -.000046 -m 96
WOLF version 0.51
t:  96 f: 0.032 a:-1.2 dp: 56.8
t: 192 f: 0.032 a:-0.6 dp: 57.1
t: 288 f: 0.033 a:-3.1 dp: 57.2
t: 384 f: 0.042 a:-0.4 dp: 56.9
t: 480 f: 0.040 a:-2.4 dp: 58.3
t: 576 f: 0.040 a:-1.3 dp: 59.2
t: 672 f: 0.037 a: 2.9 dp: 60.9
t: 768 f: 0.040 a: 2.8 dp: 61.8
t: 864 f: 0.028 a:-2.6 dp: 60.8
t: 960 f: 0.032 a:-1.6 dp: 61.9
t:1056 f: 0.035 a: 0.5 dp: 61.0
t:1152 f: 0.034 a: 0.2 dp: 60.8
t:1248 f: 0.034 a:-2.1 dp: 60.9
t:1344 f: 0.038 a:-0.8 dp: 60.5
t:1440 f: 0.044 a: 0.3 dp: 60.0
t:1536 f: 0.048 a: 2.7 dp: 60.5
t:1632 f: 0.043 a:-1.5 dp: 59.7
t:1728 f: 0.034 a: 1.1 dp: 59.0
t:1824 f: 0.035 a: 1.0 dp: 53.5

A crude noise blanker is available with the 'b' option: if a sample's magnitude exceeds the specified value (typically 4000 to 20000), that sample and the 5 surrounding in each direction are set to zero.

The 'l' option causes only the last frame processed (rather than the sum of all frames) to be used for detecting frequency and frame timing.

C:\wolf>wolf -q xmgr.wav -b 14000 -l -f 805.495 -t .1 -w -.000046 -r 8000.06
WOLF version 0.51
t:  24 f:-0.079 a: 0.4 dp: 89.7 ci: 2 cj: 82 7TIOWAN*V1/WU61 ?
t:  48 f:-0.079 a: 0.3 dp: 87.7 ci: 2 cj: 43 V//9HS???2LSEH9 ?
t:  96 f:-0.059 a: 0.0 dp: 84.3 ci: 2 cj:342 9H KV2MQ LCBARY ?
t: 192 f: 0.049 pm:  18 jm:564               /4LFHYP5AUOVUEO ?
t: 288 f: 0.010 pm:  19 jm:661               L7BZO9K7NVSPRWD ?
t: 384 f:-0.049 pm:  21 jm:  0               H1I8EP5OS16FJ F ?
t: 480 f: 0.088 pm:  19 jm: 62               57Y9BAV94152T9D ?
t: 576 f:-0.059 pm:  17 jm:851               JCB???8/SE2L??? ?
t: 672 f: 0.107 pm:  16 jm:240               LQW.PO6*/3LI*5H ?
t: 768 f: 0.020 pm:  16 jm:327               JQ21QIW 9N 3KN  ?
t: 864 f: 0.059 pm:  18 jm:116               G9TLSFQVGFMC4/D ?
t: 960 f:-0.078 pm:  24 jm:363               514GS44372XFDHG ?
t:1056 f: 0.020 pm:  22 jm:572               IVMF.AJHCP2WT3H ?
t:1152 f:-0.049 pm:  18 jm:326               EHW8V66H033H2TH -
t:1248 f: 0.088 pm:  20 jm: 90               NSC7AD06JP9 B1G ?
t:1344 f: 0.039 pm:  22 jm:564               B39HXR???RJ0I34 ?
t:1440 f: 0.049 pm:  26 jm:564               .53/SY/DZU * Y  ?
t:1536 f: 0.059 pm:  23 jm:354               VJS79LE2512*0DX ?
t:1632 f: 0.049 pm:  17 jm:  9               O57Z3VK MPPDBD  ?

The 'jm:' value gives the number of bits (0 to 959) to the best matched frame start. If three or more identical values appear in 'l' mode, you have probably detected a signal, especially if the frequency values are close. The 'pm:' values can give clues to times of best propagation, and you can then use the 's' option to focus in on that data.

New features in WOLF 0.61

A few options have been added to aid recovery of noisy signals, and to help diagnose if the right signal level, sample rate, etc., are being used.

C:\wolf>wolf -q 10419d.wav -r 8018.527 -f 800.108 -b 5000 -c 7
WOLF version 0.61
t:  24 f: 0.592 a: 0.3 dp:115.6 ci: 9 cj: 85 9O/6R/1R3BK .D0 ?
t:  48 f: 0.247 a:-0.9 dp:113.1 ci:12 cj:215 GGE7MXEPSIHAE28 -
t:  96 f: 0.590 a: 0.5 dp:109.2 ci: 7 cj: 49 7IN937BME53EEAQ ?
t: 192 f:-0.068 pm:  609 jm:602 q:-15.6 -7.6 T7.WE/7LIJWS4/0 ?
t: 288 f: 0.000 pm:  868 jm:796 q:-11.3 -7.6 Q3K*0X0U*FC195Q ?
t: 384 f: 0.000 pm: 1463 jm:796 q: -9.4 -7.8 R6FFJWB27/2FR88 ?
t: 480 f: 0.000 pm: 1739 jm:796 q: -9.5 -7.5 G1XLRUIT5MD26L2 ?
t: 576 f: 0.000 pm: 2228 jm:796 q: -9.3 -8.2  RZMD5AGU4QOXDG ?
t: 672 f: 0.000 pm: 2749 jm:796 q: -7.6 -7.9 QV0SB/5BD.14XJ. ?
t: 768 f: 0.000 pm: 3319 jm:796 q: -6.3 -8.6 88F4*KHBLL2AI83 ?
t: 864 f: 0.000 pm: 3957 jm:796 q: -5.6 -6.6 5A7F7HOBLQ6OTOT ?
t: 960 f: 0.000 pm: 4682 jm:796 q: -4.7 -5.3 M0BMU 10MW ERP  -
t:1056 f: 0.000 pm: 5349 jm:796 q: -3.6 -3.9 M0BMU 10MW ERP  -
t:1152 f: 0.000 pm: 5747 jm:796 q: -3.1 -3.1 M0BMU 10MW ERP  -
t:1248 f: 0.000 pm: 6325 jm:796 q: -2.4 -2.9 M0BMU 10MW ERP  -
t:1344 f: 0.000 pm: 6944 jm:796 q: -1.9 -2.4 M0BMU 10MW ERP  -
t:1440 f: 0.000 pm: 7637 jm:796 q: -1.5 -1.7 M0BMU 10MW ERP  -
t:1536 f: 0.000 pm: 8520 jm:796 q: -1.1 -1.0 M0BMU 10MW ERP  -
t:1632 f: 0.000 pm: 8898 jm:796 q: -0.3 -0.4 M0BMU 10MW ERP  -

In the example above, the 'c' option specifies the a number of frames over which to coherently integrate, to determine the carrier phase. The steady growth of 'pm' values shows that a valid reference is being received. If pm increases by 4000 or more in one frame, WOLF is being overloaded and the signal level should be reduced. If pm gains less than 10 counts per frame, try increasing the level. Two values are displayed for 'q': reference S/N and data S/N, both measured in dB on the 10 BPS baseband signal. Unfortunately, the data S/N is only valid when copy is correct. Values above -5 usually result in good copy; values below -6 usually result in garbage. The reference S/N, if steadily increasing, is the best sign of a valid signal. Correct copy usually occurs by the time -4 is reached. But with some settings, WOLF can choose different frequencies, phases, and timings for each frame, and will select apparently "good" matches from the noise. If those cases the displayed S/N may need to reach -1 before good copy is seen.

The 'v' option will display something like this for each received frame:

t:1632 f: 0.000 pm:10021 jm:796
fn=0 of= 0.000 p=125.9 f= 0.000 a= 0.1 j=7 r=   289
fn=1 of= 0.000 p=128.2 f= 0.000 a= 0.1 j=7 r=   216
fn=2 of= 0.000 p=129.9 f= 0.000 a= 0.2 j=7 r=   309
fn=3 of= 0.000 p=131.4 f= 0.000 a= 0.4 j=7 r=   186
fn=4 of= 0.000 p=131.7 f= 0.000 a= 0.5 j=8 r=   270
fn=5 of= 0.000 p=132.7 f= 0.000 a= 0.7 j=8 r=   324
fn=6 of= 0.000 p=132.8 f= 0.000 a= 0.8 j=8 r=   370
fn=7 of= 0.000 p=133.0 f= 0.000 a= 0.9 j=7 r=   333
fn=8 of= 0.000 p=133.2 f= 0.000 a= 1.2 j=7 r=   350
fn=9 of= 0.000 p=133.3 f= 0.000 a= 1.3 j=7 r=   413
fn=10 of= 0.000 p=133.5 f= 0.000 a= 1.4 j=7 r=   312
fn=11 of= 0.000 p=133.9 f= 0.000 a= 1.6 j=7 r=   356
fn=12 of= 0.000 p=133.9 f= 0.000 a= 1.8 j=7 r=   349
fn=13 of= 0.000 p=132.6 f= 0.000 a= 1.9 j=7 r=   380
fn=14 of= 0.000 p=131.3 f= 0.000 a= 1.9 j=7 r=   432
fn=15 of= 0.000 p=129.6 f= 0.000 a= 2.0 j=8 r=   398
q:  0.1 -0.4 M0BMU 10MW ERP  -

'fn' is the frame number.
'of' is the original frequency, relative to '-f' parameter.
'p' is relative power level of reference for this frame.
'f' is measured or constrained frequency used for this frame.
'a' is measured phase angle, over '-c' frames.
'j' is relative bit timing, in 1/80 second units.
'r' is demodulated reference in arbitrary voltage units.

In this case, the steadily rising angle shows a slight frequency error, but a relatively quiet signal. Likewise the quite steady bit timing. If these values seem to be random, the signal is not sufficient to achieve lock. A steadily rising or falling 'j' means that your sound card sample rate, and/or the bit timing at the transmitter, is incorrect.

Although WOLF does not yet have any graphical output, you can see the despread carrier by giving a '-m -1' command. This writes a wolfm.txt file. Open this with Excel or compatible, and plot a default XY chart. This gives you a good view of the noise and interference present:

Each point represents 16 seconds (6 points per frame).
If you see peaks every six points, there is probably QRM which happens to correlate slightly with the PN pattern.

Some experimental options have been added under '-o'. This takes an octal argument; each bit turns the corresponding option on. Presently available are:

001 Force all frames to use the same bit timing.
002 Force all frames to use the same frequency.
004 Crude "matched filter" (center of bit cell weighted more heavily).
010 Crude intersymbol interference (ISI) compensation.
100 Display ISI info (after compensation, if any).
For example, '-o 14' will turn on the matched filter and ISI compensation. These options will sometimes degrade performance. Try them on a signal you can already decode. If the S/N improves, the option will probably help on other signals from the same source.


Lyle Kohler's "WOLF for Beginners" page

Les Rayburn's WOLF news page

How WOLF works

The WOLF signal is very similar to BPSK. In fact, it *is* BPSK at MS100, but with a specially constructed bitstream. After each "data" bit, a "reference" bit is transmitted. You can think of the signal as having a data channel and a reference channel. The reference stream is a long pseudo-random sequence that is known in advance by the receiver. Its purpose is to enable recovery of carrier frequency and phase, bit timing, and message timing, even when the signal is very weak. The message to be transmitted is broken into packets of up to 15 characters each. The packet data is "source coded" into 80 bits; FEC coding with a 1/6 rate is then applied, resulting in a 480 bit data stream. After adding reference bits, the final packet is 960 bits long and takes 96 seconds to send.

A beacon just repeats this frame every 96 seconds. For two-way use, a special protocol would allow efficient use of the half-duplex channel.

Reference Channel

A key feature of WOLF is its pilot signal, a pseudo-random, but constant bit stream, which is interleaved with the message content. The present program only uses this signal for timing recovery as described above.

It may seem to be extremely wasteful to devote half of the transmitted energy to a signal with no "information", but future versions will use it for accurate path characterization, and I believe that will more than recover the 3 dB loss. Rather than simply summing multiple frames, it will be possible to combine them intelligently, so that during QSB dips, useless noise will be ignored. Likewise, data received during propagation peaks will be weighted heavily.

An accurate "S-meter" will also aid station adjustment, and provide useful input for the higher level protocol.

Source Coding

In any digital communication system, it is desirable to minimize the number of bits needed to represent a message, so that information can be sent faster, or so that more energy is available for each bit.

Most modern systems for lossless compression, e.g. ZIP, depend on identification of repeated patterns, and are thus not useful for very short messages. Systems such as Morse code or PSK31's Varicode work by using shorter codes for more frequent letters. However, this also is no help for the messages required for a minimal QSO - a call sign is just as likely to contain a "Q" as an "E".

How then, should our message be coded? One could develop an "application specific" code. For example, knowing that there are fewer than four million licensed hams in the world, we could put all call signs in a giant database and assign a number to each. A call sign could then be represented in just 22 bits. You could take this further and build a list of up to 1000 "LF weak signal" operators, and use only 10 bits for a call sign. However, I feel that such systems are begging the point, and that real communication is best demonstrated when information previously unknown to the recipients is successfully conveyed in both directions.

Unfortunately, I don't have a good solution, and welcome any ideas on the subject. In the short term, I feel that using a reduced symbol set can provide some compression. For example, if we restrict ourselves to upper case letters, digits, space, and no more than three punctuation marks (40 symbols total), we can code each group of three symbols into a 16 bit word, thus using about 5.3 bits per symbol. This compares favorably with Morse (~8.3 bits), 7-bit ASCII, and Varicode (~6.5 bits). To be fair, the values for Morse and Varicode include synchronization information, not required by WOLF, as that function is provided by the reference channel. On the other hand, Morse and Varicode are based on English text, and the bit usage of those codes increases greatly when arbitrary strings such as callsigns are sent. Relative to ASCII, we have a source coding gain of 10*log(7/5.33) = ~1.2 dB.

Five of these 16 bit words form an 80 bit message, to which error control information is added.

Channel Coding

What is the best error control coding for this application? The latest communication systems are being designed with turbo codes and turbo product codes with amazing performance -- some of them can operate within 1 dB of the Shannon limit! Unfortunately, these powerful codes require long message blocks for efficient operation. When the message block is shorter than about 150 bits, there is little or no advantage, compared with conventional convolutional codes. See this comparison paper. I would be interested in hearing about codes which perform well on short blocks. If none turn up, I expect to use (in a tail-biting mode) a K=15, rate 1/6, convolutional code which was considered for the Galileo space probe. This code is well suited to variable rate operation, and the code actually used by Galileo is a rate 1/4 subset. At a level such that the 80 bit message is correctly received 80% of the time, coding gain is about 6 dB over uncoded BPSK. See description and analysis.


When operating at very low S/N, it is often not possible to tell when the other station is transmitting, so standard practice is to allocate specific time slots for each direction, e.g. "east station transmits during odd periods; west during even". However, it is typically the case that trasmission in one direction is not as bad as in the other, so it would be more efficient if there were a way to allocate most of the channel time to the more degraded direction.

Also, it is desirable to send "status" or "control" information at a lower rate than "data" messages, so that they will likely be correctly received, even under conditions which would require many repeats of a data message.

My proposal is to allow two formats for the data channel: the 80-bit message described previously, and a 3-bit control/status function. The three bits are expanded into a 7-bit orthogonal code (each function differs from any other in four bits), which is then repeated to fill the frame. The receiver attempts to decode each signal as both a function and a message, and chooses the more likely match. The defined functions are:

Name   Meaning
----   -------
NIL    No reference signal is detected from the other station.
T      Reference seen, but S/N too low for solid function decode.
M      S/N sufficient for reliable function code reception.
O      Successful reception of data message.
REQ    Commands other station to send data message.
REQM   Other station should send data message seven times.
RO     Received data message OK as well as O for message sent.
R      Acknowlegement of RO or R.

Here's how the protocol might work in a typical QSO; signals are
better in the W->E direction.

Per.  Dir.  Sent  Description
----  ----  ----  -----------
 1    E->W  NIL   E has not received anything yet.
 2    W->E  T     Transmission poor from E to W.
 3    E->W  M     E can receive control functions from W.  In effect
                  this is an invitation for W to become the "master".
 4    W->E  REQM  Although W got the "M", he is seeing poor S/N, so
                  he tells E to send the message seven times.
5-11  E->W  (msg) E sends call signs, etc. to W in seven slots.
 12   W->E  REQM  W cannot decode E's message yet.
13-19 E->W  (msg) E sends his message seven more times.
 20   W->E  (msg) W has now decoded E's message and sends his.
 21   E->W  M     Although the W->E path is solid for three bits, E
                  cannot decode W's 80 bit message yet.
 22   W->E  (msg) W sends his message again.
 23   E->W  O     E has received W's message successfully.
 24   W->E  (msg) Alas, the poor E->W path lost the "O".
 25   E->W  O     E sends another "O".
 26   W->E  RO    W now has E's report (and also message).
 27   E->W  R     E has enough information for QSO.
 28   W->E  R     W has enough information for QSO.

Assuming 100 seconds for each period, this QSO takes just under 47 minutes. For strong signals, only nine periods are needed and the QSO completes in 15 minutes.


One potential problem with this system is interference from LORAN, because the required bandwidth is too great to fit between the spurs. However, I believe that it should be easy to add a front-end comb filter to the software, with negligible degradation of the desired signal. Using this "QRM" to adjust for receiver and sound card drift should also be possible.

Multitone FSK, etc.

I believe that sending multiple tones at once is not suitable for weak-signal LF work. Virtually all PA's in use are limited by PEP (rather than thermally). Therefore, sending two independently controlled tones requires that each be 6 dB below the level permitted for a single tone, to avoid clipping the envelope. Compared with sending the tones sequentially, there is a still a 3 dB loss, even after allowing for the longer durations. PSK, when filtered to keep the transmitted spectrum clean, can also suffer a loss of up to 3 dB. The nonlinear filter used by PSK31 and WOLF has an average power loss of 1.5 dB or less.

However, sending one tone from an "alphabet" of many holds some promise. Many texts on communication have a chart showing performance of M-ary FSK as a function of M, approaching the Shannon limit as M goes to infinity! However, this is IMO very misleading, because M-ary coding is in essence a form of ECC as well as a modulation scheme. For example, if you could take it to the extreme, and use a different frequency for every possible message, then each message will have a (slight) negative correlation with every other, and the required S/N will be far lower than for a simple binary code. But, it is impossible to further improve this FSK scheme with ECC; the message coding is already optimum. A practical FSK system, using e.g. 4 to 64 frequencies, can be enhanced with ECC, but the additional coding gain will be less than for a binary system. For a fair comparison of PSK vs FSK, both systems should be evaluated using the best ECC available.

When this is considered, FSK has an advantage when the path (or equipment) is unstable (relative to the channel capacity); PSK is better for stable paths. IMO, PSK should be better on LF, even for a two hop link. If that proves not to be the case, it should not be too hard to build a version of WOLF using say, 8 or 16 tones.


Please send comments, suggestions, bug reports, questions, flames, etc., to [email protected].

Stewart KK7KA