Skip to main content

Overview

FSK (Frequency Shift Keying) modems encode binary data by switching between two frequencies:
  • Mark frequency: Represents binary ‘1’ (or idle state)
  • Space frequency: Represents binary ‘0’
minimodem allows you to override the default frequencies using the --mark and --space options, enabling compatibility with custom protocols and non-standard signals.

Command-Line Options

—mark (-M)

Specifies the mark frequency in Hertz:
minimodem --tx --mark 1200 <baudmode>
minimodem --rx --mark 1200 <baudmode>
The mark frequency must be greater than 0 Hz. There is no upper limit enforced, but practical limits apply based on sample rate and audio hardware.

—space (-S)

Specifies the space frequency in Hertz:
minimodem --tx --space 2200 <baudmode>
minimodem --rx --space 2200 <baudmode>

Default Frequency Behavior

When not specified, minimodem automatically calculates mark and space frequencies based on the baud rate:

High Speed (≥ 400 bps) - Bell 202 Style

Mark frequency  = (baud_rate / 2) + 600 Hz
Space frequency = mark - (baud_rate × 5/6) Hz
Example for 1200 bps:
  • Mark: 1200 Hz
  • Space: 2200 Hz
  • Shift: -1000 Hz

Medium Speed (100-399 bps) - Bell 103 Style

Mark frequency  = 1270 Hz
Space frequency = 1070 Hz
Shift          = 200 Hz
Example for 300 bps:
  • Mark: 1270 Hz
  • Space: 1070 Hz
  • Shift: 200 Hz

Low Speed (< 100 bps) - RTTY Style

Mark frequency  = 1585 Hz
Space frequency = 1415 Hz
Shift          = 170 Hz
Example for 45.45 bps (RTTY):
  • Mark: 1585 Hz
  • Space: 1415 Hz
  • Shift: 170 Hz
Use the ###CARRIER message that minimodem prints when receiving to verify which frequencies were detected or calculated.

Examples

Standard Bell 202 (1200 bps)

Explicitly set Bell 202 frequencies:
echo "Test" | minimodem --tx --mark 1200 --space 2200 1200
Receive Bell 202:
minimodem --rx --mark 1200 --space 2200 1200

TTY/TDD (Telecommunication Device for the Deaf)

TDD uses specific frequencies for 45.45 bps Baudot:
minimodem --rx --mark 1400 --space 1800 tdd
The tdd mode automatically sets these frequencies, but you can override them if needed.

NOAA SAME Weather Radio

SAME (Specific Area Message Encoding) uses:
minimodem --rx --mark 2083.3 --space 1562.5 same

Custom Protocol

Create a completely custom FSK encoding:
echo "Custom" | minimodem --tx --mark 1000 --space 1500 600
minimodem --rx --mark 1000 --space 1500 600

UIC-751-3 Train/Ground Communication

European train control system frequencies:
minimodem --rx --mark 1300 --space 1700 uic-ground

Frequency Inversion

The --inverted option swaps the mark and space frequencies:
minimodem --rx --inverted 1200
This is equivalent to:
minimodem --rx --mark 2200 --space 1200 1200
Some protocols naturally use inverted signaling. If you’re receiving garbled data, try adding --inverted.

Frequency Shift

The shift is the difference between mark and space frequencies:
Shift = Mark frequency - Space frequency
  • Positive shift: Mark > Space (e.g., Bell 103: 1270 - 1070 = +200 Hz)
  • Negative shift: Mark < Space (e.g., Bell 202: 1200 - 2200 = -1000 Hz)
Common shifts:
  • 170 Hz: Traditional RTTY
  • 200 Hz: Bell 103
  • 850 Hz: High-speed Bell 202
  • 1000 Hz: 1200 bps Bell 202

Auto-Detection

With --auto-carrier (-a), minimodem can automatically detect the mark frequency:
minimodem --rx --auto-carrier 1200
The auto-detection:
  1. Scans incoming audio for strong frequency components
  2. Identifies the mark frequency
  3. Calculates space frequency based on the expected shift
Auto-detection works best with clean signals. For noisy environments, manually specify frequencies.

Bandwidth Filtering

The --bandwidth option affects how tightly the receiver filters around the mark and space frequencies:
minimodem --rx --mark 1200 --space 2200 --bandwidth 100 1200
  • Narrower bandwidth: Better noise rejection, requires precise frequency tuning
  • Wider bandwidth: More tolerant of frequency drift, but more noise
Default bandwidths:
  • ≥ 400 bps: 200 Hz
  • 100-399 bps: 50 Hz
  • < 100 bps: 10 Hz

Implementation Details

From src/minimodem.c, the frequency handling:
// Lines 695-701: Command-line parsing
case 'M':
    bfsk_mark_f = atof(optarg);
    assert( bfsk_mark_f > 0 );
    break;
case 'S':
    bfsk_space_f = atof(optarg);
    assert( bfsk_space_f > 0 );
    break;
The FSK plan initialization (line 1045):
fskp = fsk_plan_new(sample_rate, bfsk_mark_f, bfsk_space_f, band_width);

Troubleshooting

No Carrier Detected

If minimodem doesn’t detect a carrier:
  1. Verify frequencies: Use audio analysis tools to measure actual frequencies
  2. Check signal level: Ensure adequate volume (use --volume to adjust)
  3. Try auto-detect: Use --auto-carrier to let minimodem find the signal
  4. Increase bandwidth: Use --bandwidth to widen the filter

Garbled Output

If output is mostly garbage:
  1. Verify mark and space: Double-check frequency specifications
  2. Try inversion: Add --inverted to swap frequencies
  3. Check baud rate: Ensure the baud rate matches the signal
  4. Adjust confidence: Lower --confidence threshold

Frequency Drift

For signals with frequency instability:
  1. Widen bandwidth: Increase --bandwidth value
  2. Use higher sample rate: Try --samplerate 96000
  3. Check confidence limit: Adjust --limit for better tracking

Advanced Techniques

Scanning for Unknown Frequencies

Use a spectrum analyzer or the auto-carrier feature:
# Let minimodem find the carrier automatically
minimodem --rx --auto-carrier -q 300 2>&1 | grep CARRIER
This will print:
### CARRIER 300 @ 1270.0 Hz ###

Testing Frequency Response

Generate test tones to verify your audio path:
# Transmit a test pattern
echo "U" | minimodem --tx --mark 1200 --space 2200 1200
The letter ‘U’ (0x55 in binary: 01010101) creates an alternating pattern ideal for testing.

Frequency Reference Table

ProtocolBaud RateMark (Hz)Space (Hz)Shift (Hz)
Bell 10330012701070+200
Bell 202120012002200-1000
RTTY45.4515851415+170
TDD45.4514001800-400
NOAA SAME520.832083.31562.5+520.8
UIC Ground60013001700-400

See Also

Build docs developers (and LLMs) love