22 #include "uan-phy-gen.h"
23 #include "uan-transducer.h"
24 #include "uan-channel.h"
25 #include "uan-net-device.h"
26 #include "ns3/simulator.h"
27 #include "ns3/traced-callback.h"
29 #include "ns3/trace-source-accessor.h"
30 #include "ns3/double.h"
32 #include "ns3/uan-tx-mode.h"
34 #include "ns3/uinteger.h"
35 #include "ns3/energy-source-container.h"
36 #include "ns3/acoustic-modem-energy-model.h"
43 NS_OBJECT_ENSURE_REGISTERED (UanPhyGen);
44 NS_OBJECT_ENSURE_REGISTERED (UanPhyPerGenDefault);
45 NS_OBJECT_ENSURE_REGISTERED (UanPhyCalcSinrDefault);
46 NS_OBJECT_ENSURE_REGISTERED (UanPhyCalcSinrFhFsk);
47 NS_OBJECT_ENSURE_REGISTERED (UanPhyPerUmodem);
51 UanPhyCalcSinrDefault::UanPhyCalcSinrDefault ()
55 UanPhyCalcSinrDefault::~UanPhyCalcSinrDefault ()
61 UanPhyCalcSinrDefault::GetTypeId (
void)
63 static TypeId tid = TypeId (
"ns3::UanPhyCalcSinrDefault")
65 .AddConstructor<UanPhyCalcSinrDefault> ()
81 NS_LOG_WARN (
"Calculating SINR for unsupported modulation type");
84 double intKp = -
DbToKp (rxPowerDb);
85 UanTransducer::ArrivalList::const_iterator it = arrivalList.begin ();
86 for (; it != arrivalList.end (); it++)
88 intKp +=
DbToKp (it->GetRxPowerDb ());
91 double totalIntDb =
KpToDb (intKp +
DbToKp (ambNoiseDb));
93 NS_LOG_DEBUG (
"Calculating SINR: RxPower = " << rxPowerDb <<
" dB. Number of interferers = " << arrivalList.size () <<
" Interference + noise power = " << totalIntDb <<
" dB. SINR = " << rxPowerDb - totalIntDb <<
" dB.");
94 return rxPowerDb - totalIntDb;
98 UanPhyCalcSinrFhFsk::UanPhyCalcSinrFhFsk ()
102 UanPhyCalcSinrFhFsk::~UanPhyCalcSinrFhFsk ()
108 UanPhyCalcSinrFhFsk::GetTypeId (
void)
110 static TypeId tid = TypeId (
"ns3::UanPhyCalcSinrFhFsk")
111 .SetParent<Object> ()
112 .AddConstructor<UanPhyCalcSinrFhFsk> ()
113 .AddAttribute (
"NumberOfHops",
114 "Number of frequencies in hopping pattern",
116 MakeUintegerAccessor (&UanPhyCalcSinrFhFsk::m_hops),
117 MakeUintegerChecker<uint32_t> ())
132 NS_LOG_WARN (
"Calculating SINR for unsupported mode type");
138 double clearingTime = (m_hops - 1.0) * ts;
143 double maxTapDelay = 0.0;
145 for (; pit != pdp.
GetEnd (); pit++)
147 if (std::abs (pit->GetAmp ()) > maxAmp)
149 maxAmp = std::abs (pit->GetAmp ());
150 maxTapDelay = pit->GetDelay ().GetSeconds ();
155 double effRxPowerDb = rxPowerDb +
KpToDb (csp);
158 UanTransducer::ArrivalList::const_iterator it = arrivalList.begin ();
159 double intKp = -
DbToKp (effRxPowerDb);
160 for (; it != arrivalList.end (); it++)
162 UanPdp intPdp = it->GetPdp ();
163 double tDelta = std::abs (arrTime.
GetSeconds () + maxTapDelay - it->GetArrivalTime ().GetSeconds ());
168 int32_t syms = (uint32_t)( (
double) tDelta / (ts + clearingTime));
169 tDelta = tDelta - syms * (ts + clearingTime);
172 if (arrTime +
Seconds (maxTapDelay) > it->GetArrivalTime ())
174 tDelta = ts + clearingTime - tDelta;
177 double intPower = 0.0;
182 Seconds (2 * ts - tDelta + clearingTime));
188 intPower += intPdp.
SumTapsNc (start, end);
190 start = start +
Seconds (ts + clearingTime);
192 intPower += intPdp.
SumTapsNc (start, end);
194 intKp +=
DbToKp (it->GetRxPowerDb ()) * intPower;
197 double totalIntDb =
KpToDb (isiUpa + intKp +
DbToKp (ambNoiseDb));
199 NS_LOG_DEBUG (
"Calculating SINR: RxPower = " << rxPowerDb <<
" dB. Effective Rx power " << effRxPowerDb <<
" dB. Number of interferers = " << arrivalList.size () <<
" Interference + noise power = " << totalIntDb <<
" dB. SINR = " << effRxPowerDb - totalIntDb <<
" dB.");
200 return effRxPowerDb - totalIntDb;
204 UanPhyPerGenDefault::UanPhyPerGenDefault ()
209 UanPhyPerGenDefault::~UanPhyPerGenDefault ()
214 UanPhyPerGenDefault::GetTypeId (
void)
216 static TypeId tid = TypeId (
"ns3::UanPhyPerGenDefault")
217 .SetParent<Object> ()
218 .AddConstructor<UanPhyPerGenDefault> ()
219 .AddAttribute (
"Threshold",
"SINR cutoff for good packet reception",
221 MakeDoubleAccessor (&UanPhyPerGenDefault::m_thresh),
222 MakeDoubleChecker<double> ());
232 if (sinrDb >= m_thresh)
243 UanPhyPerUmodem::UanPhyPerUmodem ()
247 UanPhyPerUmodem::~UanPhyPerUmodem ()
252 TypeId UanPhyPerUmodem::GetTypeId (
void)
254 static TypeId tid = TypeId (
"ns3::UanPhyPerUmodem")
255 .SetParent<Object> ()
256 .AddConstructor<UanPhyPerUmodem> ()
262 UanPhyPerUmodem::NChooseK (uint32_t n, uint32_t k)
268 for (uint32_t i = std::max (k,n - k) + 1; i <= n; ++i)
273 for (uint32_t i = 2; i <= std::min (k,n - k); ++i)
285 { 12, 14, 16, 18, 20, 22, 24, 26, 28 };
288 33, 281, 2179, 15035LLU, 105166LLU, 692330LLU, 4580007LLU, 29692894LLU,
293 double ebno = std::pow (10.0, sinr / 10.0);
294 double perror = 1.0 / (2.0 + ebno);
306 for (uint32_t r = 0; r < 9; r++)
309 for (uint32_t k = 0; k < d[r]; k++)
311 sumd = sumd + NChooseK (d[r] - 1 + k, k) * std::pow (1 - perror, (
double) k);
313 P[r] = std::pow (perror, (
double) d[r]) * sumd;
318 for (uint32_t r = 0; r < 8; r++)
320 Pb = Pb + Bd[r] * P[r];
324 uint32_t bits = pkt->
GetSize () * 8;
327 double temp = NChooseK (bits, 0);
328 temp *= std::pow ( (1 - Pb), (
double) bits);
330 temp = NChooseK (288, 1) * Pb * std::pow ( (1 - Pb), bits - 1.0);
344 UanPhyGen::UanPhyGen ()
359 m_pg = CreateObject<UniformRandomVariable> ();
361 m_energyCallback.Nullify ();
364 UanPhyGen::~UanPhyGen ()
377 m_listeners.clear ();
385 m_transducer->Clear ();
415 m_energyCallback.Nullify ();
428 UanPhyGen::GetTypeId (
void)
433 .AddConstructor<UanPhyGen> ()
434 .AddAttribute (
"CcaThreshold",
435 "Aggregate energy of incoming signals to move to CCA Busy state dB",
437 MakeDoubleAccessor (&UanPhyGen::m_ccaThreshDb),
438 MakeDoubleChecker<double> ())
439 .AddAttribute (
"RxThreshold",
440 "Required SNR for signal acquisition in dB",
442 MakeDoubleAccessor (&UanPhyGen::m_rxThreshDb),
443 MakeDoubleChecker<double> ())
444 .AddAttribute (
"TxPower",
445 "Transmission output power in dB",
447 MakeDoubleAccessor (&UanPhyGen::m_txPwrDb),
448 MakeDoubleChecker<double> ())
449 .AddAttribute (
"RxGain",
450 "Gain added to incoming signal at receiver",
452 MakeDoubleAccessor (&UanPhyGen::m_rxGainDb),
453 MakeDoubleChecker<double> ())
454 .AddAttribute (
"SupportedModes",
455 "List of modes supported by this PHY",
457 MakeUanModesListAccessor (&UanPhyGen::m_modes),
458 MakeUanModesListChecker () )
459 .AddAttribute (
"PerModel",
460 "Functor to calculate PER based on SINR and TxMode",
462 MakePointerAccessor (&UanPhyGen::m_per),
463 MakePointerChecker<UanPhyPer> ())
464 .AddAttribute (
"SinrModel",
465 "Functor to calculate SINR based on pkt arrivals and modes",
467 MakePointerAccessor (&UanPhyGen::m_sinr),
468 MakePointerChecker<UanPhyCalcSinr> ())
469 .AddTraceSource (
"RxOk",
470 "A packet was received successfully",
472 .AddTraceSource (
"RxError",
473 "A packet was received unsuccessfully",
475 .AddTraceSource (
"Tx",
476 "Packet transmission beginning",
487 m_energyCallback = cb;
491 UanPhyGen::UpdatePowerConsumption (
const State state)
495 if (!m_energyCallback.IsNull ())
497 m_energyCallback (state);
505 NS_LOG_DEBUG (
"Energy depleted at node " << m_device->GetNode ()->GetId () <<
506 ", stopping rx/tx activities");
514 NS_LOG_DEBUG (
"PHY " << m_mac->GetAddress () <<
": Transmitting packet");
517 NS_LOG_DEBUG (
"Energy depleted, node cannot transmit any packet. Dropping.");
523 NS_LOG_DEBUG (
"PHY requested to TX while already Transmitting. Dropping packet.");
526 else if (m_state == SLEEP)
528 NS_LOG_DEBUG (
"PHY requested to TX while sleeping. Dropping packet.");
536 m_minRxSinrDb = -1e30;
540 m_transducer->Transmit (
Ptr<UanPhy> (
this), pkt, m_txPwrDb, txMode);
542 UpdatePowerConsumption (TX);
545 NS_LOG_DEBUG (
"PHY " << m_mac->GetAddress () <<
" notifying listeners");
546 NotifyListenersTxStart (
Seconds (txdelay));
547 m_txLogger (pkt, m_txPwrDb, txMode);
551 UanPhyGen::TxEndEvent ()
553 if (m_state == SLEEP || m_disabled ==
true)
555 NS_LOG_DEBUG (
"Transmission ended but node sleeping or dead");
560 if (GetInterferenceDb ( (Ptr<Packet>) 0) > m_ccaThreshDb)
563 NotifyListenersCcaStart ();
569 UpdatePowerConsumption (IDLE);
575 m_listeners.push_back (listener);
584 NS_LOG_DEBUG (
"Energy depleted, node cannot receive any packet. Dropping.");
598 double newSinrDb = CalculateSinrDb (m_pktRx, m_pktRxArrTime, m_rxRecvPwrDb, m_pktRxMode, m_pktRxPdp);
599 m_minRxSinrDb = (newSinrDb < m_minRxSinrDb) ? newSinrDb : m_minRxSinrDb;
600 NS_LOG_DEBUG (
"PHY " << m_mac->GetAddress () <<
": Starting RX in RX mode. SINR of pktRx = " << m_minRxSinrDb);
609 bool hasmode =
false;
610 for (uint32_t i = 0; i <
GetNModes (); i++)
624 double newsinr = CalculateSinrDb (pkt,
Simulator::Now (), rxPowerDb, txMode, pdp);
625 NS_LOG_DEBUG (
"PHY " << m_mac->GetAddress () <<
": Starting RX in IDLE mode. SINR = " << newsinr);
626 if (newsinr > m_rxThreshDb)
629 UpdatePowerConsumption (RX);
631 m_rxRecvPwrDb = rxPowerDb;
632 m_minRxSinrDb = newsinr;
635 m_pktRxMode = txMode;
639 NotifyListenersRxStart ();
650 if (m_state == IDLE && GetInterferenceDb ( (
Ptr<Packet>) 0) > m_ccaThreshDb)
653 NotifyListenersCcaStart ();
666 if (m_disabled || m_state == SLEEP)
675 if (GetInterferenceDb ( (Ptr<Packet>) 0) > m_ccaThreshDb)
678 NotifyListenersCcaStart ();
683 UpdatePowerConsumption (IDLE);
686 if (
m_pg->
GetValue (0, 1) > m_per->CalcPer (m_pktRx, m_minRxSinrDb, txMode))
688 m_rxOkLogger (pkt, m_minRxSinrDb, txMode);
689 NotifyListenersRxGood ();
690 if (!m_recOkCb.IsNull ())
692 m_recOkCb (pkt, m_minRxSinrDb, txMode);
698 m_rxErrLogger (pkt, m_minRxSinrDb, txMode);
699 NotifyListenersRxBad ();
700 if (!m_recErrCb.IsNull ())
702 m_recErrCb (pkt, m_minRxSinrDb);
723 return m_state == SLEEP;
728 return m_state == IDLE;
738 return m_state == RX;
743 return m_state == TX;
749 return m_state == CCABUSY;
767 m_rxThreshDb = thresh;
772 m_ccaThreshDb = thresh;
793 return m_ccaThreshDb;
834 m_transducer = trans;
835 m_transducer->AddPhy (
this);
839 UanPhyGen::SetSleepMode (
bool sleep)
844 if (!m_energyCallback.IsNull ())
846 m_energyCallback (SLEEP);
849 else if (m_state == SLEEP)
851 if (GetInterferenceDb ((Ptr<Packet>) 0) > m_ccaThreshDb)
854 NotifyListenersCcaStart ();
861 if (!m_energyCallback.IsNull ())
863 m_energyCallback (IDLE);
881 m_minRxSinrDb = -1e30;
888 if (m_state == CCABUSY && GetInterferenceDb (
Ptr<Packet> ()) < m_ccaThreshDb)
891 NotifyListenersCcaEnd ();
899 return m_sinr->CalcSinrDb (pkt, arrTime, rxPowerDb, noiseDb, mode, pdp, m_transducer->GetArrivalList ());
903 UanPhyGen::GetInterferenceDb (Ptr<Packet> pkt)
908 UanTransducer::ArrivalList::const_iterator it = arrivalList.begin ();
910 double interfPower = 0;
912 for (; it != arrivalList.end (); it++)
914 if (pkt != it->GetPacket ())
916 interfPower += DbToKp (it->GetRxPowerDb ());
920 return KpToDb (interfPower);
925 UanPhyGen::DbToKp (
double db)
927 return std::pow (10, db / 10.0);
930 UanPhyGen::KpToDb (
double kp)
932 return 10 * std::log10 (kp);
936 UanPhyGen::NotifyListenersRxStart (
void)
938 ListenerList::const_iterator it = m_listeners.begin ();
939 for (; it != m_listeners.end (); it++)
941 (*it)->NotifyRxStart ();
946 UanPhyGen::NotifyListenersRxGood (
void)
948 ListenerList::const_iterator it = m_listeners.begin ();
949 for (; it != m_listeners.end (); it++)
951 (*it)->NotifyRxEndOk ();
955 UanPhyGen::NotifyListenersRxBad (
void)
957 ListenerList::const_iterator it = m_listeners.begin ();
958 for (; it != m_listeners.end (); it++)
960 (*it)->NotifyRxEndError ();
964 UanPhyGen::NotifyListenersCcaStart (
void)
966 ListenerList::const_iterator it = m_listeners.begin ();
967 for (; it != m_listeners.end (); it++)
969 (*it)->NotifyCcaStart ();
973 UanPhyGen::NotifyListenersCcaEnd (
void)
975 ListenerList::const_iterator it = m_listeners.begin ();
976 for (; it != m_listeners.end (); it++)
978 (*it)->NotifyCcaEnd ();
983 UanPhyGen::NotifyListenersTxStart (Time duration)
985 ListenerList::const_iterator it = m_listeners.begin ();
986 for (; it != m_listeners.end (); it++)
988 (*it)->NotifyTxStart (duration);
virtual void NotifyTransStartTx(Ptr< Packet > packet, double txPowerDb, UanTxMode txMode)
virtual bool IsStateBusy(void)
virtual Ptr< UanTransducer > GetTransducer(void)
virtual double GetRxThresholdDb(void)
uint32_t GetNModes(void) const
std::vector< Tap >::const_iterator Iterator
Iterator is a standard template library constant interator.
virtual bool IsStateRx(void)
#define NS_LOG_FUNCTION(parameters)
void SetStream(int64_t stream)
Specifies the stream number for this RNG stream.
virtual void SetEnergyModelCallback(DeviceEnergyModel::ChangeStateCallback cb)
void NotifyRxDrop(Ptr< const Packet > packet)
virtual void SetReceiveErrorCallback(RxErrCallback cb)
virtual void EnergyDepletionHandler(void)
virtual void SetTransducer(Ptr< UanTransducer > trans)
#define NS_ASSERT(condition)
Ptr< UniformRandomVariable > m_pg
Provides uniform random variables.
#define NS_LOG_COMPONENT_DEFINE(name)
double SumTapsFromMaxNc(Time delay, Time duration) const
uint32_t GetSize(void) const
virtual void StartRxPacket(Ptr< Packet > pkt, double rxPowerDb, UanTxMode txMode, UanPdp pdp)
Packet arriving from channel: i.e. leading bit of packet has arrived.
virtual uint32_t GetNModes(void)
virtual void DoDispose(void)
Container for UanTxModes.
virtual double GetTxPowerDb(void)
virtual double GetCcaThresholdDb(void)
static EventId Schedule(Time const &time, MEM mem_ptr, OBJ obj)
ModulationType GetModType(void) const
void NotifyRxEnd(Ptr< const Packet > packet)
static UanTxMode CreateMode(UanTxMode::ModulationType type, uint32_t dataRateBps, uint32_t phyRateSps, uint32_t cfHz, uint32_t bwHz, uint32_t constSize, std::string name)
double GetSeconds(void) const
virtual double CalcSinrDb(Ptr< Packet > pkt, Time arrTime, double rxPowerDb, double ambNoiseDb, UanTxMode mode, UanPdp pdp, const UanTransducer::ArrivalList &arrivalList) const
virtual bool IsStateTx(void)
virtual void SetDevice(Ptr< UanNetDevice > device)
int64_t AssignStreams(int64_t stream)
uint32_t GetDataRateBps(void) const
double KpToDb(double kp) const
Converts kilopascals to dB re 1 uPa.
virtual Ptr< Packet > GetPacketRx(void) const
Abstraction of packet modulation information.
std::list< UanPacketArrival > ArrivalList
Arrival list is a standard template library list of UanPacketArrivals objects.
virtual void SetCcaThresholdDb(double thresh)
virtual void NotifyIntChange(void)
virtual double CalcSinrDb(Ptr< Packet > pkt, Time arrTime, double rxPowerDb, double ambNoiseDb, UanTxMode mode, UanPdp pdp, const UanTransducer::ArrivalList &arrivalList) const
virtual Ptr< UanChannel > GetChannel(void) const
virtual UanTxMode GetMode(uint32_t n)
virtual void SetRxThresholdDb(double thresh)
void NotifyRxBegin(Ptr< const Packet > packet)
hold objects of type Ptr<T>
virtual void SetRxGainDb(double gain)
Ptr< const TraceSourceAccessor > MakeTraceSourceAccessor(T a)
uint32_t GetCenterFreqHz(void) const
Interface for PHY event listener A class which implements this interface may register with Phy object...
virtual double CalcPer(Ptr< Packet > pkt, double sinrDb, UanTxMode mode)
double DbToKp(double db) const
Converts dB re 1 uPa to kilopascals.
virtual void SetChannel(Ptr< UanChannel > channel)
Iterator GetEnd(void) const
Base class for UAN Phy models.
uint32_t GetPhyRateSps(void) const
Time Seconds(double seconds)
create ns3::Time instances in units of seconds.
virtual bool IsStateIdle(void)
#define NS_LOG_DEBUG(msg)
void AppendMode(UanTxMode mode)
uint32_t GetBandwidthHz(void) const
virtual void SendPacket(Ptr< Packet > pkt, uint32_t modeNum)
Iterator GetBegin(void) const
virtual bool IsStateCcaBusy(void)
virtual void RegisterListener(UanPhyListener *listener)
virtual double GetRxGainDb(void)
Hold an floating point type.
virtual bool IsStateSleep(void)
virtual void SetMac(Ptr< UanMac > mac)
virtual void SetReceiveOkCallback(RxOkCallback cb)
uint32_t GetUid(void) const
double SumTapsNc(Time begin, Time end) const
static UanModesList GetDefaultModes(void)
a unique identifier for an interface.
virtual double CalcPer(Ptr< Packet > pkt, double sinrDb, UanTxMode mode)
virtual Ptr< UanNetDevice > GetDevice(void)
TypeId SetParent(TypeId tid)
virtual void SetTxPowerDb(double txpwr)