User Tools

Site Tools


Audio Format

Audio samples are generated by a complex modulator in the base band. These samples are upmixed to 1.5 kHz (mid of an SSB channel) and sent to the sound card.

For compatibility between different programs we need to know the physical format, the modulation:


The modulation is done with the liquid-DSP's modulator/demodulator. Formats used:


all in “normal” mode, NOT differential

to get a fully compatible program it is highly recommended to use the interpolator/filter settings as in liquid_if.cpp because these settings are optimized for the 2.7kHz SSB channel.

The complex output of the modulator is upmixed by a liquid-NCO to 1500 Hz.


the default liquid-DSP constellation is used, no changes.

Frame & Rotation detection

Frame length:

the frame length is 255 Bytes (scrambled) as shown in the next chapters. Each frame has a 3 byte header, so in summary there are 258 bytes to transmit.

The number of 258 Bytes is important because it can be divided by 2 (129) and also by 3 (86). Therefore we can convert it to QPSK and 8APSK symbols without any fractional remaining bits which makes calculations more efficient.
The same is valid for the 3 Byte header which also is dividable by 2 or 3.

Header detection

in non-differential PSK the phase is unknown, so the symbols can be rotated by 4 (QPSK) or by 8 (8APSK). For detection of the rotation value the “unique word” method is used: The header is tested 4 times for each possible QPSK rotation. If the header is detected then the rotation value is found and the whole frame is back-rotated by this value resulting in the original stream (8 values for 8APSK).

The header has the values 0x53 - 0xe1 - 0xa6 which corresponds to these symbols:

Byte: 0x53 0xe1 0xa6
bits: 01010011 11100001 10100110
syms: 01010011 11100001 10100110
syms: 1 1 0 3 3 2 0 1 2 2 1 2
syms: 2 4 7 6 0 6 4 6

these symbols are tested for 2 rotations (BPSK), 4 rotations (QPSK) or 8 rotations (8APSK). Functions to calculate the rotations and to back-rotate a complete frame can be found in constellation.cpp

False Detections

it is possible, and it will happen quite often. A header is detected but it is not a real header. This is totally irrelevant because the CRC16 will cancel the mistakenly detected frame. The only downside is that the CPU load is a bit higher because an invalid frame was checked.

Therefore we can allow some inaccuracy in the header. If only a few bits are wrong we still accept it as a header. This improves detection when weak signals are received.

See frame_packer.cpp:

Under Windows we allow 5 wrong header bits because Windows PCs usually have powerful CPUs. Under Linux only 2 wrong bits are allowed to keep the CPU load low on Rapberry PI and other SBCs.

en/hsmodem/ota.txt · Last modified: 2021/03/28 19:14 (external edit)