PageRenderTime 53ms CodeModel.GetById 22ms RepoModel.GetById 0ms app.codeStats 0ms

/src/linklayer/radio/Ieee80211gRadioModel.cc

https://github.com/Sorouri/inetmanet
C++ | 715 lines | 573 code | 92 blank | 50 comment | 153 complexity | 422d49c8d6df1830b529178dc22d7c34 MD5 | raw file
Possible License(s): GPL-2.0
  1. //
  2. // Copyright (C) 2006 Andras Varga, Levente Meszaros
  3. // Based on the Mobility Framework's SnrEval by Marc Loebbers
  4. //
  5. // This program is free software; you can redistribute it and/or
  6. // modify it under the terms of the GNU General Public License
  7. // as published by the Free Software Foundation; either version 2
  8. // of the License, or (at your option) any later version.
  9. //
  10. // This program is distributed in the hope that it will be useful,
  11. // but WITHOUT ANY WARRANTY; without even the implied warranty of
  12. // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  13. // GNU General Public License for more details.
  14. //
  15. // You should have received a copy of the GNU General Public License
  16. // along with this program; if not, write to the Free Software
  17. // Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
  18. //
  19. #include <fstream>
  20. #include <sstream>
  21. #include <string>
  22. #include "Ieee80211gRadioModel.h"
  23. #include "Ieee80211Consts.h"
  24. #include "FWMath.h"
  25. static const unsigned short comb_calc[15][15]=
  26. {
  27. { 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
  28. { 2, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
  29. { 3, 3, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
  30. { 4, 6, 4, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
  31. { 5, 10, 10, 5, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
  32. { 6, 15, 20, 15, 6, 1, 0, 0, 0, 0, 0, 0, 0, 0 },
  33. { 7, 21, 35, 35, 21, 7, 1, 0, 0, 0, 0, 0, 0, 0 },
  34. { 8, 28, 56, 70, 56, 28, 8, 1, 0, 0, 0, 0, 0, 0 },
  35. { 9, 36, 84, 126, 126, 84, 36, 9, 1, 0, 0, 0, 0, 0 },
  36. { 10, 45, 120, 210, 252, 210, 120, 45, 10, 1, 0, 0, 0, 0 },
  37. { 11, 55, 165, 330, 462, 462, 330, 165, 55, 11, 1, 0, 0, 0 },
  38. { 12, 66, 220, 495, 792, 924, 792, 495, 220, 66, 12, 1, 0, 0 },
  39. { 13, 78, 286, 715, 1287, 1716, 1716, 1287, 715, 286, 78, 13, 1, 0 },
  40. { 14, 91, 364, 1001, 2002, 3003, 3432, 3003, 2002, 1001, 364, 91, 14, 1 }
  41. };
  42. /*
  43. unsigned long comb(int n,int k){
  44. unsigned long long p1=1, p2=1,i;
  45. for(i=0; i<=k-1; i++)
  46. p1=p1*(n-i);
  47. for(i=2; i<=k; i++)
  48. p2=p2*i;
  49. return p1/p2;
  50. }
  51. */
  52. static unsigned short comb(int n,int k)
  53. {
  54. ASSERT(n>=1 && n<=14 && k>=1 && k<=14);
  55. return comb_calc[n-1][k-1];
  56. }
  57. static double Pd(int d, double Pb){
  58. long double sum=0.0;
  59. int k;
  60. if(d%2 == 1){
  61. for(k=(d+1)/2; k<=d; k++)
  62. sum+=comb(d,k)*pow(Pb,k)*pow(1.0-Pb, d-k);
  63. }
  64. else{
  65. sum=0.5*comb(d,d/2)*pow(Pb, d/2)*pow(1.0-Pb,d/2);
  66. for(k=d/2+1; k<=d; k++)
  67. sum+=comb(d,k)*pow(Pb,k)*pow(1.0-Pb, d-k);
  68. }
  69. //printf("prob=%f d=%d sum=%f \n",Pb,d, sum);
  70. return sum;
  71. //return pow(4*Pb*(1-Pb), d/2);
  72. }
  73. static double Pb(int rate, double prob){
  74. long double probc;
  75. switch(rate){
  76. case 1:
  77. //11, 0, 38, 0, 193, 0, 1331, 0, 7275, 0, 40406, 0, 234969, 0, 1337714, 0, 7594819, 0, 433775588, 0,
  78. probc=11*Pd(10,prob) + 38*Pd(12,prob) + 193*Pd(14,prob);//+1331*Pd(16,prob);
  79. break;
  80. case 2:
  81. //1, 16, 48, 158, 642, 2435, 9174, 34701, 131533, 499312,
  82. probc=Pd(6,prob)+16*Pd(7,prob)+48*Pd(8,prob);//+158*Pd(9,prob)+642*Pd(10,prob)
  83. // +2435*Pd(11,prob)+ 9174*Pd(12,prob)+34701*Pd(13,prob)+131533*Pd(14,prob)+499312*Pd(15,prob);
  84. break;
  85. case 3:
  86. //(8, 31, 160, 892, 4512, 23297, 120976, 624304, 3229885, 16721329,
  87. probc=8*Pd(5,prob)+31*Pd(6,prob)+150*Pd(7,prob);//+892*Pd(8,prob)+4512*Pd(9,prob)
  88. // +23297*Pd(10,prob)+120976*Pd(11,prob)+624304*Pd(12,prob)+ 3229885*Pd(13,prob)+ 16721329*Pd(14,prob);
  89. break;
  90. default:
  91. ;
  92. }
  93. return probc;
  94. }
  95. static double ber_bpsk(double snir, double bandwidth, double bitrate, char channelModel){
  96. double y=snir*bandwidth/bitrate;
  97. if(channelModel=='r')//Rayleigh
  98. return 0.5*(1.0-sqrt(y/(1.0+y)));
  99. return 0.5*erfc(sqrt(y));//awgn
  100. }
  101. static double ber_qpsk(double snir, double bandwidth, double bitrate, char channelModel){
  102. double y=snir*bandwidth/bitrate;
  103. if(channelModel=='r')//Rayleigh
  104. return 0.5*(1.0-sqrt(y/(1.0+y)));
  105. return 0.5*erfc(sqrt(y));//awgn
  106. }
  107. static double ber_16qam(double snir, double bandwidth, double bitrate, char channelModel){
  108. double y=snir*bandwidth/bitrate;
  109. if(channelModel=='r')//Rayleigh
  110. return ( 5.0/8.0-3.0/8.0*sqrt(2.0*y/(5.0+2.0*y))-1.0/4.0*sqrt(18.0*y/(5.0+18.0*y)) );
  111. return ( 0.375*erfc(sqrt(0.4*y))+0.25*erfc(3.0*sqrt(0.4*y)) );//awgn
  112. }
  113. static double ber_64qam(double snir, double bandwidth, double bitrate, char channelModel){
  114. double y=snir*bandwidth/bitrate;
  115. if(channelModel=='r')//Rayleigh
  116. return ( 13.0/24.0-7.0/24.0*sqrt(y/(7.0+y))-1.0/4.0*sqrt(9.0*y/(7.0+9.0*y)) );
  117. return 7.0/24.0*erfc(sqrt(y/7.0))+0.25*erfc(3.0*sqrt(y/7.0));//awgn
  118. }
  119. Register_Class(Ieee80211gRadioModel);
  120. double Ieee80211gRadioModel::getPer(double speed, double tsnr, int tlen){
  121. BerList *berlist;
  122. if (phyOpMode=='b')
  123. {
  124. if (speed<1)
  125. berlist = &r1m;
  126. else if (speed<=2&& speed<5)
  127. berlist = &r2m;
  128. else if (speed<=5&& speed<11)
  129. berlist = &r5m;
  130. else
  131. berlist = &r11m;
  132. }
  133. else
  134. {
  135. if (speed<9)
  136. berlist = &r6m;
  137. else if (speed<=9&& speed<12)
  138. berlist = &r9m;
  139. else if (speed<=12&& speed<18)
  140. berlist = &r12m;
  141. else if (speed<=18&& speed<24)
  142. berlist = &r18m;
  143. else if (speed<=24&& speed<36)
  144. berlist = &r24m;
  145. else if (speed<=36&& speed<48)
  146. berlist = &r36m;
  147. else if (speed<=48&& speed<54)
  148. berlist = &r48m;
  149. else
  150. berlist = &r54m;
  151. }
  152. LongBer * pre;
  153. LongBer * pos;
  154. unsigned int j;
  155. for (j=0;j<berlist->size();j++)
  156. {
  157. pos = *(berlist->begin()+j);
  158. if (pos->longpkt >=tlen)
  159. {
  160. break;
  161. }
  162. }
  163. if (j==0)
  164. pre = NULL;
  165. else
  166. {
  167. if (j==berlist->size())
  168. pre = *(berlist->begin()+j-2);
  169. else
  170. pre = *(berlist->begin()+j-1);
  171. }
  172. SnrBer snrdata1;
  173. SnrBer snrdata2;
  174. SnrBer snrdata3;
  175. SnrBer snrdata4;
  176. snrdata3.snr=-1;
  177. snrdata3.ber=-1;
  178. snrdata4.snr=-1;
  179. snrdata4.ber=-1;
  180. for (j=0;j<pos->snrlist.size();j++)
  181. {
  182. snrdata1 = pos->snrlist[j];
  183. if (tsnr<=snrdata1.snr)
  184. {
  185. break;
  186. }
  187. }
  188. if (j==0)
  189. {
  190. snrdata2.snr=-1;
  191. snrdata2.ber=-1;
  192. }
  193. else
  194. {
  195. if (j==pos->snrlist.size())
  196. snrdata2 = *(pos->snrlist.begin()+j-2);
  197. else
  198. snrdata2 = *(pos->snrlist.begin()+j-1);
  199. }
  200. if (pre==NULL)
  201. pre = pos;
  202. for (j=0;j<pre->snrlist.size();j++)
  203. {
  204. snrdata3 = pre->snrlist[j];
  205. if (tsnr<=snrdata3.snr)
  206. {
  207. break;
  208. }
  209. }
  210. if (j!=0)
  211. {
  212. if (j==pre->snrlist.size())
  213. snrdata4 =*(pre->snrlist.begin()+j-2);
  214. else
  215. snrdata4 =*(pre->snrlist.begin()+j-1);
  216. }
  217. if (snrdata2.snr==-1)
  218. {
  219. snrdata2.snr=snrdata1.snr;
  220. snrdata2.ber=snrdata1.ber;
  221. }
  222. if (snrdata4.snr==-1)
  223. {
  224. snrdata4.snr=snrdata3.snr;
  225. snrdata4.ber=snrdata3.ber;
  226. }
  227. double per1,per2,per;
  228. per1 = snrdata2.ber;
  229. per2 = snrdata3.ber;
  230. if (tsnr<= snrdata1.snr)
  231. {
  232. if (snrdata2.snr!=snrdata1.snr)
  233. per1 = snrdata1.ber + (snrdata2.ber-snrdata1.ber)/(snrdata2.snr-snrdata1.snr)*(tsnr- snrdata1.snr);
  234. }
  235. if (tsnr<= snrdata3.snr)
  236. {
  237. if (snrdata3.snr!=snrdata4.snr)
  238. per2 = snrdata3.ber + (snrdata4.ber-snrdata3.ber)/(snrdata4.snr-snrdata3.snr)*(tsnr- snrdata3.snr);
  239. }
  240. if (per1!=-1 && per2!=-1){
  241. if (pos->longpkt != pre->longpkt)
  242. per = per2 + (per1- per2)/(pos->longpkt - pre->longpkt)*(tlen-pre->longpkt);
  243. else
  244. per = per2;
  245. }
  246. else
  247. if (per1!=-1){
  248. per = per1;
  249. }else
  250. if (per2!=-1){
  251. per = per2;
  252. }else {EV << "No PER available";}
  253. return per;
  254. }
  255. void Ieee80211gRadioModel::parseFile(const char *filename)
  256. {
  257. std::ifstream in(filename, std::ios::in);
  258. if (in.fail())
  259. opp_error("Cannot open file '%s'",filename);
  260. std::string line;
  261. std::string subline;
  262. while (std::getline(in, line))
  263. {
  264. // '#' line
  265. std::string::size_type found=line.find('#');
  266. if (found == 0)
  267. continue;
  268. if (found != std::string::npos)
  269. subline = line;
  270. else
  271. subline = line.substr(0,found);
  272. found=subline.find("$self");
  273. if (found == std::string::npos)
  274. continue;
  275. // Node Id
  276. found = subline.find("add");
  277. if (found== std::string::npos)
  278. continue;
  279. // Initial position
  280. std::string::size_type pos1 = subline.find("Mode");
  281. std::string::size_type pos2 = subline.find("Mb");
  282. BerList *berlist;
  283. std::string substr = subline.substr(pos1+4,pos2-(pos1+4));
  284. // int speed = std::atof (subline.substr(pos1+4,pos2).c_str());
  285. if (!strcmp(substr.c_str(),"1"))
  286. berlist = &r1m;
  287. else if (!strcmp(substr.c_str(),"2"))
  288. berlist = &r2m;
  289. else if (!strcmp(substr.c_str(),"5_5"))
  290. berlist = &r5m;
  291. else if (!strcmp(substr.c_str(),"6"))
  292. berlist = &r6m;
  293. else if (!strcmp(substr.c_str(),"9"))
  294. berlist = &r9m;
  295. else if (!strcmp(substr.c_str(),"11"))
  296. berlist = &r11m;
  297. else if (!strcmp(substr.c_str(),"12"))
  298. berlist = &r12m;
  299. else if (!strcmp(substr.c_str(),"18"))
  300. berlist = &r18m;
  301. else if (!strcmp(substr.c_str(),"24"))
  302. berlist = &r24m;
  303. else if (!strcmp(substr.c_str(),"36"))
  304. berlist = &r36m;
  305. else if (!strcmp(substr.c_str(),"48"))
  306. berlist = &r48m;
  307. else if (!strcmp(substr.c_str(),"54"))
  308. berlist = &r54m;
  309. else
  310. continue;
  311. std::string parameters = subline.substr (pos2+3,std::string::npos);
  312. std::stringstream linestream(parameters);
  313. int pkSize;
  314. double snr;
  315. double ber;
  316. linestream >> pkSize;
  317. linestream >> snr;
  318. linestream >> ber;
  319. snr = dB2fraction(snr);
  320. if (pkSize<128)
  321. pkSize=128;
  322. else if (128<=pkSize && pkSize<256)
  323. pkSize=128;
  324. else if (256<=pkSize&& pkSize<512)
  325. pkSize=256;
  326. else if (512<=pkSize&& pkSize<1024)
  327. pkSize=512;
  328. else if (1024<=pkSize && pkSize<1500)
  329. pkSize=1024;
  330. else
  331. pkSize=1500;
  332. if (berlist->size()==0)
  333. {
  334. LongBer * l = new LongBer;
  335. l->longpkt = pkSize;
  336. berlist->push_back(l);
  337. }
  338. LongBer * l;
  339. bool inList = false;
  340. for (unsigned int j=0;j<berlist->size();j++)
  341. {
  342. l = *(berlist->begin()+j);
  343. if (l->longpkt==pkSize)
  344. {
  345. inList=true;
  346. break;
  347. }
  348. }
  349. if (!inList)
  350. {
  351. l = new LongBer;
  352. l->longpkt = pkSize;
  353. berlist->push_back(l);
  354. }
  355. if (l->snrlist.size()==0)
  356. {
  357. SnrBer snrdata;
  358. snrdata.snr=snr;
  359. snrdata.ber=ber;
  360. l->snrlist.push_back(snrdata);
  361. }
  362. else
  363. for (unsigned int j=0;j<l->snrlist.size();j++)
  364. {
  365. SnrBer snrdata = l->snrlist[j];
  366. if (snr<snrdata.snr)
  367. {
  368. SnrBer snrdata2;
  369. snrdata2.snr=snr;
  370. snrdata2.ber=ber;
  371. l->snrlist.insert(l->snrlist.begin()+i,snrdata2);
  372. break;
  373. }
  374. else if (j+1==l->snrlist.size())
  375. {
  376. SnrBer snrdata2;
  377. snrdata2.snr=snr;
  378. snrdata2.ber=ber;
  379. l->snrlist.push_back(snrdata2);
  380. break;
  381. }
  382. }
  383. }
  384. in.close();
  385. // exist data?
  386. }
  387. Ieee80211gRadioModel::~Ieee80211gRadioModel()
  388. {
  389. // B
  390. while (r1m.size()>0)
  391. {
  392. LongBer *p = r6m.back();
  393. r6m.pop_back();
  394. p->snrlist.clear();
  395. delete p;
  396. }
  397. while (r2m.size()>0)
  398. {
  399. LongBer *p = r6m.back();
  400. r6m.pop_back();
  401. p->snrlist.clear();
  402. delete p;
  403. }
  404. while (r5m.size()>0)
  405. {
  406. LongBer *p = r6m.back();
  407. r6m.pop_back();
  408. p->snrlist.clear();
  409. delete p;
  410. }
  411. while (r11m.size()>0)
  412. {
  413. LongBer *p = r6m.back();
  414. r6m.pop_back();
  415. p->snrlist.clear();
  416. delete p;
  417. }
  418. // A and G
  419. while (r6m.size()>0)
  420. {
  421. LongBer *p = r6m.back();
  422. r6m.pop_back();
  423. p->snrlist.clear();
  424. delete p;
  425. }
  426. while (r9m.size()>0)
  427. {
  428. LongBer *p = r9m.back();
  429. r9m.pop_back();
  430. p->snrlist.clear();
  431. delete p;
  432. }
  433. while (r12m.size()>0)
  434. {
  435. LongBer *p = r12m.back();
  436. r12m.pop_back();
  437. p->snrlist.clear();
  438. delete p;
  439. }
  440. while (r18m.size()>0)
  441. {
  442. LongBer *p = r18m.back();
  443. r18m.pop_back();
  444. p->snrlist.clear();
  445. delete p;
  446. }
  447. while (r24m.size()>0)
  448. {
  449. LongBer *p = r24m.back();
  450. r24m.pop_back();
  451. p->snrlist.clear();
  452. delete p;
  453. }
  454. while (r36m.size()>0)
  455. {
  456. LongBer *p = r36m.back();
  457. r36m.pop_back();
  458. p->snrlist.clear();
  459. delete p;
  460. }
  461. while (r48m.size()>0)
  462. {
  463. LongBer *p = r48m.back();
  464. r48m.pop_back();
  465. p->snrlist.clear();
  466. delete p;
  467. }
  468. while (r54m.size()>0)
  469. {
  470. LongBer *p = r54m.back();
  471. r54m.pop_back();
  472. p->snrlist.clear();
  473. delete p;
  474. }
  475. }
  476. void Ieee80211gRadioModel::initializeFrom(cModule *radioModule)
  477. {
  478. snirThreshold = dB2fraction(radioModule->par("snirThreshold"));
  479. phyOpMode=radioModule->par("phyOpMode");
  480. channelModel=radioModule->par("channelModel");
  481. if (phyOpMode==1)
  482. phyOpMode='b';
  483. else if (phyOpMode==2)
  484. phyOpMode='g';
  485. else
  486. phyOpMode='b';
  487. snirVector.setName("snirVector");
  488. i=0;
  489. const char *fname = radioModule->par("berTableFile");
  490. std::string name (fname);
  491. if (!name.empty())
  492. {
  493. parseFile(fname);
  494. fileBer=true;
  495. }
  496. else
  497. fileBer=false;
  498. }
  499. double Ieee80211gRadioModel::calculateDuration(AirFrame *airframe)
  500. {
  501. double duration;
  502. if(phyOpMode=='g')
  503. duration=4*ceil((16+airframe->getBitLength()+6)/(airframe->getBitrate()/1e6*4))*1e-6 + 26e-6;
  504. else
  505. // The physical layer header is sent with 1Mbit/s and the rest with the frame's bitrate
  506. duration=airframe->getBitLength()/airframe->getBitrate() + 192/BITRATE_HEADER;
  507. EV<<"Radio:frameDuration="<<duration*1e6<<"us("<<airframe->getBitLength()<<"bits)"<<endl;
  508. return duration;
  509. }
  510. bool Ieee80211gRadioModel::isReceivedCorrectly(AirFrame *airframe, const SnrList& receivedList)
  511. {
  512. // calculate snirMin
  513. double snirMin = receivedList.begin()->snr;
  514. for (SnrList::const_iterator iter = receivedList.begin(); iter != receivedList.end(); iter++)
  515. if (iter->snr < snirMin)
  516. snirMin = iter->snr;
  517. cPacket *frame = airframe->getEncapsulatedMsg();
  518. EV << "packet (" << frame->getClassName() << ")" << frame->getName() << " (" << frame->info() << ") snrMin=" << snirMin << endl;
  519. if(i%1000==0){
  520. snirVector.record(10*log10(snirMin));
  521. i=0;
  522. }
  523. i++;
  524. if (snirMin <= snirThreshold)
  525. {
  526. // if snir is too low for the packet to be recognized
  527. EV << "COLLISION! Packet got lost. Noise only\n";
  528. return false;
  529. }
  530. else if (isPacketOK(snirMin, airframe->getEncapsulatedMsg()->getBitLength(), airframe->getBitrate()))
  531. {
  532. EV << "packet was received correctly, it is now handed to upper layer...\n";
  533. return true;
  534. }
  535. else
  536. {
  537. EV << "Packet has BIT ERRORS! It is lost!\n";
  538. return false;
  539. }
  540. }
  541. bool Ieee80211gRadioModel::isPacketOK(double snirMin, int lengthMPDU, double bitrate)
  542. {
  543. double berHeader, berMPDU;
  544. berHeader = 0.5 * exp(-snirMin * BANDWIDTH / BITRATE_HEADER);
  545. // if PSK modulation
  546. if (bitrate == 1E+6 || bitrate == 2E+6)
  547. berMPDU = 0.5 * exp(-snirMin * BANDWIDTH / bitrate);
  548. // if CCK modulation (modeled with 16-QAM)
  549. else if (bitrate == 5.5E+6)
  550. berMPDU = 0.5 * (1 - 1 / sqrt(pow(2.0, 4))) * erfc(snirMin * BANDWIDTH / bitrate);
  551. else if(bitrate == 11E+6) // CCK, modelled with 256-QAM
  552. berMPDU = 0.25 * (1 - 1 / sqrt(pow(2.0, 8))) * erfc(snirMin * BANDWIDTH / bitrate);
  553. else{//802.11g rates
  554. //PLCP Header 24bits, BPSK, r=1/2, 6Mbps
  555. berHeader=ber_bpsk(snirMin, BANDWIDTH , 6E+6, channelModel);
  556. berHeader=Pb(1, berHeader);
  557. if (fileBer)
  558. berMPDU = 0;
  559. else
  560. switch((int)bitrate){
  561. case (int)(6E+6)://6Mbps, r=1/2, BPSK
  562. berMPDU=ber_bpsk(snirMin, BANDWIDTH , bitrate, channelModel);
  563. berMPDU=Pb(1, berMPDU);
  564. break;
  565. case (int)(9E+6)://9Mbps, r=3/4, BPSK
  566. berMPDU=ber_bpsk(snirMin, BANDWIDTH , bitrate, channelModel);
  567. berMPDU=Pb(3, berMPDU);
  568. break;
  569. case (int)(12E+6)://12Mbps, r=1/2, QPSK
  570. berMPDU=ber_qpsk(snirMin, BANDWIDTH , bitrate, channelModel);
  571. berMPDU=Pb(1, berMPDU);
  572. break;
  573. case (int)(18E+6)://18Mbps, r=3/4, QPSK
  574. berMPDU=ber_qpsk(snirMin, BANDWIDTH , bitrate, channelModel);
  575. berMPDU=Pb(3, berMPDU);
  576. break;
  577. case (int)(24E+6)://24Mbps, r=1/2, 16QAM
  578. berMPDU=ber_16qam(snirMin, BANDWIDTH , bitrate, channelModel);
  579. berMPDU=Pb(1, berMPDU);
  580. break;
  581. case (int)(36E+6)://36Mbps, r=3/4, 16QAM
  582. berMPDU=ber_16qam(snirMin, BANDWIDTH , bitrate, channelModel);
  583. berMPDU=Pb(3, berMPDU);
  584. break;
  585. case (int)(48E+6)://48Mbps, r=2/3, 64QAM
  586. berMPDU=ber_64qam(snirMin, BANDWIDTH , bitrate, channelModel);
  587. berMPDU=Pb(2, berMPDU);
  588. break;
  589. case (int)(54E+6)://54Mbps, r=3/4, 64QAM
  590. berMPDU=ber_64qam(snirMin, BANDWIDTH , bitrate, channelModel);
  591. berMPDU=Pb(3, berMPDU);
  592. break;
  593. default:
  594. berMPDU=0;
  595. }
  596. }
  597. if(berHeader > 1.0 || berMPDU > 1.0)
  598. return false;// error in MPDU
  599. // probability of no bit error in the PLCP header
  600. double headerNoError;
  601. if(phyOpMode=='g')
  602. headerNoError = pow(1.0 - berHeader, 24);//PLCP Header 24bit(without SERVICE), 6Mbps
  603. else
  604. headerNoError = pow(1.0 - berHeader, HEADER_WITHOUT_PREAMBLE);
  605. // probability of no bit error in the MPDU
  606. double MpduNoError;
  607. if (fileBer)
  608. MpduNoError=1-getPer(bitrate,snirMin,lengthMPDU);
  609. else
  610. MpduNoError = pow(1.0 - berMPDU, lengthMPDU);
  611. EV << "berHeader: " << berHeader << " berMPDU: " <<berMPDU <<" lengthMPDU: "<<lengthMPDU<<" PER: "<<1-MpduNoError<<endl;
  612. double rand = dblrand();
  613. if (rand > headerNoError)
  614. return false; // error in header
  615. else if (dblrand() > MpduNoError)
  616. return false; // error in MPDU
  617. else
  618. return true; // no error
  619. }
  620. double Ieee80211gRadioModel::dB2fraction(double dB)
  621. {
  622. return pow(10.0, (dB / 10));
  623. }