discuss-gnuradio
[Top][All Lists]
Advanced

[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





reply via email to

[Prev in Thread] Current Thread [Next in Thread]