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

Generated on Sun Jul 26 08:54:27 2009 for IT++ by Doxygen 1.5.9