From 6d12b9859ff0d51578524a62781792a33b174a6c Mon Sep 17 00:00:00 2001 From: Igor Almeida Date: Wed, 25 May 2011 12:08:55 -0300 Subject: [PATCH] Add a cyclic extender to gr This is similar to gr_ofdm_cyclic_prefixer, but adds cyclic suffix and symbol overlapping if instructed to do so. The functionality is based on VDSL standard, ITU-T recommendation G.993.1 section 9.2.2. There is a problem with the approach, though. With overlap>0, the overlapping suffix will only be sent after added to the next symbol's prefix. This means the last symbol will have 'overlap' less samples as it should. I'm missing some kind of signal to notify the block to include the last samples when there are no more vectors in the input. --- gnuradio-core/src/lib/general/Makefile.am | 3 + gnuradio-core/src/lib/general/general.i | 2 + .../src/lib/general/gr_dmt_cyclic_extender.cc | 113 ++++++++++++++++++++ .../src/lib/general/gr_dmt_cyclic_extender.h | 63 +++++++++++ .../src/lib/general/gr_dmt_cyclic_extender.i | 34 ++++++ gnuradio-core/src/python/gnuradio/gr/Makefile.am | 1 + .../python/gnuradio/gr/qa_dmt_cyclic_extender.py | 57 ++++++++++ 7 files changed, 273 insertions(+), 0 deletions(-) create mode 100644 gnuradio-core/src/lib/general/gr_dmt_cyclic_extender.cc create mode 100644 gnuradio-core/src/lib/general/gr_dmt_cyclic_extender.h create mode 100644 gnuradio-core/src/lib/general/gr_dmt_cyclic_extender.i create mode 100644 gnuradio-core/src/python/gnuradio/gr/qa_dmt_cyclic_extender.py diff --git a/gnuradio-core/src/lib/general/Makefile.am b/gnuradio-core/src/lib/general/Makefile.am index 3d8a428..37ec8d9 100644 --- a/gnuradio-core/src/lib/general/Makefile.am +++ b/gnuradio-core/src/lib/general/Makefile.am @@ -175,6 +175,7 @@ libgeneral_la_SOURCES = \ gr_descrambler_bb.cc \ gr_scrambler_bb.cc \ gr_probe_mpsk_snr_c.cc \ + gr_dmt_cyclic_extender.cc \ gr_probe_density_b.cc libgeneral_qa_la_SOURCES = \ @@ -344,6 +345,7 @@ grinclude_HEADERS = \ gr_descrambler_bb.h \ gr_scrambler_bb.h \ gr_probe_mpsk_snr_c.h \ + gr_dmt_cyclic_extender.h \ gr_probe_density_b.h noinst_HEADERS = \ @@ -484,5 +486,6 @@ swiginclude_HEADERS = \ gr_descrambler_bb.i \ gr_scrambler_bb.i \ gr_probe_mpsk_snr_c.i \ + gr_dmt_cyclic_extender.i \ gr_probe_density_b.i endif diff --git a/gnuradio-core/src/lib/general/general.i b/gnuradio-core/src/lib/general/general.i index 68cafce..58b1daa 100644 --- a/gnuradio-core/src/lib/general/general.i +++ b/gnuradio-core/src/lib/general/general.i @@ -141,6 +141,7 @@ #include #include #include +#include %} %include "gr_nop.i" @@ -262,3 +263,4 @@ %include "gr_copy.i" %include "gr_fll_band_edge_cc.i" %include "gr_additive_scrambler_bb.i" +%include "gr_dmt_cyclic_extender.i" diff --git a/gnuradio-core/src/lib/general/gr_dmt_cyclic_extender.cc b/gnuradio-core/src/lib/general/gr_dmt_cyclic_extender.cc new file mode 100644 index 0000000..f9b3ac2 --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_dmt_cyclic_extender.cc @@ -0,0 +1,113 @@ +/* -*- c++ -*- */ +/* + * Copyright 2004,2006 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. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include +#include + +#include +#include + +gr_dmt_cyclic_extender_sptr +gr_make_dmt_cyclic_extender (size_t input_size, unsigned int symbol_size, unsigned int prefix_size, unsigned int suffix_size, unsigned int overlap) +{ + return gr_dmt_cyclic_extender_sptr (new gr_dmt_cyclic_extender (input_size, symbol_size, prefix_size, suffix_size, overlap)); +} + +gr_dmt_cyclic_extender::gr_dmt_cyclic_extender (size_t input_size, unsigned int symbol_size, unsigned int prefix_size, unsigned int suffix_size, unsigned int overlap) + : gr_sync_interpolator ("dmt_cyclic_extender", + gr_make_io_signature (1, 1, input_size*symbol_size), + gr_make_io_signature (1, 1, input_size), + symbol_size + prefix_size + suffix_size - overlap), + d_input_size(input_size), + d_symbol_size(symbol_size), + d_prefix_size(prefix_size), + d_suffix_size(suffix_size), + d_overlap(overlap), + d_extended_size(symbol_size + prefix_size + suffix_size - overlap) +{ + d_overlapped_part = calloc(overlap, d_input_size); + if (d_overlapped_part == NULL) { + throw std::bad_alloc(); + } +} + +int +gr_dmt_cyclic_extender::work (int noutput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items) +{ + const char *in = (const char *) input_items[0]; + char *out = (char *) output_items[0]; + + //TODO windowing + + //create prefix from last samples + memcpy(out, + in + (d_symbol_size - d_prefix_size)*d_input_size, + d_prefix_size*d_input_size); + //add overlapped part + gr_complex *s, *ovc; + float *f, *ovf; + void *element; + for (unsigned int i = 0; i < d_overlap; i++) { + element = out + i*d_input_size; + + switch (d_input_size) { + case sizeof(gr_complex): + ovc = (gr_complex*) d_overlapped_part; + s = (gr_complex*) element; + *s += ovc[i]; + break; + case sizeof(float): + ovf = (float*) d_overlapped_part; + f = (float*) element; + *f += ovf[i]; + break; + default: + assert(0); + } + } + + //copy main symbol + memcpy(out + d_prefix_size*d_input_size, + in, + d_symbol_size*d_input_size); + + //create suffix from first samples + memcpy(out + (d_prefix_size + d_symbol_size)*d_input_size, + in, + d_suffix_size*d_input_size); + //update overlapped part + memcpy(d_overlapped_part, + out + d_extended_size*d_input_size, + d_overlap*d_input_size); + + return d_extended_size; +} + +gr_dmt_cyclic_extender::~gr_dmt_cyclic_extender () { + free(d_overlapped_part); +} diff --git a/gnuradio-core/src/lib/general/gr_dmt_cyclic_extender.h b/gnuradio-core/src/lib/general/gr_dmt_cyclic_extender.h new file mode 100644 index 0000000..345a778 --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_dmt_cyclic_extender.h @@ -0,0 +1,63 @@ +/* -*- c++ -*- */ +/* + * Copyright 2004,2005,2006 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. + */ + +#ifndef INCLUDED_GR_DMT_CYCLIC_EXTENDER_H +#define INCLUDED_GR_DMT_CYCLIC_EXTENDER_H + +#include + +class gr_dmt_cyclic_extender; +typedef boost::shared_ptr gr_dmt_cyclic_extender_sptr; + +gr_dmt_cyclic_extender_sptr +gr_make_dmt_cyclic_extender (size_t input_size, unsigned int symbol_size, unsigned int prefix_size, unsigned int suffix_size, unsigned int overlap); + + +/*! + * \brief adds a cyclic prefix and a cyclic suffix vector to an symbol_size long + * ofdm symbol(vector) and converts vector to a stream with given symbol overlap. + * \ingroup ofdm_blk + */ +class gr_dmt_cyclic_extender : public gr_sync_interpolator +{ + friend gr_dmt_cyclic_extender_sptr + gr_make_dmt_cyclic_extender (size_t input_size, unsigned int symbol_size, unsigned int prefix_size, unsigned int suffix_size, unsigned int overlap); + + protected: + gr_dmt_cyclic_extender (size_t input_size, unsigned int symbol_size, unsigned int prefix_size, unsigned int suffix_size, unsigned int overlap); + + public: + int work (int noutput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items); + ~gr_dmt_cyclic_extender (); + private: + size_t d_input_size; + unsigned int d_symbol_size; + unsigned int d_prefix_size; + unsigned int d_suffix_size; + unsigned int d_overlap; + unsigned int d_extended_size; + void *d_overlapped_part; +}; + +#endif /* INCLUDED_GR_DMT_CYCLIC_EXTENDER_H */ diff --git a/gnuradio-core/src/lib/general/gr_dmt_cyclic_extender.i b/gnuradio-core/src/lib/general/gr_dmt_cyclic_extender.i new file mode 100644 index 0000000..1b45d75 --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_dmt_cyclic_extender.i @@ -0,0 +1,34 @@ +/* -*- c++ -*- */ +/* + * Copyright 2006,2009 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. + */ + +GR_SWIG_BLOCK_MAGIC(gr,dmt_cyclic_extender) + +gr_dmt_cyclic_extender_sptr +gr_make_dmt_cyclic_extender (size_t input_size, unsigned int symbol_size, unsigned int prefix_size, unsigned int suffix_size, unsigned int overlap); + +class gr_dmt_cyclic_extender : public gr_sync_interpolator +{ + protected: + gr_dmt_cyclic_extender (size_t input_size, unsigned int symbol_size, unsigned int prefix_size, unsigned int suffix_size, unsigned int overlap); + + public: +}; diff --git a/gnuradio-core/src/python/gnuradio/gr/Makefile.am b/gnuradio-core/src/python/gnuradio/gr/Makefile.am index 341f588..252b55f 100644 --- a/gnuradio-core/src/python/gnuradio/gr/Makefile.am +++ b/gnuradio-core/src/python/gnuradio/gr/Makefile.am @@ -98,4 +98,5 @@ noinst_PYTHON = \ qa_repeat.py \ qa_scrambler.py \ qa_udp_sink_source.py \ + qa_dmt_cyclic_extender.py \ qa_vector_sink_source.py diff --git a/gnuradio-core/src/python/gnuradio/gr/qa_dmt_cyclic_extender.py b/gnuradio-core/src/python/gnuradio/gr/qa_dmt_cyclic_extender.py new file mode 100644 index 0000000..4975e63 --- /dev/null +++ b/gnuradio-core/src/python/gnuradio/gr/qa_dmt_cyclic_extender.py @@ -0,0 +1,57 @@ +#!/usr/bin/env python +# +# Copyright 2008 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 + +class test_cyclic_extender(gr_unittest.TestCase): + + def setUp (self): + self.tb = gr.top_block() + + def tearDown (self): + self.tb = None + + def test_001_cyclic_extender (self): + cpSize = 4 + csSize = 3 + overlap = 2 + + src_data = (1, 2, 3, 4, 5, + 10, 20, 30, 40, 50) + expected_result = (2, 3, 4, 5, 1, 2, 3, 4, 5, 1, 22, 33, + 40, 50, 10, 20, 30, 40, 50, 10) #last 'overlap' samples won't come + + vectorsize = 5 + + src = gr.vector_source_f(src_data, vlen=vectorsize) + ce = gr.dmt_cyclic_extender(gr.sizeof_float, vectorsize, cpSize, csSize, overlap) + dst = gr.vector_sink_f () + + self.tb.connect(src, ce) + self.tb.connect(ce, dst) + self.tb.run() + + result_data = dst.data() + self.assertComplexTuplesAlmostEqual(expected_result, result_data) + +if __name__ == '__main__': + gr_unittest.main() -- 1.7.0.4