diff options
49 files changed, 4359 insertions, 386 deletions
diff --git a/gnuradio-runtime/apps/evaluation_random_numbers.py b/gnuradio-runtime/apps/evaluation_random_numbers.py new file mode 100644 index 0000000000..069493c73e --- /dev/null +++ b/gnuradio-runtime/apps/evaluation_random_numbers.py @@ -0,0 +1,139 @@ +#!/usr/bin/env python +# +# Copyright 2015 Free Software Foundation, Inc. +# +# This file is part of GNU Radio +# +# GNU Radio is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 3, or (at your option) +# any later version. +# +# GNU Radio is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with GNU Radio; see the file COPYING. If not, write to +# the Free Software Foundation, Inc., 51 Franklin Street, +# Boston, MA 02110-1301, USA. +# + +from gnuradio import gr +import numpy as np +from scipy.stats import norm, laplace, rayleigh +from matplotlib import pyplot as plt + +# NOTE: scipy and matplotlib are optional packages and not included in the default gnuradio dependencies + +#*** SETUP ***# + +# Number of realisations per histogram +num_tests = 1000000 + +# Set number of bins in histograms +uniform_num_bins = 31 +gauss_num_bins = 31 +rayleigh_num_bins = 31 +laplace_num_bins = 31 + +rndm = gr.random() # instance of gnuradio random class (gr::random) + +print 'All histograms contain',num_tests,'realisations.' + +#*** GENERATE DATA ***# + +uniform_values = np.zeros(num_tests) +gauss_values = np.zeros(num_tests) +rayleigh_values = np.zeros(num_tests) +laplace_values = np.zeros(num_tests) + +for k in range(num_tests): + uniform_values[k] = rndm.ran1() + gauss_values[k] = rndm.gasdev() + rayleigh_values[k] = rndm.rayleigh() + laplace_values[k] = rndm.laplacian() + +#*** HISTOGRAM DATA AND CALCULATE EXPECTED COUNTS ***# + +uniform_bins = np.linspace(0,1,uniform_num_bins) +gauss_bins = np.linspace(-8,8,gauss_num_bins) +laplace_bins = np.linspace(-8,8,laplace_num_bins) +rayleigh_bins = np.linspace(0,10,rayleigh_num_bins) + +uniform_hist = np.histogram(uniform_values,uniform_bins) +gauss_hist = np.histogram(gauss_values,gauss_bins) +rayleigh_hist = np.histogram(rayleigh_values,rayleigh_bins) +laplace_hist = np.histogram(laplace_values,laplace_bins) + +uniform_expected = np.zeros(uniform_num_bins-1) +gauss_expected = np.zeros(gauss_num_bins-1) +rayleigh_expected = np.zeros(rayleigh_num_bins-1) +laplace_expected = np.zeros(laplace_num_bins-1) + +for k in range(len(uniform_hist[0])): + uniform_expected[k] = num_tests/float(uniform_num_bins-1) + +for k in range(len(gauss_hist[0])): + gauss_expected[k] = float(norm.cdf(gauss_hist[1][k+1])-norm.cdf(gauss_hist[1][k]))*num_tests + +for k in range(len(rayleigh_hist[0])): + rayleigh_expected[k] = float(rayleigh.cdf(rayleigh_hist[1][k+1])-rayleigh.cdf(rayleigh_hist[1][k]))*num_tests + +for k in range(len(laplace_hist[0])): + laplace_expected[k] = float(laplace.cdf(laplace_hist[1][k+1])-laplace.cdf(laplace_hist[1][k]))*num_tests + +#*** PLOT HISTOGRAMS AND EXPECTATIONS TAKEN FROM SCIPY ***# + +uniform_bins_center = uniform_bins[0:-1]+(uniform_bins[1]-uniform_bins[0])/2.0 +gauss_bins_center = gauss_bins[0:-1]+(gauss_bins[1]-gauss_bins[0])/2.0 +rayleigh_bins_center = rayleigh_bins[0:-1]+(rayleigh_bins[1]-rayleigh_bins[0])/2.0 +laplace_bins_center = laplace_bins[0:-1]+(laplace_bins[1]-laplace_bins[0])/2.0 + +plt.figure(1) + +plt.subplot(2,1,1) +plt.plot(uniform_bins_center,uniform_hist[0],'s--',uniform_bins_center,uniform_expected,'o:') +plt.xlabel('Bins'), plt.ylabel('Count'), plt.title('Uniform: Distribution') +plt.legend(['histogram gr::random','calculation scipy'],loc=1) + +plt.subplot(2,1,2) +plt.plot(uniform_bins_center,uniform_hist[0]/uniform_expected,'rs--') +plt.xlabel('Bins'), plt.ylabel('Relative deviation'), plt.title('Uniform: Relative deviation to scipy') + +plt.figure(2) + +plt.subplot(2,1,1) +plt.plot(gauss_bins_center,gauss_hist[0],'s--',gauss_bins_center,gauss_expected,'o:') +plt.xlabel('Bins'), plt.ylabel('Count'), plt.title('Gauss: Distribution') +plt.legend(['histogram gr::random','calculation scipy'],loc=1) + +plt.subplot(2,1,2) +plt.plot(gauss_bins_center,gauss_hist[0]/gauss_expected,'rs--') +plt.xlabel('Bins'), plt.ylabel('Relative deviation'), plt.title('Gauss: Relative deviation to scipy') + +plt.figure(3) + +plt.subplot(2,1,1) +plt.plot(rayleigh_bins_center,rayleigh_hist[0],'s--',rayleigh_bins_center,rayleigh_expected,'o:') +plt.xlabel('Bins'), plt.ylabel('Count'), plt.title('Rayleigh: Distribution') +plt.legend(['histogram gr::random','calculation scipy'],loc=1) + + +plt.subplot(2,1,2) +plt.plot(rayleigh_bins_center,rayleigh_hist[0]/rayleigh_expected,'rs--') +plt.xlabel('Bins'), plt.ylabel('Relative deviation'), plt.title('Rayleigh: Relative deviation to scipy') + +plt.figure(4) + +plt.subplot(2,1,1) +plt.plot(laplace_bins_center,laplace_hist[0],'s--',laplace_bins_center,laplace_expected,'o:') +plt.xlabel('Bins'), plt.ylabel('Count'), plt.title('Laplace: Distribution') +plt.legend(['histogram gr::random','calculation scipy'],loc=1) + +plt.subplot(2,1,2) +plt.plot(laplace_bins_center,laplace_hist[0]/laplace_expected,'rs--') +plt.xlabel('Bins'), plt.ylabel('Relative deviation'), plt.title('Laplace: Relative deviation to scipy') + +plt.show() diff --git a/gnuradio-runtime/include/gnuradio/random.h b/gnuradio-runtime/include/gnuradio/random.h index e01fcb7be7..e95f36d1c2 100644 --- a/gnuradio-runtime/include/gnuradio/random.h +++ b/gnuradio-runtime/include/gnuradio/random.h @@ -1,6 +1,6 @@ /* -*- c++ -*- */ /* - * Copyright 2002 Free Software Foundation, Inc. + * Copyright 2002, 2015 Free Software Foundation, Inc. * * This file is part of GNU Radio * @@ -26,17 +26,9 @@ #include <gnuradio/api.h> #include <gnuradio/gr_complex.h> -// While rand(3) specifies RAND_MAX, random(3) says that the output -// ranges from 0 to 2^31-1 but does not specify a macro to denote -// this. We define RANDOM_MAX for cleanliness. We must omit the -// definition for systems that have made the same choice. (Note that -// random(3) is from 4.2BSD, and not specified by POSIX.) - -#ifndef RANDOM_MAX -static const int RANDOM_MAX = 2147483647; // 2^31-1 -#endif /* RANDOM_MAX */ - #include <stdlib.h> +#include <boost/random.hpp> +#include <ctime> namespace gr { @@ -47,31 +39,51 @@ namespace gr { class GR_RUNTIME_API random { protected: - static const int NTAB = 32; long d_seed; - long d_iy; - long d_iv[NTAB]; - int d_iset; - float d_gset; + bool d_gauss_stored; + float d_gauss_value; + + boost::mt19937 *d_rng; // mersenne twister as random number generator + boost::uniform_real<float> *d_uniform; // choose uniform distribution, default is [0,1) + boost::variate_generator<boost::mt19937&, boost::uniform_real<float> > *d_generator; public: - random(long seed=3021); + random(unsigned int seed=0); + ~random(); - void reseed(long seed); + /*! + * \brief Change the seed for the initialized number generator. seed = 0 initializes the random number generator with the system time. Note that a fast initialization of various instances can result in the same seed. + */ + void reseed(unsigned int seed); /*! - * \brief uniform random deviate in the range [0.0, 1.0) + * \brief Uniform random numbers in the range [0.0, 1.0) */ float ran1(); /*! - * \brief normally distributed deviate with zero mean and variance 1 + * \brief Normally distributed random numbers (Gaussian distribution with zero mean and variance 1) */ float gasdev(); + /*! + * \brief Laplacian distributed random numbers with zero mean and variance 1 + */ float laplacian(); - float impulse(float factor); + + /*! + * \brief Rayleigh distributed random numbers (zero mean and variance 1 for the underlying Gaussian distributions) + */ float rayleigh(); + + /*! + * \brief FIXME: add description + */ + float impulse(float factor); + + /*! + * \brief Normally distributed random numbers with zero mean and variance 1 on real and imaginary part. This results in a Rayleigh distribution for the amplitude and an uniform distribution for the phase. + */ gr_complex rayleigh_complex(); }; diff --git a/gnuradio-runtime/lib/math/random.cc b/gnuradio-runtime/lib/math/random.cc index 7170f27edf..a2b2621307 100644 --- a/gnuradio-runtime/lib/math/random.cc +++ b/gnuradio-runtime/lib/math/random.cc @@ -1,6 +1,6 @@ /* -*- c++ -*- */ /* - * Copyright 2002 Free Software Foundation, Inc. + * Copyright 2002, 2015 Free Software Foundation, Inc. * * This file is part of GNU Radio * @@ -44,104 +44,75 @@ namespace gr { -#define IA 16807 -#define IM 2147483647 -#define AM (1.0/IM) -#define IQ 127773 -#define IR 2836 -#define NDIV (1+(IM-1)/NTAB) -#define EPS 1.2e-7 -#define RNMX (1.0-EPS) + random::random(unsigned int seed) + { + d_gauss_stored = false; // set gasdev (gauss distributed numbers) on calculation state + + // Setup random number generator + d_rng = new boost::mt19937; + reseed(seed); // set seed for random number generator + d_uniform = new boost::uniform_real<float>; + d_generator = new boost::variate_generator<boost::mt19937&, boost::uniform_real<float> > (*d_rng,*d_uniform); // create number generator in [0,1) from boost.random + } - random::random(long seed) + random::~random() { - reseed(seed); + delete d_rng; + delete d_uniform; + delete d_generator; } + /* + * Seed is initialized with time if the given seed is 0. Otherwise the seed is taken directly. Sets the seed for the random number generator. + */ void - random::reseed(long seed) + random::reseed(unsigned int seed) { - d_seed = seed; - d_iy = 0; - for(int i = 0; i < NTAB; i++) - d_iv[i] = 0; - d_iset = 0; - d_gset = 0; + if(seed==0) d_seed = static_cast<unsigned int>(std::time(0)); + else d_seed = seed; + d_rng->seed(d_seed); } /* - * This looks like it returns a uniform random deviate between 0.0 and 1.0 - * It looks similar to code from "Numerical Recipes in C". + * Returns uniformly distributed numbers in [0,1) taken from boost.random using a Mersenne twister */ float random::ran1() { - int j; - long k; - float temp; - - if(d_seed <= 0 || !d_iy) { - if(-d_seed < 1) - d_seed=1; - else - d_seed = -d_seed; - for(j=NTAB+7;j>=0;j--) { - k=d_seed/IQ; - d_seed=IA*(d_seed-k*IQ)-IR*k; - if(d_seed < 0) - d_seed += IM; - if(j < NTAB) - d_iv[j] = d_seed; - } - d_iy=d_iv[0]; - } - k=(d_seed)/IQ; - d_seed=IA*(d_seed-k*IQ)-IR*k; - if(d_seed < 0) - d_seed += IM; - j=d_iy/NDIV; - d_iy=d_iv[j]; - d_iv[j] = d_seed; - temp=AM * d_iy; - if(temp > RNMX) - temp = RNMX; - return temp; + return (*d_generator)(); } /* * Returns a normally distributed deviate with zero mean and variance 1. - * Also looks like it's from "Numerical Recipes in C". + * Used is the Marsaglia polar method. + * Every second call a number is stored because the transformation works only in pairs. Otherwise half calculation is thrown away. */ float random::gasdev() { - float fac,rsq,v1,v2; - d_iset = 1 - d_iset; - if(d_iset) { - do { - v1=2.0*ran1()-1.0; - v2=2.0*ran1()-1.0; - rsq=v1*v1+v2*v2; - } while(rsq >= 1.0 || rsq == 0.0); - fac= sqrt(-2.0*log(rsq)/rsq); - d_gset=v1*fac; - return v2*fac; - } - return d_gset; + if(d_gauss_stored){ // just return the stored value if available + d_gauss_stored = false; + return d_gauss_value; + } + else{ // generate a pair of gaussian distributed numbers + float x,y,s; + do{ + x = 2.0*ran1()-1.0; + y = 2.0*ran1()-1.0; + s = x*x+y*y; + }while(not(s<1.0)); + d_gauss_stored = true; + d_gauss_value = x*sqrt(-2.0*log(s)/s); + return y*sqrt(-2.0*log(s)/s); + } } - /* - * Copied from The KC7WW / OH2BNS Channel Simulator - * FIXME Need to check how good this is at some point - */ float random::laplacian() { - float z = ran1(); - if(z < 0.5) - return log(2.0 * z) / M_SQRT2; - else - return -log(2.0 * (1.0 - z)) / M_SQRT2; + float z = ran1()-0.5; + if(z>0) return -log(1-2*z); + else return log(1+2*z); } /* @@ -159,26 +130,12 @@ namespace gr { return z; } - /* - * Complex rayleigh is really gaussian I and gaussian Q - * It can also be generated by real rayleigh magnitude and - * uniform random angle - * Adapted from The KC7WW / OH2BNS Channel Simulator - * FIXME Need to check how good this is at some point - */ gr_complex random::rayleigh_complex() { return gr_complex(gasdev(),gasdev()); } - /* Other option - mag = rayleigh(); - ang = 2.0 * M_PI * RNG(); - *Rx = rxx * cos(z); - *Iy = rxx * sin(z); - */ - float random::rayleigh() { diff --git a/gnuradio-runtime/python/gnuradio/gr/qa_random.py b/gnuradio-runtime/python/gnuradio/gr/qa_random.py new file mode 100644 index 0000000000..83fee56181 --- /dev/null +++ b/gnuradio-runtime/python/gnuradio/gr/qa_random.py @@ -0,0 +1,64 @@ +#!/usr/bin/env python +# +# Copyright 2006,2007,2010,2015 Free Software Foundation, Inc. +# +# This file is part of GNU Radio +# +# GNU Radio is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 3, or (at your option) +# any later version. +# +# GNU Radio is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with GNU Radio; see the file COPYING. If not, write to +# the Free Software Foundation, Inc., 51 Franklin Street, +# Boston, MA 02110-1301, USA. +# + +from gnuradio import gr, gr_unittest +import numpy as np + +class test_random(gr_unittest.TestCase): + + # NOTE: For tests on the output distribution of the random numbers, see gnuradio-runtime/apps/evaluation_random_numbers.py. + + # Check for range [0,1) of uniform distributed random numbers + def test_1(self): + num_tests = 10000 + values = np.zeros(num_tests) + rndm = gr.random() + for k in range(num_tests): + values[k] = rndm.ran1() + for value in values: + self.assertLess(value, 1) + self.assertGreaterEqual(value, 0) + + # Check reseed method (init with time and seed as fix number) + def test_2(self): + num = 5 + + rndm0 = gr.random(42); # init with time + rndm1 = gr.random(42); # init with fix seed + for k in range(num): + x = rndm0.ran1(); + y = rndm1.ran1(); + self.assertEqual(x,y) + + x = np.zeros(num) + y = np.zeros(num) + rndm0 = gr.random(42); # init with fix seed 1 + for k in range(num): + x[k] = rndm0.ran1(); + rndm1.reseed(43); # init with fix seed 2 + for k in range(num): + y[k] = rndm0.ran1(); + for k in range(num): + self.assertNotEqual(x[k],y[k]) + +if __name__ == '__main__': + gr_unittest.run(test_random, "test_random.xml") diff --git a/gnuradio-runtime/swig/runtime_swig.i b/gnuradio-runtime/swig/runtime_swig.i index d4b55f134b..15cfebd300 100644 --- a/gnuradio-runtime/swig/runtime_swig.i +++ b/gnuradio-runtime/swig/runtime_swig.i @@ -60,6 +60,7 @@ #include <gnuradio/top_block.h> #include <gnuradio/logger.h> #include <gnuradio/math.h> +#include <gnuradio/random.h> %} %constant int sizeof_char = sizeof(char); @@ -95,3 +96,4 @@ %include "gr_ctrlport.i" %include "gnuradio/math.h" +%include "gnuradio/random.h" diff --git a/gr-blocks/grc/blocks_tag_object.xml b/gr-blocks/grc/blocks_tag_object.xml index f5813d3fbc..d2ef9fc41f 100644 --- a/gr-blocks/grc/blocks_tag_object.xml +++ b/gr-blocks/grc/blocks_tag_object.xml @@ -7,6 +7,7 @@ <block> <name>Tag Object</name> <key>variable_tag_object</key> + <import>import pmt</import> <var_make>self.$(id) = $(id) = gr.tag_utils.python_to_tag(($offset, $key, $value, $src))</var_make> <make></make> diff --git a/gr-dtv/grc/CMakeLists.txt b/gr-dtv/grc/CMakeLists.txt index 2187e283a5..2fed81ab12 100644 --- a/gr-dtv/grc/CMakeLists.txt +++ b/gr-dtv/grc/CMakeLists.txt @@ -60,6 +60,14 @@ install(FILES dtv_dvbt_symbol_inner_interleaver.xml dtv_dvbt_map.xml dtv_dvbt_reference_signals.xml + dtv_dvbt_ofdm_sym_acquisition.xml + dtv_dvbt_demod_reference_signals.xml + dtv_dvbt_demap.xml + dtv_dvbt_bit_inner_deinterleaver.xml + dtv_dvbt_viterbi_decoder.xml + dtv_dvbt_convolutional_deinterleaver.xml + dtv_dvbt_reed_solomon_dec.xml + dtv_dvbt_energy_descramble.xml DESTINATION ${GRC_BLOCKS_DIR} COMPONENT "dtv_python" ) diff --git a/gr-dtv/grc/dtv_block_tree.xml b/gr-dtv/grc/dtv_block_tree.xml index 1f05bc75dc..32c8974531 100644 --- a/gr-dtv/grc/dtv_block_tree.xml +++ b/gr-dtv/grc/dtv_block_tree.xml @@ -85,6 +85,14 @@ <block>dtv_dvbt_symbol_inner_interleaver</block> <block>dtv_dvbt_map</block> <block>dtv_dvbt_reference_signals</block> + <block>dtv_dvbt_ofdm_sym_acquisition</block> + <block>dtv_dvbt_demod_reference_signals</block> + <block>dtv_dvbt_demap</block> + <block>dtv_dvbt_bit_inner_deinterleaver</block> + <block>dtv_dvbt_viterbi_decoder</block> + <block>dtv_dvbt_convolutional_deinterleaver</block> + <block>dtv_dvbt_reed_solomon_dec</block> + <block>dtv_dvbt_energy_descramble</block> </cat> </cat> </cat> diff --git a/gr-dtv/grc/dtv_dvbt_bit_inner_deinterleaver.xml b/gr-dtv/grc/dtv_dvbt_bit_inner_deinterleaver.xml new file mode 100644 index 0000000000..ff338d2118 --- /dev/null +++ b/gr-dtv/grc/dtv_dvbt_bit_inner_deinterleaver.xml @@ -0,0 +1,89 @@ +<?xml version="1.0"?> +<!-- +################################################### +## DVB-T Bit Inner Deinterleaver +################################################### + --> +<block> + <name>Bit Inner Deinterleaver</name> + <key>dtv_dvbt_bit_inner_deinterleaver</key> + <import>from gnuradio import dtv</import> + <make>dtv.dvbt_bit_inner_deinterleaver($transmission_mode.payload_length, $constellation.val, $hierarchy.val, $transmission_mode.val)</make> + <param> + <name>Constellation Type</name> + <key>constellation</key> + <type>enum</type> + <option> + <name>QPSK</name> + <key>qpsk</key> + <opt>val:dtv.MOD_QPSK</opt> + </option> + <option> + <name>16QAM</name> + <key>16qam</key> + <opt>val:dtv.MOD_16QAM</opt> + </option> + <option> + <name>64QAM</name> + <key>64qam</key> + <opt>val:dtv.MOD_64QAM</opt> + </option> + </param> + <param> + <name>Hierarchy Type</name> + <key>hierarchy</key> + <type>enum</type> + <option> + <name>Non Hierarchical</name> + <key>nh</key> + <opt>val:dtv.NH</opt> + <opt>num_streams:1</opt> + </option> + <option> + <name>Alpha 1</name> + <key>alpha1</key> + <opt>val:dtv.ALPHA1</opt> + <opt>num_streams:2</opt> + </option> + <option> + <name>Alpha 2</name> + <key>alpha2</key> + <opt>val:dtv.ALPHA2</opt> + <opt>num_streams:2</opt> + </option> + <option> + <name>Alpha 4</name> + <key>alpha4</key> + <opt>val:dtv.ALPHA4</opt> + <opt>num_streams:2</opt> + </option> + </param> + <param> + <name>Transmission Mode</name> + <key>transmission_mode</key> + <type>enum</type> + <option> + <name>2K</name> + <key>T2k</key> + <opt>val:dtv.T2k</opt> + <opt>payload_length:1512</opt> + </option> + <option> + <name>8K</name> + <key>T8k</key> + <opt>val:dtv.T8k</opt> + <opt>payload_length:6048</opt> + </option> + </param> + <sink> + <name>in</name> + <type>byte</type> + <vlen>$transmission_mode.payload_length</vlen> + </sink> + <source> + <name>out</name> + <type>byte</type> + <vlen>$transmission_mode.payload_length</vlen> + <nports>$hierarchy.num_streams</nports> + </source> +</block> diff --git a/gr-dtv/grc/dtv_dvbt_convolutional_deinterleaver.xml b/gr-dtv/grc/dtv_dvbt_convolutional_deinterleaver.xml new file mode 100644 index 0000000000..315920bd42 --- /dev/null +++ b/gr-dtv/grc/dtv_dvbt_convolutional_deinterleaver.xml @@ -0,0 +1,43 @@ +<?xml version="1.0"?> +<!-- +################################################### +## DVB-T Convolutional Deinterleaver +################################################### + --> +<block> + <name>Convolutional Deinterleaver</name> + <key>dtv_dvbt_convolutional_deinterleaver</key> + <import>from gnuradio import dtv</import> + <make>dtv.dvbt_convolutional_deinterleaver($blocks, $I, $M)</make> + <param> + <name>Blocks (12 Bytes)</name> + <key>blocks</key> + <value>136</value> + <type>int</type> + </param> + <param> + <name>Number of Shift registers</name> + <key>I</key> + <value>12</value> + <type>int</type> + </param> + <param> + <name>Depth of shift registers</name> + <key>M</key> + <value>17</value> + <type>int</type> + </param> + <check>$blocks > 0</check> + <check>$I > 0</check> + <check>$M > 0</check> + <sink> + <name>in</name> + <type>byte</type> + <vlen>1</vlen> + </sink> + <source> + <name>out</name> + <type>byte</type> + <vlen>$blocks*$I</vlen> + </source> +</block> diff --git a/gr-dtv/grc/dtv_dvbt_demap.xml b/gr-dtv/grc/dtv_dvbt_demap.xml new file mode 100644 index 0000000000..2268ed7cf5 --- /dev/null +++ b/gr-dtv/grc/dtv_dvbt_demap.xml @@ -0,0 +1,90 @@ +<?xml version="1.0"?> +<!-- +################################################### +## DVB-T Demap +################################################### + --> +<block> + <name>DVB-T Demap</name> + <key>dtv_dvbt_demap</key> + <import>from gnuradio import dtv</import> + <make>dtv.dvbt_demap($transmission_mode.payload_length, $constellation.val, $hierarchy.val, $transmission_mode.val, $gain)</make> + <param> + <name>Constellation Type</name> + <key>constellation</key> + <type>enum</type> + <option> + <name>QPSK</name> + <key>qpsk</key> + <opt>val:dtv.MOD_QPSK</opt> + </option> + <option> + <name>16QAM</name> + <key>16qam</key> + <opt>val:dtv.MOD_16QAM</opt> + </option> + <option> + <name>64QAM</name> + <key>64qam</key> + <opt>val:dtv.MOD_64QAM</opt> + </option> + </param> + <param> + <name>Hierarchy Type</name> + <key>hierarchy</key> + <type>enum</type> + <option> + <name>Non Hierarchical</name> + <key>nh</key> + <opt>val:dtv.NH</opt> + </option> + <option> + <name>Alpha 1</name> + <key>alpha1</key> + <opt>val:dtv.ALPHA1</opt> + </option> + <option> + <name>Alpha 2</name> + <key>alpha2</key> + <opt>val:dtv.ALPHA2</opt> + </option> + <option> + <name>Alpha 4</name> + <key>alpha4</key> + <opt>val:dtv.ALPHA4</opt> + </option> + </param> + <param> + <name>Transmission Mode</name> + <key>transmission_mode</key> + <type>enum</type> + <option> + <name>2K</name> + <key>T2k</key> + <opt>val:dtv.T2k</opt> + <opt>payload_length:1512</opt> + </option> + <option> + <name>8K</name> + <key>T8k</key> + <opt>val:dtv.T8k</opt> + <opt>payload_length:6048</opt> + </option> + </param> + <param> + <name>Gain</name> + <key>gain</key> + <value>1</value> + <type>complex</type> + </param> + <sink> + <name>in</name> + <type>complex</type> + <vlen>$transmission_mode.payload_length</vlen> + </sink> + <source> + <name>out</name> + <type>byte</type> + <vlen>$transmission_mode.payload_length</vlen> + </source> +</block> diff --git a/gr-dtv/grc/dtv_dvbt_demod_reference_signals.xml b/gr-dtv/grc/dtv_dvbt_demod_reference_signals.xml new file mode 100644 index 0000000000..f92469b7e6 --- /dev/null +++ b/gr-dtv/grc/dtv_dvbt_demod_reference_signals.xml @@ -0,0 +1,222 @@ +<?xml version="1.0"?> +<!-- +################################################### +## Demod Reference Signals +################################################### + --> +<block> + <name>Demod Reference Signals</name> + <key>dtv_dvbt_demod_reference_signals</key> + <import>from gnuradio import dtv</import> + <make>dtv.dvbt_demod_reference_signals($type.size, $transmission_mode.fft_length, $transmission_mode.payload_length, $constellation.val, $hierarchy.val, $code_rate_hp.val, $code_rate_lp.val, $guard_interval.val, $transmission_mode.val, $include_cell_id.val, $cell_id)</make> + <param> + <name>IO Type</name> + <key>type</key> + <type>enum</type> + <option> + <name>Complex</name> + <key>complex</key> + <opt>size:gr.sizeof_gr_complex</opt> + </option> + <option> + <name>Float</name> + <key>float</key> + <opt>size:gr.sizeof_float</opt> + </option> + <option> + <name>Int</name> + <key>int</key> + <opt>size:gr.sizeof_int</opt> + </option> + <option> + <name>Short</name> + <key>short</key> + <opt>size:gr.sizeof_short</opt> + </option> + <option> + <name>Byte</name> + <key>byte</key> + <opt>size:gr.sizeof_char</opt> + </option> + </param> + <param> + <name>Constellation Type</name> + <key>constellation</key> + <type>enum</type> + <option> + <name>QPSK</name> + <key>qpsk</key> + <opt>val:dtv.MOD_QPSK</opt> + </option> + <option> + <name>16QAM</name> + <key>16qam</key> + <opt>val:dtv.MOD_16QAM</opt> + </option> + <option> + <name>64QAM</name> + <key>64qam</key> + <opt>val:dtv.MOD_64QAM</opt> + </option> + </param> + <param> + <name>Hierarchy Type</name> + <key>hierarchy</key> + <type>enum</type> + <option> + <name>Non Hierarchical</name> + <key>nh</key> + <opt>val:dtv.NH</opt> + </option> + <option> + <name>Alpha 1</name> + <key>alpha1</key> + <opt>val:dtv.ALPHA1</opt> + </option> + <option> + <name>Alpha 2</name> + <key>alpha2</key> + <opt>val:dtv.ALPHA2</opt> + </option> + <option> + <name>Alpha 4</name> + <key>alpha4</key> + <opt>val:dtv.ALPHA4</opt> + </option> + </param> + <param> + <name>Code rate HP</name> + <key>code_rate_hp</key> + <type>enum</type> + <option> + <name>1/2</name> + <key>C1_2</key> + <opt>val:dtv.C1_2</opt> + </option> + <option> + <name>2/3</name> + <key>C2_3</key> + <opt>val:dtv.C2_3</opt> + </option> + <option> + <name>3/4</name> + <key>C3_4</key> + <opt>val:dtv.C3_4</opt> + </option> + <option> + <name>5/6</name> + <key>C5_6</key> + <opt>val:dtv.C5_6</opt> + </option> + <option> + <name>7/8</name> + <key>C7_8</key> + <opt>val:dtv.C7_8</opt> + </option> + </param> + <param> + <name>Code rate LP</name> + <key>code_rate_lp</key> + <type>enum</type> + <option> + <name>1/2</name> + <key>C1_2</key> + <opt>val:dtv.C1_2</opt> + </option> + <option> + <name>2/3</name> + <key>C2_3</key> + <opt>val:dtv.C2_3</opt> + </option> + <option> + <name>3/4</name> + <key>C3_4</key> + <opt>val:dtv.C3_4</opt> + </option> + <option> + <name>5/6</name> + <key>C5_6</key> + <opt>val:dtv.C5_6</opt> + </option> + <option> + <name>7/8</name> + <key>C7_8</key> + <opt>val:dtv.C7_8</opt> + </option> + </param> + <param> + <name>Guard Interval</name> + <key>guard_interval</key> + <type>enum</type> + <option> + <name>1/32</name> + <key>GI_1_32</key> + <opt>val:dtv.GI_1_32</opt> + </option> + <option> + <name>1/16</name> + <key>GI_1_16</key> + <opt>val:dtv.GI_1_16</opt> + </option> + <option> + <name>1/8</name> + <key>GI_1_8</key> + <opt>val:dtv.GI_1_8</opt> + </option> + <option> + <name>1/4</name> + <key>GI_1_4</key> + <opt>val:dtv.GI_1_4</opt> + </option> + </param> + <param> + <name>Transmission Mode</name> + <key>transmission_mode</key> + <type>enum</type> + <option> + <name>2K</name> + <key>T2k</key> + <opt>val:dtv.T2k</opt> + <opt>fft_length:2048</opt> + <opt>payload_length:1512</opt> + </option> + <option> + <name>8K</name> + <key>T8k</key> + <opt>val:dtv.T8k</opt> + <opt>fft_length:8192</opt> + <opt>payload_length:6048</opt> + </option> + </param> + <param> + <name>Include Cell ID</name> + <key>include_cell_id</key> + <type>enum</type> + <option> + <name>Yes</name> + <key>call_id_yes</key> + <opt>val:1</opt> + </option> + <option> + <name>No</name> + <key>cell_id_no</key> + <opt>val:0</opt> + </option> + </param> + <param> + <name>Cell Id</name> + <key>cell_id</key> + <value>0</value> + <type>int</type> + </param> + <sink> + <name>in</name> + <type>complex</type> + <vlen>$transmission_mode.fft_length</vlen> + </sink> + <source> + <name>out</name> + <type>complex</type> + <vlen>$transmission_mode.payload_length</vlen> + </source> +</block> diff --git a/gr-dtv/grc/dtv_dvbt_energy_descramble.xml b/gr-dtv/grc/dtv_dvbt_energy_descramble.xml new file mode 100644 index 0000000000..689f85424f --- /dev/null +++ b/gr-dtv/grc/dtv_dvbt_energy_descramble.xml @@ -0,0 +1,29 @@ +<?xml version="1.0"?> +<!-- +################################################### +## DVB-T Energy Descramble +################################################### + --> +<block> + <name>Energy Descramble</name> + <key>dtv_dvbt_energy_descramble</key> + <import>from gnuradio import dtv</import> + <make>dtv.dvbt_energy_descramble($nsize)</make> + <param> + <name>Blocks(188 Bytes)</name> + <key>nsize</key> + <value>8</value> + <type>int</type> + </param> + <check>$nsize > 0</check> + <sink> + <name>in</name> + <type>byte</type> + <vlen>188*8</vlen> + </sink> + <source> + <name>out</name> + <type>byte</type> + <vlen>1</vlen> + </source> +</block> diff --git a/gr-dtv/grc/dtv_dvbt_ofdm_sym_acquisition.xml b/gr-dtv/grc/dtv_dvbt_ofdm_sym_acquisition.xml new file mode 100644 index 0000000000..a75dcc02c3 --- /dev/null +++ b/gr-dtv/grc/dtv_dvbt_ofdm_sym_acquisition.xml @@ -0,0 +1,76 @@ +<?xml version="1.0"?> +<!-- +################################################### +## OFDM Symbol Acquisition +################################################### + --> +<block> + <name>OFDM Symbol Acquisition</name> + <key>dtv_dvbt_ofdm_sym_acquisition</key> + <import>from gnuradio import dtv</import> + <make>dtv.dvbt_ofdm_sym_acquisition(1, $fft_length, $occupied_tones, $cp_length, $snr)</make> + <param> + <name>Output Type</name> + <key>type</key> + <value>float</value> + <type>enum</type> + <option> + <name>Complex</name> + <key>complex</key> + <opt>fcn:c</opt> + </option> + <option> + <name>Float</name> + <key>float</key> + <opt>fcn:f</opt> + </option> + <option> + <name>Int</name> + <key>int</key> + <opt>fcn:i</opt> + </option> + <option> + <name>Short</name> + <key>short</key> + <opt>fcn:s</opt> + </option> + <option> + <name>Byte</name> + <key>byte</key> + <opt>fcn:b</opt> + </option> + </param> + <param> + <name>FFT Length</name> + <key>fft_length</key> + <value>2048</value> + <type>int</type> + </param> + <param> + <name>Occupied Tones</name> + <key>occupied_tones</key> + <value>1705</value> + <type>int</type> + </param> + <param> + <name>Cyclic Prefix Length</name> + <key>cp_length</key> + <value>64</value> + <type>int</type> + </param> + <param> + <name>SNR</name> + <key>snr</key> + <value>10</value> + <type>real</type> + </param> + <sink> + <name>in</name> + <type>complex</type> + </sink> + <source> + <name>out</name> + <type>$type</type> + <vlen>$fft_length</vlen> + </source> +</block> diff --git a/gr-dtv/grc/dtv_dvbt_reed_solomon_dec.xml b/gr-dtv/grc/dtv_dvbt_reed_solomon_dec.xml new file mode 100644 index 0000000000..798a6d40f8 --- /dev/null +++ b/gr-dtv/grc/dtv_dvbt_reed_solomon_dec.xml @@ -0,0 +1,70 @@ +<?xml version="1.0"?> +<!-- +################################################### +## DVB-T Reed Solomon Decoder +################################################### + --> +<block> + <name>Reed-Solomon Decoder</name> + <key>dtv_dvbt_reed_solomon_dec</key> + <import>from gnuradio import dtv</import> + <make>dtv.dvbt_reed_solomon_dec($p, $m, $gfpoly, $n, $k, $t, $s, $blocks)</make> + <param> + <name>p</name> + <key>p</key> + <value>2</value> + <type>int</type> + </param> + <param> + <name>m</name> + <key>m</key> + <value>8</value> + <type>int</type> + </param> + <param> + <name>GF polynomial</name> + <key>gfpoly</key> + <value>0x11d</value> + <type>raw</type> + </param> + <param> + <name>N</name> + <key>n</key> + <value>255</value> + <type>int</type> + </param> + <param> + <name>K</name> + <key>k</key> + <value>239</value> + <type>int</type> + </param> + <param> + <name>t</name> + <key>t</key> + <value>8</value> + <type>int</type> + </param> + <param> + <name>Shortening size</name> + <key>s</key> + <value>51</value> + <type>int</type> + </param> + <param> + <name>Blocks</name> + <key>blocks</key> + <value>8</value> + <type>int</type> + </param> + <sink> + <name>in</name> + <type>byte</type> + <vlen>$blocks*($n-$s)</vlen> + </sink> + <source> + <name>out</name> + <type>byte</type> + <vlen>$blocks*($k-$s)</vlen> + </source> +</block> diff --git a/gr-dtv/grc/dtv_dvbt_reference_signals.xml b/gr-dtv/grc/dtv_dvbt_reference_signals.xml index 9be57630e5..3a4282cc50 100644 --- a/gr-dtv/grc/dtv_dvbt_reference_signals.xml +++ b/gr-dtv/grc/dtv_dvbt_reference_signals.xml @@ -199,7 +199,7 @@ </option> <option> <name>No</name> - <key>cell_ide_no</key> + <key>cell_id_no</key> <opt>val:0</opt> </option> </param> diff --git a/gr-dtv/grc/dtv_dvbt_viterbi_decoder.xml b/gr-dtv/grc/dtv_dvbt_viterbi_decoder.xml new file mode 100644 index 0000000000..1dde80c281 --- /dev/null +++ b/gr-dtv/grc/dtv_dvbt_viterbi_decoder.xml @@ -0,0 +1,120 @@ +<?xml version="1.0"?> +<!-- +################################################### +## DVB-T Viterbi Decoder +################################################### + --> +<block> + <name>Viterbi Decoder</name> + <key>dtv_dvbt_viterbi_decoder</key> + <import>from gnuradio import dtv</import> + <make>dtv.dvbt_viterbi_decoder($constellation.val, $hierarchy.val, $code_rate.val, $block_size)</make> + <param> + <name>Constellation Type</name> + <key>constellation</key> + <type>enum</type> + <option> + <name>QPSK</name> + <key>qpsk</key> + <opt>val:dtv.MOD_QPSK</opt> + </option> + <option> + <name>16QAM</name> + <key>16qam</key> + <opt>val:dtv.MOD_16QAM</opt> + </option> + <option> + <name>64QAM</name> + <key>64qam</key> + <opt>val:dtv.MOD_64QAM</opt> + </option> + </param> + <param> + <name>Hierarchy Type</name> + <key>hierarchy</key> + <type>enum</type> + <option> + <name>Non Hierarchical</name> + <key>nh</key> + <opt>val:dtv.NH</opt> + </option> + <option> + <name>Alpha 1</name> + <key>alpha1</key> + <opt>val:dtv.ALPHA1</opt> + </option> + <option> + <name>Alpha 2</name> + <key>alpha2</key> + <opt>val:dtv.ALPHA2</opt> + </option> + <option> + <name>Alpha 4</name> + <key>alpha4</key> + <opt>val:dtv.ALPHA4</opt> + </option> + </param> + <param> + <name>Code rate</name> + <key>code_rate</key> + <type>enum</type> + <option> + <name>1/2</name> + <key>C1_2</key> + <opt>val:dtv.C1_2</opt> + </option> + <option> + <name>2/3</name> + <key>C2_3</key> + <opt>val:dtv.C2_3</opt> + </option> + <option> + <name>3/4</name> + <key>C3_4</key> + <opt>val:dtv.C3_4</opt> + </option> + <option> + <name>5/6</name> + <key>C5_6</key> + <opt>val:dtv.C5_6</opt> + </option> + <option> + <name>7/8</name> + <key>C7_8</key> + <opt>val:dtv.C7_8</opt> + </option> + </param> + <param> + <name>Type</name> + <key>type</key> + <type>enum</type> + <option> + <name>Int</name> + <key>i</key> + <opt>io:int</opt> + </option> + <option> + <name>Short</name> + <key>s</key> + <opt>io:short</opt> + </option> + <option> + <name>Byte</name> + <key>b</key> + <opt>io:byte</opt> + </option> + </param> + <param> + <name>Block Size</name> + <key>block_size</key> + <type>int</type> + </param> + <sink> + <name>in</name> + <type>byte</type> + </sink> + <source> + <name>out</name> + <type>$type.io</type> + </source> +</block> diff --git a/gr-dtv/include/gnuradio/dtv/dvbt_bit_inner_deinterleaver.h b/gr-dtv/include/gnuradio/dtv/dvbt_bit_inner_deinterleaver.h new file mode 100644 index 0000000000..1f9aab16e5 --- /dev/null +++ b/gr-dtv/include/gnuradio/dtv/dvbt_bit_inner_deinterleaver.h @@ -0,0 +1,67 @@ +/* -*- c++ -*- */ +/* + * Copyright 2015 Free Software Foundation, Inc. + * + * This is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3, or (at your option) + * any later version. + * + * This software is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this software; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, + * Boston, MA 02110-1301, USA. + */ + +#ifndef INCLUDED_DTV_DVBT_BIT_INNER_DEINTERLEVER_H +#define INCLUDED_DTV_DVBT_BIT_INNER_DEINTERLEVER_H + +#include <gnuradio/dtv/api.h> +#include <gnuradio/block.h> +#include <gnuradio/dtv/dvb_config.h> +#include <gnuradio/dtv/dvbt_config.h> + +namespace gr { + namespace dtv { + + /*! + * \brief Bit Inner deinterleaver. + * \ingroup dtv + * + * ETSI EN 300 744 Clause 4.3.4.1 \n + * Data Input format: \n + * 000000B0B1 - QPSK. \n + * 0000B0B1B2B3 - 16QAM. \n + * 00B0B1B2B3B4B5 - 64QAM. \n + * Data Output format: \n + * 000000X0X1 - QPSK. \n + * 0000X0X1X2X3 - 16QAM. \n + * 00X0X1X2X3X4X5 - 64QAM. \n + * bit deinterleaver block size is 126. + */ + class DTV_API dvbt_bit_inner_deinterleaver : virtual public block + { + public: + typedef boost::shared_ptr<dvbt_bit_inner_deinterleaver> sptr; + + /*! + * \brief Create a Bit Inner deinterleaver + * + * \param nsize length of input stream. \n + * \param constellation constellation used. \n + * \param hierarchy hierarchy used. \n + * \param transmission transmission mode used. + */ + static sptr make(int nsize, dvb_constellation_t constellation, dvbt_hierarchy_t hierarchy, dvbt_transmission_mode_t transmission); + }; + + } // namespace dtv +} // namespace gr + +#endif /* INCLUDED_DTV_DVBT_BIT_INNER_DEINTERLEVER_H */ + diff --git a/gr-dtv/include/gnuradio/dtv/dvbt_convolutional_deinterleaver.h b/gr-dtv/include/gnuradio/dtv/dvbt_convolutional_deinterleaver.h new file mode 100644 index 0000000000..1a52c41af8 --- /dev/null +++ b/gr-dtv/include/gnuradio/dtv/dvbt_convolutional_deinterleaver.h @@ -0,0 +1,58 @@ +/* -*- c++ -*- */ +/* + * Copyright 2015 Free Software Foundation, Inc. + * + * This is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3, or (at your option) + * any later version. + * + * This software is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this software; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, + * Boston, MA 02110-1301, USA. + */ + +#ifndef INCLUDED_DTV_DVBT_CONVOLUTIONAL_DEINTERLEAVER_H +#define INCLUDED_DTV_DVBT_CONVOLUTIONAL_DEINTERLEAVER_H + +#include <gnuradio/dtv/api.h> +#include <gnuradio/block.h> + +namespace gr { + namespace dtv { + + /*! + * \brief Convolutional deinterleaver. + * \ingroup dtv + * + * ETSI EN 300 744 Clause 4.3.1 \n + * Forney (Ramsey type III) convolutional deinterleaver. \n + * Data input: Stream of 1 byte elements. \n + * Data output: Blocks of I bytes size. + */ + class DTV_API dvbt_convolutional_deinterleaver : virtual public block + { + public: + typedef boost::shared_ptr<dvbt_convolutional_deinterleaver> sptr; + + /*! + * \brief Create a DVB-T convolutional deinterleaver. + * + * \param nsize number of blocks to process. \n + * \param I size of a block. \n + * \param M depth length for each element in shift registers. + */ + static sptr make(int nsize, int I, int M); + }; + + } // namespace dtv +} // namespace gr + +#endif /* INCLUDED_DTV_DVBT_CONVOLUTIONAL_DEINTERLEAVER_H */ + diff --git a/gr-dtv/include/gnuradio/dtv/dvbt_demap.h b/gr-dtv/include/gnuradio/dtv/dvbt_demap.h new file mode 100644 index 0000000000..1f04beea0a --- /dev/null +++ b/gr-dtv/include/gnuradio/dtv/dvbt_demap.h @@ -0,0 +1,65 @@ +/* -*- c++ -*- */ +/* + * Copyright 2015 Free Software Foundation, Inc. + * + * This is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3, or (at your option) + * any later version. + * + * This software is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this software; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, + * Boston, MA 02110-1301, USA. + */ + +#ifndef INCLUDED_DTV_DVBT_DVBT_DEMAP_H +#define INCLUDED_DTV_DVBT_DVBT_DEMAP_H + +#include <gnuradio/dtv/api.h> +#include <gnuradio/block.h> +#include <gnuradio/dtv/dvb_config.h> +#include <gnuradio/dtv/dvbt_config.h> + +namespace gr { + namespace dtv { + + /*! + * \brief DVB-T demapper. + * \ingroup dtv + * + * ETSI EN 300 744 Clause 4.3.5. \n + * Data input format: \n + * complex(real(float), imag(float)). \n + * Data output format: \n + * 000000Y0Y1 - QPSK. \n + * 0000Y0Y1Y2Y3 - 16QAM. \n + * 00Y0Y1Y2Y3Y4Y5 - 64QAM. + */ + class DTV_API dvbt_demap : virtual public block + { + public: + typedef boost::shared_ptr<dvbt_demap> sptr; + + /*! + * \brief Create a DVB-T demapper. + * + * \param nsize length of input stream. \n + * \param constellation constellation used. \n + * \param hierarchy hierarchy used. \n + * \param transmission transmission mode used. \n + * \param gain gain of complex input stream. + */ + static sptr make(int nsize, dvb_constellation_t constellation, dvbt_hierarchy_t hierarchy, dvbt_transmission_mode_t transmission, float gain); + }; + + } // namespace dtv +} // namespace gr + +#endif /* INCLUDED_DTV_DVBT_DVBT_DEMAP_H */ + diff --git a/gr-dtv/include/gnuradio/dtv/dvbt_demod_reference_signals.h b/gr-dtv/include/gnuradio/dtv/dvbt_demod_reference_signals.h new file mode 100644 index 0000000000..3f28ddeec7 --- /dev/null +++ b/gr-dtv/include/gnuradio/dtv/dvbt_demod_reference_signals.h @@ -0,0 +1,73 @@ +/* -*- c++ -*- */ +/* + * Copyright 2015 Free Software Foundation, Inc. + * + * This is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3, or (at your option) + * any later version. + * + * This software is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this software; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, + * Boston, MA 02110-1301, USA. + */ + +#ifndef INCLUDED_DTV_DVBT_DEMOD_REFERENCE_SIGNALS_H +#define INCLUDED_DTV_DVBT_DEMOD_REFERENCE_SIGNALS_H + +#include <gnuradio/dtv/api.h> +#include <gnuradio/block.h> +#include <gnuradio/dtv/dvb_config.h> +#include <gnuradio/dtv/dvbt_config.h> + +namespace gr { + namespace dtv { + + /*! + * \brief Reference signals demodulator. + * \ingroup dtv + * + * ETSI EN 300 744 Clause 4.5 \n + * Data input format: \n + * complex(real(float), imag(float)). \n + * Data output format: \n + * complex(real(float), imag(float)). + */ + class DTV_API dvbt_demod_reference_signals : virtual public block + { + public: + typedef boost::shared_ptr<dvbt_demod_reference_signals> sptr; + + /*! + * \brief Create Reference signals demodulator. + * + * \param itemsize size of an in/out item. \n + * \param ninput input stream length. \n + * \param noutput output stream length. \n + * \param constellation constellation used. \n + * \param hierarchy hierarchy used. \n + * \param code_rate_HP high priority stream code rate. \n + * \param code_rate_LP low priority stream code rate. \n + * \param guard_interval guard interval used. \n + * \param transmission_mode transmission mode used. \n + * \param include_cell_id include or not Cell ID. \n + * \param cell_id value of the Cell ID. + */ + static sptr make(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, \ + int include_cell_id, int cell_id); + }; + + } // namespace dtv +} // namespace gr + +#endif /* INCLUDED_DTV_DVBT_DEMOD_REFERENCE_SIGNALS_H */ + diff --git a/gr-dtv/include/gnuradio/dtv/dvbt_energy_descramble.h b/gr-dtv/include/gnuradio/dtv/dvbt_energy_descramble.h new file mode 100644 index 0000000000..6d50da1535 --- /dev/null +++ b/gr-dtv/include/gnuradio/dtv/dvbt_energy_descramble.h @@ -0,0 +1,58 @@ +/* -*- c++ -*- */ +/* + * Copyright 2015 Free Software Foundation, Inc. + * + * This is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3, or (at your option) + * any later version. + * + * This software is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this software; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, + * Boston, MA 02110-1301, USA. + */ + +#ifndef INCLUDED_DTV_DVBT_ENERGY_DESCRAMBLE_H +#define INCLUDED_DTV_DVBT_ENERGY_DESCRAMBLE_H + +#include <gnuradio/dtv/api.h> +#include <gnuradio/block.h> + +namespace gr { + namespace dtv { + + /*! + * \brief Energy descramble + * \ingroup dtv + * + * ETSI EN 300 744 - Clause 4.3.1. \n + * Input - Randomized MPEG-2 transport packets. \n + * Output - MPEG-2 transport packets (including sync - 0x47). \n + * We assume the first byte is a NSYNC. \n + * First sync in a row of 8 packets is reversed - 0xB8. \n + * Block size is 188 bytes + */ + class DTV_API dvbt_energy_descramble : virtual public block + { + public: + typedef boost::shared_ptr<dvbt_energy_descramble> sptr; + + /*! + * \brief Create DVB-T Energy descramble. + * + * \param nblocks number of blocks. + */ + static sptr make(int nblocks); + }; + + } // namespace dtv +} // namespace gr + +#endif /* INCLUDED_DTV_DVBT_ENERGY_DESCRAMBLE_H */ + diff --git a/gr-dtv/include/gnuradio/dtv/dvbt_map.h b/gr-dtv/include/gnuradio/dtv/dvbt_map.h index d9b7976b31..5bd8f433f9 100644 --- a/gr-dtv/include/gnuradio/dtv/dvbt_map.h +++ b/gr-dtv/include/gnuradio/dtv/dvbt_map.h @@ -18,8 +18,8 @@ * Boston, MA 02110-1301, USA. */ -#ifndef INCLUDED_DVBT_DVBT_MAP_H -#define INCLUDED_DVBT_DVBT_MAP_H +#ifndef INCLUDED_DTV_DVBT_MAP_H +#define INCLUDED_DTV_DVBT_MAP_H #include <gnuradio/dtv/api.h> #include <gnuradio/dtv/dvb_config.h> diff --git a/gr-dtv/include/gnuradio/dtv/dvbt_ofdm_sym_acquisition.h b/gr-dtv/include/gnuradio/dtv/dvbt_ofdm_sym_acquisition.h new file mode 100644 index 0000000000..ced054dc22 --- /dev/null +++ b/gr-dtv/include/gnuradio/dtv/dvbt_ofdm_sym_acquisition.h @@ -0,0 +1,60 @@ +/* -*- c++ -*- */ +/* + * Copyright 2015 Free Software Foundation, Inc. + * + * This is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3, or (at your option) + * any later version. + * + * This software is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this software; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, + * Boston, MA 02110-1301, USA. + */ + +#ifndef INCLUDED_DTV_DVBT_OFDM_SYM_ACQUISITION_H +#define INCLUDED_DTV_DVBT_OFDM_SYM_ACQUISITION_H + +#include <gnuradio/dtv/api.h> +#include <gnuradio/block.h> + +namespace gr { + namespace dtv { + + /*! + * \brief OFDM symbol acquisition. + * \ingroup dtv + * + * Data input format: \n + * complex(real(float), imag(float)). \n + * Data output format: \n + * complex(real(float), imag(float)). + */ + class DTV_API dvbt_ofdm_sym_acquisition : virtual public block + { + public: + typedef boost::shared_ptr<dvbt_ofdm_sym_acquisition> sptr; + + /*! + * \brief Create OFDM symbol acquisition. + * + * \param blocks Always equal to 1.\n + * \param fft_length FFT size, 2048 or 8192. \n + * \param occupied_tones Active OFDM carriers, 1705 or 6817. \n + * \param cp_length Length of Cyclic Prefix (FFT size / 32, 16, 8 or 4). \n + * \param snr Initial Signal to Noise Ratio. + */ + static sptr make(int blocks, int fft_length, int occupied_tones, int cp_length, float snr); + }; + + } // namespace dtv +} // namespace gr + +#endif /* INCLUDED_DTV_DVBT_OFDM_SYM_ACQUISITION_H */ + diff --git a/gr-dtv/include/gnuradio/dtv/dvbt_reed_solomon_dec.h b/gr-dtv/include/gnuradio/dtv/dvbt_reed_solomon_dec.h new file mode 100644 index 0000000000..5ef8e04443 --- /dev/null +++ b/gr-dtv/include/gnuradio/dtv/dvbt_reed_solomon_dec.h @@ -0,0 +1,61 @@ +/* -*- c++ -*- */ +/* + * Copyright 2015 Free Software Foundation, Inc. + * + * This is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3, or (at your option) + * any later version. + * + * This software is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this software; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, + * Boston, MA 02110-1301, USA. + */ + +#ifndef INCLUDED_DTV_DVBT_REED_SOLOMON_DEC_H +#define INCLUDED_DTV_DVBT_REED_SOLOMON_DEC_H + +#include <gnuradio/dtv/api.h> +#include <gnuradio/block.h> + +namespace gr { + namespace dtv { + + /*! + * \brief Reed Solomon decoder. + * \ingroup dtv + * + * ETSI EN 300 744 Clause 4.3.2 \n + * RS(N=204,K=239,T=8). + */ + class DTV_API dvbt_reed_solomon_dec : virtual public block + { + public: + typedef boost::shared_ptr<dvbt_reed_solomon_dec> sptr; + + /*! + * \brief Create a Reed Solomon decoder. + * + * \param p characteristic of GF(p^m). + * \param m we use GF(p^m). + * \param gfpoly Generator Polynomial. + * \param n length of codeword of RS coder. + * \param k length of information sequence of RS decoder. + * \param t number of corrected errors. + * \param s shortened length. + * \param blocks number of blocks to process at once. + */ + static sptr make(int p, int m, int gfpoly, int n, int k, int t, int s, int blocks); + }; + + } // namespace dtv +} // namespace gr + +#endif /* INCLUDED_DTV_DVBT_REED_SOLOMON_DEC_H */ + diff --git a/gr-dtv/include/gnuradio/dtv/dvbt_viterbi_decoder.h b/gr-dtv/include/gnuradio/dtv/dvbt_viterbi_decoder.h new file mode 100644 index 0000000000..b44ec4f44a --- /dev/null +++ b/gr-dtv/include/gnuradio/dtv/dvbt_viterbi_decoder.h @@ -0,0 +1,69 @@ +/* -*- c++ -*- */ +/* + * Copyright 2015 Free Software Foundation, Inc. + * + * This is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3, or (at your option) + * any later version. + * + * This software is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this software; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, + * Boston, MA 02110-1301, USA. + */ + +#ifndef INCLUDED_DTV_DVBT_VITERBI_DECODER_H +#define INCLUDED_DTV_DVBT_VITERBI_DECODER_H + +#include <gnuradio/dtv/api.h> +#include <gnuradio/block.h> +#include <gnuradio/dtv/dvb_config.h> +#include <gnuradio/dtv/dvbt_config.h> + +namespace gr { + namespace dtv { + + /*! + * \brief DVB-T Viterbi decoder. + * \ingroup dtv + * + * ETSI EN 300 744 Clause 4.3.3 \n + * Mother convolutional code with rate 1/2. \n + * k=1, n=2, K=6. \n + * Generator polynomial G1=171(OCT), G2=133(OCT). \n + * Punctured to obtain rates of 2/3, 3/4, 5/6, 7/8. \n + * Data Input format: \n + * 000000X0X1 - QPSK. \n + * 0000X0X1X2X3 - 16QAM. \n + * 00X0X1X2X3X4X5 - 64QAM. \n + * Data Output format: Packed bytes (each bit is data). \n + * MSB - first, LSB last. + */ + class DTV_API dvbt_viterbi_decoder : virtual public block + { + public: + typedef boost::shared_ptr<dvbt_viterbi_decoder> sptr; + + /*! + * \brief Create a DVB-T Viterbi decoder. + * + * \param constellation constellation used. \n + * \param hierarchy hierarchy used. \n + * \param coderate coderate used. \n + * \param bsize block size. + */ + static sptr make(dvb_constellation_t constellation, \ + dvbt_hierarchy_t hierarchy, dvb_code_rate_t coderate, int bsize); + }; + + } // namespace dtv +} // namespace gr + +#endif /* INCLUDED_DTV_DVBT_VITERBI_DECODER_H */ + diff --git a/gr-dtv/lib/CMakeLists.txt b/gr-dtv/lib/CMakeLists.txt index f2128e9a83..f0444692f4 100644 --- a/gr-dtv/lib/CMakeLists.txt +++ b/gr-dtv/lib/CMakeLists.txt @@ -104,6 +104,14 @@ list(APPEND dtv_sources dvbt/dvbt_symbol_inner_interleaver_impl.cc dvbt/dvbt_map_impl.cc dvbt/dvbt_reference_signals_impl.cc + dvbt/dvbt_ofdm_sym_acquisition_impl.cc + dvbt/dvbt_demod_reference_signals_impl.cc + dvbt/dvbt_demap_impl.cc + dvbt/dvbt_bit_inner_deinterleaver_impl.cc + dvbt/dvbt_viterbi_decoder_impl.cc + dvbt/dvbt_convolutional_deinterleaver_impl.cc + dvbt/dvbt_reed_solomon_dec_impl.cc + dvbt/dvbt_energy_descramble_impl.cc ) if(ENABLE_GR_CTRLPORT) @@ -119,6 +127,8 @@ list(APPEND dtv_libs ${VOLK_LIBRARIES} ) +set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -msse2") + #Add Windows DLL resource file if using MSVC if(MSVC) include(${CMAKE_SOURCE_DIR}/cmake/Modules/GrVersion.cmake) diff --git a/gr-dtv/lib/dvbt/dvbt_bit_inner_deinterleaver_impl.cc b/gr-dtv/lib/dvbt/dvbt_bit_inner_deinterleaver_impl.cc new file mode 100644 index 0000000000..bf7613adae --- /dev/null +++ b/gr-dtv/lib/dvbt/dvbt_bit_inner_deinterleaver_impl.cc @@ -0,0 +1,191 @@ +/* -*- c++ -*- */ +/* + * Copyright 2015 Free Software Foundation, Inc. + * + * This is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3, or (at your option) + * any later version. + * + * This software is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this software; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, + * Boston, MA 02110-1301, USA. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include <gnuradio/io_signature.h> +#include "dvbt_bit_inner_deinterleaver_impl.h" +#include <stdio.h> + +namespace gr { + namespace dtv { + + const int dvbt_bit_inner_deinterleaver_impl::d_bsize = 126; + + int + dvbt_bit_inner_deinterleaver_impl::H(int e, int w) + { + int rez = 0; + + switch (e) { + case 0: + rez = w; + break; + case 1: + rez = (w + 63) % d_bsize; + break; + case 2: + rez = (w + 105) % d_bsize; + break; + case 3: + rez = (w + 42) % d_bsize; + break; + case 4: + rez = (w + 21) % d_bsize; + break; + case 5: + rez = (w + 84) % d_bsize; + break; + default: + break; + } + + return rez; + } + + dvbt_bit_inner_deinterleaver::sptr + dvbt_bit_inner_deinterleaver::make(int nsize, \ + dvb_constellation_t constellation, dvbt_hierarchy_t hierarchy, dvbt_transmission_mode_t transmission) + { + return gnuradio::get_initial_sptr + (new dvbt_bit_inner_deinterleaver_impl(nsize, constellation, hierarchy, transmission)); + } + + /* + * The private constructor + */ + dvbt_bit_inner_deinterleaver_impl::dvbt_bit_inner_deinterleaver_impl(int nsize, dvb_constellation_t constellation, \ + dvbt_hierarchy_t hierarchy, dvbt_transmission_mode_t transmission) + : block("dvbt_bit_inner_deinterleaver", + io_signature::make(1, 1, sizeof (unsigned char) * nsize), + io_signature::make(1, 2, sizeof (unsigned char) * nsize)), + config(constellation, hierarchy, gr::dtv::C1_2, gr::dtv::C1_2, gr::dtv::GI_1_32, transmission), + d_nsize(nsize), + d_hierarchy(hierarchy) + { + d_v = config.d_m; + d_hierarchy = config.d_hierarchy; + + d_perm = (unsigned char *)new unsigned char[d_v * d_bsize]; + if (d_perm == NULL) { + std::cout << "Cannot allocate memory for d_perm" << std::endl; + exit(1); + } + + //Init permutation table (used for b[e][do]) + for (int i = 0; i < d_bsize * d_v; i++) { + if (d_hierarchy == NH) { + d_perm[i] = ((i % d_v) / (d_v / 2)) + 2 * (i % (d_v / 2)); + } + else { + d_perm[i] = (i % (d_v - 2)) / ((d_v - 2) / 2) + 2 * (i % ((d_v - 2) / 2)) + 2; + } + } + + if (d_nsize % d_bsize) { + std::cout << "Error: Input size must be multiple of block size: " \ + << "nsize: " << d_nsize << "bsize: " << d_bsize << std::endl; + } + } + + /* + * Our virtual destructor. + */ + dvbt_bit_inner_deinterleaver_impl::~dvbt_bit_inner_deinterleaver_impl() + { + delete [] d_perm; + } + + void + dvbt_bit_inner_deinterleaver_impl::forecast (int noutput_items, gr_vector_int &ninput_items_required) + { + ninput_items_required[0] = noutput_items; + } + + int + dvbt_bit_inner_deinterleaver_impl::general_work (int noutput_items, + gr_vector_int &ninput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items) + { + const unsigned char *in = (const unsigned char *) input_items[0]; + unsigned char *outh = (unsigned char *) output_items[0]; + unsigned char *outl = (unsigned char *) output_items[1]; + + int bmax = noutput_items * d_nsize / d_bsize; + + // First index of d_b is Bit interleaver number + // Second index of d_b is the position inside Bit interleaver + unsigned char d_b[d_v][d_bsize]; + + for (int bcount = 0; bcount < bmax; bcount++) { + for (int w = 0; w < d_bsize; w++) { + int c = in[(bcount * d_bsize) + w]; + + for (int e = 0; e < d_v; e++) { + d_b[e][H(e, w)] = (c >> (d_v - e - 1)) & 1; + } + } + + for (int i = 0; i < d_bsize; i++) { + if (d_hierarchy == NH) { + // Create output from demultiplexer + int c = 0; + + for (int k = 0; k < d_v; k++) { + c = (c << 1) | d_b[d_perm[(d_v * i) + k]][i]; + } + + outh[(bcount * d_bsize) + i] = c; + } + else { + int c = 0; + + // High priority output - first 2 streams + for (int k = 0; k < 2; k++) { + c = (c << 1) | d_b[(d_v * i + k) % 2][(d_v * i + k) / 2]; + } + + outh[(bcount * d_bsize) + i] = c; + + c = 0; + // Low priority output - (v - 2) streams + for (int k = 2; k < (d_v - 2); k++) { + c = (c << 1) | d_b[d_perm[d_v * i + k]][(d_v * i + k) / (d_v - 2)]; + } + + outl[(bcount * d_bsize) + i] = c; + } + } + } + + // Tell runtime system how many input items we consumed on + // each input stream. + consume_each (noutput_items); + + // Tell runtime system how many output items we produced. + return noutput_items; + } + + } /* namespace dtv */ +} /* namespace gr */ + diff --git a/gr-dtv/lib/dvbt/dvbt_bit_inner_deinterleaver_impl.h b/gr-dtv/lib/dvbt/dvbt_bit_inner_deinterleaver_impl.h new file mode 100644 index 0000000000..9f3811301d --- /dev/null +++ b/gr-dtv/lib/dvbt/dvbt_bit_inner_deinterleaver_impl.h @@ -0,0 +1,65 @@ +/* -*- c++ -*- */ +/* + * Copyright 2015 Free Software Foundation, Inc. + * + * This is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3, or (at your option) + * any later version. + * + * This software is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this software; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, + * Boston, MA 02110-1301, USA. + */ + +#ifndef INCLUDED_DTV_DVBT_BIT_INNER_DEINTERLEVER_IMPL_H +#define INCLUDED_DTV_DVBT_BIT_INNER_DEINTERLEVER_IMPL_H + +#include <gnuradio/dtv/dvbt_bit_inner_deinterleaver.h> +#include "dvbt_configure.h" + +namespace gr { + namespace dtv { + + class dvbt_bit_inner_deinterleaver_impl : public dvbt_bit_inner_deinterleaver + { + private: + const dvbt_configure config; + + int d_nsize; + dvbt_hierarchy_t d_hierarchy; + + // constellation + int d_v; + // Bit interleaver block size + static const int d_bsize; + + // Table to keep interleaved indices + unsigned char * d_perm; + + // Permutation function + int H(int e, int w); + + public: + dvbt_bit_inner_deinterleaver_impl(int nsize, dvb_constellation_t constellation, dvbt_hierarchy_t hierarchy, dvbt_transmission_mode_t transmission); + ~dvbt_bit_inner_deinterleaver_impl(); + + 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); + }; + + } // namespace dtv +} // namespace gr + +#endif /* INCLUDED_DTV_DVBT_BIT_INNER_DEINTERLEVER_IMPL_H */ + diff --git a/gr-dtv/lib/dvbt/dvbt_convolutional_deinterleaver_impl.cc b/gr-dtv/lib/dvbt/dvbt_convolutional_deinterleaver_impl.cc new file mode 100644 index 0000000000..0358ada1ff --- /dev/null +++ b/gr-dtv/lib/dvbt/dvbt_convolutional_deinterleaver_impl.cc @@ -0,0 +1,137 @@ +/* -*- c++ -*- */ +/* + * Copyright 2015 Free Software Foundation, Inc. + * + * This is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3, or (at your option) + * any later version. + * + * This software is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this software; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, + * Boston, MA 02110-1301, USA. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include <gnuradio/io_signature.h> +#include "dvbt_convolutional_deinterleaver_impl.h" + +namespace gr { + namespace dtv { + + const int dvbt_convolutional_deinterleaver_impl::d_SYNC = 0x47; + const int dvbt_convolutional_deinterleaver_impl::d_NSYNC = 0xB8; + const int dvbt_convolutional_deinterleaver_impl::d_MUX_PKT = 8; + + dvbt_convolutional_deinterleaver::sptr + dvbt_convolutional_deinterleaver::make(int nsize, int I, int M) + { + return gnuradio::get_initial_sptr + (new dvbt_convolutional_deinterleaver_impl(nsize, I, M)); + } + + /* + * The private constructor + */ + dvbt_convolutional_deinterleaver_impl::dvbt_convolutional_deinterleaver_impl(int blocks, int I, int M) + : block("dvbt_convolutional_deinterleaver", + io_signature::make(1, 1, sizeof (unsigned char)), + io_signature::make(1, 1, sizeof (unsigned char) * I * blocks)), + d_blocks(blocks), d_I(I), d_M(M) + { + set_relative_rate(1.0 / d_I * d_blocks); + set_output_multiple(2); + //The positions are shift registers (FIFOs) + //of length i*M + for (int i = (d_I - 1); i >= 0; i--) { + d_shift.push_back(new std::deque<unsigned char>(d_M * i, 0)); + } + + // There are 8 mux packets + assert(d_blocks / d_M == d_MUX_PKT); + } + + /* + * Our virtual destructor. + */ + dvbt_convolutional_deinterleaver_impl::~dvbt_convolutional_deinterleaver_impl() + { + for (unsigned int i = 0; i < d_shift.size(); i++) { + delete d_shift.back(); + d_shift.pop_back(); + } + } + + void + dvbt_convolutional_deinterleaver_impl::forecast (int noutput_items, gr_vector_int &ninput_items_required) + { + int ninputs = ninput_items_required.size (); + + for (int i = 0; i < ninputs; i++) { + ninput_items_required[i] = noutput_items * d_I * d_blocks; + } + } + + + int + dvbt_convolutional_deinterleaver_impl::general_work(int noutput_items, + gr_vector_int &ninput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items) + { + const unsigned char *in = (const unsigned char *) input_items[0]; + unsigned char *out = (unsigned char *) output_items[0]; + + int to_out = noutput_items; + + /* + * Look for a tag that signals superframe_start and consume all input items + * that are in input buffer so far. + * This will actually reset the convolutional deinterleaver + */ + std::vector<tag_t> tags; + const uint64_t nread = this->nitems_read(0); //number of items read on port 0 + this->get_tags_in_range(tags, 0, nread, nread + (noutput_items * d_I * d_blocks), pmt::string_to_symbol("superframe_start")); + + if (tags.size()) { + if (tags[0].offset - nread) { + consume_each(tags[0].offset - nread); + return (0); + } + } + + /* + * At this moment the first item in input buffer should be NSYNC or SYNC + */ + + for (int count = 0, i = 0; i < to_out; i++) { + for (int mux_pkt = 0; mux_pkt < d_MUX_PKT; mux_pkt++) { + // This is actually the deinterleaver + for (int k = 0; k < (d_M * d_I); k++) { + d_shift[k % d_I]->push_back(in[count]); + out[count++] = d_shift[k % d_I]->front(); + d_shift[k % d_I]->pop_front(); + } + } + } + + // Tell runtime system how many input items we consumed on + // each input stream. + consume_each(d_I * d_blocks * to_out); + + // Tell runtime system how many output items we produced. + return (to_out); + } + + } /* namespace dtv */ +} /* namespace gr */ + diff --git a/gr-dtv/lib/dvbt/dvbt_convolutional_deinterleaver_impl.h b/gr-dtv/lib/dvbt/dvbt_convolutional_deinterleaver_impl.h new file mode 100644 index 0000000000..7b3fafecad --- /dev/null +++ b/gr-dtv/lib/dvbt/dvbt_convolutional_deinterleaver_impl.h @@ -0,0 +1,57 @@ +/* -*- c++ -*- */ +/* + * Copyright 2015 Free Software Foundation, Inc. + * + * This is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3, or (at your option) + * any later version. + * + * This software is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this software; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, + * Boston, MA 02110-1301, USA. + */ + +#ifndef INCLUDED_DTV_DVBT_CONVOLUTIONAL_DEINTERLEAVER_IMPL_H +#define INCLUDED_DTV_DVBT_CONVOLUTIONAL_DEINTERLEAVER_IMPL_H + +#include <gnuradio/dtv/dvbt_convolutional_deinterleaver.h> + +namespace gr { + namespace dtv { + + class dvbt_convolutional_deinterleaver_impl : public dvbt_convolutional_deinterleaver + { + private: + static const int d_SYNC; + static const int d_NSYNC; + static const int d_MUX_PKT; + + int d_blocks; + int d_I; + int d_M; + std::vector< std::deque<unsigned char> * > d_shift; + + public: + dvbt_convolutional_deinterleaver_impl(int nsize, int I, int M); + ~dvbt_convolutional_deinterleaver_impl(); + + 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); + }; + + } // namespace dtv +} // namespace gr + +#endif /* INCLUDED_DTV_DVBT_CONVOLUTIONAL_DEINTERLEAVER_IMPL_H */ + diff --git a/gr-dtv/lib/dvbt/dvbt_demap_impl.cc b/gr-dtv/lib/dvbt/dvbt_demap_impl.cc new file mode 100644 index 0000000000..4bdec1dc96 --- /dev/null +++ b/gr-dtv/lib/dvbt/dvbt_demap_impl.cc @@ -0,0 +1,185 @@ +/* -*- c++ -*- */ +/* + * Copyright 2015 Free Software Foundation, Inc. + * + * This is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3, or (at your option) + * any later version. + * + * This software is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this software; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, + * Boston, MA 02110-1301, USA. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include <gnuradio/io_signature.h> +#include "dvbt_demap_impl.h" +#include <volk/volk.h> +#include <stdio.h> + +namespace gr { + namespace dtv { + + dvbt_demap::sptr + dvbt_demap::make(int nsize, dvb_constellation_t constellation, dvbt_hierarchy_t hierarchy, \ + dvbt_transmission_mode_t transmission, float gain) + { + return gnuradio::get_initial_sptr + (new dvbt_demap_impl(nsize, constellation, hierarchy, transmission, gain)); + } + + /* + * The private constructor + */ + dvbt_demap_impl::dvbt_demap_impl(int nsize, dvb_constellation_t constellation, dvbt_hierarchy_t hierarchy, \ + dvbt_transmission_mode_t transmission, float gain) + : block("dvbt_demap", + io_signature::make(1, 1, sizeof (gr_complex) * nsize), + io_signature::make(1, 1, sizeof (unsigned char) * nsize)), + config(constellation, hierarchy, gr::dtv::C1_2, gr::dtv::C1_2, gr::dtv::GI_1_32, transmission), + d_nsize(nsize), + d_constellation_size(0), + d_step(0), + d_alpha(0), + d_gain(0.0) + { + //Get parameters from config object + d_constellation_size = config.d_constellation_size; + d_transmission_mode = config.d_transmission_mode; + d_step = config.d_step; + d_alpha = config.d_alpha; + d_gain = gain * config.d_norm; + + d_constellation_points = (gr_complex*) volk_malloc(sizeof(gr_complex) * d_constellation_size, volk_get_alignment()); + if (d_constellation_points == NULL) { + std::cout << "cannot allocate memory for d_constellation_points" << std::endl; + exit(1); + } + + d_sq_dist = (float*) volk_malloc(sizeof(float) * d_constellation_size, volk_get_alignment()); + if (d_sq_dist == NULL) { + std::cout << "cannot allocate memory for d_sq_dist" << std::endl; + volk_free(d_constellation_points); + exit(1); + } + + make_constellation_points(d_constellation_size, d_step, d_alpha); + } + + /* + * Our virtual destructor. + */ + dvbt_demap_impl::~dvbt_demap_impl() + { + volk_free(d_sq_dist); + volk_free(d_constellation_points); + } + + void + dvbt_demap_impl::make_constellation_points(int size, int step, int alpha) + { + // The symmetry of the constellation is used to calculate + // 16QAM from QPSK and 64QAM from 16QAM + + int bits_per_axis = log2(size) / 2; + int steps_per_axis = sqrt(size) / 2 - 1; + + for (int i = 0; i < size; i++) { + // This is the quadrant made of the first two bits starting from MSB + int q = i >> (2 * (bits_per_axis - 1)) & 3; + // Sign for correct calculation of I and Q in each quadrant + int sign0 = (q >> 1) ? -1 : 1; int sign1 = (q & 1) ? -1 : 1; + + int x = (i >> (bits_per_axis - 1)) & ((1 << (bits_per_axis - 1)) - 1); + int y = i & ((1 << (bits_per_axis - 1)) - 1); + + int xval = alpha + (steps_per_axis - x) * step; + int yval = alpha + (steps_per_axis - y) * step; + + int val = (bin_to_gray(x) << (bits_per_axis - 1)) + bin_to_gray(y); + + // ETSI EN 300 744 Clause 4.3.5 + // Actually the constellation is gray coded + // but the bits on each axis are not taken in consecutive order + // So we need to convert from b0b2b4b1b3b5->b0b1b2b3b4b5(64QAM) + + x = 0; y = 0; + + for (int j = 0; j < (bits_per_axis - 1); j++) { + x += ((val >> (1 + 2 * j)) & 1) << j; + y += ((val >> (2 * j)) & 1) << j; + } + + val = (q << 2 * (bits_per_axis - 1)) + (x << (bits_per_axis - 1)) + y; + + // Keep corresponding symbol bits->complex symbol in one vector + // Normalize the signal using gain + d_constellation_points[val] = d_gain * gr_complex(sign0 * xval, sign1 * yval); + } + } + + int + dvbt_demap_impl::find_constellation_value(gr_complex val) + { + float min_dist = std::norm(val - d_constellation_points[0]); + int min_index = 0; + + volk_32fc_x2_square_dist_32f(&d_sq_dist[0], &val, &d_constellation_points[0], d_constellation_size); + + for (int i = 0; i < d_constellation_size; i++) { + if (d_sq_dist[i] < min_dist) { + min_dist = d_sq_dist[i]; + min_index = i; + } + } + + //return d_constellation_bits[min_index]; + return min_index; + } + + int + dvbt_demap_impl::bin_to_gray(int val) + { + return (val >> 1) ^ val; + } + + void + dvbt_demap_impl::forecast (int noutput_items, gr_vector_int &ninput_items_required) + { + ninput_items_required[0] = noutput_items; + } + + int + dvbt_demap_impl::general_work (int noutput_items, + gr_vector_int &ninput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items) + { + const gr_complex *in = (const gr_complex *) input_items[0]; + unsigned char *out = (unsigned char *) output_items[0]; + + // TODO - use DFE (Decision Feedback Equalizer) + + for (int i = 0; i < (noutput_items * d_nsize); i++) { + out[i] = find_constellation_value(in[i]); + } + + consume_each (noutput_items); + + // Tell runtime system how many output items we produced. + return noutput_items; + } + + } /* namespace dtv */ +} /* namespace gr */ + diff --git a/gr-dtv/lib/dvbt/dvbt_demap_impl.h b/gr-dtv/lib/dvbt/dvbt_demap_impl.h new file mode 100644 index 0000000000..020578b1b5 --- /dev/null +++ b/gr-dtv/lib/dvbt/dvbt_demap_impl.h @@ -0,0 +1,71 @@ +/* -*- c++ -*- */ +/* + * Copyright 2015 Free Software Foundation, Inc. + * + * This is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3, or (at your option) + * any later version. + * + * This software is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this software; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, + * Boston, MA 02110-1301, USA. + */ + +#ifndef INCLUDED_DTV_DVBT_DVBT_DEMAP_IMPL_H +#define INCLUDED_DTV_DVBT_DVBT_DEMAP_IMPL_H + +#include <gnuradio/dtv/dvbt_demap.h> +#include "dvbt_configure.h" + +namespace gr { + namespace dtv { + + class dvbt_demap_impl : public dvbt_demap + { + private: + const dvbt_configure config; + + int d_nsize; + + //Constellation size + unsigned char d_constellation_size; + //Transmission mode + dvbt_transmission_mode_t d_transmission_mode; + //Step on each axis of the constellation + unsigned char d_step; + //Keep Alpha internally + unsigned char d_alpha; + //Gain for the complex values + float d_gain; + + gr_complex * d_constellation_points; + float * d_sq_dist; + + void make_constellation_points(int size, int step, int alpha); + int find_constellation_value(gr_complex val); + int bin_to_gray(int val); + + public: + dvbt_demap_impl(int nsize, dvb_constellation_t constellation, dvbt_hierarchy_t hierarchy, dvbt_transmission_mode_t transmission, float gain); + ~dvbt_demap_impl(); + + 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); + }; + + } // namespace dtv +} // namespace gr + +#endif /* INCLUDED_DTV_DVBT_DVBT_DEMAP_IMPL_H */ + diff --git a/gr-dtv/lib/dvbt/dvbt_demod_reference_signals_impl.cc b/gr-dtv/lib/dvbt/dvbt_demod_reference_signals_impl.cc new file mode 100644 index 0000000000..e9ee86436b --- /dev/null +++ b/gr-dtv/lib/dvbt/dvbt_demod_reference_signals_impl.cc @@ -0,0 +1,152 @@ +/* -*- c++ -*- */ +/* + * Copyright 2015 Free Software Foundation, Inc. + * + * This is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3, or (at your option) + * any later version. + * + * This software is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this software; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, + * Boston, MA 02110-1301, USA. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include <gnuradio/io_signature.h> +#include "dvbt_demod_reference_signals_impl.h" + +namespace gr { + namespace dtv { + + dvbt_demod_reference_signals::sptr + dvbt_demod_reference_signals::make(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, \ + int include_cell_id, int cell_id) + { + return gnuradio::get_initial_sptr + (new dvbt_demod_reference_signals_impl(itemsize, ninput, \ + noutput, constellation, hierarchy, code_rate_HP, code_rate_LP, \ + guard_interval, transmission_mode, include_cell_id, cell_id)); + } + + /* + * The private constructor + */ + dvbt_demod_reference_signals_impl::dvbt_demod_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, int include_cell_id, int cell_id) + : block("dvbt_demod_reference_signals", + io_signature::make(1, 1, itemsize * ninput), + io_signature::make(1, 1, itemsize * noutput)), + config(constellation, hierarchy, code_rate_HP, code_rate_LP, \ + guard_interval, transmission_mode, include_cell_id, cell_id), + d_pg(config), + d_init(0), + d_fi_start(0) + { + d_ninput = ninput; + d_noutput = noutput; + + // TODO - investigate why this is happening + if ((config.d_constellation == MOD_64QAM) && (config.d_transmission_mode == T8k)) + d_fi_start = 2; + else + d_fi_start = 3; + } + + /* + * Our virtual destructor. + */ + dvbt_demod_reference_signals_impl::~dvbt_demod_reference_signals_impl() + { + } + + void + dvbt_demod_reference_signals_impl::forecast (int noutput_items, gr_vector_int &ninput_items_required) + { + int ninputs = ninput_items_required.size(); + + for (int i = 0; i < ninputs; i++) + ninput_items_required[i] = 2 * noutput_items; + } + + int + dvbt_demod_reference_signals_impl::is_sync_start(int nitems) + { + std::vector<tag_t> tags; + const uint64_t nread = this->nitems_read(0); //number of items read on port 0 + this->get_tags_in_range(tags, 0, nread, nread + nitems, pmt::string_to_symbol("sync_start")); + + return tags.size() ? 1 : 0; + } + + int + dvbt_demod_reference_signals_impl::general_work (int noutput_items, + gr_vector_int &ninput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items) + { + const gr_complex *in = (const gr_complex *) input_items[0]; + gr_complex *out = (gr_complex *) output_items[0]; + + int symbol_index, frame_index; + int to_out = 0; + + for (int i = 0; i < noutput_items; i++) { + to_out += d_pg.parse_input(&in[i * d_ninput], &out[i * d_noutput], &symbol_index, &frame_index); + } + + /* + * Wait for a sync_start tag from upstream that signals when to start. + * Allways consume until to a superframe start. + */ + if (is_sync_start(noutput_items)) { + d_init = 0; + } + + if (d_init == 0) { + // This is super-frame start + if (((symbol_index % 68) == 0) && ((frame_index % 4) == d_fi_start)) { + d_init = 1; + + const uint64_t offset = this->nitems_written(0); + pmt::pmt_t key = pmt::string_to_symbol("superframe_start"); + pmt::pmt_t value = pmt::from_long(0xaa); + this->add_item_tag(0, offset, key, value); + } + else { + consume_each(1); + return (0); + } + } + + // Send a tag for each OFDM symbol informing about + // symbol index. + const uint64_t offset = this->nitems_written(0); + pmt::pmt_t key = pmt::string_to_symbol("symbol_index"); + pmt::pmt_t value = pmt::from_long(symbol_index); + this->add_item_tag(0, offset, key, value); + + // Consume from input stream + consume_each (noutput_items); + + // Tell runtime system how many output items we produced. + return to_out; + } + + } /* namespace dtv */ +} /* namespace gr */ + diff --git a/gr-dtv/lib/dvbt/dvbt_demod_reference_signals_impl.h b/gr-dtv/lib/dvbt/dvbt_demod_reference_signals_impl.h new file mode 100644 index 0000000000..1c7f5fde30 --- /dev/null +++ b/gr-dtv/lib/dvbt/dvbt_demod_reference_signals_impl.h @@ -0,0 +1,68 @@ +/* -*- c++ -*- */ +/* + * Copyright 2015 Free Software Foundation, Inc. + * + * This is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3, or (at your option) + * any later version. + * + * This software is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this software; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, + * Boston, MA 02110-1301, USA. + */ + +#ifndef INCLUDED_DTV_DVBT_DEMOD_REFERENCE_SIGNALS_IMPL_H +#define INCLUDED_DTV_DVBT_DEMOD_REFERENCE_SIGNALS_IMPL_H + +#include <gnuradio/dtv/dvbt_demod_reference_signals.h> +#include "dvbt_reference_signals_impl.h" + +namespace gr { + namespace dtv { + + class dvbt_demod_reference_signals_impl : public dvbt_demod_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; + + int d_init; + int d_fi_start; + + int is_sync_start(int nitems); + + public: + dvbt_demod_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_demod_reference_signals_impl(); + + 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); + }; + + } // namespace dtv +} // namespace gr + +#endif /* INCLUDED_DTV_DVBT_DEMOD_REFERENCE_SIGNALS_IMPL_H */ + diff --git a/gr-dtv/lib/dvbt/dvbt_energy_descramble_impl.cc b/gr-dtv/lib/dvbt/dvbt_energy_descramble_impl.cc new file mode 100644 index 0000000000..6b47814f8c --- /dev/null +++ b/gr-dtv/lib/dvbt/dvbt_energy_descramble_impl.cc @@ -0,0 +1,156 @@ +/* -*- c++ -*- */ +/* + * Copyright 2015 Free Software Foundation, Inc. + * + * This is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3, or (at your option) + * any later version. + * + * This software is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this software; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, + * Boston, MA 02110-1301, USA. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include <gnuradio/io_signature.h> +#include "dvbt_energy_descramble_impl.h" + +namespace gr { + namespace dtv { + + const int dvbt_energy_descramble_impl::d_nblocks = 8; + const int dvbt_energy_descramble_impl::d_bsize = 188; + const int dvbt_energy_descramble_impl::d_SYNC = 0x47; + const int dvbt_energy_descramble_impl::d_NSYNC = 0xB8; + const int dvbt_energy_descramble_impl::d_MUX_PKT = 8; + + void + dvbt_energy_descramble_impl::init_prbs() + { + d_reg = 0xa9; + } + + int + dvbt_energy_descramble_impl::clock_prbs(int clocks) + { + int res = 0; + int feedback = 0; + + for(int i = 0; i < clocks; i++) { + feedback = ((d_reg >> (14 - 1)) ^ (d_reg >> (15 - 1))) & 0x1; + d_reg = ((d_reg << 1) | feedback) & 0x7fff; + + res = (res << 1) | feedback; + } + + return res; + } + + dvbt_energy_descramble::sptr + dvbt_energy_descramble::make(int nblocks) + { + return gnuradio::get_initial_sptr + (new dvbt_energy_descramble_impl(nblocks)); + } + + /* + * The private constructor + */ + dvbt_energy_descramble_impl::dvbt_energy_descramble_impl(int nblocks) + : block("dvbt_energy_descramble", + io_signature::make(1, 1, sizeof (unsigned char) * d_nblocks * d_bsize), + io_signature::make(1, 1, sizeof (unsigned char))), + d_reg(0xa9), d_index(0), d_search(0) + { + set_relative_rate((double) (d_nblocks * d_bsize)); + + // Set output multiple of (2 search + 1 data = 3) at least (4 for now) + set_output_multiple(4 * d_nblocks * d_bsize); + + // Search interval for NSYNC is 2 * 8 * MUX size + d_search = 2 * (d_nblocks * d_bsize); + } + + /* + * Our virtual destructor. + */ + dvbt_energy_descramble_impl::~dvbt_energy_descramble_impl() + { + } + + void + dvbt_energy_descramble_impl::forecast (int noutput_items, gr_vector_int &ninput_items_required) + { + ninput_items_required[0] = 4 * (noutput_items / (d_nblocks * d_bsize)); + } + + int + dvbt_energy_descramble_impl::general_work (int noutput_items, + gr_vector_int &ninput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items) + { + const unsigned char *in = (const unsigned char *) input_items[0]; + unsigned char *out = (unsigned char *) output_items[0]; + + int to_consume, to_out; + + // Search for a NSYNC + while ((in[d_index] != d_NSYNC) && (d_index < d_search)) { + d_index += d_bsize; + } + + /* + * If we did not find a NSYNC then just consume + * and return 0. + */ + if (d_index >= d_search) { + d_index = 0; + to_consume = 2; + to_out = 0; + } + else { + // We found a NSYNC, descramble the data + + to_consume = (noutput_items / (d_nblocks * d_bsize)) - 2; + to_out = noutput_items - 2 * (d_nblocks * d_bsize); + + for (int count = 0, i = 0; i < to_consume; i++) { + init_prbs(); + + for (int mux_pkt = 0; mux_pkt < d_MUX_PKT; mux_pkt++) { + out[count++] = d_SYNC; + // PRBS clocking starts right after NSYNC + + for (int k = 1; k < d_bsize; k++) { + out[count] = in[d_index + count] ^ clock_prbs(d_nblocks); + count++; + } + + // For subsequent blocks PRBS is clocked also on SYNC + // but its output is not used + clock_prbs(d_nblocks); + } + } + } + + // Tell runtime how many input items we consumed + consume_each(to_consume); + + // Tell runtime system how many output items we produced. + return (to_out); + } + + } /* namespace dtv */ +} /* namespace gr */ + diff --git a/gr-dtv/lib/dvbt/dvbt_energy_descramble_impl.h b/gr-dtv/lib/dvbt/dvbt_energy_descramble_impl.h new file mode 100644 index 0000000000..8681732016 --- /dev/null +++ b/gr-dtv/lib/dvbt/dvbt_energy_descramble_impl.h @@ -0,0 +1,65 @@ +/* -*- c++ -*- */ +/* + * Copyright 2015 Free Software Foundation, Inc. + * + * This is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3, or (at your option) + * any later version. + * + * This software is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this software; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, + * Boston, MA 02110-1301, USA. + */ + +#ifndef INCLUDED_DTV_DVBT_ENERGY_DESCRAMBLE_IMPL_H +#define INCLUDED_DTV_DVBT_ENERGY_DESCRAMBLE_IMPL_H + +#include <gnuradio/dtv/dvbt_energy_descramble.h> + +namespace gr { + namespace dtv { + + class dvbt_energy_descramble_impl : public dvbt_energy_descramble + { + private: + static const int d_nblocks; + static const int d_bsize; + static const int d_SYNC; + static const int d_NSYNC; + static const int d_MUX_PKT; + + // Register for PRBS + int d_reg; + + // Index + int d_index; + // Search interval + int d_search; + + void init_prbs(); + int clock_prbs(int clocks); + + public: + dvbt_energy_descramble_impl(int nblocks); + ~dvbt_energy_descramble_impl(); + + 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); + }; + + } // namespace dtv +} // namespace gr + +#endif /* INCLUDED_DTV_DVBT_ENERGY_DESCRAMBLE_IMPL_H */ + diff --git a/gr-dtv/lib/dvbt/dvbt_ofdm_sym_acquisition_impl.cc b/gr-dtv/lib/dvbt/dvbt_ofdm_sym_acquisition_impl.cc new file mode 100644 index 0000000000..2383c54fbc --- /dev/null +++ b/gr-dtv/lib/dvbt/dvbt_ofdm_sym_acquisition_impl.cc @@ -0,0 +1,417 @@ +/* -*- c++ -*- */ +/* + * Copyright 2015 Free Software Foundation, Inc. + * + * This is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3, or (at your option) + * any later version. + * + * This software is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this software; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, + * Boston, MA 02110-1301, USA. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include <gnuradio/io_signature.h> +#include "dvbt_ofdm_sym_acquisition_impl.h" +#include <complex> +#include <gnuradio/math.h> +#include <gnuradio/expj.h> +#include <stdio.h> +#include <volk/volk.h> + +namespace gr { + namespace dtv { + + int + dvbt_ofdm_sym_acquisition_impl::peak_detect_init(float threshold_factor_rise, float threshold_factor_fall, int look_ahead, float alpha) + { + d_avg_alpha = alpha; + d_threshold_factor_rise = threshold_factor_rise; + d_threshold_factor_fall = threshold_factor_fall; + d_avg = 0; + + return (0); + } + + int + dvbt_ofdm_sym_acquisition_impl::peak_detect_process(const float * datain, const int datain_length, int * peak_pos, int * peak_max) + { + int state = 0; + float peak_val = -(float)INFINITY; int peak_index = 0; int peak_pos_length = 0; + + int i = 0; + + while(i < datain_length) { + if (state == 0) { + if (datain[i] > d_avg * d_threshold_factor_rise) { + state = 1; + } + else { + d_avg = d_avg_alpha * datain[i] + (1 - d_avg_alpha) * d_avg; + i++; + } + } + else if (state == 1) { + if (datain[i] > peak_val) { + peak_val = datain[i]; + peak_index = i; + d_avg = d_avg_alpha * datain[i] + (1 - d_avg_alpha) * d_avg; + i++; + } + else if (datain[i] > d_avg * d_threshold_factor_fall) { + d_avg = (d_avg_alpha) * datain[i] + (1 - d_avg_alpha) * d_avg; + i++; + } + else { + peak_pos[peak_pos_length] = peak_index; + peak_pos_length++; + state = 0; + peak_val = - (float)INFINITY; + } + } + } + + // Find peak of peaks + if (peak_pos_length) { + float max = datain[peak_pos[0]]; + int maxi = 0; + + for (int i = 1; i < peak_pos_length; i++) { + if (datain[peak_pos[i]] > max) { + max = datain[peak_pos[i]]; + maxi = i; + } + } + + *peak_max = maxi; + } + + return (peak_pos_length); + } + + int + dvbt_ofdm_sym_acquisition_impl::ml_sync(const gr_complex * in, int lookup_start, int lookup_stop, int * cp_pos, gr_complex * derot, int * to_consume, int * to_out) + { + assert(lookup_start >= lookup_stop); + assert(lookup_stop >= (d_cp_length + d_fft_length - 1)); + + int low, size; + + // Array to store peak positions + int peak_pos[d_fft_length]; + float d_phi[d_fft_length]; + + // Calculate norm + low = lookup_stop - (d_cp_length + d_fft_length - 1); + size = lookup_start - (lookup_stop - (d_cp_length + d_fft_length - 1)) + 1; + + volk_32fc_magnitude_squared_32f(&d_norm[low], &in[low], size); + + // Calculate gamma on each point +#ifdef SEGFAULT_FIX + low = lookup_stop - d_cp_length + 1; + size = lookup_start - (lookup_stop - d_cp_length + 1) + 1; +#else + low = lookup_stop - d_cp_length - 1; + size = lookup_start - (lookup_stop - d_cp_length - 1) + 1; +#endif + volk_32fc_x2_multiply_conjugate_32fc(&d_corr[low - d_fft_length], &in[low], &in[low - d_fft_length], size); + + // Calculate time delay and frequency correction + // This looks like spaghetti code but it is fast + for (int i = lookup_start - 1; i >= lookup_stop; i--) { + int k = i - lookup_stop; + + d_phi[k] = 0.0; + d_gamma[k] = 0.0; + + // Moving sum for calculating gamma and phi + for (int j = 0; j < d_cp_length; j++) { + // Calculate gamma and store it + d_gamma[k] += d_corr[i - j - d_fft_length]; + // Calculate phi and store it + d_phi[k] += d_norm[i - j] + d_norm[i - j - d_fft_length]; + } + } + + // Init lambda with gamma + low = 0; + size = lookup_start - lookup_stop; + + volk_32fc_magnitude_32f(&d_lambda[low], &d_gamma[low], size); + + // Calculate lambda + low = 0; + size = lookup_start - lookup_stop; + + volk_32f_s32f_multiply_32f(&d_phi[low], &d_phi[low], d_rho / 2.0, size); + volk_32f_x2_subtract_32f(&d_lambda[low], &d_lambda[low], &d_phi[low], size); + + int peak_length, peak, peak_max; + // Find peaks of lambda + // We have found an end of symbol at peak_pos[0] + CP + FFT + if ((peak_length = peak_detect_process(&d_lambda[0], (lookup_start - lookup_stop), &peak_pos[0], &peak_max))) { + peak = peak_pos[peak_max] + lookup_stop; + *cp_pos = peak; + + // Calculate frequency correction + float peak_epsilon = fast_atan2f(d_gamma[peak_pos[peak_max]]); + double sensitivity = (double)(-1) / (double)d_fft_length; + + // Store phases for derotating the signal + // We always process CP len + FFT len + for (int i = 0; i < (d_cp_length + d_fft_length); i++) { + if (i == d_nextpos) { + d_phaseinc = d_nextphaseinc; + } + + // We are interested only in fft_length + d_phase += d_phaseinc; + + while (d_phase > (float)M_PI) { + d_phase -= (float)(2.0 * M_PI); + } + while (d_phase < (float)(-M_PI)) { + d_phase += (float)(2.0 * M_PI); + } + + derot[i] = gr_expj(d_phase); + } + + d_nextphaseinc = sensitivity * peak_epsilon; + d_nextpos = peak - (d_cp_length + d_fft_length); + + *to_consume = d_cp_length + d_fft_length; + *to_out = 1; + } + else { + for (int i = 0; i < (d_cp_length + d_fft_length); i++) { + d_phase += d_phaseinc; + + while (d_phase > (float)M_PI) { + d_phase -= (float)(2.0 * M_PI); + } + while (d_phase < (float)(-M_PI)) { + d_phase += (float)(2.0 * M_PI); + } + } + + // We consume only fft_length + *to_consume = d_cp_length + d_fft_length; + *to_out = 0; + } + + return (peak_length); + } + + void + dvbt_ofdm_sym_acquisition_impl::send_sync_start() + { + const uint64_t offset = this->nitems_written(0); + pmt::pmt_t key = pmt::string_to_symbol("sync_start"); + pmt::pmt_t value = pmt::from_long(1); + this->add_item_tag(0, offset, key, value); + } + + dvbt_ofdm_sym_acquisition::sptr + dvbt_ofdm_sym_acquisition::make(int blocks, int fft_length, int occupied_tones, int cp_length, float snr) + { + return gnuradio::get_initial_sptr + (new dvbt_ofdm_sym_acquisition_impl(blocks, fft_length, occupied_tones, cp_length, snr)); + } + + /* + * The private constructor + */ + dvbt_ofdm_sym_acquisition_impl::dvbt_ofdm_sym_acquisition_impl(int blocks, int fft_length, int occupied_tones, int cp_length, float snr) + : block("dvbt_ofdm_sym_acquisition", + io_signature::make(1, 1, sizeof (gr_complex) * blocks), + io_signature::make(1, 1, sizeof (gr_complex) * blocks * fft_length)), + d_blocks(blocks), d_fft_length(fft_length), d_cp_length(cp_length), d_snr(snr), + d_index(0), d_phase(0.0), d_phaseinc(0.0), d_cp_found(0), d_count(0), d_nextphaseinc(0), d_nextpos(0), \ + d_sym_acq_count(0),d_sym_acq_timeout(100), d_initial_acquisition(0), \ + d_freq_correction_count(0), d_freq_correction_timeout(0) + { + set_relative_rate(1.0 / (double) (d_cp_length + d_fft_length)); + + d_snr = pow(10, d_snr / 10.0); + d_rho = d_snr / (d_snr + 1.0); + + d_gamma = (gr_complex*) volk_malloc(sizeof(gr_complex) * d_fft_length, volk_get_alignment()); + if (d_gamma == NULL) { + std::cout << "cannot allocate memory for d_gamma" << std::endl; + exit(1); + } + + d_lambda = (float*) volk_malloc(sizeof(float) * d_fft_length, volk_get_alignment()); + if (d_lambda == NULL) { + std::cout << "cannot allocate memory for d_lambda" << std::endl; + volk_free(d_gamma); + exit(1); + } + + d_derot = (gr_complex*) volk_malloc(sizeof(gr_complex) * (d_fft_length + d_cp_length), volk_get_alignment()); + if (d_derot == NULL) { + std::cout << "cannot allocate memory for d_derot" << std::endl; + volk_free(d_lambda); + volk_free(d_gamma); + exit(1); + } + + d_conj = (gr_complex*) volk_malloc(sizeof(gr_complex) * (2 * d_fft_length + d_cp_length), volk_get_alignment()); + if (d_conj == NULL) { + std::cout << "cannot allocate memory for d_conj" << std::endl; + volk_free(d_derot); + volk_free(d_lambda); + volk_free(d_gamma); + exit(1); + } + + d_norm = (float*) volk_malloc(sizeof(float) * (2 * d_fft_length + d_cp_length), volk_get_alignment()); + if (d_norm == NULL) { + std::cout << "cannot allocate memory for d_norm" << std::endl; + volk_free(d_conj); + volk_free(d_derot); + volk_free(d_lambda); + volk_free(d_gamma); + exit(1); + } + + d_corr = (gr_complex*) volk_malloc(sizeof(gr_complex) * (2 * d_fft_length + d_cp_length), volk_get_alignment()); + if (d_corr == NULL) { + std::cout << "cannot allocate memory for d_corr" << std::endl; + volk_free(d_norm); + volk_free(d_conj); + volk_free(d_derot); + volk_free(d_lambda); + volk_free(d_gamma); + exit(1); + } + + peak_detect_init(0.8, 0.9, 30, 0.9); + } + + /* + * Our virtual destructor. + */ + dvbt_ofdm_sym_acquisition_impl::~dvbt_ofdm_sym_acquisition_impl() + { + volk_free(d_corr); + volk_free(d_norm); + volk_free(d_conj); + volk_free(d_derot); + volk_free(d_lambda); + volk_free(d_gamma); + } + + void + dvbt_ofdm_sym_acquisition_impl::forecast (int noutput_items, gr_vector_int &ninput_items_required) + { + int ninputs = ninput_items_required.size(); + + // make sure we receive at least (symbol_length + fft_length) + for (int i = 0; i < ninputs; i++) { + ninput_items_required[i] = (2 * d_fft_length + d_cp_length) * noutput_items; + } + } + + /* + * ML Estimation of Time and Frequency Offset in OFDM systems + * Jan-Jaap van de Beek + */ + + int + dvbt_ofdm_sym_acquisition_impl::general_work (int noutput_items, + gr_vector_int &ninput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items) + { + const gr_complex *in = (const gr_complex *) input_items[0]; + gr_complex *out = (gr_complex *) output_items[0]; + + int low, size; + + // This is initial acquisition of symbol start + // TODO - make a FSM + if (!d_initial_acquisition) { + d_initial_acquisition = ml_sync(in, 2 * d_fft_length + d_cp_length - 1, d_fft_length + d_cp_length - 1, \ + &d_cp_start, &d_derot[0], &d_to_consume, &d_to_out); + +#ifdef SEGFAULT_FIX + d_cp_start_initial = d_cp_start; + d_cp_start_slip = 0; +#endif + // Send sync_start downstream + send_sync_start(); + } + + // This is fractional frequency correction (pre FFT) + // It is also called coarse frequency correction + if (d_initial_acquisition) { +#ifdef SEGFAULT_FIX + d_cp_found = ml_sync(in, d_cp_start + 16, d_cp_start, \ + &d_cp_start, &d_derot[0], &d_to_consume, &d_to_out); +#else + d_cp_found = ml_sync(in, d_cp_start + 8, d_cp_start - 8, \ + &d_cp_start, &d_derot[0], &d_to_consume, &d_to_out); +#endif + + if (d_cp_found) { + d_freq_correction_count = 0; + +#ifdef SEGFAULT_FIX + // detect and ignore false peaks + if (d_cp_start != d_cp_start_initial) { + d_cp_start_slip++; + if (d_cp_start_slip == 2) { + d_cp_start_slip = 0; + } + else { + d_cp_start = d_cp_start_initial; + } + } + else { + d_cp_start_slip = 0; + } +#endif + + // Derotate the signal and out + low = d_cp_start - d_fft_length + 1; + size = d_cp_start - (d_cp_start - d_fft_length + 1) + 1; + + volk_32fc_x2_multiply_32fc(&out[0], &d_derot[0], &in[low], size); + } + else { + // If we have a number of consecutive misses then we restart acquisition + if (++d_freq_correction_count > d_freq_correction_timeout) { + d_initial_acquisition = 0; + d_freq_correction_count = 0; + + // Restart with a half number so that we'll not endup with the same situation + // This will prevent peak_detect to not detect anything + d_to_consume = d_to_consume / 2; + } + } + } + + // Tell runtime system how many input items we consumed on + // each input stream. + consume_each(d_to_consume); + + // Tell runtime system how many output items we produced. + return (d_to_out); + } + } /* namespace dtv */ +} /* namespace gr */ + diff --git a/gr-dtv/lib/dvbt/dvbt_ofdm_sym_acquisition_impl.h b/gr-dtv/lib/dvbt/dvbt_ofdm_sym_acquisition_impl.h new file mode 100644 index 0000000000..7190ec5f56 --- /dev/null +++ b/gr-dtv/lib/dvbt/dvbt_ofdm_sym_acquisition_impl.h @@ -0,0 +1,105 @@ +/* -*- c++ -*- */ +/* + * Copyright 2015 Free Software Foundation, Inc. + * + * This is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3, or (at your option) + * any later version. + * + * This software is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this software; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, + * Boston, MA 02110-1301, USA. + */ + +#ifndef INCLUDED_DTV_DVBT_OFDM_SYM_ACQUISITION_IMPL_H +#define INCLUDED_DTV_DVBT_OFDM_SYM_ACQUISITION_IMPL_H + +#include <gnuradio/dtv/dvbt_ofdm_sym_acquisition.h> + +#undef SEGFAULT_FIX + +namespace gr { + namespace dtv { + + class dvbt_ofdm_sym_acquisition_impl : public dvbt_ofdm_sym_acquisition + { + private: + int d_blocks; + int d_fft_length; + int d_cp_length; + float d_snr; + float d_rho; + + int d_index; + + int d_search_max; + + gr_complex * d_conj; + float * d_norm; + gr_complex * d_corr; + gr_complex * d_gamma; + float * d_lambda; + float * d_arg; + + // For peak detector + float d_threshold_factor_rise; + float d_threshold_factor_fall; + float d_avg_alpha; + float d_avg; + float d_phase; + double d_phaseinc; + int d_cp_found; + int d_count; + double d_nextphaseinc; + int d_nextpos; + + int d_sym_acq_count; + int d_sym_acq_timeout; + + int d_initial_acquisition; + + int d_freq_correction_count; + int d_freq_correction_timeout; + + int d_cp_start; + +#ifdef SEGFAULT_FIX + int d_cp_start_initial; + int d_cp_start_slip; +#endif + + gr_complex * d_derot; + int d_to_consume; + int d_to_out; + + int ml_sync(const gr_complex * in, int lookup_start, int lookup_stop, int * cp_pos, gr_complex * derot, int * to_consume, int * to_out); + + int peak_detect_init(float threshold_factor_rise, float threshold_factor_fall, int look_ahead, float alpha); + + int peak_detect_process(const float * datain, const int datain_length, int * peak_pos, int * peak_max); + + void send_sync_start(); + public: + dvbt_ofdm_sym_acquisition_impl(int blocks, int fft_length, int occupied_tones, int cp_length, float snr); + ~dvbt_ofdm_sym_acquisition_impl(); + + 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); + }; + + } // namespace dtv +} // namespace gr + +#endif /* INCLUDED_DTV_DVBT_OFDM_SYM_ACQUISITION_IMPL_H */ + diff --git a/gr-dtv/lib/dvbt/dvbt_reed_solomon_dec_impl.cc b/gr-dtv/lib/dvbt/dvbt_reed_solomon_dec_impl.cc new file mode 100644 index 0000000000..4a5530cfbe --- /dev/null +++ b/gr-dtv/lib/dvbt/dvbt_reed_solomon_dec_impl.cc @@ -0,0 +1,106 @@ +/* -*- c++ -*- */ +/* + * Copyright 2015 Free Software Foundation, Inc. + * + * This is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3, or (at your option) + * any later version. + * + * This software is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this software; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, + * Boston, MA 02110-1301, USA. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include <gnuradio/io_signature.h> +#include "dvbt_reed_solomon_dec_impl.h" +#include <stdio.h> + +namespace gr { + namespace dtv { + + dvbt_reed_solomon_dec::sptr + dvbt_reed_solomon_dec::make(int p, int m, int gfpoly, int n, int k, int t, int s, int blocks) + { + return gnuradio::get_initial_sptr + (new dvbt_reed_solomon_dec_impl(p, m, gfpoly, n, k, t, s, blocks)); + } + + /* + * The private constructor + */ + dvbt_reed_solomon_dec_impl::dvbt_reed_solomon_dec_impl(int p, int m, int gfpoly, int n, int k, int t, int s, int blocks) + : block("dvbt_reed_solomon_dec", + io_signature::make(1, 1, sizeof(unsigned char) * blocks * (n - s)), + io_signature::make(1, 1, sizeof(unsigned char) * blocks * (k - s))), + d_p(p), d_m(m), d_gfpoly(gfpoly), d_n(n), d_k(k), d_t(t), d_s(s), d_blocks(blocks), + d_rs(p, m, gfpoly, n, k, t, s, blocks) + { + d_in = new unsigned char[d_n]; + if (d_in == NULL) { + std::cout << "Cannot allocate memory for d_in" << std::endl; + exit(1); + } + memset(&d_in[0], 0, d_n); + } + + /* + * Our virtual destructor. + */ + dvbt_reed_solomon_dec_impl::~dvbt_reed_solomon_dec_impl() + { + delete [] d_in; + } + + void + dvbt_reed_solomon_dec_impl::forecast (int noutput_items, gr_vector_int &ninput_items_required) + { + ninput_items_required[0] = noutput_items; + } + + int + dvbt_reed_solomon_dec_impl::general_work (int noutput_items, + gr_vector_int &ninput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items) + { + const unsigned char *in = (const unsigned char *) input_items[0]; + unsigned char *out = (unsigned char *) output_items[0]; + + // We receive only nonzero data + int in_bsize = d_n - d_s; + int out_bsize = d_k - d_s; + + for (int i = 0; i < (d_blocks * noutput_items); i++) { + //TODO - zero copy? + // Set first d_s symbols to zero + memset(&d_in[0], 0, d_s); + // Then copy actual data + memcpy(&d_in[d_s], &in[i * in_bsize], in_bsize); + + d_rs.rs_decode(d_in, NULL, 0); + + memcpy(&out[i * out_bsize], &d_in[d_s], out_bsize); + } + + // Tell runtime system how many input items we consumed on + // each input stream. + consume_each (noutput_items); + + // Tell runtime system how many output items we produced. + return noutput_items; + } + + } /* namespace dtv */ +} /* namespace gr */ + diff --git a/gr-dtv/lib/dvbt/dvbt_reed_solomon_dec_impl.h b/gr-dtv/lib/dvbt/dvbt_reed_solomon_dec_impl.h new file mode 100644 index 0000000000..951aa4b2a1 --- /dev/null +++ b/gr-dtv/lib/dvbt/dvbt_reed_solomon_dec_impl.h @@ -0,0 +1,62 @@ +/* -*- c++ -*- */ +/* + * Copyright 2015 Free Software Foundation, Inc. + * + * This is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3, or (at your option) + * any later version. + * + * This software is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this software; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, + * Boston, MA 02110-1301, USA. + */ + +#ifndef INCLUDED_DTV_DVBT_REED_SOLOMON_DEC_IMPL_H +#define INCLUDED_DTV_DVBT_REED_SOLOMON_DEC_IMPL_H + +#include <gnuradio/dtv/dvbt_reed_solomon_dec.h> +#include "dvbt_reed_solomon.h" + +namespace gr { + namespace dtv { + + class dvbt_reed_solomon_dec_impl : public dvbt_reed_solomon_dec + { + private: + int d_p; + int d_m; + int d_gfpoly; + int d_n; + int d_k; + int d_t; + int d_s; + int d_blocks; + + unsigned char * d_in; + + dvbt_reed_solomon d_rs; + + public: + dvbt_reed_solomon_dec_impl(int p, int m, int gfpoly, int n, int k, int t, int s, int blocks); + ~dvbt_reed_solomon_dec_impl(); + + 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); + }; + + } // namespace dtv +} // namespace gr + +#endif /* INCLUDED_DTV_DVBT_REED_SOLOMON_DEC_IMPL_H */ + diff --git a/gr-dtv/lib/dvbt/dvbt_reference_signals_impl.cc b/gr-dtv/lib/dvbt/dvbt_reference_signals_impl.cc index 58fc76c64e..b3c7046ae2 100644 --- a/gr-dtv/lib/dvbt/dvbt_reference_signals_impl.cc +++ b/gr-dtv/lib/dvbt/dvbt_reference_signals_impl.cc @@ -182,7 +182,7 @@ namespace gr { // allocate buffer for scattered pilots d_spilot_carriers_val = new gr_complex[d_Kmax - d_Kmin + 1]; if (d_spilot_carriers_val == NULL) { - std::cout << "Cannot allocate memory for d_tps_carriers_val" << std::endl; + std::cout << "Cannot allocate memory for d_spilot_carriers_val" << std::endl; delete [] d_wk; exit(1); } @@ -190,7 +190,7 @@ namespace gr { // allocate buffer for channel gains (for each useful carrier) d_channel_gain = new gr_complex[d_Kmax - d_Kmin + 1]; if (d_channel_gain == NULL) { - std::cout << "Cannot allocate memory for d_tps_carriers_val" << std::endl; + std::cout << "Cannot allocate memory for d_channel_gain" << std::endl; delete [] d_spilot_carriers_val; delete [] d_wk; exit(1); @@ -199,7 +199,7 @@ namespace gr { // Allocate buffer for continual pilots phase diffs d_known_phase_diff = new float[d_cpilot_carriers_size - 1]; if (d_known_phase_diff == NULL) { - std::cout << "Cannot allocate memory for d_tps_carriers_val" << std::endl; + std::cout << "Cannot allocate memory for d_known_phase_diff" << std::endl; delete [] d_channel_gain; delete [] d_spilot_carriers_val; delete [] d_wk; @@ -214,7 +214,7 @@ namespace gr { d_cpilot_phase_diff = new float[d_cpilot_carriers_size - 1]; if (d_cpilot_phase_diff == NULL) { - std::cout << "Cannot allocate memory for d_tps_carriers_val" << std::endl; + std::cout << "Cannot allocate memory for d_cpilot_phase_diff" << std::endl; delete [] d_known_phase_diff; delete [] d_channel_gain; delete [] d_spilot_carriers_val; @@ -263,7 +263,7 @@ namespace gr { d_prev_tps_symbol = new gr_complex[d_tps_carriers_size]; if (d_prev_tps_symbol == NULL) { - std::cout << "Cannot allocate memory for d_tps_data" << std::endl; + std::cout << "Cannot allocate memory for d_prev_tps_symbol" << std::endl; delete [] d_tps_data; delete [] d_tps_carriers_val; delete [] d_derot_in; @@ -278,7 +278,7 @@ namespace gr { d_tps_symbol = new gr_complex[d_tps_carriers_size]; if (d_tps_symbol == NULL) { - std::cout << "Cannot allocate memory for d_tps_data" << std::endl; + std::cout << "Cannot allocate memory for d_tps_symbol" << std::endl; delete [] d_prev_tps_symbol; delete [] d_tps_data; delete [] d_tps_carriers_val; @@ -306,7 +306,7 @@ namespace gr { // Allocate buffer for channel estimation carriers d_chanestim_carriers = new int[d_Kmax - d_Kmin + 1]; if (d_chanestim_carriers == NULL) { - std::cout << "Cannot allocate memory for d_tps_data" << std::endl; + std::cout << "Cannot allocate memory for d_chanestim_carriers" << std::endl; delete [] d_tps_symbol; delete [] d_prev_tps_symbol; delete [] d_tps_data; @@ -323,7 +323,7 @@ namespace gr { // Allocate buffer for payload carriers d_payload_carriers = new int[d_Kmax - d_Kmin + 1]; if (d_payload_carriers == NULL) { - std::cout << "Cannot allocate memory for d_tps_data" << std::endl; + std::cout << "Cannot allocate memory for d_payload_carriers" << std::endl; delete [] d_chanestim_carriers; delete [] d_tps_symbol; delete [] d_prev_tps_symbol; @@ -435,8 +435,9 @@ namespace gr { memset(&data_in[0], 0, 60); //fill in TPS data - start bit not included //memcpy(&data_in[60], &data[1], 53); - for (int i = 0; i < 53; i++) + for (int i = 0; i < 53; i++) { data_in[60 + i] = data[1 + i]; + } //X^14+X^9+X^8+X^6+X^5+X^4+X^2+X+1 for (int i = 0; i < 113; i++) { diff --git a/gr-dtv/lib/dvbt/dvbt_symbol_inner_interleaver_impl.cc b/gr-dtv/lib/dvbt/dvbt_symbol_inner_interleaver_impl.cc index 64d242d5fb..8bdfbf9776 100644 --- a/gr-dtv/lib/dvbt/dvbt_symbol_inner_interleaver_impl.cc +++ b/gr-dtv/lib/dvbt/dvbt_symbol_inner_interleaver_impl.cc @@ -184,7 +184,7 @@ namespace gr { // Interleave for (int q = 0; q < d_nsize; q++) { if (d_symbol_index % 2) { - out[blocks + q] = in[blocks + H(q)]; + out[blocks + q] = in[blocks + H(q)]; } else { out[blocks + H(q)] = in[blocks + q]; diff --git a/gr-dtv/lib/dvbt/dvbt_viterbi_decoder_impl.cc b/gr-dtv/lib/dvbt/dvbt_viterbi_decoder_impl.cc new file mode 100644 index 0000000000..4f2362ccf4 --- /dev/null +++ b/gr-dtv/lib/dvbt/dvbt_viterbi_decoder_impl.cc @@ -0,0 +1,495 @@ +/* -*- c++ -*- */ +/* + * Copyright 2015 Free Software Foundation, Inc. + * + * This is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3, or (at your option) + * any later version. + * + * This software is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this software; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, + * Boston, MA 02110-1301, USA. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include <gnuradio/io_signature.h> +#include "dvbt_viterbi_decoder_impl.h" +#include <stdio.h> + +namespace gr { + namespace dtv { + + const unsigned char dvbt_viterbi_decoder_impl::d_puncture_1_2[2] = {1, 1}; + const unsigned char dvbt_viterbi_decoder_impl::d_puncture_2_3[4] = {1, 1, 0, 1}; + const unsigned char dvbt_viterbi_decoder_impl::d_puncture_3_4[6] = {1, 1, 0, 1, 1, 0}; + const unsigned char dvbt_viterbi_decoder_impl::d_puncture_5_6[10] = {1, 1, 0, 1, 1, 0, 0, 1, 1, 0}; + const unsigned char dvbt_viterbi_decoder_impl::d_puncture_7_8[14] = {1, 1, 0, 1, 0, 1, 0, 1, 1, 0, 0, 1, 1, 0}; + /* 8-bit parity lookup table, generated by partab.c */ + const unsigned char dvbt_viterbi_decoder_impl::d_Partab[] = { + 0, 1, 1, 0, 1, 0, 0, 1, + 1, 0, 0, 1, 0, 1, 1, 0, + 1, 0, 0, 1, 0, 1, 1, 0, + 0, 1, 1, 0, 1, 0, 0, 1, + 1, 0, 0, 1, 0, 1, 1, 0, + 0, 1, 1, 0, 1, 0, 0, 1, + 0, 1, 1, 0, 1, 0, 0, 1, + 1, 0, 0, 1, 0, 1, 1, 0, + 1, 0, 0, 1, 0, 1, 1, 0, + 0, 1, 1, 0, 1, 0, 0, 1, + 0, 1, 1, 0, 1, 0, 0, 1, + 1, 0, 0, 1, 0, 1, 1, 0, + 0, 1, 1, 0, 1, 0, 0, 1, + 1, 0, 0, 1, 0, 1, 1, 0, + 1, 0, 0, 1, 0, 1, 1, 0, + 0, 1, 1, 0, 1, 0, 0, 1, + 1, 0, 0, 1, 0, 1, 1, 0, + 0, 1, 1, 0, 1, 0, 0, 1, + 0, 1, 1, 0, 1, 0, 0, 1, + 1, 0, 0, 1, 0, 1, 1, 0, + 0, 1, 1, 0, 1, 0, 0, 1, + 1, 0, 0, 1, 0, 1, 1, 0, + 1, 0, 0, 1, 0, 1, 1, 0, + 0, 1, 1, 0, 1, 0, 0, 1, + 0, 1, 1, 0, 1, 0, 0, 1, + 1, 0, 0, 1, 0, 1, 1, 0, + 1, 0, 0, 1, 0, 1, 1, 0, + 0, 1, 1, 0, 1, 0, 0, 1, + 1, 0, 0, 1, 0, 1, 1, 0, + 0, 1, 1, 0, 1, 0, 0, 1, + 0, 1, 1, 0, 1, 0, 0, 1, + 1, 0, 0, 1, 0, 1, 1, 0, + }; + + __m128i dvbt_viterbi_decoder_impl::d_metric0[4] __attribute__ ((aligned(16))); + __m128i dvbt_viterbi_decoder_impl::d_metric1[4] __attribute__ ((aligned(16))); + __m128i dvbt_viterbi_decoder_impl::d_path0[4] __attribute__ ((aligned(16))); + __m128i dvbt_viterbi_decoder_impl::d_path1[4] __attribute__ ((aligned(16))); + + branchtab27 dvbt_viterbi_decoder_impl::Branchtab27_sse2[2] __attribute__ ((aligned(16))); + + unsigned char dvbt_viterbi_decoder_impl::mmresult[64] __attribute__((aligned(16))); + unsigned char dvbt_viterbi_decoder_impl::ppresult[TRACEBACK_MAX][64] __attribute__((aligned(16))); + + void + dvbt_viterbi_decoder_impl::dvbt_viterbi_chunks_init_sse2(__m128i *mm0, __m128i *pp0) + { + // Initialize starting metrics to prefer 0 state + int i, j; + + for (i = 0; i < 4; i++) { + mm0[i] = _mm_setzero_si128(); + pp0[i] = _mm_setzero_si128(); + } + + int polys[2] = { POLYA, POLYB }; + for (i = 0; i < 32; i++) { + Branchtab27_sse2[0].c[i] = (polys[0] < 0) ^ d_Partab[(2*i) & abs(polys[0])] ? 1 : 0; + Branchtab27_sse2[1].c[i] = (polys[1] < 0) ^ d_Partab[(2*i) & abs(polys[1])] ? 1 : 0; + } + + for (i = 0; i < 64; i++) { + mmresult[i] = 0; + for (j = 0; j < TRACEBACK_MAX; j++) { + ppresult[j][i] = 0; + } + } + } + + void + dvbt_viterbi_decoder_impl::dvbt_viterbi_butterfly2_sse2(unsigned char *symbols, __m128i *mm0, __m128i *mm1, __m128i *pp0, __m128i *pp1) + { + int i; + + __m128i *metric0, *metric1; + __m128i *path0, *path1; + + metric0 = mm0; + path0 = pp0; + metric1 = mm1; + path1 = pp1; + + // Operate on 4 symbols (2 bits) at a time + + __m128i m0, m1, m2, m3, decision0, decision1, survivor0, survivor1; + __m128i metsv, metsvm; + __m128i shift0, shift1; + __m128i tmp0, tmp1; + __m128i sym0v, sym1v; + + sym0v = _mm_set1_epi8(symbols[0]); + sym1v = _mm_set1_epi8(symbols[1]); + + for (i = 0; i < 2; i++) { + if (symbols[0] == 2) { + metsvm = _mm_xor_si128(Branchtab27_sse2[1].v[i],sym1v); + metsv = _mm_sub_epi8(_mm_set1_epi8(1),metsvm); + } + else if (symbols[1] == 2) { + metsvm = _mm_xor_si128(Branchtab27_sse2[0].v[i],sym0v); + metsv = _mm_sub_epi8(_mm_set1_epi8(1),metsvm); + } + else { + metsvm = _mm_add_epi8(_mm_xor_si128(Branchtab27_sse2[0].v[i],sym0v),_mm_xor_si128(Branchtab27_sse2[1].v[i],sym1v)); + metsv = _mm_sub_epi8(_mm_set1_epi8(2),metsvm); + } + + m0 = _mm_add_epi8(metric0[i], metsv); + m1 = _mm_add_epi8(metric0[i+2], metsvm); + m2 = _mm_add_epi8(metric0[i], metsvm); + m3 = _mm_add_epi8(metric0[i+2], metsv); + + decision0 = _mm_cmpgt_epi8(_mm_sub_epi8(m0,m1),_mm_setzero_si128()); + decision1 = _mm_cmpgt_epi8(_mm_sub_epi8(m2,m3),_mm_setzero_si128()); + survivor0 = _mm_or_si128(_mm_and_si128(decision0,m0),_mm_andnot_si128(decision0,m1)); + survivor1 = _mm_or_si128(_mm_and_si128(decision1,m2),_mm_andnot_si128(decision1,m3)); + + shift0 = _mm_slli_epi16(path0[i], 1); + shift1 = _mm_slli_epi16(path0[2+i], 1); + shift1 = _mm_add_epi8(shift1, _mm_set1_epi8(1)); + + metric1[2*i] = _mm_unpacklo_epi8(survivor0,survivor1); + tmp0 = _mm_or_si128(_mm_and_si128(decision0,shift0),_mm_andnot_si128(decision0,shift1)); + + metric1[2*i+1] = _mm_unpackhi_epi8(survivor0,survivor1); + tmp1 = _mm_or_si128(_mm_and_si128(decision1,shift0),_mm_andnot_si128(decision1,shift1)); + + path1[2*i] = _mm_unpacklo_epi8(tmp0, tmp1); + path1[2*i+1] = _mm_unpackhi_epi8(tmp0, tmp1); + } + + metric0 = mm1; + path0 = pp1; + metric1 = mm0; + path1 = pp0; + + sym0v = _mm_set1_epi8(symbols[2]); + sym1v = _mm_set1_epi8(symbols[3]); + + for (i = 0; i < 2; i++) { + if (symbols[2] == 2) { + metsvm = _mm_xor_si128(Branchtab27_sse2[1].v[i],sym1v); + metsv = _mm_sub_epi8(_mm_set1_epi8(1),metsvm); + } + else if (symbols[3] == 2) { + metsvm = _mm_xor_si128(Branchtab27_sse2[0].v[i],sym0v); + metsv = _mm_sub_epi8(_mm_set1_epi8(1),metsvm); + } + else { + metsvm = _mm_add_epi8(_mm_xor_si128(Branchtab27_sse2[0].v[i],sym0v),_mm_xor_si128(Branchtab27_sse2[1].v[i],sym1v)); + metsv = _mm_sub_epi8(_mm_set1_epi8(2),metsvm); + } + + m0 = _mm_add_epi8(metric0[i], metsv); + m1 = _mm_add_epi8(metric0[i+2], metsvm); + m2 = _mm_add_epi8(metric0[i], metsvm); + m3 = _mm_add_epi8(metric0[i+2], metsv); + + decision0 = _mm_cmpgt_epi8(_mm_sub_epi8(m0,m1),_mm_setzero_si128()); + decision1 = _mm_cmpgt_epi8(_mm_sub_epi8(m2,m3),_mm_setzero_si128()); + survivor0 = _mm_or_si128(_mm_and_si128(decision0,m0),_mm_andnot_si128(decision0,m1)); + survivor1 = _mm_or_si128(_mm_and_si128(decision1,m2),_mm_andnot_si128(decision1,m3)); + + shift0 = _mm_slli_epi16(path0[i], 1); + shift1 = _mm_slli_epi16(path0[2+i], 1); + shift1 = _mm_add_epi8(shift1, _mm_set1_epi8(1)); + + metric1[2*i] = _mm_unpacklo_epi8(survivor0,survivor1); + tmp0 = _mm_or_si128(_mm_and_si128(decision0,shift0),_mm_andnot_si128(decision0,shift1)); + + metric1[2*i+1] = _mm_unpackhi_epi8(survivor0,survivor1); + tmp1 = _mm_or_si128(_mm_and_si128(decision1,shift0),_mm_andnot_si128(decision1,shift1)); + + path1[2*i] = _mm_unpacklo_epi8(tmp0, tmp1); + path1[2*i+1] = _mm_unpackhi_epi8(tmp0, tmp1); + } + } + + unsigned char + dvbt_viterbi_decoder_impl::dvbt_viterbi_get_output_sse2(__m128i *mm0, __m128i *pp0, int ntraceback, unsigned char *outbuf) + { + // Find current best path + int i; + int bestmetric, minmetric; + int beststate = 0; + int pos = 0; + + // Implement a circular buffer with the last ntraceback paths + store_pos = (store_pos + 1) % ntraceback; + + // TODO - find another way to extract the value + for (i = 0; i < 4; i++) { + _mm_store_si128((__m128i *) &mmresult[i*16], mm0[i]); + _mm_store_si128((__m128i *) &ppresult[store_pos][i*16], pp0[i]); + } + + // Find out the best final state + bestmetric = mmresult[beststate]; + minmetric = mmresult[beststate]; + + for (i = 1; i < 64; i++) { + if (mmresult[i] > bestmetric) { + bestmetric = mmresult[i]; + beststate = i; + } + if (mmresult[i] < minmetric) { + minmetric = mmresult[i]; + } + } + + // Trace back + for (i = 0, pos = store_pos; i < (ntraceback - 1); i++) { + // Obtain the state from the output bits + // by clocking in the output bits in reverse order. + // The state has only 6 bits + beststate = ppresult[pos][beststate] >> 2; + pos = (pos - 1 + ntraceback) % ntraceback; + } + + // Store output byte + *outbuf = ppresult[pos][beststate]; + + // Zero out the path variable + // and prevent metric overflow + for (i = 0; i < 4; i++) { + pp0[i] = _mm_setzero_si128(); + mm0[i] = _mm_sub_epi8(mm0[i], _mm_set1_epi8(minmetric)); + } + + return bestmetric; + } + + dvbt_viterbi_decoder::sptr + dvbt_viterbi_decoder::make(dvb_constellation_t constellation, \ + dvbt_hierarchy_t hierarchy, dvb_code_rate_t coderate, int bsize) + { + return gnuradio::get_initial_sptr + (new dvbt_viterbi_decoder_impl(constellation, hierarchy, coderate, bsize)); + } + + /* + * The private constructor + */ + dvbt_viterbi_decoder_impl::dvbt_viterbi_decoder_impl(dvb_constellation_t constellation, \ + dvbt_hierarchy_t hierarchy, dvb_code_rate_t coderate, int bsize) + : block("dvbt_viterbi_decoder", + io_signature::make(1, 1, sizeof (unsigned char)), + io_signature::make(1, 1, sizeof (unsigned char))), + config(constellation, hierarchy, coderate, coderate), + d_bsize(bsize), + d_init(0), + store_pos(0) + { + //Determine k - input of encoder + d_k = config.d_cr_k; + //Determine n - output of encoder + d_n = config.d_cr_n; + //Determine m - constellation symbol size + d_m = config.d_m; + // Determine puncturing vector and traceback + if (config.d_code_rate_HP == C1_2) { + d_puncture = d_puncture_1_2; + d_ntraceback = 5; + } + else if (config.d_code_rate_HP == C2_3) { + d_puncture = d_puncture_2_3; + d_ntraceback = 9; + } + else if (config.d_code_rate_HP == C3_4) { + d_puncture = d_puncture_3_4; + d_ntraceback = 10; + } + else if (config.d_code_rate_HP == C5_6) { + d_puncture = d_puncture_5_6; + d_ntraceback = 15; + } + else if (config.d_code_rate_HP == C7_8) { + d_puncture = d_puncture_7_8; + d_ntraceback = 24; + } + else { + d_puncture = d_puncture_1_2; + d_ntraceback = 5; + } + + /* + * We input n bytes, each carrying m bits => nm bits + * The result after decoding is km bits, therefore km/8 bytes. + * + * out/in rate is therefore km/8n in bytes + */ + assert((d_k * d_m) % (8 * d_n)); + set_relative_rate((d_k * d_m) / (8 * d_n)); + + assert ((d_bsize * d_n) % d_m == 0); + set_output_multiple (d_bsize * d_k / 8); + + /* + * Calculate process variables: + * Number of symbols (d_m bits) in all blocks + * It is also the number of input bytes since + * one byte always contains just one symbol. + */ + d_nsymbols = d_bsize * d_n / d_m; + // Number of bits after depuncturing a block (before decoding) + d_nbits = 2 * d_k * d_bsize; + // Number of output bytes after decoding + d_nout = d_nbits / 2 / 8; + + // Allocate the buffer for the bits + d_inbits = new unsigned char [d_nbits]; + if (d_inbits == NULL) { + std::cout << "Cannot allocate memory for d_inbits" << std::endl; + exit(1); + } + + mettab[0][0] = 1; + mettab[0][1] = 0; + mettab[1][0] = 0; + mettab[1][1] = 1; + + dvbt_viterbi_chunks_init_sse2(d_metric0, d_path0); + } + + /* + * Our virtual destructor. + */ + dvbt_viterbi_decoder_impl::~dvbt_viterbi_decoder_impl() + { + delete [] d_inbits; + } + + void + dvbt_viterbi_decoder_impl::forecast (int noutput_items, gr_vector_int &ninput_items_required) + { + int input_required = noutput_items * 8 * d_n / (d_k * d_m); + + unsigned ninputs = ninput_items_required.size(); + for (unsigned int i = 0; i < ninputs; i++) { + ninput_items_required[i] = input_required; + } + } + + int + dvbt_viterbi_decoder_impl::general_work (int noutput_items, + gr_vector_int &ninput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items) + { + int nstreams = input_items.size(); + int nblocks = 8 * noutput_items / (d_bsize * d_k); + int out_count = 0; + + for (int m = 0; m < nstreams; m++) { + const unsigned char *in = (const unsigned char *) input_items[m]; + unsigned char *out = (unsigned char *) output_items[m]; + + /* + * Look for a tag that signals superframe_start and consume all input items + * that are in input buffer so far. + * This will actually reset the viterbi decoder. + */ + std::vector<tag_t> tags; + const uint64_t nread = this->nitems_read(0); //number of items read on port 0 + this->get_tags_in_range(tags, 0, nread, nread + (nblocks * d_nsymbols), pmt::string_to_symbol("superframe_start")); + + if (tags.size()) { + d_init = 0; + dvbt_viterbi_chunks_init_sse2(d_metric0, d_path0); + + if (tags[0].offset - nread) { + consume_each(tags[0].offset - nread); + return (0); + } + } + + // This is actually the Viterbi decoder + for (int n = 0; n < nblocks; n++) { + /* + * Depuncture and unpack a block. + * We receive the symbol (d_m bits/byte) in one byte (e.g. for QAM16 00001111). + * Create a buffer of bytes containing just one bit/byte. + * Also depuncture according to the puncture vector. + * TODO - reduce the number of branches while depuncturing. + */ + for (int count = 0, i = 0; i < d_nsymbols; i++) { + for (int j = (d_m - 1); j >= 0; j--) { + // Depuncture + while (d_puncture[count % (2 * d_k)] == 0) { + d_inbits[count++] = 2; + } + + // Insert received bits + d_inbits[count++] = (in[(n * d_nsymbols) + i] >> j) & 1; + + // Depuncture + while (d_puncture[count % (2 * d_k)] == 0) { + d_inbits[count++] = 2; + } + } + } + + /* + * Decode a block. + */ + for (int in_count = 0; in_count < d_nbits; in_count++) { + if ((in_count % 4) == 0) { // 0 or 3 + dvbt_viterbi_butterfly2_sse2(&d_inbits[in_count & 0xfffffffc], d_metric0, d_metric1, d_path0, d_path1); + + if ((in_count > 0) && (in_count % 16) == 8) { // 8 or 11 + unsigned char c; + + dvbt_viterbi_get_output_sse2(d_metric0, d_path0, d_ntraceback, &c); + + if (d_init == 0) { + if (out_count >= d_ntraceback) { + out[out_count - d_ntraceback] = c; + } + } + else { + out[out_count] = c; + } + out_count++; + } + } + } + } + } + + int to_out = noutput_items; + + if (d_init == 0) { + /* + * Send superframe_start to signal this situation + * downstream + */ + const uint64_t offset = this->nitems_written(0); + pmt::pmt_t key = pmt::string_to_symbol("superframe_start"); + pmt::pmt_t value = pmt::from_long(1); + this->add_item_tag(0, offset, key, value); + + // Take in consideration the traceback length + to_out = to_out - d_ntraceback; + d_init = 1; + } + + // Tell runtime system how many input items we consumed on + // each input stream. + consume_each (nblocks * d_nsymbols); + + // Tell runtime system how many output items we produced. + return (to_out); + } + + } /* namespace dtv */ +} /* namespace gr */ + diff --git a/gr-dtv/lib/dvbt/dvbt_viterbi_decoder_impl.h b/gr-dtv/lib/dvbt/dvbt_viterbi_decoder_impl.h new file mode 100644 index 0000000000..8870a79dcf --- /dev/null +++ b/gr-dtv/lib/dvbt/dvbt_viterbi_decoder_impl.h @@ -0,0 +1,125 @@ +/* -*- c++ -*- */ +/* + * Copyright 2015 Free Software Foundation, Inc. + * + * This is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3, or (at your option) + * any later version. + * + * This software is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this software; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, + * Boston, MA 02110-1301, USA. + */ + +#ifndef INCLUDED_DTV_DVBT_VITERBI_DECODER_IMPL_H +#define INCLUDED_DTV_DVBT_VITERBI_DECODER_IMPL_H + +#include <gnuradio/dtv/dvbt_viterbi_decoder.h> +#include "dvbt_configure.h" +#include <xmmintrin.h> + +/* The two generator polynomials for the NASA Standard K=7 code. + * Since these polynomials are known to be optimal for this constraint + * length there is not much point in changing them. + */ + +#define POLYA 0x4f +#define POLYB 0x6d +// Maximum number of traceback bytes +#define TRACEBACK_MAX 24 + +union branchtab27 { + unsigned char c[32]; + __m128i v[2]; +}; + +namespace gr { + namespace dtv { + + class dvbt_viterbi_decoder_impl : public dvbt_viterbi_decoder + { + private: + dvbt_configure config; + + // Puncturing vectors + static const unsigned char d_puncture_1_2[]; + static const unsigned char d_puncture_2_3[]; + static const unsigned char d_puncture_3_4[]; + static const unsigned char d_puncture_5_6[]; + static const unsigned char d_puncture_7_8[]; + static const unsigned char d_Partab[]; + + static __m128i d_metric0[4]; + static __m128i d_metric1[4]; + static __m128i d_path0[4]; + static __m128i d_path1[4]; + + static branchtab27 Branchtab27_sse2[2]; + + // Metrics for each state + static unsigned char mmresult[64]; + // Paths for each state + static unsigned char ppresult[TRACEBACK_MAX][64]; + + // Current puncturing vector + const unsigned char * d_puncture; + + // Code rate k/n + int d_k; + int d_n; + // Constellation with m + int d_m; + + // Block size + int d_bsize; + // Symbols to consume on decoding from one block + int d_nsymbols; + // Number of bits after depuncturing a block + int d_nbits; + // Number of full packed out bytes + int d_nout; + + // Traceback (in bytes) + int d_ntraceback; + + // Viterbi tables + int mettab[2][256]; + + // Buffer to keep the input bits + unsigned char * d_inbits; + + // This is used to get rid of traceback on the first frame + int d_init; + + // Position in circular buffer where the current decoded byte is stored + int store_pos; + + void dvbt_viterbi_chunks_init_sse2(__m128i *mm0, __m128i *pp0); + void dvbt_viterbi_butterfly2_sse2(unsigned char *symbols, __m128i m0[], __m128i m1[], __m128i p0[], __m128i p1[]); + unsigned char dvbt_viterbi_get_output_sse2(__m128i *mm0, __m128i *pp0, int ntraceback, unsigned char *outbuf); + + public: + dvbt_viterbi_decoder_impl(dvb_constellation_t constellation, \ + dvbt_hierarchy_t hierarchy, dvb_code_rate_t coderate, int bsize); + ~dvbt_viterbi_decoder_impl(); + + 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); + }; + + } // namespace dtv +} // namespace gr + +#endif /* INCLUDED_DTV_DVBT_VITERBI_DECODER_IMPL_H */ + diff --git a/gr-dtv/swig/dtv_swig.i b/gr-dtv/swig/dtv_swig.i index 094e8f0faf..c2fa312e05 100644 --- a/gr-dtv/swig/dtv_swig.i +++ b/gr-dtv/swig/dtv_swig.i @@ -71,6 +71,14 @@ #include "gnuradio/dtv/dvbt_symbol_inner_interleaver.h" #include "gnuradio/dtv/dvbt_map.h" #include "gnuradio/dtv/dvbt_reference_signals.h" +#include "gnuradio/dtv/dvbt_ofdm_sym_acquisition.h" +#include "gnuradio/dtv/dvbt_demod_reference_signals.h" +#include "gnuradio/dtv/dvbt_demap.h" +#include "gnuradio/dtv/dvbt_bit_inner_deinterleaver.h" +#include "gnuradio/dtv/dvbt_viterbi_decoder.h" +#include "gnuradio/dtv/dvbt_convolutional_deinterleaver.h" +#include "gnuradio/dtv/dvbt_reed_solomon_dec.h" +#include "gnuradio/dtv/dvbt_energy_descramble.h" %} %include "gnuradio/dtv/atsc_deinterleaver.h" @@ -116,6 +124,14 @@ %include "gnuradio/dtv/dvbt_symbol_inner_interleaver.h" %include "gnuradio/dtv/dvbt_map.h" %include "gnuradio/dtv/dvbt_reference_signals.h" +%include "gnuradio/dtv/dvbt_ofdm_sym_acquisition.h" +%include "gnuradio/dtv/dvbt_demod_reference_signals.h" +%include "gnuradio/dtv/dvbt_demap.h" +%include "gnuradio/dtv/dvbt_bit_inner_deinterleaver.h" +%include "gnuradio/dtv/dvbt_viterbi_decoder.h" +%include "gnuradio/dtv/dvbt_convolutional_deinterleaver.h" +%include "gnuradio/dtv/dvbt_reed_solomon_dec.h" +%include "gnuradio/dtv/dvbt_energy_descramble.h" GR_SWIG_BLOCK_MAGIC2(dtv, atsc_deinterleaver); GR_SWIG_BLOCK_MAGIC2(dtv, atsc_depad); @@ -156,3 +172,11 @@ GR_SWIG_BLOCK_MAGIC2(dtv, dvbt_bit_inner_interleaver); GR_SWIG_BLOCK_MAGIC2(dtv, dvbt_symbol_inner_interleaver); GR_SWIG_BLOCK_MAGIC2(dtv, dvbt_map); GR_SWIG_BLOCK_MAGIC2(dtv, dvbt_reference_signals); +GR_SWIG_BLOCK_MAGIC2(dtv, dvbt_ofdm_sym_acquisition); +GR_SWIG_BLOCK_MAGIC2(dtv, dvbt_demod_reference_signals); +GR_SWIG_BLOCK_MAGIC2(dtv, dvbt_demap); +GR_SWIG_BLOCK_MAGIC2(dtv, dvbt_bit_inner_deinterleaver); +GR_SWIG_BLOCK_MAGIC2(dtv, dvbt_viterbi_decoder); +GR_SWIG_BLOCK_MAGIC2(dtv, dvbt_convolutional_deinterleaver); +GR_SWIG_BLOCK_MAGIC2(dtv, dvbt_reed_solomon_dec); +GR_SWIG_BLOCK_MAGIC2(dtv, dvbt_energy_descramble); diff --git a/gr-filter/lib/qa_fir_filter_with_buffer.cc b/gr-filter/lib/qa_fir_filter_with_buffer.cc index a1dd9f4e48..74f5261588 100644 --- a/gr-filter/lib/qa_fir_filter_with_buffer.cc +++ b/gr-filter/lib/qa_fir_filter_with_buffer.cc @@ -40,10 +40,12 @@ namespace gr { #define MAX_DATA (16383) #define ERR_DELTA (1e-5) + static gr::random rndm; + static float uniform() { - return 2.0 * ((float)(::random()) / RANDOM_MAX - 0.5); // uniformly (-1, 1) + return 2.0 * (rndm.ran1() - 0.5); // uniformly (-1, 1) } static void diff --git a/gr-qtgui/examples/CMakeLists.txt b/gr-qtgui/examples/CMakeLists.txt index d4b914a0a4..c893c0263c 100644 --- a/gr-qtgui/examples/CMakeLists.txt +++ b/gr-qtgui/examples/CMakeLists.txt @@ -39,6 +39,7 @@ GR_PYTHON_INSTALL(PROGRAMS install( FILES qtgui_tags_viewing.grc + qtgui_vector_sink_example.grc DESTINATION ${GR_PKG_QTGUI_EXAMPLES_DIR} COMPONENT "qtgui_python" ) diff --git a/gr-qtgui/examples/qtgui_vector_sink_example.grc b/gr-qtgui/examples/qtgui_vector_sink_example.grc index 4ad897d050..da10209c4a 100644 --- a/gr-qtgui/examples/qtgui_vector_sink_example.grc +++ b/gr-qtgui/examples/qtgui_vector_sink_example.grc @@ -1,22 +1,27 @@ -<?xml version='1.0' encoding='ASCII'?> +<?xml version='1.0' encoding='utf-8'?> +<?grc format='1' created='3.7.8'?> <flow_graph> <timestamp>Sun Aug 17 18:43:15 2014</timestamp> <block> <key>options</key> <param> - <key>id</key> - <value>qt_example_vector_sink</value> + <key>author</key> + <value></value> </param> <param> - <key>_enabled</key> - <value>True</value> + <key>alias</key> + <value></value> </param> <param> - <key>title</key> - <value>QT GUI Vector Sink Example</value> + <key>window_size</key> + <value>1280, 1024</value> </param> <param> - <key>author</key> + <key>category</key> + <value>Custom</value> + </param> + <param> + <key>comment</key> <value></value> </param> <param> @@ -24,24 +29,24 @@ <value></value> </param> <param> - <key>window_size</key> - <value>1280, 1024</value> + <key>_enabled</key> + <value>True</value> </param> <param> - <key>generate_options</key> - <value>qt_gui</value> + <key>_coordinate</key> + <value>(-1, 0)</value> </param> <param> - <key>category</key> - <value>Custom</value> + <key>_rotation</key> + <value>0</value> </param> <param> - <key>run_options</key> - <value>prompt</value> + <key>generate_options</key> + <value>qt_gui</value> </param> <param> - <key>run</key> - <value>True</value> + <key>id</key> + <value>qt_example_vector_sink</value> </param> <param> <key>max_nouts</key> @@ -52,424 +57,467 @@ <value></value> </param> <param> - <key>alias</key> - <value></value> + <key>run_options</key> + <value>prompt</value> </param> <param> - <key>_coordinate</key> - <value>(-1, 0)</value> + <key>run</key> + <value>True</value> </param> <param> - <key>_rotation</key> - <value>0</value> + <key>thread_safe_setters</key> + <value></value> + </param> + <param> + <key>title</key> + <value>QT GUI Vector Sink Example</value> </param> </block> <block> <key>variable</key> <param> - <key>id</key> - <value>veclen</value> + <key>comment</key> + <value></value> </param> <param> <key>_enabled</key> <value>True</value> </param> <param> - <key>value</key> - <value>512</value> - </param> - <param> - <key>alias</key> - <value></value> - </param> - <param> <key>_coordinate</key> - <value>(183, 0)</value> + <value>(272, -5)</value> </param> <param> <key>_rotation</key> <value>0</value> </param> - </block> - <block> - <key>variable</key> <param> <key>id</key> <value>samp_rate</value> </param> <param> - <key>_enabled</key> - <value>True</value> - </param> - <param> <key>value</key> <value>32000</value> </param> - <param> - <key>alias</key> - <value></value> - </param> - <param> - <key>_coordinate</key> - <value>(-1, 87)</value> - </param> - <param> - <key>_rotation</key> - <value>0</value> - </param> </block> <block> - <key>blocks_throttle</key> + <key>variable</key> <param> - <key>id</key> - <value>blocks_throttle_0</value> + <key>comment</key> + <value></value> </param> <param> <key>_enabled</key> <value>True</value> </param> <param> - <key>type</key> - <value>float</value> + <key>_coordinate</key> + <value>(183, 0)</value> </param> <param> - <key>samples_per_second</key> - <value>samp_rate</value> + <key>_rotation</key> + <value>0</value> </param> <param> - <key>vlen</key> + <key>id</key> <value>veclen</value> </param> <param> - <key>ignoretag</key> - <value>True</value> + <key>value</key> + <value>512</value> + </param> + </block> + <block> + <key>analog_fastnoise_source_x</key> + <param> + <key>amp</key> + <value>1</value> </param> <param> <key>alias</key> <value></value> </param> <param> - <key>affinity</key> + <key>comment</key> <value></value> </param> <param> - <key>minoutbuf</key> - <value>0</value> + <key>affinity</key> + <value></value> </param> <param> - <key>maxoutbuf</key> - <value>0</value> + <key>_enabled</key> + <value>True</value> </param> <param> <key>_coordinate</key> - <value>(199, 180)</value> + <value>(-1, 293)</value> </param> <param> <key>_rotation</key> <value>0</value> </param> - </block> - <block> - <key>blocks_add_xx</key> <param> <key>id</key> - <value>blocks_add_xx_0</value> + <value>analog_fastnoise_source_x_0</value> </param> <param> - <key>_enabled</key> - <value>True</value> + <key>maxoutbuf</key> + <value>0</value> + </param> + <param> + <key>minoutbuf</key> + <value>0</value> + </param> + <param> + <key>noise_type</key> + <value>analog.GR_GAUSSIAN</value> </param> <param> <key>type</key> <value>float</value> </param> <param> - <key>num_inputs</key> - <value>2</value> + <key>seed</key> + <value>0</value> </param> <param> - <key>vlen</key> - <value>veclen</value> + <key>samples</key> + <value>8192</value> </param> + </block> + <block> + <key>blocks_add_xx</key> <param> <key>alias</key> <value></value> </param> <param> - <key>affinity</key> + <key>comment</key> <value></value> </param> <param> - <key>minoutbuf</key> - <value>0</value> + <key>affinity</key> + <value></value> </param> <param> - <key>maxoutbuf</key> - <value>0</value> + <key>_enabled</key> + <value>True</value> </param> <param> <key>_coordinate</key> - <value>(382, 186)</value> + <value>(456, 145)</value> </param> <param> <key>_rotation</key> <value>0</value> </param> - </block> - <block> - <key>blocks_vector_source_x</key> <param> <key>id</key> - <value>blocks_vector_source_x_0</value> - </param> - <param> - <key>_enabled</key> - <value>True</value> + <value>blocks_add_xx_0</value> </param> <param> <key>type</key> <value>float</value> </param> <param> - <key>vector</key> - <value>range(veclen)</value> + <key>maxoutbuf</key> + <value>0</value> </param> <param> - <key>tags</key> - <value>[]</value> + <key>minoutbuf</key> + <value>0</value> </param> <param> - <key>repeat</key> - <value>True</value> + <key>num_inputs</key> + <value>2</value> </param> <param> <key>vlen</key> <value>veclen</value> </param> + </block> + <block> + <key>blocks_message_debug</key> <param> <key>alias</key> <value></value> </param> <param> - <key>affinity</key> + <key>comment</key> <value></value> </param> <param> - <key>minoutbuf</key> - <value>0</value> + <key>affinity</key> + <value></value> </param> <param> - <key>maxoutbuf</key> - <value>0</value> + <key>_enabled</key> + <value>True</value> </param> <param> <key>_coordinate</key> - <value>(-1, 165)</value> + <value>(928, 161)</value> </param> <param> <key>_rotation</key> <value>0</value> </param> + <param> + <key>id</key> + <value>blocks_message_debug_0</value> + </param> </block> <block> - <key>analog_fastnoise_source_x</key> + <key>blocks_stream_to_vector</key> <param> - <key>id</key> - <value>analog_fastnoise_source_x_0</value> + <key>alias</key> + <value></value> + </param> + <param> + <key>comment</key> + <value></value> + </param> + <param> + <key>affinity</key> + <value></value> </param> <param> <key>_enabled</key> <value>True</value> </param> <param> + <key>_coordinate</key> + <value>(216, 315)</value> + </param> + <param> + <key>_rotation</key> + <value>0</value> + </param> + <param> + <key>id</key> + <value>blocks_stream_to_vector_0</value> + </param> + <param> <key>type</key> <value>float</value> </param> <param> - <key>noise_type</key> - <value>analog.GR_GAUSSIAN</value> + <key>maxoutbuf</key> + <value>0</value> </param> <param> - <key>amp</key> - <value>1</value> + <key>minoutbuf</key> + <value>0</value> </param> <param> - <key>seed</key> - <value>0</value> + <key>num_items</key> + <value>veclen</value> </param> <param> - <key>samples</key> - <value>8192</value> + <key>vlen</key> + <value>1</value> </param> + </block> + <block> + <key>blocks_throttle</key> <param> <key>alias</key> <value></value> </param> <param> - <key>affinity</key> + <key>comment</key> <value></value> </param> <param> - <key>minoutbuf</key> - <value>0</value> + <key>affinity</key> + <value></value> </param> <param> - <key>maxoutbuf</key> - <value>0</value> + <key>_enabled</key> + <value>True</value> </param> <param> <key>_coordinate</key> - <value>(-1, 293)</value> + <value>(208, 131)</value> </param> <param> <key>_rotation</key> <value>0</value> </param> - </block> - <block> - <key>blocks_stream_to_vector</key> <param> <key>id</key> - <value>blocks_stream_to_vector_0</value> + <value>blocks_throttle_0</value> </param> <param> - <key>_enabled</key> + <key>ignoretag</key> <value>True</value> </param> <param> - <key>type</key> - <value>float</value> + <key>maxoutbuf</key> + <value>0</value> </param> <param> - <key>num_items</key> - <value>veclen</value> + <key>minoutbuf</key> + <value>0</value> + </param> + <param> + <key>samples_per_second</key> + <value>samp_rate</value> + </param> + <param> + <key>type</key> + <value>float</value> </param> <param> <key>vlen</key> - <value>1</value> + <value>veclen</value> </param> + </block> + <block> + <key>blocks_vector_source_x</key> <param> <key>alias</key> <value></value> </param> <param> - <key>affinity</key> + <key>comment</key> <value></value> </param> <param> - <key>minoutbuf</key> - <value>0</value> + <key>affinity</key> + <value></value> </param> <param> - <key>maxoutbuf</key> - <value>0</value> + <key>_enabled</key> + <value>True</value> </param> <param> <key>_coordinate</key> - <value>(197, 316)</value> + <value>(0, 115)</value> </param> <param> <key>_rotation</key> <value>0</value> </param> - </block> - <block> - <key>qtgui_vector_sink_x</key> <param> <key>id</key> - <value>qtgui_vector_sink_x_0</value> + <value>blocks_vector_source_x_0</value> </param> <param> - <key>_enabled</key> + <key>maxoutbuf</key> + <value>0</value> + </param> + <param> + <key>minoutbuf</key> + <value>0</value> + </param> + <param> + <key>type</key> + <value>float</value> + </param> + <param> + <key>repeat</key> <value>True</value> </param> <param> - <key>name</key> - <value>"A noisy line"</value> + <key>tags</key> + <value>[]</value> </param> <param> <key>vlen</key> <value>veclen</value> </param> <param> - <key>x_start</key> - <value>0</value> + <key>vector</key> + <value>range(veclen)</value> </param> + </block> + <block> + <key>qtgui_vector_sink_f</key> <param> - <key>x_step</key> - <value>1.0/veclen</value> + <key>autoscale</key> + <value>False</value> </param> <param> - <key>x_axis_label</key> - <value>"x-Axis"</value> + <key>average</key> + <value>1.0</value> </param> <param> - <key>y_axis_label</key> - <value>"y-Axis"</value> + <key>alias</key> + <value></value> </param> <param> - <key>x_units</key> - <value>"x"</value> + <key>comment</key> + <value></value> </param> <param> - <key>y_units</key> - <value>"y"</value> + <key>affinity</key> + <value></value> </param> <param> - <key>ref_level</key> - <value>.5*veclen</value> + <key>_enabled</key> + <value>True</value> + </param> + <param> + <key>_coordinate</key> + <value>(640, 91)</value> + </param> + <param> + <key>gui_hint</key> + <value></value> + </param> + <param> + <key>_rotation</key> + <value>0</value> </param> <param> <key>grid</key> <value>True</value> </param> <param> - <key>autoscale</key> - <value>False</value> + <key>id</key> + <value>qtgui_vector_sink_f_0</value> </param> <param> - <key>average</key> + <key>alpha1</key> <value>1.0</value> </param> <param> - <key>ymin</key> - <value>0</value> + <key>color1</key> + <value>"blue"</value> </param> <param> - <key>ymax</key> - <value>veclen</value> + <key>label1</key> + <value></value> </param> <param> - <key>nconnections</key> + <key>width1</key> <value>1</value> </param> <param> - <key>update_time</key> - <value>0.10</value> - </param> - <param> - <key>gui_hint</key> - <value></value> + <key>alpha10</key> + <value>1.0</value> </param> <param> - <key>showports</key> - <value>False</value> + <key>color10</key> + <value>"dark blue"</value> </param> <param> - <key>label1</key> - <value>Up</value> + <key>label10</key> + <value></value> </param> <param> - <key>width1</key> + <key>width10</key> <value>1</value> </param> <param> - <key>color1</key> - <value>"blue"</value> + <key>alpha2</key> + <value>1.0</value> </param> <param> - <key>alpha1</key> - <value>1.0</value> + <key>color2</key> + <value>"red"</value> </param> <param> <key>label2</key> @@ -480,12 +528,12 @@ <value>1</value> </param> <param> - <key>color2</key> - <value>"red"</value> + <key>alpha3</key> + <value>1.0</value> </param> <param> - <key>alpha2</key> - <value>1.0</value> + <key>color3</key> + <value>"green"</value> </param> <param> <key>label3</key> @@ -496,12 +544,12 @@ <value>1</value> </param> <param> - <key>color3</key> - <value>"green"</value> + <key>alpha4</key> + <value>1.0</value> </param> <param> - <key>alpha3</key> - <value>1.0</value> + <key>color4</key> + <value>"black"</value> </param> <param> <key>label4</key> @@ -512,12 +560,12 @@ <value>1</value> </param> <param> - <key>color4</key> - <value>"black"</value> + <key>alpha5</key> + <value>1.0</value> </param> <param> - <key>alpha4</key> - <value>1.0</value> + <key>color5</key> + <value>"cyan"</value> </param> <param> <key>label5</key> @@ -528,12 +576,12 @@ <value>1</value> </param> <param> - <key>color5</key> - <value>"cyan"</value> + <key>alpha6</key> + <value>1.0</value> </param> <param> - <key>alpha5</key> - <value>1.0</value> + <key>color6</key> + <value>"magenta"</value> </param> <param> <key>label6</key> @@ -544,12 +592,12 @@ <value>1</value> </param> <param> - <key>color6</key> - <value>"magenta"</value> + <key>alpha7</key> + <value>1.0</value> </param> <param> - <key>alpha6</key> - <value>1.0</value> + <key>color7</key> + <value>"yellow"</value> </param> <param> <key>label7</key> @@ -560,12 +608,12 @@ <value>1</value> </param> <param> - <key>color7</key> - <value>"yellow"</value> + <key>alpha8</key> + <value>1.0</value> </param> <param> - <key>alpha7</key> - <value>1.0</value> + <key>color8</key> + <value>"dark red"</value> </param> <param> <key>label8</key> @@ -576,12 +624,12 @@ <value>1</value> </param> <param> - <key>color8</key> - <value>"dark red"</value> + <key>alpha9</key> + <value>1.0</value> </param> <param> - <key>alpha8</key> - <value>1.0</value> + <key>color9</key> + <value>"dark green"</value> </param> <param> <key>label9</key> @@ -592,113 +640,102 @@ <value>1</value> </param> <param> - <key>color9</key> - <value>"dark green"</value> + <key>maxoutbuf</key> + <value>0</value> </param> <param> - <key>alpha9</key> - <value>1.0</value> + <key>minoutbuf</key> + <value>0</value> </param> <param> - <key>label10</key> - <value></value> + <key>name</key> + <value>"A noisy line"</value> </param> <param> - <key>width10</key> + <key>nconnections</key> <value>1</value> </param> <param> - <key>color10</key> - <value>"dark blue"</value> - </param> - <param> - <key>alpha10</key> - <value>1.0</value> - </param> - <param> - <key>alias</key> - <value></value> + <key>ref_level</key> + <value>0</value> </param> <param> - <key>affinity</key> - <value></value> + <key>showports</key> + <value>False</value> </param> <param> - <key>minoutbuf</key> - <value>0</value> + <key>update_time</key> + <value>0.10</value> </param> <param> - <key>maxoutbuf</key> - <value>0</value> + <key>vlen</key> + <value>veclen</value> </param> <param> - <key>_coordinate</key> - <value>(566, 136)</value> + <key>x_axis_label</key> + <value>"x-Axis"</value> </param> <param> - <key>_rotation</key> + <key>x_start</key> <value>0</value> </param> - </block> - <block> - <key>blocks_message_debug</key> <param> - <key>id</key> - <value>blocks_message_debug_0</value> + <key>x_step</key> + <value>1.0/veclen</value> </param> <param> - <key>_enabled</key> - <value>True</value> + <key>x_units</key> + <value>""</value> </param> <param> - <key>alias</key> - <value></value> + <key>ymax</key> + <value>512</value> </param> <param> - <key>affinity</key> - <value></value> + <key>ymin</key> + <value>0</value> </param> <param> - <key>_coordinate</key> - <value>(871, 204)</value> + <key>y_axis_label</key> + <value>"y-Axis"</value> </param> <param> - <key>_rotation</key> - <value>0</value> + <key>y_units</key> + <value>""</value> </param> </block> <connection> - <source_block_id>blocks_throttle_0</source_block_id> - <sink_block_id>blocks_add_xx_0</sink_block_id> + <source_block_id>analog_fastnoise_source_x_0</source_block_id> + <sink_block_id>blocks_stream_to_vector_0</sink_block_id> <source_key>0</source_key> <sink_key>0</sink_key> </connection> <connection> - <source_block_id>blocks_vector_source_x_0</source_block_id> - <sink_block_id>blocks_throttle_0</sink_block_id> + <source_block_id>blocks_add_xx_0</source_block_id> + <sink_block_id>qtgui_vector_sink_f_0</sink_block_id> <source_key>0</source_key> <sink_key>0</sink_key> </connection> <connection> - <source_block_id>analog_fastnoise_source_x_0</source_block_id> - <sink_block_id>blocks_stream_to_vector_0</sink_block_id> + <source_block_id>blocks_stream_to_vector_0</source_block_id> + <sink_block_id>blocks_add_xx_0</sink_block_id> <source_key>0</source_key> - <sink_key>0</sink_key> + <sink_key>1</sink_key> </connection> <connection> - <source_block_id>blocks_stream_to_vector_0</source_block_id> + <source_block_id>blocks_throttle_0</source_block_id> <sink_block_id>blocks_add_xx_0</sink_block_id> <source_key>0</source_key> - <sink_key>1</sink_key> + <sink_key>0</sink_key> </connection> <connection> - <source_block_id>blocks_add_xx_0</source_block_id> - <sink_block_id>qtgui_vector_sink_x_0</sink_block_id> + <source_block_id>blocks_vector_source_x_0</source_block_id> + <sink_block_id>blocks_throttle_0</sink_block_id> <source_key>0</source_key> <sink_key>0</sink_key> </connection> <connection> - <source_block_id>qtgui_vector_sink_x_0</source_block_id> + <source_block_id>qtgui_vector_sink_f_0</source_block_id> <sink_block_id>blocks_message_debug_0</sink_block_id> <source_key>xval</source_key> <sink_key>print</sink_key> |