GNU Radio's DVBS2RX Package
symbol_sync_cc_impl.h
Go to the documentation of this file.
1/* -*- c++ -*- */
2/*
3 * Copyright 2021 2019-2021 Igor Freire.
4 *
5 * This file is part of gr-dvbs2rx.
6 *
7 * SPDX-License-Identifier: GPL-3.0-or-later
8 */
9
10#ifndef INCLUDED_DVBS2RX_SYMBOL_SYNC_CC_IMPL_H
11#define INCLUDED_DVBS2RX_SYMBOL_SYNC_CC_IMPL_H
12
14#include <gnuradio/gr_complex.h>
15#include <volk/volk_alloc.hh>
16
17namespace gr {
18namespace dvbs2rx {
19
20template <typename T>
22 base_interpolator(unsigned history) : d_history(history){};
23
24 /**
25 * @brief Compute the complex interpolant.
26 *
27 * @param in Input IQ sample buffer.
28 * @param m_k Basepoint index.
29 * @param mu Fractional timing offset estimate.
30 * @return gr_complex Output interpolant.
31 */
32 virtual gr_complex operator()(const gr_complex* in, int m_k, T mu) const = 0;
33
34 /**
35 * @brief Get the interpolator history requirement.
36 *
37 * @return unsigned Historic (past) samples required to compute an interpolant.
38 */
39 unsigned history() const { return d_history; };
40
41private:
42 unsigned d_history;
43};
44
45constexpr unsigned hist_linear_interp = 1; // accesses m_k = n - 1
46constexpr unsigned hist_quadratic_interp = 3; // accesses m_k - 2 = n - 3
47constexpr unsigned hist_cubic_interp = 3; // accesses m_k - 2 = n - 3
48
49struct linear_interpolator : public base_interpolator<float> {
51 gr_complex operator()(const gr_complex* in, int m_k, float mu) const;
52};
53
56 gr_complex operator()(const gr_complex* in, int m_k, float mu) const;
57};
58
59struct cubic_interpolator : public base_interpolator<float> {
61 gr_complex operator()(const gr_complex* in, int m_k, float mu) const;
62};
63
65 polyphase_interpolator(float sps, float rolloff, int rrc_delay, size_t n_subfilt);
66 gr_complex operator()(const gr_complex* in, int m_k, double mu) const;
67 // NOTE: on the polyphase interpolator, represent mu by a double (instead of float) to
68 // avoid mu=1.0 that can result from numerical errors. While the other interpolators
69 // can handle mu=1.0 (although the effects are TBC), the polyphase would certainly
70 // segfault with mu=1.0, as that would lead to an out-of-range subfilter index.
71 size_t get_subfilt_delay() const { return d_subfilt_delay; }
72
73private:
74 std::vector<volk::vector<float>> d_rrc_subfilters; /** Vector of RRC subfilters */
75 size_t d_n_subfilt; /** Number of subfilters in the polyphase RRC filter bank */
76 size_t d_subfilt_len; /** Number of taps in each RRC subfilter */
77 size_t d_subfilt_delay; /** RRC subfilter delay */
78};
79
81{
82private:
83 int d_sps; /**< Samples per symbol (oversampling ratio) */
84 int d_midpoint; /**< Midpoint index between interpolants */
85 unsigned d_history; /**< History of samples in the input buffer */
86 float d_K1; /**< PI filter's proportional constant */
87 float d_K2; /**< PI filter's integrator constant */
88 float d_Kp; /**< Gardner TED gain */
89 double d_vi; /**< Last integrator value */
90 double d_nominal_step; /**< Nominal mod-1 counter step (equal to "1/d_sps") */
91 double d_cnt; /**< Modulo-1 counter */
92 double d_mu; /**< Fractional symbol timing offset estimate */
93 int d_jump; /**< Samples to jump until the next strobe */
94 bool d_init; /**< Whether the loop is initialized (after the first work) */
95 gr_complex d_last_xi; /**< Last output interpolant */
96 std::vector<int> d_strobe_idx; /**< Indexes of the output interpolants */
97 std::vector<tag_t> d_pending_tags; /**< Pending tags from the previous work */
98
99 // Interpolators
100 //
101 // NOTE: The synchronizer uses a single interpolator defined by the interp_method
102 // parameter. However, this class includes all interpolators as members so that these
103 // can be passed by reference to the templated loop function defined below. This
104 // approach allows the compiler to know exactly which interpolator functor is used for
105 // each templated loop instantiation. Consequently, the compiler can inline the
106 // interpolation calls, which is so much more important than saving memory here.
107 int d_interp_method;
108 linear_interpolator d_lin_interp;
109 quadratic_interpolator d_qua_interp;
110 cubic_interpolator d_cub_interp;
111 polyphase_interpolator d_poly_interp;
112
113 void set_gted_gain(float rolloff);
114 void set_pi_constants(float loop_bw, float damping_factor);
115
116
117public:
119 float loop_bw,
120 float damping_factor,
121 float rolloff,
122 int rrc_delay,
123 int n_subfilt,
124 int interp_method);
126
127 void forecast(int noutput_items, gr_vector_int& ninput_items_required);
128
129 int general_work(int noutput_items,
130 gr_vector_int& ninput_items,
131 gr_vector_const_void_star& input_items,
132 gr_vector_void_star& output_items);
133
134 template <typename Interpolator>
135 std::pair<int, int> loop(const gr_complex* in,
136 gr_complex* out,
137 int ninput_items,
138 int noutput_items,
139 const Interpolator& interp);
140
141 std::pair<int, int>
142 loop(const gr_complex* in, gr_complex* out, int ninput_items, int noutput_items);
143};
144
145} // namespace dvbs2rx
146} // namespace gr
147
148#endif /* INCLUDED_DVBS2RX_SYMBOL_SYNC_CC_IMPL_H */
Definition symbol_sync_cc_impl.h:81
void forecast(int noutput_items, gr_vector_int &ninput_items_required)
int general_work(int noutput_items, gr_vector_int &ninput_items, gr_vector_const_void_star &input_items, gr_vector_void_star &output_items)
std::pair< int, int > loop(const gr_complex *in, gr_complex *out, int ninput_items, int noutput_items)
std::pair< int, int > loop(const gr_complex *in, gr_complex *out, int ninput_items, int noutput_items, const Interpolator &interp)
symbol_sync_cc_impl(float sps, float loop_bw, float damping_factor, float rolloff, int rrc_delay, int n_subfilt, int interp_method)
Symbol Synchronizer Loop.
Definition symbol_sync_cc.h:38
#define DVBS2RX_API
Definition include/gnuradio/dvbs2rx/api.h:19
constexpr unsigned hist_linear_interp
Definition symbol_sync_cc_impl.h:45
constexpr unsigned hist_quadratic_interp
Definition symbol_sync_cc_impl.h:46
constexpr unsigned hist_cubic_interp
Definition symbol_sync_cc_impl.h:47
Fixed-length double-ended queue with contiguous volk-aligned elements.
Definition gr_bch.h:22
Definition symbol_sync_cc_impl.h:21
unsigned history() const
Get the interpolator history requirement.
Definition symbol_sync_cc_impl.h:39
base_interpolator(unsigned history)
Definition symbol_sync_cc_impl.h:22
virtual gr_complex operator()(const gr_complex *in, int m_k, T mu) const =0
Compute the complex interpolant.
Definition symbol_sync_cc_impl.h:59
cubic_interpolator()
Definition symbol_sync_cc_impl.h:60
gr_complex operator()(const gr_complex *in, int m_k, float mu) const
Compute the complex interpolant.
Definition symbol_sync_cc_impl.h:49
linear_interpolator()
Definition symbol_sync_cc_impl.h:50
gr_complex operator()(const gr_complex *in, int m_k, float mu) const
Compute the complex interpolant.
Definition symbol_sync_cc_impl.h:64
polyphase_interpolator(float sps, float rolloff, int rrc_delay, size_t n_subfilt)
gr_complex operator()(const gr_complex *in, int m_k, double mu) const
Compute the complex interpolant.
size_t get_subfilt_delay() const
Definition symbol_sync_cc_impl.h:71
Definition symbol_sync_cc_impl.h:54
gr_complex operator()(const gr_complex *in, int m_k, float mu) const
Compute the complex interpolant.
quadratic_interpolator()
Definition symbol_sync_cc_impl.h:55