Baixe o app para aproveitar ainda mais
Prévia do material em texto
Kelwin Passos Ferreira Desenvolvimento de uma biblioteca Python para simulações computacionais de Sistemas de Telecomunicações Natal – RN Abril de 2021 Kelwin Passos Ferreira Desenvolvimento de uma biblioteca Python para simulações computacionais de Sistemas de Telecomunicações Trabalho de Conclusão de Curso de Engenha- ria de Computação da Universidade Federal do Rio Grande do Norte, apresentado como requisito parcial para a obtenção do grau de Bacharel em Engenharia de Computação Orientador: Prof. Dr. Luiz Felipe de Queiroz Silveira Co-orientador: MSc. Yuri Pedro dos Santos Universidade Federal do Rio Grande do Norte – UFRN Departamento de Engenharia de Computação e Automação – DCA Curso de Engenharia de Computação Natal – RN Abril de 2021 Kelwin Passos Ferreira Desenvolvimento de uma biblioteca Python para simulações computacionais de Sistemas de Telecomunicações Trabalho de Conclusão de Curso de Engenha- ria de Computação da Universidade Federal do Rio Grande do Norte, apresentado como requisito parcial para a obtenção do grau de Bacharel em Engenharia de Computação Orientador: Prof. Dr. Luiz Felipe de Queiroz Silveira Co-orientador: MSc. Yuri Pedro dos Santos Trabalho aprovado. Natal – RN, 29 de Abril de 2021: Prof. Dr. Luiz Felipe de Queiroz Silveira - Orientador UFRN Prof. Dr. Vicente Angelo de Sousa Junior - Convidado UFRN Prof. Dr. Joilson Batista de Almeida Rego - Convidado UFRN Natal – RN Abril de 2021 Ferreira, Kelwin Passos. Desenvolvimento de uma biblioteca Python para simulações computacionais de Sistemas de Telecomunicações / Kelwin Passos Ferreira. - 2021. 59f.: il. Monografia (Graduação) - Universidade Federal do Rio Grande do Norte, Centro de Tecnologia, Departamento de Engenharia de Computação e Automação, Engenharia de Computação, Natal, 2021. Orientador: Dr. Luiz Felipe de Queiroz Silveira. Coorientador: MSc. Yuri Pedro dos Santos. 1. Simulação Computacional - Monografia. 2. Sistemas de Telecomunicações - Monografia. 3. Python - Monografia. I. Silveira, Dr. Luiz Felipe de Queiroz. II. Santos, MSc. Yuri Pedro dos. III. Título. RN/UF/BCZM CDU 004 Universidade Federal do Rio Grande do Norte - UFRN Sistema de Bibliotecas - SISBI Catalogação de Publicação na Fonte. UFRN - Biblioteca Central Zila Mamede Elaborado por RAIMUNDO MUNIZ DE OLIVEIRA - CRB-15/429 Dedico este trabalho à minha família AGRADECIMENTOS Primeiramente gostaria de agradecer a Deus. Agradeço aos meus pais Jânio e Java que sempre estiveram ao meu lado me apoiando ao longo de toda a minha trajetória. Agradeço ao meu irmão Mairon pelo apoio e amizade. Agradeço ao meu co-orientador, Yuri Pedro dos Santos pela atenção e disponibili- dade. Agradeço ao meu orientador, Luiz Felipe de Queiroz Silveira pela oportunidade. Agradeço aos docentes do curso de Engenharia de Computação da Universidade Federal do Rio Grande do Norte por todo aprendizado e assistência na minha formação. Agradeço aos meu amigos e colegas de curso que sempre estiveram ao meu lado, pela amizade e apoio demonstrado. “Mas, sejam fortes e não desanimem, pois o trabalho de vocês será recompensado” (Bíblia Sagrada, 2 Crônicas 15:7) RESUMO As simulações computacionais são de grande importância para área de sistemas de te- lecomunicações, pois possibilitam o estudo de comportamento, criação de hipóteses e representações de modelos. Apesar disso, a quantidade de ferramentas acessíveis que possi- bilitam esse estudo ainda é pequena, pois estão incompletas ou necessitam de obtenção de uma licença paga para uso. Por isso, este trabalho tem como objetivo o desenvolvimento de uma biblioteca em Python para auxílio no desenvolvimento de simulações computacionais de sistemas de telecomunicações. Foram desenvolvidas cinco funções, que dentre elas, três modulações (BSPK,OFDM,OFDMA), um modelo de canal sem fio com desvanecimento de Rayleigh e um codificador de canal de Hamming. Além disso, as funções serão analisadas em termos de desempenho, com o objetivo de compará-las com funções semelhantes da biblioteca CommPy, que é um conjunto de algoritmos de simulação de comunicação digital desenvolvido em Python com uso dos pacotes NumPy e SciPy, para levantamento das vantagens e desvantagens de cada biblioteca. Palavras-chaves: Simulação Computacional; Sistemas de Telecomunicações; Python; ABSTRACT Computer simulations are of great importance for the area of telecommunications systems, as they enable the study of behavior, creation of hypotheses and model representations. In spite of this, the amount of tools to gain that make this study possible is still small, as it is incomplete or prepared to obtain a paid licence for use. This work has a objective to develop a Python library to aid in the development of computer simulations of telecommunications systems. Five functions were developed, among which, three modulations (BSPK, OFDM, OFDMA), a wireless channel model with Rayleigh fading and a Hamming channel encoder. In addition, the functions will be analyzed in terms of performance, in order to compare them with similar functions of the CommPy library, which is a set of digital communication simulation algorithms developed in Python using the NumPy and SciPy packages, to survey of the advantages and disadvantages of each library. Keywords: Computational Simultion; Telecommunications Systems; Python; LISTA DE ILUSTRAÇÕES Figura 1 – Elementos de um sistema de comunicação . . . . . . . . . . . . . . . . 13 Figura 2 – (a) Sequência binária de dados. (b) Chaveamento de fase . . . . . . . . 15 Figura 3 – (a) Modulador BPSK (b) Detector coerente BPSK . . . . . . . . . . . 16 Figura 4 – Subportadoras de um sinal OFDM. Frequencia normalizada em relação ao valor 1/T . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 17 Figura 5 – Relação do espectro de um sinal FDM e OFDM . . . . . . . . . . . . . 18 Figura 6 – Digrama de blocos OFDM . . . . . . . . . . . . . . . . . . . . . . . . . 18 Figura 7 – Constelação 16 QAM com código Gray . . . . . . . . . . . . . . . . . . 19 Figura 8 – Símbolo OFDM adicionado por um prefixo cíclico . . . . . . . . . . . . 19 Figura 9 – Ilustração dos conceitos do OFDM e OFDMA . . . . . . . . . . . . . . 20 Figura 10 – Diagrama de blocos do OFDMA . . . . . . . . . . . . . . . . . . . . . 21 Figura 11 – Exemplos de esquemas alocação . . . . . . . . . . . . . . . . . . . . . . 22 Figura 12 – Modelo de sistema de comunicação digital . . . . . . . . . . . . . . . . 25 Figura 13 – Simulação da modulação BPSK . . . . . . . . . . . . . . . . . . . . . . 38 Figura 14 – Simulação da demodulação BPSK . . . . . . . . . . . . . . . . . . . . . 38 Figura 15 – Distribuição das subportadoras . . . . . . . . . . . . . . . . . . . . . . 40 Figura 16 – Sinal após o canal e taxa de erro de bit . . . . . . . . . . . . . . . . . . 41 Figura 17 – Distribuição das subportadoras . . . . . . . . . . . . . . . . . . . . . . 42 Figura 18 – Distribuição das subportadoras . . . . . . . . . . . . . . . . . . . . . . 43 Figura 19 – Modulação OFDMA . . . . . . . . . . . . . . . . . . . . . . . . . . . . 43 Figura 20 – Saída do codificador de Hamming . . . . . . . . . . . . . . . . . . . . . 44 Figura 21 – Saída do decodificador de Hamming . . . . . . . . . . . . . . . . . . . . 44 LISTA DE TABELAS Tabela 1 – Análise de desempenho - Modulação BPSK . . . . . . . . . . . . . . . 39 Tabela 2 – Análise de desempenho - Modulação OFDM . . . . . . . . . . . . . . . 41 Tabela 3 – Análise de desempenho - Modulação OFDMA . . . . . . . . . . . . . . 44 Tabela 4 – Análise de desempenho - Codificador de Hamming . . . . . . . . . . . 45 Tabela 5 – Análise de desempenho - Canal . . . . . . . . . . . . . . . . . . . . . . 45 LISTA DE ABREVIATURAS E SIGLAS PSK Phase Shift Keying BPSK Binary Phase Shift Keying FDM Frequency-Division Multiplexing OFDM Orthogonal Frequency-Division Multiplexing OFDMA Orthogonal Frequency-Division Multiple Access QAM QuadratureAmplitude Modulation SP Serial-Parallel Converter IDFT Inverse Discrete Fourier Transform IFFT Inverse Fast Fourier Transform FFT Fast Fourier Transform CP Cyclic Prefix GWSSUS Gaussian Wide Sense Stationary Uncorrelated Scattering WSSUS Wide Sense Stationary Uncorrelated Scattering NRZ Non Return to Zero BER Bit Error Rate SUMÁRIO 1 INTRODUÇÃO . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 13 1.1 Motivação . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 14 1.2 Objetivos . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 14 1.3 Estrutura do Trabalho . . . . . . . . . . . . . . . . . . . . . . . . . . . 14 2 REFERENCIAL TEÓRICO . . . . . . . . . . . . . . . . . . . . . . . 15 2.1 Modulação de chaveamento binário de fase . . . . . . . . . . . . . . 15 2.1.1 Geração de sinais BPSK . . . . . . . . . . . . . . . . . . . . . . . . . . . 16 2.1.2 Detecção coerente de sinais BPSK . . . . . . . . . . . . . . . . . . . . . . 16 2.2 Multiplexação por Divisão de Frequências Ortogonais . . . . . . . . 17 2.2.1 Transmissão e Recepção do sinal OFDM . . . . . . . . . . . . . . . . . . . 18 2.2.1.1 Transmissão . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 18 2.2.1.2 Recepção . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 19 2.3 Acesso Múltiplo por Divisão de Frequência Ortogonal . . . . . . . . 20 2.3.1 Transmissão e Recepcção OFDMA . . . . . . . . . . . . . . . . . . . . . . 21 2.3.1.1 Alocação de subportadoras . . . . . . . . . . . . . . . . . . . . . . . . . . . 21 2.3.1.2 Transmissão . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 22 2.3.1.3 Recepção . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 22 2.4 Canal . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 23 2.4.1 Técnica de Monte-Carlo . . . . . . . . . . . . . . . . . . . . . . . . . . . 23 2.4.2 Canal multipercurso com desvanecimento Rayleigh . . . . . . . . . . . . . 24 2.5 Codificador de canal . . . . . . . . . . . . . . . . . . . . . . . . . . . . 24 2.5.1 Código de Hamming . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 25 3 METODOLOGIA . . . . . . . . . . . . . . . . . . . . . . . . . . . . 27 3.1 Implementação . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 27 3.1.1 BPSK . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 28 3.1.1.1 Modulação . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 28 3.1.1.2 demodulação . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 29 3.1.2 OFDM . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 30 3.1.2.1 Modulação . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 31 3.1.2.2 Demodulação . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 32 3.1.3 OFDMA . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 33 3.1.3.1 Modulação e Demodulação . . . . . . . . . . . . . . . . . . . . . . . . . . . 34 3.1.4 Canal . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 34 3.1.5 Codificador Hamming . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 35 3.1.5.1 Codificação . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 35 3.1.5.2 Decodificação . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 36 4 RESULTADOS . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 37 4.1 Modulação e Demodulação BPSK . . . . . . . . . . . . . . . . . . . . 37 4.1.1 Análise de desempenho . . . . . . . . . . . . . . . . . . . . . . . . . . . . 38 4.2 Modulação e Demodulação OFDM . . . . . . . . . . . . . . . . . . . 39 4.2.1 Análise de desempenho . . . . . . . . . . . . . . . . . . . . . . . . . . . . 41 4.3 Modulação OFDMA . . . . . . . . . . . . . . . . . . . . . . . . . . . . 42 4.3.1 Análise de desempenho . . . . . . . . . . . . . . . . . . . . . . . . . . . . 43 4.4 Codificador Hamming . . . . . . . . . . . . . . . . . . . . . . . . . . . 44 4.4.1 Análise de desempenho . . . . . . . . . . . . . . . . . . . . . . . . . . . . 44 4.5 Canal . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 44 4.5.1 Análise de desempenho . . . . . . . . . . . . . . . . . . . . . . . . . . . . 45 5 CONCLUSÃO . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 47 REFERÊNCIAS . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 48 A APÊNDICE - CÓDIGOS FONTE . . . . . . . . . . . . . . . . . . . . 50 A.1 Classe BPSK . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 50 A.2 Classe OFDM . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 51 A.3 Classe OFDMA . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 53 A.4 Classe do Canal multipercurso com desvanecimento Rayleigh . . . . 56 A.5 Classe do codificador Hamming . . . . . . . . . . . . . . . . . . . . . 57 13 1 INTRODUÇÃO Ao Longo das últimas décadas, a rápida expansão das tecnologias de comunicação foi considerável. (LATHI B. P.; DING, 2012). O rádio, o telefone, a televisão, são exemplos de algumas das várias aplicações dos sistemas de comunicação, mesmo que algumas já pararam de funcionar, outras como a internet comandam como nos comunicamos atualmente. Sendo assim, a lista de aplicações que envolvem a utilização comunicações é muito grande. A Figura 1 ilustra um diagrama de blocos que representa um modelo básico de um sistema de comunicação. O transmissor, converte o sinal da mensagem em uma forma adequada para a transmissão no canal, o canal transporta o sinal de mensagem e a entrega para o receptor (HAYKIN; MOHER, 2008). Devido às imperfeições do canal o sinal é distorcido e ao longo da transmissão do canal são adicionados ruídos e sinais de interferência de outras fontes, e por isso se tem uma versão corrompida do sinal transmitido. O receptor possui a tarefa de operar no sinal recebido, de forma a produzir uma estimativa do sinal original da mensagem para o usuário da informação (HAYKIN; MOHER, 2008). Figura 1 – Elementos de um sistema de comunicação. Fonte – (HAYKIN; MOHER, 2008, p. 15) Por meio da simulação computacional, um modelo de sistema de comunicação pode ser analisado, possibilitando incorporar características reais, de modo a obter resultados estatísticos que descrevam o seu comportamento em diversos tipos de condições. Desta forma, a simulação não é somente a construção do modelo, mas também um método experimental que busca representar, criar hipóteses e estudar comportamentos. Apesar da grande importância das simulações nessa área, ainda é difícil encontrar ferramentas gratuitas e completas que auxiliem nessa finalidade. Com isso, o propósito deste trabalho é contribuir com desenvolvimento de modelos para simulações computacionais de sistemas de telecomunicação, além de analisar em termos de desempenho as funções criadas. Capítulo 1. Introdução 14 1.1 Motivação Diante da importância das simulações computacionais em sistemas de telecomu- nicações, se faz necessário o desenvolvimento de ferramentas que auxiliem e contribuam com o avanço da área. Atualmente já existem ferramentas para simulações de sistemas de comunicação, porém, parte delas necessita de compra de licença para uso ou estão incompletas, diante deste problema, é proposta a criação de uma biblioteca em Python para simulações computacionais de sistemas de telecomunicações. 1.2 Objetivos Este projeto tem como objetivo contribuir com a criação de uma biblioteca em Python, para auxílio no desenvolvimento de simulações computacionais de sistemas de telecomunicações, serão desenvolvidas as seguintes funções: • Modulador e Demodulador BPSK. • Modulador e Demodulador OFDM. • Modulador e Demodulador OFDMA. • Canal com desvanecimento Rayleigh. • Codificador de canal Hamming. De modo que cada uma das funções desenvolvidas seja fiel ao seu referencial teórico, e além disso, serão analisadas em termos de desempenho para fins de comparação. 1.3 Estruturado Trabalho Este trabalho está organizado em cinco capítulos, no qual, o primeiro capítulo apresenta um introdução sobre o tema, apresentando a motivação e objetivos. Em sequência o Capítulo 2 aborda o referencial teórico dos sistemas de comunicação usados nas simulações. O Capítulo 3, por sua vez, explica a metodologia usada para desenvolvimento das simulações na linguagem Python. O Capítulo 4 apresenta os resultados das simulações. E finalmente, o Capítulo 5 traz as conclusões e contribuições deste trabalho. 15 2 REFERENCIAL TEÓRICO Neste capítulo, são apresentados os conceitos fundamentais relacionados a modulação de chaveamento binário de fase (BPSK), as técnicas de transmissão de dados Multiplexação ortogonal por divisão em freqüência (OFDM) e sua versão multiusuário, a Multiplexação ortogonal por divisão em freqüência de acesso multiplo (OFDMA), além de um canal multipercurso com desevanecimento de Rayleigh e um codificador de canal de Hamming. 2.1 Modulação de chaveamento binário de fase O método de modulação de chaveamento binário de fase (BPSK) é uma forma de modulação binária, na qual a frequência e a amplitude da portadora são preservadas constantes e a fase da portadora é mantida em dois possíveis valores para representar os símbolos 1 e 0 (por exemplo, 0◦ e 180◦). Para representar os símbolos 0 e 1, são utilizados dois sinais s1(t) e s2(t), que podem ser definidos como: si(t) = √ 2Eb Tb cos(2πfct), para o símbolo 1, i = 1√ 2Eb Tb cos(2πfct+ π) = − √ 2Eb Tb cos(2πfct), para o símbolo 0, i = 2 (2.1) na qual 0 ≤ t ≤ Tb, com Tb representando a duração do bit, Eb representando a energia por bit do sinal transmitido e fc é a frequência da portadora (HAYKIN; MOHER, 2008). A Figura 2(b) mostra a forma de onda BPSK corresponde à sequencia binária de dados de entrada da Figura 2(a). Figura 2 – (a) Sequência binária de dados. (b) Chaveamento de fase. Fonte – (HAYKIN; MOHER, 2008, p. 277) Segundo (HAYKIN; MOHER, 2008) para geração e detecção de um sinal BPSK, é necessário seguir os passos ilustrados na Figura 3, que são explicados em seguida. Capítulo 2. Referencial Teórico 16 Figura 3 – (a) Mobudalor BPSK (b) Detector coerente BPSK. Fonte – (HAYKIN; MOHER, 2008, p. 279) 2.1.1 Geração de sinais BPSK 1. Codificador de nìvel sem retorno para zero: em que a sequência binária de dados na entrada é codificada para a forma polar com os símbolos 0 e 1 representados pelos níveis de amplitude − √ Eb e √ Eb respectivamente. 2. Modulador de produto: que multiplica a onda binária codificada em nível pela onda portadora senoidal √ 2 Tb cos(2πfct) para produzir o sinal BPSK. 2.1.2 Detecção coerente de sinais BPSK 1. Modulador de produto: que também multiplica a onda binária codificada em nível pela onda portadora senoidal √ 2Eb Tb cos(2πfct). 2. Filtro passa-baixa: para remover as as componentes centradas em 2fc e passar as componentes de freqüência nula. 3. Amostrador: amostra uniformemente a saída do filtro passa-baixa em t = iTb, na qual i = 0, ±1, ±2,... . 4. Dispositivo de tomada de decisão: compara os valores amostrados do filtro passa- baixa com um limiar, se o limiar não for ultrapassado o dispositivo escolhe o símbolo 0, caso contrário, o símbolo 1. O receptor é dito ser coerente, no sentido de que o sinal senoidal de referência aplicado ao modulador de produto no demodulador está em sincronismo de fase (e, de freqüência) com a onda portadora utilizada no modulador (HAYKIN; MOHER, 2008). Capítulo 2. Referencial Teórico 17 2.2 Multiplexação por Divisão de Frequências Ortogonais O esquema de modulação baseado na multiplexação por divisão de frequências ortogonais (OFDM), é uma técnica que usa a sua banda dividida em várias portadoras ortogonais, que são chamadas de subportadoras, e habitualmente são equidistantes na frequência. A técnica OFDM fundamenta-se na conversão de um fluxo de dados em série que possui alta taxa de transmissão, em sub-fluxos paralelos de dados em várias subporta- doras que são moduladas (geralmente em QAM ou PSK), que possuem baixa taxa de transmissão de acordo com a maior quantidade de destas empregadas. Esta redução na taxa de transmissão (aumento na duração dos simbolos) causa uma menor sensibilidade à seletividade em frequência (PINTO; ALBUQUERQUE, 2002). No sistema OFDM, o espaçamento estre as subportadoras é selecionado de forma que cada subportadora seja locada em pontos de cruzamento de zero do espectro das demais (PINTO; ALBUQUERQUE, 2002), conforme ilustrado na Figura 4, sendo T a duração de um símbolo. Figura 4 – Subportadoras de um sinal OFDM. Frequencia normalizada em relação ao valor 1/T. Fonte – (PINTO; ALBUQUERQUE, 2002) A transmissão OFDM surgiu como uma evolução da FDM (Multiplexação por divi- são de frequência), que para separar as frequências dos sinais, usava bandas de segurança, que causavam uma perda de espectro. O sistema OFDM com o uso de subportadoras otogo- nais, traz uma grande eficiência espectral em relação ao FDM (PINTO; ALBUQUERQUE, 2002) como mostrado na Figura 5. Capítulo 2. Referencial Teórico 18 Figura 5 – Relação do espectro de um sinal FDM e OFDM. Fonte – (PINTO; ALBUQUERQUE, 2002) 2.2.1 Transmissão e Recepção do sinal OFDM A Figura 6 apresenta o diagrama em blocos de um sistema OFDM, com o uso da IFFT/FFT no transmissor e receptor, respectivamente. Figura 6 – Digrama de blocos OFDM. Fonte – Própio Autor 2.2.1.1 Transmissão Primeiramente, é realizada uma conversão série-paralelo(SP) na cadeia de dados obtida, os bits irão ser agrupados em conjuntos de palavras, o tamanho destas palavras varia de acordo com a quantidade de bits por simbolo, após isso, as palavras são mapeadas, em um tipo específico, como por exemplo QAM ou PSK, gerando um conjunto de símbolos complexos representados por uma constelação, e cada ponto da constelação corresponde a um símbolo, que representa uma palavra de tamanho dependente do tipo de modolação usado (CHO et al., 2010). A Figura 7 ilustra um exemplo de uma constelação de modulação 16 QAM usando codificação de Gray. Capítulo 2. Referencial Teórico 19 Figura 7 – Constelação 16 QAM com código Gray. Fonte – (BROWN; PASUPATHY; PLATANIOTIS, 2006) Os símbolos complexos determinam os pontos da constelação de cada subportadora. Após isto, as subportadoras são somadas por uma implementação computacional eficiente da IDFT, a IFFT , que transforma os símbolos para o dominio do tempo (CHO et al., 2010), em seguida é realizada uma conversão paralelo-série e é adicionado o prefixo cíclico, que é uma extensão cíclica do símbolo OFDM para o intervalo de guarda , Ou seja, inserir no início do símbolo OFDM o conteúdo da parte final do mesmo (ARNDT, 2012) de forma a evitar interferência intersimbólica, como ilustra a Figura 8. Figura 8 – Símbolo OFDM adicionado por um prefixo cíclico. Fonte – (ARNDT, 2012) 2.2.1.2 Recepção Como ilustrado na Figura 6, inicialmente é retirado o prefixo cíclico (CP), em seguida é usada a Transformada Rápida de Fourier (FFT), para transformar o sinal de volta para o domínio da frequência (CHO et al., 2010), logo após, é feita uma estimação do canal, pois as subportadoras ainda estão sujeitas a perdas de ortogonalidade e distorções devido ao canal, estas interferências causam alterações na amplitude da constelação (Coleri et al., Capítulo 2. Referencial Teórico 20 2002), a técnica de estimação de canal usada neste trabalho é a inserção de subportadoras pilotos no símbolo OFDM , as subportadoras pilotos não carregam nenhuma informação útil, apenas o conteúdo destas é conhecido pelo receptor, tornando possível obter a função de transferência do canal (Coleri et al., 2002). Para realizar a estimação do canal, é necessário primeiramente determinar o desvanecimento nas subportadoras pilotos por meio de um estimador. Como esse valor é conhecido pelo receptor é possível estimar as variações do sinal recebido , e em seguida a estimação para todas as subportadoras de informação útil (CHO et al., 2010), e por fim é realizado o demapeamentoe conversão paralelo-serie. 2.3 Acesso Múltiplo por Divisão de Frequência Ortogonal O sistema OFDMA é muito similar ao OFDM, no qual a maior diferença entre os dois sistemas, é que ao invés de serem alocadas todas as subportadoras disponíveis para um único usuário como ocorre no OFDM, o OFDMA aloca um subconjunto de subportadoras para cada um dos usuários, com o objetivo de uma transmissão simultânea de múltiplos usuários (AL-RAWI, 2017), esta diferença é ilustrada na Figura 9. Figura 9 – Ilustração dos conceitos do OFDM e OFDMA. Fonte – (PARKER, 2017) Capítulo 2. Referencial Teórico 21 A alocação de subconjuntos de subportadoras para os usuários pode variar, na próxima subseção será abordado as duas principais estratégias para alocação. 2.3.1 Transmissão e Recepcção OFDMA Como dito anteriormente, o sistema OFDMA é semelhante ao OFDM, o que difere é que no ofdma existem multiplos usuários e as subportadoras são alocadas em subconjuntos para cada usuário. Dito isto, o diagrama de blocos a seguir ilustra um sistema OFDMA. Figura 10 – Diagrama de blocos do OFDMA. Fonte – (ALI; SUKAR; PAL, 2014) Como pode ser visto na Figura 10, compararado ao digrama de blocos do OFDM, se tem a adição de um novo bloco, o do mapeamento de subportadoras. 2.3.1.1 Alocação de subportadoras Existem dois principais de como distribuir as subportadoas aos usuários (MORELLI; KUO; PUN, 2007), como é ilustrado na Figura 11. Neste exemplo é usado 16 subportadoras, 4 usuários e 4 símbolos por usuário como parâmetros do sistema, no primeiro esquema Figura 11 (a) as subportadoras são associadas a cada usuário em grupos adjacentes, a principal desvantagem dessa abordagem é que ela não explora a diversidade de frequência oferecida pelo canal, uma vez que um desvanecimento profundo pode atingir um número substancial de subportadoras de um determinado usuário (MORELLI; KUO; PUN, 2007), como solução para isto, pode-se adotar o esquema que está ilustrado na Figura 11 (b), em que as subportadoras são espaçadas uniformemente sobre a largura de banda de sinal, explorando totalmente a diversidade de frequência do canal. Capítulo 2. Referencial Teórico 22 Figura 11 – Exemplos de esquemas alocação. Fonte – (MORELLI; KUO; PUN, 2007) 2.3.1.2 Transmissão Para a etapa de transmissão, primeiramente realiza-se uma conversão série-paralelo (SP) na cadeia de dados obtida, os bits irão ser agrupados em conjuntos de palavras, o tamanho destas palavras varia de acordo com a quantidade de bits por simbolo , após isso, as palavras são mapeadas , em um tipo específico como por exemplo, QAM ou PSK, gerando um conjunto de simbolos complexos representados por uma constelação, e cada ponto da constelação corresponde a um símbolo que representa uma palavra de tamanho dependente do tipo de modolação usado. Após a isto, as subportadoras são somadas por uma implementação computacional eficiente da IDFT, a IFFT , que transforma os símbolos para o dominio do tempo (CHO et al., 2010), em seguida é há uma conversão paralelo-série e é adicionado o prefixo cíclico, que é uma extensão cíclica do símbolo OFDMA para o intervalo de guarda, Ou seja, inserir no início do símbolo OFDMA o conteúdo da parte final do mesmo (ARNDT, 2012) 2.3.1.3 Recepção Como ilustrado na Figura 10, inicialmente é retirado o prefixo cíclico (CP), em seguida é usada a Transformada Rápida de Fourier (FFT), para transformar o sinal de volta para o domínio da frequência, logo após é feita uma estimação do canal, pois as subportadoras ainda estão sujeitas a perdas de ortogonalidade e distorções devido ao canal, estas interferências causam alterações na amplitude da constelação (Coleri et al., 2002), a técnica de estimação de canal usada neste trabalho é a inserção de subportadoras pilotos no símbolo OFDMA. As portadoras pilotos não carregam nenhuma informação útil, apenas o conteúdo destas é conhecido pelo receptor, tornando possível obter a função de transferência do canal (Coleri et al., 2002). Para realizar a estimação do canal, é necessário primeiramente determinar o desvanecimento nas subportadoras pilotos por meio de um Capítulo 2. Referencial Teórico 23 estimador . Como esse valor é conhecido pelo receptor é possível estimar as variações do sinal recebido, e em seguida a estimação para todas as subportadoras de informação útil (CHO et al., 2010), e por fim é realizado o demapeamento e conversão paralelo-serie. 2.4 Canal Um canal é o meio físico que se comporta parcialmente como um filtro que, em geral, atenua o sinal e distorce as formas de onda transmitidas. A atenuação do sinal aumenta com o comprimento do canal, variando de uma pequena porcentagem, no caso de curtas distâncias, a ordens de magnitude, no caso de comunicação interplanetária (LATHI B. P.; DING, 2012). Quando a resposta impulsiva do canal móvel é modelado como um processo gaussiano de valor complexo e média nula, este é chamado de canal com desvanecimento Rayleigh. O tipo de distorção introduzida pelo canal pode ser classificada em desvanecimento plano ou desvanecimento seletivo em frequência, e esta depende da relação da largura de banda do sinal transmitido com relação a banda de coerência do canal. Se a largura de banda do sinal for maior que a banda de coerência do canal, o desvanecimento é seletivo em frequência, caso contrário, o desvanecimento é plano. A modelagem e caracterização de canais são bastante estudados no campo da pesquisa de sistemas de comunicações. O grande motivo disso é devido as característi- cas de propagação deste meio que causam grande parte dos problemas existentes nos sistemas móveis. Por outro lado, existe uma complexidade considerável desenvolver estas característcas, visto que, possuem componentes de difícil tratamento formal, que possuem características aleatoriamente variantes no tempo. Por isso a utilização de técnicas de simulação, é fundamental. 2.4.1 Técnica de Monte-Carlo A técnica de simulação de monte-carlo foi originalmente proposta por (SCHULZE, 1989), ao longo dos anos, foi estudada e usada em vários trabalhos que envolviam simulações de sistemas de comunicações com canais GWSSUS. Esta técnica tem como fundamento um modelo estocástico que reflete diretamente a estrutura de múltiplos percursos do canal móvel. A geração da resposta do canal é dada pela superposição linear de N percursos elementares, individualmente caracterizados pelo valor de atraso τn, deslocamento de doppler υn e amplitude complexa an (GUIMARÃES; PINTO, 2001), a resposta ao impulso do canal simulado é dada por: h(τ, t) = √ 1 N N−1∑ n=0 anδ(τ − τn)ej2πυnt (2.2) Capítulo 2. Referencial Teórico 24 Em que, as amplitudes complexas an são variáveis aleatórias não nulas de media nula e variância unitária, já as variáveis υn e τn são aleatórias independentes e indenticamente distribuídas, em que, no geral são consideradas independentes entre si, e em muitas aplicações, a geração da variável τn é dispensada, para usar um modelo de retardos pré-fixados (GUIMARÃES; PINTO, 2001). É demonstrado em (Muller, 1994) que, considerando as hipóteses acima, o pro- cesso aleatório gerado em (2.2) possui propriedades estatisticas de segunda ordem que correspondem às características da resposta de um canal WSSUS. 2.4.2 Canal multipercurso com desvanecimento Rayleigh Um canal multipercurso com desvanecimento Rayleigh pode ser simulado por meio do método do Ruído branco filtrado, passando um ruído braco gaussiano por meio de um filtro gaussiano com frequência igual a raiz quadrada do espectro Doppler, o espectro de potência Doppler para o desvanecimento de Rayleigh pode ser representado pela seguinte equação (CLARKE, 1968): S(v) = 1 πfd √ 1− ( v fd )2 (2.3) Em que v é a mudança de frequência em relação à frequência portadora e fd é o deslocamento Doppler. Segundo (SAVAUX, 2013) para simulação do canal é necessario seguir os seguintes passos. Para cada percurso e para o processo de tamanho N: 1. Gerar um processo Gaussiano de tamanho N. 2. Realizar uma DFT do processo. 3. Filtrar por meio daraiz quadrada do espectro Doppler a saída do item anterior 4. Realizar uma IDFT para obtenção dos coeficientes do canal. 2.5 Codificador de canal O canal de comunicação está sujeito a interferências, ruído e estabimento, podendo causar alteração, ou até mesmo, perda de parte da mensagem. Desta forma é necessário prover uma forma capaz de transmitir informações de uma extremidade a outra do sistema, com nivel de confiabilidade e qualidade aceitáveis. O controle de erro para integridade de dados pode ser exercido por meio de correção direta de erros (FEC) (HAYKIN, 2004). A Figura 12 demonstra um modelo de sistema de comunicação digital que usa esta abordagem, Capítulo 2. Referencial Teórico 25 em que o codificador de canal adiciona redundância aos bits de mensagem com uma regra predefinida e o decodificador de canal explora essa redundância para escolher quais bits da mansegem foram transmitidos de verdade. Figura 12 – Modelo de sistema de comunicação digital. Fonte – próprio autor A meta conjunta do codificador e decodificador de canal é minimizar o efeito de ruído do canal, ou seja, o número de erros entre a entrada do codificador de canal (originado da fonte) e a saída do decodificador de canal (entregue ao usuário) é minimizado (HAYKIN, 2004). 2.5.1 Código de Hamming O código de Hamming foi desenvolvido por Richard Hamming e é considerado um código de bloco linear, é uma codificação que é usada no processaento de sinal e em telecomunicações. Seu uso permite o armazenamento e transferência de dados de forma segura e eficiente. Os modelos de código de Hamming mais usados em telecomunicações, são generalizações do Hamming(7,4) que pode corrigir erros de até um bit. O código Hamming se baseia em inserir bits de paridade sobre uma mensagem de dados de tamanho fixo. Em cada palavra de dados, de comprimento n, são inseridos um número fixo k, de bits de paridade, gerando uma mensagem de comprimento N = n+k. Permitindo a detecção e correcção dos erros. A relação entre N e k é descrita pela seguinte equação: Capítulo 2. Referencial Teórico 26 N = 2k − 1 E o tamanho da palavra de dados é: n = 2k − k − 1 27 3 METODOLOGIA Por meio da linguagem Python, foi proposto contribuir com o desenvolvimento de funções que auxiliem as simulações de sistemas de telecomunicações, ao todo, as contribui- ções foram: Modulador e Demodulador BPSK, Transmissor e Receptor OFDM/OFDMA, Canal com desvanecimento de Rayleigh e um codificador de canal de Hamming. Como dito anteriormente, a linguagem de programação usada é o Python, que é uma liguagem livre e de código aberto, possui uma sintaxe simples, pois foi projetada com a idéia de enfatizar a importância do esforço do programador sobre o esforço computacional. É uma linguagem de propósito geral de alto nível, suporta o paradigma orientado a objetos. Apresenta tipagem dinâmica e uma de suas principais particularidades é a fácil leitura e de código e exige menos linhas de código se comparada com outras linguagems de programação. Numpy1 é uma biblioteca Python que é usada principalmente para cálculos em arrays multidimensionais. Fornece um grande conjunto de funções e operações que auxiliam a execução de diversos tipos de cálculos numéricos. Scipy2 é uma biblioteca Python que possui várias ferramentas dedicadas a problemas comuns em computação científica. Seus diferentes sub-módulos correspondem a várias aplicações, como por exemplo interpolação, integração, otimização, processamento de imagens, estatísticas, etc. Matplotlib3 é uma biblioteca Python desenvolvida para geração de gráficos e vizua- lização de dados, foi usada neste projeto para apresentação dos resultados e visualização dos dados, de forma a ajudar na compreensão do que foi desenvolvido. IPython4 é um interpretador interativo, que é focado na linguagem Python, foi usado pois possui funções para medição de tempo de um trecho de código. 3.1 Implementação As simulações foram inspiradas nos diagramas de blocos mostrados no capítulo anterior. 1https://numpy.org/ 2https://www.scipy.org/ 3https://matplotlib.org/ 4https://ipython.org/ Capítulo 3. Metodologia 28 3.1.1 BPSK A classe que simula a BPSK possui dois métodos (modulação e demodulação) e recebe como parâmetros: • energy_per_bit, que representa a energia por bit. • bit_duration, que representa a duração do bit. • carrier_frequency, que representa a frequência da portadora. • sampling_frequency, que representa a frequência de amostragem. Cabe considerar, que a duração do bit bit_duration, para esse modelo, é constante para todos os bits de entrada, portanto foi possível determinar o parâmetro de amplitude√ 2Eb Tb da portadora no método de inicialização da classe: 1 import numpy as np 2 import scipy. signal as signal 3 4 class bpsk: 5 def __init__ (self , energy_per_bit , bit_duration , carrier_frequency , sampling_frequency ): 6 7 self. carrier_frequency = carrier_frequency 8 self. bit_duration = bit_duration 9 self. energy_per_bit = energy_per_bit 10 self. sampling_frequency = sampling_frequency 11 self. sqrt_Eb_Bd = np.sqrt ((2* self. energy_per_bit )/self. bit_duration ) Listing 3.1 – Classe BPSK 3.1.1.1 Modulação O primeiro passo para desenvolvimento do método de modulação BPSK, foi a codificação da sequência binária de dados por meio de um conversor sem retorno para zero (NRZ), de forma a alterar a entrada de simbolos compostos por 0 e 1 para a forma polar, representados pelos niveis de amplitude -1 e 1, após isso, foi necessário criar um array para representar as amostras do tempo, com a distribuição de acordo com a frequência de amostragem, tamanho da sequência binária e duração do bit, em seguida, é necessário fazer com que o array obtido na codificação NRZ seja disposto também no tempo, e por fim, é realizada a multiplicação pela onda portadora senoidal, como demonstrado no trecho de código a seguir: Capítulo 3. Metodologia 29 1 def modulation (self , bit_sequence ): 2 3 nrtn = 2* bit_sequence - 1 4 t = np. linspace (0, len( bit_sequence )*self. bit_duration , self. sampling_frequency *len( bit_sequence )) 5 nrtn_fs = np. repeat (nrtn , self. sampling_frequency ) 6 return nrtn_fs *( self. sqrt_Eb_Bd *np.cos (2* np.pi*self. carrier_frequency *t)) Listing 3.2 – Método de modulação BPSK 3.1.1.2 demodulação Para o método de demodulação BPSK, foi necessário criar um array para representar as amostras do tempo de acordo com a freqûencia de amostragem, para logo após, realizar a multiplicação do sinal recebido com onda portadora senoidal, em seguida é usada a função signal.butter da biblioteca signal, para obtenção dos coeficientes do filtro passa-baixa e filtragem através da função signal.filtfilt, após isso, é feita a amostragem através da obtenção da média da amplitude do sinal dentro do período de cada bit, para por fim, aplicar o dispositivo de tomada de decisão, por meio da função where da biblioteca numpy, como pode-se verificar a seguir: 1 def demodulation (self ,bpsk_sign ,cutoff ,order =2): 2 nb = len( bpsk_sign )// self. sampling_frequency 3 t = np. linspace (0,nb*self. bit_duration ,len( bpsk_sign )) 4 5 carrier = self. sqrt_Eb_Bd * np.cos (2* np.pi * self. carrier_frequency * t) 6 mult = bpsk_sign * carrier 7 8 w = ( cutoff ) / (self. sampling_frequency / 2) 9 b, a = signal . butter (order , w, ’low ’) 10 output = signal . filtfilt (b, a, mult) 11 sum_split = np.mean(np.split(output ,nb), axis = 1,dtype=np. float32 ) 12 decision = np.where( sum_split > 0, 1, 0) 13 14 return decision Listing 3.3 – Método de demodulação BPSK Capítulo 3. Metodologia 30 3.1.2 OFDM A classe que simula a OFDM possui dois métodos (modulação e demodulação) e recebe como parâmetros: • subcarrier_spacing, que representa o espaçamento entre as subportadoras. • sampling_rate, que representa a taxa de amostragem. • n_subcarriers, que representa a quantidade de subportadoras. • n_pilots, que representa a quantidade de subportadoras piloto. • pilot_value, que representa o valor queas subportadoras pilotos carregam. • cp_length, que representa o tamanho do prefixo cíclico, em unidades de subportado- ras. • bits_per_symbol, que representa a quantidade de bits que um símbolo carrega. No método de inicialização da classe OFDM, além da atribuição dos parâmetros, é realizado um cálculo para definição das posições das subportadoras piloto e subportadoras de dados: 1 self. FFTsize = int(np. round (self. sampling_rate /self. subcarrier_spacing )) 2 self. sub_carriers = np. arange (self. FFTsize ) 3 self. pilot_carriers = np. linspace (0, self.FFTsize -1, num=self. n_pilots ,dtype=int) 4 self. subcarriers_no_pilots = np. delete (self. sub_carriers , self. pilot_carriers ) 5 self. data_carriers = self. subcarriers_no_pilots [:( self. n_subcarriers -self. n_pilots ) ,...] Listing 3.4 – Definição das subportadoras Além disso, também é definido o vetor de símbolos mapeados, em que, o tipo de mapeamento depende da quantidade de bits por símbolo, caso seja 1 será o mapeamento BPSK, caso contrário, é mapeado em QAM com os símbolos codificados com o código de Gray, como ilustrado no trecho de código a seguir: 1 if bits_per_symbol == 1: 2 self. symbols = np.array ([ -1 ,1]) 3 self. bits_mapped = np.array ([[0] ,[1]]) 4 else: Capítulo 3. Metodologia 31 5 q_i = 1 + (np. arange (np.sqrt(self. qam_order ))*2) - np.sqrt( self. qam_order ) 6 q, i = np. meshgrid (q_i ,q_i) 7 symbols = i. reshape (self. qam_order ) + 1j * q. reshape (self. qam_order ) 8 symbols = symbols /np.sqrt(np.mean(np.abs( symbols )**2)) 9 10 sequence = np.array( range (self. qam_order )) 11 gray_constellation = np. bitwise_xor (sequence , np.floor( sequence /2). astype (int)) 12 13 bits = () 14 size_string = "{0:0"+str( bits_per_symbol )+"b}" 15 16 for i in gray_constellation : 17 bits = bits + (tuple ([ int(x) for x in list( size_string . format (i))]) ,) 18 bits_mapped = np. fliplr (np.array(bits)) 19 20 self. symbols = symbols [np. argsort ( gray_constellation )] 21 self. bits_mapped = bits_mapped . astype (float )[np. argsort ( gray_constellation ) ,:] Listing 3.5 – Modelo de mapeamento 3.1.2.1 Modulação Para implementar a modulação OFDM, o primeiro passo foi converter a entrada sequencial de bits em grupos , cada grupo de bits é uma subportadora e possui o tamanho igual ao número de bits por símbolo, ou seja, é uma matriz com quantidade de linhas igual o número de subportadoras e de colunas igual a número de bits por símbolo. Em seguida os grupos de bits são mapeados em simbolos de acordo com a quantidade de bits por simbolo, o próximo passo é alocar esses simbolos nas posições das subportadoras de dados e para as pilotos é alocado o valor definido pelo usuário pilot_value, e por fim as subportadoras são convertidas para o domínio do tempo por meio de uma IFFT e o prefixo cíclico é adicionado de acordo com o cp_length, como demonstrado no seguinte trecho de código: 1 def ofdm_transmitter (self ,bits): 2 3 bits_SP = bits. reshape (len(self. data_carriers ), self. bits_per_symbol ) Capítulo 3. Metodologia 32 4 bits = self. symbols [np.sum( bits_SP * 2** np. arange (self. bits_per_symbol ), axis =1, dtype=int)] 5 6 symbols = np.zeros(self.FFTsize , dtype= complex ) 7 symbols [self. pilot_carriers ] = self. pilot_value 8 symbols [self. data_carriers ] = bits. reshape ((-1,)) 9 10 signal = np.fft.ifft( symbols ) 11 12 if self.cp_length >0: 13 signal = np. concatenate ([ signal [-self. cp_length :], signal ]) 14 15 return signal Listing 3.6 – Método do transmissor OFDM 3.1.2.2 Demodulação Para a demodulação OFDM, inicialmente foi preciso remover o prefixo cíclico, em seguida converter o sinal para o domínio da frequência com a FFT para que, logo após, seja feita a estimativa do canal por meio das subportadoras piloto, que possuem valor e posição conhecidos, dessa forma é possivel saber o efeito do canal nessa subportadora, e com o efeito conhecido, é possivel estimar o efeito do canal também nas subportadoras de dados por meio de uma interpolação, para por fim, realizar o demapeamento através da menor distância dos símbolos originais, com relação ao valor estimado das subportadoras de dados. 1 def ofdm_receiver (self , signal ): 2 if self.cp_length >0: 3 signal = signal [self. cp_length :len(self. sub_carriers )+ self. cp_length ] 4 signal_f = np.fft.fft( signal ) 5 6 channel_influence = signal_f [self. pilot_carriers ]/ self. pilot_value 7 8 interp = scipy. interpolate . interp1d (self. pilot_carriers , channel_influence ) 9 equalize = ( signal_f [self. data_carriers ]/ interp (self. data_carriers )). reshape (-1,1) 10 Capítulo 3. Metodologia 33 11 distance_symbols_to_constellation = np. absolute (equalize - self. symbols ) 12 return self. bits_mapped [np. argmin ( distance_symbols_to_constellation ,axis =1) ]. reshape (-1) Listing 3.7 – Método do receptor OFDM 3.1.3 OFDMA A classe que simula a transmissão e recepção OFDMA possui como parâmetros: • subcarriers_pacing, que representa o espaçamento entre as subportadoras. • sampling_rate, que representa a taxa de amostragem. • n_subcarriers, que representa a quantidade de subportadoras. • n_pilots, que representa a quantidade de subportadoras piloto. • pilot_value, que representa o valor complexo que as subportadoras pilotos carregam. • cp_length, que representa o tamanho do prefixo cíclico, em unidades de subportado- ras. • bits_per_symbol, que representa a quantidade de bits que um símbolo carrega. • resource_units, que representa o tamanho dos subconjuntos de subportadoras dos usuários. • sc_mapping, que representa o tipo de alocação de subportadoras. A classe OFDMA é muito semelhante com relação a OFDM, a diferença é que possui a alocação de subportadoras. Na qual está demonstrada no trecho de código a seguir, em que, caso o parâmetro scmap seja igual a 0, é usado o modelo de atribuição das subportadoras de forma localizada, caso seja igual a 1, são realizadas operações com o vetor de subportadoras, para que os índices sejam definidos de forma distribuída para cada usuário, como demonstrado: 1 self. subcarrier_mapping = np.zeros(self. FFTsize ) 2 3 if sc_map == 1: 4 5 self. subcarrier_mapping = self. data_carriers [:: -1] 6 index = int(self. subcarrier_mapping .size/self. resource_units .size) Capítulo 3. Metodologia 34 7 self. subcarrier_mapping = self. subcarrier_mapping . reshape (index ,self. resource_units .size) 8 9 subcarriers_mapped_w_zeros = self. subcarrier_mapping [:: -1].T. reshape (-1) 10 self. subcarriers_mapped = subcarriers_mapped_w_zeros [ subcarriers_mapped_w_zeros != 0] 11 else: 12 13 self. subcarrier_mapping = self. data_carriers 14 self. subcarriers_mapped = self. subcarrier_mapping [self. subcarrier_mapping != 0] Listing 3.8 – Alocação de subportadoras 3.1.3.1 Modulação e Demodulação Como explicado anteriormente, os métodos de transmissão OFDM e OFDMA são semelhantes, a diferença é que após a conversão serial-paralelo é adicionada uma alocação de subportadoras a diferentes usuários podendo ser distribuidas em ordem para cada usuario ou em blocos dependendo do tamanho dos subconjuntos definidos para cada usuário resource_units e em seguida os simbolos são mapeados nas subportadoras alocadas e o resto do processo é semelhante à modulação OFDM. Do mesmo modo a função de demodulação OFDMA também é bastante semelhante a OFDM, a diferença é que é realizado o demapeamento das subportadoras dos usuários de modo a retornar a mesma sequência de dados da entrada. 3.1.4 Canal A classe de simulação do canal recebe os seguintes parâmetros: • fft_size, que representa o tamanho do processo. • tau, que representa o delay dos percursos. • pdb, que representa a potência ao longo de cada percurso. • doppler_frequency, que representa a frequência doppler. • sampling_period, que representa o período de amostragem. O único método dessa classe, tem o objetivo de retornar os coeficientes do canal, em que, para cada percurso, foi gerado um vetorde média nula gaussiano de tamanho Capítulo 3. Metodologia 35 fft_size, em seguida foi obtido o vetor na frequência por meio da FFT que foi filtrado pelo espectro doppler do desvanecimento Rayleigh e multiplicado pela ganho de cada percurso para retornar um array com os coeficientes do canal de acordo com o delay amostrado no período, como ilustrado no trecho de código a seguir: 1 for x in np. arange (len(self.pdb)): 2 gaussian = (np. random .randn(self. fft_size ) + 1j*np. random . randn(self. fft_size )); 3 filtered_taps [x ,:] = np.fft.fft( gaussian )*np.sqrt(S); 4 taps_pdb_time [x ,:] = self.pdb[x]*np.fft.ifft( filtered_taps [x ,:]); 5 taps[self. sampled_tau [x]] = taps_pdb_time [x, self. sampled_tau [x]]; Listing 3.9 – Geração dos coeficientes do canal 3.1.5 Codificador Hamming A classe de simulação de Hamming, não possui nenhum parâmetro, como parâmetro apenas os médotos de codificação e decodificação, que recebem o conjunto de dados binário. 3.1.5.1 Codificação Para codificação Hamming, o primeiro passo é verificar a quantidade de bits de paridade, de acordo com a relação do tamanho da mensagem inicial e a quantidade de bits de paridade, de acordo com o demonstrado no seguinte trecho de código: 1 for i in np. arange (data.size): 2 if (2**i - i - 1 >= data.size): 3 n_parity_bits = i 4 break Listing 3.10 – Verificação da quantidade de bits de paridade Em seguida, é criado um array com tamanho do conjunto de dados somado com o número de bits de paridade, e nas posições de potência de 2 dos bits de paridade, e por fim, é realizado o cálculo do valor dos bits de paridade, através de um OR entre as posições dos bits que possuem valor 1, para obtenção de um valor binário que corresponde ao valor dos bits de paridade. 1 ones = np. nonzero ( data_pbits )[0] 2 value = 0; 3 for x in range(len(ones)): 4 value ^= ones[x]+1 5 Capítulo 3. Metodologia 36 6 parity_values = np.array(list(bin(value)[2:]. zfill( n_parity_bits ))). astype (int) 7 8 data_pbits [ parity_index -1] = parity_values [:: -1] Listing 3.11 – Definição do valor dos bits de paridade 3.1.5.2 Decodificação O primeiro passo para a decodificação, é realizar a verificação da quantidade de bits de paridade, mas, por meio da relação entre o tamanho total da mensagem e a quantidade de bits de paridade: 1 size = 0 2 for i in np. arange (data.size): 3 if (2**i >= data.size): 4 size = i 5 break Listing 3.12 – Verificação da quantidade de bits de paridade Por fim, por meio do OR entre todos os bits de valor 1, é possível obter a posição de um bit errôneo, e em seguida é feita a remoção dos bits de paridade: 1 ones = np. nonzero (data)[0] 2 parity_bits = 2** np. arange (size) -1 3 value = 0 4 for x in range(len(ones)): 5 value ^= ones[x]+1 6 if(value !=0): 7 data[value - 1] = not(data[value - 1]) 8 decoded = np. delete (data , parity_bits ) Listing 3.13 – Obtenção da possível possição de erro e remoção de bits de paridade 37 4 RESULTADOS Neste capítulo, são apresentados os resultados das simulações e comparações de desempenho com a biblioteca CommPy para demonstrar o tempo de execução das funções desenvolvidas. Para a análise do tempo de execução, foi usada a função %timeit do IPython, que pode ser usada para mensuração de tempo de uma parte específica do código, que realiza multiplas execuções no código e retorna a média do tempo de execução. Nas simulações OFDM e OFDMA, foi demonstrado também a taxa de erro de bit (BER), que indica a proporção de bits errôneos recebidos pelo total de bits enviados durante determinado intervalo de tempo. 4.1 Modulação e Demodulação BPSK Para a simulação da modulação BPSK, foram usados os seguintes valores: • Duração do bit: Tb = 1s • Energia por bit: Eb = 0.5 • Frequência da portadora: fc = 4Hz • Frequência de amostragem: fs = 200Hz • Frequência de corte do filtro: cutoff = fc • Ordem do filtro: order = 2 • Vetor binário de dados: np.array([0, 0, 1, 0]) E foi obtido o seguinte resultado como demonstrado na Figura 13, em que o gráfico superior demonstra o sinal digital no tempo, e o inferior o sinal modulado: Capítulo 4. Resultados 38 Figura 13 – Simulação da modulação BPSK. Fonte – Próprio Autor E por meio da demodulação, que recebe como parâmetro o sinal modulado, o vetor binário de dados pode ser obtido novamente: Figura 14 – Simulação da demodulação BPSK. Fonte – Próprio Autor 4.1.1 Análise de desempenho Para a análise de desempenho, foram usados os seguintes parâmetros de simulação: Capítulo 4. Resultados 39 • Tamanho da sequência de bits: 10000 bits • Número total de execuções: 100 • função BPSK desenvolvida neste trabalho com Tb = 1s, Eb = 0.5, fc = 4Hz, fs = 50Hz A função PSK da bibloteca CommPy possui apenas o parâmetro m que é o tamanho da constelação PSK (que para essa análise foi usado o valor 2) e o método de modulação recebe apenas os bits que devem ser modulados. E foram obtidos os seguintes resultados: Tabela 1 – Análise de desempenho - Modulação BPSK Método (biblioteca) tempo de execução médio Modulação BPSK (Commpy) 21ms Modulação BPSK (Projeto) 18ms Demodulação BPSK (Commpy) 236ms Demodulação BPSK (Projeto) 81ms Cabe considerar que tempo de execução da função criada pode variar de acordo com os parâmetros, como o aumento da frequência da amostragem, que retornará mais amostras no tempo. 4.2 Modulação e Demodulação OFDM A simulação da modulação OFDM desenvolvida nessa trabalho possui os seguintes parâmetros: • Espaço entre subportadoras: subcarrier_spacing = 60Hz • Frequência de amostragem: sampling_rate = 3840Hz • Número de subportadoras total: n_subcarriers = 64 • Número de subportadoras piloto: n_pilots = 8 • Valor da subportadora piloto: pilot_value = 1 • Tamanho do prefixo cíclico: cp_length = 8 • Bits por Símbolo: bits_per_symbol = 1 • bits de entrada:bits randômicos de tamanho (n_subcarriers−n_pilots)∗bits_per_symbol) Capítulo 4. Resultados 40 A Figura 15 ilustra como são definidos os índices das portadoras piloto em vermelho, que são distribuidas de forma equidistante para transmitir o valor conhecido. Figura 15 – Distribuição das subportadoras. Fonte – Próprio Autor E a Figura 16 demontra a saída com o sinal modulado, além do resultado do sinal após o canal de 5 percursos que gerou os coficientes com os seguintes parâmetros: • Tamanho do processo fft = 512 • Delay de cada path tau = [0, 2.106, 8.106, 14.106, 20.106]s • Frequência Doppler fd = 7.5Hz • Potência de cada path pdb = [0.5, 0.25, 0.2, 0.1, 0.05] • Período de amostragem Ts = 2.106s E foi obtido os seguintes resultados, como demonstrado na Figura 16, em que o gráfico demonstra o sinal após o canal e a taxa de erro de bit (BER): Capítulo 4. Resultados 41 Figura 16 – Sinal após o canal e taxa de erro de bit. Fonte – Próprio Autor 4.2.1 Análise de desempenho Para a modulação OFDM com a bibloteca CommPy foram usados os seguintes parâmetros: • Tamanho da FFT nfft = 64 • Número de subportadoras nsc = 64 • Tamanho do prefixo cíclico cp_length = 8 • Número total de execuções: 10000 Os seguintes resultados foram obtidos, ao tentar executar a função da biblioteca CommPy para gerar o sinal OFDM, ocorreu um erro e por isso não foi possível medir o tempo de execução como indicado na Tabela 2: Tabela 2 – Análise de desempenho - Modulação OFDM Método (biblioteca) tempo de execução médio Modulação OFDM(Commpy) − Modulação OFDM(Projeto) 28µs Demodulação OFDM(Commpy) − Demodulação OFDM(Projeto) 243µs A biblioteca commpy possui funções de transmissão e recepção OFDM, mas ao tentar executar foram obtidos erros tando na modulação quanto na demodulação, impossibilitando a medição de tempo. Capítulo 4. Resultados 42 4.3 Modulação OFDMA Na simulação da modulação OFDMA desenvolvida neste trabalho, foram usados os seguintes parâmetros: • Espaço entre subportadoras subcarrier_spacing = 60Hz • Frequência de amostragem sampling_rate = 3840Hz • Número de subportadoras total n_subcarriers = 64 • Número de subportadoras piloton_pilots = 8 • Valor da subportadora piloto pilot_value = 1 • Tamanho do prefixo cíclico cp_length = 8 • Bits por símbolo bits_per_symbol = 1 • 4 usuários com 14 subportadoras cada um RUs = np.array([14, 14, 14, 14]) • bits de entrada:bits randômicos de tamanho (np.sum(RUs)) ∗ bits_per_symbol) As Figuras 17 e 18 ilustram como ficam mapeadas as subportadoras dependendo do modelo adotado, com mapeamento localizado e distribuído respectivamente. Figura 17 – Distribuição das subportadoras. Fonte – Próprio Autor E com os parâmetros definidos anteriormente, após a saída do sinal modulado eu usei a função do canal desenvovido neste projeto para gerar os coeficientes e usar o canal para a entrada da demodulação, o canal possui 5 percursos e os seguintes parâmetros: • Tamanho do processo fft_size = 512 • Delay de cada path tau = [0, 2.106, 8.106, 14.106, 20.106]s Capítulo 4. Resultados 43 Figura 18 – Distribuição das subportadoras (mapeamento distribuído). Fonte – Próprio Autor • Frequência Doppler fd = 7.5Hz • Potência de cada path pdb = [0.5, 0.25, 0.2, 0.1, 0.05] • Período de amostragem Ts = 2.106s E foi obtido os seguintes resultados na Figura 20, no qual o gráfico demonstra o sinal após o canal e a taxa de erro de bit de cada usuário e do símbolo OFDMA. Figura 19 – Modulação OFDMA Fonte – Próprio Autor 4.3.1 Análise de desempenho Como a biblioteca CommPy não possui a modulação OFDMA, apenas foram medidos os desempenhos da modulação desenvolvida, para obter a média do tempo de execução: Capítulo 4. Resultados 44 Tabela 3 – Análise de desempenho - Modulação OFDMA Método (biblioteca) tempo de execução médio Modulação OFDMA (Projeto) 36µs Demodulação OFDMA (Projeto) 257µs 4.4 Codificador Hamming O simulador da codificação de Hamming recebe como parâmetro apenas os bits de entrada, como descrito abaixo: • Palavra de bits de tamanho 20: np.array([1, 0, 0, 1, 0, 1, 1, 0, 0, 1, 0, 1, 1, 0, 0, 1, 0, 1, 1, 0]) Após a codificação, foi retornada a saída do conjunto de dados de entrada, como demonstra a Figura 19: Figura 20 – Saída do codificador de Hamming. Fonte – Próprio Autor Em seguida, foi realizada a decodificação com o resultado obtido na codificação, retornando o a mesma palavra de dados que foi usada na codificação: Figura 21 – Saída do decodificador de Hamming. Fonte – Próprio Autor 4.4.1 Análise de desempenho Para a análise desempenho do codificador de Hamming, foi usada uma entrada com 10000 bits e o trecho de código foi executado 100 vezes para obtenção das médias, como a biblioteca commpy não possui esse tipo de codificação, foram realizados os testes apenas com a codificação desenvolvida. 4.5 Canal Os seguintes parâmetros foram usados para simulação do canal com 5 percursos: Capítulo 4. Resultados 45 Tabela 4 – Análise de desempenho - Codificador de Hamming Método tempo de execução médio Codificação Hamming 8.3ms Decodificação Hamming 28.5µs • Tamanho do processo fft_size = 512 • Delay de cada percurso tau = [0, 2.106, 8.106, 14.106, 20.106]s • Frequência Doppler fd = 7.5Hz • Potência de cada percurso pdb = [0.5, 0.25, 0.2, 0.1, 0.05] • Período de amostragem Ts = 2.106s E foram obtidos os seguintes coeficientes: Figura 22 Fonte – Próprio Autor 4.5.1 Análise de desempenho O canal da biblioteca Commpy (SISOFlatChannel) é flat, por isso foi realizada a comparação com o canal desenvovido com 1 percurso, a análise de desempenho levou em conta os seguintes parâmetros: • Canal com tamanho do processo fft = 64, Delay de cada percurso tau = 0s, Frequência Doppler fd = 7.5Hz, Potência de cada percurso pdb = 0.5 e Período de amostragem Ts = 2.106s. • Canal da biblioteca CommPy com desvanecimento de Rayleigh e 64 símbolos. Tabela 5 – Análise de desempenho - Canal Método (biblioteca) tempo de execução médio Canal (Projeto) 139µs Canal (CommPy) 18.5µs Capítulo 4. Resultados 46 Apesar do tempo ser praticamente 8 vezes maior, é preciso considerar que o canal deste projeto, é mais flexível para simulações pois possui uma maior quantidade de parâmetros que podem ser defindos, além disso, a biblioteca CommPy não possui funções para canal multipercurso, enquanto o canal desenvolvido neste projeto, tem capacidade para ser multipercurso dependendo dos parâmetros informados. 47 5 CONCLUSÃO Este trabalho teve como objetivo o desenvovimento de uma biblioteca Python para contribuição no desenvolvimento de simulações de sistemas de telecomunicações. Em que, as funções criadas foram simuladas e analisadas em termos de desempenho. Com relação à análise de desempenho, nas funções que foi possível realizar a comparação, os resultados se mostraram bastante satisfatórios, pois mesmo que, o tempo de execução possa ser maior, as funções permitem uma simulação mais flexível, pois possuem uma maior quantidade de parâmetros, permitindo uma exploração dos resultados melhor para simulações computacionais. Para trabalhos futuros, pode-se continuar com o desenvovimento de funções de simulação de sistemas de telecomunicações para a biblioteca, como por exemplo, acesso ultiplo não ortogonal (NOMA), cancelamento sucessivo de interferência, codificador con- volucional. Pois a área de sistemas de telecomunicações é vasta, e mesmo que existam algumas poucas bibliotecas na linguagem Python, elas possuem limitações e podem não atender completamente ao escopo de simulações computacionais. 48 REFERÊNCIAS AL-RAWI, M. Performance analysis of ofdma and sc-fdma. International Review of Applied Sciences and Engineering, v. 8, p. 113–116, 12 2017. ALI, M.; SUKAR, N.; PAL, M. Sc-fdma and ofdma in lte physical layer. international journal of engineering trends and technology, v. 12, p. 74–84, 2014. ARNDT, D. M. Análise comparativa entre os sistemas ofdm e fbmc na transmissão de tv digital. Florianópolis, 2012. BROWN, J.; PASUPATHY, S.; PLATANIOTIS, K. Adaptive demodulation using rateless erasure codes. Communications, IEEE Transactions on, v. 54, p. 1574 – 1585, 10 2006. CHO, Y. et al. MIMO-OFDM Wireless Communications with MATLAB®: Cho/MIMO-OFDM Wireless Communications with MATLAB®. [S.l.: s.n.], 2010. ISBN 9780470825617. CLARKE, R. H. A statistical theory of mobile-radio reception. The Bell System Technical Journal, v. 47, n. 6, p. 957–1000, 1968. Coleri, S. et al. Channel estimation techniques based on pilot arrangement in ofdm systems. IEEE Transactions on Broadcasting, v. 48, n. 3, p. 223–229, 2002. GUIMARÃES, A.; PINTO, E. Técnicas de simulação de canais rádio móveis. Revista Inatel, v. 4, n. 1, 2001. HAYKIN, S. Sistemas de Comunicação Analógicos e Digitais. 4. ed. [S.l.]: BOOKMAN COMPANHIA ED, 2004. HAYKIN, S.; MOHER, M. Introdução aos Sistemas de Comunicação. 2. ed. [S.l.]: BOOKMAN COMPANHIA ED, 2008. LATHI B. P.; DING, Z. Sistemas de comunicações analógicos e digitais modernos. 4. ed. [S.l.]: Editora LTC, 2012. MORELLI, M.; KUO, C.-C. J.; PUN, M. Synchronization techniques for orthogonal frequency division multiple access (ofdma): A tutorial review. Proceedings of the IEEE, v. 95, p. 1394 – 1427, 08 2007. Muller, A. Simulation of multipath fading channels using the monte-carlo method. In: Proceedings of ICC/SUPERCOMM’94 - 1994 International Conference on Communications. [S.l.: s.n.], 1994. p. 1536–1540 vol.3. PARKER, M. Chapter 17 - orthogonal frequency division multiple access wireless communications. In: PARKER, M. (Ed.). Digital Signal Processing 101 (Second Edition). Second edition. Newnes, 2017. p. 209 – 230. ISBN 978-0-12-811453-7. Disponível em: <http://www.sciencedirect.com/science/article/pii/B9780128114537000172>. PINTO, E. L.; ALBUQUERQUE, C. P. de. A técnica de transmissão ofdm. Revista Científica Periódica-Telecomunicações ISSN, v. 1516, p. 2338, 2002. http://www.sciencedirect.com/science/article/pii/B9780128114537000172 Referências 49 SAVAUX, V. Contributions à l’estimation de canal mutli-trajets dans un contexte de modulation OFDM. Tese (Doutorado), 11 2013. SCHULZE, H. Stochastic models and digital simulation of mobile channels (in german),.U.R.S.I./ITG Conf. in Kleinheubach 1988, Germany (FR),Proc. Kleinheubacher Berichte by the German PlT, Darmstadt,, v. 32, p. 473–483, 1989. 50 A APÊNDICE - CÓDIGOS FONTE A.1 Classe BPSK 1 import numpy as np 2 import scipy. signal as signal 3 4 class bpsk: 5 def __init__ (self , energy_per_bit , bit_duration , carrier_frequency , sampling_frequency ): 6 7 self. carrier_frequency = carrier_frequency 8 self. bit_duration = bit_duration 9 self. energy_per_bit = energy_per_bit 10 self. sampling_frequency = sampling_frequency 11 self. sqrt_Eb_Bd = np.sqrt ((2* self. energy_per_bit )/self. bit_duration ) 12 13 def modulation (self , bit_sequence ): 14 15 nrtn = 2* bit_sequence - 1 16 t = np. linspace (0, len( bit_sequence ), self. sampling_frequency *len( bit_sequence )) 17 nrtn_fs = np. repeat (nrtn , self. sampling_frequency ) 18 return nrtn_fs *( self. sqrt_Eb_Bd *np.cos (2* np.pi * self. carrier_frequency * t)) 19 20 def demodulation (self ,bpsk_sign ,cutoff ,order =2): 21 nb = len( bpsk_sign )// self. sampling_frequency 22 t = np. linspace (0,nb ,len( bpsk_sign )) 23 24 carrier = self. sqrt_Eb_Bd * np.cos (2* np.pi * self. carrier_frequency * t) 25 mult = bpsk_sign * carrier 26 27 w = ( cutoff ) / (self. sampling_frequency / 2) 28 b, a = signal . butter (order , w, ’low ’) 29 output = signal . filtfilt (b, a, mult) 30 sum_split = np.mean(np.split(output ,nb), axis = 1,dtype=np. Apêndice A. APÊNDICE - CÓDIGOS FONTE 51 float32 ) 31 decision = np.where( sum_split > 0, 1, 0) 32 33 return decision Listing A.1 – Classe BPSK A.2 Classe OFDM 1 import numpy as np 2 import scipy. interpolate 3 4 class OFDM: 5 6 def __init__ (self , subcarrier_spacing , sampling_rate , n_subcarriers , n_pilots , pilot_value , cp_length , bits_per_symbol ): 7 8 self. cp_length = cp_length 9 self. n_subcarriers = n_subcarriers 10 self. subcarrier_spacing = subcarrier_spacing 11 self. sampling_rate = sampling_rate 12 self. n_pilots = n_pilots 13 self. pilot_value = pilot_value 14 15 self. bits_per_symbol = bits_per_symbol 16 self. qam_order = 2** bits_per_symbol 17 18 self. FFTsize = int(np. round (self. sampling_rate /self. subcarrier_spacing )) 19 20 self. sub_carriers = np. arange (self. FFTsize ) 21 self. pilot_carriers = np. linspace (0, self.FFTsize -1, num= self.n_pilots ,dtype=int) 22 self. subcarriers_no_pilots = np. delete (self. sub_carriers , self. pilot_carriers ) 23 self. data_carriers = self. subcarriers_no_pilots [:( self. n_subcarriers -self. n_pilots ) ,...] 24 25 if bits_per_symbol == 1: 26 self. symbols = np.array ([ -1 ,1]) 27 self. bits_mapped = np.array ([[0] ,[1]]) Apêndice A. APÊNDICE - CÓDIGOS FONTE 52 28 else: 29 q_i = 1 + (np. arange (np.sqrt(self. qam_order ))*2) - np. sqrt(self. qam_order ) 30 q, i = np. meshgrid (q_i ,q_i) 31 symbols = i. reshape (self. qam_order ) + 1j * q. reshape (self . qam_order ) 32 symbols = symbols /np.sqrt(np.mean(np.abs( symbols )**2)) 33 34 sequence = np.array( range (self. qam_order )) 35 gray_constellation = np. bitwise_xor (sequence , np.floor( sequence /2). astype (int)) 36 37 bits = () 38 size_string = "{0:0"+str( bits_per_symbol )+"b}" 39 40 for i in gray_constellation : 41 bits = bits + (tuple ([ int(x) for x in list( size_string . format (i))]) ,) 42 bits_mapped = np. fliplr (np.array(bits)) 43 44 self. symbols = symbols [np. argsort ( gray_constellation )] 45 self. bits_mapped = bits_mapped . astype (float )[np. argsort ( gray_constellation ) ,:] 46 47 def ofdm_transmitter (self ,bits): 48 49 bits_SP = bits. reshape (len(self. data_carriers ), self. bits_per_symbol ) 50 bits = self. symbols [np.sum( bits_SP * 2** np. arange (self. bits_per_symbol ), axis =1, dtype=int)] 51 52 symbols = np.zeros(self.FFTsize , dtype= complex ) 53 symbols [self. pilot_carriers ] = self. pilot_value 54 symbols [self. data_carriers ] = bits. reshape ((-1,)) 55 56 signal = np.fft.ifft( symbols ) 57 58 if self.cp_length >0: 59 signal = np. concatenate ([ signal [-self. cp_length :], signal ]) 60 Apêndice A. APÊNDICE - CÓDIGOS FONTE 53 61 return signal 62 63 def ofdm_receiver (self , signal ): 64 if self.cp_length >0: 65 signal = signal [self. cp_length :len(self. sub_carriers )+ self. cp_length ] 66 signal_f = np.fft.fft( signal ) 67 68 channel_influence = signal_f [self. pilot_carriers ]/ self. pilot_value 69 70 interp = scipy. interpolate . interp1d (self. pilot_carriers , channel_influence ) 71 equalize = ( signal_f [self. data_carriers ]/ interp (self. data_carriers )). reshape (-1,1) 72 73 distance_symbols_to_constellation = np. absolute (equalize - self. symbols ) 74 return self. bits_mapped [np. argmin ( distance_symbols_to_constellation ,axis =1) ]. reshape (-1) Listing A.2 – Classe OFDM A.3 Classe OFDMA 1 import numpy as np 2 import scipy. interpolate 3 4 class OFDMA: 5 6 def __init__ (self , subcarrier_spacing , sampling_rate , n_subcarriers , n_pilots , pilot_value , cp_length , bits_per_symbol , resource_units , sc_map = 1): 7 8 self. cp_length = cp_length 9 self. n_subcarriers = n_subcarriers 10 self. subcarrier_spacing = subcarrier_spacing 11 self. sampling_rate = sampling_rate 12 self. n_pilots = n_pilots 13 self. pilot_value = pilot_value 14 self. resource_units = resource_units 15 self. bits_per_symbol = bits_per_symbol Apêndice A. APÊNDICE - CÓDIGOS FONTE 54 16 self. qam_order = 2** bits_per_symbol 17 self. sc_map = sc_map ; 18 19 self. FFTsize = int(np. round (self. sampling_rate /self. subcarrier_spacing )) 20 21 self. sub_carriers = np. arange (self. FFTsize ) 22 self. pilot_carriers = np. linspace (0, self.FFTsize -1, num= self.n_pilots ,dtype=int) 23 self. subcarriers_no_pilots = np. delete (self. sub_carriers , self. pilot_carriers ) 24 self. data_carriers = self. subcarriers_no_pilots [:( np.sum( self. resource_units )) ,...] 25 26 if bits_per_symbol == 1: 27 self. symbols = np.array ([ -1 ,1]) 28 self. bits_mapped = np.array ([[0] ,[1]]) 29 else: 30 q_i = 1 + (np. arange (np.sqrt(self. qam_order ))*2) - np. sqrt(self. qam_order ) 31 q, i = np. meshgrid (q_i ,q_i) 32 symbols = i. reshape (self. qam_order ) + 1j * q. reshape (self . qam_order ) 33 symbols = symbols /np.sqrt(np.mean(np.abs( symbols )**2)) 34 35 sequence = np.array( range (self. qam_order )) 36 gray_constellation = np. bitwise_xor (sequence , np.floor( sequence /2). astype (int)) 37 38 bits = () 39 size_string = "{0:0"+str( bits_per_symbol )+"b}" 40 41 for i in gray_constellation : 42 bits = bits + (tuple ([ int(x) for x in list( size_string . format (i))]) ,) 43 bits_mapped = np. fliplr (np.array(bits)) 44 45 self. symbols = symbols [np. argsort ( gray_constellation )] 46 self. bits_mapped = bits_mapped . astype (float )[np. argsort ( gray_constellation ) ,:] 47 Apêndice A. APÊNDICE - CÓDIGOS FONTE 55 48 self. subcarrier_mapping = np.zeros(self. FFTsize ) 49 50 if sc_map == 1: 51 52 self. subcarrier_mapping = self. data_carriers [:: -1] 53 index = int(self. subcarrier_mapping .size/self. resource_units .size) 54 self. subcarrier_mapping = self. subcarrier_mapping . reshape (index ,self. resource_units .size) 55 56 subcarriers_mapped_w_zeros = self. subcarrier_mapping [:: -1].T. reshape (-1) 57 self. subcarriers_mapped = subcarriers_mapped_w_zeros [ subcarriers_mapped_w_zeros != 0] 58 else: 59 60 self. subcarrier_mapping = self. data_carriers 61 self. subcarriers_mapped = self. subcarrier_mapping [self. subcarrier_mapping != 0] 62 63 def ofdma_transmitter (self ,bits): 64 bits = bits. reshape (np.sum(self. resource_units ), self. bits_per_symbol ) 65 66 bits_mapped = self. symbols [np.sum(bits * 2** np. arange (self. bits_per_symbol ), axis =1, dtype=int)] 67 68 symbols = np.zeros(self.FFTsize , dtype= complex ) 69 symbols [self. pilot_carriers ] = self. pilot_value 70 71 symbols [np.array(self. subcarriers_mapped ,dtype=int)] = bits_mapped . reshape ((-1,))72 73 signal = np.fft.ifft( symbols ) 74 75 if self.cp_length >0: 76 signal = np. concatenate ([ signal [-self. cp_length :], signal ]) 77 return signal 78 79 def ofdma_receiver (self , signal ): Apêndice A. APÊNDICE - CÓDIGOS FONTE 56 80 if self.cp_length >0: 81 signal = signal [self. cp_length :len(self. sub_carriers )+ self. cp_length ] 82 83 signal_f = np.fft.fft( signal ) 84 85 channel_influence = signal_f [self. pilot_carriers ]/ self. pilot_value 86 interp = scipy. interpolate . interp1d (self. pilot_carriers , channel_influence ) 87 equalize = ( signal_f [np.array(self. subcarriers_mapped ,dtype =int)]/ interp (np.array(self. subcarriers_mapped ,dtype=int ))). reshape (-1,1) 88 89 distance_symbols_to_constellation = np. absolute ( equalize - self. symbols ) 90 return self. bits_mapped [np. argmin ( distance_symbols_to_constellation ,axis =1) ]. reshape (-1) Listing A.3 – Classe OFDMA A.4 Classe do Canal multipercurso com desvanecimento Rayleigh 1 import numpy as np 2 import math 3 4 class rayleigh_chan : 5 def __init__ (self ,fft_size ,tau , freq_doppler ,pdb ,Ts): 6 7 self. fft_size = fft_size 8 self.tau = tau; 9 self. freq_doppler = freq_doppler ; 10 self.pdb = pdb; 11 self.Ts = Ts; 12 self. sampled_tau = np. divide (self.tau ,self.Ts). astype (int) 13 def get_coef (self): 14 15 taps = np.zeros(self. sampled_tau [ -1]+1 , dtype= complex ); 16 filtered_taps = np.zeros (( len(self.pdb), self. fft_size ), dtype= complex ); 17 taps_pdb_time = np.zeros (( len(self.pdb), self. fft_size ), dtype= complex ); Apêndice A. APÊNDICE - CÓDIGOS FONTE 57 18 19 f = np. linspace (-self. freq_doppler ,self. freq_doppler ,self. fft_size ) 20 21 with np. errstate ( divide =’ignore ’): 22 S = 1/( np.pi*self. freq_doppler *np.sqrt (1 -((f/self. freq_doppler )**2))); 23 24 S[0] = S[1]+(S[1]-S[2]); 25 S[-1] = S[ -2]+(S[-2]-S[ -3]); 26 27 for x in np. arange (len(self.pdb)): 28 gaussian = (np. random .randn(self. fft_size ) + 1j*np. random .randn(self. fft_size )); 29 filtered_taps [x ,:] = np.dot(np.fft.fft( gaussian ),np.sqrt( S)); 30 taps_pdb_time [x ,:] = self.pdb[x]*np.fft.ifft( filtered_taps [x ,:]); 31 taps[self. sampled_tau [x]] = taps_pdb_time [x, self. sampled_tau [x]]; 32 return taps Listing A.4 – Classe do Canal multipercurso com desvanecimento Rayleigh A.5 Classe do codificador Hamming 1 import numpy as np 2 3 class Hamming : 4 5 def encoder (data): 6 for i in np. arange (data.size): 7 if (2**i - i - 1 >= data.size): 8 n_parity_bits = i 9 break 10 11 data_size = data.size 12 data_pbits = np.zeros( data_size + n_parity_bits ,dtype=int); 13 bits_index = np. arange (1, data_size + n_parity_bits +1) 14 parity_index = 2 ** np. arange (0, n_parity_bits ) 15 diff_index = np. setdiff1d (bits_index , 2 ** np. arange (0, data .size)) Apêndice A. APÊNDICE - CÓDIGOS FONTE 58 16 data_pbits [diff_index -1] = data 17 teste = np. bitwise_or (data_pbits ,np. arange (1, data_pbits . size + 1)) 18 19 ones = np. nonzero ( data_pbits )[0] 20 value = 0; 21 for x in range(len(ones)): 22 value ^= ones[x]+1 23 24 parity_values = np.array(list(bin(value)[2:]. zfill( n_parity_bits ))). astype (int) 25 data_pbits [ parity_index -1] = parity_values [:: -1] 26 return data_pbits 27 28 def decoder (data): 29 size = 0 30 for i in np. arange (data.size): 31 if (2**i >= data.size): 32 size = i 33 break 34 ones = np. nonzero (data)[0] 35 parity_bits = 2** np. arange (size) -1 36 value = 0 37 for x in range(len(ones)): 38 value ^= ones[x]+1 39 if(value !=0): 40 data[value - 1] = not(data[value - 1]) 41 decoded = np. delete (data , parity_bits ) 42 return decoded Listing A.5 – Classe do codificador Hamming
Compartilhar