satellite-wave-form-conf.cc
Go to the documentation of this file.
1 /* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
2 /*
3  * Copyright (c) 2013 Magister Solutions Ltd
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: Sami Rantanen <sami.rantanen@magister.fi>
19  */
20 
22 
24 #include "satellite-link-results.h"
25 #include "satellite-utils.h"
26 
27 #include <ns3/boolean.h>
28 #include <ns3/double.h>
29 #include <ns3/enum.h>
30 #include <ns3/log.h>
31 #include <ns3/uinteger.h>
32 
33 #include <algorithm>
34 #include <fstream>
35 #include <iostream>
36 #include <limits>
37 #include <map>
38 #include <sstream>
39 #include <utility>
40 
41 NS_LOG_COMPONENT_DEFINE("SatWaveformConf");
42 
43 namespace ns3
44 {
45 
47  : m_waveformId(0),
48  m_modulatedBits(0),
49  m_codingRate(0.0),
50  m_modCod(SatEnums::SAT_NONVALID_MODCOD),
51  m_payloadBytes(0),
52  m_lengthInSymbols(0),
53  m_preambleLengthInSymbols(0),
54  m_ebnoRequirement(0.0)
55 {
56  NS_ASSERT(false);
57 }
58 
60  uint32_t modulatedBits,
61  double codingRate,
62  SatEnums::SatModcod_t modcod,
63  uint32_t payloadBytes,
64  uint32_t lengthInSymbols,
65  uint32_t preambleLengthInSymbols)
66  : m_waveformId(wfId),
67  m_modulatedBits(modulatedBits),
68  m_codingRate(codingRate),
69  m_modCod(modcod),
70  m_payloadBytes(payloadBytes),
71  m_lengthInSymbols(lengthInSymbols),
72  m_preambleLengthInSymbols(preambleLengthInSymbols),
73  m_ebnoRequirement(0.0)
74 {
75 }
76 
77 uint32_t
79 {
80  NS_LOG_FUNCTION(this);
81  return m_waveformId;
82 }
83 
86 {
87  NS_LOG_FUNCTION(this);
88  return m_modCod;
89 }
90 
91 uint32_t
93 {
94  NS_LOG_FUNCTION(this);
95  return m_payloadBytes;
96 }
97 
98 uint32_t
100 {
101  NS_LOG_FUNCTION(this);
102  return m_lengthInSymbols;
103 }
104 
105 uint32_t
107 {
108  NS_LOG_FUNCTION(this);
110 }
111 
112 Time
113 SatWaveform::GetBurstDuration(double symbolRateInBaud) const
114 {
115  NS_LOG_FUNCTION(this << symbolRateInBaud);
116  return Seconds(m_lengthInSymbols / symbolRateInBaud);
117 }
118 
119 Time
120 SatWaveform::GetPreambleDuration(double symbolRateInBaud) const
121 {
122  NS_LOG_FUNCTION(this << symbolRateInBaud);
123  return Seconds(m_preambleLengthInSymbols / symbolRateInBaud);
124 }
125 
126 double
127 SatWaveform::GetSpectralEfficiency(double carrierBandwidthInHz, double symbolRateInBaud) const
128 {
129  NS_LOG_FUNCTION(this << carrierBandwidthInHz << symbolRateInBaud);
131  (m_lengthInSymbols / symbolRateInBaud) / carrierBandwidthInHz;
132 }
133 
134 double
135 SatWaveform::GetThroughputInBitsPerSecond(double symbolRateInBaud) const
136 {
137  NS_LOG_FUNCTION(this << symbolRateInBaud);
139  (m_lengthInSymbols / symbolRateInBaud);
140 }
141 
142 double
143 SatWaveform::GetCNoThreshold(double symbolRateInBaud) const
144 {
145  NS_LOG_FUNCTION(this << symbolRateInBaud);
146 
152  double cnoRequirement = m_ebnoRequirement * symbolRateInBaud * m_codingRate * m_modulatedBits;
153 
154  return cnoRequirement;
155 }
156 
157 void
158 SatWaveform::SetEbNoRequirement(double ebnoRequirement)
159 {
160  NS_LOG_FUNCTION(this << ebnoRequirement);
161  m_ebnoRequirement = ebnoRequirement;
162 }
163 
164 void
165 SatWaveform::Dump(double carrierBandwidthInHz, double symbolRateInBaud) const
166 {
167  NS_LOG_FUNCTION(this << carrierBandwidthInHz << symbolRateInBaud);
168 
169  std::cout << "ModulatedBits: " << m_modulatedBits << ", CodingRate: " << m_codingRate
170  << ", Payload: " << m_payloadBytes << ", BurstLength: " << m_lengthInSymbols
171  << ", EbNoRequirement: " << SatUtils::LinearToDb(m_ebnoRequirement)
172  << ", BurstDuration: " << GetBurstDuration(symbolRateInBaud)
173  << ", Throughput: " << GetThroughputInBitsPerSecond(symbolRateInBaud)
174  << ", SpectralEfficiency: "
175  << GetSpectralEfficiency(carrierBandwidthInHz, symbolRateInBaud)
176  << ", C/No threshold: " << SatUtils::LinearToDb(GetCNoThreshold(symbolRateInBaud))
177  << std::endl;
178 }
179 
180 NS_OBJECT_ENSURE_REGISTERED(SatWaveformConf);
181 
183  : m_waveforms(),
184  m_targetBLER(0.00001),
185  m_acmEnabled(false),
186  m_defaultWfId(3),
187  m_minWfId(0),
188  m_maxWfId(23),
189  m_burstLength(SatEnums::UNKNOWN_BURST)
190 {
191  // default constructor should not be used
192  NS_ASSERT(false);
193 }
194 
195 SatWaveformConf::SatWaveformConf(std::string filePathName)
196  : m_waveforms(),
197  m_targetBLER(0.00001),
198  m_acmEnabled(false),
199  m_defaultWfId(3),
200  m_minWfId(0),
201  m_maxWfId(23),
202  m_burstLength(SatEnums::UNKNOWN_BURST)
203 {
204  NS_LOG_FUNCTION(this);
205  ReadFromFile(filePathName);
206 
207  ObjectBase::ConstructSelf(AttributeConstructionList());
208 
209  switch (m_burstLength)
210  {
213  break;
216  break;
220  break;
221  default:
222  NS_FATAL_ERROR("Incorrect choice of burst length.");
223  }
224 }
225 
226 TypeId
228 {
229  static TypeId tid = TypeId("ns3::SatWaveformConf")
230  .SetParent<Object>()
231  .AddAttribute("TargetBLER",
232  "Block error rate target",
233  DoubleValue(0.00001),
234  MakeDoubleAccessor(&SatWaveformConf::m_targetBLER),
235  MakeDoubleChecker<double>())
236  .AddAttribute("AcmEnabled",
237  "Enable ACM",
238  BooleanValue(false),
239  MakeBooleanAccessor(&SatWaveformConf::m_acmEnabled),
240  MakeBooleanChecker())
241  .AddAttribute("DefaultWfId",
242  "Default waveform id",
243  UintegerValue(3),
244  MakeUintegerAccessor(&SatWaveformConf::m_defaultWfId),
245  MakeUintegerChecker<uint32_t>(1, 22))
246  .AddAttribute("BurstLength",
247  "Default burst length",
249  MakeEnumAccessor(&SatWaveformConf::m_burstLength),
250  MakeEnumChecker(SatEnums::SHORT_BURST,
251  "ShortBurst",
253  "LongBurst",
255  "ShortAndLongBurst"))
256  .AddConstructor<SatWaveformConf>();
257  return tid;
258 }
259 
260 TypeId
262 {
263  NS_LOG_FUNCTION(this);
264 
265  return GetTypeId();
266 }
267 
269 {
270  NS_LOG_FUNCTION(this);
271 }
272 
273 void
274 SatWaveformConf::ReadFromFile(std::string filePathName)
275 {
276  NS_LOG_FUNCTION(this << filePathName);
277 
278  std::vector<uint32_t> wfIds;
279 
280  // READ FROM THE SPECIFIED INPUT FILE
281  std::ifstream* ifs = new std::ifstream(filePathName.c_str(), std::ifstream::in);
282 
283  if (!ifs->is_open())
284  {
285  // script might be launched by test.py, try a different base path
286  delete ifs;
287  filePathName = "../../" + filePathName;
288  ifs = new std::ifstream(filePathName.c_str(), std::ifstream::in);
289 
290  if (!ifs->is_open())
291  {
292  NS_FATAL_ERROR("The file " << filePathName << " is not found.");
293  }
294  }
295 
296  // Row vector containing the waveform information for a certain waveform index
297  std::vector<double> rowVector;
298 
299  // Start conditions
300  int32_t wfIndex, modulatedBits, payloadBytes, durationInSymbols, preambleDurationInSymbols;
301  std::string sCodingRate;
302 
303  // Read line by line
304  std::string line;
305 
306  while (std::getline(*ifs, line))
307  {
308  std::istringstream line_ss(line);
309 
310  // Unpack values
311  if (!(line_ss >> wfIndex >> modulatedBits >> sCodingRate >> payloadBytes >>
312  durationInSymbols))
313  {
314  NS_FATAL_ERROR("SatWaveformConf::ReadFromFile - Waveform conf vector has unexpected "
315  "amount of elements!");
316  }
317  // Try to unpack preambule duration
318  if (!(line_ss >> preambleDurationInSymbols))
319  {
320  preambleDurationInSymbols = 0;
321  }
322 
323  // Store temporarily all wfIds
324  wfIds.push_back(wfIndex);
325 
326  // Convert the coding rate fraction into double
327  std::istringstream ss(sCodingRate);
328  std::string token;
329  std::vector<uint32_t> output;
330 
331  while (std::getline(ss, token, '/'))
332  {
333  uint32_t i;
334  std::stringstream s;
335  s.str(token);
336  s >> i;
337  output.push_back(i);
338  }
339 
340  if (output.size() != 2)
341  {
342  NS_FATAL_ERROR("SatWaveformConf::ReadFromFile - Temp fraction vector has unexpected "
343  "amount of elements!");
344  }
345 
346  double dCodingRate = double(output[0]) / output[1];
347 
348  // Convert modulated bits and coding rate to MODCOD enum
349  SatEnums::SatModcod_t modcod = ConvertToModCod(modulatedBits, output[0], output[1]);
350 
351  // Create new waveform and insert it to the waveform map
352  Ptr<SatWaveform> wf = Create<SatWaveform>(wfIndex,
353  modulatedBits,
354  dCodingRate,
355  modcod,
356  payloadBytes,
357  durationInSymbols,
358  preambleDurationInSymbols);
359  m_waveforms.insert(std::make_pair(wfIndex, wf));
360  }
361 
362  ifs->close();
363  delete ifs;
364 
365  // Note, currently we assume that the waveform ids are consecutive!
366  m_minWfId = *std::min_element(wfIds.begin(), wfIds.end());
367  m_maxWfId = *std::max_element(wfIds.begin(), wfIds.end());
368 }
369 
370 void
371 SatWaveformConf::InitializeEbNoRequirements(Ptr<SatLinkResultsRtn> linkResults)
372 {
373  NS_LOG_FUNCTION(this);
374 
375  for (std::map<uint32_t, Ptr<SatWaveform>>::iterator it = m_waveforms.begin();
376  it != m_waveforms.end();
377  ++it)
378  {
384  double ebnoRequirementDb = linkResults->GetEbNoDb(it->first, m_targetBLER);
385  it->second->SetEbNoRequirement(SatUtils::DbToLinear(ebnoRequirementDb));
386  }
387 }
388 
389 Ptr<SatWaveform>
390 SatWaveformConf::GetWaveform(uint32_t wfId) const
391 {
392  NS_LOG_FUNCTION(this << wfId);
393 
394  if (m_minWfId > wfId || wfId > m_maxWfId)
395  {
396  NS_FATAL_ERROR("SatWaveformConf::GetWaveform - unsupported waveform id: " << wfId);
397  }
398 
399  return m_waveforms.at(wfId);
400 }
401 
402 uint32_t
404 {
405  NS_LOG_FUNCTION(this << m_defaultWfId);
406 
408  {
409  NS_FATAL_ERROR(
410  "SatWaveformConf::GetDefaultWaveformId - unsupported waveform id: " << m_defaultWfId);
411  }
412 
413  return m_defaultWfId;
414 }
415 
416 bool
418  double symbolRateInBaud,
419  uint32_t& wfId,
420  double& cnoThreshold,
421  uint32_t burstLength) const
422 {
423  NS_LOG_FUNCTION(this << cno << symbolRateInBaud << wfId << cnoThreshold << burstLength);
424 
425  bool success = false;
426 
427  // If ACM is disabled, return the default waveform
428  if (!m_acmEnabled || std::isnan(cno))
429  {
430  wfId = m_defaultWfId;
431  success = true;
432  return success;
433  }
434 
435  // Return the waveform with best spectral efficiency
436  for (std::map<uint32_t, Ptr<SatWaveform>>::const_reverse_iterator rit = m_waveforms.rbegin();
437  rit != m_waveforms.rend();
438  ++rit)
439  {
440  if (rit->second->GetBurstLengthInSymbols() == burstLength)
441  {
442  double cnoThr = rit->second->GetCNoThreshold(symbolRateInBaud);
443  // The first waveform over the threshold
444  if (cnoThr <= cno)
445  {
446  wfId = rit->first;
447  cnoThreshold = cnoThr;
448  success = true;
449  break;
450  }
451  }
452  }
453 
454  NS_LOG_INFO("Get best waveform in RTN link (ACM)! CNo: "
455  << SatUtils::LinearToDb(cno) << ", Symbol rate: " << symbolRateInBaud
456  << ", burst length: " << burstLength << ", WF: " << wfId
457  << ", CNo threshold: " << SatUtils::LinearToDb(cnoThreshold));
458 
459  return success;
460 }
461 
462 bool
463 SatWaveformConf::GetMostRobustWaveformId(uint32_t& wfId, uint32_t burstLength) const
464 {
465  NS_LOG_FUNCTION(this << burstLength);
466 
467  bool found = false;
468 
469  uint32_t payloadInBytes = std::numeric_limits<uint32_t>::max();
470 
471  // find the waveform with the more robust waveform than previous one
472  for (std::map<uint32_t, Ptr<SatWaveform>>::const_reverse_iterator rit = m_waveforms.rbegin();
473  rit != m_waveforms.rend();
474  ++rit)
475  {
476  if (rit->second->GetBurstLengthInSymbols() == burstLength)
477  {
478  // The waveform more robust than previous one
479  if (rit->second->GetPayloadInBytes() < payloadInBytes)
480  {
481  payloadInBytes = rit->second->GetPayloadInBytes();
482  wfId = rit->first;
483  found = true;
484  }
485  }
486  }
487 
488  return found;
489 }
490 
491 void
492 SatWaveformConf::Dump(double carrierBandwidthInHz, double symbolRateInBaud) const
493 {
494  NS_LOG_FUNCTION(this << carrierBandwidthInHz << symbolRateInBaud);
495 
496  for (std::map<uint32_t, Ptr<SatWaveform>>::const_iterator it = m_waveforms.begin();
497  it != m_waveforms.end();
498  ++it)
499  {
500  std::cout << "WaveformId: " << it->first << " ";
501  it->second->Dump(carrierBandwidthInHz, symbolRateInBaud);
502  }
503 }
504 
506 SatWaveformConf::GetModCod(uint32_t wfId) const
507 {
508  NS_LOG_FUNCTION(this << wfId);
509 
510  if (m_minWfId > wfId || wfId > m_maxWfId)
511  {
512  NS_FATAL_ERROR("SatWaveformConf::GetModCod - unsupported waveform id: " << wfId);
513  }
514 
515  std::map<uint32_t, Ptr<SatWaveform>>::const_iterator it = m_waveforms.find(wfId);
516 
517  if (it != m_waveforms.end())
518  {
519  return m_waveforms.at(wfId)->GetModCod();
520  }
521  else
522  {
523  NS_FATAL_ERROR("Waveform id: " << wfId << " not found in the waveform container!");
524  }
525 
527 }
528 
530 SatWaveformConf::ConvertToModCod(uint32_t modulatedBits,
531  uint32_t codingRateNumerator,
532  uint32_t codingRateDenominator) const
533 {
534  NS_LOG_FUNCTION(this << modulatedBits << codingRateNumerator << codingRateDenominator);
535 
536  switch (modulatedBits)
537  {
538  // BPSK
539  case 1: {
540  if (codingRateNumerator == 1 && codingRateDenominator == 3)
541  {
543  }
544  else
545  {
546  NS_FATAL_ERROR("Unsupported coding rate numerator: "
547  << codingRateNumerator << ", denominator: " << codingRateDenominator);
548  }
549  break;
550  }
551  // QPSK
552  case 2: {
553  if (codingRateNumerator == 1 && codingRateDenominator == 3)
554  {
556  }
557  else if (codingRateNumerator == 1 && codingRateDenominator == 2)
558  {
560  }
561  else if (codingRateNumerator == 2 && codingRateDenominator == 3)
562  {
564  }
565  else if (codingRateNumerator == 3 && codingRateDenominator == 4)
566  {
568  }
569  else if (codingRateNumerator == 5 && codingRateDenominator == 6)
570  {
572  }
573  else
574  {
575  NS_FATAL_ERROR("Unsupported coding rate numerator: "
576  << codingRateNumerator << ", denominator: " << codingRateDenominator);
577  }
578  break;
579  }
580  // 8PSK
581  case 3: {
582  if (codingRateNumerator == 2 && codingRateDenominator == 3)
583  {
585  }
586  else if (codingRateNumerator == 3 && codingRateDenominator == 4)
587  {
589  }
590  else if (codingRateNumerator == 5 && codingRateDenominator == 6)
591  {
593  }
594  else
595  {
596  NS_FATAL_ERROR("Unsupported coding rate numerator: "
597  << codingRateNumerator << ", denominator: " << codingRateDenominator);
598  }
599  break;
600  }
601  // 16 QAM
602  case 4: {
603  if (codingRateNumerator == 3 && codingRateDenominator == 4)
604  {
606  }
607  else if (codingRateNumerator == 5 && codingRateDenominator == 6)
608  {
610  }
611  else
612  {
613  NS_FATAL_ERROR("Unsupported coding rate numerator: "
614  << codingRateNumerator << ", denominator: " << codingRateDenominator);
615  }
616 
617  break;
618  }
619  default: {
620  NS_FATAL_ERROR("Unsupported modulated bits:" << modulatedBits);
621  break;
622  }
623  }
625 }
626 
627 } // namespace ns3
SatEnums class is for simplifying the use of enumerators in the satellite module.
SatModcod_t
Modulation scheme and coding rate for DVB-S2.
static T DbToLinear(T db)
Converts decibels to linear.
static T LinearToDb(T linear)
Converts linear to decibels.
This class implements the available waveform configurations of DVB-RCS2 return link.
virtual ~SatWaveformConf()
Destructor for SatWaveformConf.
bool GetMostRobustWaveformId(uint32_t &wfId, uint32_t burstLength=SHORT_BURST_LENGTH) const
Get the most robust waveform id based payload of the waveform in bytes.
uint32_t m_defaultWfId
Default waveform id.
Ptr< SatWaveform > GetWaveform(uint32_t wfId) const
Get the details of a certain waveform.
void Dump(double carrierBandwidthInHz, double symbolRateInBaud) const
Dump the contents of the waveform.
void ReadFromFile(std::string filePathName)
Read the waveform table from a file.
SatEnums::SatWaveFormBurstLength_t m_burstLength
Burst length used.
bool GetBestWaveformId(double cno, double symbolRateInBaud, uint32_t &wfId, double &cnoThreshold, uint32_t burstLength=SHORT_BURST_LENGTH) const
Get the best waveform id based on UT's C/No and C/No thresholds.
std::map< uint32_t, Ptr< SatWaveform > > m_waveforms
Container of the waveforms.
static const uint32_t LONG_BURST_LENGTH
Static variable defining long burst length.
virtual TypeId GetInstanceTypeId(void) const
Get the type ID of instance.
BurstLengthContainer_t m_supportedBurstLengthsInSymbols
Container to store supported burst lengths.
SatEnums::SatModcod_t GetModCod(uint32_t wfId) const
Get MODCOD enum corresponding to a waveform id.
void InitializeEbNoRequirements(Ptr< SatLinkResultsRtn > linkResults)
Initialize the Eb/No requirements of the waveforms based on the used return link results.
double m_targetBLER
Block error rate target for the waveforms.
bool m_acmEnabled
Flag to indicate whether ACM is enabled or disabled.
static const uint32_t SHORT_BURST_LENGTH
Static variable defining short burst length.
uint32_t GetDefaultWaveformId() const
Get default waveform id.
static TypeId GetTypeId(void)
Derived from Object.
SatWaveformConf()
Default constructor, which is not to be used.
SatEnums::SatModcod_t ConvertToModCod(uint32_t modulatedBits, uint32_t codingRateNumerator, uint32_t codingRateDenominator) const
Convert modulated bits and coding rate to a MODCOD enum.
uint32_t m_minWfId
Minimum and maximum waveform ids.
void SetEbNoRequirement(double ebnoRequirement)
Set the Eb/No requirement of the waveform in linear domain based on the used link results.
SatWaveform()
Default constructor for SatWaveform.
uint32_t m_payloadBytes
Payload in bytes.
uint32_t m_lengthInSymbols
Length of the burst in symbols.
double m_codingRate
Coding rate.
double m_ebnoRequirement
Eb/No threshold calculated with a certain BLER target from the link results.
uint32_t GetWaveformId() const
Get waveform id.
double GetCNoThreshold(double symbolRateInBaud) const
Get the C/No threshold of the waveform in linear domain.
SatEnums::SatModcod_t m_modCod
MODCOD enum.
uint32_t GetBurstLengthInSymbols() const
Get burst length of the waveform in symbols.
SatEnums::SatModcod_t GetModCod() const
Get MODCOD enum.
Time GetBurstDuration(double symbolRateInBaud) const
Get/calculate the burst duration of a waveform based on symbol rate.
Time GetPreambleDuration(double symbolRateInBaud) const
Get/calculate the preamble duration of a waveform based on symbol rate.
double GetSpectralEfficiency(double carrierBandwidthInHz, double symbolRateInBaud) const
Get/calculate the spectral efficiency of a waveform.
uint32_t GetPreambleLengthInSymbols() const
Get preamble length of the waveform in symbols.
uint32_t GetPayloadInBytes() const
Get payload of a waveform in bytes.
double GetThroughputInBitsPerSecond(double symbolRateInBaud) const
Get/calculate the throughput of a waveform based on symbol rate.
void Dump(double carrierBandwidthInHz, double symbolRateInBaud) const
Dump the contents of the waveform.
uint32_t m_waveformId
Id of this waveform.
uint32_t m_modulatedBits
Modulated bits QPSK = 2 8PSK = 3 16QAM = 4.
uint32_t m_preambleLengthInSymbols
Length of the preamble in symbols.
constexpr uint32_t BITS_PER_BYTE
Number of bits in a byte.
SatArqSequenceNumber is handling the sequence numbers for the ARQ process.