summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTim O'Shea <tim.oshea753@gmail.com>2013-06-06 16:15:52 -0400
committerTim O'Shea <tim.oshea753@gmail.com>2013-06-06 16:15:52 -0400
commit9896a6727bc1446e0597ad51cc4305acfb46ff1b (patch)
treeab6fcc2f599d65ef1c46e2f2e1a78cf67068985f
parent553c06df3dcc913219e6462131861a937acb8b5e (diff)
channels: new frequency selective fading block
-rw-r--r--gr-channels/grc/CMakeLists.txt1
-rw-r--r--gr-channels/grc/channels_selective_fading_model.xml95
-rw-r--r--gr-channels/include/gnuradio/channels/CMakeLists.txt1
-rw-r--r--gr-channels/include/gnuradio/channels/selective_fading_model.h82
-rw-r--r--gr-channels/lib/CMakeLists.txt2
-rw-r--r--gr-channels/lib/fading_model_impl.cc83
-rw-r--r--gr-channels/lib/fading_model_impl.h44
-rw-r--r--gr-channels/lib/flat_fader_impl.cc117
-rw-r--r--gr-channels/lib/flat_fader_impl.h82
-rw-r--r--gr-channels/lib/selective_fading_model_impl.cc169
-rw-r--r--gr-channels/lib/selective_fading_model_impl.h79
-rw-r--r--gr-channels/lib/sincostable.h3
-rw-r--r--gr-channels/swig/channels_swig.i3
13 files changed, 644 insertions, 117 deletions
diff --git a/gr-channels/grc/CMakeLists.txt b/gr-channels/grc/CMakeLists.txt
index cbbf75901c..3bda29f01d 100644
--- a/gr-channels/grc/CMakeLists.txt
+++ b/gr-channels/grc/CMakeLists.txt
@@ -21,6 +21,7 @@ install(FILES
channels_block_tree.xml
channels_channel_model.xml
channels_fading_model.xml
+ channels_selective_fading_model.xml
DESTINATION ${GRC_BLOCKS_DIR}
COMPONENT "channels_python"
)
diff --git a/gr-channels/grc/channels_selective_fading_model.xml b/gr-channels/grc/channels_selective_fading_model.xml
new file mode 100644
index 0000000000..2d29a477ae
--- /dev/null
+++ b/gr-channels/grc/channels_selective_fading_model.xml
@@ -0,0 +1,95 @@
+<?xml version="1.0"?>
+<!--
+###################################################
+##Frequency Selective Fading Model
+###################################################
+ -->
+<block>
+ <name>Frequency Selective Fading Model</name>
+ <key>channels_selective_fading_model</key>
+ <import>from gnuradio import channels</import>
+ <make>channels.selective_fading_model( $N, $fDTs, $LOS, $K, $seed, $delays, $mags, $ntaps )</make>
+ <callback>set_fDTs($fDTs)</callback>
+ <callback>set_K($K)</callback>
+ <param>
+ <name>Num Sinusoids (SoS model)</name>
+ <key>N</key>
+ <value>8</value>
+ <type>int</type>
+ </param>
+ <param>
+ <name>Normalized Max Doppler (fD*Ts)</name>
+ <key>fDTs</key>
+ <value>10.0/samp_rate</value>
+ <type>real</type>
+ </param>
+ <param>
+ <name>LOS Model</name>
+ <key>LOS</key>
+ <type>enum</type>
+ <option>
+ <name>Rayleigh/NLOS</name>
+ <key>False</key>
+ <opt>hide_K:all</opt>
+ </option>
+ <option>
+ <name>Rician/LOS</name>
+ <key>True</key>
+ <opt>hide_K:</opt>
+ </option>
+ </param>
+ <param>
+ <name>Rician factor (K)</name>
+ <key>K</key>
+ <value>4.0</value>
+ <type>real</type>
+ <hide>$LOS.hide_K</hide>
+ </param>
+ <param>
+ <name>Seed</name>
+ <key>seed</key>
+ <value>0</value>
+ <type>int</type>
+ </param>
+ <param>
+ <name>PDP Delays (samp)</name>
+ <key>delays</key>
+ <value>3.1,3.25,3.78</value>
+ <type>float_vector</type>
+ </param>
+ <param>
+ <name>PDP Magnitudes</name>
+ <key>mags</key>
+ <value>1,0.99,0.97</value>
+ <type>float_vector</type>
+ </param>
+ <param>
+ <name>Num Taps</name>
+ <key>ntaps</key>
+ <value>8</value>
+ <type>int</type>
+ </param>
+ <sink>
+ <name>in</name>
+ <type>complex</type>
+ </sink>
+ <source>
+ <name>out</name>
+ <type>complex</type>
+ </source>
+ <doc>
+ This algorithm implements the method described in
+ Compact Rayleigh and Rician fading simulator based on random walk processes
+ A. Alimohammad S.F. Fard B.F. Cockburn C. Schlegel
+ 26th November 2008
+
+ int d_N=8; // number of sinusoids
+ float d_fDTs=0.01 // normalized maximum doppler frequency (f_doppler / f_samprate)
+ float d_K=4; // Rician factor (ratio of the specular power to the scattered power)
+ bool d_LOS=true; // LOS path exists? chooses Rician (LOS) vs Rayleigh (NLOS) model.
+ int seed=0; // noise seed
+
+ If using a LOS model, the first delay and mag should correspond with the LOS component
+
+ </doc>
+</block>
diff --git a/gr-channels/include/gnuradio/channels/CMakeLists.txt b/gr-channels/include/gnuradio/channels/CMakeLists.txt
index c0c70e2b00..f9a535b9c0 100644
--- a/gr-channels/include/gnuradio/channels/CMakeLists.txt
+++ b/gr-channels/include/gnuradio/channels/CMakeLists.txt
@@ -24,6 +24,7 @@ install(FILES
api.h
channel_model.h
fading_model.h
+ selective_fading_model.h
DESTINATION ${GR_INCLUDE_DIR}/gnuradio/channels
COMPONENT "channels_devel"
)
diff --git a/gr-channels/include/gnuradio/channels/selective_fading_model.h b/gr-channels/include/gnuradio/channels/selective_fading_model.h
new file mode 100644
index 0000000000..c68328d2d7
--- /dev/null
+++ b/gr-channels/include/gnuradio/channels/selective_fading_model.h
@@ -0,0 +1,82 @@
+/* -*- c++ -*- */
+/*
+ * Copyright 2013 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_CHANNELS_SELECTIVE_FADING_MODEL_H
+#define INCLUDED_CHANNELS_SELECTIVE_FADING_MODEL_H
+
+#include <gnuradio/channels/api.h>
+#include <gnuradio/sync_block.h>
+#include <gnuradio/types.h>
+
+namespace gr {
+ namespace channels {
+
+ const float default_delays[] = {0.0,0.1,0.5};
+ const float default_mags[] = {1.0,0.8,0.3};
+
+ /*!
+ * \brief fading simulator
+ * \ingroup channel_models_blk
+ *
+ * \details
+ * This block implements a basic fading model simulator that can
+ * be used to help evaluate, design, and test various signals,
+ * waveforms, and algorithms.
+ */
+ class CHANNELS_API selective_fading_model : virtual public sync_block
+ {
+ public:
+ // gr::channels::channel_model::sptr
+ typedef boost::shared_ptr<selective_fading_model> sptr;
+
+ /*! \brief Build the channel simulator.
+ *
+ * \param N The number of sinusiods to use in simulating the channel 8 is a good value
+ * \param fDTs normalized maximum doppler frequency, fD * Ts
+ * \param LOS include Line-of-Site path? selects between Rayleigh (NLOS) and Rician (LOS) models
+ * \param K Rician factor (ratio of the specular power to the scattered power)
+ * \param seed a random number to seed the noise generators
+ */
+ static sptr make(unsigned int N,
+ float fDTs,
+ bool LOS,
+ float K,
+ int seed,
+ std::vector<float> delays,
+ std::vector<float> mags,
+ int ntaps
+ );
+
+ virtual float fDTs() = 0;
+ virtual float K() = 0;
+ virtual float step() = 0;
+
+ virtual void set_fDTs(float fDTs) = 0;
+ virtual void set_K(float K) = 0;
+ virtual void set_step(float step) = 0;
+
+ };
+
+ } /* namespace channels */
+} /* namespace gr */
+
+#endif /* INCLUDED_CHANNELS_SELECTIVE_FADING_MODEL_H */
diff --git a/gr-channels/lib/CMakeLists.txt b/gr-channels/lib/CMakeLists.txt
index bd0151143d..46c90671c2 100644
--- a/gr-channels/lib/CMakeLists.txt
+++ b/gr-channels/lib/CMakeLists.txt
@@ -44,6 +44,8 @@ endif(ENABLE_GR_CTRLPORT)
list(APPEND channels_sources
channel_model_impl.cc
fading_model_impl.cc
+ selective_fading_model_impl.cc
+ flat_fader_impl.cc
)
#Add Windows DLL resource file if using MSVC
diff --git a/gr-channels/lib/fading_model_impl.cc b/gr-channels/lib/fading_model_impl.cc
index a39a6cf44f..4ea4d1274e 100644
--- a/gr-channels/lib/fading_model_impl.cc
+++ b/gr-channels/lib/fading_model_impl.cc
@@ -50,37 +50,8 @@ namespace gr {
: sync_block("fading_model",
io_signature::make(1, 1, sizeof(gr_complex)),
io_signature::make(1, 1, sizeof(gr_complex))),
- seed_1((int)seed),
- dist_1(-M_PI, M_PI),
- rv_1( seed_1, dist_1 ), // U(-pi,pi)
-
- seed_2((int)seed+1),
- dist_2(0, 1),
- rv_2( seed_2, dist_2 ), // U(0,1)
-
- d_N(N),
- d_fDTs(fDTs),
- d_theta(rv_1()),
- d_theta_los(rv_1()),
- d_step( powf(0.00125*fDTs, 1.1) ), // max step size approximated from Table 2
- d_m(0),
- d_K(K),
- d_LOS(LOS),
-
- d_psi(d_N+1, 0),
- d_phi(d_N+1, 0),
-
- d_table(8*1024),
-
- scale_sin(sqrtf(2.0/d_N)),
- scale_los(sqrtf(d_K)/sqrtf(d_K+1)),
- scale_nlos(1/sqrtf(d_K+1))
+ d_fader(N,fDTs, LOS, K, seed)
{
- // generate initial phase values
- for(int i=0; i<d_N+1; i++){
- d_psi[i] = rv_1();
- d_phi[i] = rv_1();
- }
}
fading_model_impl::~fading_model_impl()
@@ -138,17 +109,6 @@ namespace gr {
#endif /* GR_CTRLPORT */
}
- void
- fading_model_impl::update_theta()
- {
- d_theta += (d_step*rv_2());
- if(d_theta > M_PI){
- d_theta = M_PI; d_step = -d_step;
- } else if(d_theta < -M_PI){
- d_theta = -M_PI; d_step = -d_step;
- }
- }
-
int
fading_model_impl::work (int noutput_items,
gr_vector_const_void_star &input_items,
@@ -156,48 +116,9 @@ namespace gr {
{
const gr_complex* in = (const gr_complex*) input_items[0];
gr_complex* out = (gr_complex*) output_items[0];
-
for(int i=0; i<noutput_items; i++){
- gr_complex H(0,0);
-
- for(int n=1; n<d_N; n++){
- float alpha_n = (2*M_PI*n - M_PI + d_theta)/4*d_N;
-#if FASTSINCOS == 1
- float s_i = scale_sin*gr::fxpt::cos(gr::fxpt::float_to_fixed(2*M_PI*d_fDTs*d_m*gr::fxpt::cos(gr::fxpt::float_to_fixed(alpha_n))+d_psi[n+1]));
- float s_q = scale_sin*gr::fxpt::cos(gr::fxpt::float_to_fixed(2*M_PI*d_fDTs*d_m*gr::fxpt::sin(gr::fxpt::float_to_fixed(alpha_n))+d_phi[n+1]));
-#elif FASTSINCOS == 2
- float s_i = scale_sin*d_table.cos(2*M_PI*d_fDTs*d_m*d_table.cos(alpha_n)+d_psi[n+1]);
- float s_q = scale_sin*d_table.cos(2*M_PI*d_fDTs*d_m*d_table.sin(alpha_n)+d_phi[n+1]);
-
-#else
- float s_i = scale_sin*cos(2*M_PI*d_fDTs*d_m*cos(alpha_n)+d_psi[n+1]);
- float s_q = scale_sin*cos(2*M_PI*d_fDTs*d_m*sin(alpha_n)+d_phi[n+1]);
-#endif
-
- H += gr_complex(s_i, s_q);
- }
-
- if(d_LOS){
-#if FASTSINCOS == 1
- float los_i = gr::fxpt::cos(gr::fxpt::float_to_fixed(2*M_PI*d_fDTs*d_m*gr::fxpt::cos(gr::fxpt::float_to_fixed(d_theta_los)) + d_psi[0]));
- float los_q = gr::fxpt::sin(gr::fxpt::float_to_fixed(2*M_PI*d_fDTs*d_m*gr::fxpt::cos(gr::fxpt::float_to_fixed(d_theta_los)) + d_psi[0]));
-#elif FASTSINCOS == 2
- float los_i = d_table.cos(2*M_PI*d_fDTs*d_m*d_table.cos(d_theta_los) + d_psi[0]);
- float los_q = d_table.sin(2*M_PI*d_fDTs*d_m*d_table.cos(d_theta_los) + d_psi[0]);
-#else
- float los_i = cos(2*M_PI*d_fDTs*d_m*cos(d_theta_los) + d_psi[0]);
- float los_q = sin(2*M_PI*d_fDTs*d_m*cos(d_theta_los) + d_psi[0]);
-#endif
-
- H = H*scale_nlos + gr_complex(los_i,los_q)*scale_los;
- }
-
- out[i] = in[i]*H;
- d_m++;
- update_theta();
-
+ out[i] = in[i] * d_fader.next_sample();
}
-
return noutput_items;
}
diff --git a/gr-channels/lib/fading_model_impl.h b/gr-channels/lib/fading_model_impl.h
index 3b816b6679..cba992958d 100644
--- a/gr-channels/lib/fading_model_impl.h
+++ b/gr-channels/lib/fading_model_impl.h
@@ -25,6 +25,7 @@
#include <gnuradio/sync_block.h>
#include <gnuradio/channels/fading_model.h>
+#include "flat_fader_impl.h"
//#include <iostream>
#include <boost/format.hpp>
@@ -39,36 +40,7 @@ namespace gr {
class CHANNELS_API fading_model_impl : public fading_model
{
private:
- // initial theta variate generator
- boost::mt19937 seed_1;
- boost::uniform_real<> dist_1; // U(-pi,pi)
- boost::variate_generator<boost::mt19937&, boost::uniform_real<> > rv_1;
-
- // random walk variate
- boost::mt19937 seed_2;
- boost::uniform_real<> dist_2; // U(-pi,pi)
- boost::variate_generator<boost::mt19937&, boost::uniform_real<> > rv_2;
-
- int d_N; // number of sinusoids
- float d_fDTs; // normalized maximum doppler frequency
- double d_theta; // random walk variable (RWP)
- float d_theta_los;
- float d_step; // maximum random walk step size
- uint64_t d_m; // sample counter
-
- float d_K; // Rician factor (ratio of the specular power to the scattered power)
- bool d_LOS; // LOS path exists? chooses Rician (LOS) vs Rayleigh (NLOS) model.
-
- std::vector<float> d_psi; // in-phase initial phase
- std::vector<float> d_phi; // quadrature initial phase
-
- std::vector<float> d_costable;
-
- sincostable d_table;
-
- float scale_sin, scale_los, scale_nlos;
-
- void update_theta();
+ gr::channels::flat_fader_impl d_fader;
public:
fading_model_impl(unsigned int N, float fDTs, bool LOS, float K, int seed);
@@ -78,13 +50,13 @@ namespace gr {
gr_vector_const_void_star &input_items,
gr_vector_void_star &output_items);
- virtual float fDTs(){ return d_fDTs; }
- virtual float K(){ return d_K; }
- virtual float step(){ return d_step; }
+ virtual float fDTs(){ return d_fader.d_fDTs; }
+ virtual float K(){ return d_fader.d_K; }
+ virtual float step(){ return d_fader.d_step; }
- virtual void set_fDTs(float fDTs){ d_fDTs = fDTs; d_step = powf(0.00125*fDTs, 1.1); }
- virtual void set_K(float K){ d_K = K; scale_los = sqrtf(d_K)/sqrtf(d_K+1); scale_nlos = (1/sqrtf(d_K+1)); }
- virtual void set_step(float step){ d_step = step; }
+ virtual void set_fDTs(float fDTs){ d_fader.d_fDTs = fDTs; d_fader.d_step = powf(0.00125*fDTs, 1.1); }
+ virtual void set_K(float K){ d_fader.d_K = K; d_fader.scale_los = sqrtf(d_fader.d_K)/sqrtf(d_fader.d_K+1); d_fader.scale_nlos = (1/sqrtf(d_fader.d_K+1)); }
+ virtual void set_step(float step){ d_fader.d_step = step; }
};
diff --git a/gr-channels/lib/flat_fader_impl.cc b/gr-channels/lib/flat_fader_impl.cc
new file mode 100644
index 0000000000..af35e29ef4
--- /dev/null
+++ b/gr-channels/lib/flat_fader_impl.cc
@@ -0,0 +1,117 @@
+/* -*- c++ -*- */
+/*
+ * Copyright 2013 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.
+ */
+
+#include <flat_fader_impl.h>
+
+namespace gr {
+ namespace channels {
+
+ flat_fader_impl::flat_fader_impl(unsigned int N, float fDTs, bool LOS, float K, int seed ) :
+ seed_1((int)seed),
+ dist_1(-M_PI, M_PI),
+ rv_1( seed_1, dist_1 ), // U(-pi,pi)
+
+ seed_2((int)seed+1),
+ dist_2(0, 1),
+ rv_2( seed_2, dist_2 ), // U(0,1)
+
+ d_N(N),
+ d_fDTs(fDTs),
+ d_theta(rv_1()),
+ d_theta_los(rv_1()),
+ d_step( powf(0.00125*fDTs, 1.1) ), // max step size approximated from Table 2
+ d_m(0),
+ d_K(K),
+ d_LOS(LOS),
+
+ d_psi(d_N+1, 0),
+ d_phi(d_N+1, 0),
+
+ d_table(8*1024),
+
+ scale_sin(sqrtf(2.0/d_N)),
+ scale_los(sqrtf(d_K)/sqrtf(d_K+1)),
+ scale_nlos(1/sqrtf(d_K+1))
+ {
+ // generate initial phase values
+ for(int i=0; i<d_N+1; i++){
+ d_psi[i] = rv_1();
+ d_phi[i] = rv_1();
+ }
+ }
+
+
+ gr_complex flat_fader_impl::next_sample(){
+ gr_complex H(0,0);
+
+ for(int n=1; n<d_N; n++){
+ float alpha_n = (2*M_PI*n - M_PI + d_theta)/4*d_N;
+#if FASTSINCOS == 1
+ float s_i = scale_sin*gr::fxpt::cos(gr::fxpt::float_to_fixed(2*M_PI*d_fDTs*d_m*gr::fxpt::cos(gr::fxpt::float_to_fixed(alpha_n))+d_psi[n+1]));
+ float s_q = scale_sin*gr::fxpt::cos(gr::fxpt::float_to_fixed(2*M_PI*d_fDTs*d_m*gr::fxpt::sin(gr::fxpt::float_to_fixed(alpha_n))+d_phi[n+1]));
+#elif FASTSINCOS == 2
+ float s_i = scale_sin*d_table.cos(2*M_PI*d_fDTs*d_m*d_table.cos(alpha_n)+d_psi[n+1]);
+ float s_q = scale_sin*d_table.cos(2*M_PI*d_fDTs*d_m*d_table.sin(alpha_n)+d_phi[n+1]);
+
+#else
+ float s_i = scale_sin*cos(2*M_PI*d_fDTs*d_m*cos(alpha_n)+d_psi[n+1]);
+ float s_q = scale_sin*cos(2*M_PI*d_fDTs*d_m*sin(alpha_n)+d_phi[n+1]);
+#endif
+
+ H += gr_complex(s_i, s_q);
+ }
+
+ if(d_LOS){
+#if FASTSINCOS == 1
+ float los_i = gr::fxpt::cos(gr::fxpt::float_to_fixed(2*M_PI*d_fDTs*d_m*gr::fxpt::cos(gr::fxpt::float_to_fixed(d_theta_los)) + d_psi[0]));
+ float los_q = gr::fxpt::sin(gr::fxpt::float_to_fixed(2*M_PI*d_fDTs*d_m*gr::fxpt::cos(gr::fxpt::float_to_fixed(d_theta_los)) + d_psi[0]));
+#elif FASTSINCOS == 2
+ float los_i = d_table.cos(2*M_PI*d_fDTs*d_m*d_table.cos(d_theta_los) + d_psi[0]);
+ float los_q = d_table.sin(2*M_PI*d_fDTs*d_m*d_table.cos(d_theta_los) + d_psi[0]);
+#else
+ float los_i = cos(2*M_PI*d_fDTs*d_m*cos(d_theta_los) + d_psi[0]);
+ float los_q = sin(2*M_PI*d_fDTs*d_m*cos(d_theta_los) + d_psi[0]);
+#endif
+
+ H = H*scale_nlos + gr_complex(los_i,los_q)*scale_los;
+ }
+
+ //out[i] = in[i]*H;
+ d_m++;
+ update_theta();
+ return H;
+
+ }
+
+ void flat_fader_impl::update_theta()
+ {
+ d_theta += (d_step*rv_2());
+ if(d_theta > M_PI){
+ d_theta = M_PI; d_step = -d_step;
+ } else if(d_theta < -M_PI){
+ d_theta = -M_PI; d_step = -d_step;
+ }
+ }
+
+ } /* namespace channels */
+} /* namespace gr */
+
diff --git a/gr-channels/lib/flat_fader_impl.h b/gr-channels/lib/flat_fader_impl.h
new file mode 100644
index 0000000000..766ac43d89
--- /dev/null
+++ b/gr-channels/lib/flat_fader_impl.h
@@ -0,0 +1,82 @@
+/* -*- c++ -*- */
+/*
+ * Copyright 2013 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 FLAT_FADER_IMPL_H
+#define FLAT_FADER_IMPL_H
+
+#include <gnuradio/io_signature.h>
+#include <iostream>
+
+#include <boost/format.hpp>
+#include <boost/random.hpp>
+
+#include <gnuradio/fxpt.h>
+#include <sincostable.h>
+
+// FASTSINCOS: 0 = slow native, 1 = gr::fxpt impl, 2 = sincostable.h
+#define FASTSINCOS 2
+
+namespace gr {
+ namespace channels {
+
+ class flat_fader_impl {
+ private:
+ // initial theta variate generator
+ boost::mt19937 seed_1;
+ boost::uniform_real<> dist_1; // U(-pi,pi)
+ boost::variate_generator<boost::mt19937&, boost::uniform_real<> > rv_1;
+
+ // random walk variate
+ boost::mt19937 seed_2;
+ boost::uniform_real<> dist_2; // U(-pi,pi)
+ boost::variate_generator<boost::mt19937&, boost::uniform_real<> > rv_2;
+
+ public:
+ int d_N; // number of sinusoids
+ float d_fDTs; // normalized maximum doppler frequency
+ double d_theta; // random walk variable (RWP)
+ float d_theta_los;
+ float d_step; // maximum random walk step size
+ uint64_t d_m; // sample counter
+
+ float d_K; // Rician factor (ratio of the specular power to the scattered power)
+ bool d_LOS; // LOS path exists? chooses Rician (LOS) vs Rayleigh (NLOS) model.
+
+ std::vector<float> d_psi; // in-phase initial phase
+ std::vector<float> d_phi; // quadrature initial phase
+
+ std::vector<float> d_costable;
+
+ sincostable d_table;
+
+ float scale_sin, scale_los, scale_nlos;
+
+ void update_theta();
+
+ flat_fader_impl(unsigned int N, float fDTs, bool LOS, float K, int seed);
+ gr_complex next_sample();
+
+ }; /* class flat_fader_impl */
+ } /* namespace channels */
+} /* namespace gr */
+
+#endif // FLAT_FADER_IMPL_H
diff --git a/gr-channels/lib/selective_fading_model_impl.cc b/gr-channels/lib/selective_fading_model_impl.cc
new file mode 100644
index 0000000000..7beebf2e65
--- /dev/null
+++ b/gr-channels/lib/selective_fading_model_impl.cc
@@ -0,0 +1,169 @@
+/* -*- c++ -*- */
+/*
+ * Copyright 2013 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.
+ */
+
+#include "selective_fading_model_impl.h"
+#include <gnuradio/io_signature.h>
+#include <iostream>
+
+#include <boost/format.hpp>
+#include <boost/random.hpp>
+
+#include <gnuradio/fxpt.h>
+#include <sincostable.h>
+
+
+// FASTSINCOS: 0 = slow native, 1 = gr::fxpt impl, 2 = sincostable.h
+#define FASTSINCOS 2
+
+
+namespace gr {
+ namespace channels {
+
+ selective_fading_model::sptr
+ selective_fading_model::make( unsigned int N, float fDTs, bool LOS, float K, int seed, std::vector<float> delays, std::vector<float> mags, int ntaps)
+ {
+ return gnuradio::get_initial_sptr
+ (new selective_fading_model_impl( N, fDTs, LOS, K, seed, delays, mags, ntaps));
+ }
+
+ // Block constructor
+ selective_fading_model_impl::selective_fading_model_impl( unsigned int N, float fDTs, bool LOS, float K, int seed, std::vector<float> delays, std::vector<float> mags, int ntaps )
+ : sync_block("selective_fading_model",
+ io_signature::make(1, 1, sizeof(gr_complex)),
+ io_signature::make(1, 1, sizeof(gr_complex))),
+ d_delays(delays),
+ d_mags(mags),
+ d_sintable(1024)
+ {
+ if(mags.size() != delays.size())
+ throw std::runtime_error("magnitude and delay vectors must be the same length!");
+
+ for(size_t i=0; i<mags.size(); i++){
+ d_faders.push_back(new gr::channels::flat_fader_impl(N,fDTs, LOS, K, seed+i));
+ }
+
+ // set up tap history
+// int ntaps = 10;
+ set_history(1+ntaps);
+ d_taps.resize(ntaps, gr_complex(0,0));
+ }
+
+ selective_fading_model_impl::~selective_fading_model_impl()
+ {
+ for(size_t i=0; i<d_faders.size(); i++){
+ delete d_faders[i];
+ }
+ }
+
+ int
+ selective_fading_model_impl::work (int noutput_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];
+
+ // loop over each output sample
+ for(int i=0; i<noutput_items; i++){
+
+ // clear the current values in each tap
+ for(size_t j=0; j<d_taps.size(); j++){
+ d_taps[j] = gr_complex(0,0);
+ }
+
+ // add each flat fading component to the taps
+ for(size_t j=0; j<d_faders.size(); j++){
+ gr_complex ff_H(d_faders[j]->next_sample());
+ for(size_t k=0; k<d_taps.size(); k++){
+ float dist = k-d_delays[j];
+ float interpmag = d_sintable.sinc(2*M_PI*dist);
+ d_taps[k] += ff_H * interpmag * d_mags[j];
+ }
+ }
+
+ // apply the taps and generate output
+ gr_complex sum(0,0);
+ for(size_t j=0; j<d_taps.size(); j++){
+ sum += in[i+j] * d_taps[d_taps.size()-j-1];
+ }
+
+ // assign output
+ out[i] = sum;
+ }
+
+ // return all outputs
+ return noutput_items;
+ }
+
+ void
+ selective_fading_model_impl::setup_rpc()
+ {
+#ifdef GR_CTRLPORT
+ add_rpc_variable(
+ rpcbasic_sptr(new rpcbasic_register_get<selective_fading_model, float >(
+ alias(), "fDTs",
+ &selective_fading_model::fDTs,
+ pmt::mp(0), pmt::mp(1), pmt::mp(0.01),
+ "Hz*Sec", "normalized maximum doppler frequency (fD*Ts)",
+ RPC_PRIVLVL_MIN, DISPTIME | DISPOPTSTRIP)));
+ add_rpc_variable(
+ rpcbasic_sptr(new rpcbasic_register_set<selective_fading_model, float >(
+ alias(), "fDTs",
+ &selective_fading_model::set_fDTs,
+ pmt::mp(0), pmt::mp(1), pmt::mp(0.01),
+ "Hz*Sec", "normalized maximum doppler frequency (fD*Ts)",
+ RPC_PRIVLVL_MIN, DISPTIME | DISPOPTSTRIP)));
+
+ add_rpc_variable(
+ rpcbasic_sptr(new rpcbasic_register_get<selective_fading_model, float >(
+ alias(), "K",
+ &selective_fading_model::K,
+ pmt::mp(0), pmt::mp(8), pmt::mp(4),
+ "Ratio", "Rician factor (ratio of the specular power to the scattered power)",
+ RPC_PRIVLVL_MIN, DISPTIME | DISPOPTSTRIP)));
+ add_rpc_variable(
+ rpcbasic_sptr(new rpcbasic_register_set<selective_fading_model, float >(
+ alias(), "K",
+ &selective_fading_model::set_K,
+ pmt::mp(0), pmt::mp(8), pmt::mp(4),
+ "Ratio", "Rician factor (ratio of the specular power to the scattered power)",
+ RPC_PRIVLVL_MIN, DISPTIME | DISPOPTSTRIP)));
+
+ add_rpc_variable(
+ rpcbasic_sptr(new rpcbasic_register_get<selective_fading_model, float >(
+ alias(), "step",
+ &selective_fading_model::step,
+ pmt::mp(0), pmt::mp(8), pmt::mp(4),
+ "radians", "Maximum step size for random walk angle per sample",
+ RPC_PRIVLVL_MIN, DISPTIME | DISPOPTSTRIP)));
+ add_rpc_variable(
+ rpcbasic_sptr(new rpcbasic_register_set<selective_fading_model, float >(
+ alias(), "step",
+ &selective_fading_model::set_step,
+ pmt::mp(0), pmt::mp(1), pmt::mp(0.00001),
+ "radians", "Maximum step size for random walk angle per sample",
+ RPC_PRIVLVL_MIN, DISPTIME | DISPOPTSTRIP)));
+#endif /* GR_CTRLPORT */
+ }
+
+ } /* namespace channels */
+} /* namespace gr */
diff --git a/gr-channels/lib/selective_fading_model_impl.h b/gr-channels/lib/selective_fading_model_impl.h
new file mode 100644
index 0000000000..769077aea2
--- /dev/null
+++ b/gr-channels/lib/selective_fading_model_impl.h
@@ -0,0 +1,79 @@
+/* -*- c++ -*- */
+/*
+ * Copyright 2013 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_CHANNELS_SELECTIVE_FADING_MODEL_IMPL_H
+#define INCLUDED_CHANNELS_SELECTIVE_FADING_MODEL_IMPL_H
+
+#include <gnuradio/sync_block.h>
+#include <gnuradio/channels/selective_fading_model.h>
+#include "flat_fader_impl.h"
+
+//#include <iostream>
+#include <boost/format.hpp>
+#include <boost/random.hpp>
+
+#include <gnuradio/fxpt.h>
+#include <sincostable.h>
+
+namespace gr {
+ namespace channels {
+
+ class CHANNELS_API selective_fading_model_impl : public selective_fading_model
+ {
+ private:
+ std::vector<gr::channels::flat_fader_impl*> d_faders;
+ std::vector<float> d_delays;
+ std::vector<float> d_mags;
+ sincostable d_sintable;
+
+ public:
+ selective_fading_model_impl(unsigned int N, float fDTs, bool LOS, float K, int seed, std::vector<float> delays, std::vector<float> mags, int ntaps);
+ ~selective_fading_model_impl();
+ void setup_rpc();
+ int work (int noutput_items,
+ gr_vector_const_void_star &input_items,
+ gr_vector_void_star &output_items);
+ std::vector<gr_complex> d_taps;
+
+ virtual float fDTs(){ return d_faders[0]->d_fDTs; }
+ virtual float K(){ return d_faders[0]->d_K; }
+ virtual float step(){ return d_faders[0]->d_step; }
+
+ virtual void set_fDTs(float fDTs){
+ BOOST_FOREACH( gr::channels::flat_fader_impl* fader, d_faders )
+ { fader->d_fDTs = fDTs; fader->d_step = powf(0.00125*fDTs, 1.1); }
+ }
+ virtual void set_K(float K){
+ BOOST_FOREACH( gr::channels::flat_fader_impl* fader, d_faders )
+ { fader->d_K = K; fader->scale_los = sqrtf(fader->d_K)/sqrtf(fader->d_K+1); fader->scale_nlos = (1/sqrtf(fader->d_K+1)); }
+ }
+ virtual void set_step(float step){
+ BOOST_FOREACH( gr::channels::flat_fader_impl* fader, d_faders )
+ { fader->d_step = step; }
+ }
+
+ };
+
+ } /* namespace channels */
+} /* namespace gr */
+
+#endif /* INCLUDED_CHANNELS_SELECTIVE_FADING_MODEL_IMPL_H */
diff --git a/gr-channels/lib/sincostable.h b/gr-channels/lib/sincostable.h
index be5e6a482c..2a5adb6f4c 100644
--- a/gr-channels/lib/sincostable.h
+++ b/gr-channels/lib/sincostable.h
@@ -26,6 +26,9 @@ class sincostable {
int idx = (((int)(x*d_scale)) + d_sz) % d_sz;
return d_cos[idx];
}
+ const float sinc(float x){
+ return x==0?1:sin(x)/x;
+ }
};
#endif
diff --git a/gr-channels/swig/channels_swig.i b/gr-channels/swig/channels_swig.i
index f27dc08e56..fb7ada7dae 100644
--- a/gr-channels/swig/channels_swig.i
+++ b/gr-channels/swig/channels_swig.i
@@ -30,10 +30,13 @@
%{
#include "gnuradio/channels/channel_model.h"
#include "gnuradio/channels/fading_model.h"
+#include "gnuradio/channels/selective_fading_model.h"
%}
%include "gnuradio/channels/channel_model.h"
%include "gnuradio/channels/fading_model.h"
+%include "gnuradio/channels/selective_fading_model.h"
GR_SWIG_BLOCK_MAGIC2(channels, channel_model);
GR_SWIG_BLOCK_MAGIC2(channels, fading_model);
+GR_SWIG_BLOCK_MAGIC2(channels, selective_fading_model);