April 29, 2022 - Reading time: 2 minutes
AHICDM is a simple digital mode that transmits bits by varying the amount of silence between pulses. It is a narrowband mode that transmits slowly.
I only came across this modulation while looking at the Recently changed pages list of sigidwiki. It looked easy to implement, and didn’t have much written about it, so I decided to play around with the provided audio example.
I have never seen this modulation used in the wild, and the only mention I have seen of it is in the Signal Identification Wiki. This page is written by analyzing the audio recording provided on the wiki page.
Name | Value |
---|---|
Tone | frequency 440 Hz |
Tone | duration 100 ms / 0.1 sec |
Preamble | duration 700 ms / 0.7 sec |
The baud rate of this modulation depends on the content of the message. A message of all 1 bits will take longer to transmit compared to a message of all 0
bits.
Below is a simple modulator written in Python.
#!/usr/bin/env python3
import os
import struct
import numpy as np
class AHICDM_Modulator:
def __init__(self, freq=440, rate=64_000):
self.rate = rate
self.sample = 0
self.freq = freq
self.amp = 0
self.phase = 0
@property
def time(self):
return self.sample / self.rate
def output_sample(self, sample):
self.sample += 1
sample = np.random.normal(sample, 0.01)
sample += 1
sample *= 128
sample = int(sample)
sample = max(0, min(sample, 255))
os.write(1, bytes([sample]))
def amplitude_duration(self, amplitude, duration):
target = self.time + duration
while self.time < target:
self.amp = (self.amp * 0.991) + (amplitude * 0.009)
self.phase += 2 * np.pi * self.freq / self.rate
s = np.sin(self.phase) * self.amp
self.output_sample(s)
def send_bit(self, bit):
if bit == 1:
self.amplitude_duration(0, 0.3)
else:
self.amplitude_duration(0, 0.15)
self.amplitude_duration(1, 0.1)
def bits(buf):
for byte in buf:
for i in range(8)[::-1]:
i = (byte >> i) & 1
yield int(i)
mod = AHICDM_Modulator()
mod.amplitude_duration(0, 0.88)
mod.amplitude_duration(1, 0.7)
for bit in bits(b"gkbrk.com"):
mod.send_bit(bit)
mod.amplitude_duration(0, 0.7)
mod.amplitude_duration(1, 0.1)