A Discrete-Event Network Simulator
API
Loading...
Searching...
No Matches
lr-wpan-phy.cc
Go to the documentation of this file.
1/*
2 * Copyright (c) 2011 The Boeing Company
3 *
4 * SPDX-License-Identifier: GPL-2.0-only
5 *
6 * Author:
7 * Gary Pei <guangyu.pei@boeing.com>
8 * Sascha Alexander Jopen <jopen@cs.uni-bonn.de>
9 */
10#include "lr-wpan-phy.h"
11
12#include "lr-wpan-constants.h"
13#include "lr-wpan-error-model.h"
14#include "lr-wpan-lqi-tag.h"
15#include "lr-wpan-net-device.h"
18
19#include <ns3/abort.h>
20#include <ns3/antenna-model.h>
21#include <ns3/double.h>
22#include <ns3/error-model.h>
23#include <ns3/log.h>
24#include <ns3/mobility-model.h>
25#include <ns3/net-device.h>
26#include <ns3/node.h>
27#include <ns3/packet-burst.h>
28#include <ns3/packet.h>
29#include <ns3/pointer.h>
30#include <ns3/random-variable-stream.h>
31#include <ns3/simulator.h>
32#include <ns3/spectrum-channel.h>
33#include <ns3/spectrum-value.h>
34
35namespace ns3
36{
37namespace lrwpan
38{
39
40NS_LOG_COMPONENT_DEFINE("LrWpanPhy");
42
43/**
44 * The data and symbol rates for the different PHY options.
45 * See Table 1 in section 6.1.1 IEEE 802.15.4-2006, IEEE 802.15.4c-2009, IEEE 802.15.4d-2009.
46 * Bit rate is in kbit/s. Symbol rate is in ksymbol/s.
47 * The index follows LrWpanPhyOption (kb/s and ksymbol/s)
48 */
50 {20.0, 20.0},
51 {40.0, 40.0},
52 {20.0, 20.0},
53 {250.0, 12.5},
54 {250.0, 50.0},
55 {250.0, 62.5},
56 {100.0, 25.0},
57 {250.0, 62.5},
58 {250.0, 62.5},
59};
60
61/**
62 * The preamble, SFD, and PHR lengths in symbols for the different PHY options.
63 * See Table 19 and Table 20 in section 6.3 IEEE 802.15.4-2006, IEEE 802.15.4c-2009, IEEE
64 * 802.15.4d-2009.
65 * The PHR is 1 octet and it follows phySymbolsPerOctet in Table 23.
66 * The index follows LrWpanPhyOption.
67 */
69 {32.0, 8.0, 8.0},
70 {32.0, 8.0, 8.0},
71 {32.0, 8.0, 8.0},
72 {2.0, 1.0, 0.4},
73 {6.0, 1.0, 1.6},
74 {8.0, 2.0, 2.0},
75 {8.0, 2.0, 2.0},
76 {8.0, 2.0, 2.0},
77 {8.0, 2.0, 2.0},
78};
79
80std::ostream&
81operator<<(std::ostream& os, const PhyEnumeration& state)
82{
83 switch (state)
84 {
86 os << "BUSY";
87 break;
89 os << "BUSY_RX";
90 break;
92 os << "BUSY_TX";
93 break;
95 os << "FORCE_TRX_OFF";
96 break;
98 os << "IDLE";
99 break;
101 os << "INVALID_PARAMETER";
102 break;
104 os << "RX_ON";
105 break;
107 os << "SUCCESS";
108 break;
110 os << "TRX_OFF";
111 break;
113 os << "TX_ON";
114 break;
116 os << "UNSUPPORTED";
117 break;
119 os << "READ_ONLY";
120 break;
122 os << "UNSPECIFIED";
123 break;
124 }
125 return os;
126};
127
128std::ostream&
129operator<<(std::ostream& os, const TracedValue<PhyEnumeration>& state)
130{
131 PhyEnumeration s = state;
132 return os << s;
133};
134
135TypeId
137{
138 static TypeId tid =
139 TypeId("ns3::lrwpan::LrWpanPhy")
140 .AddDeprecatedName("ns3::LrWpanPhy")
142 .SetGroupName("LrWpan")
143 .AddConstructor<LrWpanPhy>()
144 .AddAttribute("PostReceptionErrorModel",
145 "An optional packet error model can be added to the receive "
146 "packet process after any propagation-based (SNR-based) error "
147 "models have been applied. Typically this is used to force "
148 "specific packet drops, for testing purposes.",
149 PointerValue(),
152 .AddTraceSource("TrxStateValue",
153 "The state of the transceiver",
155 "ns3::TracedValueCallback::LrWpanPhyEnumeration")
156 .AddTraceSource("TrxState",
157 "The state of the transceiver",
159 "ns3::lrwpan::LrWpanPhy::StateTracedCallback")
160 .AddTraceSource("PhyTxBegin",
161 "Trace source indicating a packet has "
162 "begun transmitting over the channel medium",
164 "ns3::Packet::TracedCallback")
165 .AddTraceSource("PhyTxEnd",
166 "Trace source indicating a packet has been "
167 "completely transmitted over the channel.",
169 "ns3::Packet::TracedCallback")
170 .AddTraceSource("PhyTxDrop",
171 "Trace source indicating a packet has been "
172 "dropped by the device during transmission",
174 "ns3::Packet::TracedCallback")
175 .AddTraceSource("PhyRxBegin",
176 "Trace source indicating a packet has begun "
177 "being received from the channel medium by the device",
179 "ns3::Packet::TracedCallback")
180 .AddTraceSource("PhyRxEnd",
181 "Trace source indicating a packet has been "
182 "completely received from the channel medium "
183 "by the device",
185 "ns3::Packet::SinrTracedCallback")
186 .AddTraceSource("PhyRxDrop",
187 "Trace source indicating a packet has been "
188 "dropped by the device during reception",
190 "ns3::Packet::TracedCallback");
191 return tid;
192}
193
195 : m_edRequest(),
196 m_setTRXState()
197{
200
201 // default PHY PIB attributes
204
206
208 m_random->SetAttribute("Min", DoubleValue(0.0));
209 m_random->SetAttribute("Max", DoubleValue(1.0));
210
211 m_isRxCanceled = false;
213}
214
218
219void
221{
222 NS_LOG_FUNCTION(this);
223
224 // This method ensures that the local mobility model pointer holds
225 // a pointer to the Node's aggregated mobility model (if one exists)
226 // in the case that the user has not directly called SetMobility()
227 // on this LrWpanPhy during simulation setup. If the mobility model
228 // needs to be added or changed during simulation runtime, users must
229 // call SetMobility() on this object.
230
231 if (!m_mobility)
232 {
234 "Either install a MobilityModel on this object or ensure that this "
235 "object is part of a Node and NetDevice");
236 m_mobility = m_device->GetNode()->GetObject<MobilityModel>();
237 if (!m_mobility)
238 {
239 NS_LOG_WARN("Mobility not found, propagation models might not work properly");
240 }
241 }
242}
243
244void
284
287{
288 return m_device;
289}
290
293{
294 return m_mobility;
295}
296
297void
299{
300 NS_LOG_FUNCTION(this << d);
301 m_device = d;
302}
303
304void
310
311void
317
320{
321 NS_LOG_FUNCTION(this);
322 return m_channel;
323}
324
327{
328 NS_LOG_FUNCTION(this);
329 if (m_txPsd)
330 {
331 return m_txPsd->GetSpectrumModel();
332 }
333 else
334 {
335 return nullptr;
336 }
337}
338
341{
342 return m_antenna;
343}
344
345void
351
352void
354{
355 NS_LOG_FUNCTION(this << spectrumRxParams);
356
357 if (!m_edRequest.IsExpired())
358 {
359 // Update the average receive power during ED.
360 Time now = Simulator::Now();
365 m_edPower.lastUpdate = now;
366 }
367
370
371 if (!lrWpanRxParams)
372 {
374 m_signal->AddSignal(spectrumRxParams->psd);
375
376 // Update peak power if CCA is in progress.
377 if (!m_ccaRequest.IsExpired())
378 {
379 double power =
382 if (m_ccaPeakPower < power)
383 {
384 m_ccaPeakPower = power;
385 }
386 }
387
388 Simulator::Schedule(spectrumRxParams->duration, &LrWpanPhy::EndRx, this, spectrumRxParams);
389 return;
390 }
391
392 Ptr<Packet> p = (lrWpanRxParams->packetBurst->GetPackets()).front();
393 NS_ASSERT(p);
394
395 // Prevent PHY from receiving another packet while switching the transceiver state.
397 {
398 // The specification doesn't seem to refer to BUSY_RX, but vendor
399 // data sheets suggest that this is a substate of the RX_ON state
400 // that is entered after preamble detection when the digital receiver
401 // is enabled. Here, for now, we use BUSY_RX to mark the period between
402 // StartRx() and EndRx() states.
403
404 // We are going to BUSY_RX state when receiving the first bit of an SHR,
405 // as opposed to real receivers, which should go to this state only after
406 // successfully receiving the SHR.
407
408 // If synchronizing to the packet is possible, change to BUSY_RX state,
409 // otherwise drop the packet and stay in RX state. The actual synchronization
410 // is not modeled.
411
412 // Add any incoming packet to the current interference before checking the
413 // SINR.
414 NS_LOG_DEBUG(this << " receiving packet with power: "
416 lrWpanRxParams->psd,
418 30
419 << "dBm");
420 m_signal->AddSignal(lrWpanRxParams->psd);
421 Ptr<SpectrumValue> interferenceAndNoise = m_signal->GetSignalPsd();
422 *interferenceAndNoise -= *lrWpanRxParams->psd;
423 *interferenceAndNoise += *m_noise;
424 double sinr =
427 LrWpanSpectrumValueHelper::TotalAvgPower(interferenceAndNoise,
429
430 // Std. 802.15.4-2006, appendix E, Figure E.2
431 // At SNR < -5 the BER is less than 10e-1.
432 // It's useless to even *try* to decode the packet.
433 if (10 * log10(sinr) > -5)
434 {
436 m_currentRxPacket = std::make_pair(lrWpanRxParams, false);
438
440 }
441 else
442 {
444 }
445 }
447 {
448 // Drop the new packet.
449 NS_LOG_DEBUG(this << " packet collision");
451
452 // Check if we correctly received the old packet up to now.
454
455 // Add the incoming packet to the current interference after we have
456 // checked for successful reception of the current packet for the time
457 // before the additional interference.
458 m_signal->AddSignal(lrWpanRxParams->psd);
459 }
460 else
461 {
462 // Simply drop the packet.
463 NS_LOG_DEBUG(this << " transceiver not in RX state");
465
466 // Add the signal power to the interference, anyway.
467 m_signal->AddSignal(lrWpanRxParams->psd);
468 }
469
470 // Update peak power if CCA is in progress.
471 if (!m_ccaRequest.IsExpired())
472 {
473 double power =
476 if (m_ccaPeakPower < power)
477 {
478 m_ccaPeakPower = power;
479 }
480 }
481
482 // Always call EndRx to update the interference.
483 // We keep track of this event, and if necessary cancel this event when a TX of a packet.
484
485 Simulator::Schedule(spectrumRxParams->duration, &LrWpanPhy::EndRx, this, spectrumRxParams);
486}
487
488void
490{
491 // Calculate whether packet was lost.
494
495 // We are currently receiving a packet.
497 {
498 // NS_ASSERT (currentRxParams && !m_currentRxPacket.second);
499
500 Ptr<Packet> currentPacket = currentRxParams->packetBurst->GetPackets().front();
501 if (m_errorModel)
502 {
503 // How many bits did we receive since the last calculation?
504 double t = (Simulator::Now() - m_rxLastUpdate).ToDouble(Time::MS);
505 uint32_t chunkSize = ceil(t * (GetDataOrSymbolRate(true) / 1000));
506 Ptr<SpectrumValue> interferenceAndNoise = m_signal->GetSignalPsd();
507 *interferenceAndNoise -= *currentRxParams->psd;
508 *interferenceAndNoise += *m_noise;
509 double sinr =
510 LrWpanSpectrumValueHelper::TotalAvgPower(currentRxParams->psd,
512 LrWpanSpectrumValueHelper::TotalAvgPower(interferenceAndNoise,
514 double per = 1.0 - m_errorModel->GetChunkSuccessRate(sinr, chunkSize);
515
516 // The LQI is the total packet success rate scaled to 0-255.
517 // If not already set, initialize to 255.
518 LrWpanLqiTag tag(std::numeric_limits<uint8_t>::max());
519 currentPacket->PeekPacketTag(tag);
520 uint8_t lqi = tag.Get();
521 tag.Set(lqi - (per * lqi));
522 currentPacket->ReplacePacketTag(tag);
523
524 if (m_random->GetValue() < per)
525 {
526 // The packet was destroyed, drop the packet after reception.
527 m_currentRxPacket.second = true;
528 }
529 }
530 else
531 {
532 NS_LOG_WARN("Missing ErrorModel");
533 }
534 }
536}
537
538void
540{
541 NS_LOG_FUNCTION(this);
542
544
545 if (!m_edRequest.IsExpired())
546 {
547 // Update the average receive power during ED.
548 Time now = Simulator::Now();
553 m_edPower.lastUpdate = now;
554 }
555
557 if (currentRxParams == params)
558 {
560 }
561
562 // Update the interference.
563 m_signal->RemoveSignal(par->psd);
564
565 if (!params)
566 {
567 NS_LOG_LOGIC("Node: " << m_device->GetAddress()
568 << " Removing interferent: " << *(par->psd));
569 return;
570 }
571
572 // If this is the end of the currently received packet, check if reception was successful.
573 if (currentRxParams == params)
574 {
575 Ptr<Packet> currentPacket = currentRxParams->packetBurst->GetPackets().front();
576 NS_ASSERT(currentPacket);
577
579 m_postReceptionErrorModel->IsCorrupt(currentPacket->Copy()))
580 {
581 NS_LOG_DEBUG("Reception failed due to post-rx error model");
582 m_currentRxPacket.second = true;
583 }
584
585 // If there is no error model attached to the PHY, we always report the maximum LQI value.
586 LrWpanLqiTag tag(std::numeric_limits<uint8_t>::max());
587 currentPacket->PeekPacketTag(tag);
588 m_phyRxEndTrace(currentPacket, tag.Get());
589
590 if (!m_currentRxPacket.second)
591 {
592 m_currentRxPacket = std::make_pair(nullptr, true);
594 NS_LOG_DEBUG("Packet successfully received");
595
596 // The packet was successfully received, push it up the stack.
598 {
599 m_pdDataIndicationCallback(currentPacket->GetSize(), currentPacket, tag.Get());
600 }
601 }
602 else
603 {
604 // The packet was destroyed due to interference, post-rx corruption or
605 // cancelled, therefore drop it.
606 m_phyRxDropTrace(currentPacket);
607 m_currentRxPacket = std::make_pair(nullptr, true);
608
609 if (!m_isRxCanceled)
610 {
612 }
613 else
614 {
615 // The state of The PHY was already changed when the packet was canceled
616 // due to a forced operation.
617 m_isRxCanceled = false;
618 }
619 }
620 }
621}
622
623void
625{
626 NS_LOG_FUNCTION(this << psduLength << p);
627
628 if (psduLength > lrwpan::aMaxPhyPacketSize)
629 {
631 {
633 }
634 NS_LOG_DEBUG("Drop packet because psduLength too long: " << psduLength);
635 return;
636 }
637
638 // Prevent PHY from sending a packet while switching the transceiver state.
640 {
642 {
643 // send down
645
646 // Remove a possible LQI tag from a previous transmission of the packet.
647 LrWpanLqiTag lqiTag;
648 p->RemovePacketTag(lqiTag);
649
651 m_currentTxPacket.first = p;
652 m_currentTxPacket.second = false;
653
655 txParams->duration = CalculateTxTime(p);
656 txParams->txPhy = GetObject<SpectrumPhy>();
657 txParams->psd = m_txPsd;
658 txParams->txAntenna = m_antenna;
660 pb->AddPacket(p);
661 txParams->packetBurst = pb;
662 m_channel->StartTx(txParams);
663 m_pdDataRequest = Simulator::Schedule(txParams->duration, &LrWpanPhy::EndTx, this);
665 return;
666 }
667 else if ((m_trxState == IEEE_802_15_4_PHY_RX_ON) ||
670 {
672 {
674 }
675 // Drop packet, hit PhyTxDrop trace
677 return;
678 }
679 else
680 {
681 NS_FATAL_ERROR("This should be unreachable, or else state "
682 << m_trxState << " should be added as a case");
683 }
684 }
685 else
686 {
687 // TODO: This error code is not covered by the standard.
688 // What is the correct behavior in this case?
690 {
692 }
693 // Drop packet, hit PhyTxDrop trace
695 return;
696 }
697}
698
699void
701{
702 NS_LOG_FUNCTION(this);
703
705 {
706 m_ccaPeakPower = 0.0;
707 Time ccaTime = Seconds(8.0 / GetDataOrSymbolRate(false));
709 }
710 else
711 {
713 {
715 {
717 }
718 else
719 {
721 }
722 }
723 }
724}
725
726void
732
733void
735{
736 NS_LOG_FUNCTION(this);
738 {
739 // Average over the powers of all signals received until EndEd()
744 }
745 else
746 {
747 PhyEnumeration result = m_trxState;
749 {
751 }
752
754 {
755 m_plmeEdConfirmCallback(result, 0);
756 }
757 }
758}
759
760void
762{
763 NS_LOG_FUNCTION(this << id);
766
767 switch (id)
768 {
770 attributes->phyCurrentChannel = m_phyPIBAttributes.phyCurrentChannel;
771 break;
772 case phyCurrentPage:
773 attributes->phyCurrentPage = m_phyPIBAttributes.phyCurrentPage;
774 break;
775 case phySHRDuration:
776 attributes->phySHRDuration = GetPhySHRDuration();
777 break;
779 attributes->phySymbolsPerOctet = GetPhySymbolsPerOctet();
780 break;
781 default:
783 break;
784 }
785
787 {
788 m_plmeGetAttributeConfirmCallback(status, id, attributes);
789 }
790}
791
792// Section 6.2.2.7.3
793void
795{
796 NS_LOG_FUNCTION(this << state);
797
798 // Check valid states (Table 14)
801
802 NS_LOG_LOGIC("Trying to set m_trxState from " << m_trxState << " to " << state);
803
804 // this method always overrides previous state setting attempts
806 {
807 if (m_trxStatePending == state)
808 {
809 // Simply wait for the ongoing state switch.
810 return;
811 }
812 else
813 {
814 NS_LOG_DEBUG("Cancel m_setTRXState");
815 // Keep the transceiver state as the old state before the switching attempt.
817 }
818 }
820 {
822 }
823
824 if (state == m_trxState)
825 {
827 {
829 }
830 return;
831 }
832
833 if (((state == IEEE_802_15_4_PHY_RX_ON) || (state == IEEE_802_15_4_PHY_TRX_OFF)) &&
835 {
836 NS_LOG_DEBUG("Phy is busy; setting state pending to " << state);
837 m_trxStatePending = state;
838 return; // Send PlmeSetTRXStateConfirm later
839 }
840
841 // specification talks about being in RX_ON and having received
842 // a valid SFD. Here, we are not modelling at that level of
843 // granularity, so we just test for BUSY_RX state (any part of
844 // a packet being actively received)
845 if (state == IEEE_802_15_4_PHY_TRX_OFF)
846 {
847 CancelEd(state);
848
850 (!m_currentRxPacket.second))
851 {
852 NS_LOG_DEBUG("Receiver has valid SFD; defer state change");
853 m_trxStatePending = state;
854 return; // Send PlmeSetTRXStateConfirm later
855 }
857 {
860 {
862 }
863 return;
864 }
865 }
866
867 if (state == IEEE_802_15_4_PHY_TX_ON)
868 {
869 CancelEd(state);
870
871 NS_LOG_DEBUG("turn on PHY_TX_ON");
873 {
874 if (m_currentRxPacket.first)
875 {
876 // TX_ON is being forced during a reception (For example, when a ACK or Beacon is
877 // issued) The current RX frame is marked as incomplete and the reception as
878 // canceled EndRx () will handle the rest accordingly
879 NS_LOG_DEBUG("force TX_ON, terminate reception");
880 m_currentRxPacket.second = true;
881 m_isRxCanceled = true;
882 }
883
884 // If CCA is in progress, cancel CCA and return BUSY.
885 if (!m_ccaRequest.IsExpired())
886 {
889 {
891 }
892 }
893
895
896 // Delay for turnaround time (BUSY_RX|RX_ON ---> TX_ON)
897 Time setTime = Seconds((double)lrwpan::aTurnaroundTime / GetDataOrSymbolRate(false));
899 return;
900 }
902 {
903 // We do NOT change the transceiver state here. We only report that
904 // the transceiver is already in TX_ON state.
906 {
908 }
909 return;
910 }
912 {
915 {
917 }
918 return;
919 }
920 }
921
923 {
925 {
926 NS_LOG_DEBUG("force TRX_OFF, was already off");
927 }
928 else
929 {
930 NS_LOG_DEBUG("force TRX_OFF, SUCCESS");
931 if (m_currentRxPacket.first)
932 {
933 // Terminate reception
934 // Mark the packet as incomplete and reception as canceled.
935 NS_LOG_DEBUG("force TRX_OFF, terminate reception");
936 m_currentRxPacket.second = true;
937 m_isRxCanceled = true;
938 }
940 {
941 NS_LOG_DEBUG("force TRX_OFF, terminate transmission");
942 m_currentTxPacket.second = true;
943 }
945 // Clear any other state
947 }
949 {
951 }
952 return;
953 }
954
955 if (state == IEEE_802_15_4_PHY_RX_ON)
956 {
958 {
959 // Turnaround delay
960 // TODO: Does it really take aTurnaroundTime to switch the transceiver state,
961 // even when the transmitter is not busy? (6.9.1)
963
964 Time setTime = Seconds((double)lrwpan::aTurnaroundTime / GetDataOrSymbolRate(false));
966 return;
967 }
969 {
971 {
973 }
974 return;
975 }
976 }
977
978 NS_FATAL_ERROR("Unexpected transition from state " << m_trxState << " to state " << state);
979}
980
981bool
983{
984 NS_LOG_FUNCTION(this << channel);
985 bool retValue = false;
986
987 // Bits 0-26 (27 LSB)
989 (1 << channel)) != 0)
990 {
991 return retValue = true;
992 }
993 else
994 {
995 return retValue;
996 }
997}
998
999bool
1001{
1002 NS_LOG_FUNCTION(this << +page);
1003 bool retValue = false;
1004
1005 // TODO: Only O-QPSK 2.4GHz is supported in the LrWpanSpectrumModel
1006 // we must limit the page until support for other modulation is added to the spectrum
1007 // model.
1008 //
1009 NS_ABORT_MSG_UNLESS(page == 0, " Only Page 0 (2.4Ghz O-QPSK supported).");
1010
1011 // IEEE 802.15.4-2006, Table 23 phyChannelsSupported Bits 27-31 (5 MSB)
1012 uint8_t supportedPage = (m_phyPIBAttributes.phyChannelsSupported[page] >> 27) & (0x1F);
1013
1014 if (page == supportedPage)
1015 {
1016 retValue = true;
1017 }
1018
1019 return retValue;
1020}
1021
1022void
1024{
1025 NS_LOG_FUNCTION(this << id << attribute);
1026 NS_ASSERT(attribute);
1028
1029 switch (id)
1030 {
1031 case phyCurrentPage: {
1032 if (!PageSupported(attribute->phyCurrentPage))
1033 {
1035 }
1036 else if (m_phyPIBAttributes.phyCurrentPage != attribute->phyCurrentPage)
1037 {
1038 // Cancel a pending transceiver state change.
1039 // Switch off the transceiver.
1040 // TODO: Is switching off the transceiver the right choice?
1043 {
1047 {
1049 }
1050 }
1051
1052 // Any packet in transmission or reception will be corrupted.
1053 if (m_currentRxPacket.first)
1054 {
1055 m_currentRxPacket.second = true;
1056 }
1057 if (PhyIsBusy())
1058 {
1059 m_currentTxPacket.second = true;
1061 m_currentTxPacket.first = nullptr;
1063 {
1065 }
1066 }
1067
1068 // Changing the Page can change they current PHY in use
1069 // Set the correct PHY according to the Page
1070 if (attribute->phyCurrentPage == 0)
1071 {
1073 {
1074 // 868 MHz BPSK
1076 NS_LOG_INFO("Page 0, 868 MHz BPSK PHY SET");
1077 }
1079 {
1080 // 915 MHz BPSK
1082 NS_LOG_INFO("Page " << (uint32_t)attribute->phyCurrentPage
1083 << ",915 MHz BPSK PHY SET");
1084 }
1086 {
1087 // 2.4 GHz MHz O-QPSK
1089 NS_LOG_INFO("Page " << (uint32_t)attribute->phyCurrentPage
1090 << ", 2.4 Ghz O-QPSK PHY SET");
1091 }
1092 }
1093 else if (attribute->phyCurrentPage == 1)
1094 {
1096 {
1097 // 868 MHz ASK
1099 NS_LOG_INFO("Page " << (uint32_t)attribute->phyCurrentPage
1100 << ", 868 MHz ASK PHY SET");
1101 }
1103 {
1104 // 915 MHz ASK
1106 NS_LOG_INFO("Page " << (uint32_t)attribute->phyCurrentPage
1107 << ", 915 MHz ASK PHY SET");
1108 }
1109 else
1110 {
1111 // No longer valid channel
1114 NS_LOG_INFO("Channel no longer valid in new page "
1115 << (uint32_t)attribute->phyCurrentPage
1116 << ", setting new default channel "
1118 NS_LOG_INFO("868 MHz ASK PHY SET");
1119 }
1120 }
1121 else if (attribute->phyCurrentPage == 2)
1122 {
1124 {
1125 // 868 MHz O-QPSK
1127 NS_LOG_INFO("Page " << (uint32_t)attribute->phyCurrentPage
1128 << ", 868 MHz O-QPSK PHY SET");
1129 }
1131 {
1132 // 915 MHz O-QPSK
1134 NS_LOG_INFO("Page " << (uint32_t)attribute->phyCurrentPage
1135 << ", 915 MHz O-QPSK PHY SET");
1136 }
1137 else
1138 {
1139 // No longer valid channel
1142 NS_LOG_INFO("Channel no longer valid in new page "
1143 << (uint32_t)attribute->phyCurrentPage
1144 << ", setting new default channel "
1146 NS_LOG_INFO("868 MHz O-QPSK PHY SET");
1147 }
1148 }
1149 else if (attribute->phyCurrentPage == 5)
1150 {
1152 {
1153 // 780 MHz O-QPSK
1155 NS_LOG_INFO("Page " << (uint32_t)attribute->phyCurrentPage
1156 << ", 915 MHz O-QPSK PHY SET");
1157 }
1158 else
1159 {
1160 // No longer valid channel
1163 NS_LOG_INFO("Channel no longer valid in new page "
1164 << (uint32_t)attribute->phyCurrentPage
1165 << ", setting new default channel "
1167 NS_LOG_INFO("780 MHz O-QPSK PHY SET");
1168 }
1169 }
1170 else if (attribute->phyCurrentPage == 6)
1171 {
1173 {
1174 // 950 MHz BPSK
1176 NS_LOG_INFO("Page " << (uint32_t)attribute->phyCurrentPage
1177 << ", 950 MHz BPSK PHY SET");
1178 }
1179 else
1180 {
1183 NS_LOG_INFO("Channel no longer valid in new page "
1184 << (uint32_t)attribute->phyCurrentPage
1185 << ", setting new default channel "
1187 NS_LOG_INFO("950 MHz BPSK PHY SET");
1188 }
1189 }
1190
1191 m_phyPIBAttributes.phyCurrentPage = attribute->phyCurrentPage;
1192
1193 // TODO: Set the maximum possible sensitivity by default.
1194 // This maximum sensitivity depends on the modulation used.
1195 // Currently Only O-QPSK 250kbps is supported so we use its max sensitivity.
1196 SetRxSensitivity(-106.58);
1197 }
1198 break;
1199 }
1200 case phyCurrentChannel: {
1201 if (!ChannelSupported(attribute->phyCurrentChannel))
1202 {
1204 }
1205 if (m_phyPIBAttributes.phyCurrentChannel != attribute->phyCurrentChannel)
1206 {
1207 // Cancel a pending transceiver state change.
1208 // Switch off the transceiver.
1209 // TODO: Is switching off the transceiver the right choice?
1212 {
1216 {
1218 }
1219 }
1220
1221 // Any packet in transmission or reception will be corrupted.
1222 if (m_currentRxPacket.first)
1223 {
1224 m_currentRxPacket.second = true;
1225 }
1226 if (PhyIsBusy())
1227 {
1228 m_currentTxPacket.second = true;
1230 m_currentTxPacket.first = nullptr;
1232 {
1234 }
1235 }
1236
1237 m_phyPIBAttributes.phyCurrentChannel = attribute->phyCurrentChannel;
1238
1239 // use the prev configured sensitivity before changing the channel
1241 }
1242 break;
1243 }
1244 case phyChannelsSupported: { // only the first element is considered in the array
1245 if ((attribute->phyChannelsSupported[0] & 0xf8000000) != 0)
1246 { // 5 MSBs reserved
1248 }
1249 else
1250 {
1251 m_phyPIBAttributes.phyChannelsSupported[0] = attribute->phyChannelsSupported[0];
1252 }
1253 break;
1254 }
1255 case phyTransmitPower: {
1256 if (attribute->phyTransmitPower & 0xC0)
1257 {
1258 NS_LOG_LOGIC("LrWpanPhy::PlmeSetAttributeRequest error - can not change read-only "
1259 "attribute bits.");
1261 }
1262 else
1263 {
1264 m_phyPIBAttributes.phyTransmitPower = attribute->phyTransmitPower;
1265 LrWpanSpectrumValueHelper psdHelper;
1269 }
1270 break;
1271 }
1272 case phyCCAMode: {
1273 if ((attribute->phyCCAMode < 1) || (attribute->phyCCAMode > 3))
1274 {
1276 }
1277 else
1278 {
1279 m_phyPIBAttributes.phyCCAMode = attribute->phyCCAMode;
1280 }
1281 break;
1282 }
1283 default: {
1285 break;
1286 }
1287 }
1288
1290 {
1292 }
1293}
1294
1295void
1301
1302void
1308
1309void
1315
1316void
1322
1323void
1329
1330void
1336
1337void
1343
1344void
1346{
1347 NS_LOG_LOGIC(this << " state: " << m_trxState << " -> " << newState);
1348
1350 m_trxState = newState;
1351}
1352
1353bool
1360
1361void
1363{
1364 NS_LOG_FUNCTION(this);
1366
1367 if (!m_edRequest.IsExpired())
1368 {
1371 {
1372 m_plmeEdConfirmCallback(state, 0);
1373 }
1374 }
1375}
1376
1377void
1379{
1380 NS_LOG_FUNCTION(this);
1381
1385 (Simulator::Now() - m_edPower.lastUpdate).GetTimeStep() /
1387
1388 uint8_t energyLevel;
1389
1390 // Per IEEE802.15.4-2006 sec 6.9.7
1391 double ratio = m_edPower.averagePower / m_rxSensitivity;
1392 ratio = 10.0 * log10(ratio);
1393 if (ratio <= 10.0)
1394 { // less than 10 dB
1395 energyLevel = 0;
1396 }
1397 else if (ratio >= 40.0)
1398 { // less than 40 dB
1399 energyLevel = 255;
1400 }
1401 else
1402 {
1403 // in-between with linear increase per sec 6.9.7
1404 energyLevel = static_cast<uint8_t>(((ratio - 10.0) / 30.0) * 255.0);
1405 }
1406
1408 {
1410 }
1411}
1412
1413void
1415{
1416 NS_LOG_FUNCTION(this);
1417 PhyEnumeration sensedChannelState = IEEE_802_15_4_PHY_UNSPECIFIED;
1418
1419 // Update peak power.
1420 double power = LrWpanSpectrumValueHelper::TotalAvgPower(m_signal->GetSignalPsd(),
1422 if (m_ccaPeakPower < power)
1423 {
1424 m_ccaPeakPower = power;
1425 }
1426
1427 if (PhyIsBusy())
1428 {
1429 sensedChannelState = IEEE_802_15_4_PHY_BUSY;
1430 }
1431 else if (m_phyPIBAttributes.phyCCAMode == 1)
1432 { // sec 6.9.9 ED detection
1433 // -- ED threshold at most 10 dB above receiver sensitivity.
1434 if (10 * log10(m_ccaPeakPower / m_rxSensitivity) >= 10.0)
1435 {
1436 sensedChannelState = IEEE_802_15_4_PHY_BUSY;
1437 }
1438 else
1439 {
1440 sensedChannelState = IEEE_802_15_4_PHY_IDLE;
1441 }
1442 }
1443 else if (m_phyPIBAttributes.phyCCAMode == 2)
1444 {
1445 // sec 6.9.9 carrier sense only
1447 {
1448 // We currently do not model PPDU reception in detail. Instead we model
1449 // packet reception starting with the first bit of the preamble.
1450 // Therefore, this code will never be reached, as PhyIsBusy() would
1451 // already lead to a channel busy condition.
1452 // TODO: Change this, if we also model preamble and SFD detection.
1453 sensedChannelState = IEEE_802_15_4_PHY_BUSY;
1454 }
1455 else
1456 {
1457 sensedChannelState = IEEE_802_15_4_PHY_IDLE;
1458 }
1459 }
1460 else if (m_phyPIBAttributes.phyCCAMode == 3)
1461 { // sect 6.9.9 both
1462 if ((10 * log10(m_ccaPeakPower / m_rxSensitivity) >= 10.0) &&
1464 {
1465 // Again, this code will never be reached, if we are already receiving
1466 // a packet, as PhyIsBusy() would already lead to a channel busy condition.
1467 // TODO: Change this, if we also model preamble and SFD detection.
1468 sensedChannelState = IEEE_802_15_4_PHY_BUSY;
1469 }
1470 else
1471 {
1472 sensedChannelState = IEEE_802_15_4_PHY_IDLE;
1473 }
1474 }
1475 else
1476 {
1477 NS_ASSERT_MSG(false, "Invalid CCA mode");
1478 }
1479
1480 NS_LOG_LOGIC(this << "channel sensed state: " << sensedChannelState);
1481
1483 {
1484 m_plmeCcaConfirmCallback(sensedChannelState);
1485 }
1486}
1487
1488void
1503
1504void
1506{
1507 NS_LOG_FUNCTION(this);
1508
1511
1512 if (!m_currentTxPacket.second)
1513 {
1514 NS_LOG_DEBUG("Packet successfully transmitted");
1517 {
1519 }
1520 }
1521 else
1522 {
1523 NS_LOG_DEBUG("Packet transmission aborted");
1526 {
1527 // See if this is ever entered in another state
1530 }
1531 }
1532 m_currentTxPacket.first = nullptr;
1533 m_currentTxPacket.second = false;
1534
1535 // We may be waiting to apply a pending state change.
1537 {
1538 // Only change the state immediately, if the transceiver is not already
1539 // switching the state.
1540 if (!m_setTRXState.IsPending())
1541 {
1542 NS_LOG_LOGIC("Apply pending state change to " << m_trxStatePending);
1546 {
1548 }
1549 }
1550 }
1551 else
1552 {
1554 {
1556 }
1557 }
1558}
1559
1560Time
1562{
1563 NS_LOG_FUNCTION(this << packet);
1564
1565 bool isData = true;
1566 Time txTime = GetPpduHeaderTxTime();
1567
1568 txTime += Seconds(packet->GetSize() * 8.0 / GetDataOrSymbolRate(isData));
1569
1570 return txTime;
1571}
1572
1573uint8_t
1578
1579uint8_t
1584
1585double
1587{
1588 double rate = 0.0;
1589
1591
1592 if (isData)
1593 {
1595 }
1596 else
1597 {
1599 }
1600
1601 return (rate * 1000.0);
1602}
1603
1604Time
1606{
1607 NS_LOG_FUNCTION(this);
1608
1609 bool isData = false;
1610 double totalPpduHdrSymbols;
1611
1613
1614 totalPpduHdrSymbols = ppduHeaderSymbolNumbers[m_phyOption].shrPreamble +
1617
1618 return Seconds(totalPpduHdrSymbols / GetDataOrSymbolRate(isData));
1619}
1620
1621void
1623{
1624 NS_LOG_FUNCTION(this);
1625
1627
1628 // TODO: Only O-QPSK 2.4GHz is supported in the LrWpanSpectrumModel
1629 // we must limit the page until support for other modulations is added to the spectrum
1630 // model.
1631 NS_ABORT_MSG_UNLESS(phyOption == IEEE_802_15_4_2_4GHZ_OQPSK, " Only 2.4Ghz O-QPSK supported.");
1632
1633 // Set default Channel and Page
1634 // IEEE 802.15.4-2006 Table 2, section 6.1.1
1635 // IEEE 802.15.4c-2009 Table 2, section 6.1.2.2
1636 // IEEE 802.15.4d-2009 Table 2, section 6.1.2.2
1637 switch (phyOption)
1638 {
1640 // IEEE 802.15.4-2006 868 MHz BPSK (Page 0, Channel 0)
1643 break;
1645 // IEEE 802.15.4-2006 915 MHz BPSK (Page 0, Channels 1 to 10)
1648 break;
1650 // IEEE 802.15.4d-2009 950 MHz BPSK (Page 6, Channels 0 to 9)
1653 break;
1655 // IEEE 802.15.4-2006 868 MHz ASK (Page 1, Channel 0)
1658 break;
1660 // IEEE 802.15.4-2006 915 MHz ASK (Page 1, Channel 1 to 10)
1663 break;
1665 // IEEE 802.15.4c-2009 780 MHz O-QPSK (Page 5, Channel 0 to 3)
1668 break;
1670 // IEEE 802.15.4-2006 868 MHz O-QPSK (Page 2, Channel 0)
1673 break;
1675 // IEEE 802.15.4-2006 915 MHz O-QPSK (Page 2, Channels 1 to 10)
1678 break;
1680 // IEEE 802.15.4-2009 2.4 GHz O-QPSK (Page 0, Channels 11 to 26)
1683 break;
1685 // IEEE 802.15.4-2006 Use Non-Registered Page and channel
1688 break;
1689 }
1690
1692
1693 m_phyOption = phyOption;
1694 // TODO: Fix/Update list when more modulations are supported.
1695 // IEEE 802.15.4-2006, Table 23
1696 // 5 MSB = Page number, 27 LSB = Supported Channels (1= supported, 0 Not supported)
1697 // Currently only page 0, channels 11-26 supported.
1699 0x7FFF800; // Page 0 should support, Channels 0 to 26 (0x07FFFFFF)
1700
1701 for (int i = 1; i <= 31; i++)
1702 {
1703 // Page 1 to 31, No support (Page set to 31, all channels 0)
1705 }
1706
1707 m_edPower.averagePower = 0.0;
1710
1711 // TODO: Change the limits Rx sensitivity when other modulations are supported
1712 // Currently, only O-QPSK 250kbps is supported and its maximum possible sensitivity is
1713 // equal to -106.58 dBm and its minimum sensitivity is defined as -85 dBm
1714 SetRxSensitivity(-106.58);
1715
1717 m_currentRxPacket = std::make_pair(nullptr, true);
1718 m_currentTxPacket = std::make_pair(nullptr, true);
1719 m_errorModel = nullptr;
1720}
1721
1722void
1723LrWpanPhy::SetRxSensitivity(double dbmSensitivity)
1724{
1725 NS_LOG_FUNCTION(this << dbmSensitivity << "dBm");
1726
1727 // See IEEE 802.15.4-2011 Sections 10.3.4, 11.3.4, 13.3.4, 13.3.4, 14.3.4, 15.3.4
1729 {
1730 if (dbmSensitivity > -92)
1731 {
1732 NS_ABORT_MSG("The minimum Rx sensitivity for this band should be at least -92 dBm");
1733 }
1734 }
1735 else
1736 {
1737 if (dbmSensitivity > -85)
1738 {
1739 NS_ABORT_MSG("The minimum Rx sensitivity for this band should be at least -85 dBm");
1740 }
1741 }
1742
1743 // Calculate the noise factor required to reduce the Rx sensitivity.
1744 // The maximum possible sensitivity in the current modulation is used as a reference
1745 // to calculate the noise factor (F). The noise factor is a dimensionless ratio.
1746 // Currently only one PHY modulation is supported:
1747 // O-QPSK 250kpps which has a Max Rx sensitivity: -106.58 dBm (Noise factor = 1).
1748 // After Rx sensitivity is set, this becomes the new point where PER < 1 % for a
1749 // PSDU of 20 bytes as described by the standard.
1750
1751 // TODO: recalculate maxRxSensitivity (Noise factor = 1) when additional modulations are
1752 // supported.
1753 double maxRxSensitivityW = DbmToW(-106.58);
1754
1755 LrWpanSpectrumValueHelper psdHelper;
1759 // Update thermal noise + noise factor added.
1760 long double noiseFactor = DbmToW(dbmSensitivity) / maxRxSensitivityW;
1761 psdHelper.SetNoiseFactor(noiseFactor);
1763
1764 m_signal = Create<LrWpanInterferenceHelper>(m_noise->GetSpectrumModel());
1765 // Change receiver sensitivity from dBm to Watts
1766 m_rxSensitivity = DbmToW(dbmSensitivity);
1767}
1768
1769double
1771{
1772 NS_LOG_FUNCTION(this);
1773 // Change receiver sensitivity from Watt to dBm
1774 return WToDbm(m_rxSensitivity);
1775}
1776
1779{
1780 NS_LOG_FUNCTION(this);
1781 return m_phyOption;
1782}
1783
1784void
1786{
1787 NS_LOG_FUNCTION(this << txPsd);
1788 NS_ASSERT(txPsd);
1789 m_txPsd = txPsd;
1790 NS_LOG_INFO("\t computed tx_psd: " << *txPsd << "\t stored tx_psd: " << *m_txPsd);
1791}
1792
1793void
1795{
1796 NS_LOG_FUNCTION(this << noisePsd);
1797 NS_LOG_INFO("\t computed noise_psd: " << *noisePsd);
1798 NS_ASSERT(noisePsd);
1799 m_noise = noisePsd;
1800}
1801
1808
1809void
1816
1819{
1820 NS_LOG_FUNCTION(this);
1821 return m_errorModel;
1822}
1823
1824uint64_t
1833
1834double
1842
1843double
1845{
1846 double powerWatts =
1849 return WToDbm(powerWatts);
1850}
1851
1852int8_t
1854{
1856
1857 // The nominal Tx power is stored in the PIB as a 6-bit
1858 // twos-complement, signed number.
1859
1860 // The 5 LSBs can be copied - as their representation
1861 // is the same for unsigned and signed integers.
1862 int8_t nominalTxPower = phyTransmitPower & 0x1F;
1863
1864 // Now check the 6th LSB (the "sign" bit).
1865 // It's a twos-complement format, so the "sign"
1866 // bit represents -2^5 = -32.
1867 if (phyTransmitPower & 0x20)
1868 {
1869 nominalTxPower -= 32;
1870 }
1871 return nominalTxPower;
1872}
1873
1874double
1876{
1877 return (10 * log10(1000 * watt));
1878}
1879
1880double
1882{
1883 return (pow(10.0, dbm / 10.0) / 1000.0);
1884}
1885
1886int64_t
1888{
1889 NS_LOG_FUNCTION(this);
1890 m_random->SetStream(stream);
1891 return 1;
1892}
1893
1894void
1900
1901} // namespace lrwpan
1902} // namespace ns3
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
void Cancel()
This method is syntactic sugar for the ns3::Simulator::Cancel method.
Definition event-id.cc:44
bool IsPending() const
This method is syntactic sugar for !IsExpired().
Definition event-id.cc:65
bool IsExpired() const
This method is syntactic sugar for the ns3::Simulator::IsExpired method.
Definition event-id.cc:58
Keep track of the current position and velocity of an object.
Ptr< T > GetObject() const
Get a pointer to the requested aggregated Object.
Definition object.h:511
virtual void DoDispose()
Destructor implementation.
Definition object.cc:433
AttributeValue implementation for Pointer.
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 Time Now()
Return the current simulation virtual time.
Definition simulator.cc:197
Abstract base class for Spectrum-aware PHY layers.
Simulation virtual time values and global simulation resolution.
Definition nstime.h:94
@ MS
millisecond
Definition nstime.h:106
int64_t GetTimeStep() const
Get the raw time value, in the current resolution unit.
Definition nstime.h:434
Trace classes with value semantics.
a unique identifier for an interface.
Definition type-id.h:48
TypeId AddDeprecatedName(const std::string &name)
Add an deprecated name for a TypeId.
Definition type-id.cc:862
TypeId SetParent(TypeId tid)
Set the parent TypeId.
Definition type-id.cc:1001
Represent the LQI (Link Quality Estination).
void Set(uint8_t lqi)
Set the LQI to the given value.
uint8_t Get() const
Get the LQI value.
Make LrWpanPhy a SpectrumPhy so we can enable the eventual modeling of device interference.
void PlmeEdRequest()
IEEE 802.15.4-2006 section 6.2.2.3 PLME-ED.request Perform an ED per section 6.9.7.
void PlmeSetAttributeRequest(PhyPibAttributeIdentifier id, Ptr< PhyPibAttributes > attribute)
IEEE 802.15.4-2006 section 6.2.2.9 PLME-SET.request Set attributes per definition from Table 23 in se...
int64_t AssignStreams(int64_t stream)
Assign a fixed random variable stream number to the random variables used by this model.
void SetRxSensitivity(double dbmSensitivity)
Set the receiver power sensitivity used by this device in dBm.
EventId m_pdDataRequest
Scheduler event of a currently running data transmission request.
void EndRx(Ptr< SpectrumSignalParameters > params)
Finish the reception of a frame.
void SetTxPowerSpectralDensity(Ptr< SpectrumValue > txPsd)
Set the Power Spectral Density of outgoing signals in W/Hz.
Ptr< AntennaModel > m_antenna
The antenna used by the transceiver.
std::pair< Ptr< LrWpanSpectrumSignalParameters >, bool > m_currentRxPacket
Status information of the currently received packet.
Ptr< NetDevice > m_device
The configured net device.
bool ChannelSupported(uint8_t channel)
Check if the given channel is supported by the PHY.
void SetPlmeGetAttributeConfirmCallback(PlmeGetAttributeConfirmCallback c)
set the callback for the end of an GetAttribute, as part of the interconnections between the PHY and ...
int8_t GetNominalTxPowerFromPib(uint8_t phyTransmitPower)
Calculates the nominal transmit power of the device in decibels relative to 1 mW according to the rep...
void DoInitialize() override
Initialize() implementation.
void SetAntenna(Ptr< AntennaModel > a)
Set the attached antenna.
Ptr< const SpectrumModel > GetRxSpectrumModel() const override
void DoDispose() override
Destructor implementation.
TracedCallback< Ptr< const Packet > > m_phyTxBeginTrace
The trace source fired when a packet begins the transmission process on the medium.
void EndCca()
Called at the end of the CCA.
Ptr< SpectrumChannel > m_channel
The channel attached to this transceiver.
void SetPostReceptionErrorModel(const Ptr< ErrorModel > em)
Attach a receive ErrorModel to the LrWpanPhy.
double GetRxSensitivity()
Get the receiver power sensitivity used by this device in dBm.
PhyOption GetMyPhyOption()
Get the currently configured PHY option.
PacketAndStatus m_currentTxPacket
Status information of the currently transmitted packet.
void EndSetTRXState()
Called after applying a deferred transceiver state switch.
PdDataConfirmCallback m_pdDataConfirmCallback
This callback is used to report packet transmission status to the MAC layer.
void SetChannel(Ptr< SpectrumChannel > c) override
Set the channel attached to this device.
void PlmeGetAttributeRequest(PhyPibAttributeIdentifier id)
IEEE 802.15.4-2006 section 6.2.2.5 PLME-GET.request Get attributes per definition from Table 23 in se...
void SetPdDataConfirmCallback(PdDataConfirmCallback c)
set the callback for the end of a TX, as part of the interconnections between the PHY and the MAC.
Ptr< LrWpanInterferenceHelper > m_signal
The accumulated signals currently received by the transceiver, including the signal of a possibly rec...
void SetPdDataIndicationCallback(PdDataIndicationCallback c)
set the callback for the end of a RX, as part of the interconnections between the PHY and the MAC.
TracedCallback< Ptr< const Packet > > m_phyTxEndTrace
The trace source fired when a packet ends the transmission process on the medium.
double WToDbm(double watt)
Transform watts (W) to decibels milliwatts (dBm).
uint8_t GetCurrentPage() const
Get The current channel page number in use in this PHY from the PIB attributes.
PhyPibAttributes m_phyPIBAttributes
The current PHY PIB attributes.
Ptr< MobilityModel > m_mobility
The mobility model used by the PHY.
void SetErrorModel(Ptr< LrWpanErrorModel > e)
set the error model to use
void SetMobility(Ptr< MobilityModel > m) override
Set the mobility model associated with this device.
PlmeSetTRXStateConfirmCallback m_plmeSetTRXStateConfirmCallback
This callback is used to report transceiver state change status to the MAC.
void SetNoisePowerSpectralDensity(Ptr< const SpectrumValue > noisePsd)
Set the noise power spectral density.
TracedCallback< Time, PhyEnumeration, PhyEnumeration > m_trxStateLogger
The trace source fired when the phy layer changes the transceiver state.
EdPower m_edPower
Helper value for tracking the average power during ED.
Time m_rxLastUpdate
Timestamp of the last calculation of the PER of a packet currently received.
EventId m_setTRXState
Scheduler event of a currently running deferred transceiver state switch.
Ptr< MobilityModel > GetMobility() const override
Get the associated MobilityModel instance.
void SetPlmeSetAttributeConfirmCallback(PlmeSetAttributeConfirmCallback c)
set the callback for the end of an SetAttribute, as part of the interconnections between the PHY and ...
void SetPhyOption(PhyOption phyOption)
Set the modulation option used by this PHY.
void PlmeCcaRequest()
IEEE 802.15.4-2006 section 6.2.2.1 PLME-CCA.request Perform a CCA per section 6.9....
TracedValue< PhyEnumeration > m_trxState
The current transceiver state.
void SetPlmeSetTRXStateConfirmCallback(PlmeSetTRXStateConfirmCallback c)
set the callback for the end of an SetTRXState, as part of the interconnections between the PHY and t...
double GetCurrentSignalPsd()
Get the current accumulated sum of signals in the transceiver including signals considered as interfe...
void SetPlmeCcaConfirmCallback(PlmeCcaConfirmCallback c)
set the callback for the end of a CCA, as part of the interconnections between the PHY and the MAC.
Ptr< LrWpanErrorModel > m_errorModel
The error model describing the bit and packet error rates.
void EndTx()
Finish the transmission of a frame.
void SetPlmeEdConfirmCallback(PlmeEdConfirmCallback c)
set the callback for the end of an ED, as part of the interconnections between the PHY and the MAC.
uint8_t GetCurrentChannelNum() const
Get The current channel number in use in this PHY from the PIB attributes.
void PlmeSetTRXStateRequest(PhyEnumeration state)
IEEE 802.15.4-2006 section 6.2.2.7 PLME-SET-TRX-STATE.request Set PHY state.
LrWpanPhy()
Default constructor.
TracedCallback< Ptr< const Packet > > m_phyRxBeginTrace
The trace source fired when a packet begins the reception process from the medium.
PlmeSetAttributeConfirmCallback m_plmeSetAttributeConfirmCallback
This callback is used to report attribute set results back to the MAC.
PhyEnumeration m_trxStatePending
The next pending state to applied after the current action of the PHY is completed.
TracedCallback< Ptr< const Packet > > m_phyRxDropTrace
The trace source fired when the phy layer drops a packet it has received.
double GetPhySymbolsPerOctet() const
Get the number of symbols per octet, depending on the currently selected channel.
PdDataIndicationCallback m_pdDataIndicationCallback
This callback is used to notify incoming packets to the MAC layer.
Ptr< LrWpanErrorModel > GetErrorModel() const
get the error model in use
void StartRx(Ptr< SpectrumSignalParameters > params) override
Notify the SpectrumPhy instance of an incoming waveform.
double m_rxSensitivity
The receiver sensitivity.
void CcaCancel()
Cancel an ongoing CCA request.
void CheckInterference()
Check if the interference destroys a frame currently received.
EventId m_ccaRequest
Scheduler event of a currently running CCA request.
Ptr< SpectrumChannel > GetChannel()
Get the currently attached channel.
Ptr< ErrorModel > m_postReceptionErrorModel
Error model for receive packet events.
PlmeCcaConfirmCallback m_plmeCcaConfirmCallback
This callback is used to report CCA status to the MAC or CSMA/CA.
uint64_t GetPhySHRDuration() const
Get the duration of the SHR (preamble and SFD) in symbols, depending on the currently selected channe...
bool m_isRxCanceled
Indicates if the reception of frame has been canceled.
void CancelEd(PhyEnumeration state)
Cancel an ongoing ED procedure.
Ptr< NetDevice > GetDevice() const override
Get the associated NetDevice instance.
void PdDataRequest(const uint32_t psduLength, Ptr< Packet > p)
IEEE 802.15.4-2006 section 6.2.1.1 PD-DATA.request Request to transfer MPDU from MAC (transmitting)
double DbmToW(double dbm)
Transforms decibels milliwatts (dBm) to watts (W).
Ptr< UniformRandomVariable > m_random
Uniform random variable stream.
EventId m_edRequest
Scheduler event of a currently running ED request.
PhyOption m_phyOption
The currently configured PHY type.
Ptr< SpectrumValue > m_txPsd
The transmit power spectral density.
bool PageSupported(uint8_t page)
Check if the given page is supported by the PHY.
Time GetPpduHeaderTxTime()
Calculate the time required for sending the PPDU header, that is the preamble, SFD and PHR.
void EndEd()
Called at the end of the ED procedure.
void SetDevice(Ptr< NetDevice > d) override
Set the associated NetDevice instance.
double GetDataOrSymbolRate(bool isData)
implement PLME SetAttribute confirm SAP bit rate is in bit/s.
PlmeGetAttributeConfirmCallback m_plmeGetAttributeConfirmCallback
This callback is used to report requested attribute values back to the MAC.
Ptr< Object > GetAntenna() const override
Get the AntennaModel used by this SpectrumPhy instance for transmission and/or reception.
TracedCallback< Ptr< const Packet > > m_phyTxDropTrace
The trace source fired when the phy layer drops a packet as it tries to transmit it.
TracedCallback< Ptr< const Packet >, double > m_phyRxEndTrace
The trace source fired when a packet ends the reception process from the medium.
double m_ccaPeakPower
Helper value for the peak power value during CCA.
Time CalculateTxTime(Ptr< const Packet > packet)
Calculate the time required for sending the given packet, including preamble, SFD and PHR.
Ptr< const SpectrumValue > GetNoisePowerSpectralDensity()
Get the noise power spectral density.
bool PhyIsBusy() const
Check if the PHY is busy, which is the case if the PHY is currently sending or receiving a frame.
PlmeEdConfirmCallback m_plmeEdConfirmCallback
This callback is used to report ED status to the MAC.
Ptr< const SpectrumValue > m_noise
The spectral density for for the noise.
void ChangeTrxState(PhyEnumeration newState)
Change the PHY state to the given new state, firing the state change trace.
static TypeId GetTypeId()
Get the type ID.
This class defines all functions to create spectrum model for LrWpan.
Ptr< SpectrumValue > CreateNoisePowerSpectralDensity(uint32_t channel)
create spectrum value for noise
static double TotalAvgPower(Ptr< const SpectrumValue > psd, uint32_t channel)
total average power of the signal is the integral of the PSD using the limits of the given channel
Ptr< SpectrumValue > CreateTxPowerSpectralDensity(double txPower, uint32_t channel)
create spectrum value
void SetNoiseFactor(double f)
Set the noise factor added to the thermal noise.
constexpr uint32_t aMaxPhyPacketSize
The maximum packet size accepted by the PHY.
constexpr uint32_t aTurnaroundTime
The turnaround time in symbol periods for switching the transceiver from RX to TX or vice-versa.
#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
#define NS_ASSERT_MSG(condition, message)
At runtime, in debugging builds, if this condition is not true, the program prints the message to out...
Definition assert.h:75
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
Callback< R, Args... > MakeNullCallback()
Definition callback.h:727
#define NS_ABORT_MSG_UNLESS(cond, msg)
Abnormal program termination if a condition is false, with a message.
Definition abort.h:133
#define NS_FATAL_ERROR(msg)
Report a fatal error with a message and terminate.
#define NS_ABORT_MSG(msg)
Unconditional abnormal program termination with a message.
Definition abort.h:38
#define NS_ABORT_IF(cond)
Abnormal program termination if a condition is true.
Definition abort.h:65
#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_LOGIC(msg)
Use NS_LOG to output a message of level LOG_LOGIC.
Definition log.h:271
#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
#define NS_LOG_INFO(msg)
Use NS_LOG to output a message of level LOG_INFO.
Definition log.h:264
PhyOption
This Phy option will be used to index various Tables in IEEE802.15.4-2011.
Definition lr-wpan-phy.h:84
PhyEnumeration
IEEE802.15.4-2006 PHY Emumerations Table 18 in section 6.2.3.
PhyPibAttributeIdentifier
IEEE802.15.4-2006 PHY PIB Attribute Identifiers Table 23 in section 6.4.2.
@ IEEE_802_15_4_915MHZ_OQPSK
Definition lr-wpan-phy.h:92
@ IEEE_802_15_4_2_4GHZ_OQPSK
Definition lr-wpan-phy.h:93
@ IEEE_802_15_4_915MHZ_ASK
Definition lr-wpan-phy.h:89
@ IEEE_802_15_4_780MHZ_OQPSK
Definition lr-wpan-phy.h:90
@ IEEE_802_15_4_868MHZ_OQPSK
Definition lr-wpan-phy.h:91
@ IEEE_802_15_4_915MHZ_BPSK
Definition lr-wpan-phy.h:86
@ IEEE_802_15_4_868MHZ_BPSK
Definition lr-wpan-phy.h:85
@ IEEE_802_15_4_950MHZ_BPSK
Definition lr-wpan-phy.h:87
@ IEEE_802_15_4_INVALID_PHY_OPTION
Definition lr-wpan-phy.h:94
@ IEEE_802_15_4_868MHZ_ASK
Definition lr-wpan-phy.h:88
@ IEEE_802_15_4_PHY_BUSY
@ IEEE_802_15_4_PHY_READ_ONLY
@ IEEE_802_15_4_PHY_BUSY_TX
@ IEEE_802_15_4_PHY_RX_ON
@ IEEE_802_15_4_PHY_TRX_OFF
@ IEEE_802_15_4_PHY_TX_ON
@ IEEE_802_15_4_PHY_INVALID_PARAMETER
@ IEEE_802_15_4_PHY_UNSUPPORTED_ATTRIBUTE
@ IEEE_802_15_4_PHY_SUCCESS
@ IEEE_802_15_4_PHY_FORCE_TRX_OFF
@ IEEE_802_15_4_PHY_BUSY_RX
@ IEEE_802_15_4_PHY_IDLE
@ IEEE_802_15_4_PHY_UNSPECIFIED
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
Ptr< T > Create(Ts &&... args)
Create class instances by constructors with varying numbers of arguments and return them by Ptr.
Definition ptr.h:436
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.
static const PhyDataAndSymbolRates dataSymbolRates[IEEE_802_15_4_INVALID_PHY_OPTION]
The data and symbol rates for the different PHY options.
const PhyPpduHeaderSymbolNumber ppduHeaderSymbolNumbers[IEEE_802_15_4_INVALID_PHY_OPTION]
The preamble, SFD, and PHR lengths in symbols for the different PHY options.
std::ostream & operator<<(std::ostream &os, const SuperframeField &superframeField)
Stream insertion operator.
Every class exported by the ns3 library is enclosed in the ns3 namespace.
Ptr< T1 > DynamicCast(const Ptr< T2 > &p)
Cast a Ptr.
Definition ptr.h:580
double averagePower
Average measured power.
Definition lr-wpan-phy.h:48
Time lastUpdate
Last update time.
Definition lr-wpan-phy.h:49
Time measurementLength
Total measurement period.
Definition lr-wpan-phy.h:50
This data structure provides the Bit rate and Symbol rate for a given channel See IEEE802....
Definition lr-wpan-phy.h:60
uint8_t phyCurrentChannel
The RF channel to use.
uint8_t phyCurrentPage
Current channel page.
uint8_t phyTransmitPower
2 MSB: tolerance on the transmit power, 6 LSB: Tx power in dBm relative to 1mW (signed int in 2-compl...
uint32_t phyChannelsSupported[32]
BitField representing the available channels supported by a channel page.
This data structure provides number of symbols for the PPDU headers: SHR and PHR See IEEE802....
Definition lr-wpan-phy.h:72
double phr
Number of symbols for the PHR.
Definition lr-wpan-phy.h:75
double shrPreamble
Number of symbols for the SHR preamble.
Definition lr-wpan-phy.h:73
double shrSfd
Number of symbols for the SHR SFD.
Definition lr-wpan-phy.h:74