IT++ Logo

channel.cpp

Go to the documentation of this file.
00001 
00031 #include <itpp/comm/channel.h>
00032 #include <itpp/base/math/error.h>
00033 #include <itpp/base/math/trig_hyp.h>
00034 #include <itpp/base/bessel.h>
00035 #include <itpp/base/matfunc.h>
00036 #include <itpp/base/specmat.h>
00037 #include <itpp/signal/resampling.h>
00038 #include <itpp/signal/transforms.h>
00039 #include <itpp/signal/window.h>
00040 #include <itpp/base/math/min_max.h>
00041 #include <itpp/stat/misc_stat.h>
00042 
00043 
00044 namespace itpp {
00045 
00046 
00047   // --------------------------------------------------------------------------
00048   // Fading_Generator class
00049   // --------------------------------------------------------------------------
00050 
00051   Fading_Generator::Fading_Generator() : init_flag(false)
00052   {
00053     // no default LOS component
00054     set_LOS_power(0.0);
00055   }
00056 
00057   void Fading_Generator::set_LOS_power(double relative_power)
00058   {
00059     it_assert(relative_power >= 0.0,
00060         "Fading_Generator::set_LOS_power(): Relative_power can not be negative");
00061     los_power = relative_power;
00062     los_diffuse = std::sqrt(1.0 / (1.0 + los_power));
00063     los_direct = los_diffuse * std::sqrt(los_power);
00064   }
00065 
00066   void Fading_Generator::set_LOS_doppler(double relative_doppler)
00067   {
00068     it_warning("Fading_Generator::set_LOS_doppler(): This function has no effect on this kind of generator");
00069   }
00070 
00071   void Fading_Generator::set_time_offset(int offset)
00072   {
00073     it_warning("Fading_Generator::set_time_offset(): This function has no effect on this kind of generator");
00074   }
00075 
00076   void Fading_Generator::set_norm_doppler(double norm_doppler)
00077   {
00078     it_warning("Fading_Generator::set_norm_doppler(): This function has no effect on this kind of generator");
00079   }
00080 
00081   void Fading_Generator::set_filter_length(int fir_length)
00082   {
00083     it_warning("Fading_Generator::set_filter_length(): This function has no effect on this kind of generator");
00084   }
00085 
00086   void Fading_Generator::set_doppler_spectrum(DOPPLER_SPECTRUM spectrum)
00087   {
00088     it_warning("Fading_Generator::set_doppler_spectrum(): This function has no effect on this kind of generator");
00089   }
00090 
00091   void Fading_Generator::set_no_frequencies(int no_freq)
00092   {
00093     it_warning("Fading_Generator::set_no_frequencies(): This function has no effect on this kind of generator");
00094   }
00095 
00096   void Fading_Generator::set_rice_method(RICE_METHOD method)
00097   {
00098     it_warning("Fading_Generator::set_rice_method(): This function has no effect on this kind of generator");
00099   }
00100 
00101   double Fading_Generator::get_LOS_doppler() const
00102   {
00103     it_warning("Fading_Generator::get_LOS_doppler(): This function has no effect on this kind of generator");
00104     return 0;
00105   }
00106 
00107   double Fading_Generator::get_time_offset() const
00108   {
00109     it_warning("Fading_Generator::get_time_offset(): This function has no effect on this kind of generator");
00110     return 0;
00111   }
00112 
00113   int Fading_Generator::get_filter_length() const
00114   {
00115     it_warning("Fading_Generator::get_filter_length(): This function has no effect on this kind of generator");
00116     return 0;
00117   }
00118 
00119   double Fading_Generator::get_norm_doppler() const
00120   {
00121     it_warning("Fading_Generator::get_norm_doppler(): This function has no effect on this kind of generator");
00122     return 0;
00123   }
00124 
00125   DOPPLER_SPECTRUM Fading_Generator::get_doppler_spectrum() const
00126   {
00127     it_warning("Fading_Generator::get_doppler_spectrum(): This function has no effect on this kind of generator");
00128     return Jakes;
00129   }
00130 
00131   int Fading_Generator::get_no_frequencies() const
00132   {
00133     it_warning("Fading_Generator::get_no_frequencies(): This function has no effect on this kind of generator");
00134     return 0;
00135   }
00136 
00137   RICE_METHOD Fading_Generator::get_rice_method() const
00138   {
00139     it_warning("Fading_Generator::get_rice_method(): This function has no effect on this kind of generator");
00140     return MEDS;
00141   }
00142 
00143   void Fading_Generator::shift_time_offset(int offset)
00144   {
00145     it_warning("Fading_Generator::shift_time_offset(): This function has no effect on this kind of generator");
00146   }
00147 
00148   cvec Fading_Generator::generate(int no_samples)
00149   {
00150     cvec output;
00151     this->generate(no_samples, output);
00152     return output;
00153   }
00154 
00155 
00156   // --------------------------------------------------------------------------
00157   // Independent_Fading_Generator class
00158   // --------------------------------------------------------------------------
00159 
00160   void Independent_Fading_Generator::generate(int no_samples, cvec& output)
00161   {
00162     output.set_size(no_samples, false);
00163     if (los_power > 0.0) {
00164       for (int i = 0; i < no_samples; ++i) {
00165   output(i) = los_diffuse * randn_c() + los_direct;
00166       }
00167     }
00168     else {
00169       output = randn_c(no_samples);
00170     }
00171   }
00172 
00173 
00174   // --------------------------------------------------------------------------
00175   // Static_Fading_Generator class
00176   // --------------------------------------------------------------------------
00177 
00178   void Static_Fading_Generator::init()
00179   {
00180     static_sample = randn_c();
00181     if (los_power > 0.0) {
00182       static_sample *= los_diffuse;
00183       static_sample += los_direct;
00184     }
00185     init_flag = true;
00186   }
00187 
00188   void Static_Fading_Generator::generate(int no_samples, cvec& output)
00189   {
00190     if (init_flag == false)
00191       init();
00192 
00193     output.set_size(no_samples, false);
00194     output = static_sample;
00195   }
00196 
00197 
00198   // --------------------------------------------------------------------------
00199   // Correlated_Fading_Generator class
00200   // --------------------------------------------------------------------------
00201 
00202   Correlated_Fading_Generator::Correlated_Fading_Generator(double norm_doppler) :
00203     Fading_Generator(), los_dopp(0.7), time_offset(0.0)
00204   {
00205     set_norm_doppler(norm_doppler);
00206   }
00207 
00208   void Correlated_Fading_Generator::set_norm_doppler(double norm_doppler)
00209   {
00210     it_assert((norm_doppler > 0) && (norm_doppler <= 1.0),
00211         "Correlated_Fading_Generator: Normalized Doppler out of range");
00212     n_dopp = norm_doppler;
00213     init_flag = false;
00214   }
00215 
00216   void Correlated_Fading_Generator::set_LOS_doppler(double relative_doppler)
00217   {
00218     it_assert((relative_doppler >= 0) && (relative_doppler <= 1.0),
00219         "Correlated_Fading_Generator::set_LOS_doppler(): Relative Doppler out of range");
00220     los_dopp = relative_doppler;
00221   }
00222 
00223   void Correlated_Fading_Generator::set_time_offset(int offset)
00224   {
00225     time_offset = static_cast<double>(offset);
00226   }
00227 
00228   void Correlated_Fading_Generator::shift_time_offset(int no_samples)
00229   {
00230     time_offset += static_cast<double>(no_samples);
00231   }
00232 
00233   void Correlated_Fading_Generator::add_LOS(int idx, std::complex<double>& sample)
00234   {
00235     double tmp_arg = m_2pi * los_dopp * n_dopp * (idx + time_offset);
00236     sample *= los_diffuse;
00237     sample += los_direct * std::complex<double>(std::cos(tmp_arg),
00238             std::sin(tmp_arg));
00239   }
00240 
00241 
00242   // --------------------------------------------------------------------------
00243   // Rice_Fading_Generator class
00244   // --------------------------------------------------------------------------
00245 
00246   Rice_Fading_Generator::Rice_Fading_Generator(double norm_doppler,
00247                  DOPPLER_SPECTRUM spectrum,
00248                  int no_freq, RICE_METHOD method) :
00249     Correlated_Fading_Generator(norm_doppler)
00250   {
00251     set_doppler_spectrum(spectrum);
00252     set_no_frequencies(no_freq);
00253     set_rice_method(method);
00254   }
00255 
00256   void Rice_Fading_Generator::set_doppler_spectrum(DOPPLER_SPECTRUM spectrum)
00257   {
00258     dopp_spectrum = spectrum;
00259     init_flag = false;
00260   }
00261 
00262   void Rice_Fading_Generator::set_no_frequencies(int no_freq)
00263   {
00264     it_assert(no_freq >= 7,
00265         "Rice_Fading_Generator::set_no_frequencies(): Too low number of Doppler frequencies");
00266     Ni = no_freq;
00267     init_flag = false;
00268   }
00269 
00270   void Rice_Fading_Generator::set_rice_method(RICE_METHOD method)
00271   {
00272     // check if this method works for the given spectrum
00273     rice_method = method;
00274     init_flag = false;
00275   }
00276 
00277   void Rice_Fading_Generator::init()
00278   {
00279     switch (rice_method) {
00280     case MEDS: // Method of Exact Doppler Spread (MEDS)
00281       init_MEDS();
00282       break;
00283     default:
00284       it_error("Rice_Fading_Generator::init(): Wrong Rice method for this fading generator");
00285     };
00286 
00287     init_flag = true; // generator ready to use
00288   }
00289 
00290   void Rice_Fading_Generator::generate(int no_samples, cvec &output)
00291   {
00292     if (init_flag == false)
00293       init();
00294 
00295     output.set_size(no_samples, false);
00296 
00297     switch (dopp_spectrum) {
00298     case Jakes:
00299       {
00300   double tmp_re, tmp_im;
00301   if (los_power > 0.0) { // LOS component exists
00302     for (int i = 0; i < no_samples; i++) {
00303       tmp_re = sum(elem_mult(c1, cos(m_2pi * f1 * n_dopp * (i + time_offset) + th1)));
00304       tmp_im = sum(elem_mult(c2, cos(m_2pi * f2 * n_dopp * (i + time_offset) + th2)));
00305       output(i) = std::complex<double>(tmp_re, tmp_im);
00306       add_LOS(i, output(i));
00307     }
00308   }
00309   else {
00310     for (int i = 0; i < no_samples; i++) {
00311       tmp_re = sum(elem_mult(c1, cos(m_2pi * f1 * n_dopp * (i + time_offset) + th1)));
00312       tmp_im = sum(elem_mult(c2, cos(m_2pi * f2 * n_dopp * (i + time_offset) + th2)));
00313       output(i) = std::complex<double>(tmp_re, tmp_im);
00314     }
00315   }
00316   break;
00317       }
00318     case GaussI:
00319     case GaussII:
00320       {
00321   double tmp;
00322   for (int i = 0; i < no_samples; i++) {
00323     tmp = m_2pi * n_dopp * (i + time_offset);
00324     output(i) = sum(elem_mult(c1, cos(f1 * tmp + th1)))
00325       * std::complex<double>(std::cos(f01 * tmp), -std::sin(f01 * tmp))
00326       + sum(elem_mult(c2, cos(f2 * tmp + th2)))
00327       * std::complex<double>(std::cos(f02 * tmp), -std::sin(f02 * tmp));
00328       }
00329       break;
00330       }
00331     }
00332 
00333     time_offset += no_samples;
00334   }
00335 
00336   void Rice_Fading_Generator::init_MEDS()
00337   {
00338     vec n;
00339     double sgm_0_2;
00340 
00341     switch (dopp_spectrum) {
00342     case Jakes:
00343       n = linspace(1, Ni, Ni);
00344       f1 = sin(pi / (2*Ni) * (n-0.5));
00345       c1 = std::sqrt(1.0/Ni) * ones(Ni);
00346       th1 = randu(Ni) * 2*pi;
00347       n = linspace(1, Ni+1, Ni+1);
00348       f2 = sin(pi / (2*(Ni+1)) * (n-0.5));
00349       c2 = std::sqrt(1.0/(Ni+1)) * ones(Ni+1);
00350       th2 = randu(Ni+1) * 2*pi;
00351       f01 = f02 = 0;
00352       break;
00353     case GaussI:
00354       n = linspace(1, Ni, Ni);
00355       sgm_0_2 = 5.0 / 6.0;
00356       c1 = std::sqrt(sgm_0_2 * 2.0 / Ni) * ones(Ni);
00357       f1 = std::sqrt(2.0) * 0.05 * erfinv((2*n-1) / (2*Ni));
00358       th1 = randu(Ni) * 2*pi;
00359       sgm_0_2 = 1.0 / 6.0;
00360       c2 = std::sqrt(sgm_0_2 * 2.0 / Ni) * ones(Ni);
00361       f2 = std::sqrt(2.0) * 0.1 * erfinv((2*n-1) / (2*Ni));
00362       th2 = randu(Ni) * 2*pi;
00363       f01 = 0.8; f02 = -0.4;
00364       break;
00365     case GaussII:
00366       n = linspace(1, Ni, Ni);
00367       sgm_0_2 = std::sqrt(10.0) / (std::sqrt(10.0) + 0.15);
00368       c1 = std::sqrt(sgm_0_2 * 2.0 / Ni) * ones(Ni);
00369       f1 = std::sqrt(2.0) * 0.1 * erfinv((2*n-1) / (2*Ni));
00370       th1 = randu(Ni) * 2*pi;
00371       sgm_0_2 = 0.15 / (std::sqrt(10.0) + 0.15);
00372       c2 = std::sqrt(sgm_0_2 * 2.0 / Ni) * ones(Ni);
00373       f2 = std::sqrt(2.0) * 0.15 * erfinv((2*n-1) / (2*Ni));
00374       th2 = randu(Ni) * 2*pi;
00375       f01 = -0.7; f02 = 0.4;
00376       break;
00377     default:
00378       it_error("Rice_Fading_Generator::init_MEDS(): Wrong spectrum method for this fading generator");
00379     };
00380   }
00381 
00382 
00383   // --------------------------------------------------------------------------
00384   // FIR_Fading_Generator class methods
00385   // --------------------------------------------------------------------------
00386 
00387   FIR_Fading_Generator::FIR_Fading_Generator(double norm_doppler,
00388                int filter_length) :
00389     Correlated_Fading_Generator(norm_doppler)
00390   {
00391     set_filter_length(filter_length);
00392   }
00393 
00394   void FIR_Fading_Generator::set_filter_length(int filter_length)
00395   {
00396     it_assert(filter_length >= 50,
00397         "FIR_Fading_Generator::set_filter_length(): Filter length should be at least 50");
00398     fir_length = filter_length;
00399     init_flag = false;
00400   }
00401 
00402   void FIR_Fading_Generator::init()
00403   {
00404     // calculate a reasonable upsample rate so that normalized doppler is > 0.1
00405     double norm_dopp = n_dopp;
00406     upsample_rate = 1;
00407     while (norm_dopp < 0.1) {
00408       norm_dopp *= 2;
00409       upsample_rate *= 2;
00410     }
00411     fir_filter.set_coeffs(Jakes_filter(norm_dopp, fir_length));
00412 
00413     // fill filter with dummy data
00414     cvec dummy = fir_filter(randn_c(fir_length));
00415 
00416     left_overs.set_size(0, false);
00417 
00418     init_flag = true; // generator ready to use
00419   }
00420 
00421   void FIR_Fading_Generator::generate(int no_samples, cvec &output)
00422   {
00423     if (init_flag == false)
00424       init();
00425 
00426     // calculate number of samples before upsampling
00427     int no_upsamples = ceil_i(static_cast<double>(no_samples - left_overs.size())
00428             / upsample_rate) + 1;
00429 
00430     // should make a smarter interpolation here!!!
00431     lininterp(fir_filter(randn_c(no_upsamples)), upsample_rate, output);
00432     output = concat(left_overs, output); // add left-overs from previous filtering
00433     left_overs = output.right(output.size() - no_samples); // save left-overs for next round of filtering
00434     output.set_size(no_samples, true);
00435 
00436     if (los_power > 0.0) { // LOS component exist
00437       for (int i = 0; i < no_samples; i++) {
00438   add_LOS(i, output(i));
00439       }
00440     }
00441 
00442     time_offset += no_samples;
00443   }
00444 
00445   vec FIR_Fading_Generator::Jakes_filter(double norm_dopp, int order)
00446   {
00447     int L = order / 2;
00448     vec x_pos(L), x_neg(L), x(2*L+1), h(2*L+1);
00449     for (int i = 1; i <= L; i++) {
00450       x_pos(i-1) = besselj(0.25, m_2pi * norm_dopp * i) / std::pow(i, 0.25);
00451       //  / std::sqrt(std::sqrt(static_cast<double>(i)));
00452     }
00453     double x0 = 1.468813 * std::pow(norm_dopp, 0.25); // std::sqrt(std::sqrt(norm_dopp));
00454     x_neg = reverse(x_pos);
00455     x = concat(concat(x_neg, x0), x_pos);
00456     h = elem_mult(hamming(2*L+1), x);
00457     h /= norm(h);
00458     return h;
00459   }
00460 
00461 
00462   // --------------------------------------------------------------------------
00463   // IFFT_Fading_Generator class methods
00464   // --------------------------------------------------------------------------
00465 
00466   void IFFT_Fading_Generator::generate(int no_samples, cvec &output)
00467   {
00468     if (init_flag == false)
00469       init();
00470 
00471     generate_Jakes(no_samples, output);
00472 
00473     if (los_power > 0.0) { // LOS component exist
00474       for (int i = 0; i < no_samples; i++) {
00475   add_LOS(i, output(i));
00476       }
00477     }
00478 
00479     time_offset += no_samples;
00480   }
00481 
00482   void IFFT_Fading_Generator::generate_Jakes(int no_samples, cvec &output)
00483   {
00484     int Nfft = pow2i(levels2bits(no_samples));
00485     double df = 1.0 / Nfft;
00486     int noisesamp = ceil_i(n_dopp / df);
00487     int no_upsample = 1;
00488 
00489     while (noisesamp <= 10) { // if too few samples, increase the FFT size
00490       Nfft *= 2;
00491       no_upsample *= 2;
00492       df = 1.0 / Nfft;
00493       noisesamp = ceil_i(n_dopp / df);
00494       it_assert(no_upsample < 128,
00495     "IFFT_Fading_Generator::generate_Jakes(): Too low normalized doppler or too small blocks of data. Results in an inefficient algorithm with lots of zero-padding");
00496     }
00497 
00498     vec Fpos = linspace(0, 0.5, Nfft/2+1);
00499     vec F = concat(Fpos, reverse(-Fpos(1, Nfft/2-1)));
00500     vec S = zeros(Nfft);
00501 
00502     for (int i = 0; i < F.size(); i++) {
00503       if (std::fabs(F(i)) < n_dopp)
00504   S(i) = std::sqrt(1.5 / (pi * n_dopp * std::sqrt(1 - std::pow(F(i) / n_dopp, 2))));
00505       else if (std::fabs(F(i)) == n_dopp)
00506   S(i) = 1000000;
00507     }
00508 
00509     S /= norm(S, 2);
00510     S *= Nfft;
00511 
00512     cvec x = zeros_c(Nfft);
00513 
00514     for (int i = 0; i < noisesamp; ++i) {
00515       x(i) = S(i) * randn_c();
00516       x(Nfft - 1 - i) = S(Nfft - 1 - i) * randn_c();
00517     }
00518 
00519     x = ifft(x);
00520 
00521     output = x.mid(0, no_samples);
00522   }
00523 
00524 
00525   // --------------------------------------------------------------------------
00526   // Channel_Specification class methods
00527   // --------------------------------------------------------------------------
00528 
00529   Channel_Specification::Channel_Specification(const vec &avg_power_dB,
00530                  const vec &delay_prof)
00531   {
00532     set_channel_profile(avg_power_dB, delay_prof);
00533   }
00534 
00535   Channel_Specification::Channel_Specification(const CHANNEL_PROFILE profile)
00536   {
00537     set_channel_profile(profile);
00538   }
00539 
00540   void Channel_Specification::set_channel_profile(const vec &avg_power_dB, const vec &delay_prof)
00541   {
00542     it_assert(min(delay_prof) == 0,
00543         "Channel_Specification::set_channel_profile(): Minimum relative delay must be 0");
00544     it_assert(avg_power_dB.size() == delay_prof.size(),
00545         "Channel_Specification::set_channel_profile(): Power and delay vectors must be of equal length");
00546     it_assert(delay_prof(0) == 0,
00547         "Channel_Specification::set_channel_profile(): First tap must be at zero delay");
00548     for (int i = 1; i < delay_prof.size(); i++) {
00549       it_assert(delay_prof(i) > delay_prof(i-1),
00550     "Channel_Specification::set_channel_profile(): Delays should be sorted and unique");
00551     }
00552 
00553     N_taps = delay_prof.size();
00554     a_prof_dB = avg_power_dB;
00555     d_prof = delay_prof;
00556 
00557     // set doppler spectrum to Jakes per default
00558     tap_doppler_spectrum.set_size(N_taps, false);
00559     tap_doppler_spectrum = Jakes;
00560 
00561     // set LOS parameters to zeros per default
00562     set_LOS(zeros(N_taps));
00563   }
00564 
00565   void Channel_Specification::set_channel_profile(const CHANNEL_PROFILE profile)
00566   {
00567     switch (profile) {
00568       // -------------- ITU Channel models -----------------
00569     case ITU_Vehicular_A:
00570       set_channel_profile(vec("0 -1 -9 -10 -15 -20"),
00571         vec("0 310 710 1090 1730 2510") * 1e-9);
00572       break;
00573 
00574     case ITU_Vehicular_B:
00575       set_channel_profile(vec("-2.5 0 -12.8 -10 -25.2 -16"),
00576         vec("0 300 8900 12900 17100 20000") * 1e-9);
00577       break;
00578 
00579     case ITU_Pedestrian_A:
00580       set_channel_profile(vec("0 -9.7 -19.2 -22.8"),
00581         vec("0 110 190 410") * 1e-9);
00582       break;
00583 
00584     case ITU_Pedestrian_B:
00585       set_channel_profile(vec("0 -0.9 -4.9 -8 -7.8 -23.9"),
00586         vec("0 200 800 1200 2300 3700") * 1e-9);
00587       break;
00588 
00589       // -------------- COST259 Channel models -----------------
00590     case COST259_TUx:
00591       set_channel_profile(vec("-5.7 -7.6 -10.1 -10.2 -10.2 -11.5 -13.4 -16.3 -16.9 -17.1 -17.4 -19 -19 -19.8 -21.5 -21.6 -22.1 -22.6 -23.5 -24.3"),
00592         vec("0 217 512 514 517 674 882 1230 1287 1311 1349 1533 1535 1622 1818 1836 1884 1943 2048 2140") * 1e-9);
00593       break;
00594 
00595     case COST259_RAx:
00596       set_channel_profile(vec("-5.2 -6.4 -8.4 -9.3 -10 -13.1 -15.3 -18.5 -20.4 -22.4"),
00597         vec("0 42 101 129 149 245 312 410 469 528") * 1e-9);
00598       set_LOS(0, sqr(0.91/0.41), 0.7);
00599       break;
00600 
00601     case COST259_HTx:
00602       set_channel_profile(vec("-3.6 -8.9 -10.2 -11.5 -11.8 -12.7 -13.0 -16.2 -17.3 -17.7 -17.6 -22.7 -24.1 -25.8 -25.8 -26.2 -29 -29.9 -30 -30.7"),
00603         vec("0 356 441 528 546 609 625 842 916 941 15000 16172 16492 16876 16882 16978 17615 17827 17849 18016") * 1e-9);
00604       break;
00605 
00606       // -------------- COST207 Channel models -----------------
00607     case COST207_RA:
00608       set_channel_profile(vec("0 -2 -10 -20"),
00609         vec("0 200 400 600") * 1e-9);
00610       set_LOS(0, sqr(0.91/0.41), 0.7);
00611       break;
00612 
00613     case COST207_RA6:
00614       set_channel_profile(vec("0 -4 -8 -12 -16 -20"),
00615         vec("0 100 200 300 400 500") * 1e-9);
00616       set_LOS(0, sqr(0.91/0.41), 0.7);
00617       break;
00618 
00619     case COST207_TU:
00620       set_channel_profile(vec("-3 0 -2 -6 -8 -10"),
00621         vec("0 200 600 1600 2400 5000") * 1e-9);
00622       set_doppler_spectrum(2, GaussI);
00623       set_doppler_spectrum(3, GaussI);
00624       set_doppler_spectrum(4, GaussII);
00625       set_doppler_spectrum(5, GaussII);
00626       break;
00627 
00628     case COST207_TU6alt:
00629       set_channel_profile(vec("-3 0 -2 -6 -8 -10"),
00630         vec("0 200 500 1600 2300 5000") * 1e-9);
00631       set_doppler_spectrum(3, GaussI);
00632       set_doppler_spectrum(4, GaussII);
00633       set_doppler_spectrum(5, GaussII);
00634       break;
00635 
00636     case COST207_TU12:
00637       set_channel_profile(vec("-4 -3 0 -2 -3 -5 -7 -5 -6 -9 -11 -10"),
00638         vec("0 200 400 600 800 1200 1400 1800 2400 3000 3200 5000") * 1e-9);
00639       set_doppler_spectrum(3, GaussI);
00640       set_doppler_spectrum(4, GaussI);
00641       set_doppler_spectrum(5, GaussI);
00642       set_doppler_spectrum(6, GaussI);
00643       set_doppler_spectrum(7, GaussI);
00644       set_doppler_spectrum(8, GaussII);
00645       set_doppler_spectrum(9, GaussII);
00646       set_doppler_spectrum(10, GaussII);
00647       set_doppler_spectrum(11, GaussII);
00648       break;
00649 
00650     case COST207_TU12alt:
00651       set_channel_profile(vec("-4 -3 0 -2.6 -3 -5 -7 -5 -6.5 -8.6 -11 -10"),
00652         vec("0 200 400 600 800 1200 1400 1800 2400 3000 3200 5000") * 1e-9);
00653       set_doppler_spectrum(4, GaussI);
00654       set_doppler_spectrum(5, GaussI);
00655       set_doppler_spectrum(6, GaussI);
00656       set_doppler_spectrum(7, GaussI);
00657       set_doppler_spectrum(8, GaussII);
00658       set_doppler_spectrum(9, GaussII);
00659       set_doppler_spectrum(10, GaussII);
00660       set_doppler_spectrum(11, GaussII);
00661       break;
00662 
00663     case COST207_BU:
00664       set_channel_profile(vec("-3 0 -3 -5 -2 -4"),
00665         vec("0 400 1000 1600 5000 6600") * 1e-9);
00666       set_doppler_spectrum(2, GaussI);
00667       set_doppler_spectrum(3, GaussI);
00668       set_doppler_spectrum(4, GaussII);
00669       set_doppler_spectrum(5, GaussII);
00670       break;
00671 
00672     case COST207_BU6alt:
00673       set_channel_profile(vec("-2.5 0 -3 -5 -2 -4"),
00674         vec("0 300 1000 1600 5000 6600") * 1e-9);
00675       set_doppler_spectrum(2, GaussI);
00676       set_doppler_spectrum(3, GaussI);
00677       set_doppler_spectrum(4, GaussII);
00678       set_doppler_spectrum(5, GaussII);
00679       break;
00680 
00681     case COST207_BU12:
00682       set_channel_profile(vec("-7 -3 -1 0 -2 -6 -7 -1 -2 -7 -10 -15"),
00683         vec("0 200 400 800 1600 2200 3200 5000 6000 7200 8200 10000") * 1e-9);
00684       set_doppler_spectrum(3, GaussI);
00685       set_doppler_spectrum(4, GaussI);
00686       set_doppler_spectrum(5, GaussII);
00687       set_doppler_spectrum(6, GaussII);
00688       set_doppler_spectrum(7, GaussII);
00689       set_doppler_spectrum(8, GaussII);
00690       set_doppler_spectrum(9, GaussII);
00691       set_doppler_spectrum(10, GaussII);
00692       set_doppler_spectrum(11, GaussII);
00693       break;
00694 
00695     case COST207_BU12alt:
00696       set_channel_profile(vec("-7.7 -3.4 -1.3 0 -2.3 -5.6 -7.4 -1.4 -1.6 -6.7 -9.8 -15.1"),
00697         vec("0 100 300 700 1600 2200 3100 5000 6000 7200 8100 10000") * 1e-9);
00698       set_doppler_spectrum(3, GaussI);
00699       set_doppler_spectrum(4, GaussI);
00700       set_doppler_spectrum(5, GaussII);
00701       set_doppler_spectrum(6, GaussII);
00702       set_doppler_spectrum(7, GaussII);
00703       set_doppler_spectrum(8, GaussII);
00704       set_doppler_spectrum(9, GaussII);
00705       set_doppler_spectrum(10, GaussII);
00706       set_doppler_spectrum(11, GaussII);
00707       break;
00708 
00709 
00710     case COST207_HT:
00711       set_channel_profile(vec("0 -2 -4 -7 -6 -12"),
00712         vec("0 200 400 600 15000 17200") * 1e-9);
00713       set_doppler_spectrum(4, GaussII);
00714       set_doppler_spectrum(5, GaussII);
00715       break;
00716 
00717     case COST207_HT6alt:
00718       set_channel_profile(vec("0 -1.5 -4.5 -7.5 -8 -17.7"),
00719         vec("0 100 300 500 15000 17200") * 1e-9);
00720       set_doppler_spectrum(4, GaussII);
00721       set_doppler_spectrum(5, GaussII);
00722       break;
00723 
00724     case COST207_HT12:
00725       set_channel_profile(vec("-10 -8 -6 -4 0 0 -4 -8 -9 -10 -12 -14"),
00726         vec("0 200 400 600 800 2000 2400 15000 15200 15800 17200 20000") * 1e-9);
00727       set_doppler_spectrum(3, GaussI);
00728       set_doppler_spectrum(4, GaussI);
00729       set_doppler_spectrum(5, GaussI);
00730       set_doppler_spectrum(6, GaussII);
00731       set_doppler_spectrum(7, GaussII);
00732       set_doppler_spectrum(8, GaussII);
00733       set_doppler_spectrum(9, GaussII);
00734       set_doppler_spectrum(10, GaussII);
00735       set_doppler_spectrum(11, GaussII);
00736       break;
00737 
00738     case COST207_HT12alt:
00739       set_channel_profile(vec("-10 -8 -6 -4 0 0 -4 -8 -9 -10 -12 -14"),
00740         vec("0 100 300 500 700 1000 1300 15000 15200 15700 17200 20000") * 1e-9);
00741       set_doppler_spectrum(4, GaussI);
00742       set_doppler_spectrum(5, GaussI);
00743       set_doppler_spectrum(6, GaussI);
00744       set_doppler_spectrum(7, GaussII);
00745       set_doppler_spectrum(8, GaussII);
00746       set_doppler_spectrum(9, GaussII);
00747       set_doppler_spectrum(10, GaussII);
00748       set_doppler_spectrum(11, GaussII);
00749       break;
00750     };
00751   }
00752 
00753 
00754   void Channel_Specification::set_doppler_spectrum(DOPPLER_SPECTRUM *tap_spectrum)
00755   {
00756     for (int i = 0; i < N_taps; i++)
00757       tap_doppler_spectrum(i) = tap_spectrum[i];
00758   }
00759 
00760   void Channel_Specification::set_doppler_spectrum(int tap_number, DOPPLER_SPECTRUM tap_spectrum)
00761   {
00762     tap_doppler_spectrum(tap_number) = tap_spectrum;
00763   }
00764 
00765   void Channel_Specification::set_LOS(int tap_number, double relative_power,
00766               double relative_doppler)
00767   {
00768     it_assert(N_taps >= 1,
00769         "Channel_Specification::set_LOS(): Cannot set LOS component if not set channel profile");
00770     it_assert((tap_number >= 0) && (tap_number < N_taps),
00771         "Channel_Specification::set_LOS(): Tap number out of range");
00772     it_assert((relative_doppler >= 0) && (relative_doppler <= 1.0),
00773         "Channel_Specification::set_LOS(): Normalized Doppler out of range");
00774     it_assert(relative_power >= 0.0,
00775         "Channel_Specification::set_LOS(): Rice factor out of range");
00776 
00777     los_power.set_size(N_taps, true);
00778     los_dopp.set_size(N_taps, true);
00779     los_power(tap_number) = relative_power;
00780     los_dopp(tap_number) = relative_doppler;
00781   }
00782 
00783   void Channel_Specification::set_LOS(const vec& relative_power,
00784               const vec& relative_doppler)
00785   {
00786     it_assert((relative_power.size() == N_taps),
00787         "Channel_Specification::set_LOS(): Improper size of input vectors");
00788 
00789     if (relative_doppler.size() == 0) {
00790       los_power.set_size(relative_power.size());
00791       los_dopp.set_size(relative_power.size());
00792       for (int i = 0; i < relative_power.size(); i++) {
00793   it_assert(relative_power(i) >= 0.0,
00794       "Channel_Specification::set_LOS(): Rice factor out of range");
00795   los_power(i) = relative_power(i);
00796   los_dopp(i) = 0.7;
00797       }
00798     }
00799     else {
00800       it_assert(relative_doppler.size() == N_taps,
00801     "Channel_Specification::set_LOS(): Improper size of input vectors");
00802       los_power.set_size(relative_power.size());
00803       los_dopp.set_size(relative_power.size());
00804       for (int i = 0; i < relative_power.size(); i++) {
00805   it_assert((relative_doppler(i) >= 0) && (relative_doppler(i) <= 1.0),
00806       "Channel_Specification::set_LOS(): Normalized Doppler out of range");
00807   it_assert(relative_power(i) >= 0.0,
00808       "Channel_Specification::set_LOS(): Rice factor out of range");
00809   los_power(i) = relative_power(i);
00810   los_dopp(i) = relative_doppler(i);
00811       }
00812     }
00813   }
00814 
00815   void Channel_Specification::get_channel_profile(vec &avg_power_dB,
00816               vec &delay_prof) const
00817   {
00818     avg_power_dB = a_prof_dB;
00819     delay_prof = d_prof;
00820   }
00821 
00822   DOPPLER_SPECTRUM Channel_Specification::get_doppler_spectrum(int index) const
00823   {
00824     it_assert((index >= 0) && (index < N_taps),
00825         "Channel_Specification::get_doppler_spectrum(): Index of of range");
00826     return tap_doppler_spectrum(index);
00827   }
00828 
00829   double Channel_Specification::calc_mean_excess_delay() const
00830   {
00831     vec a_prof = inv_dB(a_prof_dB);
00832     return (a_prof * d_prof / sum(a_prof));
00833   }
00834 
00835   double Channel_Specification::calc_rms_delay_spread() const
00836   {
00837     vec a_prof = inv_dB(a_prof_dB);
00838     double a = a_prof * d_prof / sum(a_prof);
00839     double b = a_prof * sqr(d_prof) / sum(a_prof);
00840 
00841     return std::sqrt(b-a*a);
00842   }
00843 
00844 
00845   // --------------------------------------------------------------------------
00846   // TDL_Channel class methods
00847   // --------------------------------------------------------------------------
00848 
00849   TDL_Channel::TDL_Channel(const vec &avg_power_dB, const ivec &delay_prof):
00850     init_flag(false), n_dopp(0.0), fading_type(Independent), method(Rice_MEDS),
00851     filter_length(0), nrof_freq(16), discrete_Ts(0.0)
00852   {
00853     set_channel_profile(avg_power_dB, delay_prof);
00854 
00855     // initialize LOS parameters to all zeros
00856     set_LOS(zeros(delay_prof.size()));
00857 
00858     // initialize Doppler spectra
00859     tap_doppler_spectrum.set_size(delay_prof.size());
00860     tap_doppler_spectrum = Jakes;
00861   }
00862 
00863   TDL_Channel::TDL_Channel(const Channel_Specification &channel_spec, double sampling_time):
00864     init_flag(false), n_dopp(0.0), fading_type(Independent), method(Rice_MEDS),
00865     filter_length(0), nrof_freq(16), discrete_Ts(sampling_time)
00866   {
00867     set_channel_profile(channel_spec, sampling_time);
00868 
00869     // set Doppler spectrum
00870     tap_doppler_spectrum = channel_spec.get_doppler_spectrum();
00871   }
00872 
00873   TDL_Channel::~TDL_Channel()
00874   {
00875     if (fading_gen.size() > 0) { // delete all old generators
00876       for (int i = 0; i < fading_gen.size(); i++) {
00877   if (fading_gen(i) != NULL) {
00878     delete fading_gen(i);
00879     fading_gen(i) = NULL;
00880   }
00881       }
00882     }
00883   }
00884 
00885   void TDL_Channel::set_channel_profile(const vec &avg_power_dB,
00886           const ivec &delay_prof)
00887   {
00888     it_assert(min(delay_prof) == 0,
00889         "TDL_Channel::set_channel_profile(): Minimum relative delay must be 0.");
00890     it_assert(avg_power_dB.size() == delay_prof.size(),
00891         "TDL_Channel::set_channel_profile(): Power and delay vectors must be of equal length!");
00892     it_assert(delay_prof(0) == 0,
00893         "TDL_Channel::set_channel_profile(): First tap must be at zero delay");
00894     for (int i = 1; i < delay_prof.size(); i++) {
00895       it_assert(delay_prof(i) > delay_prof(i-1),
00896     "TDL_Channel::set_channel_profile(): Delays should be sorted and unique");
00897     }
00898 
00899     N_taps = delay_prof.size();
00900     a_prof = pow(10.0, avg_power_dB/20.0); // Convert power profile to amplitude profile
00901     a_prof /= norm(a_prof); // Normalize amplitude profile
00902     d_prof = delay_prof;
00903 
00904     // initialize Doppler spectra
00905     tap_doppler_spectrum.set_size(d_prof.size());
00906     tap_doppler_spectrum = Jakes;
00907 
00908     // set size of Rice parameters according to the new channel profile
00909     set_LOS(zeros(N_taps));
00910 
00911     // changes in PDP require initialisation
00912     init_flag = false;
00913   }
00914 
00915   void TDL_Channel::set_channel_profile_uniform(int no_taps)
00916   {
00917     it_assert(no_taps >= 1, "TDL_Channel::set_channel_profile_uniform(): Minimum number of taps is 1.");
00918 
00919     vec avg_power_dB = zeros(no_taps);
00920     ivec delay_prof(no_taps);
00921     for (int i = 0; i < no_taps; i++)
00922       delay_prof(i) = i;
00923 
00924     set_channel_profile(avg_power_dB, delay_prof);
00925   }
00926 
00927   void TDL_Channel::set_channel_profile_exponential(int no_taps)
00928   {
00929     it_assert(no_taps >= 1, "TDL_Channel::set_channel_profile_exponential(): Minimum number of taps is 1.");
00930 
00931     vec avg_power_dB(no_taps);
00932     ivec delay_prof(no_taps);
00933     for (int i = 0; i < no_taps; i++) {
00934       delay_prof(i) = i;
00935       // p(i*ts) = exp(-i*ts),    k = 0...no_taps-1
00936       avg_power_dB(i) = dB(std::exp(static_cast<double>(-i)));
00937     }
00938 
00939     set_channel_profile(avg_power_dB, delay_prof);
00940   }
00941 
00942   void TDL_Channel::set_channel_profile(const Channel_Specification &channel_spec, double sampling_time)
00943   {
00944     vec avg_power_dB;
00945     vec delay_profile;
00946 
00947     // set power profile and delays
00948     channel_spec.get_channel_profile(avg_power_dB, delay_profile);
00949     discrete_Ts = sampling_time;
00950     N_taps = avg_power_dB.size();
00951     a_prof = pow(10.0, avg_power_dB/20.0); // Convert power profile to amplitude profile
00952     a_prof /= norm(a_prof); // Normalize amplitude profile
00953 
00954     // set size of Rice parameters according to the new channel profile
00955     set_LOS(channel_spec.get_LOS_power(), channel_spec.get_LOS_doppler());
00956 
00957     // set Doppler spectrum
00958     tap_doppler_spectrum = channel_spec.get_doppler_spectrum();
00959 
00960     // sets discretized delay profile
00961     discretize(delay_profile);
00962 
00963     init_flag = false;
00964   }
00965 
00966 
00967   void TDL_Channel::set_correlated_method(CORRELATED_METHOD correlated_method)
00968   {
00969     fading_type = Correlated;
00970     method = correlated_method;
00971     init_flag = false;
00972   }
00973 
00974   void TDL_Channel::set_fading_type(FADING_TYPE fading_type_in)
00975   {
00976     fading_type = fading_type_in;
00977     init_flag = false;
00978   }
00979 
00980 
00981   void TDL_Channel::set_norm_doppler(double norm_doppler)
00982   {
00983     it_assert((norm_doppler > 0) && (norm_doppler <= 1.0),
00984         "TDL_Channel::set_norm_doppler(): Normalized Doppler out of range");
00985     n_dopp = norm_doppler;
00986     // if normalized Doppler is set, we have correlated fading
00987     fading_type = Correlated;
00988     init_flag = false;
00989   }
00990 
00991 
00992   void TDL_Channel::set_LOS(const vec& relative_power, const vec& relative_doppler)
00993   {
00994     it_assert((relative_power.size() == N_taps),
00995         "TDL_Channel::set_LOS(): Improper size of input vectors");
00996 
00997     if (relative_doppler.size() == 0) {
00998       los_power.set_size(relative_power.size());
00999       los_dopp.set_size(relative_power.size());
01000       for (int i = 0; i < relative_power.size(); i++) {
01001   it_assert(relative_power(i) >= 0.0,
01002       "TDL_Channel::set_LOS(): Rice factor out of range");
01003   los_power(i) = relative_power(i);
01004   los_dopp(i) = (relative_power(i) > 0) ? 0.7 : 0.0;
01005       }
01006     }
01007     else {
01008       it_assert(relative_doppler.size() == N_taps,
01009     "TDL_Channel::set_LOS(): Improper size of input vectors");
01010       los_power.set_size(relative_power.size());
01011       los_dopp.set_size(relative_power.size());
01012       for (int i = 0; i < relative_power.size(); i++) {
01013   it_assert((relative_doppler(i) >= 0) && (relative_doppler(i) <= 1.0),
01014       "TDL_Channel::set_LOS(): Normalized Doppler out of range");
01015   it_assert(relative_power(i) >= 0.0,
01016       "TDL_Channel::set_LOS(): Rice factor out of range");
01017   los_power(i) = relative_power(i);
01018   los_dopp(i) = relative_doppler(i);
01019       }
01020     }
01021   }
01022 
01023   void TDL_Channel::set_LOS_power(const vec& relative_power)
01024   {
01025     it_assert(relative_power.size() == N_taps,
01026         "TDL_Channel::set_LOS_power(): Improper size of input vector");
01027 
01028     los_power.set_size(relative_power.size());
01029     los_dopp.set_size(relative_power.size());
01030     for (int i = 0; i < los_power.size(); ++i) {
01031       los_power(i) = relative_power(i);
01032       los_dopp(i) = (relative_power(i) > 0) ? 0.7 : 0.0;
01033     }
01034     init_flag = false;
01035   }
01036 
01037   void TDL_Channel::set_LOS_doppler(const vec& relative_doppler)
01038   {
01039     it_assert(relative_doppler.size() == los_power.size(),
01040         "TDL_Channel::set_LOS_doppler(): Improper size of input vector");
01041 
01042     it_assert(n_dopp > 0, "TDL_Channel::set_LOS_doppler(): Normalized Doppler needs to be non zero to set the LOS Doppler in a Correlated fading generator");
01043 
01044     los_dopp.set_size(relative_doppler.size());
01045     for (int i = 0; i < relative_doppler.size(); ++i) {
01046       it_assert((relative_doppler(i) >= 0) && (relative_doppler(i) <= 1.0),
01047     "TDL_Channel::set_LOS_doppler(): Normalized Doppler out of range");
01048       los_dopp(i) = relative_doppler(i);
01049     }
01050 
01051     init_flag = false;
01052   }
01053 
01054 
01055   void TDL_Channel::set_doppler_spectrum(const DOPPLER_SPECTRUM *tap_spectrum)
01056   {
01057     it_assert(N_taps > 0, "TDL_Channel::set_doppler_spectrum(): Channel profile not defined yet");
01058 
01059     it_assert(n_dopp > 0, "TDL_Channel::set_doppler_spectrum(): Normalized Doppler needs to be non zero to set the Doppler spectrum in the Correlated Rice MEDS fading generator");
01060 
01061     if (method != Rice_MEDS)
01062     method = Rice_MEDS;
01063 
01064     tap_doppler_spectrum.set_size(N_taps, false);
01065     for (int i = 0; i < N_taps; i++)
01066       tap_doppler_spectrum(i) = tap_spectrum[i];
01067 
01068     init_flag = false;
01069   }
01070 
01071   void TDL_Channel::set_doppler_spectrum(int tap_number, DOPPLER_SPECTRUM tap_spectrum)
01072   {
01073     it_assert((tap_number >= 0) && (tap_number < N_taps),
01074         "TDL_Channel::set_doppler_spectrum(): Improper tap number");
01075 
01076     it_assert(n_dopp > 0, "TDL_Channel::set_doppler_spectrum(): Normalized Doppler needs to be non zero to set the Doppler spectrum in the Correlated Rice MEDS fading generator");
01077 
01078     if (method != Rice_MEDS)
01079     method = Rice_MEDS;
01080 
01081     tap_doppler_spectrum.set_size(N_taps, true);
01082     tap_doppler_spectrum(tap_number) = tap_spectrum;
01083 
01084     init_flag = false;
01085   }
01086 
01087   void TDL_Channel::set_no_frequencies(int no_freq)
01088   {
01089     it_assert(n_dopp > 0, "TDL_Channel::set_no_frequencies(): Normalized Doppler needs to be non zero to set the number of frequencies in the Correlated Rice MEDS fading generator");
01090     nrof_freq = no_freq;
01091     if (method != Rice_MEDS)
01092     method = Rice_MEDS;
01093 
01094     init_flag = false;
01095   }
01096 
01097 
01098   void TDL_Channel::set_filter_length(int fir_length)
01099   {
01100     it_assert(n_dopp > 0, "TDL_Channel::set_filter_length(): Normalized Doppler needs to be non zero to use the Correlated FIR fading generator");
01101 
01102     filter_length = fir_length;
01103     if (method != FIR)
01104     method = FIR;
01105 
01106     init_flag = false;
01107   }
01108 
01109 
01110   void TDL_Channel::set_time_offset(int offset)
01111   {
01112     it_assert(n_dopp > 0, "TDL_Channel::set_time_offset(): Normalized Doppler needs to be non zero to set time offset in a Correlated fading generator");
01113 
01114     if (init_flag == false)
01115       init();
01116 
01117     for (int i = 0; i < N_taps; i++) {
01118       fading_gen(i)->set_time_offset(offset);
01119     }
01120   }
01121 
01122 
01123   void TDL_Channel::shift_time_offset(int no_samples)
01124   {
01125     it_assert(n_dopp > 0, "TDL_Channel::shift_time_offset(): Normalized Doppler needs to be non zero to shift time offset in a Correlated fading generator");
01126 
01127     if (init_flag == false)
01128       init();
01129 
01130     for (int i = 0; i < N_taps; i++) {
01131       fading_gen(i)->shift_time_offset(no_samples);
01132     }
01133   }
01134 
01135 
01136   void TDL_Channel::get_channel_profile(vec &avg_power_dB,
01137           ivec &delay_prof) const
01138   {
01139     avg_power_dB = 20 * log10(a_prof);
01140     delay_prof = d_prof;
01141   }
01142 
01143   vec TDL_Channel::get_avg_power_dB() const
01144   {
01145     return (20 * log10(a_prof));
01146   }
01147 
01148   double TDL_Channel::get_time_offset() const
01149   {
01150     if (fading_gen(0) != NULL)
01151       return fading_gen(0)->get_time_offset();
01152     else
01153       return -1.0;
01154   }
01155 
01156   double TDL_Channel::calc_mean_excess_delay() const
01157   {
01158     return ( sqr(a_prof)*d_prof / sum_sqr(a_prof));
01159   }
01160 
01161   double TDL_Channel::calc_rms_delay_spread() const
01162   {
01163     double a = ( sqr(a_prof)*d_prof / sum_sqr(a_prof));
01164     double b = ( sqr(a_prof)*sqr(to_vec(d_prof)) / sum_sqr(a_prof) );
01165 
01166     return ( std::sqrt(b-a*a) );
01167   }
01168 
01169   void TDL_Channel::init()
01170   {
01171     it_assert(N_taps > 0, "TDL_Channel::init(): Channel profile not defined yet");
01172     it_assert(N_taps == los_power.size(),
01173         "TDL_Channel::init(): LOS profile does not mach the channel profile");
01174 
01175     if (fading_gen.size() > 0) { // delete all old generators
01176       for (int i = 0; i < fading_gen.size(); i++) {
01177   if (fading_gen(i) != NULL) {
01178     delete fading_gen(i);
01179     fading_gen(i) = NULL;
01180   }
01181       }
01182     }
01183 
01184     // create all generators and set the parameters
01185     fading_gen.set_size(N_taps, false);
01186     switch (fading_type) {
01187 
01188     case Independent:
01189       for (int i = 0; i < N_taps; ++i) {
01190   fading_gen(i) = new Independent_Fading_Generator();
01191   if (los_power(i) > 0)
01192     fading_gen(i)->set_LOS_power(los_power(i));
01193   fading_gen(i)->init();
01194       }
01195       break;
01196 
01197     case Static:
01198       for (int i = 0; i < N_taps; ++i) {
01199   fading_gen(i) = new Static_Fading_Generator();
01200   if (los_power(i) > 0)
01201     fading_gen(i)->set_LOS_power(los_power(i));
01202   fading_gen(i)->init();
01203       }
01204       break;
01205 
01206     case Correlated:
01207       it_assert(n_dopp > 0,
01208     "TDL_Channel::init(): Correlated fading requires non zero normalized Doppler");
01209 
01210       switch (method) {
01211       case Rice_MEDS:
01212   // The third parameter is the number of sine waveforms that create the
01213   // fading process. It is increased by 2 for each tap to make taps
01214   // uncorrelated. Minimum number of waveforms set explicitly to 16.
01215   for (int i = 0; i < N_taps; ++i) {
01216     fading_gen(i) = new Rice_Fading_Generator(n_dopp, tap_doppler_spectrum(i),
01217                 nrof_freq + 2*i, MEDS);
01218     if (los_power(i) > 0) {
01219       fading_gen(i)->set_LOS_power(los_power(i));
01220       fading_gen(i)->set_LOS_doppler(los_dopp(i));
01221     }
01222     fading_gen(i)->init();
01223   }
01224   break;
01225 
01226       case FIR:
01227   for (int i = 0; i < N_taps; ++i) {
01228     it_assert(tap_doppler_spectrum(i) == Jakes,
01229         "TDL_Channel::init(): FIR fading generator can be used with Jakes spectrum only");
01230     fading_gen(i) = new FIR_Fading_Generator(n_dopp);
01231     if (los_power(i) > 0) {
01232       fading_gen(i)->set_LOS_power(los_power(i));
01233       fading_gen(i)->set_LOS_doppler(los_dopp(i));
01234     }
01235     if (filter_length > 0)
01236       fading_gen(i)->set_filter_length(filter_length);
01237     fading_gen(i)->init();
01238   }
01239   break;
01240 
01241       case IFFT:
01242   for (int i = 0; i < N_taps; ++i) {
01243     it_assert(tap_doppler_spectrum(i) == Jakes,
01244         "TDL_Channel::init(): IFFT fading generator can be used with Jakes spectrum only");
01245     fading_gen(i) = new IFFT_Fading_Generator(n_dopp);
01246     if (los_power(i) > 0) {
01247       fading_gen(i)->set_LOS_power(los_power(i));
01248       fading_gen(i)->set_LOS_doppler(los_dopp(i));
01249     }
01250     fading_gen(i)->init();
01251   }
01252   break;
01253 
01254       default:
01255   it_error("TDL_Channel::init(): No such fading generation method");
01256       }
01257       break;
01258 
01259     default:
01260       it_error("TDL_Channel::init(): No such fading type");
01261     };
01262 
01263     init_flag = true;
01264   }
01265 
01266   void TDL_Channel::generate(int no_samples, Array<cvec> &channel_coeff)
01267   {
01268     if (init_flag == false)
01269       init();
01270 
01271     channel_coeff.set_size(N_taps, false);
01272     for (int i = 0; i < N_taps; i++)
01273       channel_coeff(i) = a_prof(i) * fading_gen(i)->generate(no_samples);
01274   }
01275 
01276   void TDL_Channel::generate(int no_samples, cmat &channel_coeff)
01277   {
01278     if (init_flag == false)
01279       init();
01280 
01281     channel_coeff.set_size(no_samples, N_taps, false);
01282     for (int i = 0; i < N_taps; i++)
01283       channel_coeff.set_col(i, a_prof(i) * fading_gen(i)->generate(no_samples));
01284   }
01285 
01286 
01287   void TDL_Channel::filter_known_channel(const cvec &input, cvec &output, const Array<cvec> &channel_coeff)
01288   {
01289     int maxdelay = max(d_prof);
01290 
01291     output.set_size(input.size()+maxdelay, false);
01292     output.zeros();
01293 
01294     for (int i=0; i<N_taps; i++)
01295       output += concat( zeros_c(d_prof(i)), elem_mult(input, channel_coeff(i)), zeros_c(maxdelay-d_prof(i)) );
01296   }
01297 
01298   void TDL_Channel::filter_known_channel(const cvec &input, cvec &output, const cmat &channel_coeff)
01299   {
01300     int maxdelay = max(d_prof);
01301 
01302     output.set_size(input.size()+maxdelay, false);
01303     output.zeros();
01304 
01305     for (int i=0; i<N_taps; i++)
01306       output += concat( zeros_c(d_prof(i)), elem_mult(input, channel_coeff.get_col(i)), zeros_c(maxdelay-d_prof(i)) );
01307   }
01308 
01309   void TDL_Channel::filter(const cvec &input, cvec &output, Array<cvec> &channel_coeff)
01310   {
01311     generate(input.size(), channel_coeff);
01312     filter_known_channel(input, output, channel_coeff);
01313   }
01314 
01315   void TDL_Channel::filter(const cvec &input, cvec &output, cmat &channel_coeff)
01316   {
01317     generate(input.size(), channel_coeff);
01318     filter_known_channel(input, output, channel_coeff);
01319   }
01320 
01321   cvec TDL_Channel::filter(const cvec &input, Array<cvec> &channel_coeff)
01322   {
01323     cvec output;
01324     filter(input, output, channel_coeff);
01325     return output;
01326   }
01327 
01328   cvec TDL_Channel::filter(const cvec &input, cmat &channel_coeff)
01329   {
01330     cvec output;
01331     filter(input, output, channel_coeff);
01332     return output;
01333   }
01334 
01335   void TDL_Channel::filter(const cvec &input, cvec &output)
01336   {
01337     Array<cvec> channel_coeff;
01338     filter(input, output, channel_coeff);
01339   }
01340 
01341   cvec TDL_Channel::filter(const cvec &input)
01342   {
01343     cvec output;
01344     filter(input, output);
01345     return output;
01346   }
01347 
01348 
01349   void TDL_Channel::operator()(const cvec &input, cvec &output, Array<cvec> &channel_coeff)
01350   {
01351     filter(input, output, channel_coeff);
01352   }
01353 
01354   void TDL_Channel::operator()(const cvec &input, cvec &output, cmat &channel_coeff)
01355   {
01356     filter(input, output, channel_coeff);
01357   }
01358 
01359 
01360   cvec TDL_Channel::operator()(const cvec &input, Array<cvec> &channel_coeff)
01361   {
01362     return filter(input, channel_coeff);
01363   }
01364 
01365   cvec TDL_Channel::operator()(const cvec &input, cmat &channel_coeff)
01366   {
01367     return filter(input, channel_coeff);
01368   }
01369 
01370   cvec TDL_Channel::operator()(const cvec &input)
01371   {
01372     return filter(input);
01373   }
01374 
01375 
01376   void TDL_Channel::calc_impulse_response(const Array<cvec> &channel_coeff, Array<cvec> &impulse_response)
01377   {
01378     it_assert(init_flag == true, "calc_impulse_response: TDL_Channel is not initialized");
01379     it_assert(N_taps == channel_coeff.size(), "calc_impulse_response: number of channel taps do not match");
01380 
01381     int no_samples = channel_coeff(0).size();
01382     it_assert(no_samples > 0, "calc_impulse_response: channel_coeff must contain samples");
01383 
01384     impulse_response.set_size(no_samples);
01385 
01386     for (int i=0; i<no_samples; i++) {
01387       impulse_response(i).set_size(d_prof(N_taps-1)+1, false);
01388       impulse_response(i).zeros();
01389 
01390       for (int j=0; j<N_taps; j++)
01391   impulse_response(i)(d_prof(j)) = channel_coeff(j)(i);
01392 
01393     }
01394   }
01395 
01396   void TDL_Channel::calc_frequency_response(const Array<cvec> &channel_coeff, Array<cvec> &frequency_response, const int fft_size)
01397   {
01398     it_assert(init_flag == true, "calc_frequency_response: TDL_Channel is not initialized");
01399     it_assert(N_taps == channel_coeff.size(), "calc_frequency_response: number of channel taps do not match");
01400 
01401     int no_samples = channel_coeff(0).size();
01402     it_assert(no_samples > 0, "calc_frequency_response: channel_coeff must contain samples");
01403 
01404     frequency_response.set_size(no_samples);
01405 
01406     it_assert(fft_size > d_prof(N_taps-1), "calc_frequency_response: fft_size must be larger than the maximum delay in samples");
01407     cvec impulse_response(fft_size);
01408 
01409     for (int i=0; i<no_samples; i++) {
01410       impulse_response.zeros();
01411 
01412       for (int j=0; j<N_taps; j++)
01413   impulse_response(d_prof(j)) = channel_coeff(j)(i);
01414 
01415       fft(impulse_response, frequency_response(i));
01416 
01417     }
01418   }
01419 
01420   void TDL_Channel::calc_frequency_response(const cmat &channel_coeff, cmat &frequency_response, const int fft_size)
01421   {
01422     it_assert(init_flag == true, "calc_frequency_response: TDL_Channel is not initialized");
01423     it_assert(N_taps == channel_coeff.cols(), "calc_frequency_response: number of channel taps do not match");
01424 
01425     int no_samples = channel_coeff.rows();
01426     it_assert(no_samples > 0, "calc_frequency_response: channel_coeff must contain samples");
01427 
01428     frequency_response.set_size(fft_size, no_samples, false);
01429 
01430     it_assert(fft_size > d_prof(N_taps-1), "calc_frequency_response: fft_size must be larger than the maximum delay in samples");
01431     cvec impulse_response(fft_size);
01432     cvec freq;
01433 
01434     for (int i=0; i<no_samples; i++) {
01435       impulse_response.zeros();
01436 
01437       for (int j=0; j<N_taps; j++)
01438   impulse_response(d_prof(j)) = channel_coeff(i, j);
01439 
01440       fft(impulse_response, freq);
01441       frequency_response.set_col(i, freq);
01442     }
01443   }
01444 
01445   void TDL_Channel::discretize(const vec &delay_profile)
01446   {
01447     it_assert(N_taps > 0, "TDL_Channel::discretize(): No channel profile specified");
01448     it_assert(delay_profile(0) == 0, "TDL_Channel::discretize(): First tap should be at zero delay");
01449     it_assert(discrete_Ts > 0, "TDL_Channel::discretize(): Incorrect sampling time");
01450     it_assert((a_prof.size() == N_taps) && (delay_profile.size() == N_taps)
01451         && (los_power.size() == N_taps) && (tap_doppler_spectrum.size() == N_taps),
01452         "TDL_Channel:: discretize(): Channel profile lenghts must be equal to the number of taps");
01453 
01454     vec p_prof = sqr(a_prof); // Power profile
01455     ivec delay_prof(N_taps);
01456     vec power(N_taps);
01457     double spower;
01458     vec scattered(N_taps), direct(N_taps);
01459     vec los_doppler(N_taps);
01460     Array <DOPPLER_SPECTRUM> tap_spectrum(N_taps);
01461 
01462     delay_prof(0) = round_i(delay_profile(0)/discrete_Ts);  // should be at zero delay anyway
01463     power(0) = p_prof(0);
01464     spower = p_prof(0)/(1 + los_power(0));
01465     scattered(0) = spower;
01466     direct(0) = los_power(0) * spower;
01467     los_doppler(0) = los_dopp(0);
01468     tap_spectrum(0) = tap_doppler_spectrum(0);
01469 
01470     // taps within ((j-0.5)Ts,(j+0.5)Ts] are included in the j-th tap
01471     int j = 0, j_delay = 0;
01472     for (int i = 1; i < N_taps; i++) {
01473       if (delay_profile(i) > (j_delay + 0.5)*discrete_Ts) {
01474   // first skip empty taps
01475   while (delay_profile(i) > (j_delay + 0.5)*discrete_Ts) { j_delay++; }
01476   // create a new tap at (j+1)Ts
01477   j++;
01478   delay_prof(j) = j_delay;
01479   power(j) = p_prof(i);
01480   spower = p_prof(i)/(1 + los_power(i));
01481   scattered(j) = spower;
01482   direct(j) = los_power(i) * spower;
01483   los_doppler(j) = los_dopp(i);
01484   tap_spectrum(j) = tap_doppler_spectrum(i);
01485       }
01486       else {
01487   // add to the previously created tap
01488   power(j) += p_prof(i);
01489   spower = p_prof(i)/(1 + los_power(i));
01490   scattered(j) += spower;
01491   direct(j) += los_power(i) * spower;
01492   it_assert(tap_spectrum(j) == tap_doppler_spectrum(i),
01493       "TDL_Channel::discretize(): Sampling frequency too low. Can not discretize the channel with different Doppler spectra on merged taps.");
01494   it_warning("TDL_Channel::discretize(): Sampling frequency too low. Merging original tap " << i << " with new tap " << j << ".");
01495   if (los_doppler(j) != los_dopp(i)) {
01496     los_doppler(j) = 0.7;
01497     it_warning("TDL_Channel::discretize(): LOS Doppler value reset to 0.7 for tap " << j << " due to the merging process.");
01498   }
01499       }
01500     }
01501 
01502     int no_taps = j+1; // number of taps found
01503     if (no_taps < N_taps) {
01504       delay_prof.set_size(no_taps, true);
01505       power.set_size(no_taps, true);
01506       direct.set_size(no_taps, true);
01507       scattered.set_size(no_taps, true);
01508       los_doppler.set_size(no_taps, true);
01509       tap_spectrum.set_size(no_taps, true);
01510 
01511       // write over the existing channel profile with its new version
01512       N_taps = no_taps;
01513       a_prof = sqrt(power);
01514       los_power = elem_div(direct, scattered);
01515       los_dopp = los_doppler;
01516       tap_doppler_spectrum = tap_spectrum;
01517     }
01518     // new discretized path's delays
01519     d_prof = delay_prof; // in samples
01520   }
01521 
01522 
01523   // --------------------------------------------------------------------------
01524   // Binary Symetric Channel class methods
01525   // --------------------------------------------------------------------------
01526 
01527   bvec BSC::operator()(const bvec &input)
01528   {
01529     int i, length = input.length();
01530     bvec output(length);
01531 
01532     for (i=0; i<length; i++) {
01533       if (u() <= p) {
01534   output(i) = input(i) + bin(1);
01535       } else {
01536   output(i) = input(i);
01537       }
01538     }
01539     return output;
01540   }
01541 
01542 
01543   // --------------------------------------------------------------------------
01544   // AWGN_Channel class methods
01545   // --------------------------------------------------------------------------
01546 
01547   cvec AWGN_Channel::operator()(const cvec &input)
01548   {
01549     int n = input.size();
01550     cvec noise(n);
01551     rng_cn.sample_vector(n, noise);
01552     noise *= sigma;
01553     noise += input;
01554     return noise;
01555   }
01556 
01557   vec AWGN_Channel::operator()(const vec &input)
01558   {
01559     int n = input.size();
01560     vec noise(n);
01561     rng_n.sample_vector(n, noise);
01562     noise *= sigma;
01563     noise += input;
01564     return noise;
01565   }
01566 
01567 
01568 } // namespace itpp
SourceForge Logo

Generated on Sun Sep 14 18:52:35 2008 for IT++ by Doxygen 1.5.6