scieee AI-readable full text Open interactive document viewer

Implementació en DSP's d'un predistorsionador digital per a la linealització d'amplificadors de potència

Vázquez Rodríguez, María Sandra

Abstract

La predistorsión digital es una técnica para la linealización de amplificadores de potencia. Los amplificadores de potencia son dispositivos activos presentes en las etapas de potencia de los sistemas de comunicación RF y consumen gran parte de la energía disponible (alrededor de un 70%). Interesa pues aprovechar al máximo su eficiencia energética. Sin embargo, si se trabaja en las zonas donde la eficiencia es mayor, el amplificador de potencia se comporta de forma muy no lineal, introduciendo distorsión dentro y fuera de banda que no es fácilmente eliminable mediante el filtrado. El compromiso entre linealidad y eficiencia está presente en el diseño de los amplificadores de potencia, ya que el conjunto del sistema de comunicaciones debe cumplir las recomendaciones propuestas por los diferentes estándares de comunicación. Para conseguir el objetivo de maximizar ambas características, se están investigando numerosas técnicas de linealización. Una de ellas es la predistorsión digital que puede ser implementada en un procesador DSP (Digital Signal Processor) ya presente actualmente en muchos sistemas de comunicación. El proyecto de fin de carrera aquí presentado ha consistido en desarrollar un predistorsionador digital basado en el modelo de Hammerstein (con sus variantes FIR e IIR) en el entorno del procesador DSP C6711. Primero, se ha obtenido el modelo de comportamiento (behavioral model) paso bajo de un amplificador de potencia a partir de las muestras de entrada y salida medidas en un amplificador real. Posteriormente, una vez estimado el modelo paso bajo (de envolvente compleja) del amplificador, se ha procedido a la estimación del modelo del predistorsionador. Para ello, se han utilizado las mismas muestras de entrada y salida medidas, así como un método de estimación indirecto a fin de no necesitar el modelo del amplificador para estimar el modelo del predistorsionador, evitando así, una posible acumulación de errores. Por otro lado, se han generado secuencias pseudo-aleatorias de símbolos para las diferentes modulaciones M-QAM (de 8 a 64) y se han suavizado con un filtro RRC (Root Raised Cosine). Estas muestras se han aplicado al modelo estimado del amplificador de potencia para disponer de muestras de salida del amplificador. Las muestras de entrada y salida del amplificador han permitido estimar nuevos coeficientes del predistorsionador. Pensando en una futura implementación del predistorsionador en una FPGA, donde los coeficientes del modelo del predistorsionador se deben actualizar continuamente, se ha implementado el modelo del predistorsionador mediante unas tablas de ganancia compleja denominadas Look-Up-Tables (LUTs). Las LUTs permiten de una forma rápida asignar la ganancia compleja correspondiente a cada valor de la señal de entrada del predistorsionador, aplicando así correcciones en el módulo y en la fase de la señal de entrada. El resultado es una relación lineal entre la entrada y la salida de las etapas predistorsionador y amplificador de potencia. Se han hecho las simulaciones necesarias para verificar el correcto funcionamiento de la estimación del amplificador de potencia y del predistorsionador con LUT, aportando resultados y conclusiones al respecto.

Full text

