Skip to content

Commit bfe217f

Browse files
maribunondetalle
andauthored
Add CodingRate's stream insertion and extraction operators + tidy up LoraPhy::GetOnAirTime func (#212)
* CodingRate: add operator<< and operator>> This makes logging easier and allows passing in a CodingRate from command line. * Convert enum CodingRate to enum class * LoraPhy::GetOnAirTime(): explicit casts to double --------- Co-authored-by: Alessandro Aimi <[email protected]>
1 parent 1e62726 commit bfe217f

7 files changed

Lines changed: 92 additions & 30 deletions

File tree

examples/aloha-throughput.cc

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -242,7 +242,7 @@ main(int argc, char* argv[])
242242
LoraTxParameters txParams;
243243
txParams.sf = sf;
244244
txParams.headerDisabled = false;
245-
txParams.codingRate = CODING_RATE_4_5;
245+
txParams.codingRate = CodingRate::CR_4_5;
246246
txParams.bandwidthHz = 125000;
247247
txParams.nPreamble = 8;
248248
txParams.crcEnabled = true;

model/end-device-lorawan-mac.cc

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -96,7 +96,7 @@ EndDeviceLorawanMac::EndDeviceLorawanMac()
9696
: m_nbTrans(1),
9797
m_dataRate(0),
9898
m_txPowerDbm(14),
99-
m_codingRate(CODING_RATE_4_5),
99+
m_codingRate(CodingRate::CR_4_5),
100100
// LoraWAN default
101101
m_headerDisabled(false),
102102
// LoraWAN default

