A Discrete-Event Network Simulator
API
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Groups Pages
half-duplex-ideal-phy.cc
1 /* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
2 /*
3  * Copyright (c) 2009 CTTC
4  *
5  * This program is free software; you can redistribute it and/or modify
6  * it under the terms of the GNU General Public License version 2 as
7  * published by the Free Software Foundation;
8  *
9  * This program is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12  * GNU General Public License for more details.
13  *
14  * You should have received a copy of the GNU General Public License
15  * along with this program; if not, write to the Free Software
16  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
17  *
18  * Author: Nicola Baldo <nbaldo@cttc.es>
19  */
20 
21 #include <ns3/object-factory.h>
22 #include <ns3/log.h>
23 #include <cmath>
24 #include <ns3/simulator.h>
25 #include <ns3/trace-source-accessor.h>
26 #include <ns3/packet-burst.h>
27 #include <ns3/callback.h>
28 #include <ns3/antenna-model.h>
29 
30 #include "half-duplex-ideal-phy.h"
31 #include "half-duplex-ideal-phy-signal-parameters.h"
32 #include "spectrum-error-model.h"
33 
34 
35 NS_LOG_COMPONENT_DEFINE ("HalfDuplexIdealPhy");
36 
37 namespace ns3 {
38 
39 NS_OBJECT_ENSURE_REGISTERED (HalfDuplexIdealPhy);
40 
41 HalfDuplexIdealPhy::HalfDuplexIdealPhy ()
42  : m_mobility (0),
43  m_netDevice (0),
44  m_channel (0),
45  m_txPsd (0),
46  m_state (IDLE)
47 {
48  m_interference.SetErrorModel (CreateObject<ShannonSpectrumErrorModel> ());
49 }
50 
51 
52 HalfDuplexIdealPhy::~HalfDuplexIdealPhy ()
53 {
54 }
55 
56 void
58 {
59  NS_LOG_FUNCTION (this);
60  m_mobility = 0;
61  m_netDevice = 0;
62  m_channel = 0;
63  m_txPsd = 0;
64  m_rxPsd = 0;
65  m_txPacket = 0;
66  m_rxPacket = 0;
67  m_phyMacTxEndCallback = MakeNullCallback< void, Ptr<const Packet> > ();
68  m_phyMacRxStartCallback = MakeNullCallback< void > ();
69  m_phyMacRxEndErrorCallback = MakeNullCallback< void > ();
70  m_phyMacRxEndOkCallback = MakeNullCallback< void, Ptr<Packet> > ();
72 }
73 
74 std::ostream& operator<< (std::ostream& os, HalfDuplexIdealPhy::State s)
75 {
76  switch (s)
77  {
78  case HalfDuplexIdealPhy::IDLE:
79  os << "IDLE";
80  break;
81  case HalfDuplexIdealPhy::RX:
82  os << "RX";
83  break;
84  case HalfDuplexIdealPhy::TX:
85  os << "TX";
86  break;
87  default:
88  os << "UNKNOWN";
89  break;
90  }
91  return os;
92 }
93 
94 
95 TypeId
96 HalfDuplexIdealPhy::GetTypeId (void)
97 {
98  static TypeId tid = TypeId ("ns3::HalfDuplexIdealPhy")
99  .SetParent<SpectrumPhy> ()
100  .AddConstructor<HalfDuplexIdealPhy> ()
101  .AddAttribute ("Rate",
102  "The PHY rate used by this device",
103  DataRateValue (DataRate ("1Mbps")),
104  MakeDataRateAccessor (&HalfDuplexIdealPhy::SetRate,
106  MakeDataRateChecker ())
107  .AddTraceSource ("TxStart",
108  "Trace fired when a new transmission is started",
109  MakeTraceSourceAccessor (&HalfDuplexIdealPhy::m_phyTxStartTrace))
110  .AddTraceSource ("TxEnd",
111  "Trace fired when a previosuly started transmission is finished",
112  MakeTraceSourceAccessor (&HalfDuplexIdealPhy::m_phyTxEndTrace))
113  .AddTraceSource ("RxStart",
114  "Trace fired when the start of a signal is detected",
115  MakeTraceSourceAccessor (&HalfDuplexIdealPhy::m_phyRxStartTrace))
116  .AddTraceSource ("RxAbort",
117  "Trace fired when a previously started RX is aborted before time",
118  MakeTraceSourceAccessor (&HalfDuplexIdealPhy::m_phyRxAbortTrace))
119  .AddTraceSource ("RxEndOk",
120  "Trace fired when a previosuly started RX terminates successfully",
121  MakeTraceSourceAccessor (&HalfDuplexIdealPhy::m_phyRxEndOkTrace))
122  .AddTraceSource ("RxEndError",
123  "Trace fired when a previosuly started RX terminates with an error (packet is corrupted)",
124  MakeTraceSourceAccessor (&HalfDuplexIdealPhy::m_phyRxEndErrorTrace))
125  ;
126  return tid;
127 }
128 
129 
130 
131 Ptr<NetDevice>
133 {
134  NS_LOG_FUNCTION (this);
135  return m_netDevice;
136 }
137 
138 
141 {
142  NS_LOG_FUNCTION (this);
143  return m_mobility;
144 }
145 
146 
147 void
149 {
150  NS_LOG_FUNCTION (this << d);
151  m_netDevice = d;
152 }
153 
154 
155 void
157 {
158  NS_LOG_FUNCTION (this << m);
159  m_mobility = m;
160 }
161 
162 
163 void
165 {
166  NS_LOG_FUNCTION (this << c);
167  m_channel = c;
168 }
169 
172 {
173  if (m_txPsd)
174  {
175  return m_txPsd->GetSpectrumModel ();
176  }
177  else
178  {
179  return 0;
180  }
181 }
182 
183 void
185 {
186  NS_LOG_FUNCTION (this << txPsd);
187  NS_ASSERT (txPsd);
188  m_txPsd = txPsd;
189  NS_LOG_INFO ( *txPsd << *m_txPsd);
190 }
191 
192 void
194 {
195  NS_LOG_FUNCTION (this << noisePsd);
196  NS_ASSERT (noisePsd);
197  m_interference.SetNoisePowerSpectralDensity (noisePsd);
198 }
199 
200 void
202 {
203  NS_LOG_FUNCTION (this << rate);
204  m_rate = rate;
205 }
206 
207 DataRate
209 {
210  NS_LOG_FUNCTION (this);
211  return m_rate;
212 }
213 
214 
215 void
217 {
218  NS_LOG_FUNCTION (this);
219  m_phyMacTxEndCallback = c;
220 }
221 
222 void
224 {
225  NS_LOG_FUNCTION (this);
226  m_phyMacRxStartCallback = c;
227 }
228 
229 
230 void
232 {
233  NS_LOG_FUNCTION (this);
234  m_phyMacRxEndErrorCallback = c;
235 }
236 
237 
238 void
240 {
241  NS_LOG_FUNCTION (this);
242  m_phyMacRxEndOkCallback = c;
243 }
244 
247 {
248  NS_LOG_FUNCTION (this);
249  return m_antenna;
250 }
251 
252 void
254 {
255  NS_LOG_FUNCTION (this << a);
256  m_antenna = a;
257 }
258 
259 void
260 HalfDuplexIdealPhy::ChangeState (State newState)
261 {
262  NS_LOG_LOGIC (this << " state: " << m_state << " -> " << newState);
263  m_state = newState;
264 }
265 
266 bool
268 {
269  NS_LOG_FUNCTION (this << p);
270  NS_LOG_LOGIC (this << "state: " << m_state);
271 
272  m_phyTxStartTrace (p);
273 
274  switch (m_state)
275  {
276  case RX:
277  AbortRx ();
278  // fall through
279 
280  case IDLE:
281  {
282  m_txPacket = p;
283  ChangeState (TX);
284  Ptr<HalfDuplexIdealPhySignalParameters> txParams = Create<HalfDuplexIdealPhySignalParameters> ();
285  double txTimeSeconds = m_rate.CalculateTxTime (p->GetSize ());
286  txParams->duration = Seconds (txTimeSeconds);
287  txParams->txPhy = GetObject<SpectrumPhy> ();
288  txParams->txAntenna = m_antenna;
289  txParams->psd = m_txPsd;
290  txParams->data = m_txPacket;
291 
292  NS_LOG_LOGIC (this << " tx power: " << 10 * std::log10 (Integral (*(txParams->psd))) + 30 << " dBm");
293  m_channel->StartTx (txParams);
294  Simulator::Schedule (Seconds (txTimeSeconds), &HalfDuplexIdealPhy::EndTx, this);
295  }
296  break;
297 
298  case TX:
299 
300  return true;
301  break;
302  }
303  return false;
304 }
305 
306 
307 void
308 HalfDuplexIdealPhy::EndTx ()
309 {
310  NS_LOG_FUNCTION (this);
311  NS_LOG_LOGIC (this << " state: " << m_state);
312 
313  NS_ASSERT (m_state == TX);
314 
315  m_phyTxEndTrace (m_txPacket);
316 
317  if (!m_phyMacTxEndCallback.IsNull ())
318  {
319  m_phyMacTxEndCallback (m_txPacket);
320  }
321 
322  m_txPacket = 0;
323  ChangeState (IDLE);
324 }
325 
326 
327 void
329 {
330  NS_LOG_FUNCTION (this << spectrumParams);
331  NS_LOG_LOGIC (this << " state: " << m_state);
332  NS_LOG_LOGIC (this << " rx power: " << 10 * std::log10 (Integral (*(spectrumParams->psd))) + 30 << " dBm");
333 
334  // interference will happen regardless of the state of the receiver
335  m_interference.AddSignal (spectrumParams->psd, spectrumParams->duration);
336 
337  // the device might start RX only if the signal is of a type understood by this device
338  // this corresponds in real devices to preamble detection
339  Ptr<HalfDuplexIdealPhySignalParameters> rxParams = DynamicCast<HalfDuplexIdealPhySignalParameters> (spectrumParams);
340  if (rxParams != 0)
341  {
342  // signal is of known type
343  switch (m_state)
344  {
345  case TX:
346  // the PHY will not notice this incoming signal
347  break;
348 
349  case RX:
350  // we should check if we should re-sync on a new incoming signal and discard the old one
351  // (somebody calls this the "capture" effect)
352  // criteria considered to do might include the following:
353  // 1) signal strength (e.g., as returned by rxPsd.Norm ())
354  // 2) how much time has passed since previous RX attempt started
355  // if re-sync (capture) is done, then we should call AbortRx ()
356  break;
357 
358  case IDLE:
359  // preamble detection and synchronization is supposed to be always successful.
360 
361  Ptr<Packet> p = rxParams->data;
362  m_phyRxStartTrace (p);
363  m_rxPacket = p;
364  m_rxPsd = rxParams->psd;
365  ChangeState (RX);
366  if (!m_phyMacRxStartCallback.IsNull ())
367  {
368  NS_LOG_LOGIC (this << " calling m_phyMacRxStartCallback");
369  m_phyMacRxStartCallback ();
370  }
371  else
372  {
373  NS_LOG_LOGIC (this << " m_phyMacRxStartCallback is NULL");
374  }
375  m_interference.StartRx (p, rxParams->psd);
376  NS_LOG_LOGIC (this << " scheduling EndRx with delay " << rxParams->duration);
377  m_endRxEventId = Simulator::Schedule (rxParams->duration, &HalfDuplexIdealPhy::EndRx, this);
378 
379  break;
380 
381  }
382  }
383  else // rxParams == 0
384  {
385  NS_LOG_LOGIC (this << " signal of unknown type");
386  }
387 
388  NS_LOG_LOGIC (this << " state: " << m_state);
389 }
390 
391 
392 void
393 HalfDuplexIdealPhy::AbortRx ()
394 {
395  NS_LOG_FUNCTION (this);
396  NS_LOG_LOGIC (this << "state: " << m_state);
397 
398  NS_ASSERT (m_state == RX);
399  m_interference.AbortRx ();
400  m_phyRxAbortTrace (m_rxPacket);
401  m_endRxEventId.Cancel ();
402  m_rxPacket = 0;
403  ChangeState (IDLE);
404 }
405 
406 
407 void
408 HalfDuplexIdealPhy::EndRx ()
409 {
410  NS_LOG_FUNCTION (this);
411  NS_LOG_LOGIC (this << " state: " << m_state);
412 
413  NS_ASSERT (m_state == RX);
414 
415  bool rxOk = m_interference.EndRx ();
416 
417  if (rxOk)
418  {
419  m_phyRxEndOkTrace (m_rxPacket);
420  if (!m_phyMacRxEndOkCallback.IsNull ())
421  {
422  NS_LOG_LOGIC (this << " calling m_phyMacRxEndOkCallback");
423  m_phyMacRxEndOkCallback (m_rxPacket);
424  }
425  else
426  {
427  NS_LOG_LOGIC (this << " m_phyMacRxEndOkCallback is NULL");
428  }
429  }
430  else
431  {
432  m_phyRxEndErrorTrace (m_rxPacket);
433  if (!m_phyMacRxEndErrorCallback.IsNull ())
434  {
435  NS_LOG_LOGIC (this << " calling m_phyMacRxEndErrorCallback");
436  m_phyMacRxEndErrorCallback ();
437  }
438  else
439  {
440  NS_LOG_LOGIC (this << " m_phyMacRxEndErrorCallback is NULL");
441  }
442  }
443 
444  ChangeState (IDLE);
445  m_rxPacket = 0;
446  m_rxPsd = 0;
447 }
448 
449 
450 
451 } // namespace ns3
void SetGenericPhyTxEndCallback(GenericPhyTxEndCallback c)
#define NS_LOG_FUNCTION(parameters)
Definition: log.h:311
double Integral(const SpectrumValue &arg)
bool StartTx(Ptr< Packet > p)
#define NS_ASSERT(condition)
Definition: assert.h:64
void SetNoisePowerSpectralDensity(Ptr< const SpectrumValue > noisePsd)
void SetGenericPhyRxStartCallback(GenericPhyRxStartCallback c)
#define NS_LOG_COMPONENT_DEFINE(name)
Definition: log.h:122
uint32_t GetSize(void) const
Definition: packet.h:620
virtual void DoDispose(void)
Definition: object.cc:335
#define NS_LOG_INFO(msg)
Definition: log.h:264
void AddSignal(Ptr< const SpectrumValue > spd, const Time duration)
static EventId Schedule(Time const &time, MEM mem_ptr, OBJ obj)
Definition: simulator.h:820
Ptr< MobilityModel > GetMobility()
void StartRx(Ptr< SpectrumSignalParameters > params)
void StartRx(Ptr< const Packet > p, Ptr< const SpectrumValue > rxPsd)
Class for representing data rates.
Definition: data-rate.h:71
double CalculateTxTime(uint32_t bytes) const
Calculate transmission time.
Definition: data-rate.cc:229
void SetDevice(Ptr< NetDevice > d)
void SetAntenna(Ptr< AntennaModel > a)
void SetGenericPhyRxEndOkCallback(GenericPhyRxEndOkCallback c)
Ptr< AntennaModel > GetRxAntenna()
#define NS_LOG_LOGIC(msg)
Definition: log.h:334
void SetNoisePowerSpectralDensity(Ptr< const SpectrumValue > noisePsd)
std::ostream & operator<<(std::ostream &os, const Angles &a)
Definition: angles.cc:43
Ptr< const TraceSourceAccessor > MakeTraceSourceAccessor(T a)
void SetGenericPhyRxEndErrorCallback(GenericPhyRxEndErrorCallback c)
Time Seconds(double seconds)
create ns3::Time instances in units of seconds.
Definition: nstime.h:586
void Cancel(void)
Definition: event-id.cc:47
void SetChannel(Ptr< SpectrumChannel > c)
void SetMobility(Ptr< MobilityModel > m)
void SetTxPowerSpectralDensity(Ptr< SpectrumValue > txPsd)
Ptr< const SpectrumModel > GetRxSpectrumModel() const