TREBALL DE FI DE CARRERA TÍTOL DEL PFC: Implementación en DSP de un Predistorsionador Digital para la Linealización de Amplificadores de Potencia TITULACIÓ: Ingeniería de Telecomunicaciones (segundo ciclo) AUTOR: María Sandra Vázquez Rodríguez DIRECTOR: Pere Lluís Gilabert Pinal DATA: 26 de Septiembre de 2006 Títol: Implementación en DSP de un Predistorsionador Digital para la Linealización de Amplificadores de Potencia Autor: María Sandra Vázquez Rodríguez Director: Pere Lluís Gilabert Pinal Data: 26 de Septiembre de 2006 Resum La predistorsión digital es una técnica para la linealización de amplificadores de potencia. Los amplificadores de potencia son dispositivos activos presentes en las etapas de potencia de los sistemas de comunicación RF y consumen gran parte de la energía disponible (alrededor de un 70%). Interesa pues aprovechar al máximo su eficiencia energética. Sin embargo, si se trabaja en las zonas donde la eficiencia es mayor, el amplificador de potencia se comporta de forma muy no lineal, introduciendo distorsión dentro y fuera de banda que no es fácilmente eliminable mediante el filtrado. El compromiso entre linealidad y eficiencia está presente en el diseño de los amplificadores de potencia, ya que el conjunto del sistema de comunicaciones debe cumplir las recomendaciones propuestas por los diferentes estándares de comunicación. Para conseguir el objetivo de maximizar ambas características, se están investigando numerosas técnicas de linealización. Una de ellas es la predistorsión digital que puede ser implementada en un procesador DSP (Digital Signal Processor) ya presente actualmente en muchos sistemas de comunicación. El proyecto de fin de carrera aquí presentado ha consistido en desarrollar un predistorsionador digital basado en el modelo de Hammerstein (con sus variantes FIR e IIR) en el entorno del procesador DSP C6711. Primero, se ha obtenido el modelo de comportamiento (behavioral model) paso bajo de un amplificador de potencia a partir de las muestras de entrada y salida medidas en un amplificador real. Posteriormente, una vez estimado el modelo paso bajo (de envolvente compleja) del amplificador, se ha procedido a la estimación del modelo del predistorsionador. Para ello, se han utilizado las mismas muestras de entrada y salida medidas, así como un método de estimación indirecto a fin de no necesitar el modelo del amplificador para estimar el modelo del predistorsionador, evitando así, una posible acumulación de errores. Por otro lado, se han generado secuencias pseudo-aleatorias de símbolos para las diferentes modulaciones M-QAM (de 8 a 64) y se han suavizado con un filtro RRC (Root Raised Cosine). Estas muestras se han aplicado al modelo estimado del amplificador de potencia para disponer de muestras de salida del amplificador. Las muestras de entrada y salida del amplificador han permitido estimar nuevos coeficientes del predistorsionador. Pensando en una futura implementación del predistorsionador en una FPGA, donde los coeficientes del modelo del predistorsionador se deben actualizar continuamente, se ha implementado el modelo del predistorsionador mediante unas tablas de ganancia compleja denominadas Look-Up-Tables (LUTs). Las LUTs permiten de una forma rápida asignar la ganancia compleja correspondiente a cada valor de la señal de entrada del predistorsionador, aplicando así correcciones en el módulo y en la fase de la señal de entrada. El resultado es una relación lineal entre la entrada y la salida de las etapas predistorsionador y amplificador de potencia. Se han hecho las simulaciones necesarias para verificar el correcto funcionamiento de la estimación del amplificador de potencia y del predistorsionador con LUT, aportando resultados y conclusiones al respecto. Title: DSP implementation of a Digital Predistorter for Power Amplifier Linearization Author: María Sandra Vázquez Rodríguez Director: Pere Lluís Gilabert Pinal Date: September 26th, 2006 Overview Digital predistortion is a technique used for power amplifier linearization. Power amplifiers are active devices included in most power supply modules of RF communication systems and their consumption represents most of the available energy in the system, up to 70% of the total. It is advisable then to maximize its efficiency. Nevertheless, if the power amplifer works where efficiency is higher, its behaviour becomes non linear and it introduces in-band and out-band distortion which cannot be easily removed by filtering. The trade off between linearity and efficiency is present in the power amplifier’s design since the whole communication system must comply with recommendations proposed by the different communication standards. To achieve the objetive of maximizing both characteristics, various technologies are being investigated. One of them is digital predistortion that can be implemented in a DSP (Digital Signal Processor) already included in most communication systems. The final project presented here has consisted on the development of a digital predistorter based on a Hammerstein model (with its variants of FIR and IIR) in the DSP C6711 environment. First of all, the low-pass behavioral model of a power amplifier has been obtained using the input and output samples measured in a real power amplifier. Later on, once the amplifier low-pass model (complex envelope) has been estimated, the predistorter model has been calculated. To do so, the same input and output measured samples have been used with the indirect learning approach of this model. This approach does not need the amplifier model to estimate the predistorter and as a result, it reduces possible errors. On the other hand, pseudo-random sequences have been generated for the different M-QAM modulations (from 8 to 64) and they have been shaped with a Root Raised Cosine filter. These samples have passed through the power amplifier model previously estimated. New parameters have been calculated for the predistortion with these input and output samples. Thinking about a future implementation in a FPGA where predistorter parameters need to be continuosly updated, the predistorter model has been implemented in tables named Look-Up-Tables (LUT). The LUT provide adequate complex gains which are applied to each input sample before passing the power amplifer and that correct the module and phase of the input signal. The result is a linear relation between the input and output of the predistorter and power amplifier blocks. Several simulations have been done in order to check properly the validity of the estimations for the power amplifier and predistorter models. Some results and conclusions are also given. AGRADECIMIENTOS Se me hace difícil recordar aquí a todas las personas que me han ayudado, no solo para el proyecto final sino a llegar a él a través de largos años. Podría comenzar por los amigos que tuvieron la idea de hacer el ciclo superior poco tiempo después de que se iniciara en la misma escuela donde estudiamos la ingeniería técnica. Algunos de ellos han sido mis compañeros de proyecto en todas las asignaturas, Anabel y Txema junto con otros con los que hemos compartido la singularidad de trabajar a la vez que seguíamos los estudios. Quisiera agradecer en este punto la comprensión de aquellos profesores que entendieron esta circunstancia. Recuerdo a los amigos de mi ex – trabajo que soportaron mis charlas universitarias en los cafés durante mucho tiempo. Os echo de menos. Agradezco también el apoyo de mis padres, mi hermano Antonio y los padres de Martín preguntando cómo iba y alegrándose cada vez que superaba una asignatura. Y por supuesto, quién ha soportado mi malhumor, lloriqueos y estados de ánimo varios cuando tenía que quedarme hasta las tantas acabando alguna memoria o cuando me ha dado clases partirculares de comunicaciones y electrónica donde los libros y apuntes no llegaban. Martín, mi marido ahora y espero que por muchos años. Por último, doy las gracias a Pere como director del proyecto por las explicaciones y revisiones de la memoria. ÍNDICE INTRODUCCIÓN ............................................................................................... 1 CAPÍTULO 1. AMPLIFICADORES DE POTENCIA........................................ 3 1.1. Introducción....................................................................................................................... 3 1.2. Comportamiento no lineal del amplificador ................................................................... 3 1.3. Caracterización y parámetros de un amplificador de potencia.................................... 4 1.3.1. Curvas AM-AM y AM-PM ....................................................................................... 5 1.3.2. PAPR (Peak-to-Average Power Ratio)................................................................... 5 1.3.3. Punto de compresión a -1 dB................................................................................. 6 1.3.4. IBO/OBO (Input Back-Off/Output Backoff)............................................................. 7 1.3.5. Eficiencia ................................................................................................................ 8 1.3.6. PAE (Power Added Efficiency)............................................................................... 8 1.3.7. EVM (Error Vector Magnitude) ............................................................................... 8 1.3.8. ACPR (Adjacent Channel Power Ratio)................................................................. 9 1.3.9. IMD (InterModulation Distortion)........................................................................... 10 1.4. Clases de amplificadores ............................................................................................... 11 CAPÍTULO 2. TÉCNICAS DE LINEALIZACIÓN........................................... 12 2.1. Compromiso entre linealidad y eficiencia .................................................................... 12 2.2. Linealización a nivel de sistema .................................................................................... 12 2.2.1. Linealizadores que reducen la distorsión............................................................. 12 2.2.2. Linealizadores cuyo objetivo es evitar la distorsión ............................................. 14 CAPÍTULO 3. PREDISTORSIÓN DIGITAL................................................... 16 3.1. Introducción..................................................................................................................... 16 3.2. Predistorsión adaptativa................................................................................................. 17 3.3. Modelos del predistorsionador...................................................................................... 18 3.3.1. Modelo de Hammerstein ...................................................................................... 18 3.3.2. Modelo de Wiener ................................................................................................ 20 3.3.3. Configuraciones.................................................................................................... 21 3.4. Algoritmos de identificación .......................................................................................... 23 3.4.1. Algoritmo LMS...................................................................................................... 23 3.4.2. Algoritmo Fast-Kalman......................................................................................... 24 3.5. Predistorsionador con LUT ............................................................................................ 24 3.5.1. Implementación de LUT para Hammerstein FIR.................................................. 25 3.5.2. Cálculo de señal de salida con LUT..................................................................... 26 CAPÍTULO 4. IMPLEMENTACIÓN DE PREDISTORSIÓN DIGITAL........... 27 4.1. Introducción..................................................................................................................... 27 4.2. Modelo del amplificador de potencia y post-distorsionador a partir de muestras reales .......................................................................................................................................... 27 4.2.1. Formato de los datos............................................................................................ 28 4.2.2. Lectura de los datos desde Code Composer....................................................... 28 4.2.3. Descripción del proyecto ...................................................................................... 29 4.2.4. Salida de los datos en Code Composer............................................................... 37 4.3. Implementación de LUT para el predistorsionador ..................................................... 38 4.3.1. Descripción del proyecto ...................................................................................... 38 4.4. Generación de muestras M-QAM y estimación de post-distorsionador.................... 41 4.4.1. Descripción del proyecto ...................................................................................... 41 4.5. Demodulación de muestras M-QAM.............................................................................. 45 4.5.1. Descripción del proyecto ...................................................................................... 45 CAPÍTULO 5. RESULTADOS....................................................................... 46 5.1. Importación de resultados desde Matlab...................................................................... 46 5.2. Resultados de la simulación con muestras reales ...................................................... 46 5.2.1. Número de retardos óptimo en la estimación del PA........................................... 46 5.2.2. Estimación del modelo del amplificador de potencia ........................................... 47 5.2.3. Estimación del predistorsionador con LUT........................................................... 49 5.3. Resultados de la simulación con muestras M-QAM.................................................... 50 5.3.1. Estimación del predistorsionador con LUT........................................................... 50 5.3.2. Demodulación de señales .................................................................................... 52 5.4. Ciclos de reloj para la actualización de coeficientes................................................... 53 5.5. Conclusiones ................................................................................................................... 54 REFERENCIAS................................................................................................ 55 ANEXO 1. ENTORNO DE DESARROLLO C6711 ...................................... 59 A1.1. Introducción..................................................................................................................... 59 A1.2. C6711 DSK Starter Kit..................................................................................................... 59 A1.2.1. DSP TMS320C6711............................................................................................. 60 A1.2.2. Mapa de memoria................................................................................................. 63 A1.2.3. Descripción de periféricos .................................................................................... 64 A1.2.4. Registros............................................................................................................... 64 A1.2.5. Interrupciones....................................................................................................... 66 A1.3. Code Composer Studio................................................................................................... 67 A1.3.1. Setup .................................................................................................................... 67 A1.3.2. Mapa de memoria................................................................................................. 69 A1.3.3. Creación de un proyecto ...................................................................................... 69 A1.3.4. Librerías................................................................................................................ 74 A1.3.5. Medida del número de ciclos................................................................................ 75 ANEXO 2. IMPLEMENTACIÓN DE PREDISTORSIÓN EN EL ENTORNO C6711 77 A2.1. Formato de datos en Code Composer .......................................................................... 77 A2.1.1. Utilidad de conversión de datos ........................................................................... 77 A2.1.2. Carga de archivos en Code Composer................................................................ 78 A2.2. Inicialización de vectores y matrices ............................................................................ 79 A2.3. Funciones de complejos y matrices.............................................................................. 80 A2.3.1. Funciones de complejos....................................................................................... 80 A2.3.2. Funciones de matrices ......................................................................................... 81 A2.4. Funciones de Hammerstein............................................................................................ 83 A2.4.1. Algoritmo de cálculo del vector vq........................................................................ 83 A2.4.2. Desplazamiento de muestras............................................................................... 85 A2.4.3. Cálculo del filtro FIR con buffer lineal................................................................... 85 A2.4.4. Cálculo del filtro FIR con buffer circular ............................................................... 86 A2.5. Funciones de Fast-Kalman............................................................................................. 87 A2.5.1. Vectores vh y vc ................................................................................................... 87 A2.5.2. Actualización de la matriz λ.................................................................................. 89 A2.6. Funciones LMS................................................................................................................ 90 A2.6.1. Descripción del proyecto ...................................................................................... 90 A2.7. Implementación de LUT .................................................................................................. 92 A2.7.1. Cálculo de LUT..................................................................................................... 92 A2.7.2. Cálculo de salida a partir de tabla LUT ................................................................ 93 A2.8. Funciones de generación de símbolos M-QAM ........................................................... 95 A2.8.1. Modulación M-QAM.............................................................................................. 95 A2.8.2. Obtención de vectores real e imaginario.............................................................. 96 A2.8.3. Generación de símbolos....................................................................................... 98 A2.8.4. Root raised cosine................................................................................................ 99 A2.8.5. Demodulación..................................................................................................... 102 ANEXO 3. FUNCIONES EN MATLAB....................................................... 104 A3.1. Curva AM/AM ................................................................................................................. 104 A3.2. Curva AM/PM.................................................................................................................. 104 A3.3. Gráficas de densidad espectral ................................................................................... 105 A3.4. Gráficas de constelaciones.......................................................................................... 106 A3.4.1. Cálculo de EVM.................................................................................................. 106 A3.5. Funciones para curvas AM/AM y densidad espectral ............................................... 107 A3.5.1. Para el proyecto “Lineal.pjt”................................................................................ 107 A3.5.2. Para el proyecto “Lineal-RRC_QAM.pjt” ............................................................ 108 A3.5.3. Para el proyecto “LUT.pjt” .................................................................................. 109 A3.5.4. Para el proyecto “Demod_QAM.pjt” ................................................................... 111 A3.6. Error cuadrático medio ................................................................................................. 112 ANEXO 4. LISTADO DE PROGRAMAS EN C.......................................... 114 A4.1. Proyecto “Lineal.pjt”..................................................................................................... 114 A4.2. Proyecto “Lineal-RRC_QAM.pjt” ................................................................................. 133 4 Implementación en DSP de un predistorsionador digital En la señal de salida tendremos harmónicos y productos de intermodulación no deseados debidos, por ejemplo, a los efectos no lineales de los términos segundo y tercer orden del polinomio. Pueden identificarse componentes en banda y fuera de la banda de frecuencias de la señal original. Así por ejemplo, se distinguen las frecuencias en banda: • Compresión en ω 1 +ω 1 -ω 1 = ω 1 y ω 2 +ω 2 -ω 2 = ω 2 • Captura en ω 1 +ω 2 -ω 2 = ω 1 y en ω 2 +ω 1 -ω 1 = ω 2 Y fuera de banda definidas como: • Distorsión harmónica: o De 2º orden en 2 ω 1 y 2 ω 2 o De 3r orden en 3 ω 1 y 3 ω 2 • Distorsión de intermodulación o IMD (InterModulation Distortion): o De 2º orden en ω 1 +ω 2 y en ω 1 - ω 2 o De 3r orden en 2 ω 1 +ω 2 , 2 ω 1 -ω 2 , 2 ω 2 +ω 1 y 2 ω 2 -ω 1 La distorsión harmónica puede eliminarse mediante filtrado pero no ocurre así con la distorsión producida por los productos de intermodulación, ya que las frecuencias aparecen demasiado cerca (se necesitarían filtros con factores de calidad altísimos) de las frecuencias de la señal. La figura 1.1 muestra un ejemplo de señal de salida de un amplificador de potencia cuando la entrada es una señal de test con dos tonos a las frecuencias F1 = 650 MHz y F2 = 655 MHz (ver [1]). Fig. 1.1 Salida de un PA con entrada de dos tonos de test a F1 y F2 1.3. Caracterización y parámetros de un amplificador de potencia AMPLIFICADORES DE POTENCIA 5 1.3.1. Curvas AM-AM y AM-PM Un amplificador de potencia puede caracterizarse por las curvas características de entrada – salida: AM-AM (Amplitude Modulation – Amplitude Modulation) y AM-PM (Amplitude Modulation – Phase Modulation). La curva AM-AM modela la distorsión de amplitud, es decir, cómo la modulación de amplitud se modifica a la salida. La curva AM-PM modela la distorsión de fase, es decir, la distorsión que la amplitud de la señal introduce sobre la fase. Se denominan funciones de conversión y proporcionan información sobre las no linealidades del amplificador de potencia. Su utilidad aplica para señales de banda estrecha sin tener en cuenta efectos de memoria. Estas curvas dependen de la tecnología del amplificador y se obtienen mediante mediciones experimentales, por ejemplo, puede utilizarse un tono de entrada variable en frecuencia como la ecuación 1.2. [ ] )(cos)()( tttAtx ϕω += (1.2) La señal de salida del amplificador se puede representar como la ecuación 1.3, donde la amplitud es una función no lineal de la entrada, es el término G[A(t)], y la fase también es función no lineal de la entrada en el término Ф[A(t)]. [ ] [ ] [ ] )()(cos)()( tAtttAGty Φ++= ϕω (1.3) 1.3.2. PAPR (Peak-to-Average Power Ratio) La medida de PAPR es un ratio entre la potencia pico de la envolvente de la señal modulada y la potencia media. Se pueden identificar tres factores principales que contribuyen a la potencia de pico en los esquemas de modulación digital: • Múltiples niveles de potencia de símbolo en las modulaciones M-QAM, utilizadas en los sistemas de comunicación actuales • El filtrado en banda base introduce potencia de pico adicional. Esto es debido a que las señales moduladas digitalmente deben ser filtradas para limitar su ancho de banda teóricamente infinito. Así, las señales I y Q se filtran de manera que el modulador no tiene transiciones instantáneas al siguiente estado. Una transición digital tiene una respuesta impulsional infinita. La convolución de una serie infinita de Fourier con el filtro resulta en que la serie se trunca, se produce el fenómeno de Gibbs • Suma de potencias debidas a múltiples portadoras 6 Implementación en DSP de un predistorsionador digital Para obtener una amplificación lineal, el nivel pico de potencia debe mantenerse dentro de la región lineal del amplificador, y evitar así los efectos no deseados (e.g. productos de IMD) debido a las no linealidades. En consecuencia si se pretende una amplificación lineal, la opción más común consiste en trabajar lejos del punto de compresión y en consecuencia la eficiencia del PA disminuye. Estos factores producen una envolvente que está cambiando continuamente. El nivel pico de potencia debe mantenerse dentro de la región lineal del amplificador para evitar las no linealidades, en consecuencia se trabaja más lejos del punto de compresión y la eficiencia disminuye. El PAPR se define a continuación, ( ) [ ] dB x x CFPAPR         ⋅=⋅= − max 2 log10log10 (1.4) donde CF (Crest Factor) es el factor de cresta y es el ratio entre el valor máximo de la señal y su valor medio. 1.3.3. Punto de compresión a -1 dB A medida que la potencia de la señal de entrada aumenta, la salida ya no sigue la respuesta ideal lineal sino que se produce un efecto de saturación o compresión. Cuando la potencia de la señal de salida es 1 dB inferior a la de la entrada, a este punto se le denomina punto de compresión a -1dB. La figura 1.2 muestra esquemáticamente el punto de compresión. Fig. 1.2 Punto de compresión a 1 dB AMPLIFICADORES DE POTENCIA 7 1.3.4. IBO/OBO (Input Back-Off/Output Backoff) La relación entre la potencia de entrada de saturación y la potencia deseada es lo que se denomina el back-off de entrada del amplificador de potencia o IBO (input back-off). Si se aumenta el IBO, es decir, se disminuye la potencia de entrada, la potencia de salida también será menor pero la linealidad aumenta. El IBO puede ponerse como la diferencia entre la potencia de saturación en dBm a la entrada del amplificador de potencia y la potencia media a la entrada. También puede expresarse en función del parámetro PAPR y del parámetro PBO (Peak Back-Off) como se muestra en la ecuación 1.5. [ ] dBPAPRPBOPPIBO mediainsatin +=−= ,, (1.5) El parámetro PBO queda definido según la ecuación 1.6. ( ) [ ] dBSPBO log10 ⋅−= (1.6) El parámetro S entre 0 y 1 es una fracción de la potencia de entrada de saturación del amplificador. La potencia de entrada máxima es el producto de esta fracción S y la potencia de entrada de saturación como muestra la ecuación 1.7. SPP satinin ⋅= ,max, (1.7) El back-off de salida (OBO) es la relación entre la potencia máxima de saturación a la salida y la potencia real a la salida. Igualmente que el IBO puede ponerse como la ecuación 1.8. [ ] dBPAPRPBOPPOBO mediaoutsatout +=−= ,, (1.8) Esta vez S es una fracción de la potencia de salida de saturación del amplificador como se muestra en la ecuación 1.9. SPP satoutout ⋅= ,max, (1.9) 8 Implementación en DSP de un predistorsionador digital 1.3.5. Eficiencia La eficiencia es un parámetro crítico del amplificador de potencia. Mide el grado de efectividad con que la potencia DC es convertida a potencia RF. Puede expresarse como la ecuación 1.10. [ ] % DC outRF P P − = η (1.10) La eficiencia depende de la clase del amplificador, de la frecuencia, la temperatura, los parámetros IBO/OBO. Para maximizar la eficiencia del amplificador es recomendable trabajar con el menor IBO/OBO posible. 1.3.6. PAE (Power Added Efficiency) Puede definirse también una relación de eficiencia considerando solo la potencia neta convertida a RF sin tener en cuenta la potencia RF inyectada al amplificador de potencia, tal y como se define a continuación: [ ] % DC inRFoutRF P PP PAE −− − = (1.11) 1.3.7. EVM (Error Vector Magnitude) El parámetro EVM se determina a la salida del filtro RRC del demodulador a partir de la comparación entre el valor de símbolo recibido y el valor esperado idealmente. Se puede definir como el error RMS (Root Mean Square o raíz cuadrada del error cuadrático medio) de la diferencia de los valores de símbolos recibidos respecto a los esperados. La EVM se define en los estándares de comunicación como la ecuación 1.12, donde I y Q son las componentes en fase y cuadratura de los símbolos. ∆I es la diferencia entre la componente I de la señal recibida y esperada. N es el número de símbolos del conjunto de medida. S es la potencia media de los símbolos esperados o de referencia. ( ) [ ] % 1 2 1 22 media N jj S QI N EVM ∑ ∆+∆ = (1.12) AMPLIFICADORES DE POTENCIA 9 Es una medida de cómo la no linealidad afecta al proceso de detección. Para calcular este parámetro a menudo se utilizan analizadores vectoriales de señal o VSA (Vector Signal Analyzer) u otros instrumentos que incorporan funciones de software específicas. Se expresa en porcentaje y normalizado para permitir la comparación entre las diferentes modulaciones. La figura 1.3 muestra gráficamente el parámetro EVM (ver [2]). Fig. 1.3 Representación gráfica de parámetro EVM 1.3.8. ACPR (Adjacent Channel Power Ratio) El ACPR es la relación en potencia entre la emisión dentro de banda y la emisión de señal a los canales adyacentes, así pues, caracteriza cómo las no linealidades de la señal afectan a los canales adyacentes. La potencia en el canal adyacente debida a la señal en banda será vista como una señal interferente para la señal en banda del canal adyacente. El ACPR se define como el ratio entre la densidad espectral de energía de la señal en el canal adyacente y la densidad espectral de energía en la banda, tal y como se muestra en la siguiente ecuación: [ ] dBr dffPdffP dffP P P ACPR Lowerside Upperside outout out channeladjacent bandin ∫ ∫ ∫ ⋅+⋅ ⋅ == − − )()( )( (1.13) 10 Implementación en DSP de un predistorsionador digital La figura 1.4 muestra el parámetro ACPR en una gráfica de la densidad espectral de la señal de salida de un amplificador de potencia. Fig. 1.4 Densidad espectral de potencia de la salida de un amplificador de potencia. La entrada es una señal 16QAM, -17dBm. Los estándares de comunicaciones definen los valores mínimos de ACPR que deben cumplirse mediante máscaras de potencia y máxima emisión fuera de banda permitidos. 1.3.9. IMD (InterModulation Distortion) La distorsión de intermodulación permite describir también las no linealidades. Para medir la intermodulación se aplica, por ejemplo, una señal con dos tonos de igual amplitud y fase. La señal de salida mostrará los dos tonos y los respectivos productos de intermodulación, así como distorsión harmónica. Se define el parámetro IP3 (Interception Point 3) como el punto donde se cruzarían las funciones de: • Señal portadora C respecto a potencia de entrada P in • Señal de distorsión I respecto a potencia de entrada P in Es un punto teórico ya que antes de llegar ambas curvas se saturan pero suele utilizarse como referencia. La figura 1.5 muestra el esquema del punto de interceptación. AMPLIFICADORES DE POTENCIA 11 Fig. 1.5 Representación gráfica del IP3 1.4. Clases de amplificadores Los amplificadores de potencia se clasifican en varias clases denominadas A, B, C, D, E y F. Las clases difieren en el método de operación, linealidad y eficiencia. Las clases A y B operan como una fuente de corriente mientras que el resto, lo hacen como un interruptor o switch. A continuación, se resumen las características de los diferentes tipos de amplificadores en función de su eficiencia energética: • Clase A: proporciona la amplificación más lineal y el mayor factor de ganancia de los amplificadores. Permite su utilización a frecuencias próximas a la máxima de operación del transistor ya que no hay harmónicos en el proceso de amplificación. Por el contrario, su eficiencia es muy baja siendo para un PA ideal de un 50% • Clase B: también proporcionan amplificación lineal, aunque menos que los de clase A. La eficiencia instantánea varía con la tensión de salida y para un amplificador ideal llega al 78,5% • Clase AB: es un compromiso entre la clase A y la clase B, tanto desde el punto de vista de eficiencia como de linealidad • Clase C: se aumenta la eficiencia respecto a los anteriores, a costa de reducir la linealidad. Puede llegarse a eficiencias del 100% • Clase D, E y F: la eficiencia es del 100% para un amplificador ideal, también con linealidad baja El objetivo es mantener la linealidad y mejorar la eficiencia trabajando más lejos de la zona de back-off, para ello se utilizan técnicas de linealización. 12 Implementación en DSP de un predistorsionador digital CAPÍTULO 2. TÉCNICAS DE LINEALIZACIÓN 2.1. Compromiso entre linealidad y eficiencia Los amplificadores de potencia son elementos que consumen mucha potencia en los sistemas de RF (alrededor del 70% del consumo total en un sistema de RF). Por eso es tan importante su eficiencia en términos de la vida de las baterías. Las modulaciones actuales presentan envolventes no constantes con valores de PAPR altos. Se opera en modo de back-off para evitar los efectos no lineales de las señales pico. Esto hace que la eficiencia global del sistema se degrade. La eficiencia también está relacionada con las clases de los amplificadores de potencia como se ha visto en el apartado 1.4. A continuación, se presentan algunas técnicas de linealización a nivel de sistema englobadas en aquellas que tienen como objetivo reducir la distorsión y las que evitan que aparezca la distorsión. 2.2. Linealización a nivel de sistema Atendiendo al compromiso linealidad-eficiencia, existen diversas técnicas de linealización de amplificadores que permiten una mayor linealidad en la amplificación de señales sin degradar en exceso la eficiencia del PA. La linealización de PA puede llevarse a cabo a dos niveles: circuito y sistema. La linealización a nivel de circuito se hace en el dispositivo. Sin embargo, la reducción de la distorsión es limitada, y además, depende de las evoluciones materiales del dispositivo. Nos centraremos más en la linealización a nivel de sistema que aplica técnicas de linealización en un nivel superior y permite reducir la distorsión de intermodulación. Es posible distinguir varias familias de linealizadores que pueden agruparse en dos grupos dependiendo de la causalidad del linealizador con respecto a la cancelación de la distorsión. 2.2.1. Linealizadores que reducen la distorsión En este caso, los efectos no lineales aparecen a la salida del amplificador de potencia y el objetivo es minimizarlos a partir de las medidas de distorsión en ese momento. Se distinguen dos familias principales: TÉCNICAS DE LINEALIZACIÓN 13 2.2.1.1. Feedback En la figura 2.1 se muestra el esquema clásico de realimentación o feedback en lazo cerrado. Fig. 2.1 Esquema de realimentación en lazo cerrado Las señales indicadas d i y d o son interferencias que se suman a la entrada y la salida. La función de transferencia del bucle cerrado se considera lineal y para obtener la salida se aplica el principio de superposición. La función de salida y queda entonces según la ecuación 2.1. oi d H G d H G G x H G G y⋅ ⋅+ +⋅ ⋅+ +⋅ ⋅+ = 1 1 1 1 (2.1) G es la función de transferencia del amplificador de potencia y H es la función de transferencia del lazo cerrado o feedback. Puede deducirse que para reducir la interferencias es necesario aumentar H en el caso de d i , y H o G para d o . Si se considera únicamente la parte correspondiente a la entrada x, se puede definir la función de transferencia en frecuencia para obtener las condiciones de estabilidad. La función de transferencia queda como en la ecuación 2.2. ( ) ( ) ( ) ( ) ( ) ( ) wHwG wG wX wY wT ⋅+ == 1 (2.2) La función T(w) será inestable siempre que G(w)·H(w) = -1, o de manera equivalente que su módulo sea 1 y la fase ±180º. Este producto es la función de transferencia en lazo abierto y define las condiciones de estabilidad del sistema. La aplicación de la técnica de feedback queda limitada a comunicaciones de banda estrecha. Se han propuesto variaciones sobre esta técnica como feedback de envolvente, cartesiano o polar (ver [10]). 20 Implementación en DSP de un predistorsionador digital Finalmente, el vector q k se determina como en la ecuación 3.7. T D P NN NNN P P k kykykykxkx kxkxkxkxkxkx kxkxkxkxkxkxkxkxkx q             −−−−⋅− −⋅−−−⋅−−⋅ ⋅−−⋅⋅⋅ = )(),...,(),(,)()(,..., ,)()(),(,...,)()(,...,)( )(),(,)()(,...,)()(,)()(),( 21 111 11 2 τττττ ττττττ ττ (3.7) Para predecir el valor de la salida y k , resulta que los valores de q k son datos conocidos de la entrada y salida del amplificador de potencia. Los valores de c k pueden estimarse minimizando una función de coste. 3.3.2. Modelo de Wiener El modelo de Wiener se define cambiando el orden de los bloques respecto al modelo de Hammerstein, es decir, primero un bloque que modela un sistema LTI en cascada con un bloque no lineal sin memoria tal y como se muestra en la figura 3.5. Fig. 3.5 Diagrama de bloques del modelo de Wiener En este caso se considera un filtro FIR en lugar de IIR ya que este modelo es significativamente más complejo computacionalmente hablando que el anterior. La relación entre x(k) e y(k) queda definida en las ecuaciones 3.8 y 3.9. ∑ = −⋅= N n n nkxkv 0 )()( β (3.8) ∑ = ⋅⋅= P p p p kvkvky 0 )()()( γ (3.9) Si ambas se combinan, el resultado se muestra en la ecuación 3.10. PREDISTORSIÓN DIGITAL 21 ∑ ∑∑ = == −⋅⋅      −⋅⋅= P p p N n nn N n nnp kxkxky 0 11 )()()( τβτβγ (3.10) El parámetro β n está incluido en el término con potencias, con lo cual no es evidente la resolución como en el modelo de Hammerstein. Es posible dividir el problema en dos fases considerando que el filtro FIR es estable, que la función no lineal es invertible y que no hay ruido en el sistema. Con estas presunciones, es posible calcular la variable v(k) a partir de 3.8 y 3.9: ∑ ∑ = = − ⋅⋅=−⋅= N n P p p nn kykykxkv 1 0 1 )()()()( γτβ (3.11) El error a minimizar está en la ecuación 3.12 donde se considera que el parámetro β 1 = 1 y las soluciones γ, β = 0 no se tienen en cuenta. 1,)()()()()( 20 1 1 =        −⋅−⋅⋅−−= ∑∑ == − βτβγτ N n nn p P p kxkykykxke (3.12) La ecuación 3.12 puede ser escrita en notación matricial como la ecuación 3.13, siendo η según la ecuación 3.14 y g k como la ecuación 3.15. k H k gkxke ⋅−−= ητ )()( 1 (3.13) [ ] T npk βββγγγη ,...,,,,...,, 32 11 1 1 0 −−− = (3.14) [ ] T D p k kxkxkykykyg )(),...,(,)()(),...( 2 ττ −−−−⋅= (3.15) Una vez que el error e(k) se ha minimizado, se pueden obtener los coeficientes de Wiener a partir de v(k) y las ecuaciones 3.8 y 3.9. 3.3.3. Configuraciones Se estudian dos configuraciones básicas para la estimación de los coeficientes del predistorsionador. 22 Implementación en DSP de un predistorsionador digital 3.3.3.1. Método directo Permite la estimación directa del predistorsionador pero requiere previamente un buen modelo del amplificador de potencia como aprendizaje para la estimación de los coeficientes. En la figura 3.6 se muestra el esquema del método directo. Fig. 3.6 Esquema de predistorsión con método directo Se describe el método directo mediante la ecuación 3.16. ( ) uGuFG pre ⋅= 0 )( (3.16) 3.3.3.2. Método indirecto Con este método, se hace una estimación del modelo inverso del amplificador de potencia a partir de los datos de entrada y de salida. Cuando el proceso de aprendizaje finaliza, los coeficientes del post-distorsionador se copian idénticamente en el modelo del predistorsionador en la entrada. Con esta configuración no es necesario calcular el modelo del amplificador de potencia como en el método anterior, basta con disponer de su entrada y su salida para estimar el modelo del post-distorsionador. La ecuación 3.17 muestra dicho funcionamiento. ( ) xGxGF post ⋅= 0 )( (3.17) La figura 3.7 muestra el esquema de método indirecto. PREDISTORSIÓN DIGITAL 23 Fig. 3.7 Esquema de predistorsión con método indirecto 3.4. Algoritmos de identificación Consideraremos el modelo de Hammerstein en la configuración de método indirecto para obtener los coeficientes de predistorsionador. La función a minimizar se define como el error cuadrático medio entre las muestras de salida del post-distorsionador y las muestras de entrada al PA. El error se muestra en la ecuación 3.18, siendo x la señal deseada y x POST la señal estimada de salida del modelo. k H kPOST qckxkxkxke ⋅−=−= )()()()( (3.18) La ecuación 3.19 presenta la función de coste a minimizar. Entre otros, pueden utilizarse los algoritmos LMS y Fast-Kalman. 22 )()()()( kxkxkekJ POST −== (3.19) 3.4.1. Algoritmo LMS El algoritmo Least Mean Square (LMS) para el cálculo de los coeficientes estimados c k se describe en la ecuación 3.20. * 1 )(keqcc kkk ⋅⋅+= + µ (3.20) Siendo µ el compromiso entre la velocidad de convergencia y la exactitud. El parámetro µ está acotado según la ecuación 3.21. 24 Implementación en DSP de un predistorsionador digital ( ) H kk qqTraza ⋅ << 2 0 µ (3.21) Siendo la traza la suma de los elementos de la diagonal de la matriz resultante del producto entre el vector q k y H k q , que es su hermítico. 3.4.2. Algoritmo Fast-Kalman El algoritmo de Fast-Kalman utiliza una técnica de filtrado óptimo de Kalman para hacer la estimación de los coeficientes c k . La ecuación 3.21 describe la actualización de los coeficientes c k a partir del vector h k definido en la ecuación 3.22. * 1 )(kehcc kkk ⋅+= + (3.21) Mk k H k k k k Qqq q h + = − − 1 _ 1 _ λ λ (3.22) La matriz λ se actualiza recursivamente según la ecuación 3.23. El vector q k sigue la ecuación 3.7, H k q es su vector hermítico, Q m y la matriz Q p están relacionados con las varianzas del error de estimación y medida. p k H kk kk Qqh _ 1 _ 1 __ +−= −− λλλ (3.23) 3.5. Predistorsionador con LUT La implementación práctica de la predistorsión digital se suele hacer digitalmente con herramientas como las DSP, FPGA o circuitos ASIC. A partir de los coeficientes estimados c k se construyen unas tablas denominadas LookUp-Table o LUT que contienen valores complejos de ganancia. Para calcular la salida del predistorsionador bastará con multiplicar la muestra de entrada x(k) y sus N retardos por la ganancia adecuada. La creación de las LUT puede hacerse en un entorno DSP como el C6711 y después los resultados se pasan a una FPGA que realizará las multiplicaciones PREDISTORSIÓN DIGITAL 25 necesarias para obtener la salida del predistorsionador a partir de las muestras de entrada. 3.5.1. Implementación de LUT para Hammerstein FIR Se considerará el modelo de Hammerstein como un filtro FIR. La implementación de las diferentes tablas LUT se hace a partir de la ecuación 3.5 que mostraba los coeficientes d np . Se evalúan N+1 funciones denominadas f 0 , f 1 , ... , f N . Cada función tiene en cuenta los d np correspondientes. La ecuación 3.24 muestra la asociación de las funciones a los diferentes valores d np para un ejemplo con N= 2 y P= 4. } } } 22423222120 11413121110 00403020100 ,,,, ,,,, ,,,, fddddd fddddd fddddd (3.24) Las funciones f 0 , f 1 ,..., f N se pueden poner como la ecuación 3.25. ( ) ( ) ( ) ( ) ( ) ( ) ( ) nP P nnnnn dkxkxdkxkxdkxkxf ⋅−⋅++⋅−⋅+⋅= ττ ... 10 (3.25) Cada función debe evaluarse para x(k) desde 0 a 2 n -1 siendo 8 bits un valor suficiente para n, de manera que se calcularía para x(k) entre 0 y 255. Las tablas LUT se completan con las ganancias complejas evaluadas según la ecuación 3.26 para los valores de x(k) anteriores. ( ) ( ) ( ) ( ) ( ) nP P nnnn n dkxdkxd kx ky kG ⋅−++⋅−+== ττ ... 10 (3.26) La primera tabla LUT 0 sigue la ecuación 3.27, la tabla LUT 1 es según la ecuación 3.28 y así sucesivamente hasta N. ( ) ( ) ( ) ( ) ( ) P P dkxdkxd kx ky kG 00100 0 ... ⋅++⋅+== (3.27) ( ) ( ) ( ) ( ) ( ) P P dkxdkxd kx ky kG 1111110 1 ... ⋅−++⋅−+== ττ (3.28) 26 Implementación en DSP de un predistorsionador digital 3.5.2. Cálculo de señal de salida con LUT La figura 3.8 muestra el esquema de la implementación del cálculo de la muestra de salida con LUT en el predistorsionador. Fig. 3.8 Esquema de la implementación de predistorsión con LUT La muestra de entrada x(k) pasa por una etapa en la que se calcula el valor absoluto y así es posible indexar este valor en la LUT para conseguir el valor de ganancia correspondiente. Una vez encontrado el valor de la ganancia compleja, se multiplica la muestra x(k) por la ganancia G 0 (k) como muestra la ecuación 3.29. ( ) ( ) ( ) kGkxky 00 ⋅= (3.29) La muestra anterior τ1 pasa también por una etapa donde se calcula el módulo. Genéricamente, la salida y(k) puede ponerse como muestra la ecuación 3.30. ( ) ( ) ( ) ( ) ( ) ( ) ( ) ( ) ( ) ( ) kGkxkGkxkGkxkykykyky NNN ⋅−++⋅−+⋅=+++= ττ ...... 11010 (3.30) IMPLEMENTACIÓN DE PREDISTORSIÓN DIGITAL 27 CAPÍTULO 4. IMPLEMENTACIÓN DE PREDISTORSIÓN DIGITAL 4.1. Introducción Para la implementación de la predistorsión adaptativa en un entorno real con DSP y FPGA, se ha desarrollado el modelo de Hammerstein, en sus configuraciones FIR e IIR, en el simulador del procesador DSP C6711. Partiendo de muestras reales de entrada y salida de un amplificador de potencia, se han estimado los coeficientes del modelo del amplificador según Hammerstein. Para ello, se ha aplicado el algoritmo Fast-Kalman para la minimización de las funciones de coste correspondientes. Asimismo, se han estimado los coeficientes del post-distorsionador para muestras reales y muestras M-QAM generadas aleatoriamente. Por último, se han desarrollado las funciones para disponer de las tablas LUT para el predistorsionador en configuración FIR. El entorno de desarrollo utilizado es el software Code Composer Studio de Texas Instruments v3.1 en modo simulador del dispositivo DSP C67XX. A continuación, se presentan los diferentes proyectos que han permitido realizar las simulaciones. En el Anexo 1 se describe en detalle el entorno de desarrollo hardware y software. En el Anexo 2 se desarrollan más ampliamente las funciones que se presentan en este capítulo. 4.2. Modelo del amplificador de potencia y postdistorsionador a partir de muestras reales Para poder simular el comportamiento del amplificador de potencia en el entorno de desarrollo del procesador C6711, se estiman los coeficientes que modelan el amplificador de potencia según Hammerstein. Para ello, se dispone de un archivo de muestras reales de entrada y salida de un amplificador de potencia. En el mismo proyecto de Code Composer se ha implementado también la estimación de los coeficientes del post-distorsionador. Estos resultados permiten disponer de: • Modelo del amplificador de potencia: será utilizado en éste y otros proyectos para obtener la salida del PA • Modelo del post-distorsionador: en un nuevo proyecto de Code Composer se calculan las tablas LUT para el predistorsionador a partir de estos coeficientes del post-distorsionador. En la aplicación práctica, los coeficientes del post-distorsionador se van actualizando cada cierto tiempo 28 Implementación en DSP de un predistorsionador digital • Muestras de entrada y salida del amplificador calculadas o estimadas: permitirán calcular los errores en la estimación • Aplicación de predistorsionador + amplificador de potencia: todavía sin las LUT, en este proyecto se implementa el cálculo de la salida del predistorsionador y posterior amplificador con nuevas muestras reales. Permite obtener las gráficas AM/AM del predistorsionador y salida linealizada del amplificador 4.2.1. Formato de los datos Para estimar el modelo del amplificador de potencia, se utilizarán muestras proporcionadas en formato de Matlab (archivo .mat). Corresponden en este caso, a una modulación 16-QAM a la entrada y salida de un amplificador de potencia. La parte real e imaginaria (componentes en fase y cuadratura) de cada señal de entrada y salida se guarda en un archivo de texto que después podrá ser manipulado mediante una pequeña aplicación para adaptarse al formato adecuado para el software Code Composer. De los formatos disponibles se ha escogido el hexadecimal. El resultado se ha guardado en archivos de texto con extensión .dat. 4.2.2. Lectura de los datos desde Code Composer El software Code Composer permite la lectura y escritura de datos en archivos con la opción “Debug, Probe Points...” o el botón . A esta herramienta se la denomina probe point y permite detener la ejecución del programa en curso y realizar automáticamente una operación de lectura o escritura en los archivos asociados a la posición de código especificada cuando se crea. A continuación, la ejecución del programa continúa. Se han creado funciones específicas para la lectura de cada archivo que serán llamadas en los puntos de ejecución necesarios. En cada punto, se activa la probe, quedando señalizadas con el símbolo . Seguidamente, debe especificarse el archivo que se cargará. Se indica también el nombre de la variable que guardará los datos y el número de muestras que se leerán. La figura 4.1 muestra la configuración de una probe point. IMPLEMENTACIÓN DE PREDISTORSIÓN DIGITAL 29 Fig. 4.1 Configuración de una input probe 4.2.3. Descripción del proyecto El proyecto denominado “Lineal.pjt” permite estimar el modelo del amplificador de potencia y del post-distorsionador a partir de las muestras de entrada y salida disponibles del amplificador. Posteriormente, aplica a nuevas muestras los coeficientes obtenidos para el predistorsionador y la salida del predistorsionador pasa por el modelo del amplificador. La figura 4.2 muestra esquemáticamente el diagrama de bloques de la estimación de los coeficientes. Las muestras x(k), y(k) son las muestras reales de entrada y salida del amplificador de potencia del modelo normalizadas. La normalización de las muestras se hace en potencia, es decir, se determina el módulo máximo de la señal de entrada x(k) para el número de muestras consideradas y se divide o normalizada cada muestra de ambas señales, x(k) e y(k), entre este valor máximo. Las muestras xd(k), yd(k) son las calculadas. Los coeficientes vc_PA, vc, que describen los modelos del amplificador y post-distorsionador respectivamente, se estiman minimizando la función error cuadrático entre las muestras reales normalizadas y las calculadas. 36 Implementación en DSP de un predistorsionador digital En [15] se propone un ajuste de la potencia de entrada al PD+PA según la ecuación 4.3. in PA lin in PAPD P G G P _ 2 0 _ ⋅≈ + (4.3) Siendo G lin la ganancia del PA en la zona lineal y G 0 la ganancia del PA considerando toda la respuesta. En nuestro caso G lin es 1 ya que es la ganancia de amplificación ideal si no hubiera saturación. G 0 se determina a partir de los valores del módulo máximo de amplitud de entrada y salida como en la ecuación 4.4: in máx out máx A A G= 0 (4.4) De esta forma, si consideramos un ejemplo práctico, para las 8000 primeras muestras del modelo, los valores máximos del módulo de la señal de entrada y salida son: 1,15 y 0,9 respectivamente. Esto daría un ajuste de G 0 = 0,7826 o 1/G 0 = 1,28 que ha resultado ser bastante adecuado. 4.2.3.5. Módulo Hammerstein Este módulo implementa las funciones: • Inicialización de vector complejo a 0 (parte real e imaginaria) • Filtro FIR con muestras complejas: realiza el conjugado de uno de los vectores de muestras, después acumula y hace el producto del conjugado por el segundo vector • Desplazamiento de una muestra compleja en un vector • Generación del vector vq según la ecuación 3.7 4.2.3.6. Módulo Fast-Kalman Este módulo implementa las funciones: • Generación de los vectores complejos c k+1 y h k según el algoritmo de Fast-Kalman (ecuaciones 3.21 y 3.22) • Actualización de la matriz λ k según el algoritmo de Fast-Kalman (ecuación 3.23) IMPLEMENTACIÓN DE PREDISTORSIÓN DIGITAL 37 Las matrices λ son las estructuras que mayor cantidad de memoria reservan. Se utilizan varias matrices temporales para poder realizar las operaciones de suma, resta y producto de matrices correspondientes al numerador y denominador del vector vh y de la matriz λ. Es necesario tener en cuenta el espacio de memoria que ocupan. Por otro lado, las funciones de generación de los vectores vc, vh y la actualización de la matriz λ. son las que más ciclos de reloj emplean por la cantidad de operaciones del producto de dos matrices. En el capítulo 5 se hace una estimación del espacio de memoria y del número de ciclos empleado. 4.2.4. Salida de los datos en Code Composer La manera más sencilla de guardar los resultados obtenidos es utilizando la salida por consola estándar. Las variables indicadas con la función printf de C se muestran en una ventana “stdout” de Code Composer como se muestra en la figura 4.7. Fig. 4.7 Ventana stdout de Code Composer Si se desea que la salida estándar quede guardada en un archivo de texto, previamente se deberá haber configurado. Con el botón derecho sobre la ventana Stdout aparece la opción “Save output to file”. A continuación, se especifica el archivo destino y otros parámetros como si se añade una marca temporal, tamaño máximo del archivo y tratamiento si se llena (parar lectura o sobrescribir el inicio),... 38 Implementación en DSP de un predistorsionador digital 4.3. Implementación de LUT para el predistorsionador 4.3.1. Descripción del proyecto El proyecto llamado “LUT.pjt” implementa el algoritmo para calcular las muestras de salida del predistorsionador tras aplicar las tablas LUT y a continuación, pasa por el modelo del amplificador para obtener las muestras de salida después de las etapas predistorsionador + amplificador. Asimismo, estima la muestra de salida del amplificador sin pasar por el predistorsionador lo que nos permite tener una idea de la bondad del predistorsionador. Consta de los módulos comunes expuestos en el apartado 4.2 necesarios: complejos (módulo complex.c) y hammerstein (ham.c). Se añade un nuevo módulo específico para la implementación de las funciones de LUT, denominado lut.c con su correspondiente fichero de cabecera lut.h. 4.3.1.1. Diagrama de flujo del programa principal Las funciones principales son: • Inicialización de los vectores de muestras de entrada y salida: para calcular las muestras de salida del predistorsionador se necesita la muestra actual y las N muestras anteriores de la señal de entrada (implementación LUT de modelo Hammerstein FIR). De igual forma, para calcular las muestras de salida del amplificador se utiliza la muestra de entrada actual y las N anteriores, así como las D muestras de salida (en este caso el filtro del modelo de Hammerstein puede ser IIR) • Inicialización de LUT para modelo del predistorsionador: se calcula un vector LUT a partir de un vector de coeficientes c k del predistorsionador • Lectura de las muestras de entrada: a partir de los dos archivos .dat que contienen las partes real e imaginaria de las señal de entrada del amplificador real • Normalización de las muestras de entrada: se determina el valor máximo del módulo de la señal de entrada y se aplica además, un factor de ganancia G 0 que se calcula según se ha explicado en el apartado 4.2.3.4. • Bucle que incluye el cálculo de las muestras de salida del predistorsionador con LUT y del amplificador con q k . En el mismo bucle se estiman también las muestras de salida del amplificador sin pasar por el predistorsionador: o Desplazamiento de muestra de entrada actual al vector correspondiente o Aplicación de LUT para el predistorsionador o Desplazamiento de muestra de salida del predistorsionador IMPLEMENTACIÓN DE PREDISTORSIÓN DIGITAL 39 o Cálculo del vector vq para el PA con predistorsión o Cálculo del vector vq para el PA sin predistorsión o Cálculo de muestra de salida del PA con predistorsión o Cálculo de muestra de salida del PA sin predistorsión o Desplazamiento de las muestras calculadas a los vectores correspondientes o Visualización de los datos Las figuras 4.8 y 4.9 muestran el diagrama de flujo del programa principal. Fig. 4.8 Diagrama de flujo del programa principal (parte 1) 40 Implementación en DSP de un predistorsionador digital Fig. 4.9 Diagrama de flujo del programa principal (parte 2) 4.3.1.2. Módulo LUT Las funciones implementadas en el módulo LUT son: • Cálculo de vector LUT a partir de un vector de coeficientes vc: en función de un parámetro que determina el número de bits (definido como BITS), se tienen las muestras de entrada que serán evaluadas para obtener el vector de ganancias complejas según la ecuación genérica 3.26 aplicada desde 0 a N • Evaluación de un polinomio: la función anterior de cálculo del vector LUT requiere una función que calcule las ganancias complejas como la evaluación de un polinomio. Es equivalente a la función polyval de Matlab que evalúa la salida de un polinomio para una muestra de entrada determinada • Cálculo de la muestra de salida a partir de un vector de muestras de entrada y el vector LUT IMPLEMENTACIÓN DE PREDISTORSIÓN DIGITAL 41 4.4. Generación de muestras M-QAM y estimación de postdistorsionador 4.4.1. Descripción del proyecto El proyecto llamado “Lineal-RRC_QAM.pjt” permite generar las muestras de entrada pseudo-aleatorias según una modulación M-QAM (desde 8 hasta 64) a las que después se aplicarán los coeficientes del modelo del amplificador obtenido en el proyecto “Lineal.pjt”. A partir de las muestras de salida estimadas y de las de entrada se calculan los coeficientes del postdistorsionador. Por último, se aplica a nuevas muestras generadas los coeficientes del predistorsionador y su salida de nuevo al modelo del amplificador. La figura 4.10 muestra esquemáticamente el diagrama de bloques de la estimación de los coeficientes. Fig. 4.10 Diagrama de bloques de estimación de coeficientes vc 4.4.1.1. Diagrama de flujo de programa principal Las funciones principales son: • Inicialización de la estructura del filtro RRC que incluye los parámetros: número de muestras por símbolo, número de símbolos, factor de roll-off • Inicialización de los vectores de muestras de entrada y salida: la estimación de los coeficientes precisa las N muestras anteriores de la señal de entrada (si el filtro del modelo de Hammerstein es FIR) o también las D muestras anteriores de la señal de salida (si es IIR) • Inicialización de los vectores vc, vh y las matrices Qp y λ: los vectores y matrices que se utilizan en el algoritmo de Fast-Kalman deben ser 42 Implementación en DSP de un predistorsionador digital correctamente inicializados. En este proyecto solo aplican para la estimación del post-distorsionador • Generación de secuencia pseudo aleatoria según la modulación M-QAM • Convolución de la secuencia generada separada en parte real e imaginaria con el filtro RRC • Cálculo del módulo de la señal de entrada • Bucle de cálculo de los coeficientes del modelo del post-distorsionador: previamente se normalizan las muestras de entrada La figura 4.11 muestra el diagrama de flujo del programa principal. Fig. 4.11 Diagrama de flujo del programa principal (parte 1) La figura 4.12 muestra el diagrama de flujo del cálculo de los coeficientes del post-distorsionador. IMPLEMENTACIÓN DE PREDISTORSIÓN DIGITAL 43 Fig. 4.12 Diagrama de flujo del programa principal (parte 2) El proceso es idéntico al proyecto “Lineal.pjt” utilizando las variables adecuadas, se muestra solo para mayor claridad: • Desplazamiento de muestra de entrada actual en el vector correspondiente • Cálculo del vector q k (vq_PA) según la ecuación 3.7 • Estimación de muestra de salida del amplificador a partir de q k (vq_PA) y c k (vc_PA) conocido según la ecuación 3.4 • Desplazamiento de muestra de salida estimada en los vectores correspondientes: se utiliza para calcular el vector vq_PA y como muestra de entrada de la estimación de los coeficientes del postdistorsionador 44 Implementación en DSP de un predistorsionador digital • Cálculo del vector q k (vq) del post-distorsionador • Estimación de muestra de salida del post-distorsionador a partir de vq y vc • Cálculo del vector c k+1 (vc) según la ecuación 3.21 y 3.22 • Actualización de la matriz λ k según la ecuación 3.23 • Desplazamiento de muestra de salida estimada en el vector correspondiente • Visualización de los datos 4.4.1.2. Estructura de módulos del proyecto El proyecto consta de diferentes módulos (.c), archivos de cabeceras (.h), librerías (.lib), y archivo con el mapa de memoria (.cmd). Se utilizan las funciones base comunes (complejos, matrices, hammerstein y Fast-Kalman) y se han añadido específicas para la generación de la secuencia M-QAM: • Muestras: el módulo sample.c incluye las funciones que inicializan vectores a un valor determinado y que generan símbolos de una secuencia pseudo aleatoria con la función rand() incluida en Code Composer • Símbolos M-QAM: el módulo qam.c contiene los vectores con las partes real e imaginaria por separado de los símbolos de las modulaciones MQAM, desde 8 hasta 64. Estos valores se han reordenado a partir de secuencias obtenidas con Matlab (función constlay). El módulo qam.c permite obtener las partes real e imaginaria a partir de un símbolo generado aleatoriamente utilizando los vectores descritos • Coseno realzado: el módulo rrc.c implementa las funciones necesarias para inicializar la estructura rrc con los parámetros del filtro RRC, obtener la respuesta impulsional del filtro RRC y la convolución de la señal de entrada con el filtro RRC Cada módulo tiene su correspondiente archivo de cabecera de funciones (.h). Además de los tipos de datos base comunes a todos los módulos (SAMPLE, tComplex y tMatrix) se han definido nuevas estructuras específicas para la generación de muestras: • Tipo tRRC: estructura para el filtro RRC con el número de símbolos a tener en cuenta, número de muestras por símbolo, factor de roll-off y vector de la respuesta impulsional • Tipo tRRCFiltConv: estructura que permite trabajar con la convolución a través de buffers circulares e índice a este buffer • Tipo tRRCFiltFast: estructura similar a la anterior que implementa un algoritmo rápido de convolución que reduce el número de ciclos de ejecución IMPLEMENTACIÓN DE PREDISTORSIÓN DIGITAL 45 4.5. Demodulación de muestras M-QAM 4.5.1. Descripción del proyecto El proyecto “Demod_QAM.pjt” recoge las funcionalidades de los proyectos anteriores y permite disponer de: • Las muestras de entrada pseudo-aleatorias según una modulación MQAM y la aplicación del filtro conformador RRC • Las muestras anteriores se pasan por el predistorsionador estimado en el proyecto “Lineal_QAM-RRC.pjt” mediante LUT para obtener la salida del predistorsionador • Las muestras de salida del predistorsionador pasan por el modelo del amplificador de potencia estimado en el proyecto “Lineal.pjt”. A las muestras de entrada sin predistorsión también se les aplica el modelo del amplificador • Las muestras de salida del amplificador sin y con predistorsionador pasan por sendos filtros RRC • Las muestras de salida de los filtros RRC se demodulan a partir de zonas de decisión definidas para cada símbolo. Se obtienen así, los símbolos de la modulación correspondiente para la parte real e imaginaria Las muestras se importan en el entorno de Matlab para proceder al delmado y ajuste según los retardos introducidos por los filtros. Las muestras obtenidas permiten representar las constelaciones y calcular la figura de mérito EVM. La figura 4.13 representa el diagrama de bloque de las señales de entrada y salida sin predistorsionador y en la figura 4.14 se observa el mismo diagrama con predistorsionador. Fig. 4.13 Diagrama de bloques de las señales sin predistorsionador Fig. 4.14 Diagrama de bloques de las señales con predistorsionador 52 Implementación en DSP de un predistorsionador digital Fig. 5.7 Gráfica de densidad espectral de potencia de la salida estimada del PA y de la salida del predistorsionador y PA (muestras M-QAM pseudo-aleatorias) 5.3.2. Demodulación de señales La figura 5.8 muestra la constelación de las muestras de salida de un filtro conformador RRC después del amplificador de potencia sin predistorsión. La entrada son muestras pseudo-aleatorias de una modulación 64-QAM generada con 12 muestras por símbolo, 10000 muestras y factor de roll-off de 0.35. Fig. 5.8 Constelación de señal de salida del PA después de RRC RESULTADOS 53 La figura 5.9 muestra la constelación de las muestras a la salida del amplificador de potencia después del predistorsionador y filtro conformador RRC. Fig. 5.9 Constelación de señal de salida del PA con predistorsionador después de RRC Puede notarse que la dispersión de los símbolos a la salida del amplificador de potencia sin predistorsión es significativa, mientras que la constelación de los símbolos a la salida del amplificador con predistorsión es similar a la ideal para la modulación 64-QAM. Se ha calculado el parámetro EVM en ambos casos, obteniéndose unos valores de 4,44% cuando no hay predistorsionador y 0,29% cuando se utiliza predistorsionador. Se puede observar cómo la función de predistorsión implementada consigue corregir muy significativamente las no linealidades dentro de banda introducidas por el amplificador de potencia. 5.4. Ciclos de reloj para la actualización de coeficientes Como se ha comentado en el capítulo 4, las funciones de producto de matrices en la implementación del algoritmo Fast-Kalman son las que más ciclos de reloj consumen. 54 Implementación en DSP de un predistorsionador digital La tabla 5.1 muestra el número de ciclos para algunos ejemplos de producto de matrices con la función de la librería DSPLIB de Texas Instruments y una función en C para multiplicar matrices. Tabla. 5.1 Comparación de dos funciones para multiplicar matrices Función Ciclos con DSPLIB Ciclos con matrix_multiply Producto de dos matrices de dimensiones: 28x28 · 28x1 = 28x1 3179 156711 Producto de dos matrices de dimensiones: 28x28 · 28x28 = 28x28 43947 4353268 Función de algoritmo Fast-kalman (P+1= 7, N+1= 4, D= 0) 15938 181971 Función de actualización de matriz λ (P+1= 7, N+1= 4, D= 0) 429630 4738951 1 iteración para la estimación de los coeficientes (P+1= 7, N+1= 4, D= 0) ~480000 4931481 Si consideramos la frecuencia del procesador DSP C6711 de 150 MHz, la estimación de los coeficientes del post-distorsionador para 5000 coeficientes, tardaría alrededor de 16 seg. Así pues, podemos obtener de forma aproximada valores del tiempo de adaptación del algoritmo de predistorsión 5.5. Conclusiones El objetivo principal de este proyecto ha consistido en la implementación en DSP de un predistorsionador digital adaptativo. Se ha desarrollado un predistorsionador digital capaz de identificar un modelo de predistorsión sensible de ser implementado en una FPGA (mediante LUTs), permitiendo la linealización de un amplifiador de potencia en tiempo real. Para ello, se han creado las funciones necesarias para disponer de un predistorsionador digital basado en un modelo de Hammerstein en el entorno de desarrollo del DSP C6711. Por otro lado, se ha comprobado satisfactoriamente su correcto funcionamiento, proporcionando resultados que muestran la compensación de la distorsión introducida por el amplificador de potencia, tanto dentro como fuera de banda. Así pues, cabe concluir que se han cumplido los objetivos inicialmente propuestos. Se ha considerado que el impacto medioambiental del proyecto es mínimo, ya que está orientado a la obtención de máxima eficiencia energética de dispositivos de alto consumo energético, por lo que no se ha hecho un estudio más exhaustivo del mismo. REFERENCIAS 55 REFERENCIAS Amplificadores de potencia [1] RF & Microwave Theory – RF, RFIC, Microwave Systems, “RF, RFIC & Microwave Theory. Design”. Descargado de http://www.odyseus.nildram.co.uk/Systems_And_Devices_Files/Linearity.pdf [2] National Instruments, “Understanding RF & Microwave Specifications – Part 2”. NI Developer Zone. Descargado de http://zone.ni.com/devzone/conceptd.nsf/webmain/1D613007427ED789862570 BD00784114#4 [3] Kettering, “Power Amplifiers“. Kettering University, United States. Mayo de 2002. Descargado de http://www.kettering.edu/~bguru/Pamp/PA-01.pdf [4] Maury Microwave Corporation, “Theory of intermodulation distortion measurement (IMD)”. Julio de 1999. Descargado de http://www.maurymw.com/support/pdfs/5C-043.pdf [5] Frederick H. Raab, “RF and Microwave Power Amplifier and Transmitter Technologies – Part 2”. High Frequency Electronics, 2003 Summit Technical Media, LLC. Parte del documento “Power Amplifiers and Transmitters for RF and Microwave” aparecido en el 50 aniversario de IEEE Transactions on Microwave Theory and Techniques, Marzo de 2002. Descargado de www.highfrequencyelectronics.com/Archives/Jul03/HFE0703_RaabPart2.pdf [6] Michael D. McKinley, “EVM Calculation for broadband modulated signals”. 64th ARFTG Conf. Dig., Orlando, FL, páginas 45-52, Diciembre de 2004. NIST Boulder Laboratories, National Institute of Standards and Technology, United States. Descargado de http://www.boulder.nist.gov/div818/81801/MetrologyForWirelessSys/pubs/R1_A RFTG64_McKinley_com.pdf [7] Anritsu, “Adjacent Channel Power Ratio (ACPR)”. Application note. Febrero de 2001. Descargado de http://www.anritsu.co.jp/Products/pdf_e/PATS_ACPR.PDF [8] Parkervision, “ACPR: A description of RF System Linearity”. Descargado de http://www.parkervision.com/pdfs/ACPR_RF_system_linearity.pdf [9] TNCS, “RF Equipment Guideline”. Communications Engineering Department. TCNS, Shin Satellite Public Company Limited. Descargado de http://tcns.thaicom.net/RF/RF.asp#hhh Técnicas de linealización 56 Implementación en DSP de un predistorsionador digital [10] Zozaya A. “Aportación a la Linealización de Amplificadores de Potencia Mediante la Teoría de la Hiperestabilidad”. Ph.D. Thesis. Department of Signal Theory and Communications .Universitat Politècnica de Catalunya. Barcelona, España, Junio de 2002. [11] Pere Ll. Gilabert, “Contribution on Digital Predistortion for Power Amplifier Linearization and Channel Equalization”. PhD Thesis Proposal. Universitat Politècnica de Catalunya, Barcelona, España. 2006 Predistorsión digital [12] Pere L. Gilabert, G. Montoro, E. Bertran, “A methodology to model and predistort short-term memory non linearities in power amplifiers”. Universitat Politècnica de Catalunya, Barcelona, España. 2006 [13] Pere L. Gilabert, E. Bertran, G. Montoro, “Multiple lookup table predistortion for adaptive modulation”. Universitat Politècnica de Catalunya, Barcelona, España. 2005 [14] Pere L. Gilabert, G. Montoro, E. Bertran, “On the Wiener and Hammerstein models for power amplifier predistortion”. Universitat Politècnica de Catalunya, Barcelona, España. 2005 [15] Pere L. Gilabert, G. Montoro, “Predistorsión digital y adaptativa de amplificadores de RF con modelos de Hammerstein”. Universitat Politècnica de Catalunya, Barcelona, España. 2005 [16] P. Jardin, G. Baudoin, “Filter Look-up table method for power amplifiers linearization”. ESYCOM Communication Systems Laboratory, Noisy le Grand Cedex, France. Octubre de 2003. Descargado de http://www.esiee.fr/~baudoing/pdf/FLUT_rev.pdf [17] Roman Marsalek, “Contributions to the power amplifier linearization using digital baseband adaptive predistortion”. Université de Marne la Vallee, France. Diciembre de 2003. Descargado de www.univ-mlv.fr/recherche/WebTheses/UMLV-2004-000152.pdf [18] NCTU, “Least-mean-square algorithm (LMS algorithm)”. Descargado de http://cwww.ee.nctu.edu.tw/course/asp/asp04.pdf Procesador C6711 [19] Texas Instruments, “TMS320C6000 CPU and Instruction Set Reference Guide”. Ref: SPRU189f. Octubre de 2000 [20] Texas Instruments, “TMS320C6000 Programmer’s Guide”. Ref: SPRU198g. Marzo de 2006. Descargado de http://focus.ti.com/lit/ug/spru198i/spru198i.pdf REFERENCIAS 57 [21] Texas Instruments, “TMS320C67x DSP Library Programmer’s Reference”. Ref: SPRU657B. Marzo de 2006. Descargado de http://focus.ti.com/lit/ug/spru657b/spru657b.pdf [22] Texas Instruments, “TMS320C67x DSP Library”. Descargado de http://focus.ti.com/docs/toolsw/folders/print/sprc121.html [23] Texas Instruments, “TMS32067x FastRTS Library. Programmer’s reference”. Ref: SPRU100a. Octubre de 2002. Descargado de http://focus.ti.com/lit/ug/spru100a/spru100a.pdf [24] Texas Instruments, “TMS320C67x Fast RTS Library”. Descargado de http://focus.ti.com/docs/toolsw/folders/print/sprc060.html [25] Texas Instruments, “TMS320C6000 Peripherals Reference Guide”. Ref: SPRU190j. Abril de 2006. Descargado de http://focus.ti.com/dsp/docs/dspsupporttechdocsc.tsp?sectionId=3&tabId=409& abstractName=spru190j [26] Texas Instruments, “TMS320C6000 DSP Interrupt Selector Reference Guide”. Ref: SPRU646a. Enero de 2004. Descargado de http://focus.ti.com/dsp/docs/dspsupporttechdocsc.tsp?sectionId=3&tabId=409& abstractName=spru646a [27] Tomas McKelvey, “Texas Instruments DSP Starter Kit 6711DSK. A brief introduction”. 2003. Descargado de www.s2.chalmers.se/undergraduate/courses0304/ess145/lab2/ti6711dsk.pdf Software Code Composer Studio [28] Texas Instruments, “Code Composer Studio IDE Getting Started Guide”. Ref: SPRU509G. Mayo de 2005. Descargado de http://focus.ti.com/docs/apps/catalog/resources/appnoteabstract.jhtml?abstract Name=spru509g [29] Texas Instruments, “Code Composer Studio IDE v3 White Paper”. Ref: SPRAA08. Julio de 2004. Descargado de http://focus.ti.com/lit/an/spraa08/spraa08.pdf [30] Texas Instruments, “TMS320C6000 Instruction Set Simulator. Technical Reference”. Ref: SPRU600G. Agosto de 2005. Descargado de http://focus.ti.com/docs/apps/catalog/resources/appnoteabstract.jhtml?abstract Name=spru600g Matlab 58 Implementación en DSP de un predistorsionador digital [31] M.A. Hosany, “The MATLAB Communication Toolbox”. University of Mauritius. Mayo de 2005. Descargado de http://www.uom.ac.mu/Faculties/foe/EE/Practical_Training_2005/MATLABPart1 .pdf Modulación y demodulación [32] Ken Gentile, “The care and feeding of digital, pulse shaping filters”. Publicado por RF Design en Abril de 2002. Descargado de http://images.industryclick.com/files/4/0402Gentile50.pdf [33] Thomas Fryza, Stanislav Hanus, “Hardware implementation of OFDM modulator and demodulator using TMS320C6711DSK board”. Brno University of Technology, Czech Republic. Descargado de http://ns.snd.edu.gr/wseas/wetsi/crete2004/papers/476-241.pdf [34] Louis Litwin, “Matched filtering and timing recovery in digital receivers”. Publicado en RF Design en Septiembre de 2001. Descargado de http://rfdesign.com/images/archive/0901Litwin32.pdf [35] Guoliang Zeng, “A new implementation of root raised cosine filter with Motorola’s DSP56K”. TechOnLine - Educational Resources for Electronics Engineers, Arizona State University East, United States. Descargado de http://www.techonline.com/pdf/pavillions/gspx/2004/1183.pdf Varios [36] Wikipedia, “Diagramas de flujo”. Descargado de http://es.wikipedia.org/wiki/Diagrama_de_flujo [37] Mis-algoritmos, “Aprenda a crear diagramas de flujo”. Descargado de http://www.mis-algoritmos.com/2006/08/08/aprenda-a-crear-diagramas-de-flujo/ ENTORNO DE DESARROLLO C6711 59 ANEXO 1. ENTORNO DE DESARROLLO C6711 A1.1. Introducción Como primer paso a la implementación de la predistorsión digital en DSP y FPGA, se han codificado los algoritmos necesarios en el procesador DSP en modo simulador teniendo en cuenta el entorno de hardware en aspectos como el mapeo de memoria. En este Anexo se presenta brevemente las características de la tarjeta de desarrollo C6711 DSK y más en detalle, el procesador DSP C6711 en el que se basa. Posteriormente, se muestra el software de desarrollo Code Composer Studio v3.1 de Texas Instruments con todas las prestaciones utilizadas en la simulación. A1.2. C6711 DSK Starter Kit El entorno de desarrollo de hardware es una tarjeta C6711 DSK Starter Kit de Texas Instruments equipada con una subtarjeta para adquisición de señales de banda ancha AED-101 de Signalware Corporation. Esta tarjeta incorpora el procesador DSP del mismo nombre TMS320C6711 que opera a 150 MHz y proporciona 1200 MIPS (Million Instruction Per Second) y 600 MFLOPS (Million Floating-point Operations Per Second). La figura A1.1 muestra la tarjeta C6711 DSK (ver [33]). Fig. A1.1 Tarjeta C6711 DSK 60 Implementación en DSP de un predistorsionador digital El kit incluye: • Procesador DSP TMS320C6711 • Memoria externa SDRAM de 16 MB y flash externa de 128 KB: memoria adicional para código • TLC320AD535: conversores ADC y DAC de 16 bits que proporcionan un canal de entrada y salida muestreado a 8 KHz • Dispositivo power management TPS56100 • Controlador JTAG: facilita la emulación y depuración del código • Interface para subtarjetas de expansión • Entradas y salidas digitales • Puerto paralelo para conexión con un PC: la comunicación se establece a través del software Code Composer Studio de Texas Instruments A1.2.1. DSP TMS320C6711 A1.2.1.1. Descripción Los procesadores TMS320C67X incluyen diferentes versiones, C6711, C6711B, C6711C y C6711D, que han ido incorporando algunas mejoras. Actualmente, el procesador C6711 ha sido sustituido por el C6713 y el kit de desarrollo por el C6713 DSK. La tarjeta C6711 DSK está basada en el primer procesador de la gama, el TMS320C6711. Tiene 32 registros de propósito general de 32 bits de longitud y 8 unidades funcionales independientes. Estas unidades funcionales proporcionan 4 ALUs de punto fijo / flotante, 2 ALUs de punto fijo y 2 multiplicadores de punto fijo / flotante. Es posible realizar un total de 300 MMACS (Million of Multiply Accumulates). Utiliza una arquitectura basada en dos niveles de memoria caché. El nivel 1 de la memoria de programa cache L1P es una memoria de 32-Kbit mapeada directamente y el nivel 1 de la memoria de datos cache L1D es una memoria asociativa de 32-Kbit. El nivel 2 de la memoria/cache L2 consiste en un espacio de 512-Kbit de memoria compartido para datos y programa. Puede configurarse como memoria mapeada, cache o combinaciones de ambas. El conjunto de periféricos disponibles en la DSP incluye dos puertos serie multicanal (McBSPs), dos timers de propósito general (Timer 0 y Timer 1), un interface HPI (Host-Port Interface), un interface de memoria externa (EMIF) que puede hacer de interface con memorias SDRAM, SBSRAM y periféricos asíncronos. La figura A1.2 muestra el diagrama funcional del procesador DSP C6711. ENTORNO DE DESARROLLO C6711 61 Fig. A1.2 Diagrama funcional de la DSP C6711 La CPU gestiona palabras de 256 bits VLIW (Very-Long Instruction Words) que proporcionan instrucciones de 32 bits a las 8 unidades funcionales en cada ciclo de reloj. El primer bit de cada instrucción de 32 bits determina si la siguiente instrucción pertenece al mismo paquete de ejecución que la instrucción anterior o si por el contrario, debe ser ejecutada en el siguiente ciclo de reloj como parte de la siguiente instrucción. Los paquetes de ‘fetch’ son siempre de 256 bits de longitud y los paquetes de ejecución pueden variar de tamaño. La longitud variable permite un ahorro de memoria y es una característica diferenciadora de esta DSP frente a otras arquitecturas VLIW. La CPU contiene dos conjuntos de unidades funcionales. Cada conjunto contiene 4 unidades y un banco de registros. Las unidades son .L1, .S1, .M1 y D1 para el primer conjunto, y .D2, .M2, .S2 y .L2 para el segundo conjunto. Los dos bancos de registro contienen cada uno 16 registros de 32 bits para un total de 32 registros de propósito general. Los dos conjuntos de unidades funcionales componen los lados A, con los registros de A 0 a A 15 , y B con los registros de B 0 a B 15 . Las cuatro unidades funcionales de cada lado pueden compartir libremente los 16 registros de su lado. Adicionalmente, cada lado tiene un único bus de datos conectado de manera que es posible acceder al banco de registros del otro lado. Las unidades .D1 y .D2 permiten la transferencia de datos entre la memoria y el banco de registros. La CPU soporta diferentes modos de direccionamiento 68 Implementación en DSP de un predistorsionador digital Fig. A1.4 Pantalla de configuración de Code Composer La figura A1.5 muestra las propiedades del dispositivo seleccionado. Fig. A1.5 Propiedades de hardware seleccionado ENTORNO DE DESARROLLO C6711 69 A1.3.2. Mapa de memoria El compilador de los procesadores de la familia C6000 crea diferentes zonas para alojar los bloques de código y de datos que se denominan secciones. Las secciones se definen en el archivo link.cmd y cada una de ellas se asigna a una zona de memoria (memoria interna, memoria externa, ...). Las secciones definidas son: • .cinit: contiene tablas para inicializar variables y constantes • .const: constantes de tipo floating-point, strings literales y en general aquellos datos definidos en C como de tipo const • .text: contiene el código ejecutable • .bss: espacio para variables globales y estáticas • .far: espacio también para variables globales y estáticas declaradas como de tipo far • .stack: pila del sistema utilizada para pasar argumentos a las funciones y alojar las variables locales de las funciones. Por defecto, su valor es de 400 en hexadecimal que son 1024 bytes • .sysmem: zona de memoria para asignación dinámica. Es el espacio que utilizan las funciones C de tipo malloc (), calloc ()., realloc (), ... A1.3.3. Creación de un proyecto Una vez seleccionado el dispositivo ya se puede lanzar Code Composer Studio. Para crear un nuevo proyecto (.pjt), se accede a la opción “Project, New” donde se especifica el nombre del proyecto y el directorio donde se guardarán los archivos asociados (por defecto, el sistema propone el mismo nombre de directorio que el propio proyecto). Para abrir un proyecto existente, se accede a “Project, Open”. A1.3.3.1. Añadir archivos al proyecto Si se trata de un nuevo proyecto, es necesario añadir los archivos asociados al proyecto. Por defecto, a la izquierda de la aplicación aparecen las opciones: Dependent project, Documents, DSP/BIOS Config, Generated Files, Include, Libraries y Source. Situándonos en cualquiera de ellas, con el botón derecho está accesible la opción “Add Files to Project”. Se añadirán los archivos siguientes: • Archivos fuente o source: todos los módulos .c necesarios para la ejecución del proyecto • Archivo linker link.cmd: aparece directamente debajo del proyecto, en él se detalla el mapa de memoria del dispositivo seleccionado. En los 70 Implementación en DSP de un predistorsionador digital proyectos con el dispositivo simulador se han especificado zonas también disponibles en el dispositivo hardware C6711 DSK: o Memoria interna cache L2 de 64Kbytes: con inicio en la dirección hexadecimal 0x0 y longitud 0x00010000 (65536 o 64 Kbytes) o Memoria externa SDRAM de 16MB: configurada en la primera zona de interface a memoria externa EMIF de 128 MB, con inicio en la dirección hexadecimal 0x80000000 y longitud 0x01000000 (16 MB) • Archivo vectors.asm: proporcionado por el fabricante, describe el proceso de reset • Archivos de librerías: los archivos .lib que incluyen las funciones de sistema que se utilizan • Archivos de cabecera o include: los archivos .h con las cabeceras de las funciones de los archivos fuente .c La figura A1.6 muestra el proceso para añadir un archivo. Fig. A1.6 Añadir archivos a un proyecto Los archivos anteriores se añaden manualmente excepto los de cabecera. En los archivos fuente .c se incluye un fichero de cabecera genérico: ENTORNO DE DESARROLLO C6711 71 #include “defs.h” que a su vez incluye a todos los ficheros cabecera .h necesarios. Por ejemplo: #ifndef _DEFS_H #include <stdio.h> #include <stdlib.h> #include <string.h> #include <math.h> #include <fastmath67x.h> #include <DSPF_sp_maxval.h> #include "type.h" #include "ham.h" #include "complex.h" #include "LUT.h" #endif De esta forma, con el botón derecho sobre el nombre del proyecto, si se selecciona la opción “Scan All File Dependencies” como muestra la figura A1.7, nos aparecen todos los archivos cabecera relacionados. Fig. A1.7 Búsqueda de dependencias 72 Implementación en DSP de un predistorsionador digital A1.3.3.2. Ejecución de un proyecto El siguiente paso es compilar cada módulo con la opción “Project, Compile File” o el botón . A continuación, la opción “Project, Build” o “Project, Rebuild All” o el botón permiten crear el archivo ejecutable nombre_proyecto.out. en el directorio nombre_proyecto\Debug. Este archivo es el que se pasa al hardware en una configuración con DSK o al simulador, donde se ejecuta. Por defecto, es necesario después de ejecutar “Build”, cargar el fichero con la opción “File, Load Program” o “File, Reload Program”. Alternativamente, puede configurarse la aplicación Code Composer para que se cargue automáticamente tras un Build. La figura A1.8 muestra la pantalla de configuración a la que se accede con “Option, Customize”. La casilla “Load Program After Build” debe estar validada. Fig. A1.8 Pantalla de la opción Customize, pestaña “Program/Project Load” Se recomienda también, por comodidad, que las casillas “Auto-save Projects Before Build” y “Open Project Windows On Startup” estén validadas. Por último, se inicia la ejecución del programa con la secuencia del menú: • Debug, Reset CPU • Debug, Restart • Debug, Go Main: se inicia la ejecución situando el contador de programa en la función main(). Se simboliza con una flecha amarilla ENTORNO DE DESARROLLO C6711 73 Para verificar el funcionamiento del programa, es posible utilizar herramientas habituales en programación como: • Visualización de variables: opción “View, Watch Window” o “View, Quick Watch”. En la figura A1.9 se muestra en el extremo inferior derecho de la imagen • Visualización de funciones, etiquetas, tipos, archivos, ... En la figura A1.9 se muestra en la parte inferior central • Salida estándar de consola: se muestran las variables indicadas en funciones printf () • Ejecución paso a paso: opción “Debug, Step Into” o el botón , “Debug, Step Over” o el botón y “Debug, Step Out” o el botón • Puntos de parada o breakpoints: opción “Debug, Breakpoints...” o el botón • Probe points: puntos en los que se para la ejecución del programa para leer/escribir datos en archivos con un formato determinado. Está disponible con la opción “Debug, Probe Points...” o el botón La figura A1.9 resume el funcionamiento de estas herramientas. Fig. A1.9 Pantalla de Code Composer durante la ejecución paso a paso de un proyecto 74 Implementación en DSP de un predistorsionador digital A1.3.3.3. Obtención de resultados gráficos En el software Code Composer es posible visualizar gráficamente los resultados guardados en posiciones de memoria. Hay diferentes tipos de como gráficos tiempo/frecuencia, constelaciones, diagramas de ojo,... Para utilizar esta opción es necesario acceder a “View, Graph, Time/Frequency – Constellation – Eye Diagram – Image”. En la ventana de configuración se introducen los datos necesarios como: • Tipo de gráfica • Título de la gráfica • Dirección de inicio: puede ponerse la dirección de memoria asociada a la variable a visualizar o directamente el nombre de la variable • Tamaño del buffer de adquisición • Número de muestras a visualizar: suele coincidir con el anterior • Tipo de datos: entero, punto flotante, ... • Varios: estilo de la rejilla, cursor, ejes, mostrar unidades,... La figura A1.10 muestra un ejemplo de gráfica. Fig. A1.10 Pantalla de Code Composer con la configuración de una gráfica de tipo tiempo/frecuencia con una señal senoidal A1.3.4. Librerías Por defecto, las librerías se encuentran en el directorio de instalación, subdirectorio \C6000\Cgtools\Lib. Para algunos proyectos ha sido necesario utilizar otras librerías que pueden obtenerse en la web de Texas Instruments. En particular se han instalado las librerías siguientes: ENTORNO DE DESARROLLO C6711 75 • TMS320C67x DSP Library: contiene la librería DSP67x.lib. Para más información ver [21] y [22] • TMS320C67x Fast RTS Library: contiene la librería fastmath67x.lib. Para más información ver [23] y [24] Si se instalan en directorios diferentes, es necesario tener en cuenta el nuevo directorio en las opciones de creación del fichero ejecutable. Para ello, se accede a la opción “Project, Build Options” y la pestaña Compiler donde se indica. La figura A1.11 muestra un ejemplo del directorio \C6700 en el que se ha instalado la librería DSP67xx.lib. Opcionalmente, las librerías utilizadas pueden copiarse en cada directorio de proyecto de manera que están accesibles por defecto. Fig. A1.11 Pantalla de configuración de opciones del compilador A1.3.5. Medida del número de ciclos Para determinar el número de ciclos de una instrucción o un programa pueden utilizarse básicamente dos opciones: 76 Implementación en DSP de un predistorsionador digital A1.3.5.1. Contador de ciclos Con la opción de menú “Profile, Clock, Enable” y luego “Profile, Clock, View” se activa el contador de ciclos. Aparece con el símbolo en la barra inferior de la aplicación Code Composer. A lado del símbolo del reloj, se sitúa el contador de ciclos. Para ponerlo a cero basta con hacer doble clic sobre el reloj. A1.3.5.2. Función clock Con la función clock() de CCS insertada antes y después de la función a evaluar puede visualizarse el número de ciclos. El código es el indicado a continuación. /* Se calcula la cabecera de la función */ start = clock(); stop = clock(); overhead = stop – start; /* Se calculan los ciclos de la/s funciones a evaluar */ start = clock(); function1(); function2(); … functionN(); stop = clock(); cycle = stop – start – overhead; Para que las variables se actualicen, es necesario haber activado el reloj con la opción “Profile, Clock, Enable” como indicado en el punto anterior. IMPLEMENTACIÓN DE PREDISTORSIÓN EN EL ENTORNO C6711 77 ANEXO 2. IMPLEMENTACIÓN DE PREDISTORSIÓN EN EL ENTORNO C6711 A2.1. Formato de datos en Code Composer Los formatos que el software Code Composer puede leer y escribir son: • COFF (Common Object File format): los datos están en binario y se permite guardar grandes bloques de datos de forma compacta • Específico de Code Composer: los datos están en texto y es necesaria una cabecera de información que describe el formato utilizado (hexadecimal, long, int, float) Si como cabecera se usan unos valores por defecto 1651 1 0 0 0, ya no es necesario especificar para cada tipo de datos una cabecera específica: En el proyecto se ha utilizado el formato de datos hexadecimal. Partiendo del fichero original en formato Matlab (.mat), los datos se han separado con la ayuda de Matlab en diferentes archivos que corresponden a las partes real e imaginaria de las muestras de entrada y salida del amplificador. Cada muestra está en una línea separada por retorno de carro. En la tabla A2.1 se listan los ficheros correspondientes a cada señal utilizados en la aplicación. Tabla. A2.1 Archivos con las muestras del modelo Archivo Contenido re_in_ampl.txt Parte real de las muestras de entrada del amplifcador im_in_ampl.txt Parte imaginaria de las muestras de entrada del amplifcador re_out_ampl.txt Parte real de las muestras de salida del amplifcador im_out_ampl.txt Parte imaginaria de las muestras de entrada del amplifcador A2.1.1. Utilidad de conversión de datos La utilidad “d2f.exe” permite leer los datos de los archivos de texto de la tabla A2.1 en formato “le”, es decir, floating-point en notación científica. A continuación, se muestra un ejemplo de uno de los archivos. -1.1548163e-002 -1.1041562e-002 -1.2250310e-002 -1.0941616e-002 84 Implementación en DSP de un predistorsionador digital T k kxkxkxkxkxkxkxkxkx kxkxkxkxkxkxkxkxkx kxkxkxkxkxkxkxkxkx kxkxkxkxkxkxkxkxkxkxkxkxkx q                 −⋅−−⋅−−−−⋅−− −⋅−−⋅−−−−⋅−− −⋅−−⋅−−−−⋅−− ⋅⋅⋅⋅⋅⋅ = 732 732 732 76532 )7()7(...,)7()7(,)7()7(,)7()7(),.7( ,)5()5(,...,)5()5(,)5()5(,)5()5(),5( ,)3()3(...,)3()3(,)3()3(,)3()3(),3( ,)()(,)()(,)()(,...,)()(,)()(,)()(),( (A2.1) La figura A2.4 muestra el diagrama de flujo de cálculo del vector vq. Fig. A2.4 Diagrama de flujo de la función que calcula el vector vq El algoritmo queda como sigue: • Bucle de cálculo del módulo de la muestra de entrada en función del vector de retardos vN para el vector de entrada vx desde n = 0 hasta N • Bucle de cálculo del producto de la muestra de entrada por el módulo elevado a p, siendo p desde 0 hasta P. Este bucle está contenido en el anterior y se implementa con un factor inicializado al principio a 1 y que después se va actualizando con el producto del módulo IMPLEMENTACIÓN DE PREDISTORSIÓN EN EL ENTORNO C6711 85 • Por último, si D es mayor que 0, se realiza el desplazamiento de las muestras de salida que completan el vector vq en función del vector de retardos de salida vD A2.4.2. Desplazamiento de muestras La función de desplazamiento de muestras es necesaria para ir desplazando las muestras de los vectores vx, vy1, vy2, vd, vxPRE, vyPRE1, vyPRE2, vy en cada iteración. La muestra actual estará siempre situada en la posición 0 y en las siguientes se encontrarán las muestras n-1, n-2, n-3, n-N como muestra el esquema de la figura A2.5. Fig. A2.5 Esquema de un vector de muestras La función simplemente desplaza la muestra i a la posición i+1 desde la primera muestra a la última del vector. Por otro lado, para acceder a las muestras de estos vectores según los retardos correspondientes (τ - 1), …, (τ - N), bastará con especificar como índice la posición del vector de retardos. Por ejemplo, si vN= {0, 3, 5, 6} donde N = 6, la longitud del vector de muestras vx será de 7 elementos y contendrá las muestras 0, -1, -2, …, -6. Para acceder a la muestra del primer retardo será suficiente con buscar el elemento vx[vN(1)], es decir, vx[3]. A2.4.3. Cálculo del filtro FIR con buffer lineal La ecuación A2.2 muestra la forma de un filtro FIR: ( ) [ ] [ ] [ ] ∑∑ − = − = −⋅=−⋅= 1 0 1 0 N k N k k knzkhknxany (A2.2) 86 Implementación en DSP de un predistorsionador digital La figura A2.6 muestra el diagrama de flujo de la función que calcula el filtro FIR. Fig. A2.6 Diagrama de flujo de la función de cálculo FIR El proceso es: • Inicialización de variable del resultado a 0 • Bucle mientras el número de elementos será mayor que 0: se decrementa el contador y se incrementan los punteros al elemento siguiente en los dos vectores. La función se ha implementado pensando en los productos entre los vectores vc y vq según la ecuación 3.4. Dentro del bucle las operaciones son: o Cálculo del complejo conjugado del vector vc o Suma acumulada del producto entre vc conjugado y vq A2.4.4. Cálculo del filtro FIR con buffer circular Se ha implementado el filtro FIR con buffer circular en el módulo fir.c. Los buffers circulares están más optimizados en el entorno DSP. La figura A2.7 muestra el diagrama de flujo de la implementación de filtro FIR con buffer circular, en este caso con muestras reales. IMPLEMENTACIÓN DE PREDISTORSIÓN EN EL ENTORNO C6711 87 Fig. A2.7 Diagrama de flujo de FIR con buffer circular Se utiliza una estructura llamada FIR que contiene las muestras de entrada, el número de elementos del filtro, el vector de coeficientes del filtro h, el vector de retardos z y el estado utilizado para el buffer circular e inicializado a 0 al principio. El módulo contiene además una función de inicialización de la estructura FIR. A2.5. Funciones de Fast-Kalman A2.5.1. Vectores vh y vc El diagrama de flujo de la figura A2.8 describe la implementación del cálculo de los vectores vc y vh. 88 Implementación en DSP de un predistorsionador digital Fig. A2.8 Diagrama de flujo de la función que calcula los vectores vh y vc El proceso descrito es el siguiente: • Cálculo del error entre la muestra deseada y la estimada: por ejemplo, si se está determinando el vector vc del amplificador, la muestra deseada es la de salida real del amplificador y la estimada la que se va calculando con los vectores vc y vq • Obtención del vector h k (vh) según la ecuación A2.2 (anterior 3.22 que se repite para mayor facilidad. Mk k H k k k k Qqq q h + = − − 1 _ 1 _ λ λ (A2.2) o Cálculo del producto de la matriz λ y el vector vq IMPLEMENTACIÓN DE PREDISTORSIÓN EN EL ENTORNO C6711 89 o Cálculo parcial del denominador: es el producto del vector vq hermítico por un factor idéntico al numerador anterior o Cálculo completo del denominador: al resultado parcial del denominador se suma el valor Q M o Cálculo del inverso del denominador o Cálculo del producto del numerador por el inverso del denominador, es decir, se obtiene ya el vector vh • Obtención del vector c k+1 según la ecuación A2.3 (anterior 3.21). * 1 )(kehcc kkk ⋅+= + (A2.3) o Cálculo del complejo conjugado del error entre la muestra deseada y la estimada o Cálculo del producto del vector vh y el error conjugado o Cálculo de la suma del producto anterior y el vector vc de la iteración anterior para obtener el nuevo vector vc actualizado A2.5.2. Actualización de la matriz λ El diagrama de flujo de la figura A2.9 describe la implementación de la actualización de la matriz λ según la ecuación 3.23. El proceso descrito es como sigue: • Obtención de λ k según la ecuación A2.4 (anterior 3.23) p k H kk kk Qqh _ 1 _ 1 __ +−= −− λλλ (A2.4) o Cálculo del producto del vector vh y el vector vq hermítico, éste último se obtuvo en la función de cálculo de los vectores vh, vc o Cálculo del producto anterior por la matriz λ de la iteración anterior o Cálculo del negativo del resultado anterior o Cálculo de la suma de la matriz λ de la iteración anterior y el resultado negativo anterior o Cálculo de la suma del resultado anterior y la matriz Q p . Finalmente, el resultado es la matriz λ actualizada 90 Implementación en DSP de un predistorsionador digital Fig. A2.9 Diagrama de flujo de la función que actualiza λ A2.6. Funciones LMS A2.6.1. Descripción del proyecto El proyecto “LMS.pjt” implementa el algoritmo LMS de forma genérica sin entrar en las consideraciones que aplican para los modelos de Hammerstein y Wiener, es decir, no tiene en cuenta la cota máxima de la ecuación 3.21. Sin embargo, ha permitido comprender mejor el funcionamiento de los algoritmos adaptativos que posteriormente ha sido útil para Fast-Kalman. La selección de uno u otro algoritmo adaptativo se ha basado en estudios previos (ver [14] y [15]) en los que se demuestra que el algoritmo Fast-Kalman converge más rápido. A2.6.1.1. Función de Code Composer El software Code Composer dispone de una función que calcula el algoritmo LMS. Está incluida en la librería dsp67x.h y precisa añadir el archivo de cabecera DSPF_sp_lms.h. Recibe los parámetros siguientes: • Muestras de entrada • Puntero al vector de coeficientes IMPLEMENTACIÓN DE PREDISTORSIÓN EN EL ENTORNO C6711 91 • Puntero al vector de muestras de salida deseadas • Puntero al vector de muestras de salida filtradas • Tasa de adaptación o µ • Error inicial • Número de coeficientes • Número de muestras de salida A2.6.1.2. Módulo lms El módulo lms.c incluye las funciones siguientes: • Inicialización de LMS: se inicializan los vectores de retardos y coeficientes además del parámetro sigma • Algoritmo LMS: el diagrama de flujo de las figuras A2.4 y A2.5 describe el proceso La ecuación A2.5 muestra la señal de salida w(n). ( ) ( ) ( ) nadaptxncoefnw T _⋅= (A2.5) El error queda definido como en la ecuación A2.6. ( ) ( ) ( ) nwndne −= (A2.6) Siendo d(n) la señal deseada. La ecuación que estima la actualización adaptativa de los coeficientes es la A2.7. ( ) ( ) ( ) nadaptx e ncoefncoef _1 ⋅ ⋅ +=+ σ µ (A2.7) El parámetro σ se actualiza según la ecuación A2.8. [ ] ( ) σαασ ⋅−+⋅= 10_ 2 adaptx (A2.8) Las figuras A2.10 y A2.11 muestran el diagrama de flujo de la implementación del algoritmo LMS con muestras complejas. 92 Implementación en DSP de un predistorsionador digital Fig. A2.10 Diagrama de flujo del algoritmo LMS (parte 1) Fig. A2.11 Diagrama de flujo del algoritmo LMS (parte 2) A2.7. Implementación de LUT A2.7.1. Cálculo de LUT La figura A2.12 muestra el diagrama de flujo de cálculo del vector LUT, que contiene los valores de las N tablas LUT. El proceso es el que se describe a continuación: IMPLEMENTACIÓN DE PREDISTORSIÓN EN EL ENTORNO C6711 93 • Bucle que permite evaluar la función genérica de la ecuación 3.26 desde 0 hasta N • Bucle que calcula el vector de LUT para cada valor de N del bucle anterior: o Cálculo del módulo de la muestra de entrada a evaluar: desde 0 hasta 1 con 2 n elementos obtenidos como 0, 1/2 n , 2/2 n , 3/2 n , ..., 2 n /2 n = 1. El valor de n está definido en una constante del programa principal o main o Evaluación del polinomio de la ecuación 3.26 para cada valor del módulo anterior o El resultado se va guardando en un vector que tiene las dimensiones de (2 n +1) · (P+1) · (N+1) Fig. A2.12 Diagrama de flujo del cálculo del vector LUT A2.7.2. Cálculo de salida a partir de tabla LUT La figura A2.13 muestra el diagrama de flujo de cálculo del valor de salida y(k) a partir de las tablas LUT. 100 Implementación en DSP de un predistorsionador digital ( ) 0, 4 1 1=      +−= t T th s π α α (A2.4) ( ) αα π πα π π α 4 , 4 cos 2 1 4 sin 2 1 2 s s T t T th ±=                  −+             += (A2.5) Los parámetros que definen el comportamiento del filtro RRC son: • Número de muestras por símbolo: MUESTRAS_SIMBOLO (12) • Número de símbolos utilizados: SIMBOLOS (6) • Factor de roll-off: ALFA (0.35) De esta manera, la respuesta impulsional del filtro RRC implementado tiene MUESTRAS_SIMBOLO · SIMBOLOS muestras, es decir, 73. La respuesta es simétrica respecto al origen. La figura A2.17 muestra la respuesta impulsional obtenida con Matlab del filtro RRC generado. Fig. A2.17 Respuesta impulsional del filtro RRC La figura A2.18 muestra la secuencia de la figura A2.16 después de pasar por el filtro RRC de la figura A2.17. IMPLEMENTACIÓN DE PREDISTORSIÓN EN EL ENTORNO C6711 101 Fig. A2.18 Parte real de la señal después del filtro RRC La figura A2.19 muestra la parte imaginaria de la secuencia original después del filtro RRC. Fig. A2.19 Parte imaginaria de la señal después del filtro RRC A2.8.4.1. Módulo RRC Este módulo incluye las funciones siguientes: • Inicialización de filtro RRC: configura la estructura de tipo tRRC con el número de muestras, el factor de roll-off, el número de símbolos por muestra y la respuesta impulsional. Precisa de la función que genera el vector de respuesta impulsional • Generación del vector de respuesta impulsional: la función calcula un vector h(n) según las ecuaciones A2.3, A2.4 y A2.5 • Inicialización de buffer circular para convolución • Convolución: calcula la muestra de salida del filtro conformador mediante convolución 102 Implementación en DSP de un predistorsionador digital A2.8.5. Demodulación Al tratarse de una simulación en ordenador, se puede considerar que en la etapa de transmisión y recepción se trabaja idealmente con el mismo reloj. Aunque es una situación que no ocurre en los sistemas de comunicaciones reales, así no es necesaria la recuperación de sincronismo y de portadora en recepción. En [34] se exponen algunos métodos de recuperación de sincronismo y filtrado. En el proyecto, se ha aplicado un filtro RRC a las componentes en fase y cuadratura de las muestras de salida del amplificador sin predistorsión y con predistorsión. La figura A2.20 muestra la parte real de la señal de salida del amplificador de potencia habiendo utilizado predistorsión después de pasar por el filtro RRC. Fig. A2.20 Parte real de la señal de salida del PA con PD después de RRC La figura A2.21 muestra la parte real de la señal de salida del amplificador de potencia sin predistorsión después de pasar por el filtro RRC. Fig. A2.21 Parte real de la señal de salida del PA sin PD después de RRC IMPLEMENTACIÓN DE PREDISTORSIÓN EN EL ENTORNO C6711 103 A continuación, se han demodulado todas las muestras anteriores de salida del amplificador sin y con predistorsionador para obtener la parte real e imaginaria correspondientes a dichos símbolos sin haber realizado previamente el delmado necesario. Se ha hecho de esta forma por simplicidad ya que, las secuencias resultantes se importan desde Matlab donde es más sencillo realizar el delmado seleccionando una de cada 12 muestras (las correspondientes a las muestras por símbolo). El número de retardos introducidos por los filtros determina el instante de muestreo adecuado. En nuestro caso, se ha hecho a partir de la visualización de las primeras muestras de las secuencias de parte real e imaginaria. De esta manera, puede determinarse el instante donde las muestras se acercan más a las zonas de decisión de los símbolos de la modulación. 104 Implementación en DSP de un predistorsionador digital ANEXO 3. FUNCIONES EN MATLAB A3.1. Curva AM/AM Una de las herramientas que se ha utilizado para comprobar la bondad de la implementación ha sido la representación gráfica de la curva AM/AM. Para obtenerla basta con cargar las muestras de entrada y salida y a continuación ejecutar en Matlab la instrucción: plot (abs(x), abs(y); De esta manera se obtienen gráficas como la de la figura A3.1 que muestra la curva AM/AM para las primeras 5000 muestras del modelo. Fig. A3.1 Módulo de señal de entrada vs módulo señal de salida del amplificador de potencia del modelo A3.2. Curva AM/PM Otra figura de mérito es la curva AM/PM. Desde Matlab basta con ejecutar las sentencias siguientes para las señales que correspondan: phase1=angle(x); % señal de entrada phase2=angle(r); % señal de salida dphase = unwrap (phase2-phase1); % diferencia de fases plot (abs(x), dphase*180/pi, 'g.'); FUNCIONES EN MATLAB 105 La figura A3.2 muestra un ejemplo de esta gráfica. Fig. A3.2 Módulo de señal de entrada vs diferencia de fase entre la salida y la entrada A3.3. Gráficas de densidad espectral Desde Matlab es sencillo obtener las gráficas de la densidad espectral de potencia normalizada. Se han utilizado las sentencias siguientes: Hs=spectrum.welch; Hs.SegmentLength=samples; psd(Hs,r,'CenterDC',true); La función PSD calcula la densidad espectral de potencia según el objeto definido en Hs, en este caso, Welch. En el caso de señales complejas, la frecuencia w estaría definida entre 0 y 2π. El parámetro ‘CenterDC’ indica que el espectro se desplace para que la frecuencia 0 quede en el centro, es decir, entre – π y + π. Además, está normalizada por π. Luego, en la gráfica se muestra entre -1 y 1. En el ejemplo, la variable r indica las muestras sobre las que se calcula la densidad espectral. La figura A3.3 muestra un ejemplo de gráfica de densidad espectral para la señal de salida del PA sin predistorsión. 106 Implementación en DSP de un predistorsionador digital Fig. A3.3 Densidad espectral de potencia estimada por Welch de la salida del amplificador de potencia del modelo A3.4. Gráficas de constelaciones Para poder determinar los instantes adecuados de muestreo, se ha hecho una visualización previa de las señales de salida del amplificador de potencia y filtro RRC con y sin predistorsionador. Después se ha delmado la señal escogiendo una de cada 12 muestras. plot (real (yd_sim (1:200))); y1 = yd_sim (85:12:length (yd_sim)); scatterplot (y1, 1, 0, ‘.’); La función scatterplot permite obtener la gráfica de la constelación. A3.4.1. Cálculo de EVM Para calcular el parámetro EVM se ha partido de: • Muestras recibidas: las muestras de salida del amplificador de potencia y filtro RRC con (yd_sim) y sin predistorsionador (yPA_sim) • Muestras ideales: las muestras anteriores demoduladas en el software Code Composer, parte real e imaginaria obtenidas a partir de las zonas de decisión correspondientes a cada símbolo Las sentencias necesarias son: FUNCIONES EN MATLAB 107 % Para la señal de salida del PA sin predistorsionador y1=yPA_sim (85:12:length(yPA_sim)); yd1=dem_yPA (85:12:length(dem_yPA)); evm1= 100*sqrt (sum(abs(y1-yd1).^2)/length(y1)/max(abs(yd1)).^2); % Para la señal de salida del PA con predistorsionador y2=y_sim (85:12:length(y_sim)); yd2=dem_yd (85:12:length(dem_yd)); evm2= 100*sqrt (sum(abs(y2-yd2).^2)/length(y2)/max(abs(yd2)).^2); A3.5. Funciones para curvas AM/AM y densidad espectral A partir de las funciones descritas anteriormente, se han hecho unas funciones en Matlab que permiten obtener las gráficas a partir de los ficheros de texto que proporciona Code Composer. A3.5.1. Para el proyecto “Lineal.pjt” La función [yPRE, y]= plot_AM_Ps (r, u, G, samples) recibe como parámetros: • Variable u que se habrá cargado con el fichero de texto resultado con la función: u= load (‘ypre-y’); • Variable r: datos de salida del PA directamente del modelo para poder comparar las gráficas de densidad espectral • G: ganancia calculada en Code Composer para compensar la entrada del bloque PD+PA si fuera necesario • Samples: número de muestras consideradas en r, u La variable u tiene ‘samples’ filas y 8 columnas que se corresponden con: • Muestras de entrada del PA: parte real e imaginaria • Muestras normalizadas de entrada del PA: parte real e imaginaria • Muestras de salida del predistorsionador: parte real e imaginaria • Muestras de salida del bloque PD+PA: parte real e imaginaria El listado A3.1 muestra la función: function [yPRE, y]= plot_AM_Ps (r, u, G, samples) % poner en vectores las muestras de x x_re= u(1:samples); x_im= u(((samples*1)+1):(samples*2)); x= x_re+x_im*i; % poner en vectores las muestras de x normalizado xnorm_re= u(((samples*2)+1):(samples*3)); xnorm_im= u(((samples*3)+1):(samples*4)); xnorm= xnorm_re+xnorm_im*i; 108 Implementación en DSP de un predistorsionador digital % poner en vectores las muestras de yPRE yPRE_re= u(((samples*4)+1):(samples*5)); yPRE_im= u(((samples*5)+1):(samples*6)); yPRE= yPRE_re+yPRE_im*i; % poner en vectores las muestras de y y_re= u(((samples*6)+1):(samples*7)); y_im= u(((samples*7)+1):(samples*8)); y= y_re+y_im*i; % módulos de x, x normalizada modx= abs(x); modxn= abs(xnorm); % calcular máximo de x para normalizar y xmax= max(modx); rn= r/(xmax/G); % se tiene en cuenta factor de atenuación en Code Composer modrn= abs(rn); modr= abs(r); modypre= abs(yPRE); mody= abs(y); % plot de los módulos anteriores plot(modx, modr, 'g.'); % x-y original hold on; plot(modxn, modypre, 'r.'); % x-ypre plot(modxn, mody, 'b.'); % x-y % plot de power spectrum de salida figure; Hs=spectrum.welch; Hs.SegmentLength=samples; psd(Hs,r,'CenterDC',true); hold on; psd(Hs,y,'CenterDC',true); A3.5.2. Para el proyecto “Lineal-RRC_QAM.pjt” La función [yPRE, y]= plot_AM_Ps_RRC (u, samples) recibe los mismos parámetros que la función anterior excepto que la señal de salida del PA no es la real sino la calculada a partir de los coeficientes del modelo. Está pues incluida en la variable u (samples filas y 10 columnas) de la siguiente forma: • Muestras de entrada del PA: parte real e imaginaria • Muestras normalizadas de entrada del PA: parte real e imaginaria • Muestras de salida del predistorsionador: parte real e imaginaria • Muestras de salida del PA sin PD: parte real e imaginaria • Muestras de salida del bloque PD+PA: parte real e imaginaria La función incluye otra diferencia que consiste en desplazar las muestras al hacer las gráficas según el valor máximo de la función de correlación de las señales de entrada y de salida. El listado A3.2 muestra la función: FUNCIONES EN MATLAB 109 function [x, xn, yPRE, yPA, y]= plot_AM_Ps_RRC (u, samples) % poner en vectores las muestras de x x_re= u(1:samples); x_im= u(((samples*1)+1):(samples*2)); x= x_re+x_im*i; % poner en vectores las muestras del fichero x_norm xn_re=u(((samples*2)+1):(samples*3)); xn_im=u(((samples*3)+1):(samples*4)); xn=xn_re+xn_im*i; % poner en vectores las muestras del fichero y_PRE yPRE_re= u(((samples*4)+1):(samples*5)); yPRE_im= u(((samples*5)+1):(samples*6)); yPRE= yPRE_re+yPRE_im*i; % poner en vectores las muestras del fichero y y_re= u(((samples*6)+1):(samples*7)); y_im= u(((samples*7)+1):(samples*8)); y= y_re+y_im*i; % módulos de x, yPRE, y modx= abs(x); modxn= abs(xn); modypre= abs(yPRE); mody= abs(y); modyPA= abs(yPA); % desplazamiento de muestras según correlación x, y xco1= xcorr(modx,mody); [c1,c2]=max(xco1); % Generación de gráficas AM/AM plot (modxn(1:c2), modyPA((samples-c2+1):(samples)), 'g.'); % x-y sin PD, según el modelo hold on; plot(modxn(1:c2), modypre((samples-c2+1):(samples)),'r'); hold on; plot(modxn(1:c2), mody((samples-c2+1):(samples)), 'b.'); % x-y con PD % plot de power spectrum de salida figure; Hs=spectrum.welch; Hs.SegmentLength=samples; psd(Hs,yPA,'CenterDC',true); hold on; Hs=spectrum.welch; Hs.SegmentLength=samples; psd(Hs,y,'CenterDC',true); A3.5.3. Para el proyecto “LUT.pjt” La función [x, xnorm, yPRE, yPA, y]= plot_LUT (r, u, G, samples) es similar a las anteriores. La diferencia está en que u tiene ‘samples’ filas y 10 columnas que se corresponden con: • Muestras de entrada del PA: parte real e imaginaria 116 Implementación en DSP de un predistorsionador digital /* vector de retardos D para el PA */ static int vD_PA[] = {0}; /* vector de retardos N para el PD */ static int vN[] = {0, 1, 2, 3}; /* vector de retardos D para el PD */ static int vD[] = {0}; tComplex *vx, *vy1, *vy2, *vd; /* vectores de muestras */ tComplex *vxPRE, *vyPRE1, *vyPRE2, *vy; /* vectores de muestras */ /* muestras de entrada del modelo */ static tComplex x[X_LEN]; /* muestras de salida del modelo */ static tComplex y[Y_LEN]; /* módulo de muestras de entrada del modelo */ static SAMPLE x_mod[X_LEN]; /* módulo de muestras de salida del modelo */ static SAMPLE y_mod[Y_LEN]; /* vector de parte real señal entrada, obtenido de archivo .dat */ static SAMPLE x_re[X_LEN]; /* vector de parte imag señal entrada, obtenido de archivo .dat */ static SAMPLE x_im[X_LEN]; /* vector de parte real señal entrada, obtenido de archivo .dat */ static SAMPLE y_re[Y_LEN]; /* vector de parte imag señal entrada, obtenido de archivo .dat */ static SAMPLE y_im[Y_LEN]; static tComplex vq_PA[VQ_LEN]; /* vector qk de PA */ static tComplex vq[VQ_LEN]; /* vector qk de PD */ static tComplex vqh_PA[VQ_LEN]; /* vector qk de PA hermítico */ static tComplex vqh[VQ_LEN]; /* vector qk de PD hermítico */ static tComplex vc_PA[VC_LEN]; /* vector ck del PA */ static tComplex vc[VC_LEN]; /* vector ck del PD */ static tComplex vh_PA[VH_LEN]; /* vector hk de PA */ static tComplex vh[VH_LEN]; /* vector hk de PD*/ static tMatrix mQp; /* matriz Qp */ static tMatrix mLambdaPA; /* matriz Lambda de PA */ static tMatrix mLambda; /* matriz Lambda de PD */ tComplex Qm; /* valor Qm */ static void dataIO_xRe() { /*do data I/O --> parte real de la entrada del PA*/ return; } static void dataIO_xIm() { /*do data I/O --> parte imag de la entrada del PA*/ return; } static void dataIO_yRe() { /*do data I/O --> parte real de la entrada del PA*/ return; } static void dataIO_yIm() { /*do data I/O --> parte imag de la entrada del PA*/ return; } int main() { int v1; /* variable contador de memoria ocupada */ int i, j; /* contadores de bucles */ int start, stop, overhead, cycle1, cycle2; /* contadores de ciclos */ int vx_len, vy1_len, vy2_len, vd_len; /* tamaño de los vectores muestras para Hammerstein */ int vxp_len, vyp1_len, vyp2_len, vy_len; /* tamaño de los vectores muestras para Hammerstein */ LISTADO DE PROGRAMAS EN C 117 tComplex x_norm, y_norm; /* muestras de modelo normalizadas */ tComplex y_PRE; /* muestra de salida del PD */ tComplex xd; /* muestras de salida estimada Post-D */ tComplex yd; /* muestras de salida estimada PA */ tComplex value; /* valor de inicialización */ /* máximo de módulo de x y módulo de y*/ SAMPLE x_max, y_max; SAMPLE G; /* ganancia de bloque PD+PA */ extern int malloc_size; /* Inicializar vector entrada PA */ vx_len = vN_PA[N]+1; vx = xmalloc (sizeof(tComplex) * vx_len); fir_complex_init (vx, complex_zero (), vx_len); /* Inicializar vector de entrada del Post-D */ vy2_len = vN[N]+1; vy2 = xmalloc (sizeof(tComplex) * vy2_len); fir_complex_init (vy2, complex_zero (), vy2_len); /* Aplicar condición si D = 0 */ if (D == 0) { vy1_len = 1; vd_len = 1; } else { vy1_len = vD_PA[D-1]+1; vd_len = vD[D-1]+1; } /* Inicializar vector de salida PA */ vy1 = xmalloc (sizeof(tComplex) * vy1_len); fir_complex_init (vy1, complex_zero (), vy1_len); /* Inicializar vector de salida del Post-D */ vd = xmalloc (sizeof(tComplex) * vd_len); fir_complex_init (vd, complex_zero (), vd_len); /* Inicializar vector coeficientes c[] */ value.real= 1.0; value.imag= 0.0; fir_complex_init (vc, value, VC_LEN); fir_complex_init (vc_PA, value, VC_LEN); /* Inicializar vector h[] */ fir_complex_init (vh, complex_zero (), VH_LEN); fir_complex_init (vh_PA, complex_zero (), VH_LEN); /* Inicialización a 1 de Qm */ Qm.real= 1.0; Qm.imag= 0.0; /* Inicialización de la matriz mQp a 0 */ matrix_new (&mQp, QP_LEN, QP_LEN, NULL); value.real = 0; value.imag = 0; matrix_init_value (&mQp, value, 0, 0, 1); /* Inicialización de la diagonal de mQp a 1 */ value.real= 1.0; value.imag= 0.0; matrix_init_value (&mQp, value, 0, 0, QP_LEN+1); /* Inicialización de la matriz Lambda a 0 */ matrix_new (&mLambdaPA, ML_LEN, ML_LEN, NULL); value.real = 0; value.imag = 0; matrix_init_value (&mLambdaPA, value, 0, 0, 1); 118 Implementación en DSP de un predistorsionador digital /* Inicialización de la matriz Lambda a 0 */ matrix_new (&mLambda, ML_LEN, ML_LEN, NULL); value.real = 0; value.imag = 0; matrix_init_value (&mLambda, value, 0, 0, 1); /* Ver memoria asignada */ v1 = malloc_size; /* Calcular vector de muestras de salida PA */ for (i = 0; i < 1; i++) { /* Lee símbolos de entrada al PA disponibles en fichero externos en formato hex */ dataIO_xRe(); /*lee los datos de entrada parte real*/ /* Lee símbolos de entrada al PA disponibles en fichero externos en formato hex */ dataIO_xIm(); /*lee los datos de entrada parte imaginaria*/ /* Lee símbolos de salida del PA disponibles en fichero externos en formato hex */ dataIO_yRe(); /*lee los datos de entrada parte real*/ /* Lee símbolos de salida del PA disponibles en fichero externos en formato hex */ dataIO_yIm(); /*lee los datos de entrada parte imaginaria*/ for (j = 0; j < X_LEN; j++) { /* Asignación de parte real de entrada a variable */ x[j].real = x_re[j]; /* Asignación de parte imag de entrada a variable */ x[j].imag = x_im[j]; /* Asignación de parte real de salida a variable */ y[j].real = y_re [j]; /* Asignación de parte imag de salida a variable */ y[j].imag = y_im [j]; /* Obtener módulo de cada muestra de entrada y salida */ x_mod[j] = complex_module (x[j]); y_mod[j] = complex_module (y[j]); } /* Obtener el máximo del módulo de las muestras de entrada y salida */ x_max = DSPF_sp_maxval (x_mod, X_LEN); y_max = DSPF_sp_maxval (y_mod, X_LEN); /* Calcular G */ G = y_max / x_max; /* Contador de ciclos */ start = clock(); stop = clock(); overhead = stop - start; start = clock (); for (j = 0; j < X_LEN; j++) { /* Calcular vector de muestras de salida PA */ fir_complex_shift (vx, x_norm, vx_len); /* Calcular el vector q[] */ gen_vq (vq_PA, vx, vy1, vN_PA, vD_PA, P, N, D); /* Calcular salida estimada del filtro FIR */ LISTADO DE PROGRAMAS EN C 119 yd = fir_complex (vc_PA, vq_PA, VQ_LEN); /* Calcular los nuevos coeficientes del modelo de Hammerstein */ kalman_complex (yd, y_norm, vc_PA, vh_PA, vq_PA, vqh_PA, &mLambdaPA, Qm, VH_LEN, VQ_LEN); /* Actualizar la matriz lambda */ mLambda_update (vh_PA, vq_PA, vqh_PA, &mLambdaPA, &mQp, VH_LEN, VQ_LEN); /* Desplazar salida estimadas */ fir_complex_shift (vy1, yd, vy1_len); /* Contador de ciclos */ stop = clock (); cycle1= stop - start - overhead; /* Calcular salida del Post-D a partir de vc (Post-D) y vq (Post-D) */ /* Contador de ciclos */ start = clock (); /* Desplazar entrada modelo del Post-D */ fir_complex_shift (vy2, y_norm, vy2_len); /* Calcular el vector q[] para Post-D */ gen_vq (vq, vy2, vd, vN, vD, P, N, D); /* Calcular salida estimada del Post-D */ xd = fir_complex (vc, vq, VQ_LEN); /* Calcular los nuevos coeficientes del modelo de Hammerstein */ kalman_complex (xd, x_norm, vc, vh, vq, vqh, &mLambda, Qm, VH_LEN, VQ_LEN); /* Actualizar la matriz lambda */ mLambda_update (vh, vq, vqh, &mLambda, &mQp, VH_LEN, VQ_LEN); /* Desplazar salida estimadas xd */ fir_complex_shift (vd, xd, vd_len); /* Contador de ciclos */ stop = clock (); cycle2 = stop - start - overhead; printf ("%f, %f, ", x_norm.real, x_norm.imag); printf ("%f, %f, ", xd.real, xd.imag); printf ("%f, %f\n", y_norm.real, y_norm.imag); printf ("%f, %f\n", yd.real, yd.imag); } } /* Mostrar coeficientes estimados para PD y PA */ printf ("vc\n"); for (i = 0; i< VC_LEN; i++) { printf ("%f, %f, \n", vc_PA[i].real, vc_PA[i].imag); printf ("%f, %f, \n", vc[i].real, vc[i].imag); } printf ("ypre, y\n"); /* Trasladar coeficientes Pre-D antes del PA */ /* Inicializar vector entrada PD */ 120 Implementación en DSP de un predistorsionador digital vxp_len = vN[N]+1; vxPRE = xmalloc (sizeof(tComplex) * vxp_len); fir_complex_init (vxPRE, complex_zero (), vxp_len); /* Inicializar vector entrada PA */ vyp2_len = vN_PA[N]+1; vyPRE2 = xmalloc (sizeof(tComplex) * vyp2_len); fir_complex_init (vyPRE2, complex_zero (), vyp2_len); if (D == 0) { vyp1_len= 1; vy_len = 1; } else { vyp1_len= vD[D-1]+1; vy_len = vD_PA[D-1]+1; } /* Inicializar vector salida PD */ vyPRE1 = xmalloc (sizeof(tComplex) * vyp1_len); fir_complex_init (vyPRE1, complex_zero (), vyp1_len); /* Inicializar vector salida PA */ vy = xmalloc (sizeof(tComplex) * vy_len); fir_complex_init (vy, complex_zero (), vy_len); for (i = 0; i < 1; i++) { /* Lee símbolos de entrada al PA disponibles en fichero externos en formato hex */ dataIO_xRe(); /*lee los datos de entrada parte real*/ /* Lee símbolos de entrada al PA disponibles en fichero externos en formato hex */ dataIO_xIm(); /*lee los datos de entrada parte imaginaria*/ /* Contador de ciclos */ start = clock (); for (j = 0; j < X_LEN; j++) { /* Asignación de parte real de entrada a variable */ x[j].real = x_re [j]; /* Asignación de parte imag de entrada a variable */ x[j].imag = x_im [j]; /* Obtener módulo de cada muestra */ x_mod[j] = complex_module (x[j]); } /* Obtener el máximo del módulo de las muestras de entrada */ x_max = DSPF_sp_maxval (x_mod, X_LEN); for (j = 0; j < X_LEN ; j++) { /* Normalizar señal de entrada */ x_norm = complex_divide_escalar (x[j], x_max/G); /* Incluye la ganancia calculada en la estimación */ /* Desplazar entrada del Pre-D */ fir_complex_shift (vxPRE, x_norm, vxp_len); gen_vq (vq, vxPRE, vyPRE1, vN, vD, P, N, D); /* Calcular salida del Pre-D a partir de vc y vq */ y_PRE = fir_complex (vc, vq, VQ_LEN); /* Desplazar salida del Pre-D */ fir_complex_shift (vyPRE1, y_PRE, vyp1_len); /* Desplazar entrada del PA */ LISTADO DE PROGRAMAS EN C 121 fir_complex_shift (vyPRE2, y_PRE, vyp2_len); /* Calcular el vector q[] para PA */ gen_vq (vq_PA, vyPRE2, vy, vN_PA, vD_PA, P, N, D); /* Calcular salida del PA */ yd = fir_complex (vc_PA, vq_PA, VQ_LEN); /* Desplazar salida y */ fir_complex_shift (vy, yd, vy_len); stop = clock (); cycle3 = stop - start - overhead; printf ("%f, %f, ", x[j].real, x[j].imag); printf ("%f, %f, ", x_norm.real, x_norm.imag); printf ("%f, %f, ", y_PRE.real, y_PRE.imag); printf ("%f, %f\n", yd.real, yd.imag); } } return 0; } /*** * Modulo :Kalman.C * Contenido: Implementación de algoritmo tipo Fast-Kalman * Autor : Sandra Vázquez Rodríguez * Fecha : 29/05/2006 * * Historial: * 29/05/2006 SVR * Versión inicial módulo * 06/06/2006 SVR * Cambios en las funciones para adaptar la estructura de * matrices * 11/07/2006 SVR * Cambios de productos de matrices por las funciones * C67xx * Cambios en cabeceras de funciones para pasar el tamaño de vectores * 02/09/2006 SVR * Actualización de comentarios * */ #include "defs.h" /** * Calcula los vectores vh y vc * * @param y estimated signal * @param d desired signal * @param vh FIR filter coeficients * @param vq input signal taps * @param mLambda * @param Qm * */ void kalman_complex (tComplex y, tComplex d, tComplex vc[], tComplex vh[], tComplex vq[], tComplex vqh[], tMatrix *mLambda, tComplex Qm, int vh_len, int vq_len) { int i; tComplex he, e; tMatrix mh, mq, mqh; tMatrix mnum, mden; tComplex value; 122 Implementación en DSP de un predistorsionador digital /* Calcular la señal error */ e = complex_subs (d, y); /* Inicializar matriz intermedia mnum */ matrix_new (&mnum, vq_len, 1, NULL); /* Inicializar matriz mq al vector vq */ matrix_new (&mq, vq_len, 1, vq); /* Multiplicar num = Lambda · vq */ DSPF_sp_mat_mul_cplx((float*) mLambda->data, vh_len, vh_len, (float*) mq.data, 1, (float*) mnum.data); /* Inicializar matriz mqh al vector hermítico de vq */ matrix_new (&mqh, 1, vq_len, vqh); /* Calcular el complejo conjugado del vector vq */ for (i = 0; i < vq_len; i++) { mqh.data[i] = complex_conjugate (vq[i]); } /* Inicializar matriz intermedia mden */ matrix_new (&mden, 1, 1, NULL); /* Multiplicar den = vq' · (Lambda · vq) */ DSPF_sp_mat_mul_cplx((float*) mqh.data, 1, vq_len, (float*) mnum.data, 1, (float*) mden.data); /* Sumar den = (vq' · (Lambda · vq)) + Qm */ mden.data[0] = complex_add (mden.data[0], Qm); value.real = 1; value.imag = 0; /* Calcular inverso de den = 1 / den */ mden.data[0] = complex_divide (value, mden.data[0]); /* Inicializar matriz mh al vector vh */ matrix_new (&mh, vh_len, 1, vh); /* Multiplicar mh = (Lambda · vq) · (1 / (vq' · (Lambda · vq)) + Qm) */ matrix_multiply (&mnum, &mden, &mh); /* Borrar matrices intermedias */ matrix_delete (&mnum); matrix_delete (&mden); /* Aquí tenemos hk */ /* Actualizar coeficientes de vc */ /* Calcular complejo conjugado del error */ e = complex_conjugate(e); for (i= 0; i < vh_len; i++) { /* Multiplicar vh · e' */ he = complex_multiply (vh[i], e); /* Calcular vc + (vh ·e' */ vc[i] = complex_add (vc[i], he); /* Aquí tenemos c(k+1)= c(k) + h(k) · e' */ } return; } /** * Actualiza la matriz Lambda * * @param mLambda puntero a la matriz Lambda LISTADO DE PROGRAMAS EN C 123 * @param mQp puntero a la matriz Qp * @param vh FIR filter coeficients * @param vq input signal taps * */ void mLambda_update (tComplex vh[], tComplex vq[], tComplex vqh[], tMatrix *mLambda, tMatrix *mQp, int vh_len, int vq_len){ tMatrix mh, mqh, mh_qh, mh_qh_Lambda; /* Inicializar matriz mh al vector vh */ matrix_new (&mh, vh_len, 1, vh); /* Inicializar matriz mqh al hermítico de vq */ matrix_new (&mqh, 1, vq_len, vqh); /* Inicializar matriz intermedia mh_qh */ matrix_new (&mh_qh, vh_len, vq_len, NULL); /* Multiplicar vh · vqh */ matrix_multiply (&mh, &mqh, &mh_qh); /* Inicializar matriz intermedia mh_qh_Lambda */ matrix_new (&mh_qh_Lambda, vh_len, vh_len, NULL); /* Multiplicar (vh · vqh) · Lambda */ DSPF_sp_mat_mul_cplx((float*) mh_qh.data, vh_len, vq_len, (float*) mLambda->data, vh_len, (float*) mh_qh_Lambda.data); /* Calcular - (vh · vqh) · Lambda */ matrix_neg (&mh_qh_Lambda, &mh_qh_Lambda); /* Sumar Lambda - (vh · vqh) · Lambda */ matrix_add (mLambda, &mh_qh_Lambda, mLambda); /* Sumar Lambda - (vh · vqh) · Lambda + Qp */ matrix_add (mLambda, mQp, mLambda); /* Borrar matrices intermedias */ matrix_delete (&mh_qh_Lambda); matrix_delete (&mh_qh); return; } /*** * Modulo :HAM.C * Contenido: Hammerstein --> señal estimada= ckH · qk, se calculan * los vectores ck y qk * Autor : Sandra Vázquez Rodríguez * Fecha : 25/05/2006 * * Historial: * 20/07/2006 SVR * Correción traslado de muestras D en vq * 02/09/2006 SVR * Actualización de comentarios * */ #include "defs.h" /** * Inicialización de vector complejo * * @param vx vector de entrada * @param value valor de inicialización del vector vx * @param ntaps número de muestras del vector vx * */ void fir_complex_init (tComplex vx[], tComplex value, int ntaps) { 124 Implementación en DSP de un predistorsionador digital for (; ntaps > 0; vx++, ntaps--) { /* Inicializar a valor */ *vx = value; } } /** * Cálculo de filtro FIR con muestras complejas * * @param vc vector vc(k) * @param vq vector vq(k) * @param ntaps número de muestras * * @return y muestra de salida * */ tComplex fir_complex (tComplex vc[], tComplex vq[], int ntaps) { tComplex c, y; /* Inicializar a cero la salida y */ y = complex_zero (); for (; ntaps > 0; vc++, vq++, ntaps--) { /* Calcular el complejo conjugado de primera señal */ c = complex_conjugate (*vc); /* Calcular suma acumulada del producto de complejo conjugado de primera señal y segunda señal */ y = complex_add (y, complex_multiply (c, *vq)); } return y; } /** * Desplazamiento de muestras del vector vx[] * * @param vx vector a desplazar * @param x valor de la muestra 0 * @param ntaps número de muestras * */ void fir_complex_shift (tComplex vx[], tComplex x, int ntaps) { tComplex *p, *q; /* Desplazar muestras */ for (p = &vx[ntaps-1], q = &vx[ntaps-2]; ntaps > 1; p--, q--, ntaps--){ *p = *q; } vx [0] = x; } /** * Generación del vector q[] * * @param vq vector q(k) * @param vx vector de entrada al sistema no lineal * @param vy vector estimado de salida del sistema no lineal * @param P orden del polinomio no lineal * @param N orden del numerador del polinomio del filtro LTI * @param D orden del denominador del polinomio del filtro LTI * */ void gen_vq (tComplex vq[], tComplex vx[], tComplex vy[], int vN_delay[], int vD_delay[], int p, int n, int d) { int i, j; int k; /* índice vector vq[] */ LISTADO DE PROGRAMAS EN C 125 SAMPLE modulo; /* módulo vx[i] */ SAMPLE factor; /* factor acumulado módulo vx[i] */ /* Inicializar índice vector q[] */ k = 0; /* Calcular el vector vq(0..P) para */ for (i = 0; i <= n; i++) { modulo = complex_module (vx[vN_delay[i]]); factor = 1.0; /* Calcular el vector vq(0..P)=[vx(k), vx(k)*|vx(k)|,,..., vx(k)*|vx(k)|^P] */ for (j = 0; j <= p; j++, k++) { /* Producto vq = vx · factor */ vq[k] = complex_mult_escalar (vx[vN_delay[i]], factor); /* Actualizar factor */ factor = factor * modulo; /* complex_print (vq[k]); */ } } /* Copiar el vector de salida estimado vy[] */ if (d > 0) for (i = 0; i < d; i++, k++) { /* Desplazar muestras de salida */ vq[k] = vy[vD_delay[i]-1]; /* complex_print (vq[k]); */ } } /*** * Modulo : matrix.c * Contenido: Operaciones con matrices para el algoritmo Fast- * Kalman * Autor : Sandra Vázquez Rodríguez * Fecha : 06/06/2006 * * Historial: * * 03/06/2006 SVR * Versión inicial módulo * 06/06/2006 SVR * Cambios para adaptación a CCS */ #include "defs.h" int malloc_size = 0; /** * Inicializa una matriz de dimensiones nrow x ncol * * @param m puntero a la matriz * @param nrow número de filas * @param ncol número de columnas * @param data puntero al búffer de datos de la matriz * * @return Devuelve 0 si no ha habido error, -1 en caso contrario */ int matrix_new (tMatrix *m, int nrow, int ncol, tComplex *data) { int s = 0; if (data == NULL) { s = sizeof(tComplex)*nrow*ncol; 132 Implementación en DSP de un predistorsionador digital } /** * División de complejo por escalar * * @param x multiplicando 1 * @param y multiplicando 2 * @return w resultado de la multiplicación */ inline tComplex complex_divide_escalar (tComplex x, SAMPLE y) { tComplex w; w.real= x.real / y; w.imag= x.imag / y; return w; } /** * Conjugado de un número complejo * * @param x de entrada * @return x */ inline tComplex complex_conjugate (tComplex x) { x.imag = -x.imag; return x; } /** * Módulo de un número complejo * * @param x de entrada * @return y resultado de la operación */ inline SAMPLE complex_module (tComplex x) { SAMPLE y; y = x.real * x.real + x.imag * x.imag; return sqrtsp (y); } /** * Módulo al cuadrado de un número complejo * * @param x de entrada * @return y resultado de la operación */ inline SAMPLE complex_sq_module (tComplex x) { SAMPLE y; y = x.real * x.real + x.imag * x.imag; return y; } void complex_print (tComplex x) { printf ("re: %f, im: %f\n", x.real, x.imag); } LISTADO DE PROGRAMAS EN C A4.2. Proyecto “Lineal-RRC_QAM.pjt” El proyecto “Lineal-RRC_QAM.pjt” genera muestras aleatorias según una modulación M-QAM con RRC y calcula la salida del amplificador a partir de los coeficientes del modelo del amplificador estimados en el proyecto anterior. A partir de la entrada y la salida, estima los coeficientes del post-distorsionador. Posteriormente, a partir de nuevas muestras estima la salida del predistorsionador y a continuación, las muestras pasan por el modelo del amplificador. El resultado es: • Muestras de entrada aleatorias M-QAM con RRC • Muestras de salida del amplificador de potencia aplicando el modelo vc_PA • Coeficientes del post-distorsionador (vc) • Muestras de entrada aleatorias M-QAM con RRC normalizadas • Muestras de salida del predistorsionador: aplicando vc • Muestras de salida del amplificador: aplicando a las muestras anteriores vc_PA Los módulos incluidos son: • Main.c • Qam.c • RRC.c • Sample.c • Kalman.c • Ham.c • Matrix.c • Complex.c • Link.cmd • Vectors.asm Los ficheros de cabecera son: • Qam.h • Rrc.h • Sample.h • Kalman.h • Ham.h • Matrix.h • Complex.h • Defs.h • Type.h Las librerías utilizadas: 134 Implementación en DSP de un predistorsionado • Dsp67xx.lib • rts6700.lib • fastmath67x.lib El listado A4.2 incluye el código de los módulos anteriores que no se hayan mostrado en el listado anterior A4.1. LISTADO DE PROGRAMAS EN C 135 /*** * Modulo : MAIN.C * Contenido: Modelo de Hammerstein * Autor : Sandra Vázquez Rodríguez * Fecha : 25/05/2006 * * Historial: * * 02/04/2006 SVR * Versión inicial módulo * 29/05/2006 SVR * Algoritmo de Fast-Kalman * 06/06/2006 SVR * Cambios en la definición de algunas funciones según estructura de matriz * 07/06/2006 SVR * Cambios para sustituir ficheros de muestras por señal QAM generada * 29/06/2006 SVR * Vectores de retardos * 05/07/2006 SVR * Validación de vectores de retardos * 06/07/2006 SVR * Normalización de señales * 10/07/2006 SVR * Validación de cambios anteriores con CCS * 18/07/2006 SVR * Corrección error en desplazamiento de muestras vd * 19/07/2006 SVR * Corrección error en len de vectores de longitud D * 20/07/2006 SVR * Corrección en vector vy2 --> vd en lugar de yd_norm (fir_complex_shift (vy2, yd, vy2_len);) * 02/09/2006 SVR * Actualización de comentarios */ #include "defs.h" #define MUESTRAS 100 #define MUESTRAS_SIMBOLO 12 #define SIMBOLOS 6 #define TOTAL_MUESTRAS (MUESTRAS*MUESTRAS_SIMBOLO) #define ITER 10 #define MODULACION 64 /* número de la modulación QAM */ #define ALFA 0.35 /* factor de roll-off */ #define G 1.1 /* factor de ganancia del bloque PD+ PA calculado según el modelo */ #define P 6 /* longitud de polinomio no-lineal */ #define N 2 /* longitud de mycoef_N */ #define D 0 /* longitud de mycoef_D */ #define X_LEN (TOTAL_MUESTRAS*ITER) /* tamaño de señal de entrada */ #define Y_LEN (TOTAL_MUESTRAS*ITER) /* tamaño de señal de salida */ #define VQ_LEN (P+1)*(N+1)+D /* orden de q[] */ #define VC_LEN (P+1)*(N+1)+D /* orden de c[] */ #define VH_LEN (P+1)*(N+1)+D /* orden de h[] */ #define ML_LEN (P+1)*(N+1)+D /* tamaño fila de matriz lambda */ #define QP_LEN (P+1)*(N+1)+D /* tamaño fila de matriz Qp */ static int x_sim_re [X_LEN]; /* vector de parte real de los simbolos nQAM generados aleatoriamente */ static int x_sim_im [X_LEN]; 136 Implementación en DSP de un predistorsionador digital /* vector de parte imag de los simbolos nQAM generados aleatoriamente */ static tRRC rrc; /* definición de estructura de filtro rrc */ static tRRCFiltConv filtConv [2]; /* estructura de filtro de convolución */ static tComplex x [X_LEN]; /* muestras de entrada modelo */ static SAMPLE x_mod [X_LEN]; /* módulo de muestras de entrada modelo */ static int vN_PA[] = {0, 1, 2}; /* vector de retardos N para el PA */ static int vD_PA[] = {0}; /* vector de retardos D para el PA */ static int vN[] = {0, 1, 2}; /* vector de retardos N para el PD */ static int vD[] = {0}; /* vector de retardos D para el PD */ tComplex *vx, *vy1, *vy2, *vd; /* vectores de muestras */ tComplex *vxPRE, *vyPRE1, *vyPRE2, *vy; /* vectores de muestras */ static tComplex vq_PA[VQ_LEN]; /* vector qk de PA */ static tComplex vq[VQ_LEN]; /* vector qk de PD */ static tComplex vqh[VQ_LEN]; /* vector qkH */ static tComplex vc[VC_LEN]; /* vector ck del PD */ static tComplex vh[VH_LEN]; /* vector hk */ static tMatrix mQp; /* matriz Lambda */ static tMatrix mLambda; /* matriz Qp */ tComplex Qm; /* valor Qm */ /* Vector de coeficientes que modela el PA */ static tComplex vc_PA[] = { 0.813399, -0.033037, 0.092348, -0.065276, -0.234627, 0.165353, -0.230955, 0.227293, 0.090300, -0.109416, 0.144396, -0.297670, -0.066731, 0.152230, 0.330309, -0.023265, 0.193624, -0.045188, -0.272053, 0.054957, -0.032012, 0.124901, 0.086744, -0.015832, -0.004426, -0.120058, -0.013856, 0.067108, -0.046616, -0.003551, -0.021197, 0.031151, -0.069413, -0.003152, 0.153650, -0.062852, 0.004758, 0.007605, -0.110097, 0.064385, 0.042277, -0.047519}; int main() { int v1; /* variable contador de memoria ocupada */ int i, j, k, l; /* contadores de bucles */ int start, stop, overhead, cycle1, cycle2, cycle3; /* contadores de ciclos */ int simbolo, re, im; /* variables para los símbolos, parte real e imaginaria */ int vx_len, vy1_len, vy2_len, vd_len; /* tamaño de los vectores muestras para Hammerstein */ int vxp_len, vyp1_len, vyp2_len, vy_len; LISTADO DE PROGRAMAS EN C 137 /* tamaño de los vectores muestras para Hammerstein */ tComplex x_norm, y_norm; /* muestras de modelo normalizadas */ tComplex y; /* muestra de salida modelo */ tComplex y_PRE; /* muestra de salida del PD */ tComplex xd; /* muestras de salida estimada Post-D */ tComplex yd; /* muestras de salida estimada PA */ tComplex value; /* valor de inicialización */ SAMPLE x_max; /* máximo de módulo de x */ extern int malloc_size; /* Inicializar estructura rrc */ rrc_setup (&rrc, NULL, MUESTRAS_SIMBOLO, SIMBOLOS, ALFA); /* Inicializar filtro convolucional señal en fase */ rrc_filt_conv_setup (&rrc, &filtConv [0], NULL); /* Inicializar filtro convolucional señal en cuadratura */ rrc_filt_conv_setup (&rrc, &filtConv [1], NULL); /* Inicializar vector entrada PA */ vx_len = vN_PA[N]+1; vx = xmalloc (sizeof(tComplex) * vx_len); fir_complex_init (vx, complex_zero (), vx_len); /* Inicializar vector de entrada del Post-D */ vy2_len = vN[N]+1; vy2 = xmalloc (sizeof(tComplex) * vy2_len); fir_complex_init (vy2, complex_zero (), vy2_len); /* Aplicar condición si D = 0 */ if (D == 0) { vy1_len = 1; vd_len = 1; } else { vy1_len = vD_PA[D-1]+1; vd_len = vD[D-1]+1; } /* Inicializar vector de salida PA */ vy1 = xmalloc (sizeof(tComplex) * vy1_len); fir_complex_init (vy1, complex_zero (), vy1_len); /* Inicializar vector de salida del Post-D */ vd = xmalloc (sizeof(tComplex) * vd_len); fir_complex_init (vd, complex_zero (), vd_len); /* Inicializar vector coeficientes c[] */ value.real= 1.0; value.imag= 0.0; fir_complex_init (vc, value, VC_LEN); /* Inicializar vector h[] */ fir_complex_init (vh, complex_zero (), VH_LEN); /* Inicialización a 1 de Qm */ Qm.real= 1.0; Qm.imag= 0.0; /* Inicialización de la matriz mQp a 0 */ matrix_new (&mQp, QP_LEN, QP_LEN, NULL); value.real = 0; value.imag = 0; matrix_init_value (&mQp, value, 0, 0, 1); /* Inicialización de la diagonal de mQp a 1 */ value.real= 1.0; value.imag= 0.0; matrix_init_value (&mQp, value, 0, 0, QP_LEN+1); 138 Implementación en DSP de un predistorsionador digital /* Inicialización de la matriz Lambda a 0 */ matrix_new (&mLambda, ML_LEN, ML_LEN, NULL); value.real = 0; value.imag = 0; matrix_init_value (&mLambda, value, 0, 0, 1); /* Ver memoria asignada */ v1 = malloc_size; /* Contador de ciclos */ start = clock(); stop = clock(); overhead = stop - start; for (l = 0; l < 1; l++) { /* Generar símbolos modulación */ for (i = 0, k = 0; i < MUESTRAS*ITER; i++) { /* Símbolo aleatorio según la modulación nQAM */ simbolo = xrandom (0, MODULACION-1); /* Asignar a parte real e imaginaria el símbolo generado */ modqam (MODULACION, simbolo, &re, &im); for (j = 0; j < MUESTRAS_SIMBOLO; j++, k++) { /* Obtener vectores de símbolos */ if (j == 0) { x_sim_re [k] = re; x_sim_im [k] = im; } else { x_sim_re [k] = 0; x_sim_im [k] = 0; } /* Convolución de señal generada por RRC */ x [k].real = rrc_conv_y (&filtConv [0], &rrc, (float) x_sim_re [k]); x [k].imag = rrc_conv_y (&filtConv [1], &rrc, (float) x_sim_im [k]); /* Obtener módulo de cada muestra */ x_mod [k] = complex_module (x[k]); } } /* Obtener el máximo del módulo de las muestras de entrada */ x_max = DSPF_sp_maxval (x_mod, X_LEN); /* Calcular vector de muestras de salida PA */ for (j = 0; j < X_LEN; j++) { /* Contador de ciclos */ start = clock (); /* Normalizar señal de entrada */ x_norm = complex_divide_escalar (x[j], x_max * G); /* Calcular la muestra de salida del PA a partir de vc_PA */ fir_complex_shift (vx, x_norm, vx_len); /* Calcular el vector q[] para PA */ gen_vq (vq_PA, vx, vy1, vN_PA, vD_PA, P, N, D); LISTADO DE PROGRAMAS EN C 139 /* Calcular salida estimada del PA */ yd = fir_complex (vc_PA, vq_PA, VQ_LEN); /* Desplazar salida estimada */ fir_complex_shift (vy1, yd, vy1_len); /* Contador de ciclos */ stop = clock (); cycle1= stop - start - overhead; /* Estimación de los coeficientes del Post-D */ /* Contador de ciclos */ start = clock (); /* Desplazar entrada modelo del Post-D */ fir_complex_shift (vy2, yd, vy2_len); /* Calcular el vector q[] para Post-D */ gen_vq (vq, vy2, vd, vN, vD, P, N, D); /* Calcular salida estimada del Post-D */ xd = fir_complex (vc, vq, VQ_LEN); /* Calcular los nuevos coeficientes del modelo de Hammerstein */ kalman_complex (xd, x_norm, vc, vh, vq, vqh, &mLambda, Qm, VH_LEN, VQ_LEN); /* Actualizar la matriz lambda */ mLambda_update (vh, vq, vqh, &mLambda, &mQp, VH_LEN, VQ_LEN); /* Desplazar salida estimadas xd */ fir_complex_shift (vd, xd, vd_len); /* Contador de ciclos */ stop = clock (); cycle2= stop - start - overhead; printf ("%f, %f, ", x[j].real, x[j].imag); printf ("%f, %f, ", x_norm.real, x_norm.imag); printf ("%f, %f, ", yd.real, yd.imag); printf ("%f, %f\n", xd.real, xd.imag); } } /* Mostrar coeficientes estimados para PD y PA */ printf ("vc\n"); for (i = 0; i< VC_LEN; i++) { printf ("%f, %f, \n", vc[i].real, vc[i].imag); } printf ("ypre, y\n"); /* Trasladar coeficientes Pre-D antes del PA */ /* Inicializar vector entrada PD */ vxp_len = vN[N]+1; vxPRE = xmalloc (sizeof(tComplex) * vxp_len); fir_complex_init (vxPRE, complex_zero (), vxp_len); /* Inicializar vector entrada PA */ vyp2_len = vN_PA[N]+1; vyPRE2 = xmalloc (sizeof(tComplex) * vyp2_len); fir_complex_init (vyPRE2, complex_zero (), vyp2_len); if (D == 0) { vyp1_len= 1; vy_len = 1; } else { 140 Implementación en DSP de un predistorsionador digital vyp1_len= vD[D-1]+1; vy_len = vD_PA[D-1]+1; } /* Inicializar vector salida PD */ vyPRE1 = xmalloc (sizeof(tComplex) * vyp1_len); fir_complex_init (vyPRE1, complex_zero (), vyp1_len); /* inicializar vector salida PA */ vy = xmalloc (sizeof(tComplex) * vy_len); fir_complex_init (vy, complex_zero (), vy_len); for (l = 0; l < ITER; l++) { /* Generar nuevos símbolos modulación */ for (i = 0, k = 0; i < MUESTRAS; i++) { /* Símbolo aleatorio según la modulación nQAM */ simbolo = xrandom (0, MODULACION-1); /* Asignar a parte real e imaginaria el símbolo generado */ modqam (MODULACION, simbolo, &re, &im); for (j = 0; j < MUESTRAS_SIMBOLO; j++, k++) { /* Obtener vectores de símbolos */ if (j == 0) { x_sim_re [k] = re; x_sim_im [k] = im; } else { x_sim_re [k] = 0; x_sim_im [k] = 0; } /* Convolución de señal generada por RRC */ x [k].real = rrc_conv_y (&filtConv [0], &rrc, (float) x_sim_re [k]); x [k].imag = rrc_conv_y (&filtConv [1], &rrc, (float) x_sim_im [k]); /* Obtener módulo de cada muestra */ x_mod[k] = complex_module (x[k]); } } /* Obtener el máximo del módulo de las muestras de entrada */ x_max = DSPF_sp_maxval (x_mod, X_LEN); for (j = 0; j < X_LEN ; j++) { /* Contador de ciclos */ start = clock (); /* Normalizar señal de entrada */ x_norm = complex_divide_escalar (x[j], x_max * G); /* Desplazar entrada del Pre-D */ fir_complex_shift (vxPRE, x_norm, vxp_len); gen_vq (vq, vxPRE, vyPRE1, vN, vD, P, N, D); /* Calcular salida del Pre-D a partir de vc y vq */ y_PRE = fir_complex (vc, vq, VQ_LEN); /* Desplazar salida del Pre-D */ fir_complex_shift (vyPRE1, y_PRE, vyp1_len); LISTADO DE PROGRAMAS EN C 141 /* Desplazar entrada del PA */ fir_complex_shift (vyPRE2, y_PRE, vyp2_len); /* Calcular el vector q[] para PA */ gen_vq (vq_PA, vyPRE2, vy, vN_PA, vD_PA, P, N, D); /* Calcular salida del PA */ y = fir_complex (vc_PA, vq_PA, VQ_LEN); /* Desplazar salida y */ fir_complex_shift (vy, y, vy_len); /* Contador de ciclos */ stop = clock (); cycle3= stop - start - overhead; printf ("%f, %f, ", x[j].real, x[j].imag); printf ("%f, %f, ", x_norm.real, x_norm.imag); printf ("%f, %f, ", y_PRE.real, y_PRE.imag); printf ("%f, %f\n", y.real, y.imag); } } return 0; } /*** * Modulo : RRC.C * Contenido: Modulador envolvente QAM * Autor :Sandra Vázquez Rodríguez * Fecha : 02/04/2006 * * Historial: * * 06/03/2006 MHR * Versión inicial módulo * 20/07/2006 SVR * Añadir raíz cuadrada en RRC */ #include "defs.h" #define PI 3.14159265 /** * @param rrc estructura del RRC * @param h vector para las muestras de RRC * @param muestras * @param simbolos * @param alfa * */ void rrc_setup (tRRC *rrc, SAMPLE h[], int muestras, int simbolos, float alfa) { /* Número de muestras por símbolo */ rrc->numMuestras = muestras; /* Número de símbolos cálculo salida */ rrc->numSimbolos = simbolos; /* Factor de roll-off */ rrc->alfa = alfa; /* Número total muestras respuesta impulsional */ rrc->totalMuestras = rrc->numMuestras * rrc->numSimbolos+1;