/* -*- 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 #include #include #include /* * 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_countget_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; }