PER.cc
上传用户:rrhhcc
上传日期:2015-12-11
资源大小:54129k
文件大小:17k
源码类别:

通讯编程

开发平台:

Visual C++

  1. /*
  2.  * Copyright (c) 2007 Regents of the SIGNET lab, University of Padova.
  3.  * All rights reserved.
  4.  *
  5.  * Redistribution and use in source and binary forms, with or without
  6.  * modification, are permitted provided that the following conditions
  7.  * are met:
  8.  * 1. Redistributions of source code must retain the above copyright
  9.  *    notice, this list of conditions and the following disclaimer.
  10.  * 2. Redistributions in binary form must reproduce the above copyright
  11.  *    notice, this list of conditions and the following disclaimer in the
  12.  *    documentation and/or other materials provided with the distribution.
  13.  * 3. Neither the name of the University of Padova (SIGNET lab) nor the 
  14.  *    names of its contributors may be used to endorse or promote products 
  15.  *    derived from this software without specific prior written permission.
  16.  *
  17.  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 
  18.  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 
  19.  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 
  20.  * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR 
  21.  * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 
  22.  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 
  23.  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; 
  24.  * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 
  25.  * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR 
  26.  * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF 
  27.  * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  28.  */
  29. /* -*- Mode:C++; c-basic-offset:3; tab-width:3; indent-tabs-mode:t -*- */
  30. #include "mac.h"
  31. #include "mac-802_11mr.h"
  32. #include "PER.h"
  33. #include <math.h>
  34. #include <float.h>
  35. #include <rng.h>
  36. #define ABS(x) (((x)>=0) ? (x) : (-x) )
  37. //Completion for the ADT
  38. /// Container for the length
  39. class leng : public Object {
  40. public:
  41. int len;
  42. DLList* snr_list;
  43. leng(int len_){
  44. len=len_;
  45. snr_list= new DLList();
  46. }
  47. ~leng() {
  48. delete snr_list;
  49. }
  50. };
  51. /// Container for SNR and PER
  52. class Snr : public Object {
  53. public:
  54. double snr;
  55. double per;
  56. Snr(double snr_, double per_){
  57. snr= snr_;
  58. per= per_;
  59. }
  60. };
  61. /**
  62.  * TCL wrapper for the PER class
  63.  * 
  64.  */
  65. static class PERClass : public TclClass {
  66. public:
  67. PERClass() : TclClass("PER") {}
  68. TclObject* create(int, const char*const*) {
  69. return (new PER());
  70. }
  71. } class_per;
  72. PER::PER()
  73. {
  74. for(int i = 0 ; i < NumPhyModes ; i++)
  75. PHYmod[i] = new DLList();
  76. #ifndef COMPILING_TEST_PROGRAM
  77. bind("debug_", &debug_);
  78. bind("noise_", &noise_);
  79. #endif
  80. }
  81. PER::~PER(){
  82.   for(int i = 0 ; i < NumPhyModes ; i++)
  83. delete PHYmod[i];
  84. }
  85. int PER::command(int argc, const char*const* argv){
  86. if(debug_>2) printf("Called PER::command argc=%in",argc);
  87. if (argc == 2) {
  88. if (strcmp(argv[1], "print") == 0) {
  89. print_data();
  90.  return TCL_OK;
  91. }
  92. } else if (argc == 6) {
  93. // Command to add PER entries to PER table
  94. if (strcmp(argv[1], "add") == 0) {
  95.                        
  96. PhyMode pm = str2PhyMode(argv[2]);
  97. if (pm==ModeUnknown) return(TCL_ERROR);
  98. int len =   atoi(argv[3]);
  99. double snr = atof(argv[4]);
  100. double  per = atof(argv[5]);
  101. if(debug_>2)  printf("%s=%f ------- %s=%fn",argv[4],snr,argv[5],per);
  102. set_per(pm,len,snr,per);
  103. return TCL_OK;    
  104. }
  105. }
  106. }
  107. int PER::get_err(PowerProfile* pp, Packet* pkt, double* snrptr, double* snirptr, double* interfptr){
  108. if(debug_>3)
  109. {
  110. printf("PER::get_err(): dumping everythingn");
  111. for (int i=0; i< 12; i++)
  112. {
  113. if(PHYmod[i]!=0)
  114. {
  115. NSNode* nl  = (NSNode*)(PHYmod[i]->first());
  116. while(nl !=0  )
  117. {
  118. cout << ((leng*)nl->element())->len << "n";
  119. DLList* sl = ((leng*)nl->element())->snr_list;
  120. NSNode* ns =(NSNode*)sl->first();
  121. while( ns !=0 )
  122. {
  123. cout << ((Snr*)ns->element())->snr << "  " ;
  124. cout << ((Snr*)ns->element())->per << "n" ;
  125. ns  = (NSNode*)(sl->after(ns));
  126. }
  127. nl  = (NSNode*)(PHYmod[i]->after(nl));
  128. }
  129. }
  130. }
  131. }
  132. /* Hack needed not to link the whole NS with the test program */ 
  133. #ifdef COMPILING_TEST_PROGRAM         
  134. double pkt_pow = 0 ;
  135. int len = 0;
  136. PhyMode pm=Mode1Mb;
  137. double duration = 1;
  138. #else        
  139. struct hdr_cmn *hdr = HDR_CMN(pkt);
  140. struct MultiRateHdr *hdm = HDR_MULTIRATE(pkt);
  141. double pkt_pow = pkt->txinfo_.RxPr;
  142. double duration = hdr->txtime(); 
  143. PhyMode pm = hdm->mode(); 
  144. int len = hdr->size(); 
  145. #endif
  146. double avgpower = avg(pp,duration);
  147. double interf = avgpower-pkt_pow;
  148. double snr1=DBL_MAX; 
  149. double snr2;
  150. double per1;
  151. double per2;
  152. if (ABS(noise_) > DBL_MIN)
  153. {
  154. snr1 = 10*log10(pkt_pow/(noise_));
  155. per1 = get_per( pm, snr1, len);
  156. }
  157. else
  158. per1 = 0;
  159. if (ABS(noise_ + interf) > DBL_MIN)
  160. {
  161. snr2 = 10*log10(pkt_pow/(noise_ + interf));
  162. per2 = get_per( pm, snr2, len);
  163. }
  164. else
  165. per2=0;
  166. /* Return SNR */
  167. if (snrptr!=NULL)
  168. *snrptr = snr1;
  169. /* Return SNIR */
  170. if (snirptr!=NULL)
  171. *snirptr = snr2;
  172. /* Return interfering power */
  173. if (interfptr!=NULL)
  174. *interfptr = interf;
  175. // double x = (double) rand()/(double)RAND_MAX;
  176. double x = RNG::defaultrng()->uniform_double();
  177. //if ((debug_)&&(interf>1e-15))
  178. if ((debug_))
  179. {
  180. cout << "PER::get_err() at " << Scheduler::instance().clock() << "sn" ;
  181. cout << "PER::get_err() Average received power      "<< avgpower << " Wn"; 
  182. cout << "PER::get_err() Signal power                "<< pkt_pow << " Wn";
  183. cout << "PER::get_err() Noise power                 "<< noise_ << " Wn";
  184. cout << "PER::get_err() Interference power          "<< interf<< " Wn";
  185. cout << "PER::get_err() SNR (noise only)            "<< snr1<< " dBn";
  186. cout << "PER::get_err() SNIR (noise + interference) "<< snr2<< " dBn";
  187. cout << "PER::get_err() PER due to noise only "<< per1 << "n"; 
  188. cout << "PER::get_err() PER due to noise and interference "<< per2<< "n";
  189. cout << "PER::get_err() Rand "<< x<< "n";
  190. }
  191.   if (x<per1) 
  192. return PKT_ERROR_NOISE; 
  193. else if (x<per2) 
  194. return PKT_ERROR_INTERFERENCE ; 
  195. else 
  196. return PKT_OK; 
  197. }
  198. int PER::get_per(PhyMode pm, double tsnr, double tlen, per_set* ps_){
  199. DLList* snrlist;
  200. NSNode* pl1 =0;
  201. NSNode* pl2 =0;
  202. NSNode* ps1 =0;
  203. NSNode* ps2 =0;
  204. NSNode* ps3 =0;
  205. NSNode* ps4 =0;
  206. //cerco la lunghezza
  207. pl1 = (NSNode*)PHYmod[pm]->first();
  208.  
  209. if(pl1 == 0) {
  210.   cerr << "No PER entry found for PHYMode " << PhyMode2str(pm) << endl;
  211. return 1;
  212. }
  213. while (pl1 != PHYmod[pm]->last() && ((leng*)pl1->element())->len < tlen ){
  214. pl1=(NSNode*)PHYmod[pm]->after(pl1);
  215. }
  216. //pl1 o e' il primo maggiore o uguale di tlen o e' l'ultimo
  217. //prendo quello precedente (potrebbe essere nullo)
  218. if (((leng*)pl1->element())->len > tlen)
  219. pl2 = (NSNode*)PHYmod[pm]->before(pl1);
  220. snrlist = ((leng*)pl1->element())->snr_list;
  221. //cerco snr nella prima lunghezza
  222. ps1 = (NSNode*)snrlist->first();
  223. if(ps1 == 0) {
  224. cerr<<"Tabella non inizializzata 2";
  225. return 1;
  226. }
  227. while ( ps1 != snrlist->last()  && ((Snr*)ps1->element())->snr < tsnr  ) {
  228. ps1=(NSNode*)PHYmod[pm]->after(ps1);
  229. }
  230. //ps1 o e' maggiore di tsnr o e' l'ultimo
  231. //prendo quello precedente
  232. if (((Snr*)ps1->element())->snr > tsnr)
  233. ps2 = (NSNode*)snrlist->before(ps1);
  234. //se le lunghezze erano due diverse cerco snr anche nella seconda
  235. if ((pl1 != pl2) & (pl2 != 0)){
  236. //cerr << "dicversi";
  237. snrlist = ((leng*)pl2->element())->snr_list;
  238. //cerco
  239. ps3 = (NSNode*)snrlist->first();
  240. if(ps3 == 0) {
  241. cerr<<"Tabella non inizializzata 3";
  242. return 1;
  243. }
  244. while (not (((Snr*)ps3->element())->snr >= tsnr or ps3 == snrlist->last() ) ){
  245. ps3=(NSNode*)PHYmod[pm]->after(ps3);
  246. }
  247. //prendo anche quello precedente
  248. if (((Snr*)ps3->element())->snr > tsnr)
  249. ps4 = (NSNode*)snrlist->before(ps3);
  250. }
  251. //settaggio delle variabili di uscita in base ai risultati della ricerca. 
  252. //I valori /1 indicano che no e
  253. if (ps1){
  254. //cerr << ps_;
  255. ((Snr*)ps1->element())->snr;
  256. ps_->snr[0] = ((Snr*)ps1->element())->snr;
  257. ps_->per[0] = ((Snr*)ps1->element())->per;
  258. ps_->len[0] = ((leng*)pl1->element())->len;
  259. }else{
  260. ps_->snr[0] = -1;
  261. ps_->per[0] = -1;
  262. ps_->len[0] = -1;
  263. }
  264. if (ps2){
  265. ps_->snr[1] = ((Snr*)ps2->element())->snr;
  266. ps_->per[1] = ((Snr*)ps2->element())->per;
  267. ps_->len[1] = ((leng*)pl1->element())->len;
  268. }else{
  269. ps_->snr[1] = -1;
  270. ps_->per[1] = -1;
  271. ps_->len[1] = -1;
  272. }
  273. if (ps3){
  274. ps_->snr[2] = ((Snr*)ps3->element())->snr;
  275. ps_->per[2] = ((Snr*)ps3->element())->per;
  276. ps_->len[2] = ((leng*)pl2->element())->len;
  277. }else{
  278. ps_->snr[2] = -1;
  279. ps_->per[2] = -1;
  280. ps_->len[2] = -1;
  281. }
  282. if (ps4){
  283. ps_->snr[3] = ((Snr*)ps4->element())->snr;
  284. ps_->per[3] = ((Snr*)ps4->element())->per;
  285. ps_->len[3] = ((leng*)pl2->element())->len;
  286. }else{
  287. ps_->snr[3] = -1;
  288. ps_->per[3] = -1;
  289. ps_->len[3] = -1;
  290. }
  291. if (debug_ > 2) {
  292. int i;
  293. printf("Pointers: %x %x %x %xn",ps1,ps2,ps3,ps4);
  294. fprintf(stderr,"4 PER table entries: n");
  295. for(i=0; i<4; i++)
  296. fprintf(stderr,"t %d %f %f  n", ps_->len[i], ps_->snr[i], ps_->per[i] );
  297. }
  298. }
  299. void PER::set_per(PhyMode phy, int l , double snr, double per)
  300. {
  301. NSNode* nl  = (NSNode*)(PHYmod[phy]->first());
  302. if (nl==0){
  303. leng* le = new leng(l);
  304. PHYmod[phy]->insertFirst(le);
  305. le->snr_list->insertFirst(new Snr(snr,per));
  306. }else{
  307. while(nl !=0 && l>((leng*)nl->element())->len)
  308. nl  = (NSNode*)(PHYmod[phy]->after(nl));
  309. if (nl==0){
  310. leng* le =  new leng(l);
  311. PHYmod[phy]->insertLast(le);
  312. le->snr_list->insertFirst(new Snr(snr,per));
  313. }else
  314. {
  315. if (((leng*)nl->element())->len==l){
  316. DLList* sl = ((leng*)nl->element())->snr_list;
  317. NSNode* ns =(NSNode*)sl->first();
  318. while( ns !=0 && ((Snr*)ns->element())->snr<snr )
  319. ns  = (NSNode*)(sl->after(ns));
  320. if (ns==0){
  321. sl->insertLast(new Snr(snr,per));
  322. }
  323. else{
  324. sl->insertBefore(ns,new Snr(snr,per));
  325. }
  326. }else{
  327. leng* le =  new leng(l);
  328. PHYmod[phy]->insertBefore(nl,le);
  329. le->snr_list->insertFirst(new Snr(snr,per));
  330. }
  331. }
  332. }
  333. }
  334. double PER::get_per(PhyMode pm, double tsnr, double tlen){
  335. struct per_set ps_;
  336. get_per( pm,  tsnr, tlen, &ps_);
  337. int len1 = -1;
  338. int len2 = -1;
  339. double per1 = -1;
  340. double per2 = -1;
  341. double per = -1;
  342. //not found entries are set equal  to the clesest one
  343. //cerr <<  ps_.len[0] << ps_.len[1] << ps_.len[2] << ps_.len[3];
  344. if(ps_.len[0]==-1){
  345. ps_.len[0]=ps_.len[1];
  346. ps_.snr[0]=ps_.snr[1];
  347. ps_.per[0]=ps_.per[1];
  348. }
  349. if(ps_.len[1]==-1){
  350. ps_.len[1]=ps_.len[0];
  351. ps_.snr[1]=ps_.snr[0];
  352. ps_.per[1]=ps_.per[0];
  353. }
  354. if(ps_.len[2]==-1){
  355. ps_.len[2]=ps_.len[3];
  356. ps_.snr[2]=ps_.snr[3];
  357. ps_.per[2]=ps_.per[3];
  358. }
  359. if(ps_.len[3]==-1){
  360. ps_.len[3]=ps_.len[2];
  361. ps_.snr[3]=ps_.snr[2];
  362. ps_.per[3]=ps_.per[2];
  363. }
  364. if (debug_ > 2) {
  365. int i;
  366. fprintf(stderr,"4 PER table entries: n");
  367. for(i=0; i<4; i++)
  368. fprintf(stderr,"t %d %f %f  n", ps_.len[i], ps_.snr[i], ps_.per[i] );
  369. }
  370. // intepolation: 1) linear interpolation at the varying of the SNR for each length
  371. // 2) linear interpolation among lenghts 
  372. if (ps_.snr[1] != ps_.snr[0])
  373. per1 = ps_.per[0] +  (ps_.per[1]- ps_.per[0])/(ps_.snr[1]- ps_.snr[0])*(tsnr- ps_.snr[0]);
  374. else 
  375. per1 = ps_.per[1];
  376. if (ps_.snr[3] != ps_.snr[2])
  377. per2 = ps_.per[2] +  (ps_.per[3]- ps_.per[2])/(ps_.snr[3]- ps_.snr[2])*(tsnr- ps_.snr[2]);
  378. else
  379. per2 = ps_.per[2];
  380. if (per1!=-1 && per2!=-1){
  381. if (ps_.len[3] != ps_.len[1])
  382. per = per1 +  (per2- per1)/(ps_.len[3]- ps_.len[1])*(tlen-ps_.len[1]);
  383. else
  384. per = per1;
  385. }
  386. else 
  387. if (per1!=-1){
  388. per = per1;
  389. }else 
  390. if (per2!=-1){
  391. per = per2;
  392. }else {cerr << "No PER available";}
  393. return per;
  394. }
  395. //compute the mean average power given by the time power profile.
  396. double PER::avg(PowerProfile* pp,double duration){
  397.   if (debug_>1)  printf("PER::avg()  starting calculationsn");
  398. double avg_pow = 0 ;
  399. for (int i=0; i< pp->getNumElements()-1; i++){
  400. double a =  pp->getElement(i).power;
  401. //double b = pp->getElement(i+1).power;
  402. //cerr << "pot ist" << a << " "<< b << "---n"; 
  403. double dt = (pp->getElement(i+1).time -pp->getElement(i).time);
  404. avg_pow = avg_pow + a * dt;
  405. if (debug_>1)  printf("PER::avg()  power=%2.10f t dt=%fn",a,dt);
  406. }
  407. double a = pp->getElement(pp->getNumElements()-1).power;
  408. double dt = (duration -pp->getElement(pp->getNumElements()-1).time);
  409. // avg_pow = avg_pow + pp->getElement(pp->getNumElements()-1).power * (duration -pp->getElement(pp->getNumElements()-1).time);
  410. avg_pow = avg_pow + a * dt;
  411. if (debug_>1)  printf("PER::avg()  power=%2.10f t dt=%f duration=%fn",a,dt,duration);
  412. //cerr << "average0" << pp->getElement(1).time - pp->getElement(0).time;
  413. avg_pow = avg_pow / duration;
  414. if(debug_>1) printf("PER::avg() finished calculations: at %f average power=%2.10fn", Scheduler::instance().clock(),avg_pow);
  415. return avg_pow;
  416. }
  417. int PER::get_snr(PhyMode pm, double tper, double tlen, per_set* ps_){
  418. DLList* snrlist;
  419. NSNode* pl1 =0;
  420. NSNode* pl2 =0;
  421. NSNode* ps1 =0;
  422. NSNode* ps2 =0;
  423. NSNode* ps3 =0;
  424. NSNode* ps4 =0;
  425. //cerco la lunghezza
  426. pl1 = (NSNode*)PHYmod[pm]->first();
  427. if(pl1 == 0) {
  428. cerr<<"Tabella non inizializzata 1";
  429. return 1;
  430. }
  431. while (pl1 != PHYmod[pm]->last() && ((leng*)pl1->element())->len < tlen ){
  432. pl1=(NSNode*)PHYmod[pm]->after(pl1);
  433. }
  434. //pl1 o e' il primo maggiore o uguale di tlen o e' l'ultimo
  435. //prendo quello precedente (potrebbe essere nullo)
  436. if (((leng*)pl1->element())->len > tlen)
  437. pl2 = (NSNode*)PHYmod[pm]->before(pl1);
  438. snrlist = ((leng*)pl1->element())->snr_list;
  439. //cerco snr nella prima lunghezza
  440. ps1 = (NSNode*)snrlist->first();
  441. if(ps1 == 0) {
  442. cerr<<"Tabella non inizializzata 2";
  443. return 1;
  444. }
  445. while ( ps1 != snrlist->last()  && ((Snr*)ps1->element())->per > tper  ) {
  446. ps1=(NSNode*)PHYmod[pm]->after(ps1);
  447. }
  448. //ps1 o e' minore di tper o e' l'ultimo
  449. //prendo quello precedente
  450. if (((Snr*)ps1->element())->per < tper)
  451. ps2 = (NSNode*)snrlist->before(ps1);
  452. //se le lunghezze erano due diverse cerco snr anche nella seconda
  453. if ((pl1 != pl2) & (pl2 != 0)){
  454. //cerr << "dicversi";
  455. snrlist = ((leng*)pl2->element())->snr_list;
  456. //cerco
  457. ps3 = (NSNode*)snrlist->first();
  458. if(ps3 == 0) {
  459. cerr<<"Tabella non inizializzata 3";
  460. return 1;
  461. }
  462. while (not (((Snr*)ps3->element())->per <= tper or ps3 == snrlist->last() ) ){
  463. ps3=(NSNode*)PHYmod[pm]->after(ps3);
  464. }
  465. //prendo anche quello precedente
  466. if (((Snr*)ps3->element())->per < tper)
  467. ps4 = (NSNode*)snrlist->before(ps3);
  468. }
  469. //settaggio delle variabili di uscita in base ai risultati della ricerca. 
  470. //I valori /1 indicano che no e
  471. if (ps1){
  472. //cerr << ps_;
  473. ((Snr*)ps1->element())->snr;
  474. ps_->snr[0] = ((Snr*)ps1->element())->snr;
  475. ps_->per[0] = ((Snr*)ps1->element())->per;
  476. ps_->len[0] = ((leng*)pl1->element())->len;
  477. }else{
  478. ps_->snr[0] = -123456789;
  479. ps_->per[0] = -1;
  480. ps_->len[0] = -1;
  481. }
  482. if (ps2){
  483. ps_->snr[1] = ((Snr*)ps2->element())->snr;
  484. ps_->per[1] = ((Snr*)ps2->element())->per;
  485. ps_->len[1] = ((leng*)pl1->element())->len;
  486. }else{
  487. ps_->snr[1] = -123456789;
  488. ps_->per[1] = -1;
  489. ps_->len[1] = -1;
  490. }
  491. if (ps3){
  492. ps_->snr[2] = ((Snr*)ps3->element())->snr;
  493. ps_->per[2] = ((Snr*)ps3->element())->per;
  494. ps_->len[2] = ((leng*)pl2->element())->len;
  495. }else{
  496. ps_->snr[2] = -123456789;
  497. ps_->per[2] = -1;
  498. ps_->len[2] = -1;
  499. }
  500. if (ps4){
  501. ps_->snr[3] = ((Snr*)ps4->element())->snr;
  502. ps_->per[3] = ((Snr*)ps4->element())->per;
  503. ps_->len[3] = ((leng*)pl2->element())->len;
  504. }else{
  505. ps_->snr[3] = -123456789;
  506. ps_->per[3] = -1;
  507. ps_->len[3] = -1;
  508. }
  509. }
  510. double PER::get_snr(PhyMode pm, double tper, double tlen){
  511. struct per_set ps_;
  512. get_snr( pm,  tper, tlen, &ps_);
  513. int len1 = -1;
  514. int len2 = -1;
  515. double snr1 = -123456789;
  516. double snr2 = -123456789;
  517. double snr = -123456789;
  518. //not found entries are set equal  to the clesest one
  519. //cerr <<  ps_.len[0] << ps_.len[1] << ps_.len[2] << ps_.len[3];
  520. if(ps_.len[0]==-1){
  521. ps_.len[0]=ps_.len[1];
  522. ps_.snr[0]=ps_.snr[1];
  523. ps_.per[0]=ps_.per[1];
  524. }
  525. if(ps_.len[1]==-1){
  526. ps_.len[1]=ps_.len[0];
  527. ps_.snr[1]=ps_.snr[0];
  528. ps_.per[1]=ps_.per[0];
  529. }
  530. if(ps_.len[2]==-1){
  531. ps_.len[2]=ps_.len[3];
  532. ps_.snr[2]=ps_.snr[3];
  533. ps_.per[2]=ps_.per[3];
  534. }
  535. if(ps_.len[3]==-1){
  536. ps_.len[3]=ps_.len[2];
  537. ps_.snr[3]=ps_.snr[2];
  538. ps_.per[3]=ps_.per[2];
  539. }
  540. // intepolation: 1) linear interpolation at the varying of the PER for each length
  541. // 2) linear interpolation among lenghts 
  542. if (ps_.snr[0] == ps_.snr[1])
  543. snr1 = ps_.snr[0];
  544. else
  545. snr1 = ps_.snr[0] +  (ps_.snr[1]- ps_.snr[0])/(ps_.per[1]- ps_.per[0])*(tper- ps_.per[0]);
  546. if (ps_.snr[2] == ps_.snr[3])
  547. snr2 = ps_.snr[2];
  548. else
  549. snr2 = ps_.snr[2] +  (ps_.snr[3]- ps_.snr[2])/(ps_.per[3]- ps_.per[2])*(tper- ps_.per[2]);
  550. if (snr1!=-123456789 && snr2!=-123456789){
  551. if (ps_.len[3] != ps_.len[1])
  552. snr = snr1 +  (snr2- snr1)/(ps_.len[3]- ps_.len[1])*(tlen-ps_.len[1]);
  553. else 
  554. snr = snr1;
  555. }
  556. else 
  557. if (snr1!=-123456789){
  558. snr = snr1;
  559. }else 
  560. if (snr2!=-123456789){
  561. snr = snr2;
  562. }else {cerr << "No SNR available " << snr << " " << pm << " " << tper <<" " << tlen << "/n";}
  563. return snr;
  564. }
  565. void PER::print_data(){
  566. for (int i = 0 ; i<= Mode54Mb; i++) {
  567. for (int l = 128 ; l<= 1024; l=l*2) {
  568. for (double per = 0 ; per<1; per=per+0.1) {
  569. printf("%d %d %f %f n",i,l,per,get_snr((PhyMode)i, per , l));
  570. }
  571. }
  572. }
  573. }