Physical Layer DSP Design of a Wireless Gigabit/s Indoor LAN by

Physical Layer DSP Design of a
Wireless Gigabit/s Indoor LAN
by
Eladio Clemente Arvelo
Submitted to the Department of Electrical Engineering and Computer Science
in Partial Fulfillment of the Requirements for the Degree of
Master of Engineering in Electrical Engineering and Computer Science
at the Massachusetts Institute of Technology jointly with QUALCOMM Incorporated
May 2000
Copyright  2000 Eladio C. Arvelo. All rights reserved.
The author hereby grants to M.I.T. permission to reproduce and distribute publicly
paper and electronic copies of this thesis and to grant others the right to do so.
Author_______________________________________________________________________
Department of Electrical Engineering and Computer Science
May 22, 2000
Certified by___________________________________________________________________
Charles G. Sodini
MIT Thesis Supervisor
Certified by___________________________________________________________________
Robert P. Gilmore
QUALCOMM Thesis Supervisor
Accepted by___________________________________________________________________
Arthur C. Smith
Chairman, Department Committee on Graduate These
Physical Layer DSP Design of a
Wireless Gigabit/s Indoor LAN
by
Eladio Clemente Arvelo
earvelo@alum.mit.edu
Submitted to the
Department of Electrical Engineering and Computer Science
May 22, 2000
In Partial Fulfillment of the Requirements for the Degree of
Master of Engineering in Electrical Engineering and Computer Science
at the Massachusetts Institute of Technology jointly with QUALCOMM Incorporated
Abstract
The Wireless Gigabit/s Local-Area Network (WGLAN) project is aimed at providing highspeed data transmission between the Next Generation Internet and end-use devices within the
home or office environment. The design of the digital signal processing (DSP) required at the
physical layer of the network is the focus of this thesis. In particular, this thesis models the
indoor radio channel environment at the 5.x GHz Unlicensed National Information
Infrastructure (U-NII) frequency band, and proposes a multipath-resistant transceiver design
based on Orthogonal Frequency Division Multiplexing (OFDM) with adaptive multilevel
Quadrature Amplitude Modulation (M-QAM). The proposed network design allows two-way
communication through a Time Division Duplexing (TDD) scheme and provides multiuser
support through a series of algorithms that establish session links and allocate subchannels
among devices in an optimal way. Finally, a custom-written software simulation is used to
estimate the bit error rate (BER) network performance under different channel conditions.
MIT Thesis Supervisor: Charles G. Sodini
Title: Professor, Electrical Engineering and Computer Science
Acknowledgments
My heartful appreciation goes to my thesis supervisors, Prof. Charles Sodini at MIT
who provided me with the opportunity to work on the design of such an interesting project as
the WGLAN system, and Rob Gilmore at Qualcomm who provided the technical expertise to
shape the focus of this thesis as well as verifying the final design.
I would like to thank Qualcomm Incorporated and the MIT VI-A Internship Program
for sponsoring this thesis. In addition, I would like to acknowledge the helpful comments
provided by the engineering team at Qualcomm, in particular by Rajiv Vijayan, who provided
assistance on software simulation issues, and Prof. Elvino Sousa, who found time to review my
thought process regarding OFDM system design.
For providing the brain power to discuss technical issues related to this thesis, I would
like to thank Beng-Teck Lim and Durodami Lisk for their valuable time. I would also like to
thank my fellow MIT Co-Op interns at Qualcomm for making the summer an enjoyable time.
Finally, I would like to dedicate this thesis to my parents, sister, and extended family
who have always supported me in pursuing my own dreams wherever they may lead.
Table of Contents
CHAPTER 1 : INTRODUCTION ...................................................................................................... 11
1.1
1.2
1.3
SYSTEM SPECIFICATIONS........................................................................................................ 12
THESIS FOCUS ........................................................................................................................ 13
THESIS OUTLINE .................................................................................................................... 14
CHAPTER 2 : WLAN CONCEPTS & STANDARDS ...................................................................... 15
2.1
WLAN TECHNOLOGIES.......................................................................................................... 15
2.1.1 Narrowband Technology ................................................................................................... 16
2.1.2 Spread Spectrum Technology ............................................................................................ 16
2.1.3 Infrared Technology .......................................................................................................... 18
2.1.4 Efficiency Considerations.................................................................................................. 18
2.2
WLAN CONFIGURATIONS ...................................................................................................... 19
2.3
RADIO SPECTRUM REGULATIONS ........................................................................................... 19
2.4
IEEE 802.11 WLAN STANDARD ........................................................................................... 21
2.4.1 Network Topologies........................................................................................................... 22
2.4.2 Physical Layer Architecture .............................................................................................. 23
2.4.3 FHSS Physical Layer ........................................................................................................ 24
2.4.4 DSSS Physical Layer ......................................................................................................... 26
2.5
HIPERLAN STANDARD ......................................................................................................... 28
2.5.1 Channel Access ................................................................................................................. 28
2.5.2 Physical Layer .................................................................................................................. 29
2.6
BLUETOOTH SPECIFICATION ................................................................................................... 30
CHAPTER 3 : CHANNEL ANALYSIS ............................................................................................. 31
3.1
CHARACTERIZING INDOOR RADIO CHANNELS ........................................................................ 31
3.1.1 Power Delay Profile.......................................................................................................... 33
3.1.2 Path Loss .......................................................................................................................... 33
3.1.3 Delay Spread..................................................................................................................... 34
3.1.4 Coherence Bandwidth ....................................................................................................... 35
3.1.5 Doppler Spread ................................................................................................................. 36
3.1.6 Small-Scale Flat Fading.................................................................................................... 36
3.2
CHANNEL PARAMETERS ......................................................................................................... 37
3.2.1 Propagation at 5.2 GHz .................................................................................................... 37
3.2.2 Propagation at 5.8 GHz .................................................................................................... 38
3.2.3 Selected Parameters .......................................................................................................... 38
3.3
CHANNEL MODELS ................................................................................................................. 39
3.4
LINK BUDGET ........................................................................................................................ 40
3.4.1 Frequency Band Allocations.............................................................................................. 40
3.4.2 Controller’s Link Budget ................................................................................................... 42
3.4.3 Adapter’s Link Budget....................................................................................................... 44
3.5
CHANNEL CAPACITY .............................................................................................................. 46
CHAPTER 4 : MODULATION AND DEMODULATION .............................................................. 47
4.1
THE OFDM CONCEPT ............................................................................................................ 47
4.1.1 Conventional FDM Technology......................................................................................... 48
4.1.2 Orthogonal FDM Technology ........................................................................................... 49
4.2
TRANSMITTER BLOCK DIAGRAM ............................................................................................ 52
6
4.3
4.4
RECEIVER BLOCK DIAGRAM................................................................................................... 54
CHOOSING SYSTEM PARAMETERS........................................................................................... 56
CHAPTER 5 : MULTIPLE ACCESS SCHEME .............................................................................. 59
5.1
NETWORK T OPOLOGY ............................................................................................................ 59
5.2
NEGOTIATING A COMMUNICATION LINK ................................................................................ 61
5.2.1 Controller-to-Adapter Link Request .................................................................................. 61
5.2.2 Adapter-to-Controller Link Request .................................................................................. 62
5.2.3 Adapter-to-Adapter Link Request ...................................................................................... 62
5.3
CONTROL CHANNEL ............................................................................................................... 63
5.3.1 Transmitting bits through the Control Channel ................................................................. 63
5.3.2 Receiving bits through the Control Channel...................................................................... 64
5.4
DATA CHANNELS ................................................................................................................... 65
5.4.1 Preliminary Considerations .............................................................................................. 65
5.4.2 Subchannel Allocation Algorithm ...................................................................................... 65
5.4.3 Special Cases .................................................................................................................... 70
5.5
LINK MAINTENANCE .............................................................................................................. 71
CHAPTER 6 : SOFTWARE SIMULATION..................................................................................... 73
6.1
SIMULATION MODEL .............................................................................................................. 73
6.2
SOFTWARE E NVIRONMENT ..................................................................................................... 74
6.2.1 Parameters Header File .................................................................................................... 75
6.2.2 Simulator Program File .................................................................................................... 76
6.2.3 Data Abstraction Files ...................................................................................................... 77
6.3
SIMULATION SCENARIOS AND RESULTS .................................................................................. 79
6.3.1 Static Channel Scenarios................................................................................................... 80
6.3.2 Dynamic Channel Scenarios.............................................................................................. 81
6.3.3 Interference Channel Scenarios......................................................................................... 82
6.3.4 Subchannel Capacity Estimation ....................................................................................... 83
CHAPTER 7 : CONCLUSION........................................................................................................... 85
7.1
7.2
7.3
7.4
CHANNEL CHARACTERISTICS ................................................................................................. 85
MODULATION AND DEMODULATION....................................................................................... 86
MULTIPLE ACCESS SCHEME ................................................................................................... 87
SIMULATION AND FUTURE WORK ........................................................................................... 88
BIBLIOGRAPHY ………………………………………………………………………………………. 89
APPENDIX I: SIMULATION RESULTS…………………………………………………………….. 95
APPENDIX II: SIMULATION PROGRAM………………………………………………………… 113
7
List of Figures
FIGURE 1. WGLAN TOPOLOGY .............................................................................................................. 12
FIGURE 2. DESIGN METHODOLOGY ......................................................................................................... 13
FIGURE 3. NARROWBAND DIVIDES THE SPECTRUM INTO SUBCHANNELS WHILE SPREAD SPECTRUM EXTENDS
THE ENTIRE BAND. ......................................................................................................................... 16
FIGURE 4. FHSS SYSTEMS HOP AMONG FREQUENCY CARRIERS AT PRE-DETERMINED INTERVALS OF TIME.
...................................................................................................................................................... 17
FIGURE 5. CONSIDER A 6-BIT CHIP SEQUENCE. TO SPREAD A DIGITAL DATA STREAM, EACH 1 IN THE
STREAM IS SUBSTITUTED WITH THE SPECIFIED CHIP SEQUENCE, WHILE EACH 0 IS SUBSTITUTED WITH
THE NEGATED SEQUENCE. .............................................................................................................. 17
FIGURE 6. IBSS VERSUS ESS NETWORKS. ............................................................................................... 23
FIGURE 7. THE 802.11 STANDARD SPECIFIES THE MAC AND PHY LAYER. THE PHY LAYER, IN TURN,
CONSISTS OF THE PLCP AND PMD SUBLAYERS.............................................................................. 23
FIGURE 8. PLCP FRAME CORRESPONDING TO AN FHSS PHYSICAL LAYER IMPLEMENTATION. .................. 24
FIGURE 9. PLCP FRAME CORRESPONDING TO A DSSS PHYSICAL LAYER IMPLEMENTATION. .................... 26
FIGURE 10. (A) T IME DISPERSION AND (B) AMPLITUDE FADING ON MULTIPATH CHANNELS....................... 32
FIGURE 11. DIFFERENCE BETWEEN THE PARAMETERS TM, τM, AND τRMS IN A PDP P(T). ............................. 34
FIGURE 12. FDD SCHEME DIFFICULTIES DUE TO COMMUNICATION BETWEEN ADAPTERS. ......................... 41
FIGURE 13. CHANNEL CAPACITY AS A FUNCTION OF DISTANCE ................................................................ 46
FIGURE 14. TRANSCEIVER ARCHITECTURE FOR CONVENTIONAL FDM ..................................................... 48
FIGURE 15. TYPICAL SPECTRUM FOR CONVENTIONAL FDM..................................................................... 48
FIGURE 16. GRAPHICAL INTERPRETATION OF THE OFDM CONCEPT ......................................................... 51
FIGURE 17. TYPICAL SPECTRUM FOR ORTHOGONAL FDM........................................................................ 51
FIGURE 18. BLOCK DIAGRAM OF THE OFDM TRANSMITTER .................................................................... 53
FIGURE 19. BLOCK DIAGRAM OF THE OFDM RECEIVER .......................................................................... 55
FIGURE 20. STAR-LIKE TOPOLOGY OF THE WGLAN................................................................................ 59
FIGURE 21. TDD SCHEME. ...................................................................................................................... 60
FIGURE 22. CONTROLLER-TO-ADAPTER LINK NEGOTIATION .................................................................... 61
FIGURE 23. ADAPTER-TO-ADAPTER LINK NEGOTIATION........................................................................... 62
FIGURE 24. DISCRETE-TIME SIMULATION MODEL .................................................................................... 73
FIGURE 25. MODULE DEPENDENCY DIAGRAM OF THE SIMULATION PROGRAM .......................................... 74
FIGURE 26. BER PERFORMANCE FOR IDEAL CHANNEL MODEL ................................................................. 79
FIGURE 27. BER PERFORMANCE FOR 64-QAM STATIC CHANNEL MODELS ............................................... 80
FIGURE 28. BER PERFORMANCE FOR 64-QAM DYNAMIC CHANNEL MODELS ........................................... 81
FIGURE 29. BER PERFORMANCE FOR 64-QAM INTERFERENCE CHANNEL MODELS................................... 82
FIGURE 30. BER PERFORMANCE FOR EXPONENTIAL CHANNEL MODELS ................................................... 83
8
List of Tables
TABLE 1. FREQUENCY BANDS ALLOCATED FOR USE BY ISM EQUIPMENT. FCC CODE PART 18.301 ......... 20
TABLE 2. MAXIMUM POWER RESTRICTIONS OF THE U-NII BAND. ............................................................ 21
TABLE 3. FCC RESTRICTIONS ON THE U-NII BAND. ................................................................................ 40
TABLE 4. LINK BUDGET FOR NETWORK CONTROLLER ............................................................................. 43
TABLE 5. LINK BUDGET FOR NETWORK ADAPTERS ................................................................................. 45
TABLE 6. SYSTEM PARAMETER CONSTRAINTS. ........................................................................................ 56
TABLE 7. SYSTEM PARAMETER VALUES. ................................................................................................. 58
TABLE 8. OFDM LINK REQUEST SCENARIO ............................................................................................. 66
TABLE 9. SUBCHANNEL ALLOCATION BY MAXIMIZING EACH ADAPTER’S BANDWIDTH EFFICIENCY ........... 67
TABLE 10. SUBCHANNEL ALLOCATION BY MAXIMIZING OVERALL BANDWIDTH EFFICIENCY ..................... 68
TABLE 11. SUBCHANNEL ALLOCATION BY EQUITATIVE MAXIMIZATION OF BANDWIDTH EFFICIENCY ........ 69
TABLE 12. OPTIMIZING SUBCHANNEL ALLOCATIONS BASED ON USER SATISFACTION ............................... 70
TABLE 13. PROPORTIONAL SCALING OF OFDM TRANSCEIVER PARAMETERS ........................................... 75
TABLE 14. MINIMUM SNR NEEDED TO ACHIEVE A TARGET BER FOR DIFFERENT CONSTELLATION SIZES . 83
TABLE 15. 5. X GHZ INDOOR CHANNEL PARAMETERS............................................................................... 86
TABLE 16. OFDM SYSTEM PARAMETER. ................................................................................................. 87
TABLE 17. SNR THRESHOLDS FOR A GIVEN BER AND CONSTELLATION SIZE ........................................... 88
9
Chapter 1 : Introduction
The latest advances in digital technology and explosive growth of the Internet have
revolutionized the ways we handle daily information. Today e-mail is a common form of
communication, current music hits are sold via the Web, meeting schedules are managed with
Personal Digital Assistants (PDAs), and video conferencing is enable by low-cost equipment.
Following the current trend in multimedia innovations, new electronic devices and
applications are being conceived to handle larger amounts of information at faster speeds. In
the near future, complete music albums may be distributed over the Net directly into a home
entertainment system; video archives of yesterday’s headlines may be downloaded from a news
service into a High-Definition Television (HDTV); and company employees may use
telepresence to interact with fellow workers overseas. Overall, the projected load on the
Internet in the near future is so large that a Next Generation Internet (NGI) [57] has been
proposed to handle the information needs of these novel devices.
As the NGI delivers high-speed data between geographically distant locations, there is
a need to develop an indoor local-area network (LAN) within the home or office to continue
high-speed data transmission to end-use devices. Moreover, based on the portability of these
devices, the challenge is to provide a low-power wireless solution for this network.
This thesis builds upon the anticipated NGI to propose the physical layer digital signal
processing (DSP) design of an indoor Wireless Gigabit Local-Area Network (WGLAN) capable
of approaching gigabit-per-second (Gbps) data transmission rates at its peak performance.
1.1 System Specifications
As shown in Figure 1, the WGLAN topology consists of a single network controller
that is the gateway between the NGI and the local-area network, and multiple network adapters
connected to end-use devices. The network controller is an advanced workstation that estimates
channel properties and allocates system resources among competing adapters. The network
adapters are peripheral devices to end-use appliances that consist of a digital signal processor,
which interfaces with the appliance; a baseband analog processor, which maps blocks of bits
onto their respective analog signals and viceversa; and an RF transceiver, which modulates and
demodulates the analog signals onto a specific carrier frequency.
WGLAN
Adapter
Appliance
WGLAN
Adapter
Appliance
WGLAN
Adapter
Network
Controller
w/ channel
processor
NGI
Baseband
Analog
Processor
RF
Transceiver
Digital
Signal
Processor
Appliance
Figure 1. WGLAN topology
The WGLAN should support bidirectional communication for any controller-adapter or
adapter-adapter pairing. In addition, all communication links should provide real-time data
transmission and symmetric data throughputs in both link directions to support those interactive
multimedia applications that have intensive audio and video streaming requirements.
12
In order to maximize system capacity, the network should employ modulation
techniques that are bandwidth efficient. Thus, there is a special interest to dynamically adjust
the bit rate of a communication link to the maximum possible M-level Quadrature Amplitude
Modulation (M-QAM) based on the signal-to-noise ratio (SNR) and signal-to-interference ratio
(SNI) of the channel. In addition, the use of Orthogonal Frequency Division Multiplexing
(OFDM) should be considered as an efficient way of partitioning the available channel.
Finally, the allocation of system resources should be optimal enough to satisfy the
simultaneous requests of multiple users. Since different users will typically request varying
degrees of data throughput and quality of service, the network should be flexible enough to
meet different user requirements based on the channel conditions for each user.
1.2 Thesis Focus
The focus of this thesis is to the design the functionality of the digital signal processor
of the network controller and adapters. Such functionality includes dividing the radio spectrum
into subchannels, implementing bandwidth-efficient modulation and demodulation techniques,
and enforcing custom algorithms for the allocation of network resources among users.
Since the design of the DSP component requires an evaluation of design tradeoffs at a
system-wide level, this thesis uses an incremental methodology based on the communications
model shown in Figure 2. Starting at the center of this model, the first step is to analyze the
channel conditions in the indoor environment, then propose a suitable modulation and
demodulation technique, and finally suggest protocols for supporting multiple users.
User 1
User 2
User 1
modulation
channel
demodulation
User 2
User N
User N
Figure 2. Design Methodology
13
1.3 Thesis Outline
This thesis is organized in six chapters, which are presented in the same chronological
order as the different research stages of the project. Chapter 2 summarizes the current
technology on wireless LANs and introduces general terminology. Chapter 3 analyzes the
indoor channel environment and proposes simple models based on parameters obtained from
public literature. Chapter 4 develops the transceiver architecture and analyzes the design
tradeoffs involved in choosing specific parameter values. Chapter 5 introduces several network
protocols to support multiuser communication. Chapter 6 details how the software simulation
was put together and discusses the result of simulating the network performance under different
channel conditions. Chapter 7 concludes the thesis by summarizing achievements and
presenting leads for further research.
14
Chapter 2 : WLAN Concepts & Standards
The wireless LAN market has grown rapidly in the last five years [15]. Today, WLANs
are used in hospitals, to record patient information at bedside; in car rental companies, to input
car-return information; in warehouses and retail shops, to keep inventories; and in restaurants,
to place orders. Student volunteers participating in the MIT China Educational Technology
Initiative (MIT-CETI) program have also made use of wireless networking products to bridge
Chinese high schools to the Internet service provided by nearby universities.
Although the first experimental WLANs were conceived as replacement for wires, most
WLANs nowadays are employed to extend rather than replace existing wired networks. Indeed,
wireless LANs are ubiquitous among industries that require mobile computing resources or that
face extreme difficulties in deploying new physical media. In terms of advantages, wireless
networks are easy to install since they require no additional cables, reduce long-term costs in
dynamic organizations that are characterized by frequent moves and changes, and increase
productivity in environments that require real-time mobile access to information.
2.1 WLAN Technologies
Wireless LANs use electromagnetic airwaves (radio or light) to transmit information
from one point to another without relying on any physical connection. Normally, the data being
transmitted is superimposed or modulated onto a specific radio wave or carrier, which then
delivers electromagnetic energy to a remote receiver. Once data is modulated onto a carrier, the
resulting radio signal occupies more than a single frequency because the frequency or bit rate
of the modulating information adds to that of the carrier [16].
Most commercial WLANs are based on radio or infrared technologies [18]. Radio
technology is normally subdivided into narrowband and spread spectrum. Each technology
comes with its own set of advantages and limitations, as outlined in the next few sections.
2.1.1
Narrowband Technology
In a narrowband network, the available radio spectrum is divided into frequency
channels so that different network users may transmit and receive data on specific frequencies.
The bandwidth of each channel is kept as narrow as possible, and is usually determined by the
bit rate of the data being sent. At the receiver end, any particular user then filters out all the
radio signals except those on its designated frequency.
Narrowband is a bandwidth efficient technology because it packs all the information
content in the minimum possible bandwidth. Unfortunately, such efficiency also makes
narrowband technology very susceptible to errors due to interference on any radio channel. For
this reason, customers employing narrowband technologies must normally obtain an FCC
license to guarantee an interference-free environment on their frequency channels.
2.1.2
Spread Spectrum Technology
An alternative technology is to spread the data bits across the entire available radio
spectrum according to user-specific parameters. In this case, the transmitted signal is less
susceptible to narrowband interference since it uses more bandwidth than its actual information
content. In fact, the transmitted signal resembles background noise to all users but the intended
recipient. Frequency hopping and direct sequence are the most common spreading techniques.
Power
narrowbands
spread
Frequency
16
Figure 3. Narrowband divides the spectrum
into subchannels while spread spectrum
extends the entire band.
Frequency-Hopping Spread Spectrum Technology
Frequency-hopping spread spectrum (FHSS) systems spread the signal energy over a
wide band by jumping among narrowband carriers at specific time intervals. When the jumps
follow a pattern known to both transmitter and receiver, the system can be synchronized to
maintain a single logical channel, otherwise the signal resembles short-duration impulse noise.
FHSS minimizes interference by limiting the time spent at each carrier, thus lowering the
probability that any two transmitters will use the same frequency at any point in time.
Carriers
f5
f4
f3
f2
f1
t1
t2
t3 t4
t5
t6
t7
t8
t9 t10
Figure 4. FHSS systems hop among
frequency carriers at predetermined intervals of time.
Time
Direct-Sequence Spread Spectrum Technology
In direct-sequence spread spectrum (DSSS) systems, the signal energy is spread across
a wide band by replacing each data bit with multiple sub-bits or chips that occupy the same
time interval as the original data bit. The bandwidth ratio between chips and data bits is called
processing gain. The higher the processing gain, the greater the probability that the data can be
recovered even if several chips are corrupted during transmission. To an unintended receiver,
DSSS signals resemble low-power wideband noise that may actually fall below thermal noise.
Chip sequence:
Original data stream:
Spread data stream:
1 0 1 0 0 1
1
0
1
1 0 1 0 0 1 0 1 0 1 1 0 1 0 1 0 0 1
Figure 5. Consider a 6-bit chip sequence. To spread a digital data stream, each 1 in the stream is
substituted with the specified chip sequence, while each 0 is substituted with the negated sequence.
17
2.1.3
Infrared Technology
Some wireless networks are also based on infrared (IR) radiation, typically between
800 and 900 nanometers, just below visible light in the electromagnetic spectrum. Since
infrared light does not penetrate opaque objects, IR links are either direct, when highly focused
beams transmit signals over the shortest path between sender and receiver; or diffused, when
reflective surfaces are used to flood a room with infrared energy. Due to their limited range
(about 3 feet) and point-to-point nature, infrared systems are less suitable for multiuser
networks and so they will not be taken into account in this thesis.
2.1.4
Efficiency Considerations
Naturally, network designers would rather use the most efficient technology, if only
they could agree on a single definition for efficiency. Some designers maximize bandwidth
efficiency, or the number of bits-per-second transmitted per unit of spectrum bandwidth
(bps/Hz). Other designers optimize power efficiency, or the amount of power dissipated at
different amplifier stages. Yet other designers maximize multiuser efficiency, or the number of
multiple users that can communicate simultaneously through the network.
The different interpretations for efficiency often suggest mutually exclusive design
tradeoffs. For instance, networks that are very bandwidth efficient tend to use large signal
constellations with multiple amplitude levels, even though their implementation requires linear
power amplifiers that are inherently very power inefficient.
The disagreement on how to measure network efficiency is epitomized by the
contending cellular network technologies. FDMA cellular networks make use of bandwidth
efficient narrowband technology, even though their constraints on frequency reuse limit
multiuser efficiency. On the other hand, CDMA cellular networks make use of multiuser
efficient spread spectrum technology, even though their actual bandwidth efficiency is much
lower than 1 bps/Hz. In order to avoid such controversial standpoints, this thesis will focus first
on maximizing bandwidth efficiency, and then on optimizing multiuser efficiency. Power
efficiency concerns are postponed until the actual implementation study of the WGLAN.
18
2.2 WLAN Configurations
Regardless of their underlying technology, wireless LANs always assume one of two
basic configurations, ad hoc or infrastructure. In an ad hoc WLAN, two computers equipped
with wireless adapter cards can set up a peer-to-peer connection whenever they are within
range of one another. Such an improvised configuration requires no central controller but only
gives access to the resources available within the two networked computers.
In
infrastructure
networks,
computers
equipped
with
wireless
adapters
can
communicate with each other, as well as with a wired LAN through access points scattered
throughout a building. Since the access points are connected to the wired network, each
wireless client can also have access to server resources. Some networks allow mobile clients to
roam, that is, to move seamlessly among a cluster of access points. In those networks, clients
are handed off from one access point to another in a way that is invisible to the client, ensuring
unbroken connectivity during the same communication session.
The WGLAN project constitutes an infrastructure network. In our case, the wireless
adapters used by mobile clients are called network adapters, while the access points connected
to the wired LAN are called network controllers. Since the WGLAN is intended for indoor use
within the home or office, each setup consists of a single network controller, which eliminates
the need to include roaming capabilities into the entire system.
2.3 Radio Spectrum Regulations
In the United States, the Federal Communications Commission (FCC) regulates all
radio emissions within the frequencies of 3 kHz to 300 GHz, which includes most WLAN
technologies except those based on infrared light. According to FCC regulations, manufacturers
of radio-based WLANs employing narrowband technology must obtain a license to use specific
radio frequencies at every site where a wireless network is to be deployed. In general, licenses
increase costs and reduce system flexibility since each wireless network must be custom
designed to make use of frequencies that are unique to each site.
19
The commercial development of radio-based WLANs started in 1985 when the FCC
allowed the license-free use of a set of frequencies called the Industrial, Scientific, and Medical
(ISM) bands [10] listed in Table 1. Nowadays, most WLANs make use of the ISM bands
centered at 915 MHz, 2.45 GHz, and 5.8 GHz since they are the lowest frequency allocations
that gather several megahertz of spectrum. Higher operating frequencies generally have a
shorter propagation range and incur higher manufacturing costs, which explains, for instance,
why the 915 MHz band is the most crowded ISM band. The other two bands offer additional
benefits of their own: the 2.45 GHz ISM band is the only unlicensed allocation acceptable
worldwide, and the 5.8 GHz band has a total bandwidth that spans 150 MHz of spectrum.
Table 1. Frequency bands allocated for use by ISM equipment. FCC Code Part 18.301
Low Bandwidth Bands
6.78 MHz ± 15.0 kHz
13.56 MHz ± 7.0 kHz
27.12 MHz ± 163.0 kHz
40.68 MHz ± 20.0 kHz
Popular Bands
915 MHz ± 13.0 MHz
2.450 GHz ± 50.0 MHz
5.8 GHz ± 75.0 MHz
High Bandwidth Bands
24.125 GHz ± 125.0 MHz
61.25 GHz ± 250.0 MHz
122.5 GHz ± 500.0 MHz
245.0 GHz ± 1.0 GHz
In order to support multiuser access to ISM bands, Part 15 of the FCC code stipulates
that operation on those bands be limited to frequency hopping and direct sequence spread
spectrum radiators with maximum peak output of 1 watt. Section 15.247 also specifies that
frequency hopping systems in the 2.4 and 5.8 GHz bands shall use at least 75 hopping
frequencies, with hopping channels not wider than 1 MHz, and average time of occupancy on
any frequency not greater than 0.4 seconds within a 30 second period. For direct sequence
systems, the minimum 6 dB bandwidth shall be at least 500 kHz, with no maximum specified.
Current FHSS-based wireless networks using ISM bands achieve peak data
transmission rates of up to 2.0 Mbps. Such data rates are insufficiently low for some high-speed
applications, yet little can be done to increase these rates given that the hopping channels of
FHSS systems can be at most 1 MHz wide, with a typical spectral efficiency currently below
2 bps/Hz. In 1997, the FCC recognized that the technical restrictions on ISM bands hindered
the development of high-speed WLANs, and decided to open up an additional part of the
spectrum, which named the Unlicensed National Information Infrastructure (U-NII) band.
20
According to the FCC, U-NII devices will provide short-range, high-speed wireless
digital communications on an unlicensed basis to facilitate access to the National Information
Infrastructure, or Next Generation Internet [9]. Following this vision, the FCC provided the UNII band with 300 MHz of non-contiguous spectrum located at 5.15-5.35 GHz and 5.725-5.825
GHz. Use of this band is regulated by Part 15-E of the FCC code, which allows significant
flexibility in the design of U-NII devices by adopting the minimum technical rules needed to
prevent interference to other services and to ensure efficient use of the spectrum.
Table 2. Maximum power restrictions of the U-NII band.
Frequency Band (in GHz)
5.15 – 5.25
5.25 – 5.35
5.725 – 5.825
Peak Transmit Power
50 mW
250 mW
1000 mW
Peak Power Spectral Density
2.5 mW/MHz
12.5 mW/MHz
50 mW/MHz
As opposed to the rigid regulations on ISM bands, devices operating in the U-NII band
must simply comply with the radiation power restrictions summarized in Table 2. Note that the
5.725-5.825 GHz section of the U-NII band overlaps with part of the ISM bands centered at 5.8
GHz. Even though both bands are restricted to 1 watt of radiation power, the U-NII 5.8 GHz
band is not limited to spread spectrum technologies.
All factors considered, the U-NII band provides the bandwidth and design freedom
needed to support the objectives of the WGLAN project. Before proceeding to model the
indoor channel characteristics of the U-NII band, we first review the three major wireless LAN
standards currently in existence that make use of ISM frequencies.
2.4 IEEE 802.11 WLAN Standard
In the early days of wireless networking, WLAN products implemented by different
manufacturers were based on proprietary technology that was mutually incompatible. As a
consequence, the first WLAN customers had no alternative but to assume the high costs of
depending on a single manufacturer to provide all of their networking needs. The Institute of
Electrical and Electronic Engineers (IEEE) recognized the need for a WLAN standard in 1992,
21
and by June of 1997 it had approved a radio (and infrared) standard for the 2.4-GHz ISM band
to provide interoperability among wireless networks from different manufacturers.
The 802.11 Standard, officially named the IEEE Standard for Wireless LAN Medium
Access (MAC) and Physical Layer (PHY) Specifications, defines the protocols needed to
provide wireless connectivity of fixed, portable, and mobile stations moving at pedestrian and
vehicular speed within a local area. Specific features of the standard include:
•
Data rates of 1 or 2 Mbps, using FHSS, DSSS, or infrared modulation.
•
Carrier-sense multiple access with collision avoidance (CSMA/CA)
•
Data fragmentation to support asynchronous and time-bounded delivery service.
•
Error control at the frame level and acknowledgement of each packet received.
•
Rules for power management, authentication, and addressing.
Although 802.11 gives specifications for both the MAC and PHY layers, the following
overview will focus on the radio-based physical layers that are of direct interest to this thesis.
2.4.1
Network Topologies
The IEEE 802.11 Standard supports two types of topologies: Independent Basic Service
Set (IBSS) networks and Extended Service Set (ESS) networks. Both networks utilize a basic
building block called the BSS, which provides a coverage area whereby stations of the BSS
remain fully connected. A station is free to move within the BSS, but it can no longer
communicate directly with other stations if it leaves the area of coverage of the BSS.
An IBSS network is a stand-alone BSS that has no backbone infrastructure and consists
of at least two wireless stations. This type of network is also known as an ad hoc network and
satisfies most needs of users occupying a small, improvised area. On the other hand, an ESS
network is connected to a wired infrastructure that may include additional BSS networks.
22
BSS 1
access
point
Wired LAN
access
point
Station A
Station B
IBSS
BSS 2
ESS
Figure 6. IBSS versus ESS networks.
The 802.11 standard assumes three types of mobility. In no-transition, stations are
static or move within a local BSS. In BSS-transition, stations move between different BSS
within the same ESS. And in ESS-transition, stations move between BSS that belong to
different ESS. The standard supports the no-transition and BSS-transition mobility types but
cannot guarantee continued connectivity during an ESS-transition.
2.4.2
Physical Layer Architecture
The physical layer architecture of each 802.11-compliant station is divided into the
Physical Layer Convergence Procedure (PLCP) sublayer and the Physical Medium Dependent
(PMD) sublayer. The PLCP sublayer minimizes the dependence of the MAC Layer with the
wireless medium by appending fields to the MAC protocol data units (MPDUs) that contain
information needed by the PMD sublayer transmitters and receivers. This composite frame is
known as a PLCP protocol data unit (PPDU). Meanwhile, the PMD sublayer interfaces directly
with the wireless medium and implements carrier sense algorithms as well as modulation and
demodulation of frames during transmission and reception modes, respectively.
MAC Layer
Figure 7. The 802.11 standard specifies the
MAC and PHY layer. The PHY layer, in
turn, consists of the PLCP and PMD
sublayers.
PLCP Sublayer
PHY
PMD Sublayer
23
2.4.3
FHSS Physical Layer
Frequency-hopping is one of two radio-based spread spectrum physical layers proposed
in the 802.11 wireless LAN standard. The FHSS physical layer has the lowest power
consumption, lowest potential data rates from individual physical layers, highest aggregate
capacity using multiple physical layers, and less range than direct-sequence [1].
FHSS Frame Format
A single FHSS PLCP frame consists of a preamble, to enable the receiver to
synchronize its clocking functions; a header, to provide information about the frame; and a
whitened PSDU, or PLCP Service Data Unit, which is the MPDU the station sends.
80 bits
16 bits
12 bits
4 bits
16 bits
Variable size
SYNC
Start frame
delimiter
PLW
PSF
Header
error check
Whitened PSDU
PLCP preamble
PLCP header
PLCP service data unit
Figure 8. PLCP frame corresponding to an FHSS physical layer implementation.
The PLW, or PSDU Length Word, field specifies the length of the PSDU (0-4,095
octets). The PSF, or PLCP Signaling Field, specifies the data rate of the whitened PSDU
portion of the frame. The Header Error Check contains the result of applying the CRC-16 error
detection algorithm to the PLW and PSF fields. The physical layer does not determine whether
errors are present within the PSDU, that is a function of the MAC Layer. CRC-16 detects all
single- and double-bit errors and ensures detection of 99.998% of all possible errors.
Finally, the Whitened PSDU minimizes the dc bias by stuffing special symbols after
every four octets of the data signal. The PSDU whitening process uses a length-127 frame
synchronous scrambler and a 32/33 bias-suppression encoding algorithm to randomize the data.
24
Frequency Hopping Functions
The 802.11 standard defines a set of hopping channels that are 1 MHz wide and are
evenly spaced across the 2.4 GHz ISM band. The number of channels varies geographically,
North America and most of Europe has 79, while Japan has 23 for instance.
The available hopping frequencies are segregated into three distinct hopping sets. The
FHSS-based PMD sublayer transmits PPDUs by hopping from channel-to-channel according to
a particular pseudo-random sequence that distributes the data signal uniformly across the
frequencies in a specific hopping set. After a hopping sequence is selected in an access point,
all stations automatically synchronize to the correct hopping sequence.
Frequency Modulation Functions
The FHSS PMD sublayer transmits symbols using two-level or four-level Gaussian
frequency shift keying (GFSK) modulation depending on whether the data rate is 1 or 2 Mbps,
respectively. GFSK is a variant of frequency shift keying where the signal spectrum is shaped
by a Gaussian filter characterized by its baseband bandwidth B and transmission rate 1/T.
When transmitting data streams at 1 Mbps, the input to the GFSK modulator is either a
0 or 1 coming from the PLCP sublayer. The modulator transmits the binary data by shifting the
center operating frequency FC for each hop by a slight deviation fd, where fd must be greater
than 110 kHz. Consequently, the symbol {1} is encoded with a transmit frequency of (FC + fd),
while the symbol {0} is encoded with a transmit frequency of (FC – fd).
When transmitting data streams at 2 Mbps, the input to the GFSK modulator is
combinations of 2 bits (00, 01, 10 or 11) coming from the PLCP sublayer. Each of these 2-bit
symbols is sent at 1 Msymbol/s, meaning that the bit rate is 2 Mbps. Consequently, the symbol
{10} is encoded with a transmit frequency of (FC + 3fd), symbol {11} is encoded with (FC + fd),
symbol {01} is encoded (FC – fd), and symbol {00} is encoded (FC – 3fd). The nominal value
for fd in both two-level and four-level GFSK modulation is 160 kHz.
25
2.4.4
DSSS Physical Layer
Direct-sequence is the second radio-based spread spectrum physical layer proposed in
the 802.11 wireless LAN standard. The DSSS physical layer has the highest power
consumption, highest potential data rates from individual physical layers, lowest aggregate
capacity using multiple physical layers, and more range than frequency hopping [1].
DSSS Frame Format
The format of a DSSS PLCP frame consists of a preamble, to enable the receiver to
synchronize its clocking functions; a header, to provide information about the frame; and a
whitened PSDU, or PLCP Service Data Unit, which is the MPDU the station sends.
128 bits
16 bits
8 bits
8 bits
16 bits
8 bits
Variable size
SYNC
Start frame
delimiter
Signal
Service
Length
Frame check
sequence
MPDU
PLCP preamble
PLCP header
PLCP service data unit
Figure 9. PLCP frame corresponding to a DSSS physical layer implementation.
The Signal field specifies the type of modulation that the receiver must use to
demodulate the signal. The Service field is reserved for future use. The Length field is an
unsigned 16-bit integer indicating the number of microseconds to transmit the MPDU. The
receiver uses this information to determine the end of the frame.
The Frame Check Sequence field contains the result of applying the CRC-16 error
detection algorithm to the PLW and PSF fields, similar to the FHSS physical layer. Finally, the
PSDU field is the same as the MPDU being sent by the MAC Layer, which can range from 0
bits to a maximum size set by the PMD sublayer.
26
DSSS Spreading Sequence
The DSSS physical layer digitally spreads the original PPDU before modulating it onto
one of the 14 available frequencies as specified in the 802.11 standard. Different modulating
frequencies are provided to allow the concurrent operation of multiple users.
The original 802.11 standard specifies an 11-chip Barker sequence as the spreading
code for data payloads of 1 Mbps and 2 Mbps. Higher data rates are supported by the 802.11b
extension, which specifies an 8-chip complementary code keying (CCK) for payloads of 5.5
Mbps and 11 Mbps. The modulation rate depends on the data payload, and it is set to 1, 2, 4,
and 8 chips/symbol respectively so that the chipping rate is always equal to 11 MHz.
Frequency Modulation Functions
The spread PLCP frame is modulated by shifting the phase of the transmit carrier
frequency. For the regular data rates as specified in the original 802.11 standard, if the initial
frame had a 1 Mbps data rate, then DSSS PMD sublayer transmits the spread frame using
differential binary phase shift keying (DBPSK) modulation. Otherwise, the 2 Mbps data rate
uses differential quadrature phase shift keying (DQPSK) modulation. In phase shift keying, the
phase of the carrier frequency is changed to represent different data symbols.
When transmitting data streams at 1 Mbps, the input to the modulator is either a 0 or 1
coming from the PLCP sublayer. The modulator transmits this data by shifting the phase of the
carrier frequency in increments of 180 degrees. Consequently, the symbol {1} is encoded with
a phase shift of 180 degrees, while the symbol {0} is encoded with a phase shift of 0 degrees.
When transmitting data streams at 2 Mbps, the input to the modulator is combinations
of 2 bits (00, 01, 10 or 11) coming from the PLCP sublayer. Each of these 2-bit symbols is sent
at 1 Msymbol/s, meaning that the bit rate is 2 Mbps. Consequently, the symbol {00} is encoded
with a phase shift of 0 degrees, symbol {01} is encoded with 90 degrees, symbol {11} is
encoded with 180 degrees, and symbol {10} is encoded with 270 or negative 90 degrees.
27
2.5 HIPERLAN Standard
In 1998, the European Telecommunications Standards Institute (ETSI) adopted its High
Performance Radio Local Area Network (HIPERLAN) standard. This standard defines the
Physical and Medium Access Control layers for a high data rate wireless network operating in
the 5.15 – 5.30 GHz frequency band.
Systems that are HIPERLAN-compliant can be deployed in an ad-hoc or pre-arranged
fashion, where nodes can move as fast as 360 degrees per second or 1.4 meters per second.
HIPERLAN systems also provide coverage beyond the radio range limitation of a single node,
support asynchronous and time-bound communication, and attempt to conserve power by
arranging the times when mobile clients need to be active for signal reception.
2.5.1
Channel Access
The nominal frequency band of HIPERLAN is the 5.15 – 5.25 GHz band, which
supports three channels, each 23.5294 MHz wide. This is a pan-European frequency allocation
on a secondary, non-interference basis. Within Europe, the 5.25 – 5.3 GHz band can also be
allocated on demand to provide two additional channels. In order to increase multiuser
capacity, HIPERLAN equipment is required to operate on all five channels.
The channel access protocol used in HIPERLAN is by means of a “listen before talk”
scheme that is termed Elimination-Yield Non-pre-emptive Priority Multiple Access (EYNPMA). A node alternately transmits a short burst and listens to the channel to determine if
another node is transmitting. If a node can hear another transmission then it yields to that node
and tries to gain access to the channel when it becomes free again. Five different levels of
traffic priority are supported by allowing a node with higher priority to start contending for the
channel before nodes with lower priority. The access protocol also includes a contention
resolution mechanism that copes with the possibility of multiple nodes trying to access the
channel at the exact same time.
28
2.5.2
Physical Layer
The tasks of the physical layer include the following: (1) Modulating and demodulating
radio carriers to create RF links. (2) Acquiring bit and burst synchronization. (3) Transmitting
or receiving a defined number of bits at a requested time and on a particular carrier frequency.
(4) Encoding and decoding the Forward Error Correction scheme. (5) Deciding whether a
channel is idle or busy, for the purposes of deferral during channel access attempts.
HIPERLAN transmits information using data bursts. There are two types of data bursts:
LBR data bursts encode low bit-rate data streams, while LBR-HBR data bursts encode high bitrate data streams preceded by a LBR segment. The two admissible signaling rates are
1.4705875 Mbps for the low bit rate, and 23.5294 Mbps for the high bit rate. The maximum
permissible transmit power is 1 watt, giving a maximum operating range of about 50 meters.
User data is sent in blocks of 416 bits (52 octets). This data is encoded for error
correction/detection purposes using a (31,26) BCH code to produce blocks of 496 bits (62
octets). The encoded data is then interleaved over one of these blocks to randomize bit errors.
The maximum packet length in HIPERLAN is 47 blocks of 62 octets (around 25000 bits),
which lasts for about 1ms. This is the maximum time over which the indoor radio channel is
assumed to be reasonably static. In addition, each packet is protected with a CRC field.
The modulation technique employed depends on the data bit rate. Gaussian Minimum
Shift Keying (GMSK) with BT=0.3 is used to modulate high bit rate transmissions, while
Frequency Shift Keying (FSK) is used to modulate low bit rate transmissions. GMSK is a
special form of binary continuous-phase FSK based on the minimum frequency separation that
is necessary to ensure the orthogonality of the modulation signals from the response of a
Gaussian filter to a rectangular pulse interval of length T [4]. Implementation details about this
modulation technique can be found in the HIPERLAN standard [8]. In FSK, signaling is
accomplished by adding small deviations to the center carrier frequency. Thus, the symbol {0}
is encoded with the frequency (FC – fd), while the symbol {1} is encoded with the frequency
(FC + fd), where fd is set to 368 kHz.
29
2.6 Bluetooth Specification
The Bluetooth Specification was released in December of 1999 as a de facto standard
created by a Special Interest Group (SIG) that includes several telecommunication industry
leaders. Bluetooth provides a short-range radio link, within a so-called Personal Area Network
(PAN), intended to replace the cable(s) connecting portable and/or fixed electronic devices
[12]. Due to its limited 10-meter range, Bluetooth is not considered a wireless LAN by any
means, yet an overview of its technical features may prove useful for future reference.
Bluetooth-enabled
devices
can
establish
point-to-point
and
point-to-multipoint
connections by forming an ad hoc network or piconet. Each piconet consists of one Bluetooth
unit that acts as master, and several units that act as slaves. All devices in the same piconet are
synchronized to the master’s clock so that full-duplex transmission may be accomplished
through a Time Division Duplex (TDD) scheme. Multiple piconets with overlapping coverage
areas form a scatternet. Slave units can participate in different piconets on a Time-Division
Multiplex basis, and master units in one piconet can act as slaves in another piconet.
At the physical layer, Bluetooth radios communicate using frequency-hopping spread
spectrum technology at the globally available 2.4 GHz ISM band. The frequency hopping
channels are 1 MHz wide and the gross data rate is 1 Mbps. The modulation used is GFSK with
BT = 0.5, where a binary one corresponds to a positive frequency deviation and a binary zero to
a negative frequency deviation. The minimum deviation shall exceed 115 kHz.
In contrast to the 802.11 and HIPERLAN standard, the Bluetooth Specification
explains how to manage cryptic keys to provide for authentication and user privacy. The
specification also includes instructions on how to interface to multiple communication
protocols such IrDA, USB, RS232, and UART. Indeed, the versatility and technical feasibility
of Bluetooth played a decisive role for this specification to become a de facto standard.
30
Chapter 3 : Channel Analysis
The communications channel is the physical medium through which data-bearing
signals propagate. Some examples include the twisted-wire-pair telephone line, coaxial cable,
fiber optic lines, and the wireless radio frequency spectrum. Since energy dissipates differently
in various media, the communications channel must be characterized to determine such
network parameters as power requirements, maximum range, signaling rate, and data capacity.
In this chapter, we first review the mathematical concepts used to characterize indoor
radio channels of the type used by the WGLAN. Next, we refer to the public literature to
extract key parameters that characterize the U-NII frequency bands. Finally, we use the
collected information to propose several channel models and a network link budget.
3.1 Characterizing Indoor Radio Channels
The indoor radio channel is an adverse communication channel where the transmitted
signal arrives at the receiver via multiple propagation paths that differ in amplitude, phase, and
delay time. Due to the existence of multipaths, the information signals that propagate through
indoor radio channels are distorted by both time dispersion and amplitude fading [32].
The phenomenon of time dispersion is illustrated in Figure 10a. Here, even though the
transmitter sends an extremely short pulse, ideally an impulse, the channel response due to
multiple scatterers causes the received signal to be spread in time. If, in addition, the channel
experiences physical changes over time, then the response of any signal transmitted through it
will change with time as well, hence the designation of time-varying channel [3].
Signal Transmitted
Signal Received
Frequency Spectrum of Received Signal
power
time
T2
power
T1
time
frequency
T3
time
(a)
(b)
Figure 10. (a) Time dispersion and (b) amplitude fading on multipath channels
The phenomenon of amplitude fading is illustrated in Figure 10b. Since multiple
propagation paths have different phase offsets, two or more multipath components may add
destructively at times, causing the received signal to vanish, or fade, in certain locations.
Fading is equivalent to a notch in the channel’s magnitude frequency response.
Mathematically, the baseband multipath channel impulse response is modeled as [32]
N
Eq. 1
j
h( t ) = ∑ β k e θ k δ ( t − τ k )
k =1
Where for N total paths, k is the path index, βk is the real-positive path gain, θk is the
phase shift, and τk is the time delay of the kth path. δ(⋅) is the Dirac delta function. Originally,
the time delay of each propagation path is lower bounded by the speed of electromagnetic
waves, i.e. 3⋅108 m/s. However, since the absolute delay of the channel is irrelevant, the first
arriving path is taken as a time reference by setting τ1 = 0.
Because of the motion of people and equipment in and around the indoor environment,
the parameters βk, θk, and τk are time-varying stochastic processes. Such variations in the
structure of the multipath channel cause the received signals to be unpredictable to the user of
the channel, and so we must characterize the time-variant multipath channel statistically.
However, later in this chapter we will show that since the transmitter and receiver have a fixed
position, the channel parameters change very slowly in comparison with the signaling rate, and
thus the communications channel may be assumed to be quasi-static [41].
32
3.1.1
Power Delay Profile
The power delay profile (PDP) [32], also called the multipath intensity profile or the
delay power spectrum [4], is equivalent to the autocorrelation of the channel impulse response.
The PDP P(t) gives the time distribution of the received signal power from a transmitted δpulse, and is defined as follows
N
P(t ) ≡ h(t ) ∗ h * (t ) = h(t ) = ∑ β k2δ (t − τ k )
2
Eq. 2
k =1
In practical measurements, the transmitted pulses s(t) have finite width. When the pulse
width of s(t) is less than the delay time differences between the paths, the PDP is given by
N
P(t ) = s (t ) ∗ h(t ) = ∑ β k2 s (t − τ k )
2
Eq. 3
2
k =1
3.1.2
Path Loss
Signals propagating through free space experience a power loss that is proportional to
the distance, d, from the source, and inversely proportional to the wavelength, λ, of the carrier
wave. If the carrier wave is centered at a frequency f, then its wavelength is given by the
relationship λ = c / f, where c = 3⋅108 m/s. Hence, in free space the power loss Ls is given by
Eq. 4
 4 ⋅π ⋅ d 
Ls = 

 λ 
2
In reality, however, the signal travels through multiple paths not in free space. Hence,
path loss measurements in indoor environments require a different model. The following simple
model is frequently used to describe path loss (in dB) [32]
Eq. 5
Loss = Lo + Ld = Ls
d o =1m
+ 10 ⋅ n ⋅ log 10 (d / d o )
Where n is the path loss exponent of the environment and d (in meters) is the distance
between the transmitter and receiver, which together define the additional path loss component
Ld. Meanwhile, Lo is the free space loss (in dB) of a path of do meters (often do = 1m).
33
3.1.3
Delay Spread
The range of time values over which the PDP is essentially nonzero is called the
multipath time dispersion of the channel [4] and is denoted by Tm . In essence, the parameter Tm
is the minimum channel symbol duration that can be implemented when no special precautions
are taken, such as adaptive equalization or antenna diversity. Avoiding the use of equalizers is
very desirable in order to reduce system complexity and power consumption [32].
power
2rms
2m
time
Tm
Figure 11. Difference between the parameters Tm, τm, and τrms in a PDP P(t).
Although Tm is the parameter of interest, most channel propagation studies available in
the public literature report instead the root-mean-square delay spread, or simply the delay
spread, τrms. The parameter τrms is equivalent to the standard deviation of Tm, hence it gives a
measure of the amount of signal dispersion. Formally, τrms is defined as:
Eq. 6
τ rms =
∞
∫ (t − τ
m
) 2 Pnorm (t )dt
−∞
Where τm is the mean excess delay time, and Pnorm(t) is the normalized PDP:
∞
Eq. 7
τ m = ∫ tPnorm (t )dt
Pnorm (t ) =
−∞
P(t )
∞
∫ P(t )dt
−∞
34
3.1.4
Coherence Bandwidth
The coherence bandwidth, Bcoh, is the statistical average bandwidth of the radio channel
over which signal propagation characteristics are correlated. The definition of Bcoh is based on
the complex autocorrelation function R(∆f) of the frequency response H(f), where H(f) is the
Fourier transform of the multipath impulse response h(t). R(∆f) is defined as [30]
∞
Eq. 8
R(∆f ) ≡
∫ H ( f )H
*
( f + ∆f )df
−∞
Bcoh is usually defined as the value of ∆f where the magnitude of R(∆f) has decreased by
3dB. As a result of the Fourier transform relationship between P(t) and R(∆f), the reciprocal of
the multipath spread is also a measure of the coherence bandwidth of the channel, that is: [4]
Eq. 9
Bcoh ≡ (∆f ) coh ≈
1
Tm
According to the above relationship, the coherence bandwidth can be easily estimated
from the time dispersion Tm. The problem is that the public literature only provides τrms.
Fortunately, a lower-bound for Bcoh based on τrms was derived by Fleury [22]:
Eq. 10
Bcoh ≥
arccos(c )
2 ⋅ π ⋅ τ rms
Where c is the selected coherence level in the interval (0, 1], and is defined to be the
minimum value of the lag ∆f such that the correlation coefficient between the random variables
H(f) and H(f+∆f) drops below c. For instance, c = 0.5 for a coherence level of 3dB.
Two sinusoids with frequency separation greater than Bcoh are affected (attenuated and
phase shifted) differently by the channel. Hence, when an information-bearing signal is sent
through the channel, if Bcoh is smaller than the bandwidth of the transmitted signal, the signal is
then severely distorted and the channel is said to be frequency selective. On the other hand, if
Bcoh is larger than the bandwidth of the transmitted signal, then all frequency components of the
signal are similarly affected and the channel is said to be frequency nonselective [3].
35
3.1.5
Doppler Spread
For the indoor radio channel, the multipath characteristics are static at any one location
until some movement occurs causing Doppler spreading. Such movements include people in
transit, slow displacement of transceiver antennas, and relocation of line-of-sight obstacles.
The Doppler spread is the width of the received spectrum when a single tone is
transmitted, and it is related to the rate at which channel characteristics, such as fading, occur.
The Doppler spread is important in determining the minimum signaling rate allowable for
coherent demodulation and the minimum adaptation rate for an adaptive receiver. The Doppler
spread of indoor radio channels is reportedly below 10 Hz [29].
3.1.6
Small-Scale Flat Fading
In a radio environment, the short-term fluctuations caused by wave interference among
multipath components is called small-scale fading, to distinguish it from the large-scale path
loss dependent on distance to the source. Small-scale fading is classified as being either flat or
frequency selective. Small-scale flat fading occurs in frequency nonselective channels [40].
Small-scale flat fading is modeled differently when there is an obstructed line-of-sight
(OBS) or a direct line-of-sight (LOS) path between transceivers. In the OBS scenario, the
receiver is immersed in cluttered surroundings and the amplitude of the resultant signal is
characterized by the Rayleigh probability distribution
Eq. 11
p R (r ) =
r −r 2
⋅e
σ2
( 2σ 2 )
for r ≥ 0 ;
where σ 2 = var( R )
In the LOS scenario, there is a dominant signal component in addition to the indirect
multipaths, hence the resultant amplitude is characterized by the Rician probability distribution
Eq. 12
r
r 2 + A2
A
p R (r ) = 2 exp − (
) ⋅ I o ( r2 )
2
σ
σ
2σ
for
{A ≥ 0, r ≥ 0}
Where A is the deterministic signal power about the carrier wave in decibels [40].
36
3.2 Channel Parameters
With the advent of unlicensed FCC radio spectrum, several channel propagation studies
have been completed at the frequencies centered around 5.2 GHz (lower-band U-NII) and 5.8
GHz (upper-band U-NII, and ISM). Several studies are reviewed next to obtain representative
values for the rms delay spread and path loss exponent at these frequency bands.
3.2.1
Propagation at 5.2 GHz
Hafezi et al [25] studied the wideband propagation characteristics for LOS and OBS
scenarios in five different indoor environments: three meeting rooms, a house, and an office
cube. The study reports a worst-case τrms of 40ns when using omni-directional antennas and
with people moving in the room. In general, τrms decreases when directional antennas are used,
although the non-optimal alignment of the antennas may cause an increase in τrms.
Nobles and Halsall [38] performed similar measurements on the 6th floor of the Faraday
Tower building at the University of Wales Swansea. Their results agree with a worst-case τrms
of 40ns for OBS scenarios. This study also argues that τrms is generally independent of the
distance between the transmitter and receiver, but that it is greater in larger rooms and rooms
with many line-of-sight obstacles such as walls and metal furniture.
In their study, Nobles and Halsall also conclude that the value of the path-loss exponent
n increases with the number of obstructions in the propagation path. The reported value of n
was 1.87 in LOS scenarios, 2.09 after passing through one wall, and 4.29 after two walls.
Measurements matched their path loss predictions best when n = 4.29. The tower’s rooms had
block interior walls, concrete floors, and several pieces of wooden furniture.
McDonnell [35] carried out path-loss measurements in four different houses. His pathloss exponent estimates are: n= 4 to 5, in an obstructed path to an adjoining room with brick
internal walls; n= 4 to 6, in a room directly above the transmitter with brick internal walls; n=
3.5 to 4.5, in a room directly above the transmitter with plasterboard internal walls; and n= 6 to
7, in a room not directly above the transmitter with brick internal walls.
37
3.2.2
Propagation at 5.8 GHz
Huang and Khayata [31] studied the channel propagation characteristics of several
indoor environments at Columbia University. At 5.8 GHz, they report that all observed values
of τrms are under 100ns, with a median level under 50ns. Their study also found that τrms shows
only a small increase in magnitude as a function of distance.
Bergljung and Karlsson [20] performed delay spread and path-loss measurements at 80
different locations in an office building environment. Their study reports a worst-case τrms of
50ns for inter-office OBS scenarios, 60ns for cross-floor scenarios, and a 95%-level close to
60ns for an atrium environment. The report also concludes that room size has a large influence
on the time dispersive multipath propagation characteristics.
Regarding path-loss measurements, Bergljung and Karlsson found a transmission loss
of about 108 dB at a distance of 30 m from the source in an OBS scenario. Additional
regression models showed that n= 2.9 in a same-floor OBS scenario, while n is as high as 3.6
when the transmitter and the receiver are one floor apart. The study also verified the validity of
the coherence bandwidth lower bound derived by Fleury [22].
3.2.3
Selected Parameters
The results from different channel propagation studies tend to vary slightly since they
are statistical models of environments that are never exactly equal to each other. Nevertheless,
it is important to choose representative channel parameters in order to design our network.
Considering worst-case reported values for τrms as low as 40ns and as high as 60ns,
with an upper bound of 100ns, our design will consider an overall τrms equal to 60ns to account
for most worst-case scenarios without being overly conservative.
With regards to path-loss exponent, our design will consider a representative value of n
equal to 4. This value is deemed adequate since it exceeds the path losses reported at 5.8 GHz,
and meets most path-loss measurements through two internal brick walls at 5.2 GHz
38
3.3 Channel Models
Representative parameters for the 5.x GHz frequencies can be used to model the delay
spectrum of multipath channels. For instance, once τrms is set at 60ns, Eq. 10 lower bounds the
channel’s coherence bandwidth by 2.778 MHz, for a coherence level of c=0.5. Based on this
estimate of Bcoh, Eq. 9 upper bounds the absolute time dispersion Tm of the channel by 360ns.
For indoor environments, the impulse response h(t) of the multipath radio channel has
been found to vary with τrms. Bello and Nelin [19] assumed that the impulse response of this
channel is slowly time-varying, where the value for any delay is a Gaussian stationary process
and is independent of the value at all other delays. Lacking more specific data, they proposed a
channel impulse response hgau(t) that has a Gaussian shape as defined in Eq. 13
Eq. 13
hgau (t ) =
1
1
exp{− (t / τ rms ) 2 }
2
2π τ rms
for t • Glance and Greenstein [23] proposed two additional channel models after observing
that the indoor multipath impulse response follows an exponential decay with one or more
spikes. To simplify their study, they considered an exponential hexp(t) and double-spike hdbl(t)
impulse responses as limiting cases. Note that hdbl(t) is a rare occurrence for a physical system
since it involves two paths of equal magnitude arriving at the receiver after some time delay.
Eq. 14
Eq. 15
hexp (t ) =
1
τ rms
exp{−t / τ rms }
for t • 1
hdbl (t ) = [δ (t ) + δ (t − 2τ rms )]
2
Assuming energy conservation, each model of h(t) must be scaled in amplitude so that
their area is unity. All three multipath channel models are used in the software simulation for
estimating the network’s bit-error rate performance as explained in Chapter 6.
39
3.4 Link Budget
The link budget is a tabulation of signal gains and losses through the entire
communications path. Normally, this path starts at the information source and ends at the
information sink, including all the intermediate steps such as encoding and modulation at the
transmitter, channel distortions, and signal processing decoding at the receiver [6]. However, in
order to reduce implementation dependencies, our link budget analysis will only consider the
channel distortions that take place between the transmitting and receiving antennas. We discuss
the allocation of frequency bands before detailing the link budgets of the network.
3.4.1
Frequency Band Allocations
The WGLAN project qualifies for using all or part of the 300 MHz of non-contiguous
spectrum made available by the FCC for Unlicensed National Information Infrastructure (UNII) devices. The U-NII spectrum may be segmented into three different bands based on the
FCC restrictions summarized in Table 3. Only Bands B and C may be used by the WGLAN
since Band A is restricted to a peak transmit power of up to 50mW, which falls short of the
100mW transmitter RF power available to WGLAN adapters.
Table 3. FCC restrictions on the U-NII band.
Bands
A
B
C
Frequencies (GHz)
5.15 – 5.25
5.25 – 5.35
5.725 – 5.825
Peak Transmit Power
50 mW
250 mW
1000 mW
Peak PSD
2.5 mW/MHz
12.5 mW/MHz
50 mW/MHz
Max Tx Ant. Gain
6 dBi
6 dBi
6 dBi
At first glance, the wide spectrum gap between Bands B and C suggests that the
WGLAN could support two-way communications through Frequency Division Duplexing
(FDD) as in cellular phone networks. For instance, if the WGLAN controller transmits
information to all adapters through Band B, then the adapters could transmit information back
to the controller using Band C. Since this scheme allows information to be sent concurrently in
two different directions, the system is said to be full-duplex. Unfortunately, the implementation
of an FDD scheme doubles cost and complexity when two adapters are required to
communicate directly between each other, unlike mobile phones in a cellular network.
40
Adapter #1
sends on C,
receives on B
band B
band C
Network Controller
sends on B,
receives on C
band ?
band ?
band C
Adapter #2
sends on C,
receives on B
band B
Figure 12. FDD scheme difficulties due to communication between adapters.
Figure 12 illustrates the added complexity of FDD in the WGLAN. Here, the controller
transmits data through Band B and the adapters through Band C, which implies that the
controller receives data through Band C and the adapters through Band B. In this scenario, a
deadlock arises when Adapter #1 wishes to talk to Adapter #2 since both adapters send and
receive data through the same bands. In order to establish a link, one of the adapters must then
swap its transmitting and receiving bands, which in fact doubles the RF circuitry needed in
each adapter with a consequent increase in power consumption.
Time Division Duplexing (TDD) is an alternative scheme that allows two-way
communication without the added cost or complexity of FDD. In TDD, a single frequency band
is shared among all network devices, which take alternate turns to transmit and receive
information. If the transmit and receive time slots are made short enough, the network appears
to be full-duplex when in reality it is half-duplex since information flows in only one direction
at a time. The deadlock scenario illustrated in Figure 12 is solved in TDD by swaping the time
slots that two communicating adapters use to transmit and receive data. Section 5.1 discusses
TDD implementation issues in more detail.
Since TDD requires just one frequency band, either Band B or C may be adequate. The
WGLAN system makes use of Band B, which expands 100 MHz of spectrum in the 5.25 – 5.35
GHz range. This band is preferred because it is less crowded than Band C, which shares
spectrum with ISM devices operating at 5.8 GHz. In addition, Band B allows a maximum
transmit power of 250mW, which is low enough for adapters to “compete” for use of the
spectrum with a maximum of 100mW of RF power. On the other hand, Band C allows up to
1000mW of RF power, which could hinder the operation of power-limited WGLAN adapters.
41
3.4.2
Controller’s Link Budget
As explained later in Chapter 4, the WGLAN project divides the full 100 MHz of Band
B into 1024 subchannels using OFDM technology. By design choice, the network controller
must be able to use all 1024 subchannels to communicate with adapters located as far as 25
meters away. It is convenient then to propose a link budget based on a single subchannel,
assuming that the transmitter’s RF power is equally divided among all subchannels.
Table 4 shows the link budget for the network controller. The first intermediate step
(line 3) is to compute the terminal Effective Isotropic Radiated Power (EIRP), defined as the
transmitter’s radiated power with respect to an isotropic antenna [6]. The EIRP is the sum of
line 1 and line 2. The transmitted power is given by the decibel equivalent of dividing the
250mW maximum available RF power among all 1024 subchannels. The transmitter antenna
gain is set to 0dBi based on omni-directional radiators.
The second intermediate step (line 6) is to compute the total path loss as defined on Eq.
5 for the center frequency of Band B, i.e. 5.3 GHz. This quantity breaks down into the 1-meter
loss in free-space and the 25-meter loss contribution with an exponent of 4 (see Section 3.2.3).
The third intermediate step (line 9) is to compute the received power. This quantity is
given by adding the received isotropic power, or terminal EIRP plus total path loss, to the
receiver diversity gain. This additional gain is provided by a combination of space- and timediversity based on BLAST-technology, which is currently under study at MIT’s Microsystems
Technology Laboratories.
Finally, we compute the Signal-to-Noise Ratio (SNR) by dividing the received power
spectral density (PSD) by the noise spectral density. The noise contribution is based solely on
thermal noise parameters, while the signal contribution is based on the power received per
subchannel, where each subchannel is 100 MHz / 1024 = 97.65 kHz wide. The resultant SNR is
26.5dB which is equivalent to a channel capacity of 8.8 bps/Hz based on Shannon’s formula.
42
Table 4. Link Budget for Network Controller
#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
Item
Transmitter Power
Transmitter Antenna Gain
Terminal EIRP
Path Loss, at 1m in free-space
Path Loss, at 25m with n=4
Total Path Loss
Received Isotropic Power
Receiver Diversity Gain
Received Power
Antenna Temperature
Receiver Temperature
System Temperature
Boltzmann’s Constant
Noise Spectral Density
Received PSD
Signal-to-Noise Ratio
Channel Capacity
Formula
TxPower = dB(250 mW / 1024)
TxGain is given
EIRP = TxPower + TxGain
First term in Eq. 5
Second term in Eq. 5
Path Loss = Eq. 5
RiPower = EIRP – Path Loss
RvGain is given
RvPower = RiPower + RvGain
ScTmp is assumed
RvTmp is assumed
Tsys = dB(ScTmp + RvTmp)
dBm(κ = 1.38x10-23 W/K-Hz)
No = Tsys + dBm(κ)
dB[RvPower(in mW) / 97.65 kHz]
Received PSD – No
From Shannon’s Capacity
Budget
-6.0
0.0
-6.0
(46.9)
(55.9)
(102.8)
-108.8
12.0
-96.8
150
180
25.2
-198.6
-173.4
-146.9
26.5
8.8
Units
dBm
dBi
dBm
dB
dB
dB
dBm
dBi
dBm
K
K
dB-K
dBm/K-Hz
dBm/Hz
dBm/Hz
dB
bps/Hz
3.4.3
Adapter’s Link Budget
Recall that the WGLAN topology consists of a single network controller along with
multiple network adapters connected to all sorts of communication devices. In contrast to the
network controller, each network adapter is constrained to a maximum RF transmitter power of
100mW to support battery-operation. In addition, the circuit design of network adapters is
simplified by assuming a lesser receiver diversity gain. These two features alone account for
the differences between the link budget of the network controller and the network adapters.
Table 5 shows the link budget for each network adapter. The first intermediate step
(line 3) is to compute the terminal EIRP. In this case, the transmitted power is given by the
decibel equivalent of dividing the 100mW maximum available RF power among just 100
subchannels. This constraint implies that each adapter may use up to 100 of the available 1024
subchannels. The transmitter antenna gain is set to 0dBi based on omni-directional radiators.
The total path loss in line 6 equals that of the network controller’s since all adapters
communicate using the same 5.3 GHz center frequency through distances of up to 25 meters.
Similarly, the received power equals that of the network controller’s since the terminal EIRP,
total path loss, and receiver diversity gain have all been adjusted accordingly.
Finally, the resulting Signal-to-Noise Ratio is again 26.5dB, corresponding to a channel
capacity of 8.8 bps/Hz based on Shannon’s formula. A careful comparison between Table 4 and
Table 5 reveals that both link budgets differ only in line 1 and line 8, since the received power
is kept constant in both cases by adjusting the transmitter power and receiver diversity gain.
By limiting the number of subchannels used by the network adapters to 100, both link
budgets guarantee that transmitting antennas radiate 1mW of effective power per subchannel.
Since each subchannel is 97.65 kHz, this implies that the peak transmit power per MHz is (1
MHz / 97.65 kHz) • (1mW) = 10.24mW. This PSD value satisfies the FCC’s peak PSD
constraint of 12.5 mW/MHz as explained in Section 3.4.1.
Table 5. Link Budget for Network Adapters
#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
Item
Transmitter Power
Transmitter Antenna Gain
Terminal EIRP
Path Loss, at 1m in free-space
Path Loss, at 30m with n=4
Total Path Loss
Received Isotropic Power
Receiver Diversity Gain
Received Power
Antenna Temperature
Receiver Temperature
System Temperature
Boltzmann’s Constant
Noise Spectral Density
Received PSD
Signal-to-Noise Ratio
Channel Capacity
Formula
TxPower = dB(100 mW / 100)
TxGain is given
EIRP = TxPower + TxGain
First term in Eq. 5
Second term in Eq. 5
Path Loss = Eq. 5
RiPower = EIRP – Path Loss
RvGain is given
RvPower = RiPower + RvGain
ScTmp is assumed
RvTmp is assumed
Tsys = dB(ScTmp + RvTmp)
dBm(κ = 1.38x10-23 W/K-Hz)
No = Tsys + dBm(κ)
dB[RvPower(in mW) / 97.65 kHz]
Received PSD – No
From Shannon’s Capacity
Budget
0.0
0.0
0.0
(46.9)
(55.9)
(102.8)
-102.8
6.0
-96.8
150
180
25.2
-198.6
-173.4
-146.9
26.5
8.8
Units
dBm
dBi
dBm
dB
dB
dB
dBm
dBi
dBm
K
K
dB-K
dBm/K-Hz
dBm/Hz
dBm/Hz
dB
bps/Hz
3.5 Channel Capacity
Claude Shannon showed [6] that the system capacity C, in bps/Hz, of a channel
perturbed by additive white Gaussian noise (AWGN) is a logarithmic function of the ratio
between average received signal power and average noise power, or Signal-to-Noise Ratio,
C = log 2 (1 + SNR)
Eq. 16
Shannon argued that, if a channel has capacity C, then it is theoretically possible to
send information over such a channel at any normalized rate R, where R < C, with an arbitrarily
small error probability by using a sufficiently complicated coding scheme.
For an SNR of 26.5dB, the AWGN channel capacity is 8.8 bps/Hz as derived in the link
budgets. Since the SNR is directly proportional to received signal power, it follows that the
channel capacity increases at shorter separations between transmitter and receiver. Figure 13
shows the corresponding channel capacities for distances below the worst-case 25-meter range.
capacity (bps/Hz)
30
25
20
15
10
5
0
1
3
5
7
9
11
13
15
17
19
21
23
25
distance (meters)
Figure 13. Channel capacity as a function of distance
Finally, the SNR is also inversely proportional to noise power, including interference
and multipath radiations. The effects of noise on the SNR and channel capacity are considered
during multiuser allocations in Chapter 5 and estimations of BER performance in Chapter 6.
46
Chapter 4 : Modulation and Demodulation
Modulation and demodulation, in its broadest context, refers to the series of signal
processing steps needed to exchange digital data bits through an analog channel. This chapter
describes the transceiver modem design that implements the adaptive QAM-OFDM technology
proposed for the WGLAN project. We first present the principles behind OFDM, then describe
the modem design, and finally choose system parameters based on several design tradeoffs.
4.1 The OFDM Concept
The basic principle behind Orthogonal Frequency Division Multiplexing (OFDM), also
known as Multicarrier Modulation (MCM) or Discrete Multitone (DMT), is to divide a highrate data stream into relatively low-rate substreams which are then used to modulate several
subcarriers in parallel [44]. In a multipath environment, OFDM is especially useful when the
individual bandwidth of each subchannel is less than the coherence bandwidth of the composite
channel, since then each subchannel experiences frequency nonselective fading that can be
undone on the receiver end without using cumbersome equalizing techniques.
In order to explain the inherent advantages of OFDM, it is convenient to first review
the premises behind conventional FDM technology. Such a review will provide a basis for
comparison when qualifying the performance of orthogonal FDM.
4.1.1
Conventional FDM Technology
Frequency Division Multiplexing (FDM) allows different signals to be transmitted on
any set of non-overlapping frequency bands. Assuming M lowpass bandlimited signals { x1(t),
x2(t), …, xM(t) }, conventional FDM first upsamples each signal to a center frequency fm for m =
1, 2, …, M before transmitting the composite spectrum onto the channel. On the receiver end,
analog bandpass filters are used to completely separate the different bands.
eMŒI1t
ÜÜÜ
e-MŒI1t
ÜÜÜ
channel
ÜÜÜ
ÜÜÜ
xM(t)
ÜÜÜ
y1(t)
ÜÜÜ
x1(t)
yM(t)
e-MŒIMt
eMŒIMt
Figure 14. Transceiver architecture for conventional FDM
Since implementing very sharp filters on the receiver end is a challenging task, each of
.
the signals xm(t) normally uses a bandwidth
IS
which is greater than the Nyquist
minimum, fS. As shown in Figure 15, this excess bandwidth wastes part of the spectrum as the
efficiency of band usage is now fS ûI
.. Even though spectrum efficiency may be
increased to 100% in some cases by making adjacent bands overlap at their –3dB point, the
power
implementation of a large filter bank is still a significant bottleneck.
ÜÜÜ
f1
f2
ÜÜÜ
fM
frequency
Figure 15. Typical spectrum for conventional FDM
48
4.1.2
Orthogonal FDM Technology
On the transmitter side, OFDM differs from conventional FDM technology in that all
carrier frequencies are equally spaced apart, hence the name orthogonal, and that carriers are
“keyed” by incoming data signals using Quadrature Amplitude Modulation (QAM). We first
derive the OFDM concept mathematically, and then provide some graphical intuition.
Starting in the continuous-time domain, consider a high-rate data stream x(t) that can be
divided into M low-rate substreams xm(t) for m = 0, 1, …, M-1 such that Eq. 17 holds:
x (t ) =
Eq. 17
M −1
∑ xm (t )
m =0
According to conventional FDM technology, each substream xm(t) is then upsampled to
a different carrier frequency fm for m = 0, 1, …, M-1 as follows:
Eq. 18
y (t ) =
M −1
∑ xm (t ) ⋅ e j 2πf
mt
m =0
Now we can apply the two distinctive features of OFDM technology. First, since all M
subcarriers are equally spaced in a support bandwidth W, we can write the subcarrier
frequencies as fm = m • ( W / M ). Second, since the subcarriers are keyed by points from QAM
constellations, we can write the low-rate substreams as complex-valued constants xm(t) = Zm.
Substituting these definitions into Eq. 18:
Eq. 19
y (t ) =
M −1
∑ Zm ⋅ e
m=0
49
j 2π (
mW
)t
M
Sampling the signal y(t) every T seconds in Eq. 19 results in:
y (nT ) =
Eq. 20
M −1
∑ Zm ⋅ e
j 2π (
mW
)(nT )
M
m=0
To arrive at a discrete-time expression, we set the sampling frequency to 1/T = LW,
where L is the oversampling factor. Based on Nyquist sampling theory, L • since W is
assumed to be a complex support bandwidth. Substituting for T in Eq. 20 and simplifying:
y[n] =
Eq. 21
M −1
∑ Zm ⋅ e
j 2π
mn
LM
m=0
Eq. 21 resembles the expression for computing the inverse Discrete Fourier Transform
(DFT) except for a slight mismatch in the summation limits. This can be “fixed” by making a
change of variable for Zm as follows:
Eq. 22
y[n] =
LM −1
∑
m=0
Z m'
⋅e
j 2π
mn
LM
where
 Z : 0 ≤ m ≤ M −1
Z m' =  m
0 : M ≤ m ≤ LM − 1
From the final expression in Eq. 22, it follows that the transmitted signal can be
synthesized through an inverse DFT. Moreover, it should be evident that on the receiver end the
values of Zm can be recovered by computing the forward DFT of y[n].
The greatest implementation advantage of OFDM is that frequency-division is achieved
without a need for a bank of analog filters on the receiving end. In fact, both transmitter and
receiver can be implemented digitally using efficient Fast Fourier Transform (FFT) techniques.
50
For some graphical intuition regarding OFDM we refer to Figure 16. Every T seconds,
a total of M complex-valued points Zm from different QAM constellations are used to modulate
M complex carriers centered at fm. The composite signal is sampled by the inverse DFT, which
outputs M complex-valued time-domain samples that gather all the information contained in the
original data. Each block of M time-domain samples is called an OFDM symbol.
=
Z1
eMŒI1t
x2(t)
=
Z2
eMŒI2t
xM(t)
=
ZM
ÜÜÜ
x1(t)
eMŒIMt
OFDM symbol: y(nT) = y[1]
y[2]
y[3]
y[4]
ÜÜÜ
y[M]
Figure 16. Graphical interpretation of the OFDM concept
It is important to note that OFDM achieves frequency-division by baseband processing
rather than by bandpass filtering. Indeed, as shown in Figure 17, the individual spectra have
sinc shapes. Even though they are not bandlimited, each signal can still be separated since
power
orthogonality guarantees that all interfering sincs have nulls at the peak of the sinc of interest.
f1
f2
f3
f4
f5
ÜÜÜ
fM
frequency
Figure 17. Typical spectrum for orthogonal FDM
To preserve orthogonality among carriers, OFDM symbols are guarded with a cyclic
prefix whose length exceeds the time dispersion Tm of the multipath channel. Since each OFDM
symbol is periodic by virtue of the DFT, the guard interval is made by replicating the last k
time-domain samples, i.e. M-k … M-1, at the beginning of each OFDM symbol.
51
4.2 Transmitter Block Diagram
Figure 18 shows a block diagram implementation of an OFDM transmitter based on the
mathematical analysis just completed. Since the transmitter can be thought of as a pipeline that
produces one OFDM symbol every TS seconds, we now analyze each pipeline step at a time.
The input to the pipeline is a high-rate data stream whose bit rate is given by Eq. 23,
where ûI is the subcarrier spacing and bm is the number of bits assigned to the mth subcarrier:
Eq. 23
input _ bit _ rate =
M −1
∑ ∆f ⋅ bm
m=0
Serial-to-Parallel (S/P) conversion is the first processing step in the pipeline. Based on
the SNR of each subchannel, the S/P block divides the incoming data stream into M substreams
by assigning 0 to 8 bits to each output line. Details on the algorithm used to allocate bits among
subchannels is postponed until Chapter 5.
Once bm has been set for each parallel line, the second step is QAM-constellation
assignments. First, each subchannel is assigned a power-of-two QAM constellation that has 2bm
points. Second, for each parallel line the incoming bm bits are used to select a specific point in
the respective constellation, so the output at each of the outgoing M lines is a multibit complexvalued number representing a single QAM point.
The IFFT block is the third step in the transmitter pipeline. Every TS seconds, the QAM
block generates M complex-valued numbers that are used to modulate the lowest M carriers of
an inverse DFT. The higher (L-1)•M carriers are set to zero to account for the oversampling
factor L. The inverse DFT can be efficiently implemented with a simplified version of an LM
complex-point IFFT algorithm that takes into account the (L-1)•M zeroed inputs. After
processing, the IFFT block generates LM complex-valued time-domain samples.
52
clk = 1 / TS
y1
ZM-1
IFFT
0
0
•••
(L-1)•M
LM
complex
points
clk = LW
plus
guard
period
insertion
yLM-1
0
I channel
digital
D/A
LPF
x
FRV ŒIc)t
clock = LW
VLQ ŒIc)t
analog
fc = 5.3GHz
Q channel
digital
D/A
LPF
x
Figure 18. Block diagram of the OFDM transmitter
I
P/S
register
Zm =
Xm + jYm
Z1
•••
bM-1
QAM
y0
register
ûI ‡ Em
bm function
of SNRm
b1
register
S/P
•••
data rate =
Z0
•••
b0
clk = 1 / TS
+
output
register
clk = 1 / TS
Q
Parallel-to-Serial (P/S) conversion is the fourth step in the pipeline. This step has two
functions. First, a cyclic prefix of length TG is appended at the beginning of the original OFDM
symbol of length TB. Second, the P/S block merges the low-rate substreams back into a single
high-rate stream, with real and imaginary parts split into the I and Q channels respectively.
The final steps in the pipeline involve analog signal processing. First, the multibit
samples from the I and Q channels are passed through two digital-to-analog converters (DAC)
clocked at a frequency of LW Hz. After analog conversion, each channel is filtered to reduce
out-of-band emissions before upsampling the signal to the center frequency of 5.3 GHz.
4.3 Receiver Block Diagram
On the receiver end, the analog signal must be transformed back into a high-rate digital
data stream by undoing all the processing steps performed at the transmitter. For this reason, as
shown in Figure 19, the receiver block diagram resembles a mirror image of the transmitter
block diagram. We now explain the few distinct blocks on the receiver end.
After downsampling and digitizing the analog signal, the S/P block first removes the
cyclic prefix from the OFDM symbol before splitting the incoming samples into LM low-rate
substreams. These substreams are then input to the FFT block which computes a forward DFT
and returns LM complex-valued frequency-domain amplitudes. Since the latter (L-1)M points
should equal zero, we are only interested on the first M outputs that correspond to the original
Zm points scaled by the flat power spectral density level of the mth subchannel, respectively.
The Slicer block recovers the original bits from the scaled Zm by performing two
functions. First, an estimate äm is created for the mth subchannel by multiplying the received Zm
by the respective complex-valued reciprocal scaling factor computed during the training stage.
Then, for each estimate äm and mth constellation size, the slicer determines the most likely bit
sequence by matching äm to the closest point in the respective constellation. Finally, the
resulting bits are merged again into a high-rate data stream by the P/S block.
I channel
x
BPF
analog
FRV ŒIc)t
input
VLQ ŒIc)t
LPF
A/D
digital
clock = LW
fc = 5.3GHz
Q channel
y0
Z0
b0
y1
Z1
LM
complex
points
yLM-1
ZM-1
•••
•••
register
plus
guard
period
removal
FFT
Slicer
Zm =
Xm + jYm
0
0
(L-1)•M
0
Figure 19. Block diagram of the OFDM receiver
register
clk = 1 / TS
S/P
register
Q
clk = 1 / TS
register
I
A/D
clk = 1 / TS
•••
clk = LW
LPF
digital
b1
bM-1
data rate =
•••
x
BPF
P/S
ûI ‡ Em
4.4 Choosing System Parameters
Thus far, the OFDM system presented in this chapter has been described in terms of
general parameters. The goal of this section is to choose specific values for these parameters
after reviewing the relevant design tradeoffs. For convenience, all free system parameters and
corresponding constraints are summarized in Table 6.
Table 6. System parameter constraints.
Variable Name
W
L
M
TB
TG
TS
Meaning
Support bandwidth
Oversampling factor
Number of subchannels
Length of original OFDM block
Length of guard interval (cyclic prefix)
Length of guarded OFDM symbol
Constraints
= 100 MHz
• PXVW EH SRZHU RI must be power of 2
=M/W
• 7m from Section 3.3
= TB + TG
The first step is to choose values for W and L based on system specifications. On this
regard, Section 3.4.1 targets the unlicensed spectrum contained between 5.25 – 5.35 GHz,
which sets W equal to 100 MHz. Meanwhile, additional analog specifications require that the
oversampling ratio L be set to 4 in order to ease the design of several filters. Choosing W and L
effectively sets the clock frequency of the D/A and A/D converters equal to 400 MHz.
Another highly constrained parameter is the guard interval length, TG. From Section
4.1.2, the value of TG should exceed the time dispersion Tm of the multipath channel. Since
Section 3.3 upper bounded Tm by 360ns, setting TG equal to 500ns provides a reasonable margin
of error and an integer number of cyclic prefix samples for a sampling frequency of 400 MHz.
At this point, only one degree of freedom remains since assigning a value to anyone
among M, TB, or TS, also determines the value of the other two parameters. However, for design
purposes it is more convenient to analyze the tradeoffs involved in choosing either the number
of subchannels, M, or the overall length of an OFDM symbol, TS. Thus, we now discuss the
arguments behind both approaches before selecting values for the remaining three parameters.
For starters, the number of subchannels in an OFDM system should be a power of two
so that efficient FFT algorithms may be used in the transceiver architecture. On a more
fundamental basis, the actual bounds on M are related to the respective subchannel bandwidth
that results from dividing the support spectrum W. First, in order to assume a flat power
spectral density for all subchannels at the receiver, the individual bandwidth of each subchannel
must be smaller than the coherence bandwidth of the composite channel. From Section 3.3,
since Bcoh
• 0+] WKHQ
M
• VR WKDW
W/M
” 0+] 6HFRQG LQ RUGHU WR DVVXPH
coherent detection in the receiver, the individual bandwidth of each subchannel must be greater
than the Doppler spread of the composite channel. From Section 3.1.5, for a Doppler spread of
100 Hz (or ten times the reported 10 Hz), it follows that M ” 19 so that W / M • +]
Since the fundamental bounds on M are quite loose, i.e. 26
”
M
” 19
, the actual choice
of M must be further constrained by more practical bounds. With respect to implementation
issues, increasing values of M present two main disadvantages. First, it is clear that very large
values of M increase the complexity of the IFFT and FFT blocks to extremes beyond what can
be achieved with currently available silicon technology. Second, larger values of M imply more
latency in end-to-end data transmission because as OFDM transmits data bits in parallel the
receiver must wait some time TB (proportional to M) before it can start demodulating an OFDM
symbol to retrieve the data bits. Latency becomes a special concern if the system requires fast
response time to such requests as power control commands.
However, increasing M does have its advantages. Since a larger number of subchannels
provides higher spectrum resolution, the size of QAM constellations can be adapted more
closely to the SNR conditions of each subchannel, which increases the overall bandwidth
efficiency of the network. A higher spectrum resolution also provides more flexibility in
meeting the varying throughput requests of different network adapters; for instance, if
subchannels are 1 MHz wide then the minimum throughput that can be provided is 1 bps/Hz x
1 MHz = 1 Mbps. Finally, a higher spectrum resolution makes it less likely for a strong
narrowband interferer near the boundary between adjacent subchannels to simultaneously
knock down both wider band subchannels.
57
Since the tradeoffs involved in choosing M do not seem to provide a strong argument
one way or the other, previous OFDM-system designers have opted to choose a value for TS
instead [51]. For a given TG, the only tradeoff on TS is time efficiency, that is, the percentage of
time used to transmit the guard interval over the actual length of the OFDM block.
A good rule of thumb is to choose TG to be 5% of TB, where TB is the length of the
original (unguarded) OFDM symbol. Since TG was set at 500ns, this makes TB be 10µs and M
be 1,000 subcarriers. However, because M must be a power of two, we will settle on M being
1,024 instead, which sets TB equal to 10.24µs and TS equal to 10.74µs. The final choice of
system parameter values is summarized in Table 7.
Table 7. System parameter values.
Variable Name
W
L
M
TB
TG
TS
Meaning
Support bandwidth
Oversampling factor
Number of subchannels
Length of original OFDM block
Length of guard interval (cyclic prefix)
Length of guarded OFDM symbol
Value Chosen
100 MHz
4
1,024 carriers
10.24µs
500ns
10.74µs
Based on our choice of system parameter values, a 4,096 complex-point FFT must be
computed every 10.74µs. For comparison purposes, Texas Instrument’s TMS320C62x DSP
platform can compute a complex-valued radix-4 4096-point FFT in about 312µs [56]. Although
the FFT block does represent a substantial computational expense, its performance requirement
should nevertheless be feasible with an optimized implementation using VLSI technology.
58
Chapter 5 : Multiple Access Scheme
Multiuser networks share their physical layer resources among simultaneous users
based on a series of protocols that are collectively known as multiple access schemes. In this
chapter, we propose a multiple access scheme that uses the inherent advantages of OFDM to
negotiate and maintain simultaneous communication links among different users. An overview
of the WGLAN topology precedes the description of features in the proposed scheme.
5.1 Network Topology
In the WGLAN model, the network consists of a single controller, physically
connected to the Internet, and multiple adapters, physically connected to different devices. As
shown in Figure 20, the WGLAN has a star-like topology where the controller is at the center
of the network and the adapters are at the periphery. Wireless bidirectional communication is
supported between any controller-adapter pair and also between any adapter-adapter pair.
Adapter 3
Adapter 2
Adapter 4
Controller
Adapter 1
Adapter N
Figure 20. Star-like topology of the WGLAN
Bidirectional communication is accomplished through Time Division Duplexing
(TDD), a technique where the network controller and existing adapters take alternate turns to
transmit and receive information. As shown in Figure 21, TDD segments time into two slots, A
and B. During time slot A, the controller transmits information and the adapters listen. During
time slot B, the adapters transmit information and the controller listens. If the length of the time
slots is made short enough, then the network resembles a real-time full-duplex system.
A
B
A
B
A
B
A
B
A
B
A
B
time
Link Endpoints
Controller, adapter
Slot A
Controller transmits,
Adapters receive
Slot B
Adapters transmit,
Controller receives
Adapter, adapter
Master adapter transmits,
Slave adapter receives
Slave adapter transmits,
Master adapter receives
Figure 21. TDD scheme.
The TDD scheme mentioned above supports bidirectional links between controlleradapter pairs, but is insufficient in the case of adapter-adapter pairs since all adapters transmit
and receive in the same time slot. To solve this difficulty, the master adapter in an adapteradapter link must be able to switch TDD slots. In this master-slave convention, “master” refers
to the adapter that initiated the link and “slave” refers to the other adapter in the link.
The length of the TDD time slots is a function of the maximum round-trip delay
allowed in the network. Assuming that slot A and B have the same length so as to support an
equal throughput in both link directions, and that the maximum round-trip delay is set to 10ms,
then each slot could consist of a maximum of ( 5ms / 10.74µs = ) 465 OFDM symbols.
Finally, in order to support bidirectional communication effectively, TDD requires that
all devices in the network have the same time reference. For simplicity, the network controller
shall determine this time reference. Assuming that the length of TDD slots is fixed by design,
then any adapter joining the network can become synchronized by determining the time
difference between pilot symbols transmitted on two consecutive “A” slots.
60
5.2 Negotiating a Communication Link
The proposed multiple access scheme defines a control channel and several data
channels consisting of different OFDM subchannels. The WGLAN negotiates communication
links through the control channel, and supports multiple simultaneous links by allocating
different data subchannels among users. This section describes the three-case protocol used to
establish a link based on the type of communicating devices and who initiates the link request.
5.2.1
Controller-to-Adapter Link Request
Figure 22 summarizes the protocol for establishing a communication link between a
controller-adapter pair when the link request is initiated by the network controller. Initially, the
network controller uses the control channel to issue a link request requiring a specific
throughput and quality of service (or BER). This request is received by the intended adapter,
which acknowledges it through the control channel. Then the controller transmits pilot symbols
on the currently available data subchannels (the controller is always aware of all subchannel
allocations). These pilots are received by the adapter and used by the adapter to compute the
SNR of each subchannel. Subchannels are then ranked by the adapter based on their estimated
bit capacity, and the ranking is sent back to the controller through the control channel. This
subchannel ranking is used by the controller to allocate a limited number of subchannels for
exclusive use of the requested link. The respective subchannel allocation is finally announced
by the network controller, which establishes a communication link between the two devices.
Issue link request on control channel
Acknowledges link request on control channel
Transmits pilot symbols on available data subchannels
Controller
Returns ranking of subchannels on control channel
Announce data subchannel allocation on control channel
Acknowledges allocation on selected subchannels
Bidirectional link established on allocated data subchannels
Figure 22. Controller-to-adapter link negotiation
61
Adapter
5.2.2
Adapter-to-Controller Link Request
If the link request is initiated by the adapter, the controller-adapter link protocol
follows the same transactions described in Section 5.2.1. except that the direction of the first
two transactions is reversed. That is, now the adapter issues the link request through the control
channel, while the controller acknowledges it through the control channel. All other subsequent
transactions follow the same order and direction shown in Figure 22.
5.2.3
Adapter-to-Adapter Link Request
In the adapter-adapter case, the network controller mediates link negotiations since it is
the only device that is aware of all subchannel allocations. The protocol is summarized in
Figure 23. First, the master adapter establishes a low-throughput link with the controller in
order to allow real-time communication during mediation. Once bidirectional communication
has been established, the controller provides a list of available data subchannels to the master
adapter. The master adapter then sends pilot symbols on these subchannels to the slave adapter.
Based on the SNR of each subchannel, the slave adapter ranks its subchannel preference and
returns this ranking to the controller. In turn, the network controller uses this ranking to allocate
a limited number of data subchannels and announces this allocation to both adapters. After each
adapter has acknowledged the allocation, a bidirectional link is established between adapters
and the temporary link between the master adapter and the controller is terminated.
Same as Section 5.2.2
Bidirectional link
switch
slots
Controller
Transmits pilot symbols …
switch
slots
Announce allocation
Acknowledges allocation
Issue link request
Acknowledges link request
… on available subchannels
Ranks subchannels
Announce allocation
Acknowledges allocation
Adapter-Adapter bidirectional link established on allocated subchannels
Figure 23. Adapter-to-adapter link negotiation
62
Slave Adapter
Master Adapter
List of available subchannels
5.3 Control Channel
The control channel is reserved for link management transactions such as issuing and
acknowledging requests as well as ranking and allocating data subchannels. Since the control
channel is used before establishing a communication link, its location in the radio spectrum
must be known to the controller and all adapters by design. In addition, the control channel
must be very reliable even in the presence of undesired interference since access to the network
resources depends on its availability at all times.
An uncoded OFDM system provides channel reliability through frequency diversity.
According to this technique, the control channel is a logical grouping of a fixed number of
subchannels that are equally spaced across the spectrum and that transmit exactly the same
information. Data redundancy in frequency diversity enhances the robustness of the control
channel by decreasing the probability that all underlying subchannels are simultaneously
affected by undesired interference. To provide the lowest possible bit error rate, the
subchannels that constitute the control channel must use 2-point QAM constellations.
5.3.1
Transmitting bits through the Control Channel
Due to TDD, the control channel is an exclusive resource to the network controller but
a shared resource to the network adapters. Consequently, the access protocol of the control
channel depends on the type of device wishing to transmit information.
The network controller may transmit information through the control channel at any
time during slot A of the TDD scheme. The control channel is an exclusive resource to the
network controller because in the controller-adapter case, no other device may transmit
information during slot A (see Figure 21), and in the adapter-adapter case, the master adapter
only transmits pilot symbols on data subchannels during slot A (see Figure 23), which avoids
any potential channel contention. To transmit bits through the control channel, the network
controller must replicate the original bits on each of the reserved subchannels that constitute the
control channel to account for the frequency diversity explained before.
63
To the network adapters, the control channel is a shared resource because any adapter
can use it to transmit information during slot B of the TDD scheme. Since several adapters may
try to use the control channel at the same time, the ideal access protocol must be able to resolve
any potential collisions. One such protocol is Carrier Sense Multiple Access with Collision
Avoidance (CSMA/CA) [1]. In CSMA/CA, an adapter must sense that the control channel is
available before starting to transmit bits. If the control channel is busy, as determined by the
increased amount of energy perceived on all reserved subchannels, the adapter then waits for a
random amount of time before sensing the channel again. A collision occurs only if two
adapters simultaneously sense the control channel as available, but the probability of this event
is minimized by the random waits. Wireless networks use collision avoidance rather than
collision detection because detections cannot be identified as radio transmitters saturate nearby
radio receivers. If the control channel is available, an adapter may transmit bits through it by
replicating the original bits on each of the respective reserved subchannels.
5.3.2
Receiving bits through the Control Channel
On the receiving end of the control channel, there is no distinction between the network
controller and adapters. Since all network devices transmit control bits by replicating them on
reserved subchannels, the receivers can use this redundancy to improve their decisions.
Assuming an AWGN channel and 2-point QAM constellations, the maximum likelihood test
verifies that the optimal decision rule is to add the control subchannels, yi, appropriately scaled
by their respective noise variance, i, to estimate the actual bit that was sent [5].
Eq. 24
yˆ = ∑
i
yi
λi
However, the optimal decision rule, as shown in Eq. 24, is expensive to compute since
it requires each network device to continuously measure the noise variance of all reserved
subchannels. An alternative, yet sub-optimal, decision rule is to base receiver estimates solely
on the reserved subchannel that has the largest SNR. As undesired interferences change with
time, the control channel maintains its reliability by the low probability that all reserved
subchannels are knocked down due to multiple interferers.
64
5.4
Data Channels
Data channels are used to support real-time bidirectional communication between
different devices in the network. In OFDM systems, a data channel is a logical grouping of
subchannels that together satisfy the link throughput (in bps) and quality of service (or BER)
requested by the communicating devices. Once the network controller allocates data
subchannels to a particular link, these subchannels become unavailable to other devices in the
network. The algorithm for allocating data subchannels is the focus of the current section.
5.4.1
Preliminary Considerations
In order to compare different subchannel allocation algorithms, we will use two criteria
as our measure of goodness, namely bandwidth efficiency and user satisfaction. In general, an
allocation is said to be bandwidth efficient if each data subchannel is allocated to the device
that can send the largest number of bits through it. On the other hand, an allocation is said to
satisfy a user if it meets the requested throughput and quality of service for a link.
Assuming that all link requests are reasonable, an optimal allocation algorithm must be
bandwidth efficient and satisfy all users. By convention, a reasonable request is one whose
requirements can be met by assigning at most 100 (see Section 3.4.3) of the subchannels ranked
by a network device. However, even if all requests are reasonable, it is possible that no optimal
allocation exists when several devices rank the same subchannels in a similar order.
5.4.2
Subchannel Allocation Algorithm
In order for the network controller to allocate subchannels among users, contending
adapters must first rank their subchannel preference based on the signal-to-“noise” ratio (SNR)
of each subchannel. To compute the SNR of each subchannel, an adapter divides the “signal”
energy of the respective pilot symbol sent by the controller during slot A, by the “noise” energy
received during slot B (when the controller is quiet). Note that from this point forward, “noise”
refers to the energy contributed by both thermal noise and undesired interferers.
65
Based on the SNR of each subchannel, an adapter then determines each subchannel’s
capacity according to the requested quality of service and the BER performance estimates
summarized in Table 14. After this step, a sorted list of subchannels and their respective
capacities is sent back to the network controller for processing. On the controller side, the
throughput requested by each adapter along with the respective subchannel ranking is sufficient
to perform an efficient allocation. Note that since the available RF power is equally distributed
among all subchannels by design (see Table 4 and Table 5), the current algorithm simplifies the
problem of power distribution among subchannels into a problem of throughput maximization.
At this point, the network controller has enough information to allocate subchannels
among users, and so we now analyze different algorithm alternatives to perform this allocation.
For illustration purposes, consider the 12-subchannel OFDM scenario shown in Table 8. Here,
three adapters X, Y, and Z have submitted their subchannel rankings sorted by their respective
bit capacity (in square brackets). A dot next to a subchannel indicates that the subchannel has
not been allocated to a particular adapter. Besides the subchannel ranking, each adapter’s
request also specifies the total number of bits to be allocated as shown on the first row of the
table (in parentheses). For instance, Adapter X requested 25 bits, which corresponds to a link
throughput of (7 + 7 + 6 + 5 bps/Hz) • (97.65kHz) = 2.44 Mbps.
Table 8. OFDM link request scenario
Adapter X
(requested 25)
Adapter Y
(requested 20)
Adapter Z
(requested 22)
#7: [7] Ü
#3: [7] Ü
#6: [6] Ü
#5: [5] Ü
#11: [5] Ü
#8: [5] Ü
#12: [4] Ü
#1: [4] Ü
#10: [3] Ü
#4: [2] Ü
#9: [2] Ü
#2: [2] Ü
Total allocation: 0
#11: [8] Ü
#5: [7] Ü
#8: [6] Ü
#3: [6] Ü
#1: [6] Ü
#9: [5] Ü
#6: [4] Ü
#10: [3] Ü
#7: [3] Ü
#12: [2] Ü
#2: [1] Ü
#4: [0] Ü
Total allocation: 0
#11: [8] Ü
#3: [8] Ü
#12: [8] Ü
#8: [7] Ü
#4: [6] Ü
#2: [6] Ü
#10: [5] Ü
#9: [4] Ü
#5: [3] Ü
#7: [3] Ü
#6: [3] Ü
#1: [2] Ü
Total allocation: 0
66
Assuming that all adapters have equal priority, one approach is to select an adapter at a
time and allocate its best available subchannels until we satisfy the requested throughput. Table
9 shows the result of running this algorithm on our sample scenario. Since Adapter X is
satisfied first, it has no subchannel constraints and gets allocated its four best subchannels.
Adapter Y is constrained by the subchannels already allocated to X, so it receives the best three
subchannels that are still available. Since Adapter Z is satisfied last, its choice of subchannels is
constrained by all previous allocations. Adapter Z’s allocation exceeds the requested 22 bits
because its partial allocation is 20 bits by the time subchannel #2 is claimed, and then
subchannel #9 is the smallest capacity subchannel still available within the system.
Table 9. Subchannel allocation by maximizing each adapter’s bandwidth efficiency
Adapter X
(requested 25)
Adapter Y
(requested 20)
Adapter Z
(requested 22)
#7: [7] X
#3: [7] X
#6: [6] X
#5: [5] X
#11: [5] Ü
#8: [5] Ü
#12: [4] Ü
#1: [4] Ü
#10: [3] Ü
#4: [2] Ü
#9: [2] Ü
#2: [2] Ü
Total allocation: 25
#11: [8] Y
#5: [7] Ü
#8: [6] Y
#3: [6] Ü
#1: [6] Y
#9: [5] Ü
#6: [4] Ü
#10: [3] Ü
#7: [3] Ü
#12: [2] Ü
#2: [1] Ü
#4: [0] Ü
Total allocation: 20
#11: [8] Ü
#3: [8] Ü
#12: [8] Z
#8: [7] Ü
#4: [6] Z
#2: [6] Z
#10: [5] Ü
#9: [4] Z
#5: [3] Ü
#7: [3] Ü
#6: [3] Ü
#1: [2] Ü
Total allocation: 24
According to the subchannel allocation just outlined, the current algorithm is
bandwidth efficient for a single adapter, but not bandwidth efficient overall. As shown in Table
9, subchannel #3 gets assigned to Adapter X even though Adapter Z claimed a higher capacity
on that same subchannel. A more striking deficiency of this algorithm is its potentially unfair
allocation when several adapters rank the same subcarriers among their top choices, since then
only one adapter will get all the best subchannels allocated to it. We would like to consider
other ways of distributing network resources that maximize bandwidth efficiency while
providing each adapter with a fair opportunity to claim its top-ranked subchannels.
67
In order to maximize overall bandwidth efficiency, a second approach suggests that the
network controller allocate each subchannel to that adapter that claims the highest capacity,
breaking any ties randomly. This approach is illustrated in Table 10. After receiving all
subchannel rankings, the network controller compares the capacities reported by each adapter
(fourth column) and sorts the subchannels based on their maximum capacity (fifth column)
among all adapters. The algorithm then goes through the ordered list of subchannels and
allocates them to their best bidder. Once an adapter’s requested throughput is met, the list of
remaining subchannels must be re-sorted based on the capacities reported by those adapters
whose request is still unsatisfied. In the example shown, re-sorting occurs when Adapter Z’s
requested throughput is met by allocating subchannel #8 (sixth column), and when Adapter Y’s
requested throughput is met by allocating subchannel #1 (seventh column).
Table 10. Subchannel allocation by maximizing overall bandwidth efficiency
Adapter X
(requested 25)
Adapter Y
(requested 20)
Adapter Z
(requested 22)
#7: [7] X
#3: [7] Ü
#6: [6] X
#5: [5] Ü
#11: [5] Ü
#8: [5] Ü
#12: [4] Ü
#1: [4] Ü
#10: [3] X
#4: [2] X
#9: [2] X
#2: [2] X
Total allocation: 22
#11: [8] Y
#5: [7] Y
#8: [6] Ü
#3: [6] Ü
#1: [6] Y
#9: [5] Ü
#6: [4] Ü
#10: [3] Ü
#7: [3] Ü
#12: [2] Ü
#2: [1] Ü
#4: [0] Ü
Total allocation: 21
#11: [8] Ü
#3: [8] Z
#12: [8] Z
#8: [7] Z
#4: [6] Ü
#2: [6] Ü
#10: [5] Ü
#9: [4] Ü
#5: [3] Ü
#7: [3] Ü
#6: [3] Ü
#1: [2] Ü
Total allocation: 23
Capacity
Comparison
#1:
#2:
#3:
#4:
#5:
#6:
#7:
#8:
#9:
#10:
#11:
#12:
Progressive
Ordering
Y6,X4,Z2 #3
Z6,X2,Y1 #11
Z8,X7,Y6 #12
Z6,X2,Y0 #5
Y7,X5,Z3 #7
X6,Y4,Z3 #8
X7,Y3,Z3 #1
Z7,Y6,X5 #2
Y5,Z4,X2 #4
Z5,X3,Y3 #6
Y8,Z8,X5 #9
Z8,X4,Y2 #10
-----
Ü
Ü
Ü
Ü
Ü
Ü
Ü
Ü
Ü
Ü
Ü
Ü
#1
#6
#9
#10
#
#4
Ü
#6
#10
#9
#2
#4
This approach guarantees the overall maximization of bandwidth efficiency but
increases the algorithm’s complexity due to multiple comparisons and sorts of subchannel
capacities. In addition, the algorithm is especially unfair for user satisfaction since adapters that
are farther away from the controller will necessarily report lower capacities for all subchannels,
which effectively prevents these adapters from being allocated any of their top-ranked choices.
Adapter X’s allocation, for instance, does not meet its requested throughput. Thus, it is
convenient to trade some bandwidth efficiency for a better chance of satisfying all users.
68
A third, and last, approach attempts to satisfy a larger number of adapters by
equitatively maximizing their bandwidth efficiency. According to this algorithm, the network
controller cycles over the contending adapters allocating the best available subchannel per
round. The resulting allocation from running this algorithm on the sample scenario is shown in
Table 11. On the first round, the controller allocates subchannel #7 to Adapter X, subchannel
#11 to Adapter Y, and subchannel #3 to Adapter Z. The cycle then repeats for as many rounds
as needed to satisfy the throughput request of each adapter.
Table 11. Subchannel allocation by equitative maximization of bandwidth efficiency
Adapter X
(requested 25)
Adapter Y
(requested 20)
Adapter Z
(requested 22)
#7: [7] X
#3: [7] Ü
#6: [6] X
#5: [5] Ü
#11: [5] Ü
#8: [5] X
#12: [4] Ü
#1: [4] X
#10: [3] X
#4: [2] Ü
#9: [2] Ü
#2: [2] Ü
Total allocation: 25
#11: [8] Y
#5: [7] Y
#8: [6] Ü
#3: [6] Ü
#1: [6] Ü
#9: [5] Y
#6: [4] Ü
#10: [3] Ü
#7: [3] Ü
#12: [2] Ü
#2: [1] Ü
#4: [0] Ü
Total allocation: 20
#11: [8] Ü
#3: [8] Z
#12: [8] Z
#8: [7] Ü
#4: [6] Z
#2: [6] Ü
#10: [5] Ü
#9: [4] Ü
#5: [3] Ü
#7: [3] Ü
#6: [3] Ü
#1: [2] Ü
Total allocation: 22
This approach represents a suitable balance between our two measures of goodness. On
one hand, it is fair for user satisfaction since the top-ranked subchannels get equally allocated
among all contending adapters. On the other hand, the algorithm maximizes bandwidth
efficiency sub-optimally by allocating the best subchannel available on each round.
In reality, the network controller is unlikely to receive link requests simultaneously.
Instead, requests are received and processed one at a time. When a single request is received,
the controller will first attempt to satisfy the link requirements using the subchannels that are
available at the time. If the request cannot be satisfied, then the controller will ask all existing
linked adapters to re-measure their subchannels’ SNR to try to satisfy the new request by reallocating subchannels among all existing connections based on the algorithm just described.
69
5.4.3
Special Cases
Since the proposed algorithm is based on the assumption that all link requests are
reasonable, the first step of the algorithm should be to validate this assumption. Attempting to
satisfy an unreasonable request may otherwise monopolize network resources to a single
adapter, thus preventing the satisfaction of most link requests.
However, even if all requests are reasonable it is possible that the current algorithm
may not yield a subchannel allocation that satisfies all link requests. If after running the
algorithm, the network controller determines that an adapter’s request has not been satisfied, it
may attempt to remedy the situation by reallocating subchannels to the affected adapter only if
additional subchannels can be allocated to the donor adapter such as to maintain its current link
satisfaction. A sample scenario is shown in Table 12. Here, the original allocation assigned
only 12 bits to Adapter Z, not meeting its link requirement. However, during the optimization
round, subchannel #11 is reallocated from Adapter Y to Adapter Z only because subchannels
#1 and #10 could also be allocated to Adapter Y in order to maintain its link satisfaction.
Table 12. Optimizing subchannel allocations based on user satisfaction
Adapter X
(requested 18)
Adapter Y
(requested 20)
#7: [7] X
#3: [7] Ü
#6: [6] X
#5: [5] Ü
#11: [5] Ü
#8: [5] X
#12: [4] Ü
#1: [4] Ü
#10: [3] Ü
#4: [2] Ü
#9: [2] Ü
#2: [2] Ü
Total allocation: 18
#11: [8] Y Z
#5: [7]
Y
#8: [6]
Ü
#3: [6]
Ü
#1: [6] Ü <
#9: [5]
Y
#6: [4]
Ü
#10: [3] Ü <
#7: [3]
Ü
#12: [2]
Ü
#2: [1]
Ü
#4: [0]
Ü
Total allocation: 21
:
:
:
Adapter Z
(requested 16)
:
#11: [4] Ü =
#3: [4]
Z
#12: [4]
Z
#8: [3]
Ü
#4: [2]
Z
#2: [2]
Z
#10: [0]
Ü
#9: [0]
Ü
#5: [0]
Ü
#7: [0]
Ü
#6: [0]
Ü
#1: [0]
Ü
Total allocation: 16
If an adapter is still unsatisfied after the optimization stage, the network controller may
choose to either support a communication link with limited throughput or request the affected
adapter to relax its original link requirements.
70
5.5 Link Maintenance
Due to the time-varying nature of the indoor channel environment (see Chapter 3),
several subchannels may experience different levels of fading through the duration of a
communication link. Since fading reduces the SNR, the capacity of allocated subchannels may
need to be periodically adjusted to maintain a specific BER performance.
Fortunately, the indoor channel changes very slowly (see Section 3.1.5), which
facilitates the tractability of the fading profiles for the allocated subchannels. By transmitting a
pilot symbol at the start of each TDD slot, the receiving device may recompute the complex
scaling factor and bit capacity of each subchannel. The new bit capacity may then be sent back
to the transmitting device to adjust the respective throughput of the link.
If the original subchannel allocation was such that it exactly met the requested
throughput, it is conceivable that fading adjustments may reduce the actual throughput of the
link. For this reason, it is recommended that subchannel allocations satisfy a slightly higher
throughput than the one requested to account for some margin of error. From the Rayleigh
fading distribution in Eq. 11, assuming an SNR of 26.5dB at 25 meters, it follows that any
single subchannel will experience a 6% degree of fading on average, so the recommended bit
allocation is 106% the requested throughput.
If actual throughput falls below a predetermined threshold even after taking the
precaution of exceeding the requested throughput, the affected device must issue a new link
request to the controller to regain the desired link performance.
71
Chapter 6 : Software Simulation
Software simulation is an appropriate way of validating the performance of the
proposed WGLAN system design prior to its actual physical implementation. This chapter
describes the simulation model used for system validation before discussing the results of
simulated bit-error rate (BER) performance under different channel conditions.
6.1 Simulation Model
The WGLAN system was simulated using the discrete-time model shown in Figure 24.
Each simulation scenario is characterized by a specific QAM constellation, a channel model,
and SNR-dependent additive white gaussian noise (AWGN). In order to compute the BER for a
particular scenario, bits are randomly generated at the transmitter and modulated onto a single
subchannel using the specified QAM constellation. The digital samples of the respective
OFDM symbol are then convolved with the discrete-time samples of the specified channel
model and corrupted with AWGN according to the specified SNR. OFDM symbols are
continuously generated this way until the receiver detects 100 bit errors, at which point the
BER is given by the ratio of those 100 bit errors and the total number of bits received.
noise
Figure 24. Discrete-time simulation model
P/S
SLICER
+
FFT
channel
S/P
receiver
P/S
IFFT
QAM
S/P
transmitter
The channel model used in each simulation scenario is characterized by a multipath
delay spread, a power delay profile among those presented in Section 3.3, and an interference
pattern from devices sharing the same radio spectrum. Since the channel model is assumed to
have the same characteristics in both directions between the network controller and adapters,
the actual simulation estimates BER performance for a one-way communication link with data
flowing from the controller to an adapter. Due to the one-way links, the simulation model does
not include the proposed TDD scheme.
The simulation model assumes perfect exchange of information through the control
channel when negotiating a communication link. This assumption allows all network devices to
perfectly estimate the scaling factor of each subchannel at the receiver end. Finally, since BER
performance is a function of the channel conditions alone, the simulation model is limited to
the single-user scenario and does not include the subchannel allocation algorithm.
6.2 Software Environment
The simulation model was implemented as a custom-written, object-oriented C++
program. The program consists of five modules: the global header file, main program routine,
and three data abstractions. Since each module is extensively documented in their respective
files, we limit the following exposition to an overview of the contents of each module.
Parameters
Simulator
OfdmSymbol
Adapter
Channel
Figure 25. Module dependency diagram of the simulation program
74
6.2.1
Parameters Header File
The header file
SDUDPHWHUVK
specifies all the system parameter values that
characterize the proposed network design. These parameters include specifications for the
OFDM transceiver, channel models, link budget, coding scheme, and QAM constellations. As
explained next, some parameters were added or modified solely for simulation purposes.
In order to allow each simulation run to finish within a couple of hours when executed
on a Sun Ultra10 workstation, the OFDM transceiver parameters were proportionally scaled
down as shown in Table 13. Since the subchannel bandwidth and guard interval length remain
constant after the proportional scaling, the simulated BER performance is equivalent to the
performance that would be obtained with the original parameter values.
Table 13. Proportional scaling of OFDM transceiver parameters
Parameters
Bandwidth
Oversampling
Subcarriers
Guard samples
Subchannel bandwidth
Guard interval length
Formula
W
L
M
K
W/M
TG = K/LW
Proposed value
100 MHz
4
1,024
200
97.65 kHz
500 ns
Simulated value
12.5 MHz
4
128
25
97.65 kHz
500 ns
In order to compare BER performance at constant power levels, the spacing between
QAM points was scaled to normalize each constellation’s average energy level to 1, or 0dB. By
definition, the points of a QAM constellation are complex numbers, with real and imaginary
parts located at odd integer values in the x- and y-axis respectively. Hence, normalizing an Npoint QAM constellation requires scaling both axes by a factor DMIN that satisfies Eq. 25,
N
Eq. 25
energy = ∑ DMIN ⋅ ( X n + jYn )
2
n =1
N
= ∑ ( DMIN ⋅ X n ) 2 + ( DMIN ⋅ Yn ) 2 = 1
n =1
Finally, the coding parameters are set so that no coding scheme is used. Since the
simulation program supports feature scalability, some of the features provided are intended for
future work and so they were not utilized during the final stages of this thesis.
75
6.2.2
Simulator Program File
The file
VLPXODWRUFSS
provides the user interface of the simulation program and
implements the actual subroutines that handle the data abstractions involved in a specific
simulation scenario. The user menu of the simulator includes three options for testing the
implementation of the different data abstractions, and three options for computing single-user
BER performance under different simulation scenarios as described next.
Static Channel Scenario
In this scenario the channel model is time-invariant, that is, once its power delay profile
is characterized by a specific channel variance and shape, the profile remains unchanged during
the entire simulation run. This scenario requires that the network controller first transmit a
single pilot symbol when the communication link is initiated, and then transmit consecutive
OFDM data symbols until the specified number of bit errors is reached at the receiver end.
Dynamic Channel Scenario
This scenario assumes a time-variant channel model where the channel variance of a
specific power delay profile is randomly changed between the limits declared in
SDUDPHWHUVK
at the rate instructed by the user. For a nominal rate of change of 10 Hz, for instance, this
implies that the channel variance is changed every 100ms. This scenario is especially useful to
simulate the effects of fading on different subchannels.
In order to determine how often the channel should change, a time reference is
established by counting the number of OFDM symbols that have been transmitted so far given
that they all have a constant duration of 10.74µs. Due to the implicit subchannel fading, this
scenario requires the network controller to re-train the receiving adapter by transmitting a pilot
symbol at the start of every TDD slot. The length of a TDD slot is measured in units of OFDM
symbols, as specified in the header file SDUDPHWHUVK.
76
Interference Channel Scenario
This scenario builds upon the dynamic channel scenario by including an FHSS
interferer that uses 1 MHz wide subchannels and hops at a rate of 1600 hops/sec. Such an
interference pattern resembles the impulse noise provided by a Bluetooth network whose
operating frequency overlaps that of the WGLAN. The average energy was normalized to the
average energy of a QAM constellation, that is, to 0dB.
6.2.3
Data Abstraction Files
The actual manipulation of bits, QAM points, and discrete-time samples relies on the
three data abstractions OfdmSymbol, Channel, and Adapter. Each of these data abstractions
encapsulates the state and functionality of the respectively-named network entity.
OfdmSymbol Class
The
OfdmSymbol
2IGP6\PEROFSS
class,
implemented
by
the
files
2IGP6\PEROK
and
, encapsulates the entire signal processing on an OFDM symbol as it is
transmitted and received by different devices on the network. The information contained on
each instantiation of the OfdmSymbol class is used on the receiver end to compute error
statistics for each OFDM symbol with respect to bits or QAM points.
Channel Class
The Channel class, implemented by the files
FKDQQHOK
and
FKDQQHOFSS
,
encapsulates the power delay profile of the channel that links two devices. An instantiation of
the Channel class provides discrete-time samples of the channel model, which are generated by
choosing the variance of a specific power delay profile and then sampling the profile at the rate
determined by the parameters contained in SDUDPHWHUVK
77
This class also provides several methods to change the channel model by specifying a
different channel variance, different delay profile, or a combination of both. Fading effects are
built into the simulation scenario by changing the channel model as a function of time.
Adapter Class
The Adapter class, implemented by the files
DGDSWHUK
and
DGDSWHUFSS
,
encapsulates the digital signal processor contained in each network device. This class
implements the different signal processing steps that are performed on an OFDM symbol by the
transmitter and receiver architectures shown in Figure 18 and Figure 19.
Each instantiation of the Adapter class has an associated Channel instantiation. The
Adapter class provides methods to change several parameters of the channel, which models the
characteristics of the link between the network controller and a network adapter.
The Adapter class also specifies how to map blocks of bits onto QAM constellations. In
general, since AWGN confines most symbol errors to adjacent points in a QAM constellation,
the bit error rate is reduced by selecting a bit mapping so that adjacent constellation points
differ by the minimum possible number of bits in one dimension.
In the case of even power-of-two constellations, the optimum bit mapping is a Graylike encoding where adjacent constellations points differ by exactly one bit in one dimension.
However, in the case of odd power-or-two constellations, the bit mapping is sub-optimal since
adjacent constellations points may differ by one, two, or even three bits in one dimension. For
this reason, a QAM-point error in an even power-of-two constellation is more likely to result in
a single bit error than in the case of odd power-of-two constellations.
78
6.3 Simulation Scenarios and Results
The first step in the simulation process was to verify the correct implementation of the
simulator. This was done at a class-level by providing test subroutines for each of the data
abstractions. A system-level verification was done by computing the BER performance for an
ideal channel model, i.e. a Dirac-delta function with AWGN. The result of the simulation is
shown in Figure 26, which compares well with the expected theoretical performance [4].
As shown in Figure 26, larger QAM constellations require a higher SNR than smaller
constellations to achieve a target BER. For a BER of 10-3, the required SNR of progressively
larger constellations increases by roughly 3dB. The careful reader may notice that the BER
curve for 8-QAM has a slightly different profile than all other curves. This is caused by the
sub-optimality of odd power-of-two constellations, which is most evident in 8-QAM due to the
1.E+00
Bit Error Rate
1.E-01
1.E-02
1.E-03
1.E-04
Signal-to-Noise Ratio (dB)
2-QAM
4-QAM
128-QAM
256-QAM
8-QAM
16-QAM
32-QAM
Figure 26. BER performance for ideal channel model
79
64-QAM
30
28
26
24
22
20
18
16
14
12
10
8
6
4
2
0
sparse spreading of constellation points with respect to its average level of energy.
6.3.1
Static Channel Scenarios
This scenario estimates the BER performance of time-invariant power delay profiles
characterized by a worst-case delay spread of 60ns, as determined in Section 3.2.3. Since the
BER performance across different constellation sizes has similar profiles, the following three
sections only consider the simulation results of 64-QAM for comparison purposes.
As shown in Figure 27, at a BER of 10-3, the Gaussian model requires an additional
2.5dB of SNR than the ideal model, while the Exponential model requires an additional 4dB,
and the Double-Spike model fails to converge fast enough.
In general, the Gaussian and Exponential models are better approximations to the actual
power delay profile of the indoor multipath channel, and so their BER performance is a more
representative figure. Since the Double-Spike model is a limiting case profile of the physical
1.E+00
Bit Error Rate
1.E-01
1.E-02
1.E-03
1.E-04
Signal-to-Noise Ratio (dB)
Ideal
Gaussian
Exponential
Double-Spike
Figure 27. BER performance for 64-QAM static channel models
80
28
26
24
22
20
18
16
14
12
10
8
6
4
2
0
channel, its BER performance tends to reflect excessively poor results.
6.3.2
Dynamic Channel Scenarios
This scenario estimates the BER performance of time-variant power delay profiles
whose variance is randomly changed in the 40ns-60ns range every 100ms. This rate of change
is based on the 10 Hz Doppler spread reported in Section 3.1.5
As shown in Figure 28, at a BER of 10-3 the Gaussian model requires 2dB of additional
SNR than the ideal model, while the Exponential model requires an additional 3dB, and the
Double-Spike model requires an additional 5dB.
In general, the BER performance in the dynamic channel scenario is better than in the
static channel scenario because the channel variance deviates below its worst-case value. The
random changes in channel variance also explain the occasional intersections among the BER
curves of different power delay profiles since at those intersection points different models may
1.E+00
Bit Error Rate
1.E-01
1.E-02
1.E-03
1.E-04
Signal-to-Noise Ratio (dB)
Ideal
Gaussian
Exponential
Double-Spike
Figure 28. BER performance for 64-QAM dynamic channel models
81
28
26
24
22
20
18
16
14
12
10
8
6
4
2
0
have simultaneously considered the best- and worst-case variance of the channel.
6.3.3
Interference Channel Scenarios
This scenario estimates the BER performance of time-variant channel models as in
Section 6.3.2 with the addition of a 1 MHz wide FHSS interferer hopping at a rate of 1600
hops/sec. In this case, the interferer’s parameters resemble those of a Bluetooth device.
As shown in Figure 29, none of the BER curves for the three channel models proposed
reaches the 10-3 level in the interference scenario. This is attributed to the lack of an errorcorrecting scheme in the proposed OFDM system. In this case, the FHSS interferer resembles
impulse noise that corrupts OFDM symbols unexpectedly, resulting in a BER performance that
is poor and unpredictable.
Future work on the WGLAN system should include error-correcting codes and symbol
1.E+00
Bit Error Rate
1.E-01
1.E-02
1.E-03
1.E-04
Signal-to-Noise Ratio (dB)
Ideal
Gaussian
Exponential
Double-Spike
Figure 29. BER performance for 64-QAM interference channel models
82
28
26
24
22
20
18
16
14
12
10
8
6
4
2
0
interleaving to improve the BER performance in an impulse-noise environment.
6.3.4
Subchannel Capacity Estimation
According to the previous simulation results, the exponential power delay profile is a
suitably conservative model for estimating the BER performance of the network. For this
reason, Figure 30 shows the BER curves for the static exponential channel scenario as an
indicator of worst-case performance in an interferer-free environment. This information is used
in Table 14 to summarize the minimum SNR needed to achieve a specific BER for each
available constellation size. These thresholds are used by all network devices to estimate the
capacity of each subchannel as explained in Section 5.4.2
Table 14. Minimum SNR needed to achieve a target BER for different constellation sizes
32
30
26
256-QAM
22dB
26dB
30dB
31dB
33dB
28
128-QAM
20dB
23dB
27dB
28dB
29dB
24
22
64-QAM
17dB
20dB
24dB
25dB
27dB
20
18
16
32-QAM
15dB
18dB
20dB
21dB
23dB
14
12
16-QAM
12dB
14dB
18dB
19dB
21dB
10
8
8-QAM
10dB
12dB
16dB
17dB
18dB
6
4
4-QAM
6dB
8dB
11dB
12dB
14dB
2
2-QAM
3dB
5dB
8dB
9dB
11dB
0
BER
1•10-1
5•10-2
1•10-2
5•10-3
1•10-3
Bit Error Rate
1.E+00
1.E-01
1.E-02
1.E-03
1.E-04
Signal-to-Noise Ratio (dB)
2-QAM
4-QAM
8-QAM
16-QAM
32-QAM
64-QAM
128-QAM
Figure 30. BER performance for exponential channel models
83
256-QAM
Chapter 7 : Conclusion
Starting with the premise of the Next Generation Internet, this thesis pursued the
physical layer digital signal processing design of an indoor Wireless Gigabit Local-Area
Network (WGLAN) capable of approaching gigabit-per-second (Gbps) data transmission rates.
The WGLAN topology consists of a single network controller that is the gateway
between the NGI and the local-area network, and multiple network adapters connected to enduse devices. The WGLAN supports real-time bidirectional communication between pairs of
network devices at variable data rates and quality of service, through the bandwidth-efficient
allocation of subchannels among competing communication links.
Several system-wide design tradeoffs were evaluated in this thesis following a bottomup methodology. First, we analyzed the characteristics of the indoor channel environment, next
we proposed an adaptive modulation-demodulation technique, then we presented a suitable
multiple access scheme, and finally we simulated the BER performance of the network.
7.1 Channel Characteristics
The WGLAN uses the 100 MHz of radio spectrum centered at 5.3 GHz that is available on an
unlicensed basis to National Information Infrastructure (U-NII) devices. The parameters that
characterize the multipath propagation of the indoor channel environment at 5.x GHz have been
extensively analyzed in the public literature, and are summarized in Table 15.
Table 15. 5.x GHz indoor channel parameters.
Parameter
Worst-case delay spread
Worst-case time dispersion
Minimum coherence bandwidth
Typical path loss exponent
Variable
2rms
Tm
Bcoh
n
Value
60ns
360ns
2.778 MHz
4
The indoor radio channel is an adverse communication channel characterized by
multiple propagation paths. Based on the reported worst-case delay spread, the indoor
multipath channel was modeled by three power delay profiles whose shapes resemble those of
one-sided Gaussian, Exponential, and Double-Spike distributions. These models assumed a
slowly varying channel with a Doppler spread reportedly below 10 Hz.
Finally, the channel characterization also included a link budget that outlined the power
gains and loses in the communication link so as to achieve a maximum channel capacity of 8
bps/Hz for each subchannel at a worst-case transmitter-receiver separation of 25 meters.
7.2 Modulation and Demodulation
Due to the multipath nature of indoor channels, it is convenient to divide the 100 MHz
of available spectrum into many parallel subchannels. If each subchannel’s bandwidth is less
than Bcoh, then the power spectral density of each subchannel can be assumed to be flat at the
receiver, or equivalently, each subchannel experiences frequency nonselective fading that can
be undone on the receiver end without using cumbersome equalizing techniques.
The multicarrier modulation of choice is Orthogonal Frequency Division Multiplexing
(OFDM). The advantages of OFDM over conventional FDM are the efficient use of the
spectrum and the digital implementation of frequency division through baseband processing.
The system parameters of the proposed OFDM system are summarized in Table 16.
86
Table 16. OFDM system parameter.
Variable Name
W
L
M
TB
TG
TS
Meaning
Support bandwidth
Oversampling factor
Number of subchannels
Length of original OFDM block
Length of guard interval (cyclic prefix)
Length of guarded OFDM symbol
Value Chosen
100 MHz
4
1,024 carriers
10.24µs
500ns
10.74µs
The proposed OFDM scheme uses adaptive Quadrature Amplitude Modulation (QAM)
to approach bandwidth efficiency. According to this technique, the constellation size of each
subchannel is determined based on the signal-to-noise ratio of each subchannel. The supported
constellation sizes are increments of power-of-two in the range of 2- to 256-level QAM.
7.3 Multiple Access Scheme
The WGLAN topology resembles a star-like configuration where bidirectional
communication
is
supported
between any controller-adapter
or
adapter-adapter
pair.
Bidirectional communication is accomplished through Time Division Duplexing (TDD), a
technique where the network controller and existing adapters take alternate turns to transmit
and receive information on their communication link.
The proposed multiple access scheme defines a control channel and several data
channels consisting of different groupings of OFDM subchannels. The WGLAN negotiates
communication links through the control channel, and supports multiple simultaneous links by
allocating different data subchannels among users. This scheme also provides the negotiation
protocols for establishing communication links based on three different types of requests.
Once the network controller has gathered the necessary information from each link
request, it proceeds to allocate data subchannels according to an equitative maximization of
bandwidth efficiency among devices. Such an allocation maximizes the probability of
satisfying all network users while making efficient use of the network resources.
87
7.4 Simulation and Future Work
The BER performance of the proposed WGLAN design was simulated in software and
shown to meet a 10-3 level within acceptable SNR constraints. As summarized in Table 17, the
exponential static channel scenario results were used to determine the minimum SNR needed to
achieve a specific BER for different constellation sizes.
Table 17. SNR thresholds for a given BER and constellation size
BER
1· 10-1
5· 10-2
1· 10-2
5· 10-3
1· 10-3
2-QAM
3dB
5dB
8dB
9dB
11dB
4-QAM
6dB
8dB
11dB
12dB
14dB
8-QAM
10dB
12dB
16dB
17dB
18dB
16-QAM
12dB
14dB
18dB
19dB
21dB
32-QAM
15dB
18dB
20dB
21dB
23dB
64-QAM
17dB
20dB
24dB
25dB
27dB
128-QAM
20dB
23dB
27dB
28dB
29dB
256-QAM
22dB
26dB
30dB
31dB
33dB
However, the BER performance of the network was shown to be unpredictable in the
presence of impulse-noise caused by a frequency-hopping interferer. For this reason, future
work on the WGLAN should consider the addition of error-correcting codes as well as symbol
interleaving [4] to reduce the impact of impulse-noise on BER performance.
Finally, the next step on the WGLAN project is the actual implementation of the
network, which may introduce a new set of tradeoffs depending on hardware limitations with
respect to analog constraints or digital computation power.
88
Bibliography
Digital Communications
[1] Geier, Jim. Wireless LANs. Macmillan Technical Publishing. 1999.
[2] Gibson, Jerry D. (editor). The Mobile Communications Handbook. IEEE Press. 1996.
[3] Proakis, John G. and Salehi, Masoud. Communication Systems Engineering. Upper Saddle
River, NJ: Prentice Hall. 1994.
[4] Proakis, John G. Digital Communications. McGraw-Hill. 3rd Edition, 1995.
[5] Shapiro, Jeffrey; Willsky, Alan; and Wornell, Gregory. Stochastic Processes, Detection,
and Estimation. MIT 6.432 Course Notes. Cambridge, MA. Fall 1999.
[6] Sklar, Bernard. Digital Communications: Fundamentals and Applications. Englewood
Cliffs, NJ: Prentice Hall. 1988.
[7] Starr, Thomas; Cioffi, John; Silverman, Peter. Understanding Digital Subscriber Line
Technology. Upper Saddle River, NJ: Prentice Hall. 1999.
Regulations and Standards
[8] European Telecommunications Standards Institute. BRAN and HIPERLAN Type 1
Functional Specification. European Standard EN 300 652 v1.2.1, July 1998.
[9] Federal Communications Commission. Ammendment of the Commision’s Rules to Provide
for Operation of Unlicensed NII Devices in the 5 GHz Frequency Range. Report and Order
FCC 97-5, released January 1997.
[10]
Federal Communications Commission. Title 47 CFR Part 15 and 18.
[11]
Institute of Electrical and Electronic Engineers. Wireless LAN Medium Access Control
(MAC) and Physical Layer (PHY) specifications. IEEE Standard 802.11-1997.
[12]
The Bluetooth Special Interest Group. Specification of the Bluetooth System. Dec. 1999
Wireless Local-Area Networks
[13]
Johnson, I.R. and Barton, S.K. “Standards for Wireless LANs,” IEE Colloquium on
Wireless Technology, Digest No. 1996/199, pp. 5/1-5/5, 1996.
[14]
Pahlavan, Kaveh and Falsafi, Aram. “Trends in Local Wireless Data Networks,” 46th
IEEE Vehicular Technology Conference, vol. 1, pp. 21-25, 1996.
[15]
Pasmooij, Laurie F. “Wireless LANs: Worldwide Market Review and Forecast, 1997-
2003”. International Data Corporation, document no. 16377, 1998.
[16]
Proxim Inc. “What is a Wireless LAN?” White paper, March 1998.
[17]
Weste, N.; Skellern, D.; Percival, T. “Broadband U-NII Wireless Data,” Proceedings
of the 11th International Conference on VLSI Design, pp. 72-77, 1998.
[18]
Wickelgren, Ingrid J. “Local-Area Networks Go Wireless,” IEEE Spectrum, pp. 34-40,
September 1996.
Indoor Channel Characterization
[19]
Bello, P.A. and Nelin, B.D. “The effect of frequency selective fading on the binary
error probability of incoherent and differentially coherent matched filter receivers,” IEEE
Transactions on Communication Systems, vol. CS-11, pp. 170-186, June 1963.
[20]
Bergljung, Christian and Karlsson, Peter. “Propagation Characteristics for Indoor
Broadband Radio Access Networks in the 5 GHz Band,” 9th IEEE International Symposium
on Personal, Indoor and Mobile Radio Communications, vol. 2, pp. 612-616, 1998.
[21]
Durgin, Greg; Rappaport, Theodore S.; Xu, Hao. “Measurements and Models for Radio
Path Loss and Penetration Loss In and Around Homes and Trees at 5.85 GHz,” IEEE
Transactions on Communications, vol. 46, pp. 1484-1496, November 1998.
[22]
Fleury, Bernard H. “An Uncertainty Relation for WSS Processes and Its Application to
WSSUS Systems,” IEEE Transactions on Communications, vol. 44, pp. 1632-1634,
December 1996.
[23]
Glance, Bernard and Greenstein, Larry J. “Frequency-Selective Fading Effects in
Digital Mobile Radio with Diversity Combining,” IEEE Transactions on Communications,
vol. 31, pp. 1085-1094, September 1983.
90
[24]
Guerin, S.; Guo, Y.J.; Barton, S.K. “Indoor Propagation Measurements at 5 GHz for
HIPERLAN,” IEEE 10th International Conference on Antennas and Propagation, publ. no.
436, vol. 2, pp. 306-310, 1997.
[25]
Hafezi, P.; Wedge, D.; Beach, M.A.; Lawton, M. “Propagation Measurements at 5.2
GHz in Commercial and Domestic Environments,” 8th IEEE International Symposium on
Personal, Indoor and Mobile Radio Communications, vol. 2, pp. 509-513, 1997.
[26]
Hashemi, Homayoun and Tholl, David. “Analysis of the RMS Delay Spread of Indoor
Radio Propagation Channels,” IEEE International Conference on Communications, vol. 2,
pp. 875-881, 1992.
[27]
Hashemi, Homayoun; Tholl, David; Morrison, Gerald. “Statistical Modeling of the
Indoor Radio Propagation Channel, Part I & II,” 42nd IEEE Vehicular Technology
Conference, vol.1 pp.338-342 and vol. 2 pp.839-843, 1992.
[28]
Heddergott, R.; Bernhard, U.P.; Fleury, B.H. “Stochastic Radio Channel Model for
Advanced Indoor Mobile Communication Systems,” 8th IEEE International Symposium on
Personal, Indoor and Mobile Radio Communications, vol. 1, pp. 140-144, 1997.
[29]
Howard, S.J. and Pahlavan, K. “Doppler Spread Measurements of Indoor Radio
Channel,” Electronics Letters, vol. 26, pp. 107-109, January 18th, 1990.
[30]
Howard, Steven J. and Pahlavan, Kaveh. “Measurement and Analysis of the Indoor
Radio Channel in the Frequency Domain,” IEEE Transactions on Instrumentation and
Measurement, vol. 39, pp. 751-755, October 1990.
[31]
Huang, Chia-Chi and Khayata, Rana. “Delay Spreads and Channel Dynamics
Measurements at ISM Bands,” IEEE International Conference on Communications, vol. 3,
pp. 1222-1226, 1992.
[32]
Janssen, Gerard J.M.; Stigter, Patrick A.; Prasad, Ramjee. “Wideband Indoor Channel
Measurements and BER Analysis of Frequency Selective Multipath Channels at 2.4, 4.75,
and 11.5 GHz,” IEEE Transactions on Communications, vol. 44, pp. 1272-1288, Oct 1996.
[33]
Layer, Frank; Kattenbach, Ralf; Fruchting, Henning. “Modeling and Analysis of
Dominant Propagation Effects in Real Indoor Environment at 5.2 GHz,” 9th IEEE
International Symposium on Personal, Indoor and Mobile Radio Communications, vol. 2,
pp. 630-634, 1998.
91
[34]
Louzir, A.; Aemamra, A.; Harrison, D.; Howson, C. “Spatial Characterisation of Single
Room Indoor Propagation at 5.8 GHz,” IEEE Antennas and Propagation Society
International Symposium, vol. 1, pp. 518-521, 1995.
[35]
McDonnell, J.T. Edward. “5 GHz Indoor Channel Characterization: Measurements and
Models,”
IEE
Colloquium
on
Antennas
and
Propagation
for
Future
Mobile
Communications, ref. No. 1998/219, pp. 10/1-10/6, 1998.
[36]
McDonnell, J.T. Edward; Spiller, T.P.; Wilkinson, T.A. “Characterization of the Spatial
Distribution of RMS Delay Spread in Indoor LOS Wireless Environments at 5.2 GHz,”
IEEE 9th International Symposium on Personal, Indoor and Mobile Radio Communications,
vol. 2, pp. 621-624, 1998.
[37]
Nobles, P.; Ashworth, D.; Halsall, F. “Indoor Radiowave Propagation Measurements at
Frequencies up to 20 GHz,” IEEE 44th Vehicular Technology Conference, vol. 2, pp. 873877, 1994.
[38]
Nobles, P.; Halsall, F. “Delay Spread and Received Power Measurements within a
Building at 2 GHz, 5 GHz, and 17 GHz,” 10th IEEE International Conference on Antennas
and Propagation, publ. no. 436, vol. 2, pp. 319-324, 1997.
[39]
Plattner, A.; Prediger, N.; Herzig, W. “Indoor and Outdoor Propagation Measurements
at 5 and 60 GHz for Radio LAN Application,” IEEE MTT-S International Microwave
Symposium Digest, vol. 2, pp. 853-856, 1993.
[40]
Rappaport, Theodore S.; Muhamed, Rias; Kapoor, Varun. “Propagation Models,” The
Mobile Communications Handbook, CRC Press, pp. 355-369, 1996.
[41]
Saleh, Adel A.M. and Valenzuela, Reinaldo A. “A Statistical Model for Indoor
Multipath Propagation,” IEEE Journal on Selected Areas in Communications, vol. 5, pp.
128-137, February 1987.
[42]
Takeuchi, Tsutomu; Sako, Masahiro; Yoshida, Susumu. “Multipath Delay Estimation
for Indoor Wireless Communication,” IEEE 40th Vehicular Technology Conference, pp.
401-406, 1990.
92
Orthogonal Frequency Division Multiplexing
[43]
Akansu, Ali N.; Duhamel, Pierre; Lin, Xueming; de Courville, Marc. “Orthogonal
Transmultiplexers in Communication: A Review,” IEEE Transactions on Signal
Processing, vol. 46, pp. 979-995, April 1998.
[44]
Bingham, John A.C. “Multicarrier Modulation for Data Transmission: An Idea Whose
Time Has Come,” IEEE Communications Magazine, vol. 28, pp. 5-14, May 1990.
[45]
Castle, R.; Jones, A. “A 20 Mbits/s OFDM Demonstrator at 5 GHz: System Design,
Implementation and Experimental Results,” 48th IEEE Vehicular Technology Conference,
vol. 2, pp. 1295-1299, 1998.
[46]
Jeon, Won Gi; Chang, Kyung Hi; Cho, Yong Soo. “An Equalization Technique for
Orthogonal
Frequency-Division
Multiplexing
Systems
in
Time-Variant
Multipath
Channels,” IEEE Transactions on Communications, vol. 47, pp. 27-32, January 1999.
[47]
O'Neill, Rorie and Lopes, Luis B. “A Study of Novel OFDM Transmission Schemes for
Use in Indoor Environments,” 46th IEEE Vehicular Technology Conference, vol. 2, pp. 909913, 1996.
[48]
Vahlin, Anders and Holte, Nils. “Optimal Finite Duration Pulses for OFDM,” IEEE
Transactions on Communications, vol. 44, pp. 10-14, January 1996.
[49]
Zhao, Yuping and Huang, Aiping. “A Novel Channel Estimation Method for OFDM
Mobile Communication Systems
Based on Pilot
Signals
and Transform-Domain
Processing,” 47th IEEE Vehicular Technology Conference, vol. 3, pp. 2089-2093, 1997.
Digital Subscriber Line Technology
[50]
Chow, Jacky S.; Tu, Jerry C.; Cioffi, John M. “A Discrete Multitone Transceiver
System for HDSL Applications,” IEEE Journal on Selected Areas in Communications, vol.
9, pp. 895-908, August 1991.
[51]
Chow, Peter S.; Cioffi, John M.; Bingham, John A.C. “DMT-Based ADSL: Concept,
Architecture, and Performance,” IEE Colloquium on High Speed Access Technology and
Services, digest no. 1994/192, pp. 3/1-3/6, 1994.
93
[52]
Hawryluck, M.; Yongacoglu, A.; Kavehrad, M. “Simulation of a FFT Based Multi-
Carrier System for ADSL and VDSL Transmission,” 3rd IEEE Symposium on Computers
and Communications, pp. 537-542, 1998.
[53]
Jackson, Al. “ADSL for High-Speed Broadband Data Service,” IEEE Aerospace
Conference, vol. 4, pp. 451-465, 1998.
[54]
Jones,
E.V.
“Asymmetric
Digital
Subscriber
Line (ADSL)
Systems
–
An
Introduction,” IEE Colloquium on High Speed Access Technology and Services, digest no.
1994/192, pp. 1/1-1/8, 1994.
[55]
Kyees, Philip J.; McConnell, Ronald C.; Sistanizadeh, Kamran. “ADSL: A New
Twisted-Pair Access to the Information Highway,” IEEE Communications Magazine, vol.
33, pp. 52-60, April 1995.
Miscellaneous
[56]
TMS32C6000 Assembly Benchmarks at Texas Instruments,
http://www.ti.com/sc/docs/products/dsp/c6000/benchmarks/62x.htm#fft
[57]
U.S. President William J. Clinton. “State of the Union Address.” February, 1997.
94
Appendix I:
Simulation Results
12
10
8
6
4
2
0
2-QAM Static Channel Scenario
Bit Error Rate
1.E+00
1.E-01
1.E-02
1.E-03
1.E-04
Signal-to-Noise Ratio (dB)
Ideal
Gaussian
Exponential
Double-Spike
Bit Error Rate
1.E+00
1.E-01
1.E-02
1.E-03
1.E-04
Signal-to-Noise Ratio (dB)
Ideal
Gaussian
Exponential
Double-Spike
12
10
8
6
4
2
0
2-QAM Dynamic Channel Scenario
12
10
8
6
4
2
0
2-QAM Interference Channel Scenario
Bit Error Rate
1.E+00
1.E-01
1.E-02
1.E-03
1.E-04
Signal-to-Noise Ratio (dB)
Ideal
Gaussian
Exponential
Double-Spike
Bit Error Rate
1.E+00
1.E-01
1.E-02
1.E-03
1.E-04
Signal-to-Noise Ratio (dB)
Ideal
Static
97
Dynamic
Interference
10
8
6
4
2
0
2-QAM Exponential Channel Comparison
14
12
10
8
6
4
2
0
4-QAM Static Channel Scenario
Bit Error Rate
1.E+00
1.E-01
1.E-02
1.E-03
1.E-04
Signal-to-Noise Ratio (dB)
Ideal
Gaussian
Exponential
Double-Spike
Bit Error Rate
1.E+00
1.E-01
1.E-02
1.E-03
1.E-04
Signal-to-Noise Ratio (dB)
Ideal
Gaussian
98
Exponential
Double-Spike
14
12
10
8
6
4
2
0
4-QAM Dynamic Channel Scenario
14
12
10
8
6
4
2
0
4-QAM Interference Channel Scenario
Bit Error Rate
1.E+00
1.E-01
1.E-02
1.E-03
1.E-04
Signal-to-Noise Ratio (dB)
Ideal
Gaussian
Exponential
Double-Spike
Bit Error Rate
1.E+00
1.E-01
1.E-02
1.E-03
1.E-04
Signal-to-Noise Ratio (dB)
Ideal
Static
99
Dynamic
Interference
12
10
8
6
4
2
0
4-QAM Exponential Channel Comparison
18
16
14
12
10
8
6
4
2
0
8-QAM Static Channel Scenario
Bit Error Rate
1.E+00
1.E-01
1.E-02
1.E-03
Signal-to-Noise Ratio (dB)
Ideal
Gaussian
Exponential
Double-Spike
Bit Error Rate
1.E+00
1.E-01
1.E-02
1.E-03
Signal-to-Noise Ratio (dB)
Ideal
Gaussian
100
Exponential
Double-Spike
18
16
14
12
10
8
6
4
2
0
8-QAM Dynamic Channel Scenario
18
16
14
12
10
8
6
4
2
0
8-QAM Interference Channel Scenario
Bit Error Rate
1.E+00
1.E-01
1.E-02
1.E-03
Signal-to-Noise Ratio (dB)
Ideal
Gaussian
Exponential
Double-Spike
Bit Error Rate
1.E+00
1.E-01
1.E-02
1.E-03
Signal-to-Noise Ratio (dB)
Ideal
Static
101
Dynamic
Interference
16
14
12
10
8
6
4
2
0
8-QAM Exponential Channel Comparison
20
22
20
22
18
16
14
12
10
8
6
4
2
0
16-QAM Static Channel Scenario
Bit Error Rate
1.E+00
1.E-01
1.E-02
1.E-03
1.E-04
Signal-to-Noise Ratio (dB)
Ideal
Gaussian
Exponential
Double-Spike
18
16
14
12
10
8
6
4
2
0
16-QAM Dynamic Channel Scenario
Bit Error Rate
1.E+00
1.E-01
1.E-02
1.E-03
1.E-04
Signal-to-Noise Ratio (dB)
Ideal
Gaussian
102
Exponential
Double-Spike
22
20
18
16
14
12
10
8
6
4
2
0
16-QAM Interference Channel Scenario
Bit Error Rate
1.E+00
1.E-01
1.E-02
1.E-03
1.E-04
Signal-to-Noise Ratio (dB)
Ideal
Gaussian
Exponential
Double-Spike
Bit Error Rate
1.E+00
1.E-01
1.E-02
1.E-03
1.E-04
Signal-to-Noise Ratio (dB)
Ideal
Static
103
Dynamic
Interference
20
18
16
14
12
10
8
6
4
2
0
16-QAM Exponential Channel Comparison
24
26
24
26
22
20
18
16
14
12
10
8
6
4
2
0
32-QAM Static Channel Scenario
Bit Error Rate
1.E+00
1.E-01
1.E-02
1.E-03
1.E-04
Signal-to-Noise Ratio (dB)
Ideal
Gaussian
Exponential
Double-Spike
22
20
18
16
14
12
10
8
6
4
2
0
32-QAM Dynamic Channel Scenario
Bit Error Rate
1.E+00
1.E-01
1.E-02
1.E-03
1.E-04
Signal-to-Noise Ratio (dB)
Ideal
Gaussian
104
Exponential
Double-Spike
24
26
22
24
22
20
18
16
14
12
10
8
6
4
2
0
32-QAM Interference Channel Scenario
Bit Error Rate
1.E+00
1.E-01
1.E-02
1.E-03
1.E-04
Signal-to-Noise Ratio (dB)
Ideal
Gaussian
Exponential
Double-Spike
Bit Error Rate
1.E+00
1.E-01
1.E-02
1.E-03
1.E-04
Signal-to-Noise Ratio (dB)
Ideal
Static
105
Dynamic
Interference
20
18
16
14
12
10
8
6
4
2
0
32-QAM Exponential Channel Comparison
26
28
26
28
24
22
20
18
16
14
12
10
8
6
4
2
0
64-QAM Static Channel Scenario
Bit Error Rate
1.E+00
1.E-01
1.E-02
1.E-03
1.E-04
Signal-to-Noise Ratio (dB)
Ideal
Gaussian
Exponential
Double-Spike
24
22
20
18
16
14
12
10
8
6
4
2
0
64-QAM Dynamic Channel Scenario
Bit Error Rate
1.E+00
1.E-01
1.E-02
1.E-03
1.E-04
Signal-to-Noise Ratio (dB)
Ideal
Gaussian
106
Exponential
Double-Spike
28
26
24
22
20
18
16
14
12
10
8
6
4
2
0
64-QAM Interference Channel Scenario
Bit Error Rate
1.E+00
1.E-01
1.E-02
1.E-03
1.E-04
Signal-to-Noise Ratio (dB)
Ideal
Gaussian
Exponential
Double-Spike
Bit Error Rate
1.E+00
1.E-01
1.E-02
1.E-03
1.E-04
Signal-to-Noise Ratio (dB)
Ideal
Static
107
Dynamic
Interference
26
24
22
20
18
16
14
12
10
8
6
4
2
0
64-QAM Exponential Channel Comparison
28
30
32
28
30
32
26
24
22
20
18
16
14
12
10
8
6
4
2
0
128-QAM Static Channel Scenario
Bit Error Rate
1.E+00
1.E-01
1.E-02
1.E-03
1.E-04
Signal-to-Noise Ratio (dB)
Ideal
Gaussian
Exponential
Double-Spike
26
24
22
20
18
16
14
12
10
8
6
4
2
0
128-QAM Dynamic Channel Scenario
Bit Error Rate
1.E+00
1.E-01
1.E-02
1.E-03
1.E-04
Signal-to-Noise Ratio (dB)
Ideal
Gaussian
108
Exponential
Double-Spike
30
32
28
30
28
26
24
22
20
18
16
14
12
10
8
6
4
2
0
128-QAM Interference Channel Scenario
Bit Error Rate
1.E+00
1.E-01
1.E-02
1.E-03
1.E-04
Signal-to-Noise Ratio (dB)
Ideal
Gaussian
Exponential
Double-Spike
Bit Error Rate
1.E+00
1.E-01
1.E-02
1.E-03
1.E-04
Signal-to-Noise Ratio (dB)
Ideal
Static
109
Dynamic
Interference
26
24
22
20
18
16
14
12
10
8
6
4
2
0
128-QAM Exponential Channel Comparison
32
34
32
34
30
28
26
24
22
20
18
16
14
12
10
8
6
4
2
0
256-QAM Static Channel Scenario
Bit Error Rate
1.E+00
1.E-01
1.E-02
1.E-03
1.E-04
Signal-to-Noise Ratio (dB)
Ideal
Gaussian
Exponential
Double-Spike
30
28
26
24
22
20
18
16
14
12
10
8
6
4
2
0
256-QAM Dynamic Channel Scenario
Bit Error Rate
1.E+00
1.E-01
1.E-02
1.E-03
1.E-04
Signal-to-Noise Ratio (dB)
Ideal
Gaussian
110
Exponential
Double-Spike
32
34
30
32
30
28
26
24
22
20
18
16
14
12
10
8
6
4
2
0
256-QAM Interference Channel Scenario
Bit Error Rate
1.E+00
1.E-01
1.E-02
1.E-03
1.E-04
Signal-to-Noise Ratio (dB)
Ideal
Gaussian
Exponential
Double-Spike
Bit Error Rate
1.E+00
1.E-01
1.E-02
1.E-03
1.E-04
Signal-to-Noise Ratio (dB)
Ideal
Static
111
Dynamic
Interference
28
26
24
22
20
18
16
14
12
10
8
6
4
2
0
256-QAM Exponential Channel Comparison
Appendix II:
Simulation Program
#define PL_EXP
#define RCV_GAIN
gain for adapters (in dBi)
#define NOISE_DENSITY
density (in dBm/Hz)
Parameters.h
#include <iostream>
using namespace std;
#define CODING_BITS_IN
bits per block
#define CODING_BITS_OUT
bits per block
// Parameters of OFDM transceiver
////////////////////////////////////////////
// Actual parameters as specified in thesis
// #define SUBCARRIERS
1024
carriers (multiple of 2)
// #define BANDWIDTH
100000000.0
(in Hz, type double)
// #define SAMPLING
4
factor (multiple of 2)
// #define GUARD_SAMPLES
200
(guard time) * SAMPLING * BANDWIDTH
3.6e-7
#define DMIN1
point constellation
#define DMIN2
point constellation
#define DMIN3
point constellation
#define DMIN4
point constellation
#define DMIN5
point constellation
#define DMIN6
point constellation
#define DMIN7
point constellation
#define DMIN8
point constellation
// number of complex
// spectrum support
// oversampling
// guard samples =
// number of complex
// spectrum support
// oversampling
// guard samples =
// length of channel
40
// minimum channel
60
// maximum channel
25
// maximum
46
// numbers of symbols
// Parameters from link budget
////////////////////////////////////////////
#define PL_1M
in free-space (in dB)
-46.9
-173.4
// 2D noise spectral
1
// number of incoming
1
// number of outgoing
// Spacing of QAM constellation points
////////////////////////////////////////////
// Parameters of channel models
////////////////////////////////////////////
#define CHANNEL_TRANSIENT
response (in seconds)
#define MIN_VARIANCE
variance (in nanoseconds)
#define MAX_VARIANCE
variance (in nanoseconds)
#define MAX_INTERFERENCE
interference per carrier (in dB)
#define TDD_SYMBOLS
sent per TDD slot
// path loss exponent
// receiver diversity
// Parameters of coding scheme (unavailable)
////////////////////////////////////////////
///////////////////////////////////////////////////////////////
// PROJECT: WGLAN Software Simulation
// FILE:
Parameters.h
// AUTHOR:
Eladio Arvelo <earvelo@alum.mit.edu>
// MODS:
Created file -- 11.22.99
///////////////////////////////////////////////////////////////
// Scale-down parameters for faster simulation
#define SUBCARRIERS
128
carriers (multiple of 2)
#define BANDWIDTH
12500000.0
(in Hz, type double)
#define SAMPLING
4
factor (multiple of 2)
#define GUARD_SAMPLES
25
(guard time) * SAMPLING * BANDWIDTH
4
6
// path loss at 1 meter
114
1.000000000
// min dist in 2^1
0.707106781
// min dist in 2^2
0.408248290
// min dist in 2^3
0.316227766
// min dist in 2^4
0.223606797
// min dist in 2^5
0.154303350
// min dist in 2^6
0.110600252
// min dist in 2^7
0.076696498
// min dist in 2^8
/////////////////////////////////////////////////
Simulator.h
void TestOfdmSymbolClass();
// effects: tests basic features of the OfdmSymbol class
#include "Adapter.h"
#include "Parameters.h"
#include "time.h"
#include <string>
#include <fstream>
#include <iostream>
using namespace std;
void TestChannelClass();
// effects: tests basic features of the Channel class
void TestAdapterClass();
// effects: tests basic features of the Adapter class
////////////////////////////////////////////////////////////////////////
// PROJECT: WGLAN Software Simulation
// FILE:
simulator.h
// AUTHOR:
Eladio Arvelo <earvelo@alum.mit.edu>
// MODS:
Created file -- 11.09.99
//
Added prototype of TestChannelClass() -- 11.24.99
//
Added prototype of TestOfdmSymbolClass() -- 11.25.99
//
Added prototype of BitmapOptimization() -- 12.03.99
//
Added prototype of TestAdapterClass() -- 12.04.99
//
Added prototype of TestBitReversal() -- 12.08.99
//
Added prototype of MeasureSubchannelErrorRate() -01.21.00
//
Added prototype of MeasureConstellationErrorRates() -02.08.00
//
Changed prototype to measure error rates -- 02.12.00
//
Added prototype of MeasureMultipathErrorRate() -- 03.05.00
////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////
// Prototype of Test Routines for Algorithms
/////////////////////////////////////////////////
void TestBitReversal();
// effects: tests ordering of an array by bit reversal
void TestGaussianDeviates(double);
// requires: double be 1D noise variance in linear scale
// effects: verify mean and variance of Gaussian random deviates
/////////////////////////////////////////////////
// Prototype of Utility Functions
/////////////////////////////////////////////////
double antidB(double);
// requires: nothing
// effects: converts double from dB scale to linear scale
/////////////////////////////////////////////////
// Prototype of Design Measurement
/////////////////////////////////////////////////
void MeasureTimeInvariantErrorRate(int bits, int chanType, double
chanVar, double startSNR, double endSNR, double stepSNR, int maxErr);
// requires: constellationBits be an integer between 1 and 8, other
parameters be within range
// effects: returns respective single-user error rates for a specified
time-invariant channel model
/////////////////////////////////////////////////
// Prototype of Numerical Recipe Functions
/////////////////////////////////////////////////
void MeasureTimeVariantErrorRate(int bits, int chanType, double
chanRate, double startSNR, double endSNR, double stepSNR, int maxErr);
// requires: constellationBits be an integer between 1 and 8, other
parameters be within range
// effects: returns respective single-user error rates for a specified
time-variant channel model
double gasdev(long *idum, double variance);
// requires: variance be greater than zero
// effects: returns samples from a Gaussian random number generator
double ran1(long *idum);
// effects: returns samples from a uniform random number generator
void MeasureTimeVariantWithInterferenceErrorRate(int bits, int chanType,
double chanRate, double startSNR, double endSNR, double stepSNR, int
maxErr);
// requires: constellationBits be an integer between 1 and 8, other
parameters be within range
// effects: returns respective single-user error rates for a specified
time-variant channel model with random interference
/////////////////////////////////////////////////
// Prototype of Test Routines for Classes
115
{
Simulator.cpp
cout << "*** Routine 1 selected. Please specify parameters,"
<< endl;
cout << "(a) Number of bits in constellation [1-8]: ";
cin >> intSpec1;
cout << "(b) Channel type [1=impulse, 2=gaussian,
3=exponential, 4=spikes]: ";
cin >> intSpec2;
cout << "(c) Channel variance [in ns, normally 60]: ";
cin >> dblSpec1;
cout << "(d) Start of SNR range [in dB, >= 0.0]: ";
cin >> dblSpec2;
cout << "(e) End of SNR range [in dB]: ";
cin >> dblSpec3;
cout << "(f) Incremental step of SNR range [in dB]: ";
cin >> dblSpec4;
cout << "(g) Maximum number of symbol errors [normally 100]:
";
cin >> intSpec3;
MeasureTimeInvariantErrorRate(intSpec1, intSpec2, dblSpec1,
dblSpec2, dblSpec3, dblSpec4, intSpec3);
}
else if (selection == 2)
{
cout << "*** Routine 2 selected. Please specify parameters,"
<< endl;
cout << "(a) Number of bits in constellation [1-8]: ";
cin >> intSpec1;
cout << "(b) Channel type [1=ideal, 2=gaussian, 3=exponential,
4=spikes]: ";
cin >> intSpec2;
cout << "(c) Channel rate of change [in Hz, normally 10]: ";
cin >> dblSpec1;
cout << "(d) Start of SNR range [in dB, >= 0.0]: ";
cin >> dblSpec2;
cout << "(e) End of SNR range [in dB]: ";
cin >> dblSpec3;
cout << "(f) Incremental step of SNR range [in dB]: ";
cin >> dblSpec4;
cout << "(g) Maximum number of symbol errors [normally 100]:
";
cin >> intSpec3;
MeasureTimeVariantErrorRate(intSpec1, intSpec2, dblSpec1,
dblSpec2, dblSpec3, dblSpec4, intSpec3);
}
else if (selection == 3)
{
cout << "*** Routine 3 selected. Please specify parameters,"
<< endl;
cout << "(a) Number of bits in constellation [1-8]: ";
cin >> intSpec1;
cout << "(b) Channel type [1=ideal, 2=gaussian, 3=exponential,
4=spikes]: ";
cin >> intSpec2;
cout << "(c) Channel rate of change [in Hz, normally 10]: ";
cin >> dblSpec1;
cout << "(d) Start of SNR range [in dB, >= 0.0]: ";
cin >> dblSpec2;
cout << "(e) End of SNR range [in dB]: ";
cin >> dblSpec3;
#include "Simulator.h"
////////////////////////////////////////////////////////////////////////
// PROJECT: WGLAN Software Simulation
// FILE:
simulator.cpp
// AUTHOR:
Eladio Arvelo <earvelo@alum.mit.edu>
// MODS:
Created file -- 11.09.99
//
Created TestOfdmSymbolClass -- 11.25.99
//
Created TestChannelClass -- 11.25.99
//
Created TestAdapterClass -- 12.04.99
//
Modified test classes -- 12.06.99
//
Created TestBitReversal -- 12.08.99
//
Added a routine menu to main() -- 01.21.00
//
Implemented MeasureSubchannelErrorRate() -- 01.24.00
//
Reimplemented TestGaussianDeviates() -- 01.28.00
//
Implemented MeasureConstellationErrorRates() -- 02.08.00
////////////////////////////////////////////////////////////////////////
void main()
{
int selection;
int intSpec1, intSpec2, intSpec3;
bool boolSpec1, boolSpec2, boolSpec3;
double dblSpec1, dblSpec2, dblSpec3, dblSpec4, dblSpec5;
string wait;
do
{
system("clear");
cout << "*******************************************************"
<< endl;
cout << "** Welcome to the WGLAN System Software Simulation **"
<< endl;
cout << "** written by Eladio Arvelo - earvelo@alum.mit.edu **"
<< endl;
cout << "*******************************************************"
<< endl;
cout << endl;
cout << "There are several simulation routines available:" <<
endl;
cout << "(1) Single-user BER for time-invariant AWGN channel
model" << endl;
cout << "(2) Single-user BER for time-variant AWGN channel model"
<< endl;
cout << "(3) Single-user BER for time-variant interference channel
model" << endl;
cout << "(4) Test implementation of OfdmSymbol class" << endl;
cout << "(5) Test implementation of Channel class" << endl;
cout << "(6) Test implementation of Adapter class" << endl;
cout << endl;
cout << "Please select a routine [1-8, 0 to end]: ";
cin >> selection;
cout << endl;
if (selection == 1)
116
cout << "(f) Incremental step of SNR range [in dB]: ";
cin >> dblSpec4;
cout << "(g) Maximum number of symbol errors [normally 100]:
cin >> filename;
// identify channel name
if (chanType == 1)
chanName = "impulse";
else if (chanType == 2)
chanName = "gaussian";
else if (chanType == 3)
chanName = "exponential";
else if (chanType == 4)
chanName = "spikes";
else
{
cerr << "Error: invalid channel type. Simulation aborted." <<
endl;
return;
}
";
cin >> intSpec3;
MeasureTimeVariantWithInterferenceErrorRate(intSpec1,
intSpec2, dblSpec1, dblSpec2, dblSpec3, dblSpec4, intSpec3);
}
else if (selection == 4)
{
cout << "*** Routine 4 selected." << endl;
TestOfdmSymbolClass();
}
else if (selection == 5)
{
cout << "*** Routine 5 selected." << endl;
TestChannelClass();
}
else if (selection == 6)
{
cout << "*** Routine 6 selected." << endl;
TestAdapterClass();
}
// open logfile
logFile.open(filename, ios::out);
if (!logFile)
{
cerr << "Error: cannot open logfile. Simulation aborted." << endl;
return;
}
else
{
cout << endl << "*** Simulation has started. Please standby." <<
endl << endl;
logFile << "*** WGLAN System Software Simulation." << endl;
logFile << "*** by Eladio Arvelo, earvelo@alum.mit.edu" << endl <<
endl;
logFile << "Channel characteristics:" << endl;
logFile << " (1) Type: " << chanName << endl;
logFile << " (2) Variance: " << chanVar << " nanoseconds" << endl;
logFile << "SNR characteristics:" << endl;
logFile << " (1) Start of range: " << startSNR << " dB" << endl;
logFile << " (2) End of range: " << endSNR << " dB" << endl;
logFile << " (3) Step of range: " << stepSNR << " dB" << endl;
logFile << "Error characteristics:" << endl;
logFile << " (1) Maximum number of errors: " << maxErr << endl;
logFile << " (2) Bits in constellation: " << bits << endl << endl
<< endl;
logFile << "Respective BER values follow:" << endl;
}
if (selection != 0)
{
cout << endl << "Press a key and then Enter to continue. ";
cin >> wait;
}
}
while (selection != 0);
}
//////////////////////////////////////////
// MeasureTimeInvariantErrorRate
//////////////////////////////////////////
void MeasureTimeInvariantErrorRate(int bits, int chanType, double
chanVar, double startSNR, double endSNR, double stepSNR, int maxErr){
// This routine computes the single-user error rate of a specific
time-invariant channel model
// for a given constellation size, range of signal-to-noise ratios,
and max number of errors
// initialize SNR range
currentSNR = startSNR;
int i,subchannel;
double distance;
double currentSNR;
ofstream logFile;
char filename[80];
string chanName;
// start simulation
while (currentSNR <= endSNR)
{
// determine adapter distance based on desired signal-to-noise
ratio
distance = (antidB(NOISE_DENSITY + currentSNR) * BANDWIDTH) /
SUBCARRIERS;
distance = (10*log10(distance)) - RCV_GAIN - PL_1M;
distance = pow(10, (-distance / (10 * PL_EXP)));
OfdmSymbol *symbolPtr = new OfdmSymbol();
assert(symbolPtr != NULL);
// get name of logfile
cout << endl << "*** Simulation is about to start." << endl;
cout << "Please enter name of logfile: ";
if (distance < 1.0)
117
{
//
logFile << " (2) Symbols received = " <<
testAdapter.getSymbolsReceived(subchannel) << endl;
//
logFile << " (3) Uncoded bit errors = " <<
testAdapter.getUncodedBitErrors(subchannel) << endl;
//
logFile << " (4) Bits received = " <<
testAdapter.getBitsReceived(subchannel) << endl;
//
logFile << " (5) Symbol error rate = ";
//
logFile <<
((double)testAdapter.getSymbolErrors(subchannel) /
(double)testAdapter.getSymbolsReceived(subchannel)) << endl;
//
logFile << " (6) Uncoded bit error rate = ";
//
logFile <<
((double)testAdapter.getUncodedBitErrors(subchannel) /
(double)testAdapter.getBitsReceived(subchannel)) << endl;
//
logFile << endl << endl;
distance = 1.0;
cerr << "Warning: Adapter distance was under 1 meter in
MeasureSubchannelErrorRate()" << endl;
}
else
{
cout << "Simulating performance for SNR = " << currentSNR <<
endl;
}
// create adapter with distance as computed above
Adapter testAdapter(1, distance, chanName, chanVar*(1e-9));
// set all constellation sizes equal to zero except for one
subcarrier
subchannel = SUBCARRIERS/4;
for (i=0; i < SUBCARRIERS; i++)
testAdapter.setConstellationSize(i, 0);
testAdapter.setConstellationSize(SUBCARRIERS/4, bits);
currentSNR += stepSNR;
}
// end simulation
logFile.close();
// output simulation parameters
//
logFile << "Measuring AWGN error rate with the following
parameters:" << endl;
//
logFile << " (1) Number of bits in constellation: " <<
constellationBits << endl;
//
logFile << " (2) Signal-to-noise ratio in dB: " <<
currentSNR << endl;
//
logFile << " (3) Respective adapter distance in meters: "
<< testAdapter.getDistance() << endl;
}
//////////////////////////////////////////
// MeasureTimeVariantErrorRate
//////////////////////////////////////////
void MeasureTimeVariantErrorRate(int bits, int chanType, double
chanRate, double startSNR, double endSNR, double stepSNR, int maxErr){
// This routine computes the single-user error rate of a specific
time-variant channel model
// for a given constellation size, range of signal-to-noise ratios,
and max number of errors
// initialize equalizers by processing a pilot symbol
testAdapter.initiateReception();
testAdapter.transmitPilotSymbol(1, 1, symbolPtr);
testAdapter.receiveSymbol(symbolPtr, false, false);
do
{
int i,subchannel,chanConstant;
double distance;
double currentSNR;
ofstream logFile;
char filename[80];
string chanName;
long int symbolCounter = 0;
// create and process one OFDM symbol
testAdapter.transmitDataSymbol(1, 1, symbolPtr);
testAdapter.receiveSymbol(symbolPtr);
// keep user informed about progress
if ((testAdapter.getSymbolsReceived(subchannel) % 100) == 0)
{
cout << "So far, " <<
testAdapter.getSymbolsReceived(subchannel) << " OFDM symbols have
resulted in ";
cout << testAdapter.getSymbolErrors(subchannel) << "
errors" << endl;
}
}
while(testAdapter.getSymbolErrors(subchannel) < maxErr);
OfdmSymbol *symbolPtr = new OfdmSymbol();
assert(symbolPtr != NULL);
// get name of logfile
cout << endl << "*** Simulation is about to start." << endl;
cout << "Please enter name of logfile: ";
cin >> filename;
// identify channel name
if (chanType == 1)
chanName = "impulse";
else if (chanType == 2)
chanName = "gaussian";
else if (chanType == 3)
chanName = "exponential";
// output test results to file
logFile << ((double)testAdapter.getUncodedBitErrors(subchannel) /
(double)testAdapter.getBitsReceived(subchannel)) << endl;
//
logFile << "Results of simulation:" << endl;
//
logFile << " (1) Symbol errors = " <<
testAdapter.getSymbolErrors(subchannel) << endl;
118
else if (chanType == 4)
chanName = "spikes";
else
{
cerr << "Error: invalid channel type. Simulation aborted." <<
endl;
return;
}
{
cout << "Simulating performance for SNR = " << currentSNR <<
endl;
}
// create adapter with distance as computed above
Adapter testAdapter(1, distance, chanName, 60*(1e-9));
// assign random variance to channel
testAdapter.changeChannelVariance();
// cout << "Variance = " << testAdapter.getChannelVariance() <<
// open logfile
logFile.open(filename, ios::out);
if (!logFile)
{
cerr << "Error: cannot open logfile. Simulation aborted." << endl;
return;
}
else
{
cout << endl << "*** Simulation has started. Please standby." <<
endl << endl;
logFile << "*** WGLAN System Software Simulation." << endl;
logFile << "*** by Eladio Arvelo, earvelo@alum.mit.edu" << endl <<
endl;
logFile << "Channel characteristics:" << endl;
logFile << " (1) Type: " << chanName << endl;
logFile << " (2) Rate of change: " << chanRate << " Hz" << endl;
logFile << "SNR characteristics:" << endl;
logFile << " (1) Start of range: " << startSNR << " dB" << endl;
logFile << " (2) End of range: " << endSNR << " dB" << endl;
logFile << " (3) Step of range: " << stepSNR << " dB" << endl;
logFile << "Error characteristics:" << endl;
logFile << " (1) Maximum number of errors: " << maxErr << endl;
logFile << " (2) Bits in constellation: " << bits << endl << endl
<< endl;
logFile << "Respective BER values follow:" << endl;
}
endl;
// set all constellation sizes equal to zero except for one
subcarrier
subchannel = SUBCARRIERS/4;
for (i=0; i < SUBCARRIERS; i++)
testAdapter.setConstellationSize(i, 0);
testAdapter.setConstellationSize(SUBCARRIERS/4, bits);
// output simulation parameters
//
logFile << "Measuring AWGN error rate with the following
parameters:" << endl;
//
logFile << " (1) Number of bits in constellation: " <<
constellationBits << endl;
//
logFile << " (2) Signal-to-noise ratio in dB: " <<
currentSNR << endl;
//
logFile << " (3) Respective adapter distance in meters: "
<< testAdapter.getDistance() << endl;
// compute number of symbols sent before changing channel's
impulse response
chanConstant = 1 / (2 * chanRate *
((GUARD_SAMPLES/(SAMPLING*BANDWIDTH)) + (SUBCARRIERS/BANDWIDTH)));
// initialize session
testAdapter.initiateReception();
// initialize SNR range
currentSNR = startSNR;
do
{
// start simulation
while (currentSNR <= endSNR)
{
// initialize symbol counter on each SNR iteration
symbolCounter = 0;
// send and process a pilot symbol every
if ((symbolCounter % TDD_SYMBOLS) == 0)
{
testAdapter.transmitPilotSymbol(1, 1, symbolPtr);
testAdapter.receiveSymbol(symbolPtr, false, false);
symbolCounter++;
// cout << "... sent pilot symbol!" << endl;
}
// determine adapter distance based on desired signal-to-noise
ratio
distance = (antidB(NOISE_DENSITY + currentSNR) * BANDWIDTH) /
SUBCARRIERS;
distance = (10*log10(distance)) - RCV_GAIN - PL_1M;
distance = pow(10, (-distance / (10 * PL_EXP)));
// create and process one OFDM symbol
testAdapter.transmitDataSymbol(1, 1, symbolPtr);
testAdapter.receiveSymbol(symbolPtr);
symbolCounter++;
if (distance < 1.0)
{
distance = 1.0;
cerr << "Warning: Adapter distance was under 1 meter in
MeasureSubchannelErrorRate()" << endl;
}
else
// keep user informed about progress
if ((testAdapter.getSymbolsReceived(subchannel) % 100) == 0)
{
cout << "So far, " <<
testAdapter.getSymbolsReceived(subchannel) << " OFDM symbols have
resulted in ";
119
cout << testAdapter.getSymbolErrors(subchannel) << "
errors" << endl;
}
int
i,subchannel,chanConstant,chanInterferers,interConstant,randomLocation;
double distance;
double currentSNR;
ofstream logFile;
char filename[80];
string chanName;
long int symbolCounter = 0;
// change channel characteristics at rate specified by user
if ((symbolCounter % (((int)(TDD_SYMBOLS / 2)) +
chanConstant)) == 0)
{
testAdapter.changeChannelVariance();
cout << "... changed variance!" << endl;
}
}
while(testAdapter.getSymbolErrors(subchannel) < maxErr);
OfdmSymbol *symbolPtr = new OfdmSymbol();
assert(symbolPtr != NULL);
OfdmSymbol *interPtr = new OfdmSymbol();
assert(interPtr != NULL);
// output test results to file
logFile << ((double)testAdapter.getUncodedBitErrors(subchannel) /
(double)testAdapter.getBitsReceived(subchannel)) << endl;
//
logFile << "Results of simulation:" << endl;
//
logFile << " (1) Symbol errors = " <<
testAdapter.getSymbolErrors(subchannel) << endl;
//
logFile << " (2) Symbols received = " <<
testAdapter.getSymbolsReceived(subchannel) << endl;
//
logFile << " (3) Uncoded bit errors = " <<
testAdapter.getUncodedBitErrors(subchannel) << endl;
//
logFile << " (4) Bits received = " <<
testAdapter.getBitsReceived(subchannel) << endl;
//
logFile << " (5) Symbol error rate = ";
//
logFile <<
((double)testAdapter.getSymbolErrors(subchannel) /
(double)testAdapter.getSymbolsReceived(subchannel)) << endl;
//
logFile << " (6) Uncoded bit error rate = ";
//
logFile <<
((double)testAdapter.getUncodedBitErrors(subchannel) /
(double)testAdapter.getBitsReceived(subchannel)) << endl;
//
logFile << endl << endl;
// get name of logfile
cout << endl << "*** Simulation is about to start." << endl;
cout << "Please enter name of logfile: ";
cin >> filename;
// identify channel name
if (chanType == 1)
chanName = "impulse";
else if (chanType == 2)
chanName = "gaussian";
else if (chanType == 3)
chanName = "exponential";
else if (chanType == 4)
chanName = "spikes";
else
{
cerr << "Error: invalid channel type. Simulation aborted." <<
endl;
return;
}
currentSNR += stepSNR;
// open logfile
logFile.open(filename, ios::out);
if (!logFile)
{
cerr << "Error: cannot open logfile. Simulation aborted." << endl;
return;
}
else
{
cout << endl << "*** Simulation has started. Please standby." <<
endl << endl;
logFile << "*** WGLAN System Software Simulation." << endl;
logFile << "*** by Eladio Arvelo, earvelo@alum.mit.edu" << endl <<
endl;
logFile << "Channel characteristics:" << endl;
logFile << " (1) Type: " << chanName << endl;
logFile << " (2) Rate of change: " << chanRate << " Hz" << endl;
logFile << " (3) Interference hopping rate: 1.6 kHz" << endl;
logFile << "SNR characteristics:" << endl;
logFile << " (1) Start of range: " << startSNR << " dB" << endl;
logFile << " (2) End of range: " << endSNR << " dB" << endl;
logFile << " (3) Step of range: " << stepSNR << " dB" << endl;
logFile << "Error characteristics:" << endl;
logFile << " (1) Maximum number of errors: " << maxErr << endl;
}
// end simulation
logFile.close();
}
//////////////////////////////////////////
// MeasureTimeVariantWithInterferenceErrorRate
//////////////////////////////////////////
void MeasureTimeVariantWithInterferenceErrorRate(int bits, int chanType,
double chanRate, double startSNR, double endSNR, double stepSNR, int
maxErr)
{
// This routine computes the single-user error rate of a specific
time-variant channel model
// that is affected by Bluetooth-like interference at an equivalent
subchannel SNR intensity
// for a given constellation size, range of signal-to-noise ratios,
and max number of errors
120
logFile << " (2) Bits in constellation: " << bits << endl << endl
<< endl;
logFile << "Respective BER values follow:" << endl;
}
//
logFile << " (1) Number of bits in constellation: " <<
constellationBits << endl;
//
logFile << " (2) Signal-to-noise ratio in dB: " <<
currentSNR << endl;
//
logFile << " (3) Respective adapter distance in meters: "
<< testAdapter.getDistance() << endl;
// initialize SNR range
currentSNR = startSNR;
// compute number of symbols sent before changing channel's
impulse response
chanConstant = 1 / (2 * chanRate *
((GUARD_SAMPLES/(SAMPLING*BANDWIDTH)) + (SUBCARRIERS/BANDWIDTH)));
// start simulation
while (currentSNR <= endSNR)
{
// initialize symbol counter on each SNR iteration
symbolCounter = 0;
// compute number of symbols sent before changing interferer's
location (based on 1600 hops/sec)
interConstant = 1 / (1600 * ((GUARD_SAMPLES/(SAMPLING*BANDWIDTH))
+ (SUBCARRIERS/BANDWIDTH)));
// determine adapter distance based on desired signal-to-noise
ratio
distance = (antidB(NOISE_DENSITY + currentSNR) * BANDWIDTH) /
SUBCARRIERS;
distance = (10*log10(distance)) - RCV_GAIN - PL_1M;
distance = pow(10, (-distance / (10 * PL_EXP)));
// initialize session
testAdapter.initiateReception();
testInterferer.initiateReception();
if (distance < 1.0)
{
distance = 1.0;
cerr << "Warning: Adapter distance was under 1 meter in
MeasureSubchannelErrorRate()" << endl;
}
else
{
cout << "Simulating performance for SNR = " << currentSNR <<
endl;
}
do
{
// send and process a pilot symbol every
if ((symbolCounter % TDD_SYMBOLS) == 0)
{
testAdapter.transmitPilotSymbol(1, 1, symbolPtr);
testAdapter.receiveSymbol(symbolPtr, false, false);
symbolCounter++;
// cout << "... sent pilot symbol!" << endl;
}
// create and process one OFDM symbol
testAdapter.transmitDataSymbol(1, 1, symbolPtr);
testInterferer.transmitDataSymbol(1, 1, interPtr);
(*symbolPtr).addInterferer(interPtr);
testAdapter.receiveSymbol(symbolPtr);
symbolCounter++;
// create adapters with distance as computed above
Adapter testAdapter(1, distance, chanName, 60*(1e-9));
Adapter testInterferer(1, distance, chanName, 60*(1e-9));
// assign random variance to channel
testAdapter.changeChannelVariance();
// cout << "Variance = " << testAdapter.getChannelVariance() <<
// keep user informed about progress
if ((testAdapter.getSymbolsReceived(subchannel) % 100) == 0)
{
cout << "So far, " <<
testAdapter.getSymbolsReceived(subchannel) << " OFDM symbols have
resulted in ";
cout << testAdapter.getSymbolErrors(subchannel) << "
errors" << endl;
}
endl;
// set all constellation sizes equal to zero except for one
subcarrier
subchannel = SUBCARRIERS/4;
for (i=0; i < SUBCARRIERS; i++)
testAdapter.setConstellationSize(i, 0);
testAdapter.setConstellationSize(SUBCARRIERS/4, bits);
// set constellation sizes for subchannel interferers
chanInterferers = (SUBCARRIERS / 100.0) + 1;
for (i=0; i < SUBCARRIERS; i++)
testInterferer.setConstellationSize(i, 0);
randomLocation = 1 + rand() % (SUBCARRIERS - chanInterferers - 5);
for (i=randomLocation; i < randomLocation+chanInterferers; i++)
testInterferer.setConstellationSize(i, bits);
// change channel characteristics at rate specified by user
if ((symbolCounter % (((int)(TDD_SYMBOLS / 2)) +
chanConstant)) == 0)
{
testAdapter.changeChannelVariance();
cout << "... changed variance!" << endl;
}
// output simulation parameters
//
logFile << "Measuring AWGN error rate with the following
parameters:" << endl;
// change interferer location based on a 1600 hops/sec
if ((symbolCounter % interConstant) == 0)
{
121
randomLocation = 1 + rand() % (SUBCARRIERS chanInterferers - 5);
for (i=0; i < SUBCARRIERS; i++)
testInterferer.setConstellationSize(i, 0);
for (i=randomLocation; i < randomLocation+chanInterferers;
i++)
testInterferer.setConstellationSize(i, bits);
// cout << "... changed interferer location! (loc=" <<
randomLocation << ", inter=" << chanInterferers << ")" << endl;
}
}
while(testAdapter.getSymbolErrors(subchannel) < maxErr);
int i;
bool randomBit, passedTest=true;
// seed random number generator
srand(time(0));
// user-friendly information
cout << "Testing OfdmSymbol class. Please standby." << endl << endl;
// Test (1)
///////////////////////////////////////////////////////////
// output test results to file
logFile << ((double)testAdapter.getUncodedBitErrors(subchannel) /
(double)testAdapter.getBitsReceived(subchannel)) << endl;
//
logFile << "Results of simulation:" << endl;
//
logFile << " (1) Symbol errors = " <<
testAdapter.getSymbolErrors(subchannel) << endl;
//
logFile << " (2) Symbols received = " <<
testAdapter.getSymbolsReceived(subchannel) << endl;
//
logFile << " (3) Uncoded bit errors = " <<
testAdapter.getUncodedBitErrors(subchannel) << endl;
//
logFile << " (4) Bits received = " <<
testAdapter.getBitsReceived(subchannel) << endl;
//
logFile << " (5) Symbol error rate = ";
//
logFile <<
((double)testAdapter.getSymbolErrors(subchannel) /
(double)testAdapter.getSymbolsReceived(subchannel)) << endl;
//
logFile << " (6) Uncoded bit error rate = ";
//
logFile <<
((double)testAdapter.getUncodedBitErrors(subchannel) /
(double)testAdapter.getBitsReceived(subchannel)) << endl;
//
logFile << endl << endl;
cout << "Performing Test 1..." << endl;
// create test objects
OfdmSymbol *symbolPtr1 = new OfdmSymbol(0, 1, 100, 8*SUBCARRIERS,
8*SUBCARRIERS);
OfdmSymbol *symbolPtr2 = new OfdmSymbol(0, 2, 200, 4*SUBCARRIERS,
4*SUBCARRIERS);
assert(symbolPtr1 != NULL);
assert(symbolPtr2 != NULL);
// fill modulatedData with random numbers
for (i=0; i < SUBCARRIERS*SAMPLING; i++)
(*symbolPtr1).putModulatedSample(i, complex<double>(rand()%6,
rand()%6));
for (i=0; i < SUBCARRIERS*SAMPLING; i++)
(*symbolPtr2).putModulatedSample(i, complex<double>(rand()%6,
rand()%6));
// copy modulatedData into corruptedData
for (i=0; i < SUBCARRIERS*SAMPLING; i++)
(*symbolPtr1).putCorruptedSample(i,
(*symbolPtr1).getModulatedSample(i));
currentSNR += stepSNR;
}
for (i=0; i < SUBCARRIERS*SAMPLING; i++)
(*symbolPtr2).putCorruptedSample(i,
(*symbolPtr2).getModulatedSample(i));
// end simulation
logFile.close();
}
// add guard samples to modulatedData
(*symbolPtr1).guardModulatedSamples();
(*symbolPtr2).guardModulatedSamples();
//////////////////////////////////////////
// Test Routine for OfdmSymbol
//////////////////////////////////////////
for (i=0; i < GUARD_SAMPLES; i++)
{
if ((*symbolPtr1).getModulatedSample(i) !=
(*symbolPtr1).getModulatedSample(i+SUBCARRIERS*SAMPLING))
passedTest = false;
}
void TestOfdmSymbolClass()
{
// This routine performs the following tests on OfdmSymbol:
// (1) Addition of guard samples
// (2) Independent handling of two different OfdmSymbol's
// (3) Packing and retrieval of bits from uncoded and coded data
arrays
// (4) Packing and retrieval of bits from sliced and decoded data
arrays
// (5) Copy of an OfdmSymbol object
// (6) Independent handling of two copied OfdmSymbol's
///////////////////////////////////////////////////////////
for (i=0; i < SUBCARRIERS*SAMPLING; i++)
{
if ((*symbolPtr1).getCorruptedSample(i) !=
(*symbolPtr1).getModulatedSample(i+GUARD_SAMPLES))
passedTest = false;
}
if (passedTest == false)
122
{
while (!(*symbolPtr1).isUncodedRetrievalFinished())
{
if ((*symbolPtr1).getUncodedBit() != (*symbolPtr1).getCodedBit())
passedTest = false;
}
cout << "The contents of modulatedData are:" << endl;
for (i=0; i < (SUBCARRIERS*SAMPLING + GUARD_SAMPLES); i++)
cout << "Index [" << i << "]: " <<
(*symbolPtr1).getModulatedSample(i) << endl;
cout << endl;
cout << "The contents of corruptedData are:" << endl;
for (i=0; i < (SUBCARRIERS*SAMPLING); i++)
cout << "Index [" << i << "]: " <<
(*symbolPtr1).getCorruptedSample(i) << endl;
cout << endl;
cout << "Test of OfdmSymbol -- FAILED --" << endl << endl;
return;
}
if (passedTest == false)
{
cout << "Unable to handle uncoded and coded bit arrays!" << endl;
cout << "Test of OfdmSymbol -- FAILED --" << endl << endl;
return;
}
// Test (4)
///////////////////////////////////////////////////////////
// Test (2)
///////////////////////////////////////////////////////////
cout << "Performing Test 4..." << endl;
cout << "Performing Test 2..." << endl;
passedTest = true;
passedTest = false;
// assuming that uncodedBlockSize is equal to codedBlockSize
(*symbolPtr2).beginSlicedPacking();
(*symbolPtr2).beginDecodedPacking();
for (i=0; i < (SUBCARRIERS*SAMPLING + GUARD_SAMPLES); i++)
{
if ((*symbolPtr1).getModulatedSample(i) !=
(*symbolPtr2).getModulatedSample(i))
passedTest = true;
}
while (!(*symbolPtr2).isSlicedPackingFinished())
{
randomBit = rand() % 1;
(*symbolPtr2).putSlicedBit(randomBit);
(*symbolPtr2).putDecodedBit(randomBit);
}
if (passedTest == false)
{
cout << "Unable to handle two OfdmSymbol objects independently!"
<< endl;
cout << "Test of OfdmSymbol -- FAILED --" << endl << endl;
return;
}
(*symbolPtr2).beginSlicedRetrieval();
(*symbolPtr2).beginDecodedRetrieval();
while (!(*symbolPtr2).isSlicedRetrievalFinished())
{
if ((*symbolPtr2).getSlicedBit() != (*symbolPtr2).getDecodedBit())
passedTest = false;
}
// Test (3)
///////////////////////////////////////////////////////////
if (passedTest == false)
{
cout << "Unable to handle sliced and decoded bit arrays!" << endl;
cout << "Test of OfdmSymbol -- FAILED --" << endl << endl;
return;
}
cout << "Performing Test 3..." << endl;
passedTest = true;
// assuming that uncodedBlockSize is equal to codedBlockSize
(*symbolPtr1).beginUncodedPacking();
(*symbolPtr1).beginCodedPacking();
// Test (5)
///////////////////////////////////////////////////////////
while (!(*symbolPtr1).isUncodedPackingFinished())
{
randomBit = rand() % 2;
(*symbolPtr1).putUncodedBit(randomBit);
(*symbolPtr1).putCodedBit(randomBit);
}
cout << "Performing Test 5..." << endl;
passedTest = true;
delete symbolPtr2;
symbolPtr2 = new OfdmSymbol(symbolPtr1);
assert(symbolPtr2 != NULL);
(*symbolPtr1).beginUncodedRetrieval();
(*symbolPtr1).beginCodedRetrieval();
123
(*symbolPtr1).beginUncodedRetrieval();
(*symbolPtr2).beginUncodedRetrieval();
void TestChannelClass()
{
// This routine performs the following tests on Channel:
// (1) Content verification of impulse-shaped channel
// (2) Convolution of impulse-shaped channel with random input
// (3) Shape verification of exponential channel
// (4) Shape verification of spikes channel
// (5) Shape verification of gaussian channel
// (6) Random shape verification of interference profile
//
// This routine creates the following output files:
// --> channelClassLog.txt
///////////////////////////////////////////////////////////
while (!(*symbolPtr1).isUncodedRetrievalFinished())
{
if ((*symbolPtr1).getUncodedBit() !=
(*symbolPtr2).getUncodedBit())
passedTest = false;
}
if (passedTest == false)
{
cout << "Unable to copy two different OfdmSymbol objects!" <<
endl;
cout << "Test of OfdmSymbol -- FAILED --" << endl << endl;
return;
}
int i;
bool passedTest = true;
// create log file
ofstream logFile;
logFile.open("channelClassLog.txt", ios::out);
// Test (6)
///////////////////////////////////////////////////////////
// seed random number generator
srand(time(0));
cout << "Performing Test 6..." << endl;
passedTest = false;
// create test objects
Channel impulseChannel(30, "impulse", 6e-8);
Channel testChannel(30, "impulse", 6e-8);
OfdmSymbol *symbolPtr = new OfdmSymbol(0, 1, 100, 8*SUBCARRIERS,
8*SUBCARRIERS);
assert(symbolPtr != NULL);
(*symbolPtr2).beginUncodedPacking();
while (!(*symbolPtr2).isUncodedPackingFinished())
(*symbolPtr2).putUncodedBit(rand() % 2);
(*symbolPtr1).beginUncodedRetrieval();
(*symbolPtr2).beginUncodedRetrieval();
// user-friendly information
cout << "Testing Channel class. Please standby." << endl << endl;
while (!(*symbolPtr1).isUncodedRetrievalFinished())
{
if ((*symbolPtr1).getUncodedBit() !=
(*symbolPtr2).getUncodedBit())
passedTest = true;
}
// Test (1)
///////////////////////////////////////////////////////////
cout << "Performing Test 1..." << endl;
if (impulseChannel.getSample(0) != complex<double>(1,0))
{
cerr << "Test 1a FAILED: impulseResponse[0] = " <<
impulseChannel.getSample(0) << endl;
passedTest = false;
logFile.close();
return;
}
if (passedTest == false)
{
cout << "Unable to guarantee independence between copied
OfdmSymbol objects!" << endl;
cout << "Test of OfdmSymbol -- FAILED --" << endl << endl;
return;
}
else
{
cout << "Test of OfdmSymbol passed" << endl << endl;
}
}
for (i=1; i < impulseChannel.getResponseLength(); i++)
{
if (impulseChannel.getSample(i) != complex<double>(0,0))
{
cerr << "Test 1b FAILED: impulseResponse[" << i << "] = " <<
impulseChannel.getSample(i) << endl;
passedTest = false;
logFile.close();
return;
}
}
//////////////////////////////////////////
// Test Routine for Channel
//////////////////////////////////////////
124
cout << "Performing Test 4..." << endl;
// Test (2)
///////////////////////////////////////////////////////////
testChannel.changeShape("spikes");
logFile << "Entries of spike-shape channel:" << endl;
for (i=0; i < testChannel.getResponseLength(); i++)
logFile << testChannel.getSample(i).real() << endl;
logFile << endl;
cout << "Performing Test 2..." << endl;
// fill modulatedData with random numbers
for (i=0; i < SUBCARRIERS*SAMPLING; i++)
(*symbolPtr).putModulatedSample(i, complex<double>(rand()%6,
rand()%6));
// Test (5)
///////////////////////////////////////////////////////////
cout << "Performing Test 5..." << endl;
// add guard samples to modulatedData
(*symbolPtr).guardModulatedSamples();
testChannel.changeShape("gaussian");
logFile << "Entries of gaussian-shape channel:" << endl;
for (i=0; i < testChannel.getResponseLength(); i++)
logFile << testChannel.getSample(i).real() << endl;
logFile << endl;
// convolve testSymbol with impulse channel
impulseChannel.convolveSymbol(symbolPtr, false);
// verify that convolution left testSymbol untouched
for (i=0; i < (SUBCARRIERS*SAMPLING + GUARD_SAMPLES); i++)
{
if ((*symbolPtr).getModulatedSample(i) !=
(*symbolPtr).getCorruptedSample(i))
passedTest = false;
}
// Test (6)
///////////////////////////////////////////////////////////
cout << "Performing Test 6..." << endl;
logFile << "Entries of interference profile:" << endl;
for (i=0; i < SUBCARRIERS; i++)
logFile << testChannel.getInterference(i) << endl;
logFile << endl;
if (passedTest == false)
{
cerr << "Test 2 FAILED. Core dump of array contents follows." <<
endl << endl;
cout << "Writing output file: channelClassLog,txt" << endl <<
endl;
logFile << "Contents of modulatedData:" << endl;
for (i=0; i < (SUBCARRIERS*SAMPLING + GUARD_SAMPLES); i++)
logFile << "Entry[" << i << "] = " <<
(*symbolPtr).getModulatedSample(i) << endl;
logFile << endl;
logFile << "Contents of corruptedData:" << endl;
for (i=0; i < (SUBCARRIERS*SAMPLING + GUARD_SAMPLES); i++)
logFile << "Entry[" << i << "] = " <<
(*symbolPtr).getCorruptedSample(i) << endl;
logFile.close();
return;
}
else
{
// Test (3)
///////////////////////////////////////////////////////////
// user-friendly information
cout << "Writing output file: channelClassLog,txt" << endl <<
endl;
logFile << "Contents of modulatedData:" << endl;
for (i=0; i < SUBCARRIERS*SAMPLING + GUARD_SAMPLES; i++)
logFile << " modulatedData[" << i << "]= " <<
(*symbolPtr).getModulatedSample(i) << endl;
logFile << endl << endl;
logFile << "Contents of corruptedData:" << endl;
for (i=0; i < SUBCARRIERS*SAMPLING + GUARD_SAMPLES; i++)
logFile << " corruptedData[" << i << "]= " <<
(*symbolPtr).getCorruptedSample(i) << endl;
logFile << endl << endl;
cout << "Test of Channel passed" << endl << endl;
}
logFile.close();
cout << "Performing Test 3..." << endl;
}
testChannel.changeShape("exponential");
logFile << "Entries of exponential-shape channel:" << endl;
for (i=0; i < testChannel.getResponseLength(); i++)
logFile << testChannel.getSample(i).real() << endl;
logFile << endl;
//////////////////////////////////////////
// Test Routine for Adapter
//////////////////////////////////////////
// Test (4)
///////////////////////////////////////////////////////////
void TestAdapterClass()
{
// This routine performs the following tests on Channel:
125
// (1) Perfect transmission and reception of an OFDM symbol
//
// This routine creates the following output files:
// --> adapterClassLog.txt
///////////////////////////////////////////////////////////
{
qamEnergy += pow((*symbolPtr).getQamSample(i).real(),2);
qamEnergy += pow((*symbolPtr).getQamSample(i).imag(),2);
}
for (i=GUARD_SAMPLES; i < SUBCARRIERS*SAMPLING+GUARD_SAMPLES; i++)
{
modulatedEnergy +=
pow((*symbolPtr).getModulatedSample(i).real(),2);
modulatedEnergy +=
pow((*symbolPtr).getModulatedSample(i).imag(),2);
}
int i,j;
bool passedTest = true;
Adapter testAdapter(1, 5, "impulse", 6e-8);
OfdmSymbol *symbolPtr = new OfdmSymbol();
assert(symbolPtr != NULL);
srand(time(0));
cout << "QAM energy = " << qamEnergy << endl;
cout << "Modulated energy = " << modulatedEnergy << endl << endl;
// create log file
ofstream logFile;
logFile.open("adapterClassLog.txt", ios::out);
// user-friendly information
cout << "Writing output file: adapterClassLog.txt" << endl;
// user-friendly information
cout << "Testing Adapter class. Please standby." << endl << endl;
// output test results to log file
logFile << "Results of testing Adapter Class:" << endl;
logFile << " (1) Symbol errors = " << testAdapter.getSymbolErrors() <<
endl;
logFile << " (2) Symbols received = " <<
testAdapter.getSymbolsReceived() << endl;
logFile << " (3) Uncoded bit errors = " <<
testAdapter.getUncodedBitErrors() << endl;
logFile << " (5) Bits received = " << testAdapter.getBitsReceived() <<
endl << endl;
// Test (1)
///////////////////////////////////////////////////////////
cout << "Performing Test 1..." << endl;
// set constellation sizes randomly
for (i=0; i < SUBCARRIERS; i++)
{
testAdapter.setConstellationSize(i, rand()%8 + 1);
//
testAdapter.setConstellationSize(i, 0);
}
//
testAdapter.setConstellationSize(45,8);
(*symbolPtr).beginCodedRetrieval();
(*symbolPtr).beginSlicedRetrieval();
logFile << "Respective constellation sizes:" << endl;
for (i=0; i < SUBCARRIERS; i++)
logFile << " size for subcarrier[" << i << "]= " <<
testAdapter.getConstellationSize(i) << endl;
logFile << endl << endl;
// initialize slicing distances by processing a pilot symbol
testAdapter.initiateReception();
testAdapter.transmitPilotSymbol(1, 1, symbolPtr);
testAdapter.receiveSymbol(symbolPtr, false, false);
logFile << "Respective coded bits for each subcarrier:" << endl;
for (i=0; i < SUBCARRIERS; i++)
{
logFile << " coded bits for subcarrier[" << i << "]= ";
// create and process one OFDM symbol
testAdapter.transmitDataSymbol(1, 1, symbolPtr);
testAdapter.receiveSymbol(symbolPtr, false);
// output test results to screen
cout << "Results of testing Adapter Class:" << endl;
cout << " (1) Symbol errors = " << testAdapter.getSymbolErrors() <<
endl;
cout << " (2) Symbols received = " << testAdapter.getSymbolsReceived()
<< endl;
cout << " (3) Uncoded bit errors = " <<
testAdapter.getUncodedBitErrors() << endl;
cout << " (4) Bits received = " << testAdapter.getBitsReceived() <<
endl << endl;
if (testAdapter.getConstellationSize(i) == 0)
{
logFile << "none" << endl;
}
else
{
for (j = testAdapter.getConstellationSize(i); j > 0; j--)
logFile << (*symbolPtr).getCodedBit();
logFile << endl;
}
}
logFile << endl << endl;
// info on conservation of energy
double qamEnergy = 0;
double modulatedEnergy = 0;
logFile << "Contents of qamData:" << endl;
for (i=0; i < SUBCARRIERS; i++)
for (i=0; i < SUBCARRIERS; i++)
126
logFile << " qamData[" << i << "]= " << (*symbolPtr).getQamSample(i)
<< endl;
logFile << endl << endl;
void TestBitReversal()
{
// Verify algorithm for bit reversing entries in an array
///////////////////////////////////////////////////////////
logFile << "Contents of modulatedData:" << endl;
for (i=0; i < SUBCARRIERS*SAMPLING+GUARD_SAMPLES; i++)
logFile << " modulatedData[" << i << "]= " <<
(*symbolPtr).getModulatedSample(i) << endl;
logFile << endl << endl;
unsigned long i, j, m, n;
int tempValue;
int dataArray[8];
for (i=0; i < 8; i++)
dataArray[i] = i;
logFile << "Contents of corruptedData:" << endl;
for (i=0; i < SUBCARRIERS*SAMPLING+GUARD_SAMPLES; i++)
logFile << " corruptedData[" << i << "]= " <<
(*symbolPtr).getCorruptedSample(i) << endl;
logFile << endl << endl;
cout << "Contents of data array BEFORE bit reversal: " << endl;
for (i=0; i < 8; i++)
cout << " dataArray[" << i << "] = " << dataArray[i] << endl;
cout << endl;
logFile << "Contents of equalizers:" << endl;
for (i=0; i < SUBCARRIERS; i++)
logFile << " equalizer[" << i << "]= " <<
testAdapter.getEqualizer(i) << endl;
logFile << endl << endl;
n = 8;
j = 1;
for (i=1; i < n+1; i++)
{
if (j > i)
{
tempValue = dataArray[j-1];
dataArray[j-1] = dataArray[i-1];
dataArray[i-1] = tempValue;
}
m = n >> 1;
while (m >= 2 && j > m)
{
j -= m;
m >>= 1;
}
j += m;
}
logFile << "Contents of demodulatedData:" << endl;
for (i=0; i < SUBCARRIERS; i++)
logFile << " demodulatedData[" << i << "]= " <<
(*symbolPtr).getDemodulatedSample(i) << endl;
logFile << endl << endl;
logFile << "Respective sliced bits for each subcarrier:" << endl;
for (i=0; i < SUBCARRIERS; i++)
{
logFile << " sliced bits for subcarrier[" << i << "]= ";
if (testAdapter.getConstellationSize(i) == 0)
{
logFile << "none" << endl;
}
else
{
for (j = testAdapter.getConstellationSize(i); j > 0; j--)
logFile << (*symbolPtr).getSlicedBit();
logFile << endl;
}
cout << "Contents of data array AFTER bit reversal: " << endl;
for (i=0; i < 8; i++)
cout << " dataArray[" << i << "] = " << dataArray[i] << endl;
cout << endl;
}
}
logFile << endl << endl;
//////////////////////////////////////////
// Test Routine for Gaussian Deviates
//////////////////////////////////////////
logFile << "Samples of channel impulse response:" << endl;
for (i=0; i < testAdapter.getChannelLength(); i++)
logFile << " channel response sample[" << i << "] = " <<
testAdapter.getChannelSample(i) << endl;
logFile << endl << endl;
void TestGaussianDeviates(double targetVar)
{
// Find mean and variance of 50 random deviates
///////////////////////////////////////////////////////////
logFile.close();
}
int i;
long int idum=0;
double measuredMean, measuredVar;
double samples[50];
//////////////////////////////////////////
// Test Routine for Bit Reversal Ordering
//////////////////////////////////////////
127
// user-friendly screen output
cout << endl << "*** Simulation has started. Please standby." << endl;
static long iv[NTAB];
double temp;
for (i=0; i < 50; i++)
{
samples[i] = gasdev(&idum, targetVar);
cout << "Sample [" << i << "]= " << samples[i] << endl;
}
if (*idum <= 0 || !iy) {
if (-(*idum) < 1) *idum=1;
else *idum = -(*idum);
for (j=NTAB+7;j>=0;j--) {
k=(*idum)/IQ;
*idum=IA*(*idum-k*IQ)-IR*k;
if (*idum < 0) *idum += IM;
if (j < NTAB) iv[j] = *idum;
}
iy=iv[0];
}
k=(*idum)/IQ;
*idum=IA*(*idum-k*IQ)-IR*k;
if (*idum < 0) *idum += IM;
j=iy/NDIV;
iy=iv[j];
iv[j] = *idum;
if ((temp=AM*iy) > RNMX) return RNMX;
else return temp;
measuredMean = measuredVar = 0;
for (i=0; i < 50; i++)
measuredMean += samples[i];
measuredMean = measuredMean / 50;
for (i=0; i < 50; i++)
measuredVar += pow(samples[i] - measuredMean, 2);
measuredVar = measuredVar / 49;
cout << endl;
cout << "Target mean was 0, measured was " << measuredMean << endl;
cout << "Target variance was " << targetVar << ", measured was " <<
measuredVar << endl;
}
}
#undef
#undef
#undef
#undef
#undef
#undef
#undef
#undef
#undef
/////////////////////////////////////////////////
// Utility Functions
/////////////////////////////////////////////////
double antidB(double value)
{
value = pow(10,(value/10.0));
return value;
}
double gasdev(long *idum, double variance)
{
double ran1(long *idum);
static int iset=0;
static float gset;
double fac,rsq,v1,v2;
/////////////////////////////////////////////////
// Numerical Recipe Functions
/////////////////////////////////////////////////
#define
#define
#define
#define
#define
#define
#define
#define
#define
IA
IM
AM
IQ
IR
NTAB
NDIV
EPS
RNMX
if (*idum < 0) iset=0;
if (iset == 0) {
do {
v1=2.0*ran1(idum)-1.0;
v2=2.0*ran1(idum)-1.0;
rsq=v1*v1+v2*v2;
} while (rsq >= 1.0 || rsq == 0.0);
fac=sqrt(-2.0*log(rsq)/rsq);
gset=v1*fac*sqrt(variance);
iset=1;
return v2*fac*sqrt(variance);
} else {
iset=0;
return gset;
}
IA 16807
IM 2147483647
AM (1.0/IM)
IQ 127773
IR 2836
NTAB 32
NDIV (1+(IM-1)/NTAB)
EPS 1.2e-7
RNMX (1.0-EPS)
double ran1(long *idum)
{
int j;
long k;
static long iy=0;
}
128
long int bitsReceived[SUBCARRIERS];
long int symbolsReceived[SUBCARRIERS];
Adapter.h
#include "Channel.h"
#include <iostream>
using namespace std;
////////////////////////////////////
// Constructors
////////////////////////////////////
public:
////////////////////////////////////////////////////////////////////////
// PROJECT: WGLAN Software Simulation
// FILE:
Adapter.h
// AUTHOR:
Eladio Arvelo <earvelo@alum.mit.edu>
// MODS:
Created file -- 11.09.99
//
Added private data and method signatures -- 11.10.99
//
Restructured some methods -- 11.26.99
//
Modified several method signatures -- 12.03.99
//
Modified several method signatures -- 12.04.99
//
Modified several method signatures -- 12.05.99
//
Modified several method signatures -- 12.06.99
//
Replaced OfdmSymbol& with OfdmSymbol* -- 12.08.99
//
Changed distance from type int to double -- 01.23.00
//
Modified method signatures to handle noise -- 01.23.00
//
Added symbolErrors and symbolsReceived -- 01.27.00
//
Modified handling of error statistics -- 02.08.00
////////////////////////////////////////////////////////////////////////
Adapter(int deviceID, double distance, string channelShape, double
channelVariance);
// requires: channelShape belong to {"impulse", "exponential",
"spikes", "gaussian"}
// modifies: this
// effects: creates a new Device with default parameters
Adapter(const Adapter&);
// effects: this is a copy constructor
////////////////////////////////////
// Observer Methods
////////////////////////////////////
public:
class Adapter
{
// OVERVIEW
// Adapter is an abstraction of a WGLAN Network Adapter
bool isMaster();
// effects: returns true if adapter initiated session, false
otherwise
int getDeviceID();
// effects: returns ID of this device
////////////////////////////////////
// Private data
////////////////////////////////////
double getDistance();
// effects: returns distance between network controller and adapter
private:
// Adapter parameters
int deviceID;
1..M if an adapter
int constellationSizes[SUBCARRIERS];
1..8 otherwise
complex<double> equalizers[SUBCARRIERS];
bool isMasterDevice;
Channel deviceChannel;
int getConstellationSize(int index);
// requires: index be in range [0, (SUBCARRIERS=1)]
// effects: returns the constellation size of the respective
subcarrier
// 0 if a controller;
// 0 if carrier not used;
complex<double> getEqualizer(int index);
// requires: index be in range [0, (SUBCARRIERS-1)]
// effects: returns the complex equalizer of the respective
subcarrier
int getSubcarrierInterference(int);
// requires: int be in range [0, (SUBCARRIERS-1)]
// effects: returns level of interference in dB for respective
subcarrier
// transmission profile parameters
bool txActive;
bool txFiniteload;
long int txPayload;
int getChannelLength();
// effects: returns length of channel impulse response
// reception profile parameters
bool rvActive;
long int symbolErrors[SUBCARRIERS];
long int codedBitErrors[SUBCARRIERS];
long int uncodedBitErrors[SUBCARRIERS];
complex<double> getChannelSample(int);
// requires: int be in range [0, getChannelLength()]
// effects: returns respective sample of channel impulse response
129
double getChannelVariance();
// effects: returns variance of channel impulse response
void setConstellationSize(int index, int size);
// requires: index be in range [0, (SUBCARRIERS-1)], size be in range
[0,8]
// modifies: this.constellationSizes[index]
// effects: sets the constellation size of the respective subcarrier
string getChannelShape();
// effects: returns shape of channel impulse response
long int getSymbolErrors(int index = -1);
// requires: index be in range [-1, (SUBCARRIERS-1)]
// effects: returns number of point errors in specified subcarrier,
//
or sum of total number of point errors if index == -1
OfdmSymbol* transmitDataSymbol(int receiverID, int time, OfdmSymbol
*symbolPtr);
// requires: argument list be valid
// modifies: OfdmSymbol*
// effects: creates and processes an OfdmSymbol up to its air
transmission
long int getCodedBitErrors(int index = -1);
// requires: index be in range [-1, (SUBCARRIERS-1)]
// effects: returns number of coded bit errors in specified
subcarrier,
//
or sum of total number of coded bit errors if index == -1
OfdmSymbol* transmitPilotSymbol(int receiverID, int time, OfdmSymbol
*symbolPtr);
// requires: argument list be valid
// modifies: OfdmSymbol*
// effects: creates and processes an OfdmSymbol containing pilot
constellation points
long int getUncodedBitErrors(int index = -1);
// requires: index be in range [-1, (SUBCARRIERS-1)]
// effects: returns number of uncoded bit errors in specified
subcarrier,
//
or sum of total number of uncoded bit errors if index ==
-1
OfdmSymbol* receiveSymbol(OfdmSymbol* symbolPtr, bool noise=true, bool
analyze=true);
// modifies: OfdmSymbol*, this.equalizers
// effects: receives and processes an OfdmSymbol up to its bit
decoding,
//
adds gaussian noise to OfdmSymbol if noise is true,
//
updates error statistics if analyze is true.
long int getBitsReceived(int index = -1);
// requires: index be in range [-1, (SUBCARRIERS-1)]
// effects: returns number of bits received in specified subcarrier,
//
or sum of total number of bits received if index == -1
void changeChannelVariance(double newVariance=0);
// requires: double be greater than zero for non-random variance
assignment
// modifies: variance, impulseResponse
// effects: changes channel impulse response to the given variance in
nanoseconds,
//
or to a random value between MAX_VARIANCE and
MIN_VARIANCE if newVariance == 0.
long int getSymbolsReceived(int index = -1);
// requires: index be in range [-1, (SUBCARRIERS-1)]
// effects: returns number of symbols received in specified
subcarrier,
//
or sum of total number of symbols received if index == -1
////////////////////////////////////
// Mutator Methods
////////////////////////////////////
void changeChannelShape(string newShape="random");
// requires: empty parameter list or string = {impulse, exponential,
spikes, gaussian}
// modifies: shape, impulseResponse
// effects: changes channel impulse response to the specified shape,
//
or to a random shape if newShape == "random"
public:
void initiateTransmission(bool finiteLength, long int length);
// requires: length be > 0 if finiteLength is true
// modifies: this
// effects: prepares Adapter to transmit OFDM symbols
void changeChannelInterference();
// modifies: jammingProfile
// effects: assign new random numbers to entries in jammingProfile
void initiateReception();
// modifies: this
// effects: prepares Adapter to receive OFDM symbols
////////////////////////////////////
// Destructor
////////////////////////////////////
void terminateTransmission();
// modifies: this
// effects: instructs Adapter to stop sending OFDM symbols
public:
void terminateReception();
// modifies: this
// effects: instructs Adapter to stop receiving OFDM symbols
~Adapter();
// effects:
130
deletes private data of this
// requires: OfdmSymbol* be created by either transmitDataSymbol or
transmitPilotSymbol
// modifies: OfdmSymbol*, this.slicingDistances
// effects: determines slicing distances at the receiver, adds noise
if bool is true
////////////////////////////////////
// Helper Functions
////////////////////////////////////
private:
OfdmSymbol* analyzeSymbol(OfdmSymbol*);
// requires: OfdmSymbol* be created by either transmitDataSymbol or
transmitPilotSymbol
// modifies: this
// effects: captures all statistical information contained in
OfdmSymbol&
OfdmSymbol* createSymbol(int recID, int time, OfdmSymbol *symbolPtr);
// requires: argument list be valid
// effects: creates a new OfdmSymbol& and stuffs uncodedData with
uncodedBlSize random bits
OfdmSymbol* encodeSymbol(OfdmSymbol*);
// requires: this.createSymbol be invoked beforehand
// modifies: OfdmSymbol*
// effects: stuffs codedData with appropriate bits
////////////////////////////////////
// Numerical Recipe Functions
////////////////////////////////////
OfdmSymbol* qamSymbol(OfdmSymbol*);
// requires: this.encodeSymbol be invoked beforehand
// modifies: OfdmSymbol*
// effects: stuffs qamData with appropriate complex values
private:
void dfour1(double data[], unsigned long nn, int isign);
// effects: computes forward FFT if isign==-1, or inverser FFT if
isign==1
OfdmSymbol* modulateSymbol(OfdmSymbol*);
// requires: this.qamSymbol be invoked beforehand
// modifies: OfdmSymbol*
// effects: stuffs modulatedData with appropriate complex samples
(IFFT)
////////////////////////////////////////////////////////////////////////
// BIT MAPPING TO CONSTELLATION POINTS
////////////////////////////////////////////////////////////////////////
//
// Bits are mapped in a Gray-like fashion so that selecting adjacent
//
constellation points due to noise results in a single bit error.
//
// In the case of even-sized constellations, i.e. for a 2^k-point
//
constellation where k is even, the one-dimensional mapping follows
//
the pattern below. Note that the leftmost indicates the sign of the
axis,
//
i.e. 0 is positive half and 1 is negative half. Except for the
"sign"
//
bit, the pattern is a mirrored image at the origin which allows the
//
additional bits to convey the one-dimensional magnitude of the
//
respective constellation point. For instance, in the pattern 11-1000-01,
//
the leftmost bit of 11 and 10 indicates negative x-axis while the
lefmost
//
bit of 00 and 01 indicates positive x-axis. Moreover, 00 and 10 are
//
mirror image of each other (except for the sign bit), while 11 and
01
//
are also mirror image of each other (except for the sign bit).
//
// The even-sized constellation patterns are:
// 10-00
// 11-10-00-01
// 110-111-101-100-000-001-011-010
// 1100-1101-1111-1110-1010-1011-1001-1000-0000-0001-0011-0010-01100111-0101-0100
//
//
// In the case of odd-sized constellations, i.e. for a 2^k-point
OfdmSymbol* guardSymbol(OfdmSymbol*);
// requires: this.modulateSymbol be invoked beforehand
// modifies: OfdmSymbol*
// effects: adds guard samples to modulatedData
OfdmSymbol* corruptSymbol(OfdmSymbol* symbolPtr, bool noise=true);
// requires: this.guardSymbol be invoked beforehand
// modifies: OfdmSymbol*
// effects: convolves OfdmSymbol& with channel response and adds
noise if bool is true
OfdmSymbol* demodulateSymbol(OfdmSymbol*);
// requires: this.transmitSymbol be invoked beforehand
// modifies: OfdmSymbol*
// effects: stuffs demodulatedData with appropriate complex values
(FFT)
OfdmSymbol* sliceSymbol(OfdmSymbol*, bool analyze);
// requires: this.demodulateSymbol be invoked beforehand
// modifies: OfdmSymbol*
// effects: stuffs slicedData with appropriate bits,
//
updates statistics on symbol errors if analyze is true
OfdmSymbol* decodeSymbol(OfdmSymbol*);
// requires: this.sliceSymbol be invoked beforehand
// modifies: OfdmSymbol*
// effects: stuffs decodedData with appropriate bits
OfdmSymbol* receivePilotSymbol(OfdmSymbol* symbolPtr, bool
noise=true);
131
//
constellation where k is odd, the one-dimensional mapping follows a
pattern
//
that is customized for each constellation. Each mapping is
optimized by
//
minimizing the average hamming distance between points. The
patterns chosen
//
may be suboptimal, so we recommend their re-evaluation before
actual
//
implementation of the system. In general though, the two leftmost
bits
//
indicate the quadrant in which the point is located, that is, 00 is
first
//
quadrant, 01 is second quadrant, 11 is third quadrant, and 10 is
fourth quadrant.
//
//
//
// /////////////////////////////////////
// 2-POINT CONSTELLATION
// /////////////////////////////////////
//
// 1-0
//
//
// /////////////////////////////////////
// 4-POINT CONSTELLATION
// /////////////////////////////////////
//
// 10-00
// ----// 11-01
//
//
// /////////////////////////////////////
// 8-POINT CONSTELLATION
// /////////////////////////////////////
//
// 110-100-000-010
// --------------// 111-101-001-011
//
//
// /////////////////////////////////////
// 16-POINT CONSTELLATION
// /////////////////////////////////////
//
// 1101-1001-0001-0101
// 1100-1000-0000-0100
// ------------------// 1110-1010-0010-0110
// 1111-1011-0011-0111
//
//
// /////////////////////////////////////
// 32-POINT CONSTELLATION
// /////////////////////////////////////
//
// ------01111-01110-00110-00111-----// 01101-01011-01010-00010-00011-00101
// 01100-01001-01000-00000-00001-00100
// ----------------------------------// 11100-11001-11000-10000-10001-10100
// 11101-11011-11010-10010-10011-10101
// ------11111-11110-10110-10111-----//
//
// /////////////////////////////////////
// 64-POINT CONSTELLATION
// /////////////////////////////////////
//
// 110010-111010-101010-100010-000010-001010-011010-010010
// 110011-111011-101011-100011-000011-001011-011011-010011
// 110001-111001-101001-100001-000001-001001-011001-010001
// 110000-111000-101000-100000-000000-001000-011000-010000
// ------------------------------------------------------// 110100-111100-101100-100100-000100-001100-011100-010100
// 110101-111101-101101-100101-000101-001101-011101-010101
// 110111-111111-101111-100111-000111-001111-011111-010111
// 110110-111110-101110-100110-000110-001110-011110-010110
//
//
// /////////////////////////////////////
// 128-POINT CONSTELLATION
// /////////////////////////////////////
//
// ------------------------0111111-0101011-0101111-0001111-00010110011111-----------------------// --------0111001-0110101-0111101-0101101-0100101-0000101-00011010011101-0010101-0011001-------// 0101001-0111011-0110100-0111100-0101100-0100100-0000100-00011000011100-0010100-0011011-0001001
// 0100111-0110111-0110110-0111110-0101110-0100110-0000110-00011100011110-0010110-0010111-0000111
// 0100011-0110011-0110010-0111010-0101010-0100010-0000010-00010100011010-0010010-0010011-0000011
// 0100001-0110001-0110000-0111000-0101000-0100000-0000000-00010000011000-0010000-0010001-0000001
// ---------------------------------------------------------------------------------------------// 1100001-1110001-1110000-1111000-1101111-1100000-1000000-10010001011000-1010000-1010001-1000001
// 1100011-1110011-1110010-1111010-1101010-1100010-1000010-10010101011010-1010010-1010011-1000011
// 1100111-1110111-1110110-1111110-1101110-1100110-1000110-10011101011110-1010110-1010111-1000111
// 1101001-1111011-1110100-1111100-1101100-1100100-1000100-10011001011100-1010100-1011011-1001001
// --------1111001-1110101-1111101-1101101-1100101-1000101-10011011011101-1010101-1011001-------// ------------------------1111111-1101011-1101111-1001111-10010111011111-----------------------//
//
// /////////////////////////////////////
// 256-POINT CONSTELLATION
// /////////////////////////////////////
//
// 11000100-11010100-11110100-11100100-10100100-10110100-1001010010000100-00000100-00010100-00110100-00100100-01100100-01110100-0101010001000100
132
// 11000101-11010101-11110101-11100101-10100101-10110101-1001010110000101-00000101-00010101-00110101-00100101-01100101-01110101-0101010101000101
// 11000111-11010111-11110111-11100111-10100111-10110111-1001011110000111-00000111-00010111-00110111-00100111-01100111-01110111-0101011101000111
// 11000110-11010110-11110110-11100110-10100110-10110110-1001011010000110-00000110-00010110-00110110-00100110-01100110-01110110-0101011001000110
// 11000010-11010010-11110010-11100010-10100010-10110010-1001001010000010-00000010-00010010-00110010-00100010-01100010-01110010-0101001001000010
// 11000011-11010011-11110011-11100011-10100011-10110011-1001001110000011-00000011-00010011-00110011-00100011-01100011-01110011-0101001101000011
// 11000001-11010001-11110001-11100001-10100001-10110001-1001000110000001-00000001-00010001-00110001-00100001-01100001-01110001-0101000101000001
// 11000000-11010000-11110000-11100000-10100000-10110000-1001000010000000-00000000-00010000-00110000-00100000-01100000-01110000-0101000001000000
// --------------------------------------------------------------------------------------------------------------------------------------------// 11001000-11011000-11111000-11101000-10101000-10111000-1001100010001000-00001000-00011000-00111000-00101000-01101000-01111000-0101100001001000
// 11001001-11011001-11111001-11101001-10101001-10111001-1001100110001001-00001001-00011001-00111001-00101001-01101001-01111001-0101100101001001
// 11001011-11011011-11111011-11101011-10101011-10111011-1001101110001011-00001011-00011011-00111011-00101011-01101011-01111011-0101101101001011
// 11001010-11011010-11111010-11101010-10101010-10111010-1001101010001010-00001010-00011010-00111010-00101010-01101010-01111010-0101101001001010
// 11001110-11011110-11111110-11101110-10101110-10111110-1001111010001110-00001110-00011110-00111110-00101110-01101110-01111110-0101111001001110
// 11001111-11011111-11111111-11101111-10101111-10111111-1001111110001111-00001111-00011111-00111111-00101111-01101111-01111111-0101111101001111
// 11001101-11011101-11111101-11101101-10101101-10111101-1001110110001101-00001101-00011101-00111101-00101101-01101101-01111101-0101110101001101
// 11001100-11011100-11111100-11101100-10101100-10111100-1001110010001100-00001100-00011100-00111100-00101100-01101100-01111100-0101110001001100
}; //end Adapter class
133
isMasterDevice = oldAdapter.isMasterDevice;
for (i=0; i < SUBCARRIERS; i++)
{
constellationSizes[i] = oldAdapter.constellationSizes[i];
equalizers[i] = oldAdapter.equalizers[i];
}
deviceChannel = oldAdapter.deviceChannel;
Adapter.cpp
#include "Adapter.h"
////////////////////////////////////////////////////////////////////////
// PROJECT: WGLAN Software Simulation
// FILE:
Adapter.cpp
// AUTHOR:
Eladio Arvelo <earvelo@alum.mit.edu>
// MODS:
Created file -- 11.29.99
//
Implemented several helper functions -- 11.30.99
//
Implemented additional methods -- 12.02.99
//
Completed implementation of all methods -- 12.04.99
//
Compiled class successfully -- 12.04.99
//
Replaced OfdmSymbol& with OfdmSymbol* -- 12.08.99
//
Implemented IFFT and FFT algorithms -- 12.09.99
//
Changed scaling in IFFT and FFT algorithms -- 02.03.00
//
Modified handling of error statistics -- 02.08.00
////////////////////////////////////////////////////////////////////////
// session profiles parameters
txActive = oldAdapter.txActive;
rvActive = oldAdapter.rvActive;
txPayload = oldAdapter.txPayload;
for (i=0; i < SUBCARRIERS; i++)
{
symbolErrors[i] = oldAdapter.symbolErrors[i];
codedBitErrors[i] = oldAdapter.codedBitErrors[i];
uncodedBitErrors[i] = oldAdapter.uncodedBitErrors[i];
bitsReceived[i] = oldAdapter.bitsReceived[i];
symbolsReceived[i] = oldAdapter.symbolsReceived[i];
}
}
////////////////////////////////////
// Constructors
////////////////////////////////////
////////////////////////////////////
// Observer Methods
////////////////////////////////////
Adapter::Adapter(int deviceID, double distance, string channelShape,
double channelVariance)
{
int i;
bool Adapter::isMaster()
{
return isMasterDevice;
// device parameters
this->deviceID = deviceID;
isMasterDevice = false;
for (i=0; i < SUBCARRIERS; i++)
{
constellationSizes[i] = 0;
equalizers[i] = 0;
}
deviceChannel = Channel(distance, channelShape, channelVariance);
}
int Adapter::getDeviceID()
{
return deviceID; }
double Adapter::getDistance()
{
return deviceChannel.getDistance();
}
int Adapter::getConstellationSize(int index)
{
return constellationSizes[index]; }
// session profile parameters
txActive = rvActive = false;
txPayload = 0;
for (i=0; i < SUBCARRIERS; i++)
{
symbolErrors[i] = codedBitErrors[i] = uncodedBitErrors[i] = 0;
bitsReceived[i] = symbolsReceived[i] = 0;
}
complex<double> Adapter::getEqualizer(int index)
{
// this method must be deprecated once pilot symbols are supported
if (index < SUBCARRIERS)
return equalizers[index];
else
{
cerr << "Index is OUT OF BOUND in Adapter::getEqualizer" << endl;
return 0;
}
}
}
Adapter::Adapter(const Adapter& oldAdapter)
{
int i;
int Adapter::getSubcarrierInterference(int index)
{
return deviceChannel.getInterference(index);
// device parameters
deviceID = oldAdapter.deviceID;
134
}
int Adapter::getChannelLength()
{
return deviceChannel.getResponseLength();
long int Adapter::getUncodedBitErrors(int index)
{
long int runningSum = 0;
}
complex<double> Adapter::getChannelSample(int index)
{
return deviceChannel.getSample(index);
}
double Adapter::getChannelVariance()
{
return deviceChannel.getVariance();
string Adapter::getChannelShape()
{
return deviceChannel.getShape();
if (index == -1)
{
for (int i=0; i < SUBCARRIERS; i++)
runningSum += uncodedBitErrors[i];
return runningSum;
}
}
if (index < SUBCARRIERS)
return uncodedBitErrors[index];
else
{
cerr << "Index is OUT OF BOUND in Adapter::getUncodedBitErrors" <<
endl;
return 0;
}
}
}
long int Adapter::getSymbolErrors(int index)
{
long int runningSum = 0;
if (index == -1)
{
for (int i=0; i < SUBCARRIERS; i++)
runningSum += symbolErrors[i];
return runningSum;
}
long int Adapter::getBitsReceived(int index)
{
long int runningSum = 0;
if (index == -1)
{
for (int i=0; i < SUBCARRIERS; i++)
runningSum += bitsReceived[i];
return runningSum;
}
if (index < SUBCARRIERS)
return symbolErrors[index];
else
{
cerr << "Index is OUT OF BOUND in Adapter::getSymbolErrors" <<
endl;
return 0;
}
}
if (index < SUBCARRIERS)
return bitsReceived[index];
else
{
cerr << "Index is OUT OF BOUND in Adapter::getBitsReceived" <<
endl;
return 0;
}
}
long int Adapter::getCodedBitErrors(int index)
{
long int runningSum = 0;
if (index == -1)
{
for (int i=0; i < SUBCARRIERS; i++)
runningSum += codedBitErrors[i];
return runningSum;
}
long int Adapter::getSymbolsReceived(int index)
{
long int runningSum = 0;
if (index == -1)
{
for (int i=0; i < SUBCARRIERS; i++)
runningSum += symbolsReceived[i];
return runningSum;
}
if (index < SUBCARRIERS)
return codedBitErrors[index];
else
{
cerr << "Index is OUT OF BOUND in Adapter::getCodedBitErrors" <<
endl;
return 0;
}
}
if (index < SUBCARRIERS)
return symbolsReceived[index];
else
{
135
cerr << "Index is OUT OF BOUND in Adapter::getSymbolsReceived" <<
{
endl;
// create, process, and send OFDM symbol
createSymbol(receiverID, time, symbolPtr);
encodeSymbol(symbolPtr);
qamSymbol(symbolPtr);
modulateSymbol(symbolPtr);
guardSymbol(symbolPtr);
return symbolPtr;
return 0;
}
}
////////////////////////////////////
// Mutator Methods
////////////////////////////////////
}
void Adapter::initiateTransmission(bool finiteLength, long int length)
{
// the correct implementation of this method has been postponed
txActive = true;
txFiniteload = finiteLength;
txPayload = length;
}
OfdmSymbol* Adapter::transmitPilotSymbol(int receiverID, int time,
OfdmSymbol *symbolPtr)
{
// create default OFDM Symbol, contents of uncoded and coded bits is
irrelevant
createSymbol(receiverID, time, symbolPtr);
// mark symbol as a pilot
(*symbolPtr).setPilot();
void Adapter::initiateReception()
{
// the correct implementation of this method has been postponed
int i;
rvActive = true;
// enter pilot points, which are the highest energy first-quadrant
constellation
// points that have the same magnitude in both dimensions
for (int i=0; i < SUBCARRIERS; i++)
{
if (constellationSizes[i] == 0)
{
// subcarrier is not in use
(*symbolPtr).putQamSample(i, complex<double>(0,0));
}
else if (constellationSizes[i] == 1)
{
// subcarrier uses a 2-point constellation
(*symbolPtr).putQamSample(i, complex<double>(DMIN1,0));
}
else if (constellationSizes[i] == 2)
{
// subcarrier uses a 4-point constellation
(*symbolPtr).putQamSample(i, complex<double>(DMIN2, DMIN2));
for (i=0; i < SUBCARRIERS; i++)
{
symbolErrors[i] = codedBitErrors[i] = uncodedBitErrors[i] = 0;
bitsReceived[i] = symbolsReceived[i] = 0;
}
}
void Adapter::terminateTransmission()
{
txActive = false; }
void Adapter::terminateReception()
{
rvActive = false; }
}
else if (constellationSizes[i] == 3)
{
// subcarrier uses a 8-point constellation
(*symbolPtr).putQamSample(i, complex<double>(DMIN3, DMIN3));
}
else if (constellationSizes[i] == 4)
{
// subcarrier uses a 16-point constellation
(*symbolPtr).putQamSample(i, complex<double>(3*DMIN4,
3*DMIN4));
}
else if (constellationSizes[i] == 5)
{
// subcarrier uses a 32-point constellation
(*symbolPtr).putQamSample(i, complex<double>(3*DMIN5,
3*DMIN5));
}
void Adapter::setConstellationSize(int index, int size)
{
if (index < SUBCARRIERS)
constellationSizes[index] = size;
else
cerr << "Index is OUT OF BOUND in Adapter::setConstellation" <<
endl;
}
OfdmSymbol* Adapter::transmitDataSymbol(int receiverID, int time,
OfdmSymbol *symbolPtr)
136
else if (constellationSizes[i] == 6)
{
// subcarrier uses a 64-point constellation
(*symbolPtr).putQamSample(i, complex<double>(7*DMIN6,
7*DMIN6));
}
else if (constellationSizes[i] == 7)
{
// subcarrier uses a 128-point constellation
(*symbolPtr).putQamSample(i, complex<double>(9*DMIN7,
9*DMIN7));
}
else if (constellationSizes[i] == 8)
{
// subcarrier uses a 256-point constellation
(*symbolPtr).putQamSample(i, complex<double>(15*DMIN8,
15*DMIN8));
}
else
{
// subcarrier has an invalid constellation size
cerr << "Constellation size TOO LARGE in Adapter::qamSymbol()"
<< endl;
}
}
void Adapter::changeChannelShape(string newShape)
{
deviceChannel.changeShape(newShape);
}
void Adapter::changeChannelInterference()
{
deviceChannel.changeInterference();
}
////////////////////////////////////
// Destructor
////////////////////////////////////
Adapter::~Adapter()
{ }
////////////////////////////////////
// Helper Functions
////////////////////////////////////
OfdmSymbol* Adapter::createSymbol(int recID, int time, OfdmSymbol
*symbolPtr)
{
int uncodedBitCapacity = 0;
int codedBitCapacity = 0;
// finish processing OFDM symbol as usual
modulateSymbol(symbolPtr);
guardSymbol(symbolPtr);
return symbolPtr;
}
// determine maximum number of coded bits that can be sent per OFDM
symbol
for (int i=0; i < SUBCARRIERS; i++)
codedBitCapacity += constellationSizes[i];
OfdmSymbol* Adapter::receiveSymbol(OfdmSymbol *symbolPtr, bool noise,
bool analyze)
{
if ((*symbolPtr).isPilot())
return receivePilotSymbol(symbolPtr, noise);
else
{
// receive, process, and reconstruct data from OFDM symbol
corruptSymbol(symbolPtr, noise);
demodulateSymbol(symbolPtr);
sliceSymbol(symbolPtr, analyze);
decodeSymbol(symbolPtr);
// determine maximum number of uncoded bits that can be sent per OFDM
symbol
uncodedBitCapacity = codedBitCapacity * (double) CODING_BITS_IN /
(double) CODING_BITS_OUT;
// create new empty symbol
delete symbolPtr;
symbolPtr = new OfdmSymbol(deviceID, recID, time, uncodedBitCapacity,
codedBitCapacity);
assert(symbolPtr != NULL);
// update error statistics if requested to do so
if (analyze == true)
analyzeSymbol(symbolPtr);
// fill symbol with random bits
(*symbolPtr).beginUncodedPacking();
while (!(*symbolPtr).isUncodedPackingFinished())
(*symbolPtr).putUncodedBit(rand() % 2);
return symbolPtr;
}
return symbolPtr;
}
}
void Adapter::changeChannelVariance(double newVariance)
{
deviceChannel.changeVariance(newVariance); }
OfdmSymbol* Adapter::encodeSymbol(OfdmSymbol *symbolPtr)
{
// currently there's no coding scheme built into the design, so:
137
(*symbolPtr).beginUncodedRetrieval();
(*symbolPtr).beginCodedPacking();
// use first quadrant to determine point's magnitudes
if (!bit1)
(*symbolPtr).putQamSample(i, complex<double>(signX*DMIN3,
signY*DMIN3));
else
(*symbolPtr).putQamSample(i, complex<double>(3*signX*DMIN3,
signY*DMIN3));
}
while (!(*symbolPtr).isCodedPackingFinished())
(*symbolPtr).putCodedBit((*symbolPtr).getUncodedBit());
return symbolPtr;
}
else if (constellationSizes[i] == 4)
{
// subcarrier uses a 16-point constellation
bit3 = (*symbolPtr).getCodedBit();
bit2 = (*symbolPtr).getCodedBit();
bit1 = (*symbolPtr).getCodedBit();
bit0 = (*symbolPtr).getCodedBit();
bit3 ? signX = -1 : signX = 1;
bit1 ? signY = -1 : signY = 1;
OfdmSymbol* Adapter::qamSymbol(OfdmSymbol *symbolPtr)
{
int signX, signY;
// by convention, leftmost bit is bit7 and rightmost bit is bit0
bool bit7, bit6, bit5, bit4, bit3, bit2, bit1, bit0;
// prepare symbol for retrieving coded bits
(*symbolPtr).beginCodedRetrieval();
// use first quadrant to determine point's magnitudes
if (!bit2 && !bit0)
(*symbolPtr).putQamSample(i, complex<double>(signX*DMIN4,
signY*DMIN4));
else if (bit2 && !bit0)
(*symbolPtr).putQamSample(i, complex<double>(3*signX*DMIN4,
signY*DMIN4));
else if (!bit2 && bit0)
(*symbolPtr).putQamSample(i, complex<double>(signX*DMIN4,
3*signY*DMIN4));
else
(*symbolPtr).putQamSample(i, complex<double>(3*signX*DMIN4,
3*signY*DMIN4));
}
// create a complex number point for each subcarrier
for (int i=0; i < SUBCARRIERS; i++)
{
// initialize sign variables to the first quadrant
signX = signY = 1;
if (constellationSizes[i] == 0)
{
// subcarrier is not in use
(*symbolPtr).putQamSample(i, complex<double>(0,0));
}
else if (constellationSizes[i] == 1)
{
// subcarrier uses a 2-point constellation
bit0 = (*symbolPtr).getCodedBit();
bit0 ? signX = -1 : signX = 1;
(*symbolPtr).putQamSample(i, complex<double>(signX*DMIN1,0));
}
else if (constellationSizes[i] == 5)
{
// subcarrier uses a 32-point constellation
bit4 = (*symbolPtr).getCodedBit();
bit3 = (*symbolPtr).getCodedBit();
bit2 = (*symbolPtr).getCodedBit();
bit1 = (*symbolPtr).getCodedBit();
bit0 = (*symbolPtr).getCodedBit();
else if (constellationSizes[i] == 2)
{
// subcarrier uses a 4-point constellation
bit1 = (*symbolPtr).getCodedBit();
bit0 = (*symbolPtr).getCodedBit();
bit1 ? signX = -1 : signX = 1;
bit0 ? signY = -1 : signY = 1;
(*symbolPtr).putQamSample(i, complex<double>(signX*DMIN2,
signY*DMIN2));
}
// determine point's quadrant
if (!bit4 && !bit3)
{ signX = 1; signY = 1; }
else if (!bit4 && bit3)
{ signX = -1; signY = 1; }
else if (bit4 && bit3)
{ signX = -1; signY = -1; }
else
{ signX = 1; signY = -1; }
else if (constellationSizes[i] == 3)
{
// subcarrier uses a 8-point constellation
bit2 = (*symbolPtr).getCodedBit();
bit1 = (*symbolPtr).getCodedBit();
bit0 = (*symbolPtr).getCodedBit();
bit2 ? signX = -1 : signX = 1;
bit0 ? signY = -1 : signY = 1;
// use first quadrant to determine point's magnitudes
if (!bit2 && !bit1 && !bit0)
(*symbolPtr).putQamSample(i, complex<double>(signX*DMIN5,
signY*DMIN5));
else if (!bit2 && bit1 && !bit0)
138
(*symbolPtr).putQamSample(i, complex<double>(signX*DMIN5,
3*signY*DMIN5));
else if (bit2 && bit1 && !bit0)
(*symbolPtr).putQamSample(i, complex<double>(signX*DMIN5,
5*signY*DMIN5));
else if (!bit2 && !bit1 && bit0)
(*symbolPtr).putQamSample(i, complex<double>(3*signX*DMIN5,
signY*DMIN5));
else if (!bit2 && bit1 && bit0)
(*symbolPtr).putQamSample(i, complex<double>(3*signX*DMIN5,
3*signY*DMIN5));
else if (bit2 && bit1 && bit0)
(*symbolPtr).putQamSample(i, complex<double>(3*signX*DMIN5,
5*signY*DMIN5));
else if (bit2 && !bit1 && !bit0)
(*symbolPtr).putQamSample(i, complex<double>(5*signX*DMIN5,
signY*DMIN5));
else
(*symbolPtr).putQamSample(i, complex<double>(5*signX*DMIN5,
3*signY*DMIN5));
}
else if (bit1 && bit0)
(*symbolPtr).putQamSample(i,
complex<double>(3*signX*DMIN6, 5*signY*DMIN6));
else
(*symbolPtr).putQamSample(i,
complex<double>(3*signX*DMIN6, 7*signY*DMIN6));
}
else if (bit4 && bit3)
{
// third column
if (!bit1 && !bit0)
(*symbolPtr).putQamSample(i,
complex<double>(5*signX*DMIN6, signY*DMIN6));
else if (!bit1 && bit0)
(*symbolPtr).putQamSample(i,
complex<double>(5*signX*DMIN6, 3*signY*DMIN6));
else if (bit1 && bit0)
(*symbolPtr).putQamSample(i,
complex<double>(5*signX*DMIN6, 5*signY*DMIN6));
else
(*symbolPtr).putQamSample(i,
complex<double>(5*signX*DMIN6, 7*signY*DMIN6));
}
else
{
// fourth column
if (!bit1 && !bit0)
(*symbolPtr).putQamSample(i,
complex<double>(7*signX*DMIN6, signY*DMIN6));
else if (!bit1 && bit0)
(*symbolPtr).putQamSample(i,
complex<double>(7*signX*DMIN6, 3*signY*DMIN6));
else if (bit1 && bit0)
(*symbolPtr).putQamSample(i,
complex<double>(7*signX*DMIN6, 5*signY*DMIN6));
else
(*symbolPtr).putQamSample(i,
complex<double>(7*signX*DMIN6, 7*signY*DMIN6));
}
}
else if (constellationSizes[i] == 6)
{
// subcarrier uses a 64-point constellation
bit5 = (*symbolPtr).getCodedBit();
bit4 = (*symbolPtr).getCodedBit();
bit3 = (*symbolPtr).getCodedBit();
bit2 = (*symbolPtr).getCodedBit();
bit1 = (*symbolPtr).getCodedBit();
bit0 = (*symbolPtr).getCodedBit();
bit5 ? signX = -1 : signX = 1;
bit2 ? signY = -1 : signY = 1;
// use first quadrant to determine point's magnitudes
if (!bit4 && !bit3)
{
// first column
if (!bit1 && !bit0)
(*symbolPtr).putQamSample(i,
complex<double>(signX*DMIN6, signY*DMIN6));
else if (!bit1 && bit0)
(*symbolPtr).putQamSample(i,
complex<double>(signX*DMIN6, 3*signY*DMIN6));
else if (bit1 && bit0)
(*symbolPtr).putQamSample(i,
complex<double>(signX*DMIN6, 5*signY*DMIN6));
else
(*symbolPtr).putQamSample(i,
complex<double>(signX*DMIN6, 7*signY*DMIN6));
}
else if (!bit4 && bit3)
{
// second column
if (!bit1 && !bit0)
(*symbolPtr).putQamSample(i,
complex<double>(3*signX*DMIN6, signY*DMIN6));
else if (!bit1 && bit0)
(*symbolPtr).putQamSample(i,
complex<double>(3*signX*DMIN6, 3*signY*DMIN6));
else if (constellationSizes[i] == 7)
{
// subcarrier uses a 128-point constellation
bit6 = (*symbolPtr).getCodedBit();
bit5 = (*symbolPtr).getCodedBit();
bit4 = (*symbolPtr).getCodedBit();
bit3 = (*symbolPtr).getCodedBit();
bit2 = (*symbolPtr).getCodedBit();
bit1 = (*symbolPtr).getCodedBit();
bit0 = (*symbolPtr).getCodedBit();
// determine point's quadrant
if (!bit6 && !bit5)
{ signX = 1; signY = 1; }
else if (!bit6 && bit5)
{ signX = -1; signY = 1; }
else if (bit6 && bit5)
{ signX = -1; signY = -1; }
else
139
{ signX = 1; signY = -1; }
else if (bit4 && !bit3 && !bit2 && bit1 && !bit0)
(*symbolPtr).putQamSample(i, complex<double>(7*signX*DMIN7,
3*signY*DMIN7));
else if (bit4 && !bit3 && bit2 && bit1 && !bit0)
(*symbolPtr).putQamSample(i, complex<double>(7*signX*DMIN7,
5*signY*DMIN7));
else if (bit4 && !bit3 && bit2 && !bit1 && !bit0)
(*symbolPtr).putQamSample(i, complex<double>(7*signX*DMIN7,
7*signY*DMIN7));
else if (bit4 && !bit3 && bit2 && !bit1 && bit0)
(*symbolPtr).putQamSample(i, complex<double>(7*signX*DMIN7,
9*signY*DMIN7));
else if (bit4 && !bit3 && !bit2 && !bit1 && bit0)
(*symbolPtr).putQamSample(i, complex<double>(9*signX*DMIN7,
signY*DMIN7));
else if (bit4 && !bit3 && !bit2 && bit1 && bit0)
(*symbolPtr).putQamSample(i, complex<double>(9*signX*DMIN7,
3*signY*DMIN7));
else if (bit4 && !bit3 && bit2 && bit1 && bit0)
(*symbolPtr).putQamSample(i, complex<double>(9*signX*DMIN7,
5*signY*DMIN7));
else if (bit4 && bit3 && !bit2 && bit1 && bit0)
(*symbolPtr).putQamSample(i, complex<double>(9*signX*DMIN7,
7*signY*DMIN7));
else if (bit4 && bit3 && !bit2 && !bit1 && bit0)
(*symbolPtr).putQamSample(i, complex<double>(9*signX*DMIN7,
9*signY*DMIN7));
else if (!bit4 && !bit3 && !bit2 && !bit1 && bit0)
(*symbolPtr).putQamSample(i, complex<double>(11*signX*DMIN7,
signY*DMIN7));
else if (!bit4 && !bit3 && !bit2 && bit1 && bit0)
(*symbolPtr).putQamSample(i, complex<double>(11*signX*DMIN7,
3*signY*DMIN7));
else if (!bit4 && !bit3 && bit2 && bit1 && bit0)
(*symbolPtr).putQamSample(i, complex<double>(11*signX*DMIN7,
5*signY*DMIN7));
else
(*symbolPtr).putQamSample(i, complex<double>(11*signX*DMIN7,
7*signY*DMIN7));
}
// use first quadrant to determine point's magnitudes
if (!bit4 && !bit3 && !bit2 && !bit1 && !bit0)
(*symbolPtr).putQamSample(i, complex<double>(signX*DMIN7,
signY*DMIN7));
else if (!bit4 && !bit3 && !bit2 && bit1 && !bit0)
(*symbolPtr).putQamSample(i, complex<double>(signX*DMIN7,
3*signY*DMIN7));
else if (!bit4 && !bit3 && bit2 && bit1 && !bit0)
(*symbolPtr).putQamSample(i, complex<double>(signX*DMIN7,
5*signY*DMIN7));
else if (!bit4 && !bit3 && bit2 && !bit1 && !bit0)
(*symbolPtr).putQamSample(i, complex<double>(signX*DMIN7,
7*signY*DMIN7));
else if (!bit4 && !bit3 && bit2 && !bit1 && bit0)
(*symbolPtr).putQamSample(i, complex<double>(signX*DMIN7,
9*signY*DMIN7));
else if (!bit4 && bit3 && bit2 && bit1 && bit0)
(*symbolPtr).putQamSample(i, complex<double>(signX*DMIN7,
11*signY*DMIN7));
else if (!bit4 && bit3 && !bit2 && !bit1 && !bit0)
(*symbolPtr).putQamSample(i, complex<double>(3*signX*DMIN7,
signY*DMIN7));
else if (!bit4 && bit3 && !bit2 && bit1 && !bit0)
(*symbolPtr).putQamSample(i, complex<double>(3*signX*DMIN7,
3*signY*DMIN7));
else if (!bit4 && bit3 && bit2 && bit1 && !bit0)
(*symbolPtr).putQamSample(i, complex<double>(3*signX*DMIN7,
5*signY*DMIN7));
else if (!bit4 && bit3 && bit2 && !bit1 && !bit0)
(*symbolPtr).putQamSample(i, complex<double>(3*signX*DMIN7,
7*signY*DMIN7));
else if (!bit4 && bit3 && bit2 && !bit1 && bit0)
(*symbolPtr).putQamSample(i, complex<double>(3*signX*DMIN7,
9*signY*DMIN7));
else if (!bit4 && bit3 && !bit2 && bit1 && bit0)
(*symbolPtr).putQamSample(i, complex<double>(3*signX*DMIN7,
11*signY*DMIN7));
else if (bit4 && bit3 && !bit2 && !bit1 && !bit0)
(*symbolPtr).putQamSample(i, complex<double>(5*signX*DMIN7,
signY*DMIN7));
else if (bit4 && bit3 && !bit2 && bit1 && !bit0)
(*symbolPtr).putQamSample(i, complex<double>(5*signX*DMIN7,
3*signY*DMIN7));
else if (bit4 && bit3 && bit2 && bit1 && !bit0)
(*symbolPtr).putQamSample(i, complex<double>(5*signX*DMIN7,
5*signY*DMIN7));
else if (bit4 && bit3 && bit2 && !bit1 && !bit0)
(*symbolPtr).putQamSample(i, complex<double>(5*signX*DMIN7,
7*signY*DMIN7));
else if (bit4 && bit3 && bit2 && !bit1 && bit0)
(*symbolPtr).putQamSample(i, complex<double>(5*signX*DMIN7,
9*signY*DMIN7));
else if (bit4 && bit3 && bit2 && bit1 && bit0)
(*symbolPtr).putQamSample(i, complex<double>(5*signX*DMIN7,
11*signY*DMIN7));
else if (bit4 && !bit3 && !bit2 && !bit1 && !bit0)
(*symbolPtr).putQamSample(i, complex<double>(7*signX*DMIN7,
signY*DMIN7));
else if (constellationSizes[i] == 8)
{
// subcarrier uses a 256-point constellation
bit7 = (*symbolPtr).getCodedBit();
bit6 = (*symbolPtr).getCodedBit();
bit5 = (*symbolPtr).getCodedBit();
bit4 = (*symbolPtr).getCodedBit();
bit3 = (*symbolPtr).getCodedBit();
bit2 = (*symbolPtr).getCodedBit();
bit1 = (*symbolPtr).getCodedBit();
bit0 = (*symbolPtr).getCodedBit();
bit7 ? signX = -1 : signX = 1;
bit3 ? signY = -1 : signY = 1;
// use first quadrant to determine point's magnitudes
if (!bit6 && !bit5 && !bit4)
{
// first column
if (!bit2 && !bit1 && !bit0)
140
(*symbolPtr).putQamSample(i,
complex<double>(signX*DMIN8, signY*DMIN8));
else if (!bit2 && !bit1 && bit0)
(*symbolPtr).putQamSample(i,
complex<double>(signX*DMIN8, 3*signY*DMIN8));
else if (!bit2 && bit1 && bit0)
(*symbolPtr).putQamSample(i,
complex<double>(signX*DMIN8, 5*signY*DMIN8));
else if (!bit2 && bit1 && !bit0)
(*symbolPtr).putQamSample(i,
complex<double>(signX*DMIN8, 7*signY*DMIN8));
else if (bit2 && bit1 && !bit0)
(*symbolPtr).putQamSample(i,
complex<double>(signX*DMIN8, 9*signY*DMIN8));
else if (bit2 && bit1 && bit0)
(*symbolPtr).putQamSample(i,
complex<double>(signX*DMIN8, 11*signY*DMIN8));
else if (bit2 && !bit1 && bit0)
(*symbolPtr).putQamSample(i,
complex<double>(signX*DMIN8, 13*signY*DMIN8));
else
(*symbolPtr).putQamSample(i,
complex<double>(signX*DMIN8, 15*signY*DMIN8));
}
else if (!bit6 && !bit5 && bit4)
{
// second column
if (!bit2 && !bit1 && !bit0)
(*symbolPtr).putQamSample(i,
complex<double>(3*signX*DMIN8, signY*DMIN8));
else if (!bit2 && !bit1 && bit0)
(*symbolPtr).putQamSample(i,
complex<double>(3*signX*DMIN8, 3*signY*DMIN8));
else if (!bit2 && bit1 && bit0)
(*symbolPtr).putQamSample(i,
complex<double>(3*signX*DMIN8, 5*signY*DMIN8));
else if (!bit2 && bit1 && !bit0)
(*symbolPtr).putQamSample(i,
complex<double>(3*signX*DMIN8, 7*signY*DMIN8));
else if (bit2 && bit1 && !bit0)
(*symbolPtr).putQamSample(i,
complex<double>(3*signX*DMIN8, 9*signY*DMIN8));
else if (bit2 && bit1 && bit0)
(*symbolPtr).putQamSample(i,
complex<double>(3*signX*DMIN8, 11*signY*DMIN8));
else if (bit2 && !bit1 && bit0)
(*symbolPtr).putQamSample(i,
complex<double>(3*signX*DMIN8, 13*signY*DMIN8));
else
(*symbolPtr).putQamSample(i,
complex<double>(3*signX*DMIN8, 15*signY*DMIN8));
}
else if (!bit6 && bit5 && bit4)
{
// third column
if (!bit2 && !bit1 && !bit0)
(*symbolPtr).putQamSample(i,
complex<double>(5*signX*DMIN8, signY*DMIN8));
else if (!bit2 && !bit1 && bit0)
(*symbolPtr).putQamSample(i,
complex<double>(5*signX*DMIN8, 3*signY*DMIN8));
else if (!bit2 && bit1 && bit0)
(*symbolPtr).putQamSample(i,
complex<double>(5*signX*DMIN8, 5*signY*DMIN8));
else if (!bit2 && bit1 && !bit0)
(*symbolPtr).putQamSample(i,
complex<double>(5*signX*DMIN8, 7*signY*DMIN8));
else if (bit2 && bit1 && !bit0)
(*symbolPtr).putQamSample(i,
complex<double>(5*signX*DMIN8, 9*signY*DMIN8));
else if (bit2 && bit1 && bit0)
(*symbolPtr).putQamSample(i,
complex<double>(5*signX*DMIN8, 11*signY*DMIN8));
else if (bit2 && !bit1 && bit0)
(*symbolPtr).putQamSample(i,
complex<double>(5*signX*DMIN8, 13*signY*DMIN8));
else
(*symbolPtr).putQamSample(i,
complex<double>(5*signX*DMIN8, 15*signY*DMIN8));
}
else if (!bit6 & bit5 && !bit4)
{
// fourth column
if (!bit2 && !bit1 && !bit0)
(*symbolPtr).putQamSample(i,
complex<double>(7*signX*DMIN8, signY*DMIN8));
else if (!bit2 && !bit1 && bit0)
(*symbolPtr).putQamSample(i,
complex<double>(7*signX*DMIN8, 3*signY*DMIN8));
else if (!bit2 && bit1 && bit0)
(*symbolPtr).putQamSample(i,
complex<double>(7*signX*DMIN8, 5*signY*DMIN8));
else if (!bit2 && bit1 && !bit0)
(*symbolPtr).putQamSample(i,
complex<double>(7*signX*DMIN8, 7*signY*DMIN8));
else if (bit2 && bit1 && !bit0)
(*symbolPtr).putQamSample(i,
complex<double>(7*signX*DMIN8, 9*signY*DMIN8));
else if (bit2 && bit1 && bit0)
(*symbolPtr).putQamSample(i,
complex<double>(7*signX*DMIN8, 11*signY*DMIN8));
else if (bit2 && !bit1 && bit0)
(*symbolPtr).putQamSample(i,
complex<double>(7*signX*DMIN8, 13*signY*DMIN8));
else
(*symbolPtr).putQamSample(i,
complex<double>(7*signX*DMIN8, 15*signY*DMIN8));
}
else if (bit6 && bit5 && !bit4)
{
// fifth column
if (!bit2 && !bit1 && !bit0)
(*symbolPtr).putQamSample(i,
complex<double>(9*signX*DMIN8, signY*DMIN8));
else if (!bit2 && !bit1 && bit0)
(*symbolPtr).putQamSample(i,
complex<double>(9*signX*DMIN8, 3*signY*DMIN8));
else if (!bit2 && bit1 && bit0)
141
(*symbolPtr).putQamSample(i,
complex<double>(9*signX*DMIN8, 5*signY*DMIN8));
else if (!bit2 && bit1 && !bit0)
(*symbolPtr).putQamSample(i,
complex<double>(9*signX*DMIN8, 7*signY*DMIN8));
else if (bit2 && bit1 && !bit0)
(*symbolPtr).putQamSample(i,
complex<double>(9*signX*DMIN8, 9*signY*DMIN8));
else if (bit2 && bit1 && bit0)
(*symbolPtr).putQamSample(i,
complex<double>(9*signX*DMIN8, 11*signY*DMIN8));
else if (bit2 && !bit1 && bit0)
(*symbolPtr).putQamSample(i,
complex<double>(9*signX*DMIN8, 13*signY*DMIN8));
else
(*symbolPtr).putQamSample(i,
complex<double>(9*signX*DMIN8, 15*signY*DMIN8));
}
else if (bit6 && bit5 && bit4)
{
// sixth column
if (!bit2 && !bit1 && !bit0)
(*symbolPtr).putQamSample(i,
complex<double>(11*signX*DMIN8, signY*DMIN8));
else if (!bit2 && !bit1 && bit0)
(*symbolPtr).putQamSample(i,
complex<double>(11*signX*DMIN8, 3*signY*DMIN8));
else if (!bit2 && bit1 && bit0)
(*symbolPtr).putQamSample(i,
complex<double>(11*signX*DMIN8, 5*signY*DMIN8));
else if (!bit2 && bit1 && !bit0)
(*symbolPtr).putQamSample(i,
complex<double>(11*signX*DMIN8, 7*signY*DMIN8));
else if (bit2 && bit1 && !bit0)
(*symbolPtr).putQamSample(i,
complex<double>(11*signX*DMIN8, 9*signY*DMIN8));
else if (bit2 && bit1 && bit0)
(*symbolPtr).putQamSample(i,
complex<double>(11*signX*DMIN8, 11*signY*DMIN8));
else if (bit2 && !bit1 && bit0)
(*symbolPtr).putQamSample(i,
complex<double>(11*signX*DMIN8, 13*signY*DMIN8));
else
(*symbolPtr).putQamSample(i,
complex<double>(11*signX*DMIN8, 15*signY*DMIN8));
}
else if (bit6 && !bit5 && bit4)
{
// seventh column
if (!bit2 && !bit1 && !bit0)
(*symbolPtr).putQamSample(i,
complex<double>(13*signX*DMIN8, signY*DMIN8));
else if (!bit2 && !bit1 && bit0)
(*symbolPtr).putQamSample(i,
complex<double>(13*signX*DMIN8, 3*signY*DMIN8));
else if (!bit2 && bit1 && bit0)
(*symbolPtr).putQamSample(i,
complex<double>(13*signX*DMIN8, 5*signY*DMIN8));
else if (!bit2 && bit1 && !bit0)
(*symbolPtr).putQamSample(i,
complex<double>(13*signX*DMIN8, 7*signY*DMIN8));
else if (bit2 && bit1 && !bit0)
(*symbolPtr).putQamSample(i,
complex<double>(13*signX*DMIN8, 9*signY*DMIN8));
else if (bit2 && bit1 && bit0)
(*symbolPtr).putQamSample(i,
complex<double>(13*signX*DMIN8, 11*signY*DMIN8));
else if (bit2 && !bit1 && bit0)
(*symbolPtr).putQamSample(i,
complex<double>(13*signX*DMIN8, 13*signY*DMIN8));
else
(*symbolPtr).putQamSample(i,
complex<double>(13*signX*DMIN8, 15*signY*DMIN8));
}
else
{
// eighth column
if (!bit2 && !bit1 && !bit0)
(*symbolPtr).putQamSample(i,
complex<double>(15*signX*DMIN8, signY*DMIN8));
else if (!bit2 && !bit1 && bit0)
(*symbolPtr).putQamSample(i,
complex<double>(15*signX*DMIN8, 3*signY*DMIN8));
else if (!bit2 && bit1 && bit0)
(*symbolPtr).putQamSample(i,
complex<double>(15*signX*DMIN8, 5*signY*DMIN8));
else if (!bit2 && bit1 && !bit0)
(*symbolPtr).putQamSample(i,
complex<double>(15*signX*DMIN8, 7*signY*DMIN8));
else if (bit2 && bit1 && !bit0)
(*symbolPtr).putQamSample(i,
complex<double>(15*signX*DMIN8, 9*signY*DMIN8));
else if (bit2 && bit1 && bit0)
(*symbolPtr).putQamSample(i,
complex<double>(15*signX*DMIN8, 11*signY*DMIN8));
else if (bit2 && !bit1 && bit0)
(*symbolPtr).putQamSample(i,
complex<double>(15*signX*DMIN8, 13*signY*DMIN8));
else
(*symbolPtr).putQamSample(i,
complex<double>(15*signX*DMIN8, 15*signY*DMIN8));
}
}
else
{
// subcarrier has an invalid constellation size
cerr << "Constellation size TOO LARGE in Adapter::qamSymbol()"
<< endl;
}
}
return symbolPtr;
}
OfdmSymbol* Adapter::modulateSymbol(OfdmSymbol *symbolPtr)
{
142
// this method uses the IFFT algorithm from numerical recipes:
//
//
m=LM-1
// y[n] = (1/sqrt(LM)) * SUM
Zm * exp(j*2pi*m*n / L*M)
for n
in the range [0, LM-1]
//
m=0
//
// where: L = SAMPLING, M = SUBCARRIERS, and
//
Zm is zero for m in the range [M, LM-1]
// this method implements the FFT algorithm from numerical recipes:
//
//
m=LM-1
// y[n] = (1/sqrt(LM)) * SUM
Zm * exp(-j*2pi*m*n / L*M)
for n
in the range [0, M-1]
//
m=0
//
// where: L = SAMPLING, M = SUBCARRIERS.
int i;
double scaleFactor;
double data[2*SUBCARRIERS*SAMPLING];
int i;
double scaleFactor;
double data[2*SUBCARRIERS*SAMPLING];
// first we initialize the array passed to the dfour1 function
for (i=GUARD_SAMPLES; i < SUBCARRIERS*SAMPLING + GUARD_SAMPLES; i++)
{
data[2*(i-GUARD_SAMPLES)] =
(*symbolPtr).getCorruptedSample(i).real();
data[2*(i-GUARD_SAMPLES)+1] =
(*symbolPtr).getCorruptedSample(i).imag();
}
// first we initialize the arrays passed to Matlab
for (i=0; i < SUBCARRIERS; i++)
{
data[2*i] = (*symbolPtr).getQamSample(i).real();
data[2*i+1] = (*symbolPtr).getQamSample(i).imag();
}
for (i=SUBCARRIERS; i < SUBCARRIERS*SAMPLING; i++)
{
data[2*i] = 0;
data[2*i+1] = 0;
}
// next we compute the forward fast Fourier transform
dfour1(data-1, SUBCARRIERS*SAMPLING, -1);
// scale samples by 1/sqrt(N) and restore them to our standard data
structure
scaleFactor = sqrt(SUBCARRIERS*SAMPLING);
for (i=0; i < SUBCARRIERS; i++)
(*symbolPtr).putDemodulatedSample(i,
complex<double>(data[2*i]/scaleFactor, data[2*i+1]/scaleFactor));
// compute the inverse fast Fourier transform, watch out for function
arguments:
// array index must be decreased by one, isign==-1 is forward FFT
dfour1(data-1, SUBCARRIERS*SAMPLING, 1);
// scale samples by 1/sqrt(N) and restore them to our standard data
structure
scaleFactor = sqrt(SUBCARRIERS*SAMPLING);
for (i=0; i < SUBCARRIERS*SAMPLING; i++)
(*symbolPtr).putModulatedSample(i,
complex<double>(data[2*i]/scaleFactor, data[2*i+1]/scaleFactor));
return symbolPtr;
}
OfdmSymbol* Adapter::sliceSymbol(OfdmSymbol *symbolPtr, bool analyze)
{
int signX, signY;
double lengthX, lengthY;
complex<double> equalized;
double equalizedX, equalizedY;
return symbolPtr;
}
OfdmSymbol* Adapter::guardSymbol(OfdmSymbol *symbolPtr)
{
(*symbolPtr).guardModulatedSamples();
return symbolPtr;
}
// by convention, leftmost bit is bit7 and rightmost bit is bit0
bool bit7, bit6, bit5, bit4, bit3, bit2, bit1, bit0;
// prepare symbol for retrieving coded bits
(*symbolPtr).beginSlicedPacking();
// prepare symbol to analyze symbol error rate
(*symbolPtr).beginCodedRetrieval();
OfdmSymbol* Adapter::corruptSymbol(OfdmSymbol *symbolPtr, bool noise)
{
return deviceChannel.convolveSymbol(symbolPtr, noise);
}
// create a complex number point for each subcarrier
for (int i=0; i < SUBCARRIERS; i++)
{
// initialize sign variables to the first quadrant
signX = signY = 1;
OfdmSymbol* Adapter::demodulateSymbol(OfdmSymbol *symbolPtr)
{
if (constellationSizes[i] == 0)
143
{
// subcarrier is not in use
// update symbol error statistics
if (analyze)
{
if (((*symbolPtr).getCodedBit() != bit2) ||
((*symbolPtr).getCodedBit() != bit1) ||
((*symbolPtr).getCodedBit() != bit0))
symbolErrors[i] = symbolErrors[i] + 1;
}
}
}
else if (constellationSizes[i] == 1)
{
// subcarrier uses a 2-point constellation
equalized = (*symbolPtr).getDemodulatedSample(i) *
equalizers[i];
equalizedX = equalized.real();
(equalizedX >= 0) ? bit0 = 0 : bit0 = 1;
(*symbolPtr).putSlicedBit(bit0);
else if (constellationSizes[i] == 4)
{
// subcarrier uses a 16-point constellation
equalized = (*symbolPtr).getDemodulatedSample(i) *
equalizers[i];
equalizedX = equalized.real();
equalizedY = equalized.imag();
(equalizedX >= 0) ? signX = 1 : signX = -1;
(equalizedY >= 0) ? signY = 1 : signY = -1;
lengthX = equalizedX * signX / DMIN4;
lengthY = equalizedY * signY / DMIN4;
// update symbol error statistics
if (analyze)
{
if ((*symbolPtr).getCodedBit() != bit0)
symbolErrors[i] = symbolErrors[i] + 1;
}
}
else if (constellationSizes[i] == 2)
{
// subcarrier uses a 4-point constellation
equalized = (*symbolPtr).getDemodulatedSample(i) *
equalizers[i];
equalizedX = equalized.real();
equalizedY = equalized.imag();
(equalizedX >= 0) ? bit1 = 0 : bit1 = 1;
(equalizedY >= 0) ? bit0 = 0 : bit0 = 1;
(*symbolPtr).putSlicedBit(bit1);
(*symbolPtr).putSlicedBit(bit0);
(signX == 1) ?
(signY == 1) ?
(lengthX <= 2)
(lengthY <= 2)
bit3 =
bit1 =
? bit2
? bit0
0
0
=
=
:
:
0
0
bit3 =
bit1 =
: bit2
: bit0
1;
1;
= 1;
= 1;
(*symbolPtr).putSlicedBit(bit3);
(*symbolPtr).putSlicedBit(bit2);
(*symbolPtr).putSlicedBit(bit1);
(*symbolPtr).putSlicedBit(bit0);
// update symbol error statistics
if (analyze)
{
if (((*symbolPtr).getCodedBit() != bit1) ||
((*symbolPtr).getCodedBit() != bit0))
symbolErrors[i] = symbolErrors[i] + 1;
}
}
// update symbol error statistics
if (analyze)
{
if (((*symbolPtr).getCodedBit() != bit3) ||
((*symbolPtr).getCodedBit() != bit2) ||
((*symbolPtr).getCodedBit() != bit1) ||
((*symbolPtr).getCodedBit() != bit0))
symbolErrors[i] = symbolErrors[i] + 1;
}
}
else if (constellationSizes[i] == 3)
{
// subcarrier uses a 8-point constellation
equalized = (*symbolPtr).getDemodulatedSample(i) *
equalizers[i];
equalizedX = equalized.real();
equalizedY = equalized.imag();
(equalizedX >= 0) ? signX = 1 : signX = -1;
(equalizedY >= 0) ? signY = 1 : signY = -1;
lengthX = equalizedX * signX / DMIN3;
else if (constellationSizes[i] == 5)
{
// subcarrier uses a 32-point constellation
equalized = (*symbolPtr).getDemodulatedSample(i) *
equalizers[i];
equalizedX = equalized.real();
equalizedY = equalized.imag();
(equalizedX >= 0) ? signX = 1 : signX = -1;
(equalizedY >= 0) ? signY = 1 : signY = -1;
lengthX = equalizedX * signX / DMIN5;
lengthY = equalizedY * signY / DMIN5;
(signX == 1) ? bit2 = 0 : bit2 = 1;
(signY == 1) ? bit0 = 0 : bit0 = 1;
(lengthX <= 2) ? bit1 = 0 : bit1 = 1;
if (signX==1 && signY==1)
{ bit4 = 0; bit3 = 0; }
else if (signX==-1 && signY==1)
{ bit4 = 0; bit3 = 1; }
(*symbolPtr).putSlicedBit(bit2);
(*symbolPtr).putSlicedBit(bit1);
(*symbolPtr).putSlicedBit(bit0);
144
else if (signX==-1 && signY==-1)
{ bit4 = 1; bit3 = 1; }
else
{ bit4 = 1; bit3 = 0; }
if (lengthX <= 2)
{
// first column
if (lengthY <= 2)
{ bit2 = 0; bit1
else if (lengthY <=
{ bit2 = 0; bit1
else
{ bit2 = 1; bit1
}
else if (lengthX <= 4)
{
// second column
if (lengthY <= 2)
{ bit2 = 0; bit1
else if (lengthY <=
{ bit2 = 0; bit1
else
{ bit2 = 1; bit1
}
else
{
// third column
if (lengthY <= 2)
{ bit2 = 1; bit1
else
{ bit2 = 1; bit1
}
(equalizedY >= 0) ? signY = 1 : signY = -1;
lengthX = equalizedX * signX / DMIN6;
lengthY = equalizedY * signY / DMIN6;
(signX == 1) ? bit5 = 0 : bit5 = 1;
(signY == 1) ? bit2 = 0 : bit2 = 1;
if (lengthX <= 2)
{ bit4 = 0; bit3 = 0;
else if (lengthX <= 4)
{ bit4 = 0; bit3 = 1;
else if (lengthX <= 6)
{ bit4 = 1; bit3 = 1;
else
{ bit4 = 1; bit3 = 0;
= 0; bit0 = 0; }
4)
= 1; bit0 = 0; }
= 1; bit0 = 0; }
if (lengthY <= 2)
{ bit1 = 0; bit0 = 0;
else if (lengthY <= 4)
{ bit1 = 0; bit0 = 1;
else if (lengthY <= 6)
{ bit1 = 1; bit0 = 1;
else
{ bit1 = 1; bit0 = 0;
= 0; bit0 = 1; }
4)
= 1; bit0 = 1; }
= 1; bit0 = 1; }
}
}
}
}
}
}
}
}
(*symbolPtr).putSlicedBit(bit5);
(*symbolPtr).putSlicedBit(bit4);
(*symbolPtr).putSlicedBit(bit3);
(*symbolPtr).putSlicedBit(bit2);
(*symbolPtr).putSlicedBit(bit1);
(*symbolPtr).putSlicedBit(bit0);
= 0; bit0 = 0; }
= 0; bit0 = 1; }
// update symbol error statistics
if (analyze)
{
if (((*symbolPtr).getCodedBit() != bit5) ||
((*symbolPtr).getCodedBit() != bit4) ||
((*symbolPtr).getCodedBit() != bit3) ||
((*symbolPtr).getCodedBit() != bit2) ||
((*symbolPtr).getCodedBit() != bit1) ||
((*symbolPtr).getCodedBit() != bit0))
symbolErrors[i] = symbolErrors[i] + 1;
}
}
(*symbolPtr).putSlicedBit(bit4);
(*symbolPtr).putSlicedBit(bit3);
(*symbolPtr).putSlicedBit(bit2);
(*symbolPtr).putSlicedBit(bit1);
(*symbolPtr).putSlicedBit(bit0);
// update symbol error statistics
if (analyze)
{
if (((*symbolPtr).getCodedBit() != bit4) ||
((*symbolPtr).getCodedBit() != bit3) ||
((*symbolPtr).getCodedBit() != bit2) ||
((*symbolPtr).getCodedBit() != bit1) ||
((*symbolPtr).getCodedBit() != bit0))
symbolErrors[i] = symbolErrors[i] + 1;
}
}
else if (constellationSizes[i] == 7)
{
// subcarrier uses a 128-point constellation
equalized = (*symbolPtr).getDemodulatedSample(i) *
equalizers[i];
equalizedX = equalized.real();
equalizedY = equalized.imag();
(equalizedX >= 0) ? signX = 1 : signX = -1;
(equalizedY >= 0) ? signY = 1 : signY = -1;
lengthX = equalizedX * signX / DMIN7;
lengthY = equalizedY * signY / DMIN7;
else if (constellationSizes[i] == 6)
{
// subcarrier uses a 64-point constellation
equalized = (*symbolPtr).getDemodulatedSample(i) *
equalizers[i];
equalizedX = equalized.real();
equalizedY = equalized.imag();
(equalizedX >= 0) ? signX = 1 : signX = -1;
if (signX==1 && signY==1)
{ bit6 = 0; bit5 = 0; }
else if (signX==-1 && signY==1)
145
{ bit6 = 0; bit5
else if (signX==-1
{ bit6 = 1; bit5
else
{ bit6 = 1; bit5
= 1; }
&& signY==-1)
= 1; }
{
else
{
else
{
else
{
= 0; }
if (lengthX <= 2)
{
// first column
if (lengthY <= 2)
{ bit4 = 0; bit3
else if (lengthY <=
{ bit4 = 0; bit3
else if (lengthY <=
{ bit4 = 0; bit3
else if (lengthY <=
{ bit4 = 0; bit3
else if (lengthY <=
{ bit4 = 0; bit3
else
{ bit4 = 0; bit3
}
else if (lengthX <= 4)
{
// second column
if (lengthY <= 2)
{ bit4 = 0; bit3
else if (lengthY <=
{ bit4 = 0; bit3
else if (lengthY <=
{ bit4 = 0; bit3
else if (lengthY <=
{ bit4 = 0; bit3
else if (lengthY <=
{ bit4 = 0; bit3
else
{ bit4 = 0; bit3
}
else if (lengthX <= 6)
{
// third column
if (lengthY <= 2)
{ bit4 = 1; bit3
else if (lengthY <=
{ bit4 = 1; bit3
else if (lengthY <=
{ bit4 = 1; bit3
else if (lengthY <=
{ bit4 = 1; bit3
else if (lengthY <=
{ bit4 = 1; bit3
else
{ bit4 = 1; bit3
}
else if (lengthX <= 8)
{
// fourth column
if (lengthY <= 2)
{ bit4 = 1; bit3
else if (lengthY <=
= 0;
4)
= 0;
6)
= 0;
8)
= 0;
10)
= 0;
bit2 = 0; bit1 = 0; bit0 = 0; }
bit2 = 0; bit1 = 1; bit0 = 0; }
bit2 = 1; bit1 = 1; bit0 = 0; }
bit2 = 1; bit1 = 0; bit0 = 0; }
bit2 = 1; bit1 = 0; bit0 = 1; }
= 1; bit2 = 1; bit1 = 1; bit0 = 1; }
= 1;
4)
= 1;
6)
= 1;
8)
= 1;
10)
= 1;
bit2 = 0; bit1 = 0; bit0 = 0; }
bit2 = 0; bit1 = 1; bit0 = 0; }
bit2 = 1; bit1 = 1; bit0 = 0; }
bit2 = 1; bit1 = 0; bit0 = 0; }
= 0; bit2 = 0; bit1 = 1; bit0 = 0; }
6)
= 0; bit2 = 1; bit1 = 1; bit0 = 0; }
8)
= 0; bit2 = 1; bit1 = 0; bit0 = 0; }
bit4 = 1; bit3
}
else if (lengthX <= 10)
{
// fifth column
if (lengthY <= 2)
{ bit4 = 1; bit3
else if (lengthY <=
{ bit4 = 1; bit3
else if (lengthY <=
{ bit4 = 1; bit3
else if (lengthY <=
{ bit4 = 1; bit3
else
{ bit4 = 1; bit3
}
else
{
// sixth column
if (lengthY <= 2)
{ bit4 = 0; bit3
else if (lengthY <=
{ bit4 = 0; bit3
else if (lengthY <=
{ bit4 = 0; bit3
else
{ bit4 = 0; bit3
}
= 0; bit2 = 1; bit1 = 0; bit0 = 1; }
= 0;
4)
= 0;
6)
= 0;
8)
= 1;
bit2 = 0; bit1 = 0; bit0 = 1; }
bit2 = 0; bit1 = 1; bit0 = 1; }
bit2 = 1; bit1 = 1; bit0 = 1; }
bit2 = 0; bit1 = 1; bit0 = 1; }
= 1; bit2 = 0; bit1 = 0; bit0 = 1; }
= 0; bit2 = 0; bit1 = 0; bit0 = 1; }
4)
= 0; bit2 = 0; bit1 = 1; bit0 = 1; }
6)
= 0; bit2 = 1; bit1 = 1; bit0 = 1; }
= 1; bit2 = 0; bit1 = 0; bit0 = 1; }
bit2 = 1; bit1 = 0; bit0 = 1; }
(*symbolPtr).putSlicedBit(bit6);
(*symbolPtr).putSlicedBit(bit5);
(*symbolPtr).putSlicedBit(bit4);
(*symbolPtr).putSlicedBit(bit3);
(*symbolPtr).putSlicedBit(bit2);
(*symbolPtr).putSlicedBit(bit1);
(*symbolPtr).putSlicedBit(bit0);
= 1; bit2 = 0; bit1 = 1; bit0 = 1; }
= 1;
4)
= 1;
6)
= 1;
8)
= 1;
10)
= 1;
bit4 = 1; bit3
if (lengthY <=
bit4 = 1; bit3
if (lengthY <=
bit4 = 1; bit3
bit2 = 0; bit1 = 0; bit0 = 0; }
// update symbol error statistics
if (analyze)
{
if (((*symbolPtr).getCodedBit() != bit6) ||
((*symbolPtr).getCodedBit() != bit5) ||
((*symbolPtr).getCodedBit() != bit4) ||
((*symbolPtr).getCodedBit() != bit3) ||
((*symbolPtr).getCodedBit() != bit2) ||
((*symbolPtr).getCodedBit() != bit1) ||
((*symbolPtr).getCodedBit() != bit0))
symbolErrors[i] = symbolErrors[i] + 1;
}
}
bit2 = 0; bit1 = 1; bit0 = 0; }
bit2 = 1; bit1 = 1; bit0 = 0; }
bit2 = 1; bit1 = 0; bit0 = 0; }
bit2 = 1; bit1 = 0; bit0 = 1; }
= 1; bit2 = 1; bit1 = 1; bit0 = 1; }
else if (constellationSizes[i] == 8)
{
// subcarrier uses a 256-point constellation
= 0; bit2 = 0; bit1 = 0; bit0 = 0; }
4)
146
equalized = (*symbolPtr).getDemodulatedSample(i) *
equalizers[i];
equalizedX = equalized.real();
equalizedY = equalized.imag();
(equalizedX >= 0) ? signX = 1 : signX = -1;
(equalizedY >= 0) ? signY = 1 : signY = -1;
lengthX = equalizedX * signX / DMIN8;
lengthY = equalizedY * signY / DMIN8;
((*symbolPtr).getCodedBit() != bit5) ||
((*symbolPtr).getCodedBit() != bit4) ||
((*symbolPtr).getCodedBit() != bit3) ||
((*symbolPtr).getCodedBit() != bit2) ||
((*symbolPtr).getCodedBit() != bit1) ||
((*symbolPtr).getCodedBit() != bit0))
symbolErrors[i] = symbolErrors[i] + 1;
}
}
(signX == 1) ? bit7 = 0 : bit7 = 1;
(signY == 1) ? bit3 = 0 : bit3 = 1;
if (lengthX <= 2)
{ bit6 = 0; bit5 = 0;
else if (lengthX <= 4)
{ bit6 = 0; bit5 = 0;
else if (lengthX <= 6)
{ bit6 = 0; bit5 = 1;
else if (lengthX <= 8)
{ bit6 = 0; bit5 = 1;
else if (lengthX <= 10)
{ bit6 = 1; bit5 = 1;
else if (lengthX <= 12)
{ bit6 = 1; bit5 = 1;
else if (lengthX <= 14)
{ bit6 = 1; bit5 = 0;
else
{ bit6 = 1; bit5 = 0;
if (lengthY <= 2)
{ bit2 = 0; bit1 = 0;
else if (lengthY <= 4)
{ bit2 = 0; bit1 = 0;
else if (lengthY <= 6)
{ bit2 = 0; bit1 = 1;
else if (lengthY <= 8)
{ bit2 = 0; bit1 = 1;
else if (lengthY <= 10)
{ bit2 = 1; bit1 = 1;
else if (lengthY <= 12)
{ bit2 = 1; bit1 = 1;
else if (lengthY <= 14)
{ bit2 = 1; bit1 = 0;
else
{ bit2 = 1; bit1 = 0;
else
{
// subcarrier has an invalid constellation size
cerr << "Constellation size TOO LARGE in
Adapter::sliceSymbol()" << endl;
}
}
bit4 = 0; }
bit4 = 1; }
bit4 = 1; }
return symbolPtr;
bit4 = 0; }
}
bit4 = 0; }
bit4 = 1; }
OfdmSymbol* Adapter::decodeSymbol(OfdmSymbol *symbolPtr)
{
// currently there's no coding scheme built into the design, so:
(*symbolPtr).beginSlicedRetrieval();
(*symbolPtr).beginDecodedPacking();
bit4 = 1; }
bit4 = 0; }
while (!(*symbolPtr).isDecodedPackingFinished())
(*symbolPtr).putDecodedBit((*symbolPtr).getSlicedBit());
bit0 = 0; }
bit0 = 1; }
return symbolPtr;
}
bit0 = 1; }
bit0 = 0; }
OfdmSymbol* Adapter::receivePilotSymbol(OfdmSymbol *symbolPtr, bool
noise)
{
// corrupt and demodulate incoming symbol as usual
corruptSymbol(symbolPtr, noise);
demodulateSymbol(symbolPtr);
bit0 = 0; }
bit0 = 1; }
bit0 = 1; }
bit0 = 0; }
// update slicing distances
for (int i=0; i < SUBCARRIERS; i++)
{
if (constellationSizes[i] == 0)
{
// subcarrier is not in use
}
(*symbolPtr).putSlicedBit(bit7);
(*symbolPtr).putSlicedBit(bit6);
(*symbolPtr).putSlicedBit(bit5);
(*symbolPtr).putSlicedBit(bit4);
(*symbolPtr).putSlicedBit(bit3);
(*symbolPtr).putSlicedBit(bit2);
(*symbolPtr).putSlicedBit(bit1);
(*symbolPtr).putSlicedBit(bit0);
else if (constellationSizes[i] == 1)
{
// pilot is complex<double>(DMIN1,0)
equalizers[i] = complex<double>(DMIN1, 0) /
(*symbolPtr).getDemodulatedSample(i);
}
// update symbol error statistics
if (analyze)
{
if (((*symbolPtr).getCodedBit() != bit7) ||
((*symbolPtr).getCodedBit() != bit6) ||
else if (constellationSizes[i] == 2)
147
{
// pilot is complex<double>(DMIN2, DMIN2)
equalizers[i] = complex<double>(DMIN2, DMIN2) /
(*symbolPtr).getDemodulatedSample(i);
}
OfdmSymbol* Adapter::analyzeSymbol(OfdmSymbol *symbolPtr)
{
int i,j,k;
if (!(*symbolPtr).isPilot())
{
// update number symbols and bits received
for (i=0; i < SUBCARRIERS; i++)
{
if (constellationSizes[i] > 0)
{
symbolsReceived[i] = symbolsReceived[i] + 1;
bitsReceived[i] = bitsReceived[i] + constellationSizes[i];
}
}
else if (constellationSizes[i] == 3)
{
// pilot is complex<double>(DMIN3, DMIN3)
equalizers[i] = complex<double>(DMIN3, DMIN3) /
(*symbolPtr).getDemodulatedSample(i);
}
else if (constellationSizes[i] == 4)
{
// pilot is complex<double>(3*DMIN4, 3*DMIN4)
equalizers[i] = complex<double>(3*DMIN4, 3*DMIN4) /
(*symbolPtr).getDemodulatedSample(i);
}
// update number of uncoded bit errors
(*symbolPtr).beginUncodedRetrieval();
(*symbolPtr).beginDecodedRetrieval();
else if (constellationSizes[i] == 5)
{
// pilot is complex<double>(3*DMIN5, 3*DMIN5)
equalizers[i] = complex<double>(3*DMIN5, 3*DMIN5) /
(*symbolPtr).getDemodulatedSample(i);
}
for (i=0; i < SUBCARRIERS; i++)
{
k = constellationSizes[i];
for (j=0; j < k; j++)
{
if (((*symbolPtr).getUncodedBit()) !=
((*symbolPtr).getDecodedBit()))
uncodedBitErrors[i] = uncodedBitErrors[i] + 1;
}
}
else if (constellationSizes[i] == 6)
{
// pilot is complex<double>(7*DMIN6, 7*DMIN6)
equalizers[i] = complex<double>(7*DMIN6, 7*DMIN6) /
(*symbolPtr).getDemodulatedSample(i);
}
// update number of coded bit errors
// this function will not be implemented due to a
// lack of a coding scheme in the current design
else if (constellationSizes[i] == 7)
{
// pilot is complex<double>(9*DMIN7, 9*DMIN7)
equalizers[i] = complex<double>(9*DMIN7, 9*DMIN7) /
(*symbolPtr).getDemodulatedSample(i);
}
}
return symbolPtr;
}
else if (constellationSizes[i] == 8)
{
// pilot is complex<double>(15*DMIN8, 15*DMIN8)
equalizers[i] = complex<double>(15*DMIN8, 15*DMIN8) /
(*symbolPtr).getDemodulatedSample(i);
}
////////////////////////////////////
// Numerical Recipe Functions
////////////////////////////////////
#define SWAP(a,b) tempr=(a);(a)=(b);(b)=tempr
else
{
void Adapter::dfour1(double data[], unsigned long nn, int isign)
{
unsigned long n,mmax,m,j,istep,i;
double wtemp,wr,wpr,wpi,wi,theta;
double tempr,tempi;
// subcarrier has an invalid constellation size
cerr << "Constellation size TOO LARGE in Adapter::qamSymbol()"
<< endl;
}
}
n=nn << 1;
j=1;
for (i=1;i<n;i+=2) {
if (j > i) {
SWAP(data[j],data[i]);
return symbolPtr;
}
148
SWAP(data[j+1],data[i+1]);
}
m=n >> 1;
while (m >= 2 && j > m) {
j -= m;
m >>= 1;
}
j += m;
}
mmax=2;
while (n > mmax) {
istep=mmax << 1;
theta=isign*(6.28318530717959/mmax);
wtemp=sin(0.5*theta);
wpr = -2.0*wtemp*wtemp;
wpi=sin(theta);
wr=1.0;
wi=0.0;
for (m=1;m<mmax;m+=2) {
for (i=m;i<=n;i+=istep) {
j=i+mmax;
tempr=wr*data[j]-wi*data[j+1];
tempi=wr*data[j+1]+wi*data[j];
data[j]=data[i]-tempr;
data[j+1]=data[i+1]-tempi;
data[i] += tempr;
data[i+1] += tempi;
}
wr=(wtemp=wr)*wpr-wi*wpi+wr;
wi=wi*wpr+wtemp*wpi+wi;
}
mmax=istep;
}
}
#undef SWAP
149
Channel.h
// complex valued samples of the channel impulse response
complex<double> impulseResponse[(int) (CHANNEL_TRANSIENT * SAMPLING *
BANDWIDTH)];
#include "Parameters.h"
#include "OfdmSymbol.h"
#include "math.h"
#include "time.h"
#include <string>
#include <complex>
#include <iostream>
using namespace std;
////////////////////////////////////
// Constructors
////////////////////////////////////
public:
Channel(double distance=1.0, string shape="impulse", double
variance=6e-8);
// requires: int be distance in meters (greater than or equal to 1),
//
string belongs to {impulse, exponential, spikes,
gaussian},
//
double be variance in seconds
// effects: creates a channel with given shape and variance
////////////////////////////////////////////////////////////////////////
// PROJECT: WGLAN Software Simulation
// FILE:
Channel.h
// AUTHOR:
Eladio Arvelo <earvelo@alum.mit.edu>
// MODS:
Created file -- 11.09.99
//
Added method signatures -- 11.23.99
//
Added default parameters to several methods -- 12.06.99
//
Replaced OfdmSymbol& with OfdmSymbol* -- 12.08.99
//
Renamed jammingProfile to interference -- 01.14.00
//
Change signature of convolveSymbol -- 01.15.00
//
Added antidB, gaussianSample, attenuateSymbol -- 01.15.00
//
Cleaned up file -- 01.15.00
//
Removed attenuateSymbol() method -- 01.19.00
//
Restructured handling of noise variance -- 01.21.00
//
Changed distance from type int to double -- 01.23.00
//
Added methods from numerical recipes -- 01.28.00
////////////////////////////////////////////////////////////////////////
Channel(const Channel&);
// effects: this is a copy constructor
////////////////////////////////////
// Observer Methods
////////////////////////////////////
public:
int getResponseLength();
// effects: returns length of this channel's impulse response
class Channel
{
// OVERVIEW
// Channel is an abstraction of a channel between Controller and
Adapter
int getInterference(int);
// requires: int be in range [0, (SUBCARRIERS-1)]
// effects: returns interference (in dB) for the given subcarrier
index
double getDistance();
// effects: returns distance between communicating devices
////////////////////////////////////
// Private data
////////////////////////////////////
double getVariance();
// effects: returns variance of this channel's impulse response
private:
int responseLength;
samples) of impulseResponse array
double distance;
between devices
double variance;
this channel
double deltaT;
which channel is sampled
string shape;
exponential, spikes, gaussian}
complex<double> getSample(int);
// requires: int be in the range [0, (responseLength - 1)]
// effects: returns impulseResponse array entry indexed by int
// equal to length (in
// distance (in meters)
string getShape();
// effects: returns shape of this channel's impulse response
// variance (in seconds) of
// time intervals (in seconds) at
////////////////////////////////////
// Mutator Methods
////////////////////////////////////
// shape belongs to {impulse,
// jamming profile of each OFDM subcarrier due to interference
int interference[SUBCARRIERS];
public:
150
void changeDistance(double);
// modifies: distance
// effects: changes distance between network adapter and controller
// requires:
response,
//
// modifies:
// effects:
void changeVariance(double newVariance = 0);
// requires: double be greater than zero for non-random variance
assignment
// modifies: variance, impulseResponse
// effects: changes channel impulse response to the given variance in
nanoseconds,
//
or to a random value between MAX_VARIANCE and
MIN_VARIANCE if newVariance == 0.
double be 1D noise variance in linear scale
OfdmSymbol*
adds white Gaussian noise to OfdmSymbol
void takeChannelSamples();
// effects: fill impulseResponse array with samples of continuoustime channel model
////////////////////////////////////
// Numerical Recipe Functions
////////////////////////////////////
void changeShape(string newShape = "random");
// requires: empty parameter list or string = {impulse, exponential,
spikes, gaussian}
// modifies: shape, impulseResponse
// effects: changes channel impulse response to the specified shape,
//
or to a random shape if newShape == "random"
private:
double ran1(long *idum);
// effects: returns samples from a uniform random number generator
void changeInterference();
// modifies: interference
// effects: assign new random numbers to entries in jamming profile
double gasdev(long *idum, double variance);
// requires: variance be 1D noise variance in linear scale
// effects: returns samples from a Gaussian random number generator
OfdmSymbol* convolveSymbol(OfdmSymbol* symbolPtr, bool noise = true);
// requires: modulated data array of OfdmSymbol be full,
//
noiseVar be 2D noise variance in dB scale
// modifies: OfdmSymbol*
// effects: convolves OfdmSymbol with channel impulse response,
//
adds gaussian noise with variance noiseVar if bool is
true
}; //end Channel class
////////////////////////////////////
// Destructor
////////////////////////////////////
public:
~Channel();
// effects:
OfdmSymbol be convolved first with channel impulse
deletes private data of this
////////////////////////////////////
// Helper Functions
////////////////////////////////////
private:
double log2(double);
// requires: double be greater than or equal to zero
// effects: returns the log base-2 of double
double antidB(double);
// requires: nothing
// effects: converts double from dB scale to linear scale
OfdmSymbol* addNoise(OfdmSymbol*, double);
151
Channel.cpp
// copy attenuation profile of each OFDM subcarrier
for (int i=0; i < SUBCARRIERS; i++)
interference[i] = oldChannel.interference[i];
#include "Channel.h"
// copy samples of the channel impulse response
for (int j=0; j < responseLength; j++)
impulseResponse[j] = oldChannel.impulseResponse[j];
////////////////////////////////////////////////////////////////////////
// PROJECT: WGLAN Software Simulation
// FILE:
Channel.cpp
// AUTHOR:
Eladio Arvelo <earvelo@alum.mit.edu>
// MODS:
Created file -- 11.23.99
//
Implemented all methods except addNoise() -- 11.24.99
//
Compiled class successfully -- 11.24.99
//
Postponed implementation of addNoise() -- 11.24.99
//
Deleted several redundant methods -- 12.06.99
//
Replaced OfdmSymbol& with OfdmSymbol* -- 12.08.99
//
Implemented gaussianSample(), attenuateSymbol() -01.15.00
//
Removed attenuateSymbol() -- 01.19.00
//
Changed distance from type int to double -- 01.23.00
//
Removed gaussianSamples() -- 01.28.00
//
Added methods from numerical recipes -- 01.28.00
////////////////////////////////////////////////////////////////////////
}
////////////////////////////////////
// Observer Methods
////////////////////////////////////
int Channel::getResponseLength()
{
return responseLength;
}
int Channel::getInterference(int index)
{
if (index < SUBCARRIERS)
{
return interference[index];
}
else
{
cerr << "Index OUT-OF-BOUND in Channel::getInterference()" <<
endl;
return 0;
}
}
////////////////////////////////////
// Constructors
////////////////////////////////////
Channel::Channel(double distance, string shape, double variance)
{
// initialize parameters of channel impulse response
this->distance = distance;
this->shape = shape;
this->variance = variance;
deltaT = (double) 1 / (double) (SAMPLING * BANDWIDTH);
responseLength = (int) (CHANNEL_TRANSIENT / deltaT);
double Channel::getDistance()
{
return distance; }
// seed random number generator
srand(time(0));
// assign random interference profile (in dB) to subcarriers
for (int i=0; i < SUBCARRIERS; i++)
interference[i] = rand() % MAX_INTERFERENCE;
double Channel::getVariance()
{
return variance; }
// take samples of continuous-time channel impulse response template
takeChannelSamples();
complex<double> Channel::getSample(int index)
{
if (index < responseLength)
{
return impulseResponse[index];
}
else
{
cerr << "Index OUT-OF-BOUND in Channel::getSample()" << endl;
return complex<double>(0,0);
}
}
}
Channel::Channel(const Channel& oldChannel)
{
// initialize Channel parameters
distance = oldChannel.distance;
shape = oldChannel.shape;
variance = oldChannel.variance;
responseLength = oldChannel.responseLength;
deltaT = oldChannel.deltaT;
152
// assign specified shape
shape = newShape;
string Channel::getShape()
{
return shape;
}
}
// re-evaluate samples of continuous-time channel impulse response
template
takeChannelSamples();
}
////////////////////////////////////
// Mutator Methods
////////////////////////////////////
void Channel::changeDistance(double newDistance)
{
distance = newDistance;
}
void Channel::changeInterference()
{
srand(time(0));
for (int i=0; i < SUBCARRIERS; i++)
interference[i] = rand() % MAX_INTERFERENCE;
}
void Channel::changeVariance(double newVariance)
{
// seed random number generator
srand(time(0));
OfdmSymbol* Channel::convolveSymbol(OfdmSymbol *symbolPtr, bool noise)
{
int i=0, j=0, outputSampleIndex=0;
double snr, pathLoss;
complex<double> newSample, dumbSamples;
if (newVariance == 0)
{
// assign random variance within valid range in seconds
variance = ((rand() % ((int)MAX_VARIANCE - (int)MIN_VARIANCE)) +
(int)MIN_VARIANCE + 1) * 1e-9;
}
else
{
// assign specified variance
variance = newVariance;
}
// case when channel response is shorter than input signal data
if (responseLength < (SUBCARRIERS*SAMPLING + GUARD_SAMPLES))
{
// compute convolution of impulseResponse with modulatedData
for (outputSampleIndex=0; outputSampleIndex <
(SUBCARRIERS*SAMPLING + GUARD_SAMPLES); outputSampleIndex++)
{
newSample = complex<double>(0,0);
// re-evaluate samples of continuous-time channel impulse response
template
takeChannelSamples();
}
// impulseResponse partially overlaps with samples of
modulatedData
if (outputSampleIndex < responseLength)
{
for (i=0, j=outputSampleIndex; j>=0; j--, i++)
newSample += (*symbolPtr).getModulatedSample(j) *
impulseResponse[i];
}
// impulseResponse overlaps fully with samples of
modulatedData
else
{
for (i=0, j=outputSampleIndex; j>(outputSampleIndexresponseLength); j--, i++)
newSample += (*symbolPtr).getModulatedSample(j) *
impulseResponse[i];
}
void Channel::changeShape(string newShape)
{
int randomNumber;
srand(time(0));
if (newShape == "random")
{
// assign random shape
randomNumber = rand() % 4;
if (randomNumber == 0)
{
shape = "impulse";
else if (randomNumber == 1)
{
shape = "exponential";
else if (randomNumber == 2)
{
shape = "spikes"; }
else
{
shape = "gaussian";
}
else
{
}
}
(*symbolPtr).putCorruptedSample(outputSampleIndex, newSample);
}
}
}
// case when channel response is longer than input signal data
else
{
153
// compute convolution of impulseResponse with modulatedData
for (outputSampleIndex=0; outputSampleIndex <
(SUBCARRIERS*SAMPLING + GUARD_SAMPLES); outputSampleIndex++)
{
newSample = complex<double>(0,0);
}
double Channel::antidB(double value)
{
value = pow(10,(value/10.0));
return value;
}
for (i=0, j=outputSampleIndex; j>=0; j--, i++)
newSample += (*symbolPtr).getModulatedSample(j) *
impulseResponse[i];
(*symbolPtr).putCorruptedSample(outputSampleIndex, newSample);
}
}
// adds gaussian noise if instructed to do so
if (noise)
{
// first compute one-dimensional noise variance
if (distance <= 1.0)
{
pathLoss = PL_1M; }
else
{
pathLoss = PL_1M - (10 * PL_EXP * log10(distance));
OfdmSymbol* Channel::addNoise(OfdmSymbol *symbolPtr, double noiseVar)
{
static long int idum = 0;
complex<double> newSample;
// add gaussian noise to each corrupted sample
for (int index=0; index < (SUBCARRIERS*SAMPLING + GUARD_SAMPLES);
index++)
{
newSample = (*symbolPtr).getCorruptedSample(index) +
complex<double>(gasdev(&idum, noiseVar), gasdev(&idum,
noiseVar));
(*symbolPtr).putCorruptedSample(index, newSample);
}
return symbolPtr;
}
}
snr = 10*log10(antidB(pathLoss + RCV_GAIN) * SUBCARRIERS /
BANDWIDTH) - NOISE_DENSITY;
if (snr < 0)
{
cerr << "Warning: SNR is negative in
Channel::ConvolveSymbol()" << endl;
snr = 1.0;
}
void Channel::takeChannelSamples()
{
int k;
double responseArea;
double tempSample;
// then add noise with respective variance
addNoise(symbolPtr, (1 / antidB(snr)) / 2);
}
// return processed symbol
return symbolPtr;
// initialize contents of impulseResponse array
for (k=0; k < responseLength; k++)
impulseResponse[k] = complex<double>(0,0);
}
// take samples of continuous-time channel impulse response template
if (shape == "impulse")
{
impulseResponse[0] = complex<double>(1,0);
}
else if (shape == "exponential")
{
responseArea = 0;
////////////////////////////////////
// Destructor
////////////////////////////////////
Channel::~Channel()
{ }
for (k=0; k < responseLength; k++)
{
tempSample = exp(-(double)k*deltaT/variance) / variance;
impulseResponse[k] = complex<double>(tempSample,0);
responseArea += tempSample;
}
////////////////////////////////////
// Helper Functions
////////////////////////////////////
double Channel::log2(double value)
{
value = log10(value) / log10(2);
return value;
// normalize channel response to an area equal to unity
for (k=0; k < responseLength; k++)
154
impulseResponse[k] = complex<double>(impulseResponse[k].real() /
responseArea,0);
}
else if (shape == "spikes")
{
impulseResponse[0] = complex<double>(0.5,0);
impulseResponse[(int)(2*variance/deltaT)] =
complex<double>(0.5,0);
}
else if (shape == "gaussian")
{
responseArea = 0;
for (j=NTAB+7;j>=0;j--) {
k=(*idum)/IQ;
*idum=IA*(*idum-k*IQ)-IR*k;
if (*idum < 0) *idum += IM;
if (j < NTAB) iv[j] = *idum;
}
iy=iv[0];
}
k=(*idum)/IQ;
*idum=IA*(*idum-k*IQ)-IR*k;
if (*idum < 0) *idum += IM;
j=iy/NDIV;
iy=iv[j];
iv[j] = *idum;
if ((temp=AM*iy) > RNMX) return RNMX;
else return temp;
for (k=0; k < responseLength; k++)
{
tempSample = exp(-pow((double)(k*deltaT/variance),2)/2.) /
2.506628275 * variance;
impulseResponse[k] = complex<double>(tempSample,0);
responseArea += tempSample;
}
}
#undef
#undef
#undef
#undef
#undef
#undef
#undef
#undef
#undef
// normalize channel response to an area equal to unity
for (k=0; k < responseLength; k++)
impulseResponse[k] = complex<double>(impulseResponse[k].real() /
responseArea,0);
}
else
{
cerr << "Invalid CHANNEL SHAPE in Channel::takeChannelSamples()"
<< endl;
}
}
double Channel::gasdev(long *idum, double variance)
{
double ran1(long *idum);
static int iset=0;
static float gset;
double fac,rsq,v1,v2;
////////////////////////////////////
// Numerical Recipe Functions
////////////////////////////////////
#define
#define
#define
#define
#define
#define
#define
#define
#define
IA
IM
AM
IQ
IR
NTAB
NDIV
EPS
RNMX
if (*idum < 0) iset=0;
if (iset == 0) {
do {
v1=2.0*ran1(idum)-1.0;
v2=2.0*ran1(idum)-1.0;
rsq=v1*v1+v2*v2;
} while (rsq >= 1.0 || rsq == 0.0);
fac=sqrt(-2.0*log(rsq)/rsq);
gset=v1*fac*sqrt(variance);
iset=1;
return v2*fac*sqrt(variance);
} else {
iset=0;
return gset;
}
IA 16807
IM 2147483647
AM (1.0/IM)
IQ 127773
IR 2836
NTAB 32
NDIV (1+(IM-1)/NTAB)
EPS 1.2e-7
RNMX (1.0-EPS)
double Channel::ran1(long *idum)
{
int j;
long k;
static long iy=0;
static long iv[NTAB];
double temp;
}
if (*idum <= 0 || !iy) {
if (-(*idum) < 1) *idum=1;
else *idum = -(*idum);
155
// (e): corruptedData fixed length = subcarriers * sampling + guard
samples
// (f): demodulatedData
fixed length = subcarriers
// (g): slicedData
variable length
// (h): decodedData
variable length
//
//
// Data representation per stages:
// (a): uncodedData
bits
// (b): codedData
bits
// (c): qamData
complex numbers, points spaced with same
average energy
// (d): modulatedData
complex numbers, samples of time-domain
OFDM symbol
// (e): corruptedData
complex numbers, output of multipath
channel plus noise
// (f): demodulatedData
complex numbers, points received (without
equalization)
// (g): slicedData
bits
// (h): decodedData
bits
OfdmSymbol.h
#include "Parameters.h"
#include "assert.h"
#include <complex>
#include <iostream>
using namespace std;
////////////////////////////////////////////////////////////////////////
// PROJECT: WGLAN Software Simulation
// FILE:
OfdmSymbol.h
// AUTHOR:
Eladio Arvelo <earvelo@alum.mit.edu>
// MODS:
Created file -- 11.09.99
//
Added private data and method signatures -- 11.10.99
//
Reorganized iterator methods -- 11.23.99
//
Redefined iterator methods -- 11.24.99
//
Redefined entire class -- 11.24.99
//
Added operator= signature -- 12.05.99
//
Changed int type to bool type for bit variables -12.06.99
//
Deleted data and methods regarding dataGuarded -- 12.06.99
//
Added errorsAfterDemodulating signature -- 12.06.99
//
Added data and methods to support pilot symbols -12.06.99
//
Added constructor that takes a OfdmSymbol* -- 12.08.99
//
Deleted operator= signature -- 12.08.99
//
Specified data representation per stages -- 01.15.00
//
Deleted operator= signature -- 01.15.00
//
Cleanup up file -- 01.15.00
//
Changed signature of errorsAfterDemodulating -- 01.24.00
//
Removed methods for computing error statistics -- 02.08.00
////////////////////////////////////////////////////////////////////////
////////////////////////////////////
// Private data
////////////////////////////////////
private:
// identification parameters for this OfdmSymbol
int senderID;
that created this OfdmSymbol
int recipientID;
recipient for this OfdmSymbol
int startTime;
left transmitter
bool pilotSymbol;
or not symbol is used as a pilot
class OfdmSymbol
{
// OVERVIEW
//
// OfdmSymbol is an abstraction of a data block as it is encoded, made
a constellation,
// modulated, corrupted by the channel, demodulated, sliced, and
decoded.
//
// (a)
(b)
(c)
(d)
(e)
(f)
(g)
(h)
//
-------------------------------------------// ---->|coding|-->|QAM|-->|IFFT|-->|channel|-->|FFT|-->|slicer|->|decoding|---->
//
-------------------------------------------//
// Naming conventions:
// (a): uncodedData
variable length
// (b): codedData
variable length
// (c): qamData
fixed length = subcarriers
// (d): modulatedData fixed length = subcarriers * sampling + guard
samples
// device
// intended
// time when symbol
// whether
// size of data blocks contained within this OfdmSymbol
int uncodedBlockSize;
int codedBlockSize;
// arrays containing blocks of data
bool *uncodedData;
bool *codedData;
complex<double> qamData[SUBCARRIERS];
complex<double> modulatedData[SUBCARRIERS*SAMPLING + GUARD_SAMPLES];
complex<double> corruptedData[SUBCARRIERS*SAMPLING + GUARD_SAMPLES];
complex<double> demodulatedData[SUBCARRIERS];
bool *slicedData;
bool *decodedData;
// array indexes for iterators
int uncodedArrayPutIndex;
int codedArrayPutIndex;
int slicedArrayPutIndex;
int decodedArrayPutIndex;
int uncodedArrayGetIndex;
156
int codedArrayGetIndex;
int slicedArrayGetIndex;
int decodedArrayGetIndex;
// effects:
corruptedData
returns magnitude of maximum real or imag component of
double averageCorruptedSample();
// requires: all data arrays be full
// effects: returns average of magnitudes of real and imag components
of corruptedData
////////////////////////////////////
// Constructors
////////////////////////////////////
double peakToAverageCorruptedSample();
// requires: all data arrays be full
// effects: returns ratio between peakCorruptedSample() and
averageCorruptedSample()
public:
OfdmSymbol(int senderID=1, int recipientID=1, int startTime=1,
int uncodedBlockSize=1, int codedBlockSize=1);
// requires: parameter list be valid
// effects: creates a new OfdmSymbol with given parameters
////////////////////////////////////
// Mutator Methods
////////////////////////////////////
OfdmSymbol(const OfdmSymbol&);
// effects: this is a copy constructor
public:
OfdmSymbol(const OfdmSymbol*);
// effects: this is a copy constructor
void setPilot();
// effects: marks this symbol as a pilot symbol
////////////////////////////////////
// Observer Methods
////////////////////////////////////
void putUncodedBit(bool);
// requires: method be called fewer than uncodedBlockSize times
// effects: adds bit to uncodedData and increases respective array
index
public:
void putCodedBit(bool);
// requires: method be called fewer than codedBlockSize times
// effects: adds bit to codedData and increases respective array
index
int getSender();
// effects: returns ID of sender device
int getRecipient();
// effects: returns ID of recipient device
void putQamSample(int, complex<double>);
// requires: int be in the range [0, (SUBCARRIERS - 1)]
// effects: adds sample to qamData
int getBitPayload();
// effects: returns number of uncoded bits sent in this symbol
bool isPilot();
// effects: returns true if this OfdmSymbol is used as a pilot, false
otherwise
void putModulatedSample(int, complex<double>);
// requires: int be in the range [0, (SUBCARRIERS*SAMPLING +
GUARD_SAMPLES - 1)]
// effects: adds sample to modulatedData
double peakModulatedSample();
// requires: all data arrays be full
// effects: returns magnitude of maximum real or imag component of
modulatedData
void guardModulatedSamples();
// requires: putModulatedSample() be called (SUBCARRIERS*SAMPLING +
GUARD_SAMPLES) times
// effects: adds guard samples to modulatedData
double averageModulatedSample();
// requires: all data arrays be full
// effects: returns average of magnitudes of real and imag components
of modulatedData
void putCorruptedSample(int, complex<double>);
// requires: int be in the range [0, (SUBCARRIERS*SAMPLING +
GUARD_SAMPLES -1)]
// effects: adds sample to corruptedData
double peakToAverageModulatedSample();
// requires: all data arrays be full
// effects: returns ratio between peakModulatedSample() and
averageModulatedSample()
void putDemodulatedSample(int, complex<double>);
// requires: int be in the range [0, (SUBCARRIERS - 1)]
// effects: adds sample to demodulatedData
void putSlicedBit(bool);
// requires: method be called fewer than codedBlockSize times
double peakCorruptedSample();
// requires: all data arrays be full
157
// effects:
index
adds bit to slicedData and increases respective array
void beginSlicedRetrieval();
// effects: resets sliced data iteration to the first bit
void putDecodedBit(bool);
// requires: method be called fewer than uncodedBlockSize times
// effects: adds bit to decodedData and increases respective array
index
void beginDecodedRetrieval();
// effects: resets decoded data iteration to the first bit
bool isUncodedRetrievalFinished();
// effects: returns true if uncodedArrayGetIndex >=
length(uncodedData), else false
void addInterferer(OfdmSymbol *);
// requires: OfdmSymbol have arrays up to modulatedData filled up
// effects: adds modulatedData of OfdmSymbol to modulatedData of this
bool isCodedRetrievalFinished();
// effects: returns true if codedArrayGetIndex >= length(codedData),
else false
////////////////////////////////////
// Iterator Methods
////////////////////////////////////
bool isSlicedRetrievalFinished();
// effects: returns true if slicedArrayGetIndex >= length(codedData),
else false
public:
bool isDecodedRetrievalFinished();
// effects: returns true if decodedArrayGetIndex >=
length(uncodedData), else false
// ITERATORS FOR FILLING UP DATA ARRAYS
/////////////////////////////////////////////
void beginUncodedPacking();
// effects: resets uncoded data iteration to the first bit
bool getUncodedBit();
// requires: method be called fewer times than uncodedBlockSize
// effects: returns next uncoded bit and updates respective iterator
array index
void beginCodedPacking();
// effects: resets coded data iteration to the first bit
bool getCodedBit();
// requires: method be called fewer times than codedBlockSize
// effects: returns next coded bit and updates respective iterator
array index
void beginSlicedPacking();
// effects: resets demodulated data iteration to the first bit
void beginDecodedPacking();
// effects: resets decoded data iteration to the first bit
complex<double> getQamSample(int);
// requires: int be in the range [0, (SUBCARRIERS - 1)]
// effects: returns qam sample located in given index
bool isUncodedPackingFinished();
// effects: returns true if length(uncodedData) == uncodedBlockSize,
false otherwise
complex<double> getModulatedSample(int);
// requires: int be in the range [0, (SUBCARRIERS*SAMPLING +
GUARD_SAMPLES - 1)]
// effects: returns modulated sample located in given index
bool isCodedPackingFinished();
// effects: returns true if length(codedData) == codedBlockSize,
false otherwise
complex<double> getCorruptedSample(int);
// requires: int be in the range [0, (SUBCARRIERS*SAMPLING +
GUARD_SAMPLES - 1)]
// effects: returns corrupted sample located in given index
bool isSlicedPackingFinished();
// effects: returns true if length(slicedData) == codedBlockSize,
false otherwise
bool isDecodedPackingFinished();
// effects: returns true if length(decodedData) == uncodedBlockSize,
false otherwise
complex<double> getDemodulatedSample(int);
// requires: int be in the range [0, (SUBCARRIERS - 1)]
// effects: returns demodulated sample located in given index
bool getSlicedBit();
// requires: method be called fewer times than codedBlockSize
// effects: returns next sliced bit and updates respective iterator
array index
// ITERATORS FOR RETRIEVING DATA FROM ARRAYS
/////////////////////////////////////////////
void beginUncodedRetrieval();
// effects: resets uncoded data iteration to the first bit
bool getDecodedBit();
// requires: method be called fewer times than uncodedBlockSize
// effects: returns next decoded bit and updates respective iterator
array index
void beginCodedRetrieval();
// effects: resets coded data iteration to the first bit
158
////////////////////////////////////
// Destructor
////////////////////////////////////
public:
~OfdmSymbol();
// effects: deletes private data of this
}; //end OfdmSymbol class
159
uncodedData = new bool[uncodedBlockSize];
codedData = new bool[codedBlockSize];
slicedData = new bool[codedBlockSize];
decodedData = new bool[uncodedBlockSize];
OfdmSymbol.cpp
#include "OfdmSymbol.h"
// verify that memory allocation was successful
assert(uncodedData != NULL);
assert(codedData != NULL);
assert(slicedData != NULL);
assert(decodedData != NULL);
////////////////////////////////////////////////////////////////////////
// PROJECT: WGLAN Software Simulation
// FILE:
OfdmSymbol.cpp
// AUTHOR:
Eladio Arvelo <earvelo@alum.mit.edu>
// MODS:
Created file -- 11.10.99
//
Implemented all methods -- 11.10.99
//
Compiled class successfully -- 11.10.99
//
Reorganized iterator methods -- 11.23.99
//
Redefined iterator methods -- 11.24.99
//
Reimplemented entire class -- 11.24.99
//
Implemented operator= method -- 12.05.99
//
Changed int type to bool type for bit variables -12.06.99
//
Deleted data and methods regarding dataGuarded -- 12.06.99
//
Implemented errorsAfterDemodulating method -- 12.06.99
//
Reimplemented methods to support pilot symbols -- 12.06.99
//
Added constructor that takes a OfdmSymbol* -- 12.08.99
//
Deleted operator= method -- 01.15.00
//
Reimplemented errorsAfterDemodulating() -- 01.21.00
//
Reimplemented errorsAfterDemodulating() -- 01.24.00
//
Removed methods for computing error statistics -- 02.08.00
////////////////////////////////////////////////////////////////////////
}
OfdmSymbol::OfdmSymbol(const OfdmSymbol& oldSymbol)
{
int i=0;
// initialize OfdmSymbol parameters
senderID = oldSymbol.senderID;
recipientID = oldSymbol.recipientID;
startTime = oldSymbol.startTime;
pilotSymbol = oldSymbol.pilotSymbol;
// initialize block sizes
uncodedBlockSize = oldSymbol.uncodedBlockSize;
codedBlockSize = oldSymbol.codedBlockSize;
// initialize iterator counters
uncodedArrayPutIndex = oldSymbol.uncodedArrayPutIndex;
codedArrayPutIndex = oldSymbol.codedArrayPutIndex;
slicedArrayPutIndex = oldSymbol.slicedArrayPutIndex;
decodedArrayPutIndex = oldSymbol.decodedArrayPutIndex;
////////////////////////////////////
// Constructors
////////////////////////////////////
uncodedArrayGetIndex = oldSymbol.uncodedArrayGetIndex;
codedArrayGetIndex = oldSymbol.codedArrayGetIndex;
slicedArrayGetIndex = oldSymbol.slicedArrayGetIndex;
decodedArrayGetIndex = oldSymbol.decodedArrayGetIndex;
OfdmSymbol::OfdmSymbol(int senderID, int recipientID, int startTime,
int uncodedBlockSize, int codedBlockSize)
{
// initialize OfdmSymbol parameters
this->senderID = senderID;
this->recipientID = recipientID;
this->startTime = startTime;
pilotSymbol = false;
uncodedData = new bool[uncodedBlockSize];
codedData = new bool[codedBlockSize];
slicedData = new bool[codedBlockSize];
decodedData = new bool[uncodedBlockSize];
// initialize block sizes
this->uncodedBlockSize = uncodedBlockSize;
this->codedBlockSize = codedBlockSize;
// verify that memory allocation was successful
assert(uncodedData != NULL);
assert(codedData != NULL);
assert(slicedData != NULL);
assert(decodedData != NULL);
// initialize iterator counters
uncodedArrayPutIndex = 0;
codedArrayPutIndex = 0;
slicedArrayPutIndex = 0;
decodedArrayPutIndex = 0;
for (i=0; i < uncodedBlockSize; i++)
uncodedData[i] = oldSymbol.uncodedData[i];
for (i=0; i < codedBlockSize; i++)
codedData[i] = oldSymbol.codedData[i];
uncodedArrayGetIndex = 0;
codedArrayGetIndex = 0;
slicedArrayGetIndex = 0;
decodedArrayGetIndex = 0;
for (i=0; i < SUBCARRIERS; i++)
qamData[i] = oldSymbol.qamData[i];
// initialize data arrays
for (i=0; i < (SUBCARRIERS*SAMPLING + GUARD_SAMPLES); i++)
160
modulatedData[i] = oldSymbol.modulatedData[i];
qamData[i] = (*symbolPtr).qamData[i];
for (i=0; i < (SUBCARRIERS*SAMPLING + GUARD_SAMPLES); i++)
corruptedData[i] = oldSymbol.corruptedData[i];
for (i=0; i < (SUBCARRIERS*SAMPLING + GUARD_SAMPLES); i++)
modulatedData[i] = (*symbolPtr).modulatedData[i];
for (i=0; i < SUBCARRIERS; i++)
demodulatedData[i] = oldSymbol.demodulatedData[i];
for (i=0; i < (SUBCARRIERS*SAMPLING + GUARD_SAMPLES); i++)
corruptedData[i] = (*symbolPtr).corruptedData[i];
for (i=0; i < codedBlockSize; i++)
slicedData[i] = oldSymbol.slicedData[i];
for (i=0; i < SUBCARRIERS; i++)
demodulatedData[i] = (*symbolPtr).demodulatedData[i];
for (i=0; i < uncodedBlockSize; i++)
decodedData[i] = oldSymbol.decodedData[i];
for (i=0; i < codedBlockSize; i++)
slicedData[i] = (*symbolPtr).slicedData[i];
}
for (i=0; i < uncodedBlockSize; i++)
decodedData[i] = (*symbolPtr).decodedData[i];
}
OfdmSymbol::OfdmSymbol(const OfdmSymbol *symbolPtr)
{
int i=0;
////////////////////////////////////
// Observer Methods
////////////////////////////////////
// initialize OfdmSymbol parameters
senderID = (*symbolPtr).senderID;
recipientID = (*symbolPtr).recipientID;
startTime = (*symbolPtr).startTime;
pilotSymbol = (*symbolPtr).pilotSymbol;
int OfdmSymbol::getSender()
{
return senderID; }
// initialize block sizes
uncodedBlockSize = (*symbolPtr).uncodedBlockSize;
codedBlockSize = (*symbolPtr).codedBlockSize;
// initialize iterator counters
uncodedArrayPutIndex = (*symbolPtr).uncodedArrayPutIndex;
codedArrayPutIndex = (*symbolPtr).codedArrayPutIndex;
slicedArrayPutIndex = (*symbolPtr).slicedArrayPutIndex;
decodedArrayPutIndex = (*symbolPtr).decodedArrayPutIndex;
uncodedArrayGetIndex = (*symbolPtr).uncodedArrayGetIndex;
codedArrayGetIndex = (*symbolPtr).codedArrayGetIndex;
slicedArrayGetIndex = (*symbolPtr).slicedArrayGetIndex;
decodedArrayGetIndex = (*symbolPtr).decodedArrayGetIndex;
int OfdmSymbol::getRecipient()
{
return recipientID;
}
int OfdmSymbol::getBitPayload()
{
return uncodedBlockSize;
}
bool OfdmSymbol::isPilot()
{
return pilotSymbol;
}
double OfdmSymbol::peakModulatedSample()
{
double maxSample=0.;
uncodedData = new bool[uncodedBlockSize];
codedData = new bool[codedBlockSize];
slicedData = new bool[codedBlockSize];
decodedData = new bool[uncodedBlockSize];
for (int i=0; i < (SUBCARRIERS*SAMPLING + GUARD_SAMPLES); i++)
{
if ((double) abs(modulatedData[i].real()) > maxSample)
maxSample = (double) abs(modulatedData[i].real());
if ((double) abs(modulatedData[i].imag()) > maxSample)
maxSample = (double) abs(modulatedData[i].imag());
}
// verify that memory allocation was successful
assert(uncodedData != NULL);
assert(codedData != NULL);
assert(slicedData != NULL);
assert(decodedData != NULL);
return maxSample;
for (i=0; i < uncodedBlockSize; i++)
uncodedData[i] = (*symbolPtr).uncodedData[i];
}
for (i=0; i < codedBlockSize; i++)
codedData[i] = (*symbolPtr).codedData[i];
double OfdmSymbol::averageModulatedSample()
{
double runningSum=0.;
for (int i=0; i < (SUBCARRIERS*SAMPLING + GUARD_SAMPLES); i++)
for (i=0; i < SUBCARRIERS; i++)
161
{
{
pilotSymbol = true;
}
runningSum += (double) abs(modulatedData[i].real());
runningSum += (double) abs(modulatedData[i].imag());
}
void OfdmSymbol::putUncodedBit(bool dataBit)
{
if (uncodedArrayPutIndex < uncodedBlockSize)
{
uncodedData[uncodedArrayPutIndex] = dataBit;
uncodedArrayPutIndex++;
}
else
{
cerr << "Input OVERFLOW in OfdmSymbol::putUncodedBit()" << endl;
}
}
runningSum = runningSum / ((double) 2 * (double) (SUBCARRIERS*SAMPLING
+ GUARD_SAMPLES));
return runningSum;
}
double OfdmSymbol::peakToAverageModulatedSample()
{
return peakModulatedSample() / averageModulatedSample();
}
double OfdmSymbol::peakCorruptedSample()
{
double maxSample=0.;
void OfdmSymbol::putCodedBit(bool dataBit)
{
if (codedArrayPutIndex < codedBlockSize)
{
codedData[codedArrayPutIndex] = dataBit;
codedArrayPutIndex++;
}
else
{
cerr << "Input OVERFLOW in OfdmSymbol::putCodedBit()" << endl;
}
}
for (int i=0; i < (SUBCARRIERS*SAMPLING + GUARD_SAMPLES); i++)
{
if ((double) abs(corruptedData[i].real()) > maxSample)
maxSample = (double) abs(corruptedData[i].real());
if ((double) abs(corruptedData[i].imag()) > maxSample)
maxSample = (double) abs(corruptedData[i].imag());
}
return maxSample;
}
void OfdmSymbol::putQamSample(int index, complex<double> dataSample)
{
if (index < SUBCARRIERS)
qamData[index] = dataSample;
else
cerr << "Index OUT OF BOUND in OfdmSymbol::putQamSample()" << endl;
}
double OfdmSymbol::averageCorruptedSample()
{
double runningSum=0.;
for (int i=0; i < (SUBCARRIERS*SAMPLING + GUARD_SAMPLES); i++)
{
runningSum += (double) abs(corruptedData[i].real());
runningSum += (double) abs(corruptedData[i].imag());
}
void OfdmSymbol::putModulatedSample(int index, complex<double>
dataSample)
{
if (index < (SUBCARRIERS*SAMPLING + GUARD_SAMPLES))
modulatedData[index] = dataSample;
else
cerr << "Index OUT OF BOUND in OfdmSymbol::putModulatedSample()" <<
endl;
}
runningSum = runningSum / ((double) 2 * (double) (SUBCARRIERS*SAMPLING
+ GUARD_SAMPLES));
return runningSum;
}
double OfdmSymbol::peakToAverageCorruptedSample()
{
return peakCorruptedSample() / averageCorruptedSample();
}
void OfdmSymbol::guardModulatedSamples()
{
// first shift all samples to the right of the array by guardBlockSize
spaces
for (int i=0; i < SUBCARRIERS*SAMPLING; i++)
modulatedData[SUBCARRIERS*SAMPLING+GUARD_SAMPLES-i-1] =
modulatedData[SUBCARRIERS*SAMPLING-i-1];
////////////////////////////////////
// Mutator Methods
////////////////////////////////////
void OfdmSymbol::setPilot()
162
// then copy last guardBlockSize samples of the array and place them
to the left of the array
for (int j=0; j < GUARD_SAMPLES; j++)
modulatedData[j] = modulatedData[SUBCARRIERS*SAMPLING+j];
}
modulatedData[i] = modulatedData[i] +
(*interSymbol).modulatedData[i];
}
////////////////////////////////////
// Iterator Methods
////////////////////////////////////
void OfdmSymbol::putCorruptedSample(int index, complex<double>
dataSample)
{
if (index < (SUBCARRIERS*SAMPLING + GUARD_SAMPLES))
corruptedData[index] = dataSample;
else
cerr << "Index OUT OF BOUND in OfdmSymbol::putCorruptedSample()" <<
endl;
}
// ITERATORS FOR FILLING UP DATA ARRAYS
/////////////////////////////////////////////
void OfdmSymbol::beginUncodedPacking()
{
uncodedArrayPutIndex = 0; }
void OfdmSymbol::beginCodedPacking()
{
codedArrayPutIndex = 0;
}
void OfdmSymbol::putDemodulatedSample(int index, complex<double>
dataSample)
{
if (index < SUBCARRIERS)
demodulatedData[index] = dataSample;
else
cerr << "Index OUT OF BOUND in OfdmSymbol::putDemodulatedSample()"
<< endl;
}
void OfdmSymbol::beginSlicedPacking()
{
slicedArrayPutIndex = 0; }
void OfdmSymbol::beginDecodedPacking()
{
decodedArrayPutIndex = 0; }
void OfdmSymbol::putSlicedBit(bool dataBit)
{
if (slicedArrayPutIndex < codedBlockSize)
{
slicedData[slicedArrayPutIndex] = dataBit;
slicedArrayPutIndex++;
}
else
{
cerr << "Input OVERFLOW in OfdmSymbol::putSlicedBit()" << endl;
}
}
void OfdmSymbol::putDecodedBit(bool dataBit)
{
if (decodedArrayPutIndex < uncodedBlockSize)
{
decodedData[decodedArrayPutIndex] = dataBit;
decodedArrayPutIndex++;
}
else
{
cerr << "Input OVERFLOW in OfdmSymbol::putDecodedBit()" << endl;
}
}
bool OfdmSymbol::isUncodedPackingFinished()
{
return (uncodedArrayPutIndex == uncodedBlockSize);
}
bool OfdmSymbol::isCodedPackingFinished()
{
return (codedArrayPutIndex == codedBlockSize);
}
bool OfdmSymbol::isSlicedPackingFinished()
{
return (slicedArrayPutIndex == codedBlockSize);
}
bool OfdmSymbol::isDecodedPackingFinished()
{
return (decodedArrayPutIndex == uncodedBlockSize);
}
// ITERATORS FOR RETRIEVING DATA FROM ARRAYS
/////////////////////////////////////////////
void OfdmSymbol::beginUncodedRetrieval()
{
uncodedArrayGetIndex = 0; }
void OfdmSymbol::beginCodedRetrieval()
{
codedArrayGetIndex = 0;
}
void OfdmSymbol::beginSlicedRetrieval()
{
slicedArrayGetIndex = 0; }
void OfdmSymbol::addInterferer(OfdmSymbol *interSymbol)
{
for (int i=0; i < SUBCARRIERS*SAMPLING + GUARD_SAMPLES; i++)
163
void OfdmSymbol::beginDecodedRetrieval()
{
decodedArrayGetIndex = 0; }
}
}
bool OfdmSymbol::isUncodedRetrievalFinished()
{
return (uncodedArrayGetIndex == uncodedBlockSize);
}
bool OfdmSymbol::isCodedRetrievalFinished()
{
return (codedArrayGetIndex == codedBlockSize);
}
bool OfdmSymbol::isSlicedRetrievalFinished()
{
return (slicedArrayGetIndex == codedBlockSize);
}
bool OfdmSymbol::isDecodedRetrievalFinished()
{
return (decodedArrayGetIndex == uncodedBlockSize);
}
complex<double> OfdmSymbol::getModulatedSample(int index)
{
if (index < (SUBCARRIERS*SAMPLING + GUARD_SAMPLES))
return modulatedData[index];
else
{
cerr << "Index OUT-OF-BOUND in OfdmSymbol::getModulatedSample()"
<< endl;
return complex<double>(0,0);
}
}
complex<double> OfdmSymbol::getCorruptedSample(int index)
{
if (index < (SUBCARRIERS*SAMPLING + GUARD_SAMPLES))
return corruptedData[index];
else
{
cerr << "Index OUT-OF-BOUND in OfdmSymbol::getCorruptedSample()"
<< endl;
return complex<double>(0,0);
}
}
bool OfdmSymbol::getUncodedBit()
{
if (uncodedArrayGetIndex < uncodedBlockSize)
{
uncodedArrayGetIndex++;
return uncodedData[uncodedArrayGetIndex - 1];
}
else
{
cerr << "Iterator OVERFLOW in OfdmSymbol::getUncodedBit()" <<
endl;
return 0;
}
}
complex<double> OfdmSymbol::getDemodulatedSample(int index)
{
if (index < SUBCARRIERS)
return demodulatedData[index];
else
{
cerr << "Index OUT-OF-BOUND in OfdmSymbol::getDemodulatedSample()"
<< endl;
return complex<double>(0,0);
}
}
bool OfdmSymbol::getCodedBit()
{
if (codedArrayGetIndex < codedBlockSize)
{
codedArrayGetIndex++;
return codedData[codedArrayGetIndex - 1];
}
else
{
cerr << "Iterator OVERFLOW in OfdmSymbol::getCodedBit()" << endl;
return 0;
}
}
bool OfdmSymbol::getSlicedBit()
{
if (slicedArrayGetIndex < codedBlockSize)
{
slicedArrayGetIndex++;
return slicedData[slicedArrayGetIndex - 1];
}
else
{
cerr << "Iterator OVERFLOW in OfdmSymbol::getSlicedBit()" << endl;
return 0;
}
}
complex<double> OfdmSymbol::getQamSample(int index)
{
if (index < SUBCARRIERS)
return qamData[index];
else
{
cerr << "Index OUT-OF-BOUND in OfdmSymbol::getQamSample()" <<
endl;
return complex<double>(0,0);
bool OfdmSymbol::getDecodedBit()
{
164
if (decodedArrayGetIndex < uncodedBlockSize)
{
decodedArrayGetIndex++;
return decodedData[decodedArrayGetIndex - 1];
}
else
{
cerr << "Iterator OVERFLOW in OfdmSymbol::getDecodedBit()" <<
endl;
return 0;
}
}
////////////////////////////////////
// Destructor
////////////////////////////////////
OfdmSymbol::~OfdmSymbol()
{
delete [] uncodedData;
delete [] codedData;
delete [] slicedData;
delete [] decodedData;
}
165