A Discrete-Event Network Simulator
API
Loading...
Searching...
No Matches
uan-phy-gen.cc
Go to the documentation of this file.
1/*
2 * Copyright (c) 2009 University of Washington
3 *
4 * SPDX-License-Identifier: GPL-2.0-only
5 *
6 * Author: Leonard Tracy <lentracy@gmail.com>
7 * Andrea Sacco <andrea.sacco85@gmail.com>
8 */
9
10#include "uan-phy-gen.h"
11
13#include "uan-channel.h"
14#include "uan-net-device.h"
15#include "uan-transducer.h"
16#include "uan-tx-mode.h"
17
18#include "ns3/double.h"
19#include "ns3/energy-source-container.h"
20#include "ns3/log.h"
21#include "ns3/node.h"
22#include "ns3/ptr.h"
23#include "ns3/simulator.h"
24#include "ns3/string.h"
25#include "ns3/trace-source-accessor.h"
26#include "ns3/traced-callback.h"
27#include "ns3/uinteger.h"
28
29namespace ns3
30{
31
32NS_LOG_COMPONENT_DEFINE("UanPhyGen");
33
35NS_OBJECT_ENSURE_REGISTERED(UanPhyPerGenDefault);
36NS_OBJECT_ENSURE_REGISTERED(UanPhyCalcSinrDefault);
37NS_OBJECT_ENSURE_REGISTERED(UanPhyCalcSinrFhFsk);
38NS_OBJECT_ENSURE_REGISTERED(UanPhyPerUmodem);
39NS_OBJECT_ENSURE_REGISTERED(UanPhyPerCommonModes);
40
41/*************** UanPhyCalcSinrDefault definition *****************/
45
49
52{
53 static TypeId tid = TypeId("ns3::UanPhyCalcSinrDefault")
55 .SetGroupName("Uan")
56 .AddConstructor<UanPhyCalcSinrDefault>();
57 return tid;
58}
59
60double
62 Time arrTime,
63 double rxPowerDb,
64 double ambNoiseDb,
65 UanTxMode mode,
66 UanPdp pdp,
67 const UanTransducer::ArrivalList& arrivalList) const
68{
69 if (mode.GetModType() == UanTxMode::OTHER)
70 {
71 NS_LOG_WARN("Calculating SINR for unsupported modulation type");
72 }
73
74 double intKp = -DbToKp(rxPowerDb); // This packet is in the arrivalList
75 auto it = arrivalList.begin();
76 for (; it != arrivalList.end(); it++)
77 {
78 intKp += DbToKp(it->GetRxPowerDb());
79 }
80
81 double totalIntDb = KpToDb(intKp + DbToKp(ambNoiseDb));
82
83 NS_LOG_DEBUG("Calculating SINR: RxPower = "
84 << rxPowerDb << " dB. Number of interferers = " << arrivalList.size()
85 << " Interference + noise power = " << totalIntDb
86 << " dB. SINR = " << rxPowerDb - totalIntDb << " dB.");
87 return rxPowerDb - totalIntDb;
88}
89
90/*************** UanPhyCalcSinrFhFsk definition *****************/
94
98
101{
102 static TypeId tid = TypeId("ns3::UanPhyCalcSinrFhFsk")
104 .SetGroupName("Uan")
105 .AddConstructor<UanPhyCalcSinrFhFsk>()
106 .AddAttribute("NumberOfHops",
107 "Number of frequencies in hopping pattern.",
108 UintegerValue(13),
111 return tid;
112}
113
114double
116 Time arrTime,
117 double rxPowerDb,
118 double ambNoiseDb,
119 UanTxMode mode,
120 UanPdp pdp,
121 const UanTransducer::ArrivalList& arrivalList) const
122{
123 if ((mode.GetModType() != UanTxMode::FSK) && (mode.GetConstellationSize() != 13))
124 {
125 NS_FATAL_ERROR("Calculating SINR for unsupported mode type");
126 }
127
128 Time ts = Seconds(1.0 / mode.GetPhyRateSps());
129 Time clearingTime = (m_hops - 1.0) * ts;
130 double csp = pdp.SumTapsFromMaxNc(Time(), ts);
131
132 // Get maximum arrival offset
133 double maxAmp = -1;
134 Time maxTapDelay(0);
135 auto pit = pdp.GetBegin();
136 for (; pit != pdp.GetEnd(); pit++)
137 {
138 if (std::abs(pit->GetAmp()) > maxAmp)
139 {
140 maxAmp = std::abs(pit->GetAmp());
141 // Modified in order to subtract delay of first tap (maxTapDelay appears to be used
142 // later in code as delay from first reception, not from TX time)
143 maxTapDelay = pit->GetDelay() - pdp.GetTap(0).GetDelay();
144 }
145 }
146
147 double effRxPowerDb = rxPowerDb + KpToDb(csp);
148 // It appears to be just the first elements of the sum in Parrish paper,
149 // "System Design Considerations for Undersea Networks: Link and Multiple Access Protocols",
150 // eq. 14
151 double isiUpa =
152 DbToKp(rxPowerDb) * pdp.SumTapsFromMaxNc(ts + clearingTime, ts); // added DpToKp()
153 auto it = arrivalList.begin();
154 double intKp = -DbToKp(effRxPowerDb);
155 for (; it != arrivalList.end(); it++)
156 {
157 UanPdp intPdp = it->GetPdp();
158 Time tDelta = Abs(arrTime + maxTapDelay - it->GetArrivalTime());
159 // We want tDelta in terms of a single symbol (i.e. if tDelta = 7.3 symbol+clearing
160 // times, the offset in terms of the arriving symbol power is
161 // 0.3 symbol+clearing times.
162
163 tDelta = Rem(tDelta, ts + clearingTime);
164
165 // Align to pktRx
166 if (arrTime + maxTapDelay > it->GetArrivalTime())
167 {
168 tDelta = ts + clearingTime - tDelta;
169 }
170
171 double intPower = 0.0;
172 if (tDelta < ts) // Case where there is overlap of a symbol due to interferer arriving just
173 // after desired signal
174 {
175 // Appears to be just the first two elements of the sum in Parrish paper, eq. 14
176 intPower += intPdp.SumTapsNc(Time(), ts - tDelta);
177 intPower +=
178 intPdp.SumTapsNc(ts - tDelta + clearingTime, 2 * ts - tDelta + clearingTime);
179 }
180 else // Account for case where there's overlap of a symbol due to interferer arriving with a
181 // tDelta of a symbol + clearing time later
182 {
183 // Appears to be just the first two elements of the sum in Parrish paper, eq. 14
184 Time start = ts + clearingTime - tDelta;
185 Time end =
186 /*start +*/ ts; // Should only sum over portion of ts that overlaps, not entire ts
187 intPower += intPdp.SumTapsNc(start, end);
188
189 start = start + ts + clearingTime;
190 // Should only sum over portion of ts that overlaps, not entire ts
191 end = end + ts + clearingTime; // start + Seconds (ts);
192 intPower += intPdp.SumTapsNc(start, end);
193 }
194 intKp += DbToKp(it->GetRxPowerDb()) * intPower;
195 }
196
197 double totalIntDb = KpToDb(isiUpa + intKp + DbToKp(ambNoiseDb));
198
199 NS_LOG_DEBUG("Calculating SINR: RxPower = "
200 << rxPowerDb << " dB. Effective Rx power " << effRxPowerDb
201 << " dB. Number of interferers = " << arrivalList.size()
202 << " Interference + noise power = " << totalIntDb
203 << " dB. SINR = " << effRxPowerDb - totalIntDb << " dB.");
204 return effRxPowerDb - totalIntDb;
205}
206
207/*************** UanPhyPerGenDefault definition *****************/
211
215
216TypeId
218{
219 static TypeId tid = TypeId("ns3::UanPhyPerGenDefault")
221 .SetGroupName("Uan")
222 .AddConstructor<UanPhyPerGenDefault>()
223 .AddAttribute("Threshold",
224 "SINR cutoff for good packet reception.",
225 DoubleValue(8),
228 return tid;
229}
230
231// Default PER calculation simply compares SINR to a threshold which is configurable
232// via an attribute.
233double
235{
236 if (sinrDb >= m_thresh)
237 {
238 return 0;
239 }
240 else
241 {
242 return 1;
243 }
244}
245
246/*************** UanPhyPerCommonModes definition *****************/
251
255
256TypeId
258{
259 static TypeId tid = TypeId("ns3::UanPhyPerCommonModes")
261 .SetGroupName("Uan")
262 .AddConstructor<UanPhyPerCommonModes>();
263
264 return tid;
265}
266
267double
269{
270 NS_LOG_FUNCTION(this);
271
272 double EbNo = std::pow(10.0, sinrDb / 10.0);
273 double BER = 1.0;
274 double PER = 0.0;
275
276 switch (mode.GetModType())
277 {
278 case UanTxMode::PSK:
279 switch (mode.GetConstellationSize())
280 {
281 case 2: // BPSK
282 {
283 BER = 0.5 * erfc(sqrt(EbNo));
284 break;
285 }
286 case 4: // QPSK, half BPSK EbNo
287 {
288 BER = 0.5 * erfc(sqrt(0.5 * EbNo));
289 break;
290 }
291
292 default:
293 NS_FATAL_ERROR("constellation " << mode.GetConstellationSize() << " not supported");
294 break;
295 }
296 break;
297
298 // taken from Ronell B. Sicat, "Bit Error Probability Computations for M-ary Quadrature
299 // Amplitude Modulation", EE 242 Digital Communications and Codings, 2009
300 case UanTxMode::QAM: {
301 // generic EbNo
302 EbNo *= static_cast<double>(mode.GetBandwidthHz()) / mode.GetDataRateBps();
303
304 auto M = (double)mode.GetConstellationSize();
305
306 // standard squared quantized QAM, even number of bits per symbol supported
307 int log2sqrtM = (int)::std::log2(sqrt(M));
308
309 double log2M = ::std::log2(M);
310
311 if ((int)log2M % 2)
312 {
313 NS_FATAL_ERROR("constellation " << M << " not supported");
314 }
315
316 double sqrtM = ::std::sqrt(M);
317
318 NS_LOG_DEBUG("M=" << M << "; log2sqrtM=" << log2sqrtM << "; log2M=" << log2M
319 << "; sqrtM=" << sqrtM);
320
321 BER = 0.0;
322
323 // Eq (75)
324 for (int k = 0; k < log2sqrtM; k++)
325 {
326 int sum_items =
327 (int)((1.0 - ::std::pow(2.0, (-1.0) * (double)k)) * ::std::sqrt(M) - 1.0);
328 double pow2k = ::std::pow(2.0, (double)k - 1.0);
329
330 NS_LOG_DEBUG("k=" << k << "; sum_items=" << sum_items << "; pow2k=" << pow2k);
331
332 double PbK = 0;
333
334 // Eq (74)
335 for (int j = 0; j < sum_items; ++j)
336 {
337 PbK += ::std::pow(-1.0, ::std::floor((double)j * pow2k / sqrtM)) *
338 (pow2k - ::std::floor((double)(j * pow2k / sqrtM) + 0.5)) *
339 erfc((2.0 * (double)j + 1.0) *
340 ::std::sqrt(3.0 * (log2M * EbNo) / (2.0 * (M - 1.0))));
341
342 NS_LOG_DEBUG("j=" << j << "; PbK=" << PbK);
343 }
344 PbK *= 1.0 / sqrtM;
345
346 BER += PbK;
347
348 NS_LOG_DEBUG("k=" << k << "; PbK=" << PbK << "; BER=" << BER);
349 }
350
351 BER *= 1.0 / (double)log2sqrtM;
352
353 break;
354 }
355
356 case UanTxMode::FSK:
357 switch (mode.GetConstellationSize())
358 {
359 case 2: {
360 BER = 0.5 * erfc(sqrt(0.5 * EbNo));
361 break;
362 }
363
364 default:
365 NS_FATAL_ERROR("constellation " << mode.GetConstellationSize() << " not supported");
366 }
367 break;
368
369 default: // OTHER and error
370 NS_FATAL_ERROR("Mode " << mode.GetModType() << " not supported");
371 break;
372 }
373
374 PER = (1.0 - pow(1.0 - BER, (double)pkt->GetSize() * 8.0));
375
376 NS_LOG_DEBUG("BER=" << BER << "; PER=" << PER);
377
378 return PER;
379}
380
381/*************** UanPhyPerUmodem definition *****************/
385
389
390TypeId
392{
393 static TypeId tid = TypeId("ns3::UanPhyPerUmodem")
395 .SetGroupName("Uan")
396 .AddConstructor<UanPhyPerUmodem>();
397 return tid;
398}
399
400double
402{
403 double result;
404
405 result = 1.0;
406
407 for (uint32_t i = std::max(k, n - k) + 1; i <= n; ++i)
408 {
409 result *= i;
410 }
411
412 for (uint32_t i = 2; i <= std::min(k, n - k); ++i)
413 {
414 result /= i;
415 }
416
417 return result;
418}
419
420double
422{
423 uint32_t d[] = {12, 14, 16, 18, 20, 22, 24, 26, 28};
424 double Bd[] =
425 {33, 281, 2179, 15035LLU, 105166LLU, 692330LLU, 4580007LLU, 29692894LLU, 190453145LLU};
426
427 // double Rc = 1.0 / 2.0;
428 double ebno = std::pow(10.0, sinr / 10.0);
429 double perror = 1.0 / (2.0 + ebno);
430 double P[9];
431
432 if ((mode.GetModType() != UanTxMode::FSK) && (mode.GetConstellationSize() != 13))
433 {
434 NS_FATAL_ERROR("Calculating SINR for unsupported mode type");
435 }
436 if (sinr >= 10)
437 {
438 return 0;
439 }
440 if (sinr <= 6)
441 {
442 return 1;
443 }
444
445 for (uint32_t r = 0; r < 9; r++)
446 {
447 double sumd = 0;
448 for (uint32_t k = 0; k < d[r]; k++)
449 {
450 sumd = sumd + NChooseK(d[r] - 1 + k, k) * std::pow(1 - perror, (double)k);
451 }
452 P[r] = std::pow(perror, (double)d[r]) * sumd;
453 }
454
455 double Pb = 0;
456 for (uint32_t r = 0; r < 8; r++)
457 {
458 Pb = Pb + Bd[r] * P[r];
459 }
460
461 // cout << "Pb = " << Pb << endl;
462 uint32_t bits = pkt->GetSize() * 8;
463
464 double Ppacket = 1;
465 double temp = NChooseK(bits, 0);
466 temp *= std::pow((1 - Pb), (double)bits);
467 Ppacket -= temp;
468 temp = NChooseK(288, 1) * Pb * std::pow((1 - Pb), bits - 1.0);
469 Ppacket -= temp;
470
471 if (Ppacket > 1)
472 {
473 return 1;
474 }
475 else
476 {
477 return Ppacket;
478 }
479}
480
481/*************** UanPhyGen definition *****************/
483 : UanPhy(),
484 m_state(IDLE),
485 m_channel(nullptr),
486 m_transducer(nullptr),
487 m_device(nullptr),
488 m_mac(nullptr),
489 m_txPwrDb(0),
490 m_rxThreshDb(0),
491 m_ccaThreshDb(0),
492 m_pktRx(nullptr),
493 m_pktTx(nullptr),
494 m_cleared(false)
495{
497
499}
500
504
505void
507{
508 if (m_cleared)
509 {
510 return;
511 }
512 m_cleared = true;
513 m_listeners.clear();
514 if (m_channel)
515 {
516 m_channel->Clear();
517 m_channel = nullptr;
518 }
519 if (m_transducer)
520 {
522 m_transducer = nullptr;
523 }
524 if (m_device)
525 {
526 m_device->Clear();
527 m_device = nullptr;
528 }
529 if (m_mac)
530 {
531 m_mac->Clear();
532 m_mac = nullptr;
533 }
534 if (m_per)
535 {
536 m_per->Clear();
537 m_per = nullptr;
538 }
539 if (m_sinr)
540 {
541 m_sinr->Clear();
542 m_sinr = nullptr;
543 }
544 m_pktRx = nullptr;
545}
546
547void
554
557{
558 UanModesList l;
559
560 // micromodem only
561 l.AppendMode(UanTxModeFactory::CreateMode(UanTxMode::FSK, 80, 80, 22000, 4000, 13, "FH-FSK"));
562 l.AppendMode(UanTxModeFactory::CreateMode(UanTxMode::PSK, 200, 200, 22000, 4000, 4, "QPSK"));
563 // micromodem2
564 l.AppendMode(UanTxModeFactory::CreateMode(UanTxMode::PSK, 5000, 5000, 25000, 5000, 4, "QPSK"));
565
566 return l;
567}
568
569TypeId
571{
572 static TypeId tid =
573 TypeId("ns3::UanPhyGen")
574 .SetParent<UanPhy>()
575 .SetGroupName("Uan")
576 .AddConstructor<UanPhyGen>()
577 .AddAttribute("CcaThreshold",
578 "Aggregate energy of incoming signals to move to CCA Busy state dB.",
579 DoubleValue(10),
582 .AddAttribute("RxThreshold",
583 "Required SNR for signal acquisition in dB.",
584 DoubleValue(10),
587 .AddAttribute("TxPower",
588 "Transmission output power in dB.",
589 DoubleValue(190),
592 .AddAttribute("SupportedModes",
593 "List of modes supported by this PHY.",
597 .AddAttribute("PerModel",
598 "Functor to calculate PER based on SINR and TxMode.",
599 StringValue("ns3::UanPhyPerGenDefault"),
602 .AddAttribute("SinrModel",
603 "Functor to calculate SINR based on pkt arrivals and modes.",
604 StringValue("ns3::UanPhyCalcSinrDefault"),
607 .AddTraceSource("RxOk",
608 "A packet was received successfully.",
610 "ns3::UanPhy::TracedCallback")
611 .AddTraceSource("RxError",
612 "A packet was received unsuccessfuly.",
614 "ns3::UanPhy::TracedCallback")
615 .AddTraceSource("Tx",
616 "Packet transmission beginning.",
618 "ns3::UanPhy::TracedCallback");
619 return tid;
620}
621
622void
628
629void
631{
632 NS_LOG_FUNCTION(this);
633
635 {
636 m_energyCallback(state);
637 }
638}
639
640void
642{
643 NS_LOG_FUNCTION(this);
644 NS_LOG_DEBUG("Energy depleted at node " << m_device->GetNode()->GetId()
645 << ", stopping rx/tx activities");
646
649 {
652 m_pktTx = nullptr;
653 }
655 {
658 m_pktRx = nullptr;
659 }
660}
661
662void
664{
665 NS_LOG_FUNCTION(this);
666 NS_LOG_DEBUG("Energy recharged at node " << m_device->GetNode()->GetId()
667 << ", restoring rx/tx activities");
668
669 m_state = IDLE;
670}
671
672void
674{
675 NS_LOG_DEBUG("PHY " << m_mac->GetAddress() << ": Transmitting packet");
676 if (m_state == DISABLED)
677 {
678 NS_LOG_DEBUG("Energy depleted, node cannot transmit any packet. Dropping.");
679 return;
680 }
681
682 if (m_state == TX)
683 {
684 NS_LOG_DEBUG("PHY requested to TX while already Transmitting. Dropping packet.");
685 return;
686 }
687 else if (m_state == SLEEP)
688 {
689 NS_LOG_DEBUG("PHY requested to TX while sleeping. Dropping packet.");
690 return;
691 }
692
693 UanTxMode txMode = GetMode(modeNum);
694
695 if (m_pktRx)
696 {
697 m_minRxSinrDb = -1e30;
698 m_pktRx = nullptr;
699 }
700
701 m_transducer->Transmit(Ptr<UanPhy>(this), pkt, m_txPwrDb, txMode);
702 m_state = TX;
704 double txdelay = pkt->GetSize() * 8.0 / txMode.GetDataRateBps();
705 m_pktTx = pkt;
707 NS_LOG_DEBUG("PHY " << m_mac->GetAddress() << " notifying listeners");
709 m_txLogger(pkt, m_txPwrDb, txMode);
710}
711
712void
714{
715 if (m_state == SLEEP || m_state == DISABLED)
716 {
717 NS_LOG_DEBUG("Transmission ended but node sleeping or dead");
718 return;
719 }
720
721 NS_ASSERT(m_state == TX);
723 {
726 }
727 else
728 {
729 m_state = IDLE;
730 }
732
734}
735
736void
738{
739 m_listeners.push_back(listener);
740}
741
742void
743UanPhyGen::StartRxPacket(Ptr<Packet> pkt, double rxPowerDb, UanTxMode txMode, UanPdp pdp)
744{
745 NS_LOG_DEBUG("PHY " << m_mac->GetAddress() << ": rx power after RX gain = " << rxPowerDb
746 << " dB re uPa");
747
748 switch (m_state)
749 {
750 case DISABLED:
751 NS_LOG_DEBUG("Energy depleted, node cannot receive any packet. Dropping.");
752 NotifyRxDrop(pkt); // traced source netanim
753 return;
754 case TX:
755 NotifyRxDrop(pkt); // traced source netanim
756 NS_ASSERT(false);
757 break;
758 case RX: {
760 double newSinrDb =
762 m_minRxSinrDb = (newSinrDb < m_minRxSinrDb) ? newSinrDb : m_minRxSinrDb;
763 NS_LOG_DEBUG("PHY " << m_mac->GetAddress()
764 << ": Starting RX in RX mode. SINR of pktRx = " << m_minRxSinrDb);
765 NotifyRxBegin(pkt); // traced source netanim
766 }
767 break;
768
769 case CCABUSY:
770 case IDLE: {
772 bool hasmode = false;
773 for (uint32_t i = 0; i < GetNModes(); i++)
774 {
775 if (txMode.GetUid() == GetMode(i).GetUid())
776 {
777 hasmode = true;
778 break;
779 }
780 }
781 if (!hasmode)
782 {
783 break;
784 }
785
786 double newsinr = CalculateSinrDb(pkt, Simulator::Now(), rxPowerDb, txMode, pdp);
787 NS_LOG_DEBUG("PHY " << m_mac->GetAddress()
788 << ": Starting RX in IDLE mode. SINR = " << newsinr);
789 if (newsinr > m_rxThreshDb)
790 {
791 m_state = RX;
793 NotifyRxBegin(pkt); // traced source netanim
794 m_rxRecvPwrDb = rxPowerDb;
795 m_minRxSinrDb = newsinr;
796 m_pktRx = pkt;
798 m_pktRxMode = txMode;
799 m_pktRxPdp = pdp;
800 double txdelay = pkt->GetSize() * 8.0 / txMode.GetDataRateBps();
803 this,
804 pkt,
805 rxPowerDb,
806 txMode);
808 }
809 }
810 break;
811 case SLEEP:
812 NS_LOG_DEBUG("Sleep mode. Dropping packet.");
813 NotifyRxDrop(pkt); // traced source netanim
814 break;
815 }
816
818 {
821 }
822}
823
824void
825UanPhyGen::RxEndEvent(Ptr<Packet> pkt, double /* rxPowerDb */, UanTxMode txMode)
826{
827 if (pkt != m_pktRx)
828 {
829 return;
830 }
831
832 if (m_state == DISABLED || m_state == SLEEP)
833 {
834 NS_LOG_DEBUG("Sleep mode or dead. Dropping packet");
835 m_pktRx = nullptr;
836 NotifyRxDrop(pkt); // traced source netanim
837 return;
838 }
839
840 NotifyRxEnd(pkt); // traced source netanim
842 {
845 }
846 else
847 {
848 m_state = IDLE;
849 }
850
852
853 if (m_pg->GetValue(0, 1) > m_per->CalcPer(m_pktRx, m_minRxSinrDb, txMode))
854 {
855 m_rxOkLogger(pkt, m_minRxSinrDb, txMode);
857 if (!m_recOkCb.IsNull())
858 {
859 m_recOkCb(pkt, m_minRxSinrDb, txMode);
860 }
861 }
862 else
863 {
864 m_rxErrLogger(pkt, m_minRxSinrDb, txMode);
866 if (!m_recErrCb.IsNull())
867 {
869 }
870 }
871
872 m_pktRx = nullptr;
873}
874
875void
880
881void
886
887bool
889{
890 return m_state == SLEEP;
891}
892
893bool
895{
896 return m_state == IDLE;
897}
898
899bool
901{
902 return !IsStateIdle() && !IsStateSleep();
903}
904
905bool
907{
908 return m_state == RX;
909}
910
911bool
913{
914 return m_state == TX;
915}
916
917bool
919{
920 return m_state == CCABUSY;
921}
922
923void
925{
926 m_txPwrDb = txpwr;
927}
928
929void
931{
932 m_rxThreshDb = thresh;
933}
934
935void
937{
938 m_ccaThreshDb = thresh;
939}
940
941double
943{
944 return m_txPwrDb;
945}
946
947double
952
953double
958
961{
962 return m_channel;
963}
964
967{
968 return m_device;
969}
970
976
977void
979{
980 m_channel = channel;
981}
982
983void
985{
986 m_device = device;
987}
988
989void
991{
992 m_mac = mac;
993}
994
995void
1001
1002void
1004{
1005 if (sleep)
1006 {
1007 m_state = SLEEP;
1008 if (!m_energyCallback.IsNull())
1009 {
1011 }
1012 }
1013 else if (m_state == SLEEP)
1014 {
1016 {
1017 m_state = CCABUSY;
1019 }
1020 else
1021 {
1022 m_state = IDLE;
1023 }
1024
1025 if (!m_energyCallback.IsNull())
1026 {
1028 }
1029 }
1030}
1031
1032int64_t
1034{
1035 NS_LOG_FUNCTION(this << stream);
1036 m_pg->SetStream(stream);
1037 return 1;
1038}
1039
1040void
1042 double /* txPowerDb */,
1043 UanTxMode /* txMode */)
1044{
1045 if (m_pktRx)
1046 {
1047 m_minRxSinrDb = -1e30;
1048 }
1049}
1050
1051void
1060
1061double
1063 Time arrTime,
1064 double rxPowerDb,
1065 UanTxMode mode,
1066 UanPdp pdp)
1067{
1068 double noiseDb = m_channel->GetNoiseDbHz((double)mode.GetCenterFreqHz() / 1000.0) +
1069 10 * std::log10(mode.GetBandwidthHz());
1070 return m_sinr
1071 ->CalcSinrDb(pkt, arrTime, rxPowerDb, noiseDb, mode, pdp, m_transducer->GetArrivalList());
1072}
1073
1074double
1076{
1078
1079 auto it = arrivalList.begin();
1080
1081 double interfPower = 0;
1082
1083 for (; it != arrivalList.end(); it++)
1084 {
1085 if (pkt != it->GetPacket())
1086 {
1087 interfPower += DbToKp(it->GetRxPowerDb());
1088 }
1089 }
1090
1091 return KpToDb(interfPower);
1092}
1093
1094double
1096{
1097 return std::pow(10, db / 10.0);
1098}
1099
1100double
1102{
1103 return 10 * std::log10(kp);
1104}
1105
1106void
1108{
1109 auto it = m_listeners.begin();
1110 for (; it != m_listeners.end(); it++)
1111 {
1112 (*it)->NotifyRxStart();
1113 }
1114}
1115
1116void
1118{
1119 auto it = m_listeners.begin();
1120 for (; it != m_listeners.end(); it++)
1121 {
1122 (*it)->NotifyRxEndOk();
1123 }
1124}
1125
1126void
1128{
1129 auto it = m_listeners.begin();
1130 for (; it != m_listeners.end(); it++)
1131 {
1132 (*it)->NotifyRxEndError();
1133 }
1134}
1135
1136void
1138{
1139 auto it = m_listeners.begin();
1140 for (; it != m_listeners.end(); it++)
1141 {
1142 (*it)->NotifyCcaStart();
1143 }
1144}
1145
1146void
1148{
1149 auto it = m_listeners.begin();
1150 for (; it != m_listeners.end(); it++)
1151 {
1152 (*it)->NotifyCcaEnd();
1153 }
1154}
1155
1156void
1158{
1159 auto it = m_listeners.begin();
1160 for (; it != m_listeners.end(); it++)
1161 {
1162 (*it)->NotifyTxStart(duration);
1163 }
1164}
1165
1166void
1168{
1169 auto it = m_listeners.begin();
1170 for (; it != m_listeners.end(); it++)
1171 {
1172 (*it)->NotifyTxEnd();
1173 }
1174}
1175
1178{
1179 return m_modes.GetNModes();
1180}
1181
1184{
1186
1187 return m_modes[n];
1188}
1189
1192{
1193 return m_pktRx;
1194}
1195
1196} // namespace ns3
void Nullify()
Discard the implementation, set it to null.
Definition callback.h:561
bool IsNull() const
Check for null implementation.
Definition callback.h:555
This class can be used to hold variables of floating point type such as 'double' or 'float'.
Definition double.h:31
bool IsPending() const
This method is syntactic sugar for !IsExpired().
Definition event-id.cc:65
uint32_t GetId() const
Definition node.cc:106
virtual void DoDispose()
Destructor implementation.
Definition object.cc:433
Smart pointer class similar to boost::intrusive_ptr.
static EventId Schedule(const Time &delay, FUNC f, Ts &&... args)
Schedule an event to expire after delay.
Definition simulator.h:560
static void Cancel(const EventId &id)
Set the cancel bit on this event: the event's associated function will not be invoked when it expires...
Definition simulator.cc:274
static Time Now()
Return the current simulation virtual time.
Definition simulator.cc:197
Hold variables of type string.
Definition string.h:45
Time GetDelay() const
Get the delay time, usually from first arrival of signal.
Simulation virtual time values and global simulation resolution.
Definition nstime.h:94
a unique identifier for an interface.
Definition type-id.h:48
TypeId SetParent(TypeId tid)
Set the parent TypeId.
Definition type-id.cc:1001
Container for UanTxModes.
uint32_t GetNModes() const
Get the number of modes in this list.
void AppendMode(UanTxMode mode)
Add mode to this list.
void Clear()
Clear all pointer references.
Ptr< Node > GetNode() const override
The power delay profile returned by propagation models.
Iterator GetEnd() const
Get the end of the tap list (one beyond the last entry).
double SumTapsFromMaxNc(Time delay, Time duration) const
Compute the non-coherent sum of tap amplitudes starting after a delay from the maximum amplitude for ...
double SumTapsNc(Time begin, Time end) const
Compute the non-coherent sum of tap amplitudes between a start and end time.
const Tap & GetTap(uint32_t i) const
Get the Tap at the specified delay index.
Iterator GetBegin() const
Get the beginning of the tap vector.
Default SINR calculator for UanPhyGen.
double CalcSinrDb(Ptr< Packet > pkt, Time arrTime, double rxPowerDb, double ambNoiseDb, UanTxMode mode, UanPdp pdp, const UanTransducer::ArrivalList &arrivalList) const override
Calculate the SINR value for a packet.
UanPhyCalcSinrDefault()
Constructor.
static TypeId GetTypeId()
Register this type.
~UanPhyCalcSinrDefault() override
Destructor.
WHOI Micromodem like FH-FSK model.
UanPhyCalcSinrFhFsk()
Constructor.
double CalcSinrDb(Ptr< Packet > pkt, Time arrTime, double rxPowerDb, double ambNoiseDb, UanTxMode mode, UanPdp pdp, const UanTransducer::ArrivalList &arrivalList) const override
Calculate the SINR value for a packet.
static TypeId GetTypeId()
Register this type.
~UanPhyCalcSinrFhFsk() override
Destructor.
uint32_t m_hops
Number of hops.
Class used for calculating SINR of packet in UanPhy.
Definition uan-phy.h:33
double DbToKp(double db) const
Convert dB re 1 uPa to kilopascals.
Definition uan-phy.h:69
double KpToDb(double kp) const
Convert kilopascals to dB re 1 uPa.
Definition uan-phy.h:80
Generic PHY model.
Ptr< UanChannel > GetChannel() const override
Get the attached channel.
bool IsStateSleep() override
void SetTxPowerDb(double txpwr) override
Set the transmit power.
double KpToDb(double kp)
Convert kilopascals to dB.
void NotifyTransStartTx(Ptr< Packet > packet, double txPowerDb, UanTxMode txMode) override
Called when a transmission is beginning on the attached transducer.
int64_t AssignStreams(int64_t stream) override
Assign a fixed random variable stream number to the random variables used by this model.
Ptr< UanPhyPer > m_per
Error model.
UanPhyGen()
Constructor.
void SetRxThresholdDb(double thresh) override
Set the minimum SINR threshold to receive a packet without errors.
void EnergyDepletionHandler() override
Handle the energy depletion event.
void NotifyListenersTxStart(Time duration)
Call UanListener::NotifyTxStart on all listeners.
Time m_pktRxArrTime
Packet arrival time.
UanTxMode GetMode(uint32_t n) override
Get a specific transmission mode.
void UpdatePowerConsumption(const State state)
Update energy source with new state.
void SetEnergyModelCallback(energy::DeviceEnergyModel::ChangeStateCallback cb) override
Set the DeviceEnergyModel callback for UanPhy device.
double GetRxThresholdDb() override
Get the minimum received signal strength required to receive a packet without errors.
ListenerList m_listeners
List of listeners.
void NotifyListenersCcaStart()
Call UanListener::NotifyCcaStart on all listeners.
void SetSleepMode(bool sleep) override
Set the Phy SLEEP mode.
~UanPhyGen() override
Dummy destructor, see DoDispose.
double m_rxRecvPwrDb
Receiver power.
bool IsStateBusy() override
void NotifyListenersRxGood()
Call UanListener::NotifyRxEndOk on all listeners.
uint32_t GetNModes() override
Get the number of transmission modes supported by this Phy.
Ptr< UanPhyCalcSinr > m_sinr
SINR calculator.
void NotifyListenersRxBad()
Call UanListener::NotifyRxEndError on all listeners.
double GetCcaThresholdDb() override
Get the CCA threshold signal strength required to detect channel busy.
Ptr< Packet > m_pktRx
Received packet.
void SetReceiveErrorCallback(RxErrCallback cb) override
Set the callback to be used when a packet is received with errors.
Ptr< UanTransducer > GetTransducer() override
Get the attached transducer.
Ptr< UanTransducer > m_transducer
Associated transducer.
double m_rxThreshDb
Receive SINR threshold.
EventId m_rxEndEvent
Rx event.
void DoDispose() override
Destructor implementation.
double m_ccaThreshDb
CCA busy threshold.
void SetTransducer(Ptr< UanTransducer > trans) override
Attach a transducer to this Phy.
RxOkCallback m_recOkCb
Callback for packets received without error.
State m_state
Phy state.
void NotifyListenersTxEnd()
Call UanListener::NotifyTxEnd on all listeners.
Ptr< UanMac > m_mac
MAC layer.
Ptr< UanNetDevice > GetDevice() const override
Get the device hosting this Phy.
double GetInterferenceDb(Ptr< Packet > pkt)
Calculate interference power from overlapping packet arrivals, in dB.
double m_txPwrDb
Transmit power.
double CalculateSinrDb(Ptr< Packet > pkt, Time arrTime, double rxPowerDb, UanTxMode mode, UanPdp pdp)
Calculate the SINR value for a packet.
void SetReceiveOkCallback(RxOkCallback cb) override
Set the callback to be used when a packet is received without error.
static UanModesList GetDefaultModes()
Get the default transmission modes.
bool IsStateTx() override
ns3::TracedCallback< Ptr< const Packet >, double, UanTxMode > m_rxOkLogger
A packet destined for this Phy was received without error.
Ptr< UniformRandomVariable > m_pg
Provides uniform random variables.
EventId m_txEndEvent
Tx event.
void SendPacket(Ptr< Packet > pkt, uint32_t modeNum) override
Send a packet using a specific transmission mode.
void RegisterListener(UanPhyListener *listener) override
Register a UanPhyListener to be notified of common UanPhy events.
bool m_cleared
Flag when we've been cleared.
bool IsStateRx() override
void SetMac(Ptr< UanMac > mac) override
Set the MAC forwarding messages to this Phy.
double m_minRxSinrDb
Minimum receive SINR during packet reception.
static TypeId GetTypeId()
Register this type.
energy::DeviceEnergyModel::ChangeStateCallback m_energyCallback
Energy model callback.
void SetCcaThresholdDb(double thresh) override
Set the threshold for detecting channel busy.
Ptr< UanChannel > m_channel
Attached channel.
bool IsStateCcaBusy() override
void SetDevice(Ptr< UanNetDevice > device) override
Set the device hosting this Phy.
double DbToKp(double db)
Convert dB to kilopascals.
UanTxMode m_pktRxMode
Packet transmission mode at receiver.
void TxEndEvent()
Event to process end of packet transmission.
void Clear() override
Clear all pointer references.
Ptr< Packet > GetPacketRx() const override
Get the packet currently being received.
RxErrCallback m_recErrCb
Callback for packets received with errors.
void RxEndEvent(Ptr< Packet > pkt, double rxPowerDb, UanTxMode txMode)
Event to process end of packet reception.
Ptr< UanNetDevice > m_device
Device hosting this Phy.
void StartRxPacket(Ptr< Packet > pkt, double rxPowerDb, UanTxMode txMode, UanPdp pdp) override
Packet arriving from channel: i.e.
Ptr< Packet > m_pktTx
Sent packet.
void SetChannel(Ptr< UanChannel > channel) override
Attach to a channel.
ns3::TracedCallback< Ptr< const Packet >, double, UanTxMode > m_txLogger
A packet was sent from this Phy.
void NotifyIntChange() override
Called when there has been a change in the amount of interference this node is experiencing from othe...
double GetTxPowerDb() override
Get the current transmit power, in dB.
bool IsStateIdle() override
UanPdp m_pktRxPdp
Power delay profile of packet.
void NotifyListenersCcaEnd()
Call UanListener::NotifyCcaEnd on all listeners.
void EnergyRechargeHandler() override
Handle the energy recharge event.
void NotifyListenersRxStart()
Call UanListener::NotifyRxStart on all listeners.
ns3::TracedCallback< Ptr< const Packet >, double, UanTxMode > m_rxErrLogger
A packet destined for this Phy was received with error.
UanModesList m_modes
List of modes supported by this PHY.
Base class for UAN Phy models.
Definition uan-phy.h:167
void NotifyTxDrop(Ptr< const Packet > packet)
Called when the transducer attempts to transmit a new packet while already transmitting a prior packe...
Definition uan-phy.cc:111
void NotifyRxDrop(Ptr< const Packet > packet)
Called when the Phy drops a packet.
Definition uan-phy.cc:129
void NotifyRxBegin(Ptr< const Packet > packet)
Called when the Phy begins to receive a packet.
Definition uan-phy.cc:117
void NotifyRxEnd(Ptr< const Packet > packet)
Called when a packet is received without error.
Definition uan-phy.cc:123
State
Enum defining possible Phy states.
Definition uan-phy.h:171
@ RX
Receiving.
Definition uan-phy.h:174
@ SLEEP
Sleeping.
Definition uan-phy.h:176
@ IDLE
Idle state.
Definition uan-phy.h:172
@ DISABLED
Disabled.
Definition uan-phy.h:177
@ TX
Transmitting.
Definition uan-phy.h:175
@ CCABUSY
Channel busy.
Definition uan-phy.h:173
Interface for PHY event listener.
Definition uan-phy.h:134
Packet error rate calculation for common tx modes based on UanPhyPerUmodem.
~UanPhyPerCommonModes() override
Destructor.
double CalcPer(Ptr< Packet > pkt, double sinrDb, UanTxMode mode) override
Calculate the Packet ERror probability based on SINR at the receiver and a tx mode.
UanPhyPerCommonModes()
Constructor.
static TypeId GetTypeId()
Register this type.
Default Packet Error Rate calculator for UanPhyGen.
Definition uan-phy-gen.h:35
UanPhyPerGenDefault()
Constructor.
~UanPhyPerGenDefault() override
Destructor.
double CalcPer(Ptr< Packet > pkt, double sinrDb, UanTxMode mode) override
Calculate the packet error probability based on SINR at the receiver and a tx mode.
static TypeId GetTypeId()
Register this type.
double m_thresh
SINR threshold.
Definition uan-phy-gen.h:51
Calculate packet error probability, based on received SINR and modulation (mode).
Definition uan-phy.h:99
Packet error rate calculation assuming WHOI Micromodem-like PHY (FH-FSK)
Definition uan-phy-gen.h:65
double CalcPer(Ptr< Packet > pkt, double sinrDb, UanTxMode mode) override
Calculate the packet error probability based on SINR at the receiver and a tx mode.
static TypeId GetTypeId()
Register this type.
double NChooseK(uint32_t n, uint32_t k)
Binomial coefficient.
UanPhyPerUmodem()
Constructor.
~UanPhyPerUmodem() override
Destructor.
virtual void AddPhy(Ptr< UanPhy > phy)=0
Attach a physical network layer above this transducer.
virtual const ArrivalList & GetArrivalList() const =0
Get the list of overlapped (in time) packets at this transducer.
std::list< UanPacketArrival > ArrivalList
List of arriving packets overlapping in time.
virtual void Transmit(Ptr< UanPhy > src, Ptr< Packet > packet, double txPowerDb, UanTxMode txMode)=0
Transmit a packet from this transducer.
virtual void Clear()=0
Clears all pointer references.
static UanTxMode CreateMode(UanTxMode::ModulationType type, uint32_t dataRateBps, uint32_t phyRateSps, uint32_t cfHz, uint32_t bwHz, uint32_t constSize, std::string name)
Abstraction of packet modulation information.
Definition uan-tx-mode.h:32
uint32_t GetUid() const
Get a unique id for the mode.
@ QAM
Quadrature amplitude modulation.
Definition uan-tx-mode.h:43
@ OTHER
Unspecified/undefined.
Definition uan-tx-mode.h:45
@ PSK
Phase shift keying.
Definition uan-tx-mode.h:42
@ FSK
Frequency shift keying.
Definition uan-tx-mode.h:44
uint32_t GetConstellationSize() const
Get the number of constellation points in the modulation scheme.
uint32_t GetPhyRateSps() const
Get the physical signaling rate.
uint32_t GetDataRateBps() const
Get the data rate of the transmit mode.
uint32_t GetBandwidthHz() const
Get the transmission signal bandwidth.
ModulationType GetModType() const
Get the modulation type of the mode.
uint32_t GetCenterFreqHz() const
Get the transmission center frequency.
Hold an unsigned integer type.
Definition uinteger.h:34
#define NS_ASSERT(condition)
At runtime, in debugging builds, if this condition is not true, the program prints the source file,...
Definition assert.h:55
Ptr< const AttributeAccessor > MakePointerAccessor(T1 a1)
Create an AttributeAccessor for a class data member, or a lone class get functor or set method.
Definition pointer.h:248
Ptr< AttributeChecker > MakePointerChecker()
Create a PointerChecker for a type.
Definition pointer.h:269
#define NS_FATAL_ERROR(msg)
Report a fatal error with a message and terminate.
int64x64_t Abs(const int64x64_t &value)
Absolute value.
Definition int64x64.h:203
#define NS_LOG_COMPONENT_DEFINE(name)
Define a Log component with a specific name.
Definition log.h:191
#define NS_LOG_DEBUG(msg)
Use NS_LOG to output a message of level LOG_DEBUG.
Definition log.h:257
#define NS_LOG_FUNCTION(parameters)
If log level LOG_FUNCTION is enabled, this macro will output all input parameters separated by ",...
#define NS_LOG_WARN(msg)
Use NS_LOG to output a message of level LOG_WARN.
Definition log.h:250
Ptr< T > CreateObject(Args &&... args)
Create an object by type, with varying number of constructor parameters.
Definition object.h:619
#define NS_OBJECT_ENSURE_REGISTERED(type)
Register an Object subclass with the TypeId system.
Definition object-base.h:35
Time Seconds(double value)
Construct a Time in the indicated unit.
Definition nstime.h:1308
Ptr< const TraceSourceAccessor > MakeTraceSourceAccessor(T a)
Create a TraceSourceAccessor which will control access to the underlying trace source.
Every class exported by the ns3 library is enclosed in the ns3 namespace.
Ptr< const AttributeChecker > MakeUanModesListChecker()
Time Rem(const Time &lhs, const Time &rhs)
Remainder (modulus) from the quotient of two Times.
Definition nstime.h:1115
Ptr< const AttributeChecker > MakeUintegerChecker()
Definition uinteger.h:85
Ptr< const AttributeAccessor > MakeUintegerAccessor(T1 a1)
Definition uinteger.h:35
Ptr< const AttributeChecker > MakeDoubleChecker()
Definition double.h:82
Ptr< const AttributeAccessor > MakeUanModesListAccessor(T1 a1)
Ptr< const AttributeAccessor > MakeDoubleAccessor(T1 a1)
Definition double.h:32
@ IDLE
Channel is IDLE, no packet is being transmitted.