MIL-STD-188-110 - US military HF serial tone modem standard.
| Property | Value |
|---|---|
| Frequency Range | 2-30 MHz (HF band) |
| Modulation | PSK (BPSK, QPSK, 8-PSK) |
| Data Rates | 75, 150, 300, 600, 1200, 2400, 4800 bps |
| FEC | Convolutional (K=7, rate 1/2) |
| Interleaving | Block (short: 0.6s, long: 4.8s) |
| Bandwidth | 3 kHz (voice channel compatible) |
┌─────────────────────────────────────────────────────────────────┐
│ MIL-STD-188-110 Implementation Status │
├─────────────────────────────────────────────────────────────────┤
│ [█████████████████████████████████████░░░░░░░░░░░] 94% │
├─────────────────────────────────────────────────────────────────┤
│ ✅ PSK Modulation (all modes) (25% effort) - Complete │
│ ✅ Convolutional FEC (20% effort) - Complete │
│ ✅ Block Interleaver (15% effort) - Complete │
│ ✅ Preamble Generation (15% effort) - Complete │
│ ✅ Data Rate Modes (10% effort) - Complete │
│ ⚠️ Viterbi Decoder (15% effort) - Basic (60%) │
└─────────────────────────────────────────────────────────────────┘
This waveform is fully unclassified. No classified components need porting.
┌─────────────────────────────────────────────────────────────────┐
│ MIL-STD-188-110 Modem │
├─────────────────────────────────────────────────────────────────┤
│ │
│ ┌─────────────────────────────────────────────────────────┐ │
│ │ Input Data │ │
│ └────────────────────────┬────────────────────────────────┘ │
│ │ │
│ ┌────────▼────────┐ │
│ │ FEC Encoder │ │
│ │ (K=7, Rate 1/2) │ │
│ └────────┬────────┘ │
│ │ │
│ ┌────────▼────────┐ │
│ │ Interleaver │ │
│ │ (Short or Long) │ │
│ └────────┬────────┘ │
│ │ │
│ ┌────────▼────────┐ │
│ │ Symbol Mapper │ │
│ │ (BPSK/QPSK/8PSK)│ │
│ └────────┬────────┘ │
│ │ │
│ ┌────────▼────────┐ │
│ │ Preamble Insert │ │
│ │ (Sync/Probe) │ │
│ └────────┬────────┘ │
│ │ │
│ ┌────────▼────────┐ │
│ │ PSK Modulator │ │
│ │ (1800 Hz tone) │ │
│ └────────┬────────┘ │
│ │ │
│ ▼ │
│ Audio Output │
│ (300-3000 Hz) │
└─────────────────────────────────────────────────────────────────┘
Since this waveform is fully unclassified, improvements can be contributed directly to R4W.
The current Viterbi decoder is functional but could be optimized:
// Current implementation in r4w-core
pub struct ViterbiDecoder {
constraint_length: usize, // K=7
polynomials: (u8, u8), // G1=0o171, G2=0o133
// ...
}
// Enhancement opportunities:
// 1. SIMD acceleration for path metric calculations
// 2. Traceback optimization with circular buffer
// 3. Soft-decision input support
// 4. Punctured code support for higher ratesSuggested improvements:
// Enhanced Viterbi with SIMD
#[cfg(target_arch = "x86_64")]
use std::arch::x86_64::*;
impl ViterbiDecoder {
/// SIMD-accelerated butterfly computation
#[target_feature(enable = "avx2")]
unsafe fn butterfly_avx2(&mut self, symbols: &[f32]) {
// Use AVX2 for parallel path metric updates
// Each butterfly updates 2 states, process 8 at once
// ...
}
/// Soft-decision decoding with log-likelihood ratios
pub fn decode_soft(&mut self, llr: &[f32]) -> Vec<u8> {
// Process soft symbols for better BER performance
// 2-3 dB improvement over hard decision
// ...
}
}The standard defines additional modes:
| Rate | Modulation | Current | Enhancement |
|---|---|---|---|
| 75 bps | BPSK | ✅ | - |
| 150 bps | BPSK | ✅ | - |
| 300 bps | BPSK | ✅ | - |
| 600 bps | QPSK | ✅ | - |
| 1200 bps | QPSK | ✅ | - |
| 2400 bps | QPSK | ✅ | - |
| 4800 bps | 8-PSK | ✅ | - |
| 9600 bps | 8-PSK | ❌ | Appendix C |
| 19200 bps | 8-PSK | ❌ | Appendix D |
MIL-STD-188-110 is often used with ALE:
// Integration with existing ALE implementation
use r4w_core::waveform::ale::Ale;
use r4w_core::waveform::milstd188110::MilStd188110;
pub struct AleDataModem {
ale: Ale,
data_modem: MilStd188110,
}
impl AleDataModem {
/// Establish link and send data
pub async fn send_data(&mut self, address: &str, data: &[u8]) -> Result<(), Error> {
// 1. ALE call
self.ale.call(address).await?;
// 2. Switch to data mode
let modulated = self.data_modem.modulate(data);
// 3. Transmit
self.transmit(&modulated).await?;
// 4. ALE terminate
self.ale.terminate().await?;
Ok(())
}
}Since no classified components are involved, standard development workflow applies:
# Build
cargo build --release
# Run tests
cargo test -p r4w-core waveform::milstd188110
# Benchmark Viterbi decoder
cargo bench --bench viterbi
# Test with known waveform samples
cargo run --bin r4w -- decode --waveform MIL-STD-188-110 \
--input test_signal.wav --rate 2400Test against other implementations:
#[test]
fn test_interop_with_reference() {
// Load reference signal generated by Harris radio
let reference = load_wav("test_data/milstd_2400bps_reference.wav");
let modem = MilStd188110::new(DataRate::Bps2400);
let decoded = modem.demodulate(&reference);
assert_eq!(decoded, b"THE QUICK BROWN FOX");
}
#[test]
fn test_loopback_all_rates() {
for rate in [75, 150, 300, 600, 1200, 2400, 4800] {
let modem = MilStd188110::new(DataRate::from_bps(rate));
let test_data = b"TEST MESSAGE";
let modulated = modem.modulate(test_data);
// Add realistic channel effects
let noisy = add_awgn(&modulated, 10.0); // 10 dB SNR
let decoded = modem.demodulate(&noisy);
assert_eq!(decoded, test_data, "Failed at {} bps", rate);
}
}MIL-STD-188-110 modems are commonly deployed on:
| Platform | Target | Use Case |
|---|---|---|
| Raspberry Pi | aarch64-unknown-linux-gnu |
Field testing |
| BeagleBone | armv7-unknown-linux-gnueabihf |
Embedded HF modem |
| Desktop | x86_64-unknown-linux-gnu |
Development/simulation |
| WebAssembly | wasm32-unknown-unknown |
Browser simulation |
# Cross-compile for ARM
cross build --release --target aarch64-unknown-linux-gnu
# Build for WASM (training/simulation)
cargo build --release --target wasm32-unknown-unknown// Enable SIMD features
#[cfg(target_arch = "x86_64")]
compile_error!("Enable AVX2 for best performance: RUSTFLAGS='-C target-cpu=native'");
// Build with:
RUSTFLAGS="-C target-cpu=native" cargo build --releaseFor real-time HF operation:
// Use ring buffer for continuous processing
use ringbuf::{HeapRb, Rb};
pub struct RealtimeModem {
modem: MilStd188110,
sample_buffer: HeapRb<f32>,
symbol_buffer: HeapRb<Complex32>,
}
impl RealtimeModem {
/// Process samples in real-time
pub fn process_chunk(&mut self, samples: &[f32]) -> Option<Vec<u8>> {
self.sample_buffer.push_slice(samples);
// Process when we have enough samples
if self.sample_buffer.len() >= self.modem.samples_per_symbol() * 100 {
let chunk: Vec<f32> = self.sample_buffer.pop_iter().take(1000).collect();
Some(self.modem.demodulate_chunk(&chunk))
} else {
None
}
}
}Since this is fully unclassified:
git checkout -b feature/viterbi-simd
# ... implement ...
cargo test
git commit -m "perf(milstd188110): add AVX2 Viterbi acceleration"
git push origin feature/viterbi-simd
# Create PR on GitHub