IT++ Logo
channel.cpp
Go to the documentation of this file.
00001 
00030 #include <itpp/comm/channel.h>
00031 #include <itpp/base/math/error.h>
00032 #include <itpp/base/math/trig_hyp.h>
00033 #include <itpp/base/bessel.h>
00034 #include <itpp/base/matfunc.h>
00035 #include <itpp/base/specmat.h>
00036 #include <itpp/signal/resampling.h>
00037 #include <itpp/signal/transforms.h>
00038 #include <itpp/signal/window.h>
00039 #include <itpp/base/math/min_max.h>
00040 #include <itpp/stat/misc_stat.h>
00041 
00042 
00043 namespace itpp
00044 {
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)
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)
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)
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)
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)
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)
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)
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)
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     double tmp_re, tmp_im;
00300     if (los_power > 0.0) { // LOS component exists
00301       for (int i = 0; i < no_samples; i++) {
00302         tmp_re = sum(elem_mult(c1, cos(m_2pi * f1 * n_dopp * (i + time_offset) + th1)));
00303         tmp_im = sum(elem_mult(c2, cos(m_2pi * f2 * n_dopp * (i + time_offset) + th2)));
00304         output(i) = std::complex<double>(tmp_re, tmp_im);
00305         add_LOS(i, output(i));
00306       }
00307     }
00308     else {
00309       for (int i = 0; i < no_samples; i++) {
00310         tmp_re = sum(elem_mult(c1, cos(m_2pi * f1 * n_dopp * (i + time_offset) + th1)));
00311         tmp_im = sum(elem_mult(c2, cos(m_2pi * f2 * n_dopp * (i + time_offset) + th2)));
00312         output(i) = std::complex<double>(tmp_re, tmp_im);
00313       }
00314     }
00315     break;
00316   }
00317   case GaussI:
00318   case GaussII: {
00319     double tmp;
00320     for (int i = 0; i < no_samples; i++) {
00321       tmp = m_2pi * n_dopp * (i + time_offset);
00322       output(i) = sum(elem_mult(c1, cos(f1 * tmp + th1)))
00323                   * std::complex<double>(std::cos(f01 * tmp), -std::sin(f01 * tmp))
00324                   + sum(elem_mult(c2, cos(f2 * tmp + th2)))
00325                   * std::complex<double>(std::cos(f02 * tmp), -std::sin(f02 * tmp));
00326     }
00327     break;
00328   }
00329   }
00330 
00331   time_offset += no_samples;
00332 }
00333 
00334 void Rice_Fading_Generator::init_MEDS()
00335 {
00336   vec n;
00337   double sgm_0_2;
00338 
00339   switch (dopp_spectrum) {
00340   case Jakes:
00341     n = linspace(1, Ni, Ni);
00342     f1 = sin(pi / (2 * Ni) * (n - 0.5));
00343     c1 = std::sqrt(1.0 / Ni) * ones(Ni);
00344     th1 = randu(Ni) * 2 * pi;
00345     n = linspace(1, Ni + 1, Ni + 1);
00346     f2 = sin(pi / (2 * (Ni + 1)) * (n - 0.5));
00347     c2 = std::sqrt(1.0 / (Ni + 1)) * ones(Ni + 1);
00348     th2 = randu(Ni + 1) * 2 * pi;
00349     f01 = f02 = 0;
00350     break;
00351   case GaussI:
00352     n = linspace(1, Ni, Ni);
00353     sgm_0_2 = 5.0 / 6.0;
00354     c1 = std::sqrt(sgm_0_2 * 2.0 / Ni) * ones(Ni);
00355     f1 = std::sqrt(2.0) * 0.05 * erfinv((2 * n - 1) / (2 * Ni));
00356     th1 = randu(Ni) * 2 * pi;
00357     sgm_0_2 = 1.0 / 6.0;
00358     c2 = std::sqrt(sgm_0_2 * 2.0 / Ni) * ones(Ni);
00359     f2 = std::sqrt(2.0) * 0.1 * erfinv((2 * n - 1) / (2 * Ni));
00360     th2 = randu(Ni) * 2 * pi;
00361     f01 = 0.8;
00362     f02 = -0.4;
00363     break;
00364   case GaussII:
00365     n = linspace(1, Ni, Ni);
00366     sgm_0_2 = std::sqrt(10.0) / (std::sqrt(10.0) + 0.15);
00367     c1 = std::sqrt(sgm_0_2 * 2.0 / Ni) * ones(Ni);
00368     f1 = std::sqrt(2.0) * 0.1 * erfinv((2 * n - 1) / (2 * Ni));
00369     th1 = randu(Ni) * 2 * pi;
00370     sgm_0_2 = 0.15 / (std::sqrt(10.0) + 0.15);
00371     c2 = std::sqrt(sgm_0_2 * 2.0 / Ni) * ones(Ni);
00372     f2 = std::sqrt(2.0) * 0.15 * erfinv((2 * n - 1) / (2 * Ni));
00373     th2 = randu(Ni) * 2 * pi;
00374     f01 = -0.7;
00375     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     }
01536     else {
01537       output(i) = input(i);
01538     }
01539   }
01540   return output;
01541 }
01542 
01543 
01544 // --------------------------------------------------------------------------
01545 // AWGN_Channel class methods
01546 // --------------------------------------------------------------------------
01547 
01548 cvec AWGN_Channel::operator()(const cvec &input)
01549 {
01550   int n = input.size();
01551   cvec noise(n);
01552   rng_cn.sample_vector(n, noise);
01553   noise *= sigma;
01554   noise += input;
01555   return noise;
01556 }
01557 
01558 vec AWGN_Channel::operator()(const vec &input)
01559 {
01560   int n = input.size();
01561   vec noise(n);
01562   rng_n.sample_vector(n, noise);
01563   noise *= sigma;
01564   noise += input;
01565   return noise;
01566 }
01567 
01568 
01569 } // namespace itpp
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines
SourceForge Logo

Generated on Wed Jul 27 2011 16:27:04 for IT++ by Doxygen 1.7.4