A Discrete-Event Network Simulator
API
wifi-spectrum-value-helper.cc
Go to the documentation of this file.
1 /* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
2 /*
3  * Copyright (c) 2009 CTTC
4  * Copyright (c) 2010 TELEMATICS LAB, DEE - Politecnico di Bari
5  *
6  * This program is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License version 2 as
8  * published by the Free Software Foundation;
9  *
10  * This program is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13  * GNU General Public License for more details.
14  *
15  * You should have received a copy of the GNU General Public License
16  * along with this program; if not, write to the Free Software
17  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
18  *
19  * Author: Nicola Baldo <nbaldo@cttc.es>
20  * Giuseppe Piro <g.piro@poliba.it>
21  */
22 
23 #include <map>
24 #include <cmath>
26 #include "ns3/log.h"
27 #include "ns3/fatal-error.h"
28 #include "ns3/assert.h"
29 
30 namespace ns3 {
31 
32 NS_LOG_COMPONENT_DEFINE ("WifiSpectrumValueHelper");
33 
35 {
36  WifiSpectrumModelId (uint32_t f, uint32_t w);
38  uint32_t m_channelWidth;
39 };
40 
42  : m_centerFrequency (f),
43  m_channelWidth (w)
44 {
45  NS_LOG_FUNCTION (this << f << w);
46 }
47 
48 bool
50 {
52 }
53 
54 static std::map<WifiSpectrumModelId, Ptr<SpectrumModel> > g_wifiSpectrumModelMap;
55 
57 WifiSpectrumValueHelper::GetSpectrumModel (uint32_t centerFrequency, uint32_t channelWidth)
58 {
59  NS_LOG_FUNCTION (centerFrequency << channelWidth);
61  WifiSpectrumModelId key (centerFrequency, channelWidth);
62  std::map<WifiSpectrumModelId, Ptr<SpectrumModel> >::iterator it = g_wifiSpectrumModelMap.find (key);
63  if (it != g_wifiSpectrumModelMap.end ())
64  {
65  ret = it->second;
66  }
67  else
68  {
69  Bands bands;
70  double centerFrequencyHz = centerFrequency * 1e6;
71  // Overall bandwidth will be channelWidth plus 10 MHz guards on each side
72  double bandwidth = (channelWidth + 20) * 1e6;
73  // Use OFDM subcarrier width of 312.5 KHz as band granularity
74  double bandBandwidth = 312500;
75  // For OFDM, the center subcarrier is null (at center frequency)
76  uint32_t numBands = static_cast<uint32_t> (bandwidth / bandBandwidth + 0.5);
77  NS_ASSERT (numBands > 0);
78  if (numBands % 2 == 0)
79  {
80  // round up to the nearest odd number of subbands so that bands
81  // are symmetric around center frequency
82  NS_LOG_DEBUG ("Total bandwidth evenly divided by 312.5 KHz");
83  numBands += 1;
84  }
85  NS_ASSERT_MSG (numBands % 2 == 1, "Number of bands should be odd");
86  // lay down numBands/2 bands symmetrically around center frequency
87  // and place an additional band at center frequency
88  double startingFrequencyHz = centerFrequencyHz - (numBands/2 * bandBandwidth) - bandBandwidth/2;
89  for (size_t i = 0; i < numBands; i++)
90  {
91  BandInfo info;
92  double f = startingFrequencyHz + (i * bandBandwidth);
93  info.fl = f;
94  f += bandBandwidth/2;
95  info.fc = f;
96  f += bandBandwidth/2;
97  info.fh = f;
98  NS_LOG_DEBUG ("creating band " << i << " (" << info.fl << ":" << info.fc << ":" << info.fh << ")");
99  bands.push_back (info);
100  }
101  ret = Create<SpectrumModel> (bands);
102  g_wifiSpectrumModelMap.insert (std::pair<WifiSpectrumModelId, Ptr<SpectrumModel> > (key, ret));
103  }
104  NS_LOG_LOGIC ("returning SpectrumModel::GetUid () == " << ret->GetUid ());
105  return ret;
106 }
107 
109 WifiSpectrumValueHelper::CreateHtOfdmTxPowerSpectralDensity (uint32_t centerFrequency, uint32_t channelWidth, double txPowerW)
110 {
111  NS_LOG_FUNCTION (centerFrequency << channelWidth << txPowerW);
112  Ptr<SpectrumValue> c = Create<SpectrumValue> (GetSpectrumModel (centerFrequency, channelWidth));
113  Values::iterator vit = c->ValuesBegin ();
114  Bands::const_iterator bit = c->ConstBandsBegin ();
115  double txPowerPerBand;
116  switch (channelWidth)
117  {
118  case 20:
119  // 56 subcarriers (52 data + 4 pilot)
120  NS_ASSERT_MSG (c->GetSpectrumModel ()->GetNumBands () == 129, "Unexpected number of bands");
121  // skip 32 subbands, then place power in 28 of the next 32 subbands, then
122  // skip the center subband, then place power in 28 of the next 32
123  // subbands, then skip the final 32 subbands.
124  txPowerPerBand = txPowerW / 56;
125  for (size_t i = 0; i < c->GetSpectrumModel ()->GetNumBands (); i++, vit++, bit++)
126  {
127  if ((i >=36 && i <=63) || (i >=65 && i <=92))
128  {
129  *vit = txPowerPerBand / (bit->fh - bit->fl);
130  }
131  }
132  NS_LOG_DEBUG ("Added signal power to subbands 36-63 and 65-92");
133  NS_LOG_DEBUG ("Integrated power " << Integral (*c));
134  NS_ASSERT_MSG (std::abs (txPowerW - Integral (*c)) < 1e-6, "Power allocation failed");
135  break;
136  case 40:
137  // 112 subcarriers (104 data + 8 pilot)
138  // possible alternative: 114 subcarriers (108 data + 6 pilot)
139  NS_ASSERT_MSG (c->GetSpectrumModel ()->GetNumBands () == 193, "Unexpected number of bands");
140  txPowerPerBand = txPowerW / 112;
141  for (size_t i = 0; i < c->GetSpectrumModel ()->GetNumBands (); i++, vit++, bit++)
142  {
143  if ((i >=36 && i <=63) || (i >=65 && i <=92) || (i >=100 && i<=127) || (i >=129 && i<= 156))
144  {
145  *vit = txPowerPerBand / (bit->fh - bit->fl);
146  }
147  }
148  NS_LOG_DEBUG ("Added signal power to subbands 36-63, 65-92, 100-127, and 129-156");
149  NS_LOG_DEBUG ("Integrated power " << Integral (*c));
150  NS_ASSERT_MSG (std::abs (txPowerW - Integral (*c)) < 1e-6, "Power allocation failed");
151  break;
152  case 80:
153  // 224 subcarriers (208 data + 16 pilot)
154  // possible alternative: 242 subcarriers (234 data + 8 pilot)
155  NS_ASSERT_MSG (c->GetSpectrumModel ()->GetNumBands () == 321, "Unexpected number of bands");
156  txPowerPerBand = txPowerW / 224;
157  for (size_t i = 0; i < c->GetSpectrumModel ()->GetNumBands (); i++, vit++, bit++)
158  {
159  if ((i >= 36 && i <= 63) || (i >= 65 && i <= 92) ||
160  (i >= 100 && i <= 127) || (i >= 129 && i <= 156) ||
161  (i >= 164 && i <= 191) || (i >= 193 && i <= 220) ||
162  (i >= 228 && i <= 255) || (i >= 257 && i <= 284))
163  {
164  *vit = txPowerPerBand / (bit->fh - bit->fl);
165  }
166  }
167  NS_LOG_DEBUG ("Added signal power to subbands 36-63, 65-92, 100-127, 129-156, 164-191, 193-220, 228-255, 257-284");
168  NS_LOG_DEBUG ("Integrated power " << Integral (*c));
169  NS_ASSERT_MSG (std::abs (txPowerW - Integral (*c)) < 1e-6, "Power allocation failed");
170  break;
171  case 160:
172  // 448 subcarriers (416 data + 32 pilot) VHT
173  // possible alternative: 484 subcarriers (468 data + 16 pilot)
174  NS_ASSERT_MSG (c->GetSpectrumModel ()->GetNumBands () == 577, "Unexpected number of bands");
175  txPowerPerBand = txPowerW / 448;
176  for (size_t i = 0; i < c->GetSpectrumModel ()->GetNumBands (); i++, vit++, bit++)
177  {
178  if ((i >= 36 && i <= 63) || (i >= 65 && i <= 92) ||
179  (i >= 100 && i <= 127) || (i >= 129 && i <= 156) ||
180  (i >= 164 && i <= 191) || (i >= 193 && i <= 220) ||
181  (i >= 228 && i <= 255) || (i >= 257 && i <= 284) ||
182  (i >= 292 && i <= 319) || (i >= 321 && i <= 348) ||
183  (i >= 356 && i <= 383) || (i >= 385 && i <= 412) ||
184  (i >= 420 && i <= 447) || (i >= 449 && i <= 476) ||
185  (i >= 484 && i <= 511) || (i >= 513 && i <= 540))
186  {
187  *vit = txPowerPerBand / (bit->fh - bit->fl);
188  }
189  }
190  NS_LOG_DEBUG ("Added signal power to subbands 36-63, 65-92, 100-127, 129-156, 164-191, 193-220, 228-255, 257-284, 292-319, 321-348, 356-383, 385-412, 420-447, 449-476, 484-511, and 513-540");
191  NS_LOG_DEBUG ("Integrated power " << Integral (*c));
192  NS_ASSERT_MSG (std::abs (txPowerW - Integral (*c)) < 1e-6, "Power allocation failed");
193  break;
194  default:
195  NS_FATAL_ERROR ("ChannelWidth " << channelWidth << " unsupported");
196  break;
197  }
198  return c;
199 }
200 
202 WifiSpectrumValueHelper::CreateOfdmTxPowerSpectralDensity (uint32_t centerFrequency, uint32_t channelWidth, double txPowerW)
203 {
204  NS_LOG_FUNCTION (centerFrequency << channelWidth << txPowerW);
205  Ptr<SpectrumValue> c = Create<SpectrumValue> (GetSpectrumModel (centerFrequency, channelWidth));
206  Values::iterator vit = c->ValuesBegin ();
207  Bands::const_iterator bit = c->ConstBandsBegin ();
208  double txPowerPerBand;
209  switch (channelWidth)
210  {
211  case 20:
212  // 52 subcarriers (48 data + 4 pilot)
213  // skip 38 subbands, then place power in 26 subbands, then
214  // skip the center subband, then place power in 26 subbands, then skip
215  // the final 38 subbands.
216  NS_ASSERT_MSG (c->GetSpectrumModel ()->GetNumBands () == 129, "Unexpected number of bands");
217  txPowerPerBand = txPowerW / 52;
218  for (size_t i = 0; i < c->GetSpectrumModel ()->GetNumBands (); i++, vit++, bit++)
219  {
220  if ((i >=38 && i <=63) || (i >=65 && i <=90))
221  {
222  *vit = txPowerPerBand / (bit->fh - bit->fl);
223  }
224  else
225  {
226  *vit = 0;
227  }
228  }
229  NS_LOG_DEBUG ("Added signal power to subbands 38-63 and 65-90");
230  NS_LOG_DEBUG ("Integrated power " << Integral (*c));
231  NS_ASSERT_MSG (std::abs (txPowerW - Integral (*c)) < 1e-6, "Power allocation failed");
232  break;
233  case 10:
234  // 28 subcarriers (24 data + 4 pilot)
235  // skip 34 subbands, then place power in 14 subbands, then
236  // skip the center subband, then place power in 14 subbands, then skip
237  // the final 34 subbands.
238  NS_ASSERT_MSG (c->GetSpectrumModel ()->GetNumBands () == 97, "Unexpected number of bands");
239  txPowerPerBand = txPowerW / 28;
240  for (size_t i = 0; i < c->GetSpectrumModel ()->GetNumBands (); i++, vit++, bit++)
241  {
242  if ((i >=34 && i <=47) || (i >=49 && i <=62))
243  {
244  *vit = txPowerPerBand / (bit->fh - bit->fl);
245  }
246  else
247  {
248  *vit = 0;
249  }
250  }
251  NS_LOG_DEBUG ("Added signal power to subbands 34-47 and 49-62");
252  NS_LOG_DEBUG ("Integrated power " << Integral (*c));
253  NS_ASSERT_MSG (std::abs (txPowerW - Integral (*c)) < 1e-6, "Power allocation failed");
254  break;
255  case 5:
256  // 16 subcarriers (12 data + 4 pilot)
257  // skip 34 subbands, then place power in 14 subbands, then
258  // skip the center subband, then place power in 14 subbands, then skip
259  // the final 34 subbands.
260  NS_ASSERT_MSG (c->GetSpectrumModel ()->GetNumBands () == 81, "Unexpected number of bands");
261  txPowerPerBand = txPowerW / 16;
262  for (size_t i = 0; i < c->GetSpectrumModel ()->GetNumBands (); i++, vit++, bit++)
263  {
264  if ((i >=32 && i <=39) || (i >=41 && i <=48))
265  {
266  *vit = txPowerPerBand / (bit->fh - bit->fl);
267  }
268  else
269  {
270  *vit = 0;
271  }
272  }
273  NS_LOG_DEBUG ("Added signal power to subbands 32-39 and 41-48");
274  NS_LOG_DEBUG ("Integrated power " << Integral (*c));
275  NS_ASSERT_MSG (std::abs (txPowerW - Integral (*c)) < 1e-6, "Power allocation failed");
276  break;
277  default:
278  NS_FATAL_ERROR ("ChannelWidth " << channelWidth << " unsupported");
279  break;
280  }
281  return c;
282 }
283 
284 // Power allocated to 71 center subbands out of 135 total subbands in the band
286 WifiSpectrumValueHelper::CreateDsssTxPowerSpectralDensity (uint32_t centerFrequency, double txPowerW)
287 {
288  NS_LOG_FUNCTION (centerFrequency << txPowerW);
289  uint32_t channelWidth = 22; // DSSS channels are 22 MHz wide
290  Ptr<SpectrumValue> c = Create<SpectrumValue> (GetSpectrumModel (centerFrequency, channelWidth));
291  Values::iterator vit = c->ValuesBegin ();
292  Bands::const_iterator bit = c->ConstBandsBegin ();
293  double txPowerPerBand;
294  // Evenly spread power across 22 MHz (71 bands)
295  NS_ASSERT (c->GetSpectrumModel ()->GetNumBands () == 135);
296  txPowerPerBand = txPowerW / 71;
297  for (size_t i = 0; i < c->GetSpectrumModel ()->GetNumBands (); i++, vit++, bit++)
298  {
299  if (i >=32 && i <=102)
300  {
301  *vit = txPowerPerBand / (bit->fh - bit->fl);
302  }
303  }
304  return c;
305 }
306 
308 WifiSpectrumValueHelper::CreateNoisePowerSpectralDensity (uint32_t centerFrequency, uint32_t channelWidth, double noiseFigure)
309 {
310  Ptr<SpectrumModel> model = GetSpectrumModel (centerFrequency, channelWidth);
311  return CreateNoisePowerSpectralDensity (noiseFigure, model);
312 }
313 
316 {
317  NS_LOG_FUNCTION (noiseFigureDb << spectrumModel);
318 
319  // see "LTE - From theory to practice"
320  // Section 22.4.4.2 Thermal Noise and Receiver Noise Figure
321  const double kT_dBm_Hz = -174.0; // dBm/Hz
322  double kT_W_Hz = std::pow (10.0, (kT_dBm_Hz - 30) / 10.0);
323  double noiseFigureLinear = std::pow (10.0, noiseFigureDb / 10.0);
324  double noisePowerSpectralDensity = kT_W_Hz * noiseFigureLinear;
325 
326  Ptr<SpectrumValue> noisePsd = Create <SpectrumValue> (spectrumModel);
327  (*noisePsd) = noisePowerSpectralDensity;
328  NS_LOG_DEBUG ("NoisePowerSpectralDensity has integrated power of " << Integral (*noisePsd));
329  return noisePsd;
330 }
331 
333 WifiSpectrumValueHelper::CreateRfFilter (uint32_t centerFrequency, uint32_t channelWidth)
334 {
335  NS_LOG_FUNCTION (centerFrequency << channelWidth);
336  Ptr<SpectrumValue> c = Create <SpectrumValue> (GetSpectrumModel (centerFrequency, channelWidth));
337  size_t numBands = c->GetSpectrumModel ()->GetNumBands ();
338  Bands::const_iterator bit = c->ConstBandsBegin ();
339  Values::iterator vit = c->ValuesBegin ();
340  uint32_t bandBandwidth = static_cast<uint32_t> (((bit->fh - bit->fl) + 0.5));
341  NS_LOG_DEBUG ("Band bandwidth: " << bandBandwidth);
342  size_t numBandsInFilter = static_cast<size_t> (channelWidth * 1e6 / bandBandwidth);
343  if (channelWidth % bandBandwidth != 0)
344  {
345  numBandsInFilter += 1;
346  }
347  NS_LOG_DEBUG ("Num bands in filter: " << numBandsInFilter);
348  // Set the value of the filter to 1 for the center-most numBandsInFilter
349  NS_ASSERT_MSG ((numBandsInFilter % 2 == 1) && (numBands % 2 == 1), "Should have odd number of bands");
350  size_t startIndex = (numBands - numBandsInFilter) / 2;
351  vit += startIndex;
352  bit += startIndex;
353  for (size_t i = startIndex; i < startIndex + numBandsInFilter; i++, vit++, bit++)
354  {
355  *vit = 1;
356  }
357  NS_LOG_DEBUG ("Added subbands " << startIndex << " to " << startIndex + numBandsInFilter << " to filter");
358  return c;
359 }
360 
362 
364 {
365 }
366 
368 {
369 }
370 
375 {
376 public:
378  {
379  Bands bands;
380  for (int i = -4; i < 13 + 7; i++)
381  {
382  BandInfo bi;
383  bi.fl = 2407.0e6 + i * 5.0e6;
384  bi.fh = 2407.0e6 + (i + 1) * 5.0e6;
385  bi.fc = (bi.fl + bi.fh) / 2;
386  bands.push_back (bi);
387  }
388  g_WifiSpectrumModel5Mhz = Create<SpectrumModel> (bands);
389  }
391 
392 
393 
394 Ptr<SpectrumValue>
396 {
397  Ptr<SpectrumValue> c = Create <SpectrumValue> (g_WifiSpectrumModel5Mhz);
398  (*c) = v;
399  return c;
400 }
401 
402 
405 {
406  Ptr<SpectrumValue> txPsd = Create <SpectrumValue> (g_WifiSpectrumModel5Mhz);
407 
408  // since the spectrum model has a resolution of 5 MHz, we model
409  // the transmitted signal with a constant density over a 20MHz
410  // bandwidth centered on the center frequency of the channel. The
411  // transmission power outside the transmission power density is
412  // calculated considering the transmit spectrum mask, see IEEE
413  // Std. 802.11-2007, Annex I
414 
415  double txPowerDensity = txPower / 20e6;
416 
417  NS_ASSERT (channel >= 1);
418  NS_ASSERT (channel <= 13);
419 
420  (*txPsd)[channel - 1] = txPowerDensity * 1e-4; // -40dB
421  (*txPsd)[channel] = txPowerDensity * 1e-4; // -40dB
422  (*txPsd)[channel + 1] = txPowerDensity * 0.0015849; // -28dB
423  (*txPsd)[channel + 2] = txPowerDensity * 0.0015849; // -28dB
424  (*txPsd)[channel + 3] = txPowerDensity;
425  (*txPsd)[channel + 4] = txPowerDensity;
426  (*txPsd)[channel + 5] = txPowerDensity;
427  (*txPsd)[channel + 6] = txPowerDensity;
428  (*txPsd)[channel + 7] = txPowerDensity * 0.0015849; // -28dB
429  (*txPsd)[channel + 8] = txPowerDensity * 0.0015849; // -28dB
430  (*txPsd)[channel + 9] = txPowerDensity * 1e-4; // -40dB
431  (*txPsd)[channel + 10] = txPowerDensity * 1e-4; // -40dB
432 
433  return txPsd;
434 }
435 
436 
439 {
440  Ptr<SpectrumValue> rf = Create <SpectrumValue> (g_WifiSpectrumModel5Mhz);
441 
442  NS_ASSERT (channel >= 1);
443  NS_ASSERT (channel <= 13);
444 
445  (*rf)[channel + 3] = 1;
446  (*rf)[channel + 4] = 1;
447  (*rf)[channel + 5] = 1;
448  (*rf)[channel + 6] = 1;
449 
450  return rf;
451 }
452 
453 
454 } // namespace ns3
tuple channel
Definition: third.py:85
static std::map< WifiSpectrumModelId, Ptr< SpectrumModel > > g_wifiSpectrumModelMap
static Ptr< SpectrumModel > GetSpectrumModel(uint32_t centerFrequency, uint32_t channelWidth)
Return a SpectrumModel instance corresponding to the center frequency and channel width...
#define NS_LOG_FUNCTION(parameters)
If log level LOG_FUNCTION is enabled, this macro will output all input parameters separated by "...
size_t GetNumBands() const
static class ns3::WifiSpectrumModel5MhzInitializer g_WifiSpectrumModel5MhzInitializerInstance
initialization instance for WifiSpectrumModel5Mhz
double Integral(const SpectrumValue &arg)
#define NS_ASSERT(condition)
At runtime, in debugging builds, if this condition is not true, the program prints the source file...
Definition: assert.h:67
#define NS_LOG_COMPONENT_DEFINE(name)
Define a Log component with a specific name.
Definition: log.h:201
#define NS_FATAL_ERROR(msg)
Report a fatal error with a message and terminate.
Definition: fatal-error.h:162
static Ptr< SpectrumValue > CreateHtOfdmTxPowerSpectralDensity(uint32_t centerFrequency, uint32_t channelWidth, double txPowerW)
Create a transmit power spectral density corresponding to OFDM High Throughput (HT) (802...
std::vector< BandInfo > Bands
Container of BandInfo.
static Ptr< SpectrumValue > CreateDsssTxPowerSpectralDensity(uint32_t centerFrequency, double txPowerW)
Create a transmit power spectral density corresponding to DSSS.
virtual Ptr< SpectrumValue > CreateTxPowerSpectralDensity(double txPower, uint32_t channel)
Creates a SpectrumValue instance that represents the TX Power Spectral Density of a wifi device corre...
SpectrumModelUid_t GetUid() const
Ptr< const SpectrumModel > GetSpectrumModel() const
double fc
center frequency
#define NS_LOG_LOGIC(msg)
Use NS_LOG to output a message of level LOG_LOGIC.
Definition: log.h:252
static Ptr< SpectrumValue > CreateRfFilter(uint32_t centerFrequency, uint32_t channelWidth)
bool operator<(const int64x64_t &lhs, const int64x64_t &rhs)
Less than operator.
Definition: int64x64-128.h:356
Bands::const_iterator ConstBandsBegin() const
double f(double x, void *params)
Definition: 80211b.c:60
Every class exported by the ns3 library is enclosed in the ns3 namespace.
double fl
lower limit of subband
virtual Ptr< SpectrumValue > CreateConstant(double psd)
Creates a SpectrumValue instance with a constant value for all frequencies.
static Ptr< SpectrumValue > CreateNoisePowerSpectralDensity(uint32_t centerFrequency, uint32_t channelWidth, double noiseFigure)
virtual Ptr< SpectrumValue > CreateRfFilter(uint32_t channel)
Creates a SpectrumValue instance which represents the frequency response of the RF filter which is us...
static Ptr< SpectrumValue > CreateOfdmTxPowerSpectralDensity(uint32_t centerFrequency, uint32_t channelWidth, double txPowerW)
Create a transmit power spectral density corresponding to OFDM (802.11a/g).
#define NS_ASSERT_MSG(condition, message)
At runtime, in debugging builds, if this condition is not true, the program prints the message to out...
Definition: assert.h:90
virtual ~WifiSpectrumValueHelper()
Destructor.
Values::iterator ValuesBegin()
#define NS_LOG_DEBUG(msg)
Use NS_LOG to output a message of level LOG_DEBUG.
Definition: log.h:236
Static class to initialize the values for the 2.4 GHz Wi-Fi spectrum model.
double fh
upper limit of subband
static Ptr< SpectrumModel > g_WifiSpectrumModel5Mhz
The building block of a SpectrumModel.
WifiSpectrumModelId(uint32_t f, uint32_t w)