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
Generated on Wed Feb 9 2011 13:47:23 for IT++ by Doxygen 1.7.3