DESERT 3.5.1
Loading...
Searching...
No Matches
uwofdmphy.cpp
Go to the documentation of this file.
1//
2// Copyright (c) 2017 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
39#include "uwofdmphy.h"
40#include <fstream>
41#include <sstream>
42
43#include "uwphy-clmsg.h"
44
45static class UwOFDMPhyClass : public TclClass
46{
47public:
49 : TclClass("Module/UW/OFDM/PHY")
50 {
51 }
52 TclObject *
53 create(int, const char *const *)
54 {
55 return (new UwOFDMPhy);
56 }
58
60 : UnderwaterPhysical(), sentUpPkts(0), totTransTime(0), phySentPkt_(0),
61 bufferSize_(50), buffered_pkt_num(0), current_rcvs(0), nodeNum_(-1), centerFreq_(0),
62 subCarrier_(-1), nodeID_(-1), tx_busy_(0), powerScaling(1)
63
64{ // binding to TCL variables
65 bind("FRAME_BIT", &FRAME_BIT);
66 bind("powerScaling_", (int *)&powerScaling);
67 Interference_Model = "MEANPOWER";
68}
69
73
74int UwOFDMPhy::command(int argc, const char *const *argv)
75{
76 Tcl &tcl = Tcl::instance();
77 if (argc == 2)
78 {
79 if (strcasecmp(argv[1], "getTotalDelay") == 0)
80 {
81 // return Get_Rx_Time();
82 tcl.resultf("%f", getTotalDelay());
83 return TCL_OK;
84 }
85 else if (strcasecmp(argv[1], "getNodeNum") == 0)
86 {
87 tcl.resultf("%d", getNodeNum());
88 return TCL_OK;
89 }
90 else if (strcasecmp(argv[1], "getSubCarNum") == 0)
91 {
92 tcl.resultf("%d", getSubCarNum());
93 return TCL_OK;
94 }
95 else if (strcasecmp(argv[1], "showSubCar") == 0)
96 {
97 showSubCar();
98 return TCL_OK;
99 }
100 else if (strcasecmp(argv[1], "getNodeID") == 0)
101 {
102 tcl.resultf("%d", getNodeID());
103 return TCL_OK;
104 }
105 else if (strcasecmp(argv[1], "getSentUpPkts") == 0)
106 {
107 tcl.resultf("%d", getSentUpPkts());
108 return TCL_OK;
109 }
110 else if (strcasecmp(argv[1], "getLowSnrPktLost") == 0)
111 {
112 tcl.resultf("%d", getLowSnrPktLost());
113 return TCL_OK;
114 }
115 else if (strcasecmp(argv[1], "getNoiseErrPktLost") == 0)
116 {
117 tcl.resultf("%d", getNoiseErrPktLost());
118 return TCL_OK;
119 }
120 else if (strcasecmp(argv[1], "getCollErrPktLost") == 0)
121 {
122 tcl.resultf("%d", getCollErrPktLost());
123 return TCL_OK;
124 }
125 else if (strcasecmp(argv[1], "getTxPenPktLost") == 0)
126 {
127 tcl.resultf("%d", getTxPenPktLost());
128 return TCL_OK;
129 }
130 else if (strcasecmp(argv[1], "getTxPenCtrlLost") == 0)
131 {
132 tcl.resultf("%d", getTxPenCtrlLost());
133 return TCL_OK;
134 }
135 else if (strcasecmp(argv[1], "getFreqCollPktLost") == 0)
136 {
137 tcl.resultf("%d", getFreqCollPktLost());
138 return TCL_OK;
139 }
140 else if (strcasecmp(argv[1], "getModErrPktLost") == 0)
141 {
142 tcl.resultf("%d", getModErrPktLost());
143 return TCL_OK;
144 }
145 else if (strcasecmp(argv[1], "getTransmissionTime") == 0)
146 {
147 tcl.resultf("%f", getTransmissionTime());
148 return TCL_OK;
149 }
150 else if (strcasecmp(argv[1], "getCtrlFCollPktLost") == 0)
151 {
152 tcl.resultf("%d", getCtrlFCollPktLost());
153 return TCL_OK;
154 }
155 else if (strcasecmp(argv[1], "getCtrlCerrPktLost") == 0)
156 {
157 tcl.resultf("%d", getCtrlCErrPktLost());
158 return TCL_OK;
159 }
160 else if (strcasecmp(argv[1], "getPhyPktSent") == 0)
161 {
162 tcl.resultf("%d", getPhyPktSent());
163 return TCL_OK;
164 }
165 }
166 else if (argc == 3)
167 {
168 if (strcasecmp(argv[1], "setNodeNum") == 0)
169 {
170 setNodeNum(atoi(argv[2]));
171 return TCL_OK;
172 }
173 else if (strcasecmp(argv[1], "setSubCarNum") == 0)
174 {
175 setSubCarNum(atoi(argv[2]));
176 return TCL_OK;
177 }
178 else if (strcasecmp(argv[1], "setNodeID") == 0)
179 {
180 setNodeID(atoi(argv[2]));
181 return TCL_OK;
182 }
183 else if (strcasecmp(argv[1], "setBufferSize") == 0)
184 {
185 setBufferSize(atoi(argv[2]));
186 return TCL_OK;
187 }
188 }
189 else if (argc == 4)
190 {
191 if (strcasecmp(argv[1], "setBrokenCar") == 0)
192 {
193 setBrokenCar(atoi(argv[2]), atoi(argv[3]));
194 return TCL_OK;
195 }
196 }
197 else if (argc == 6)
198 {
199 if (strcasecmp(argv[1], "init_ofdm_node") == 0)
200 {
201 init_ofdm_node(atoi(argv[2]), atoi(argv[3]), atoi(argv[4]), atoi(argv[5]));
202 return TCL_OK;
203 }
204 }
205
206 return UnderwaterPhysical::command(argc, argv);
207}
208
209// This function initializes set the buffer size for a node
211{
212 bufferSize_ = s;
213}
214
215// This function initializes all the parameter inside the node
216// All subcarriers are used
217void UwOFDMPhy::init_ofdm_node(int nn, int cf, int scn, int ID)
218{
219 nodeNum_ = nn;
220 centerFreq_ = cf;
221 subCarrier_ = scn;
222 nodeID_ = ID;
223 msgDisp.initDisplayer(nodeID_, "UwOFDMPhy", debug_);
224 std::cout << NOW << " UwOFDMPhy(" << nodeID_ << ")::init_ofdm_node Node created" << std::endl;
225 msgDisp.printStatus("Node Created ", "init_ofdm_node", NOW, nodeID_);
226 return;
227}
228
229/*
230THe recv method takes care any packet comes to phy layer.
231direction for both up and down is permitted.
232The assignment of subcarrier is done here just before the packet is
233transmitted. ( direction down)
234TODO: save only non conflitting packets
235*/
236
237void UwOFDMPhy::recv(Packet *p)
238{
239 hdr_cmn *ch = HDR_CMN(p);
240 hdr_MPhy *ph = HDR_MPHY(p);
241 hdr_mac *mach = HDR_MAC(p);
242 hdr_OFDM *ofdmph = HDR_OFDM(p);
243
244 double temptxtime;
245
246 if (ch->direction() == hdr_cmn::UP)
247 {
248
249 ph->dstSpectralMask = getRxSpectralMask(p);
250 ph->dstPosition = getPosition();
251 ph->dstAntenna = getRxAntenna(p);
252
253 assert(ph->dstSpectralMask);
254 assert(ph->dstPosition);
255
256 ph->Pr = getRxPower(p);
257
258 p->txinfo_.RxPr = 0;
259 p->txinfo_.CPThresh = 0;
260
262 cerr << "UwOFDMPhy ERROR: buffer overflow" << endl;
263 dropPacket(p);
264
265 } else if (ph->Pr > 0) {
266 if (ofdmph->nativeOFDM)
267 ph->Pn = getOFDMNoisePower(p);
268 else
269 ph->Pn = getNoisePower(p);
270 msgDisp.printStatus("received a native? " + itos(ofdmph->nativeOFDM) + " pkt", "recv", NOW, nodeID_);
271
272 if (!ofdmph->nativeOFDM)
273 createOFDMhdr(p);
274 msgDisp.printStatus("Adding to Interference", "recv", NOW, nodeID_);
275
276 if (interference_) {
278 }
279 msgDisp.printStatus("START recv new pkt_type " + itos(ch->ptype()) +
280 " duration is " + dtos(ph->duration),
281 "recv", NOW, nodeID_);
282
283 ph->rxtime = NOW;
284 ph->worth_tracing = true;
285
286 if (isOn == true) {
287 PacketEvent *pe = new PacketEvent(p);
288 Scheduler::instance().schedule(&rxtimer, pe, ph->duration);
290
291 startRx(p);
292 } else {
293 Packet::free(p);
294 }
295 } else {
296 Packet::free(p);
297 }
298 }
299 else
300 { // Direction DOWN
301 assert(isOn);
302 hdr_OFDM *ofdmph = HDR_OFDM(p);
303
304 if (current_rcvs > 0)
305 {
306 // IDEALLY this should never happen, MAC layer must handle concurrency not phy layer
307
308 std::cerr << NOW << " UwOFDMPhy(" << nodeID_
309 << ")::recv ATTENTION: KILLING RECEIVING PACKETS TO TRANSMIT "
310 << current_rcvs << std::endl;
312 }
313
314 ph->Pr = 0;
315 ph->Pn = 0;
316 ph->Pi = 0;
317 ph->txtime = NOW;
318 ph->rxtime = ph->txtime;
319 ofdmph->srcID = nodeID_;
320
321 ph->worth_tracing = false;
322
323 ph->srcSpectralMask = getTxSpectralMask(p);
324 ph->srcAntenna = getTxAntenna(p);
325 ph->srcPosition = getPosition();
326 ph->dstSpectralMask = 0;
327 ph->dstPosition = 0;
328 ph->dstAntenna = 0;
329 ph->modulationType = getModulationType(p);
330 ph->duration = getTxDuration(p);
331
332 if (powerScaling)
333 {
334 int usedCarriers = 0;
335 for (int i = 0; i < subCarrier_; i++)
336 {
337 if (ofdmph->carriers[i] == 1)
338 usedCarriers++;
339 }
340 // TxPower is scaled with used carriers
341 ph->Pt = getTxPower(p) * usedCarriers / subCarrier_;
342 }
343 else
344 ph->Pt = getTxPower(p);
345
346 assert(ph->srcSpectralMask);
347 assert(ph->srcPosition);
348 assert(ph->duration > 0);
349 assert(ph->Pt > 0);
350
351 Packet *pnew = Packet::alloc();
352
353 PacketEvent *pe = new PacketEvent(p->copy());
354
355 msgDisp.printStatus("Sending pkt_type " + itos(ch->ptype()) +
356 " duration is " + dtos(ph->duration),
357 "recv", NOW, nodeID_);
358
359 Scheduler::instance().schedule(&txtimer, pe, (ph->duration));
360
361 temptxtime = ph->duration;
362 totTransTime += Scheduler::instance().clock() - ch->timestamp();
363
364 msgDisp.printStatus("Ready to start transmission", "recv",
365 Scheduler::instance().clock(), nodeID_);
366
367 phySentPkt_++;
368 if (current_rcvs > 0)
369 if (debug_)
370 std::cerr << NOW << " UwOFDMPhy(" << nodeID_
371 << ")::recv() ERROR sending while receiving " << std::endl;
372
373 startTx(p);
374 }
375} /* UnderwaterPhysical::recv */
376
377void UwOFDMPhy::endTx(Packet *p)
378{
379 hdr_cmn *ch = HDR_CMN(p);
380 hdr_MPhy *ph = HDR_MPHY(p);
381 hdr_OFDM *ofdmph = HDR_OFDM(p);
382
383 Tx_Time_ += ph->duration;
384
385 if (powerScaling)
386 {
387 int bw = 0;
388 for (int i = 0; i < subCarrier_; i++)
389 if (ofdmph->carriers[i] == 1)
390 bw += 1;
391 Energy_Tx_ += consumedEnergyTx(ph->duration) * bw / subCarrier_;
392 }
393 else
394 Energy_Tx_ += consumedEnergyTx(ph->duration);
395
396 Transmitted_bytes_ += ch->size();
397
398 return UnderwaterMPhyBpsk::endTx(p);
399} /* UwOFDMPhy::endTx */
400
401void UwOFDMPhy::startRx(Packet *p)
402{
403 hdr_mac *mach = HDR_MAC(p);
404 hdr_MPhy *ph = HDR_MPHY(p);
405
406 hdr_OFDM *ofdmph = HDR_OFDM(p);
407 hdr_cmn *ch = HDR_CMN(p);
408
409 std::ofstream myfile;
410 bool overlapping;
411
412 static int mac_addr = -1;
413
414 ClMsgPhy2MacAddr msg;
415 sendSyncClMsg(&msg);
416 mac_addr = msg.getAddr();
417
418 msgDisp.printStatus("Reception starting, current_rcvs " +
419 std::to_string(current_rcvs), "startRx",
420 Scheduler::instance().clock(), nodeID_);
421
422 overlapping = freqOverlap(p, ofdmph->nativeOFDM);
423
424 msgDisp.printStatus("freqOverlap() executed. Overlapping is " +
425 std::to_string(overlapping), "startRx", NOW, nodeID_);
426
427 if (txPending == false && tx_busy_ == false && overlapping == false)
428 { // for simultaneous receptions
429
430 // The receiver is is not synchronized on any transmission
431 // so we can sync on this packet
432 double snr_dB = 10 * log10(ph->Pr / ph->Pn);
433 ;
434 if (snr_dB > getAcquisitionThreshold())
435 {
436 if (ph->modulationType == modid)
437 {
438 // This is a BPSK packet so we sync on it
439 PktRx = p;
440
441 if (debug_)
442 std::cout << NOW << " UwOFDMPhy(" << nodeID_ << ")::StartRx() Adding packet " << p
443 << " seq_num " << ch->uid() << " isnative " << ofdmph->nativeOFDM
444 << " ph->Pr " << ph->Pn << " ph->Pn " << ph->Pn << std::endl;
445
446 pktqueue_.push_back(*p);
447
448 if (debug_)
449 plotPktQueue();
450
451 current_rcvs++; // I am ACTUALLY TRYING TO RECEIVE THE PACKET, same for above
452
453 msgDisp.printStatus("About to notify the MAC", "startRx", NOW, nodeID_);
454
455 // Notify the MAC
456 Phy2MacStartRx(p);
457
458 return;
459 } else {
460
462 if ((mach->macDA() == mac_addr) && (mach->ftype() != MF_CONTROL)){
464
465 } else if ((mach->macDA() == mac_addr) && (mach->ftype() == MF_CONTROL)) {
467 }
468 }
469 } else {
470
472 msgDisp.printStatus("dropping pkt, LOW SNR", "startRx", NOW, nodeID_);
473
474 incrErrorPktsNoise();
475 if (mach->ftype() != MF_CONTROL) {
477
478 } else if (mach->ftype() == MF_CONTROL) {
480 }
481 }
482 } else if (txPending == true || tx_busy_ == true) {
483 msgDisp.printStatus("dropping pkt, tx pending", "startRx", NOW, nodeID_);
484
486 if (mach->ftype() == MF_DATA) {
487
488 if (mach->macDA() == nodeID_)
489 if(debug_)
490 std::cout << NOW << " UwOFDMPhy(" << nodeID_
491 << ")::startRx() [PROBLEM] Dropping DATA that was for me seq_num "
492 << ch->uid() << " src = " << mach->macSA() << " bc txpending" << std::endl;
493
495 }
496 if (mach->ftype() == MF_RTS || mach->ftype() == MF_CTS) {
499 }
500 } else {
501
503 msgDisp.printStatus("dropping pkt, Frequency Collision", "startRx", NOW, nodeID_);
504
505 if (mach->ftype() == MF_DATA) {
506 if (mach->macDA() == nodeID_)
507 if(debug_)
508 std::cerr << NOW << " UwOFDMPhy(" << nodeID_
509 << ")::startRx() [PROBLEM] Dropping DATA that was for me seq_num "
510 << ch->uid() << " src = " << mach->macSA() << " bc freqcollisions" << std::endl;
512 } else if (mach->ftype() == MF_RTS || mach->ftype() == MF_CTS) {
515 }
516 }
517} /* UwOFDMPhy::startRx */
518
519/*
520The method is activate at the end of receiving side.
521*/
522
523void UwOFDMPhy::endRx(Packet *p)
524{
525 Packet *current_p;
526 current_p = p;
527 hdr_cmn *ch = HDR_CMN(p);
528 hdr_MPhy *ph = HDR_MPHY(p);
529 hdr_mac *mach = HDR_MAC(p);
530 hdr_OFDM *ofdmph = HDR_OFDM(p);
531
532 counter interferent_pkts;
533 static int mac_addr = -1;
534 ClMsgPhy2MacAddr msg;
535 sendSyncClMsg(&msg);
536 total_delay_ = ph->duration;
537 mac_addr = msg.getAddr();
538
539 bool pktfound = false;
540
541 msgDisp.printStatus("Reception ended for pkt_type " + itos(ch->ptype()) + " seq_num " + itos(ch->uid()) +
542 ", current_rcvs " + itos(current_rcvs),
543 "EndRx()", Scheduler::instance().clock(), nodeID_);
544
545 for (auto x = pktqueue_.begin(); x != pktqueue_.end();)
546 {
547 hdr_cmn *chx = HDR_CMN(&*x);
548 hdr_mac *machx = HDR_MAC(&*x);
549
550 if ((chx->uid() == ch->uid()) && (ch->ptype() == chx->ptype())
551 && (mach->macDA() == machx->macDA()) && (mach->macSA() == machx->macSA()))
552 {
553 if (debug_)
554 std::cout << NOW << " UwOFDMPhy(" << nodeID_ << ")::EndRx() Packet found in pktqueue_. current_p "
555 << current_p << " isNative " << ofdmph->nativeOFDM << " seq_num " << ch->uid()
556 << " dest " << mach->macDA() << std::endl;
557
558 pktfound = true;
559 current_p = &*x;
560 x = pktqueue_.erase(x);
561 break;
562 } else {
563 ++x;
564 }
565 }
566 if (debug_)
567 plotPktQueue();
568
569 ch = HDR_CMN(current_p);
570 ph = HDR_MPHY(current_p);
571 mach = HDR_MAC(current_p);
572 ofdmph = HDR_OFDM(current_p);
573
574 if (pktfound) {
575
576 if (pktfound) {
577
578 double per_ni; // packet error rate due to noise and/or interference
579 double per_n; // packet error rate due to noise only
580 int nbits = ch->size() * 8;
581 double interference_power;
582 double x = RNG::defaultrng()->uniform_double();
583 if (debug_)
584 std::cout << NOW << " UwOFDMPhy(" << nodeID_
585 << ")::EndRx() FOUND IN QUEUE packet seq_num " << ch->uid()
586 << " isnative " << ofdmph->nativeOFDM << " ph->Pr " << ph->Pn
587 << " ph->Pn " << ph->Pn << std::endl;
588
589 current_rcvs--; // I previously started to receive the packet
590
591 if (ofdmph->nativeOFDM) {
592 if (debug_)
593 std::cout << NOW << " UwOFDMPhy::endRx(" << nodeID_
594 << ") getOFDMPER with noise. ph->Pr " << ph->Pr
595 << " Ph->Pn " << ph->Pn << std::endl;
596
597 per_n = getOFDMPER(ph->Pr / ph->Pn, nbits, current_p);
598 } else {
599 if (debug_)
600 std::cout << NOW << " UwOFDMPhy::endRx(" << nodeID_
601 << ") getPER with noise. ph->Pr " << ph->Pr << " Ph->Pn " << ph->Pn << std::endl;
602 per_n = getPER(ph->Pr / ph->Pn, nbits, p);
603 }
604
605 bool error_n = x <= per_n;
606 bool error_ni = 0;
607
608 if (!error_n)
609 {
610 if (interference_)
611 {
612 if (Interference_Model == "MEANPOWER")
613 { // only meanpower
614 // is allow in right now
615 // OFDMphy. It's a uwphysical class variable
616 msgDisp.printStatus("getting interference power", "EndRx()", NOW, nodeID_);
617
618 // WARNING: this only uses the interference power on the used subcarriers
619 // the problem is that it averages it which is not always the case in real life
620 interference_power = interference_->getInterferencePower(p);
621 // per_ni = interference > 0; // this if model unknown and interf always distructive
622 msgDisp.printStatus("getOFDMPER with Interference", "EndRx()", NOW, nodeID_);
623
624 if (ofdmph->nativeOFDM)
625 per_ni = getOFDMPER(ph->Pr / (ph->Pn + interference_power), nbits, p);
626 else
627 per_ni = getPER(ph->Pr / (ph->Pn + interference_power), nbits, p);
628 error_ni = x <= per_ni;
629
630 if (debug_)
631 std::cout << "Interference from x = " << x << " interf_power = "
632 << interference_power << " per_ni " << per_ni << std::endl;
633 } else {
634 std::cerr << "Please choose only MEANPOWER as "
635 "Interference_Model"
636 << std::endl;
637 exit(1);
638 }
639 interferent_pkts = interference_->getCounters(p);
640
641 } else {
642 if (ofdmph->nativeOFDM)
643 per_ni = getOFDMPER(ph->Pr / (ph->Pn + ph->Pi),
644 nbits, p); // PER of OFDM acoustic modem
645 else
646 per_ni = getPER(ph->Pr / (ph->Pn + ph->Pi),
647 nbits, p); // PER of OFDM acoustic modem
648 error_ni = x <= per_ni;
649 }
650 }
651 if (time_ready_to_end_rx_ > Scheduler::instance().clock())
652 {
654 Scheduler::instance().clock();
655 } else {
656 Rx_Time_ += (ph->duration + getPropagationDelay(p)); // calculating the total delay.
657 }
658
659 time_ready_to_end_rx_ = Scheduler::instance().clock() + ph->duration;
660 Energy_Rx_ += consumedEnergyRx(ph->duration);
662
663 ch->error() = error_ni || error_n;
664 if (ch->error()) {
665 if (error_n) {
666 if(debug_)
667 std::cout << NOW << " UwOFDMPhy(" << nodeID_
668 << ")::endRx() error due to noise. PER = " << per_n << std::endl;
669
670 if (mach->ftype() == MF_DATA) {
671 if (mach->macDA() == nodeID_)
672 if(debug_)
673 std::cout << NOW << " UwOFDMPhy(" << nodeID_
674 << ")::endRx() [PROBLEM] Dropping DATA for me seq_num "
675 << ch->uid() << " src = " << mach->macSA() << " bc noise" << std::endl;
676 }
677 }
678 if (error_ni) {
679 if(debug_)
680 std::cout
681 << NOW << " UwOFDMPhy(" << nodeID_
682 << ")::endRx() error due to interference. PER = " << per_ni
683 << " Interference Power " << interference_power << std::endl;
684 if (mach->ftype() == MF_DATA)
685 {
686 if (mach->macDA() == nodeID_)
687 if (debug_)
688 std::cout << NOW << " UwOFDMPhy(" << nodeID_
689 << ")::endRx() [PROBLEM] Dropping DATA for me seq_num "
690 << ch->uid() << " src = " << mach->macSA() << " bc interference"
691 << " pwr " << ph->Pr << " noise " << ph->Pn << " interf_pwr "
692 << interference_power << std::endl;
693 }
694 }
695 }
696 if (debug_)
697 {
698 if (error_ni == 1) {
699 std::cout
700 << NOW << " UwOFDMPhy(" << nodeID_
701 << ")::endRx() packet " << ch->uid()
702 << " contains errors due to noise and interference."
703 << std::endl;
704 }
705 else if (error_n == 1)
706 {
707 std::cout << NOW << " UwOFDMPhy(" << nodeID_
708 << ")::endRx() packet " << ch->uid()
709 << " contains errors due to noise." << std::endl;
710 }
711 }
712 if (error_n)
713 {
714 incrErrorPktsNoise();
716 if (mach->ftype() != MF_CONTROL) {
718
719 } else if (mach->ftype() == MF_CONTROL) {
721 }
722 } else if (error_ni) {
724 if (mach->ftype() != MF_CONTROL) {
725
726 incrErrorPktsInterf();
728
729 if (interferent_pkts.second >= 1) {
731 } else {
732 if (interferent_pkts.first > 0) {
734 }
735 }
736 } else if (mach->ftype() == MF_CONTROL) {
737
741
742 if (interferent_pkts.first > 0) {
744 }
745 }
746 }
748 sentUpPkts++;
749
750 sendUp(p);
751
752 if (debug_)
753 std::cout << NOW << " UwOFDMPhy(" << nodeID_
754 << ")::EndRx() Packet UP DONE" << std::endl;
755
756 // PktRx = 0;
757 } else {
759 dropPacket(p);
760 }
761 } else {
762 msgDisp.printStatus("Packet NOT found in pktqueue_, DROPPING it", "EndRx()", NOW, nodeID_);
763
765 dropPacket(p);
766 }
767
768 msgDisp.printStatus("Function Ending", "EndRx", NOW, nodeID_);
769}
770
772{
773
774 for (auto x = pktqueue_.begin(); x != pktqueue_.end();)
775 {
776 dropPacket(&*x);
777 x = pktqueue_.erase(x);
779 }
780
781 current_rcvs = 0;
782 std::cerr << NOW << " UwOFDMPhy(" << nodeID_
783 << ")::interruptReceptions() pktqueue size " << pktqueue_.size()
784 << " buffered pkts " << buffered_pkt_num << " current_rcvs " << current_rcvs << std::endl;
785}
786
788{
789 hdr_cmn *ch = HDR_CMN(p);
790 hdr_MPhy *ph = HDR_MPHY(p);
791 hdr_OFDM *ofdmph = HDR_OFDM(p);
792
793 double new_BitRate_;
794 int txdurationtemp;
795
796 // assert(ph->srcSpectralMask);
797 msgDisp.printStatus("ph->carrierNum " + itos(ofdmph->carrierNum), "getTxDuration", NOW, nodeID_);
798
799 double used_bw = 0;
800 for (int i = 0; i < ofdmph->carrierNum; i++)
801 {
802 if (ofdmph->carriers[i] == 1) {
803 if (ofdmph->carMod[i] == "BPSK")
804 used_bw += 1;
805
806 else if (ofdmph->carMod[i] == "QPSK")
807 used_bw += 2;
808 }
809 }
810
811 if (used_bw == 0)
812 std::cerr << "UwOFDMPhy(" << nodeID_ << ")::getTxDuration() ERROR: USED BANDWIDTH = 0" << std::endl;
813
814 // for BPSK the bandwidth is B = 2/T,
815 // where T is the symbol duration.
816 // Here B is pre-determined by the Spectral Mask,
817 // so we can calculate the bitrate R = 1/T = B/2
818 if (BitRate_ <= 0)
819 BitRate_ = ph->srcSpectralMask->getBandwidth() / 2.0;
820
821 new_BitRate_ = used_bw / ofdmph->carrierNum * BitRate_;
822
823 double txtime = (ch->size() * 8.0 / new_BitRate_);
824
825 if (txtime <= 0) {
826 cerr << " ch->size(): " << ch->size() << " bitrate: " << BitRate_ << std::endl;
827 }
828 assert(txtime > 0);
829
830 if (debug_)
831 {
832 cerr << showpoint << NOW << " " << __PRETTY_FUNCTION__
833 << " packet size: " << ch->size()
834 << " tx duration: " << txtime
835 << " new_bitrate: " << new_BitRate_
836 << endl;
837 }
838 msgDisp.printStatus("tx_time " + dtos(txtime) + " old_brate " + dtos(BitRate_) +
839 " new_brate " + dtos(new_BitRate_), "getTxDuration", NOW, nodeID_);
840
841 return (txtime);
842}
843
844double
845UwOFDMPhy::getOFDMPER(double _snr, int _nbits, Packet *p)
846{
847 hdr_MPhy *ph = HDR_MPHY(p);
848 MSpectralMask *sm = getRxSpectralMask(p);
849 hdr_OFDM *ofdmph = HDR_OFDM(p);
850 assert(sm);
851
852 int ncarriers = sm->getBandwidth() / ofdmph->carrierSize;
853 double snr_with_penalty = _snr * pow(10, RxSnrPenalty_dB_ / 10.0);
854 double ber_ = 0;
855 int usedCarriers = 0;
856 double tber_ = 0;
857 int brokenProb = 10; // out of 100
858
859 for (int i = 0; i < ofdmph->carrierNum; i++)
860 {
861 // set the associated modulation with something like ph->modulationType = subCarMod
862
863 if (ofdmph->carMod[i] == "BPSK")
864 {
865 tber_ = 0.5 * erfc(sqrt(snr_with_penalty));
866 }
867 else if (ofdmph->carMod[i] == "QPSK")
868 {
869 tber_ = erfc(sqrt(snr_with_penalty));
870 }
871 else if (ofdmph->carMod[i] == "BFSK")
872 {
873 tber_ = 0.5 * exp(-snr_with_penalty / 2);
874 }
875 else if (ofdmph->carMod[i] == "8PSK")
876 {
877 double const M = 8;
878 tber_ = (1 / this->log2(M)) *
879 get_prob_error_symbol_mpsk(snr_with_penalty, M);
880 }
881 else if (ofdmph->carMod[i] == "16PSK")
882 {
883 double const M = 16;
884 tber_ = (1 / this->log2(M)) *
885 get_prob_error_symbol_mpsk(snr_with_penalty, M);
886 }
887 else if (ofdmph->carMod[i] == "32PSK")
888 {
889 double const M = 32;
890 tber_ = (1 / this->log2(M)) *
891 get_prob_error_symbol_mpsk(snr_with_penalty, M);
892 }
893
894 ber_ += tber_ * ofdmph->carriers[i];
895 usedCarriers += ofdmph->carriers[i];
896 }
897 ber_ = ber_ / usedCarriers;
898 // WARNING: the BER calculated carrier by carrier makes sense if there are weird thinngs in the network,
899 // otherwise, since the noise it's already scaled, it's the same as computing on total snr
900
901 // PER calculation
902 double per = 1 - pow(1 - ber_, _nbits);
903 if (debug_)
904 std::cout << NOW << " UwOFDMPhy(" << nodeID_ << ")::getOFDMPER BER = " << ber_ << " PER = " << per << std::endl;
905 return per;
906}
907
908// Redefinition of getNoisePower function dependent on subcarriers
909// The noise has a constant value that is multiplied for the used bandwidth
910// A smaller bandwidth corresponds to a smaller noise value and higher SNR
911
913{
914 double actualBand = 0;
915 hdr_MPhy *ph = HDR_MPHY(p);
916 hdr_OFDM *ofdmph = HDR_OFDM(p);
917
918 // std::cout << "NodeID " << nodeID_ << " subCarrier_ " << subCarrier_ << std::endl;
919 MSpectralMask *sm = getRxSpectralMask(p);
920 assert(sm);
921 for (int i = 0; i < ofdmph->carrierNum; i++)
922 {
923 actualBand += ofdmph->carrierSize * ofdmph->carriers[i];
924 }
925
926 double noiseOFDM = getNoisePower(p) * actualBand / sm->getBandwidth();
927 if (debug_)
928 std::cout << NOW << " UwOFDMPhy::getOFDMNoisePower actualBand " << actualBand
929 << " noisePower " << getNoisePower(p) << " noiseOFDM " << noiseOFDM << std::endl;
930
931 return (noiseOFDM);
932}
933
934double
935UwOFDMPhy::getDistance(Packet *_p) // calculates the distance from src to the sink.
936{
937 hdr_MPhy *ph = HDR_MPHY(_p);
938 double x_src = (ph->srcPosition)->getX();
939 double y_src = (ph->srcPosition)->getY();
940 double z_src = (ph->srcPosition)->getZ();
941 double x_dst = (ph->dstPosition)->getX();
942 double y_dst = (ph->dstPosition)->getY();
943 double z_dst = (ph->dstPosition)->getZ();
944 return sqrt(pow(x_src - x_dst, 2.0) + pow(y_src - y_dst, 2.0) +
945 pow(z_src - z_dst, 2.0));
946}
947
948// calculates the propagation delay based on the distance and velocity of sound in sea water.
949double
951{
952 double dist = getDistance(_p);
953
954 return (dist / 1500);
955}
956
957// Checks if the arriving packet overlaps in carriers with previous packets that
958// are being received in this moment
959bool UwOFDMPhy::freqOverlap(Packet *p2, bool isOFDM)
960{
961 if (!p2)
962 return false;
963
964 hdr_OFDM *ofdmph2 = HDR_OFDM(p2);
965
966 if (debug_)
967 for (int i = 0; i < ofdmph2->carrierNum; i++)
968 std::cout << "carrier[" << i << "]=" << ofdmph2->carriers[i] << std::endl;
969
970 for (const auto &x : pktqueue_)
971 {
972 hdr_OFDM *ofdmph1 = HDR_OFDM(&x);
973 for (int i = 0; i < ofdmph1->carrierNum; i++)
974 if (ofdmph1->carriers[i] && ofdmph2->carriers[i])
975 return true;
976 }
977
978 if (!isOFDM)
979 {
980 // A non-OFDM packet arrives
981 std::cout << "WARNING: OFDM node receiving NON OFDM packet" << std::endl;
982 }
983
984 return false;
985}
987{
988 // TODO: are these spectral mask really different,
989 // how does the packet know?
990 // Fill the carriers of the original system
991
992 hdr_OFDM *ofdmph = HDR_OFDM(p);
993 hdr_MPhy *ph = HDR_MPHY(p);
994
995 MSpectralMask *txsm = ph->srcSpectralMask;
996 MSpectralMask *rxsm = getRxSpectralMask(p);
997 double newPktStart = txsm->getFreq() - txsm->getBandwidth() / 2;
998 double newPktEnd = txsm->getFreq() + txsm->getBandwidth() / 2;
999 double nodeStart = rxsm->getFreq() - rxsm->getBandwidth() / 2;
1000 double nodeEnd = rxsm->getFreq() + rxsm->getBandwidth() / 2;
1001 double carsize = rxsm->getBandwidth() / subCarrier_;
1002
1003 if (debug_)
1004 {
1005 std::cout << NOW << " incoming Pkt Start and End: " << newPktStart << " " << newPktEnd << std::endl;
1006 std::cout << NOW << " node Start and End: " << nodeStart << " " << nodeEnd << std::endl;
1007 }
1008
1009 ofdmph->carrierNum = subCarrier_;
1010 int i = 0;
1011 for (double s = nodeStart; s < nodeEnd; s = s + carsize)
1012 if ((newPktStart <= s + carsize) && (newPktEnd > s))
1013 {
1014 if (debug_)
1015 std::cout << NOW << " 1 Added " << std::endl;
1016 ofdmph->carriers[i] = 1;
1017 }
1018 else
1019 ofdmph->carriers[i] = 0;
1020 i++;
1021
1022 if (debug_)
1023 std::cout << NOW << " End createOFDMhdr function" << std::endl;
1024 return;
1025}
1026
1027// Returns total number of packets lost for low SNR
1029{
1030 return lostPackets[LOWSNR];
1031}
1032
1033// Returns total number of packets lost for noise error
1035{
1036 return lostPackets[NOISEERR];
1037}
1038
1039// Returns total number of packets lost for Collision error
1041{
1042 return lostPackets[COLLERR];
1043}
1044
1045// Returns total number of packets lost for transmission pending
1047{
1048 return lostPackets[TXPEN];
1049}
1050
1051// Returns total number of packets lost for transmission pending
1053{
1054 return lostPackets[TXPENCTRL];
1055}
1056
1057// Returns total number of packets (DATA + CTRL) lost for collision in frequency
1059{
1060 return lostPackets[FREQCOLL];
1061}
1062
1063// Returns total number of SubCarriers available for a given node
1065{
1066 return lostPackets[MODERR];
1067}
1068
1069// Returns total number of CTRL Packets lost for collision in frequency
1071{
1072 return lostPackets[CTRLFERR];
1073}
1074
1075// Returns total number of CTRL Packets lost for collision error
1077{
1078 return lostPackets[CTRLCERR];
1079}
1080// Returns total number of SubCarriers available for a given node
1082{
1083 return totTransTime;
1084}
1085// Returns total number of packets sent by phy layer
1087{
1088 return phySentPkt_;
1089}
1090
1091// return nodeID
1093{
1094 return nodeID_;
1095}
1096
1097// return number of nodes in the simulation
1099{
1100 return nodeNum_;
1101}
1102
1103// return the number of subcarriers in the simulation
1105{
1106 return subCarrier_;
1107}
1108
1109// set number of nodes in the simulation
1111{
1112 nodeNum_ = n;
1113 return;
1114}
1116{
1117 return sentUpPkts;
1118}
1119
1120// set number of nodes in the simulation
1122{
1123 nodeID_ = n;
1124 return;
1125}
1126
1127// set number of nodes in the simulation
1129{
1130 subCarrier_ = n;
1131 return;
1132}
1133void UwOFDMPhy::setBrokenCar(int bottom, int top)
1134{
1135 brokenCarriers_.push_back(bottom);
1136 brokenCarriers_.push_back(top);
1137 return;
1138}
1139
1140// return the number of subcarriers in the simulation
1142{
1143 std::cout << "showSubCar() unimplemented\n"
1144 << std::endl;
1145 return;
1146}
1147
1148// sets subcarriers from outside the class
1149void UwOFDMPhy::setSubCar(int index, int value)
1150{
1151 std::cerr << "setSubCar() unimplemented\n"
1152 << std::endl;
1153 return;
1154}
1155
1157{
1158 if (m->type() == CLMSG_UWPHY_TX_BUSY)
1159 {
1160 if (((ClMsgUwPhyTxBusy *)m)->getGetOp() == 1)
1161 {
1162 if (debug_)
1163 std::cout << NOW << " UwOFDMPhy(" << nodeID_
1164 << ")::recvSyncClMsg [get] tx_busy_ to send back is " << tx_busy_ << std::endl;
1165 ((ClMsgUwPhyTxBusy *)m)->setTxBusy(tx_busy_);
1166 }
1167 else
1168 {
1169 tx_busy_ = ((ClMsgUwPhyTxBusy *)m)->getTxBusy();
1170 if (debug_)
1171 std::cout << NOW << " UwOFDMPhy(" << nodeID_
1172 << ")::recvSyncClMsg [set] tx_busy_ received is " << tx_busy_ << std::endl;
1173 }
1174 return 0;
1175 }
1176 return UnderwaterMPhyBpsk::recvSyncClMsg(m);
1177}
1179{
1180 std::cout << NOW << " UwOFDMPhy(" << nodeID_ << ")::plotPktQueue()" << std::endl;
1181 for (auto x = pktqueue_.begin(); x != pktqueue_.end();)
1182 {
1183 hdr_cmn *ch = HDR_CMN(&*x);
1184 hdr_MPhy *ph = HDR_MPHY(&*x);
1185 hdr_OFDM *ofdmph = HDR_OFDM(&*x);
1186 hdr_mac *mach = HDR_MAC(&*x);
1187 std::cout << "Packet " << &*x << " seq_num " << ch->uid()
1188 << " native " << ofdmph->nativeOFDM << " ph->Pr " << ph->Pn
1189 << " ph->Pn " << ph->Pn << " MACDE " << mach->macDA()
1190 << " MACSRC " << mach->macSA() << std::endl;
1191 ++x;
1192 }
1193}
ClMsgUwPhyTxBusy should be and used to ask either to set or get the transmitting busy variable of a s...
void initDisplayer(int n, std::string pn, int pactive)
void printStatus(std::string st, std::string fxName, double now, int addr)
void incrTot_pkts_lost()
Increment the number of packets discarded.
Definition uwphysical.h:295
std::string Interference_Model
Interference calcuation mode chosen: CHUNK model or MEANPOWER model.
Definition uwphysical.h:463
virtual double consumedEnergyTx(const double &_duration)
Compute the energy (in Joule) spent by the modem in transmission.
Definition uwphysical.h:188
virtual double consumedEnergyRx(const double &_duration)
Compute the energy (in Joule) spent by the modem in reception.
Definition uwphysical.h:200
double Tx_Time_
Time (in seconds) spent by the node in transmission.
Definition uwphysical.h:433
uwinterference * interference_
Pointer to the interference model module.
Definition uwphysical.h:467
void incrErrorCtrlPktsInterf()
Increment the number of CTRL packets discarded due to interference.
Definition uwphysical.h:313
virtual double getPER(double snr, int nbits, Packet *)
Returns the packet error rate by using the length of a packet and the information contained in the pa...
double Energy_Rx_
Energy (in Joule) spent by the node in transmission.
Definition uwphysical.h:441
double Transmitted_bytes_
Number of bytes transmitted.
Definition uwphysical.h:444
const double log2(const double &_input) const
Definition uwphysical.h:411
double Energy_Tx_
Energy (in Joule) spent by the node in transmission.
Definition uwphysical.h:438
void incrCollisionCTRL()
Increment the number of CTRL pkts discarded due to a collision.
Definition uwphysical.h:331
void incrCollisionDATAvsCTRL()
Increment the number of collisions DATA/CTRL.
Definition uwphysical.h:322
double time_ready_to_end_rx_
Used to keep track of the arrival time.
Definition uwphysical.h:430
const double get_prob_error_symbol_mpsk(const double &_snr, const uint32_t _M) const
Definition uwphysical.h:423
double Rx_Time_
Time (in seconds) spent by the node in reception.
Definition uwphysical.h:435
virtual int command(int, const char *const *)
TCL command interpreter.
void incrCollisionDATA()
Increment the number of DATA pkts discarded due to a collision.
Definition uwphysical.h:340
void incrTotCrtl_pkts_lost()
Increment the number of CTRL packets discarded.
Definition uwphysical.h:304
TclObject * create(int, const char *const *)
Definition uwofdmphy.cpp:53
int getModErrPktLost() const
int getTxPenPktLost() const
int buffered_pkt_num
Definition uwofdmphy.h:306
virtual void startRx(Packet *p)
Handles the start of a packet reception.
virtual double getDistance(Packet *)
Return the distance between source and destination.
int sentUpPkts
Definition uwofdmphy.h:324
void setSubCarNum(int)
double totTransTime
Definition uwofdmphy.h:326
virtual double getOFDMPER(double _snr, int _nbits, Packet *)
Returns the packet error rate by using the length of a packet and the information contained in the pa...
int bufferSize_
Definition uwofdmphy.h:317
int FRAME_BIT
Definition uwofdmphy.h:315
int getCollErrPktLost() const
void setNodeNum(int)
int phySentPkt_
Definition uwofdmphy.h:327
int powerScaling
Definition uwofdmphy.h:313
UwOFDMPhy()
Constructor of UwOFDMPhy class.
Definition uwofdmphy.cpp:59
int tx_busy_
transmission power might be carried out just by re-setting this value.
Definition uwofdmphy.h:338
double getTxDuration(Packet *p)
Computes the transmission time duration depending on the used carriers.
int nodeID_
Definition uwofdmphy.h:311
virtual int getTotalDelay()
returns total delay
Definition uwofdmphy.h:281
int getCtrlFCollPktLost() const
int current_rcvs
Definition uwofdmphy.h:307
int getSubCarNum() const
virtual int command(int, const char *const *)
TCL command interpreter.
Definition uwofdmphy.cpp:74
int subCarrier_
Definition uwofdmphy.h:310
virtual ~UwOFDMPhy()
Destructor of UwOFDMPhy class.
Definition uwofdmphy.cpp:70
MsgDisplayer msgDisp
Definition uwofdmphy.h:340
void init_ofdm_node(int nn, int cf, int scn, int ID)
std::vector< Packet > pktqueue_
Definition uwofdmphy.h:319
void setBrokenCar(int, int)
void setNodeID(int)
void interruptReceptions()
Interrupts reception if MAC has other priorities Theoretically should never be called.
void plotPktQueue()
Plots pktqueue elements.
double total_delay_
Definition uwofdmphy.h:312
virtual double getOFDMNoisePower(Packet *p)
Handles the end of a transmission, redefined to scale the power into the carriers.
int getFreqCollPktLost() const
bool freqOverlap(Packet *, bool)
int getNodeNum() const
string dtos(double d)
Definition uwofdmphy.h:301
virtual double getPropagationDelay(Packet *)
Return the propagation delay for the packet.
virtual void endTx(Packet *p)
Handles the end of a transmission, redefined to scale the power into the carriers.
int getTxPenCtrlLost() const
double getTransmissionTime() const
void createOFDMhdr(Packet *p)
Creates an OFDM header for non-OFDM packets.
virtual void recv(Packet *)
recv method.
int lostPackets[8]
Definition uwofdmphy.h:325
std::vector< double > brokenCarriers_
Definition uwofdmphy.h:322
virtual void endRx(Packet *p)
Handles the end of a packet reception.
int nodeNum_
Definition uwofdmphy.h:308
int getLowSnrPktLost() const
int centerFreq_
Definition uwofdmphy.h:309
int getPhyPktSent() const
void showSubCar()
int getCtrlCErrPktLost() const
void setSubCar(int, int)
int getSentUpPkts()
void setBufferSize(int)
int getNodeID() const
int getNoiseErrPktLost() const
int recvSyncClMsg(ClMessage *m)
Handles receiving messages from the MAC layer.
string itos(int i)
Definition uwofdmphy.h:291
virtual counter getCounters(Packet *p)
Returns the counters of collisions.
virtual void addToInterference(Packet *p)
Add a packet to the interference calculation.
virtual double getInterferencePower(Packet *p)
Compute the average interference power for the given packet.
Header of the OFDM message with fields to implement a multi carrier system.
int carriers[MAX_CARRIERS]
double carrierSize
bool nativeOFDM
string carMod[MAX_CARRIERS]
std::pair< int, int > counter
counter of collisions
UwOFDMPhyClass class_module_uwofdmphy
Definition of UwOFDMPhy class. Your can find the brief description of this physical layer in the pape...
@ TXPEN
Definition uwofdmphy.h:64
@ TXPENCTRL
Definition uwofdmphy.h:64
@ LOWSNR
Definition uwofdmphy.h:64
@ MODERR
Definition uwofdmphy.h:64
@ NOISEERR
Definition uwofdmphy.h:64
@ FREQCOLL
Definition uwofdmphy.h:64
@ COLLERR
Definition uwofdmphy.h:64
@ CTRLFERR
Definition uwofdmphy.h:64
@ CTRLCERR
Definition uwofdmphy.h:64
#define HDR_OFDM(p)
alias defined to access the PROBE HEADER
Definition of ClMsgUwMmac class.