PageRenderTime 50ms CodeModel.GetById 19ms RepoModel.GetById 0ms app.codeStats 1ms

/src/linklayer/radio/Ieee80211aRadioModel.cc

https://github.com/Sorouri/inetmanet
C++ | 455 lines | 293 code | 85 blank | 77 comment | 85 complexity | 2040f5604c654cb035c60ee47201f2bf 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. #define IEEE80211A
  20. #include "Ieee80211aRadioModel.h"
  21. #include "Ieee80211aConsts.h"
  22. #include "FWMath.h"
  23. #include "Modulation.h"
  24. /* added by Sorin Cocorada sorin.cocorada@gmail.com*/
  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. int comb(int n,int k){
  44. int 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. {
  59. long double sum=0.0;
  60. int k;
  61. if(d%2 == 1){
  62. for(k=(d+1)/2; k<=d; k++)
  63. sum+=comb(d,k)*pow(Pb,k)*pow(1.0-Pb, d-k);
  64. }
  65. else{
  66. sum=0.5*comb(d,d/2)*pow(Pb, d/2)*pow(1.0-Pb,d/2);
  67. for(k=d/2+1; k<=d; k++)
  68. sum+=comb(d,k)*pow(Pb,k)*pow(1.0-Pb, d-k);
  69. }
  70. //printf("prob=%f d=%d sum=%f \n",Pb,d, sum);
  71. return sum;
  72. //return pow(4*Pb*(1-Pb), d/2);
  73. }
  74. static double Pb(int rate, double prob)
  75. {
  76. long double probc;
  77. switch(rate){
  78. case 1:
  79. //11, 0, 38, 0, 193, 0, 1331, 0, 7275, 0, 40406, 0, 234969, 0, 1337714, 0, 7594819, 0, 433775588, 0,
  80. probc=11*Pd(10,prob) + 38*Pd(12,prob) + 193*Pd(14,prob);//+1331*Pd(16,prob);
  81. break;
  82. case 2:
  83. //1, 16, 48, 158, 642, 2435, 9174, 34701, 131533, 499312,
  84. probc=Pd(6,prob)+16*Pd(7,prob)+48*Pd(8,prob);//+158*Pd(9,prob)+642*Pd(10,prob)
  85. //+2435*Pd(11,prob)+ 9174*Pd(12,prob)+34701*Pd(13,prob)+131533*Pd(14,prob)+499312*Pd(15,prob);
  86. break;
  87. case 3:
  88. //(8, 31, 160, 892, 4512, 23297, 120976, 624304, 3229885, 16721329,
  89. probc=8*Pd(5,prob)+31*Pd(6,prob)+150*Pd(7,prob);//+892*Pd(8,prob)+4512*Pd(9,prob)
  90. //+23297*Pd(10,prob)+120976*Pd(11,prob)+624304*Pd(12,prob)+ 3229885*Pd(13,prob)+ 16721329*Pd(14,prob);
  91. break;
  92. default:
  93. ;
  94. }
  95. return probc;
  96. }
  97. static double ber_bpsk(double snir, double bandwidth, double bitrate, char channelModel)
  98. {
  99. double y=snir*bandwidth/bitrate;
  100. if(channelModel=='r')//Rayleigh
  101. return 0.5*(1.0-sqrt(y/(1.0+y)));
  102. return 0.5*erfc(sqrt(y));//awgn
  103. }
  104. static double ber_qpsk(double snir, double bandwidth, double bitrate, char channelModel)
  105. {
  106. double y=snir*bandwidth/bitrate;
  107. if(channelModel=='r')//Rayleigh
  108. return 0.5*(1.0-sqrt(y/(1.0+y)));
  109. return 0.5*erfc(sqrt(y));//awgn
  110. }
  111. static double ber_16qam(double snir, double bandwidth, double bitrate, char channelModel)
  112. {
  113. double y=snir*bandwidth/bitrate;
  114. if(channelModel=='r')//Rayleigh
  115. 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)) );
  116. return ( 0.375*erfc(sqrt(0.4*y))+0.25*erfc(3.0*sqrt(0.4*y)) );//awgn
  117. }
  118. static double ber_64qam(double snir, double bandwidth, double bitrate, char channelModel)
  119. {
  120. double y=snir*bandwidth/bitrate;
  121. if(channelModel=='r')//Rayleigh
  122. 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)) );
  123. return 7.0/24.0*erfc(sqrt(y/7.0))+0.25*erfc(3.0*sqrt(y/7.0));//awgn
  124. }
  125. /* end added by Sorin Cocorada sorin.cocorada@gmail.com*/
  126. Register_Class(Ieee80211aRadioModel);
  127. Ieee80211aRadioModel::~Ieee80211aRadioModel()
  128. {
  129. if(phyOpMode=='a')
  130. {
  131. for (ModesCI j = modes.begin (); j != modes.end (); j++) {
  132. delete (*j);
  133. }
  134. modes.erase (modes.begin (), modes.end ());
  135. if (IS_ERROR_MASK_GENERATED)
  136. fclose(error_masks);
  137. }
  138. }
  139. void Ieee80211aRadioModel::initializeFrom(cModule *radioModule)
  140. {
  141. snirThreshold = dB2fraction(radioModule->par("snirThreshold"));
  142. //snirThreshold = dB2fraction(4);
  143. phyOpMode = radioModule->hasPar("phyOpMode") ? radioModule->par("phyOpMode") : 'b';
  144. if (phyOpMode==1)
  145. phyOpMode='b';
  146. else if (phyOpMode==2)
  147. phyOpMode='g';
  148. else if (phyOpMode==3)
  149. phyOpMode='a';
  150. else
  151. phyOpMode='b';
  152. channelModel = radioModule->hasPar("channelModel") ? radioModule->par("channelModel") : 'r';
  153. if (channelModel==1)
  154. channelModel='r';
  155. else if (channelModel==2)
  156. channelModel='a';
  157. else
  158. channelModel='r';
  159. snirVector.setName("snirVector");
  160. perVector.setName("PER");
  161. i=0;
  162. if(phyOpMode=='a')
  163. {
  164. configure80211a();
  165. error_masks = 0;
  166. if (IS_ERROR_MASK_GENERATED)
  167. {
  168. char str[80];
  169. sprintf(str,"%s%i%s","error_masks",(int)radioModule->par("ID"),".dat");
  170. error_masks= fopen(str, "w+");
  171. EV<<"Generation mask file : "<<str<<endl;
  172. }
  173. }
  174. }
  175. double Ieee80211aRadioModel::calculateDuration(AirFrame *airframe)
  176. {
  177. double duration = 0;
  178. if(phyOpMode=='a')
  179. duration= (16+airframe->getBitLength()*8+6)/airframe->getBitrate()+PLCP_PREAMBLE_DELAY+PLCP_SIGNAL_DELAY+T_SYM/2;
  180. else if(phyOpMode=='g')
  181. duration=4*ceil((16+airframe->getBitLength()+6)/(airframe->getBitrate()/1e6*4))*1e-6 + 26e-6;
  182. else
  183. // The physical layer header is sent with 1Mbit/s and the rest with the frame's bitrate
  184. duration=airframe->getBitLength()/airframe->getBitrate() + 192/BITRATE_HEADER;
  185. EV<<"Radio:frameDuration="<<duration*1e6<<"us("<<airframe->getBitLength()<<"bits)"<<endl;
  186. return duration;
  187. }
  188. bool Ieee80211aRadioModel::isReceivedCorrectly(AirFrame *airframe, const SnrList& receivedList)
  189. {
  190. // unsigned char packet_ok;
  191. // unsigned long length;
  192. unsigned char *buffer=NULL;
  193. // buffer=(unsigned char*)malloc(airframe->getBitLength()*sizeof(unsigned char));
  194. if (buffer)
  195. for(int j=0;j<airframe->getBitLength();j++)
  196. // buffer[i] = airframe->getBuffer(i);
  197. buffer[j] = 0;///Error, there is no getBuffer() to airframe ;
  198. // length = airframe->getBitLength()+PHY_HEADER_LENGTH_A+2;
  199. // length = length/8;
  200. // printf("\n length = %d length sans phy=%d",length,airframe->getBitLength());
  201. // calculate snirMin
  202. double snirMin = receivedList.begin()->snr;
  203. for (SnrList::const_iterator iter = receivedList.begin(); iter != receivedList.end(); iter++)
  204. if (iter->snr < snirMin)
  205. snirMin = iter->snr;
  206. cPacket *frame = airframe->getEncapsulatedMsg();
  207. EV << "packet (" << frame->getClassName() << ")" << frame->getName() << " (" << frame->info() << ") snrMin=" << snirMin << endl;
  208. if(i%1000==0){
  209. snirVector.record(10*log10(snirMin));
  210. i=0;
  211. }
  212. i++;
  213. if (snirMin <= snirThreshold)
  214. {
  215. // if snir is too low for the packet to be recognized
  216. EV << "COLLISION! Packet got lost. Noise only\n";
  217. return false;
  218. }
  219. else if (isPacketOK(buffer,snirMin, airframe->getBitLength(), airframe->getBitrate()))
  220. {
  221. EV << "packet was received correctly, it is now handed to upper layer...\n";
  222. // for(int i=0;i<airframe->getBitLength();i++)
  223. // airframe->setBuffer(i,buffer[i]);
  224. return true;
  225. }
  226. else
  227. {
  228. EV << "Packet has BIT ERRORS! It is lost!\n";
  229. return false;
  230. }
  231. if (buffer)
  232. free(buffer);
  233. }
  234. //static unsigned char phy_header[PHY_HEADER_LENGTH_A];
  235. bool Ieee80211aRadioModel::isPacketOK(unsigned char *buffer, double snirMin, int length, double bitrate)
  236. {
  237. double berHeader, berMPDU;
  238. if(phyOpMode=='b')
  239. {
  240. berHeader = 0.5 * exp(-snirMin * BANDWIDTH / BITRATE_HEADER);
  241. // if PSK modulation
  242. if (bitrate == 1E+6 || bitrate == 2E+6)
  243. berMPDU = 0.5 * exp(-snirMin * BANDWIDTH / bitrate);
  244. // if CCK modulation (modeled with 16-QAM)
  245. else if (bitrate == 5.5E+6)
  246. berMPDU = 0.5 * (1 - 1 / sqrt(pow(2.0, 4))) * erfc(snirMin * BANDWIDTH / bitrate);
  247. else if(bitrate == 11E+6) // CCK, modelled with 256-QAM
  248. berMPDU = 0.25 * (1 - 1 / sqrt(pow(2.0, 8))) * erfc(snirMin * BANDWIDTH / bitrate);
  249. }
  250. #if 0
  251. else if(phyOpMode=='a')
  252. {
  253. double per, psr = 1;
  254. unsigned char packet_ok=1;
  255. if (IS_ERROR_MASK_GENERATED) fprintf(error_masks,"]\n");
  256. psr = 1;
  257. EV<<"PHY_HEADER_LENGTH"<<PHY_HEADER_LENGTH_A<<endl;
  258. //psr *= getMode(bitrate)->getChunkSuccessRate (snirMin, PHY_HEADER_LENGTH_A, error_masks, HEADER_BITRATE);
  259. //psr *= getMode(bitrate)->getChunkSuccessRate (snirMin, length, error_masks, bitrate);
  260. psr *= getMode(bitrate)->getChunkSuccessRate (snirMin, length, buffer, bitrate);
  261. per = 1- psr;
  262. if(i%100==0) perVector.record(per);
  263. for(int i=0;i<PHY_HEADER_LENGTH_A;i++)
  264. if(phy_header[i]!=0)
  265. return(false);
  266. /*double rand = dblrand();
  267. if (rand > per)
  268. return (true);
  269. //if no error
  270. else
  271. return (false);
  272. */
  273. return (true);
  274. }
  275. else if (phyOpMode=='g')
  276. #endif
  277. else if ((phyOpMode=='g') || (phyOpMode=='a'))
  278. {
  279. //802.11g rates
  280. //PLCP Header 24bits, BPSK, r=1/2, 6Mbps
  281. berHeader=ber_bpsk(snirMin, BANDWIDTH , 6E+6, channelModel);
  282. berHeader=Pb(1, berHeader);
  283. switch((int)bitrate){//added by Sorin Cocorada
  284. case (int)(6E+6)://6Mbps, r=1/2, BPSK
  285. berMPDU=ber_bpsk(snirMin, BANDWIDTH , bitrate, channelModel);
  286. berMPDU=Pb(1, berMPDU);
  287. break;
  288. case (int)(9E+6)://9Mbps, r=3/4, BPSK
  289. berMPDU=ber_bpsk(snirMin, BANDWIDTH , bitrate, channelModel);
  290. berMPDU=Pb(3, berMPDU);
  291. break;
  292. case (int)(12E+6)://12Mbps, r=1/2, QPSK
  293. berMPDU=ber_qpsk(snirMin, BANDWIDTH , bitrate, channelModel);
  294. berMPDU=Pb(1, berMPDU);
  295. break;
  296. case (int)(18E+6)://18Mbps, r=3/4, QPSK
  297. berMPDU=ber_qpsk(snirMin, BANDWIDTH , bitrate, channelModel);
  298. berMPDU=Pb(3, berMPDU);
  299. break;
  300. case (int)(24E+6)://24Mbps, r=1/2, 16QAM
  301. berMPDU=ber_16qam(snirMin, BANDWIDTH , bitrate, channelModel);
  302. berMPDU=Pb(1, berMPDU);
  303. break;
  304. case (int)(36E+6)://36Mbps, r=3/4, 16QAM
  305. berMPDU=ber_16qam(snirMin, BANDWIDTH , bitrate, channelModel);
  306. berMPDU=Pb(3, berMPDU);
  307. break;
  308. case (int)(48E+6)://48Mbps, r=2/3, 64QAM
  309. berMPDU=ber_64qam(snirMin, BANDWIDTH , bitrate, channelModel);
  310. berMPDU=Pb(2, berMPDU);
  311. break;
  312. case (int)(54E+6)://54Mbps, r=3/4, 64QAM
  313. berMPDU=ber_64qam(snirMin, BANDWIDTH , bitrate, channelModel);
  314. berMPDU=Pb(3, berMPDU);
  315. break;
  316. default:
  317. berMPDU=0;
  318. }
  319. }
  320. // probability of no bit error in the PLCP header
  321. double headerNoError;
  322. // if(phyOpMode=='g')//added by Sorin Cocorada
  323. if ((phyOpMode=='g') || (phyOpMode=='a'))//added by Sorin Cocorada
  324. headerNoError = pow(1.0 - berHeader, 24);//PLCP Header 24bit(without SERVICE), 6Mbps
  325. else
  326. headerNoError = pow(1.0 - berHeader, HEADER_WITHOUT_PREAMBLE);
  327. // probability of no bit error in the MPDU
  328. double MpduNoError = pow(1.0 - berMPDU, length);
  329. EV << "berHeader: " << berHeader << " berMPDU: " <<berMPDU <<" length: "<<length<<" PER: "<<1-MpduNoError<<endl;
  330. double rand = dblrand();
  331. if (rand > headerNoError)
  332. return false; // error in header
  333. else if (dblrand() > MpduNoError)
  334. return false; // error in MPDU
  335. else
  336. return true; // no error
  337. }
  338. double Ieee80211aRadioModel::dB2fraction(double dB)
  339. {
  340. return pow(10.0, (dB / 10));
  341. }
  342. void Ieee80211aRadioModel::addTransmissionMode (TransmissionMode *mode)
  343. {
  344. modes.push_back (mode);
  345. }
  346. TransmissionMode * Ieee80211aRadioModel::getMode (double rate) const
  347. {
  348. //EV<<" getMode "<< rate<<endl;
  349. int mode;
  350. if (rate == 6E+6) mode = 0;
  351. else if (rate == 9E+6) mode = 1;
  352. else if (rate == 12E+6) mode = 2;
  353. else if (rate == 18E+6) mode = 3;
  354. else if (rate == 24E+6) mode = 4;
  355. else if (rate == 36E+6) mode = 5;
  356. else if (rate == 48E+6) mode = 6;
  357. else if (rate == 54E+6) mode = 7;
  358. return modes[mode];
  359. }
  360. void Ieee80211aRadioModel::configure80211a (void)
  361. {
  362. // addTransmissionMode (new FecBpskMode (20e6, 6000000, 0.5 ));
  363. // addTransmissionMode (new FecBpskMode (20e6, 9000000, 0.75));
  364. // addTransmissionMode (new FecQamMode (20e6, 12000000, 0.5, 4));
  365. // addTransmissionMode (new FecQamMode (20e6, 18000000, 0.75, 4));
  366. // addTransmissionMode (new FecQamMode (20e6, 24000000, 0.5, 16));
  367. // addTransmissionMode (new FecQamMode (20e6, 36000000, 0.75, 16));
  368. // addTransmissionMode (new FecQamMode (20e6, 48000000, 0.666, 64));
  369. // addTransmissionMode (new FecQamMode (20e6, 54000000, 0.75, 64));
  370. }