Repository navigation
Olivia
Olivia is an MFSK mode with a strong forward error correction, designed by Pawel Jalocha for weak signal keyboard chat in amateur radio. Each symbol is one of 2 to 256 tones. The characters are sent in blocks: each character is a Walsh-Hadamard code word of 64 bits, which is scrambled and spread diagonally over the 64 symbols of the block, so that a disturbed symbol only damages a few bits of many characters. Contestia is the faster variant with 6 bit characters (upper case text) and blocks of 32 symbols. Both are implemented like in fldigi.
Advantages
- Very robust:
olivia-32-1000decodes about 12 dB below the noise (in 3 kHz bandwidth). - Robust against frequency offsets (the receiver searches ±8 bins) and different clocks.
- The same signal as fldigi (the tones, the symbol shape and the error correction follow fldigi's source code).
- No configuration of the receiver beyond the mode: it finds the timing and the frequency itself.
Disadvantages
- Very slow: 1 to 5 characters per second (
olivia-32-1000: 2.4). - 7 bit text: Olivia sends bytes above 127 escaped with 127 (like fldigi with 8 bit characters), so the byte 127 itself can't be sent. Contestia only sends upper case letters, digits and some punctuation.
- The receiver needs more CPU and memory than the simple modems (about 30 KB for
olivia-32-1000). - The receiver shows random characters in pure noise, like fldigi without squelch.
- The interoperability with fldigi has not been tested with fldigi itself.
The mode name is olivia-T-B or contestia-T-B with T tones (2 - 256, a power of 2) and a bandwidth B of 125, 250, 500, 1000 or 2000 Hz (also 1k, 2k). Common modes:
| Mode | Symbols/s | Characters/s | |
|---|---|---|---|
olivia-4-125 |
31.25 | 0.98 | |
olivia-8-250 |
31.25 | 1.46 | popular |
olivia-8-500 |
62.5 | 2.9 | |
olivia-16-500 |
31.25 | 1.95 | |
olivia-32-1000 (olivia) |
31.25 | 2.44 | fldigi default |
olivia-64-2000 |
31.25 | 2.9 | |
contestia-8-250 (contestia) |
31.25 | 2.9 | |
contestia-32-1000 |
31.25 | 4.9 |
The signal is centered at 1500 Hz (center_freq, -M on the command line). The signal is defined at 8000 Hz: other sample rates are converted.
I2SStream i2s;
OliviaStream modem(i2s, RXTX_MODE);
void setup() {
OliviaConfig cfg = modem.defaultConfig(); // olivia-32-1000
cfg.setMode("olivia-8-250");
cfg.sample_rate = 8000;
...
modem.begin(cfg);
}
void loop() {
modem.println("CQ CQ de N0CALL");
modem.flush(); // sends the last block and the stop tones
while (modem.available()) Serial.write(modem.read());
}echo "CQ CQ de N0CALL" | tinymodem --tx -f cq.wav olivia-8-250
tinymodem --rx -f cq.wav olivia-8-250OliviaConfig, OliviaEncoder, OliviaDecoder, OliviaStream, OliviaStreamRTOS and OliviaCodec (the error correction) are the Olivia classes. Characters are collected until a block is complete (bits per symbol characters): call flush() (or endTransmission()) to send an incomplete block, which is filled with the idle character 0. On the command line, -R, -v, -M (center frequency), -q, --rx-one and --Xrxnoise are supported.
OliviaConfig field |
Default | |
|---|---|---|
tones |
32 | Number of tones (2 - 256) |
bandwidth |
1000 | Bandwidth (125, 250, 500, 1000 or 2000 Hz) |
center_freq |
1500 | Center frequency (Hz) |
contestia |
false | Contestia instead of Olivia |
volume |
1.0 | Transmit amplitude |
start_tones |
true | Transmitter: send fldigi's start and stop tones at the band edges |
sync_margin |
8 | Receiver: frequency search range in FFT bins (tone spacing / 2), limited to the audio band |
sync_integration |
4 | Receiver: integration period of the synchronizer in blocks |
sync_threshold |
3.0 | Receiver: minimum signal to noise ratio |
rx_one |
false | Receiver: stop after the first transmission |
channel |
0 | Receiver: input channel |
sample_rate, channels, bits_per_sample
|
48000, 1, 16 | Audio format |
The transmitter sends each symbol as a tone with a raised cosine envelope over two symbol periods, so consecutive symbols overlap by half. The phase continues from symbol to symbol with a random step of ±90 degrees, like fldigi. Each character (7 bits, Contestia 6 bits) becomes a Walsh-Hadamard code word of 64 (32) bits with an inverse fast Hadamard transform. The code word is scrambled with a fixed sequence and its bits are spread diagonally over the symbols of the block. A tone carries bits per symbol bits (Gray coded). A transmission starts and ends with the fldigi start/stop tones at the band edges.
The receiver converts the input to 8000 Hz. Twice per symbol it calculates the tone energies with an FFT and converts them to soft bits for each possible frequency offset. For each time slice and frequency offset, the last block is decoded after every symbol with a fast Hadamard transform: the strongest correlation is the character. The synchronizer integrates the signal and noise of these decodings over a few blocks and selects the timing and frequency with the strongest signal. A block is provided if its signal to noise ratio is above the threshold. Blocks of steady tones (like the start and stop tones) are rejected. The idle character 0 is not provided.
Measured at 8000 Hz:
-
Noise:
olivia-32-1000without errors up to noise 6 (about -12.5 dB SNR in 3 kHz bandwidth), Contestiacontestia-8-250up to 5. -
Frequency offset: ±60 Hz with
olivia-32-1000. -
Different clocks: ±0.2% (
olivia-16-500). -
Speed: 270 × real time on a PC. On microcontrollers at 8000 Hz: 2.6 (ESP32-S3) and 5 (ESP32-P4) × real time for
olivia-32-1000. The RP2040 (0.5) is too slow for real time decoding, see Performance. -
Over the air on the ESP32-P4 (speaker to the onboard microphone of the same board):
olivia-32-1000,olivia-8-500andcontestia-8-250were received without errors.