1 stable release

Uses old Rust 2015

1.0.0 Feb 27, 2017

#13 in #fm

MIT license

6KB
54 lines

demod_fm.rs -- FM signal demodulator

Documentation

This crates provides a simple FM signal demodulator for use with software radio.

Usage

This crate can be used through cargo by adding it as a dependency in Cargo.toml:

[dependencies]
demod_fm = "1.0.0"

and importing it in the crate root:

extern crate demod_fm;

lib.rs:

This crates provides a simple FM signal demodulator for use with software radio. It demodulates using phase difference approximation as described below.

Theory

Consider the classical equation [1] for an FM signal:

s(t) = a(t) cos(ωct + φ(t))

with

φ(t) = ω∫x(τ)dτ

where the integral is evaluated from 0 to t and x(t) is the modulating signal to be recovered.

Differentiating this gives

dφ(t) / dt = ωx(t)

so

x(t) = ω-1 dφ(t) / dt

Differentiation in continuous time is approximated by finite backward difference in discrete time, so

x(t) ≈ ω-1 (φ[t] - φ[t-1]) / T

Assuming a "normalized" period of T = 1, this becomes

x(t) ≈ w-1 (φ[t] - φ[t-1])

This requires the change in phase between the current and previous sampling instants, which can be computed from the corresponding I/Q samples. Given an FM signal s(t), the received I/Q sequence will have components

i(t) = a(t) cos φ(t)

q(t) = a(t) sin φ(t)

with each sample represented as

p(t) = i(t) + j q(t)

Evaluating the complex argument of this gives

arg(p(t)) = arctan[q(t) / i(t)] = arctan tan φ(t) = φ(t)

so

arg(p(t)) - arg(p(t-1)) = φ(t) - φ(t-1)

Applying the complex identities arg(uv) ≡ arg(u) + arg(v) (mod (-π, π]) and arg(u*) = -arg(u),

arg(p(t)p(t-1)*) = arg(p(t)) - arg(p(t-1)) = φ(t) - φ(t-1)

Combining all these results leads to the equation calculated at each sample:

x[t] = ω-1 arg(p[t]p[t - 1]*)

using angular frequency deviation ω = 2π f and the current and previous complex samples.

References

  1. "FM demodulation using a digital radio and digital signal processing", J.M. Shima,

Dependencies

~240KB