/* -*- c++ -*- */ /* * Copyright 2015,2020 Free Software Foundation, Inc. * * SPDX-License-Identifier: GPL-3.0-or-later * */ #ifndef INCLUDED_DTV_DVBT_REFERENCE_SIGNALS_IMPL_H #define INCLUDED_DTV_DVBT_REFERENCE_SIGNALS_IMPL_H #include "dvbt_configure.h" #include <gnuradio/dtv/dvbt_reference_signals.h> #include <gnuradio/fft/fft.h> #include <gnuradio/logger.h> #include <deque> #include <vector> // This should eventually go into a const file constexpr int SYMBOLS_PER_FRAME = 68; constexpr int FRAMES_PER_SUPERFRAME = 4; constexpr int SCATTERED_PILOT_SIZE_2k = 142; constexpr int CONTINUAL_PILOT_SIZE_2k = 45; constexpr int TPS_PILOT_SIZE_2k = 17; constexpr int SCATTERED_PILOT_SIZE_8k = 568; constexpr int CONTINUAL_PILOT_SIZE_8k = 177; constexpr int TPS_PILOT_SIZE_8k = 68; namespace gr { namespace dtv { class dvbt_pilot_gen { private: // this should be first in order to be initialized first const dvbt_configure& config; const int d_Kmin; const int d_Kmax; const int d_fft_length; const int d_payload_length; const int d_zeros_on_left; const int d_zeros_on_right; const int d_cp_length; static const int d_symbols_per_frame; static const int d_frames_per_superframe; // 2k mode // scattered pilot carriers info static const int d_spilot_carriers_size_2k; // continual pilot carriers info static const int d_cpilot_carriers_size_2k; static const int d_cpilot_carriers_2k[]; // TPS carriers info static const int d_tps_carriers_size_2k; static const int d_tps_carriers_2k[]; // 8k mode // scattered pilot carriers info static const int d_spilot_carriers_size_8k; // continual pilot carriers info static const int d_cpilot_carriers_size_8k; static const int d_cpilot_carriers_8k[]; // TPS carriers info static const int d_tps_carriers_size_8k; static const int d_tps_carriers_8k[]; // TPS sync data static const int d_tps_sync_size; static const int d_tps_sync_even[]; static const int d_tps_sync_odd[]; // Variables to keep data for 2k, 8k, 4k int d_spilot_carriers_size; volk::vector<gr_complex> d_spilot_carriers_val; volk::vector<gr_complex> d_channel_gain; int d_cpilot_carriers_size; const int* d_cpilot_carriers; volk::vector<float> d_known_phase_diff; volk::vector<float> d_cpilot_phase_diff; int d_freq_offset = 0; float d_carrier_freq_correction = 0.0; float d_sampling_freq_correction = 0.0; // Variable to keep corrected OFDM symbol volk::vector<gr_complex> d_derot_in; int d_tps_carriers_size; const int* d_tps_carriers; volk::vector<gr_complex> d_tps_carriers_val; // Keeps TPS data volk::vector<unsigned char> d_tps_data; // Keep TPS carriers values from previous symbol volk::vector<gr_complex> d_prev_tps_symbol; // Keep TPS carriers values from current symbol volk::vector<gr_complex> d_tps_symbol; // Keeps the rcv TPS data, is a FIFO std::deque<char> d_rcv_tps_data; // Keeps the TPS sync sequence std::deque<char> d_tps_sync_evenv; std::deque<char> d_tps_sync_oddv; // Keeps channel estimation carriers // we use both continual and scattered carriers volk::vector<int> d_chanestim_carriers; // Keeps paload carriers volk::vector<int> d_payload_carriers; // Indexes for all carriers int d_spilot_index = 0; int d_cpilot_index = 0; int d_tpilot_index = 0; int d_symbol_index = 0; int d_symbol_index_known = 0; int d_frame_index = 0; int d_superframe_index = 0; int d_freq_offset_max = 8; int d_trigger_index = 0; int d_payload_index = 0; int d_chanestim_index = 0; int d_prev_mod_symbol_index = 0; int d_mod_symbol_index = 0; int d_equalizer_ready; // PRPS generator data buffer std::vector<char> d_wk; // Generate PRBS void generate_prbs(); // TPS private methods void set_tps_bits(int start, int stop, unsigned int data); void set_symbol_index(int index); int get_symbol_index(); void set_tps_data(); void get_tps_data(); void reset_pilot_generator(); // Scattered pilot generator methods int get_current_spilot(int spilot) const; gr_complex get_spilot_value(int spilot); void set_spilot_value(int spilot, gr_complex val); void advance_spilot(int sindex); // Methods used to quick iterate through all spilots int get_first_spilot(); int get_last_spilot() const; int get_next_spilot(); // Scattered pilot data processing method int process_spilot_data(const gr_complex* in); // Channel estimation methods void set_channel_gain(int spilot, gr_complex val); // Continual pilot generator methods int get_current_cpilot() const; gr_complex get_cpilot_value(int cpilot); void advance_cpilot(); // Continual pilot data processing methods void process_cpilot_data(const gr_complex* in); void compute_oneshot_csft(const gr_complex* in); gr_complex* frequency_correction(const gr_complex* in, gr_complex* out); // TPS generator methods int get_current_tpilot() const; gr_complex get_tpilot_value(int tpilot); void advance_tpilot(); // TPS data void format_tps_data(); // Encode TPS data void generate_bch_code(); // Verify parity on TPS data int verify_bch_code(std::deque<char> data); // TPS data processing methods int process_tps_data(const gr_complex* in, const int diff_symbo_index); // Channel estimation methods void set_chanestim_carrier(int k); // Payload data processing methods int get_current_payload(); void advance_chanestim(); void set_payload_carrier(int k); void advance_payload(); void process_payload_data(const gr_complex* in, gr_complex* out); public: gr::logger_ptr d_logger; gr::logger_ptr d_debug_logger; dvbt_pilot_gen(const dvbt_configure& config); ~dvbt_pilot_gen(); /*! * ETSI EN 300 744 Clause 4.5. \n * Update a set of carriers with the pilot signals. \n */ void update_output(const gr_complex* in, gr_complex* out); /*! * TODO * ETSI EN 300 744 Clause 4.5. \n * Extract data from a set of carriers using pilot signals. \n * This is doing frequency correction, equalization. \n */ int parse_input(const gr_complex* in, gr_complex* out, int* symbol_index, int* frame_index); }; class dvbt_reference_signals_impl : public dvbt_reference_signals { // configuration object for this class const dvbt_configure config; private: // Pilot Generator object dvbt_pilot_gen d_pg; // In and Out data length int d_ninput; int d_noutput; fft::fft_complex_rev ofdm_fft; int ofdm_fft_size; float normalization; public: dvbt_reference_signals_impl(int itemsize, int ninput, int noutput, dvb_constellation_t constellation, dvbt_hierarchy_t hierarchy, dvb_code_rate_t code_rate_HP, dvb_code_rate_t code_rate_LP, dvb_guardinterval_t guard_interval, dvbt_transmission_mode_t transmission_mode = gr::dtv::T2k, int include_cell_id = 0, int cell_id = 0); ~dvbt_reference_signals_impl() override; void forecast(int noutput_items, gr_vector_int& ninput_items_required) override; int general_work(int noutput_items, gr_vector_int& ninput_items, gr_vector_const_void_star& input_items, gr_vector_void_star& output_items) override; }; } // namespace dtv } // namespace gr #endif /* INCLUDED_DTV_DVBT_REFERENCE_SIGNALS_IMPL_H */