[Top][All Lists]
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
Re: [Discuss-gnuradio] Questions about gr_block
From: |
Jens Elsner |
Subject: |
Re: [Discuss-gnuradio] Questions about gr_block |
Date: |
Fri, 21 Jul 2006 20:01:29 +0200 |
User-agent: |
Mutt/1.5.9i |
Ok, never mind, my error was based on a fundamental misunderstanding of
what "io_signature" defines: I found the answer in the mailing list.
It would be great to see just a few words about this in the
"how-to-write-a-block" tutorial.
Have a nice week-end,
Jens
On Thu, Jul 20, 2006 at 12:54:25PM +0200, Jens Elsner wrote:
> Good morning!
>
> I started writing a small signal processing block (OFDM transmitter) and ran
> into some problems.
>
> My starting point was the well written gr-how-to-write-a-block tutorial.
>
> I have, let's say, 1536 input samples and want to produce 1800 output
> samples with my block. When I run my code with small values
> (say fft size of 32) I get valid OFDM symbols but a lot of zeros in
> between. When I uses higher values either the scheduler quits
>
> (
> sched: <gr_block ofdm_tx_vcc (0)> is
> requesting more input data
> than we can provide.
> )
>
> or even the buffer can't be allocated. This makes me sure that there is
> a programming mistake on my part, but I can't seem to find it.
> I would be thankful if somebody could point out my mistake? The main
> files are attached, a modified gr-how-to-build-a-block can be found here:
> http://www.1c3.de/gr-dab.tar.bz2 .
>
> Yet another question: Can blocks somehow interchange values? I would
> like to write two blocks, one that estimates a frequency offset and
> another one that compensates it (simple modulation). Or do I have to
> do that in one block?
>
> Jens
>
> /* -*- c++ -*- */
>
> %feature("autodoc", "1"); // generate python docstrings
>
> %include "exception.i"
> %import "gnuradio.i" // the common stuff
>
> %{
> #include "gnuradio_swig_bug_workaround.h" // mandatory bug fix
> #include "ofdm_tx_cc.h"
> #include <stdexcept>
> %}
>
> // ----------------------------------------------------------------
>
> /*
> * First arg is the package prefix.
> * Second arg is the name of the class minus the prefix.
> *
> * This does some behind-the-scenes magic so we can
> * access howto_square_ff from python as howto.square_ff
> */
> GR_SWIG_BLOCK_MAGIC(ofdm,tx_cc);
>
> ofdm_tx_cc_sptr ofdm_do_tx_cc (int ofdm_sym_len, int gi_len, int fft_len);
>
> class ofdm_tx_cc : public gr_sync_block
> {
> private:
> ofdm_tx_cc (int ofdm_sym_len, int gi_len, int fft_len);
> };
>
> /* -*- c++ -*- */
> /*
> * Copyright 2004 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 2, 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., 59 Temple Place - Suite 330,
> * Boston, MA 02111-1307, USA.
> */
>
> /*
> * config.h is generated by configure. It contains the results
> * of probing for features, options etc. It should be the first
> * file included in your .cc file.
> */
> #ifdef HAVE_CONFIG_H
> #include "config.h"
> #endif
>
> #include <ofdm_tx_cc.h>
> #include <gr_io_signature.h>
>
> #include <gri_fft.h>
> #include <math.h>
>
> /*
> * Create a new instance of gr_ofdm_tx_cc and return
> * a boost shared_ptr. This is effectively the public constructor.
> */
> ofdm_tx_cc_sptr
> ofdm_do_tx_cc (int ofdm_sym_len, int gi_len, int fft_len)
> {
> return ofdm_tx_cc_sptr (new ofdm_tx_cc (ofdm_sym_len, gi_len, fft_len));
> }
>
> /*
> * Specify constraints on number of input and output streams.
> * This info is used to construct the input and output signatures
> * (2nd & 3rd args to gr_block's constructor). The input and
> * output signatures are used by the runtime system to
> * check that a valid number and type of inputs and outputs
> * are connected to this block. In this case, we accept
> * only 1 input and 1 output.
> */
> static const int MIN_IN = 1; // mininum number of input streams
> static const int MAX_IN = 1; // maximum number of input streams
> static const int MIN_OUT = 1; // minimum number of output streams
> static const int MAX_OUT = 1; // maximum number of output streams
>
> /*
> * The private constructor
> * Takes length of OFDM symbol (including guard interval) and guard interval
> length as
> * arguments. Variable FFT length and subcarrier selection mask is
> implemented later.
> */
> ofdm_tx_cc::ofdm_tx_cc (int ofdm_sym_len, int gi_len, int fft_len)
> : gr_block ("ofdm_tx_vcc",
> gr_make_io_signature (MIN_IN, MAX_IN,
> (ofdm_sym_len-gi_len)*sizeof(gr_complex)),
> gr_make_io_signature (MIN_OUT, MAX_OUT, ofdm_sym_len *
> sizeof(gr_complex)))
> {
> d_ofdm_sym_len = ofdm_sym_len;
> d_gi_len = gi_len;
> d_fft_len = ofdm_sym_len-gi_len; // FIXME: not yet implemented
>
> // OFDM symbols can't be split, contrain request size
> set_output_multiple(d_ofdm_sym_len);
>
> // set approximate out rate
> set_relative_rate((double)(d_ofdm_sym_len) /
> (double)(d_ofdm_sym_len-d_gi_len));
>
> d_fft = new gri_fft_complex(d_fft_len, true);
> }
>
> /*
> * Our virtual destructor.
> */
> ofdm_tx_cc::~ofdm_tx_cc ()
> {
> delete d_fft;
> }
>
> /*
> * Implementation of gr_block::forecast() - estimate the number of input
> samples, if we are asked to
> * output noutput_items samples.
> */
> void
> ofdm_tx_cc::forecast (int noutput_items, gr_vector_int
> &ninput_items_required)
> {
> // noutput_items should be a multiple of d_ofdm_sym_len (see
> constructor)
> assert ((noutput_items % d_ofdm_sym_len) == 0);
>
> int nblocks = noutput_items / d_ofdm_sym_len;
> int input_required = nblocks * (d_ofdm_sym_len-d_gi_len);
>
> unsigned ninputs = ninput_items_required.size();
> for (unsigned int i = 0; i < ninputs; i++)
> ninput_items_required[i] = input_required;
> }
>
>
> /*
> * Here the actual work is done - "d_ofdm_sym_len-d_gi_len" complex samples
> are consumed and
> * "d_ofdm_sym_len" samples are written.
> */
>
> int
> ofdm_tx_cc::general_work (int noutput_items,
> gr_vector_int &ninput_items,
> gr_vector_const_void_star &input_items,
> gr_vector_void_star &output_items)
> {
> // pointers to data
> const gr_complex *in = (const gr_complex *) input_items[0];
> gr_complex *out = (gr_complex *) output_items[0];
>
> int out_count=0; // counts the number of written complex samples
> int in_count=0; // counts number of samples consumed
>
> printf("available in (samples): %i\n", ninput_items[0]);
> printf("requested out (samples): %i\n", noutput_items);
>
> while(out_count<noutput_items)
> {
> memcpy(d_fft->get_inbuf(), in, d_fft_len*sizeof(gr_complex)); // copy
> to input buffer
> d_fft->execute(); // compute fft
> // cyclic prefix is repetition of the end in the beginning
> memcpy(out, d_fft->get_outbuf()+(d_fft_len-d_gi_len),
> d_gi_len*sizeof(gr_complex)); // guard interval; last argument of memcpy is
> length in bytes
> memcpy(out+d_gi_len, d_fft->get_outbuf(),
> d_fft_len*sizeof(gr_complex)); // copy data
>
> // increase pointers, counters
> in += d_ofdm_sym_len-d_gi_len;
> out += d_ofdm_sym_len;
> out_count += d_ofdm_sym_len;
> in_count += d_ofdm_sym_len-d_gi_len;
> }
>
> // noutput_items should always be a multiple of d_ofdm_sym_len, so the
> assert shouldn't fail now
> assert (out_count == noutput_items);
>
> // Tell runtime system how many input items we consumed.
> consume_each(in_count);
>
> // Tell runtime system how many output items we produced.
> return out_count;
> }
>
> /* -*- c++ -*- */
> /*
> * Copyright 2004 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 2, 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., 59 Temple Place - Suite 330,
> * Boston, MA 02111-1307, USA.
> */
> #ifndef INCLUDED_OFDM_TX_CC_H
> #define INCLUDED_OFDM_TX_CC_H
>
> #include <gr_block.h>
>
> class gri_fft_complex;
>
> class ofdm_tx_cc;
>
> /*
> * We use boost::shared_ptr's instead of raw pointers for all access
> * to gr_blocks (and many other data structures). The shared_ptr gets
> * us transparent reference counting, which greatly simplifies storage
> * management issues. This is especially helpful in our hybrid
> * C++ / Python system.
> *
> * See http://www.boost.org/libs/smart_ptr/smart_ptr.htm
> *
> * As a convention, the _sptr suffix indicates a boost::shared_ptr
> */
> typedef boost::shared_ptr<ofdm_tx_cc> ofdm_tx_cc_sptr;
>
> /*!
> * \brief Return a shared_ptr to a new instance of howto_square2_ff.
> *
> * To avoid accidental use of raw pointers, howto_square2_ff's
> * constructor is private. howto_make_square2_ff is the public
> * interface for creating new instances.
> */
> ofdm_tx_cc_sptr ofdm_do_tx_cc ();
>
> /*!
> * \brief OFDM transmitter.
> * \ingroup block
> *
> * A simple OFDM transmitter block.
> */
> class ofdm_tx_cc : public gr_block
> {
> private:
> // The friend declaration allows ofdm_do_tx_cc to
> // access the private constructor.
>
> friend ofdm_tx_cc_sptr ofdm_do_tx_cc (int ofdm_sym_len, int gi_len, int
> fft_len);
>
> ofdm_tx_cc (int ofdm_sym_len, int gi_len, int fft_len); // private
> constructor
>
> unsigned int d_ofdm_sym_len;
> unsigned int d_gi_len;
> unsigned int d_fft_len;
> gri_fft_complex *d_fft;
>
> public:
> ~ofdm_tx_cc (); // public destructor
>
> // Where all the action really happens
>
> int general_work (int noutput_items,
> gr_vector_int &ninput_items,
> gr_vector_const_void_star &input_items,
> gr_vector_void_star &output_items);
>
> void forecast(int noutput_items, gr_vector_int &ninput_items_required);
>
> };
>
> #endif /* INCLUDED_OFDM_TX_H */
> #!/usr/bin/env python
> #
> # Copyright 2004 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 2, 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., 59 Temple Place - Suite 330,
> # Boston, MA 02111-1307, USA.
> #
>
> from gnuradio import gr, gr_unittest
> import ofdm, inspect
>
> class qa_ofdm (gr_unittest.TestCase):
>
> def setUp (self):
> self.fg = gr.flow_graph ()
>
> def tearDown (self):
> self.fg = None
>
> def test_001_square_ff (self):
>
> fft_len = 32 # fails for higher values (eg. 512)
> gi_len = 4
> ofdm_sym_len = fft_len+gi_len;
> ofdm_tx = ofdm.ofdm_do_tx_cc (ofdm_sym_len, gi_len, 0)
> print ofdm_tx.output_multiple()
> print ofdm_tx.relative_rate()
>
> s2p = gr.serial_to_parallel (gr.sizeof_gr_complex, fft_len)
> p2s = gr.parallel_to_serial (gr.sizeof_gr_complex, ofdm_sym_len)
>
> dst = gr.file_sink(gr.sizeof_gr_complex, "ofdm_sym_out")
>
> SNR=10
> src = gr.noise_source_c(gr.GR_GAUSSIAN, pow(10.0,-SNR/20.0))
>
> self.fg.connect(src, s2p)
> self.fg.connect(s2p, ofdm_tx)
> self.fg.connect(ofdm_tx, p2s)
> self.fg.connect(p2s, dst)
>
> self.fg.run()
>
> if __name__ == '__main__':
> gr_unittest.main ()
> _______________________________________________
> Discuss-gnuradio mailing list
> address@hidden
> http://lists.gnu.org/mailman/listinfo/discuss-gnuradio