@@ -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+
199251std::ostream&
200252operator <<(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
0 commit comments