model/end-device-lorawan-mac.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ namespace ns3
2424
namespace lorawan
2525
{
2626

27-
enum CodingRate : uint8_t;
27+
enum class CodingRate : uint8_t;
2828

2929
/**
3030
* @ingroup lorawan

model/gateway-lorawan-mac.cc

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -69,7 +69,7 @@ GatewayLorawanMac::Send(Ptr<Packet> packet)
6969
LoraTxParameters params;
7070
params.sf = GetSfFromDataRate(dataRate);
7171
params.headerDisabled = false;
72-
params.codingRate = CODING_RATE_4_5;
72+
params.codingRate = CodingRate::CR_4_5;
7373
params.bandwidthHz = GetBandwidthFromDataRate(dataRate);
7474
params.nPreamble = 8;
7575
params.crcEnabled = true;

model/lora-phy.cc

Lines changed: 64 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -164,24 +164,28 @@ LoraPhy::GetOnAirTime(Ptr<Packet> packet, LoraTxParameters txParams)
164164
double tSym = GetTSym(txParams).GetSeconds();
165165

166166
// Compute the preamble duration
167-
double tPreamble = (double(txParams.nPreamble) + 4.25) * tSym;
167+
auto nPreamble = static_cast<double>(txParams.nPreamble);
168+
double tPreamble = (nPreamble + 4.25) * tSym;
168169

169170
// Payload size
170-
uint32_t pl = packet->GetSize(); // Size in bytes
171-
NS_LOG_DEBUG("Packet of size " << pl << " bytes");
171+
uint32_t payloadLen = packet->GetSize(); // Size in bytes
172+
NS_LOG_DEBUG("Packet of size " << payloadLen << " bytes");
172173

173-
// This step is needed since the formula deals with double values.
174+
// Safety casts since the formula deals with double values.
175+
auto pl = static_cast<double>(payloadLen);
176+
auto sf = static_cast<double>(txParams.sf);
177+
auto cr = static_cast<double>(txParams.codingRate);
174178
// de = 1 when the low data rate optimization is enabled, 0 otherwise
175179
// h = 1 when header is implicit, 0 otherwise
176-
double de = txParams.lowDataRateOptimizationEnabled ? 1 : 0;
177-
double h = txParams.headerDisabled ? 1 : 0;
178-
double crc = txParams.crcEnabled ? 1 : 0;
180+
// crc = 1 when cyclic redundancy check is present, 0 otherwise
181+
double de = txParams.lowDataRateOptimizationEnabled ? 1.0 : 0.0;
182+
double h = txParams.headerDisabled ? 1.0 : 0.0;
183+
double crc = txParams.crcEnabled ? 1.0 : 0.0;
179184

180185
// num and den refer to numerator and denominator of the time on air formula
181-
double num = 8.0 * pl - 4 * txParams.sf + 28 + 16 * crc - 20 * h;
182-
double den = 4 * (txParams.sf - 2 * de);
183-
double payloadSymbNb =
184-
8 + std::max(std::ceil(num / den) * (txParams.codingRate + 4), double(0));
186+
double num = 8.0 * pl - 4.0 * sf + 28.0 + 16.0 * crc - 20.0 * h;
187+
double den = 4.0 * (sf - 2.0 * de);
188+
double payloadSymbNb = 8.0 + std::max(std::ceil(num / den) * (cr + 4.0), 0.0);
185189

186190
// Time to transmit the payload
187191
double tPayload = payloadSymbNb * tSym;
@@ -196,11 +200,59 @@ LoraPhy::GetOnAirTime(Ptr<Packet> packet, LoraTxParameters txParams)
196200
return Seconds(tPreamble + tPayload);
197201
}
198202

203+
std::ostream&
204+
operator<<(std::ostream& os, const CodingRate& codingRate)
205+
{
206+
switch (codingRate)
207+
{
208+
case CodingRate::CR_4_5:
209+
return os << "4/5";
210+
case CodingRate::CR_4_6:
211+
return os << "4/6";
212+
case CodingRate::CR_4_7:
213+
return os << "4/7";
214+
case CodingRate::CR_4_8:
215+
return os << "4/8";
216+
default:
217+
NS_FATAL_ERROR("Unknown coding rate value");
218+
return (os << "UNKNOWN");
219+
}
220+
}
221+
222+
std::istream&
223+
operator>>(std::istream& is, CodingRate& codingRate)
224+
{
225+
std::string value;
226+
is >> value;
227+
if (value == "4/5")
228+
{
229+
codingRate = CodingRate::CR_4_5;
230+
}
231+
else if (value == "4/6")
232+
{
233+
codingRate = CodingRate::CR_4_6;
234+
}
235+
else if (value == "4/7")
236+
{
237+
codingRate = CodingRate::CR_4_7;
238+
}
239+
else if (value == "4/8")
240+
{
241+
codingRate = CodingRate::CR_4_8;
242+
}
243+
else
244+
{
245+
is.setstate(std::ios_base::failbit);
246+
}
247+
NS_ABORT_MSG_IF(is.bad(), "Failure to parse " << value);
248+
return is;
249+
}
250+
199251
std::ostream&
200252
operator<<(std::ostream& os, const LoraTxParameters& params)
201253
{
202254
os << "SF: " << unsigned(params.sf) << ", headerDisabled: " << params.headerDisabled
203-
<< ", codingRate: " << unsigned(params.codingRate) << ", bandwidthHz: " << params.bandwidthHz
255+
<< ", codingRate: " << params.codingRate << ", bandwidthHz: " << params.bandwidthHz
204256
<< ", nPreamble: " << params.nPreamble << ", crcEnabled: " << params.crcEnabled
205257
<< ", lowDataRateOptimizationEnabled: " << params.lowDataRateOptimizationEnabled << ")";
206258

model/lora-phy.h

Lines changed: 21 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -26,14 +26,24 @@ class LoraChannel;
2626
*
2727
* Enumeration of the LoRa supported coding rates
2828
*/
29-
enum CodingRate : uint8_t
29+
enum class CodingRate : uint8_t
3030
{
31-
CODING_RATE_4_5 = 1, //!< Coding rate 4/5
32-
CODING_RATE_4_6 = 2, //!< Coding rate 4/6
33-
CODING_RATE_4_7 = 3, //!< Coding rate 4/7
34-
CODING_RATE_4_8 = 4, //!< Coding rate 4/8
31+
CR_4_5 = 1, //!< Coding rate 4/5
32+
CR_4_6, //!< Coding rate 4/6
33+
CR_4_7, //!< Coding rate 4/7
34+
CR_4_8, //!< Coding rate 4/8
3535
};
3636

37+
/**
38+
* Allow logging of CodingRate like any other data type.
39+
*/
40+
std::ostream& operator<<(std::ostream& os, const CodingRate& codingRate);
41+
42+
/**
43+
* Allow parsing of CodingRate from CommandLine.
44+
*/
45+
std::istream& operator>>(std::istream& is, CodingRate& codingRate);
46+
3747
/**
3848
* @ingroup lorawan
3949
*
@@ -42,12 +52,12 @@ enum CodingRate : uint8_t
4252
*/
4353
struct LoraTxParameters
4454
{
45-
uint8_t sf = 7; //!< Spreading Factor
46-
bool headerDisabled = false; //!< Whether to use implicit header mode
47-
CodingRate codingRate = CODING_RATE_4_5; //!< Code rate (obtained as 4/(codingRate+4))
48-
uint32_t bandwidthHz = 125000; //!< Bandwidth in Hz
49-
uint32_t nPreamble = 8; //!< Number of preamble symbols
50-
bool crcEnabled = true; //!< Whether Cyclic Redundancy Check (CRC) is enabled
55+
uint8_t sf = 7; //!< Spreading Factor
56+
bool headerDisabled = false; //!< Whether to use implicit header mode
57+
CodingRate codingRate = CodingRate::CR_4_5; //!< Code rate (obtained as 4/(codingRate+4))
58+
uint32_t bandwidthHz = 125000; //!< Bandwidth in Hz
59+
uint32_t nPreamble = 8; //!< Number of preamble symbols
60+
bool crcEnabled = true; //!< Whether Cyclic Redundancy Check (CRC) is enabled
5161
bool lowDataRateOptimizationEnabled = false; //!< Whether low data rate optimization is enabled
5262
};
5363

test/lorawan-test-suite.cc

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1014,7 +1014,7 @@ TimeOnAirTest::DoRun()
10141014
LoraTxParameters txParams;
10151015
txParams.sf = 7;
10161016
txParams.headerDisabled = false;
1017-
txParams.codingRate = CODING_RATE_4_5;
1017+
txParams.codingRate = CodingRate::CR_4_5;
10181018
txParams.bandwidthHz = 125000;
10191019
txParams.nPreamble = 8;
10201020
txParams.crcEnabled = true;
@@ -1031,7 +1031,7 @@ TimeOnAirTest::DoRun()
10311031
duration = LoraPhy::GetOnAirTime(packet, txParams);
10321032
NS_TEST_EXPECT_MSG_EQ_TOL(duration.GetSeconds(), 0.072192, 0.0001, "Unexpected duration");
10331033

1034-
txParams.codingRate = CODING_RATE_4_6;
1034+
txParams.codingRate = CodingRate::CR_4_6;
10351035
duration = LoraPhy::GetOnAirTime(packet, txParams);
10361036
NS_TEST_EXPECT_MSG_EQ_TOL(duration.GetSeconds(), 0.078336, 0.0001, "Unexpected duration");
10371037

@@ -1075,7 +1075,7 @@ TimeOnAirTest::DoRun()
10751075
duration = LoraPhy::GetOnAirTime(packet, txParams);
10761076
NS_TEST_EXPECT_MSG_EQ_TOL(duration.GetSeconds(), 2.629632, 0.0001, "Unexpected duration");
10771077

1078-
txParams.codingRate = CODING_RATE_4_5;
1078+
txParams.codingRate = CodingRate::CR_4_5;
10791079
duration = LoraPhy::GetOnAirTime(packet, txParams);
10801080
NS_TEST_EXPECT_MSG_EQ_TOL(duration.GetSeconds(), 2.301952, 0.0001, "Unexpected duration");
10811081
}

0 commit comments

Comments
 (0)