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. eMI1t ÜÜÜ e-MI1t ÜÜÜ channel ÜÜÜ ÜÜÜ xM(t) ÜÜÜ y1(t) ÜÜÜ x1(t) yM(t) e-MIMt eMIMt 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 eMI1t x2(t) = Z2 eMI2t xM(t) = ZM ÜÜÜ x1(t) eMIMt 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