00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041
00042
00043
00044
00045
00046
00047
00048
00049
00050
00051
00052
00053 #include "p802_15_4csmaca.h"
00054 #include "p802_15_4const.h"
00055 #include "p802_15_4trace.h"
00056
00057
00058 CsmaCA802_15_4::CsmaCA802_15_4(Phy802_15_4 *p, Mac802_15_4 *m)
00059 {
00060 phy = p;
00061 mac = m;
00062 txPkt = 0;
00063 waitNextBeacon = false;
00064 backoffT = new macBackoffTimer(this);
00065 assert(backoffT);
00066 bcnOtherT = new macBeaconOtherTimer(this);
00067 assert(bcnOtherT);
00068 deferCCAT = new macDeferCCATimer(this);
00069 assert(deferCCAT);
00070 }
00071
00072 CsmaCA802_15_4::~CsmaCA802_15_4()
00073 {
00074 delete backoffT;
00075 delete bcnOtherT;
00076 delete deferCCAT;
00077 }
00078
00079 void CsmaCA802_15_4::reset(void)
00080 {
00081 if (beaconEnabled)
00082 {
00083 NB = 0;
00084 CW = 2;
00085 BE = mac->mpib.macMinBE;
00086 if ((mac->mpib.macBattLifeExt)&&(BE > 2))
00087 BE = 2;
00088 }
00089 else
00090 {
00091 NB = 0;
00092 BE = mac->mpib.macMinBE;
00093 }
00094 }
00095
00096 double CsmaCA802_15_4::adjustTime(double wtime)
00097 {
00098
00099
00100 double neg;
00101 double tmpf;
00102
00103 assert(txPkt);
00104 if (!mac->toParent(txPkt))
00105 {
00106 if (mac->mpib.macBeaconOrder != 15)
00107 {
00108
00109
00110
00111 {
00112 tmpf = mac->beaconPeriods * bPeriod;
00113 tmpf = CURRENT_TIME - tmpf;
00114 tmpf += wtime;
00115 neg = tmpf - bcnTxTime;
00116 }
00117
00118 if (neg < 0.0)
00119 wtime -= neg;
00120 return wtime;
00121 }
00122 else
00123 return wtime;
00124 }
00125 else
00126 {
00127 if (mac->macBeaconOrder2 != 15)
00128 {
00129
00130
00131
00132 {
00133 tmpf = mac->beaconPeriods2 * bPeriod;
00134 tmpf = CURRENT_TIME - tmpf;
00135 tmpf += wtime;
00136 neg = tmpf - bcnRxTime;
00137 }
00138
00139 if (neg < 0.0)
00140 wtime -= neg;
00141 return wtime;
00142 }
00143 else
00144 return wtime;
00145 }
00146 }
00147
00148 bool CsmaCA802_15_4::canProceed(double wtime, bool afterCCA)
00149 {
00150
00151
00152 bool ok;
00153 UINT_16 t_bPeriods,t_CAP;
00154 double t_fCAP,t_CCATime,t_IFS,t_transacTime,bcnOtherTime,BI2;
00155
00156 waitNextBeacon = false;
00157 wtime = mac->locateBoundary(mac->toParent(txPkt),wtime);
00158 if (!mac->toParent(txPkt))
00159 {
00160 if (mac->mpib.macBeaconOrder != 15)
00161 {
00162 if (mac->sfSpec.BLE)
00163 t_CAP = mac->getBattLifeExtSlotNum();
00164 else
00165 t_CAP = (mac->sfSpec.FinCAP + 1) * (mac->sfSpec.sd / aUnitBackoffPeriod) - mac->beaconPeriods;
00166
00167
00168
00169
00170 {
00171 double tmpf;
00172 tmpf = CURRENT_TIME + wtime;
00173 tmpf -= bcnTxTime;
00174 tmpf /= bPeriod;
00175 t_bPeriods = (UINT_16)(tmpf - mac->beaconPeriods);
00176 }
00177
00178
00179
00180
00181 double tmpf;
00182 tmpf = CURRENT_TIME + wtime;
00183 tmpf -= bcnTxTime;
00184 if (fmod(tmpf, bPeriod) > 0.0)
00185 t_bPeriods++;
00186 bPeriodsLeft = t_bPeriods - t_CAP;
00187 }
00188 else
00189 bPeriodsLeft = -1;
00190 }
00191 else
00192 {
00193 if (mac->macBeaconOrder2 != 15)
00194 {
00195 BI2 = mac->sfSpec2.BI / phy->getRate('s');
00196
00197
00198
00199
00200 {
00201 double tmpf;
00202 tmpf = (mac->sfSpec2.FinCAP + 1) * mac->sfSpec2.sd;
00203 tmpf += mac->macBcnRxTime;
00204 t_CAP = (UINT_16)(tmpf / phy->getRate('s'));
00205 }
00206
00207
00208
00209
00210 double tmpf;
00211 tmpf = aMaxLostBeacons * BI2;
00212 if (t_CAP + tmpf < CURRENT_TIME)
00213 bPeriodsLeft = -1;
00214 else
00215 {
00216 if (mac->sfSpec2.BLE)
00217 t_CAP = mac->getBattLifeExtSlotNum();
00218 else
00219 t_CAP = (mac->sfSpec2.FinCAP + 1) * (mac->sfSpec2.sd / aUnitBackoffPeriod) - mac->beaconPeriods2;
00220
00221
00222
00223
00224 {
00225 double tmpf;
00226 tmpf = CURRENT_TIME + wtime;
00227 tmpf -= bcnRxTime;
00228 tmpf /= bPeriod;
00229 t_bPeriods = (UINT_16)(tmpf - mac->beaconPeriods2);
00230 }
00231
00232
00233
00234
00235 double tmpf;
00236 tmpf = CURRENT_TIME + wtime;
00237 tmpf -= bcnRxTime;
00238 if (fmod(tmpf, bPeriod) > 0.0)
00239 t_bPeriods++;
00240 bPeriodsLeft = t_bPeriods - t_CAP;
00241 }
00242 }
00243 else
00244 bPeriodsLeft = -1;
00245 }
00246
00247 ok = true;
00248 if (bPeriodsLeft > 0)
00249 ok = false;
00250 else if (bPeriodsLeft == 0)
00251 {
00252 if ((!mac->toParent(txPkt))
00253 && (!mac->sfSpec.BLE))
00254 ok = false;
00255 else if ((mac->toParent(txPkt))
00256 && (!mac->sfSpec2.BLE))
00257 ok = false;
00258 }
00259 if (!ok)
00260 {
00261 #ifdef DEBUG802_15_4
00262 fprintf(stdout,"[%s::%s][%f](node %d) cannot proceed: bPeriodsLeft = %d, orders = %d/%d/%d, type = %s, src = %d, dst = %d, uid = %d, mac_uid = %ld, size = %d\n",__FILE__,__FUNCTION__,CURRENT_TIME,mac->index_,bPeriodsLeft,mac->mpib.macBeaconOrder,mac->macBeaconOrder2,mac->macBeaconOrder3,wpan_pName(txPkt),p802_15_4macSA(txPkt),p802_15_4macDA(txPkt),ch->uid(),HDR_LRWPAN(txPkt)->uid,ch->size());
00263 #endif
00264 if (mac->macBeaconOrder2 != 15)
00265 if (!mac->bcnRxT->busy())
00266 mac->bcnRxT->start();
00267 waitNextBeacon = true;
00268 return false;
00269 }
00270
00271
00272 t_CCATime = 8 / phy->getRate('s');
00273 if (HDR_CMN(txPkt)->size() <= aMaxSIFSFrameSize)
00274 t_IFS = aMinSIFSPeriod;
00275 else
00276 t_IFS = aMinLIFSPeriod;
00277 t_IFS /= phy->getRate('s');
00278 t_transacTime = mac->locateBoundary(mac->toParent(txPkt),wtime) - wtime;
00279 if (!afterCCA)
00280 {
00281 t_transacTime += t_CCATime;
00282 t_transacTime += mac->locateBoundary(mac->toParent(txPkt),t_transacTime) - (t_transacTime);
00283 t_transacTime += t_CCATime;
00284 }
00285 t_transacTime += mac->locateBoundary(mac->toParent(txPkt),t_transacTime) - (t_transacTime);
00286 t_transacTime += phy->trxTime(txPkt);
00287 if (ackReq)
00288 {
00289 t_transacTime += mac->mpib.macAckWaitDuration/phy->getRate('s');
00290 t_transacTime += 2*max_pDelay;
00291 t_transacTime += t_IFS;
00292 t_fCAP = mac->getCAP(true);
00293
00294
00295
00296
00297 double tmpf;
00298 tmpf = CURRENT_TIME + wtime;
00299 tmpf += t_transacTime;
00300 if (tmpf > t_fCAP)
00301 ok = false;
00302 else
00303 ok= true;
00304 }
00305 else
00306 {
00307
00308 ok = true;
00309 t_fCAP = mac->getCAPbyType(1);
00310
00311
00312
00313
00314 double tmpf;
00315 tmpf = CURRENT_TIME + wtime;
00316 tmpf += t_transacTime;
00317 if (tmpf > t_fCAP)
00318 ok = false;
00319 if (ok)
00320 {
00321 t_fCAP = mac->getCAPbyType(2);
00322 t_transacTime += max_pDelay;
00323 t_transacTime += 12/phy->getRate('s');
00324 t_transacTime += t_IFS;
00325
00326
00327
00328
00329 double tmpf;
00330 tmpf = CURRENT_TIME + wtime;
00331 tmpf += t_transacTime;
00332 if (tmpf > t_fCAP)
00333 ok = false;
00334 }
00335 if (ok)
00336 {
00337 t_fCAP = mac->getCAPbyType(3);
00338 t_transacTime -= t_IFS;
00339
00340
00341
00342
00343 double tmpf;
00344 tmpf = CURRENT_TIME + wtime;
00345 tmpf += t_transacTime;
00346 if (tmpf > t_fCAP)
00347 ok = false;
00348 }
00349 }
00350
00351
00352 if (!ok)
00353 {
00354 bPeriodsLeft = 0;
00355 if ((mac->mpib.macBeaconOrder == 15)
00356 && (mac->macBeaconOrder2 == 15)
00357 && (mac->macBeaconOrder3 != 15))
00358 {
00359
00360
00361
00362 {
00363 double tmpf;
00364 tmpf = (mac->macBcnOtherRxTime + mac->sfSpec3.BI);
00365 bcnOtherTime = tmpf / phy->getRate('s');
00366 }
00367
00368 while (bcnOtherTime < CURRENT_TIME)
00369 bcnOtherTime += (mac->sfSpec3.BI / phy->getRate('s'));
00370 bcnOtherT->start(bcnOtherTime - CURRENT_TIME);
00371 }
00372 #ifdef DEBUG802_15_4
00373 fprintf(stdout,"[%s::%s][%f](node %d) cannot proceed: orders = %d/%d/%d, type = %s, src = %d, dst = %d, uid = %d, mac_uid = %ld, size = %d\n",__FILE__,__FUNCTION__,CURRENT_TIME,mac->index_,mac->mpib.macBeaconOrder,mac->macBeaconOrder2,mac->macBeaconOrder3,wpan_pName(txPkt),p802_15_4macSA(txPkt),p802_15_4macDA(txPkt),ch->uid(),HDR_LRWPAN(txPkt)->uid,ch->size());
00374 #endif
00375 if (mac->macBeaconOrder2 != 15)
00376 if (!mac->bcnRxT->busy())
00377 mac->bcnRxT->start();
00378 waitNextBeacon = true;
00379 return false;
00380 }
00381 else
00382 {
00383 bPeriodsLeft = -1;
00384 return true;
00385 }
00386 }
00387
00388 void CsmaCA802_15_4::newBeacon(char trx)
00389 {
00390
00391 double rate,wtime;
00392
00393 if (!mac->txAck)
00394 mac->plme_set_trx_state_request(p_RX_ON);
00395
00396 if (bcnOtherT->busy())
00397 bcnOtherT->stop();
00398
00399
00400 beaconEnabled = ((mac->mpib.macBeaconOrder != 15)||(mac->macBeaconOrder2 != 15));
00401 beaconOther = (mac->macBeaconOrder3 != 15);
00402 reset();
00403 rate = phy->getRate('s');
00404 bcnTxTime = mac->macBcnTxTime / rate;
00405 bcnRxTime = mac->macBcnRxTime / rate;
00406 bPeriod = aUnitBackoffPeriod / rate;
00407
00408 if (waitNextBeacon)
00409 if ((txPkt)
00410 && (!backoffT->busy()))
00411 {
00412 assert(bPeriodsLeft >= 0);
00413 if (bPeriodsLeft == 0)
00414 {
00415 wtime = adjustTime(0.0);
00416 if (canProceed(wtime));
00417 backoffHandler();
00418 }
00419 else
00420 {
00421 wtime = adjustTime(0.0);
00422 wtime += bPeriodsLeft * bPeriod;
00423 if (canProceed(wtime));
00424 backoffT->start(wtime);
00425 }
00426 }
00427 waitNextBeacon = false;
00428 }
00429
00430 void CsmaCA802_15_4::start(bool firsttime,Packet *pkt,bool ackreq)
00431 {
00432 bool backoff;
00433 double rate,wtime,BI2;
00434
00435
00436 if (mac->txAck)
00437 {
00438 mac->backoffStatus = 0;
00439 txPkt = 0;
00440 return;
00441 }
00442
00443 assert(backoffT->busy() == 0);
00444 if (firsttime)
00445 {
00446 beaconEnabled = ((mac->mpib.macBeaconOrder != 15)||(mac->macBeaconOrder2 != 15));
00447 beaconOther = (mac->macBeaconOrder3 != 15);
00448 reset();
00449 assert(txPkt == 0);
00450 txPkt = pkt;
00451 ackReq = ackreq;
00452 rate = phy->getRate('s');
00453 bPeriod = aUnitBackoffPeriod / rate;
00454 if (beaconEnabled)
00455 {
00456 bcnTxTime = mac->macBcnTxTime / rate;
00457 bcnRxTime = mac->macBcnRxTime / rate;
00458
00459 BI2 = (mac->sfSpec2.BI / phy->getRate('s'));
00460 if (mac->macBeaconOrder2 != 15)
00461 while (bcnRxTime + BI2 < CURRENT_TIME)
00462 bcnRxTime += BI2;
00463 }
00464 }
00465
00466 wtime = (Random::random() % (1<<BE)) * bPeriod;
00467 wtime = adjustTime(wtime);
00468 backoff = true;
00469 if (beaconEnabled||beaconOther)
00470 {
00471 if (beaconEnabled)
00472 if (firsttime)
00473 wtime = mac->locateBoundary(mac->toParent(txPkt),wtime);
00474 if (!canProceed(wtime))
00475 backoff = false;
00476 }
00477 if (backoff)
00478 backoffT->start(wtime);
00479 }
00480
00481 void CsmaCA802_15_4::cancel(void)
00482 {
00483 if (bcnOtherT->busy())
00484 bcnOtherT->stop();
00485 else if (backoffT->busy())
00486 backoffT->stop();
00487 else if (deferCCAT->busy())
00488 deferCCAT->stop();
00489 else
00490 mac->taskP.taskStatus(TP_CCA_csmaca) = false;
00491 txPkt = 0;
00492 }
00493
00494 void CsmaCA802_15_4::backoffHandler(void)
00495 {
00496 mac->taskP.taskStatus(TP_RX_ON_csmaca) = true;
00497 mac->plme_set_trx_state_request(p_RX_ON);
00498 }
00499
00500 void CsmaCA802_15_4::RX_ON_confirm(PHYenum status)
00501 {
00502 double now,wtime;
00503
00504 if (status != p_RX_ON)
00505 {
00506 if (status == p_BUSY_TX)
00507 mac->taskP.taskStatus(TP_RX_ON_csmaca) = true;
00508 else
00509 backoffHandler();
00510 return;
00511 }
00512
00513
00514 now = CURRENT_TIME;
00515 if (beaconEnabled)
00516 wtime = mac->locateBoundary(mac->toParent(txPkt),0.0);
00517 else
00518 wtime = 0.0;
00519
00520 if (wtime == 0.0)
00521 {
00522 mac->taskP.taskStatus(TP_CCA_csmaca) = true;
00523 phy->PLME_CCA_request();
00524 }
00525 else
00526 deferCCAT->start(wtime);
00527 }
00528
00529 void CsmaCA802_15_4::bcnOtherHandler(void)
00530 {
00531 newBeacon('R');
00532 }
00533
00534 void CsmaCA802_15_4::deferCCAHandler(void)
00535 {
00536 mac->taskP.taskStatus(TP_CCA_csmaca) = true;
00537 phy->PLME_CCA_request();
00538 }
00539
00540 void CsmaCA802_15_4::CCA_confirm(PHYenum status)
00541 {
00542
00543 bool idle;
00544
00545 idle = (status == p_IDLE)?1:0;
00546 if (idle)
00547 {
00548 if ((!beaconEnabled)&&(!beaconOther))
00549 {
00550 txPkt = 0;
00551 mac->csmacaCallBack(p_IDLE);
00552 }
00553 else
00554 {
00555 if (beaconEnabled)
00556 CW--;
00557 else
00558 CW = 0;
00559 if (CW == 0)
00560 {
00561
00562 if (canProceed(0.0, true))
00563 {
00564 txPkt = 0;
00565 mac->csmacaCallBack(p_IDLE);
00566 }
00567 else
00568 {
00569 if (beaconEnabled) CW = 2;
00570 bPeriodsLeft = 0;
00571 }
00572 }
00573 else
00574 backoffHandler();
00575 }
00576 }
00577 else
00578 {
00579 if (beaconEnabled) CW = 2;
00580 NB++;
00581 if (NB > mac->mpib.macMaxCSMABackoffs)
00582 {
00583 txPkt = 0;
00584 mac->csmacaCallBack(p_BUSY);
00585 }
00586 else
00587 {
00588 BE++;
00589 if (BE > aMaxBE)
00590 BE = aMaxBE;
00591 start(false);
00592 }
00593 }
00594 }
00595
00596