Skip to content

Commit

Permalink
gr-digital: replace clk recovery MM in hier blks
Browse files Browse the repository at this point in the history
As Clock Recovery MM is deprecated, this commit replaces them
in the hier blocks, gmfsk demod and gfsk demod, with Andy Wall's Symbol
Sync block. Backward compatibility is maintained by keeping the
parameters unchanged, and converting the two gain values to the
corresponding loop bandwidth value that Symbol Sync requires.

Even though `mu` parameter's services is no longer required, we leave it
in the hier block for backward compatibility purposes.

Signed-off-by: Solomon Tan <solomonbstoner@yahoo.com.au>
  • Loading branch information
solomonbstoner authored and mormj committed Sep 2, 2021
1 parent c0565ae commit aa0efa5
Show file tree
Hide file tree
Showing 4 changed files with 52 additions and 28 deletions.
2 changes: 1 addition & 1 deletion gr-digital/grc/digital_gfsk_demod.block.yml
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ parameters:
dtype: real
default: '0.175'
- id: mu
label: Mu
label: Mu (Unused)
dtype: real
default: '0.5'
- id: omega_relative_limit
Expand Down
2 changes: 1 addition & 1 deletion gr-digital/grc/digital_gmsk_demod.block.yml
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ parameters:
dtype: real
default: '0.175'
- id: mu
label: Mu
label: Mu (Unused)
dtype: real
default: '0.5'
- id: omega_relative_limit
Expand Down
38 changes: 25 additions & 13 deletions gr-digital/python/digital/gfsk.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@


# See gnuradio-examples/python/digital for examples
from math import log as ln

import numpy

