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