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

通讯编程

开发平台:

Visual C++

  1. /********************************************/
  2. /*     NS2 Simulator for IEEE 802.15.4      */
  3. /*           (per P802.15.4/D18)            */
  4. /*------------------------------------------*/
  5. /* by:        Jianliang Zheng               */
  6. /*        (zheng@ee.ccny.cuny.edu)          */
  7. /*              Myung J. Lee                */
  8. /*          (lee@ccny.cuny.edu)             */
  9. /*        ~~~~~~~~~~~~~~~~~~~~~~~~~         */
  10. /*           SAIT-CUNY Joint Lab            */
  11. /********************************************/
  12. // File:  p802_15_4phy.cc
  13. // Mode:  C++; c-basic-offset:8; tab-width:8; indent-tabs-mode:t
  14. // $Header: /cvsroot/nsnam/ns-2/wpan/p802_15_4phy.cc,v 1.5 2007/01/30 15:54:40 tom_henderson Exp $
  15. /*
  16.  * Copyright (c) 2003-2004 Samsung Advanced Institute of Technology and
  17.  * The City University of New York. All rights reserved.
  18.  *
  19.  * Redistribution and use in source and binary forms, with or without
  20.  * modification, are permitted provided that the following conditions
  21.  * are met:
  22.  * 1. Redistributions of source code must retain the above copyright
  23.  *    notice, this list of conditions and the following disclaimer.
  24.  * 2. Redistributions in binary form must reproduce the above copyright
  25.  *    notice, this list of conditions and the following disclaimer in the
  26.  *    documentation and/or other materials provided with the distribution.
  27.  * 3. All advertising materials mentioning features or use of this software
  28.  *    must display the following acknowledgement:
  29.  * This product includes software developed by the Joint Lab of Samsung 
  30.  *      Advanced Institute of Technology and The City University of New York.
  31.  * 4. Neither the name of Samsung Advanced Institute of Technology nor of 
  32.  *    The City University of New York may be used to endorse or promote 
  33.  *    products derived from this software without specific prior written 
  34.  *    permission.
  35.  *
  36.  * THIS SOFTWARE IS PROVIDED BY THE JOINT LAB OF SAMSUNG ADVANCED INSTITUTE
  37.  * OF TECHNOLOGY AND THE CITY UNIVERSITY OF NEW YORK ``AS IS'' AND ANY EXPRESS 
  38.  * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 
  39.  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN 
  40.  * NO EVENT SHALL SAMSUNG ADVANCED INSTITUTE OR THE CITY UNIVERSITY OF NEW YORK 
  41.  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 
  42.  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE 
  43.  * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 
  44.  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 
  45.  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT 
  46.  * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  47.  */
  48. #include "p802_15_4pkt.h"
  49. #include "p802_15_4phy.h"
  50. #include "p802_15_4mac.h"
  51. #include "p802_15_4sscs.h"
  52. #include "p802_15_4const.h"
  53. #include "p802_15_4timer.h"
  54. #include "p802_15_4trace.h"
  55. #include "p802_15_4fail.h"
  56. #include "p802_15_4nam.h"
  57. #ifndef MAX
  58. #define MAX(x,y)        (((x)>(y))?(x):(y))
  59. #endif
  60. #ifndef MIN
  61. #define MIN(x,y)        (((x)<(y))?(x):(y))
  62. #endif
  63. PHY_PIB Phy802_15_4::PPIB =
  64. {
  65. def_phyCurrentChannel,
  66. def_phyChannelsSupported,
  67. def_phyTransmitPower,
  68. def_phyCCAMode
  69. };
  70. void Phy802_15_4Timer::start(double wtime)
  71. {
  72. active = true;
  73. nullEvent.uid_ = 0;
  74. Scheduler::instance().schedule(this,&nullEvent,wtime);
  75. }
  76. void Phy802_15_4Timer::cancel(void)
  77. {
  78. active = false;
  79. Scheduler::instance().cancel(&nullEvent);
  80. }
  81. void Phy802_15_4Timer::handle(Event* e)
  82. {
  83. active = false;
  84. if (type == phyCCAHType)
  85. phy->CCAHandler();
  86. else if(type == phyEDHType)
  87. phy->EDHandler();
  88. else if(type == phyTRXHType)
  89. phy->TRXHandler();
  90. else if(type == phyRecvOverHType)
  91. phy->recvOverHandler((Packet *)e);
  92. else if(type == phySendOverHType)
  93. phy->sendOverHandler();
  94. else if(type == phyCCAReportHType) // 2.31 change: new timer added for CCA reporting
  95. phy->CCAReportHandler();
  96. else
  97. assert(0);
  98. }
  99. static class Phy802_15_4Class : public TclClass {
  100. public:
  101. Phy802_15_4Class() : TclClass("Phy/WirelessPhy/802_15_4") {}
  102. TclObject* create(int, const char*const*) {
  103. return (new Phy802_15_4(&(Phy802_15_4::PPIB)));
  104. }
  105. } class_Phy802_15_4;
  106. Phy802_15_4::Phy802_15_4(PHY_PIB *pp)
  107. : WirelessPhy(),
  108.   CCAH(this, phyCCAHType),
  109.   EDH(this, phyEDHType),
  110.   TRXH(this, phyTRXHType),
  111.   recvOverH(this, phyRecvOverHType),
  112.   sendOverH(this, phySendOverHType),
  113.   CCAReportH(this, phyCCAReportHType) // 2.31 change: new timer added for CCA reporting
  114. {
  115. int i;
  116. ppib = *pp;
  117. trx_state = p_RX_ON;
  118. trx_state_defer_set = p_IDLE;
  119. tx_state = p_IDLE;
  120. rxPkt = 0;
  121. for (i=0;i<27;i++)
  122. {
  123. rxTotPower[i] = 0.0;
  124. rxTotNum[i] = 0;
  125. rxThisTotNum[i] = 0;
  126. }
  127. mac = 0;
  128. T_transition_local_ = T_transition_; // 2.31 change: set local variable since WirelessPhy::T_transition_ is not visible to CsmaCA802_15_4
  129. }
  130. void Phy802_15_4::macObj(Mac802_15_4 *m)
  131. {
  132. mac = m;
  133. }
  134. bool Phy802_15_4::channelSupported(UINT_8 channel)
  135. {
  136. return ((ppib.phyChannelsSupported & (1 << channel)) != 0);
  137. }
  138. double Phy802_15_4::getRate(char dataOrSymbol)
  139. {
  140. double rate;
  141. if (ppib.phyCurrentChannel == 0)
  142. {
  143. if (dataOrSymbol == 'd')
  144. rate = BR_868M;
  145. else
  146. rate = SR_868M;
  147. }
  148. else if (ppib.phyCurrentChannel <= 10)
  149. {
  150. if (dataOrSymbol == 'd')
  151. rate = BR_915M;
  152. else
  153. rate = SR_915M;
  154. }
  155. else
  156. {
  157. if (dataOrSymbol == 'd')
  158. rate = BR_2_4G;
  159. else
  160. rate = SR_2_4G;
  161. }
  162. return (rate*1000);
  163. }
  164. double Phy802_15_4::trxTime(Packet *p,bool phyPkt)
  165. {
  166. int phyHeaderLen;
  167. double trx;
  168. hdr_cmn* ch = HDR_CMN(p);
  169. phyHeaderLen = (phyPkt)?0:defPHY_HEADER_LEN;
  170. trx = ((ch->size() + phyHeaderLen)*8/getRate('d'));
  171. return trx;
  172. }
  173. void Phy802_15_4::construct_PPDU(UINT_8 psduLength,Packet *psdu)
  174. {
  175. //not really a new packet in simulation, but just update some packet header fields.
  176. hdr_lrwpan* wph = HDR_LRWPAN(psdu);
  177. hdr_cmn* ch = HDR_CMN(psdu);
  178. wph->SHR_PreSeq = defSHR_PreSeq;
  179. wph->SHR_SFD = defSHR_SFD;
  180. wph->PHR_FrmLen = psduLength;
  181. //also set channel (for filtering in simulation)
  182. wph->phyCurrentChannel = ppib.phyCurrentChannel;
  183. ch->size() = psduLength + defPHY_HEADER_LEN;
  184. ch->txtime() = trxTime(psdu,true);
  185. }
  186. void Phy802_15_4::PD_DATA_request(UINT_8 psduLength,Packet *psdu)
  187. {
  188. hdr_cmn* ch = HDR_CMN(psdu);
  189. //check packet length
  190. if (psduLength > aMaxPHYPacketSize)
  191. {
  192. fprintf(stdout,"[%s::%s][%f](node %d) Invalid PSDU/MPDU length: type = %s, src = %d, dst = %d, uid = %d, mac_uid = %u, size = %dn",__FILE__,__FUNCTION__,CURRENT_TIME,index_,wpan_pName(psdu),p802_15_4macSA(psdu),p802_15_4macDA(psdu),ch->uid(),HDR_LRWPAN(psdu)->uid,ch->size());
  193. Packet::free(psdu);
  194. mac->PD_DATA_confirm(p_UNDEFINED);
  195. return;
  196. }
  197. if (trx_state == p_TX_ON)
  198. {
  199. if (tx_state == p_IDLE)
  200. {
  201. #ifdef DEBUG802_15_4
  202. fprintf(stdout,"[%s::%s][%f](node %d) sending pkt: type = %s, src = %d, dst = %d, uid = %d, mac_uid = %ld, size = %dn",__FILE__,__FUNCTION__,CURRENT_TIME,index_,wpan_pName(psdu),p802_15_4macSA(psdu),p802_15_4macDA(psdu),ch->uid(),HDR_LRWPAN(psdu)->uid,ch->size());
  203. #endif
  204. //construct a PPDU packet (not really a new packet in simulation, but still <psdu>)
  205. construct_PPDU(psduLength,psdu);
  206. //somehow the packet size is set to 0 after sendDown() -- ok, the packet is out and anything can happen (we shouldn't care once it's out)
  207. //so we have to calculate the transmission time before sendDown()
  208. double trx_time = trxTime(psdu,true);
  209. //send the packet to Radio (channel target) for transmission
  210. txPkt = psdu;
  211. txPktCopy = psdu->copy(); //for debug purpose, we still want to access the packet after transmission is done
  212. sendDown(psdu); //WirelessPhy::sendDown()
  213. tx_state = p_BUSY; //for carrier sense
  214. sendOverH.start(trx_time);
  215. }
  216. else //impossible
  217. assert(0);
  218. }
  219. else
  220. {
  221. #ifdef DEBUG802_15_4
  222. fprintf(stdout,"[D][TRX][%s::%s][%f](node %d) dropping pkt: type = %s, src = %d, dst = %d, uid = %d, mac_uid = %ld, size = %dn",__FILE__,__FUNCTION__,CURRENT_TIME,index_,wpan_pName(psdu),p802_15_4macSA(psdu),p802_15_4macDA(psdu),ch->uid(),HDR_LRWPAN(psdu)->uid,ch->size());
  223. #endif
  224. Packet::free(psdu);
  225. mac->PD_DATA_confirm(trx_state);
  226. }
  227. }
  228. void Phy802_15_4::PD_DATA_indication(UINT_8 psduLength,Packet *psdu,UINT_8 ppduLinkQuality)
  229. {
  230. //refer to sec 6.7.8 for LQI details
  231. hdr_lrwpan* wph = HDR_LRWPAN(psdu);
  232. wph->ppduLinkQuality = ppduLinkQuality;
  233. /* 2.31 change. sendUp() function call is not necessary as recv() already does it. 
  234. Including this only causes energy to be decremented a second time.
  235. if (sendUp(psdu) == 0)
  236. Packet::free(psdu);
  237. else
  238. */
  239. uptarget_->recv(psdu, (Handler*) 0);
  240. }
  241. void Phy802_15_4::PLME_CCA_request()
  242. {
  243. if (trx_state == p_RX_ON)
  244. {
  245. //perform CCA
  246. //refer to sec 6.7.9 for CCA details
  247. //we need to delay 8 symbols
  248. CCAH.start(4/getRate('s')); // 2.32 change: start CCA at the end of 4th symbol
  249. }
  250. else
  251. mac->PLME_CCA_confirm(trx_state);
  252. }
  253. void Phy802_15_4::PLME_ED_request()
  254. {
  255. if (trx_state == p_RX_ON)
  256. {
  257. //perform ED
  258. //refer to sec 6.7.7 for ED implementation details
  259. //we need to delay 8 symbols
  260. rxEDPeakPower = rxTotPower[ppib.phyCurrentChannel];
  261. EDH.start(8/getRate('s'));
  262. }
  263. else
  264. mac->PLME_ED_confirm(trx_state,0);
  265. }
  266. void Phy802_15_4::PLME_GET_request(PPIBAenum PIBAttribute)
  267. {
  268. PHYenum t_status;
  269. switch(PIBAttribute)
  270. {
  271. case phyCurrentChannel:
  272. case phyChannelsSupported:
  273. case phyTransmitPower:
  274. case phyCCAMode:
  275. t_status = p_SUCCESS;
  276. break;
  277. default:
  278. t_status = p_UNSUPPORT_ATTRIBUTE;
  279. break;
  280. }
  281. mac->PLME_GET_confirm(t_status,PIBAttribute,&ppib);
  282. }
  283. void Phy802_15_4::PLME_SET_TRX_STATE_request(PHYenum state)
  284. {
  285. bool delay;
  286. PHYenum t_status;
  287. //ignore any pending request
  288. if (trx_state_defer_set != p_IDLE)
  289. trx_state_defer_set = p_IDLE;
  290. else if (TRXH.active)
  291. {
  292. TRXH.cancel();
  293. }
  294. t_status = trx_state;
  295. if (state != trx_state)
  296. {
  297. delay = false;
  298. if (((state == p_RX_ON)||(state == p_TRX_OFF))&&(tx_state == p_BUSY))
  299. {
  300. t_status = p_BUSY_TX;
  301. trx_state_defer_set = state;
  302. }
  303. else if (((state == p_TX_ON)||(state == p_TRX_OFF))
  304.         &&(rxPkt)&&(!HDR_CMN(rxPkt)->error())) //if after received a valid SFD
  305. {
  306. t_status = p_BUSY_RX;
  307. trx_state_defer_set = state;
  308. }
  309. else if (state == p_FORCE_TRX_OFF)
  310. {
  311. t_status = (trx_state == p_TRX_OFF)?p_TRX_OFF:p_SUCCESS;
  312. trx_state = p_TRX_OFF;
  313. //terminate reception if needed
  314. if (rxPkt)
  315. {
  316. #ifdef DEBUG802_15_4
  317. hdr_cmn *ch = HDR_CMN(rxPkt);
  318. hdr_lrwpan *wph = HDR_LRWPAN(rxPkt);
  319. fprintf(stdout,"[%s::%s][%f](node %d) FORCE_TRX_OFF sets error bit for incoming pkt: type = %s, src = %d, dst = %d, uid = %d, mac_uid = %ld, size = %dn",__FILE__,__FUNCTION__,CURRENT_TIME,index_,wpan_pName(rxPkt),p802_15_4macSA(rxPkt),p802_15_4macDA(rxPkt),ch->uid(),wph->uid,ch->size());
  320. #endif
  321. HDR_CMN(rxPkt)->error() = 1; //incomplete reception -- force packet discard
  322. }
  323. //terminate transmission if needed
  324. if (tx_state == p_BUSY)
  325. {
  326. #ifdef DEBUG802_15_4
  327. hdr_cmn *ch = HDR_CMN(txPkt);
  328. hdr_lrwpan *wph = HDR_LRWPAN(txPkt);
  329. fprintf(stdout,"[%s::%s][%f](node %d) FORCE_TRX_OFF sets error bit for outgoing pkt: type = %s, src = %d, dst = %d, uid = %d, mac_uid = %ld, size = %dn",__FILE__,__FUNCTION__,CURRENT_TIME,index_,wpan_pName(txPkt),p802_15_4macSA(txPkt),p802_15_4macDA(txPkt),ch->uid(),wph->uid,ch->size());
  330. #endif
  331. HDR_CMN(txPkt)->error() = 1;
  332. sendOverH.cancel();
  333. Packet::free(txPktCopy);
  334. last_tx_time=NOW;
  335. tx_state = p_IDLE;
  336. mac->PD_DATA_confirm(p_TRX_OFF);
  337. if (trx_state_defer_set != p_IDLE)
  338. trx_state_defer_set = p_IDLE;
  339. }
  340. }
  341. else
  342. {
  343. t_status = p_SUCCESS;
  344. if (((state == p_RX_ON)&&(trx_state == p_TX_ON))
  345.   ||((state == p_TX_ON)&&(trx_state == p_RX_ON)))
  346. {
  347. trx_state_turnaround = state;
  348. delay = true;
  349. }
  350. else
  351. trx_state = state;
  352. }
  353. //we need to delay <aTurnaroundTime> symbols if Tx2Rx or Rx2Tx
  354. if (delay)
  355. {
  356. trx_state = p_TRX_OFF; //should be disabled immediately (further transmission/reception will not succeed)
  357. TRXH.start(aTurnaroundTime/getRate('s'));
  358. }
  359. else
  360. mac->PLME_SET_TRX_STATE_confirm(t_status);
  361. }
  362. else
  363. mac->PLME_SET_TRX_STATE_confirm(t_status);
  364. #ifdef DEBUG802_15_4
  365. fprintf(stdout,"[%s::%s][%f](node %d) SET TRX: old = %s req = %s ret = %sn",__FILE__,__FUNCTION__,CURRENT_TIME,index_,
  366. (trx_state == p_RX_ON)?"RX_ON":
  367. (trx_state == p_TX_ON)?"TX_ON":
  368. (trx_state == p_TRX_OFF)?"TRX_OFF":"???",
  369. (state == p_RX_ON)?"RX_ON":
  370. (state == p_TX_ON)?"TX_ON":
  371. (state == p_TRX_OFF)?"TRX_OFF":
  372. (state == p_FORCE_TRX_OFF)?"FORCE_TRX_OFF":"???",
  373. (t_status == p_RX_ON)?"RX_ON":
  374. (t_status == p_TX_ON)?"TX_ON":
  375. (t_status == p_TRX_OFF)?"TRX_OFF":
  376. (t_status == p_BUSY_TX)?"BUSY_TX":
  377. (t_status == p_BUSY_RX)?"BUSY_RX":
  378. (t_status == p_SUCCESS)?"SUCCESS":"???");
  379. #endif
  380. }
  381. void Phy802_15_4::PLME_SET_request(PPIBAenum PIBAttribute,PHY_PIB *PIBAttributeValue)
  382. {
  383. PHYenum t_status;
  384. t_status = p_SUCCESS;
  385. switch(PIBAttribute)
  386. {
  387. case phyCurrentChannel:
  388. if (!channelSupported(PIBAttributeValue->phyCurrentChannel))
  389. t_status = p_INVALID_PARAMETER;
  390. if (ppib.phyCurrentChannel != PIBAttributeValue->phyCurrentChannel)
  391. {
  392. //any packet in transmission or reception will be corrupted
  393. if (rxPkt)
  394. {
  395. #ifdef DEBUG802_15_4
  396. hdr_cmn *ch = HDR_CMN(rxPkt);
  397. hdr_lrwpan *wph = HDR_LRWPAN(rxPkt);
  398. fprintf(stdout,"[%s::%s][%f](node %d) SET phy channel sets error bit for incoming pkt: type = %s, src = %d, dst = %d, uid = %d, mac_uid = %ld, size = %dn",__FILE__,__FUNCTION__,CURRENT_TIME,index_,wpan_pName(rxPkt),p802_15_4macSA(rxPkt),p802_15_4macDA(rxPkt),ch->uid(),wph->uid,ch->size());
  399. #endif
  400. HDR_CMN(rxPkt)->error() = 1;
  401. }
  402. if (tx_state == p_BUSY)
  403. {
  404. #ifdef DEBUG802_15_4
  405. hdr_cmn *ch = HDR_CMN(txPkt);
  406. hdr_lrwpan *wph = HDR_LRWPAN(txPkt);
  407. fprintf(stdout,"[%s::%s][%f](node %d) SET phy channel sets error bit for outgoing pkt: type = %s, src = %d, dst = %d, uid = %d, mac_uid = %ld, size = %dn",__FILE__,__FUNCTION__,CURRENT_TIME,index_,wpan_pName(txPkt),p802_15_4macSA(txPkt),p802_15_4macDA(txPkt),ch->uid(),wph->uid,ch->size());
  408. #endif
  409. HDR_CMN(txPkt)->error() = 1;
  410. sendOverH.cancel();
  411. Packet::free(txPktCopy);
  412. last_tx_time=NOW;
  413. tx_state = p_IDLE;
  414. mac->PD_DATA_confirm(p_TRX_OFF);
  415. if (trx_state_defer_set != p_IDLE)
  416. trx_state_defer_set = p_IDLE;
  417. }
  418. ppib.phyCurrentChannel = PIBAttributeValue->phyCurrentChannel;
  419. }
  420. break;
  421. case phyChannelsSupported:
  422. if ((PIBAttributeValue->phyChannelsSupported&0xf8000000) != 0) //5 MSBs reserved
  423. t_status = p_INVALID_PARAMETER;
  424. else
  425. ppib.phyChannelsSupported = PIBAttributeValue->phyChannelsSupported;
  426. break;
  427. case phyTransmitPower:
  428. if (PIBAttributeValue->phyTransmitPower > 0xbf)
  429. t_status = p_INVALID_PARAMETER;
  430. else
  431. ppib.phyTransmitPower = PIBAttributeValue->phyTransmitPower;
  432. break;
  433. case phyCCAMode:
  434. if ((PIBAttributeValue->phyCCAMode < 1)
  435.  || (PIBAttributeValue->phyCCAMode > 3))
  436. t_status = p_INVALID_PARAMETER;
  437. else
  438. ppib.phyCCAMode = PIBAttributeValue->phyCCAMode;
  439. break;
  440. default:
  441. t_status = p_UNSUPPORT_ATTRIBUTE;
  442. break;
  443. }
  444. mac->PLME_SET_confirm(t_status,PIBAttribute);
  445. }
  446. UINT_8 Phy802_15_4::measureLinkQ(Packet *p)
  447. {
  448. //Link quality measurement is somewhat simulation/implementation specific;
  449. //here's our way:
  450. int lq,lq2;
  451. //consider energy
  452. /* Linux floating number compatibility
  453. lq = (int)((p->txinfo_.RxPr/RXThresh_)*128);
  454. */
  455. {
  456. double tmpf;
  457. tmpf = p->txinfo_.RxPr/RXThresh_;
  458. lq = (int)(tmpf * 128);
  459. }
  460. if (lq > 255) lq = 255;
  461. //consider signal-to-noise
  462. /* Linux floating number compatibility
  463. lq2 = (int)((p->txinfo_.RxPr/HDR_LRWPAN(p)->rxTotPower)*255);
  464. */
  465. {
  466. double tmpf;
  467. tmpf = p->txinfo_.RxPr/HDR_LRWPAN(p)->rxTotPower;
  468. lq2 = (int)(tmpf * 255);
  469. }
  470. if (lq > lq2) lq = lq2; //use worst value
  471. return (UINT_8) lq;
  472. }
  473. void Phy802_15_4::recv(Packet *p, Handler *h)
  474. {
  475. hdr_lrwpan* wph = HDR_LRWPAN(p);
  476. hdr_cmn *ch = HDR_CMN(p);
  477.         FrameCtrl frmCtrl;
  478. PacketStamp s;
  479. switch(ch->direction())
  480. {
  481. case hdr_cmn::DOWN:
  482. #ifdef DEBUG802_15_4
  483. fprintf(stdout,"[%s::%s][%f](node %d) outgoing pkt: type = %s, src = %d, dst = %d, uid = %d, mac_uid = %ld, size = %dn",__FILE__,__FUNCTION__,CURRENT_TIME,index_,wpan_pName(p),p802_15_4macSA(p),p802_15_4macDA(p),ch->uid(),wph->uid,ch->size());
  484. #endif
  485. PD_DATA_request((UINT_8) ch->size(),p);
  486. break;
  487. case hdr_cmn::UP:
  488. default:
  489. if (sendUp(p) == 0)
  490. {
  491. // 2.31 change: sendUp(p) returns 0 if the node is asleep or if the received power is less than CS threshold. In the former case, we still need rxTotPower and rxTotNum for CS (for future csma). recvOverHandler frees that packet when it finds that it is not destined for the node. recvOverHandler also decrements rxTotPower and rxTotNum. In the latter case, the packet is simply freed without further action.
  492. if(propagation_) {
  493. s.stamp((MobileNode*)node(), ant_, 0, lambda_);
  494. if (propagation_->Pr(&p->txinfo_, &s, this) < CSThresh_) {
  495. Packet::free(p);
  496. return;
  497. }
  498. }
  499.                  frmCtrl.FrmCtrl = wph->MHR_FrmCtrl;
  500.                  frmCtrl.parse();
  501. //tap out
  502. if (mac->tap() && frmCtrl.frmType == defFrmCtrl_Type_Data)
  503. mac->tap()->tap(p);
  504. if (node()->energy_model() && node()->energy_model()->adaptivefidelity())
  505. node()->energy_model()->add_neighbor(p802_15_4macSA(p));
  506. rxTotPower[wph->phyCurrentChannel] += p->txinfo_.RxPr;
  507. rxTotNum[wph->phyCurrentChannel]++;
  508. // printf("RxTotNum at node %d is %dn", index_, rxTotNum[wph->phyCurrentChannel]);
  509. Scheduler::instance().schedule(&recvOverH, (Event *)p, trxTime(p,true));
  510. // Packet::free(p);
  511. return;
  512. }
  513. if (updateNFailLink(fl_oper_est,index_) == 0)
  514. {
  515. Packet::free(p);
  516. return;
  517. }
  518.                 if (updateLFailLink(fl_oper_est,p802_15_4macSA(p),index_) == 0) //broadcast packets can still reach here
  519.                 {
  520.                         Packet::free(p);
  521.                         return;
  522.                 }
  523.                 frmCtrl.FrmCtrl = wph->MHR_FrmCtrl;
  524.                 frmCtrl.parse();
  525. //tap out
  526. if (mac->tap() && frmCtrl.frmType == defFrmCtrl_Type_Data)
  527. mac->tap()->tap(p);
  528. if (node()->energy_model() && node()->energy_model()->adaptivefidelity())
  529. node()->energy_model()->add_neighbor(p802_15_4macSA(p));
  530. //Under whatever condition, we should mark the media as busy.
  531. // --no matter the packet(s) is for this node or not, no matter
  532. //   what state the transceiver is in, RX_ON,TX_ON or TRX_OFF, and
  533. //   no matter which channel is being used.
  534. //Note that current WirelessPhy->sendUp() prevents packets with (Pr < CSThresh_)
  535. //from reaching here --. need to modify.WirelessPhy->sendUp() if we want to see
  536. //all the packets here (but seems no reason to do that).
  537. // in dB as can be seen from following:
  538. // not very clear (now CPThresh_ is just a ratio, not in dB?)
  539. rxTotPower[wph->phyCurrentChannel] += p->txinfo_.RxPr;
  540. rxTotNum[wph->phyCurrentChannel]++;
  541. if (EDH.active)
  542. if(rxEDPeakPower < rxTotPower[ppib.phyCurrentChannel])
  543. rxEDPeakPower = rxTotPower[ppib.phyCurrentChannel];
  544. if ((p802_15_4macDA(p) == index_) //packet for this node
  545.   ||(p802_15_4macDA(p) == ((int)MAC_BROADCAST))) //broadcast packet
  546. rxThisTotNum[wph->phyCurrentChannel]++;
  547. if (trx_state == p_RX_ON)
  548. if (wph->phyCurrentChannel == ppib.phyCurrentChannel) //current channel
  549. if ((p802_15_4macDA(p) == index_) //packet for this node
  550.   ||(p802_15_4macDA(p) == ((int)MAC_BROADCAST))) //broadcast packet
  551. if (wph->SHR_SFD == defSHR_SFD) //valid SFD
  552. {
  553. #ifdef DEBUG802_15_4
  554. fprintf(stdout,"[%s::%s][%f](node %d) incoming pkt: type = %s, src = %d, dst = %d, uid = %d, mac_uid = %ld, size = %dn",__FILE__,__FUNCTION__,CURRENT_TIME,index_,wpan_pName(p),p802_15_4macSA(p),p802_15_4macDA(p),ch->uid(),wph->uid,ch->size());
  555. #endif
  556. wph->colFlag = false;
  557. if (rxPkt == 0)
  558. {
  559. rxPkt = p;
  560. HDR_LRWPAN(rxPkt)->rxTotPower = rxTotPower[wph->phyCurrentChannel];
  561. }
  562. else
  563. {
  564. #ifdef DEBUG802_15_4
  565. fprintf(stdout,"[D][COL][%s::%s][%f](node %d) COLLISION:nt First (power:%f): type = %s, src = %d, dst = %d, uid = %d, mac_uid = %ld, size = %dntSecond (power:%f): type = %s, src = %d, dst = %d, uid = %d, mac_uid = %ld, size = %dn",
  566. __FILE__,__FUNCTION__,CURRENT_TIME,index_,
  567. rxPkt->txinfo_.RxPr,wpan_pName(rxPkt),p802_15_4macSA(rxPkt),p802_15_4macDA(rxPkt),HDR_CMN(rxPkt)->uid(),HDR_LRWPAN(rxPkt)->uid,HDR_CMN(rxPkt)->size(),
  568. p->txinfo_.RxPr,wpan_pName(p),p802_15_4macSA(p),p802_15_4macDA(p),ch->uid(),wph->uid,ch->size());
  569. #endif
  570. wph->colFlag = true;
  571. HDR_LRWPAN(rxPkt)->colFlag = true;
  572. mac->nam->flashNodeColor(CURRENT_TIME);
  573. if (p->txinfo_.RxPr > rxPkt->txinfo_.RxPr)
  574. {
  575. //What should we do if there is a transceiver state set pending?
  576. //  1. continue defering (could be unbounded delay)
  577. //..2. set transceiver state now (the incoming packet ignored)
  578. //We select choice 1, as the traffic rate is supposed to be low.
  579. rxPkt = p;
  580. HDR_LRWPAN(rxPkt)->rxTotPower = rxTotPower[wph->phyCurrentChannel];
  581. }
  582. }
  583. }
  584. if (rxPkt)
  585. if (HDR_LRWPAN(rxPkt)->rxTotPower < rxTotPower[HDR_LRWPAN(rxPkt)->phyCurrentChannel])
  586. HDR_LRWPAN(rxPkt)->rxTotPower = rxTotPower[HDR_LRWPAN(rxPkt)->phyCurrentChannel];
  587. assert(ch->size() > 0);
  588. if (ch->direction() != hdr_cmn::UP)
  589. {
  590. printf("Packet-flow direction not specified: sending up the stack on default.nn");
  591. ch->direction() = hdr_cmn::UP; //we don't want MAC to handle the same problem
  592. }
  593. Scheduler::instance().schedule(&recvOverH, (Event *)p, trxTime(p,true));
  594. break;
  595. }
  596. }
  597. void Phy802_15_4::CCAHandler(void)
  598. {
  599. PHYenum t_status;
  600. //refer to sec 6.7.9 for CCA details
  601. //  1. CCA will be affected by outgoing packets,
  602. //     incoming packets (both destined for this device 
  603. //     and not destined for this device) and other
  604. //     interferences.
  605. //  2. In implementation, we don't care about the details 
  606. //     and just need to perform an actual measurement.
  607. if ((tx_state == p_BUSY)||(rxTotNum[ppib.phyCurrentChannel] > 0))
  608. {
  609. t_status = p_BUSY;
  610. }
  611. else if (ppib.phyCCAMode == 1) //ED detection
  612. {
  613. //sec 6.5.3.3 and 6.6.3.4
  614. // -- receiver sensitivity: -85 dBm or better for 2.4G
  615. // -- receiver sensitivity: -92 dBm or better for 868M/915M
  616. //sec 6.7.9
  617. // -- ED threshold at most 10 dB above receiver sensitivity.
  618. //For simulations, we simply compare with CSThresh_
  619. t_status = (rxTotPower[ppib.phyCurrentChannel] >= CSThresh_)?p_BUSY:p_IDLE;
  620. }
  621. else if (ppib.phyCCAMode == 2) //carrier sense only
  622. {
  623. t_status = (rxTotNum[ppib.phyCurrentChannel] > 0)?p_BUSY:p_IDLE;
  624. }
  625. else //if (ppib.phyCCAMode == 3) //both
  626. {
  627. t_status = ((rxTotPower[ppib.phyCurrentChannel] >= CSThresh_)&&(rxTotNum[ppib.phyCurrentChannel] > 0))?p_BUSY:p_IDLE;
  628. }
  629. CCAReportH.start(4/getRate('s')); // 2.31 change: Report CCA at the end of 8th symbol (i.e. wait 4 more symbols)
  630. sensed_ch_state = t_status; // 2.31 change: CCA reporting is done by CCAReportHandler
  631. // 2.31 change: Decrement energy spent in CCA
  632. if (node()->energy_model()) { 
  633. if((NOW-4/getRate('s')-aTurnaroundTime/getRate('s'))-channel_idle_time_ > 0) {
  634. node()->energy_model()->DecrIdleEnergy((NOW-4/getRate('s')-aTurnaroundTime/getRate('s'))-channel_idle_time_, P_idle_);
  635. }
  636. if ((NOW-4/getRate('s')-aTurnaroundTime/getRate('s')+aCCATime/getRate('s'))-channel_idle_time_ > 0){
  637. node()->energy_model()->DecrRcvEnergy((aTurnaroundTime+aCCATime)/getRate('s'),Pr_consume_);
  638. channel_idle_time_ = NOW-4/getRate('s')+aCCATime/getRate('s');
  639. update_energy_time_ = NOW-4/getRate('s')+aCCATime/getRate('s');
  640. }
  641. else {
  642. node()->energy_model()->DecrRcvEnergy((aTurnaroundTime+aCCATime)/getRate('s'),2*Pr_consume_-P_idle_); // P_idle_ has already been decremented; just compensating for that
  643. channel_idle_time_ = MAX(channel_idle_time_, NOW-4/getRate('s')+aCCATime/getRate('s'));
  644. update_energy_time_ = MAX(channel_idle_time_,NOW-4/getRate('s')+aCCATime/getRate('s'));
  645. }
  646. }
  647. void Phy802_15_4::CCAReportHandler(void) // 2.31 change: New timer added to report CCA
  648. {
  649. mac->PLME_CCA_confirm(sensed_ch_state);
  650. }
  651. void Phy802_15_4::EDHandler(void)
  652. {
  653. int energy;
  654. UINT_8 t_EnergyLevel;
  655. //refer to sec 6.7.7 for ED implementation details
  656. //ED is somewhat simulation/implementation specific; here's our way:
  657. /* Linux floating number compatibility
  658. energy = (int)((rxEDPeakPower/RXThresh_)*128);
  659. */
  660. {
  661. double tmpf;
  662. tmpf = rxEDPeakPower/RXThresh_;
  663. energy = (int)(tmpf * 128);
  664. }
  665. t_EnergyLevel = (energy > 255)?255:energy;
  666. mac->PLME_ED_confirm(p_SUCCESS,t_EnergyLevel);
  667. }
  668. void Phy802_15_4::TRXHandler(void)
  669. {
  670. trx_state = trx_state_turnaround;
  671. //send a confirm
  672. mac->PLME_SET_TRX_STATE_confirm(trx_state);
  673. }
  674. void Phy802_15_4::recvOverHandler(Packet *p)
  675. {
  676. UINT_8 lq;
  677. hdr_lrwpan* wph = HDR_LRWPAN(p);
  678. hdr_cmn *ch = HDR_CMN(p);
  679. rxTotPower[wph->phyCurrentChannel] -= p->txinfo_.RxPr;
  680. rxTotNum[wph->phyCurrentChannel]--;
  681. if (rxTotNum[wph->phyCurrentChannel] == 0)
  682. rxTotPower[wph->phyCurrentChannel] = 0.0;
  683. if ((p802_15_4macDA(p) != index_)
  684.   &&(p802_15_4macDA(p) != ((int)MAC_BROADCAST))) //packet not for this node (interference)
  685. Packet::free(p);
  686. else if (p != rxPkt) //packet corrupted (not the strongest one) or un-detectable
  687. {
  688. #ifdef DEBUG802_15_4
  689. fprintf(stdout,"[D][%s][%s::%s::%d][%f](node %d) dropping pkt: type = %s, src = %d, dst = %d, uid = %d, mac_uid = %ld, size = %dn",(wph->phyCurrentChannel != ppib.phyCurrentChannel)?"CHN":"NOT",__FILE__,__FUNCTION__,__LINE__,CURRENT_TIME,index_,wpan_pName(p),p802_15_4macSA(p),p802_15_4macDA(p),ch->uid(),wph->uid,ch->size());
  690. #endif
  691. rxThisTotNum[wph->phyCurrentChannel]--;
  692. drop(p,(wph->phyCurrentChannel != ppib.phyCurrentChannel)?"CHN":"NOT");
  693. }
  694. else
  695. {
  696. rxThisTotNum[wph->phyCurrentChannel]--;
  697. //measure (here calculate) the link quality
  698. lq = measureLinkQ(p);
  699. ch->size() -= defPHY_HEADER_LEN;
  700. rxPkt = 0;
  701. if ((ch->size() <= 0) 
  702.     ||(ch->size() > aMaxPHYPacketSize)
  703.     ||ch->error()) //incomplete reception (due to FORCE_TRX_OFF),data packet received during ED or other errors
  704. {
  705. #ifdef DEBUG802_15_4
  706. fprintf(stdout,"[D][ERR][%s::%s::%d][%f](node %d) dropping pkt: type = %s, src = %d, dst = %d, uid = %d, mac_uid = %ld, size = %dn",__FILE__,__FUNCTION__,CURRENT_TIME,__LINE__,index_,wpan_pName(p),p802_15_4macSA(p),p802_15_4macDA(p),ch->uid(),wph->uid,ch->size());
  707. #endif
  708. drop(p,"ERR");
  709. }
  710. else
  711. {
  712. #ifdef DEBUG802_15_4
  713. fprintf(stdout,"[%s::%s][%f](node %d) incoming pkt: type = %s, src = %d, dst = %d, uid = %d, mac_uid = %ld, size = %d --> PD_DATA_indication()n",__FILE__,__FUNCTION__,CURRENT_TIME,index_,wpan_pName(p),p802_15_4macSA(p),p802_15_4macDA(p),ch->uid(),wph->uid,ch->size());
  714. #endif
  715. PD_DATA_indication(ch->size(),p,lq); //MAC sublayer need to further check if the packet
  716. //is really received successfully or not.
  717. }
  718. if (trx_state_defer_set != p_IDLE)
  719. {
  720. trx_state_turnaround = trx_state_defer_set;
  721. trx_state_defer_set = p_IDLE;
  722. if (trx_state_turnaround == p_TRX_OFF)
  723. {
  724. trx_state = trx_state_turnaround;
  725. mac->PLME_SET_TRX_STATE_confirm(trx_state);
  726. }
  727. else
  728. {
  729. //we need to delay <aTurnaroundTime> symbols for Rx2Tx
  730. trx_state = p_TRX_OFF; //should be disabled immediately (further reception will not succeed)
  731. TRXH.start(aTurnaroundTime/getRate('s'));
  732. }
  733. }
  734. }
  735. }
  736. void Phy802_15_4::sendOverHandler(void)
  737. {
  738. #ifdef DEBUG802_15_4
  739. fprintf(stdout,"[%s::%s][%f](node %d) sending over: type = %s, src = %d, dst = %d, uid = %d, mac_uid = %ld, size = %dn",__FILE__,__FUNCTION__,CURRENT_TIME,index_,wpan_pName(txPktCopy),p802_15_4macSA(txPktCopy),p802_15_4macDA(txPktCopy),HDR_CMN(txPktCopy)->uid(),HDR_LRWPAN(txPktCopy)->uid,HDR_CMN(txPktCopy)->size());
  740. #endif
  741. assert(tx_state == p_BUSY);
  742. assert(txPktCopy);
  743. Packet::free(txPktCopy);
  744. last_tx_time=NOW;
  745. tx_state = p_IDLE;
  746. mac->PD_DATA_confirm(p_SUCCESS);
  747. if (trx_state_defer_set != p_IDLE)
  748. {
  749. trx_state_turnaround = trx_state_defer_set;
  750. trx_state_defer_set = p_IDLE;
  751. if (trx_state_turnaround == p_TRX_OFF)
  752. {
  753. trx_state = trx_state_turnaround;
  754. mac->PLME_SET_TRX_STATE_confirm(trx_state);
  755. }
  756. else
  757. {
  758. //we need to delay <aTurnaroundTime> symbols for Rx2Tx
  759. trx_state = p_TRX_OFF; //should be disabled immediately (further transmission will not succeed)
  760. TRXH.start(aTurnaroundTime/getRate('s'));
  761. }
  762. }
  763. }
  764. void Phy802_15_4::wakeupNode(int cause)
  765. {
  766. // cause=0 for beacon reception (to account for sleep-to-wake ramp-up) and 1 for outgoing packtes
  767. if (node()->energy_model()->sleep())
  768. {
  769. node()->energy_model()->set_node_sleep(0);
  770. node()->energy_model()->DecrSleepEnergy(NOW-channel_sleep_time_-T_transition_,P_sleep_);
  771. if (cause==0){
  772. node()->energy_model()->DecrIdleEnergy(T_transition_,P_transition_);
  773. }
  774. channel_idle_time_ = NOW; 
  775. update_energy_time_ = NOW;
  776. status_ = IDLE; 
  777. }
  778. }
  779. void Phy802_15_4::putNodeToSleep(void)
  780. {
  781. node()->energy_model()->set_node_sleep(1);
  782. channel_sleep_time_=NOW;
  783. update_energy_time_ = NOW;
  784. if (mac->wakeupT->busy())
  785. mac->wakeupT->stop();
  786. mac->wakeupT->start(); // This function will automatically determine the time to wake up for the next beacon and set itself an alarm
  787. status_ = SLEEP;
  788. }
  789. // End of file: p802_15_4phy.cc