Expand Down Expand Up @@ -190,7 +191,7 @@ def __init__(self,
Args:
gain_mu: controls rate of mu adjustment (float)
mu: fractional delay [0.0, 1.0] (float)
mu: unused but unremoved for backward compatibility (unused)
omega_relative_limit: sets max variation in omega (float, typically 0.000200 (200 ppm))
freq_error: bit rate error as a fraction
float:
Expand All @@ -202,7 +203,6 @@ def __init__(self,

self._samples_per_symbol = samples_per_symbol
self._gain_mu = gain_mu
self._mu = mu
self._omega_relative_limit = omega_relative_limit
self._freq_error = freq_error
self._differential = False
Expand All @@ -217,15 +217,27 @@ def __init__(self,

self._gain_omega = .25 * self._gain_mu * self._gain_mu # critically damped

self._damping = 1.0
self._loop_bw = -ln((self._gain_mu + self._gain_omega)/(-2.0) + 1) # critically damped
self._max_dev = self._omega_relative_limit * self._samples_per_symbol

# Demodulate FM
#sensitivity = (pi / 2) / samples_per_symbol
self.fmdemod = analog.quadrature_demod_cf(1.0 / sensitivity)

# the clock recovery block tracks the symbol clock and resamples as needed.
# the output of the block is a stream of soft symbols (float)
self.clock_recovery = digital.clock_recovery_mm_ff(self._omega, self._gain_omega,
self._mu, self._gain_mu,
self._omega_relative_limit)
self.clock_recovery = self.digital_symbol_sync_xx_0 = digital.symbol_sync_ff(digital.TED_MUELLER_AND_MULLER,
self._omega,
self._loop_bw,
self._damping,
1.0, # Expected TED gain
self._max_dev,
1, # Output sps
digital.constellation_bpsk().base(),
digital.IR_MMSE_8TAP,
128,
[])

# slice the floats at 0, outputting 1 bit (the LSB of the output byte) per sample
self.slicer = digital.binary_slicer_fb()
Expand All @@ -248,10 +260,10 @@ def bits_per_symbol(self=None): # staticmethod that's also callable on an inst

def _print_verbage(self):
print("bits per symbol = %d" % self.bits_per_symbol())
print("M&M clock recovery omega = %f" % self._omega)
print("M&M clock recovery gain mu = %f" % self._gain_mu)
print("M&M clock recovery mu = %f" % self._mu)
print("M&M clock recovery omega rel. limit = %f" % self._omega_relative_limit)
print("Symbol Sync M&M omega = %f" % self._omega)
print("Symbol Sync M&M gain mu = %f" % self._gain_mu)
print("M&M clock recovery mu (Unused) = %f" % self._mu)
print("Symbol Sync M&M omega rel. limit = %f" % self._omega_relative_limit)
print("frequency error = %f" % self._freq_error)


Expand All @@ -270,13 +282,13 @@ def add_options(parser):
Adds GFSK demodulation-specific options to the standard parser
"""
parser.add_option("", "--gain-mu", type="float", default=_def_gain_mu,
help="M&M clock recovery gain mu [default=%default] (GFSK/PSK)")
help="Symbol Sync M&M gain mu [default=%default] (GFSK/PSK)")
parser.add_option("", "--mu", type="float", default=_def_mu,
help="M&M clock recovery mu [default=%default] (GFSK/PSK)")
help="M&M clock recovery mu [default=%default] (Unused)")
parser.add_option("", "--omega-relative-limit", type="float", default=_def_omega_relative_limit,
help="M&M clock recovery omega relative limit [default=%default] (GFSK/PSK)")
help="Symbol Sync M&M omega relative limit [default=%default] (GFSK/PSK)")
parser.add_option("", "--freq-error", type="float", default=_def_freq_error,
help="M&M clock recovery frequency error [default=%default] (GFSK)")
help="Symbol Sync M&M frequency error [default=%default] (GFSK)")

@staticmethod
def extract_kwargs_from_options(options):
Expand Down
38 changes: 25 additions & 13 deletions gr-digital/python/digital/gmsk.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
# See gnuradio-examples/python/digital for examples

from math import pi
from math import log as ln
from pprint import pprint
import inspect

Expand Down Expand Up @@ -167,7 +168,7 @@ class gmsk_demod(gr.hier_block2):
Args:
samples_per_symbol: samples per baud (integer)
gain_mu: controls rate of mu adjustment (float)
mu: fractional delay [0.0, 1.0] (float)
mu: unused but unremoved for backward compatibility (unused)
omega_relative_limit: sets max variation in omega (float)
freq_error: bit rate error as a fraction (float)
verbose: Print information about modulator? (boolean)
Expand All @@ -189,7 +190,6 @@ def __init__(self,

self._samples_per_symbol = samples_per_symbol
self._gain_mu = gain_mu
self._mu = mu
self._omega_relative_limit = omega_relative_limit
self._freq_error = freq_error
self._differential = False
Expand All @@ -204,15 +204,27 @@ def __init__(self,

self._gain_omega = .25 * self._gain_mu * self._gain_mu # critically damped

self._damping = 1.0
self._loop_bw = -ln((self._gain_mu + self._gain_omega)/(-2.0) + 1) # critically damped
self._max_dev = self._omega_relative_limit * self._samples_per_symbol

# Demodulate FM
sensitivity = (pi / 2) / samples_per_symbol
self.fmdemod = analog.quadrature_demod_cf(1.0 / sensitivity)

# the clock recovery block tracks the symbol clock and resamples as needed.
# the output of the block is a stream of soft symbols (float)
self.clock_recovery = digital.clock_recovery_mm_ff(self._omega, self._gain_omega,
self._mu, self._gain_mu,
self._omega_relative_limit)
self.clock_recovery = self.digital_symbol_sync_xx_0 = digital.symbol_sync_ff(digital.TED_MUELLER_AND_MULLER,
self._omega,
self._loop_bw,
self._damping,
1.0, # Expected TED gain
self._max_dev,
1, # Output sps
digital.constellation_bpsk().base(),
digital.IR_MMSE_8TAP,
128,
[])

# slice the floats at 0, outputting 1 bit (the LSB of the output byte) per sample
self.slicer = digital.binary_slicer_fb()
Expand All @@ -235,10 +247,10 @@ def bits_per_symbol(self=None): # staticmethod that's also callable on an inst

def _print_verbage(self):
print("bits per symbol = %d" % self.bits_per_symbol())
print("M&M clock recovery omega = %f" % self._omega)
print("M&M clock recovery gain mu = %f" % self._gain_mu)
print("M&M clock recovery mu = %f" % self._mu)
print("M&M clock recovery omega rel. limit = %f" % self._omega_relative_limit)
print("Symbol Sync M&M omega = %f" % self._omega)
print("Symbol Sync M&M gain mu = %f" % self._gain_mu)
print("M&M clock recovery mu (Unused) = %f" % self._mu)
print("Symbol Sync M&M omega rel. limit = %f" % self._omega_relative_limit)
print("frequency error = %f" % self._freq_error)


Expand All @@ -257,13 +269,13 @@ def add_options(parser):
Adds GMSK demodulation-specific options to the standard parser
"""
parser.add_option("", "--gain-mu", type="float", default=_def_gain_mu,
help="M&M clock recovery gain mu [default=%default] (GMSK/PSK)")
help="Symbol Sync M&M gain mu [default=%default] (GMSK/PSK)")
parser.add_option("", "--mu", type="float", default=_def_mu,
help="M&M clock recovery mu [default=%default] (GMSK/PSK)")
help="M&M clock recovery mu [default=%default] (Unused)")
parser.add_option("", "--omega-relative-limit", type="float", default=_def_omega_relative_limit,
help="M&M clock recovery omega relative limit [default=%default] (GMSK/PSK)")
help="Symbol Sync M&M omega relative limit [default=%default] (GMSK/PSK)")
parser.add_option("", "--freq-error", type="float", default=_def_freq_error,
help="M&M clock recovery frequency error [default=%default] (GMSK)")
help="Symbol Sync M&M frequency error [default=%default] (GMSK)")

@staticmethod
def extract_kwargs_from_options(options):
Expand Down

0 comments on commit aa0efa5

Please sign in to comment.