![]() |
four_multi
Multi-Antenna,Multi-Node,Multi-Band,Multi-Cell
|
00001 // 00002 // Copyright 2011-2013, Per Zetterberg, KTH Royal Institute of Technology 00003 // 00004 // This program is free software: you can redistribute it and/or modify 00005 // it under the terms of the GNU General Public License as published by 00006 // the Free Software Foundation, either version 3 of the License, or 00007 // (at your option) any later version. 00008 // 00009 // This program is distributed in the hope that it will be useful, 00010 // but WITHOUT ANY WARRANTY; without even the implied warranty of 00011 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00012 // GNU General Public License for more details. 00013 // 00014 // You should have received a copy of the GNU General Public License 00015 // along with this program. If not, see <http://www.gnu.org/licenses/>. 00016 // 00017 00018 00019 #include "simulator.hpp" 00020 #include "four_multi.hpp" 00021 #include <itpp/itbase.h> 00022 #include <itpp/base/itfile.h> 00023 #include <itpp/itsignal.h> 00024 #include <ctime> 00025 00026 00027 using namespace itpp; 00028 00040 void simulate(std::vector<four_multi_node*> *nodes,channel_model *c){ 00041 std::vector<four_multi_node*> cnodes; 00042 cnodes=*nodes; 00043 frame_settings next_frame; 00044 frame_settings next_frame_all[nodes->size()]; 00045 frame_settings next_next_frame_all[nodes->size()]; 00046 std::complex<int16_t> *pr; // Pointers to receive buffers. 00047 std::complex<int16_t> *pt; // Pointers to transmit buffers. 00048 double gain_tx, gain_rx, f_tx, f_rx; 00049 uint32_t no_ant_tx, no_ant_rx; 00050 uint32_t buffer_length; 00051 bool all_are_done; 00052 void* feedback_buffers[(nodes->size())*(nodes->size())]; 00053 bool feedback_buffers_empty[(nodes->size())*(nodes->size())]; 00054 uint32_t num_nodes; 00055 00056 num_nodes=nodes->size(); 00057 00058 00059 #if 0 00060 buffer_length=cnodes[0]->d_buffer_length; 00061 for (uint32_t node_counter=1;node_counter<nodes->size();node_counter++){ 00062 if (!(buffer_length==cnodes[node_counter]->d_buffer_length)) { 00063 std::cout << "All nodes must have the same buffer length \n"; 00064 exit(1); 00065 } 00066 }; 00067 #endif 00068 00069 00070 for (uint32_t node_counter1=0;node_counter1<nodes->size();node_counter1++){ 00071 for (uint32_t node_counter2=0;node_counter2<nodes->size();node_counter2++){ 00072 cnodes[node_counter1]->d_simulate=true; 00073 //feedback_buffers_empty[node_counter1+num_nodes*node_counter2]=new bool; 00074 feedback_buffers_empty[node_counter1+num_nodes*node_counter2]=true; 00075 }; 00076 }; 00077 00078 00079 for (uint32_t node_counter=0;node_counter<nodes->size();node_counter++){ 00080 cnodes[node_counter]->feedback_buffers=feedback_buffers; 00081 cnodes[node_counter]->feedback_buffers_empty=feedback_buffers_empty; 00082 cnodes[node_counter]->num_nodes=num_nodes; 00083 }; 00084 00085 00086 for (uint32_t node_counter=0;node_counter<nodes->size();node_counter++){ 00087 next_frame=cnodes[node_counter]->node_init(); 00088 while (IS_CALIB_BURST(next_frame)) { 00089 next_frame=cnodes[node_counter]->node_process(); 00090 }; 00091 next_frame_all[node_counter]=next_frame; 00092 }; 00093 00094 00095 all_are_done=true; 00096 for (uint32_t node_counter=0;node_counter<nodes->size();node_counter++){ 00097 next_frame=next_frame_all[node_counter]; 00098 if (!(next_frame.what==END)) 00099 all_are_done=false; 00100 }; 00101 00102 00103 00104 while (!all_are_done) { 00105 00106 00107 std::cout << "================================================ \n"; 00108 00109 double time; 00110 00111 uint32_t node_counter0; 00112 for (node_counter0=0;node_counter0<nodes->size();node_counter0++){ 00113 if (!(next_frame_all[node_counter0].what==END)) { 00114 time=(double) next_frame_all[node_counter0].time.get_real_secs(); 00115 break; 00116 } 00117 }; 00118 for (uint32_t node_counter=node_counter0;node_counter<nodes->size();node_counter++){ 00119 00120 if (!(next_frame_all[node_counter].what==END)) { 00121 00122 if (!(time==(double) next_frame_all[node_counter].time.get_real_secs())) { 00123 std::cout << "All nodes must have the same frame times \n"; 00124 exit(1); 00125 }; 00126 }; 00127 }; 00128 00129 00130 std::cout << "time=" << time << "\n"; 00131 00132 00133 00134 for (uint32_t node_rx=0;node_rx<nodes->size();node_rx++){ 00135 no_ant_rx=cnodes[node_rx]->d_no_ant1+cnodes[node_rx]->d_no_ant2; 00136 00137 00138 if (next_frame_all[node_rx].what==RX) { 00139 00140 for (uint32_t i1=0;i1<no_ant_rx;i1++) { 00141 00142 if (i1<next_frame_all[node_rx].frequency.size()) { 00143 f_rx=next_frame_all[node_rx].frequency[i1]; 00144 } else { 00145 f_rx=next_frame_all[node_rx].frequency.back(); 00146 }; 00147 00148 00149 if (i1<next_frame_all[node_rx].gain_rx.size()) { 00150 gain_rx=next_frame_all[node_rx].gain_rx[i1]; 00151 } 00152 else { 00153 gain_rx=next_frame_all[node_rx].gain_rx.back(); 00154 }; 00155 00156 00157 pr=(std::complex<short int>*)(cnodes[node_rx]->d_rx_buffers[i1]); 00158 for (uint32_t i2=0;i2<cnodes[node_rx]->d_buffer_length;i2++) { 00159 pr[i2]=0; 00160 }; 00161 00162 for (uint32_t node_tx=0;node_tx<nodes->size();node_tx++){ 00163 00164 00165 if (next_frame_all[node_tx].what==TX) { 00166 00167 00168 no_ant_tx=cnodes[node_tx]->d_no_ant1+cnodes[node_tx]->d_no_ant2; 00169 00170 for (uint32_t i2=0;i2<no_ant_tx;i2++) { 00171 00172 00173 if (i2<next_frame_all[node_tx].frequency.size()) 00174 f_tx=next_frame_all[node_tx].frequency[i2]; 00175 else 00176 f_tx=next_frame_all[node_tx].frequency.back(); 00177 00178 if (i2<next_frame_all[node_tx].gain_tx.size()) 00179 gain_tx=next_frame_all[node_tx].gain_tx[i2]; 00180 else 00181 gain_tx=next_frame_all[node_tx].gain_tx.back(); 00182 00183 00184 pt=(std::complex<short int>*) cnodes[node_tx]->d_tx_buffers[i2]; 00185 00186 buffer_length=cnodes[node_tx]->d_buffer_length; 00187 if ((cnodes[node_rx]->d_buffer_length)<buffer_length) 00188 buffer_length=cnodes[node_rx]->d_buffer_length; 00189 00190 c->sub_channel(node_tx,node_rx,i2,i1,f_tx,f_rx,time,gain_tx, 00191 gain_rx,pt,pr,buffer_length); 00192 }; 00193 }; 00194 }; 00195 // Add noise 00196 buffer_length=cnodes[node_rx]->d_buffer_length; 00197 c->add_noise(gain_rx,pr,buffer_length); 00198 }; 00199 // Process the received data at the receivers 00200 00201 if (cnodes[node_rx]->save_input_on_file) { 00202 cnodes[node_rx]->log_raw_buffer(cnodes[0]->d_buffer_length); 00203 }; 00204 next_frame=cnodes[node_rx]->node_process(); 00205 next_next_frame_all[node_rx]=next_frame; 00206 }; 00207 00208 }; 00209 00210 00211 // Do all the transmitters 00212 for (uint32_t node_tx=0;node_tx<nodes->size();node_tx++){ 00213 if (next_frame_all[node_tx].what==TX) { 00214 next_frame=cnodes[node_tx]->node_process(); 00215 next_next_frame_all[node_tx]=next_frame; 00216 }; 00217 }; 00218 00219 00220 // Those who have ended 00221 for (uint32_t node_tx=0;node_tx<nodes->size();node_tx++){ 00222 if (next_frame_all[node_tx].what==END) { 00223 next_next_frame_all[node_tx].what=END; 00224 }; 00225 }; 00226 00227 00228 for (uint32_t node_counter=0;node_counter<nodes->size();node_counter++){ 00229 next_frame_all[node_counter]=next_next_frame_all[node_counter]; 00230 }; 00231 00232 00233 00234 all_are_done=true; 00235 for (uint32_t node_counter=0;node_counter<nodes->size();node_counter++){ 00236 next_frame=next_frame_all[node_counter]; 00237 if (!(next_frame.what==END)) 00238 all_are_done=false; 00239 }; 00240 00241 00242 }; 00243 for (uint32_t node_ix=0;node_ix<nodes->size();node_ix++){ 00244 if (cnodes[node_ix]->save_input_on_file) { 00245 cnodes[node_ix]->save_logged_raw_data(); 00246 }; 00247 cnodes[node_ix]->end_of_run(); 00248 }; 00249 std::cout << "Simulation done! \n"; 00250 00251 }; 00252 00253 void block_fading::sub_channel(uint32_t from_node_ix 00254 ,uint32_t to_node_ix, uint32_t from_antenna_ix, uint32_t to_antenna_ix, 00255 double freq_tx, double freq_rx, double time, double gain_tx, double gain_rx, 00256 std::complex<short int> const* signal_in, std::complex<short int>* signal_out,uint32_t number_of_samples) 00257 { 00258 00259 00260 // Save the old seed and create a random 00261 ivec seed_state; 00262 RNG_get_state(seed_state); 00263 if (seed==0) 00264 RNG_randomize(); 00265 else { 00266 RNG_reset(seed); 00267 seed++; 00268 }; 00269 // Randomize a single coefficient 00270 std::complex<double> h; 00271 itpp::cvec s_in, s_out; 00272 00273 // Set length of ITPP vectors 00274 s_in.set_length(number_of_samples); 00275 s_out.set_length(number_of_samples); 00276 00277 // Convert input to cvec 00278 for (uint32_t i1=0;i1<number_of_samples;i1++) { 00279 s_in[i1]=signal_in[i1]; 00280 }; 00281 00282 // Convert receiver buffer to cvec 00283 for (uint32_t i1=0;i1<number_of_samples;i1++) { 00284 s_out[i1]=signal_out[i1]; 00285 }; 00286 00287 00288 // Do the channel model 00289 mat temp; 00290 double t; 00291 temp=old_time[from_node_ix][to_node_ix]; 00292 t=temp.get(from_antenna_ix,to_antenna_ix); 00293 00294 for (uint32_t i3=0;i3<num_of_taps;i3++) { 00295 00296 if (time>t) { 00297 h=itpp::randn_c(); 00298 h=forgetting_factor*(old_h[from_node_ix][to_node_ix][i3]). 00299 get(from_antenna_ix,to_antenna_ix)+ 00300 sqrt(1-forgetting_factor*forgetting_factor)*h; 00301 old_h[from_node_ix][to_node_ix][i3].set(from_antenna_ix,to_antenna_ix,h); 00302 } else { 00303 h=(old_h[from_node_ix][to_node_ix][i3]).get(from_antenna_ix, to_antenna_ix); 00304 }; 00305 00306 if (is_awgn) { 00307 if (i3==0) 00308 h=1; 00309 else 00310 h=0; 00311 }; 00312 if (is_diagonal) { 00313 if (from_antenna_ix!=to_antenna_ix) { 00314 h=0; 00315 }; 00316 }; 00317 00318 h=path_gain[from_node_ix][to_node_ix]*scaling_signal*h; 00319 h=h/sqrt(num_of_taps); 00320 for (int i4=i3;i4<s_in.length();i4++) { 00321 s_out(i4)+=h*s_in(i4-i3); 00322 }; 00323 }; 00324 // Convert output to std::complex<short int> 00325 for (uint32_t i1=0;i1<number_of_samples;i1++) { 00326 signal_out[i1]=s_out[i1]; 00327 }; 00328 00329 // Reset the seed 00330 RNG_set_state(seed_state); 00331 00332 }; 00333 00334 void block_fading::add_noise(double gain_rx, 00335 std::complex<short int>* signal, 00336 uint32_t number_of_samples) { 00337 00338 itpp::cvec s, n; 00339 00340 // Save the old seed and create a random 00341 ivec seed_state; 00342 RNG_get_state(seed_state); 00343 RNG_randomize(); 00344 00345 00346 // Set length of ITPP vectors 00347 s.set_length(number_of_samples); 00348 00349 // Convert input to cvec 00350 for (uint32_t i1=0;i1<number_of_samples;i1++) { 00351 s[i1]=signal[i1]; 00352 }; 00353 00354 // Generate noise 00355 n=itpp::randn_c(number_of_samples); 00356 n=scaling_noise*n; 00357 00358 00359 // Add noise 00360 s=s+n; 00361 00362 // Convert output to std::complex<short int> 00363 for (uint32_t i1=0;i1<number_of_samples;i1++) { 00364 signal[i1]=s[i1]; 00365 }; 00366 00367 // Reset the seed 00368 RNG_set_state(seed_state); 00369 00370 00371 00372 } 00373 00374 block_fading::block_fading(void) { 00375 00376 scaling_signal=0.45; 00377 scaling_noise=4.5;//21.7; 00378 seed=0; 00379 forgetting_factor=0.0; 00380 is_awgn=false; 00381 is_diagonal=false; 00382 num_of_taps=1; 00383 // Save the old seed and create a random 00384 ivec seed_state; 00385 RNG_get_state(seed_state); 00386 if (seed==0) 00387 RNG_randomize(); 00388 else { 00389 RNG_reset(seed); 00390 seed=seed+1; 00391 }; 00392 00393 00394 for (uint32_t i1=0;i1<max_num_nodes;i1++) { 00395 for (uint32_t i2=0;i2<max_num_nodes;i2++) { 00396 old_time[i1][i2].set_size(max_num_ant,max_num_ant); 00397 old_time[i1][i2].zeros(); 00398 path_gain[i1][i2]=1.0; 00399 for (uint32_t i3=0;i3<max_num_taps;i3++) { 00400 old_h[i1][i2][i3].set_size(max_num_ant,max_num_ant); 00401 old_h[i1][i2][i3]=randn_c(max_num_ant,max_num_ant); 00402 }; 00403 }; 00404 }; 00405 // Reset the seed 00406 RNG_set_state(seed_state); 00407 00408 00409 }; 00410 00411 void block_fading::reset(void) { 00412 00413 ivec seed_state; 00414 00415 RNG_get_state(seed_state); 00416 if (seed==0) 00417 RNG_randomize(); 00418 else { 00419 RNG_reset(seed); 00420 seed++; 00421 }; 00422 00423 for (uint32_t i1=0;i1<max_num_nodes;i1++) { 00424 for (uint32_t i2=0;i2<max_num_nodes;i2++) { 00425 old_time[i1][i2].zeros(); 00426 for (uint32_t i3=0;i3<max_num_taps;i3++) { 00427 old_h[i1][i2][i3]=randn_c(max_num_ant,max_num_ant); 00428 }; 00429 }; 00430 }; 00431 00432 //std::cout << "old_h=" << old_h[0][0][0](0,0) << "\n"; 00433 00434 // Reset the seed 00435 RNG_set_state(seed_state); 00436 00437 00438 }; 00439 00440 from_file::from_file(std::string directory_name) { 00441 raw_data_dir=directory_name; 00442 for (uint32_t i1=0;i1<max_num_nodes;i1++) { 00443 for (uint32_t i2=0;i2<max_num_nodes;i2++) { 00444 old_time[i1][i2].set_size(max_num_ant,max_num_ant); 00445 old_time[i1][i2]=-ones(max_num_ant,max_num_ant); 00446 frame_ix[i1][i2].set_size(max_num_ant,max_num_ant); 00447 frame_ix[i1][i2]=-ones_i(max_num_ant,max_num_ant); 00448 00449 }; 00450 }; 00451 }; 00452 00453 00454 00455 00456 00457 00458 00459 void from_file::sub_channel(uint32_t from_node_ix,uint32_t to_node_ix, 00460 uint32_t from_antenna_ix, uint32_t to_antenna_ix 00461 , double freq_tx, double freq_rx, 00462 double time, double gain_tx, double gain_rx, 00463 std::complex<short int> const* signal_in, std::complex<short int>* signal_out,uint32_t number_of_samples) { 00464 00465 00466 mat temp; 00467 double t; 00468 int f_ix; 00469 std::string filename; 00470 std::stringstream temp_ss; 00471 std::ifstream s1; 00472 00473 temp=old_time[from_node_ix][to_node_ix]; 00474 t=temp.get(from_antenna_ix,to_antenna_ix); 00475 00476 f_ix=frame_ix[from_node_ix][to_node_ix](from_antenna_ix,to_antenna_ix); 00477 00478 if (time>t) { 00479 f_ix++; 00480 (frame_ix[from_node_ix][to_node_ix])(from_antenna_ix,to_antenna_ix)=f_ix; 00481 (old_time[from_node_ix][to_node_ix])(from_antenna_ix,to_antenna_ix)=time; 00482 }; 00483 00484 temp_ss << to_node_ix; 00485 filename=raw_data_dir+"node="+temp_ss.str()+"_"; 00486 temp_ss.str(""); 00487 temp_ss << f_ix; 00488 filename+="frame="+temp_ss.str()+".dat"; 00489 temp_ss.str(""); 00490 //std::cout << "filename=" << filename << std::endl; 00491 00492 s1.open(filename.c_str(), std::ios::binary); 00493 for (uint32_t i1=0;i1<to_antenna_ix+1;i1++) { 00494 s1.read((char *) signal_out,number_of_samples*4); 00495 }; 00496 s1.close(); 00497 00498 00499 }; 00500 00501 OFDM_channel_from_file::OFDM_channel_from_file(std::string filename, 00502 ivec num_ant,int Nfft,int Nc, 00503 ivec ix_all ,int tx_start_sample, int rx_start_sample, 00504 double signal_scaling, double EVM,double EVM_RX, double CPE) { 00505 00506 d_EVM=EVM; 00507 d_EVM_RX=EVM_RX; 00508 d_CPE=CPE; 00509 d_filename=filename; 00510 d_num_ant=num_ant; 00511 d_num_nodes=d_num_ant.length(); 00512 d_Nfft=Nfft; 00513 d_signal_scaling=signal_scaling; 00514 d_Nc=Nc; 00515 d_tx_start_sample=tx_start_sample; 00516 d_rx_start_sample=rx_start_sample; 00517 d_frame_ix=0; 00518 t_old=0; 00519 d_ix_all=ix_all; 00520 counter=0; 00521 rand_cpe.set_size(max_num_ant,max_num_nodes); 00522 00523 for (int i1=0;i1<d_num_nodes;i1++) { 00524 for (int i2=0;i2<d_num_nodes;i2++) { 00525 for (int i3=0;i3<d_num_ant(i1);i3++) { 00526 (H[i1][i2][i3]).set_size(d_num_ant(i2),ix_all.length()); 00527 }; 00528 }; 00529 }; 00530 00531 00532 std::stringstream temp_ss; 00533 temp_ss << d_frame_ix; 00534 load_file(d_filename+"_frame_ix="+temp_ss.str()+".dat"); 00535 00536 }; 00537 00538 void OFDM_channel_from_file::reset(void) { 00539 d_frame_ix=0; 00540 t_old=0; 00541 counter=0; 00542 std::stringstream temp_ss; 00543 temp_ss << d_frame_ix; 00544 load_file(d_filename+"_frame_ix="+temp_ss.str()+".dat"); 00545 }; 00546 00547 void OFDM_channel_from_file::load_file(std::string filename) { 00548 00549 00550 std::ifstream s1; 00551 s1.open(filename.c_str(), std::ios::binary); 00552 double r,i; 00553 00554 for (int i2=0;i2<d_num_nodes;i2++) { 00555 for (int i1=0;i1<d_num_nodes;i1++) { 00556 00557 00558 for (int i5=0;i5<d_ix_all.length();i5++) { 00559 for (int i4=0;i4<d_num_ant(i1);i4++) { 00560 for (int i3=0;i3<d_num_ant(i2);i3++) { 00561 00562 00563 s1.read((char *) &r,sizeof(double)); 00564 real(H[i1][i2][i4](i3,i5))=r; 00565 00566 00567 00568 }; 00569 }; 00570 }; 00571 00572 00573 for (int i5=0;i5<d_ix_all.length();i5++) { 00574 for (int i4=0;i4<d_num_ant(i1);i4++) { 00575 for (int i3=0;i3<d_num_ant(i2);i3++) { 00576 s1.read((char *) &i,sizeof(double)); 00577 imag(H[i1][i2][i4](i3,i5))=i; 00578 00579 }; 00580 }; 00581 }; 00582 00583 }; 00584 }; 00585 s1.close(); 00586 00587 double x,y; 00588 vec tempn; 00589 //rand_cpe=d_CPE*randn(max_num_ant,max_num_nodes); 00590 for (int i1=0;i1<(int) max_num_ant;i1++) { 00591 for (int i2=0;i2<(int) max_num_nodes;i2++) { 00592 tempn=randu(2); 00593 x=tempn(0); 00594 if (x<0.5) 00595 y=(1/sqrt(2))*log(2.0*x); 00596 else 00597 y=(1/sqrt(2))*log(2.0*(1-x)); 00598 00599 if (x>0.5){ 00600 y=-y; 00601 }; 00602 rand_cpe(i1,i2)=d_CPE*y; 00603 }; 00604 }; 00605 00606 00607 }; 00608 00609 00610 void OFDM_channel_from_file::sub_channel(uint32_t from_node_ix, 00611 uint32_t to_node_ix, 00612 uint32_t from_antenna_ix, uint32_t to_antenna_ix 00613 , double freq_tx, double freq_rx, 00614 double time, double gain_tx, double gain_rx, 00615 std::complex<short int> const* signal_in, std::complex<short int>* signal_out, 00616 uint32_t number_of_samples) { 00617 00618 cvec s_in, s_out; 00619 00620 if (time>t_old) { 00621 d_frame_ix++; 00622 std::stringstream temp_ss; 00623 temp_ss << d_frame_ix; 00624 load_file(d_filename+"_frame_ix="+temp_ss.str()+".dat"); 00625 t_old=time; 00626 }; 00627 00628 00629 // Set length of ITPP vectors 00630 s_in.set_length(number_of_samples); 00631 s_out.set_length(number_of_samples); 00632 00633 // Convert input to cvec 00634 for (uint32_t i1=0;i1<number_of_samples;i1++) { 00635 s_in[i1]=signal_in[i1]; 00636 }; 00637 s_in/=d_signal_scaling; 00638 00639 // Convert receiver buffer to cvec 00640 for (uint32_t i1=0;i1<number_of_samples;i1++) { 00641 s_out[i1]=signal_out[i1]; 00642 }; 00643 00644 // Do the channel model 00645 int sample_ix=d_tx_start_sample; 00646 cvec w(d_Nfft), W(d_Nfft); 00647 cvec Hc(d_Nfft); 00648 cvec st(d_Nfft), St(d_Nfft); 00649 bool cond=true; 00650 00651 Hc.zeros(); 00652 00653 while (cond) { 00654 00655 for (int i1=0;i1<d_ix_all.length();i1++){ 00656 Hc(d_ix_all(i1)) 00657 =H[from_node_ix][to_node_ix][from_antenna_ix](to_antenna_ix,i1); 00658 }; 00659 Hc=std::polar(1.0,rand_cpe(from_antenna_ix,from_node_ix)*0.017453)*Hc; 00660 00661 w=s_in.mid(sample_ix,d_Nfft); 00662 W=fft(w); 00663 St=elem_mult(Hc,W); 00664 st=ifft(St); 00665 double c=sum_sqr(abs(st))/((double) d_Nfft); 00666 00667 c=c*(((double) (d_Nfft))/((double) (d_ix_all.length())))* 00668 (((double) (d_Nfft))/((double) (d_ix_all.length()))); 00669 c=d_EVM*sqrt(c); 00670 st=st+c*randn_c(d_Nfft); 00671 00672 00673 for (int i1=0;i1<d_Nfft;i1++) { 00674 s_out[sample_ix+d_rx_start_sample-d_tx_start_sample+i1]+=st(i1); 00675 }; 00676 sample_ix+=d_Nfft+d_Nc; 00677 00678 cond=sample_ix<((int) number_of_samples-d_Nfft); 00679 cond=cond && (sample_ix+d_rx_start_sample-d_tx_start_sample+d_Nfft+d_Nc < 00680 (int) number_of_samples); 00681 00682 counter++; 00683 00684 }; 00685 00686 00687 // Convert output to std::complex<short int> 00688 for (int i1=0;i1<(int) number_of_samples;i1++) { 00689 signal_out[i1]=s_out[i1]; 00690 }; 00691 }; 00692 00693 00694 void OFDM_channel_from_file::add_noise(double gain_rx, 00695 std::complex<short int>* signal, 00696 uint32_t number_of_samples) { 00697 00698 itpp::cvec s, n, n_evm; 00699 00700 // Save the old seed and create a random 00701 ivec seed_state; 00702 RNG_get_state(seed_state); 00703 RNG_randomize(); 00704 00705 00706 // Set length of ITPP vectors 00707 s.set_length(number_of_samples); 00708 00709 // Convert input to cvec 00710 for (uint32_t i1=0;i1<number_of_samples;i1++) { 00711 s[i1]=signal[i1]; 00712 }; 00713 00714 // Calculate power for receive EVM generation 00715 double power=0.0; 00716 double power_local=0; 00717 int sample_ix=d_rx_start_sample; 00718 int no_of_symbols=0; 00719 bool cond=sample_ix<((int) number_of_samples-d_Nfft); 00720 while (cond) { 00721 power_local=0.0; 00722 for (int i1=0;i1<d_Nfft;i1++) { 00723 power_local+=abs(s(sample_ix))*abs(s(sample_ix)); 00724 }; 00725 power_local=power_local/((double) d_Nfft); 00726 if (sqrt(power_local)>10) { 00727 power+=power_local; 00728 no_of_symbols++; 00729 }; 00730 sample_ix+=d_Nfft+d_Nc; 00731 cond=sample_ix<((int) number_of_samples-d_Nfft); 00732 }; 00733 00734 power*=(((double) (d_Nfft))/((double) (d_ix_all.length())))* 00735 (((double) (d_Nfft))/((double) (d_ix_all.length()))); 00736 power=power/((double) no_of_symbols); 00737 00738 // Generate noise 00739 n=itpp::randn_c(number_of_samples); 00740 n=scaling_noise*n; 00741 00742 // Generate RX EVM 00743 n_evm=itpp::randn_c(number_of_samples); 00744 n_evm=d_EVM_RX*sqrt(power)*n_evm; 00745 00746 00747 // Add noise and EVM 00748 //s=s+n+n_evm; 00749 00750 // Convert output to std::complex<short int> 00751 for (uint32_t i1=0;i1<number_of_samples;i1++) { 00752 signal[i1]=s[i1]; 00753 }; 00754 00755 // Reset the seed 00756 RNG_set_state(seed_state); 00757 00758 00759 00760 }