File: | /tmp/asd-nat/home/nat/Work/ns-3-dev-git/build/../src/wimax/model/simple-ofdm-wimax-phy.cc |
Location: | line 552, column 33 |
Description: | The left operand of '>>' is a garbage value |
1 | /* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */ | |||
2 | /* | |||
3 | * Copyright (c) 2007,2008, 2009 INRIA, UDcast | |||
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: Mohamed Amine Ismail <amine.ismail@sophia.inria.fr> | |||
19 | * <amine.ismail@udcast.com> | |||
20 | */ | |||
21 | ||||
22 | #include "ns3/simulator.h" | |||
23 | #include "ns3/packet.h" | |||
24 | #include "ns3/node.h" | |||
25 | #include "ns3/uinteger.h" | |||
26 | #include "ns3/double.h" | |||
27 | #include "ns3/string.h" | |||
28 | #include "wimax-net-device.h" | |||
29 | #include "simple-ofdm-wimax-phy.h" | |||
30 | #include "wimax-channel.h" | |||
31 | #include "ns3/packet-burst.h" | |||
32 | #include "wimax-mac-header.h" | |||
33 | #include "simple-ofdm-wimax-channel.h" | |||
34 | #include "ns3/trace-source-accessor.h" | |||
35 | #include <string> | |||
36 | #include <cmath> | |||
37 | ||||
38 | namespace ns3 { | |||
39 | ||||
40 | NS_LOG_COMPONENT_DEFINE ("SimpleOfdmWimaxPhy")static ns3::LogComponent g_log = ns3::LogComponent ("SimpleOfdmWimaxPhy" , "../src/wimax/model/simple-ofdm-wimax-phy.cc"); | |||
41 | ||||
42 | NS_OBJECT_ENSURE_REGISTERED (SimpleOfdmWimaxPhy)static struct ObjectSimpleOfdmWimaxPhyRegistrationClass { ObjectSimpleOfdmWimaxPhyRegistrationClass () { ns3::TypeId tid = SimpleOfdmWimaxPhy::GetTypeId (); tid .SetSize (sizeof (SimpleOfdmWimaxPhy)); tid.GetParent (); } } ObjectSimpleOfdmWimaxPhyRegistrationVariable; | |||
43 | ||||
44 | TypeId SimpleOfdmWimaxPhy::GetTypeId (void) | |||
45 | { | |||
46 | static TypeId tid = TypeId ("ns3::SimpleOfdmWimaxPhy") | |||
47 | .SetParent<WimaxPhy> () | |||
48 | .SetGroupName ("Wimax") | |||
49 | ||||
50 | .AddConstructor<SimpleOfdmWimaxPhy> () | |||
51 | ||||
52 | .AddAttribute ("NoiseFigure", | |||
53 | "Loss (dB) in the Signal-to-Noise-Ratio due to non-idealities in the receiver.", | |||
54 | DoubleValue (5), | |||
55 | MakeDoubleAccessor (&SimpleOfdmWimaxPhy::SetNoiseFigure, &SimpleOfdmWimaxPhy::GetNoiseFigure), | |||
56 | MakeDoubleChecker<double> ()) | |||
57 | ||||
58 | .AddAttribute ("TxPower", | |||
59 | "Transmission power (dB).", | |||
60 | DoubleValue (30), | |||
61 | MakeDoubleAccessor (&SimpleOfdmWimaxPhy::SetTxPower, &SimpleOfdmWimaxPhy::GetTxPower), | |||
62 | MakeDoubleChecker<double> ()) | |||
63 | ||||
64 | .AddAttribute ("G", | |||
65 | "This is the ratio of CP time to useful time.", | |||
66 | DoubleValue (0.25), | |||
67 | MakeDoubleAccessor (&SimpleOfdmWimaxPhy::DoSetGValue, &SimpleOfdmWimaxPhy::DoGetGValue), | |||
68 | MakeDoubleChecker<double> ()) | |||
69 | ||||
70 | .AddAttribute ("TxGain", | |||
71 | "Transmission gain (dB).", | |||
72 | DoubleValue (0), | |||
73 | MakeDoubleAccessor (&SimpleOfdmWimaxPhy::SetTxGain, &SimpleOfdmWimaxPhy::GetTxGain), | |||
74 | MakeDoubleChecker<double> ()) | |||
75 | ||||
76 | .AddAttribute ("RxGain", | |||
77 | "Reception gain (dB).", | |||
78 | DoubleValue (0), | |||
79 | MakeDoubleAccessor (&SimpleOfdmWimaxPhy::SetRxGain, &SimpleOfdmWimaxPhy::GetRxGain), | |||
80 | MakeDoubleChecker<double> ()) | |||
81 | ||||
82 | .AddAttribute ("Nfft", | |||
83 | "FFT size", | |||
84 | UintegerValue (256), | |||
85 | MakeUintegerAccessor (&SimpleOfdmWimaxPhy::DoSetNfft, &SimpleOfdmWimaxPhy::DoGetNfft), | |||
86 | MakeUintegerChecker<uint16_t> (256, 1024)) | |||
87 | ||||
88 | .AddAttribute ("TraceFilePath", | |||
89 | "Path to the directory containing SNR to block error rate files", | |||
90 | StringValue (""), | |||
91 | MakeStringAccessor (&SimpleOfdmWimaxPhy::GetTraceFilePath, | |||
92 | &SimpleOfdmWimaxPhy::SetTraceFilePath), | |||
93 | MakeStringChecker ()) | |||
94 | ||||
95 | .AddTraceSource ("Rx", "Receive trace", | |||
96 | MakeTraceSourceAccessor (&SimpleOfdmWimaxPhy::m_traceRx), | |||
97 | "ns3::PacketBurst::TracedCallback") | |||
98 | .AddTraceSource ("Tx", "Transmit trace", | |||
99 | MakeTraceSourceAccessor (&SimpleOfdmWimaxPhy::m_traceTx), | |||
100 | "ns3::PacketBurst::TracedCallback") | |||
101 | ||||
102 | .AddTraceSource ("PhyTxBegin", | |||
103 | "Trace source indicating a packet has begun transmitting over the channel medium", | |||
104 | MakeTraceSourceAccessor (&SimpleOfdmWimaxPhy::m_phyTxBeginTrace), | |||
105 | "ns3::PacketBurst::TracedCallback") | |||
106 | ||||
107 | .AddTraceSource ("PhyTxEnd", | |||
108 | "Trace source indicating a packet has been completely transmitted over the channel", | |||
109 | MakeTraceSourceAccessor (&SimpleOfdmWimaxPhy::m_phyTxEndTrace), | |||
110 | "ns3::PacketBurst::TracedCallback") | |||
111 | ||||
112 | .AddTraceSource ("PhyTxDrop", | |||
113 | "Trace source indicating a packet has been dropped by the device during transmission", | |||
114 | MakeTraceSourceAccessor (&SimpleOfdmWimaxPhy::m_phyTxDropTrace), | |||
115 | "ns3::PacketBurst::TracedCallback") | |||
116 | ||||
117 | .AddTraceSource ("PhyRxBegin", | |||
118 | "Trace source indicating a packet has begun being received from the channel medium by the device", | |||
119 | MakeTraceSourceAccessor (&SimpleOfdmWimaxPhy::m_phyRxBeginTrace), | |||
120 | "ns3::PacketBurst::TracedCallback") | |||
121 | ||||
122 | .AddTraceSource ("PhyRxEnd", | |||
123 | "Trace source indicating a packet has been completely received from the channel medium by the device", | |||
124 | MakeTraceSourceAccessor (&SimpleOfdmWimaxPhy::m_phyRxEndTrace), | |||
125 | "ns3::PacketBurst::TracedCallback") | |||
126 | ||||
127 | .AddTraceSource ("PhyRxDrop", | |||
128 | "Trace source indicating a packet has been dropped by the device during reception", | |||
129 | MakeTraceSourceAccessor (&SimpleOfdmWimaxPhy::m_phyRxDropTrace), | |||
130 | "ns3::PacketBurst::TracedCallback"); | |||
131 | return tid; | |||
132 | } | |||
133 | ||||
134 | void | |||
135 | SimpleOfdmWimaxPhy::InitSimpleOfdmWimaxPhy (void) | |||
136 | { | |||
137 | m_fecBlockSize = 0; | |||
138 | m_nrFecBlocksSent = 0; | |||
139 | m_dataRateBpsk12 = 0; | |||
140 | m_dataRateQpsk12 = 0; | |||
141 | m_dataRateQpsk34 = 0; | |||
142 | m_dataRateQam16_12 = 0; | |||
143 | ||||
144 | m_dataRateQam16_34 = 0; | |||
145 | m_dataRateQam64_23 = 0; | |||
146 | m_dataRateQam64_34 = 0; | |||
147 | ||||
148 | m_nrBlocks = 0; | |||
149 | m_blockSize = 0; | |||
150 | m_paddingBits = 0; | |||
151 | m_rxGain = 0; | |||
152 | m_txGain = 0; | |||
153 | m_nfft = 256; | |||
154 | m_g = (double) 1 / 4; | |||
155 | SetNrCarriers (192); | |||
156 | m_fecBlocks = new std::list<bvec>; | |||
157 | m_receivedFecBlocks = new std::list<bvec>; | |||
158 | m_currentBurstSize = 0; | |||
159 | m_noiseFigure = 5; // dB | |||
160 | m_txPower = 30; // dBm | |||
161 | SetBandwidth (10000000); // 10Mhz | |||
162 | m_nbErroneousBlock = 0; | |||
163 | m_nrRecivedFecBlocks = 0; | |||
164 | m_snrToBlockErrorRateManager = new SNRToBlockErrorRateManager (); | |||
165 | } | |||
166 | ||||
167 | SimpleOfdmWimaxPhy::SimpleOfdmWimaxPhy (void) | |||
168 | { | |||
169 | m_URNG = CreateObject<UniformRandomVariable> (); | |||
170 | ||||
171 | InitSimpleOfdmWimaxPhy (); | |||
172 | m_snrToBlockErrorRateManager->SetTraceFilePath ((char*) ""); | |||
173 | m_snrToBlockErrorRateManager->LoadTraces (); | |||
174 | } | |||
175 | ||||
176 | SimpleOfdmWimaxPhy::SimpleOfdmWimaxPhy (char * tracesPath) | |||
177 | { | |||
178 | InitSimpleOfdmWimaxPhy (); | |||
179 | m_snrToBlockErrorRateManager->SetTraceFilePath (tracesPath); | |||
180 | m_snrToBlockErrorRateManager->LoadTraces (); | |||
181 | } | |||
182 | ||||
183 | SimpleOfdmWimaxPhy::~SimpleOfdmWimaxPhy (void) | |||
184 | { | |||
185 | ||||
186 | } | |||
187 | ||||
188 | void | |||
189 | SimpleOfdmWimaxPhy::ActivateLoss (bool loss) | |||
190 | { | |||
191 | m_snrToBlockErrorRateManager->ActivateLoss (loss); | |||
192 | } | |||
193 | ||||
194 | void | |||
195 | SimpleOfdmWimaxPhy::SetSNRToBlockErrorRateTracesPath (char * tracesPath) | |||
196 | { | |||
197 | m_snrToBlockErrorRateManager->SetTraceFilePath (tracesPath); | |||
198 | m_snrToBlockErrorRateManager->ReLoadTraces (); | |||
199 | } | |||
200 | ||||
201 | uint32_t | |||
202 | SimpleOfdmWimaxPhy::GetBandwidth (void) const | |||
203 | { | |||
204 | return WimaxPhy::GetChannelBandwidth (); | |||
205 | } | |||
206 | ||||
207 | void | |||
208 | SimpleOfdmWimaxPhy::SetBandwidth (uint32_t BW) | |||
209 | { | |||
210 | WimaxPhy::SetChannelBandwidth (BW); | |||
211 | } | |||
212 | ||||
213 | double | |||
214 | SimpleOfdmWimaxPhy::GetTxPower (void) const | |||
215 | { | |||
216 | return m_txPower; | |||
217 | } | |||
218 | void | |||
219 | SimpleOfdmWimaxPhy::SetTxPower (double txPower) | |||
220 | { | |||
221 | m_txPower = txPower; | |||
222 | } | |||
223 | ||||
224 | double | |||
225 | SimpleOfdmWimaxPhy::GetNoiseFigure (void) const | |||
226 | { | |||
227 | return m_noiseFigure; | |||
228 | } | |||
229 | void | |||
230 | SimpleOfdmWimaxPhy::SetNoiseFigure (double noiseFigure) | |||
231 | { | |||
232 | m_noiseFigure = noiseFigure; | |||
233 | } | |||
234 | ||||
235 | void | |||
236 | SimpleOfdmWimaxPhy::DoDispose (void) | |||
237 | { | |||
238 | delete m_receivedFecBlocks; | |||
239 | delete m_fecBlocks; | |||
240 | m_receivedFecBlocks = 0; | |||
241 | m_fecBlocks = 0; | |||
242 | delete m_snrToBlockErrorRateManager; | |||
243 | WimaxPhy::DoDispose (); | |||
244 | } | |||
245 | ||||
246 | void | |||
247 | SimpleOfdmWimaxPhy::DoAttach (Ptr<WimaxChannel> channel) | |||
248 | { | |||
249 | GetChannel ()->Attach (this); | |||
250 | } | |||
251 | ||||
252 | void | |||
253 | SimpleOfdmWimaxPhy::Send (SendParams *params) | |||
254 | { | |||
255 | OfdmSendParams *o_params = dynamic_cast<OfdmSendParams*> (params); | |||
256 | NS_ASSERT (o_params !=0)do { if (!(o_params !=0)) { std::cerr << "assert failed. cond=\"" << "o_params !=0" << "\", "; do { std::cerr << "file=" << "../src/wimax/model/simple-ofdm-wimax-phy.cc" << ", line=" << 256 << std::endl; ::ns3::FatalImpl ::FlushStreams (); if (true) std::terminate (); } while (false ); } } while (false); | |||
257 | Send (o_params->GetBurst (), | |||
258 | (WimaxPhy::ModulationType) o_params->GetModulationType (), | |||
259 | o_params->GetDirection ()); | |||
260 | ||||
261 | } | |||
262 | ||||
263 | WimaxPhy::PhyType | |||
264 | SimpleOfdmWimaxPhy::GetPhyType (void) const | |||
265 | { | |||
266 | return WimaxPhy::simpleOfdmWimaxPhy; | |||
267 | } | |||
268 | ||||
269 | void | |||
270 | SimpleOfdmWimaxPhy::Send (Ptr<PacketBurst> burst, | |||
271 | WimaxPhy::ModulationType modulationType, | |||
272 | uint8_t direction) | |||
273 | { | |||
274 | ||||
275 | if (GetState () != PHY_STATE_TX) | |||
276 | { | |||
277 | m_currentBurstSize = burst->GetSize (); | |||
278 | m_nrFecBlocksSent = 0; | |||
279 | m_currentBurst = burst; | |||
280 | SetBlockParameters (burst->GetSize (), modulationType); | |||
281 | NotifyTxBegin (m_currentBurst); | |||
282 | StartSendDummyFecBlock (true, modulationType, direction); | |||
283 | m_traceTx (burst); | |||
284 | } | |||
285 | } | |||
286 | ||||
287 | void | |||
288 | SimpleOfdmWimaxPhy::StartSendDummyFecBlock (bool isFirstBlock, | |||
289 | WimaxPhy::ModulationType modulationType, | |||
290 | uint8_t direction) | |||
291 | { | |||
292 | SetState (PHY_STATE_TX); | |||
293 | bool isLastFecBlock = 0; | |||
294 | if (isFirstBlock) | |||
295 | { | |||
296 | m_blockTime = GetBlockTransmissionTime (modulationType); | |||
297 | } | |||
298 | ||||
299 | SimpleOfdmWimaxChannel *channel = dynamic_cast<SimpleOfdmWimaxChannel*> (PeekPointer (GetChannel ())); | |||
300 | NS_ASSERT (channel != 0)do { if (!(channel != 0)) { std::cerr << "assert failed. cond=\"" << "channel != 0" << "\", "; do { std::cerr << "file=" << "../src/wimax/model/simple-ofdm-wimax-phy.cc" << ", line=" << 300 << std::endl; ::ns3::FatalImpl ::FlushStreams (); if (true) std::terminate (); } while (false ); } } while (false); | |||
301 | ||||
302 | if (m_nrRemainingBlocksToSend==1) | |||
303 | { | |||
304 | isLastFecBlock = true; | |||
305 | } | |||
306 | else | |||
307 | { | |||
308 | isLastFecBlock = false; | |||
309 | } | |||
310 | channel->Send (m_blockTime, | |||
311 | m_currentBurstSize, | |||
312 | this, | |||
313 | isFirstBlock, | |||
314 | isLastFecBlock, | |||
315 | GetTxFrequency (), | |||
316 | modulationType, | |||
317 | direction, | |||
318 | m_txPower, | |||
319 | m_currentBurst); | |||
320 | ||||
321 | m_nrRemainingBlocksToSend--; | |||
322 | Simulator::Schedule (m_blockTime, &SimpleOfdmWimaxPhy::EndSendFecBlock, this, modulationType, direction); | |||
323 | } | |||
324 | ||||
325 | ||||
326 | void | |||
327 | SimpleOfdmWimaxPhy::EndSendFecBlock (WimaxPhy::ModulationType modulationType, | |||
328 | uint8_t direction) | |||
329 | { | |||
330 | m_nrFecBlocksSent++; | |||
331 | SetState (PHY_STATE_IDLE); | |||
332 | ||||
333 | if (m_nrFecBlocksSent * m_blockSize == m_currentBurstSize * 8 + m_paddingBits) | |||
334 | { | |||
335 | // this is the last FEC block of the burst | |||
336 | NS_ASSERT_MSG (m_nrRemainingBlocksToSend == 0, "Error while sending a burst")do { if (!(m_nrRemainingBlocksToSend == 0)) { std::cerr << "assert failed. cond=\"" << "m_nrRemainingBlocksToSend == 0" << "\", "; do { std::cerr << "msg=\"" << "Error while sending a burst" << "\", "; do { std::cerr << "file=" << "../src/wimax/model/simple-ofdm-wimax-phy.cc" << ", line=" << 336 << std::endl; ::ns3::FatalImpl ::FlushStreams (); if (true) std::terminate (); } while (false ); } while (false); } } while (false); | |||
337 | NotifyTxEnd (m_currentBurst); | |||
338 | } | |||
339 | else | |||
340 | { | |||
341 | StartSendDummyFecBlock (false,modulationType,direction); | |||
342 | } | |||
343 | } | |||
344 | ||||
345 | void | |||
346 | SimpleOfdmWimaxPhy::EndSend (void) | |||
347 | { | |||
348 | SetState (PHY_STATE_IDLE); | |||
349 | } | |||
350 | ||||
351 | void | |||
352 | SimpleOfdmWimaxPhy::StartReceive (uint32_t burstSize, | |||
353 | bool isFirstBlock, | |||
354 | uint64_t frequency, | |||
355 | WimaxPhy::ModulationType modulationType, | |||
356 | uint8_t direction, | |||
357 | double rxPower, | |||
358 | Ptr<PacketBurst> burst) | |||
359 | { | |||
360 | ||||
361 | uint8_t drop = 0; | |||
362 | double Nwb = -114 + m_noiseFigure + 10 * std::log (GetBandwidth () / 1000000000.0) / 2.303; | |||
363 | double SNR = rxPower - Nwb; | |||
364 | ||||
365 | SNRToBlockErrorRateRecord * record = m_snrToBlockErrorRateManager->GetSNRToBlockErrorRateRecord (SNR, modulationType); | |||
366 | double I1 = record->GetI1 (); | |||
367 | double I2 = record->GetI2 (); | |||
368 | ||||
369 | double blockErrorRate = m_URNG->GetValue (I1, I2); | |||
370 | ||||
371 | double rand = m_URNG->GetValue (0.0, 1.0); | |||
372 | ||||
373 | if (rand < blockErrorRate) | |||
374 | { | |||
375 | drop = 1; | |||
376 | } | |||
377 | if (rand > blockErrorRate) | |||
378 | { | |||
379 | drop = 0; | |||
380 | } | |||
381 | ||||
382 | if (blockErrorRate == 1.0) | |||
383 | { | |||
384 | drop = 1; | |||
385 | } | |||
386 | if (blockErrorRate == 0.0) | |||
387 | { | |||
388 | drop = 0; | |||
389 | } | |||
390 | delete record; | |||
391 | ||||
392 | NS_LOG_INFO ("PHY: Receive rxPower=" << rxPower << ", Nwb=" << Nwb << ", SNR=" << SNR << ", Modulation="do { if (g_log.IsEnabled (ns3::LOG_INFO)) { if (g_log.IsEnabled (ns3::LOG_PREFIX_TIME)) { ns3::LogTimePrinter printer = ns3:: LogGetTimePrinter (); if (printer != 0) { (*printer)(std::clog ); std::clog << " "; } }; if (g_log.IsEnabled (ns3::LOG_PREFIX_NODE )) { ns3::LogNodePrinter printer = ns3::LogGetNodePrinter (); if (printer != 0) { (*printer)(std::clog); std::clog << " "; } }; ; if (g_log.IsEnabled (ns3::LOG_PREFIX_FUNC)) { std ::clog << g_log.Name () << ":" << __FUNCTION__ << "(): "; }; if (g_log.IsEnabled (ns3::LOG_PREFIX_LEVEL )) { std::clog << "[" << g_log.GetLevelLabel (ns3 ::LOG_INFO) << "] "; }; std::clog << "PHY: Receive rxPower=" << rxPower << ", Nwb=" << Nwb << ", SNR=" << SNR << ", Modulation=" << modulationType << ", BlocErrorRate=" << blockErrorRate << ", drop=" << (int) drop << std::endl; } } while ( false) | |||
393 | << modulationType << ", BlocErrorRate=" << blockErrorRate << ", drop=" << (int) drop)do { if (g_log.IsEnabled (ns3::LOG_INFO)) { if (g_log.IsEnabled (ns3::LOG_PREFIX_TIME)) { ns3::LogTimePrinter printer = ns3:: LogGetTimePrinter (); if (printer != 0) { (*printer)(std::clog ); std::clog << " "; } }; if (g_log.IsEnabled (ns3::LOG_PREFIX_NODE )) { ns3::LogNodePrinter printer = ns3::LogGetNodePrinter (); if (printer != 0) { (*printer)(std::clog); std::clog << " "; } }; ; if (g_log.IsEnabled (ns3::LOG_PREFIX_FUNC)) { std ::clog << g_log.Name () << ":" << __FUNCTION__ << "(): "; }; if (g_log.IsEnabled (ns3::LOG_PREFIX_LEVEL )) { std::clog << "[" << g_log.GetLevelLabel (ns3 ::LOG_INFO) << "] "; }; std::clog << "PHY: Receive rxPower=" << rxPower << ", Nwb=" << Nwb << ", SNR=" << SNR << ", Modulation=" << modulationType << ", BlocErrorRate=" << blockErrorRate << ", drop=" << (int) drop << std::endl; } } while ( false); | |||
394 | ||||
395 | switch (GetState ()) | |||
396 | { | |||
397 | case PHY_STATE_SCANNING: | |||
398 | if (frequency == GetScanningFrequency ()) | |||
399 | { | |||
400 | Simulator::Cancel (GetChnlSrchTimeoutEvent ()); | |||
401 | SetScanningCallback (); | |||
402 | SetSimplex (frequency); | |||
403 | SetState (PHY_STATE_IDLE); | |||
404 | } | |||
405 | break; | |||
406 | case PHY_STATE_IDLE: | |||
407 | if (frequency == GetRxFrequency ()) | |||
408 | { | |||
409 | if (isFirstBlock) | |||
410 | { | |||
411 | NotifyRxBegin (burst); | |||
412 | m_receivedFecBlocks->clear (); | |||
413 | m_nrRecivedFecBlocks=0; | |||
414 | SetBlockParameters (burstSize, modulationType); | |||
415 | m_blockTime = GetBlockTransmissionTime (modulationType); | |||
416 | } | |||
417 | ||||
418 | Simulator::Schedule (m_blockTime, | |||
419 | &SimpleOfdmWimaxPhy::EndReceiveFecBlock, | |||
420 | this, | |||
421 | burstSize, | |||
422 | modulationType, | |||
423 | direction, | |||
424 | drop, | |||
425 | burst); | |||
426 | ||||
427 | SetState (PHY_STATE_RX); | |||
428 | } | |||
429 | break; | |||
430 | case PHY_STATE_RX: | |||
431 | // drop | |||
432 | break; | |||
433 | case PHY_STATE_TX: | |||
434 | if (IsDuplex () && frequency == GetRxFrequency ()) | |||
435 | { | |||
436 | ||||
437 | } | |||
438 | break; | |||
439 | } | |||
440 | } | |||
441 | ||||
442 | void | |||
443 | SimpleOfdmWimaxPhy::EndReceiveFecBlock (uint32_t burstSize, | |||
444 | WimaxPhy::ModulationType modulationType, | |||
445 | uint8_t direction, | |||
446 | uint8_t drop, | |||
447 | Ptr<PacketBurst> burst) | |||
448 | { | |||
449 | SetState (PHY_STATE_IDLE); | |||
450 | m_nrRecivedFecBlocks++; | |||
451 | ||||
452 | if (drop == true) | |||
453 | { | |||
454 | m_nbErroneousBlock++; | |||
455 | } | |||
456 | ||||
457 | if ((uint32_t) m_nrRecivedFecBlocks * m_blockSize == burstSize * 8 + m_paddingBits) | |||
458 | { | |||
459 | NotifyRxEnd (burst); | |||
460 | if (m_nbErroneousBlock == 0) | |||
461 | { | |||
462 | Simulator::Schedule (Seconds (0), | |||
463 | &SimpleOfdmWimaxPhy::EndReceive, | |||
464 | this, | |||
465 | burst); | |||
466 | } | |||
467 | else | |||
468 | { | |||
469 | NotifyRxDrop (burst); | |||
470 | } | |||
471 | m_nbErroneousBlock = 0; | |||
472 | m_nrRecivedFecBlocks = 0; | |||
473 | } | |||
474 | } | |||
475 | ||||
476 | void | |||
477 | SimpleOfdmWimaxPhy::EndReceive (Ptr<const PacketBurst> burst) | |||
478 | { | |||
479 | Ptr<PacketBurst> b = burst->Copy (); | |||
480 | GetReceiveCallback () (b); | |||
481 | m_traceRx (burst); | |||
482 | } | |||
483 | ||||
484 | bvec | |||
485 | SimpleOfdmWimaxPhy::ConvertBurstToBits (Ptr<const PacketBurst> burst) | |||
486 | { | |||
487 | bvec buffer (burst->GetSize () * 8, 0); | |||
488 | ||||
489 | std::list<Ptr<Packet> > packets = burst->GetPackets (); | |||
490 | ||||
491 | uint32_t j = 0; | |||
492 | for (std::list<Ptr<Packet> >::iterator iter = packets.begin (); iter != packets.end (); ++iter) | |||
493 | { | |||
494 | Ptr<Packet> packet = *iter; | |||
495 | uint8_t *pstart = (uint8_t*) std::malloc (packet->GetSize ()); | |||
496 | std::memset (pstart, 0, packet->GetSize ()); | |||
497 | packet->CopyData (pstart, packet->GetSize ()); | |||
498 | bvec temp (8); | |||
499 | temp.resize (0, 0); | |||
500 | temp.resize (8, 0); | |||
501 | for (uint32_t i = 0; i < packet->GetSize (); i++) | |||
502 | { | |||
503 | for (uint8_t l = 0; l < 8; l++) | |||
504 | { | |||
505 | temp[l] = (bool)((((uint8_t) pstart[i]) >> (7 - l)) & 0x01); | |||
506 | buffer.at (j * 8 + l) = temp[l]; | |||
507 | } | |||
508 | j++; | |||
509 | } | |||
510 | std::free (pstart); | |||
511 | } | |||
512 | ||||
513 | return buffer; | |||
514 | } | |||
515 | ||||
516 | /* | |||
517 | Converts back the bit buffer (bvec) to the actual burst. | |||
518 | Actually creates byte buffer from the bvec and resets the buffer | |||
519 | of each packet in the copy of the orifinal burst stored before transmitting. | |||
520 | By doing this it preserves the metadata and tags in the packet. | |||
521 | Function could also be named DeserializeBurst because actually it | |||
522 | copying to the burst's byte buffer. | |||
523 | */ | |||
524 | Ptr<PacketBurst> | |||
525 | SimpleOfdmWimaxPhy::ConvertBitsToBurst (bvec buffer) | |||
526 | { | |||
527 | uint8_t init[buffer.size () / 8]; | |||
528 | uint8_t *pstart = init; | |||
529 | uint8_t temp; | |||
530 | int32_t j = 0; | |||
531 | // recreating byte buffer from bit buffer (bvec) | |||
532 | for (uint32_t i = 0; i < buffer.size (); i += 8) | |||
| ||||
533 | { | |||
534 | ||||
535 | temp = 0; | |||
536 | for (int l = 0; l < 8; l++) | |||
537 | { | |||
538 | bool bin = buffer.at (i + l); | |||
539 | temp += (uint8_t)(bin * std::pow (2.0, (7 - l))); | |||
540 | } | |||
541 | ||||
542 | *(pstart + j) = temp; | |||
543 | j++; | |||
544 | } | |||
545 | uint16_t bufferSize = buffer.size () / 8; | |||
546 | uint16_t pos = 0; | |||
547 | Ptr<PacketBurst> RecvBurst = Create<PacketBurst> (); | |||
548 | while (pos < bufferSize) | |||
549 | { | |||
550 | uint16_t packetSize = 0; | |||
551 | // Get the header type: first bit | |||
552 | uint8_t ht = (pstart[pos] >> 7) & 0x01; | |||
| ||||
553 | if (ht == 1) | |||
554 | { | |||
555 | // BW request header. Size is always 8 bytes | |||
556 | packetSize = 6; | |||
557 | } | |||
558 | else | |||
559 | { | |||
560 | // Read the size | |||
561 | uint8_t Len_MSB = pstart[pos + 1] & 0x07; | |||
562 | packetSize = (uint16_t)((uint16_t)(Len_MSB << 8) | (uint16_t)(pstart[pos + 2])); | |||
563 | if (packetSize == 0) | |||
564 | { | |||
565 | break; // padding | |||
566 | } | |||
567 | } | |||
568 | ||||
569 | Ptr<Packet> p = Create<Packet> (&(pstart[pos]), packetSize); | |||
570 | RecvBurst->AddPacket (p); | |||
571 | pos += packetSize; | |||
572 | } | |||
573 | return RecvBurst; | |||
574 | } | |||
575 | ||||
576 | void | |||
577 | SimpleOfdmWimaxPhy::CreateFecBlocks (const bvec &buffer, WimaxPhy::ModulationType modulationType) | |||
578 | { | |||
579 | ||||
580 | bvec fecBlock (m_blockSize); | |||
581 | for (uint32_t i = 0, j = m_nrBlocks; j > 0; i += m_blockSize, j--) | |||
582 | { | |||
583 | ||||
584 | if (j == 1 && m_paddingBits > 0) // last block can be smaller than block size | |||
585 | { | |||
586 | fecBlock = bvec (buffer.begin () + i, buffer.end ()); | |||
587 | fecBlock.resize (m_blockSize, 0); | |||
588 | } | |||
589 | else | |||
590 | { | |||
591 | fecBlock = bvec (buffer.begin () + i, buffer.begin () + i + m_blockSize); | |||
592 | } | |||
593 | ||||
594 | m_fecBlocks->push_back (fecBlock); | |||
595 | } | |||
596 | } | |||
597 | ||||
598 | bvec | |||
599 | SimpleOfdmWimaxPhy::RecreateBuffer () | |||
600 | { | |||
601 | ||||
602 | bvec buffer (m_blockSize * (unsigned long)m_nrBlocks); | |||
603 | bvec block (m_blockSize); | |||
604 | uint32_t i = 0; | |||
605 | for (uint32_t j = 0; j < m_nrBlocks; j++) | |||
606 | { | |||
607 | bvec tmpRecFecBloc = m_receivedFecBlocks->front (); | |||
608 | buffer.insert (buffer.begin () + i, tmpRecFecBloc.begin (), tmpRecFecBloc.end ()); | |||
609 | m_receivedFecBlocks->pop_front (); | |||
610 | i += m_blockSize; | |||
611 | } | |||
612 | return buffer; | |||
613 | } | |||
614 | ||||
615 | void | |||
616 | SimpleOfdmWimaxPhy::DoSetDataRates (void) | |||
617 | { | |||
618 | m_dataRateBpsk12 = CalculateDataRate (MODULATION_TYPE_BPSK_12); // 6912000 bps | |||
619 | m_dataRateQpsk12 = CalculateDataRate (MODULATION_TYPE_QPSK_12); // 13824000 | |||
620 | m_dataRateQpsk34 = CalculateDataRate (MODULATION_TYPE_QPSK_34); // 20736000 | |||
621 | m_dataRateQam16_12 = CalculateDataRate (MODULATION_TYPE_QAM16_12); // 27648000 | |||
622 | m_dataRateQam16_34 = CalculateDataRate (MODULATION_TYPE_QAM16_34); // 41472000 | |||
623 | m_dataRateQam64_23 = CalculateDataRate (MODULATION_TYPE_QAM64_23); // 55224000 | |||
624 | m_dataRateQam64_34 = CalculateDataRate (MODULATION_TYPE_QAM64_34); // 62208000 | |||
625 | } | |||
626 | ||||
627 | void | |||
628 | SimpleOfdmWimaxPhy::GetModulationFecParams (WimaxPhy::ModulationType modulationType, | |||
629 | uint8_t &bitsPerSymbol, | |||
630 | double &fecCode) const | |||
631 | { | |||
632 | switch (modulationType) | |||
633 | { | |||
634 | case MODULATION_TYPE_BPSK_12: | |||
635 | bitsPerSymbol = 1; | |||
636 | fecCode = (double) 1 / 2; | |||
637 | break; | |||
638 | case MODULATION_TYPE_QPSK_12: | |||
639 | bitsPerSymbol = 2; | |||
640 | fecCode = (double) 1 / 2; | |||
641 | break; | |||
642 | case MODULATION_TYPE_QPSK_34: | |||
643 | bitsPerSymbol = 2; | |||
644 | fecCode = (double) 3 / 4; | |||
645 | break; | |||
646 | case MODULATION_TYPE_QAM16_12: | |||
647 | bitsPerSymbol = 4; | |||
648 | fecCode = (double) 1 / 2; | |||
649 | break; | |||
650 | case MODULATION_TYPE_QAM16_34: | |||
651 | bitsPerSymbol = 4; | |||
652 | fecCode = (double) 3 / 4; | |||
653 | break; | |||
654 | case MODULATION_TYPE_QAM64_23: | |||
655 | bitsPerSymbol = 6; | |||
656 | fecCode = (double) 2 / 3; | |||
657 | break; | |||
658 | case MODULATION_TYPE_QAM64_34: | |||
659 | bitsPerSymbol = 6; | |||
660 | fecCode = 0.75; | |||
661 | break; | |||
662 | } | |||
663 | } | |||
664 | ||||
665 | uint32_t | |||
666 | SimpleOfdmWimaxPhy::CalculateDataRate (WimaxPhy::ModulationType modulationType) const | |||
667 | { | |||
668 | uint8_t bitsPerSymbol = 0; | |||
669 | double fecCode = 0; | |||
670 | GetModulationFecParams (modulationType, bitsPerSymbol, fecCode); | |||
671 | double symbolsPerSecond = 1 / GetSymbolDuration ().GetSeconds (); | |||
672 | uint16_t bitsTransmittedPerSymbol = (uint16_t)(bitsPerSymbol * GetNrCarriers () * fecCode); | |||
673 | // 96, 192, 288, 384, 576, 767 and 864 bits per symbol for the seven modulations, respectively | |||
674 | ||||
675 | return (uint32_t) symbolsPerSecond * bitsTransmittedPerSymbol; | |||
676 | } | |||
677 | ||||
678 | uint32_t | |||
679 | SimpleOfdmWimaxPhy::DoGetDataRate (WimaxPhy::ModulationType modulationType) const | |||
680 | { | |||
681 | switch (modulationType) | |||
682 | { | |||
683 | case MODULATION_TYPE_BPSK_12: | |||
684 | return m_dataRateBpsk12; | |||
685 | break; | |||
686 | case MODULATION_TYPE_QPSK_12: | |||
687 | return m_dataRateQpsk12; | |||
688 | break; | |||
689 | case MODULATION_TYPE_QPSK_34: | |||
690 | return m_dataRateQpsk34; | |||
691 | break; | |||
692 | case MODULATION_TYPE_QAM16_12: | |||
693 | return m_dataRateQam16_12; | |||
694 | break; | |||
695 | case MODULATION_TYPE_QAM16_34: | |||
696 | return m_dataRateQam16_34; | |||
697 | break; | |||
698 | case MODULATION_TYPE_QAM64_23: | |||
699 | return m_dataRateQam64_23; | |||
700 | break; | |||
701 | case MODULATION_TYPE_QAM64_34: | |||
702 | return m_dataRateQam64_34; | |||
703 | break; | |||
704 | } | |||
705 | NS_FATAL_ERROR ("Invalid modulation type")do { std::cerr << "msg=\"" << "Invalid modulation type" << "\", "; do { std::cerr << "file=" << "../src/wimax/model/simple-ofdm-wimax-phy.cc" << ", line=" << 705 << std::endl; ::ns3::FatalImpl ::FlushStreams (); if (true) std::terminate (); } while (false ); } while (false); | |||
706 | return 0; | |||
707 | } | |||
708 | ||||
709 | Time | |||
710 | SimpleOfdmWimaxPhy::GetBlockTransmissionTime (WimaxPhy::ModulationType modulationType) const | |||
711 | { | |||
712 | return Seconds ((double) GetFecBlockSize (modulationType) / DoGetDataRate (modulationType)); | |||
713 | } | |||
714 | ||||
715 | Time | |||
716 | SimpleOfdmWimaxPhy::DoGetTransmissionTime (uint32_t size, WimaxPhy::ModulationType modulationType) const | |||
717 | { | |||
718 | /*adding 3 extra nano second to cope with the loss of precision problem. | |||
719 | the time is internally stored in a 64 bit hence a floating-point time would loss | |||
720 | precision, e.g., 0.00001388888888888889 seconds will become 13888888888 femtoseconds.*/ | |||
721 | return Seconds (DoGetNrSymbols (size, modulationType) * GetSymbolDuration ().GetSeconds ()) + NanoSeconds (3); | |||
722 | } | |||
723 | ||||
724 | uint64_t | |||
725 | SimpleOfdmWimaxPhy::DoGetNrSymbols (uint32_t size, WimaxPhy::ModulationType modulationType) const | |||
726 | { | |||
727 | Time transmissionTime = Seconds ((double)(GetNrBlocks (size, modulationType) * GetFecBlockSize (modulationType)) | |||
728 | / DoGetDataRate (modulationType)); | |||
729 | return (uint64_t) std::ceil (transmissionTime.GetSeconds () / GetSymbolDuration ().GetSeconds ()); | |||
730 | } | |||
731 | ||||
732 | uint64_t | |||
733 | SimpleOfdmWimaxPhy::DoGetNrBytes (uint32_t symbols, WimaxPhy::ModulationType modulationType) const | |||
734 | { | |||
735 | Time transmissionTime = Seconds (symbols * GetSymbolDuration ().GetSeconds ()); | |||
736 | return (uint64_t) std::floor ((transmissionTime.GetSeconds () * DoGetDataRate (modulationType)) / 8); | |||
737 | } | |||
738 | ||||
739 | uint32_t | |||
740 | SimpleOfdmWimaxPhy::GetFecBlockSize (WimaxPhy::ModulationType modulationType) const | |||
741 | { | |||
742 | uint32_t blockSize = 0; | |||
743 | switch (modulationType) | |||
744 | { | |||
745 | case MODULATION_TYPE_BPSK_12: | |||
746 | blockSize = 12; | |||
747 | break; | |||
748 | case MODULATION_TYPE_QPSK_12: | |||
749 | blockSize = 24; | |||
750 | break; | |||
751 | case MODULATION_TYPE_QPSK_34: | |||
752 | blockSize = 36; | |||
753 | break; | |||
754 | case MODULATION_TYPE_QAM16_12: | |||
755 | blockSize = 48; | |||
756 | break; | |||
757 | case MODULATION_TYPE_QAM16_34: | |||
758 | blockSize = 72; | |||
759 | break; | |||
760 | case MODULATION_TYPE_QAM64_23: | |||
761 | blockSize = 96; | |||
762 | break; | |||
763 | case MODULATION_TYPE_QAM64_34: | |||
764 | blockSize = 108; | |||
765 | break; | |||
766 | default: | |||
767 | NS_FATAL_ERROR ("Invalid modulation type")do { std::cerr << "msg=\"" << "Invalid modulation type" << "\", "; do { std::cerr << "file=" << "../src/wimax/model/simple-ofdm-wimax-phy.cc" << ", line=" << 767 << std::endl; ::ns3::FatalImpl ::FlushStreams (); if (true) std::terminate (); } while (false ); } while (false); | |||
768 | break; | |||
769 | } | |||
770 | return blockSize * 8; // in bits | |||
771 | } | |||
772 | ||||
773 | // Channel coding block size, Table 215, page 434 | |||
774 | uint32_t | |||
775 | SimpleOfdmWimaxPhy::GetCodedFecBlockSize (WimaxPhy::ModulationType modulationType) const | |||
776 | { | |||
777 | uint32_t blockSize = 0; | |||
778 | switch (modulationType) | |||
779 | { | |||
780 | case MODULATION_TYPE_BPSK_12: | |||
781 | blockSize = 24; | |||
782 | break; | |||
783 | case MODULATION_TYPE_QPSK_12: | |||
784 | blockSize = 48; | |||
785 | break; | |||
786 | case MODULATION_TYPE_QPSK_34: | |||
787 | blockSize = 48; | |||
788 | break; | |||
789 | case MODULATION_TYPE_QAM16_12: | |||
790 | blockSize = 96; | |||
791 | break; | |||
792 | case MODULATION_TYPE_QAM16_34: | |||
793 | blockSize = 96; | |||
794 | break; | |||
795 | case MODULATION_TYPE_QAM64_23: | |||
796 | blockSize = 144; | |||
797 | break; | |||
798 | case MODULATION_TYPE_QAM64_34: | |||
799 | blockSize = 144; | |||
800 | break; | |||
801 | default: | |||
802 | NS_FATAL_ERROR ("Invalid modulation type")do { std::cerr << "msg=\"" << "Invalid modulation type" << "\", "; do { std::cerr << "file=" << "../src/wimax/model/simple-ofdm-wimax-phy.cc" << ", line=" << 802 << std::endl; ::ns3::FatalImpl ::FlushStreams (); if (true) std::terminate (); } while (false ); } while (false); | |||
803 | break; | |||
804 | } | |||
805 | return blockSize * 8; // in bits | |||
806 | } | |||
807 | ||||
808 | void | |||
809 | SimpleOfdmWimaxPhy::SetBlockParameters (uint32_t burstSize, WimaxPhy::ModulationType modulationType) | |||
810 | { | |||
811 | m_blockSize = GetFecBlockSize (modulationType); | |||
812 | m_nrBlocks = GetNrBlocks (burstSize, modulationType); | |||
813 | m_paddingBits = (m_nrBlocks * m_blockSize) - (burstSize * 8); | |||
814 | m_nrRemainingBlocksToSend = m_nrBlocks; | |||
815 | NS_ASSERT_MSG (static_cast<uint32_t> (m_nrBlocks * m_blockSize) >= (burstSize * 8), "Size of padding bytes < 0")do { if (!(static_cast<uint32_t> (m_nrBlocks * m_blockSize ) >= (burstSize * 8))) { std::cerr << "assert failed. cond=\"" << "static_cast<uint32_t> (m_nrBlocks * m_blockSize) >= (burstSize * 8)" << "\", "; do { std::cerr << "msg=\"" << "Size of padding bytes < 0" << "\", "; do { std::cerr << "file=" << "../src/wimax/model/simple-ofdm-wimax-phy.cc" << ", line=" << 815 << std::endl; ::ns3::FatalImpl ::FlushStreams (); if (true) std::terminate (); } while (false ); } while (false); } } while (false); | |||
816 | } | |||
817 | ||||
818 | uint16_t | |||
819 | SimpleOfdmWimaxPhy::DoGetTtg (void) const | |||
820 | { | |||
821 | // assumed equal to 2 symbols | |||
822 | return 2 * GetPsPerSymbol (); | |||
823 | } | |||
824 | ||||
825 | uint16_t | |||
826 | SimpleOfdmWimaxPhy::DoGetRtg (void) const | |||
827 | { | |||
828 | // assumed equal to 2 symbols | |||
829 | return 2 * GetPsPerSymbol (); | |||
830 | } | |||
831 | ||||
832 | uint8_t | |||
833 | SimpleOfdmWimaxPhy::DoGetFrameDurationCode (void) const | |||
834 | { | |||
835 | uint16_t duration = 0; | |||
836 | duration = (uint16_t)(GetFrameDuration ().GetSeconds () * 10000); | |||
837 | uint8_t retval = 0; | |||
838 | switch (duration) | |||
839 | { | |||
840 | case 25: | |||
841 | { | |||
842 | retval = FRAME_DURATION_2_POINT_5_MS; | |||
843 | break; | |||
844 | } | |||
845 | case 40: | |||
846 | { | |||
847 | retval = FRAME_DURATION_4_MS; | |||
848 | break; | |||
849 | } | |||
850 | case 50: | |||
851 | { | |||
852 | retval = FRAME_DURATION_5_MS; | |||
853 | break; | |||
854 | } | |||
855 | case 80: | |||
856 | { | |||
857 | retval = FRAME_DURATION_8_MS; | |||
858 | break; | |||
859 | } | |||
860 | case 100: | |||
861 | { | |||
862 | retval = FRAME_DURATION_10_MS; | |||
863 | break; | |||
864 | } | |||
865 | case 125: | |||
866 | { | |||
867 | retval = FRAME_DURATION_12_POINT_5_MS; | |||
868 | break; | |||
869 | } | |||
870 | case 200: | |||
871 | { | |||
872 | retval = FRAME_DURATION_20_MS; | |||
873 | break; | |||
874 | } | |||
875 | default: | |||
876 | { | |||
877 | NS_FATAL_ERROR ("Invalid frame duration = " << duration)do { std::cerr << "msg=\"" << "Invalid frame duration = " << duration << "\", "; do { std::cerr << "file=" << "../src/wimax/model/simple-ofdm-wimax-phy.cc" << ", line=" << 877 << std::endl; ::ns3::FatalImpl:: FlushStreams (); if (true) std::terminate (); } while (false) ; } while (false); | |||
878 | retval = 0; | |||
879 | } | |||
880 | } | |||
881 | return retval; | |||
882 | } | |||
883 | ||||
884 | Time | |||
885 | SimpleOfdmWimaxPhy::DoGetFrameDuration (uint8_t frameDurationCode) const | |||
886 | { | |||
887 | switch (frameDurationCode) | |||
888 | { | |||
889 | case FRAME_DURATION_2_POINT_5_MS: | |||
890 | return Seconds (2.5); | |||
891 | break; | |||
892 | case FRAME_DURATION_4_MS: | |||
893 | return Seconds (4); | |||
894 | break; | |||
895 | case FRAME_DURATION_5_MS: | |||
896 | return Seconds (5); | |||
897 | break; | |||
898 | case FRAME_DURATION_8_MS: | |||
899 | return Seconds (8); | |||
900 | break; | |||
901 | case FRAME_DURATION_10_MS: | |||
902 | return Seconds (10); | |||
903 | break; | |||
904 | case FRAME_DURATION_12_POINT_5_MS: | |||
905 | return Seconds (12.5); | |||
906 | break; | |||
907 | case FRAME_DURATION_20_MS: | |||
908 | return Seconds (20); | |||
909 | break; | |||
910 | default: | |||
911 | NS_FATAL_ERROR ("Invalid modulation type")do { std::cerr << "msg=\"" << "Invalid modulation type" << "\", "; do { std::cerr << "file=" << "../src/wimax/model/simple-ofdm-wimax-phy.cc" << ", line=" << 911 << std::endl; ::ns3::FatalImpl ::FlushStreams (); if (true) std::terminate (); } while (false ); } while (false); | |||
912 | } | |||
913 | return Seconds (0); | |||
914 | } | |||
915 | ||||
916 | /* | |||
917 | Retruns number of blocks (FEC blocks) the burst will be splitted in. | |||
918 | The size of the block is specific for each modulation type. | |||
919 | */ | |||
920 | uint16_t | |||
921 | SimpleOfdmWimaxPhy::GetNrBlocks (uint32_t burstSize, WimaxPhy::ModulationType modulationType) const | |||
922 | { | |||
923 | uint32_t blockSize = GetFecBlockSize (modulationType); | |||
924 | uint16_t nrBlocks = (burstSize * 8) / blockSize; | |||
925 | ||||
926 | if ((burstSize * 8) % blockSize > 0) | |||
927 | { | |||
928 | nrBlocks += 1; | |||
929 | } | |||
930 | ||||
931 | return nrBlocks; | |||
932 | } | |||
933 | /*---------------------PHY parameters functions-----------------------*/ | |||
934 | ||||
935 | void | |||
936 | SimpleOfdmWimaxPhy::DoSetPhyParameters (void) | |||
937 | { | |||
938 | /*Calculations as per section 8.3.2. | |||
939 | Currently assuming license-exempt 5 GHz band. For channel bandwidth 20 MHz (Table B.28, page 812) and frame duration 10 ms | |||
940 | (Table 232, page 460) i.e, 100 frames per second, sampling frequency is 23040000, symbol (OFDM symbol) duration is | |||
941 | 1.388888888888889e-05 seconds, PS duration is 1.7361111111111112e-07 seconds. Hence PSs per frame is 57600, symbols per frame | |||
942 | is 720 and PSs per symbol is 80. Note that defining these parameters (symbol and PS duration) as Time may not result in exaclty | |||
943 | these values therefore lrint has been used (otherwise should be defined as double). | |||
944 | For licensed bands set channel bandwidth according to Table B.26, page 810.*/ | |||
945 | ||||
946 | double samplingFrequency = DoGetSamplingFrequency (); | |||
947 | Time psDuration = Seconds ((double) 4 / samplingFrequency); | |||
948 | ||||
949 | SetPsDuration (psDuration); | |||
950 | uint16_t psPerFrame = (uint16_t)(GetFrameDuration ().GetSeconds () / psDuration.GetSeconds ()); | |||
951 | SetPsPerFrame (psPerFrame); | |||
952 | double subcarrierSpacing = samplingFrequency / DoGetNfft (); | |||
953 | double tb = (double) 1 / subcarrierSpacing; // Tb (useful symbol time) | |||
954 | double tg = DoGetGValue () * tb; // Tg (cyclic prefix time) | |||
955 | Time symbolDuration = Seconds (tb + tg); // OFDM Symbol Time | |||
956 | SetSymbolDuration (symbolDuration); | |||
957 | uint16_t psPerSymbol = lrint (symbolDuration.GetSeconds () / psDuration.GetSeconds ()); | |||
958 | SetPsPerSymbol (psPerSymbol); | |||
959 | uint32_t symbolsPerFrame = lrint (GetFrameDuration ().GetSeconds () / symbolDuration.GetSeconds ()); | |||
960 | SetSymbolsPerFrame (symbolsPerFrame); | |||
961 | } | |||
962 | ||||
963 | void | |||
964 | SimpleOfdmWimaxPhy::DoSetNfft (uint16_t nfft) | |||
965 | { | |||
966 | m_nfft = nfft; | |||
967 | ||||
968 | } | |||
969 | ||||
970 | uint16_t | |||
971 | SimpleOfdmWimaxPhy::DoGetNfft (void) const | |||
972 | { | |||
973 | return m_nfft; | |||
974 | ||||
975 | } | |||
976 | ||||
977 | double | |||
978 | SimpleOfdmWimaxPhy::DoGetSamplingFactor (void) const | |||
979 | { | |||
980 | // sampling factor (n), see Table 213, page 429 | |||
981 | ||||
982 | uint32_t channelBandwidth = GetChannelBandwidth (); | |||
983 | ||||
984 | if (channelBandwidth % 1750000 == 0) | |||
985 | { | |||
986 | return (double) 8 / 7; | |||
987 | } | |||
988 | else if (channelBandwidth % 1500000 == 0) | |||
989 | { | |||
990 | return (double) 86 / 75; | |||
991 | } | |||
992 | else if (channelBandwidth % 1250000 == 0) | |||
993 | { | |||
994 | return (double) 144 / 125; | |||
995 | } | |||
996 | else if (channelBandwidth % 2750000 == 0) | |||
997 | { | |||
998 | return (double) 316 / 275; | |||
999 | } | |||
1000 | else if (channelBandwidth % 2000000 == 0) | |||
1001 | { | |||
1002 | return (double) 57 / 50; | |||
1003 | } | |||
1004 | else | |||
1005 | { | |||
1006 | NS_LOG_DEBUG ("Oops may be wrong channel bandwidth for OFDM PHY!")do { if (g_log.IsEnabled (ns3::LOG_DEBUG)) { if (g_log.IsEnabled (ns3::LOG_PREFIX_TIME)) { ns3::LogTimePrinter printer = ns3:: LogGetTimePrinter (); if (printer != 0) { (*printer)(std::clog ); std::clog << " "; } }; if (g_log.IsEnabled (ns3::LOG_PREFIX_NODE )) { ns3::LogNodePrinter printer = ns3::LogGetNodePrinter (); if (printer != 0) { (*printer)(std::clog); std::clog << " "; } }; ; if (g_log.IsEnabled (ns3::LOG_PREFIX_FUNC)) { std ::clog << g_log.Name () << ":" << __FUNCTION__ << "(): "; }; if (g_log.IsEnabled (ns3::LOG_PREFIX_LEVEL )) { std::clog << "[" << g_log.GetLevelLabel (ns3 ::LOG_DEBUG) << "] "; }; std::clog << "Oops may be wrong channel bandwidth for OFDM PHY!" << std::endl; } } while (false); | |||
1007 | NS_FATAL_ERROR ("wrong channel bandwidth for OFDM PHY")do { std::cerr << "msg=\"" << "wrong channel bandwidth for OFDM PHY" << "\", "; do { std::cerr << "file=" << "../src/wimax/model/simple-ofdm-wimax-phy.cc" << ", line=" << 1007 << std::endl; ::ns3:: FatalImpl::FlushStreams (); if (true) std::terminate (); } while (false); } while (false); | |||
1008 | } | |||
1009 | ||||
1010 | return (double) 8 / 7; | |||
1011 | } | |||
1012 | ||||
1013 | double | |||
1014 | SimpleOfdmWimaxPhy::DoGetSamplingFrequency (void) const | |||
1015 | { | |||
1016 | // sampling frequency (Fs), see 8.3.2.2 | |||
1017 | ||||
1018 | return (DoGetSamplingFactor () * GetChannelBandwidth () / 8000) * 8000; | |||
1019 | } | |||
1020 | ||||
1021 | double | |||
1022 | SimpleOfdmWimaxPhy::DoGetGValue (void) const | |||
1023 | { | |||
1024 | ||||
1025 | return m_g; | |||
1026 | } | |||
1027 | ||||
1028 | void | |||
1029 | SimpleOfdmWimaxPhy::DoSetGValue (double g) | |||
1030 | { | |||
1031 | m_g = g; | |||
1032 | ||||
1033 | } | |||
1034 | ||||
1035 | void | |||
1036 | SimpleOfdmWimaxPhy::SetTxGain (double txGain) | |||
1037 | { | |||
1038 | m_txGain = txGain; | |||
1039 | } | |||
1040 | ||||
1041 | void | |||
1042 | SimpleOfdmWimaxPhy::SetRxGain (double txRain) | |||
1043 | { | |||
1044 | m_rxGain = txRain; | |||
1045 | } | |||
1046 | ||||
1047 | double | |||
1048 | SimpleOfdmWimaxPhy::GetTxGain (void) const | |||
1049 | { | |||
1050 | return m_txGain; | |||
1051 | } | |||
1052 | ||||
1053 | double | |||
1054 | SimpleOfdmWimaxPhy::GetRxGain (void) const | |||
1055 | { | |||
1056 | return m_rxGain; | |||
1057 | } | |||
1058 | ||||
1059 | std::string | |||
1060 | SimpleOfdmWimaxPhy::GetTraceFilePath (void) const | |||
1061 | { | |||
1062 | return (m_snrToBlockErrorRateManager->GetTraceFilePath ()); | |||
1063 | } | |||
1064 | ||||
1065 | void | |||
1066 | SimpleOfdmWimaxPhy::SetTraceFilePath (std::string path) | |||
1067 | { | |||
1068 | ||||
1069 | m_snrToBlockErrorRateManager->SetTraceFilePath ((char*) path.c_str ()); | |||
1070 | m_snrToBlockErrorRateManager->LoadTraces (); | |||
1071 | } | |||
1072 | ||||
1073 | void | |||
1074 | SimpleOfdmWimaxPhy::NotifyTxBegin (Ptr<PacketBurst> burst) | |||
1075 | { | |||
1076 | m_phyTxBeginTrace (burst); | |||
1077 | } | |||
1078 | ||||
1079 | void | |||
1080 | SimpleOfdmWimaxPhy::NotifyTxEnd (Ptr<PacketBurst> burst) | |||
1081 | { | |||
1082 | m_phyTxEndTrace (burst); | |||
1083 | } | |||
1084 | ||||
1085 | void | |||
1086 | SimpleOfdmWimaxPhy::NotifyTxDrop (Ptr<PacketBurst> burst) | |||
1087 | { | |||
1088 | m_phyTxDropTrace (burst); | |||
1089 | } | |||
1090 | ||||
1091 | void | |||
1092 | SimpleOfdmWimaxPhy::NotifyRxBegin (Ptr<PacketBurst> burst) | |||
1093 | { | |||
1094 | m_phyRxBeginTrace (burst); | |||
1095 | } | |||
1096 | ||||
1097 | void | |||
1098 | SimpleOfdmWimaxPhy::NotifyRxEnd (Ptr<PacketBurst> burst) | |||
1099 | { | |||
1100 | m_phyRxEndTrace (burst); | |||
1101 | } | |||
1102 | ||||
1103 | void | |||
1104 | SimpleOfdmWimaxPhy::NotifyRxDrop (Ptr<PacketBurst> burst) | |||
1105 | { | |||
1106 | m_phyRxDropTrace (burst); | |||
1107 | } | |||
1108 | ||||
1109 | int64_t | |||
1110 | SimpleOfdmWimaxPhy::AssignStreams (int64_t stream) | |||
1111 | { | |||
1112 | NS_LOG_FUNCTION (this << stream)do { if (g_log.IsEnabled (ns3::LOG_FUNCTION)) { if (g_log.IsEnabled (ns3::LOG_PREFIX_TIME)) { ns3::LogTimePrinter printer = ns3:: LogGetTimePrinter (); if (printer != 0) { (*printer)(std::clog ); std::clog << " "; } }; if (g_log.IsEnabled (ns3::LOG_PREFIX_NODE )) { ns3::LogNodePrinter printer = ns3::LogGetNodePrinter (); if (printer != 0) { (*printer)(std::clog); std::clog << " "; } }; ; std::clog << g_log.Name () << ":" << __FUNCTION__ << "("; ns3::ParameterLogger (std::clog) << this << stream; std::clog << ")" << std::endl ; } } while (false); | |||
1113 | m_URNG->SetStream (stream); | |||
1114 | return 1; | |||
1115 | } | |||
1116 | ||||
1117 | } // namespace ns3 |