PFC 2000

Descargar como pdf o txt
Descargar como pdf o txt
Está en la página 1de 245

UNIVERSITAT POLITÈCNICA DE CATALUNYA

ESCOLA TÈCNICA SUPERIOR D´ENGINYERIA DE


TELECOMUNICACIONS DE BARCELONA

PROJECTE FI DE CARRERA

MODULADOR DIGITAL PROGRAMABLE

Juan Luis Tébar Garcı́a


Barcelona, 2000
PROJECTE FI DE CARRERA

MODULADOR DIGITAL PROGRAMABLE

Autor:
Juan Luis Tébar Garcı́a

Tutor:
Josep Vidal Manzano
Profesor Titular del Dept. de Teoria del Senyal i Comunicacions
Universitat Politècnica de Catalunya

DEPARTAMENT DE TEORIA DEL SENYAL I COMUNICACIO


ESCOLA TÈCNICA SUPERIOR D´ENGINYERIA DE
TELECOMUNICACIONS DE BARCELONA
UNIVERSITAT POLITÈCNICA DE CATALUNYA

Barcelona, 2000
A mi única familia
Agradecimientos

Este Proyecto de Fin de Carrera no hubiera sido posible sin la ayuda de algunas personas
a quienes me gustarı́a expresar mi sincera gratitud.
Comenzaré este turno por mi familia, pues ellos han sido en gran parte los “cul-
pables” de que este trabajo haya visto la luz: A mis padres Eusebio y Emilia por sus
continuos ánimos, a mi hermano Eusebio por ser el responsable de mi reciclaje software, a
José Antonio y Marı́a José por su ayuda y soporte “hardware” en mis viajes a Barcelona,
y en general a todos por su cariño y apoyo moral.
También he de dar las gracias a mi tutor, Josep Vidal, por las facilidades y consejos
prestados a la hora de desarrollar este trabajo en la distancia. No puedo dejarme en el
tintero a mi amigo Cesar, quien con su inestimable ayuda tanto en el plano técnico como en
el anı́mico tiene parte del mérito de este trabajo. Gracias también a mi compañero Cesáreo
por su ayuda con los equipos de medida y a Garve por su apoyo con la mecanografı́a.
No puedo tampoco dejar de nombrar a mis amigos de siempre Avelino, Iñaki, Juan
Ernesto, Claudio y a sus familias por su paciencia conmigo a lo largo de tanto tiempo.

Barcelona
Septiembre del 2000 Juan Luis Tébar Garcı́a

i
Resumen

El objetivo de este trabajo ha sido el desarrollo de un Modulador Digital Programable


para su empleo en la realización de pruebas de laboratorio. Se pretende realizar medidas
de propagación con nuevos tipos de comunicaciones digitales tales como W − CDM A,
habiéndose conseguido alcanzar una velocidad de modulación de 13.5 Mbps, valor suficiente
para la realización de las mismas.
El trabajo realiza un repaso teórico de lo que es la Sı́ntesis Digital Directa poniendo
de relieve los avances más recientes en este campo. Se observa un esfuerzo por parte
de los fabricantes en añadir nuevas prestaciones a los circuitos integrados DDS que ya
está incidiendo en la implantación de estos sistemas de forma generalizada. Al final de
este capı́tulo teórico se incluye una recopilación de circuitos DDS comerciales junto con
sus principales caracterı́sticas, aunque cada mes aparecen chips que igualan o superan las
prestaciones de sus competidores.
El montaje práctico utiliza un modulador DDS, y en él se ven aplicados los conceptos
de interpolación y filtrado mediante filtros FIR. Es por ello que también se repasan estos
conceptos e incluso se incluye un ejemplo de utilidad en el propio diseño: Se han calculado
los coeficientes a programar en cada etapa del filtro según la curva de respuesta en coseno
alzado, acompañándose gráficas mostrando los resultados obtenidos.
En segundo lugar, y para poder llevar a cabo las pruebas de funcionamiento del mo-
dulador, se ha desarrollado conjuntamente un generador de secuencias pseudoaleatorias.
Éste sistema funciona como un equipo medidor de tasa de bits erróneos BER y está di-
señado para poder funcionar de manera autónoma e independiente del modulador, con lo
que se puede aprovechar para realizar todo tipo de medidas por separado.
Con respecto a la medida de tasas de error, ha sido necesario el estudio de los
criterios establecidos al respecto por la UIT. Aquellos contenidos básicos de aplicación en
el trabajo también han sido reflejados en esta memoria. Lo que se pretendı́a era realizar
una aplicación que pudiera ser utilizada en la práctica, de modo que era deseable suscribir
al máximo posible las citadas recomendaciones.
Para los dos sistemas desarrollados se han realizado sendas aplicaciones de control
desde PC en el entorno Labwindows CVI. Por sencillez, economı́a y facilidad de uso se ha
escogido como método de control el puerto paralelo del PC, para ası́ favorecer su utilización
en un entorno portátil si se desean realizar medidas de campo.

ii
Índice general

1. La sı́ntesis digital directa 4


1.1. Teorı́a de operación . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5
1.2. Espectro de salida . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 7
1.3. Capacidad de sintonı́a en fase y frecuencia de los DDS . . . . . . . . . . . . 10
1.3.1. Sintonı́a en frecuencia . . . . . . . . . . . . . . . . . . . . . . . . . . 10
1.3.2. Velocidad de cambio de sintonı́a . . . . . . . . . . . . . . . . . . . . 11
1.3.3. Registros adicionales preprogramados . . . . . . . . . . . . . . . . . 12
1.4. Efecto del DAC en sistemas DDS . . . . . . . . . . . . . . . . . . . . . . . . 12
1.4.1. Conversores D/A de alta velocidad . . . . . . . . . . . . . . . . . . . 13
1.4.2. Conversores A/D de alta velocidad . . . . . . . . . . . . . . . . . . . 15
1.4.2.1. Parámetros de los dispositivos de conversión . . . . . . . . 15
1.4.2.2. Efectos del “jitter” de apertura y del reloj de muestreo . . 19
1.4.2.3. Arquitectura de conversores A/D de alta velocidad . . . . . 19
1.4.3. Efecto del sobremuestreo en el nivel de ruido de cuantificación . . . 22
1.5. Efecto del truncamiento del acumulador de fase . . . . . . . . . . . . . . . . 23
1.5.1. Magnitud de los espúreos por truncamiento de fase . . . . . . . . . . 24
1.5.2. Distribución espectral de los espúreos por truncamiento de fase . . . 26
1.5.3. Resumen del truncamiento de fase . . . . . . . . . . . . . . . . . . . 29
1.6. Otras fuentes de espúreos en un sistema DDS . . . . . . . . . . . . . . . . . 30
1.7. Consideraciones sobre el filtrado de salida . . . . . . . . . . . . . . . . . . . 31
1.8. Caracterı́sticas de salida de los sistemas DDS . . . . . . . . . . . . . . . . . 35
1.8.1. Acoplamiento con transformador simétrico . . . . . . . . . . . . . . . 36
1.8.2. Consideraciones sobre la potencia de salida . . . . . . . . . . . . . . 37
1.8.3. Terminación de salida del DDS-DAC . . . . . . . . . . . . . . . . . . 37
1.9. Modulación digital con DDS . . . . . . . . . . . . . . . . . . . . . . . . . . . 38
1.9.1. Requerimientos y arquitectura del sistema . . . . . . . . . . . . . . . 39
1.9.2. Filtros digitales . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 40
1.9.2.1. Filtros FIR . . . . . . . . . . . . . . . . . . . . . . . . . . . 41
1.9.2.2. Filtros IIR . . . . . . . . . . . . . . . . . . . . . . . . . . . 43
1.9.3. Procesado DSP a varias velocidades . . . . . . . . . . . . . . . . . . 44
1.9.3.1. Interpolación . . . . . . . . . . . . . . . . . . . . . . . . . . 45
1.9.3.2. Decimado . . . . . . . . . . . . . . . . . . . . . . . . . . . . 46
1.9.3.3. Conversión de velocidad racional n/m . . . . . . . . . . . . 47
1.9.3.4. Filtros digitales multivelocidad . . . . . . . . . . . . . . . . 48
1.9.3.5. Consideraciones acerca del sincronismo entre el reloj y los
datos de entrada . . . . . . . . . . . . . . . . . . . . . . . . 52
1.10. Evolución y técnicas auxiliares en los DDS . . . . . . . . . . . . . . . . . . . 52

iii
1.10.1. Mejora del Margen Libre de Espúreos mediante dithering de fase . . 53
1.10.2. Generación de barridos “chirp” mediante DDS . . . . . . . . . . . . 55
1.10.3. Generación de modulación de amplitud mediante DDS . . . . . . . . 56
1.10.4. Funcionalidades adicionales en DDS . . . . . . . . . . . . . . . . . . 57
1.10.5. Chips DDS comerciales . . . . . . . . . . . . . . . . . . . . . . . . . 59

2. Secuencias pseudoaleatorias y registros de desplazamiento 62


2.1. Secuencias con propiedades de aleatoriedad . . . . . . . . . . . . . . . . . . 63
2.1.1. Propiedades de las secuencias aleatorias . . . . . . . . . . . . . . . . 63
2.2. Secuencias generadas mediante registros de desplazamiento . . . . . . . . . 64
2.2.1. Funciones generadoras . . . . . . . . . . . . . . . . . . . . . . . . . . 66
2.2.2. Determinación del perı́odo . . . . . . . . . . . . . . . . . . . . . . . . 68
2.2.2.1. Una condición necesaria para longitud máxima . . . . . . . 68
2.2.3. El método matricial . . . . . . . . . . . . . . . . . . . . . . . . . . . 69
2.3. Polinomios módulo 2 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 70
2.3.1. Periodos primos de Mersenne . . . . . . . . . . . . . . . . . . . . . . 70
2.3.2. Las funciones de Euler y de Möbious . . . . . . . . . . . . . . . . . . 70
2.3.3. Número de polinomios irreducibles . . . . . . . . . . . . . . . . . . . 71
2.3.4. Periodos mas pequeños . . . . . . . . . . . . . . . . . . . . . . . . . 73
2.4. Aleatoriedad de las secuencias de registros de desplazamiento . . . . . . . . 73
2.4.1. Propiedad de balance . . . . . . . . . . . . . . . . . . . . . . . . . . 73
2.4.2. Propiedad de realización . . . . . . . . . . . . . . . . . . . . . . . . . 74
2.4.3. Propiedad de correlación . . . . . . . . . . . . . . . . . . . . . . . . . 74
2.5. Resumen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 75

3. Medidas de calidad 76
3.1. La Recomendación G.821 ITU . . . . . . . . . . . . . . . . . . . . . . . . . 76
3.2. Asignación de los objetivos G.821 . . . . . . . . . . . . . . . . . . . . . . . . 79
3.3. Especificaciones G.821 para otras velocidades . . . . . . . . . . . . . . . . . 81

4. Modulador DDS 83
4.1. Especificaciones de la placa DDS . . . . . . . . . . . . . . . . . . . . . . . . 84
4.2. Diseño hardware de la placa DDS . . . . . . . . . . . . . . . . . . . . . . . . 87
4.2.1. El modulador AD9853 . . . . . . . . . . . . . . . . . . . . . . . . . . 87
4.2.1.1. Filtrado de datos (FIR + etapas interpoladoras) . . . . . . 91
4.2.2. Bloques funcionales de la placa DDS . . . . . . . . . . . . . . . . . . 97
4.2.2.1. Puerto paralelo de control . . . . . . . . . . . . . . . . . . . 98
4.2.2.2. Buffer de control y datos . . . . . . . . . . . . . . . . . . . 99
4.2.2.3. Modulador DDS . . . . . . . . . . . . . . . . . . . . . . . . 100
4.2.2.4. Generador de reloj de bit . . . . . . . . . . . . . . . . . . . 102
4.2.2.5. Oscilador de referencia . . . . . . . . . . . . . . . . . . . . 105
4.2.2.6. Salida de FI . . . . . . . . . . . . . . . . . . . . . . . . . . 106
4.2.2.7. Entrada-salida de datos . . . . . . . . . . . . . . . . . . . . 107
4.2.2.8. Alimentación . . . . . . . . . . . . . . . . . . . . . . . . . . 108
4.3. Software de control . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 109
4.3.1. Módulo principal mod.c . . . . . . . . . . . . . . . . . . . . . . . . . 109
4.3.1.1. Función ValorDiv . . . . . . . . . . . . . . . . . . . . . . . 111
4.3.1.2. Función ValorFirAx . . . . . . . . . . . . . . . . . . . . . . 112

iv
4.3.2. Módulo de funciones hardware mod hard.c . . . . . . . . . . . . . . 113
4.3.2.1. Función prog hard . . . . . . . . . . . . . . . . . . . . . . . 113
4.3.2.2. Función interpolador . . . . . . . . . . . . . . . . . . . . . 113
4.4. Resultados prácticos . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 115

5. Generador medidor de tasa de bits erróneos 121


5.1. Opciones de diseño . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 121
5.2. Especificaciones de la placa BER . . . . . . . . . . . . . . . . . . . . . . . . 123
5.3. Diseño hardware de la placa BER . . . . . . . . . . . . . . . . . . . . . . . . 124
5.3.1. Composición interna del DS2172 . . . . . . . . . . . . . . . . . . . . 125
5.3.1.1. Configuración del registro de desplazamiento . . . . . . . . 127
5.3.2. Bloques funcionales de la placa de BER . . . . . . . . . . . . . . . . 130
5.3.2.1. Puerto paralelo de control . . . . . . . . . . . . . . . . . . . 131
5.3.2.2. Buffer de control . . . . . . . . . . . . . . . . . . . . . . . . 131
5.3.2.3. Buffer de datos . . . . . . . . . . . . . . . . . . . . . . . . . 133
5.3.2.4. Medidor de BER DS2172 . . . . . . . . . . . . . . . . . . . 134
5.3.2.5. Conector de transmisión-recepción . . . . . . . . . . . . . . 136
5.3.2.6. Alimentación . . . . . . . . . . . . . . . . . . . . . . . . . . 138
5.4. Software de control . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 138
5.4.1. Módulo principal ber.c . . . . . . . . . . . . . . . . . . . . . . . . . . 139
5.4.1.1. Función principal bucle . . . . . . . . . . . . . . . . . . . . 139
5.4.2. Módulo de funciones hardware ber hard.c . . . . . . . . . . . . . . . 140
5.4.2.1. Función lee par bert . . . . . . . . . . . . . . . . . . . . . . 141
5.4.2.2. Función escribe par bert . . . . . . . . . . . . . . . . . . . 142
5.4.2.3. Función aplicacion bert . . . . . . . . . . . . . . . . . . . . 142
5.5. Resultados prácticos . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 143
5.6. Mejoras futuras . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 144

A. El puerto paralelo del PC 147


A.1. Generalidades . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 147
A.2. Propiedades de la interfaz fı́sica . . . . . . . . . . . . . . . . . . . . . . . . . 149
A.3. Direcciones del puerto paralelo . . . . . . . . . . . . . . . . . . . . . . . . . 150
A.4. Registros software . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 150
A.5. Utilización particular en la aplicación . . . . . . . . . . . . . . . . . . . . . 153

B. Fotografı́as del montaje 155

C. Listados fuente 159


C.1. Aplicación modulAD . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 159
C.2. Aplicación mediBER . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 197
C.3. Ficheros de Matlab . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 227

v
Índice de figuras

1.1. Esquema interno de un NCO . . . . . . . . . . . . . . . . . . . . . . . . . . 5


1.2. Flujo de señal a través de la arquitectura DDS . . . . . . . . . . . . . . . . 6
1.3. Rueda digital de fase . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 6
1.4. Reconstrucción de la señal a la salida del convertidor D/A . . . . . . . . . . 7
1.5. Ejemplo de señal analógica y sus diversos tipos de muestreo . . . . . . . . . 8
1.6. Espectro resultante para los diferentes tipos de muestreo práctico . . . . . . 9
1.7. Espectro positivo teórico de salida de un sistema DDS . . . . . . . . . . . . 10
1.8. Cambios de frecuencia en la arquitectura DDS . . . . . . . . . . . . . . . . 11
1.9. Estructura completa de un dispositivo DDS . . . . . . . . . . . . . . . . . . 13
1.10. Estructuras de los conversores D/A . . . . . . . . . . . . . . . . . . . . . . . 13
1.11. Degradación del margen libre de espúreos en un D/A . . . . . . . . . . . . . 14
1.12. Espectro de salida de un conversor D/A . . . . . . . . . . . . . . . . . . . . 15
1.13. Espectro de la FFT . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 17
1.14. Potencia equivalente de ruido (NPR) . . . . . . . . . . . . . . . . . . . . . . 19
1.15. Relación S/N en función del “jitter” de apertura y del reloj de muestreo . . 20
1.16. Conversor de subrango de 8 bits . . . . . . . . . . . . . . . . . . . . . . . . 21
1.17. Conversor A/D serie . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 21
1.18. El efecto del sobremuestreo sobre el ruido de cuantificación . . . . . . . . . 22
1.19. Rueda de fase y Error por truncamiento de fase . . . . . . . . . . . . . . . . 23
1.20. Relación del Truncamiento de fase con los espúreos generados . . . . . . . . 25
1.21. Secuencia seguida por el acumulador de fase . . . . . . . . . . . . . . . . . . 27
1.22. Comportamiento de la palabra de truncamiento . . . . . . . . . . . . . . . . 28
1.23. Espectro de los espúreos producidos por el truncamiento de fase . . . . . . 29
1.24. Efecto del desdoblamiento de los armónicos por el aliasing . . . . . . . . . . 30
1.25. Glitches a la salida de un DAC . . . . . . . . . . . . . . . . . . . . . . . . . 31
1.26. Filtro antialiasing . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 32
1.27. Respuestas de la familia Chevyshev . . . . . . . . . . . . . . . . . . . . . . . 33
1.28. Respuestas de la familia Gausiana . . . . . . . . . . . . . . . . . . . . . . . 34
1.29. Respuesta de la familia Legendre . . . . . . . . . . . . . . . . . . . . . . . . 35
1.30. Combinación de salidas complementarias en un DDS-DAC . . . . . . . . . . 36
1.31. Acoplo de cargas reactivas a la salida del conjunto DDS-DAC . . . . . . . . 37
1.32. Estructuras de modulación básicas en el dominio temporal . . . . . . . . . . 38
1.33. Estructuras de modulación básicas digitales . . . . . . . . . . . . . . . . . . 39
1.34. Estructuras de modulación básicas DDS . . . . . . . . . . . . . . . . . . . . 39
1.35. Modulador DDS . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 40
1.36. Filtro FIR básico . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 41
1.37. Respuesta FIR de ejemplo . . . . . . . . . . . . . . . . . . . . . . . . . . . . 42
1.38. Filtro FIR generalizado . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 42

vi
1.39. Filtro IIR básico . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 43
1.40. Filtro IIR generalizado . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 44
1.41. Interpolador básico . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 45
1.42. Visión en el dominio frecuencial de la interpolación . . . . . . . . . . . . . . 46
1.43. Decimador básico . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 46
1.44. Visión en el dominio frecuencial de la decimación . . . . . . . . . . . . . . . 47
1.45. Convertidor de velocidad de muestreo n/m básico . . . . . . . . . . . . . . . 48
1.46. Etapas básicas de los bloques filtro peine e integrador . . . . . . . . . . . . 49
1.47. Respuesta en frecuencia de los bloques básicos del filtro peine y del integrador 49
1.48. CIC funcionando de interpolador y de decimador . . . . . . . . . . . . . . . 49
1.49. Respuesta en frecuencia del filtro CIC básico . . . . . . . . . . . . . . . . . 50
1.50. Variaciones al bloque CIC básico . . . . . . . . . . . . . . . . . . . . . . . . 51
1.51. Comparación de las respuestas CIC modificadas . . . . . . . . . . . . . . . . 51
1.52. Diagrama de bloques de un modulador DDS genérico . . . . . . . . . . . . . 52
1.53. Compresión de la memoria ROM . . . . . . . . . . . . . . . . . . . . . . . . 53
1.54. Diagrama de bloques de un DDS genérico . . . . . . . . . . . . . . . . . . . 54
1.55. Dithering de fase en un DDS . . . . . . . . . . . . . . . . . . . . . . . . . . 54
1.56. Sistema Chirp basado en DDS . . . . . . . . . . . . . . . . . . . . . . . . . 55
1.57. DDS con control de amplitud . . . . . . . . . . . . . . . . . . . . . . . . . . 56
1.58. Prestaciones añadidas en un sistema DDS . . . . . . . . . . . . . . . . . . . 57
1.59. Modulaciones de fase en un dispositivo DDS . . . . . . . . . . . . . . . . . . 58

2.1. Ejemplo de registro de desplazamiento con realimentación lineal . . . . . . . 65


2.2. Función de autocorrelación de la secuencia pseudoaleatoria de ejemplo . . . 67

3.1. Consideración de los errores en la determinación del tiempo de disponibilidad 77


3.2. Tiempo de disponibilidad en un enlace . . . . . . . . . . . . . . . . . . . . . 77
3.3. Términos de la recomendación G.821 . . . . . . . . . . . . . . . . . . . . . . 78
3.4. La conexión hipotética de referencia según la recomendación G.821 . . . . . 79

4.1. Puentes de configuración hardware en la placa DDS . . . . . . . . . . . . . 86


4.2. Diagrama de bloques del modulador DDS AD9853 . . . . . . . . . . . . . . 87
4.3. Funcionamiento del codificador Reed-Solomon . . . . . . . . . . . . . . . . . 89
4.4. Detalle de construcción de las etapas de interpolación en el AD9853 . . . . 91
4.5. Simulación en Matlab de respuestas impulsivas en coseno alzado . . . . . . 94
4.6. Compensación del efecto de la etapa CIC en el filtro FIR . . . . . . . . . . 96
4.7. Esquema de bloques de la placa DDS . . . . . . . . . . . . . . . . . . . . . . 97
4.8. Buffer de control y datos de la placa DDS . . . . . . . . . . . . . . . . . . . 99
4.9. El circuito AD9853 y su conexionado en la placa DDS . . . . . . . . . . . . 101
4.10. Selector JP2 de habilitación de transmisión . . . . . . . . . . . . . . . . . . 101
4.11. Esquema del generador de reloj de bit . . . . . . . . . . . . . . . . . . . . . 102
4.12. Formas de onda de salida del generador de reloj de bit . . . . . . . . . . . . 104
4.13. Oscilador interno de referencia y jumper JP1 de selección de reloj maestro . 106
4.14. Filtro antialiasing de salida en la placa DDS . . . . . . . . . . . . . . . . . . 107
4.15. Conector de entrada de datos de la placa DDS . . . . . . . . . . . . . . . . 107
4.16. Reguladores de alimentación independientes en la placa DDS . . . . . . . . 109
4.17. Distintas pantallas de la aplicación de control modulAD . . . . . . . . . . . 110
4.18. Protocolo hardware del puerto serie en el AD9853 . . . . . . . . . . . . . . 113
4.19. Placa DDS y placa de BER trabajando conjuntamente . . . . . . . . . . . . 115

vii
4.20. Medidas de salida realizadas con analizador vectorial HP89410A . . . . . . 116
4.21. Medidas de los espúreos de truncamiento de fase de salida . . . . . . . . . . 117
4.22. Medidas en banda ancha para QPSK con imágenes generadas por el proceso
de conversión D/A. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 118
4.23. Medidas en banda ancha para FSK sin filtro antialiasing . . . . . . . . . . . 118
4.24. Efecto del filtro antialiasing de salida. . . . . . . . . . . . . . . . . . . . . . 119
4.25. Espectro cercano para los tres tipos de modulaciones principales. . . . . . . 120

5.1. Diagrama de bloques del integrado medidor de BER DS2172 . . . . . . . . 126


5.2. Registro de desplazamiento para generación de secuencias en el DS2172 . . 127
5.3. Diagrama de bloques de la placa de BER . . . . . . . . . . . . . . . . . . . 131
5.4. Buffer de control de la placa de BER . . . . . . . . . . . . . . . . . . . . . . 132
5.5. Buffer de datos de la placa de BER . . . . . . . . . . . . . . . . . . . . . . . 134
5.6. El DS2172 y su conexionado en la placa de BER . . . . . . . . . . . . . . . 135
5.7. Entrada salida de señales en la placa de BER . . . . . . . . . . . . . . . . . 137
5.8. Regulador de alimentación de la placa de BER . . . . . . . . . . . . . . . . 138
5.9. Entorno gráfico de la aplicación de control mediBER . . . . . . . . . . . . . 139
5.10. Conexión de la placa de BER para la simulación de una medida . . . . . . . 143
5.11. Diversos tipos de secuencias generadas en la placa de BER . . . . . . . . . . 145

A.1. Conexionado externo para lectura de datos en el puerto paralelo del PC . . 148
A.2. Hardware interno del PC en puertos bidireccionales . . . . . . . . . . . . . . 152
A.3. Utilización particular del puerto paralelo en nuestra aplicación . . . . . . . 154

B.1. Vista general del montaje que contiene las placas DDS y BER . . . . . . . . 156
B.2. Vista interior donde se pueden distinguir las dos placas . . . . . . . . . . . 156
B.3. Vista lateral con los conectores de IF y de entrada/salida de datos . . . . . 157
B.4. Vista lateral con los conectores de control y alimentación . . . . . . . . . . 158

viii
Índice de cuadros

1.1. “Estado del Arte” de la tecnologı́a DDS comercial (1999) . . . . . . . . . . 59

2.1. Primos de Mersenne: 2p − 1. Primeros 23 valores de p. . . . . . . . . . . . . 71


2.2. Funciones φ y µ tabuladas hasta para n = 50 . . . . . . . . . . . . . . . . . 72
2.3. Funciones ψ y λ tabuladas hasta r = 24 . . . . . . . . . . . . . . . . . . . . 73

3.1. Objetivos máximos de servicio defectuoso según G.821 . . . . . . . . . . . . 78


3.2. Asignación de objetivos de minutos degradados y segundos erróneos . . . . 80
3.3. Distribución del 0.1 % de segundos severamente erróneos . . . . . . . . . . . 80
3.4. Clasificación de calidad de sección digital . . . . . . . . . . . . . . . . . . . 81

4.1. Función de los puentes hardware de la placa DDS . . . . . . . . . . . . . . . 85


4.2. Coeficientes del filtro FIR sin compensar . . . . . . . . . . . . . . . . . . . . 93
4.3. Coeficientes del filtro FIR compensados . . . . . . . . . . . . . . . . . . . . 96
4.4. Interface paralelo de la placa DDS. . . . . . . . . . . . . . . . . . . . . . . . 98
4.5. Sumario de velocidades de bit generadas en la placa DDS . . . . . . . . . . 105

5.1. Descripción matemática de las secuencias generadas en la placa de BER . . 129


5.2. Descripción de las secuencias repetitivas programadas en la placa de BER. . 130
5.3. Interface entre la placa BER y el puerto paralelo del PC. . . . . . . . . . . 132

A.1. Hilos del puerto paralelo del PC . . . . . . . . . . . . . . . . . . . . . . . . 149


A.2. Posiciones de la BIOS que almacenan las direcciones de I/O de LPTs . . . . 150
A.3. Puerto de datos . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 151
A.4. Puerto de estado . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 151
A.5. Puerto de control . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 152
A.6. Puerto paralelo en la aplicación . . . . . . . . . . . . . . . . . . . . . . . . . 153

B.1. Conector de interface de la placa DDS . . . . . . . . . . . . . . . . . . . . . 157


B.2. Conector de interface de la placa BER . . . . . . . . . . . . . . . . . . . . . 157
B.3. Pines del conector al puerto paralelo . . . . . . . . . . . . . . . . . . . . . . 158
B.4. Conector de alimentación . . . . . . . . . . . . . . . . . . . . . . . . . . . . 158

ix
Introducción

En la era de la información en que vivimos, y dado que la naturaleza de la mayorı́a de


la misma, por no decir la práctica totalidad, es digital, la actual tendencia de desarrollo
tecnológico se ha ido dirigiendo claramente desde hace años hacia el procesado digital
de señal. Sin embargo, hasta hace poco tiempo, la “limpieza” que suponı́a el realizar las
operaciones a nivel teórico en el dominio digital se veı́a devaluada por el elevado coste
de los circuitos prácticos unido a su considerable consumo. Esto reducı́a el margen de
empleo de las técnicas DSP (Procesado Digital de la Señal) al rango de aplicaciones de
baja frecuencia.
Actualmente la situación ha cambiado de manera radical, pues el DSP más avanzado
de Texas está ya sobre los 800 MIPS (los modelos TMS320C55xx) haciendo gala de unos
rendimientos de 0.05 mw/MIPS, con lo que se puede ver que la industria se está volcando
es este campo. Lo mismo sucede en la rama de la sı́ntesis digital directa, donde se ha
conseguido integrar el núcleo DDS junto a DACs exhibiendo un excelente comportamiento
dinámico, bajo consumo, tamaño y precio.
Tradicionalmente la aplicación más corriente e inmediata de la sı́ntesis digital directa
ha sido en sintetizadores de señal como sustitución de los tradicionales PLLs analógicos.
A medida que ha ido avanzando el grado de integración de estos circuitos, los fa-
bricantes han añadido filtros digitales y otras funcionalidades DSP a los mismos. De esta
manera, ya podemos encontrar todo tipo de sistemas como moduladores y demoduladores
integrados en un sólo chip, que dan lugar a aplicaciones prácticas más compactas y de
menor consumo, liberando ası́ de carga computacional a los controladores.
Este trabajo hace un repaso a la tecnologı́a de la sı́ntesis digital directa mostrando
el actual “estado del arte” de esta especialidad, a la vez que se desarrolla un sistema de
utilidad práctica en el laboratorio.
Por otra parte se ha realizado otro sistema como fuente de señal de datos para
el montaje DDS. Lo que en un principio iba a ser una pequeña aplicación, al final ha
resultado tener casi la misma entidad que el sistema principal. Por esta razón, no se
considera desacertado incluir en la memoria un pequeño capı́tulo que repase las bases de
este “sistema auxiliar”.
Se trata de una introducción sobre las secuencias generadas en registros de despla-
zamiento realimentados. Constituye un intento de animar al lector a profundizar en el
conocimiento de las secuencias pseudoleatorias y los polinomios primitivos, pues a pesar
de ser un tema poco novedoso, no es fácil encontrar información ordenada sobre el mismo.
Personalmente, este interés resurgió durante el diseño de la placa de generación de medida
de BER.

1
2

Organización de la memoria
El trabajo se ha organizado en dos partes principales:

Descripciones Teóricas.
Comprenden los 3 primeros capı́tulos, y en ellos se resumen los fundamentos teóricos
de aplicación en los dos montajes del trabajo.
El capı́tulo 1 es el principal componente de este bloque teórico. En él se comentan
los aspectos principales de las técnicas de sı́ntesis digital directa (DDS) haciendo
especial incapié en los procesos de conversión D/A [?]. Como complemento a la
descripción teórica, se ha realizado una labor de recopilación de datos y comparativa
entre algunos de los chips que implementan técnicas DDS de entre los principales
fabricantes [?].
A continuación, el capı́tulo 2 contiene una descripción particularmente interesante
de las caracterı́sticas matemáticas de las secuencias pseudoaleatorias recogidas prin-
cipalmente de [?]. Por último, en el capı́tulo 3 se recogen las precisiones principales
establecidas por la UIT para la realización de medidas de calidad en los enlaces de
datos, obtenidas de las recomendaciones [?] y [?].
Diseño Práctico.
La segunda mitad del trabajo comprende dos capı́tulos que constituyen la memoria
de las mismas aplicaciones prácticas. En ellos se comenta el funcionamiento indivi-
dual de cada circuito incluyendo esquemáticos, y también se hace una descripción
del software de control desarrollado para cada placa.
El capı́tulo 4 está dedicado a la placa PCB donde se ha montado un modulador DDS.
Se trata de un modulador digital QPSK, FSK y 16QAM, con un margen de frecuencia
de salida de hasta 65 Mhz y diversas funcionalidades integradas que se verán durante
su exposición. Entre estas, podemos destacar la inclusión dentro del chip DDS de un
filtro de datos FIR, que permite la realización de gran cantidad de caracterı́sticas de
filtrado en el dominio digital. La aplicación de control del modulador digital dispone
de una pantalla donde se pueden cambiar los coeficientes del filtro. Para servir de
ayuda en el cálculo de los mismos se realiza un ejercicio en Matlab de cálculo de los
coeficientes de un filtro FIR con una curva de respuesta en coseno alzado.
El capı́tulo 5 corresponde a la placa de circuito impreso donde se ha implementado
un generador de secuencias pseudoaleatorias. Este diseño, construido como apoyo de
la placa de modulación DDS, constituye por sı́ mismo un montaje independiente que
puede utilizarse por separado para la medida de tasa de bits erróneos. El programa de
control suministra información sobre los parámetros más importantes recomendados
por la UIT para la realización de medidas de calidad en enlaces. Entre ellos podemos
destacar el número de segundos con errores, los segundos severamente erróneos, y
por supuesto, la tasa de BER del canal bajo prueba.
Las secuencias generadas en la parte de transmisión de este circuito se utilizarán
como señal de información en la placa de modulación DDS sirviendo como trama
digital de entrada al mismo.
Durante la exposición de estos capı́tulos se presentan medidas variadas obtenidas
con diferentes equipos de laboratorio tales como analizador de espectros, analizador
vectorial y osciloscopio.
3

Para finalizar, se presentan tres apéndices con información adicional. El apéndice A


contiene una breve descripción teórica del funcionamiento del puerto paralelo en el PC,
los diversos registros que son de interés para el programador, y unos pocos conceptos
referentes a su construcción hardware. Todo ello para entender mejor el modo en que se
ha desarrollado la interface de control del sistema.
En el apéndice B se muestran diversas fotografı́as presentando el aspecto real de los
circuitos y el chasis donde se ha mecanizado todo el conjunto, y también se han incluido
unas tablas recopilando las funciones de cada terminal en los diversos conectores a los que
tiene acceso el usuario.
Por último, en el apéndice C se han incluido los códigos fuente de las aplicaciones
de control realizadas en Labwindows CVI.
Capı́tulo 1

La sı́ntesis digital directa

La Sı́ntesis Digital Directa (DDS) se puede definir como un medio de generar señales
a partir de representaciones digitales armónicamente puras y altamente precisas. Esta
representación digital es posteriormente reconstruida mediante un convertidor Digital-
Analógico de alta velocidad, para proporcionar una señal de salida analógica, tı́picamente
un tono sinusoidal o una secuencia de tonos. Como en estos dispositivos la señal se procesa
de forma digital, su generación es fácilmente configurable mediante software, haciendo más
amplia su gama de utilidades.
Actualmente se encuentran disponibles una amplia gama de DACs de altas presta-
ciones con los que se consiguen espúreos de potencia extremadamente baja a la salida del
conjunto DDS-DAC.
Las técnicas DDS ofrecen prestaciones únicas en contraste con los otros métodos
de sı́ntesis. Aunque se encuentran limitados por el criterio de Nyquist (hasta 1/2 de la
frecuencia del reloj aplicado como referencia), la técnica DDS permite un control en la
resolución de frecuencia del orden de milihertzios, al igual que con la resolución en fase,
donde es fácil obtener resoluciones de 0.02o en los dispositivos comerciales.
Adicionalmente, las técnicas DDS no imponen restricciones de tiempo de estableci-
miento (settling time) en cambios de frecuencia, salvo los requeridos por el control digital.
Como resultado se consiguen frecuencias de conmutación extremadamente elevadas, del
orden de nanosegundos.
Todos los cambios de frecuencia se realizan automáticamente sin discontinuidad
de fase. Como la señal se genera en el dominio digital, el proceso se puede manipular
con excepcional precisión. Esto permite un control preciso tanto de la fase como de la
frecuencia, consiguiéndose fácilmente las modulaciones PSK ó FSK.
Si se desea, un sistema controlado por microprocesador se puede utilizar para alma-
cenar datos de compensación de frecuencia en lazo abierto de un dispositivo particular o
de algún parámetro del sistema. El microprocesador puede controlar el DDS para corregir
de forma dinámica la frecuencia según se necesite. Con un detector de frecuencia adecuado
en un sistema de recepción, se puede construir fácilmente un sistema de lazo cerrado.
En resumen, podemos enumerar las ventajas de las técnicas DDS:

Resolución en frecuencia muy elevada (hasta órdenes de µHz, y también en fase


(mejor del orden de un grado), todo bajo control digital.

Extremada velocidad de “salto de frecuencia o fase”, cambios de frecuencia continuos


en fase y sin problemas de transitorios como ocurre en los sintetizadores analógicos.

4
1.1 Teorı́a de operación 5

Eliminación de los problemas relacionados con los retoques y la sintonı́a fina manual
ocasionados por el envejecimiento de componentes y derivas de temperatura tı́picos
de los sintetizadores analógicos.

Control digital del sistema, con las ventajas que esto conlleva: posibilidad de control
remoto, ajuste optimizado, y cualquier aplicación que se nos pueda ocurrir bajo
control de un microprocesador.

Cuando se utilizan como sintetizadores en cuadratura, posibilidad de afrontar ajustes


y controles independientes para cada canal I y Q.

1.1. Teorı́a de operación

Un DDS está formado básicamente por un contador de elevado número de bits que
direcciona una memoria ROM en la que se han almacenado los valores de amplitud de una
función del tipo seno o coseno. La salida de la memoria va directamente a un convertidor
D/A el cual transforma los “números” almacenados en la memoria en valores de tensión,
reconstruyendo ası́ la señal analógica.
El problema fundamental con esta arquitectura es que para cambiar la frecuencia
de salida es necesario cambiar la frecuencia de reloj, lo que es un método poco práctico.
Para evitar esto, se emplea una técnica hardware muy eficiente que se denomina Oscilador
Controlado Numéricamente (NCO). Un diagrama de bloques de esta técnica se puede ver
en la figura 1.1.

Figura 1.1: Esquema interno de un NCO

El corazón del sistema es el acumulador de fase cuyos contenidos se actualizan una


vez por ciclo de reloj. Cada pulso de reloj, el número digital almacenado en el registro de
fase se incrementa con el valor almacenado en el registro de incremento de fase M. Por lo
tanto, puesto que el acumulador es de un elevado número de bits, por ejemplo N = 32
bits, se necesitan 232 ciclos de reloj (más de 4000 millones) para que el acumulador genere
un ciclo completo.
Otra forma de entender la función del acumulador de fase es observando la figura 1.3,
donde se puede considerar la oscilación de salida como un vector girando a velocidad
constante alrededor de un cı́rculo de fase (la velocidad de giro será la del reloj de referencia).
Cada punto del cı́rculo de fase se corresponde con un punto equivalente de un ciclo de la
1.1 Teorı́a de operación 6

Figura 1.2: Flujo de señal a través de la arquitectura DDS

función seno. El acumulador de fase se utiliza para “direccionar” cada uno de los puntos
del cı́rculo y la palabra de sintonı́a M determina el salto del vector en cada pulso de
reloj. La resolución del acumulador N determina el número de puntos en que se divide la
“rueda”.

Figura 1.3: Rueda digital de fase

Para transformar la salida lineal del acumulador de fase en cualquier tipo de ampli-
tud, normalmente senoidal, se necesita una tabla de referencia, generalmente en memoria
ROM. Existen técnicas para ahorrar memoria en esta tabla, por ejemplo el explotar la si-
metrı́a de la forma de onda senoidal, de manera que sólo se guardan los valores de amplitud
correspondientes a 1/4 de ciclo y por medio de los 2 bits más significativos se determina
el cuadrante de situación: el más significativo directamente indica el signo de la amplitud
al DAC, mientras que el segundo determina la forma de recorrer la tabla de referencia.
El acumulador de fase es un contador módulo N que incrementa su valor cada vez
que recibe un pulso de reloj. La magnitud de ese incremento depende de la palabra de
sintonı́a M cargada en el “registro de incremento de fase”. Este registro es el que determina
la cantidad de puntos que se avanzan en cada salto de la rueda de fase. Por tanto si M = 1
la frecuencia del reloj de referencia se divide por 232 (continuando con el ejemplo anterior
de N = 32), si M = 2 por la mitad, y ası́ sucesivamente. De acuerdo con esto, la frecuencia
de salida vale:
1.2 Espectro de salida 7

M · fclk
Fout = (1.1)
2N
Ecuación conocida como de sintonı́a básica del NCO, siendo la resolución en fre-
cuencia:

fclock
∆f = (1.2)
2N
Como la resolución del convertidor D/A de salida está limitada a 12 ó 14 bits, la
salida del acumulador se trunca a los 13 - 15 bits más significativos. Esto reduce el tamaño
de la tabla de referencia y no afecta a la resolución en frecuencia. El truncamiento de fase
solamente añade una cierta cantidad de ruido de fase a la salida del circuito.
La resolución del convertidor D/A es tı́picamente 2 a 4 bits menor que el ancho de
la tabla de referencia, siendo los espúreos generados por el truncamiento del acumulador
inferiores a 90 dBc, [?] y [?], para el caso de emplear 15 bits en el acumulador, valor
superior a las prestaciones que ofrecen los mejores convertidores D/A.

1.2. Espectro de salida

Para entender más fácilmente el espectro de la forma de onda que se genera a la


salida del convertidor D/A, en la figura 1.4 se incluye una representación de lo que serı́a
un ciclo de onda senoidal reconstruida a la salida del mismo:

Figura 1.4: Reconstrucción de la señal a la salida del convertidor D/A

Dado que por mucha resolución que quiera tener un DAC, ésta va a ser siempre
limitada, a su salida la señal siempre tendrá la forma de onda tı́pica con escalones de
amplitud equiespaciados un perı́odo de tiempo igual a la frecuencia de reloj del sistema,
que es la frecuencia a la que se actualiza.
Comparando las figuras 1.4 y 1.5, se puede deducir que la salida del convertidor
es equivalente al muestreo práctico instantáneo de la señal senoidal a reconstruir x(t),
por una señal muestreadora s(t) en forma de trenes de pulsos muestreadores p(t − nTs ),
llevando el caso al lı́mite en el que la duración del pulso es igual al periodo de muestreo;
en la figura corresponde al apartado (d).
El pulso muestreador y la señal muestreadora son:
Y t 

p(t) = (1.3)
Ts
1.2 Espectro de salida 8

Figura 1.5: Ejemplo de señal analógica y sus diversos tipos de muestreo


(a) Forma de onda analógica original
(b) Muestreo práctico natural
(c) Muestreo práctico instantáneo
(d) Muestreo práctico instantáneo de tipo sample and hold

X
s(t) = p(t − nTs ) (1.4)
n
resultando:

xsi (t) = x(t) · s(t) para t = nTs

X
xsi (t) = x(nTs ) · p(t − nTs ) (1.5)
n
que es lo mismo que:
" #
X
xsi (t) = p(t) ∗ x(t) · δ(t − nTs ) (1.6)
n
Realizando la transformada de Fourier encontramos el espectro de salida:

1 X m
Xsi (f ) = · P (f ) · X(f − ) (1.7)
Ts m
Ts
como

sen(πf Ts )
P (f ) = Ts · (1.8)
πf Ts
resulta el espectro de salida de la señal generada por el convertidor D/A:

sen(πf Tclk ) X m
XDAC (f ) = · X(f − ) (1.9)
πf Tclk m
Tclk
1.2 Espectro de salida 9

que corresponde al espectro de la señal muestreada, en nuestro caso la señal sinteti-


zada sen(ωt), repetida a intervalos iguales a la frecuencia de muestreo, el reloj del sistema
DDS, y conformado por la envolvente sinc(f Tclk ). La representación gráfica de este resul-
tado para una señal paso bajo generalizada la podemos apreciar el la figuras 1.6 (g) y (h),
donde se representa también el espectro resultante para los demás tipos de muestreo. El
resultado particular para un tono fijo se muestra en la figura 1.7.

Figura 1.6: Espectro resultante para los diferentes tipos de muestreo práctico

Según se puede apreciar, el proceso de construcción de la señal analógica por el


DAC produce por sı́ mismo la aparición de respuestas imagen alrededor de N · fclock ± fout .
También es de destacar la coincidencia de los nulos de la envolvente con los múltiplos de
la frecuencia de reloj del sistema. Para eliminar las componentes imagen, lo normal es
utilizar un filtro pasobajo externo con frecuencia de corte ligeramente inferior al ancho
de banda de Nyquist fclock /2 (por conveniencia práctica en los requerimientos del mismo,
normalmente el 40 % de fclock ).
Se puede calcular la caı́da de la curva de respuesta en un sistema DDS a causa de
la envolvente sinc(f Tclk ), resultando valer −3,92 dB desde DC hasta el ancho de banda
1.3 Capacidad de sintonı́a en fase y frecuencia de los DDS 10

Figura 1.7: Espectro positivo teórico de salida de un sistema DDS. No se


consideran las no-linealidades del mismo

de Nyquist. Las arquitecturas DDS actuales incluyen un filtro con curva caracterı́stica
x/sen(x) que compensa esta caı́da, dejando la respuesta en amplitud a la salida del con-
vertidor A/D prácticamente plana (±0,1 dB) sobre un ancho de banda igual al 45 % de la
frecuencia de reloj, equivalente al 80 % de Nyquist.
Es de destacar la gran amplitud de la primera frecuencia imagen, que para valores
de frecuencia de salida cercanos a Nyquist puede tener niveles de amplitud muy similares
a la componente fundamental. Es preciso, por tanto, realizar un estudio del margen de
frecuencias útiles según la aplicación particular, y especificar un filtro antialiasing apro-
piado.
El resto de imperfecciones del sistema tales como errores de linealidad, energı́a de
glitches asociada al convertidor D/A, acoplamiento de la frecuencia de reloj, etc, no siguen
la curva de caı́da sen(x)/x, dependiendo en este caso del layout del circuito impreso, la
calidad de la fuente de alimentación, la calidad del reloj de referencia, etc. De estos efectos
se hablará en las secciones siguientes.

1.3. Capacidad de sintonı́a en fase y frecuencia de los DDS

En principio, la frecuencia de salida del DDS es fácilmente controlable siguiendo las


ecuaciones 1.1 y 1.2 de sintonı́a del NCO. Veamos a continuación un ejemplo concreto
donde se emplean estas relaciones para conseguir una resolución en pasos de Hz exactos.

1.3.1. Sintonı́a en frecuencia


Por ejemplo, utilizando una frecuencia de reloj fclock = 227 = 134,217728 MHz, si
disponemos de un DDS con un registro de frecuencia de 32 bits (N=32), se puede generar
una frecuencia decimal exacta:

227
∆f = = 1Hz/25
232
Ahora sólo tenemos que calcular la palabra M de sintonı́a de frecuencia:

Fout = M · ∆f
1.3 Capacidad de sintonı́a en fase y frecuencia de los DDS 11

M = 25 = 20(h para fout = 1Hz


M= 26 = 40(h para fout = 2Hz
M = 96 = 60(h para fout = 3Hz
.. ..
. .
M = 1720583456 = 668E0520(h para fout = 53768233Hz

1.3.2. Velocidad de cambio de sintonı́a


Esta prestación es clave en aplicaciones en las que se requiere una máxima veloci-
dad de cambio de frecuencia como GMSK y FSK en “modo rampa”. Viene claramente
determinada por la velocidad máxima de la interface de control y por su configuración.
Existen muchos tipos de configuraciones para esta interface, tanto con carga paralelo
como su contrapartida serie. Se puede encontrar desde registros simples de 40 bits que
almacenan todas las palabras de configuración, hasta puertos de comunicaciones sı́ncronos
compatibles con algunos microprocesadores.
Obviamente será mucho más rápida una interface de tipo paralelo que una serie. La
desventaja está en el número de pines empleados, cuya cuenta aumenta considerablemente
en el caso de la interface paralelo.
Actualmente ya se encuentran DDS con control paralelo y velocidades de carga de
datos del orden de 100 MHz. Esto significa que se puede presentar una palabra de frecuencia
nueva a la salida del DDS cada ¡10ns!. La caracterı́stica de cambio de fase continua de
los dispositivos DDS los hace adecuados para aplicaciones de salto de frecuencias a alta
velocidad (frequency hopping).

(a)

(b)

Figura 1.8: Cambios de frecuencia en la arquitectura DDS


(a) Cambio de frecuencia en el acumulador de fase
(b) Detalle del cambio de frecuencia en la señal de salida

Existen dispositivos DDS con diversos registros adicionales que pueden programarse
con otras palabras de sintonı́a de frecuencia; el contenido de estos registros se ejecuta por
1.4 Efecto del DAC en sistemas DDS 12

medio de algún terminal externo del integrado, consiguiendose fácilmente la generación de


FSK. Utilizando estos registros preprogramados se pueden obtener velocidades de salto de
fase de hasta 250 MHz.
La velocidad de conmutación es un tema importante en muchos diseños de sintetiza-
dores. Un sintetizador se consideraba “rápido” cuando su tiempo de asentamiento era de
pocos milisegundos. La evolución de los sintetizadores analógicos-directos permitió conse-
guir el establecimiento en unos pocos microsegundos. Sin embargo, DDS es incuestiona-
blemente la técnica de conmutación más rápida.
Los diseños más lentos DDS incluyen técnicas pipeline que degradan la caracterı́stica
de conmutación. Cuando la velocidad de conmutación es una especificación crı́tica, la
velocidad del DDS puede ser tan rápida como un ciclo de reloj más el retardo añadido por
el filtro de salida. Algunos diseños DDS pueden conmutar a cualquier frecuencia dentro
de su ancho de banda en un ciclo de reloj.

1.3.3. Registros adicionales preprogramados


Aunque en la sección anterior nos hemos referido únicamente a la conmutación en
frecuencia, todo lo dicho sirve para la caracterı́stica de fase si el dispositivo DDS dispone
de un registro de fase entre el acumulador de fase y la memoria ROM del mismo.
En general, existen otros registros adicionales que no forman parte de la estructura
madre de un DDS, pero que aportan beneficios indudables a la hora de utilizarlos en
aplicaciones prácticas. Algunos de ellos ya se han nombrado, pero de nuevo se enumeran
todos a continuación, de forma que la estructura final de un dispositivo DDS genérico
puede ser la que se observa en la figura 1.9:

1. Registro adicional de sintonı́a de frecuencia (acumulador de fase). Seleccionando con


un terminal externo del DDS un registro u otro se consiguen fácilmente modulaciones
FSK.

2. Registro de control de fase cuyo contenido se suma al acumulador, permitiendo al


usuario comandar retardos de fase programados. La cantidad de retardo que se puede
programar varı́a desde 11.5o (5 bits), hasta ±0,02o (14 bits). Es la forma inmediata
de implementar modulaciones del tipo PSK.

3. Registro de control de amplitud. La salida de la memoria ROM se multiplica con


el contenido de este registro. Se toman los bits más significativos del resultado para
alimentar al DAC. De este modo obtenemos modulaciones de amplitud.

4. En otras arquitecturas DDS más especı́ficas como moduladores y convertidor ascen-


dentes digitales, se incluyen registros adicionales para realizar funciones tales como
filtros FIR, etapas de interpolación, ası́ como inversión espectral de la señal de salida.
Se tratarán en la sección 1.9.

1.4. Efecto del DAC en sistemas DDS

Los convertidores D/A son los que marcan las prestaciones de los sistemas DDS.
Dado que el sistema trabaja con representaciones de señales en el dominio digital, por
tanto perfectas en teorı́a y sin fuentes de ruido alguno, de el bloque de conversión D/A va
1.4 Efecto del DAC en sistemas DDS 13

Figura 1.9: Estructura completa de un dispositivo DDS equipado para todas


las funcionalidades

a depender en buena parte la calidad y el funcionamiento final del sistema. En esta sección
se van a analizar los distintos tipos de conversores existentes, sus prestaciones, problemas
prácticos, etc.

1.4.1. Conversores D/A de alta velocidad


Un conversor D/A está formado por una serie de fuentes de corriente que se conmu-
tan por medio de conmutadores analógicos para generar las distintas tensiones de salida,
como se puede ver en la figura 1.10.

Figura 1.10: Estructuras de los conversores D/A

Los problemas derivados de esta arquitectura son:

Resolución
1.4 Efecto del DAC en sistemas DDS 14

No linealidades

Generación de impulsos o “glitches”

Dependencia de la distorsión con la relación reloj de salida/frecuencia de salida

Un convertidor D/A no ideal introduce distorsión por varios motivos, entre los prin-
cipales que podemos citar están las no linealidades del amplificador de entrada, las di-
ferencias entre las fuentes de corriente y los impulsos que se producen al conmutar los
interruptores analógicos. Las dos primeras fuentes de distorsión son difı́ciles de cuantificar
y analizar, pues son parámetros intrı́nsecos del circuito.
El tercer problema es la generación de impulsos o “glitches”. Este efecto presenta la
máxima incidencia a mitad de escala, cuando se pasa del código 1000..00 al 0111..11, y por
tanto se deben conmutar todos los interruptores de corriente al mismo tiempo. En esta
situación, se producen impulsos por el desigual tiempo de conmutación de los interruptores
de corriente lo que produce la aparición de ruido dentro y fuera de la banda de trabajo
del conversor. Este proceso se repite con menor incidencia a 1/4, 1/8 de escala, etc.

(a) (b)

Figura 1.11: Degradación del margen libre de espúreos (D/A de 12 bits)


(a) En función de la frecuencia de entrada.
(b) En función de la frecuencia de entrada para 5 MSPS.

Por otra parte, la energı́a de impulso aumenta exponencialmente al aumentar la


frecuencia de reloj y al aumentar la frecuencia de la señal de entrada, por lo que las
prestaciones del D/A se degradan de forma logarı́tmica al aumentar la frecuencia de reloj
por causa de este fenómeno. En la figura 1.11 se puede ver este parámetro que se caracteriza
por medio del margen libre de espúreos “SFDR”, tanto en función de la frecuencia de
entrada como de la de muestreo.
En la figura 1.12 se compara el SFDR de dos conversores, uno de 10 bits y otro de
12 bits, trabajando a un régimen elevado de frecuencia de reloj (100 MSPS). A pesar de
que la frecuencia de salida no es la misma en ambos, se observa una importante reducción
del nivel de espúreos en el de 12 bits, siendo éste el actual lı́mite práctico del no de bits en
los conversores D/A de alta velocidad con tecnologı́a TTL, pues el aumento del número
de bits a 14 o superior no supone una reducción del nivel de espúreos a causa de las no
linealidades y los glitches que se producen.
1.4 Efecto del DAC en sistemas DDS 15

(a) (b)

Figura 1.12: Espectro de salida de un conversor D/A.


(a) Conversor D/A de 10 bits, 125 MSPS.
(b) Conversor D/A de 12 bits, 100 MSPS

En resumen, si se van a emplear frecuencias de muestreo del orden de 50 Mhz, el


conversor D/A óptimo será de 12 bits con tecnologı́a TTL, con lo que conseguirı́amos un
margen libre de espúreos de unos 60 dB.
De cualquier forma, las prestaciones de las etapas de conversión D/A son superiores
a las de conversión A/D, por lo tanto es éste el elemento más delicado en un procesador
digital de señal.

1.4.2. Conversores A/D de alta velocidad


Hoy en dı́a están apareciendo multitud de aplicaciones en las que se realiza muestreo
de alta velocidad. Las más comunes son aplicaciones de vı́deo y de radiofrecuencia donde
se muestrea una señal de frecuencia intermedia para luego procesarla.
El auge de estas aplicaciones, ha provocado el desarrollo de los convertidores analógi-
co/ digital (ADC) que han aumentado sus prestaciones de forma considerable, pues son
estos dispositivos los que limitan la calidad máxima en un procesador de señal.
En estos nuevos conversores diseñados para aplicaciones de alta velocidad, las carac-
terı́sticas en alterna y el margen dinámico son mucho más importantes que las de contı́nua,
por lo tanto existe una nueva generación de dispositivos especı́ficamente optimizados para
el trabajo en alta velocidad.

1.4.2.1. Parámetros de los dispositivos de conversión


En este apartado vamos a tratar los efectos de la cuantificación en los conversor
A/D (y también D/A). Los únicos errores asociados a un conversor ideal de N bits son
los asociados al proceso de muestreo y cuantificación. El máximo error que comete un
convertidor al digitalizar una señal de DC es ±1/2LSB. Por lo tanto cualquier señal de
CA generada por un conversor de n bits ideal producirá un ruido de cuantificación cuyo
valor eficaz medido en el ancho de banda de Nyquist y para señal uniforme es:
1.4 Efecto del DAC en sistemas DDS 16

q
ERRORRM S = √ (1.10)
12
ası́, para una señal sinusoidal tenemos que la relación señal ruido vale:

S
= 6,02N + 1,76dB (1.11)
N
donde “N” es el número de bits. Esta relación solamente es válida si el ruido es medido
en todo el ancho de banda de Nyquist, desde DC a fs /2.
Por ejemplo, un convertidor A/D de 8 bits exhibe un SQR de 49.92 dB. Una precisión
importante a la ecuación 1.11 es que en ella no se hace referencia a la situación frecuencial
de los espúreos ni a su amplitud individual, únicamente se calcula la potencia combinada
total de los mismos en relación a la componente fundamental.
Otro punto a considerar es que la SRQ definida en la ecuación 1.11 toma la amplitud
de salida de la componente fundamental como la del fondo de escala. Por tanto, cuando
tal situación no sea la real se empeorará un factor igual a:

A = 20log(F F S) (dB) (1.12)


con FFS igual a la fracción del fondo de escala a la que opera el DAC. Tomando en
consideración este efecto resulta:

SQR = 1, 76 + 6,02N + A = 1, 76 + 6,02N + 20log(F F S) (dB) (1.13)


Continuando con el ejemplo anterior, si el DAC opera al 70 % del fondo de escala
(A=0.7), el SQR resultante es de 46.82 dB ( una reducción de 3.1 dB respecto al funcio-
namiento original del DAC).
En √lo que respecta al ruido de cuantificación, aunque su valor eficaz si es aproximada-
mente q/ 12, su contenido en el dominio de la frecuencia puede estar altamente correlado
con la señal alterna de entrada. Ası́ por ejemplo, hay una correlación mucho mayor para
señales periódicas de pequeña amplitud que para señales aleatorias de gran amplitud. Por
eso, aunque normalmente se toma el ruido de cuantificación como ruido blanco distribuido
uniformemente en todo el ancho de banda, esta suposición no es correcta, pues en el caso
de fuerte correlación el ruido aparece concentrado en los armónicos de la señal, justamente
donde menos se desea.
Normalmente se muestrean señales aleatorias, centradas en una banda de frecuencias,
por lo que el ruido de cuantificación suele ser aleatorio. Sin embargo, las correlación entre
el ruido de cuantificación y la señal depende de la relación entre la frecuencia de muestreo
y la señal de entrada. Ası́, si introducimos dos tonos de distinta frecuencia a un conversor
A/D y variamos la diferencia de frecuencias entre ellos, podemos observar como el nivel
de espúreos varı́a en función de dicha diferencia, por lo tanto dicho nivel no viene marcado
por la distorsión del conversor A/D sino que se trata de un artefacto del proceso de
muestreo y de la correlación del error de cuantificación con la frecuencia de entrada. En
una aplicación práctica de conversión A/D, generalmente el ruido de cuantificación es
aleatorio, porque siempre existe una cierta cantidad de ruido en el sistema que actúa
como “dither” aleatorizando el espectro del error de cuantificación.
Es importante entender este proceso, porque la prueba que se emplea habitualmente
para medir las prestaciones en alterna de un A/D consiste en realizar la FFT de las
muestras de un tono sinusoidal. Se trata de un método universalmente aceptado, y para
1.4 Efecto del DAC en sistemas DDS 17

medir de forma precisa la distorsión armónica se deben respetar una serie de normas para
asegurar que realmente se mide la distorsión del A/D. En primer lugar hay que elegir
adecuadamente la relación de frecuencias, y algunas veces inyectar una cierta cantidad de
ruido. Luego hay que tener en cuenta el número de muestras que se toman en la FFT,
pues estas marcan el nivel de ruido de la función. Este nivel vale:
 
M
GF F T = 10log (1.14)
2
siendo M el número de puntos, por tanto si por ejemplo M=4096, la ganancia de proceso
de la FFT serı́a de 33 dB, por lo que el ruido de la FFT estarı́a 33 dB por debajo del ruido
del conversor A/D.

Figura 1.13: Espectro de la FFT

En la figura 1.13 se puede ver detalladas los distintos parámetros que se usan para
caracterizar un conversor A/D de 12 bits.
Un conversor A/D real presenta una serie de fuentes de ruido y distorsión. En primer
lugar está el buffer de entrada que es un circuito de banda ancha que aporta ruido blanco y
no linealidades, y presenta un ancho de banda limitado. A continuación está el circuito de
muestreo y retención que introduce más no linealidades, limitaciones del ancho de banda
y “jitter”, por último el cuantificador del A/D introduce ruido de cuantificación y no
linealidades diferenciales.
De acuerdo a estas fuentes de error se emplean una serie de parámetros para carac-
terizar los conversores A/D:

Distorsión armónica.

Peor armónico.

Distorsión armónica total.

Distorsión armónica total más ruido.

Relación señal ruido y relación de distorsión.(SINAD)


1.4 Efecto del DAC en sistemas DDS 18

Número efectivo de bits.(ENOB)

Relación señal a ruido.(SNR)

Ancho de banda analógico (ABW).

Margen libre de espúreos (SFDR).

Distorsión de intermodulación de dos tonos.

Relación de potencia de ruido (NPR).

Hay varias formas de medir la distorsión armónica de un A/D, pero todas ellas
emplean la FFT para medir dicho valor. Para medir este efecto se introduce al A/D una
señal 1 dB por debajo del fondo de escala y se mide la relación en dB de la señal con
respecto a el peor armónico, para saber el pero caso, o con respecto al valor cuadrático
medio de la suma de todos los armónicos para saber la distorsión armónica total.
La distorsión total más ruido es igual a la distorsión armónica total pero te-
niendo en cuenta el ruido de cuantificación.
La relación señal-ruido-distorsión es la relación entre el valor eficaz de la am-
plitud de la señal con respecto al valor cuadrático medio de todas las demás componentes
espectrales.
El número efectivo de bits se define (ENOB) como:

SIN AD − 1,76dB
EN OB = (1.15)
6,02
La relación señal ruido (S/N) sin armónicos se define como la relación entre el
valor RMS de la señal con respecto al valor medio de la suma de los cuadrados de todas
las demás componentes espectrales excluyendo los 5 primeros armónicos y la componente
contı́nua [?].
El ancho de banda analógico es el valor para el cual el espectro de un barrido
de entrada plano en frecuencia cae 3 dB.
El margen libre de espúreos (SFDR) es uno de las medidas más empleadas y
se define como el valor rms entre la componente principal y los picos de las componente
espúreas, medido sobre la primera ventana de Nyquist. Este valor depende de la amplitud
de la señal y se suele expresar en función del fondo de escala.
La distorsión de intermodulación de dos tonos es igual a la medida clásica en
cualquier circuito analógico. Se emplean dos señales cuya amplitud está 6 dB por debajo
del nivel de fondo de escala del A/D y se miden las componentes nf1 ± mf2 .
La relación de potencia de ruido (NPR) se emplea frecuentemente en los sis-
temas de múltiples por división en frecuencia (FDM). En estos sistemas los canales de voz
se multiplexan en bloques de 4 Khz para su transmisión, por lo que resulta importante
ver la influencia de los canales adyacentes sobre el de interés. Para realizar la medida se
inyecta ruido blanco al A/D y se filtra una banda de 4 Khz por medio de un filtro banda
eliminada, de forma que el ruido que aparece en esa banda es debido a la intermodulación
y distorsión del A/D, midiéndose la relación (NPR) entre el nivel de ruido de entrada y
el de la banda filtrada. Esta medida se puede ver en la figura 1.14.
1.4 Efecto del DAC en sistemas DDS 19

Figura 1.14: Potencia equivalente de ruido (NPR)

1.4.2.2. Efectos del “jitter” de apertura y del reloj de muestreo


El jitter de apertura es otro parámetro importante que hace disminuir la relación
S/N de un A/D. El “jitter de fase” causa un error que es función del tiempo de subida
y que resulta en una degradación total de la relación S/N. Este es un parámetro muy
importante, especialmente para frecuencia de entrada/salida muy elevadas, por lo que el
reloj de muestreo debe ser de muy bajo “jitter”. En la figura 1.15 se puede ver dicho efecto.

1.4.2.3. Arquitectura de conversores A/D de alta velocidad


La arquitectura de los conversores resulta determinante en sus caracterı́sticas dinámi-
cas, por lo que es muy importante conocer las posibilidades existentes para aplicaciones
de alta velocidad:

Aproximaciones sucesivas (SAR).

Flash.

Subrango.

Serie.

Los conversores de Aproximaciones Sucesivas han sido muy populares y se han


usado y siguen usándose para frecuencias de muestreo por debajo de 1 MSPS o menos.
Un bloque SAR es únicamente un cuantificador, pues no realiza muestreo, y para una
conversión adecuada la entrada debe permanecer constante durante todo el tiempo de
conversión.
Los conversores FLASH también llamados paralelo, son los A/D más rápidos exis-
tentes lo que consiguen gracias al empleo de un gran número de comparadores en paralelo.
Un conversor Flash de N bits emplea 2N resistencias y 2N − 1 comparadores en paralelo,
de forma que cada comparador tiene una tensión de referencia que es 1 LSB superior a la
del anterior. La señal de entrada se aplica a todos los comparadores a la vez, por lo que el
retardo de propagación es el de un solo comparador, sin embargo la arquitectura emplea
1.4 Efecto del DAC en sistemas DDS 20

Figura 1.15: Relación S/N en función del “jitter” de apertura y del reloj de muestreo

un gran número de resistencias y comparadores, lo que limita su resolución a un número


reducido de bits. Además para que los comparadores sean rápidos deben trabajar con
una potencia elevada, por lo tanto los problemas de los conversores Flash son su limitada
resolución, elevada disipación de potencia y elevado coste.
Tı́picamente, los conversores Flash emplean 8 bits y alcanzan frecuencias de 500 Msps
con anchos de banda analógicos de más de 300 Mhz. Pero como se ha mencionado antes,
el ancho de banda de potencia total no tiene porqué ser el mismo que el ancho de banda
de resolución.
Idealmente los comparadores de un convertidor Flash están bien adaptados en CC
y CA, pero en la práctica hay diferencias cuando se aplica una señal a la entrada de
todos los comparadores simultáneamente, lo que causa una degradación en la señal a altas
frecuencias. Esto se traduce en que la distorsión de estos conversores es de unos 70 dBc
para frecuencias de 1 Mhz y se degrada a 35 dBc a 100 Mhz.
Por lo tanto, estos conversores tienen aplicación en sistemas donde se requiere un
muestreo de muy alta velocidad con una calidad media o baja en cuanto a distorsión y
espúreos. Algunas aplicaciones serı́an por ejemplo, osciloscopios digitales, aplicaciones de
comunicaciones de alta velocidad, etc.
Aunque no es práctico realizar un conversor FLASH con un elevado número de
bits, sin embargo estos conversores se utilizan como subsistemas para realizar Conversores
de Subrango también denominados como conversores “medio Flash” que son capaces de
conseguir una resolución de hasta 16 bits y cuya arquitectura interior es la de la figura
1.16.
En estos conversores, el proceso de conversión se realiza en dos pasos, en el primero
los 4 bits más significativos se digitalizan por medio de un conversor analógico digital
del tipo Flash, el dato digitalizado se convierte de nuevo a analógico por medio de otro
conversor D/A y se resta del valor de entrada, de forma que el residuo resultante se
1.4 Efecto del DAC en sistemas DDS 21

Figura 1.16: Conversor de subrango de 8 bits

amplifica y se aplica al segundo conversor Flash. Por último, la salida de los dos conversores
Flash se combina en una palabra binaria de 8 bits.
Esta técnica de conversión multietapa se puede extender a dos, tres o cuatro etapas
de forma que la precisión en bits puede llegar a ser de 12, 14 ó 16 bits. El tiempo de
conversión se multiplica por el número de etapas de que disponga el sistema, por lo tanto
un A/D de dos etapas y 12 bits tendrá un régimen de muestreo de 50 MSPS.
Por último los conversores Serie emplean una etapa por bit para realizar una con-
versión A/D, por tanto son equivalentes a conversores de subrango con un bit por etapa
y sin corrección de errores. La figura 1.17 muestra un conversor de este tipo.

Figura 1.17: Conversor A/D serie

El circuito de muestreo y retención mantiene la señal de entrada constante durante


el tiempo que dura el ciclo de conversión , y hay N etapas, cada una tiene una salida de bit
y una de residuo que va a la etapa siguiente. El último bit es detectado con un comparador
como se muestra en la figura.
El problema fundamental de esta arquitectura son las discontinuidades en el residuo
de salida y la necesidad de que exista un tiempo de establecimiento adecuado entre etapas,
por lo tanto, no es una arquitectura adecuada para aplicaciones de alta velocidad.
Para terminar este apartado dedicado a los procesos de conversión, podemos resumir
el margen de posibilidades de elección en aplicaciones de alta velocidad a los siguientes
1.4 Efecto del DAC en sistemas DDS 22

tipos:

Flash: muy alta velocidad (500 MSPS), con baja resolución (8-9 bits) y elevada
distorsión (SFDR=-30 dBc)

Subrango: alta resolución (10-14 bits) con baja distorsión (SFDR= -60 dBc ) y alta
velocidad de operación (50 MSPS).

1.4.3. Efecto del sobremuestreo en el nivel de ruido de cuantificación


Sobremuestrear equivale a utilizar una frecuencia de muestreo mayor de la de Nyquist
intencionadamente. La figura 1.18 demuestra cómo el sobremuestreo mejora la relación
SQR, Señal-Ruido de Cuantificación.

Figura 1.18: El efecto del sobremuestreo sobre el ruido de cuantificación

En la ecuación 1.11 se mostraba la relación señal-ruido para el caso en que el ancho


de banda útil era el de Nyquist. Cuando se sobremuestrea, el ancho de banda de interés
o utilizado, BW, es menor de Fs /2. La relación S/N con respecto al ancho de banda se
incrementa porque el porcentaje de ruido de cuantificación es menor.
La resolución del DAC determina la potencia de ruido de cuantificación, es una
cantidad fija y está representada por el área sombreada en la figura. En el caso de so-
bremuestreo la potencia de ruido es la misma que el caso de muestreo a la frecuencia de
Nyquist. Al existir un ancho de banda mayor sobre el que distribuir la potencia de ruido
de cuantificación, en la banda de interés el rectángulo que representa la potencia de ruido
tiene menor altura, lo que indica que se mejora la relación señal-ruido en esta zona.
El efecto de mejora producido por el sobremuestreo es cuantificable:

C = 10log(Fsos /Fs ) (dB) (1.16)


donde Fs es la frecuencia de muestreo de Nyquist y Fsos la frecuencia de sobremues-
treo. La relación SQR modificada por todos los efectos es:

SQR = 1, 76 + 6,02N + A + C = 1, 76 + 6,02N + 20log(F F S) + 10log(Fsos /Fs ) (dB)


(1.17)
1.5 Efecto del truncamiento del acumulador de fase 23

1.5. Efecto del truncamiento del acumulador de fase

El truncamiento de fase es un aspecto importante de las arquitecturas DDS. Por


ejemplo, consideremos un DDS con un acumulador de fase de 32 bits. Convertir cada uno
de esos valores en un nivel de amplitud requerirı́a una tabla de 232 entradas, o lo que es lo
mismo, ¡ 4294967296 posiciones de memoria !. Si cada una de estas entradas almacenara
un valor de amplitud de 8 bits, serı́a necesaria una memoria de 4 Gigabits. Claramente
esto es algo impracticable.
La solución es utilizar una fracción de los bits más significativos del acumulador para
proporcionar la información de fase. En el ejemplo anterior, de los 32 bits del acumulador
de fase sólo se aprovechan los 12 más significativos. Los 20 restantes serán ignorados.
Ahora sólo se necesitan 48 kilobits de memoria suponiendo información de amplitud de 12
bits.
Para entender las implicaciones del truncamiento de fase se recurrirá con insistencia
a la figura 1.19, que dibuja el caso hipotético de un acumulador de 8 bits donde solamente
los 5 bits superiores se utilizan para resolver la fase.

Figura 1.19: Rueda de fase y Error por truncamiento de fase

En esta figura se representan dos cı́rculos punteados representando los valores de


fase representables con cada una de las resoluciones utilizadas: con 8 bits se dispone de
una resolución de 360o /28 = 1,41o , mientras que si utilizamos únicamente los 5 bits más
significativos de la palabra de fase, en este caso tendremos una resolución de 360o /25 =
11,25o . El cı́rculo externo de puntos verdes representa la resolución de 8 bits, mientras que
al caso de peor resolución le corresponde la circunferencia de puntos rojos interior.
Ahora supongamos por ejemplo que la palabra de sintonı́a programada en nuestro
DDS del ejemplo es igual a 6. Esto quiere decir que la cuenta del acumulador se realiza con
incrementos de 6 en 6. En la ya nombrada figura 1.19, también se representan los cuatro
primeros cambios de ángulo de fase realizados por el DDS. Como se puede distinguir, se
produce una discrepancia entre la fase indicada en el acumulador (la circunferencia externa
de 8 bits), y la fase determinada por la resolución de 5 bits (circunferencia interior).
Estas discrepancias corresponden a los arcos E1 para la primera cuenta, E2 para
la segunda y ası́ sucesivamente hasta llegar a la cuarta cuenta para la que no se produce
1.5 Efecto del truncamiento del acumulador de fase 24

error. La equivalencia en grados es de 8.46o , 5.64o y 2.82o para los errores E1, E2 y E3
respectivamente.
A partir de ahı́ el patrón se repite periódicamente conforme el acumulador se incre-
menta a saltos de 6 en 6 posiciones en la circunferencia exterior a cada intervalo de reloj
del sistema.
Obviamente, estos errores de fase introducidos por el truncamiento de fase se tra-
ducirán en errores de amplitud durante el proceso de conversión fase-amplitud inherente
a todo dispositivo DDS. Estos errores son periódicos porque, independientemente de la
palabra de sintonı́a elegida, tras un número determinado de vueltas en la rueda de fase,
la fase de acumulador y la fase truncada coincidirán. Como los errores de amplitud son
periódicos en el tiempo, aparecen como lı́neas espectrales de frecuencia conocidos con el
nombre de espúreos por truncamiento de fase.
En [?] se determina que la magnitud y distribución de los espúreos por truncamiento
de fase dependen de tres factores:

1. Tamaño del acumulador de fase (A bits)

2. Tamaño de la palabra de fase, es decir, el número de bits de fase después del trun-
camiento (P bits)

3. Palabra de sintonı́a (M)

1.5.1. Magnitud de los espúreos por truncamiento de fase


Hay palabras de sintonı́a que no provocan espúreos de truncamiento de fase, mientras
que otras los generan del máximo nivel. Si la diferencia entre el tamaño del acumulador A
y el tamaño de la palabra de fase después del truncamiento P es mayor de 4, (A − P ≥ 4),
lo cual es muy corriente en los diseños DDS prácticos, se puede establecer el nivel máximo
de espúreos:

Pmax espur trunc



= −6,02 · P (dBc) (1.18)
Por ejemplo, para un DDS de 32 bits de resolución en frecuencia y un truncamiento
de fase a 12 bits, los espúreos por truncamiento de fase nunca estarán por encima de
−72 dBc independientemente de la palabra de sintonı́a de frecuencia elegida.
En la figura 1.20 se representa gráficamente el acumulador de fase de un dispositivo
DDS de A bits de resolución en la que aparece indicado el truncamiento a los P bits más
significativos.
La primera parte de la figura corresponde al caso en que se generan los espúreos de
mayor nivel; son aquellas palabras de sintonı́a M que cumplen:

M CD(M, 2(A−P ) ) = 2A−P −1 (1.19)


siendo M CD(X, Y ) el máximo común divisor de X e Y .
En el ejemplo de la figura, la palabra de sintonı́a es de A bits (resolución del acu-
mulador de fase), dónde los P bits superiores constituyen la palabra de fase (los bits que
se van a utilizar para la conversión). Los bits A − P inferiores se desprecian, esto es, se
ignoran en lo que se refiere a resolución de fase. La palabra de sintonı́a T, consta de los
A − 1 bits menos significativos (el bit más significativo de la palabra de sintonı́a debe ser
0 para evitar el aliasing). Tal y como se aprecia en la figura, cualquier palabra de sintonı́a
1.5 Efecto del truncamiento del acumulador de fase 25

(a)

(b)

Figura 1.20: Relación del Truncamiento de fase con los espúreos generados
(a) Patrones de palabras de sintonı́a que provocan el máximo
nivel de espúreos
(b) Patrones de sintonı́a que provocan el mı́nimo nivel de
espúreos
1.5 Efecto del truncamiento del acumulador de fase 26

con un 1 en la posición de bit 2A−P −1 y ceros en el resto de los bits de menos peso nos
dan el truncamiento de fase con peor nivel de espúreos (−6,02P dBc).
El otro extremo se da en las palabras de sintonı́a que no producen espúreos algu-
nos. Son palabras de sintonı́a cuya parte “despreciada” es igual a cero. Formalmente son
aquellas que cumplen:
M CD(M, 2(A−P ) ) = 2A−P (1.20)
Para que esta ecuación se cumpla, el patrón de la palabra de sintonı́a debe ser el
del apartado (b) de la figura 1.20. Por tanto, las palabras de sintonı́a que no provocan
espúreos de truncamiento de fase se caracterizan por tener un 1 en la posición de bit 2A−P
y ceros en los restantes bits de menos peso. El resto de patrones de palabra de sintonı́a
provocan niveles intermedios de espureos.

1.5.2. Distribución espectral de los espúreos por truncamiento de fase


Analizar de forma precisa la distribución de los espúreos que provoca el truncamiento
de la palabra de fase es bastante complicado. Un análisis detallado se puede encontrar en
[?]. Aquı́ se hará una presentación más intuitiva.
Hay que recordar, en primer lugar, que el núcleo de un DDS consta de un acumulador
que suma de forma recursiva el valor de la palabra de sintonı́a. En la figura 1.21 se pueden
ver varias iteraciones de este proceso. Inicialmente, el acumulador contiene el valor de la
palabra de sintonı́a, (en este caso el valor arbitrario K). A cada ciclo sucesivo de reloj
la palabra de sintonı́a se suma al contenido anterior del acumulador. El proceso continúa
indefinidamente hasta que se vuelve a la posición de partida, pues al ser el acumulador
módulo 2A , llega un momento en el cual se produce desbordamiento en el mismo. El
número de pulsos de reloj necesarios hasta completar uno de estos ciclos se llama Velocidad
de Repetición Superior, (GRR).

GRR = 2A /M CD(M, 2A ) (1.21)


Por ejemplo, si A vale 20 y M es 182.898 (base 10), resulta un GRR de 524.288.
De este resultado se desprende que se necesitan alrededor de medio millón de ciclos de
reloj antes de que el acumulador comience a repetir su secuencia. Aunque esto puede
parecer un perı́odo de repetición grande, no es comparable al de algunos DDS que utilizan
acumuladores de 48 bits.
Volvamos a la figura 1.21. Como de los A bits de la palabra de fase, (que representan
la verdadera fase), sólo se utilizan en el proceso de conversión a amplitud los P bits más
significativos, podemos considerar la señal de salida como una señal compuesta de una
señal de resolución completa (que serı́a la que se obtendrı́a sin truncamiento de fase) y
una señal de error equivalente a los B bits de la palabra de truncamiento.
Se puede considerar entonces que la señal de error es la fuente de los espúreos. Estu-
diando las propiedades de esta palabra de truncamiento profundizaremos en la naturaleza
de la señal de error.
Si se consideran por separado los bits de truncamiento, es posible determinar el
perı́odo de repetición de la palabra de truncamiento; es decir, el GRR de la palabra de
truncamiento. Por ejemplo, para las condiciones de la figura 1.21, el valor de A se convierte
en 12 (el número de bits de truncamiento). La palabra de truncamiento se comporta como
un acumulador de B bits con una palabra de sintonı́a equivalente (ETW) dada por:

ET W = T modulo 2B (1.22)
1.5 Efecto del truncamiento del acumulador de fase 27

Figura 1.21: Secuencia seguida por el acumulador de fase

donde T es la palabra de sintonı́a original. El resultado de ésta operación no es nada


más que el valor de la parte truncada de la palabra de sintonı́a original. En el ejemplo
considerado, la ETW vale 2.674 (base 10). Por tanto, con A = 12 y T = 2674, la GRR
es 2.048. Esto quiere decir que cada 2.048 ciclos de reloj, la palabra de truncamiento
repetirá el patrón de su secuencia. Acabamos de demostrar una propiedad importante de
la palabra de truncamiento: su perı́odo.
¿Cuál es el comportamiento de la palabra de truncamiento durante este perı́odo? La
cuestión se puede responder observando que la “capacidad” de la palabra de truncamiento
es 2B . Dividiendo la capacidad por la ETW obtendremos el número de ciclos de reloj
necesarios para provocar que el acumulador se desborde. En el ejemplo considerado, como
B=12, la capacidad de la palabra de truncamiento es 212 = 4,096.
Antes de dividir por la ETW, sin embargo, es importante señalar que el bit más
significativo del ETW es un 1. Esto implica un perı́odo de desbordamiento menor de 2
ciclos de reloj, o lo que es lo mismo, se producirı́a una frecuencia con aliasing. Por tanto,
debemos ajustar la ETW restándola de la capacidad de la palabra de truncamiento (4.096).
Ası́ la ETW ajustada es 1.422 (4.096-2.674). Si el bit más significativo de la ETW hubiera
sido 0, este ajuste no hubiese sido necesario.
Ahora que ya conocemos la capacidad de la palabra de truncamiento y el valor de
ETW ajustado correctamente, podemos determinar el perı́odo de desbordamiento de la
palabra de truncamiento:

Capacidad/ET W = 2B /1422 = 4096/1422 = 2,88045 (1.23)


Este valor es el número medio de ciclos de reloj que se necesitan para que la palabra
de truncamiento se desborde. Como sabemos que la GRR de la palabra de truncamiento es
de 2.048 ciclos de reloj y que se lleva 2,88 ciclos de reloj el que la palabra de truncamiento
se desborde, entonces el número de desbordamientos que ocurren sobre un perı́odo de la
GRR es:
1.5 Efecto del truncamiento del acumulador de fase 28

N ro de desbordamientos = GRR/(Capacidad/ET W ) = 2048/2,88045 = 711 (1.24)


Con esta información se puede observar el comportamiento de la palabra de trunca-
miento en la figura 1.22.

Figura 1.22: Comportamiento de la palabra de truncamiento

La palabra de truncamiento alcanza un valor máximo de 2B . Tiene la forma de


diente de sierra con un perı́odo de 4,096/1,422 = 2,88 ciclos de reloj.
La forma de onda de diente de sierra resulta de la caracterı́stica de desbordamiento
del acumulador. También se ve que la secuencia completa de valores de la palabra de trun-
camiento se repite después de un perı́odo de 2.048 ciclos de reloj. Como el comportamiento
de la palabra de truncamiento es periódico en el dominio del tiempo su transformada de
Fourier es periódica en el dominio de la frecuencia. Como la secuencia de la palabra de
truncamiento es una secuencia real, su transformada se puede representar por la mitad de
puntos de los que consta la secuencia en el dominio del tiempo aprovechando sus propieda-
des de simetrı́a. Por tanto, habrá 1.024 frecuencias discretas asociadas al comportamiento
de la palabra de truncamiento, y estas frecuencias constituyen los espúreos de truncamien-
to.
Por tanto, el espectro de la secuencia de la palabra de truncamiento será el de una
forma de onda en diente de sierra con el matiz siguiente: La frecuencia fundamental del
diente de sierra es Fs × (ET W/Capacidad) ó 0,3472Fs en el ejemplo. Como sabemos que
hay 1.024 frecuencias asociadas con la secuencia de la palabra de truncamiento, entonces
el espectro está formado por los primeros 1.024 armónicos del espectro de la forma de onda
en diente de sierra espaciados a intervalos de 0,3472Fs . Esto se expande hasta un margen
de frecuencia de 355,5Fs . Por supuesto, se produce aliasing de los armónicos de alto orden
dentro del ancho de banda de Nyquist, Fs /2. La figura 1.23 ilustra este fenómeno.
La traza superior de la figura 1.23 muestra el espectro parcial de la forma de onda en
diente de sierra. La figura intermedia indica “la reflexión”de las lı́neas espectrales debida
al aliasing. Obsérvese que los espúreos que caen dentro de bandas de frecuencia que son
múltiplos enteros impares de Fs /2 coinciden directamente en la región de Fs /2. En cambio,
los espúreos que caen en bandas de frecuencias que son múltiplos pares de Fs /2 quedan
como imágenes simétricas en la región de Nyquist. La traza inferior de la figura muestra
la región Fs /2 resultante. Este es el verdadero espectro de espúreos que se produce en el
DDS a causa del truncamiento del acumulador de fase. Por supuesto, aunque en la figura
solo se representa el margen desde 0 hasta 3Fs , ya hemos determinado en el ejemplo que
los armónicos generados llegaban hasta 355,5Fs . Esto quiere decir que realmente habrı́a
muchı́simos más espúreos por truncamiento de los que se representan en esta figura.
1.5 Efecto del truncamiento del acumulador de fase 29

Figura 1.23: Espectro de los espúreos producidos por el truncamiento de fase

1.5.3. Resumen del truncamiento de fase


En resumen, el truncamiento del acumulador de fase resulta en un error de la señal
de salida del DDS. Esta señal de error se caracteriza mediante el estudio de la palabra
de truncamiento (la palabra de truncamiento es la porción del acumulador de fase que
contiene los bits truncados). Además la señal de error de truncamiento provoca espúreos
discretos en frecuencia a la salida del DDS.
La magnitud de los espúreos de truncamiento de fase tiene un lı́mite superior deter-
minado por el número de bits de la palabra de fase P. El valor de este lı́mite es −6,02P dBc
y este lı́mite superior se da en un tipo especı́fico de palabras de sintonı́a. Nominalmente,
estas palabras de sintonı́a son aquellas en las que los bits truncados son todos 0 excepto
el bit truncado más significativo. Sin embargo una segunda clase de palabras de sintonı́a
no provocan espúreos de truncamiento de fase. Estas se caracterizan por ser todo ceros
en la palabra de sintonı́a y un 1 en al menos la posición del bit menos significativo de la
palabra de fase. El resto de palabras de sintonı́a producen espúreos de truncamiento de
fase cuyo máximo valor es siempre menor de −6,02P dBc.
La distribución espectral de las palabras de truncamiento no se caracteriza tan
fácilmente como su magnitud máxima. Sin embargo, se ha explicado que la porción de
palabra de truncamiento del acumulador se puede considerar como una fuente de señal
de error de fase. Esta señal de error tiene la forma de onda de diente de sierra con un
frecuencia de:

F esp trunc = Fs (ET W/2B ) (1.25)


Dónde Fs , es la frecuencia del reloj del sistema del DDS, ETW es la palabra de
sintonı́a equivalente representada por los bits truncados (después de la corrección del
aliasing), y B es el número de bits truncados. El número de armónicos de esta frecuencia
que se deben de considerar en el análisis de espúreos de truncamiento de fase viene dado
1.6 Otras fuentes de espúreos en un sistema DDS 30

por:

No armonicos trunc = 2B−1 /M CD(ET W, 2B ) (1.26)


dónde M CD(x, y) es el máximo común divisor de x e y. El resultado es un espec-
tro que se expande muchos múltiplos de Fs . Sin embargo, debido al desdoblamiento de
armónicos producido por el aliasing, todos estos armónicos caen dentro del ancho de ban-
da de Nyquist, constituyendo la distribución de espúreos por truncamiento de fase que se
genera en los DDS.

1.6. Otras fuentes de espúreos en un sistema DDS

Hasta ahora, hemos analizado en las dos secciones anteriores las dos fuentes prin-
cipales de espúreos en un DDS, el ruido de cuantificación en el convertidor D/A y el
truncamiento de fase. Podemos enumerar otras fuentes adicionales de espúreos a la salida
de un sistema DDS:

1. Distorsión armónica a causa de la no linealidad del DAC. También tratamos la no


linealidad y sus fuentes en el apartado 1.4. Su efecto es la generación de armónicos
de la señal sintetizada. Para conocer la situación exacta de estos armónicos hay que
considerar el fenómeno de “reflexión” que se produce en aquellos que son superiores
al ancho de banda de Nyquist. El fenómeno se muestra en la figura 1.24.

Figura 1.24: Efecto del desdoblamiento de los armónicos por el aliasing

El procedimiento para determinar la frecuencia resultante al aliasing del N-ésimo


armónico es:

a) Calcular el resto R del cociente (N fo )/Fs dónde N es el orden del armónico.


b) Sea SP U RN la frecuencia reflejada del N-ésimo armónico.
c) Entonces SP U RN = R si R ≤ 1/2Fs , en otro caso SP U RN = Fs − R

El procedimiento anterior es un medio para conocer la situación del armónico que


resulta de las no linealidades asociadas a un convertidor D/A práctico. Como ya se
ha dicho antes, la magnitud de este armónico no se puede predecir ya que está di-
rectamente relacionada con la cantidad de no linealidad exhibida por el DAC en
particular.
1.7 Consideraciones sobre el filtrado de salida 31

2. Transitorios de conmutaciones asociados con el DAC. Los “glitches” de conmu-


tación constituyen otra fuente de espúreos que se generan debido a la arquitectura
fı́sica del DAC. Tiempos de subida y bajada desiguales contribuyen también a la
distorsión armónica. La cantidad de distorsión está determinada por la función de
transferencia dinámica. Los transitorios pueden provocar oscilaciones en los flancos
de subida y / o bajada de la forma de onda de salida del DAC. Estas oscilaciones
tienden a ocurrir a la frecuencia natural de resonancia del circuito implicado y se
pueden manifestar como espúreos en la salida. Su efecto de salida se observa en la
figura 1.25.

(a)

(b)

Figura 1.25: Glitches a la salida de un DAC


(a) Señal de salida con glitches de conmutación
(b) Etapa de conmutación diseñada para minimizar los glitches

3. El acoplamiento de la señal de reloj. Es otra fuente importante de espúreos en


los sistemas DDS. Muchos diseños incluyen uno o más circuitos de reloj integrados.
No es extraño que estas señales de reloj aparezcan a la salida del DAC a causa de
acoplamientos inductivos o capacitivos. Obviamente este acoplamiento se manifiesta
en el espectro de salida como una lı́nea espectral a la frecuencia del reloj interferente.
Otra posibilidad es que la señal de reloj se acople al reloj de muestreo del DAC.
Esto provoca que la señal de salida del DAC esté modulada por la señal de reloj. El
resultado se manifiesta en espúreos simétricos alrededor de la frecuencia de la señal
de salida.
La única defensa contra esta forma de espúreos consiste en una buena técnica de fa-
bricación del circuito impreso, con un buen desacoplo en las fuentes de alimentación.

1.7. Consideraciones sobre el filtrado de salida

Fundamentalmente, un DDS es un sistema muestreado. Como tal, el espectro de


salida es infinito. Aunque el dispositivo esté “sintonizado” a una frecuencia especı́fica, (se
1.7 Consideraciones sobre el filtrado de salida 32

supone que ésta cae dentro del ancho de banda de Nyquist), en realidad, el espectro de
salida consta de F0 y sus componentes de aliasing como se demostró en la sección 1.2.
También se puede ver el espectro resultante en un ejemplo para un tono sintetizado en la
figura 1.7.
La teorı́a de muestreo en banda base vigente en la generación DDS implica, como
ya se ha dicho, que la señal generada esté en la primera zona de Nyquist. Sin embargo,
siempre es necesario filtrar la salida del convertidor D/A, en primer lugar para eliminar
las componentes generadas fuera de esta zona, pero también para evitar el efecto nocivo de
cualquier señal o espúreo que caiga fuera del ancho de banda de Nyquist, ya que también
tendrán una imagen solapada dentro de esta zona. Por esta razón, un filtro anti-aliasing se
usa en casi todas las aplicaciones DDS. Las especificaciones de este filtro pueden limitar
el margen dinámico a determinadas frecuencias, como se puede ver en la figura 1.26. En
muchas aplicaciones no se emplea todo el ancho de banda de Nyquist por lo que el empleo
de este filtro no es tan riguroso, aunque en las aplicaciones basadas en DSP si se suele
aplicar este criterio.

Figura 1.26: Filtro antialiasing

El filtro antialiasing es un elemento crı́tico en el diseño de un sistema DDS. Existen


muchas clases de filtros en la literatura técnica. Sin embargo, para la mayorı́a de apli-
caciones el campo se restringe a tres familias de filtros básicos. Los tres tipos de filtros
son las respuestas de las familias Chebyshev, Gausianos y de Legendre. Las aplicaciones
de filtrado que requieren respuestas en frecuencia bastante abruptas utilizan respuestas
de tipo Chebyshev. En este caso, en cambio, se asume que la respuesta en el dominio del
tiempo no tiene gran importancia. Por contra, las aplicaciones de filtrado que requieren
caracterı́sticas en el dominio temporal suaves (sobreimpulso y retardo de grupo constante)
suelen utilizar la respuesta de tipo Gausiano. En estas aplicaciones se supone que no se
necesitan transiciones abruptas en frecuencia. Para las aplicaciones que están entre estos
dos extremos, la familia de filtros de Legendre es la mejor elección.
En resumen, la complejidad del filtro antialiasing puede llegar a ser muy grande,
especialmente cuando la señal de interés está muy próxima a fs /2. Por ejemplo, si se
emplea un filtro Butterworth que consigue 6 dB de atenuación por octava, para obtener
60dB de atenuación en un ancho de banda de 1 a 2 Mhz se requiere un mı́nimo de 10
polos, lo que no es ni mucho menos un filtro trivial. Por lo tanto, para aplicaciones de
alta velocidad que utilicen todo el ancho de banda de Nyquist el filtro utilizado debe de
cumplir los siguientes requerimientos:

Transición abrupta.
Respuesta plana en la banda de paso.
1.7 Consideraciones sobre el filtrado de salida 33

Respuesta en fase lineal.


Los filtros elı́pticos suelen cumplir estos criterios y son la solución más popular, de
cualquier forma son filtros complejos y caros.
Otra posibilidad que permite relajar el filtro antialiasing es que no halla nunca una
señal de fondo de escala en alta frecuencia. Esto ocurre en muchas aplicaciones de alta
frecuencia en las que la señal se concentra en una zona del espectro centrada en una
frecuencia.
De todas formas, cada aplicación particular tiene sus propias connotaciones, y será pre-
ciso realizar un estudio pormenorizado de las especificaciones concretas a la hora de selec-
cionar el filtro antialiasing. Seguidamente se recuerdan brevemente las caracterı́sticas más
importantes de las tres familias de filtros.

Las respuestas de la Familia Chebyshev


Esta familia generalmente ofrece caracterı́sticas abruptas en el dominio de la frecuen-
cia. Como tal, la respuesta en el dominio del tiempo es bastante pobre con sobreimpulsos
y retardos de grupo significativos. Esto hace que la familia de Chebyshev sea la adecuada
en aplicaciones para las cuales las caracterı́sticas en frecuencia son la premisa dominante,
mientras que las caracterı́sticas temporales son de menor importancia.

Figura 1.27: Respuestas de la familia Chevyshev

La respuesta de Butterworth es completamente monótona. La atenuación se incre-


menta continuamente según la frecuencia aumenta; es decir, no existe rizado en la curva
de atenuación. De la familia de filtros Chebyshev, la respuesta de Butterworth es la mas
plana. Su frecuencia de corte se toma como el punto de atenuación a 3 dB. La atenuación
continúa incrementándose con la frecuencia, pero el ritmo de atenuación después del corte
es bastante lento.
La respuesta Chebyshev se caracteriza por rizados de atenuación en la banda de
paso seguida de atenuación que se incrementa de forma monótona en la banda eliminada.
Tiene una transición de la banda de paso a la banda eliminada mucho más abrupta que la
respuesta de Butterworth. El coste es el rizado de la banda de paso. La profundidad de la
atenuación en la banda eliminada es directamente proporcional a la magnitud del rizado
en la banda de paso; cuanto mayor es el rizado, mas profunda es la atenuación.
La respuesta Chebyshev Inversa se caracteriza por una atenuación que se incrementa
continuamente en la banda de paso con rizado en la banda eliminada. Igual que en la
respuesta de Chebyshev, cuanto más grande es el rizado en la banda eliminada más abrupta
es la transición de la banda de paso a la banda eliminada.
La respuesta elı́ptica ofrece la transición desde la banda de paso a la banda elimi-
nada más profunda de toda esta familia. La contrapartida, por supuesto, son los rizados
1.7 Consideraciones sobre el filtrado de salida 34

de atenuación. En este caso se producen tanto en la banda de paso como en la banda


eliminada. En aplicaciones de filtros anti aliasing, éste suele ser el filtro utilizado debido a
lo abrupto de su región de transición.

Las respuestas de la Familia Gausiana


La familia Gausiana de respuestas es la más adecuada para aplicaciones en las que es
fundamental la respuesta temporal. Ofrecen caracterı́sticas suaves en el dominio del tiempo
con mı́nimo sobreimpulso. Además, el retardo de grupo es prácticamente constante. Como
las caracterı́sticas en el dominio del tiempo tienen buen comportamiento, la respuesta
frecuencial no exhibe transiciones muy abruptas. De hecho, la respuesta en frecuencia
es completamente constante. La curva de atenuación siempre mantiene una pendiente
negativa sin picos tanto en la banda de paso como en la banda eliminada.
La familia Gausiana se puede dividir en tres tipos de respuesta, cada una de ellas con
sus caracterı́sticas especiales. Son las respuestas Magnitud Gausiana, Bessel, y Retardo de
Grupo con Rizado Constante. La figura 1.28 muestra estos tres tipos de respuesta. Aunque
la curva de amplitud parece ser la misma en los tres tipos, cada una tiene su caracterı́stica
particular en el dominio del tiempo para la que ha sido optimizada.

Figura 1.28: Respuestas de la familia Gausiana

La respuesta de Magnitud Gausiana está optimizada para conseguir la curva en


amplitud que más se asemeje a la distribución gausiana. La caracterı́stica en el dominio
del tiempo ofrece respuesta de fase prácticamente lineal con el mı́nimo sobreimpulso. El
retardo de grupo no es tan constante, pero es mucho mejor que el de la familia Chebyshev.
La respuesta de Bessel está completamente optimizada para el retardo de grupo.
Ofrece un retardo de grupo casi plano en la banda de paso. La respuesta de Bessel es al
dominio de tiempo lo que la respuesta de Butterworth al dominio de la frecuencia. Esto
hace del filtro de Bessel la elección adecuada cuando el retardo de grupo es la principal
especificación. Ofrece respuesta de fase prácticamente lineal con el mı́nimo sobreimpulso.
La respuesta de Retardo de Grupo con Rizado Constante está optimizada para pro-
porcionar rizados en la respuesta del retardo del grupo que no excedan el máximo especifi-
cado en la banda de paso (muy parecido a la respuesta en amplitud del filtro Chebyshev).
Debido a que la banda de paso completa ofrece un máximo retardo de grupo, este filtro es
adecuado para aplicaciones de banda ancha donde el retardo de grupo se debe de controlar
sobre la banda de interés en su totalidad. Al igual que en los otros filtros gausianos, la
respuesta de fase es principalmente lineal con mı́nimo sobreimpulso.

La respuestas de la Familia Legendre


1.8 Caracterı́sticas de salida de los sistemas DDS 35

Figura 1.29: Respuesta de la familia Legendre

La familia de filtros Legendre consta de un único tipo. Su respuesta en la banda de


paso tiene ligeros rizados y es similar a la respuesta de Chebyshev de 0.1 dB de rizado.
La respuesta en la banda eliminada decae continuamente. La velocidad de atenuación
después de la frecuencia de corte es más pronunciada que la del tipo Butterworth, pero no
tanto como la del tipo Chebyshev. El retardo de grupo es virtualmente constante sobre el
primer 25 % de la banda de paso, pero se incrementa continuamente conforme se aproxima
la frecuencia de corte.

1.8. Caracterı́sticas de salida de los sistemas DDS

Los DDS de alta velocidad con DAC integrado proporcionan una salida en modo
corriente. Esta corriente se puede aplicar a cualquier carga resistiva, incluyendo un corto-
circuito, siempre que la tensión generada en el pin de salida referida a masa, no viole la
especificación de salida del DAC. Esta especificación es simplemente la tensión máxima
que el pin de salida del DAC aguanta. Las tensiones que superen los lı́mites provocarán
distorsión de salida del DAC de moderada a drástica. Normalmente, las salidas se termi-
nan a masa mediante una resistencia, aunque se pueden terminar a cualquier otra tensión
que no viole las especificaciones de operación del DAC. Por regla general la corriente de
salida se puede predefinir mediante una resistencia conectada a un pin especial.
Los convertidores D/A con salida de tensión se evitan en aplicaciones DDS debido
a que las pérdidas internas provocarı́an que la salida variara de acuerdo con la resistencia
de carga. Las salidas de alta impedancia suministran su corriente especificada con pocas
variaciones de salida a ó desde la carga siempre que no se sobrepasen las especificaciones
de tensión de salida. Los DACs con conmutadores de corriente generalmente son los que
exhiben mejores prestaciones a velocidades de reloj altas.
La especificación de resistencia de salida de un DDS/DAC es la impedancia combi-
nada de los dispositivos CMOS que forman los conmutadores y la circuiterı́a de la fuente
de corriente. Normalmente es tan alta (usualmente mayor de 100K), que su presencia
se puede ignorar y es la resistencia de carga elegida por el usuario la que determina la
impedancia de salida del sistema.
En DACs con salida de corriente de tipo unipolar, si la resistencia de carga está ter-
minada en masa, entonces los voltajes que se desarrollan en la resistencia variarán entre
0 y un valor extremo positivo o negativo (fondo de escala). Por el contrario, una corriente
bipolar desarrollará una tensión negativa en un extremo (0 de escala) y positiva en el otro
(fondo de escala). El punto medio entre los dos extremos suele ser 0 voltios.
¿En qué afecta el que la corriente sea unipolar? Primero, los puntos centrales de la
1.8 Caracterı́sticas de salida de los sistemas DDS 36

forma de onda senoidal de salida del DDS tendrán un offset de continua que estará en el
punto central del margen de fondo de escala. Esto puede ser importante cuando se aplica
la señal de salida a algún amplificador acoplado en continua para evitar que la componente
de continua provoque recortes en la forma de onda. Por otro lado, cuando se modula en
AM la salida utilizando la resistencia de control de corriente del DAC, la envolvente de la
modulación será asimétrica, asemejándose más a una salida pulsada, que a una portadora
modulada simétricamente.

1.8.1. Acoplamiento con transformador simétrico


Existen DDS-DAC cuya salida se compone de 2 terminales en oposición de fase.
Estas dos señales se pueden combinar en un transformador de RF con toma intermedia
para producir formas de onda simétricas tal y como se muestra en la figura 1.30. En estos
casos, cuando se programa la corriente de salida del DAC, se está programando la suma de
las dos corrientes disponibles en las salidas Iout A e Iout B. Por ejemplo, si se programa una
corriente de fondo de escala de 10mA, entonces si una salida tiene 2 mA, la otra tendrá 8
mA. Combinando estas dos corrientes complementarias en un transformador, la salida de
corriente se convierte en simétrica y se pierde el offset de continua.

Figura 1.30: Combinación de salidas complementarias en un DDS-DAC

El acoplamiento por transformador también es beneficioso cuando se quiere acoplar


las corrientes de salida del DAC a entradas reactivas como filtros LC . El camino de baja
impedancia existente a masa a través de la toma central del transformador es mucho
mejor que tomar el camino reactivo a través del filtro LC que está terminado solamente
a la salida del filtro, figura 1.31 (c). Sin transformador, el siguiente método preferible es
aplicar la corriente de salida del DAC a un filtro LC que esté doblemente terminado, como
se muestra en la figura 1.31 (b).
Las flechas en la figura 1.30 muestran el flujo de corriente en el primario del trans-
formador 1:1 de banda ancha y cómo la corriente unipolar de 2 salidas complementarias se
puede usar para simular una corriente bipolar. La resistencia de carga de 50Ω del secunda-
rio del transformador se refleja en el primario dónde aparece como una resistencia de carga
de 25Ω para cada salida. Se puede escoger otra relación de transformación distinta, lo que
permite cargas diferentes siempre que no se viole la especificación de salida del DDS-DAC.
En el ejemplo de la figura, los voltajes presentes en los pines de salida no serán unipolares
como lo serı́an si cada pin estuviera conectado mediante una resistencia de carga a tierra.
En cambio, serán bipolares y simétricos alrededor de la tensión presente en el punto central
del transformador (masa en el ejemplo) a causa del efecto producido por los acoplamientos
magnéticos del transformador. Se necesita prestar atención a la especificación de tensión
negativa además de a la positiva cuando se configuran las salidas para acoplamiento de
1.8 Caracterı́sticas de salida de los sistemas DDS 37

Figura 1.31: Acoplo de cargas reactivas a la salida del conjunto DDS-DAC

transformador.
Otro beneficio del acoplamiento por transformador es el fenómeno del rechazo del
modo común. Si las salidas del DDS-DAC Iout A e Iout B contienen señales comunes o
idénticas tales como acoplamiento del reloj, componentes de la fuente de alimentación, y
otras señales espúreas, estas señales se pueden ver reducidas o eliminadas en el espectro de
salida por el acoplamiento del transformador. Si las señales idénticas están presentes en las
dos entradas del primario del transformador, entonces sus campos opuestos se cancelarán
uno a otro en algún grado. El grado de cancelación depende de la coincidencia del bobinado
del transformador además de la coincidencia de las señales “idénticas”.

1.8.2. Consideraciones sobre la potencia de salida


Combinar dos salidas complementarias en un transformador no ofrece ninguna ga-
nancia de potencia. La única manera de incrementar la potencia de salida es configurando
una corriente de salida mayor mediante la resistencia de ajuste de corriente. Se deben
consultar las hojas del fabricante y elevar la corriente de operación hasta cerca del nivel
máximo; sin embargo, la distorsión armónica de la salida puede incrementarse ligeramente.
La utilización de un transformador permite la transferencia más eficiente de la potencia
a la carga, eliminando la necesidad de una resistencia de terminación que disipe potencia
que debe transferirse a la salida.

1.8.3. Terminación de salida del DDS-DAC


Sin tener en cuenta el esquema de terminación de salida que se escoja, la experiencia
ha demostrado que la supresión óptima de armónicos y espúreos se consigue cuando las
salidas complementarias están terminadas de la misma manera. Si esto no se hace, puede
que no se note la diferencia a bajas frecuencias, pero a altas frecuencias de salida, dónde
cada dB de SFDR cuenta, esta práctica dará un espectro de salida más limpio, espúreos
más débiles y mayor SFDR.
1.9 Modulación digital con DDS 38

1.9. Modulación digital con DDS

Dado que nuestro montaje es un DDS en funciones de modulador, dedicaremos este


apartado a comentar las caracterı́sticas particulares de este método de modulación.
Ya sabemos que modular una señal es trasladarla en el espectro. Matemáticamente,
esto se consigue multiplicando la señal a modular por una sinusoide, lo que desplaza la señal
modulada en ±fc , con fc la frecuencia de la señal senoidal moduladora. Existe también
la variante de modulación en cuadratura en la que dos informaciones se modulan con dos
señales senoidales de la misma frecuencia desfasadas π/2.
La figura 1.32 muestra los diagramas de bloque funcionales de las dos estructu-
ras básicas de modulación. La figura (a) muestra modulación senoidal, mientras que (b)
representa modulación en cuadratura. Habrı́a que añadir las variaciones de estos dos es-
quemas para producir formas especializadas de modulación como banda lateral única y
doble banda lateral.

Figura 1.32: Estructuras de modulación básicas en el dominio temporal

La modulación digital es la contrapartida en tiempo discreto a los conceptos de


modulación en tiempo continuo que se acaban de mencionar. En vez de tratar con formas de
onda analógicas, x(t), ya sabemos que tratamos con muestras instantáneas de esas ondas,
x(n). Aquı́, n que es un número entero, equivale a los instantes de muestreo en el tiempo.
Esto es, si T representa el intervalo de tiempo entre muestras sucesivas, nT representa el
tiempo instantáneo en que se toman las muestras. La similitud entre señales en tiempo
continuo y discreto resulta obvia cuando se escriben juntas. Por ejemplo, considere una
señal sinusoidal

x(t) = Acos(ωt) tiempo continuo


x(n) = Acos(ωnT ) tiempo discreto
La principal diferencia en la señal en tiempo discreto es que existen ciertas restric-
ciones sobre ω y T como resultado del teorema de Nyquist. Especı́ficamente, T debe ser
menor de π/ω. Como x(n) es una serie de muestras instantáneas de x(t), entonces x(n) se
puede representar como una serie de números, cada uno de ellos es el valor instantáneo de
x(t) en los instantes nT.
Esta idea es fundamental para comprender los moduladores digitales. La modulación
en el mundo analógico se consigue multiplicando formas de onda continuas en el tiempo
utilizando circuitos analógicos especializados. Sin embargo, en el mundo digital es posible
conseguir la modulación simplemente manipulando secuencias de números. Una operación
puramente numérica.
1.9 Modulación digital con DDS 39

Los esquemas de modulación para señales en tiempo continuo se pueden adaptar en


las moduladores digitales tal y como se muestra en la figura 1.33.

Figura 1.33: Estructuras de modulación básicas digitales

Aquı́, g(n), g1 (n), g2 (n), sen(ωc nT ) y cos(ωc nT ) son secuencias de números. Los mul-
tiplicadores y sumadores son elementos lógicos. Su complejidad es función del número de
bits utilizados para representar las muestras de las formas de onda de entrada. Esto parece
fácil en teorı́a. Sin embargo, cuando se implementan en hardware, el número de elementos
de circuiterı́a puede crecer muy rápidamente. Por ejemplo, si las formas de onda digital se
representan como números de 8 bits, entonces se requieren multiplicadores y sumadores
capaces de manejar palabras de 8 bits. Por otra parte, si las señales digitales están repre-
sentadas por números flotantes de doble precisión (64 bits), entonces los multiplicadores
y sumadores se convierten en estructuras muy grandes.
Es en el entorno de los moduladores digitales dónde la tecnologı́a DDS se vuelve
más atractiva. Ello es debido a que un DDS genera directamente las series de números
que representan muestras de una onda senoidal o cosenoidal. Estructuras de moduladores
digitales basadas en DDS se muestran en la figura 1.34.

Figura 1.34: Estructuras de modulación básicas DDS

1.9.1. Requerimientos y arquitectura del sistema


Las estructuras de modulación básicas DDS descritas en la sección previa son muy
simples. Falta añadir el resto de componentes constitutivos de un DDS para que un modu-
lador digital trabaje en la práctica. El elemento más crı́tico es la fuente de reloj. Un DDS
puede solo generar muestras si está alimentado de un reloj de muestreo. También, hemos
visto que se necesitaba un convertidor A/D para trasformar el conjunto de números que
se mueve por el interior de la estructura DDS en señales reales.
1.9 Modulación digital con DDS 40

Un modulador DDS más realista se presenta en la figura 1.35. Con objeto de fa-
cilitar la exposición únicamente se muestra el modulador sinusoidal. La extensión a una
estructura de modulación en cuadratura es trivial.

Figura 1.35: Modulador DDS

A primera vista, el modulador DDS parece bastante simple. Sin embargo, existe
una serie de requerimientos que hacen que la modulación digital sea un poco más difı́cil
de implementar. Este requerimiento es que g(n) debe de ser una secuencia muestreada
a la misma frecuencia que la velocidad de muestreo del DDS. De lo contrario, la etapa
de multiplicación estarı́a multiplicando valores que hubiesen sido tomados en instantes de
tiempo completamente distintos.
Pongamos un ejemplo sencillo. Supongamos que la señal moduladora vale

g(n) = cos[2π(1khz)nT1 ]
donde T1 vale 0.25 ms. Por tanto, g(n) se puede describir como una señal de 1 Khz
muestreada a 4 Khz. Supongamos, también, que la salida del DDS es

DDS = cos[2π(3khz)nT2 ]
donde T2 es igual a 0.1 ms. Esto significa que la salida del DDS es una señal de
3khz muestreada a 10 Khz. En el modulador DDS, el valor de n (el ı́ndice de muestra)
del multiplicador es el mismo tanto para las entradas como para las salidas. Ası́, para un
valor especı́fico de n, digamos n = 10, el ı́ndice del tiempo para el DDS es nT2 , el cual
vale 1 ms. Claramente, nT1 6= nT2 (2.5 ms 6= 1 ms). Por tanto, en un ı́ndice de tiempo
n=10, el tiempo DDS es 1 ms mientras que el tiempo g(n) es 2.5 ms. La consecuencia es
que el resultado de salida del multiplicador g(n)cos(ωc nT ), no es lo que se espera que sea,
debido a que la referencia de tiempo de g(n) no es la misma que la de cos(ωc nT ).
El requerimiento de “coincidencia en la velocidad de muestreo” es la primera con-
sideración de diseño en un modulador digital. Si, en un sistema de modulación DDS, la
fuente de la señal g(n) opera a una velocidad de muestreo distinta a la del reloj DDS, se
deben de realizar los pasos necesarios para corregir esta discrepancia en velocidad. El di-
seño de un modulador DDS se convierte entonces en un ejercicio de procesamiento digital
de señal multimuestreo. Este tipo de procesado requiere un conocimiento de las técnicas
implicadas de interpolación y decimado. Sin embargo, la interpolación y el decimado re-
quieren algún conocimiento de filtros digitales. De todo ello hablaremos en las siguientes
secciones.

1.9.2. Filtros digitales


Los filtros digitales son la contrapartida en tiempo discreto a los filtros analógicos
de tiempo continuo. Ya se repasaron algunas caracterı́sticas sobre filtros analógicos en el
1.9 Modulación digital con DDS 41

apartado 1.7 cuando se trató el filtrado antialiasing de la salida del DDS.


Existen dos tipos básicos de filtros digitales; uno es el tipo FIR (respuesta al impulso
finita) y el otro es el filtro IIR (respuesta al impulso infinita). Desde el punto de vista del
diseño de filtros, el tipo FIR es el más sencillo de trabajar. Sin embargo, desde el punto de
vista de los requerimientos hardware, el IIR tiene una ventaja. Usualmente requiere mucha
menos circuiterı́a que un filtro FIR para la misma respuesta básica. Desafortunadamente,
el tipo IIR tiene la caracterı́stica de ser potencialmente inestable bajo ciertas condiciones.
Esta propiedad lo excluye a menudo en sistemas dónde no se conoce a priori la señal de
entrada.

1.9.2.1. Filtros FIR


Fundamentalmente, un FIR es una estructura muy simple. Está compuesto de una
cadena de etapas de retardo, multiplicación, y suma. Cada etapa consta de un camino de
datos de entrada y de salida y un coeficiente fijo (que sirve como uno de los multiplicandos
en la sección multiplicadora). La figura 1.36 muestra un filtro FIR de 2 etapas.

Figura 1.36: Filtro FIR básico

Para este filtro simple obtenemos la secuencia de salida:

y(n) = a0 x(n) + a1 x(n − 1)


Esto quiere decir, para un instante dado, que la salida del filtro FIR no es ni más
ni menos que la suma de la muestra actual y de la muestra anterior ponderadas por los
valores a0 y a1 respectivamente.
Realizando la transformada z de la ecuación anterior, la función de transferencia
H(z), resulta:

H(z) = a0 + a1 z −1
donde z = ejω , ω = 2πf /Fs y Fs es la frecuencia de muestreo.
Ahora apliquemos algunos números a nuestro ejemplo para hacer las cosas un poco
más visuales. Supongamos que empleamos una velocidad de muestreo de 10 khz y utili-
zamos a0 = a1 = 0,5. La representación de H(z) en función de la frecuencia resulta en la
figura 1.37.
Claramente, esto constituye una respuesta del tipo paso bajo. En la figura sólo se
representa el ancho de banda de Nyquist por la caracterı́stica de simetrı́a en la banda de
fs /2 a fs .
El comportamiento de un filtro FIR es fácil de analizar si se calcula su respuesta
impulsiva. Su calculo se realiza de forma similar al equivalente analógico. En este caso, la
1.9 Modulación digital con DDS 42

Figura 1.37: Respuesta FIR del ejemplo

secuencia de entrada que se utiliza es la secuencia impulso unitario δ(n) = 1, 0, 0, 0, 0, 0, . . .


En la figura 1.38, que representa un filtro FIR de n etapas generalizado, el 1 inicial de
la secuencia δ(n) se propaga a cada pulso de reloj hasta la última etapa de retardo. Esto
significa que y(n) = 0 después de la n-ésima muestra y también permanecerá a 0 en
adelante.
Se observa entonces que la respuesta impulsiva solo existe durante n muestras. De
aquı́ su nombre, filtro de respuesta al impulso finita. Además, la respuesta impulsiva tam-
bién demuestra que una entrada a un filtro FIR necesita exactamente n muestras para
propagarse a través del filtro completo antes de que su efecto esté presente a la salida. El
incremento del número de etapas n incrementará el retardo total a través del filtro final.
Esto puede ser un problema en sistemas que son poco tolerantes al retardo. Sin embar-
go, la ventaja inherente al incrementar n es que se aumenta la pendiente de la curva de
respuesta.

Figura 1.38: Filtro FIR generalizado

La ecuación que expresa la salida y(n) en función de la entrada x(n) en el dominio


1.9 Modulación digital con DDS 43

temporal es:

y(n) = a0 x(n) + a1 x(n − 1) + a2 x(n − 2) + . . . + aN −1 x(n − N − 1) (1.27)

resultando una ecuación de transferencia H(z), para un filtro FIR multietapa de N coefi-
cientes de realimentación:

H(z) = a0 + a1 z −1 + a2 z −2 + . . . + aN −1 z −(N −1) (1.28)

1.9.2.2. Filtros IIR


La diferencia entre un IIR y un FIR está en la realimentación. Un filtro IIR tiene una
sección de alimentación con retardo, multiplicación y suma adicionales. En la figura 1.39
se muestra una estructura simple IIR.

Figura 1.39: Filtro IIR básico

La parte de la izquierda es una copia exacta de un filtro FIR; esta porción del IIR se
conoce normalmente como la sección “feedforward”. La porción de la derecha es la sección
de realimentación “feedback”. La realimentación es una versión retardada y escalada de
la señal de salida y(n), y todo ello se suma con la salida de la sección feedforward. La
existencia de realimentación en un filtro IIR supone una diferencia sustancial en el com-
portamiento del filtro. Como en cualquier sistema realimentado, la estabilidad se convierte
en un asunto importante. La elección inadecuada de los coeficientes o un desconocimiento
de la señal de entrada pueden provocar inestabilidades en un IIR. El resultado puede ser
oscilaciones o distorsión severa de la señal de salida. El problema de la estabilidad puede
ser suficiente para excluir el uso de un IIR en ciertas aplicaciones.
El ejercicio de cálculo de la respuesta impulsiva realizado para el filtro FIR anterior
puede servirnos de ayuda para examinar el comportamiento del IIR. El comportamiento de
la parte izquierda es exactamente idéntico, esto es, después de n muestras su salida será 0.
La diferencia reside en el bloque de realimentación de la derecha. Cada nuevo instante
de muestreo modifica el valor de y(n) con el valor anterior de y(n) recursivamente. El
resultado es que y(n) continua sacando valores indefinidamente, incluso aunque la señal
de entrada haya desaparecido. Ası́, un impulso único a la entrada puede resultar en una
secuencia infinita de impulsos a la salida. De aquı́ el nombre, filtro de respuesta al impulso
infinita.
Aún ası́, el concepto infinito es un ideal en la práctica. Los filtros IIR solo pueden
ser implementados con una cantidad finita de resolución numérica. Por ejemplo, en apli-
caciones dónde el camino de datos se debe restringir, digamos a palabras de 16 bits, los
valores muy pequeños serán redondeados a un valor de 0. Esto lleva a que el funciona-
miento del IIR se desvı́e del ideal. Un filtro IIR ideal continuarı́a infinitamente su salida
1.9 Modulación digital con DDS 44

con valores que se aproximarı́an a 0 gradualmente. Sin embargo, a causa de la resolución


finita, llega un momento en que los valores se redondean a 0 y por tanto provocan el fin
de la “respuesta impulsiva infinita”.
La estructura de un filtro IIR simple nos lleva, al igual que en caso anterior, a la
descripción de un filtro IIR multietapa. En este caso, sin embargo, los lados izquierdo y
derechos del filtro IIR no tiene porqué tener el mismo número de etapas de retardo. Por
lo tanto, la cantidad de coeficientes A y B no tiene por que ser la misma. La figura 1.40
muestra un filtro IIR multietapa.

Figura 1.40: Filtro IIR generalizado

Examinando la figura obtenemos al ecuación de la salida y(n), en términos de la


entrada x(n). El resultado es

y(n) = a0 x(n) + a1 x(n − 1) + a2 x(n − 2) + . . . + aN −1 x(n − N − 1)+


(1.29)
b1 y(n − 1) + b2 y(n − 2) + . . . + bM y(n − M )

cuya función de transferencia general, H(z) resulta ser, para un filtro IIR multietapa de N
coeficientes de realimentación hacia delante y M coeficientes de feedback:

a0 + a1 z −1 + a2 z −2 + . . . + aN −1 z −(N −1)
H(z) = (1.30)
1 − b1 z −1 − b2 z −2 − . . . − bM z −M

1.9.3. Procesado DSP a varias velocidades


Este proceso consiste en convertir datos muestreados con una frecuencia Fs1 a datos
muestreados a otra velocidad Fs2 . Si Fs1 > Fs2 , el proceso se llama decimado. Si Fs1 < Fs2 ,
el proceso se denomina interpolación.
1.9 Modulación digital con DDS 45

La necesidad del procesamiento a diferentes velocidades se pone de manifiesto con


el siguiente ejemplo. Supongamos que tenemos 1.000 muestras de una onda senoidal de un
1 Khz almacenadas en memoria, y que estas muestras se adquirieron con una velocidad
de muestreo de 10 Khz. Esto implica que la duración en tiempo del conjunto completo de
muestras es 100 ms (1000 muestras a 10.000 muestras/seg.). Si este mismo conjunto de
muestras es ahora leı́do de la memoria a una velocidad de 100 Khz, solo se necesitarán 10
ms para extraer todos los datos. Por tanto, las 1.000 muestras de datos a una velocidad
de 100 Khz parecerán ahora una onda de 10 Khz en lugar de la onda original a 1 Khz.
Obviamente, si se cambia la velocidad de muestreo pero no los datos, el resultado es
indeseable. Sin embargo, si los datos originales a 10 Khz representaban una señal de 1
Khz, serı́a deseable tener también una salida muestreada a 100 Khz de una señal de 1
Khz. Para hacer esto posible se deben modificar de alguna manera los datos originales.

1.9.3.1. Interpolación
El problema del ejemplo es un caso de interpolación. La función de un interpolador
es tomar datos que fueron muestreados a una velocidad y convertirlos en nuevos datos
muestreados a otra velocidad mas alta. Los datos deben de ser modificados de tal modo que
cuando se muestreen a mayor velocidad se preserve la señal original. Una representación
gráfica del proceso de interpolación se muestra en la figura 1.41.

Figura 1.41: Interpolador básico

Se pueden distinguir dos procesos separados: una sección de entrada que muestrea a
una velocidad Fs y una sección de salida que muestrea a otra velocidad nFs dónde n es un
número entero positivo mayor de 1. La estructura de un interpolador básico indica que para
cualquier muestra de entrada habrá n muestras de salida. Esto nos plantea la pregunta:
¿qué debemos de hacer a los datos originales de manera que, cuando se muestreen a una
velocidad más alta, la señal original quede preservada?.
Se podrı́a razonar intuitivamente que, si se insertan n − 1 ceros entre cada una de
las muestras de entrada, (zero stuffing), entonces el dato de salida tendrı́a la caracterı́stica
deseada. Después de todo, añadir nada (0) a algo, no deberı́a cambiarlo. Es un buen punto
de partida, aunque todavı́a nos faltarı́a algo más para completar el cuadro.
Tal y como se aprecia en la figura 1.42, que es un ejemplo para un factor de interpo-
lación de 3, el proceso de interpolación genera réplicas del espectro de la señal original que
ahora caen dentro del nuevo ancho de banda de Nyquist, 3 veces mayor. Es decir, que para
que la señal interpolada mantenga las propiedades de la señal original, es preciso realizar
un filtrado pasobajo a posteriori, que elimine esas componentes “réplicas”. Lo normal es
realizarlo mediante un filtro FIR en el dominio digital.
1.9 Modulación digital con DDS 46

Figura 1.42: Visión en el dominio frecuencial de la interpolación

1.9.3.2. Decimado
En este caso la función del decimado es la opuesta a la de la interpolación: datos que
fueron adquiridos a una velocidad de muestreo Fs1 se vuelven a muestrear a otra velocidad
menor submúltiplo entero de la original Fs2 = Fs1 /m.
La figura 1.43 muestra el esquema de un decimador simple, con m un entero igual
a la relación entre las dos frecuencias de muestreo. De nuevo se nos plantea la misma
cuestión que en el apartado anterior: ¿cómo se deben de manipular los datos originales
para que tomándolos a una velocidad menor no se cambien las caracterı́sticas originales
de la señal?

Figura 1.43: Decimador básico

Se podrı́a pensar que tomando las muestras m-ésimas de la trama original y despre-
ciando las demás, la señal resultante de salida tendrı́a las mismas propiedades. La idea es
buena pero todavı́a no tendrı́amos toda la solución. Observemos la figura 1.44, donde de
nuevo se utiliza un ejemplo sencillo en el que la relación entre las frecuencias de muestreo
es 3.
En este caso, al ser la frecuencia de muestreo de salida 3 veces menor a la de entrada,
1.9 Modulación digital con DDS 47

Figura 1.44: Visión en el dominio frecuencial de la decimación

el criterio de Nyquist cambia y se hace más restrictivo. Para evitar el aliasing en la señal
de salida, es preciso asegurarnos de que la señal de entrada al interpolador cumpla con el
criterio de Nyquist en el nuevo marco de salida, es decir, en un ancho de banda de Nyquist
3 veces menor al de la señal original.
Esto nos lleva a la regla clave de la decimación: El ancho de banda de los datos
antes de la decimación debe de confinarse al ancho de banda de Nyquist de la velocidad de
muestreo menor de salida. Ası́, para un factor de decimación de m, la información original
debe de residir en un ancho de banda dado por Fs1 /(2m), con Fs1 igual a la velocidad
original de muestreo. Si los datos originales contienen información válida en la porción del
espectro más allá de Fs1 /(2m), el decimado no es posible. Este serı́a el caso del ejemplo,
si la porción del espectro de los datos originales más allá de Fs1 /6 de la figura 1.44 fuese
parte integrante de la señal de información en lugar de ruido o señales interferentes.
El filtrado pasobajo previo de la trama digital a decimar se suele realizar, al igual que
en el caso de la interpolación, mediante filtros FIR. El paso siguiente consiste en “sacar”
cada muestra m-ésima utilizando la velocidad de muestreo menor de salida. El resultado
se puede ver en la figura 1.44 (c).

1.9.3.3. Conversión de velocidad racional n/m


Los procesos que se acaban de describir de interpolación y decimado sólo permiten
cambios de velocidades de muestreo enteras. Si se precisa un cambio racional en la veloci-
dad, se pueden llevar a cabo los dos procesos en cascada. Sin embargo, es importante para
que no se pierdan las caracterı́sticas originales de la señal, que el proceso de interpolación
preceda al proceso de decimado. De lo contrario, será preciso confinar el ancho de banda
de los datos originales a Fs /(2m), donde Fs es la velocidad de muestreo original.
1.9 Modulación digital con DDS 48

Figura 1.45: Convertidor de velocidad de muestreo n/m básico

1.9.3.4. Filtros digitales multivelocidad


Hemos visto que tanto en interpoladores como en decimadores se precisa el uso
de filtros pasobajo. En estos casos, se pueden utilizar los conocidos filtros FIR, aunque
existen otros tipos de filtros que no se han mencionado hasta ahora y que encuentran
una aplicación ideal en los casos de cambio de velocidad de muestreo. Son los filtros FIR
polifase y los filtros peine-integrador en cascada, CIC.

Filtro FIR polifase

Este filtro está particularmente indicado para aplicaciones de interpolación. Nor-


malmente la interpolación comienza con la inserción de n − 1 ceros entre cada muestra de
señal, para posteriormente filtrarse la trama resultante una vez muestreada a la velocidad
de salida.
Sin embargo, es posible hacer todas las operaciones de una vez, si el filtro FIR se
diseña de una forma peculiar: En principio, el filtro se diseña normalmente pensando en
que la frecuencia de muestreo va a ser nFs . Como resultado se obtendrá un filtro FIR
de un cierto número de etapas, T. Ahora, se añade a cada etapa un número de retardos
igual a n − 1, que equivalen a las mismas operaciones de multiplicación por cero entre
cada etapa del filtro FIR. De esta manera se consigue la respuesta deseada, a la vez que
se realiza la inserción de los ceros de relleno. El resultado es un filtro FIR de nT etapas,
pero con (n − 1)T de las etapas multiplicadas por cero.

Filtro peine-integrador en cascada, (Cascaded Integrador-Comb, CIC)

El filtro CIC es la combinación de un filtro peine y de un integrador. Un filtro peine


es un filtro FIR simple que contiene un retardo y una etapa sumadora. El integrador es
un tipo de filtro IIR pero sin bloque de realimentación hacia adelante. Un diagrama de
bloques de ambas estructuras se incluye en la figura 1.46.
Una caracterı́stica importante que hace a esta topologı́a tan atractiva es el hecho
de no incluir etapas multiplicadoras: en el integrador se da la multiplicación implı́cita
por uno, mientras que el filtro peine lleva implı́cita la multiplicación por −1, pero ésta
puede realizarse fácilmente mediante una negación. Con esta ausencia de multiplicadores
se consigue un ahorro tremendo en hardware comparado con las arquitecturas tı́picas FIR
e IIR.
Por lo que respecta a la curva de respuesta en frecuencia, el filtro peine actúa como
filtro eliminabanda. Para la etapa simple de la figura 1.46, aparecen dos puntos de ate-
nuación, uno en DC y otro a la frecuencia de muestreo Fs . Añadiendo etapas de retardo,
1.9 Modulación digital con DDS 49

Figura 1.46: Etapas básicas de los bloques filtro peine e integrador

se puede modificar ligeramente la curva de respuesta. De hecho, K bloques de retardo


producen K + 1 puntos de atenuación equiespaciados. De los K + 1 puntos, uno ocurre en
DC y otro en Fs . El resto se distribuye de manera equiespaciada entre DC y Fs .
Por otra parte, el integrador actúa como filtro pasobajo. La respuesta de cada bloque
se representa en la figura 1.47, normalizadas a Fs .

Figura 1.47: Respuesta en frecuencia de los bloques básicos del filtro peine y del integrador

El filtro CIC se construye conectando en cascada los bloques de integrador y filtro


peine. Con vista a realizar la conversión de velocidad de muestreo, el integrador se opera
a una velocidad mientras que el filtro peine funciona con otra distinta siempre divisor
entero de la frecuencia de muestreo del integrador. Lo interesante del montaje es que
puede funcionar tanto de interpolador como de decimador dependiendo del orden en que
se conecte cada etapa. Esta importante caracterı́stica se representa en la figura 1.48.

Figura 1.48: CIC funcionando de interpolador y de decimador

En el caso de filtro CIC funcionando en modo de interpolación, hay que añadir


una ligera puntualización para que el montaje funcione adecuadamente. La modificación
consiste en que la etapa de integración debe de ser capaz de realizar el rellenado de ceros
a su entrada, para asimilar el incremento de velocidad de muestreo. Para cada muestra
1.9 Modulación digital con DDS 50

suministrada por el filtro peine, el integrador debe de insertar n − 1 ceros.


En la figura 1.49 se aprecia la respuesta en frecuencia de un filtro básico CIC para
un factor de interpolación o decimado de 2. (m ó n = 2 en la figura anterior).

Figura 1.49: Respuesta en frecuencia del filtro CIC básico

En esta figura se pone de manifiesto uno de sus problemas potenciales, la distorsión


de atenuación. Se puede ver cómo el nulo se produce para la frecuencia normalizada de
f = 0,5. Como se representa un ejemplo con factor de interpolación igual a 2, resulta un
ancho de banda de Nyquist de f = 0,25. En ese punto, la curva de respuesta manifiesta
una caı́da de aproximadamente 5 dB, en lo que corresponderı́a a la banda de paso de la
señal. Esta caı́da puede resultar un problema serio en algunas aplicaciones a menos que se
compense de alguna manera.
Un método de compensación consiste en preceder la etapa CIC con un filtro inverso
que corrija la caı́da que se produce en él a lo largo del ancho de banda de Nyquist. Otro
método consiste en asegurar la limitación en banda de los datos de entrada, de forma que
se asegure que su banda está concentrada lejos de la caı́da de la curva de respuesta en la
parte mas hacia la izquierda de la gráfica, donde ésta es prácticamente plana.
Existen dos métodos de cambiar la curva de respuesta básica de la figura 1.49. El
primer método consiste en aumentar el número de etapas en cascada, siempre insertando
el mismo número de etapas de filtro peine que de etapas integradoras. Un ejemplo en el
que se utilizan el triple de etapas se representa en la figura 1.50 (a).
El segundo método es añadir múltiples retardos dentro de la sección de filtro peine,
siempre añadiendo el mismo número de retardos a todas las etapas peine en el caso de
existir varias de ellas en cascada. Un ejemplo de un filtro básico CIC con un bloque de
retardo adicional en la etapa de filtro peine se representa en la figura 1.50 (b).
El efecto de cada una de estas opciones se representa en la figura 1.51, junto con la
respuesta básica para comparación. En cada caso se ha empleado un factor de cambio de
velocidad de muestreo igual a 2.
La gráfica (b) corresponde a un aumento del número de etapas en cascada, apre-
ciándose cómo se incrementa la pendiente de caı́da y la amplitud de la banda eliminada.
Por otro lado, la gráfica (c) representa el caso de adicción de etapas de retardo en la
etapa de filtro peine, que resulta en un incremento del número de ceros de la función de
transferencia. También se incrementa la atenuación en la banda de paso, disminuyéndose
a su vez en la banda eliminada. Se suele emplear una combinación de los dos métodos para
conseguir respuestas de tipo variado.
1.9 Modulación digital con DDS 51

(a)

(b)

Figura 1.50: Variaciones al bloque CIC básico


(a) Interpolador CIC triple
(b) Decimador CIC con doble retardo

(a) (b) (c)

Figura 1.51: Comparación de las respuestas CIC modificadas


1.10 Evolución y técnicas auxiliares en los DDS 52

1.9.3.5. Consideraciones acerca del sincronismo entre el reloj y los datos de


entrada
En los moduladores digitales es importante mantener la correcta temporización entre
la fuente de datos y el modulador. En la figura 1.52 se representa un ejemplo de diagrama
de bloques de un modulador digital que se parece bastante al utilizado en el trabajo
práctico. La primera fuente de tiempo en un modulador DDS es el reloj que alimenta al
DDS. De este modo se establece la velocidad de muestreo en las señales seno y coseno
del modulador. Ahora, cualquier señal que se propague desde la entrada de datos hasta
el modulador debe de muestrearse a la misma velocidad que la portadora de salida. Esto
es importante para que exista una correspondencia uno a uno con las muestras de la
portadora. De otro modo, se puede deducir que las operaciones de procesado llevadas a
cabo en el interior del modulador no se realizarán adecuadamente.

Figura 1.52: Diagrama de bloques de un modulador DDS genérico

Aquı́ es donde entra en juego el bloque llamado “convertidor multivelocidad” de la


figura 1.52. Es la manera de trasladar la velocidad de datos de entrada hasta la frecuencia
de muestreo del DDS. Como este convertidor sólo puede trabajar con un factor racional, ésa
debe de ser obligatoriamente la relación entre la velocidad de datos y el reloj del sistema.
Es decir, el reloj del sistema debe operar a un factor n/m veces el reloj de datos (o un
múltiplo entero de ese factor). En los sistemas moduladores corrientes, este convertidor de
velocidad está formado simplemente por una o varias etapas de interpolación o decimado.
En estos casos, el multiplicador de reloj es simplemente un multiplicador o un divisor por
un entero. Por tanto, la fuente de datos y el reloj del sistema están relacionados por un
múltiplo entero en lugar de por un múltiplo fraccional.
En el capı́tulo 4 dedicado al modulador DDS realizado en la práctica, veremos que
la relación entre las dos velocidades de reloj se adecúa mediante dos etapas interpoladoras
CIC en cascada con factor de interpolación ajustable para acomodar diferentes velocidades
de datos de entrada.

1.10. Evolución y técnicas auxiliares en los DDS

Las retos más obvios de un DDS son la velocidad (ancho de banda) y la pureza es-
pectral. Ambos están relacionadas inversamente, mientras que ancho de banda y consumo
lo están de forma directa. Cuanto más densa es la circuiterı́a, más precisa es la forma
de onda de salida y se suprimen más los espúreos, pero la circuiterı́a adicional limita la
velocidad y de aquı́ el ancho de banda, etc. Otros factores son a menudo importantes,
1.10 Evolución y técnicas auxiliares en los DDS 53

incluyendo funciones de modulación, velocidad de conmutación o actualización. Actual-


mente se encuentran fácilmente dispositivos DDS con convertidores D/A integrados de 10
bit soportando velocidades de reloj internas de 180 MHz. El actual “estado del arte” en
tecnologı́a DDS se encuentra a 300 MHz de velocidades de reloj con un convertidor D/A
integrado de 12 bits.
Las tendencias actuales de desarrollo de la tecnologı́a DDS focalizan su atención en
la mejora de los convertidores D/A. La pureza espectral está relacionada con la resolución
del DAC. Si bien es teóricamente posible multiplexar tanto el acumulador como la memoria
a casi cualquier nivel, y por tanto, conseguir virtualmente cualquier velocidad, el DAC es
un cuello de botella a través del que debe pasar la señal, y es la tecnologı́a del DAC la que
impone el lı́mite en los DDSs avanzados.
El acumulador de fase es el menos crı́tico de los bloques constitutivos de los sistemas
DDS. Aunque debe ser construido cuidadosamente, su expansión no es un problema serio.
De hecho los nuevos conceptos de diseño de acumuladores reducen complejidad, número
de puertas lógicas, tamaño y consumo, por tanto haciendo más prácticos estos sistemas.
Otro asunto complicado es la reducción de la memoria utilizada para convertir los
datos de fase en datos de amplitud. Las metodologı́as convencionales requieren aproxima-
damente 119 K para mapear 14 bits de información de fase (del acumulador) a 12 bits de
amplitud (para el DAC). Actualmente ninguna tecnologı́a soporta una memoria de 200
K a alta velocidad (500 Mhz o más), aunque se están realizando desarrollos que intentan
comprimir la memoria considerablemente. Basada en la expansión en serie de Taylor de
la función seno, se consigue comprimir el tamaño de la memoria desde 192K hasta ∼ 3K,
que ya pueden funcionar a 2 nanosegundos (figura 1.53).

Figura 1.53: Compresión de la memoria ROM basada en la monotonicidad


de la función seno

Además de esta mejora en la memoria de conversión fase-amplitud, a continuación


comentaremos brevemente otras funcionalidades fáciles de añadir a la estructura básica
DDS y que, o bien mejoran sus caracterı́sticas básica, o bien permiten ampliar el margen
de aplicaciones de estos sistemas. Actualmente, ya existen gran cantidad de dispositivos
comerciales que las incorporan.

1.10.1. Mejora del Margen Libre de Espúreos mediante dithering de fase


En la sección 1.5 se habló del efecto del truncamiento de fase en la arquitectura DDS.
El resultado principal es su traducción en espúreos en el espectro de salida dependiendo
de la elección de la palabra de sintonı́a. En algunas aplicaciones, es deseable reducir la
energı́a de los espúreos a cualquier precio. La agitación (dithering) de fase es una técnica
para conseguirlo. Esto se consigue a costa de elevar el suelo de ruido e incrementar el ruido
1.10 Evolución y técnicas auxiliares en los DDS 54

de fase del sistema.


La figura 1.54, es un diagrama de bloques de un DDS simple. En la figura 1.54
(a), la palabra de sintonı́a de T bits se aplica a la entrada del acumulador. Los A bits
más significativos de la salida del acumulador alimentan al bloque de conversión ángulo-
amplitud, el cual suministra valores de D bits al conversor A/D. Se supone que T > A > D.

(a)

(b)

Figura 1.54: Diagrama de bloques de un DDS genérico

En figura 1.54(b) se ve la relación entre esta variedad de longitudes en las palabras


del DDS. Podemos apreciar que los bits de salida del acumulador de tamaño A, constituyen
un subconjunto del grupo de palabras de sintonı́a de tamaño T . De la misma manera, la
salida del convertidor fase-amplitud tiene un tamaño de palabra D que es subconjunto del
tamaño de la palabra de salida del acumulador.
El dithering de fase requiere que los valores de fase generados por el acumulador
contengan una cierta cantidad de ruido. Esto se puede conseguir añadiendo un pequeño
numero aleatorio generado a la salida del acumulador. El método se describe en la figu-
ra 1.55.

Figura 1.55: Dithering de fase en un DDS

En el modelo de dithering de fase, un generador de secuencia binaria seudoaleatoria


se utiliza para producir un nuevo número aleatorio de R bits con cada actualización del
acumulador. Los números seudoaleatorios se escalan en potencias de 2 para encajar dentro
1.10 Evolución y técnicas auxiliares en los DDS 55

del margen deseado de la palabra de P bits de salida del acumulador. El número aleatorio se
posiciona de forma que su bit más significativo sea menor que el bit menos significativo de
la palabra de A bits de entrada al convertidor angulo-amplitud (AAC). No se recomienda
desplazar el número aleatorio de forma que se superponga a la palabra de A bits. Hacer
esto desecha el propósito de tener A bits de resolución de fase en primer lugar, ya que ello
añade un ruido que es mayor al ruido de cuantificación asociado a la palabra de A bits.
La posición de la palabra de R bits tiene impacto significativo en la magnitud del
dithering de fase. En efecto, el desplazar a la izquierda el número aleatorio incrementa
su impacto cuando se suma con la palabra de P bits tomada a la salida del acumulador.
Tı́picamente, el bit mas significativo del número aleatorio se posiciona un bit menos del
bit menos significativo de la palabra de A bits que se envı́a al AAC.
El número de bits del número aleatorio determina el modo en el que la fase aleatoria
se disgrega en el espectro de salida del DDS. Tı́picamente, un número aleatorio de 3 a 4
bits es suficiente.

1.10.2. Generación de barridos “chirp” mediante DDS


El “chirp” (chirrido) en frecuencia es un método de realizar transiciones entre dos
frecuencias de salida, f1 y f2 durante un intervalo de tiempo especı́fico. La forma más
simple de realización es un barrido lineal desde f1 a f2 . Sin embargo, en sistemas más
avanzados, la transición de frecuencias desde f1 a f2 puede ser una función no lineal en el
tiempo. Un sistema chirp basado en DDS se muestra en la figura 1.56.

Figura 1.56: Sistema Chirp basado en DDS

Empezando desde el acumulador de fase y trabajando hacia la derecha, el sistema es


un DDS básico. Sin embargo, el acumulador de fase no está alimentado por una palabra de
sintonı́a estática como es el caso del DDS básico. En cambio, la entrada al acumulador de
fase es la suma de la palabra de sintonı́a de inicio y la salida del acumulador de frecuencia.
La palabra de sintonı́a de inicio es la palabra de sintonı́a de frecuencia que marca f1 (la
frecuencia inicial del barrido).
El acumulador de frecuencia suma recursivamente la palabra delta de frecuencia a
la velocidad prescrita por el “reloj de rampa”. Por tanto, a cada pulso del reloj de rampa
se incrementa el valor de entrada al acumulador de fase una cantidad igual a la palabra
delta de frecuencia. Como la entrada al acumulador de fase determina la frecuencia de
salida del DDS y este valor está cambiando con el tiempo, entonces también la frecuencia
de salida del DDS lo hará. Este es el mecanismo básico de generación de barridos “chirp”.
1.10 Evolución y técnicas auxiliares en los DDS 56

Asumiendo que el reloj de rampa genera un pulso de reloj a intervalos regulares


y que la palabra delta de frecuencia es constante, entonces la salida del acumulador de
frecuencia crece a velocidad lineal. Esto es, la pendiente de la frecuencia en función del
tiempo es constante. Estarı́amos ante un “chirp” lineal.
También es posible general barridos no lineales. Si la palabra delta de frecuencia se
modifica, la velocidad a la cual la frecuencia de salida del DDS cambia también se modi-
fica. Esto es, la pendiente de la frecuencia en función del tiempo cambia, de manera que
modificar la palabra delta de frecuencia durante el intervalo del barrido varı́a la pendiente
de la frecuencia en función del tiempo. Esto proporciona un medio de generar cualquier
función “chirp” mediante aproximaciones lineales de la respuesta deseada.
La funcionalidad de implementar barridos en un DDS requiere temporización y con-
troles adicionales. Esta es función de la lógica de temporización de rampa. Realmente sirve
a dos propósitos. En primer lugar, debe de dividir el reloj del sistema para producir la
adecuada frecuencia de reloj de rampa definida en el registro ramp rate. En segundo lugar,
debe terminar el reloj de rampa cuando la frecuencia de salida alcanza el valor f2 (la
frecuencia de final del barrido). La determinación del momento en que el reloj de rampa
debe terminar se consigue monitorizando la salida del acumulador de frecuencia y el valor
de la palabra de final de sintonı́a. Cuando la salida del acumulador de frecuencia es mayor
o igual a la palabra de stop, el reloj de rampa se deshabilita. La lógica de temporización
de rampa debe de asegurar que el acumulador de frecuencia no sobrepase el valor de la
palabra de final de sintonı́a.

1.10.3. Generación de modulación de amplitud mediante DDS


Para algunas aplicaciones es interesante controlar la amplitud de salida de la señal
DDS. Tal es el caso de un transmisor AM basado en DDS o en aplicaciones en las que la
portadora está presente únicamente durante los intervalos de trasmisión. En aplicaciones
de señales pulsadas se pueden producir problemas en las transiciones bruscas de amplitud,
que pueden producir interferencias en los canales adyacentes. En estos casos, un control
preciso de amplitud permite que la señal se desvanezca poco a poco, haciendo menor el
ruido durante los transitorios de conmutación.
La arquitectura básica DDS no permite el control de amplitud. Sin embargo, esto
se consigue con una modificación muy simple: la adición de una etapa multiplicadora
precediendo al convertidor D/A. Muchos dispositivos comerciales suelen incorporar esta
caracterı́stica.

Figura 1.57: DDS con control de amplitud

En la figura 1.57, si suponemos que la palabra de control de amplitud de entrada


puede tomar valores entre 0 y 1, la salida del DDS presentará una versión a escala del
valor suministrado desde el convertidor ángulo-amplitud. Un valor 0 anula la salida del
1.10 Evolución y técnicas auxiliares en los DDS 57

DDS, mientras que para el valor de 1 la salida es la indicada desde el conversor AAC. Se ve
que es una manera inmediata de generar señales AM, también de controlar el transitorio
ON-OFF en señales pulsadas.

1.10.4. Funcionalidades adicionales en DDS


En resumen, los nuevos diseños añaden gran cantidad de registros y circuiterı́a que,
sin formar parte de la estructura básica DDS hacen que estos sistemas se acerquen real-
mente al mundo práctico. En este apartado se realiza un resumen de todas estas variaciones
que habiendo sido nombradas a lo largo del capı́tulo, a buen seguro formarán parte del
núcleo de evolución de esta tecnologı́a.
El diagrama de bloques de un dispositivo DDS con prestaciones añadidas ya se
representó el la figura 1.9. Por comodidad se presenta de nuevo a continuación.

(a)

(b)

Figura 1.58: Prestaciones añadidas en un sistema DDS


(a) Puntos sobre los que se accede para conseguir estas presta-
ciones
(b) Esquema de bloques de un dispositivo DDS con prestaciones
añadidas

Enumeramos los bloques adicionales que se representan en la figura 1.58 (b).

Multiplicador interno del reloj de referencia. De este modo se reduce la frecuencia


del reloj de referencia de entrada facilitando la utilización de los dispositivos DDS
con fuentes de reloj más fáciles de manejar.
1.10 Evolución y técnicas auxiliares en los DDS 58

Acumulador de fase después del sumador, que permite retardos de fase dependiendo
de una palabra de sintonı́a de fase. De este modo se consiguen modulaciones de
fase, con una resolución que depende de los bits de la palabra de sintonı́a de fase.
Tı́picamente se utilizan registros de 14 bits, aunque pueden llegarse a utilizar 32
bits, con lo que la resolución de fase es enorme, figura 1.59 (a).

(a)

(b)

Figura 1.59: Modulaciones de fase en un dispositivo DDS


(a) Modulación de fase.
(b) Modulación de frecuencia

Bloque sinc inverso. Compensa la caı́da sinx/x producida por la curva de respuesta
de la salida cuantificada del DAC minimizando este efecto.

Multiplicador digital insertado entre la salida de la tabla de referencia y el conversor


D/A, permitiendo la modulación de amplitud de la salida senoidal.

A veces se integra otro conversor adicional D/A para generar simultáneamente la


función coseno, lo que permite generar las salidas I y Q totalmente coincidentes en
frecuencia, cuadratura de fase y amplitud.

Comparador adicional, que facilita el uso del dispositivo DDS como generador de
reloj, convirtiendo la senoide del DDS en una forma de onda cuadrada.

Registros adicionales de frecuencia y fase que pueden ser preprogramados a priori,


activándose mediante un único pin de control. Es una configuración ideal para gene-
rar FSK si se dispone de dos registros de frecuencia, uno programado a la frecuencia
de “marca el otro a la de “espacio”.
2
1.10 Evolución y técnicas auxiliares en los DDS 59

Aunque la tecnologı́a DDS está en continuo avance, y circuitos con prestaciones


que hoy nos parecen superiores en seis meses quedan superadas por los nuevos diseños,
podemos resumir el actual estado de desarrollo de esta técnica en la tabla 1.1.

Caracterı́stica Prestación Observaciones


Sintonı́a en frecuencia 48 bits Resolución de 1 µHz
Sintonı́a de fase 32 bits Resol. control de retardo
de fase 0.00000008o
fclk interno 300 MHz Hab. multiplic. interno ×10
Rango de multiplic. CLKref ×4 hasta ×10
Ancho de Banda salida 100 MHz Asumiendo 1/3 de fclk
Velocidad de cambio de frec. 100 MHz 8 bit carga paralela
Control de amplitud 12bits Desde 0 a fondo escala
Espureos -50 dBc Peor caso en WB para fout
de 80 MHz
Adaptación I-Q 0.01o
Rizado desde DC a Niquist 0.01 dB
DAC 12 bits Doble

Cuadro 1.1: “Estado del Arte” de la tecnologı́a DDS comercial (1999)

1.10.5. Chips DDS comerciales

Terminamos el capı́tulo con una tabla donde se incluye una recopilación realizada
en internet sobre los últimos dispositivos DDS del mercado. Son circuitos de las marcas
Analog Devices, Harris Semiconductor, Qualcom y Standford Telecom.
En cada entrada de la tabla se incluyen las caracterı́sticas fundamentales de cada
circuito, que pueden servir de comparación con el resto de los integrados.
1.10 Evolución y técnicas auxiliares en los DDS 60

Nombre Clk max. Disipación Res Frec DAC Control Descripción


Mhz mW bits bits
Q2240 1 100 2000 32 12 (NI)2 Paralelo, NCO simple sin DAC integrado
100Mhz
Q2368 130 o 1250 32 × 2 12(NI) Paralelo, Doble DDS,
65×2 Serie BPSK/BFSK/QPSK/8PSK/Chirp,
Circuito de reducción de espúreos
NCR patentado
Q2334 50 667 32 × 2 12(NI) Paralelo Doble DDS, PSK/FSK/MSK/FH,
32 bits de resolución de fase
AD9832 3 25 120 32 10 Serie DDS Completo, Capacidad
FM/PM, Truncamiento a 12 bits
AD9831 25 120 32 10 Paralelo DDS Completo, Capacidad
FM/PM, Truncamiento a 12 bits
AD9835 50 200 32 10 Serie DDS Completo, Capacidad
FM/PM, Truncamiento a 12 bits,
16 pines
AD9830 50 300 32 10 Paralelo DDS Completo, Capacidad
FM/PM, Truncamiento a 12 bits
AD9850 125 480 32 10 Paralelo, DDS Completo, Comparador in-
Serie dep
AD9853 165 1150 32 10 Serie Modulador DDS,
FSK/QPSK/16QAM, Multi-
plicador fclk interno ×6, Filtro
programable, compensación
sen(x)/x
AD9851 180 650 32 10 Paralelo, DDS Completo, Comparador in-
Serie dep, Multiplicador fclk interno ×6
AD9856 180 450 32 12 Serie Convertidor ascendente en cuadra-
tura
AD9854 300 1200 - 2 × 12 - DDS Completo, Modo Chirp, Mul-
tiplicador fclk programable
AD9852 300 1200 - 12 - DDS Completo, Modo Chirp, Mul-
tiplicador fclk programable
AD7008 50 625 32 10 Paralelo, DDS Generador vectorial, Tablas
Serie de seno y coseno, Truncamiento fa-
se a 12 bits, AM/FM/PM, Modu-
lador I/Q 10 de bit
HSP45102 4 40 785 32 12 (NI) Serie DDS simple sin DAC integrado,
FSK/QPSK
HSP45106 33 1240 32 16 (NI) Paralelo NCO,
FM/FSK/BPSK/QPSK/8PSK,
Reg. offset fase de 32 bits, Trunca-
miento a 20 bits
HSP45116A 52 2850 32 16 (NI) Paralelo NCO, AM/FM/PM/QAM etc,
Reg. offset fase de 32 bits,
Truncamiento a 20 bits, Acumula-
dor/multiplicador complejo de 16
bit (modulaciones I/Q)
STEL-1172B 50 750 32 2 × 8 Paralelo NCO con tablas de seno y coseno,
(NI) Truncamiento a 12 bits
STEL-1173 5 50 750 48 12 (NI) Paralelo NCO alta resolución, Truncamien-
to a 13 bits, tabla de seno o coseno

1
Qualcomm, http://www.qualcomm.com
2
DAC no incluido en el chip
3
Analog Devices, http://www.analog.com/
4
Harris, http://www.harris.com/
5
Standford Telecom, http://www.stelhq.com/
1.10 Evolución y técnicas auxiliares en los DDS 61

Nombre Clk max. Disipación Res Frec DAC Control Descripción


Mhz mW bits bits
STEL-1174 50 750 16 12 (NI) Paralelo NCO de bajo costo, Truncamiento
a 13 bits, tabla de seno o coseno
STEL-1175 125 1875 32 12 (NI) Paralelo NCO Modulador, Truncamiento a
13 bits, tabla de seno o coseno, Sa-
lida lineal 12 bits disponible para
PM/PSK/QAM/FSK
STEL-1176 80 1200 35 12 (NI) Paralelo NCO Modulador, Truncamiento a
15 bits, modulación directa 8PSK
con 3 bits
STEL-1177 60 2100 32 2 × 12 Paralelo NCO Modulador, Truncamiento a
(NI) 13 bits, Tablas de seno y coseno,
FM/PM/FSK, Reg. offset fase de
12 bits
STEL-1178A 80 800 2 × 32 2× Paralelo NCO Modulador DOBLE, Trunca-
12(NI) miento de fase a 13 bits, PM (3
bits)/FM
STEL-1179 25 250 24 12 (NI) Serie NCO Modulador, PM (3 bits)
STEL-1180 60 - 32 12 (NI) - NCO-Chirp, Truncamiento a 13
bits, PM (16 bits)/FM, Generación
lineal chirp 16 bits con produc-
to pendiente/duración de 16 bits,
chirp no lineal programable
STEL-2173 800 - 32 8 (NI) - NCO Modulado, Truncamiento a
10 bits, BPSK/QPSK 2 bits
STEL-2176 160 1010 32 10 Paralelo Modulador-Demodulador DDS
Completo, BPSK/QPSK/16QAM,
Multiplicador interno de fclk ,
filtro FIR de 32 etapas, máxima
velocidad 10Mbps en BPSK
Capı́tulo 2

Secuencias pseudoaleatorias y
registros de desplazamiento

Desde hace cuatro décadas se ha desarrollado, explotado y refinado la idea de utilizar


registros de desplazamiento para generar secuencias binarias. Actualmente, existe una
gran variedad de aplicaciones diferentes de los registros de desplazamiento, incluida la
generación de secuencias pseudoaleatorias. El creciente interés por este tipo de secuencias
justifica la inclusión de este capı́tulo.
Las principales áreas de aplicación de las secuencias generadas en registros de des-
plazamiento son las siguientes:

Generadores de códigos seguros y de acceso limitado.

1. Cifrado: Se realiza la suma en módulo 2 del mensaje binario con una secuen-
cia generada en un registro de desplazamiento que actúa como “llave”. Para
descifrar se vuelve a sumar la llave al mensaje codificado.
2. Códigos de direcciones múltiples: Diferentes porciones de una secuencia gene-
rada en un registro de desplazamiento se pueden asignar como dirección carac-
terı́stica de un gran número de elementos, estaciones, aeronaves, nodos de red,
etc. Se consigue que un gran número de generadores puedan enviar información
sistemáticamente a su controlador.

Generadores de códigos eficientes.

1. Códigos correctores de error: Los códigos cı́clicos se basan en secuencias de re-


gistros de desplazamiento. Ejemplos de este tipo de códigos son los códigos de
Hamming, de Golay extendidos, los códigos BCH (Bose-Chadhuri-Hocquenghem),
y los códigos de Reed-Solomon.
2. Señales recuperables en entorno ruidoso: La propiedad de autocorrelación de
estas secuencias hace que en aplicaciones de radar de largo alcance con mucho
ruido de fondo, trenes de pulsos modulados por un registro de desplazamiento
sean recuperables incluso bajo relaciones señal/ruido negativas de muchos dB.
3. Modulaciones de espectro ensanchado: Esa misma propiedad de autocorrelación
hace que un gran número de usuarios pueda compartir una misma frecuencia
de transmisión y un mismo ancho de banda, si cada uno de ellos utiliza una
secuencia pseudoaleatoria diferente para modular su información.

62
2.1 Secuencias con propiedades de aleatoriedad 63

Generadores de códigos con propiedades predefinidas.


1. Generadores de perı́odo predefinido: Se ha probado que con un registro de
desplazamiento de grado n, todas las longitudes de secuencias p entre 1 y 2n
(inclusive) se pueden conseguir si se escoge adecuadamente la lógica de reali-
mentación.
Modelos matemáticos.
1. Generadores de secuencias aleatorias: Un registro de desplazamiento que genere
secuencias de longitud máxima sirve como modelo aproximado de experimento
aleatorio, al margen de la componente determinista del sistema.
2. Máquinas de estados finitos: Un registro de desplazamiento con realimentación
sirve como el ejemplo no trivial más simple de máquina de estados finitos sin
entradas externas. El registro de desplazamiento sirve como “animal experi-
mental” para investigaciones en máquinas de lógica recursiva y de autómatas.
3. Procesos de Markov: Se puede establecer una analogı́a entre el diagrama de
estados y transiciones de un registro de desplazamiento de n-etapas y el dia-
grama de estados de Markov para un canal binario con dependencia estadı́stica
limitada a n bits anteriores.

2.1. Secuencias con propiedades de aleatoriedad

El uso de secuencias de datos binarios que se asemejen el máximo posible a secuencias


aleatorias está muy extendido en la actualidad: modulaciones de espectro ensanchado
spread spectrum, donde se trata de distribuir la energı́a lo más amplia y uniformemente
posible a lo largo de un gran ancho de banda simulando ruido; también se utilizan circuitos
aleatorizadores, scramblers, circuitos que generan este tipo de secuencias, . . .
Cualquiera que sea la aplicación para la que se utilicen, se trata siempre de secuencias
lo más parecidas al ruido blanco, pero generadas de modo controlado.
¿En qué se diferencia una señal pseudoaleatoria de una verdaderamente aleatoria?
Una señal aleatoria no se puede predecir ; sus variaciones futuras solo pueden ser descritas
en sentido estadı́stico. Sin embargo, una señal pseudoaleatoria no es en absoluto aleatoria,
es determinista, periódica y conocida tanto por el transmisor como por el receptor. ¿Por
qué entonces las llamamos “pseudoruido” ó “pseudoaleatorias¿: Incluso aunque la señal
sea determinista, parece tener las propiedades estadı́sticas del ruido blanco muestreado.
Para un escucha no autorizado parece como si se tratase de una verdadera señal aleatoria.

2.1.1. Propiedades de las secuencias aleatorias


¿Cuáles son las propiedades que hacen que una señal pseudoaleatoria aparezca co-
mo verdaderamente aleatoria? Hay tres propiedades básicas que pueden ser aplicadas a
cualquier secuencia binaria periódica como prueba de su grado de aleatoriedad. Las pro-
piedades, llamadas de balance, realización y correlación, se describen a continuación para
señales binarias:

Propiedad de Balance . Un buen balance requiere que en cada periodo de la secuencia,


el número de unos binarios difiera del número de ceros binarios como máximo en
una unidad.
2.2 Secuencias generadas mediante registros de desplazamiento 64

Propiedad de realización . Una realización se define como una secuencia de un único


tipo de dı́gitos binarios. La aparición de un dı́gito alterno en una secuencia arranca
una nueva realización. La longitud de una realización es el número de dı́gitos en
la misma. Entre las realizaciones de unos y ceros en cada periodo, es deseable que
alrededor de la mitad de las mismas de cada tipo sean de longitud 1, alrededor de
un cuarto sean de longitud 2, la octava parte de longitud 3 y ası́ sucesivamente.

Propiedad de correlación . Si un periodo de la secuencia es comparado término a


término con cualquier desplazamiento cı́clico de la misma, es mejor que el núme-
ro de coincidencias difiera del número de diferencias en no más de una unidad. Esto
es equivalente a decir que su función de autocorrelación R(τ ) tienda a cero para
τ 6= 0.

La función de autocorrelación Rx (τ ) de una función periódica x(t) de periodo To , se


define de forma normalizada como:
 Z T0 /2
1 1
Rx (τ ) = x(t)x(t + τ )dt para − ∞ < τ < ∞ (2.1)
K T0 −T0 /2

donde Z T0 /2
1
K= x2 (t)dt (2.2)
T0 −T0 /2

Cuando x(t) es una secuencia periódica representando un código pseudoaleatorio,


nos referimos a cada dı́gito fundamental como un sı́mbolo del código pseudoaleatorio o un
chip. Para una secuencia pseudoaleatoria de periodo p chips, la función de autocorrelación
normalizada se puede expresar como:

 
numero de coincidencias menos numero de desacuerdos
 
1  comparando un periodo completo de la secuencia con 
Rx (τ ) = ·  (2.3)
p  una versión desplazada de la misma un numero τ de
 

desplazamientos cı́clicos

La función de autocorrelación normalizada para una secuencia de longitud máxima,


Rx (τ ), se puede apreciar en la figura 2.2. Está claro que para τ = 0, cuando x(t) y su réplica
coinciden perfectamente, Rx (τ ) = 1. Sin embargo, para cualquier otro desplazamiento
cı́clico ente x(t) y x(t + τ ) con 1 ≤ τ < p, la función de autocorrelación es igual a
−1/p (para valores de p grandes, las secuencias están virtualmente incorreladas para un
desplazamiento de un único chip.
En la siguiente sección se genera una secuencia pseudoaleatoria para comprobar
estas tres propiedades.

2.2. Secuencias generadas mediante registros de desplaza-


miento

Consideremos el registro de desplazamiento de la figura 2.1. Consta de cuatro re-


gistros de desplazamiento, un sumador módulo 2 y una conexión de realimentación desde
2.2 Secuencias generadas mediante registros de desplazamiento 65

el sumador a la entrada del registro. El sumador módulo dos puede ser implementado
mediante una puerta or-exclusiva. La operación del registro de desplazamiento se controla
mediante los pulsos de reloj que no aparecen en la figura. En cada pulso de reloj los con-
tenidos de cada etapa del registro se desplazan una etapa a la derecha. También, a cada
pulso de reloj los contenidos de las etapas x3 y x4 se suman módulo 2 (una operación
lineal), y el resultado es llevado de nuevo hacia atrás a la etapa x1 .
Prestemos atención a la sucesión de estados de una etapa, por ejemplo la primera.
Supongamos que la historia del registro está formada por los sucesivos términos a0 , a1 ,
a2 , . . . , an . Desde el punto de vista de la realimentación, an es una suma módulo 2 de los
contenidos de varias etapas del registro en el estado n − 1. De hecho cada registro en la
suma módulo 2 que calcula an se puede tracear hacia atrás hasta llegar a un estado previo
de la primera etapa del registro en sı́. Por tanto, an satisface una ecuación del tipo:

an = c1 an−1 + c2 an−2 + · · · + cr an−r

donde los coeficientes c1 , c2 , . . . , cr son unos y ceros que no dependen de n. Por


supuesto la suma es módulo 2. A esta relación se la denomina recurrencia lineal.

Figura 2.1: Ejemplo de registro de desplazamiento con realimentación lineal

Siguiendo con el ejemplo de la figura 2.1 asumamos que la etapa x1 está inicialmente
a uno y las restantes a cero, esto es, el estado inicial del registro es 1000. De la figura 2.1
podemos ver que la sucesión de estados en las etapas del registro serán las siguientes:

1000 0100 0010 1001 1100 0110 1011 0101


1010 1101 1110 1111 0111 0011 0001 1000

Como el último estado, 1000, se corresponde con el inicial, vemos que el registro
repite la secuencia anterior después de 15 ciclos de reloj. Se han generado todos los estados
posibles exceptuando el 0000. La secuencia de estados de la primera etapa es la siguiente:

100110101111000

Esta secuencia cumple la recurrencia lineal

an = an−3 + an−4
2.2 Secuencias generadas mediante registros de desplazamiento 66

Además se cumple que la historia de estados de la segunda etapa es la misma que


la de la primera con un retardo de un periodo de reloj, y ası́ sucesivamente con las demás
etapas. Esto quiere decir que todas las etapas cumplen la misma relación de recurrencia
lineal al igual que la primera etapa. Se puede decir que todo el registro de desplazamiento
cumple la relación de recurrencia.
No es difı́cil demostrar el enunciado que sigue a continuación, referido a que la
sucesión de estados en un registro de desplazamiento es periódica, con un periodo p 5
2r − 1, donde r es el número de etapas del registro.
Cada estado del registro de desplazamiento viene determinado por su predecesor.
De aquı́ que si siempre ocurre que un estado es igual a algún estado anterior, entonces los
siguientes estados son los mismos, de manera que ya tenemos establecida una perioricidad.
Con r etapas en un registro de desplazamiento existen sólo 2r estados posibles. Por
lo tanto la repetición se produce entre alguno de los primeros 2r + 1 estados, y de aquı́ ya
tenemos la perioricidad con p 5 2r .
Finalmente, si se produce el estado “todo ceros”, los siguientes estados serán siempre
también “todo ceros”, y la perioricidad es p = 1. Por lo tanto el periodo largo no puede
incluir este estado, y p 5 2r − 1.
Este teorema se cumple independientemente del estado inicial del registro de des-
plazamiento.
Comprobemos en la secuencia anterior las propiedades de aleatoriedad de la sec-
ción 2.1.1 . En primer lugar. la propiedad de balance; hay siete ceros y ocho unos en la
secuencia; de aquı́, se ve que la secuencia cumple la condición de balance. A continuación
la propiedad de realización; consideremos las realizaciones del cero, hay cuatro. La mitad
son de longitud 1, y un cuarto son de longitud 2. Lo mismo ocurre con las realizaciones
del uno. La secuencia es demasiado pequeña para ir más allá, pero podemos ver que la
condición de realización se cumple. Para comprobar si la secuencia de salida del registro de
desplazamiento de la figura 2.1 cumple la tercera propiedad de aleatoriedad, correlación,
se muestra la secuencia de salida y también la misma secuencia desplazada de forma cı́clica
en un chip:

000100110101111
100010011010111
dccddcdcddddccc

Los dı́gitos coincidentes están etiquetados con una ç”, mientras que con una ”d”se
indican los desacuerdos. Según la ecuación 2.3 el valor de la función de autocorrelación
para este desplazamiento simple de un chip es:
1 1
R(τ = 1) = (7 − 8) = −
15 15
Cualquier desplazamiento cı́clico que difiera de la coincidencia completa resulta tener
el mismo valor de autocorrelación, −1/p. De aquı́ que la secuencia cumple la tercera
propiedad de aleatoriedad.

2.2.1. Funciones generadoras


Dada la secuencia {an } = {a0 , a1 , a2 , . . . }, sucesión de estados de la primera etapa
de un registro de desplazamiento, podemos asociar a ella la función generadora:
2.2 Secuencias generadas mediante registros de desplazamiento 67

Figura 2.2: Función de autocorrelación de la secuencia pseudoaleatoria de


ejemplo


X
G(x) = an xn (2.4)
n=0
El estado inicial del registro de desplazamiento se puede considerar como

a−1 , a−2 , . . . , a−r (2.5)


Si an satisface la relación de recurrencia
r
X
an = ci an−i ,
i=1
operando resulta:
Pr −i + · · · +
i
i=1 ci x (a−i x a−1 x−1 )
G(x) = Pr (2.6)
1 − i=1 ci xi
Esta relación expresa G(x) enteramente en función de las condiciones iniciales a−1 ,
a−2 ,. . . , a−r , y de los coeficientes de realimentación c1 , c2 ,. . . cr . De hecho, el denominador
de 2.6 es independiente incluso de las condiciones iniciales.
Si las condiciones iniciales son a−1 = a−2 = · · · = a1−r = 0, a−r = 1, la expresión
2.6 se reduce a
c
G(x) = Prr i
(2.7)
1− i=1 ci x
Al denominador de esta última relación se le llama polinomio caracterı́stico de la
secuencia {an } y del registro de desplazamiento que la produce
r
X
f (x) = 1 − ci xi (2.8)
i=1
P n
Obsérvese lo fácil que se genera el polinomio caracterı́stico f (x) = 1 − x , donde el
sumatorio se aplica a los valores de n donde la n-ésima etapa del registro de desplazamiento
2.2 Secuencias generadas mediante registros de desplazamiento 68

se realimenta al sumador módulo 2 (figura 2.1). También conviene recordar que la resta
en aritmética módulo 2 equivale a la suma.

2.2.2. Determinación del perı́odo


Ya sabemos que las secuencias generadas en los registros de desplazamiento son
periódicas, y conocemos la acotación superior para tal perı́odo. La ecuación 2.7 nos permite
dar una aproximación más exacta.
Si se cumplen las condiciones iniciales descritas en el apartado anterior a−1 = a−2 =
· · · = a1−r = 0, a−r = 1, se demuestra que el periodo de la secuencia es el entero positivo
menor p para el cual el polinomio caracterı́stico f (x) divide a 1 − xp módulo 2:
Bajo las condiciones indicadas, al ser la secuencia {an } de perı́odo p se cumple:

1 X
G(x) = = an cn (2.9)
f (x)
n=0

1
= (a0 + a1 x + · · · + ap−1 xp−1 ) + xp (a0 + a1 x + · · · + ap−1 xp−1 )
f (x)
+x2p (a0 + a1 x + · · · + ap−1 xp−1 ) + . . .
= (a0 + a1 x + · · · + ap−1 xp−1 )(1 + xp + x2p + x3p + . . . )
= (a0 + a1 x + · · · + ap−1 xp−1 )/(1 − xp )

Por tanto:

f (x)(a0 + a1 x + · · · + ap−1 xp−1 ) = 1 − xp , (2.10)


y f (x) divide a 1 − xp .

Según 2.6, G(x) = g(x)/f (x), donde el numerador g(x) tiene un grado menos que
f (x). Si el registro de desplazamiento está aprovechando el hecho de que tiene r etapas,
entonces f (x) tiene grado r, y no se pierde la generalidad si se supone que siempre es éste el
caso. Si g(x) no tiene factores en común con f (x), entonces se sigue cumpliendo el teorema
demostrado anteriormente y el número entero menor p tal que f (x) divide a 1 − xp , es el
perı́odo de la correspondiente secuencia. Al número p se le conoce como exponente de Fax.
El caso particular de la demostración corresponde a g(x) = 1. Otro caso muy importante
se da cuando f (x) es irreducible, en cuyo caso no puede tener factores en común con
g(x), un polinomio de grado más bajo, a no ser que g(x) = 0, que corresponde a unas
condiciones iniciales “todo ceros”. Por lo tanto, cuando f (x) es irreducible, el periodo
de la secuencia del registro de desplazamiento no depende de las condiciones iniciales,
exceptuando únicamente el caso de la condición inicial “todo ceros”.

2.2.2.1. Una condición necesaria para longitud máxima


En el caso en que la secuencia A = {an } sea de longitud máxima, su perı́odo es
p = 2r − 1, y se cumple que su polinomio caracterı́stico f (x) es irreducible. El recı́proco
no es cierto.
La demostración de este teorema parte de que al ser la secuencia A de longitud
máxima, existirán a lo largo de la misma todas las combinaciones de secuencias de unos
y ceros de longitud r (excepto r ceros consecutivos). En particular, se podrá encontrar un
2.2 Secuencias generadas mediante registros de desplazamiento 69

uno seguido de r − 1 ceros, que constituyen las condiciones iniciales con las que se obtuvo
el polinomio caracterı́stico del registro de desplazamiento. Consecuentemente se cumple
que el perı́odo de la secuencia A es el exponente de f (x). Por reducción al absurdo se
demuestra que no puede cumplirse el que la secuencia sea de longitud máxima si se diera
el caso de que f (x) fuese reducible y tuviera dos factores de la forma f (x) = s(x)t(x),
alcanzándose en este caso una longitud de secuencia menor a 2r − 1.
Tampoco se cumple el recı́proco, es decir, el hecho de que el polinomio caracterı́stico
f (x) sea irreducible no es condición suficiente para establecer que la secuencia sea de
longitud máxima: Por ejemplo, f (x) = x4 + x3 + x2 + x + 1 es irreducible, pero como
divide a 1 − x5 , la secuencia que genera es de periodo 5, en lugar del periodo máximo
24 − 1 = 15. De la misma manera, f (x) = x6 + x3 + 1 es irreducible, pero tiene exponente
9 en vez de 63.

2.2.3. El método matricial


También se llega a las mismas deducciones si se considera a cada estado de un registro
de desplazamiento de r etapas como un vector r-dimensional. El registro de desplazamiento
es entonces un operador lineal que cambia cada estado en el siguiente. De esta forma, lo
más conveniente es representar al operador lineal sobre vectores r-dimensionales mediante
una matriz de r × r.
En general, una matriz representativa de un registro de desplazamiento toma la
forma:
 
c1 1 0 . . . 0
 
 c2 0 1 0 
 
 .. .
. . . .
.
M = . , (2.11)

 . . . 

 cr−1 0 0 1 
 

cr 0 0 . . . 0
con unos a lo largo de la diagonal justo encima de la diagonal principal, y los “coeficientes
de realimentación.en la primera columna. Realicemos una verificación explı́cita:

 
c1 1 0 ... 0
 
 c2 0 1 0 
(an−1 , an−2 , . . . , an−r )  .. .. . . ..

. . 1 
 
 . .
cr 0 0 . . . 0
= (c1 an−1 + c2 an−2 + · · · + cr an−r , an−1 , an−2 , . . . , an−r+1 )
= (an , an−1 , . . . , an−r+1 )

La ecuación caracterı́stica de la matriz M es:


2.3 Polinomios módulo 2 70


c1 − λ 1 0 ··· 0


c2
−λ 1 · · · 0
f (λ) = det|M − λI| = c3 0 −λ · · · 0

.. .. .. ..

. . . .


cr 0 0 −λ
h c 1 c2 c 3 cr i
= −(−λ)r 1 − − 2 − 3 − ··· − r
λ λ λ λ
(−1)r+1 
1 − (c1 x + c2 x2 + · · · + cr xr )

= r
x
donde se ha realizado la sustitución x = 1/λ. Se puede apreciar que exceptuando el
término(−1)r+1 /xr , la ecuación caracterı́stica de la matriz M es el polinomio caracterı́stico
del registro de desplazamiento.
En este caso, determinar el periodo del registro de desplazamiento equivale, excepto
en casos degenerados, a encontrar la potencia más baja p de la matriz equivalente M tal
que M p = I, la matriz identidad.
La teorı́a de matrices establece que toda matriz cumple su ecuación caracterı́stica:
por tanto f (M ) = 0. Si f (x) divide a 1 − xp , entonces M es una raı́z de I − X p , ya que es
raı́z del factor f (X) = 0. Esto es, si f (x) divide a 1 − xp , entonces M p = I. A la inversa,
si f (x) es irreducible, entonces divide todo polinomio que tenga la raı́z M en común con
él, y dividirá a 1 − xp si M p = I.

2.3. Polinomios módulo 2


En esta sección se incluye el método para determinar el número de polinomios irre-
ducibles y primitivos de un grado determinado.

2.3.1. Periodos primos de Mersenne


Cualquier polinomio irreducible módulo 2, de grado r > 1, divide al polinomio
r
1− x2 −1 . Para r = 3, por ejemplo, se cumple que tanto 1 + x + x3 como 1 + x2 + x3
dividen a 1 − x7 . Realmente 1 − x7 = (1 − x)(1 + x + x3 )(1 + x2 + x3 ) módulo 2.
De este hecho y del teorema demostrado en 2.2.2 sobre la duración del periodo de
una secuencia (es el menor entero p para el que el polinomio caracterı́stico f (x) divide
a 1 − xp ) se concluye fácilmente que si una secuencia tiene un polinomio caracterı́stico
irreducible de grado r, el perı́odo de la secuencia es un factor de 2r − 1.
Como corolario a este último enunciado, si 2r − 1 es primo, entonces a cualquier
polinomio irreducible de grado r le corresponde una secuencia de longitud máxima.
Los números primos correspondientes a 2r − 1 son conocidos como primos de Mer-
senne. Los primeros veintitrés primos de Mersenne se han calculado mediante ordenador
y se muestran en la tabla 2.1.

2.3.2. Las funciones de Euler y de Möbious


Existe una fórmula explı́cita para calcular el número de polinomios irreducibles mod
2 de grado r, e incluso para calcular el número de polinomios de “exponente máximo”(en
2.3 Polinomios módulo 2 71

Cuadro 2.1: Primos de Mersenne: 2p − 1. Primeros 23 valores de p.


2 17 107 2203 9689
3 19 127 2281 9941
5 31 521 3217 11213
7 61 607 4253
13 89 1279 4423

algunos textos también llamados polinomios primitivos) de grado r. Estas fórmulas están
constituidas a partir de dos funciones utilizadas usualmente en teorı́a de números y se
definen en esta sección.
Por el teorema de factorización única de aritmética, todo entero n > 1 se puede
descomponer en factores primos,
k
Y
n= pαi i (2.12)
i=1

Según los términos de esta factorización, la función de Euler φ se define como


(
1 si n = 1
φ(n) = Qk αi −1
(2.13)
p
i=1 i (p i − 1) si n > 1
En particular, si P es un número primo φ(P ) = P − 1. Si Q es también primo,
φ(P Q) = (P − 1)(Q − 1). También, φ(P 2 ) = P (P − 1). La función φ está tabulada en la
tabla 2.2
Una definición equivalente de la función de Euler es: φ(n) es el número de fracciones
positivas irreducibles no mayores de 1 con denominador n. Por ejemplo, si n = 6, los únicos
sextos irreducibles son 1/6 y 5/6. Entonces φ(6) = 2. Esto coincide con la definición original
puesto que, según esta, φ(6) = φ(2 · 3) = (2 − 1)(3 − 1) = 2.
La función de Möbius µ se define según 2.12 como:



 1 si n = 1
si ki=1 αi > 1
 Q
0

µ(n) = (2.14)


 (−1)k en cualquier otro caso (ej. si n es el

producto de k distintos primos)

Si P es primo, µ(P ) = −1. Si Q también es primo, µ(P Q) = 1, mientras que


µ(P 2 ) = 0. También la función de Möbius está tabulada en 2.2.

2.3.3. Número de polinomios irreducibles


El número de polinomios irreducibles módulo 2 de grado n viene dado por:
1X d r
ψ2 (r) = 2 µ( ), (2.15)
r d
d|r

donde la suma se extiende sobre todos los divisores positivos d de r.


2.3 Polinomios módulo 2 72

n µ(n) φ(n) n µ(n) φ(n) n µ(n) φ(n)


1 1 1 18 0 6 35 1 24
2 -1 1 19 -1 18 36 0 12
3 -1 2 20 0 8 37 -1 36
4 0 2 21 1 12 38 1 18
5 -1 4 22 1 10 39 1 24
6 1 2 23 -1 22 40 0 16
7 -1 6 24 0 8 41 -1 40
8 0 4 25 0 20 42 -1 12
9 0 6 26 1 12 43 -1 42
10 1 4 27 0 18 44 0 20
11 -1 10 28 0 12 45 0 24
12 0 4 29 -1 28 46 1 22
13 -1 12 30 -1 8 47 -1 46
14 1 6 31 -1 30 48 0 16
15 1 8 32 0 16 49 0 42
16 0 8 33 1 20 50 0 20
17 -1 16 34 1 16

Cuadro 2.2: Funciones φ y µ tabuladas hasta para n = 50

Por ejemplo, para calcular el número de polinomios irreducibles módulo 2 de grado


8, los divisores de 8 son d = 1, 2, 4, 8. Entonces r/d = 8, 4, 2, 1 y µ(8/d) = 0, 0, −1, +1. Por
tanto, d|r 2d µ(8/d) = 0 + 0 − 16 + 256 = 240, y
P

1X d 8
ψ2 (8) = 2 µ( ) = 30
8 d
d|8

Los valores de ψ2 (r) se incluyen en la tabla 2.3 para r 5 24.


Ya se ha dicho que no todos los polinomios irreducibles de grado r tienen máximo
exponente (no todos son primitivos). Es decir, no todos corresponden a secuencias de
registros de desplazamiento de longitud 2r − 1. El número de polinomios módulo 2 de
grado r que tienen máximo exponente viene dado por:

φ(2r − 1)
λ2 (r) = (2.16)
r
Por ejemplo, el número de polinomios primitivos de grado 8 es

φ(255) φ(3,5,17) 2 · 4 · 16
λ2 (8) = = = = 16
8 8 8
Por tanto, en este caso, la mitad de los polinomios irreducibles tienen máximo ex-
ponente. Sin embargo, cuando 2r − 1 es primo, ψ2 (r) = λ2 (r) = (2r − 2)/r.
También se ha tabulado λ2 (r) en 2.3.
2.4 Aleatoriedad de las secuencias de registros de desplazamiento 73

r 2r − 1 λ2 (r) ψ2 (r) r 2r − 1 λ2 (r) ψ2 (r)


1 1 1 2 13 8191 630 630
2 3 1 1 14 16383 756 1161
3 7 2 2 15 32767 1800 2182
4 15 2 3 16 65535 2048 4080
5 31 6 6 17 131071 7710 7710
6 63 6 9 18 262143 8064 14532
7 127 18 18 19 524287 27594 27594
8 255 16 30 20 1048575 24000 52377
9 511 48 56 21 2097151 84672 99858
10 1023 60 99 22 4194303 120032 190557
11 2047 176 186 23 8388607 356960 364722
12 4095 144 335 24 16777215 276480 698870

Cuadro 2.3: Funciones ψ y λ tabuladas hasta r = 24

2.3.4. Periodos mas pequeños


No es difı́cil catalogar los posibles periodos cortos (es decir, los exponentes menores)
que un polinomio irreducible mod 2 de grado r puede tener. También es fácil establecer
cuántos polinomios irreducibles existen con cada uno de estos exponentes.
Cada factor f de 2r − 1 que no es factor de cualquier número 2s − 1 con s < r se da
como exponente de los polinomios irreducibles de grado r. Concretamente, existen φ(f )/r
polinomios irreducibles de grado r con exponente f .
Por ejemplo,si r = 8, 2r − 1 = 255, que tiene los factores 1, 3, 5, 15, 17, 51, 85, 255.
De ellos, 1, 3, 5, y 15 ya dividen 24 − 1. Por tanto, los otros factores 17, 51, 85 y 255 se
dan como periodos de polinomios irreducibles.
En particular, hay φ(17)/8 = 2 con exponente 17, φ(51)/8 = 4 con exponente 51,
φ(85)/8 = 8 con exponente 85, y φ(255)/8 = 16 con exponente 255. Ya tenemos los 30
polinomios irreducibles de grado 8, 2 + 4 + 8 + 16 = 30.

2.4. Aleatoriedad de las secuencias de registros de despla-


zamiento
2.4.1. Propiedad de balance
Supongamos que un registro de desplazamiento de r etapas recorre todos los 2r −
1 estados posibles antes de volver a repetir la secuencia. Si numeramos estos estados
en notación binaria desde 1 hasta 2r − 1, y consideramos el dı́gito unitario (el menos
significativo), veremos que éste es un 1 para los números impares y 0 para los pares. Desde
1 hasta 2r −1, hay 2r−1 números impares, y 2r−1 −1 números pares. Por tanto, en cualquier
secuencia de registro de desplazamiento de longitud máxima hay 2r − 1 unos, y 2r−1 ceros.
Por lo tanto, podemos concluir que la propiedad de balance se cumple en todas las
secuencias generadas en registros de desplazamiento.
2.4 Aleatoriedad de las secuencias de registros de desplazamiento 74

2.4.2. Propiedad de realización


En la secuencia de máxima longitud {an } generada en un registro de desplazamiento,
hay 2r − 1 formas de elegir r términos consecutivos. Es decir, cualquier posible array de r
términos consecutivos, exceptuando la combinación “todo ceros”, ocurre exactamente una
vez.
En particular, r unos consecutivos ocurre sólo una vez. Esta realización debe estar
precedida por un cero y seguida de un cero, ya que de lo contrario existirı́a alguna otra
realización de r unos consecutivos.
Un cero seguido por r − 1 unos ocurre exactamente una vez. Pero eso ya se ha tenido
en cuenta en la secuencia de r unos, que viene precedida de un cero. De forma similar,
r − 1 unos seguidos por un cero ocurre exactamente una vez, y aquı́ se tiene en cuenta
el que la realización de r unos debe de ir seguida de un cero. Entonces, ésta no es una
verdadera realización de r − 1 unos.
Supongamos 0 < k < r − 1. Para encontrar el número de realizaciones de unos de
longitud k, consideremos r términos consecutivos que empiecen en cero seguido de k unos,
después un cero, y los restantes r − k − 2 términos arbitrarios. Esto ocurre 2r−k−2 veces,
ya que cada modo de completar los r términos (los r − k − 2 términos arbitrarios), ocurre
sólo una vez.
Razonamientos análogos se cumplen para el número de realizaciones de ceros de
longitud k, para 0 < k < r − 1. La combinación de r ceros consecutivos no se da nunca
(esto pararı́a al registro de desplazamiento). El resto de combinaciones, como por ejemplo
un “uno seguido de r − 1 ceros”debe de producirse, de manera que exista una realización
de r − 1 ceros.
De esta manera se ha determinado completamente la forma de estudiar la estructura
completa de una secuencia de longitud máxima generada en un registro de desplazamiento,
en lo que se refiere a número de realizaciones de unos (a partir de aquı́ se llamarán bloques)
y de ceros (llamadas huecos):
Si 0 < k < r − 1, hay 2r−k−2 bloques y huecos de longitud k. También, hay un sólo
hueco de longitud r − 1 y un bloque de longitud r.
En términos del periodo p de la secuencia (p = 2r − 1), hay (p + 1)/2 realizaciones,
la mitad de ellas bloques y la otra mitad huecos. De los bloques, la mitad tienen longitud
1, un cuarto tienen longitud 2, la octava parte tienen longitud 3, . . . y lo mismo ocurre
con los huecos. Ası́ se continúa hasta llegar a sólo un bloque y un hueco de longitud r − 2.
Sólo queda un hueco de longitud r − 1 y un bloque de longitud r.
Este resultado se puede resumir diciendo que la propiedad de realización se cumple
en las secuencias de longitud máxima generadas en registros de desplazamiento.

2.4.3. Propiedad de correlación


Sea {bn }la secuencia resultante de transformar la secuencia binaria {an } mediante
la operación bn = 1 − 2an , esto es, los ceros se transforman en unos y los unos en -1.
También es equivalente la transformación bn = eiπan .
Si tomamos las secuencias A0 , A1 , . . . , Ap del apartado ?? y les aplicamos la trans-
formación anterior, obtenemos las secuencias B0 , B1 , . . . , Bp . Ahora la adición módulo 2
para las secuencias Ai equivale a la multiplicación de las Bi , como se pone de manifiesto
en las tablas de adición y multiplicación:
2.5 Resumen 75

⊕ 1 0 × -1 1
1 0 1 -1 1 -1 (2.17)
0 1 0 1 -1 1
Como Ai + Aj = Ak , ahora Bi Bj = Bk , donde el producto Bi Bj también se toma
término a término. También se cumple (con la excepción de Bk = B0 = {1, 1, 1, . . .}, que
sólo ocurre cuando i = j), que Bk contiene (p − 1)/2 unos y (p + 1)/2 menos unos, por la
propiedad de balance y pertenecer al grupo Abeliano.
La función de autocorrelación ya se enunció en el apartado 2.1.1 pero se repite
particularizada para las secuencias {bn } a continuación:
p
(
1X 1 si τ = 0
Rb (τ ) = bn bn+τ = (2.18)
p −1/p si 0 < τ < p,
n=1

ya que {bn bn+τ } es una secuencia del tipo Bi · Bj , y por tanto también es del tipo
Bk . Entonces, el exceso de +1 con respecto a −1 es p para B0 , y -1 en cualquier otro caso.
De aquı́ se puede establecer que todas las secuencias generadas en registros de des-
plazamiento de longitud máxima cumplen la tercera propiedad de aleatoriedad.

2.5. Resumen
En este capı́tulo se han enunciado las propiedades que cumplen las secuencias bina-
rias consideradas pseudoaleatorias. Se ha visto que un método muy sencillo de generarlas
consiste en utilizar un registro de desplazamiento con realimentación módulo 2.
Las secuencias generadas en registros de desplazamiento satisfacen una relación de
recurrencia lineal an = ri=1 ci an−i , donde los coeficientes ci valen 0 ó 1 en función de si la
P
etapa i está o no implicada en la realimentación.PA partir de esta relación de recurrencia se
deduce el polinomio caracterı́stico f (x) = 1 − ri=1 ci xi , cuyas propiedades matemáticas
determinan el comportamiento de la secuencia. En concreto, se demuestra que el periodo
de la secuencia es el menor entero positivo p para el que se cumple que 1 − xp es divisible
por f (x).
Según términos de teorı́a elemental de números, se enuncian las formulas explı́citas
que determinan el número de polinomios irreducibles de grado r, y el número de polinomios
primitivos, también llamados de máximo exponente, de grado r. Este número coincide
únicamente si 2r − 1 resulta ser un número primo. El número de polinomios irreducibles es
ligeramente menor a 2r /r (asintóticamente igual), y el número de polinomios primitivos
es del mismo orden de magnitud.
Por último, se ha demostrado que las secuencias generadas a partir de polinomios
primitivos satisfacen las tres caracterı́sticas básicas de aleatoriedad.
La referencia [?] constituye una recopilación excelente sobre el tema. En ella se
pueden encontrar diversos procedimientos para encontrar polinomios primitivos, aunque
dada su extensión no se pueden incluir en este trabajo.
Capı́tulo 3

Medidas de calidad

Después de haber efectuado un repaso de la teorı́a de las secuencias pseudoaleato-


rias, su generación y propiedades fundamentales, necesitamos saber cómo se utilizan estas
secuencias a la hora de hacer las pruebas de simulación de tráfico real. Las consideraciones
y procedimientos definidos a este respecto por la ITU han sido tenidas en cuenta en la
medida de lo posible a la hora de realizar este trabajo.
Estas consideraciones se han ido revisando ya que en la actualidad el aumento de las
transmisiones de datos ha cambiado las exigencias de calidad en los enlaces. Definir y medir
el factor de calidad no es una tarea fácil. Primeramente, es necesario contestar a preguntas
como, si la calidad es el número total de errores de bit o si es la probabilidad de errores de
bit dentro de un cierto perı́odo, si se requiere una configuración de prueba especial y cómo
comparar diferentes resultados provenientes de lı́neas diferentes con distintas velocidades.
La transmisión de voz en las redes digitales no es muy sensible a los errores de bit,
dado que éstos ocasionan sólo una leve distorsión del sonido, mientras que la exactitud en la
recepción de información es algo crı́tico en la transmisión de datos. Con el fin de asegurar
que el término “calidad” tenga el mismo significado para todos, la ITU especificó en
las recomendaciones G.821 y M.550 las condiciones y lı́mites de clasificación para hacer
mediciones en servicios defectuosos.

3.1. La Recomendación G.821 ITU


Los parámetros de servicio defectuoso son especificados en la Recomendación G.821
de la ITU. La recomendación especifica la calidad de servicio de una conexión digital
hipotética de referencia con longitud de 27.500 km, y se recomienda un perı́odo de me-
dición de un mes. La asignación de los datos de calidad del servicio a una parte de la
conexión y mediciones durante un perı́odo menor que un mes están especificadas en las
Recomendaciones G.821 y M.550.
Como se requiere un cierto nivel de calidad de una lı́nea antes que pueda ser usada
para transmisión de datos, la recomendación divide la medición en tiempo disponible y
tiempo no disponible. La medición de errores sólo se debe evaluar mientras la conexión
esté en estado de disponibilidad.
Un cambio de tiempo disponible a tiempo no disponible es ocasionado por 10 se-
gundos sucesivos con alarmas o con una proporción o relación de bits erróneos de más de
10−3 . Los 10 segundos serán parte del tiempo no disponible.
Un cambio de tiempo no disponible a tiempo disponible es ocasionado por 10 se-

76
3.1 La Recomendación G.821 ITU 77

gundos sucesivos en los cuales la relación de errores de bit ha sido mejor de 10−3 . De la
misma manera que en el caso anterior, los 10 segundos serán parte del tiempo disponible.
Una indicación gráfica de los dos cambios de estado se muestra en la figura 3.1.

Figura 3.1: Consideración de los errores en la determinación del tiempo de disponibilidad

La figura 3.2 pone de manifiesto cómo se deben considerar los dos sentidos de un
enlace a la hora de realizar la medida de calidad del mismo en lo que se refiere a tiempos
de disponibilidad. Como se podrı́a deducir fácilmente, el enlace está fuera de servicio o en
periodo de tiempo no disponible cuando alguno de los dos sentidos lo esté.

Figura 3.2: Tiempo de disponibilidad en un enlace según la disponibilidad


de los dos sentidos

Los parámetros de servicio son calculados y clasificados sólo para el tiempo dis-
ponible. Esto significa que cuando se realicen las mediciones de servicio es importante
comprobar cuánto tiempo ha sido clasificado como tiempo no disponible.
En el tiempo disponible se usan diferentes términos para definir el nivel de degra-
dación en el enlace. Los términos son los siguientes:
Segundo Erróneo (SE, en inglés ES): Un segundo en tiempo disponible en el cual se
produce al menos un error en un bit.
Segundo Severamente Erróneo (SSE, en inglés SES): Un segundo en tiempo disponi-
ble con una relación de bits erróneos superior a 10−3 , o un segundo en el cual se ha
detectado un alarma.
3.1 La Recomendación G.821 ITU 78

Minuto Degradado (MD, inglés DM): Un minuto en tiempo disponible con una propor-
ción de bits erróneos superior a 10−6 , en la cual los segundos severamente erróneos
son excluidos del tiempo disponible y el resto del tiempo es dividido en bloques de
60 segundos.
Un bloque es un minuto degradado si la proporción de bits erróneos es superior a
10−6 .

Figura 3.3: Términos de la recomendación G.821

Una clasificación de la calidad de transmisión es inevitablemente un compromiso


entre el deseo de satisfacer las necesidades de diferentes servicios y la necesidad de realizar
sistemas de transmisión tomando en consideración condiciones técnicas y económicas. En
la Recomendación G.821, se han convenido los objetivos de servicio defectuoso para la
conexión hipotética de referencia1 , durante un perı́odo de medición de un mes, que se
muestran en la tabla 3.1.

Clasificación de servicio Objetivo ( % máx. de tiempo)


Minutos degradados 10
Segundos severamente erróneos 0.2
Segundos erróneos 8

Cuadro 3.1: Objetivos máximos de servicio defectuoso según G.821

Otro parámetro que a menudo es usado en las mediciones de servicio defectuoso


para sistemas de radioenlaces es la proporción de errores de bit residual. En los sistemas
de radioenlaces, los errores son causados principalmente por desvanecimientos, los cuales
provocan que los sistemas de protección mediante redundancia conmuten automáticamente
el enlace a una conexión alternativa. Por ello, el tiempo que contiene la proporción de
errores más grande no deberá ser tomado en cuenta. La proporción de errores de bit
residual no está descrita en la recomendación G. 821, pero sı́ en la Rec. 634 de la ITU, donde
el procedimiento de medición está descrito preliminarmente. Este principio consiste en
hacer mediciones de proporción de bits erróneos durante un perı́odo de un mes usando un
tiempo de integración de 15 minutos. El 50 % de los intervalos que contienen la proporción
más alta de bits con error son descartados y la proporción más alta del resto de intervalos
es entonces la proporción de errores de bits residual.
Otra manera, más práctica, de calcular la proporción residual de bits erróneos, y que
está más relacionada con los parámetros de la recomendación G.821, es similar al cálculo
1
Ver la Figura 3.4
3.2 Asignación de los objetivos G.821 79

de los minutos degradados. Los segundos severamente erróneos son excluidos del tiempo
disponible y la proporción de bits erróneos del tiempo restante es entonces la proporción
residual de bits erróneos.
De todas maneras, a la vista de comparaciones realizadas con otros equipos profe-
sionales de medida de BER, y por coherencia con la filosofı́a adoptada en ellos, no han
sido tomadas en cuenta estas últimas precisiones de la norma acerca de la tasa de BER
residual. Es una medida más realista el tener en cuenta todos y cada uno de los errores,
incluidos los que provocan las conmutaciones de redundancia porque al fin y al cabo, si
dichas conmutaciones se producen, y de hecho ocurre en la práctica, los enlaces y comu-
nicaciones afectados se verán perjudicados por ellas. En tal caso, ¿por qué no van a ser
tenidos en cuenta estos errores en el momento de las mediciones?.

3.2. Asignación de los objetivos G.821


A fin de asignar los objetivos a mediciones reales, la conexión hipotética de referencia
es dividida en grado local, grado medio y grado alto.
Los circuitos en grado local son definidos como aquellos que operan entre el recinto
del usuario y una central local a velocidades bajo los 2 Mbits/s.
Los sistemas en grado medio son aquellos que operan entre centrales locales y la red
nacional. La longitud combinada de los enlaces en grados medio y local no debe exceder
1250 km.
Los circuitos en grado alto son conexiones de larga distancia e internacionales que
operan preferentemente a altas velocidades.

Figura 3.4: La conexión hipotética de referencia y su división según los di-


ferentes grados de la recomendación G.821

Los segundos erróneos y minutos degradados son asignados a los diferentes grados,
de manera que al grado local le es permitido el 15 % de los objetivos en cada extremo, al
grado medio, el 15 % de los objetivos en cada extremo, y al grado alto, el 40 % restante de
los objetivos.
La asignación de segundos severamente erróneos está basada en un principio dife-
rente. El objetivo total es 0.2 %, y el 0.1 % es asignado a las tres clasificaciones de circuitos
en las mismas relaciones que para los segundos erróneos y los minutos degradados. Esto
da la siguiente distribución:
3.2 Asignación de los objetivos G.821 80

Clasificación de circuito Asignación de objetivos MD y SE


Grado Local (dos extremos) 15 % asignación en bloque a cada extremo
Grado Medio (dos extremos) 15 % asignación en bloque a cada extremo
Grado Alto 40 %

Cuadro 3.2: Asignación de objetivos de minutos degradados y segundos


erróneos

Clasificación de circuito Asignación de objetivos SSE


Grado Local (dos extremos) 0.015 % asignación en bloque a cada extremo
Grado Medio (dos extremos) 0.015 % asignación en bloque a cada extremo
Grado Alto 0.04 %

Cuadro 3.3: Distribución del 0.1 % de segundos severamente erróneos

El resto del 0.1 % de segundos severamente erróneos es asignado a la clasificación


grado alto y medio para dar cabida a los meses peores del año para sistemas de transmisión
de larga distancia. Pero debido a la naturaleza estadı́stica de los meses peores en una
conexión mundial, es recomendable la distribución siguiente:
El 0.05 % de los segundos severamente erróneos a un sistema de radioenlaces de
2500 km que puede ser usado en el grado alto o medio de la conexión.
El 0.01 % de los segundos severamente erróneos para una conexión por satélite.
Para circuitos en grado medio y grado local, la distribución es una en bloque. Esto
significa que es el total permitido de extremo a extremo sin que importe la longitud de la
conexión. Para conexiones de grado alto, la longitud de la conexión tiene que ser tomada
en cuenta al asignar los objetivos de calidad del servicio. Para demostrar la manera de
calcular la distribución, se usará una conexión con una longitud de 10000 km para el
cálculo de la distribución de los segundos erróneos. El 40 % del 8 % es asignado a una
conexión en grado alto con una longitud de 25000 km. Esto significa que el 3,2 % es
asignado a toda la longitud, pero como la longitud es sólo 10000 km, se deberá multiplicar
por 10000/25000. Por consiguiente, la asignación es 1,28 % de segundos erróneos. Para
los segundos severamente erróneos, el 0,04 % es asignado al grado alto, lo cual debe ser
multiplicado por 10000/25000. Por tanto, la asignación será 0.016 % más el valor extra
arriba mencionado si se trata de una conexión por satélite o un sistema de radioenlaces.
Como en realidad los enlaces rara vez tienen 27500 km de longitud, una distribución
más práctica de los objetivos de calidad del servicio es indicada en la recomendación G.821
donde se describen las secciones digitales con longitudes de 280 km y 50 km. En teorı́a,
sólo se pueden usar las secciones de 280 km, pues la asignación basada en la longitud
solamente es usada para los circuitos en grado alto. Sin embargo, como las conexiones de
grado medio pueden ser divididas en diferentes secciones, la asignación para circuitos en
grado medio es usada también.
Al calcular la asignación para las diferentes secciones, la longitud es redondeada
al valor entero más alto de 280 km y multiplicada por el valor apropiado de la tabla.
Por ejemplo, la asignación de minutos degradados para un enlace con una longitud de
500 km puede ser calculada con la fórmula siguiente: 2 × 0,45 % del 10 % = 0,09 %. De
3.3 Especificaciones G.821 para otras velocidades 81

Clase de calidad de Longitud SDHR Asignación Para clasificación de


sección (Km) ( %) circuitos
1 280 0.45 Alto o medio
2 280 2 Medio
3 50 2 Medio
4 50 5 Medio

Cuadro 3.4: Clasificación de calidad de sección digital

la misma manera, la asignación de segundos severamente erróneos puede ser calculada


como: 2 × 0,45 % del 0,1 % = 0,0009 % más el valor de margen extra para los sistemas de
radioenlaces o conexiones por satélite.

3.3. Especificaciones G.821 para otras velocidades


Como los objetivos de G.821 son especificados para una conexión de 64 kbit/s, las
mediciones en otras velocidades tienen que ser normalizadas a 64 kbits/s. La manera de
proceder está especificada en el Apéndice D de esa recomendación. Los segundos severa-
mente erróneos y minutos degradados están basados en la proporción de errores de bit
y por lo tanto pueden ser calculados directamente. Sin embargo, esto puede causar pro-
blemas en ráfagas de errores menores de un segundo pues éstas pueden no resultar en un
segundo severamente erróneo en el orden superior, mientras que pueden resultar en segun-
dos severamente erróneos en los canales de 64 kbit/s debido a la pérdida de alineación de
trama en multiplexores de orden superior. Para solucionar este problema, un tiempo de
integración menor de un segundo o lı́mites más estrictos deberán ser tenidos en cuenta.
Un segundo erróneo es definido como un segundo con uno o más errores de bit en
un canal de 64 kbit/s, lo cual hace más complicado normalizar segundos erróneos a otras
velocidades. El método más sencillo es dividir el número de errores en un segundo con
una constante para la velocidad. Esta constante es la velocidad dividida por 64 kbit/s,
es decir, el equivalente en número de canales telefónicos contenidos en la trama que se
trasmite. Por ejemplo, si en un enlace de 2 Mbit/s se cuentan 16 errores en el perı́odo de
un segundo, se contarán 16/32 = 0.5 segundos erróneos. Si la medición tiene lugar durante
10 segundos, el porcentaje de segundos erróneos será 0.5/10 = 5 %. Como un segundo jamás
puede considerarse como más de un segundo erróneo, la fórmula es solamente usada si el
número de errores es menor de la velocidad dividida por 64 kbit/s, si no, el segundo es un
segundo erróneo. En otras palabras, en un enlace de 2 Mbps, 32 o más bits erróneos en un
segundo se comportarán como un segundo erróneo, y menos de 32 errores como menos de
un segundo erróneo.
Esta fórmula está basada en la suposición de que, en el peor de los casos, 32 errores
de bit darán un error en cada uno de los canales de 64 kbit/s, lo cual no tiene porqué ser
estrictamente cierto, y menos de 32 bits erróneos jamás afectarán a todos los canales. De
la misma manera, el número de errores en un segundo erróneo puede ser calculado para
las otras velocidades.
Es importante señalar los cálculos anteriormente mencionados están únicamente
especificados para velocidades de 2 Mbit/s o más altas, y que el uso del cálculo para
3.3 Especificaciones G.821 para otras velocidades 82

servicio defectuoso del sistema no asegura que el objetivo de calidad se cumpla según el
criterio de la recomendación G.821 a nivel de canal telefónico de 64 kbit/s.
Capı́tulo 4

Modulador DDS

Terminada la exposición teórica, comenzamos la parte práctica del trabajo en la que


se incluyen las memorias correspondientes a los dos circuitos desarrollados. Este capı́tulo
corresponde al primero de ellos, y consiste en el montaje de un modulador digital que
utiliza las técnicas DDS expuestas en el capı́tulo 1.
La placa moduladora DDS constituye un modesto intento de poner en práctica los
conceptos tratados sobre la sı́ntesis digital directa, y de comprobar “in situ” el estado del
arte en lo que se refiere a integración de estos sistemas. Como en casi todas las ramas de
la ciencia y de la técnica, los fundamentos teóricos siempre se establecen de antemano y su
aplicación suele topar contra alguna barrera de ı́ndole tecnológico. En este caso particular
ha ocurrido ası́, y ha sido necesario esperar un par de décadas hasta que la sı́ntesis digital
directa ha alcanzado el factor de integración suficiente como para poder resultar en chips
atractivos y compactos, aptos para su utilización a escala masiva.
El diseño tiene como componente fundamental un dispositivo DDS al que el fa-
bricante ha añadido recursos hardware para implementar los tipos de modulación más
ampliamente utilizados: FSK, QPSK y 16QAM. ¿Por qué se ha escogido para el diseño
este modulador y no otro? Se puede comprobar en la tabla resumen de la sección 1.10.5
que para realizar un modulador completo utilizando técnicas DDS no habı́a muchas po-
sibilidades de elección. La mayorı́a de los circuitos integrados son dispositivos DDS-DAC
a secas, es decir, útiles en la generación de tonos fijos, o si tienen los registros auxiliares
necesarios para generar las modulaciones, entonces no integran el conversor D/A. Ası́ que
son pocos, al menos que se hayan encontrado, los que podı́an generar las modulaciones
requeridas.
Cumpliendo estos objetivos generales se encuentran en la misma tabla los chips
AD9853 de Analog Devices y el STEL-2176 de Standford Telecom. Los dos son bastante
parecidos, aunque el segundo supera al primero en cuanto a que también es demodulador,
lo que lo encarece considerablemente, además de aumentar la complejidad de su control.
La única pega que se le puede achacar al integrado de Standford es que no se encuentra
en sus abundantes hojas caracterı́sticas la resolución en frecuencia del dispositivo DDS
del modulador. El integrado de Analog es únicamente modulador, con lo que su control es
bastante más sencillo, además de que su uso está bastante más extendido. Al final optamos
por el modulador AD9853 basándonos en criterios económicos y de facilidad en cuanto a
su disponibilidad.
En la placa del circuito impreso, a la que en el resto de la memoria denominaremos
placa DDS, se han incluido una serie de accesorios que complementan su funcionamiento
convirtiéndola en un sistema completo de modulación, capaz de funcionar en un amplio

83
4.1 Especificaciones de la placa DDS 84

margen de velocidades de modulación y de frecuencia de salida. El interface de control


utilizado para todo el montaje es el puerto paralelo del PC. En el apéndice A se ha incluido
un resumen de funcionamiento del mismo, haciendo incapié en la forma en que se utiliza
en nuestro trabajo.

4.1. Especificaciones de la placa DDS

La placa DDS es la encargada de generar la señal modulada con la que se quiere


realizar medidas de propagación en el laboratorio. El rango de frecuencias de salida está en
lo que comercialmente se denomina de frecuencia intermedia, FI, que corresponde a un
margen que va desde lo que serı́an frecuencias altas de la banda de HF, hasta las frecuencias
bajas de la banda de VHF. Todavı́a no tenemos el sistema completo si lo que queremos
medir es la banda L, banda de 1800 Mhz asignada a comunicaciones móviles, que es donde
se plantean los problemas prácticos de propagación.
Queda por lo tanto pendiente la adquisición o diseño de un convertidor que traslade
la señal modulada de salida de esta placa a la frecuencia de interés. No será difı́cil encontrar
equipos comerciales con estas caracterı́sticas.
A modo de introducción sobre la placa DDS, podemos empezar esta exposición con
una sı́ntesis de lo que son sus prestaciones.
Generales

Aplicaciones: Modulador digital en transmisores digitales. Se puede emplear en redes


de cable e inalámbricas para el envı́o de video, voz o cualquier tipo de datos digitales.

Modulaciones soportadas: FSK, QPSK, 16QAM, DQPSK y D16QAM.

Señal de salida de FI modulada de 0 a 65 Mhz, (40 % Nyquist), con una impedancia


de 50 Ω. Filtro antialiasing pasobajo con frecuencia de corte a 3 dB de 67 Mhz.

Modo de trabajo:

1. Modo continuo. El diseño está optimizado para este modo de transmisión.


2. Modo a ráfagas controlado por un terminal externo.

La trama de datos a transmitir debe cumplir la condición de ser una fracción par
de la frecuencia del reloj del sistema además de estar sincronizada con él.

Caracterı́sticas operacionales principales

Formato de las señales digitales: TTL NRZ.

Frecuencia de referencia de 27 MHz (oscilador a cristal TTL de estabilidad media).


El sistema está equipado con un zócalo por si se desea cambiar esta frecuencia y
también admite una fuente de reloj externa.

Frecuencia de reloj del sistema de 162 Mhz, (frecuencia de referencia multiplicada


×6).
4.1 Especificaciones de la placa DDS 85

Generador de reloj de bit incorporado. Crea la frecuencia de transmisión de datos


a partir del reloj de referencia de la placa. Ası́ se solventa el requisito general de
sincronismo entre estas dos señales.
La forma de onda puede ser simétrica o asimétrica dependiendo de la selección
realizada en el puente hardware JP3. El reloj de referencia es dividido por un factor
que varı́a entre 2 y 2047 para salida asimétrica mas otro factor adicional de 2 si la
salida se prefiere simétrica.
Señales de entrada a la placa DDS:
1. Trama de datos de transmisión sincronizada y con una velocidad divisor par de
la frecuencia de reloj del sistema. El reloj del sistema y el reloj de referencia
de la placa DDS están relacionados mediante el factor ×6; según esta relación,
se cumple que cualquiera de las valores creados en el generador de reloj de
bit anterior cumple esta condición. Existe además otra restricción por la cual
no todas las velocidades de bit que se pueden generar en la placa DDS están
permitidas: la descomposición en factores primos del valor que relaciona la
frecuencia del sistema con la velocidad de datos que tenga un factor mayor a
63 no está permitida. En el apartado 4.2.1.1 se profundiza sobre este tema,
aunque para la tranquilidad del lector, podemos adelantar que el programa de
control se encarga de evitar que estos valores se seleccionen, eliminando ası́ los
problemas que se pudieran producir.
2. Oscilador externo seleccionable mediante el puente hardware JP1 de la placa.
3. Control de transmisión externo, también seleccionable mediante un puente JP2,
por si se quiere utilizar otro control de transmisión diferente al generado desde
el programa de control y funcionar en modo a ráfagas.
Puentes hardware de configuración: Su función está resumida en la tabla 4.1 y su
situación fı́sica representada en la figura 4.1.

Alimentación

Tensión de entrada: 12 voltios DC.


Regulación independiente para las partes analógicas (PLL y DAC) y la parte digital
del circuito.
Consumo: 680 mA + 70 mA del ventilador de refrigeración.

Control

Puerto Paralelo estándar del PC en modo compatible.


Programa de Control modulAD para los sistemas operativos Windows 98 y NT.
Diseñado para transmisión en modo continuo controlada desde el PC.

Software de control. Programa modulAD

Control de los parámetros operacionales más importantes, tales como frecuencia de


salida (marca y espacio en caso de FSK), tipo de modulación, codificación diferencial,
tipo de aleatorizador y velocidad de transmisión de datos.
4.1 Especificaciones de la placa DDS 86

JP1 Efecto en la operación


1-2 Reloj interno utilizado como reloj de referencia
3-4 Reloj externo utilizado como reloj de referencia
1-2, 3-4 Reloj interno utilizado como reloj de referencia y accesible en el conector
de datos
JP2
1-2 Habilitación de transmisión y programación del DDS desde el programa de
control
3-4 Señal externa de comienzo de transmisión
1-2,3-4 Seleccionado control interno de transmisión y accesible al exterior en el
conector de datos
JP3
1-2 Reloj de bit asimétrico generado por el divisor principal accesible al exterior
3-4 Reloj de bit simétrico generado por el divisor principal, más un factor
añadido de 2, accesible al exterior

Cuadro 4.1: Función de los puentes hardware de la placa DDS

Figura 4.1: Situación fı́sica de los puentes de configuración hardware en la


placa DDS
4.2 Diseño hardware de la placa DDS 87

Programación de los coeficientes del filtro FIR de conformación de pulso, responsable


de la eliminación de los lóbulos laterales y de la forma del espectro de salida.

Ventana principal de la aplicación parecida al frontal de un equipo comercial. En


ella se indican los principales parámetros de interés:

1. Frecuencia de salida.
2. Tipo de modulación seleccionada.
3. Estado de activación del aleatorizador y del codificador diferencial.
4. Indicación de la velocidad de transmisión en bps.

Desactivación de señal modulada a la salida. Permite el ahorro de energı́a cuando


no se necesita transmitir.

4.2. Diseño hardware de la placa DDS

Ya sabemos que el elemento central de esta placa es el modulador AD9853, cuyo


núcleo es un DDS que genera dos señales desfasadas π/2 en el dominio digital, para multi-
plicarlas por dos tramas binarias I y Q conformadas de antemano también interiormente,
constituyendo lo que serı́a un modulador en cuadratura, todo ello en el dominio digital
(ver la figura 1.34).
Para no desmerecer el resultado, también se incluye lo que ha sido el último avance
en integración: el convertidor digital/analógico, todo dentro del mismo chip.
Nos encontramos entonces con un circuito integrado que ¡nos lo hace todo!. ¿Que
necesitamos para obtener la señal de salida? Tan sólo una trama binaria de datos con los
que modular la señal, (el modulador se encarga de su procesado como veremos en la sección
siguiente), una señal de reloj para que la circuiterı́a interna del modulador funcione, un
filtro paso bajo antialiasing y un programa de control con el que cargar al modulador las
opciones concretas de funcionamiento.
Vemos entonces que la potencia de la placa de modulación DDS reside en el interior
del propio modulador DDS. Es casi obligatorio, por tanto, comenzar entendiendo todas y
cada una de las funcionalidades del AD9853, pues es la llave con la que entender el resto
de los circuitos auxiliares de la placa.

4.2.1. El modulador AD9853


La figura 4.2, obtenida de las hojas de datos suministradas por el fabricante, es el
diagrama de bloques interno del modulador AD9853, y a ella vamos a hacer referencia
asiduamente a lo largo de este apartado.
La parte de la derecha constituirı́a el “núcleo DDS” del sistema, donde se realizan las
operaciones de modulación recién mencionadas. Tal y como se ve en la figura, el diagrama
dibuja un modulador en cuadratura de libro, eso sı́, este caso en el dominio digital.
La señal modulada es una secuencia de palabras de 10 bits cuyo valor equivale
al valor instantáneo en amplitud de la forma de onda modulada equivalente analógica.
Su velocidad de variación o régimen con el que cambian estas muestras será la del reloj
del sistema. Para generar esa señal analógica, la secuencia se entrega a un convertidor
analógico-digital A/D lo más perfecto posible para generar el menor número de señales
4.2 Diseño hardware de la placa DDS 88

Figura 4.2: Diagrama de bloques del modulador DDS AD9853

indeseadas, resultando, como consecuencia de este proceso de conversión, la señal modu-


lada sintetizada originalmente mas unas componentes espectrales, que podrı́amos llamar
“imágenes”, producidas por efecto de tratarse de un sistema muestreado. En el capı́tulo 1
se calcula teóricamente el espectro resultante.
Un “defecto” notable de este espectro de salida es que tiene un factor envolvente en
forma de función sen(x)/x. El diseñador del AD9853 ha pensado en ello y ha incluido a la
entrada del convertidor A/D una etapa para compensarlo. Se trata de un filtro pasoalto
diseñado con la función de transferencia inversa (x/sen(x)) dentro del ancho de banda
de Nyquist, de manera que los usuarios sólo tenemos que preocuparnos de eliminar las
imágenes generadas y olvidarnos del factor envolvente dentro del intervalo de Nyquist.
Otra ventaja más de este circuito la constituye el hecho de tener incorporado un
multiplicador interno del reloj de referencia de entrada ×6 mediante PLL.
Para alcanzar un amplio margen de variación en la frecuencia de salida, (ancho de
banda de salida), se deberá trabajar, en teorı́a, como mı́nimo a una frecuencia de reloj
igual al doble de ese ancho de banda, en la práctica algo más para facilitar el filtrado.
En los márgenes en que nos movemos actualmente, estarı́amos hablando de frecuencias
del orden de 150 a 300 Mhz para circuitos DDS comerciales. Un oscilador a 300 Mhz es
cualquier cosa menos fácil de realizar, ya que suelen producir problemas de estabilidad y
de armónicos.
Pensando en facilitarnos la vida a los usuarios, de nuevo han añadido un circuito
PLL dentro del AD9853 preparado para generar una frecuencia de reloj de sistema igual
a seis veces la señal de reloj de referencia de entrada. El precio que hay que pagar por
esta facilidad es que el espectro en banda estrecha de la señal de salida tiene un ruido de
fase superior al del reloj de entrada, caracterı́stica esta tı́pica de los osciladores a partir
de lazos de enganche de fase PLL. En este caso es el usuario quien decide si utiliza o no
este multiplicador, puesto que su activación se puede controlar desde el control externo.
Haciendo referencia a la gráfica 4.2, este subsistema está en la esquina inferior izquierda
de este esquema de bloques.
El resto de los bloques funcionales que aparecen en el esquema 4.2 nada tienen que
ver con la sı́ntesis digital directa. Se trata de diferentes manipulaciones a la trama binaria
de entrada para acondicionarla antes de llegar a los moduladores digitales en cuadratura.
Entre todos los procesos que refleja el esquema de bloques, el más conocido es el de
4.2 Diseño hardware de la placa DDS 89

la conformación del pulso de salida. Es el caso, por ejemplo, de las conocidas respuestas
en coseno alzado, que eliminan los lóbulos laterales del espectro de salida. Tratándose de
señales en el dominio digital, la manera más cómoda y fiable de sintetizar este filtro con-
formador es mediante una topologı́a del tipo FIR. En el esquema de bloques del AD9853
encontramos en el camino de las tramas I y Q otros elementos poco conocidos llamados
“filtros de interpolación” a continuación de los filtros FIR. Su función resulta imprescin-
dible para el correcto funcionamiento del sistema por lo que se tratarán con un poco más
de detalle en el siguiente apartado.
Para completar el gráfico nos quedarı́an otros cuatro bloques que añaden valor al
sistema, pero que podrı́an no estar dentro del integrado sin que ello supusiera la pérdida
de mérito del circuito. El verdadero mérito consiste en reunir todos los componentes del
proceso de generación de la señal incluyendo un DAC que trabaja a 180 Mhz y 10 bits de
precisión.
Volviendo al hilo de la exposición, el primer módulo que encontramos siguiendo
la ruta de la trama de datos es un codificador Reed-Salomon. La codificación de Reed-
Solomon es un tipo de codificación cı́clica especialmente útil en la corrección de errores
a ráfagas, es decir, es efectiva en canales que tienen memoria. Las referencias [?] y [?]
contienen abundante información sobre este tipo de codificación de bloque.
Desde el punto de vista práctico, un codificador Reed-Solomon añade bits de redun-
dancia a la trama digital de entrada organizada en bloques. Se dice que un codificador R-S
genera un código (N, K), cuando a un bloque de K bytes, se le añaden otros 2t más, con
t siendo el número de bytes erróneos corregibles, (aquı́ los errores se consideran a nivel de
byte, da lo mismo que haya uno u ocho bits erróneos dentro del mismo), resultando una
longitud de bloque de código (mensaje + paridad) de:

N = K + 2t bytes (4.1)
Cuando se utiliza el codificador R-S, los datos del mensaje deben “rellenarse” con
datos no válidos durante el perı́odo en que el codificador añade los 2t bytes de redundancia,
pues durante ese tiempo los bits de entrada son ignorados. Esa circunstancia se refleja en
la figura 4.3

Figura 4.3: Funcionamiento del codificador Reed-Solomon

La siguiente etapa en el camino de modulación es la etapa de aleatorización. El


problema que se trata de resolver en este caso, siempre se trata de eso, es la dependencia
que existe entre la señal modulada y las caracterı́sticas estadı́sticas de la fuente digital. Las
secuencias largas de ceros o unos pueden provocar errores de sincronismo en recepción. Si
hay patrones de datos repetitivos, la señal modulada aparece con tonos espúreos discretos
que pueden producir intermodulaciones. También ocurre que en esquemas de modulación
4.2 Diseño hardware de la placa DDS 90

con portadora suprimida, los datos no aleatorios empeoran el rechazo de portadora. La


solución es usar un aleatorizador para “blanquear” la trama de entrada.
El esquema del aleatorizador en el AD9853 utiliza la técnica de los registros de
desplazamiento de la misma manera que el generador de tramas de BER en la placa de
secuencias pseudoaleatorias. Los polinomios generadores que emplea el modulador DDS
son, según las hojas del fabricante:

1 + x5 + x6 compatibilidad DAVIC/DVB
1 + x14 + x15 compatibilidad MCNS(DOCSIS)

Los valores iniciales del registro de desplazamiento son totalmente programables.


También se incluye un bloque de inserción de secuencia preámbulo programable. El
preámbulo es un conjunto de hasta 96 bits que se transmiten cada vez que se inicia la
transmisión. El propósito de enviar unos bits durante el inicio es el de ayudar al receptor
a sincronizarse. Por un convenio establecido en las normas DAVIC/DVB, la secuencia de
preámbulo no se codifica de forma diferencial en DQPSK, mientras que no ocurre lo mismo
en D16QAM.
El preámbulo, seguido de los datos codificados y aleatorizados son a continuación
formateados de acuerdo con la modulación elegida. El último bloque, al que se conoce
como codificador de modulación, tiene la función de transformar la secuencia de entrada
de bits, a sı́mbolos, para formar las dos corrientes I y Q que alimentan al modulador en
cuadratura.
En el caso concreto de FSK, y según los datos del fabricante, para poder crear saltos
de frecuencia continuos en fase, la trama digital de entrada se salta todos los bloques de
“preprocesado” y se dirige directamente a comandar los dos registros de palabra de sintonı́a
del DDS. Esto equivale en la práctica a decir que en FSK no se permite la utilización de
FEC Reed-Solomon, ni del aleatorizador, como tampoco de la secuencia preámbulo, algo
que no tendrı́a porqué ser ası́. Los datos podrı́an enviarse al control del DDS después de
salir de estos procesos para ası́ poder aprovechar la mejora que ofrecen en el rendimiento
del sistema.
Además del comentario pendiente sobre la función de los interpoladores, no se ha
aclarado hasta ahora de todos estos bloques qué se ha hecho o cómo se utilizan en el
trabajo práctico. No es ético criticar al fabricante por haberse saltado los bloques de
“precodificación” de la trama de datos en FSK, y no reconocer nuestras carencias. Hagamos
entonces una puesta al dı́a del resultado de nuestro trabajo, aunque más adelante se
vuelvan a reflejar sus caracterı́sticas. En este momento tenemos frescos todos los conceptos:
El codificador de sı́mbolos se controla totalmente mediante la aplicación de control
y de este modo se pueden generar cualquiera de los cinco esquemas de modulación
posibles. De todas formas, hay que reconocer que es posible que la aplicación de
control lleve a error. Aunque en el pulsador de selección de modulación no aparecen
DQPSK ni D16QAM, estos dos tipos de modulación se activan cuando se selecciona
el recurso “ficticio” llamado en la interface gráfica de usuario codificador diferencial.
El bloque de inserción de preámbulo no ha sido tenido en cuenta a la hora de realizar
la aplicación. En las hojas del fabricante se sugiere que siempre son necesarios como
mı́nimo 4 bits de preámbulo. Dicho y hecho, se programó la secuencia preámbulo
“0000” y no se pensó que algún usuario del circuito pudiese evaluar la variación
introducida por un cambio en esa secuencia. Son deformaciones del mundo práctico.
4.2 Diseño hardware de la placa DDS 91

Lo contrario se pensó respecto del aleatorizador. Existen controles que lo habilitan y


deshabilitan, y además, también se puede seleccionar el tipo de scrambler utilizado,
en las dos variantes permitidas.
Del codificador Reed-Solomon no nos olvidamos. Desafortunadamente, por un fallo
de diseño, ha quedado inutilizado aunque en un principio se pensó que lo ı́bamos
a poder utilizar. Sin embargo, a causa de la construcción hardware del generador
de reloj de bit, que es un bloque funcional de esta placa DDS de que hablaremos
más adelante, era preciso generar otra temporización añadida para “bloquear” la
transmisión de bits de información durante el perı́odo en que el codificador R-S
inserta sus bytes de paridad. Para realizar este cambio habı́a que reconstruir toda
la circuiterı́a de división de reloj, amén de necesitar mayor número de buffers de
control, que equivalı́a a volver a diseñar una nueva placa. Bajo esta circunstancia,
la decisión que primó fue la de rentabilizar el trabajo realizado hasta ese momento
y continuar hacia adelante. Para resumir, se puede habilitar el funcionamiento del
codificador Reed-Solomon, pero no se ha previsto en la aplicación de control por no
ser utilizable con nuestro sistema; sı́ que lo serı́a con una fuente de datos externa
que tuviese en cuenta el detalle de los bytes de paridad. En ese caso, serı́a cuestión
de añadir una opción más al programa.

Después de esta cura de humildad, continuamos con la explicación del funcionamien-


to del modulador DDS AD9853. A continuación se trata el bloque que quedó pendiente
sobre los filtros interpoladores.

4.2.1.1. Filtrado de datos (FIR + etapas interpoladoras)


A lo largo del camino seguido por los datos, se debe de llevar a cabo una “equipa-
ración” entre la velocidad con que se realizan sus transiciones, que equivale a su intervalo
de “muestreo.o velocidad de transmisión, y por otro lado, la velocidad a la que trabaja el
DDS que en este caso, y puesto que vamos a modular, funciona como señal de oscilador
local. Para que el sistema entregue el resultado que se espera de él, es obligatorio hacer
coincidir estos dos intervalos de muestreo, ver figura 1.34.
Como la velocidad de trabajo del DDS no se puede bajar, resulta obvio que la
operación a realizar es la de volver a “muestrear” los datos de transmisión, pues entran a
una velocidad menor que la del reloj del sistema DDS. Como resultado se transformarán en
nuevos datos muestreados a la frecuencia del sistema, siempre manteniendo las propiedades
de la señal original de entrada. De ese modo conseguimos que las dos señales digitales que
se procesan en el interior del modulador mantengan la misma referencia temporal.
La transformación que acabamos de describir corresponde al funcionamiento de un
interpolador, con algunos matices. Un interpolador sobremuestrea una trama digital de
entrada a una velocidad múltiplo entero de la misma. Como resultado se generan compo-
nentes espectrales imágenes de la señal de entrada solapadas dentro del ancho de banda
de Nyquist del régimen binario de salida, (ver figura 1.42).
De lo que se trata es de filtrar esas componentes solapadas en el nuevo ancho de ban-
da de Nyquist resultante, para que las propiedades originales de la señal sobremuestreada
no se alteren.
Estas son las dos funciones básicas que llevan a cabo la etapa de filtrado FIR y
las dos etapas interpoladoras encadenadas en el camino de datos, (todo ello para las dos
tramas I y Q): por un lado acondicionar la escala de tiempo de los datos de entrada a la
4.2 Diseño hardware de la placa DDS 92

Figura 4.4: Detalle de construcción de las etapas de interpolación en el AD9853

de proceso del DDS, y por otro lado, eliminar las componentes indeseadas que se generan
en ese sobremuestreo de acondicionamiento.
Dentro del filtrado pasobajo a que se somete la trama de datos, la etapa FIR se
aprovecha para conformar la parte “fundamental” ó significativa de la forma del espectro
de salida, mientras que el efecto de las dos etapas interpoladoras CIC, también de respuesta
pasobajo, no tiene relevancia en este caso. Su pendiente de caı́da en la banda de interés
es menos pronunciada que la de los filtros FIR. Lo que se hace es compensar la caı́da
originada por las etapas interpoladoras en el diseño de la curva de respuesta del filtro de
pulso FIR.
En la sección 1.9 se describe el funcionamiento de los filtros FIR y de los interpola-
dores CIC (Cascaded Integrator Comb).
Los caminos I y Q del modulador contienen cada uno un filtro FIR conformador
del pulso de 41 etapas con coeficientes ai de 10 bits. Los coeficientes se representan me-
diante valores enteros en complemento a dos. Por tanto, cada etapa tiene un coeficiente
multiplicativo con valores posibles −512 ≤ ai ≤ 511.
Respecto a la constitución interna de los filtros, una importante caracterı́stica es que
por diseño y para ahorrar el número de multiplicadores necesarios en total, el fabricante
ha elegido una realización simétrica de los mismos. Al programar los coeficientes, sólo se
pueden definir el de la etapa central y los de las 20 inferiores.
Se puede demostrar, que los filtros digitales cuya respuesta impulsiva es de la forma

h(n) = h(M − n) para n = 0, 1, . . . , M (4.2)


tienen una respuesta en frecuencia

H(ejω ) = He (ejω )e−jωM/2 (4.3)


con He (ejω ) una función par real de ω. El término e−jωM/2 representa un término
de fase lineal o retardo constante [?]. Por eso los filtros FIR con esta caracterı́stica se
denominan de fase lineal.
El manual del fabricante advierte de que esta primera etapa FIR sobremuestrea
ó interpola la velocidad de sı́mbolo en un factor de 4. Al final de la cadena sin embargo,
las tasas que hay que hacer coincidir son la del reloj del sistema con el que trabaja el DDS
4.2 Diseño hardware de la placa DDS 93

y la velocidad de transmisión de datos en bits/seg. Por tanto, habrá que tener en cuenta
o “compensar” este factor de interpolación de sı́mbolo ×4 en el factor total dependiendo
de la modulación que se emplee.
Un ejemplo del filtrado que se puede sintetizar corresponde a la caracterı́stica en
coseno alzado. En primer lugar se calcularán los coeficientes a programar en cada una de
las etapas sin tener en cuenta el efecto ya comentado de las etapas de interpolación. Dicho
efecto se tendrá en cuenta a posteriori.
Puesto que trabajamos con señales reales, se calcula la transformada inversa de
Fourier de la parte positiva de la caracterı́stica, sustituyendo la exponencial compleja por
un coseno. El ejercicio se ha realizado teniendo en cuenta el factor de interpolación ×4
introducido por el filtro FIR. Los detalles del mismo se incluyen en el listado del fichero
de Matlab que se incluye en el apéndice ??.
La figura 4.5 representa el resultado de la simulación de algunas de las respuestas
en coseno alzado para diferentes factores de α.
En las distintas simulaciones de la gráfica 4.5, se fue modificando manualmente el
valor de α en el fichero de comandos ad9853 srrc.m.
Como resultado, se obtuvieron los coeficientes que se debe programar en cada una
de las etapas de los filtros FIR. En la tabla 4.2 se anotan los valores una vez normalizados
al valor máximo de 511, siendo la etapa número 20 el punto central del mismo. Ya se ha
dicho que por construcción interna del modulador DDS, los valores se cargan de forma
simétrica alrededor de la toma central.

α 0 1 2 3 4 5 6 7 8 9 10
0.1 -11 9 25 28 12 -16 -37 -38 -12 27 58
0.5 0 3 2 -2 -5 -2 5 7 1 -7 -7
0.9 0 2 0 -2 -1 2 1 -3 -3 3 4
α 11 12 13 14 15 16 17 18 19 20
0.1 55 13 -52 -102 -97 -13 138 315 457 511
0.5 7 19 7 -34 -71 -48 71 260 438 511
0.9 -5 -8 5 13 -11 -41 11 189 410 511

Cuadro 4.2: Coeficientes de cada etapa del filtro FIR en el AD9853 para las distintas
curvas de respuesta en coseno alzado sin compensar la caı́da provocada por las etapas
interpoladoras.

Si en el camino de datos intercalamos a continuación unas etapas interpoladoras,


el resultado en el dominio de la frecuencia es el de “repetición” de la curva de respuesta
sintetizada dentro del nuevo ancho de banda de Nyquist. La figura 1.42 representaba esta
situación en el dominio espectral, y en ella se podı́a apreciar cómo el número de imágenes
solapadas dependı́a del factor R de interpolación.
Afortunadamente, el mismo bloque utilizado para interpolar contiene la respuesta
compensatoria del “defecto” descrito. Ya se comentó la construcción interna de los filtros
con estructura CIC, Cascaded Integrator-Comb, en la sección 1.9.3.4. Se puede demostrar
que la respuesta de un filtro CIC viene determinada por:
4.2 Diseño hardware de la placa DDS 94

(a) (b)

(c) (d)

(e) (f)

Figura 4.5: Respuestas impulsivas y en frecuencia simuladas en Matlab para


el filtro FIR del AD9853 correspondientes a funciones en coseno
alzado con factores α de 0.1, 0.5 y 0.9
(a) y (b) Curvas de respuesta para α 0.1
(c) y (d) Curvas de respuesta para α 0.5
(e) y (f) Curvas de respuesta para α 0.9
4.2 Diseño hardware de la placa DDS 95

RM −1
!N
X
−k
HCIC (z) = z (4.4)
k=0

donde N es el número de secciones de integración y filtros peine contenidos en la


estructura CIC, recordando que siempre coinciden en número. R es el factor de interpo-
lación programable del bloque, y M el número de retardos dentro de cada etapa de filtro
peine. Dentro del AD9853 dos de estas variables se han fijado, N = 4 y M = 1 y queda
disponible al usuario el factor de interpolación.
La curva de respuesta en frecuencia se encuentra evaluando H(z) para z = ej(2πf /R) :

RM −1
!N
X
HCIC (f ) = e−j(2πf /R)k (4.5)
k=0

que es una respuesta pasobajo tal y como se vió en la figura 1.51 para distintos
valores de parámetros M y N.
Cada rama de datos I y Q dispone de dos de estas etapas además del filtro confor-
mador FIR, todas en cascada. Es preciso si se quiere conseguir una función conformadora
lo mas precisa posible, tener en cuenta la variación introducida en la respuesta del filtro
FIR por las etapas CIC, pues su caracterı́stica no es perfectamente plana en la banda
de paso. Lo que sı́ resulta práctico es despreciar el efecto de la segunda de estas etapas,
puesto que como ya hay que tener en cuenta el factor de interpolación total, en este caso
sı́ que resulta despreciable su efecto.
Lo que se hace es “precompensar” la curva de respuesta del filtro FIR en su diseño.
Para ello, multiplicamos su función de transferencia por una función compensadora

1
HCOM P (f ) = (4.6)
HCIC (f )
aplicándola en un margen del 90 % del ancho de banda de interés (parámetro β en
el fichero cic.m de simulación de Matlab). Si se aplica en todo el rango de frecuencias,
el incremento de amplitud que experimentan los lóbulos espúreos fuera de la banda no
compensa con la precisión conseguida en la banda de paso.
Por último, otro efecto importante sobre el que se debe de actuar es el de la escala en
frecuencia. La frecuencia de muestreo a la entrada de la etapa CIC resulta ser la de salida
del filtro FIR, o lo que es lo mismo, cuatro veces la velocidad de sı́mbolo: existe por tanto
un problema de escala. Afortunadamente la solución es fácil puesto que la interpolación
en frecuencia equivalı́a a hacer un cambio de variable en la función de transferencia de
H(f ) por H(f /Escala). En este caso el factor Escala = 4.
Se ha realizado en ejercicio en Matlab donde se ponen en práctica todas estas con-
sideraciones. Su listado se incluye en el fichero cic.m del apéndice C. Aquı́ incluimos
simplemente las gráficas que ponen de manifiesto la precompensación de la respuesta del
filtro en coseno alzado y la tabla con los nuevos valores de los coeficientes. ¿Cual es el
problema principal planteado por este fenómeno? La compensación es especı́fica para un
factor de interpolación del filtro R determinado, ya que según se ha visto en la ecua-
ción 4.5, la curva de respuesta de las etapas CIC depende de este parámetro, que varı́a
según lo haga la velocidad de transmisión. Por tanto, idealmente serı́a necesario recalcular
esta precompensación cada vez que cambiara la tasa de transmisión. En nuestra aplicación
no lo hacemos ası́, y tampoco es que se haya visto una degradación tan importante en la
4.2 Diseño hardware de la placa DDS 96

curva de respuesta, puesto que después de haber jugado con el fichero cic.m cambiando
algunos valores de parámetros, no se aprecia un cambio tan sustancial en los coeficientes
resultantes.

(a) (b)

Figura 4.6: Compensación de la caı́da producida por la etapa de interpola-


ción CIC en el filtro FIR del AD9853. Valores de R = 6, α = 0,5
y β = 0,9.
(a) Respuesta impulsiva antes y después de la compensación
(b) Curva de respuesta en frecuencia antes y después de la com-
pensación.

Nos quedarı́a por determinar cómo se calculan los valores de interpolación que se
deben de cargar en las distintas etapas, pero preferimos posponerlo para la sección 4.3
donde se describe el software, puesto que se tendrá que volver a explicar un problema que
se plantea al respecto.

Etapa 0 1 2 3 4 5 6 7 8 9 10
Valor org. 0 3 2 -2 -5 -2 5 7 1 -7 -7
Valor comp. 1 4 2 -3 -6 -1 7 9 1 -10 -9
Etapa 11 12 13 14 15 16 17 18 19 20
Valor org. 7 19 7 -34 -71 -48 71 260 438 511
Valor comp. 8 24 12 -33 -78 -62 56 251 435 511

Cuadro 4.3: Coeficientes de cada etapa del filtro FIR en el AD9853 antes y
después de la compensación del efecto de las etapas interpola-
doras CIC. Valores de R = 6, α = 0,5 y β = 0,9.

4.2.2. Bloques funcionales de la placa DDS


Después de esta revisión de las caracterı́sticas del circuito AD9853, vamos a tratar
del resto de los módulos que lo acompañan en la placa DDS. Está claro que la finalidad de
estos módulos es la de proporcionar las señales de control y sincronismo que el modulador
4.2 Diseño hardware de la placa DDS 97

necesita para funcionar satisfactoriamente. En este apartado trataremos en profundidad


en cada uno de estos módulos.

Figura 4.7: Esquema de bloques de la placa DDS

La representación esquemática de la placa DDS se muestra en la figura 4.7. En ella


se pueden distinguir los principales módulos de que consta la placa:

1. Puerto paralelo de control

2. Buffer de control y datos

3. Modulador DDS

4. Generador de reloj de bit

5. Oscilador de referencia

6. Salida FI

7. Entrada-salida de datos

Los bloques de acceso al exterior son el puerto paralelo, la salida de FI y el bloque de


entrada-salida de datos. El primero posibilita la comunicación con el ordenador de control,
y los restantes reciben o entregan las señales necesarias para la operación. El bloque de
salida de FI entrega la salida modulada y filtrada en un conector BNC, mientras que el
bloque de entrada-salida es el que recibe la trama digital moduladora y un conjunto de
señales de diversa ı́ndole, todas teniendo la cualidad de ser señales digitales que forman
parte de las distintas opciones operativas del sistema en su conjunto. De ellas hablaremos
llegado su momento.
Los bloques principales de la placa DDS son el oscilador de referencia, el generador
de reloj de bit, y el modulador DDS. El primero genera la señal de reloj maestro para los
4.2 Diseño hardware de la placa DDS 98

otros dos módulos: el generador de reloj de bit, del que se obtiene el reloj de transmisión de
datos, y el modulador DDS, constituido por el circuito integrado AD9853 que ya conocemos
en profundidad.
El buffer de control y datos está formado por un grupo de demultiplexores que
reciben las señales enviadas por el bus de datos del puerto paralelo y las acondicionan
para ser utilizadas en el hardware del circuito.
En los siguientes apartados entramos más en detalle en todos y cada uno de estos
bloques.

4.2.2.1. Puerto paralelo de control


Accesible por medio de un conector plano de 26 patillas, se prolonga mediante un
cable plano paralelo hasta el conector exterior DB-25 del chasis que contiene todo el
sistema. El mismo cable plano se emplea en paralelo para conectar también al puerto
la placa de generación de secuencias. Desde el conector DB-25 del chasis sólo hace falta
conectar un cable paralelo hasta el PC de control. En la tabla 4.4 están anotados los
terminales utilizados para la comunicación de esta placa con el ordenador de control.

Pin Nombre Función en la placa DDS


2 D0 LSB del Bus de datos
3 D1 Bus de datos
4 D2 ”
5 D3 ”
6 D4 ”
7 D5 ”
8 D6 ”
9 D7 MSB del Bus de datos
14 LATCH1 Strobe de carga del bus de datos en placa DDS
15 OD3 Hilo de lectura de datos desde placa DDS
16 LATCH2 LSB de Selección de Registro en placas DDS y BER
17 LATCH3 MSB de Selección de Registro en placas DDS y BER
18 a 26 GND Masa

Cuadro 4.4: Interface paralelo de la placa DDS.

En este caso, el PC de control sólo lee información de la placa DDS a través del hilo
de estado OD3, desde donde se lee el puerto serie de control del AD9853. Del resto de
circuitos de la placa DDS no hay forma de obtener información.

4.2.2.2. Buffer de control y datos


Este bloque es el encargado de recibir los datos del puerto paralelo y, como cual-
quier buffer, mantenerlos en sus terminales de salida al margen de las variaciones del bus
cuando éste se encuentra enviando información a otros periféricos, por ejemplo la placa de
secuencias pseudoaleatorias.
4.2 Diseño hardware de la placa DDS 99

Figura 4.8: Buffer de control y datos de la placa DDS

Casi podrı́amos haber denominado a este bloque como de control, puesto que la
mayorı́a de las señales que se reciben realizan esa función. La excepción corre a cargo del
terminal etiquetado como BUS DATIN del buffer U5, encargado de soportar la comuni-
cación serie con el bus de control del modulador AD9853.
Comentaremos la función de los componentes que constituyen este bloque apoyándo-
nos en la figura 4.8:

U10, 74HC139. Es un demultiplexor dos a cuatro que genera las señales de “enable”
de activación de los drivers que retienen la información enviada desde el PC a través
del bus de datos del puerto paralelo (D0 a D7). Los hilos de selección son los ter-
minales LATCH2 y LATCH3 del puerto de control del PC, y su validación también
llega directamente desde el puerto paralelo a través de la señal de control LATCH1.
En la figura se ve cómo se aprovechan sólo dos de las cuatro salidas demultiplexadas
disponibles (CHIP0 y CHIP1). Es el resultado de la optimización realizada a fin de
reducir en lo posible el tamaño y número de circuitos de la placa.

U3, 74HC574. Es el primero de los buffers triestado de este bloque, siendo el encarga-
do de mantener el byte menos significativo de la palabra de comando de división que
el programa de control envı́a al generador de reloj de bit, P0 a P7. Este componente
tiene anulada su capacidad de poner en estado de alta impedancia sus salidas al no
ser de utilidad en este caso.
La salida se actualiza con el dato presente en los hilos del bus en el flanco de subida
de su señal de enable, CHIP0, que le llega desde U10.

U5, 74HC574. Es el otro buffer triestado, aunque esta caracterı́stica no se emplea


al igual que en su predecesor. Sus salidas ya se dirigen a sitios muy variados del
sistema, razón ésta por la que se comenta separadamente de su compañero.

Los tres bits menos significativos completan la función de controlar el divisor pro-
gramable del generador de reloj de bit, P8 a P10. Para programar el divisor ha
de procederse de forma curiosa: si lo que se desea es programar un factor de
división de 2, hay que cargar el valor 37EH , o 111111111102 ; para programar
4.2 Diseño hardware de la placa DDS 100

el máximo valor de división de 2047, en este caso el valor a cargar debe ser
1H . El valor 0H no tiene validez puesto que impide el correcto funcionamiento
del circuito, y serı́a el correspondiente a un factor de división de 2048. Vemos
por tanto que el valor a cargar corresponde al complemento a 2 del factor de
división deseado.
Q4 es el hilo que resetea el modulador DDS, también accesible en el conector de
entrada-salida por si se quiere aprovechar en otro sistema externo.
Q5 es un terminal de control de la transmisión del AD9853 que también juega
un papel importante en la programación del mismo a través de su puerto de
control serie. Su función se comenta con mayor rigor en el apartado dedicado
al conexionado del modulador AD9853.
Q6 a Q8 controlan el flujo de señales en el puerto serie de control del modulador.
Utilizando sus etiquetas de la figura 4.8, 3 STATE BUS es el hilo que controla
el estado de alta impedancia del transceptor U8 incluido dentro del bloque
del modulador DDS. Este transceptor debe estar en alta impedancia durante
las respuestas del integrado hacia el terminal OD3 del puerto paralelo del
PC. BUS DATIN constituye el otro sentido de datos en el puerto serie; su
contenido se envı́a hacia el modulador pasando a través del transceptor U8. Por
último, BUS CLK es el hilo conectado al terminal de reloj que temporiza las
transacciones del puerto serie del modulador DDS. En este caso, se requiere una
alta actividad en el puerto paralelo del PC, puesto que como ya se podrá intuir,
los intercambios de información con el modulador DDS se han de realizar bit a
bit.

4.2.2.3. Modulador DDS


Es el bloque que más conocemos, pues está constituido por el circuito integrado
AD9853 con el que ya estamos familiarizados desde la sección 4.2.1. Genera la señal mo-
dulada directamente en el dominio digital a partir de la trama binaria moduladora de
entrada. Su salida es una señal analógica a la que únicamente se debe someter a un pro-
ceso de filtrado para eliminar las componentes espectrales indeseadas que el procesado
digital origina.
En la figura 4.9 podemos observar el esquema de conexiones del AD9853 en la placa
DDS. Se ha añadido el driver triestate U8B para resaltar el caracter bidireccional del
puerto serie de control del AD9853 (terminal BUS DAT IN). Formalmente este integrado
deberı́a de haberse incluido en el bloque de datos y control.
En la figura se puede apreciar cómo los datos que se reciben de control han de
pasar a través del buffer U8B hacia el modulador, etiqueta BUS DATIN, mientras que
las respuestas desde el modulador DDS exigen que este buffer pase al estado de triestate,
dependiendo del hilo 3 STATE BUS, para que las señales de salida del terminal BUS DAT
IN lleguen hasta el módulo de control y datos, etiqueta BUS DAT, sin que la entrada
cargue la lı́nea. La temporización del bus está gobernada por medio del hilo BUS CLK,
a donde se han de aplicar los pulsos de reloj según el diagrama que aparece en las hojas
del fabricante [?]. Estos pulsos se “generan” desde el programa de control, pues es el que
controla todo el proceso de programación del AD9853.
Otra parte integrante de este módulo, que también podrı́a haber sido incluida en el
bloque de control, está representada en la figura 4.9. Su función, más próxima al modo
de funcionamiento del modulador que al mero hecho de tratarse de un hilo de control,
4.2 Diseño hardware de la placa DDS 101

Figura 4.9: El circuito AD9853 y su conexionado en la placa DDS

nos ha decidido a recogerlo dentro de este bloque. El terminal TX EN es el que deter-


mina el paso a la condición de transmisión del modulador DDS, con la caracterı́stica de
que es obligatorio su deshabilitación cuando se reprograman los registros del modulador.
Cualquier cambio de configuración del modulador pasa por el cambio a nivel bajo de este
terminal. Si este terminal está activo, y por lo tanto la circuiterı́a de modulación también,
el bus de control estará inactivo y viceversa.

Figura 4.10: Selector JP2 de habilitación de transmisión

Existe otra cuestión operativa en la que está implicada el terminal TX EN. Se


trata de que sirve como referencia de sincronismo en el inicio de la transmisión. Por eso se
incluye el biestable U7B (figura 4.10): para que la transición de bajo a alto que se produce
en este terminal durante el inicio de la transmisión esté sincronizada con el reloj de bit,
y a la postre con el reloj del sistema. Por otra parte, se puede gobernar la transmisión
del modulador si se le sincroniza a un sistema externo, cambiando el puente JP2 a las
conexiones 3-4.
Continuamos conociendo la función del resto de terminales importantes para el fun-
4.2 Diseño hardware de la placa DDS 102

cionamiento del modulador DDS:

REF CLK IN, reloj de referencia de entrada, en este caso se ha elegido 27Mhz, por
estar cerca del lı́mite máximo de 28 Mhz y haberse encontrado con relativa facilidad.
El reloj del sistema, o reloj con el que trabaja el DDS es 6 veces mayor porque se ha
habilitado el multiplicador interno a través del bus de control.

DAT IN, es el terminal al que se aplican los datos a transmitir. Está conectado a la
etiqueta SDI, que llega desde el conector de entrada-salida.

4.2.2.4. Generador de reloj de bit


Este bloque es simplemente un conjunto de divisores programables en cascada con el
fin de obtener la frecuencia de reloj de bit a partir del reloj de referencia de la placa DDS.
Esto quiere decir que no se puede generar cualquier velocidad de transmisión: todas serán
divisores exactos de la frecuencia de referencia. Éste es uno de los factores determinantes
de la frecuencia de referencia de la placa.

Figura 4.11: Esquema del generador de reloj de bit

Por ejemplo, para transmitir a la velocidad estándar de 2.048 Mbps, con el cristal
de referencia actual de 27 Mhz se necesita una relación de división de 13.1835, imposible
de conseguir. En ese caso, seleccionando un factor de división de 13 necesitarı́amos una
referencia de 26.624 Mhz, que no sobrepasa el lı́mite superior de frecuencia permitida
por el modulador DDS. El factor de división 14 da como resultado 28.672 Mhz que sı́ lo
sobrepasa. En este ejemplo serı́a necesario, por tanto, sustituir el oscilador de referencia
actual por uno de 26.624 Mhz.
En nuestro diseño no tenı́amos especificada ninguna velocidad en particular, porque
para hacer pruebas de laboratorio lo que importan son los órdenes de magnitud, ası́ que
se escogió la frecuencia que más se acercaba al lı́mite máximo de 28 Mhz y que se en-
contró fácilmente en el mercado: 27 Mhz.
4.2 Diseño hardware de la placa DDS 103

Por lo que respecta a la circuiterı́a en particular, U1,U2 y U4 son los tres contadores
sı́ncronos conectados en cascada que dividen el reloj de referencia CLK BUF. Se trata de
contadores descendentes programables con un terminal de indicación de final de cuenta
RCO empleado como habilitación en el contador siguiente de la cadena. Aún utilizando
este método, se trata de un contador sı́ncrono si se observa que la señal de reloj CLK BUF
se aplica a los tres contadores en paralelo.
El terminal RCO del último contador U4 es la salida asimétrica de este bloque,
y como tal está conectada a JP3; pero también se emplea en la carga de los valores de
programación de todos los contadores después de invertirse en U8A. El terminal Y1 de
U8A es la señal de salida invertida, con lo que al final de cada ciclo se genera un pulso
de bajada de duración igual a la del periodo de la frecuencia de referencia, que al estar
conectado a los terminales LOAD de los contadores, provoca que los valores enviados desde
el buffer de datos P0 a P10 se carguen en la salida de éstos, comenzando de nuevo la cuenta
descendente en el siguiente pulso de reloj. Se deduce que para programar una relación de
división en este circuito lo único que hace falta es colocar el valor adecuado de división en
los hilos P0 a P10 y el mismo circuito se encarga de cargarlo en el siguiente ciclo.
Se observa en la figura 4.11 que no se utiliza el terminal D de carga paralelo en U4.
Esto es porque con 11 terminales, P0 a P10, podemos conseguir un margen de división
de 211 − 1 = 2047 (el valor 7F FH no es válido), margen más que suficiente en QPSK y
16QAM dado que el modulador DDS como máximo tiene un factor de interpolación de
3906 al que hay que descontar el factor multiplicativo ×6 a que se somete la frecuencia de
referencia en el interior del modulador AD9853. La única modulación para la que resulta
útil tanto margen de división es para FSK que no tiene ningún procesado en el modulador
DDS.
Podı́amos habernos casi ahorrado incluso un hilo más de control del contador. No
se hizo ası́ puesto que no se necesitaba para ninguna otra función.
El biestable U7A sobraba y se pensó aprovecharlo para el caso en que se deseara un
factor de forma en la señal de salida de reloj de bit del 50 %. Conectandolo en forma de
biestable T conseguimos que su salida bascule a cada pulso de reloj asimétrico, obteniendo
por tanto un factor adicional de división ×2, además del cambio en la forma de onda.
La selección de salida de un reloj de bit u otro se realiza fı́sicamente en JP3, donde
determinamos el reloj de bit disponible en el conector de entrada-salida:

1. Puente JP3 1-2. El reloj de bit utilizado es asimétrico.


2. Puente JP3 3-4. El reloj de bit empleado tiene factor de forma del 50 % y además
es sometido a una división adicional ×2, además de la comandada por el bus de
control. Existe sin embargo un modo de indicarle al programa de control que se ha
seleccionado esta opción, de modo que las indicaciones del mismo no sean erróneas.

La capacidad de división conjunta de todas las etapas de contadores en cascada


resulta estar entre 2 y 2047 más el factor adicional × 2 añadido con el biestable U7A. El
lı́mite práctico superior utilizado depende del tipo de modulación que se esté empleando,
puesto que está limitado por el software de control para no sobrepasar los lı́mites operativos
de las etapas de interpolación del modulador DDS. Los márgenes de funcionamiento del
circuito se resumen en la tabla 4.5.
Para un reloj de referencia de 27 Mhz, se obtiene una velocidad de transmisión de
datos máxima de 13.5 Mbps en modo asimétrico. Los lı́mites inferiores resultan ser en
nuestro caso:
4.2 Diseño hardware de la placa DDS 104

(a) (b)

(c) (d)

(e) (f)

Figura 4.12: Formas de onda de salida del generador de reloj de bit:


(a),(c) y (e) Salida asimétrica para valores del divisor principal
2, 13 y 2047.
(b),(d) y (f) Salida simétrica para los mismos valores del divisor
principal y con JP3 en la posición 3-4
4.2 Diseño hardware de la placa DDS 105

Modo asimétrico Modo simétrico


fBIT max fBIT min fBIT max fBIT min
FSK fREF /2 fREF /2047 fREF /4 fREF /4094
QPSK fREF /2 fREF /651 fREF /4 fREF /650
16QAM fREF /2 fREF /325 fREF /4 fREF /324

Cuadro 4.5: Sumario de velocidades de bit generadas en la placa DDS

1. FSK: 13.190 Kbps en modo asimétrico y 6.595 Kbps en modo simétrico.

2. QPSK y DQPSK: 41.474 Kbps en ambos modos.

3. 16QAM y D16QAM: 83.077 Kbps en ambos modos.

Obviamente, estos valores dependen del reloj de referencia, por lo tanto se pueden variar
cambiando el oscilador de referencia o utilizando uno externo según las necesidades de
cada momento.
Para ilustrar el funcionamiento independiente de este bloque se han obtenido fácil-
mente las gráficas de la figura 4.2.2.4. Al disponer en el terminal de salida de la placa
DDS de la señal de reloj de bit generada en este bloque, no resulta difı́cil comprobar el
funcionamiento de este circuito. Se puede distinguir el distinto factor de forma de la señal
de salida cuando se intercala el divisor U7A, resultando el factor adicional de división ×2.

4.2.2.5. Oscilador de referencia

Figura 4.13: Oscilador interno de referencia y jumper JP1 de selección de reloj maestro

Se utiliza como reloj maestro de transmisión y también, tal y como se acaba de


comentar en el apartado anterior, para la creación del reloj de bit, puesto que ambos
relojes deben de ser sı́ncronos según las especificaciones del modulador DDS. No tenı́amos
4.2 Diseño hardware de la placa DDS 106

ninguna razón que nos forzase la elección de la frecuencia, al margen de no sobrepasar


el lı́mite del AD9853 de 28 Mhz. Se escogió la frecuencia de 27 Mhz por ser un valor
fácilmente asequible en el mercado. De todos modos, si se desea trabajar con otra señal
de información generada en un circuito con su propia fuente de reloj, es preciso utilizar
esa misma fuente de reloj como referencia en la placa DDS. Es por lo que se ha previsto
la entrada de otro reloj externo en JP1.
De acuerdo con la figura 4.13, la etiqueta CLK representa el terminal interno de reloj
de la placa DDS. El bloque Y1 representa el oscilador a cristal incorporado en el circuito,
con una frecuencia nominal de 27 Mhz y salida TTL, encapsulado en una carcasa DIL-16
similar a la de los circuitos integrados TTL tradicionales. Es un buen método si se quiere
sustituir en el futuro por otro de frecuencia diferente. La contraprestación que nos toca
pagar por esa comodidad es la escasa precisión de los mismos, puesto que suelen tener una
estabilidad caracterı́stica de 10−7 . La etiqueta EXT OL es la entrada de oscilador externa
del conector de entrada salida.
Jugando con los puentes en JP1 podemos conseguir las siguientes posibilidades:

1. Puente JP1 1-2 aislado. El circuito trabaja con el oscilador interno Y1 de 27 Mhz.

2. Puente JP1 3-4 único. En este caso el reloj de la placa DDS es el externo suministrado
desde el conector de entrada-salida.

3. Puentes JP1 1-2 y 3-4 conjuntos. Ahora el circuito trabaja con el reloj interno y
además disponemos de él en lo que normalmente es entrada, por si queremos utilizar
el reloj de la placa DDS en otro sistema distinto.

4.2.2.6. Salida de FI
Esta etapa comprende el filtro antialiasing y el acoplamiento mediante transformador
para convertir las salidas unipolares de corriente del DAC, a señales bipolares simétricas
tal y como se recomienda en la sección 1.8.

Figura 4.14: Filtro antialiasing de salida en la placa DDS

El esquema de la etapa de salida se representa en la figura 4.14, donde no se incluyen


las resistencias de terminación que se conectaron a los terminales de salida del DAC durante
la etapa de diseño mientras suministraban el transformador de banda ancha. La conexión
4.2 Diseño hardware de la placa DDS 107

definitiva ha quedado tal y como aparece en la figura, únicamente con el transformador y


el filtro, y de ahı́ al conector BNC de salida. Las caracterı́sticas de los dos componentes
se resumen a continuación:

Transformador de banda ancha T1-1T-X65 de Minicircuits.

Relación de impedancias: 1:1.


Margen de frecuencia: 80 Khz a 200 Mhz.
Pérdidas de inserción 1 dB: 200 Khz a 80 Mhz.
Pérdidas de inserción 2 dB: 150 Khz a 150 Mhz.
Pérdidas de inserción 3 dB: 80 Khz a 200 Mhz.

Filtro paso bajo PLP-70 de Minicircuits.

Banda de paso: DC - 60 Mhz (atenuación < 1 dB).


Frecuencia de corte a 3 dB: 67 Mhz.
Banda eliminada: atenuación > 20 dB a 90 Mhz.

4.2.2.7. Entrada-salida de datos


En este apartado comentaremos brevemente el conector de entrada-salida de la placa
DDS, que es el punto donde se han reunido todas las señales digitales que por una causa
u otra han de estar accesibles al exterior. La ubicación fı́sica del mismo se encuentra en
la parte lateral superior del chasis donde se ha mecanizado todo el sistema, justo encima
de su homólogo de la placa de secuencias pseudoaleatorias, y a la misma altura que el
conector BNC de salida de señal.

Figura 4.15: Conector de entrada de datos de la placa DDS

Es un conector plano de diez terminales agrupados en dos filas, y las señales se han
distribuido de tal forma que su correspondencia en el conector de la placa de secuencias
permita un cable plano paralelo de interconexión. De este modo, los terminales conectados
a este conector son los siguientes:
4.3 Software de control 108

SDI Serial Data Input. Entrada de la trama digital de información a transmitir. Debe
de cumplir obligatoriamente la condición que ya se ha repetido muchas veces a esta
altura, pero fundamental para el correcto funcionamiento del sistema: su velocidad
debe ser un submúltiplo par del reloj del sistema, además de estar sincronizado con
él.

EXT OL External Oscillator. Entrada TTL de frecuencia de referencia externa. Se activa


cambiando el puente JP1 a la posición 3-4 y su función es permitir al modulador
trabajar cuando la trama de datos a transmitir tiene ya un reloj de referencia que
no se puede cambiar. Se puede jugar astutamente con los puentes de JP1 y utilizar
este terminal también como terminal de salida de la frecuencia de referencia interna,
tal y como se comentó en la sección 4.2.2.5.

EXT TXE External Transmission Enable. Entrada de activación de la transmisión cuan-


do se quiere trabajar con otra señal distinta a su homóloga generada internamente.
Es útil si se quiere trabajar en modo a ráfagas para sincronizar con la circuiterı́a de
datos la activación de la transmisión.

CLK DAT Data Clock. Frecuencia de datos creada con la caracterı́stica de ser sı́ncrona
al reloj de referencia de la placa, por tanto apta para servir de señal de reloj en la
circuiterı́a de datos de entrada. La señal viene desde el generador de reloj de bit
que tiene incorporado la placa DDS. En nuestra aplicación particular se utiliza en la
placa de secuencias pseudoaleatorias como señal de reloj de bit y como tal, determina
la velocidad de transmisión de datos.

RESET. Señal de reset del modulador AD9853 generado desde el control de la placa y
que se ha dejado accesible al exterior por si en algún momento fuera de utilidad.

4.2.2.8. Alimentación
El bloque de alimentación está constituido por tres reguladores similares, cada uno
de los cuales suministra la tensión de 5 voltios a partir de los 12 de entrada. El motivo
de separar las distintas alimentaciones está en el intento de mejorar en lo posible las
prestaciones de margen libre de espúreos del modulador DDS. Se ha separado por una
parte la alimentación al convertidor D/A del DDS (+VDA), por otro lado, la alimentación
del PLL interno multiplicador de la frecuencia de referencia de la placa DDS × 6 para
generar el reloj del sistema, en un intento de minimizar el acoplo de la señal de reloj a la
salida (+VD). Por último, la alimentación de la parte digital del modulador DDS y del
resto de la placa, +V.
Con la última nos llevamos la sorpresa de tener que cambiar el regulador por otro que
aguantase más corriente, dado el elevado consumo del AD9853. La sorpresa siguió cuando
descubrimos su calentamiento, lo que nos decidió a instalar un ventilador para mantener
la temperatura dentro de los márgenes de seguridad.
En el apéndice A se puede ver cómo ha quedado montado todo el sistema dentro de
un chasis de aluminio.
4.3 Software de control 109

Figura 4.16: Reguladores de alimentación independientes en la placa DDS

4.3. Software de control

Después de tanto hardware llega el turno de revisar el software de control de la placa


DDS, que comprende una aplicación a la que se ha dado el nombre de modulAD. Consta
fundamentalmente de dos ficheros fuente, separación hecha con el fin de ordenar por un
lado lo que son las funciones de bajo nivel encargadas de interactuar con el hardware de
la placa DDS, y por otro las funciones tı́picamente encargadas del aspecto gráfico de la
interfaz de usuario.
En el apéndice C se presentan los listados completos de la aplicación modulAD.

4.3.1. Módulo principal mod.c


Las mayorı́a de las funciones de este módulo están pendientes principalmente del
aspecto gráfico de la aplicación. En la figura 4.17 se ha hecho el despliegue de todos los
paneles gráficos.
De entre todas estas ventanas, las más interesantes son las de Configuración del
generador de reloj de bit y Configuración del filtro FIR de datos. La primera controla
directamente el valor de frecuencia de bit generado por el bloque del mismo nombre. En
esta ventana se presenta una manera peculiar de comandar la frecuencia de bit deseada.
Lo más lógico hubiera sido mostrar un control numérico donde escribir directamente la
velocidad de datos que se deseara utilizar. Sin embargo, surge un problema por la necesidad
que tiene este valor de ser múltiplo par de la frecuencia del sistema, o lo que es equivalente,
de la frecuencia de referencia de la placa. El resultado final cuando se hubiese querido hacer
cambios rápidos, casi seguro que habrı́a sido un continuo mareo al usuario advirtiéndole de
la imposibilidad de generar la velocidad que hubiese acabado de programar en el hipotético
control. Puede que haya otra forma mejor de hacerlo, pero la solución adoptada en este caso
ha sido la de comandar directamente el valor entero de división que se quiere programar.
Aquı́ la aplicación es la encargada de mostrarnos automáticamente el valor de velocidad
de transmisión resultante. La función directamente relacionada con la programación del
4.3 Software de control 110

Figura 4.17: Distintas pantallas de la aplicación de control modulAD


4.3 Software de control 111

generador de reloj de bit es ValorDiv.


Una aplicación comercial no hubiese dispuesto de la ventana para configurar los
coeficientes del filtro FIR. Lo usual serı́a que el filtro estuviese programado para una
curva determinada, resultando un proceso transparente para el usuario. Desde el punto de
vista de la operación del modulador, lo importante es que el espectro de salida aparezca sin
lóbulos laterales. Sin embargo, dado que se piensa utilizar esta aplicación en el laboratorio,
se ha añadido en este caso esta posibilidad de configuración: resultará interesante ver
en el futuro el efecto de distintas curvas conformadoras del pulso en el espectro de la
señal de salida. Hablaremos de la función ValorFirAx, con “x” refiriéndose al coeficiente
respectivo del filtro FIR, que nos servirá para introducirnos en uno de los aspectos clave
en la programación del camino de procesado de datos.
Aunque las dos funciones que vamos a comentar en este apartado se encuentran en el
módulo de la interface gráfica de usuario, la verdad es que en este caso se puede considerar
que están bastante cerca del hardware de la aplicación. Evidentemente, pertenecen al
módulo mod.c porque están a cargo de unos controles concretos y bien determinados de
las ventanas de la aplicación.

4.3.1.1. Función ValorDiv


La primera función que vamos a comentar de este módulo se encuentra asociada a la
ventana Configuración del generador del reloj de bit. Su control de llamada es el etiquetado
como “Divisor programable se ejecuta cada vez que el usuario modifica su contenido a
2

golpe de ratón o directamente escribiendo un número dentro del mismo. Esta es la forma
de cambiar el valor de frecuencia del reloj de bit generado por la placa DDS, o lo que
es lo mismo, la velocidad de transmisión de datos. La función ValorDiv también es una
función importante porque se llama desde muchas otras funciones del módulo, siempre
que la operación que realize el usuario implique un cambio “serio” de configuración del
sistema.
A priori su funcionamiento no presenta muchas complicaciones conceptuales. De lo
que se trata es de escribir la palabra de programación en el divisor de la placa DDS, y
este trabajo lo descarga sobre la función de bajo nivel gen bit clk. Las complicaciones
surgen cuando se analizan un poco todas las posibilidades de funcionamiento, pues los
valores máximos y mı́nimos de frecuencia de bit permitidos dependen del tipo de modu-
lación seleccionado, y hay que considerar la estructura interna del modulador que no nos
permitirá programar todos los valores que fı́sicamente son posibles de generar. Toda esta
complicación también se descarga sobre la función del módulo mod hard.c interpolador
que trataremos un poco más adelante.
De momento nos sirve con saber que esta función chequea el valor que se ha coman-
dado, y si se detecta un valor imposible de programar, la función interpolador automáti-
camente busca el valor “permitido” por defecto y lo programa. Por supuesto, informa a la
función llamante para que la presentación gráfica se actualize correctamente y le aparezca
al usuario el mensaje de aviso pertinente.
Lo realmente destacable de esta función puede que no sea fácil de distinguir en
su listado: es realmente la función que gobierna la correcta temporización de la placa
DDS. Por un lado se ejecuta cada vez que se cambia el tipo de modulación (FSK, QPSK,
16QAM), también cuando se pulsa el botón del divisor fijo en la misma ventana, por
supuesto cuando se cambia el valor desde el mismo control. A continuación llama a la
función que valida el valor comandado, después llama a la función que modifica fı́sicamente
4.3 Software de control 112

la programación del generador de reloj de bit, también ordena la correcta reprogramación


de todos los coeficientes del filtro de datos, y por último modifica los registros internos
del modulador de acuerdo con la nueva velocidad. Es decir, es la encargada de que todo
esté como debe de estar.
Otro detalle que se debe de mencionar no tiene nada que ver con ésta función,
pero se refiere a un control junto al botón Divisor programable, en este caso de nombre
Divisor fijo. Lo importante es señalar que no tiene ningún efecto sobre el hardware de la
placa. Se ha incluido dentro de la interface gráfica como medio de avisarle al programa de
control de la posición fı́sica del puente JP2. Es responsabilidad del usuario el no modificar
inadecuadamente este control, porque de lo contrario la velocidad de datos indicada por
la aplicación serı́a incorrecta.

4.3.1.2. Función ValorFirAx


Además del trabajo de programar el coeficiente del filtro FIR correspondiente, estas
funciones (existe una por cada coeficiente) nos sirven de excusa para comentar una carac-
terı́stica en la que tenemos pendiente profundizar como es el factor de escala del camino
de datos. El efecto se aprecia en el listado viendo cómo el valor a programar se divide por
una variable esc old, para en la siguiente instrucción multiplicar el resultado por esc.
El funcionamiento del modulador depende de la correcta propagación de los datos
a través del filtro conformador de pulso y de los interpoladores en cascada. Según el
manual del AD9853, el tamaño de las palabras que manejan las etapas CIC depende
directamente de los factores de interpolación con que trabajan. En efecto, los integradores
de los filtros CIC realizan sumas que acumularán mayores resultados a medida que aumenta
su velocidad de trabajo en proporción directa al factor de interpolación. De todas formas,
los interpoladores se han diseñado con suficiente margen para evitar el desbordamiento
trabajando al máximo de sus posibilidades. El problema se plantea porque a la salida de
los mismos se realiza un truncamiento variando la precisión de los datos. Si se le echa un
vistazo a la figura 4.4, vemos que a la salida de cada interpolador existe una etapa llamada
scaler. Si el factor de interpolación elegido es muy bajo, los valores significativos de los
datos de salida estarán concentrados en los bit menor peso, mientras que lo contrario
ocurre a velocidades de interpolación alta. La función de los bloques escaladores serı́a
la de mantener siempre el mismo orden de precisión independientemente del factor de
interpolación seleccionado.
El problema que se plantea es el programar las etapas escaladoras de manera óptima
evitando por un lado pérdidas en la precisión de salida, y por otro que se produzca el
desbordamiento. Lo ideal serı́a estar siempre al borde del desbordamiento; de este modo
mantendrı́amos un alto grado de bits útiles con pocos “ceros a la izquierda”.
El fabricante recomienda programar las etapas escaladoras con un valor inferior en
una unidad al factor de interpolación asociado. En las hojas de datos se publica una tabla
con un factor de “ganancia nominal” correspondiente a cada factor de escalado, siendo éste
un factor de mérito que indica lo más o menos cerca que estamos del desbordamiento. Para
que el sistema permanezca estable, la ganancia conjunta de la etapa FIR, del interpolador
1 y del interpolador 2 debe ser a toda costa ≤ 1.
El fabricante recomienda elegir valores de escalado en los dos interpoladores que
resulten en una ganancia lo más cerca posible a 1 pero nunca por debajo, digamos z, para
luego escalar los coeficientes del filtro FIR con un valor igual a 1/z, que siempre será menor
de la unidad. Es el proceso comentado al principio de este apartado.
4.3 Software de control 113

La búsqueda de los factores de escalado siguiendo el criterio del fabricante se realiza


en la función busca esc llamada por interpolador, que a su vez es llamada por la función
ValorDiv que acabamos de comentar. Es en la función que nos ocupa cuando se completa
el ciclo, al multiplicar el valor de programación por la variable global esc.

4.3.2. Módulo de funciones hardware mod hard.c


Hablaremos en primer lugar de la función prog hard que es la función encargada
de dialogar con el modulador AD9853 a través de su puerto serie, y también de la función
interpolador, con la que terminaremos la descripción del camino de procesado de señal
en el interior del modulador, pendiente desde el apartado 4.2.1.1.

4.3.2.1. Función prog hard


Hablar de esta función es comentar el protocolo de comunicaciones serie del modu-
lador AD9853.

Figura 4.18: Protocolo hardware del puerto serie en el AD9853

Si observamos la figura 4.18, existe una parte común en los protocolos de lectura y
escritura del modulador en la cual se envı́a la dirección del dispositivo y la del registro
interno al que se quiere acceder, independientemente de que sea para leer o escribir. Co-
mo se habrá podido intuir, el trabajo se ha repartido entre tres funciones de bajo nivel:
carga reg ser, la parte común a las operaciones de lectura/escritura, escribe ser y lee ser,
de función clara según indica su nombre.
Comentando ya el funcionamiento concreto de la instrucción prog hard, se observa
en el listado de la aplicación su función de escribir datos de configuración en el modulador.
Según las hojas de datos del fabricante, la lı́nea fı́sica TXE debe estar desactivada durante
la utilización del puerto serie del modulador. Como durante la secuencia de inicialización
del programa principal, la lı́nea TXE se deshabilita un tiempo considerable, se quiere
evitar esa reiteración de órdenes con la construcción if del interior de la función.

4.3.2.2. Función interpolador


Se explicó en el apartado 4.2.1.1 cómo las etapas de interpolación sirven para ajustar
la frecuencia de datos a la frecuencia del reloj del sistema DDS. A continuación vamos a
analizar brevemente la relación entre todos los parámetros que intervienen es este proceso
para ver las opciones de maniobra que tenemos disponibles.
En primer lugar enumerammos los parámetros fijos que nos impone nuestra cons-
trucción hardware. La frecuencia de referencia de la placa es constante e igual a la del
cristal del circuito, en nuestro caso:
4.3 Software de control 114

FREF = 27M hz = cte


La frecuencia del sistema DDS también lo será puesto que se obtiene mediante
multiplicación del valor de referencia .

FSIS = 6FREF (4.7)


El usuario puede modificar la frecuencia de transmisión de datos cambiando el factor
de división según hemos visto en el apartado anterior.

FREF
FBIT = (4.8)
Div
Ahora expresamos la relación entre la frecuencia del sistema y la velocidad de trans-
misión de datos según las hojas del fabricante:
1
FSIS = 4I1 I2 FBIT (4.9)
M
donde el cuatro es un factor de interpolación fijo en la etapa FIR y M es el número
de bits por sı́mbolo de valor 2 en QPSK y 4 en 16QAM.
Operando con todos estos datos, y teniendo en cuenta los valores máximos y mı́nimos
de las etapas de interpolación, obtenemos

I1 I2 = 3Div
I1 I2max = 1953 Divmax = 651
I1 I2min = 6 Divmin = 2 Para QPSK
bit]
I1 I2 = 6Div
I1 I2max = 1953 Divmax = 325
I1 I2min = 12 Divmin = 2 Para 16QAM

Jugando con estos valores y con la ecuación 4.8 podemos calcular los valores máximos
y mı́nimos de frecuencias de transmisión de datos de nuestro sistema.
Podemos erróneamente pensar en este momento que todos los valores de factor de
división entre los lı́mites que se acaban de enunciar son posibles. Sin embargo, hay que
tener en cuenta que los interpoladores están diseñados para funcionar con unos factores
máximos de interpolación de 31 el primero y 63 el segundo. Esto supone una limitación
importante puesto que elimina aquellos valores de división cuya descomposición en factores
primos tenga un factor mayor de 63. Por ejemplo, podrı́amos querer seleccionar un factor
de división de 316 para trabajar en QPSK a una velocidad de 85.443 kbps. Pues bien,
como su descomposición en factores primos es 316 = 79 × 22 , no podemos programar a
ninguno de los interpoladores con el factor 79 y por tanto, aunque el circuito de generación
de reloj de bit admitiese ese valor, luego no podrı́amos trabajar con el modulador DDS.
La función interpolador realiza este trabajo de control sobre los parámetros de
temporización. En la aplicación se ha incluido una tabla con todos los valores que tienen
un factor primo mayor de 63 mediante el fichero de encabezamiento primo 63.h.
Cada vez que se cambia la velocidad de transmisión, lo primero hace esta función es
comprobar si el valor comandado es un valor permitido. Si esto no se cumple, la función
4.4 Resultados prácticos 115

empieza a buscar un valor de velocidad hasta que se encuentra el primero permitido por
defecto.
Cuando se ha encontrado un valor posible o bien el que se comandó ya lo era, la
función busca la repartición del factor de interpolación más adecuada siguiendo las reco-
mendaciones del fabricante. Aconsejan que el factor de interpolación global se reparta lo
más equitativamente posible en cada una de las etapas. Por ello, el algoritmo de búsqueda
empieza haciendo la raı́z cuadrada del valor a conseguir y le asigna a cada interpolador el
entero más cercano a ese valor.

4.4. Resultados prácticos

Una vez finalizada la descripción de la placa DDS es obligado el comprobar el co-


rrecto funcionamiento del sistema. Para obtener los resultados que se presentan en este
apartado se ha realizado la conexión representada en la figura 4.19, que es la forma usual
de utilizar el montaje en su conjunto: La placa BER de secuencias pseudoaleatorias genera
datos utilizando el reloj de bit proporcionado desde la placa DDS, datos que se aplican
como señal de información a transmitir a la entrada de la placa DDS. Obtendremos una
señal modulada con la que se pretende hacer medidas de propagación en el laboratorio.
En caso de disponer de algún método de demodulación, serı́a bueno el volver a aplicar
los datos recibidos a la placa de BER, para ası́ poder calcular la tasa de bits erróneos del
canal de transmisión.

Figura 4.19: Conexionado usual del sistema: placa DDS y placa de BER
trabajando conjuntamente

En el momento de redacción de este documento todavı́a no ha sido posible llevar


a cabo esta última comprobación. Los únicos medios a nuestro alcance han sido la ob-
servación de la señal en el dominio espectral y la revisión de los diagramas de ojos y la
constelación generados con las diferentes modulaciones.
Los gráficos que se presentan en la figura 4.20 han sido obtenidas en el laboratorio
con el analizador vectorial HP89410A, para una velocidad de transmisión de 2.5175 Mbps,
resultando en una velocidad de sı́mbolo de 2.5175 Msps en FSK, 1.25875 Msps en QPSK,
y 629 Ksps para 16QAM. El filtrado seleccionado en el equipo de medida fue un filtro en
coseno alzado con factor α = 0,28.
En el modulador DDS lo único que se programó fue una frecuencia de salida dentro
del margen operativo del analizador, que alcanza hasta los 15 Mhz, y como filtro de pulso
4.4 Resultados prácticos 116

(a) (b)

(c) (d)

(e) (f)

Figura 4.20: Medidas de salida para vt = 2,7175M bps realizadas con anali-
zador vectorial HP89410A y filtro de datos en coseno alzado de
factor α = 0,28.
(a),(c) y (e) Diagramas I-Q para QPSK, 16QAM y FSK.
(b),(d) y (f) Diagramas de ojos correspondientes
4.4 Resultados prácticos 117

no se modificó el que tiene la aplicación modulAD cargado por defecto en coseno alzado
con α = 0,5.
Por otra parte se incluyen las medidas realizadas con el analizador de espectros,
tanto en banda ancha para observar el comportamiento del modulador en lo referente a
margen libre de espúreos, como en banda estrecha para observar el filtrado que se realiza
en el dominio digital mediante las etapas FIR conformadores del pulso.

(a) (b)

Figura 4.21: Medidas de los espúreos de truncamiento de fase de salida.


(a) Palabra de sintonı́a que no genera espúreos.
(b) Palabra de sintonı́a donde se genera el máximo nivel de
espúreos

En la primera figura 4.21, se querı́a comprobar la teorı́a sobre la generación de


espúreos por truncamiento de fase expuesta en el apartado 1.5. En efecto, se puede apreciar
cómo existen palabras de sintonı́a de frecuencia que no generan espúreo alguno como en la
figura (a), donde sólo se aprecia distorsión armónica, mientras que la figura (b) se presenta
un caso de sintonı́a para máximo nivel de espúreos. En aplicaciones donde sea importante
esta especificación habrá que seleccionar adecuadamente la frecuencia de referencia para
que nuestra frecuencia de interés caiga en una palabra de sintonı́a “limpia”.
Se han obtenido gráficas como las de la figura 4.22 habiéndose anulado el filtro an-
tialiasing de la placa DDS. En ellas se pueden apreciar claramente las imágenes generadas
en el proceso de conversión D/A alrededor de la frecuencia de reloj del sistema de 162
Mhz. Esta señal de reloj tiene un gran acoplamiento de salida, incluso después de haberse
realizado trabajos de blindaje en la placa.
La gráfica (a) representa la señal de salida para una frecuencia nominal de 15 Mhz.
En este caso, las dos imágenes representadas corresponden a las frecuencias de 162 ±
15M hz = 147 y 177 Mhz. Como curiosidad, los principales espúreos que se aprecian
corresponden a la banda de FM comercial de 88 a 108 Mhz. En la gráfica (b) se representa
la misma situación, en este caso para una frecuencia de salida nominal de 65 Mhz. Aquı́ ya
vemos únicamente la imagen de 162 − 65 = 97 Mhz. Otro efecto que se pone de manifiesto
es el empeoramiento de las prestaciones del sistema a medida que subimos en frecuencia,
obsérvense si no los espúreos que aparecen.
La figura 4.23 corresponde a la misma situación de la anterior gráfica, en este caso
para una modulación FSK. La frecuencia nominal es 65 Mhz y la velocidad de datos de
4.4 Resultados prácticos 118

(a) (b)

Figura 4.22: Medidas en banda ancha para QPSK donde se observan las
imágenes generadas por el proceso de conversión D/A.
(a) QPSK a 13.5 Mbps a la frecuencia de 15 Mhz.
(b) QPSK a 13.5 Mbps a la frecuencia de 65 Mhz

Figura 4.23: Medidas en banda ancha para FSK sin filtro antialiasing
4.4 Resultados prácticos 119

133.66 kbps. La razón de volver a incluir una gráfica similar es destacar la mejorı́a en
SFDR de este caso, motivada por el cambio en el esquema de modulación y el régimen
de transmisión: Para todos los esquemas de modulación, el DAC del DDS genera la mis-
ma potencia de salida puesto que no se cambia para nada su configuración de corriente
máxima. Ahora bien, en QPSK y 16QAM la potencia se distribuye uniformemente sobre
todo el ancho de banda ocupado, mientras que en el ejemplo de FSK a baja velocidad,
como el régimen de transmisión es mucho menor, el espectro de salida se asemeja mucho
más a dos tonos, por lo que esa potencia de salida se “concentra” y la relación señal ruido
mejora ostensiblemente.

(a) (b)

Figura 4.24: Efecto del filtro antialiasing de salida.


(a) QPSK a 13.5 Mbps a la frecuencia de 15 Mhz.
(b) FSK a 13.5 Mbps a la frecuencia marca de 15 Mhz

La inclusión del filtro antialiasing de salida es muy efectiva como se aprecia en la


gráfica 4.24. La verdad es que para ser del todo realistas habrı́a que decir que la gráfica
corresponde a la situación más favorable del DDS puesto que la frecuencia de salida es
bastante baja, 15 Mhz. Desgraciadamente, en el momento de confeccionar este trabajo
todavı́a no se disponı́a de el filtro nominal con frecuencia de corte de 67 Mhz que estaba
especificado en el diseño, y ası́ poder cubrir todo el margen de salida del DDS. De cualquier
modo, es fácil de imaginar el resultado, si acaso con algunos espúreos más que no se ven
en la gráfica actual por haber sido eliminados con el filtro de 15 Mhz.
Queda por comentar el espectro cercano para las tres modulaciones. En las figu-
ras 4.25 (a) y (b) se puede comprobar el funcionamiento del filtro FIR conformador de
pulso programado para una curva de respuesta en coseno alzado. La figura (c) corresponde
a FSK, y aquı́ no se da filtrado alguno, por lo cual la señal se expande considerablemente
en el espectro.
Hasta aquı́ las medidas realizadas en la placa de modulación. Queda por comprobar
si los resultados prácticos de laboratorio son satisfactorios, una vez se sustituya el filtro
pasobajo de salida por el definitivo con frecuencia de corte 67 Mhz. En el apéndice B se
incluyen fotografı́as con indicaciones prácticas que facilitan el manejo del sistema. Son
vistas laterales del chasis que contiene el sistema, y en ellas se indica qué conector es cada
cual. También se incluyen tablas con la función de los pines de cada conector.
4.4 Resultados prácticos 120

(a)

(b)

(c)

Figura 4.25: Espectro cercano para los tres tipos de modulaciones principa-
les.
(a) QPSK a 13.5 Mbps a la frecuencia de 10 Mhz.
(b) 16QAM a 13.5 Mbps a la frecuencia de 10 Mhz.
(c) FSK a 133.66 Kbps a la frecuencia de marca de 10 Mhz.
Capı́tulo 5

Generador medidor de tasa de bits


erróneos

Corresponde a este capı́tulo la descripción del funcionamiento de la placa hardwa-


re de generación de secuencias aleatorias, ası́ como de su correspondiente aplicación de
control. La función de este circuito dentro del proyecto es servir como fuente de datos de
información a la placa de modulación DDS. Esta es la forma más sencilla de obtener una
trama de entrada para la evaluación del funcionamiento y las prestaciones del sistema.
El montaje práctico está basado en el integrado de Dallas DS2172, que genera las
secuencias de salida gracias a un banco de registros de desplazamiento con realimenta-
ción configurable. Esta caracterı́stica permite obtener una amplia gama de secuencias con
algunas restricciones que se verán más adelante.
Aunque la aplicación particular para la que se utiliza es la generación de secuencias
pseudoaleatorias, el chip también dispone de un circuito “sincronizador” que permite de-
tectar la recepción coincidente con la secuencia transmitida, útil en la comprobación de
tasa de bit erróneos (BER).
Con el objetivo de sacar el máximo partido a las prestaciones del integrado, tanto
la placa hardware como la aplicación de control se ha desarrollado para aprovechar la
caracterı́stica principal del chip DS2172: la medida de tasas de BER.
El aspecto de la interface de usuario trata de emular el frontal “virtual” de un equipo
de medida de BER, siguiendo un método similar al de algunas otras aplicaciones prácticas
comerciales corrientes, como por ejemplo las tarjetas de adquisición de señal para PC
utilizadas en forma de osciloscopios, analizadores de espectros y analizadores de bus.
Durante la exposición del resto del capı́tulo, haremos referencia a esta placa de
circuito impreso como placa de BER.

5.1. Opciones de diseño


En principio, la necesidad de disponer de una trama de datos con la que comprobar
la placa de modulación DDS obligaba a generar esos datos de alguna manera práctica. Se
pensaron varias alternativas a la hora de acometer el diseño del sistema, cotejándose la
medida en que cada una de estas alternativas se adaptaba a nuestras necesidades.
Los requisitos que el sistema de generación de tramas digitales necesitaba cumplir
se pueden resumir en los siguientes puntos:

Altas velocidades de operación, del orden de decenas de Mhz, ya que se pretende

121
5.1 Opciones de diseño 122

analizar el modulador a regı́menes altos de velocidades de transmisión simulando los


nuevos servicios de telecomunicaciones en banda ancha que se están empezando a
introducir.

Número de secuencias suficientemente amplio como para poder realizar diferentes


tipos de pruebas. A ser posible serı́a interesante el contar con la posibilidad de generar
secuencias arbitrarias creadas por el usuario permitiendo provocar determinadas
condiciones en el modulador especialmente particulares: secuencias del tipo 1010...
1100... 11110000... hacen que la señal de salida de los moduladores adquiera en según
qué tipos de modulación la caracterı́stica de tonos fijos.

Facilidad de control externo que permita el desarrollo de un software de control


apropiado.

La primera opción que se barajó fue la de generar las secuencias de datos mediante
un programa desde el ordenador. La ventaja inherente a la generación software estriba
en el control que se tiene sobre la secuencia generada, permitiendo ampliar fácilmente el
número de secuencias y patrones de transmisión para poder simular los nuevos escenarios
prácticos que vayan apareciendo en el futuro.
Por otra parte, el principal inconveniente de esta opción consiste en que el sistema
operativo Windows proporciona un control de temporizaciones que como máximo llega a
1 milisegundo. Por tanto, si se pretende llegar a unos regı́menes de transmisión del orden
de los 15 Mbit/s es preciso enviar a un buffer 15000 bits por operación de entrada/salida,
(15000 bits / 1 ms). El bus ISA del PC funcionarı́a sobrado de capacidad, pero tendrı́amos
el inconveniente de necesitar un dispositivo hardware que estuviese dotado de una memo-
ria de doble puerto que, funcionando en forma de buffer plesiócrono, recibiera los datos
ası́ncronos del PC para enviarlos al modulador DDS de forma sincronizada.
La necesidad de utilizar el bus ISA nos obliga a un desarrollo en forma de tarjeta de
expansión del PC, que dificulta su instalación en un portátil y limita considerablemente
su abanico de utilización a entornos cerrados de laboratorio.
Alternativamente surgió la idea de generar los datos directamente desde hardware,
puesto que incluso la primera opción obligaba a realizar por este mismo método el ya
comentado dispositivo de sincronización. De esta forma se liberarı́a de mucho trabajo a
la CPU principal del PC, a costa de disminuir el grado de libertad en la generación de
secuencias. Se buscaron circuitos integrados que realizaran ese trabajo, encontrándose el
integrado de Dallas DS2172.
En este caso la opción de diseño contempla la realización de una placa de circuito
impreso, siendo necesaria únicamente la programación de los registros del integrado de-
pendiendo de la secuencia que se desee utilizar. Dada la relativamente escasa cantidad
de instrucciones y comandos necesarios, al menos comparada con la primera opción, se
puede utilizar al puerto paralelo del PC como interface de control, que además es una
interfaz ampliamente conocida y sobre la que se puede encontrar multitud de información
al formar parte integral del PC. [?].
Al utilizar el puerto paralelo del PC se gana en flexibilidad de uso, ya que lo único
que hace falta en este caso es un cable paralelo, y por tanto se puede utilizar cualquier
portátil para controlar el circuito en medidas de campo.
Se optó por esta última opción dadas sus ventajas sobre la primera filosofı́a, con
la particularidad de que fue ésta decisión la que determinó el tipo de control a utilizar
5.2 Especificaciones de la placa BER 123

en la placa DDS. No hubiese tenido sentido realizar dos tipos de control independientes
pudiendo controlar los dos circuitos de modo homogéneo.

5.2. Especificaciones de la placa BER


Una vez justificada la opción de diseño seleccionada, resumimos las prestaciones que
se han conseguido en el trabajo.
Generales

Aplicaciones: Generación de secuencias aleatorias de prueba y medida de tasas de


error de bit.

Puede funcionar conjuntamente con la placa DDS como fuente de bits a transmitir,
o utilizarse como sistema aislado independiente.

Tipos de secuencias generadas:

1. Modo pseudoaleatorio: 23 secuencias diferentes resumidas en la tabla 5.1. La


longitud de la secuencia más larga es 232 − 1.
2. Modo repetitivo: Cualquier secuencia programable de hasta 32 bits de longitud.
Se han predefinido 10 que se muestran en la tabla 5.2.

Control

Puerto Paralelo estándar PC en modo compatible

Programa de Control mediBER para los sistemas operativos Windows 98 y NT.

Caracterı́sticas de Entrada Salida

Formato de señales digitales: TTL NRZ.

Velocidad máxima de transmisión y recepción: 52 Mhz.

Modos de trabajo:

1. Modo continuo. Conectando los pines 3 y 5 (RDIS y TDIS) del conector de


transmisión/recepción a masa.
2. Modo ráfagas. Gobernado por los hilos RDIS y TDIS del conector de transmi-
sión/recepción.

Alimentación

Tensión exterior: 12 voltios DC.

Consumo: 85 mA

Software de control. Programa mediBER

Duración de los test programable hasta en un mes.


5.3 Diseño hardware de la placa BER 124

Selección de la secuencia digital de prueba de entre 33 predefinidas. También está dis-


ponible la opción de generar una secuencia repetitiva de hasta 32 bits.

Inserción manual y automática de errores en la secuencia transmitida. Las tasas de


error que se pueden generar automáticamente son 10−1 , 10−2 , 10−3 , 10−4 , 10−5 , 10−6
y 10−7 .

Indicación en la ventana de la aplicación de los principales parámetros de interés:

1. Tiempo de test y tiempo de disponibilidad.


2. Número total de bits recibidos y número de errores.
3. Indicación de las tasas de ES, SES, DM y BER. (Segundos erróneos, segundos
severamente erróneos, minutos degradados y tasa de error de bit).

Indicación gráfica del estado de sincronismo entre la secuencia transmitida y recibida.


Indicaciones adicionales auxiliares para cuando se reciben las señales de error “todo
unos” y “todo ceros”.

Grabación del resultado de los test en fichero de texto con los parámetros más
importantes de la prueba realizada.

5.3. Diseño hardware de la placa BER


Dado que el principal bloque constitutivo de esta placa es el integrado DS2172 de
Dallas, lo primero que debemos determinar claramente es su función: El chip DS2172
está pensado para analizar y comprobar la calidad de los sistemas digitales por medio de
la generación y detección de patrones digitales binarios.
También enumeramos sus principales caracterı́sticas, muchas de las cuales son las
responsables de las especificaciones que se acaban de enunciar en el apartado anterior.

Generación de secuencias aleatorias a partir de un registro de desplazamiento de


hasta 32 etapas con un punto de realimentación intermedio programable. Esto per-
mite generar cualquier secuencia, bien sea de longitud máxima o no, cuyo polinomio
generador sea del tipo:

g(x) = 1 + xB + xA (5.1)

teniendo A una gama de valores de 1 a 32 (determina la cantidad de etapas utilizadas


en la generación de la secuencia), y B también una gama de 1 hasta A (determina
la posición del punto intermedio de realimentación). En realidad existe libertad a
la hora de programar los dos valores, y B puede valer también de 1 a 32, lo que se
desconoce es el efecto de programar un valor de realimentación intermedio B mayor
de la longitud total del banco de etapas A.
Las hojas caracterı́sticas del fabricante contienen la información concreta para la
programación de las secuencias pseudoaleatorias estándar utilizadas en la industria,
pero se han hecho pruebas de generación de otras secuencias diferentes sin haber
encontrado ningún tipo de problema.
5.3 Diseño hardware de la placa BER 125

También dispone de la posibilidad de generar secuencias repetitivas de hasta 32 bits,


incluyendo cualquier patrón decidido por el usuario. Los registros se cargan con el
valor programado y sus contenidos son desplazados a la salida de forma periódica
sin alteración de los mismos.

Tanto trabajando en modo repetitivo como en modo pseudoaleatorio, la parte de


recepción dispone de un autosincronizador que busca la coincidencia entre la trama
que está generando y la que recibe. De este modo, si se encuentra una comparación
positiva entre las dos secuencias, se activa el mecanismo de conteo de errores, con lo
que se pueden obtener parámetros de funcionamiento de un enlace digital.
El dispositivo es capaz de detectar mediante este procedimiento tasas de error de
hasta 10−2 .

Inserción de errores tanto de forma automática como manual. De forma automática


se puede programar para generar las tasas de BER desde 10−7 hasta 10−1 , en 6 pasos
de un orden de magnitud cada uno.

Velocidades de operación desde DC hasta 52 Mhz. Esto nos permite generar una
amplia gama de velocidades de transmisión. En la práctica esta ventaja no se explota
en su totalidad dado que el reloj maestro del sistema realizado es 27 Mhz, y por
construcción práctica de la placa DDS la máxima velocidad de datos que se puede
conseguir es 27/2 = 13,5 Mbps. Si se utiliza la placa de BER por separado esta
limitación no existe, siempre suministrando la señal de reloj de forma externa.

Puerto paralelo de control de 8 bits. Factor importante que hace que el puerto
paralelo del PC se convierta en una interface casi directa con el chip. Se requiere
una pequeña variación hardware si, como en nuestro caso, se quiere utilizar el puerto
paralelo en modo compatible.

5.3.1. Composición interna del DS2172

En esta sección profundizaremos en el esquema de bloques del DS2172 con el obje-


tivo de clarificar su funcionamiento interno, de forma que al lector le resultará más fácil
entender su operación. El diagrama general del integrado se representa en la figura 5.1.
Dentro del mismo podemos distinguir los siguientes bloques:

Puerto de control: Está constituido por un bus multiplexado de direcciones y datos


que puede funcionar en dos configuraciones de protocolo que se selecciona mediante
el pin BTS: el modo Intel (BT S = 0) o el modo Motorola (BT S = 1). Cada modo
tiene su forma particular de funcionar, pero ambos utilizan la premisa de primero
colocar la dirección del registro al que se quiere acceder, tanto para leer como para
escribir, y en último lugar el dato. La información concreta de diagramas de tiempo
se encuentra en las hojas del fabricante [?]

Generador de secuencias patrón: Forman parte de este bloque funcional los


registros PSR, Pattern Set Register ó Registro de Configuración de Patrón, PLR,
Pattern Length Register ó Registro de Longitud de Patrón, y el PTR, Pattern Tap
Register ó Registro de Etapa de Patrón. Su función conjunta es la de determinar la
5.3 Diseño hardware de la placa BER 126

Figura 5.1: Diagrama de bloques del integrado medidor de BER DS2172

secuencia generada, y está relacionada con la configuración del registro de despla-


zamiento que la crea. Este bloque se estudia con mayor profundidad en el siguiente
apartado.

Bloque de inserción de errores: Está encargado de la producción de errores en


la secuencia generada, invirtiéndola instantáneamente. Los errores generados pueden
ser automáticos, en cuyo caso este bloque se encarga de generar una tasa determinada
de error, o bien manuales, insertándose entonces a petición desde el puerto de control.

Detector de Patrón: Es un bloque en el que se realiza la comparación entre el


patrón de secuencia transmitida y lo que se recibe en el bloque de recepción. Su
función es la de detectar la “coincidencia” o estado de sincronización entre ambas
secuencias. Se puede configurar para que trabaje de modo automático ante la pérdida
del sincronismo o bien para que sea el usuario el que comande el momento de empezar
el proceso de sincronización, (bits SYNCE y RESYNC del registro PCR, Registro
de Control).

Bloque de control de Transmisión: Controla la salida de los bits generados al


exterior. Es el encargado de la temporización de transmisión.

Bloque de control de Recepción: Controla la entrada de datos desde el exterior.


Recibe el reloj con el que se temporiza toda la parte de recepción.

Multiplexación de Bucle: Determina la trama de entrada hacia los subsistemas de


recepción, bien la secuencia de entrada desde el bloque de recepción (funcionamiento
normal), o por el contrario la secuencia que se genera en los bloques de transmisión,
útil en la realización de un bucle interno. Su funcionamiento se gobierna mediante
el bit LPBK del registro de control, PCR.
5.3 Diseño hardware de la placa BER 127

Bloque de recepción: Es el bloque donde se ubican los bits recibidos desde el


bloque de multiplexación y desde el que se alimenta el detector de secuencias o
sincronizador. También se puede leer su contenido desde el puerto de control. En
este caso, se debe de acceder al registro PRR, Pattern Receive Register, Registro de
patrón de recepción

Contadores de Errores y de Bits: Son dos registros donde el sincronizador ano-


ta el resultado de estas dos cuentas, por lo tanto son dos registros claves para la
obtención de tasas de BER. Totalmente controlables desde el puerto de control, sus
nombres son BECR, Bit Error Count Register, y BCR, Bit Count Register.

Quedarı́an por mencionar el registro de estado, SR, Status Register, y el registro


de máscara de interrupciones, IMR, Interrupt Mask Register, desde donde se
conocen en tiempo real las circunstancias de operación del sistema, y se gobierna la
activación del pin externo IN T de interrupción.

5.3.1.1. Configuración del registro de desplazamiento


En nuestro conocido integrado medidor de BER se utiliza la técnica descrita en el
capı́tulo 2 para generar secuencias de test. Se trata de un registro de desplazamiento al
cual se le puede programar la realimentación dependiendo del polinomio generador de la
secuencia elegida.
No obstante, existen una serie de limitaciones impuestas por las caracterı́sticas del
hardware, que añaden una serie de condiciones a la hora de seleccionar la secuencia a
generar. Se impone por tanto una revisión interna del registro de desplazamiento.
Su representación esquemática se muestra en la figura 5.2, donde se pueden observar
varios aspectos destacables:

Figura 5.2: Esquema del registro de desplazamiento para generación de se-


cuencias en el DS2172

Modo pseudoaleatorio
Por un lado, lo referente a la naturaleza de la secuencia pseudoaleatoria generada.
Su descripción matemática, y por tanto su longitud y patrón vienen determinados por dos
parámetros:
5.3 Diseño hardware de la placa BER 128

1. La cantidad de etapas utilizadas del registro de desplazamiento (como máximo 32).


Esto determina directamente el grado del polinomio generador de la secuencia. Es lo
que en la figura viene indicado como “toma de realimentación A”, Tap A Feedback.
El registro interno determinante de esta longitud es el Pattern Length Register, PLR,
y se encuentra en la dirección hexadecimal 04H .

2. El punto intermedio de realimentación. Esto determina el termino de menor grado


del polinomio generador, (ver la ecuación 5.1). Aquı́ el término de menor grado viene
indicado por xB .
El valor de la “toma de realimentación B” se configura mediante el registro Polyno-
mial Tap Register, PTR, de dirección 05H .

Otro de los aspectos destacables de la figura 5.2 es la puerta and incluida en la toma
de realimentación B. El terminal PCR.5 es el que la habilita: Un uno permite que los
valores que se desplazan por el registro de desplazamiento se realimenten a la puerta xor
de entrada, por tanto modificando las caracterı́sticas de la secuencia de salida, siempre
dependiendo del polinomio generador elegido.
Por el contrario, un cero en el terminal PCR.5 anula la realimentación a la entrada
del registro de desplazamiento de los valores que se propagan a su través, resultando una
secuencia periódica o repetitiva, igual al valor inicial cargado en los flip-flops tipo D que
conforman el registro.
De este análisis podemos concluir que es el terminal PCR.5 el que determina el modo
de trabajo del generador de secuencias patrón, bien en el modo pseudoaleatorio, bien en
modo repetitivo.
El terminal EIR.5 realiza la inversión de los bits transmitidos. Esta inversión se
puede configurar de forma permanente desde el controlador, aunque como su nombre
sugiere: EIR, Error Insert Register, forma parte de la circuiterı́a de inserción de errores y
por eso está situado en el camino de la trama de salida.
¿Cuántas secuencias pseudoaleatorias se pueden generar con esta topologı́a del re-
gistro de desplazamiento?. La respuesta más inmediata es ¡muchas!. Obviamente, aunque
no vamos a poder determinar su número exacto, ahora estamos en condiciones de decir
algo más gracias al capı́tulo 2.
La ecuación 2.16 calculaba el número de polinomios primitivos de un grado deter-
minado, de forma que estamos en condiciones de determinar el número de polinomios
primitivos que existen desde grado 2, (1 + x + x2 serı́a la primera secuencia de longitud
máxima generable), hasta grado 32:
r=32 r=32
X X φ(2r − 1)
N P Ptot = λ2 (r) = (5.2)
r
r=2 r=2

siendo λ2 (r) el número total de polinomios primitivos de grado r, y φ(n) la función


de Euler.
Este valor se puede calcular, y es del orden de millones, aunque afortunadamente
el problema se simplifica enormemente. Para cada grado r de polinomio generador, sólo
tenemos que comprobar si los r − 1 polinomios generadores que existen de la forma 1 +
xB + xr , con B desde 1 hasta r − 1 son primitivos.
El número total de polinomios existentes de este tipo es:
5.3 Diseño hardware de la placa BER 129

r=32
X
N P 3tot = (r − 1) = 496 (5.3)
r=2

Estos 496 polinomios representan otras tantas secuencias, y todas se pueden generar
con nuestro medidor de BER, incluso aquellas que no son de longitud máxima (primitivos).
Aunque no hemos resuelto el problema, quedarı́a ahora por averiguar utilizando técnicas
computacionales, cuáles de esos 496 polinomios son primitivos realmente.
Con la intención de retornar al mundo práctico se incluye la tabla 5.1 enumerando
las secuencias recomendadas por el fabricante, y aunque, se podrı́a programar cualquiera
de la forma 1 + xB + xA , no todo es perfecto y no se ha previsto esa posibilidad en la
aplicación de control. Solamente se realizaron diversas pruebas satisfactorias durante la
fase de desarrollo.

Secuencia Polinomio generador Observaciones


23 − 1 1 + x + x3
24 − 1 1 + x + x4
25 − 1 1 + x2 + x5
26 − 1 1 + x5 + x6
27 − 1 1 + x + x7
27 − 1 1 + x4 + x7 LB T1
27 − 1 1 + x4 + x7 LB T1 Invertida
29 −1 1+ x5 + x9 Recomendación O.153
210 −1 1+ x3 + x10
211 −1 1+ x9 + x11 Recomendación O.152 y O.153
215 −1 1+ x14 + x15 Recomendación O.151
217 −1 1+ x3 + x17
218 −1 1+ x7 + x18
220 − 1 1 + x3 + x20 Recomendación O.153
220 − 1 1 + x17 + x20 Recomendación O.151, QRSS
221 −1 1+ x2 + x21
222 −1 1 + x + x22
223 − 1 1 + x18 + x23 Recomendación O.151
225 −1 1+ x3 + x25
228 −1 1+ x3 + x28
229 − 1 1 + x2 + x29
231 − 1 1 + x3 + x31
232 − 1 1 + x17 + x32

Cuadro 5.1: Descripción matemática de las secuencias pseudoaleatorias pro-


gramadas en la placa de BER. Se puede apreciar cómo los poli-
nomios generadores siempre tienen 3 términos a causa del diseño
interno del DS2172
5.3 Diseño hardware de la placa BER 130

Modo repetitivo
Las secuencias repetitivas que se permite configurar tienen como máximo una lon-
gitud de 32 bits. Este lı́mite viene impuesto por el hardware del integrado, ya que es éste
el número de etapas que posee el registro de desplazamiento.
La verdad es que en este aspecto notamos una cierta limitación de prestaciones,
pues se echa de menos el poder generar secuencias repetitivas de mayor longitud; al menos
esa es una de las pocas diferencias que se han encontrado con respecto a otros equipos
comerciales comparados [?]. Por ejemplo, con 256 bits de longitud se podrı́a simular una
trama E1 de 2048 kbits/s repetitiva, jerarquı́a primaria en Europa.
De cualquier forma, en la tabla 5.2 se reflejan las secuencias repetitivas recomendadas
por el fabricante que son las que se han predefinido en la aplicación de control. Para poder
programar cualquier otra secuencia, esta vez si que se ha dispuesto de una opción en la
pantalla principal de la aplicación de control.

Secuencia Patrón Observaciones


Todo unos . . . 11111 . . .
Todo ceros . . . 00000 . . .
Unos y ceros alternativos . . . 10101 . . .
Unos y ceros dobles alternados . . . 1100110011 . . .
3 unos en 24 bits . . . 001000000000000000100010 . . .
1 uno en 16 bits . . . 1000000000000000 . . .
1 uno en 8 bits . . . 1000000010000000 . . .
1 uno en 4 bits . . . 10001000 . . .
Bucle D4 activado . . . 1000010000 . . . 1 uno en 5 bits
Bucle D4 desactivado . . . 100100 . . . 1 uno en 3 bits

Cuadro 5.2: Descripción de las secuencias repetitivas programadas en la placa de BER.

5.3.2. Bloques funcionales de la placa de BER

La placa de BER está concebida para “acomodar” al principal bloque funcional


de misma, el medidor de tasa de BER DS2172. En la sección anterior se analizaron en
profundidad sus prestaciones; ahora que ya tenemos un conocimiento más preciso de las
mismas y sabemos los tipos de secuencias que podemos generar, es el momento de describir
el funcionamiento global de la placa y ver cómo el resto de bloques da soporte a las tareas
de intercambio de datos entre el programa de control y el DS2172.
En figura 5.3 se presenta el diagrama de bloques de la placa de BER. En ella podemos
distinguir los siguientes elementos:

1. Puerto paralelo de control

2. Buffer de control

3. Buffer de datos

4. Medidor de BER
5.3 Diseño hardware de la placa BER 131

Figura 5.3: Diagrama de bloques de la placa de BER

5. Conector de transmisión/recepción

El puerto paralelo y el bloque de entrada/salida son los puntos de acceso a la placa


desde el exterior. El primero permite la comunicación de datos entre el PC donde reside
la aplicación de control y los recursos hardware de la placa de BER, representados prin-
cipalmente por el medidor de BER, o lo que es lo mismo, el circuito integrado de Dallas
DS2172. El bloque de entrada/salida es el punto de acceso a las tramas de test generadas
por el medidor de BER, y también por donde entran las secuencias recibidas en las pruebas
de tasa de errores.
Los dos bloques que actúan como buffers canalizan el flujo de señales de control y
de información entre el medidor de BER y el PC que lo controla.

5.3.2.1. Puerto paralelo de control


Al igual que en la placa DDS, el interface de control de la tarjeta es un conector
plano de 26 pines en el que se acomodan las señales del puerto paralelo. El conexionado
con el exterior se realiza por medio de un cable plano hasta un conector DB-25 (el último
hilo de masa se queda sin conectar), que se encuentra montado en el chasis que contiene
al sistema completo. Desde ahı́ hasta el puerto del PC ya es cuestión de que el usuario
compre un cable paralelo corriente.
En la tabla 5.3 se recogen los hilos del puerto paralelo que se utilizan en la placa
ası́ como su función.

5.3.2.2. Buffer de control


Este bloque es el encargado de demultiplexar los comandos que llegan desde el PC
por el bus de datos del puerto paralelo y convertirlos en señales válidas de control hardware.
5.3 Diseño hardware de la placa BER 132

Pin Nombre Función en la placa BER


1 LATCH0 Strobe de carga del bus de datos en placa BER
2 D0 LSB del Bus de datos
3 D1 Bus de datos
4 D2 ”
5 D3 ”
6 D4 ”
7 D5 ”
8 D6 ”
9 D7 MSB del Bus de datos
10 OD6 Bit del nibble de lectura de estado desde placa BER
11 OD7 MSB del nibble de estado (invertido hardware)
12 OD5 Bit del nibble de estado
13 OD4 LSB del nibble de estado
16 LATCH2 LSB de Selección de Registro en placas DDS y BER
17 LATCH3 MSB de Selección de Registro en placas DDS y BER
18 a 26 GND Masa

Cuadro 5.3: Interface entre la placa BER y el puerto paralelo del PC.

Figura 5.4: Buffer de control de la placa de BER


5.3 Diseño hardware de la placa BER 133

Tal y como se ve en la figura 5.4, está constituido por los siguientes componentes:

U10, 74HC139. Es un demultiplexor dos a cuatro que genera las señales de “enable”
de activación de los drivers que retienen la información enviada desde el PC a través
del bus de datos del puerto paralelo (D0 a D7). Los hilos de selección son los ter-
minales LATCH2 y LATCH3 del puerto de control del PC, y su validación también
llega directamente desde el puerto paralelo a través de la señal de control LATCH0.
Su funcionamiento es idéntico a su componente homólogo de la placa DDS, salvo
por la señal de control que lo activa, en aquel caso LATCH1. En este caso, la lı́nea
CHIP0 se emplea para demultiplexar las señales de control hardware de la placa,
y por otro lado CHIP1 se utiliza para cargar el bus del puerto paralelo en el bus
interno de datos.

U5, 74HC574. Es uno de los dos buffers del circuito, y su función es la de fijar todos
los comandos de control recibidos por el bus de datos. Sus hilos de salida reflejan
el valor lógico presente en las entradas justo en el flanco de subida de su señal de
enable CHIP0, que es proporcionada por U10.
Aunque este circuito es un buffer triestado, esta posibilidad no se utiliza en este caso
al realizar funciones de transceptor de control. Por eso el hilo OC está directamente
conectado a masa. Podemos decir que este integrado gobierna el funcionamiento del
resto de recursos hardware de la placa de BER.

Es importante que el programa de control realize la secuencia de operaciones correc-


tas con el fin de que los datos se carguen en el registro adecuado. En el caso concreto de
un comando de control, esta secuencia debe ser la siguiente:

1. Colocar el dato de control a cargar en el bus de datos.

2. Seleccionar el driver en el que se quiere escribir el valor mediante los hilos de selección
LATCH2 y LATCH3 (concretamente CHIP0).

3. Activar el hilo de strobe correspondiente poniéndolo a nivel lógico bajo. En este


caso LATCH0 para la placa de BER. Esto produce que se active el hilo de enable
especı́fico del driver direccionado, como ya se ha dicho en el ejemplo, CHIP0.

4. Desactivar el hilo LATCH0 anterior. Esto provoca que el hilo enable del buffer se
desactive subiendo a nivel lógico alto, y como consecuencia de ello, el dato se fije a
la salida del mismo.

5.3.2.3. Buffer de datos


Este bloque es el equivalente al anterior en lo que se refiere a datos de configuración.
Su función es la de demultiplexar los datos de configuración que se envı́an por el bus
del PC, actuando de puente entre este bus y el bus de datos interno de la placa de
BER. Es necesario precisar que el bus interno es bidireccional porque está directamente
conectado al puerto de control del DS2172. Ya se habló en la sección A.1 de las distintas
modalidades de funcionamiento del puerto paralelo del PC y, aunque en los PC modernos
el hardware permite transmisiones bidireccionales por el bus de datos, se querı́a mantener
la compatibilidad con el bus original, y por eso se diseñó el hardware pensando en enviar
datos hacia el PC utilizando los hilos de estado.
5.3 Diseño hardware de la placa BER 134

Figura 5.5: Buffer de datos de la placa de BER

Con esta premisa se ha diseñado el buffer de datos, de forma que, dependiendo de la


dirección de la información, se habilitará uno u otro de los transceptores de que consta el
bloque, tal y como se refleja en la figura 5.5. A continuación se comenta el funcionamiento
de cada uno de ellos:

U3, 74HC574. Es el buffer que da paso a los datos desde el puerto paralelo. Su
activación se realiza mediante la selección de la dirección CHIP1 en el bloque de
control y su funcionamiento es análogo a U5 del mismo bloque. En este caso, sin
embargo, si que se debe prestar atención a la dirección de la información puesto que
cuando se quiere enviar algún dato hacia el PC se deben de poner las salidas de U3
en alta impedancia para no interferir en el bus interno AD0 − AD7.

U4, 74LS241. Es el transceptor encargado de multiplexar el bus interno hacia los


hilos de estado del puerto paralelo, cumpliendo con la función de envı́o de datos
en la dirección de salida. En la figura se señala cómo se utilizan en el sentido de
lectura cuatro hilos de estado, OD7 a OD4, del puerto paralelo. El bus interno es de
ocho bits; por ello es necesario multiplexarlo y realizar la lectura en dos operaciones
seguidas.
El integrado tiene dos secciones de cuatro bits cada una, con habilitación indepen-
diente, aunque curiosamente las señales de enable son invertidas. Da la sensación de
que el diseñador pensó en una utilización de este estilo.

Todas las operaciones están gobernadas mediante hilos del bloque de control, por lo que
toda transferencia de datos hacia el PC estará precedida de los correspondientes envı́os de
comandos de control hacia la placa de BER.

5.3.2.4. Medidor de BER DS2172


Es el bloque principal y ya conocemos sus caracterı́sticas más importantes, pues
está constituido ı́ntegramente por el circuito DS2172. En este apartado comentamos la
5.3 Diseño hardware de la placa BER 135

figura 5.6, donde podemos observar el conexionado particular del mismo en nuestra apli-
cación.

Figura 5.6: El DS2172 y su conexionado en la placa de BER

El puerto de control AD0 a AD7 está conectado al bus de datos interno de la placa.
Existe un grupo de hilos de control que gobiernan la temporización de los intercambios
de datos tanto de entrada como de salida. Todos estos hilos llegan desde el bloque “buffer
de control” comentado hace unos párrafos en el apartado 5.3.2.2. Se admiten dos tipos
de temporizaciones para los mismos terminales de control dependiendo del estado lógico
del pin BTS, Bus Type Select: Si esta señal está a nivel alto, el bus funciona según la
temporización estándar de Motorola, mientras que si su valor lógico es bajo, el tipo de
temporización que se emplea es la de Intel. Dependiendo de ello, el funcionamiento de los
pines 15, 17 y 18 difiere.
En nuestro diseño se ha escogido arbitrariamente la temporización del tipo Intel, ya
que no existı́a ningún motivo coercitivo que nos obligara a escoger un tipo determinado en
concreto. Realizada esta elección, la función de los terminales de control se puede resumir
del siguiente modo:

Pin 16 Chip Select, CS. Activo a nivel bajo sirve para indicarle al DS2172 que
debe prestar atención al bus, bien para leer o escribir en él.

Pin 17 Address Latch Enable, ALE. Es el terminal que sirve para demultiplexar
las direcciones del bus de datos interno. Los datos de dirección se cargan en el
integrado en el flanco de bajada de este terminal, siempre y cuando esté habilitado
el hilo de Chip Select.

Pin 15 Read, RD. Hilo de lectura de datos desde el registro previamente seleccio-
nado. El chip pone el dato en el bus en el flanco de bajada del terminal. En este
5.3 Diseño hardware de la placa BER 136

caso habrá que tener la precaución de poner el buffer de datos a alta impedancia
previamente.

Pin 18 Write, W R. Hilo de escritura activo a nivel bajo. El integrado carga en el


registro previamente seleccionado, el dato presente en el bus justamente en el flanco
de subida de esta señal.

Existen otros tres pines externos de control que no utilizamos puesto que tienen su
homólogo en un bit de los registros de control, y resulta muy fácil acceder a ellos mediante
software. Para inhabilitar los terminales se han conectado a masa. De todas maneras, los
enumeramos añadiendo un comentario explicativo de su función.

Terminal RL, Receive Load. Un flanco de subida en este pin carga los últimos
32 bits recibidos en los registros PRR, registros de recepción de secuencia patrón.
Su valor lógico está combinado mediante puerta OR con el valor del bit PCR.3 del
registro de control PCR.

Terminal LC, Load Count. Una transición de bajo a alto carga los contadores de
bits recibidos y errores detectados en los registros accesibles al usuario BCR y BECR,
y resetea la cuenta de los registros internos. Se combina mediante puerta OR con el
valor del bit PCR.4 del registro de control de patrón.

Terminal TL, Transmit Load. Es el terminal dual a RL, esta vez referido al gene-
rador de secuencia patrón: El valor de los registros de configuración de patrón PSR
se carga en el registro de desplazamiento que genera la secuencia a transmitir en el
flanco de subida de este terminal. Su valor también está combinado con el bit PCR.7
mediante un operador OR lógico.

Otro terminal que no se utiliza, esta vez no de control sino de estado, es el terminal
RLOS, que es un indicador hardware de sincronización. Como la misma indicación se
puede leer del bit SR.4 del registro de estado, en el montaje este pin se queda sin conexión.
Nosotros utilizaremos en nuestra aplicación la lectura de ese registro para determinar el
correcto “enganche” del medidor a la secuencia recibida.
Aparte de los terminales de alimentación nos queda el bloque de pines de transmi-
sión-recepción, que se comentan en el siguiente apartado.

5.3.2.5. Conector de transmisión-recepción


La conexión al exterior de los terminales de transmisión y recepción del módulo de
BER se realiza mediante el conector dibujado en el esquema de la figura 5.7. Es el conector
de diez terminales plano que aparece en la parte lateral inferior del chasis que contiene
todo el montaje. Su fotografı́a se incluye en el apéndice A.
Es importante precisar la función concreta de cada uno de los terminales para poder
trabajar adecuadamente con la placa de BER; a continuación los enumeramos y damos
una descripción de los mismos.

TCLK Transmission Clock. Reloj de transmisión con un margen de frecuencias váli-


das desde 0 hasta 52 MHz. No tiene porqué tener un factor de forma del 50 %, ni
tampoco necesita ser isócrono.
5.3 Diseño hardware de la placa BER 137

Figura 5.7: Entrada y salida de señales en la placa de BER

Es usual en medidas de test prácticas que las secuencias de prueba estén sincroni-
zadas con el resto del sistema. Pensando en esta razón no se incluyó un oscilador
interno que aplicado a este pin permitiera al diseño funcionar independientemente.
Ahora pensamos que no hubiese estado de más incluirlo, aunque sólo hubiera sido
un zócalo para insertar el cristal a la frecuencia necesaria. Sólo se pensó en que para
cualquier aplicación que se utilizara, se necesitarı́a ese sincronismo que obligarı́a a
la generación del reloj de transmisión en el circuito a probar.
Ello nos plantea la necesidad de suministrar la señal de reloj de transmisión desde el
exterior en cualquier tipo de prueba. Con todo, no creemos que sea una desventaja
muy significativa. Siempre se puede utilizar cualquier fuente de señal TTL que actúe
de reloj de transmisión.
TDAT Transmit Data. Hilo de transmisión donde aparece la secuencia generada en
forma de trama de datos serie NRZ (unipolar no retorno a cero). Los datos tienen
sus transiciones en el flanco de subida de TCLK.
TDIS Transmit Disable. A nivel alto deshabilita el reloj de transmisión, por lo que
la secuencia de salida en el pin TDAT se detiene. A nivel bajo permite que la señal
de reloj de bit que llega por TCLK alcance la circuiterı́a de transmisión y ası́ pueda
continuar la secuencia de salida.
Este terminal es útil para aplicaciones donde se necesite que la secuencia de test se
transmita en modo de ráfagas (burst).

Continuamos con la parte de recepción.

RCLK Receive Clock. Reloj de recepción con el mismo margen operativo que el de
transmisión. Es totalmente independiente del reloj de transmisión pero tiene sus
mismas caracterı́sticas en lo que se refiere a factor de forma y sincronismo.
En este caso sı́ que no ocurre como en el parte de transmisión. Aquı́ sı́ que es forzoso
el suministro de la señal de reloj desde el exterior.
RDAT Receive Data. Hilo de recepción donde se muestrean los datos recibidos en el
flanco de subida de RCLK. Los datos han de recibirse en formato NRZ como en el
caso de su homólogo de transmisión.
5.4 Software de control 138

RDIS Receive Disable. A nivel alto impide que los datos recibidos en RDAT se
muestreen. A nivel bajo permite que la señal de reloj de bit recibida entre en la
circuiterı́a interna permitiendo que funcione el bloque de recepción.
Es el terminal dual de TDIS, útil también en aplicaciones en modo burst.

5.3.2.6. Alimentación

Figura 5.8: Regulador de alimentación de la placa de BER

El módulo de alimentación está constituido simplemente por un regulador 78LS05


que baja la tensión de alimentación exterior de 12 voltios a la tensión nominal TTL de 5.
Por destacar alguna caracterı́stica en particular, se incluye una inductancia de protección
EMI.

5.4. Software de control

La aplicación de control de la placa de BER está constituida por dos ficheros fuente.
Al igual que en la placa DDS, se han separado por un lado las tareas relacionadas directa-
mente con el hardware particular del diseño, y por otro lo que tiene que ver con el entorno
gráfico de usuario y la medida de tasas de bits erróneos.
Del fichero principal ber.c comentaremos únicamente la función bucle, que es una
función lanzada por el temporizador automático de Labwindows cada intervalo de 1 se-
gundo, y es la encargada de realizar todos los cálculos a la hora de ejecutar una prueba
de medida de tasa de error de bit. Para ello utiliza los servicios que prestan las funciones
de bajo nivel contenidas en el otro fichero fuente ber hard.c. También se encarga de la
presentación de los resultados en pantalla.
El fichero auxiliar de funciones hardware ber hard.c es el encargado de canalizar las
instrucciones de control por el puerto paralelo hacia los registros de la placa de BER,
cargando los datos precisos en función de los comandos enviados desde el módulo princi-
pal. En este caso, podemos comentar el funcionamiento de las instrucciones particulares
de lectura y escritura de datos en la placa de BER lee par bert y escribe par bert,
ası́ como la función aplicacion bert, que es la encargada de informar al módulo prin-
cipal del estado de sincronismo de la placa. El resto de las funciones resultan un poco
tediosas puesto que se trata únicamente de funciones reiterativas, cuyo trabajo consiste en
ir enviando el grupo de valores concretos a los registros determinados dependiendo de la
5.4 Software de control 139

Figura 5.9: Entorno gráfico de la aplicación de control mediBER

función en particular de que se trate, y la verdad, su exposición no aporta mucho, puesto


que son códigos que aparecen en las hojas del fabricante.
En el apéndice C se presentan los listados completos de la aplicación mediBER.

5.4.1. Módulo principal ber.c


Este es, sobre todo, el módulo de la presentación gráfica de usuario. Aquı́ es donde
se soportan de forma sencilla todas las funciones activadas con el ratón desde la ventana
de la aplicación. De lo depurado de este módulo depende lo aparente de la presentación.
Aquı́ se ha intentado presentar un frontal de un equipo virtual de medida de BER, pero
también intentando sacar el máximo de provecho a las prestaciones que nos ofrece el
montaje práctico. Su aspecto se presenta en la figura 5.9.
También se han trabajado los cálculos que mantienen una presentación actualizada
del máximo número de parámetros de interés mientras se realizan las medidas de BER.
La función responsable de estos cálculos es la función bucle.

5.4.1.1. Función principal bucle


Esta función se considera como la principal de la aplicación porque es la encargada
de realizar los cálculos de tasa de BER en caso de estar activadas las medidas. La verdad
es que si no se activa la prueba de BER, la función no hace gran cosa, y se limita a buscar
en el puerto paralelo del PC la conexión correcta de la placa, informando al usuario en
caso contrario y deshabilitando los controles principales de la ventana de la aplicación.
El nombre de la función viene motivado porque está asociada a una temporización
automática en Labwindows que la ejecuta automáticamente cada segundo.
Si suponemos que se está realizando una prueba de BER, bien porque realmente
estemos interesados en realizarla, o como puede darse el caso, si lo que queremos es que el
circuito se ponga a transmitir datos pseudoaleatorios, es entonces cuando la función bucle
realiza su trabajo más importante.
5.4 Software de control 140

Lo primero que hace la función es leer el registro de estado y los registros contadores
de bits recibidos y de errores detectados por el medidor de BER. Para ello llama a la función
aplicación bert que comentaremos en el apartado siguiente. Como esta actualización se
realiza periódicamente, podemos conocer con una demora de un segundo el estado en
tiempo real del medidor de tasas de error DS2172. El resultado de esta consulta será:

Información actualizada sobre el estado de sincronismo del circuito.

Actualización de los valores que se necesitan para calcular la tasa de BER instantánea
del segundo transcurrido desde la última ejecución de esta función.

A renglón seguido y disponiendo de la tasa de BER instantánea se determina si el


segundo que acaba de finalizar ha sido un segundo severamente erróneo, ses instantáneo,
ó simplemente un segundo con errores, es instantáneo. Estos valores se almacenan en una
especie de buffer dinámico donde se guardan los resultados de los últimos diez segundos a
modo de memoria FIFO, con lo que siempre se tiene actualizado el contenido de los diez
segundos más recientes. El objetivo es detectar el paso de disponibilidad a no disponibili-
dad, y eso ocurre según la recomendación G.821 cuando se producen diez o más segundos
seguidos con alarma o con una tasa de error peor de 10−3 . Al contrario sucede cuando
se dan diez segundos seguidos sin alarmas y con una tasa de error mejor de 10−3 . Estos
enunciados dados por la UIT se vieron ya en el capı́tulo 3.
Después de realizarse el análisis global de los últimos diez segundos, se determina
el paso a situación de disponibilidad, ó por el contrario a la de no disponibilidad.
En caso de que se produzcan transiciones de una situación a la opuesta, se deben de
añadir/descontar según proceda, los valores de bits recibidos y errores detectados corres-
pondientes a estos diez segundos.
Estando en situación de disponibilidad se mantiene además otro buffer, en este caso
con los valores correspondiente a los sesenta segundos últimos excluyendo aquellos en
los que se produjeron errores severos: Vemos en este caso que no tienen por qué ser los
últimos sesenta los segundos que estén almacenados. Los valores de bits recibidos y errores
detectados se almacenan en ese caso para determinar el porcentaje de minutos degradados,
donde lo que se debe de calcular es la tasa de error en bloques de sesenta segundos en
tiempo de disponibilidad excluyendo los segundos severamente erróneos, ver la sección 3.1.
Obviamente no pueden dejarse de actualizar los valores de bits recibidos y bits
erróneos totales durante el tiempo de disponibilidad del test, ya que son los parámetros
principales que nos determinarán la tasa de BER final de la prueba.
También se lleva el control sobre el tiempo de duración del test y el tiempo de
disponibilidad, imprescindibles el primero para saber cuándo debe de terminar la prueba,
y el segundo necesario en el cálculo de las tasas globales de BER.
El trabajo de esta función termina manteniendo actualizados los indicadores corres-
pondientes de la ventana principal de la aplicación.

5.4.2. Módulo de funciones hardware ber hard.c


Las funciones más importantes de este módulo utilizan los servicios de la función
de más bajo nivel en la aplicación, la función carga pp. Es una función común a las dos
aplicaciones, y en ella se adapta el protocolo y los niveles del puerto paralelo al hardware
particular con que se han desarrollado las interfaces de las dos placas. Su función es
5.4 Software de control 141

escribir en la dirección que se le determine el valor pasado como entrada. Para ello genera
la temporización adecuada en las lı́neas de control y datos del puerto paralelo.
En su trabajo, esta función utiliza la librerı́a externa dlportbc.lib que permite el
acceso directo a los puertos de entrada-salida del PC sorteando la barrera de protección
que impone Windows NT para acceder al hardware. La instrucciones más importantes
utilizadas de esta librerı́a son DlPortReadPortUchar(dirección io) y DlPortWrite-
PortUchar(dirección io, byte que se escribe). A partir de estas dos se ha creado la
función base carga pp.

5.4.2.1. Función lee par bert


Esta función es la encargada de leer datos desde la placa de BER. Dicho ası́ parece
que debe de ser una función simple de muy bajo nivel; sin embargo, dado que la construc-
ción hardware de dicha placa es bastante peculiar, resulta un poco complicada pues se han
tenido en cuenta todas las variantes operativas. Recordemos que la placa tiene un bus de
datos interno paralelo bidireccional, separado del puerto paralelo por un buffer de datos.
Se dan por tanto dos posibilidades de funcionamiento dependiendo de la variable de
entrada dir:

1. Lectura del dato que se acaba de escribir en la placa desde el puerto paralelo. Es decir,
se puede acceder, porque nos interese en un momento determinado, al bus interno
de la placa para comprobar o leer el dato que acabamos de escribir en él utilizando
una función de escritura. Es el caso de una función que se ejecuta periódicamente
para comprobar la correcta conexión de la tarjeta al puerto.

2. Lectura de datos puestos en el bus interno de la placa al leer desde los registros
internos del circuito DS2172. Ésta es la utilización corriente de la función.

En este segundo caso, la función realiza automáticamente una lectura secuencial si


lo que se quiere es acceder a un conjunto grande de registros del generador de BER. El
gobierno de esta caracterı́stica lo proporcionan las variables de entrada reg ini y nro reg.
Probablemente ya se habrá intuido la función de cada uno de ellas:

reg ini es la dirección hardware del primer registro del cual se desea leer el contenido.

nro reg es un ı́ndice que controla el número de registros que se leen en las direcciones
siguientes a la indicada por la variable reg ini.

Si la opción de operación que se seleccionó fue la de lectura simple del bus interno
(la opción primera), no tiene sentido el contenido de estas dos variables.
La función almacena el resultado en el array global de caracteres reservado al efecto
control bert[nro registro]. El propósito es disponer de un “reflejo” en la memoria de
la aplicación que contenga los contenidos de los registros hardware. Aquı́ acceden las
funciones de alto nivel cuando necesitan conocer estos contenidos.
Recordemos también que la lectura de los datos desde el circuito BER, se realiza en
este caso nibble a nibble, dado que tenemos 4 hilos de lectura de datos hacia el PC. El
hardware del buffer de datos se encarga de multiplexar el bus interno de 8 bits hacia estos
4 hilos del puerto paralelo, y es entonces esta función la que se encarga de ir enviando a la
placa BER los comandos de control necesarios para canalizar el flujo de información hacia
el PC.
5.4 Software de control 142

5.4.2.2. Función escribe par bert


En este caso no se dan las dos posibilidades anteriores, puesto que para escribir
directamente sobre el bus interno se utiliza la función carga pp en su utilidad básica. El
trabajo de la función que nos ocupa, por tanto, es el dual del realizado generalmente por
la función lee par bert, y cuya descripción acabamos de terminar.
Nos referimos a la carga de datos desde las aplicaciones de alto nivel a los registros
hardware internos del circuito DS2172. Para ello se utiliza la memoria reservada al efecto
en forma de array global control bert[nro registro]. Si una aplicación quiere programar
algún parámetro determinado del medidor de BER, lo que hace es escribir el dato en esta
memoria y llamar a la función escribe par bert que se encarga del resto.
Tendremos entonces los parámetros de entrada reg ini y nro reg, que le indican
a la función desde donde empezar a copiar y cuántas veces tiene que reiterar el bucle de
copiado.
Faltarı́a por recordar que durante las escrituras y lecturas en el circuito DS2172,
estas dos funciones han de ejecutar la secuencia de activación de señales de control según
el protocolo de Intel seleccionado arbitrariamente al construir la placa de BER.

5.4.2.3. Función aplicacion bert


Mediante esta función se informa a la aplicación principal del estado operativo del
circuito DS2172. ¿Qué queremos decir con esto? Esto quiere decir que la función se encarga
de leer el registro de estado y la máscara de interrupciones del integrado (aunque no se
emplee en nuestra aplicación es necesario limpiarla periódicamente), para detectar el estado
de operación en que se encuentra e informar a la aplicación de usuario. La función analiza
los valores obtenidos y como resultado decide si el medidor de BER está sincronizado o
no. El medidor de BER estará sincronizado cuando la secuencia que está transmitiendo y
la que recibe coinciden.
El registro de estado se almacena en un parámetro de entrada a la función pasado
por referencia que se llama t datos *ptd. El tipo t datos es la estructura siguiente:
struct datos {
char todo_1, todo_0, busca_sincro, error_dec, con_ovf, con_err_ovf, sincro;
double bits_rx, bits_err;
};

Aquı́ se almacena también la cuenta de bits recibidos y número de bits erróneos. Vemos
que se ha reservado un lugar especial a cada uno de los bits del registro de estado:

todo 1: Activo cuando la secuencia que se recibe es siempre 1.

todo 0: Activo cuando la secuencia que se recibe es siempre 0.

busca sincro: Se activa cada vez que el integrado pierde el sincronismo.

error dec: Se activa cuando se detectan errores estando sincronizado.

con ovf: Indica desbordamiento en el contador de bits recibidos.

con err ovf: Indica desbordamiento en el contador de errores.

sincro: Estado del sincronizador. Se activa cuando se reciben las secuencias continuas
de 1 ó 0.
5.5 Resultados prácticos 143

A consecuencia de esta “desviación” de lo que uno puede entender como estar sin-
cronizado, fue preciso añadirle a esta función otro parámetro más de entrada, secuencia,
que no es ni mas ni menos que el código de secuencia seleccionada en la aplicación de
control. De este modo se puede decidir de manera fiable sobre el estado de sincronismo
del circuito. En este sentido, la verdad es que la función se acerca bastante a la aplicación
de usuario.
La función considera que el circuito está sincronizado en los siguientes casos:

1. El integrado informa que está sincronizado y no se están recibiendo ceros continuos


ni unos continuos.
2. Se reciben ceros constantemente y se ha seleccionado como secuencia de prueba la
de “todo ceros”.
3. Se reciben unos constantemente y se ha seleccionado como secuencia de prueba la
de “todo unos”.

Además de informar a la aplicación de usuario del estado de sincronismo, la función


accede a los contadores de bits recibidos y errores detectados para actualizar su contenido
en la memoria de la aplicación. También resetea los contadores evitando ası́ su desborda-
miento. Estos valores son clave en caso de existir sincronización, puesto que son los que se
utilizan para calcular la tasa de error en la aplicación de usuario. Los valores adquiridos
se guardan en este caso en las variables bits rx y bits err del parámetro t datos *ptd de
entrada, donde quedan accesibles a la aplicación principal.

5.5. Resultados prácticos

Para finalizar con el capı́tulo, en esta sección se presenta un ejemplo donde se mues-
tran los resultados prácticos de funcionamiento individual de la placa de BER. Recordemos
que el sistema puede trabajar de forma independiente con la ya comentada restricción de la
necesidad de fuentes externas de reloj. Para emular este caso, las medidas se han realizado
simulando una prueba real.

Figura 5.10: Conexión de la placa de BER para la simulación de una medida


práctica de tasa de error

Para preparar la prueba se ha puenteado el terminal de salida de datos con el de


recepción, (es decir, se ha realizado un bucle local hardware), y como reloj de transmisión
5.6 Mejoras futuras 144

y recepción se ha utilizado el reloj de bit generado en la placa DDS. Esta situación se


asemeja en gran medida al conexionado necesario para el uso normal del montaje, puesto
que para trabajar conjuntamente con la placa DDS se precisa el concurso del reloj de bit
generado en la misma. Es la parte de recepción la que se ha simulado con el bucle local al
no disponerse de demodulador digital con el que poder “recibir” la señal de FI (frecuencia
intermedia) creada por la placa DDS.
En la figura 5.11, podemos observar las capturas obtenidas con el osciloscopio para
los dos modos de trabajo de la placa de BER.
Para poder guardar los resultados de la prueba que se esté realizando, la aplicación
permite generar un fichero de texto con los resultados. Los datos que incluye este fichero
se van a ver a continuación, y podemos decir que lo que contienen principalmente es lo
que se puede ver en la pantalla principal. Un ejemplo de fichero de resultados serı́a el que
se generó al final del test en la figura 5.9:

RESULTADOS DE LA PRUEBA DE MEDIDA DE TASA DE BER

Fecha del test (mes-dı́a-a~


no): 09-05-2000
Hora del test: 21:26:47

Tipo de secuencia utilizada: 2^21 - 1


Tiempo de duración programada del test: 5 min
Inserción de errores automáticos: Ninguno

Secuencia de usuario programada: 8CEF0FF0


Errores insertados manualmente: 1

Tiempo de duración real del test: 0d 0h 5m 0s


Tiempo de disponibilidad durante test: 0d 0h 5m 0s
Número total de bits recibidos: 4048702109
Número total de bits erróneos: 1316

Número de segundos erróneos (ES): 6.60


% de segundos erróneos (ES): 2.20 %
Número de segundos severamente erróneos (SES): 0
% de segundos severamente erróneos (SES): 0.00 %
Número de minutos degradados (DM): 1
% de minutos degradados (DM): 20.00 %

Tasa de bits erróneos (BER): 3.2504e-07

5.6. Mejoras futuras

Como siempre se suele decir, una aplicación nunca está totalmente terminada, pues
seguro que se puede mejorar en un sentido u otro. En este caso podrı́amos acometer estas
mejoras tanto a nivel hardware como de programa de control, puesto que las aplicaciones
y posibilidades del sistema son muy amplias.
En cualquier caso, para competir con los dispositivos comerciales en el mercado se
deberı́a aumentar la flexibilidad del sistema, pues aunque puede parecer que las presta-
ciones son bastante amplias, los equipos comerciales tienen alguna prestación añadida que
les hacen ganar en utilidad.
Por comentar algunas, se podrı́an enumerar las siguientes:
Generador de reloj interno. Esto hace que el equipo se pueda utilizar por sı́ solo, en
vez de necesitar una fuente de reloj externa.
5.6 Mejoras futuras 145

(a)

(b)

Figura 5.11: Diagramas de señal para diversos tipos de secuencias generadas


en la placa de BER
(a) Ejemplo de secuencia pseudoaleatoria
(b) Ejemplo de secuencia repetitiva.
5.6 Mejoras futuras 146

Incluir el divisor de reloj y mejorarlo. Nos referimos al generador de reloj de bit que
en nuestro diseño se ha implementado dentro de la placa DDS. A su vez, mejorarlo
para que permita no sólo la generación de secuencias en modo continuo, sino que,
aprovechando los hilos de control de los bloques de transmisión y recepción del
DS2172, también se puedan generar secuencias aleatorias en modo ráfaga.
Esta pequeña modificación del sistema permitirı́a, por ejemplo, la realización de
medidas de BER en un único slot de tiempo de una trama digital de 2.048 Mbps de
la jerarquı́a primaria europea, (se las denomina tramas E1 en la literatura técnica).

Por último, como posible mejora del programa de control mediBER, podrı́a pro-
ponerse la configuración exterior mediante fichero y la grabación automática de la
última configuración antes de abandonar el programa. En este caso, no se perderı́an
los datos de configuración de la última prueba realizada.
Apéndice A

El puerto paralelo del PC

Dado que el método de control utilizado para gobernar todo el sistema es el puerto
paralelo del PC, se realiza a continuación una breve introducción al mismo, con el objetivo
de conocer su funcionamiento y los registros de que consta, pues serán importantes a la
hora de confeccionar las aplicaciones de control.

A.1. Generalidades
El puerto paralelo del PC se conoce normalmente con el nombre de Centronics 1 .
Aunque la idea para la que se concibió originalmente fue la de comunicación con la im-
presora, las evoluciones posteriores del citado bus han ampliado su rango de aplicación,
y actualmente el puerto paralelo es un puerto ampliamente usado como interfaz de todo
tipo de periféricos como scaners de sobremesa, dispositivos de backup, grabadoras de CD
externas, etc.
El puerto está compuesto de 4 lı́neas de control, 5 lı́neas de estado y 8 lı́neas de datos.
Se encuentra normalmente en la parte trasera del PC con un tipo de conector hembra D25.
Aunque también puede existir otro conector D25 macho, éste será un puerto serie RS-232
y por tanto, es totalmente incompatible con el primero. La tendencia actual es la de usar
conectores D9 macho para los puertos serie, por lo que resulta difı́cil la confusión.
Como consecuencia de la evolución en el puerto paralelo se hizo necesaria una estan-
darización del mismo, y ası́ se publicó la norma IEEE 1284 del año 1994, donde se definen
5 modos de operación, que son los siguientes:

1. Modo compatible

2. Modo nibble (un nibble es medio byte, 4 bits)

3. Modo byte.

4. Modo mejorado, EPP (Enhanced Paralell Port)

5. Modo extendido, ECP (Extended Capabilities Port)

El objetivo era desarrollar drivers y dispositivos nuevos que fueran compatibles entre
ellos y también hacia atrás con el Puerto Paralelo Estándar (Standart Paralell Port). Los
modos compatible, nibble y byte utilizan el hardware estándar disponible en las tarjetas de
1
Centronics era el nombre de un fabricante de impresoras

147
A.1 Generalidades 148

puerto paralelo original, mientras que los modos EPP y ECP requieren hardware especı́fico
que pueda correr a velocidades más rápidas, siendo también compatibles hacia atrás con
el Puerto Paralelo Estándar SPP.
El modo compatible o “modo Centronics”, como se conoce normalmente, se di-
señó para enviar datos en dirección de salida a una velocidad tı́pica de 50 Kbytes por
segundo, pudiendo llegar hasta los 150 Kbytes. Para recibir datos, se debe cambiar a
modo nibble o modo byte. El modo nibble puede leer un nibble (4 bits) en la dirección
inversa, es decir desde el periférico hacia el ordenador. El modo byte utiliza la caracterı́sti-
ca que sólo se encuentra en las tarjetas más modernas en las que el puerto paralelo es
bidireccional, de manera que se puede leer directamente un byte en la dirección inversa.

(a) (b)

Figura A.1: Conexionado externo para lectura de datos en el puerto paralelo


del PC
(a) Conexión externa para lectura de datos en modo nibble
(b) Conexión externa para lectura de datos en modo compatible.

Los otros dos modos mas avanzados, EPP y ECP, utilizan hardware adicional para
generar y gestionar el protocolo de intercambio de comandos entre el PC y los periféricos
conectados. Normalmente para enviar un byte a una impresora u otro dispositivo en el
modo compatible, el software debe:

1. Escribir el dato en el puerto.

2. Comprobar si la impresora está ocupada. Si la impresora está ocupada, ésta no


aceptará ningún dato y por tanto, cualquier dato escrito en el puerto se perderı́a.

3. Activar el hilo de Strobe (hilo 1) a nivel bajo. Esto le indica a la impresora que hay
un dato correcto en las lı́neas de datos. (hilos 2-9).

4. Poner la lı́nea de Strobe en alto después de esperar aproximadamente 5 microsegun-


dos tras haber puesto la lı́nea de Strobe a bajo. Esto limita la velocidad a la que el
puerto puede funcionar.

Los puertos EPP y ECP solventan esta limitación dejando al hardware chequear y
ver si la impresora está ocupada, generar el strobe y realizar el resto de operaciones de
A.2 Propiedades de la interfaz fı́sica 149

intercambio de protocolo adecuado, incrementando de ese modo la velocidad de transfe-


rencia. Estos puertos pueden funcionar a unas velocidades entre 1 y 2 Mbytes por segundo.
El puerto ECP también tiene la ventaja de utilizar canales DMA y buffers de tipo FIFO,
con lo cual los datos se pueden enviar y recibir sin utilizar instrucciones de entrada/salida.

A.2. Propiedades de la interfaz fı́sica


En la tabla A.1 se representan los hilos del conector tipo D25 y del conector de
34 pines Centronics. El conector D25 es el conector más común en el puerto paralelo del
ordenador, mientras que el conector Centronics es el que tienen todas las impresoras. El
estándar IEEE 1284 especifica tres tipos de conectores para utilizar en el puerto paralelo.
El primero, 1284 tipo A, es el conector D25 de la trasera de la mayorı́a de los ordenadores.
El segundo es el 1284 tipo B y es el conector Centronics que se encuentra en la mayorı́a
de las impresoras.
El IEEE 1284 tipo C, es un conector de 36 contactos como el Centronics, pero
más pequeño. Se dice de este conector que tiene mejor enganche, mejores caracterı́sticas
eléctricas y más facilidad de montaje. Tiene dos pines más que se pueden utilizar para ver
si el otro dispositivo conectado tiene alimentación. Este nuevo conector se recomienda para
nuevos diseños, y será cuestión de esperar un tiempo para observar su grado de aceptación
por parte de los fabricantes.

DB 25 Centronics Señal SPP Dirección Registro Inv. Hardware 2

1 1 #Strobe 3 Ent/Sal Control Si


2 2 Datos 0 Salida Datos
3 3 Datos 1 Salida Datos
4 4 Datos 2 Salida Datos
5 5 Datos 3 Salida Datos
6 6 Datos 4 Salida Datos
7 7 Datos 5 Salida Datos
8 8 Datos 6 Salida Datos
9 9 Datos 7 Salida Datos
10 10 #Ack Entrada Estado
11 11 Busy Entrada Estado Si
12 12 Paper Out Entrada Estado
13 13 Select Entrada Estado
14 14 #Auto Line Feed Ent/Sal Control Si
15 32 #Error Entrada Estado
16 31 #Initialize Ent/Sal Control
17 36 #Select Printer Ent/Sal Control Si
18-25 19-30 Ground Gnd

Cuadro A.1: Hilos del puerto paralelo del PC


A.3 Direcciones del puerto paralelo 150

A.3. Direcciones del puerto paralelo


El puerto paralelo utiliza normalmente tres direcciones. La dirección base 3BCh
se introdujo originalmente para puertos paralelo incorporados en las primeras tarjetas de
vı́deo. Posteriormente desapareció cuando se separaron los circuitos hardware. Actualmen-
te ha vuelto a aparecer como opción en los puertos paralelo integrados en las placas madre
de los PC, en las que se puede cambiar su configuración a través de la BIOS.
Normalmente LPT1 está asignado a la dirección base 378h, mientras que LPT2
está asignado a la 278h. Sin embargo este puede no ser siempre el caso. Cuando el or-
denador arranca, la BIOS (Basic Input/Output System) determina el número de puertos
disponibles y les asigna los nombres LPT1, LPT2 . . . La BIOS busca en primer lugar en la
dirección 3BCh. Si ahı́ encuentra un puerto paralelo le asignará el nombre LPT1, y después
busca en la posición 378h. Si también ahı́ encuentra otro puerto paralelo le asignará el
siguiente nombre en la secuencia. Este nombre será LPT1 si no se encontró nada en 3BCh,
o LPT2 si ya se encontró un puerto en la primera posición. Por último, la BIOS busca
otro puerto paralelo en la dirección 278h siguiendo el mismo procedimiento anterior. Por
lo tanto, es posible tener un LPT2 que esté situado en la posición de memoria 378h y no
en la 278h como se podrı́a esperar en un primer momento.
Todavı́a se puede dar una situación aún mas confusa, puesto que hay placas con
puertos paralelo con direcciones seleccionables mediante puentes que permiten configurar-
los como LPT1, LPT2, o LPT3. Entonces, ¿cuál es la dirección de LPT1? Normalmente,
LPT1 es la 378h, y LPT2 está en la dirección 278h. En cualquier caso, si se quiere saber en
qué dirección de entrada-salida tiene situados la BIOS los puertos paralelo LPT1, LPT2,
etc, existe una tabla donde se almacena su dirección, esta vez en posiciones especı́ficas de
la memoria. Estos datos se recogen en la tabla A.2.

Dirección Inicial Función


0000:0408 Dirección base de LPT1
0000:040A Dirección base de LPT2
0000:040C Dirección base de LPT3
0000:040E Dirección base de LPT4 4

Cuadro A.2: Posiciones de la BIOS que almacenan las direcciones de I/O de LPTs

A.4. Registros software


En la tabla A.3 se representa el puerto o registro de datos. La dirección base se utiliza
para obtener datos de las lı́neas de datos del puerto paralelo (hilos 2-9). Este registro es
normalmente un registro de sólo escritura. Si se lee el registro, se deberá obtener el último
dato enviado. Sin embargo, los nuevos diseños hardware consiguen que este puerto sea
bidireccional, pudiéndose recibir datos en dirección de entrada al PC.
2
Inversión realizada por el hardware
3
# Indica señal activa a nivel bajo
4
La dirección 0000:040E del área de datos de las BIOS puede ser usada como área de datos de Bios
extendida en las nuevas Bios
A.4 Registros software 151

El puerto de estado (dirección base +1), es un puerto de sólo lectura. Cualquier


dato que se escriba en este puerto será ignorado. El puerto de estado consta de 5 lı́neas
de entrada (hilos 10, 11, 12, 13 y 15), un bit de IRQ del registro de estado, y dos bits
reservados. Obsérvese que el bit 7 (Busy) tiene inversión hardware. Esto quiere decir que
si se lee un cero, entonces existe un nivel lógico alto de +5v en el pin 11. El bit #IRQ es
activo a nivel bajo. Por tanto, si se lee un 1, entonces no ha ocurrido una interrupción.

Offset Nombre Dirección Bit # Propiedades


Base + 0 Puerto de Datos Escritura 5 Bit 7 Datos 7
Bit 6 Datos 6
Bit 5 Datos 5
Bit 4 Datos 4
Bit 3 Datos 3
Bit 2 Datos 2
Bit 1 Datos 1
Bit 0 Datos 0

Cuadro A.3: Puerto de datos

Offset Nombre Dirección Bit # Propiedades


Base + 1 Puerto de Estado Lectura Bit 7 Busy
Bit 6 #Ack
Bit 5 Paper Out
Bit 4 Select In
Bit 3 Error
Bit 2 IRQ (Inv. Hard.)
Bit 1 Reservado
Bit 0 Reservado

Cuadro A.4: Puerto de estado

El puerto de control (dirección base + 2) es un puerto pensado para ser utilizado


como de sólo escritura. Sin embargo, sı́ que se puede utilizar como entrada. El hardware
de salida de estos pines utiliza lógica en “open colector”, y la mayorı́a de las tarjetas con
puertos paralelo llevan integradas las resistencias de pull-up. No obstante, es una buena
medida añadir resistencias externas para asegurarnos del buen funcionamiento del puerto.
Los puertos paralelo bidireccionales utilizan el pin 5 del puerto de control para
habilitar-inhabilitar los drivers de salida. Un posible esquema se muestra en la figura A.2.
Cuando este bit se pone a uno, los pines 2 a 9 cambian a estado de alta impedancia.
Una vez en este estado, se pueden leer datos de estas lı́neas y recuperarlas en el registro
de datos (dirección base). En estas condiciones, cualquier dato escrito en el puerto de
5
Si el puerto es bidireccional, entonces se pueden realizar operaciones de lectura y escritura en el puerto
de datos
A.4 Registros software 152

Offset Nombre Dirección Bit # Propiedades


Base + 2 Puerto de Control Lec/Escr Bit 7 Sin uso
Bit 6 Sin uso
Bit 5 Ena. bidir. port
Bit 4 Ena. IRQ via ACK
Bit 3 #Select Printer
Bit 2 #Initialize
Bit 1 #Auto Linefeed
Bit 0 #Strobe

Cuadro A.5: Puerto de control

datos será almacenado, pero no estará disponible en los pines de salida. Para inhabilitar
el modo bidireccional, se conecta el bit 5 del puerto de control a cero. Esta caracterı́stica
está únicamente disponible en los puertos bidireccionales.
Sin embargo, no todos los puertos paralelo se comportan de la misma manera. Otros
puertos pueden requerir la activación del bit 6 del puerto de control para habilitar el
modo bidireccional y el bit 5 para inhibirlo. Diferentes fabricantes implementan el puerto
paralelo de forma diferente. Si se quiere profundizar más sobre el funcionamiento del puerto
paralelo del PC, existen varias páginas en internet con bastante información al respecto
[?].

Figura A.2: Hardware interno del PC en puertos bidireccionales


A.5 Utilización particular en la aplicación 153

A.5. Utilización particular en la aplicación


Precisamente para no tener problemas de compatibilidad en la interface de nuestra
aplicación, se decidió utilizar el puerto paralelo en el modo estándar. En este modo, las
ocho lı́neas del bus de datos se emplean en modo escritura para colocar los datos de salida
del PC, el puerto de estado en modo lectura para la adquisición de datos desde el exterior,
y los terminales del puerto de control en modo de salida para demultiplexar los datos que
se escriban en el bus. En la tabla A.6 se resumen las conexiones del puerto paralelo en
nuestro sistema.

Pin DB-25 Señal SPP Original Aplicación Sentido Registro Inv. Hardware 6

2 Datos 0 Datos 0 Salida Datos


3 Datos 1 Datos 1 Salida Datos
4 Datos 2 Datos 2 Salida Datos
5 Datos 3 Datos 3 Salida Datos
6 Datos 4 Datos 4 Salida Datos
7 Datos 5 Datos 5 Salida Datos
8 Datos 6 Datos 6 Salida Datos
9 Datos 7 Datos 7 Salida Datos
11 Busy OD7 Entrada Estado Si
10 #Ack OD6 Entrada Estado
12 Paper Out OD5 Entrada Estado
13 Select OD4 Entrada Estado
15 #Error OD3 Entrada Estado
17 #Select Printer LATCH3 Salida Control Si
16 #Inicialize LATCH2 Salida Control
14 #Auto Line Feed LATCH1 Salida Control Si
1 #Strobe 7 LATCH0 Salida Control Si
18-25 Ground Gnd Gnd

Cuadro A.6: Puerto paralelo en la aplicación

Los ocho hilos de datos constituyen el bus de salida desde el PC. En ellos se colocan
datos válidos que se cargarán en los diferentes registros de las placas de la aplicación. Los
hilos del registro de estado aquı́ los denominaremos como OD7 a OD3, y se utilizan para
la lectura de datos desde las tarjetas del montaje. Los hilos OD7 a OD4 se emplean en
la tarjeta de BER para leer los bytes nibble a nibble (de cuatro en cuatro bits). El hilo
OD3 se utiliza con la placa de modulación DDS, leyéndose desde esa tarjeta los datos de
entrada bit a bit. Esta selección no se ha hecho de forma caprichosa, sino que, como se
ha podido comprobar, ha venido impuesta por la construcción hardware de los integrados
utilizados en la práctica.
6
Invertida por el hardware
7
Señal activa a nivel bajo
A.5 Utilización particular en la aplicación 154

Para terminar, los hilos de control son cuatro, LATH3 a LATH0, y se emplean en
la carga y demultiplexación de los hilos de datos. LATCH3 y LATCH2 son los hilos de
selección de registro dentro de cada tarjeta. LATCH1 carga el contenido del bus de datos
en el registro seleccionado de la placa DDS, y LATCH0 realiza la misma función pero en
este caso con la tarjeta de BER. Estos dos últimos hilos realizan la función de terminales
de selección de tarjeta. En la figura A.3 se representa esquemáticamente la conexión del
puerto paralelo en nuestra aplicación.

Figura A.3: Utilización particular del puerto paralelo en nuestra aplicación


Apéndice B

Fotografı́as del montaje

Hasta aquı́ hemos hablado de la composición interna de las placas de modulación


DDS y de la placa BER de generación de secuencias pseudoaleatorias. Nos falta mostrar
el soporte necesario que hace que todo el conjunto sea manejable.
Ambos circuitos impresos se han montado conjuntamente en un chasis de aluminio
que se puede ver en la figura B.1 donde se han mecanizado todos los conectores de acceso
a los circuitos.
La figura B.2 es una vista interior. La placa DDS va montada sobre la placa de BER,
pero en la fotografı́a se ha colocado fuera para poder observar el aspecto de ambas.
También se ha indicado en las figuras B.3 y B.4 la función de los diferentes conectores
accesibles al usuario.

155
156

Figura B.1: Vista general del montaje que contiene las placas DDS y BER

Figura B.2: Vista interior donde se pueden distinguir las dos placas
157

Figura B.3: Lateral del chasis donde se pueden observar el conector de salida
de IF y los interfaces de datos de las dos placas

Pin Función Pin Función


1 Sin conexión 6 Entrada externa de habilitación
de transmisión
2 Entrada serie de datos 7 Sin conexión
3 Masa 8 Salida de reloj de bit interno
4 Entrada de OL externo 9 Masa
5 Masa 10 Salida de Reset

Cuadro B.1: Conector de interface de la placa DDS

Pin Función Pin Función


1 Entrada de datos Rx 6 Sin conexión
2 Salida de datos Tx 7 Entrada de reloj de recepción
3 Entrada de señal de inhabilitación 8 Entrada de reloj de transmisión
de recepción
4 Sin conexión 9 Masa
5 Entrada de señal de inhabilitación 10 Sin conexión
de transmisión

Cuadro B.2: Conector de interface de la placa BER


158

Figura B.4: Lateral del chasis que contiene los conectores de control y ali-
mentación

Pin DB-25 Señal SPP Original Aplicación Sentido Registro Inv. Hardware 1

2 Datos 0 Datos 0 Salida Datos


3 Datos 1 Datos 1 Salida Datos
4 Datos 2 Datos 2 Salida Datos
5 Datos 3 Datos 3 Salida Datos
6 Datos 4 Datos 4 Salida Datos
7 Datos 5 Datos 5 Salida Datos
8 Datos 6 Datos 6 Salida Datos
9 Datos 7 Datos 7 Salida Datos
11 Busy OD7 Entrada Estado Si
10 #Ack OD6 Entrada Estado
12 Paper Out OD5 Entrada Estado
13 Select OD4 Entrada Estado
15 #Error OD3 Entrada Estado
17 #Select Printer LATCH3 Salida Control Si
16 #Inicialize LATCH2 Salida Control
14 #Auto Line Feed LATCH1 Salida Control Si
1 #Strobe 2 LATCH0 Salida Control Si
18-25 Ground Gnd Gnd

Cuadro B.3: Pines del conector al puerto paralelo

Pin Función
Tip +12 voltios DC
Ring Masa

Cuadro B.4: Conector de alimentación


Apéndice C

Listados fuente

En este apartado se incluyen los listados fuentes de las dos aplicación de control
desarrolladas, modulAD para la placa de modulación DDS y mediBER para la placa de
BER, junto con los ficheros de comandos de Matlab utilizados en la simulación de los
distintos bloques del modulador DDS AD9853.

C.1. Aplicación modulAD


Ficheros mod.c y mod hard.c
/****************************************************************************
MODULO: Aplicacion principal de control de placa del MODULADOR AD9853
FICHERO: mod.c VERSION: 1.0
-----------------------------------------------------------------------------
AUTOR: Juan Luis jltebar@retemail.es
FECHA: Abril-2000
-----------------------------------------------------------------------------
DESCRIPCION:
****************************************************************************/
#include <cvirte.h> // Needed if linking in external compiler; harmless
//otherwise
#include <userint.h>
#include <formatio.h>
#include <ansi_c.h>
#include <utility.h>
#include "mod_def.h" // Defines para todo el proyecto
#include "mod.h" // Controles del panel
#include "dlportio.h" // Interfaz para acceder al hardware desde windows
#include "mod_hard.h" // Contiene las funciones hardware para programar
// la placa del modulador AD9853 mediante el puerto
// paralelo

//DEFINICIONES DE TIPOS
//DECLARACION DE FUNCIONES
void inicializa(int inic);

//VARIABLES GLOBALES
// Del módulo de funciones hardware
extern double esc, esc_old;

// Propias
// Gestion de paneles
static int panel_conf, panel_fir, panel_frec, panel_principal, panel_scr, panel_vel, err;
char puerto_control;

// caracteres reservados para el envı́o de parámetros a los registros del modem

159
C.1 Aplicación modulAD 160

unsigned char control_modem[74];


unsigned char inicio;

// registros del puerto paralelo


unsigned long pp_datos; //Normalmente sólo escritura
unsigned long pp_estado; //lectura
unsigned long pp_control; //lectura y escritura con lineas fı́sicas en "open colector"

// Bytes utilizados para la comunicación con el modulador. Se especifican como


// global al tenerlos que utilizar para la programación del generador de
// reloj de bit, ası́ como para controlar el modulador
unsigned char byte_bajo, byte_alto;

// Comprobación de la existencia fı́sica de la placa


char hay_placa_mod, primer_bucle;

int main (int argc, char *argv[]) {


/* Needed if linking in external compiler; harmless otherwise */
if (InitCVIRTE (0, argv, 0) == 0)
return -1; /* out of memory */

// Inicialización de las variables de control del modem


byte_bajo = 0x0;
byte_alto = 0xE8;

// Carga de paneles previa a la inicialización de variables


if ((panel_principal = LoadPanel (0, "mod.uir", PANEL_MOD)) < 0)
return -1;
if ((panel_conf = LoadPanel (0, "mod.uir", PANEL_CONF)) < 0)
return -1;
if ((panel_frec = LoadPanel (0, "mod.uir", PANEL_FREC)) < 0)
return -1;
if ((panel_vel = LoadPanel (0, "mod.uir", PANEL_VEL)) < 0)
return -1;
if ((panel_scr = LoadPanel (0, "mod.uir", PANEL_SCR)) < 0)
return -1;
if ((panel_fir = LoadPanel (0, "mod.uir", PANEL_FIR)) < 0)
return -1;

// Consideramos que la placa está correctamente conectada en principio


hay_placa_mod = SI;
primer_bucle = SI;

// Inicialización
inicio = SI;
// Utilizamos el puerto paralelo LPT1
puerto_control = 1;
inicializa(SI);
inicio = NO;

// Arranque de la presentación
DisplayPanel (panel_principal);
RunUserInterface ();

// Puerto paralelo a alta impedancia si es bidireccional


inicio=DlPortReadPortUchar(pp_control);
inicio = inicio | 0x20;
DlPortWritePortUchar(pp_control, inicio);

return 0;
}

/****************************************************************************
DESCRIPCION DE LAS FUNCIONES
****************************************************************************/
/****************************************************************************
FUNCION: inicializa
DESCRIPCION: Realiza la secuencia de inicialización de la aplicación
C.1 Aplicación modulAD 161

PARAMETROS DE ENTRADA:
PARAMETROS DE SALIDA:
RESULTADO Y ERRORES:
OBSERVACIONES:
****************************************************************************/
void inicializa(int inic) {
unsigned short byte;

// Selección del puerto paralelo de control


if (puerto_control==1) { //pp_datos==LPT1;
err = ReadFromPhysicalMemory (0x00000408, &pp_datos, 1);
err = ReadFromPhysicalMemory (0x00000409, &byte, 1);
byte= byte << 8;
pp_datos = pp_datos | byte;
}
else if (puerto_control==2) { //pp_datos==LPT2;
err = ReadFromPhysicalMemory (0x0000040A, &pp_datos, 1);
err = ReadFromPhysicalMemory (0x0000040B, &byte, 1);
byte= byte << 8;
pp_datos = pp_datos | byte;
}
else if (puerto_control==3) { //pp_datos==LPT3;
err = ReadFromPhysicalMemory (0x0000040C, &pp_datos, 1);
err = ReadFromPhysicalMemory (0x0000040D, &byte, 1);
byte= byte << 8;
pp_datos = pp_datos | byte;
}
else if (puerto_control==4) { //pp_datos==LPT4;
err = ReadFromPhysicalMemory (0x0000040E, &pp_datos, 1);
err = ReadFromPhysicalMemory (0x0000040F, &byte, 1);
byte= byte << 8;
pp_datos = pp_datos | byte;
}
pp_estado=pp_datos+1;
pp_control=pp_datos+2;

// Inicialización del puerto paralelo


// Modificación para funcionamiento con puertos bidireccionales
byte=0x0;
byte=DlPortReadPortUchar(pp_control);
byte = byte & 0xDF;
DlPortWritePortUchar(pp_control, byte);

byte=0x0;
DlPortWritePortUchar(pp_datos, byte);
byte=DlPortReadPortUchar(pp_estado);
byte=DlPortReadPortUchar(pp_control);
//byte=byte & 0xF0;
byte=byte & 0xD0;
byte=byte | 0x8;
DlPortWritePortUchar(pp_control, byte);

// Inicialización de variables
inicia_hard();
// Inicialización de parámetro de escalado en modulador
esc = 1;

// Programación del harware.


// Se sigue la secuencia de inicialización indicada en el manual del integrado
// AD9853 pag. 14
desactiva_txe();
reset_9853();
// Entorno y envı́o de comandos de programación al modem
PulsaMod (panel_principal, PANEL_MOD_PULSA_MOD, EVENT_COMMIT, 0, 0, 0);
TipoScrambler (panel_conf, PANEL_CONF_TIPO_SCRAMBLER, EVENT_COMMIT, 0, 0, 0);
SwitchSpectrum (panel_conf, PANEL_CONF_SWITCH_SPECTRUM, EVENT_COMMIT, 0, 0, 0);
if (inic) SwitchDac (panel_conf, PANEL_CONF_SWITCH_DAC, EVENT_COMMIT, 0, 0, 0);
// Esta incluye a las dos siguientes que se han anulado
C.1 Aplicación modulAD 162

ValorFrecRef (panel_conf, PANEL_CONF_VALOR_FREC_REF, EVENT_COMMIT, 0, 0, 0);


// ValorFrecMarca (panel_frec, PANEL_CONF_VALOR_FREC_MARCA, EVENT_COMMIT, 0, 0, 0);
// ValorFrec (panel_frec, PANEL_FREC_VALOR_FREC, EVENT_COMMIT, 0, 0, 0);
// La siguiente función anulada está incluı́da en PulsaMod
// PulsaCodDif (panel_scr, PANEL_SCR_PULSA_COD_DIF, EVENT_COMMIT, 0, 0, 0);
PulsaScr (panel_scr, PANEL_SCR_PULSA_SCR, EVENT_COMMIT, 0, 0, 0);
ValorDiv (panel_vel, PANEL_VEL_VALOR_DIV, EVENT_COMMIT, 0, 0, 0);
// El efecto de la siguiente en la inicialización se consigue con la anterior
// PulDiv2 (panel_vel, PANEL_VEL_PUL_DIV_2, EVENT_COMMIT, 0, 0, 0);
ValorFirA0(panel_fir, PANEL_FIR_VALOR_FIR_A0, EVENT_COMMIT, 0, 0, 0);
ValorFirA1(panel_fir, PANEL_FIR_VALOR_FIR_A1, EVENT_COMMIT, 0, 0, 0);
ValorFirA2(panel_fir, PANEL_FIR_VALOR_FIR_A2, EVENT_COMMIT, 0, 0, 0);
ValorFirA3(panel_fir, PANEL_FIR_VALOR_FIR_A3, EVENT_COMMIT, 0, 0, 0);
ValorFirA4(panel_fir, PANEL_FIR_VALOR_FIR_A4, EVENT_COMMIT, 0, 0, 0);
ValorFirA5(panel_fir, PANEL_FIR_VALOR_FIR_A5, EVENT_COMMIT, 0, 0, 0);
ValorFirA6(panel_fir, PANEL_FIR_VALOR_FIR_A6, EVENT_COMMIT, 0, 0, 0);
ValorFirA7(panel_fir, PANEL_FIR_VALOR_FIR_A7, EVENT_COMMIT, 0, 0, 0);
ValorFirA8(panel_fir, PANEL_FIR_VALOR_FIR_A8, EVENT_COMMIT, 0, 0, 0);
ValorFirA9(panel_fir, PANEL_FIR_VALOR_FIR_A9, EVENT_COMMIT, 0, 0, 0);
ValorFirA10(panel_fir, PANEL_FIR_VALOR_FIR_A10, EVENT_COMMIT, 0, 0, 0);
ValorFirA11(panel_fir, PANEL_FIR_VALOR_FIR_A11, EVENT_COMMIT, 0, 0, 0);
ValorFirA12(panel_fir, PANEL_FIR_VALOR_FIR_A12, EVENT_COMMIT, 0, 0, 0);
ValorFirA13(panel_fir, PANEL_FIR_VALOR_FIR_A13, EVENT_COMMIT, 0, 0, 0);
ValorFirA14(panel_fir, PANEL_FIR_VALOR_FIR_A14, EVENT_COMMIT, 0, 0, 0);
ValorFirA15(panel_fir, PANEL_FIR_VALOR_FIR_A15, EVENT_COMMIT, 0, 0, 0);
ValorFirA16(panel_fir, PANEL_FIR_VALOR_FIR_A16, EVENT_COMMIT, 0, 0, 0);
ValorFirA17(panel_fir, PANEL_FIR_VALOR_FIR_A17, EVENT_COMMIT, 0, 0, 0);
ValorFirA18(panel_fir, PANEL_FIR_VALOR_FIR_A18, EVENT_COMMIT, 0, 0, 0);
ValorFirA19(panel_fir, PANEL_FIR_VALOR_FIR_A19, EVENT_COMMIT, 0, 0, 0);
ValorFirA20(panel_fir, PANEL_FIR_VALOR_FIR_A20, EVENT_COMMIT, 0, 0, 0);
reset_9853();
prog_hard(CONF, 1);
reset_9853();
prog_hard(RS_k, 0x49); // Incluye CONF
prog_hard(GCB, 1);
// Se activa el funcionamiento
activa_txe();
}

/****************************************************************************
FUNCIONES CVICALLBACK
****************************************************************************/
/****************************************************************************
FUNCION: PulsaFrec
DESCRIPCION: Muestra el panel donde se programa la frecuencia de salida del
modulador
PARAMETROS DE ENTRADA: Los usuales en una función callback
PARAMETROS DE SALIDA:
RESULTADO Y ERRORES: Entero 0, todo OK
OBSERVACIONES:
****************************************************************************/
int CVICALLBACK PulsaFrec (int panel, int control, int event,
void *callbackData, int eventData1, int eventData2)
{
static char panel_visible;

switch (event) {
case EVENT_COMMIT:
if (panel_visible) {
HidePanel(panel_frec);
panel_visible = NO;
}
else {
DisplayPanel (panel_frec);
panel_visible = SI;
}
break;
C.1 Aplicación modulAD 163

case EVENT_RIGHT_CLICK:
break;
}
return 0;
}

/****************************************************************************
FUNCION: PulsaFec
DESCRIPCION: Muestra el panel donde se programan la habilitación o no del
aleatorizador y del codificador diferencial del modulador
PARAMETROS DE ENTRADA: Los usuales en una función callback
PARAMETROS DE SALIDA:
RESULTADO Y ERRORES: Entero 0, todo OK
OBSERVACIONES:
****************************************************************************/
int CVICALLBACK PulsaFec (int panel, int control, int event,
void *callbackData, int eventData1, int eventData2)
{
static char panel_visible;

switch (event) {
case EVENT_COMMIT:
if (panel_visible) {
HidePanel(panel_scr);
panel_visible = NO;
}
else {
DisplayPanel (panel_scr);
panel_visible = SI;
}
break;
case EVENT_RIGHT_CLICK:
break;
}
return 0;
}

/****************************************************************************
FUNCION: PulsaVel
DESCRIPCION: Muestra el panel donde se programa el reloj de bit
PARAMETROS DE ENTRADA: Los tı́picos de las funciones callback
PARAMETROS DE SALIDA:
RESULTADO Y ERRORES: Entero 0, todo OK
OBSERVACIONES:
****************************************************************************/
int CVICALLBACK PulsaVel (int panel, int control, int event,
void *callbackData, int eventData1, int eventData2)
{
static char panel_visible;

switch (event) {
case EVENT_COMMIT:
if (panel_visible) {
HidePanel(panel_vel);
panel_visible = NO;
}
else {
DisplayPanel (panel_vel);
panel_visible = SI;
}
break;
case EVENT_RIGHT_CLICK:
break;
}
return 0;
}

/****************************************************************************
C.1 Aplicación modulAD 164

FUNCION: PulsaFir
DESCRIPCION: Ense~
na la pantalla donde se programan los coeficientes del
filtro FIR integrado dentro del modulador
PARAMETROS DE ENTRADA: Es una función callback
PARAMETROS DE SALIDA:
RESULTADO Y ERRORES: Entero 0, todo OK
OBSERVACIONES:
****************************************************************************/
int CVICALLBACK PulsaFir (int panel, int control, int event,
void *callbackData, int eventData1, int eventData2)
{
static char panel_visible;

switch (event) {
case EVENT_COMMIT:
if (panel_visible) {
HidePanel(panel_fir);
panel_visible = NO;
}
else {
DisplayPanel (panel_fir);
panel_visible = SI;
}
break;
case EVENT_RIGHT_CLICK:
break;
}
return 0;
}

/****************************************************************************
FUNCION: PulsaConf
DESCRIPCION: Activa el panel donde se cambian otros parámetros de
configuración.
PARAMETROS DE ENTRADA: Los de las funciones callback
PARAMETROS DE SALIDA:
RESULTADO Y ERRORES: Entero 0, todo OK
OBSERVACIONES:
****************************************************************************/
int CVICALLBACK PulsaConf (int panel, int control, int event,
void *callbackData, int eventData1, int eventData2)
{
static char panel_visible;

switch (event) {
case EVENT_COMMIT:
if (panel_visible) {
HidePanel(panel_conf);
panel_visible = NO;
}
else {
DisplayPanel (panel_conf);
panel_visible = SI;
}
break;
case EVENT_RIGHT_CLICK:
MessagePopup ("Otros parámetros de Configuración",
"Provoca la visualización de otra pantalla donde cambiar \n"
" la configuración de otros parámetros del modem.");
break;
}
return 0;
}

/****************************************************************************
FUNCION: Salida
DESCRIPCION: Cierra la aplicación
PARAMETROS DE ENTRADA: Función callback
C.1 Aplicación modulAD 165

PARAMETROS DE SALIDA:
RESULTADO Y ERRORES: Entero 0, todo OK
OBSERVACIONES:
****************************************************************************/
int CVICALLBACK Salida (int panel, int control, int event,
void *callbackData, int eventData1, int eventData2)
{
switch (event) {
case EVENT_COMMIT:
QuitUserInterface (0);
break;
case EVENT_RIGHT_CLICK:
MessagePopup ("Botón \"SALIDA\"",
" Salida del programa.");
break;
}
return 0;
}

/****************************************************************************
FUNCION: PulsaMod
DESCRIPCION: Cambia el tipo de modulación con el que se modulan los datos de
entrada. Los tipos de modulación implementados en el modulador AD9853 son
FSK, QPSK y 16QAM.
PARAMETROS DE ENTRADA: Tı́picos de funciones callback
PARAMETROS DE SALIDA:
RESULTADO Y ERRORES: Entero 0, todo OK
OBSERVACIONES:
****************************************************************************/
int CVICALLBACK PulsaMod (int panel, int control, int event,
void *callbackData, int eventData1, int eventData2)
{
static int div_var, div_fijo, tipo_mod, factor_div, overfl;
static char txt_modo[7], modulacion, cod_dif;

switch (event) {
case EVENT_COMMIT:
err = GetCtrlVal (panel_principal, PANEL_MOD_PULSA_MOD, &tipo_mod);
err = GetCtrlVal (panel_vel, PANEL_VEL_VALOR_DIV, &div_var);
err = GetCtrlVal (panel_vel, PANEL_VEL_PUL_DIV_2, &div_fijo);

// Cálculo del factor de división total


if (div_fijo==SI) factor_div=div_var * 2;
else factor_div=div_var;
overfl=NO;

switch (tipo_mod) {
case 0: //FSK
strcpy(txt_modo, "FSK");
modulacion = FSK;
// control_modem[MODO_MOD] = 0x80;
control_modem[MODO_MOD] = control_modem[MODO_MOD] & 0x3F;
control_modem[MODO_MOD] = control_modem[MODO_MOD] | 0x80;
err = SetCtrlAttribute (panel_vel, PANEL_VEL_VALOR_DIV,
ATTR_MAX_VALUE, 2047);
break;
case 1: //QPSK
strcpy(txt_modo, "QPSK");
modulacion = QPSK;
control_modem[MODO_MOD] = control_modem[MODO_MOD] & 0x3F;
// Control de que no nos pasamos de factor de división
if (factor_div > 651 ) {
if (div_fijo) err = SetCtrlVal (panel_vel, PANEL_VEL_VALOR_DIV, 325);
else err = SetCtrlVal (panel_vel, PANEL_VEL_VALOR_DIV, 651);
err = GetCtrlVal (panel_vel, PANEL_VEL_VALOR_DIV, &div_var);
overfl=SI;
}
err = SetCtrlAttribute (panel_vel, PANEL_VEL_VALOR_DIV,
C.1 Aplicación modulAD 166

ATTR_MAX_VALUE, 651);
break;
case 3: //16QAM
strcpy(txt_modo, "16QAM");
modulacion = _16QAM;
control_modem[MODO_MOD] = control_modem[MODO_MOD] & 0x3F;
control_modem[MODO_MOD] = control_modem[MODO_MOD] | 0x40;
// Control de que no nos pasamos de factor de división
if (factor_div > 325 ) {
if (div_fijo) err = SetCtrlVal (panel_vel, PANEL_VEL_VALOR_DIV, 162);
else err = SetCtrlVal (panel_vel, PANEL_VEL_VALOR_DIV, 325);
err = GetCtrlVal (panel_vel, PANEL_VEL_VALOR_DIV, &div_var);
overfl=SI;
}
err = SetCtrlAttribute (panel_vel, PANEL_VEL_VALOR_DIV,
ATTR_MAX_VALUE, 325);
break;
}
// Se ha de actualizar el registro dependiendo de la codificación diferencial
PulsaCodDif (panel_scr, PANEL_SCR_PULSA_COD_DIF, EVENT_COMMIT, 0, 0, 0);

if (overfl) {
switch (tipo_mod) {
case 1:
MessagePopup ("Error al cambiar el tipo de modulación",
"Se superó el valor máximo de división en QPSK.\n"
"Ajustado el divisor variable al máximo valor permitido.");
break;
case 3:
MessagePopup ("Error al cambiar el tipo de modulación",
"Se superó el valor máximo de división en 16QAM.\n"
"Ajustado el divisor variable al máximo valor permitido.");
break;
default:
break;
}
}

// Si se dió error con el factor de división, se cambia el valor del divisor


// ahora se ejecuta en el hardware
ValorDiv (panel_vel, PANEL_VEL_VALOR_DIV, EVENT_COMMIT, 0, 0, 0);

// Programación del hardware


prog_hard(MODO_MOD, 1);
// Entorno gráfico
err = SetCtrlVal (panel_principal, PANEL_MOD_TEXT_MOD_VAL, txt_modo);
break;
case EVENT_RIGHT_CLICK:
break;
}
return 0;
}

/****************************************************************************
FUNCION: TipoScrambler
DESCRIPCION: Permite la selección del tipo de aleatorizador utilizado,
programando a continuación el registro adecuado
PARAMETROS DE ENTRADA: Los tı́picos de las funciones callback.
PARAMETROS DE SALIDA:
RESULTADO Y ERRORES: Entero 0, todo OK
OBSERVACIONES:
****************************************************************************/
int CVICALLBACK TipoScrambler (int panel, int control, int event,
void *callbackData, int eventData1, int eventData2)
{
char tipo_scr;

switch (event) {
C.1 Aplicación modulAD 167

case EVENT_COMMIT:
err = GetCtrlVal (panel_conf, PANEL_CONF_TIPO_SCRAMBLER, &tipo_scr);
switch (tipo_scr) {
case 0:
control_modem[RS_t] = control_modem[RS_t] & 0xFD;
break;
case 1:
control_modem[RS_t] = control_modem[RS_t] | 0x02;
break;
}
// Programación del hardware
prog_hard(RS_t, 1);
break;
case EVENT_RIGHT_CLICK:
break;
}
return 0;
}

/****************************************************************************
FUNCION: SwitchSpectrum
DESCRIPCION: Actualiza la variable de selección del espectro de salida,
programando el registro implicado.
PARAMETROS DE ENTRADA: Los tı́picos de una callback.
PARAMETROS DE SALIDA:
RESULTADO Y ERRORES: Entero 0, todo OK
OBSERVACIONES:
****************************************************************************/
int CVICALLBACK SwitchSpectrum (int panel, int control, int event,
void *callbackData, int eventData1, int eventData2)
{
static char espectro;

switch (event)
{
case EVENT_COMMIT:
// Selección del espectro de salida
err = GetCtrlVal (panel_conf, PANEL_CONF_SWITCH_SPECTRUM, &espectro);
if (espectro == NORMAL) control_modem[CONF] = control_modem[CONF] | 0x80;
else control_modem[CONF] = control_modem[CONF] & 0x7F;
// Programación del hardware
prog_hard(CONF, 1);
break;
case EVENT_RIGHT_CLICK:
MessagePopup ("Espectro de salida",
"Selección del espectro: Normal Icos - Qsen; Invertido Icos + Qsen.");
break;
}
return 0;
}

/****************************************************************************
FUNCION: SwitchDac
DESCRIPCION: Permite activar o poner en modo shutdown el AD9853
PARAMETROS DE ENTRADA:
PARAMETROS DE SALIDA:
RESULTADO Y ERRORES: Entero 0, todo OK
OBSERVACIONES: Ahorra energı́a cuando no se necesita la se~
nal de salida
****************************************************************************/
int CVICALLBACK SwitchDac (int panel, int control, int event,
void *callbackData, int eventData1, int eventData2)
{
static char rf_sleep;

switch (event)
{
case EVENT_COMMIT:
// Modo de funcionamiento del DAC de salida
C.1 Aplicación modulAD 168

err = GetCtrlVal (panel_conf, PANEL_CONF_SWITCH_DAC, &rf_sleep);


if (rf_sleep) {
control_modem[CONF] = control_modem[CONF] & 0x87;
control_modem[CONF] = control_modem[CONF] | 0x58;
// Programación del hardware
prog_hard(CONF, 1);
}
else {
control_modem[CONF] = control_modem[CONF] & 0x87;
control_modem[CONF] = control_modem[CONF] | 0x20;
// Programación del hardware
inicio = SI;
inicializa(NO); //El "NO" evita la entrada en bucle
inicio = NO;

break;
case EVENT_RIGHT_CLICK:

break;
}
return 0;
}

/****************************************************************************
FUNCION: ValorFrecRef
DESCRIPCION: Actualiza la presentación de la velocidad de datos y de la
frecuencia de referencia como consecuencia de una modificación de esta
última.
PARAMETROS DE ENTRADA: Los corrientes de una función callback
PARAMETROS DE SALIDA:
RESULTADO Y ERRORES: 0, OK
OBSERVACIONES:
****************************************************************************/
int CVICALLBACK ValorFrecRef (int panel, int control, int event,
void *callbackData, int eventData1, int eventData2)
{
static double frec_ref;

switch (event) {
case EVENT_COMMIT:
// Obtenemos la nueva frecuencia de referencia
err = GetCtrlVal (panel_conf, PANEL_CONF_VALOR_FREC_REF, &frec_ref);

// Reprogramación de los registros de frecuencia según la nueva frecuencia de ref.


ValorFrecMarca (panel_frec, PANEL_FREC_VALOR_FREC_MARCA, EVENT_COMMIT, 0, 0, 0);
ValorFrec (panel_frec, PANEL_FREC_VALOR_FREC, EVENT_COMMIT, 0, 0, 0);
ValorDiv (panel_vel, PANEL_VEL_VALOR_DIV, EVENT_COMMIT, 0, 0, 0);

// Entorno gráfico en el panel informativo


err = SetCtrlVal (panel_vel, PANEL_VEL_VALOR_FREC_REF, frec_ref);

break;
case EVENT_RIGHT_CLICK:
MessagePopup ("Frecuencia de Referencia",
"Este valor se debe actualizar adecuadamente cada vez que se cambie\n"
"el cristal de referencia de la placa del modem, o se utilize una frecuencia\n"
" de referencia externa distinta.");
break;
}
return 0;
}

/****************************************************************************
FUNCION: ValorFrecMarca
DESCRIPCION: Calcula el valor a programar en el registro de frecuencia
secundario utilizado en FSK, y carga el registro con el contenido
C.1 Aplicación modulAD 169

adecuado.
PARAMETROS DE ENTRADA: Los tı́picos de las funciones callback.
PARAMETROS DE SALIDA:
RESULTADO Y ERRORES: Entero 0, todo OK
OBSERVACIONES:
****************************************************************************/
int CVICALLBACK ValorFrecMarca (int panel, int control, int event,
void *callbackData, int eventData1, int eventData2)
{
static double frec_marca, frec_ref;

switch (event) {
case EVENT_COMMIT:
// Obtenemos la nueva frecuencia de referencia
err = GetCtrlVal (panel_frec, PANEL_FREC_VALOR_FREC_MARCA, &frec_marca);
err = GetCtrlVal (panel_conf, PANEL_CONF_VALOR_FREC_REF, &frec_ref);
// Carga del hardware
frec_32 (frec_marca, NRO_BITS, F1_0, frec_ref);
prog_hard(F1_0, 4);
break;
case EVENT_RIGHT_CLICK:
break;
}
return 0;
}

/****************************************************************************
FUNCION: ValorFrec
DESCRIPCION: Calcula el valor a programar en el registro de frecuencia
y carga el registro con el contenido adecuado.
PARAMETROS DE ENTRADA: Los tı́picos de las funciones callback.
PARAMETROS DE SALIDA:
RESULTADO Y ERRORES: Entero 0, todo OK
OBSERVACIONES:
****************************************************************************/
int CVICALLBACK ValorFrec (int panel, int control, int event,
void *callbackData, int eventData1, int eventData2)
{
static double frec_sal, frec_ref;
static char txt_frec_sal[50];

switch (event) {
case EVENT_COMMIT:
err = GetCtrlVal (panel_frec, PANEL_FREC_VALOR_FREC, &frec_sal);
err = GetCtrlVal (panel_conf, PANEL_CONF_VALOR_FREC_REF, &frec_ref);
// Entorno gráfico
Fmt (txt_frec_sal, "%s<%f[w14p4]", frec_sal);
if (hay_placa_mod) err = SetCtrlVal (panel_principal,
PANEL_MOD_TEXT_FREC_VAL, txt_frec_sal);
// Carga del hardware
frec_32 (frec_sal, NRO_BITS, F0_0, frec_ref);
prog_hard(F0_0, 4);
break;
case EVENT_RIGHT_CLICK:
break;
}
return 0;
}

/****************************************************************************
FUNCION: PulsaCodDif
DESCRIPCION: Permite habilitar / deshabilitar el codificador diferencial
PARAMETROS DE ENTRADA: Los tı́picos de las funciones callback.
PARAMETROS DE SALIDA:
RESULTADO Y ERRORES: Entero 0, todo OK
OBSERVACIONES:
****************************************************************************/
int CVICALLBACK PulsaCodDif (int panel, int control, int event,
C.1 Aplicación modulAD 170

void *callbackData, int eventData1, int eventData2)


{
static char txt_cod[4], cod_dif;
static int tipo_mod;

switch (event) {
case EVENT_COMMIT:
err = GetCtrlVal (panel_scr, PANEL_SCR_PULSA_COD_DIF, &cod_dif);
err = GetCtrlVal (panel_principal, PANEL_MOD_PULSA_MOD, &tipo_mod);
switch (cod_dif) {
case 0:
strcpy(txt_cod, "OFF");
switch (tipo_mod) {
case 0: break; //FSK
default: control_modem[MODO_MOD] = control_modem[MODO_MOD] & 0xC0; break; //QPSK
}
break;
case 1:
strcpy(txt_cod, "ON");
switch (tipo_mod) {
case 0: break; //FSK
default: control_modem[MODO_MOD] = control_modem[MODO_MOD] | 0x20; break; // DQPSK
}
break;
}
// Programación del hardware
prog_hard(MODO_MOD, 1);
// Entorno gráfico
if (hay_placa_mod) err = SetCtrlVal (panel_principal,
PANEL_MOD_TEXT_COD_VAL, txt_cod);
break;
case EVENT_RIGHT_CLICK:
break;
}
return 0;
}

/****************************************************************************
FUNCION: PulsaScr
DESCRIPCION: Permite habilitar / deshabilitar el aleatorizador (scrambler),
programando a continuación el registro del chip implicado
PARAMETROS DE ENTRADA: Los tı́picos de las funciones callback.
PARAMETROS DE SALIDA:
RESULTADO Y ERRORES: Entero 0, todo OK
OBSERVACIONES:
****************************************************************************/
int CVICALLBACK PulsaScr (int panel, int control, int event,
void *callbackData, int eventData1, int eventData2)
{
static char txt_scr[4], scr;

switch (event) {
case EVENT_COMMIT:
err = GetCtrlVal (panel_scr, PANEL_SCR_PULSA_SCR, &scr);
switch (scr) {
case 0:
strcpy(txt_scr, "OFF");
control_modem[RS_t] = control_modem[RS_t] | 0x04;
break;
case 1:
strcpy(txt_scr, "ON");
control_modem[RS_t] = control_modem[RS_t] & 0xFB;
break;
}
if (hay_placa_mod) err = SetCtrlVal (panel_principal,
PANEL_MOD_TEXT_SCR_VAL, txt_scr);
// Programación del hardware
prog_hard(RS_t, 1);
C.1 Aplicación modulAD 171

break;
case EVENT_RIGHT_CLICK:
break;
}
return 0;
}

/****************************************************************************
FUNCION: ValorDiv
DESCRIPCION: Permite cambiar el valor del divisor principal para generar la
frecuencia de bit. A continuación carga en la placa del modulador los
datos adecuados.
PARAMETROS DE ENTRADA:
PARAMETROS DE SALIDA:
RESULTADO Y ERRORES: 0, OK
OBSERVACIONES:
****************************************************************************/
int CVICALLBACK ValorDiv (int panel, int control, int event,
void *callbackData, int eventData1, int eventData2)
{
static double frec_ref, dato_clock;
static int div_var, div_fijo, tipo_mod, factor_I1I2;
static char txt_vel_datos[50], modulacion;

switch (event) {
case EVENT_COMMIT:
err = GetCtrlVal (panel_vel, PANEL_VEL_VALOR_DIV, &div_var);
// Demás parámetros necesarios para configurar el modem a las nuevas condiciones
err = GetCtrlVal (panel_conf, PANEL_CONF_VALOR_FREC_REF, &frec_ref);
err = GetCtrlVal (panel_vel, PANEL_VEL_PUL_DIV_2, &div_fijo);
err = GetCtrlVal (panel_principal, PANEL_MOD_PULSA_MOD, &tipo_mod);

switch (tipo_mod) {
case 0: modulacion = FSK; break;
case 1: modulacion = QPSK; break;
case 3: modulacion = _16QAM; break;
default: modulacion = FSK;
}

// Al cambiar el reloj de bit, cambia el factor de interpolación


err = interpolador (&div_var, div_fijo, modulacion);
SetCtrlVal (panel_vel, PANEL_VEL_VALOR_DIV, div_var);

switch (err) {
/* -1 Número resultante es primo "para los interpoladores" y por tanto
corresponde a un factor de interpolación total no válido
-2 El tipo de modulación es FSK. En este caso la función no tiene
ningún efecto.
-3 El tipo de modulación es QPSK y el valor de división total es
mayor de 651.
-4 El tipo de modulación es 16QAM y el valor de división total es
mayor de 325. */
case -1:
MessagePopup ("Error al cambiar la velocidad de transmisión",
"El comando de división es un valor no permitido.\n"
"Ajustado el factor de división total por defecto.");
break;
case -3:
MessagePopup ("Error al cambiar la velocidad de transmisión",
"Se superó el valor máximo de división permitido en QPSK.\n"
"Ajustado el divisor variable al valor máximo permitido.");
break;
case -4:
MessagePopup ("Error al cambiar la velocidad de transmisión",
"Se superó el valor máximo de división permitido en 16QAM.\n"
"Ajustado el divisor variable al valor máximo permitido.");
break;
}
C.1 Aplicación modulAD 172

// Programación del generador de reloj de bit


dato_clock = gen_bit_clk (div_var, div_fijo, frec_ref);

// Al cambiar la interpolación, también lo hace el factor de escalado,


// con lo que se vuelven a programar los coeficientes FIR
ValorFirA0(panel_fir, PANEL_FIR_VALOR_FIR_A0, EVENT_COMMIT, 0, 0, 0);
ValorFirA1(panel_fir, PANEL_FIR_VALOR_FIR_A1, EVENT_COMMIT, 0, 0, 0);
ValorFirA2(panel_fir, PANEL_FIR_VALOR_FIR_A2, EVENT_COMMIT, 0, 0, 0);
ValorFirA3(panel_fir, PANEL_FIR_VALOR_FIR_A3, EVENT_COMMIT, 0, 0, 0);
ValorFirA4(panel_fir, PANEL_FIR_VALOR_FIR_A4, EVENT_COMMIT, 0, 0, 0);
ValorFirA5(panel_fir, PANEL_FIR_VALOR_FIR_A5, EVENT_COMMIT, 0, 0, 0);
ValorFirA6(panel_fir, PANEL_FIR_VALOR_FIR_A6, EVENT_COMMIT, 0, 0, 0);
ValorFirA7(panel_fir, PANEL_FIR_VALOR_FIR_A7, EVENT_COMMIT, 0, 0, 0);
ValorFirA8(panel_fir, PANEL_FIR_VALOR_FIR_A8, EVENT_COMMIT, 0, 0, 0);
ValorFirA9(panel_fir, PANEL_FIR_VALOR_FIR_A9, EVENT_COMMIT, 0, 0, 0);
ValorFirA10(panel_fir, PANEL_FIR_VALOR_FIR_A10, EVENT_COMMIT, 0, 0, 0);
ValorFirA11(panel_fir, PANEL_FIR_VALOR_FIR_A11, EVENT_COMMIT, 0, 0, 0);
ValorFirA12(panel_fir, PANEL_FIR_VALOR_FIR_A12, EVENT_COMMIT, 0, 0, 0);
ValorFirA13(panel_fir, PANEL_FIR_VALOR_FIR_A13, EVENT_COMMIT, 0, 0, 0);
ValorFirA14(panel_fir, PANEL_FIR_VALOR_FIR_A14, EVENT_COMMIT, 0, 0, 0);
ValorFirA15(panel_fir, PANEL_FIR_VALOR_FIR_A15, EVENT_COMMIT, 0, 0, 0);
ValorFirA16(panel_fir, PANEL_FIR_VALOR_FIR_A16, EVENT_COMMIT, 0, 0, 0);
ValorFirA17(panel_fir, PANEL_FIR_VALOR_FIR_A17, EVENT_COMMIT, 0, 0, 0);
ValorFirA18(panel_fir, PANEL_FIR_VALOR_FIR_A18, EVENT_COMMIT, 0, 0, 0);
ValorFirA19(panel_fir, PANEL_FIR_VALOR_FIR_A19, EVENT_COMMIT, 0, 0, 0);
ValorFirA20(panel_fir, PANEL_FIR_VALOR_FIR_A20, EVENT_COMMIT, 0, 0, 0);
// Programación del hardware
prog_hard(INT1_RATE, 4);
prog_hard(CONF, 1);

// Entorno gráfico
if (hay_placa_mod) {
err = SetCtrlVal (panel_vel, PANEL_VEL_VALOR_VEL_DAT, dato_clock);
Fmt (txt_vel_datos, "%s<%f[w14p4]", dato_clock);
err = SetCtrlVal (panel_principal, PANEL_MOD_TEXT_VEL_VAL, txt_vel_datos);
}
break;
case EVENT_RIGHT_CLICK:
break;
}
return 0;
}

/****************************************************************************
FUNCION: PulDiv2
DESCRIPCION: Pone de manifiesto el efecto producido al activar/desactivar
mediante el puente hardware JP2 el divisor adicional por 2 en el
generador de reloj de bit.
PARAMETROS DE ENTRADA: Es una función callback
PARAMETROS DE SALIDA:
RESULTADO Y ERRORES: 0, OK
OBSERVACIONES:
****************************************************************************/
int CVICALLBACK PulDiv2 (int panel, int control, int event,
void *callbackData, int eventData1, int eventData2)
{
static double frec_ref, dato_clock;
static int div_var, div_fijo, tipo_mod;
static char txt_vel_datos[50], modulacion;

switch (event) {
case EVENT_COMMIT:
err = GetCtrlVal (panel_vel, PANEL_VEL_PUL_DIV_2, &div_fijo);
// Demás parámetros necesarios para configurar el modem a las nuevas condiciones

if (div_fijo == 1) {
SetCtrlVal (panel_vel, PANEL_VEL_MENSG_2, "JP2 pines 3-4");
C.1 Aplicación modulAD 173

SetCtrlAttribute (panel_vel, PANEL_VEL_PUL_DIV_2, ATTR_LABEL_TEXT,


"x 2");
}
else { //div_fijo == 0
SetCtrlVal (panel_vel, PANEL_VEL_MENSG_2, "JP2 pines 1-2");
SetCtrlAttribute (panel_vel, PANEL_VEL_PUL_DIV_2, ATTR_LABEL_TEXT,
"x 1");
}

ValorDiv (panel_vel, PANEL_VEL_VALOR_DIV, EVENT_COMMIT, 0, 0, 0);


break;
case EVENT_RIGHT_CLICK:
break;
}
return 0;
}

/****************************************************************************
FUNCION: PulsaFrecOk
DESCRIPCION: Oculta el panel de la sintonı́a de frecuencia
PARAMETROS DE ENTRADA:
PARAMETROS DE SALIDA:
RESULTADO Y ERRORES: 0, ok
OBSERVACIONES:
****************************************************************************/
int CVICALLBACK PulsaFrecOk (int panel, int control, int event,
void *callbackData, int eventData1, int eventData2)
{
switch (event) {
case EVENT_COMMIT:
PulsaFrec (panel_principal, PANEL_MOD_PULSA_FREC, EVENT_COMMIT, 0, 0, 0);
break;
case EVENT_RIGHT_CLICK:
break;
}
return 0;
}

/****************************************************************************
FUNCION: PulsaOk
DESCRIPCION: Oculta el panel de configuración
PARAMETROS DE ENTRADA:
PARAMETROS DE SALIDA:
RESULTADO Y ERRORES: 0, OK
OBSERVACIONES:
****************************************************************************/
int CVICALLBACK PulsaOk (int panel, int control, int event,
void *callbackData, int eventData1, int eventData2)
{
switch (event) {
case EVENT_COMMIT:
PulsaConf (panel_principal, PANEL_MOD_PULSA_CONF, EVENT_COMMIT, 0, 0, 0);
break;
case EVENT_RIGHT_CLICK:

break;
}
return 0;
}

/****************************************************************************
FUNCION: PulsaFirOk
DESCRIPCION: Oculta el panel de programación de los coeficientes del filtro FIR
PARAMETROS DE ENTRADA:
PARAMETROS DE SALIDA:
RESULTADO Y ERRORES: 0, OK
OBSERVACIONES:
****************************************************************************/
C.1 Aplicación modulAD 174

int CVICALLBACK PulsaFirOk (int panel, int control, int event,


void *callbackData, int eventData1, int eventData2)
{
switch (event) {
case EVENT_COMMIT:
PulsaFir (panel_principal, PANEL_MOD_PULSA_FIR, EVENT_COMMIT, 0, 0, 0);
break;
case EVENT_RIGHT_CLICK:
break;
}
return 0;
}

/****************************************************************************
FUNCION: PulsaVelOk
DESCRIPCION: Oculta el panel de programación del generador de reloj de bit
PARAMETROS DE ENTRADA:
PARAMETROS DE SALIDA:
RESULTADO Y ERRORES: 0, OK
OBSERVACIONES:
****************************************************************************/
int CVICALLBACK PulsaVelOk (int panel, int control, int event,
void *callbackData, int eventData1, int eventData2)
{
switch (event) {
case EVENT_COMMIT:
PulsaVel (panel_principal, PANEL_MOD_PULSA_VEL, EVENT_COMMIT, 0, 0, 0);
break;
case EVENT_RIGHT_CLICK:
break;
}
return 0;
}

/****************************************************************************
FUNCION: PulsaScrOk
DESCRIPCION: Oculta el panel desde el que se habilitan/deshabilitan el
scrambler y el codificador diferencial
PARAMETROS DE ENTRADA:
PARAMETROS DE SALIDA:
RESULTADO Y ERRORES: 0, OK
OBSERVACIONES:
****************************************************************************/
int CVICALLBACK PulsaScrOk (int panel, int control, int event,
void *callbackData, int eventData1, int eventData2)
{
switch (event) {
case EVENT_COMMIT:
PulsaFec (panel_principal, PANEL_MOD_PULSA_FEC, EVENT_COMMIT, 0, 0, 0);
break;
case EVENT_RIGHT_CLICK:
break;
}
return 0;
}

/****************************************************************************
FUNCION: ValorFirAx
DESCRIPCION: Modifican el coeficiente x del filtro FIR de que consta el
modulador AD9853
PARAMETROS DE ENTRADA: Los tı́picos de las funciones Callback
PARAMETROS DE SALIDA:
RESULTADO Y ERRORES:
OBSERVACIONES: Se "escala" el dato introducido en el panel frontal según
los valores que estén programados en los dos interpoladores del integrado
****************************************************************************/
int CVICALLBACK ValorFirA0 (int panel, int control, int event,
void *callbackData, int eventData1, int eventData2)
C.1 Aplicación modulAD 175

{
static short dos_bytes;

switch (event) {
case EVENT_COMMIT:
err = GetCtrlVal (panel_fir, PANEL_FIR_VALOR_FIR_A0, &dos_bytes);
// Escalado del valor
dos_bytes = dos_bytes / esc_old;
dos_bytes = dos_bytes * esc;
control_modem[FIR_A00_L] = dos_bytes & 0xFF;
dos_bytes = dos_bytes >> 2;
control_modem[FIR_A00_H] = dos_bytes & 0xC0;
// Programación del hardware
prog_hard(FIR_A00_L, 2);
break;
case EVENT_RIGHT_CLICK:

break;
}
return 0;
}

int CVICALLBACK ValorFirA1 (int panel, int control, int event,


void *callbackData, int eventData1, int eventData2)
{
static short dos_bytes;

switch (event) {
case EVENT_COMMIT:
err = GetCtrlVal (panel_fir, PANEL_FIR_VALOR_FIR_A1, &dos_bytes);
// Escalado del valor
dos_bytes = dos_bytes / esc_old;
dos_bytes = dos_bytes * esc;
control_modem[FIR_A01_L] = dos_bytes & 0xFF;
dos_bytes = dos_bytes >> 2;
control_modem[FIR_A01_H] = dos_bytes & 0xC0;
// Programación del hardware
prog_hard(FIR_A01_L, 2);
break;
case EVENT_RIGHT_CLICK:

break;
}
return 0;
}

int CVICALLBACK ValorFirA2 (int panel, int control, int event,


void *callbackData, int eventData1, int eventData2)
{
static short dos_bytes;

switch (event) {
case EVENT_COMMIT:
err = GetCtrlVal (panel_fir, PANEL_FIR_VALOR_FIR_A2, &dos_bytes);
// Escalado del valor
dos_bytes = dos_bytes / esc_old;
dos_bytes = dos_bytes * esc;
control_modem[FIR_A02_L] = dos_bytes & 0xFF;
dos_bytes = dos_bytes >> 2;
control_modem[FIR_A02_H] = dos_bytes & 0xC0;
// Programación del hardware
prog_hard(FIR_A02_L, 2);
break;
case EVENT_RIGHT_CLICK:

break;
}
return 0;
C.1 Aplicación modulAD 176

int CVICALLBACK ValorFirA3 (int panel, int control, int event,


void *callbackData, int eventData1, int eventData2)
{
static short dos_bytes;

switch (event) {
case EVENT_COMMIT:
err = GetCtrlVal (panel_fir, PANEL_FIR_VALOR_FIR_A3, &dos_bytes);
// Escalado del valor
dos_bytes = dos_bytes / esc_old;
dos_bytes = dos_bytes * esc;
control_modem[FIR_A03_L] = dos_bytes & 0xFF;
dos_bytes = dos_bytes >> 2;
control_modem[FIR_A03_H] = dos_bytes & 0xC0;
// Programación del hardware
prog_hard(FIR_A03_L, 2);
break;
case EVENT_RIGHT_CLICK:

break;
}
return 0;
}

int CVICALLBACK ValorFirA4 (int panel, int control, int event,


void *callbackData, int eventData1, int eventData2)
{
static short dos_bytes;

switch (event) {
case EVENT_COMMIT:
err = GetCtrlVal (panel_fir, PANEL_FIR_VALOR_FIR_A4, &dos_bytes);
// Escalado del valor
dos_bytes = dos_bytes / esc_old;
dos_bytes = dos_bytes * esc;
control_modem[FIR_A04_L] = dos_bytes & 0xFF;
dos_bytes = dos_bytes >> 2;
control_modem[FIR_A04_H] = dos_bytes & 0xC0;
// Programación del hardware
prog_hard(FIR_A04_L, 2);
break;
case EVENT_RIGHT_CLICK:

break;
}
return 0;
}

int CVICALLBACK ValorFirA5 (int panel, int control, int event,


void *callbackData, int eventData1, int eventData2)
{
static short dos_bytes;

switch (event) {
case EVENT_COMMIT:
err = GetCtrlVal (panel_fir, PANEL_FIR_VALOR_FIR_A5, &dos_bytes);
// Escalado del valor
dos_bytes = dos_bytes / esc_old;
dos_bytes = dos_bytes * esc;
control_modem[FIR_A05_L] = dos_bytes & 0xFF;
dos_bytes = dos_bytes >> 2;
control_modem[FIR_A05_H] = dos_bytes & 0xC0;
// Programación del hardware
prog_hard(FIR_A05_L, 2);
break;
case EVENT_RIGHT_CLICK:
C.1 Aplicación modulAD 177

break;
}
return 0;
}

int CVICALLBACK ValorFirA6 (int panel, int control, int event,


void *callbackData, int eventData1, int eventData2)
{
static short dos_bytes;

switch (event) {
case EVENT_COMMIT:
err = GetCtrlVal (panel_fir, PANEL_FIR_VALOR_FIR_A6, &dos_bytes);
// Escalado del valor
dos_bytes = dos_bytes / esc_old;
dos_bytes = dos_bytes * esc;
control_modem[FIR_A06_L] = dos_bytes & 0xFF;
dos_bytes = dos_bytes >> 2;
control_modem[FIR_A06_H] = dos_bytes & 0xC0;
// Programación del hardware
prog_hard(FIR_A06_L, 2);
break;
case EVENT_RIGHT_CLICK:

break;
}
return 0;
}

int CVICALLBACK ValorFirA7 (int panel, int control, int event,


void *callbackData, int eventData1, int eventData2)
{
static short dos_bytes;

switch (event) {
case EVENT_COMMIT:
err = GetCtrlVal (panel_fir, PANEL_FIR_VALOR_FIR_A7, &dos_bytes);
// Escalado del valor
dos_bytes = dos_bytes / esc_old;
dos_bytes = dos_bytes * esc;
control_modem[FIR_A07_L] = dos_bytes & 0xFF;
dos_bytes = dos_bytes >> 2;
control_modem[FIR_A07_H] = dos_bytes & 0xC0;
// Programación del hardware
prog_hard(FIR_A07_L, 2);
break;
case EVENT_RIGHT_CLICK:

break;
}
return 0;
}

int CVICALLBACK ValorFirA8 (int panel, int control, int event,


void *callbackData, int eventData1, int eventData2)
{
static short dos_bytes;

switch (event) {
case EVENT_COMMIT:
err = GetCtrlVal (panel_fir, PANEL_FIR_VALOR_FIR_A8, &dos_bytes);
// Escalado del valor
dos_bytes = dos_bytes / esc_old;
dos_bytes = dos_bytes * esc;
control_modem[FIR_A08_L] = dos_bytes & 0xFF;
dos_bytes = dos_bytes >> 2;
control_modem[FIR_A08_H] = dos_bytes & 0xC0;
C.1 Aplicación modulAD 178

// Programación del hardware


prog_hard(FIR_A08_L, 2);
break;
case EVENT_RIGHT_CLICK:

break;
}
return 0;
}

int CVICALLBACK ValorFirA9 (int panel, int control, int event,


void *callbackData, int eventData1, int eventData2)
{
static short dos_bytes;

switch (event) {
case EVENT_COMMIT:
err = GetCtrlVal (panel_fir, PANEL_FIR_VALOR_FIR_A9, &dos_bytes);
// Escalado del valor
dos_bytes = dos_bytes / esc_old;
dos_bytes = dos_bytes * esc;
control_modem[FIR_A09_L] = dos_bytes & 0xFF;
dos_bytes = dos_bytes >> 2;
control_modem[FIR_A09_H] = dos_bytes & 0xC0;
// Programación del hardware
prog_hard(FIR_A09_L, 2);
break;
case EVENT_RIGHT_CLICK:

break;
}
return 0;
}

int CVICALLBACK ValorFirA10 (int panel, int control, int event,


void *callbackData, int eventData1, int eventData2)
{
static short dos_bytes;

switch (event) {
case EVENT_COMMIT:
err = GetCtrlVal (panel_fir, PANEL_FIR_VALOR_FIR_A10, &dos_bytes);
// Escalado del valor
dos_bytes = dos_bytes / esc_old;
dos_bytes = dos_bytes * esc;
control_modem[FIR_A10_L] = dos_bytes & 0xFF;
dos_bytes = dos_bytes >> 2;
control_modem[FIR_A10_H] = dos_bytes & 0xC0;
// Programación del hardware
prog_hard(FIR_A10_L, 2);
break;
case EVENT_RIGHT_CLICK:

break;
}
return 0;
}

int CVICALLBACK ValorFirA11 (int panel, int control, int event,


void *callbackData, int eventData1, int eventData2)
{
static short dos_bytes;

switch (event) {
case EVENT_COMMIT:
err = GetCtrlVal (panel_fir, PANEL_FIR_VALOR_FIR_A11, &dos_bytes);
// Escalado del valor
dos_bytes = dos_bytes / esc_old;
C.1 Aplicación modulAD 179

dos_bytes = dos_bytes * esc;


control_modem[FIR_A11_L] = dos_bytes & 0xFF;
dos_bytes = dos_bytes >> 2;
control_modem[FIR_A11_H] = dos_bytes & 0xC0;
// Programación del hardware
prog_hard(FIR_A11_L, 2);
break;
case EVENT_RIGHT_CLICK:

break;
}
return 0;
}

int CVICALLBACK ValorFirA12 (int panel, int control, int event,


void *callbackData, int eventData1, int eventData2)
{
static short dos_bytes;

switch (event) {
case EVENT_COMMIT:
err = GetCtrlVal (panel_fir, PANEL_FIR_VALOR_FIR_A12, &dos_bytes);
// Escalado del valor
dos_bytes = dos_bytes / esc_old;
dos_bytes = dos_bytes * esc;
control_modem[FIR_A12_L] = dos_bytes & 0xFF;
dos_bytes = dos_bytes >> 2;
control_modem[FIR_A12_H] = dos_bytes & 0xC0;
// Programación del hardware
prog_hard(FIR_A12_L, 2);
break;
case EVENT_RIGHT_CLICK:

break;
}
return 0;
}

int CVICALLBACK ValorFirA13 (int panel, int control, int event,


void *callbackData, int eventData1, int eventData2)
{
static short dos_bytes;

switch (event) {
case EVENT_COMMIT:
err = GetCtrlVal (panel_fir, PANEL_FIR_VALOR_FIR_A13, &dos_bytes);
// Escalado del valor
dos_bytes = dos_bytes / esc_old;
dos_bytes = dos_bytes * esc;
control_modem[FIR_A13_L] = dos_bytes & 0xFF;
dos_bytes = dos_bytes >> 2;
control_modem[FIR_A13_H] = dos_bytes & 0xC0;
// Programación del hardware
prog_hard(FIR_A13_L, 2);
break;
case EVENT_RIGHT_CLICK:

break;
}
return 0;
}

int CVICALLBACK ValorFirA14 (int panel, int control, int event,


void *callbackData, int eventData1, int eventData2)
{
static short dos_bytes;

switch (event) {
C.1 Aplicación modulAD 180

case EVENT_COMMIT:
err = GetCtrlVal (panel_fir, PANEL_FIR_VALOR_FIR_A14, &dos_bytes);
// Escalado del valor
dos_bytes = dos_bytes / esc_old;
dos_bytes = dos_bytes * esc;
control_modem[FIR_A14_L] = dos_bytes & 0xFF;
dos_bytes = dos_bytes >> 2;
control_modem[FIR_A14_H] = dos_bytes & 0xC0;
// Programación del hardware
prog_hard(FIR_A14_L, 2);
break;
case EVENT_RIGHT_CLICK:

break;
}
return 0;
}

int CVICALLBACK ValorFirA15 (int panel, int control, int event,


void *callbackData, int eventData1, int eventData2)
{
static short dos_bytes;

switch (event) {
case EVENT_COMMIT:
err = GetCtrlVal (panel_fir, PANEL_FIR_VALOR_FIR_A15, &dos_bytes);
// Escalado del valor
dos_bytes = dos_bytes / esc_old;
dos_bytes = dos_bytes * esc;
control_modem[FIR_A15_L] = dos_bytes & 0xFF;
dos_bytes = dos_bytes >> 2;
control_modem[FIR_A15_H] = dos_bytes & 0xC0;
// Programación del hardware
prog_hard(FIR_A15_L, 2);
break;
case EVENT_RIGHT_CLICK:

break;
}
return 0;
}

int CVICALLBACK ValorFirA16 (int panel, int control, int event,


void *callbackData, int eventData1, int eventData2)
{
static short dos_bytes;

switch (event) {
case EVENT_COMMIT:
err = GetCtrlVal (panel_fir, PANEL_FIR_VALOR_FIR_A16, &dos_bytes);
// Escalado del valor
dos_bytes = dos_bytes / esc_old;
dos_bytes = dos_bytes * esc;
control_modem[FIR_A16_L] = dos_bytes & 0xFF;
dos_bytes = dos_bytes >> 2;
control_modem[FIR_A16_H] = dos_bytes & 0xC0;
// Programación del hardware
prog_hard(FIR_A16_L, 2);
break;
case EVENT_RIGHT_CLICK:

break;
}
return 0;
}

int CVICALLBACK ValorFirA17 (int panel, int control, int event,


void *callbackData, int eventData1, int eventData2)
C.1 Aplicación modulAD 181

{
static short dos_bytes;

switch (event) {
case EVENT_COMMIT:
err = GetCtrlVal (panel_fir, PANEL_FIR_VALOR_FIR_A17, &dos_bytes);
// Escalado del valor
dos_bytes = dos_bytes / esc_old;
dos_bytes = dos_bytes * esc;
control_modem[FIR_A17_L] = dos_bytes & 0xFF;
dos_bytes = dos_bytes >> 2;
control_modem[FIR_A17_H] = dos_bytes & 0xC0;
// Programación del hardware
prog_hard(FIR_A17_L, 2);
break;
case EVENT_RIGHT_CLICK:

break;
}
return 0;
}

int CVICALLBACK ValorFirA18 (int panel, int control, int event,


void *callbackData, int eventData1, int eventData2)
{
static short dos_bytes;

switch (event) {
case EVENT_COMMIT:
err = GetCtrlVal (panel_fir, PANEL_FIR_VALOR_FIR_A18, &dos_bytes);
// Escalado del valor
dos_bytes = dos_bytes / esc_old;
dos_bytes = dos_bytes * esc;
control_modem[FIR_A18_L] = dos_bytes & 0xFF;
dos_bytes = dos_bytes >> 2;
control_modem[FIR_A18_H] = dos_bytes & 0xC0;
// Programación del hardware
prog_hard(FIR_A18_L, 2);
break;
case EVENT_RIGHT_CLICK:

break;
}
return 0;
}

int CVICALLBACK ValorFirA19 (int panel, int control, int event,


void *callbackData, int eventData1, int eventData2)
{
static short dos_bytes;

switch (event) {
case EVENT_COMMIT:
err = GetCtrlVal (panel_fir, PANEL_FIR_VALOR_FIR_A19, &dos_bytes);
// Escalado del valor
dos_bytes = dos_bytes / esc_old;
dos_bytes = dos_bytes * esc;
control_modem[FIR_A19_L] = dos_bytes & 0xFF;
dos_bytes = dos_bytes >> 2;
control_modem[FIR_A19_H] = dos_bytes & 0xC0;
// Programación del hardware
prog_hard(FIR_A19_L, 2);
break;
case EVENT_RIGHT_CLICK:

break;
}
return 0;
C.1 Aplicación modulAD 182

int CVICALLBACK ValorFirA20 (int panel, int control, int event,


void *callbackData, int eventData1, int eventData2)
{
static short dos_bytes;

switch (event) {
case EVENT_COMMIT:
err = GetCtrlVal (panel_fir, PANEL_FIR_VALOR_FIR_A20, &dos_bytes);
// Escalado del valor
dos_bytes = dos_bytes / esc_old;
dos_bytes = dos_bytes * esc;
control_modem[FIR_A20_L] = dos_bytes & 0xFF;
dos_bytes = dos_bytes >> 2;
control_modem[FIR_A20_H] = dos_bytes & 0xC0;
// Programación del hardware
prog_hard(FIR_A20_L, 2);
break;
case EVENT_RIGHT_CLICK:

break;
}
return 0;
}

/****************************************************************************
FUNCION: Bucle
DESCRIPCIÓN: Realiza el chequeo necesario para determinar la existencia
de la placa DDS, actuando en consecuencia sobre la interface de usuario
PARAMETROS DE ENTRADA: Función callback.
PARAMETROS DE SALIDA: No hay
RESULTADO Y ERRORES: 0 OK
OBSERVACIONES:
****************************************************************************/
int CVICALLBACK Bucle (int panel, int control, int event,
void *callbackData, int eventData1, int eventData2)
{
switch (event) {
case EVENT_TIMER_TICK:
hay_placa_mod = busca_equipo_mod();
if (!hay_placa_mod) {
if (primer_bucle) {
primer_bucle = NO; // Control de ejecución del bucle

// Display en la pantalla de mensajes


err = SetCtrlVal (panel_principal, PANEL_MOD_TEXT_FREC_2, "");
err = SetCtrlVal (panel_principal, PANEL_MOD_TEXT_FREC, "");
err = SetCtrlVal (panel_principal, PANEL_MOD_TEXT_MOD, "");
err = SetCtrlVal (panel_principal, PANEL_MOD_TEXT_VEL, "");
err = SetCtrlVal (panel_principal, PANEL_MOD_TEXT_VEL_2, "");
err = SetCtrlVal (panel_principal, PANEL_MOD_TEXT_MOD_VAL, "");
err = SetCtrlVal (panel_principal, PANEL_MOD_TEXT_FREC_VAL, "");
err = SetCtrlVal (panel_principal, PANEL_MOD_TEXT_VEL_VAL, "");
err = SetCtrlVal (panel_principal, PANEL_MOD_TEXT_SCR, "");
err = SetCtrlVal (panel_principal, PANEL_MOD_TEXT_SCR_VAL, "");
err = SetCtrlVal (panel_principal, PANEL_MOD_TEXT_COD_VAL, "");
err = SetCtrlVal (panel_principal, PANEL_MOD_TEXT_COD, "");

// Mensaje de error
err = SetCtrlVal (panel_principal, PANEL_MOD_TEXT_FALLO,
"Fallo del puerto de control. Imposible controlar el modulador");

// Inhabilitación de los controles


err = SetCtrlAttribute (panel_principal, PANEL_MOD_PULSA_MOD, ATTR_DIMMED, 1);
err = SetCtrlAttribute (panel_principal, PANEL_MOD_PULSA_FREC, ATTR_DIMMED, 1);
err = SetCtrlAttribute (panel_principal, PANEL_MOD_PULSA_FEC, ATTR_DIMMED, 1);
err = SetCtrlAttribute (panel_principal, PANEL_MOD_PULSA_VEL, ATTR_DIMMED, 1);
C.1 Aplicación modulAD 183

err = SetCtrlAttribute (panel_principal, PANEL_MOD_PULSA_FIR, ATTR_DIMMED, 1);


err = SetCtrlAttribute (panel_principal, PANEL_MOD_PULSA_CONF, ATTR_DIMMED, 1);
// Color de fondo del display
err = SetCtrlAttribute (panel_principal, PANEL_MOD_DISPLAY,
ATTR_FRAME_COLOR, 0x00FFFFFF);
}
}
else {
if (primer_bucle == NO) {
primer_bucle = SI; // Control de ejecución del bucle

// Color de fondo del display


err = SetCtrlAttribute (panel_principal, PANEL_MOD_DISPLAY,
ATTR_FRAME_COLOR, 0x0033CC99);
// Habilitación de los controles
err = SetCtrlAttribute (panel_principal, PANEL_MOD_PULSA_MOD, ATTR_DIMMED, 0);
err = SetCtrlAttribute (panel_principal, PANEL_MOD_PULSA_FREC, ATTR_DIMMED, 0);
err = SetCtrlAttribute (panel_principal, PANEL_MOD_PULSA_FEC, ATTR_DIMMED, 0);
err = SetCtrlAttribute (panel_principal, PANEL_MOD_PULSA_VEL, ATTR_DIMMED, 0);
err = SetCtrlAttribute (panel_principal, PANEL_MOD_PULSA_FIR, ATTR_DIMMED, 0);
err = SetCtrlAttribute (panel_principal, PANEL_MOD_PULSA_CONF, ATTR_DIMMED, 0);

// Se limpia el mensaje de error


err = SetCtrlVal (panel_principal, PANEL_MOD_TEXT_FALLO, "");

// Display
err = DefaultCtrl (panel_principal, PANEL_MOD_TEXT_FREC_2);
err = DefaultCtrl (panel_principal, PANEL_MOD_TEXT_FREC);
err = DefaultCtrl (panel_principal, PANEL_MOD_TEXT_MOD);
err = DefaultCtrl (panel_principal, PANEL_MOD_TEXT_VEL);
err = DefaultCtrl (panel_principal, PANEL_MOD_TEXT_VEL_2);
err = DefaultCtrl (panel_principal, PANEL_MOD_TEXT_SCR);
err = DefaultCtrl (panel_principal, PANEL_MOD_TEXT_COD);

// Inicialización para recuperar el marco anterior


inicio = SI;
puerto_control = 1;
inicializa(SI);
inicio = NO;
}
}
break;
}
return 0;
}
C.1 Aplicación modulAD 184

/****************************************************************************
MODULO: Recopilación de funciones hardware para la aplicacion de control
del modulador a partir del integrado AD9853
FICHERO: mod_hard.c VERSION: 1.0
-----------------------------------------------------------------------------
AUTOR: Juan Luis Tébar FECHA: 27 de Abril del 2000
-----------------------------------------------------------------------------
DESCRIPCION:
****************************************************************************/
#include <userint.h>
#include <ansi_c.h>
#include <utility.h>
#include "DLPORTIO.h"
#include "mod_def.h" // Defines de todo el proyecto
#include "mod_hard_.h"
#include "primo_63.h" // Contiene tablas del fabricante

// Variables importadas
// caracteres reservados para el envı́o de parámetros a los registros del modem
extern unsigned char control_modem[74];
extern unsigned char inicio;

// Bytes utilizados para la comunicación con el modulador. Se especifican como


// global al tenerlos que utilizar para la programación del generador de
// reloj de bit, además de para controlar el modulador
extern unsigned char byte_bajo, byte_alto;

// registros del puerto paralelo


extern unsigned long pp_datos; //Normalmente sólo escritura
extern unsigned long pp_estado; //lectura
extern unsigned long pp_control; //lectura y escritura, lı́neas fı́sicas "open colector"

// Variables globales propias


double esc, esc_old;

// Codificación de las funciones


/****************************************************************************
FUNCION: carga_pp
DESCRIPCION: Realiza la escritura de un byte en un registro de los circuitos
controlados mediante el puerto paralelo
PARAMETROS DE ENTRADA: dato: es el byte que se escribe
pcb: se refiere a la tarjeta destino: LATCH0 placa ber, LATCH1 placa mod
reg_pcb: registro concreto dentro de cada placa: CHIP0, ... , CHIP3
PARAMETROS DE SALIDA:
RESULTADO Y ERRORES: Entero -1 error; 0 todo bien
OBSERVACIONES: El puerto paralelo seleccionado para el envı́o depende del valor
de la variable global "puerto_control".
La escritura se realiza de forma que el valor a escribir esté en el
puerto antes de activar la carga, con el objetivo de no perturbar
aquellas salidas que afecten muy directamente al funcionamiento hardware
de los circuitos.
****************************************************************************/
int carga_pp (unsigned char dato, char pcb, char reg_pcb) {
static unsigned char byte;

//Escritura del dato en el puerto paralelo


DlPortWritePortUchar(pp_datos, dato);

//Selección del registro dentro de la placa


byte=DlPortReadPortUchar(pp_control);
byte=byte & 0xF0;
switch (reg_pcb) {
case CHIP0:
byte=byte | 0x8; // Selección de CHIP0
DlPortWritePortUchar(pp_control, byte);
break;
case CHIP1:
byte=byte | 0xC; // Selección de CHIP1
C.1 Aplicación modulAD 185

DlPortWritePortUchar(pp_control, byte);
break;
case CHIP2:
byte=byte | 0x0; // Selección de CHIP2 (Ya estaba seleccionado)
DlPortWritePortUchar(pp_control, byte);
break;
case CHIP3:
byte=byte | 0x4; // Selección de CHIP3
DlPortWritePortUchar(pp_control, byte);
break;
default: break;
}

// Activación de la linea chip_select en el registro en cuestión


if (pcb==LATCH0) {
byte=byte & 0xFC;
byte=byte | 0x1; // Selección de LATCH0
DlPortWritePortUchar(pp_control, byte);
}
if (pcb==LATCH1) {
byte=byte & 0xFC;
byte=byte | 0x2; // Selección de LATCH1
DlPortWritePortUchar(pp_control, byte);
}

// Dejamos el registro de control con los cuatro bits a 1


// ESTE ES EL MOMENTO EN QUE VERDADERAMENTE SE GRABA EL DATO DENTRO
// DE LOS REGISTROS, PUES SE CARGAN EN EL FLANCO DE SUBIDA
byte=byte & 0xFC; // valor final de reposo
DlPortWritePortUchar(pp_control, byte);

// Queda direccionado un registro inexistente


byte=byte & 0xF0;
byte=byte | 0x4; // Selección de CHIP3
DlPortWritePortUchar(pp_control, byte);

return 0;
}

/****************************************************************************
FUNCION: carga_reg_ser
DESCRIPCION:Realiza la secuencia de selección de registro dentro del integrado
AD9853 para posteriormente escribir o leer datos del mismo.
PARAMETROS DE ENTRADA:
reg: Registro al que se desea acceder a continuación.
PARAMETROS DE SALIDA: No hay
RESULTADO Y ERRORES: Entero -1 error, esclavo no contesta; 0 todo bien
OBSERVACIONES: En esta función se ejecuta la parte común de los ciclos de
lectura y escritura del chip AD9853 tal y como se describe en la página
13 de las hojas de datos del fabricante
****************************************************************************/
int carga_reg_ser(char reg) {
unsigned char un_byte, byte_s;
int n;

// Start.
// linea de reloj a alto
byte_alto = byte_alto | 0x80;
carga_pp(byte_alto, LATCH1, CHIP1);
// linea de datos a bajo
byte_alto = byte_alto & 0xBF; //Datos a uno
byte_alto = byte_alto & 0xDF; //Desactivación de tri-state
carga_pp(byte_alto, LATCH1, CHIP1);
byte_alto = byte_alto | 0x40; //Datos a cero (invierte el hardware)
carga_pp(byte_alto, LATCH1, CHIP1);
// linea de reloj a bajo
byte_alto = byte_alto & 0x7F;
carga_pp(byte_alto, LATCH1, CHIP1);
C.1 Aplicación modulAD 186

// Device Address 00000100, escritura


un_byte = 0x4;
for (n=0; n<8; n++) {
// datos, empezando por el bit mas significativo
if ((un_byte & 0x80)== NO) byte_alto = byte_alto | 0x40;// cero
else byte_alto = byte_alto & 0xBF; // uno
carga_pp(byte_alto, LATCH1, CHIP1);
un_byte = un_byte << 1; // Desplazamiento a la izquierda
// linea de reloj a alto
byte_alto = byte_alto | 0x80;
carga_pp(byte_alto, LATCH1, CHIP1);
// linea de reloj a bajo
byte_alto = byte_alto & 0x7F;
carga_pp(byte_alto, LATCH1, CHIP1);
}

// Recepción del acknowledge desde el modem esclavo


// linea de datos a alta impedancia
byte_alto = byte_alto | 0x20; //Activación de tri-state
carga_pp(byte_alto, LATCH1, CHIP1);
// reloj a alto
byte_alto = byte_alto | 0x80;
carga_pp(byte_alto, LATCH1, CHIP1);
// lectura de la linea de datos
byte_s=DlPortReadPortUchar(pp_estado);
// reloj a bajo
byte_alto = byte_alto & 0x7F;
carga_pp(byte_alto, LATCH1, CHIP1);
if (byte_s & 0x8) return -1; // esclavo no envió acknowledge

// Envı́o del código de direccion del registro


un_byte = reg;
byte_alto = byte_alto & 0xDF; //Desactivación de tri-state
carga_pp(byte_alto, LATCH1, CHIP1);
for (n=0; n<8; n++) {
// datos, empezando por el bit mas significativo
if ((un_byte & 0x80)== NO) byte_alto = byte_alto | 0x40;// cero
else byte_alto = byte_alto & 0xBF; // uno
carga_pp(byte_alto, LATCH1, CHIP1);
un_byte = un_byte << 1; //* 0x2; // Desplazamiento a la izquierda
// linea de reloj a alto
byte_alto = byte_alto | 0x80;
carga_pp(byte_alto, LATCH1, CHIP1);
// linea de reloj a bajo
byte_alto = byte_alto & 0x7F;
carga_pp(byte_alto, LATCH1, CHIP1);
}

// Recepción del acknowledge desde el modem esclavo


// linea de datos a alta impedancia
byte_alto = byte_alto | 0x20; //Activación de tri-state
carga_pp(byte_alto, LATCH1, CHIP1);
// reloj a alto
byte_alto = byte_alto | 0x80;
carga_pp(byte_alto, LATCH1, CHIP1);
// lectura de la linea de datos
byte_s=DlPortReadPortUchar(pp_estado);
// reloj a bajo
byte_alto = byte_alto & 0x7F;
carga_pp(byte_alto, LATCH1, CHIP1);
if (byte_s & 0x8) return -1; // esclavo no envió acknowledge

return 0;
}

/****************************************************************************
FUNCION: lee_ser
C.1 Aplicación modulAD 187

DESCRIPCION: Realiza la secuencia de leer datos a partir del registro


seleccionado previamente con la función carga_reg_ser, una cantidad de
registros igual al número de entrada
PARAMETROS DE ENTRADA:
reg_ini: registro del que se va a obtener el primer byte leı́do.
nro_reg: Número de registros a leer a partir del cargado como dirección
en la ejecución obligatoria anterior de la función carga_reg_ser.
PARAMETROS DE SALIDA: No hay
RESULTADO Y ERRORES: Entero -1 error; 0 todo bien
OBSERVACIONES: Los valores leı́dos se cargan en el array de caracteres global
control_modem[], con ı́ndice igual al del registro leı́do.
****************************************************************************/
int lee_ser(char reg_ini, char nro_reg) {
unsigned char un_byte, byte_s;
int n;
char m;

// Start.
// linea de reloj a alto
byte_alto = byte_alto | 0x80;
carga_pp(byte_alto, LATCH1, CHIP1);
// linea de datos a bajo
byte_alto = byte_alto & 0xBF; //Datos a uno
byte_alto = byte_alto & 0xDF; //Desactivación de tri-state
carga_pp(byte_alto, LATCH1, CHIP1);
byte_alto = byte_alto | 0x40; //Datos a cero (invierte el hardware)
carga_pp(byte_alto, LATCH1, CHIP1);
// linea de reloj a bajo
byte_alto = byte_alto & 0x7F;
carga_pp(byte_alto, LATCH1, CHIP1);

// Device Address 00000101, lectura


un_byte = 0x5;
for (n=0; n<8; n++) {
// datos, empezando por el bit mas significativo
if ((un_byte & 0x80)== NO) byte_alto = byte_alto | 0x40;// cero
else byte_alto = byte_alto & 0xBF; // uno
carga_pp(byte_alto, LATCH1, CHIP1);
un_byte = un_byte << 1; //* 0x2; // Desplazamiento a la izquierda
// linea de reloj a alto
byte_alto = byte_alto | 0x80;
carga_pp(byte_alto, LATCH1, CHIP1);
// linea de reloj a bajo
byte_alto = byte_alto & 0x7F;
carga_pp(byte_alto, LATCH1, CHIP1);
}

// Recepción del acknowledge desde el modem esclavo


// linea de datos a alta impedancia
byte_alto = byte_alto | 0x20; //Activación de tri-state
carga_pp(byte_alto, LATCH1, CHIP1);
// reloj a alto
byte_alto = byte_alto | 0x80;
carga_pp(byte_alto, LATCH1, CHIP1);
// lectura de la linea de datos
byte_s=DlPortReadPortUchar(pp_estado);
// reloj a bajo
byte_alto = byte_alto & 0x7F;
carga_pp(byte_alto, LATCH1, CHIP1);
if (byte_s & 0x8) return -1; // esclavo no envió acknowledge

// Inicio del bucle de lectura que se repite tantas veces como registros
// se van a leer, y viene indicado en el parámetro de entrada nro_reg
un_byte = 0x0;
for (m = reg_ini; m < (reg_ini + nro_reg); m++) {
// Puesto que seguimos leyendo datos desde el slave, la lı́nea debe de
// seguir en alta impedancia
// lectura de un byte
C.1 Aplicación modulAD 188

for (n=0; n<8; n++) {


// reloj a alto
byte_alto = byte_alto | 0x80;
carga_pp(byte_alto, LATCH1, CHIP1);
// lectura de la linea de datos, empezando por el bit mas significativo
byte_s=DlPortReadPortUchar(pp_estado);
// reloj a bajo
byte_alto = byte_alto & 0x7F;
carga_pp(byte_alto, LATCH1, CHIP1);
// formateo de los bits recibidos
un_byte = (byte_s & 0x8)? un_byte | 0x1 : un_byte & 0xFE;
// evitamos el último desplazamiento
if (n == 7) break;
un_byte = un_byte << 1; //* 0x2;
}
control_modem[m] = un_byte;
un_byte = 0x0;

// anulación del último acknowledge


if (m == (reg_ini + nro_reg - 1)) break;

// Generación del acknowledge desde el control


byte_alto = byte_alto & 0xDF; //Desactivación de tri-state
carga_pp(byte_alto, LATCH1, CHIP1);
// linea de datos a bajo
byte_alto = byte_alto | 0x40; //Datos a cero (invierte el hardware)
carga_pp(byte_alto, LATCH1, CHIP1);
// reloj a alto
byte_alto = byte_alto | 0x80;
carga_pp(byte_alto, LATCH1, CHIP1);
// linea de reloj a bajo
byte_alto = byte_alto & 0x7F;
carga_pp(byte_alto, LATCH1, CHIP1);
// linea de datos a alta impedancia
byte_alto = byte_alto | 0x20; //Activación de tri-state
carga_pp(byte_alto, LATCH1, CHIP1);
}

// No acknowledge desde el master para provocar que el modem salga del


// modo lectura
byte_alto = byte_alto & 0xDF; //Desactivación de tri-state
carga_pp(byte_alto, LATCH1, CHIP1);
// linea de datos a alto
byte_alto = byte_alto & 0xBF; //Datos a uno (invierte el hardware)
carga_pp(byte_alto, LATCH1, CHIP1);
// reloj a alto
byte_alto = byte_alto | 0x80;
carga_pp(byte_alto, LATCH1, CHIP1);
// linea de reloj a bajo
byte_alto = byte_alto & 0x7F;
carga_pp(byte_alto, LATCH1, CHIP1);

// Stop
// linea de datos a bajo
byte_alto = byte_alto | 0x40; //Datos a cero (invierte el hardware)
carga_pp(byte_alto, LATCH1, CHIP1);
// reloj a alto
byte_alto = byte_alto | 0x80;
carga_pp(byte_alto, LATCH1, CHIP1);
// linea de datos a alto, condición de STOP
byte_alto = byte_alto & 0xBF; //Datos a uno (invierte el hardware)
carga_pp(byte_alto, LATCH1, CHIP1);
// reloj a bajo
byte_alto = byte_alto & 0x7F;
carga_pp(byte_alto, LATCH1, CHIP1);
// linea de datos a alta impedancia
byte_alto = byte_alto | 0x20; //Activación de tri-state
carga_pp(byte_alto, LATCH1, CHIP1);
C.1 Aplicación modulAD 189

return 0;
}

/****************************************************************************
FUNCION: escribe_ser
DESCRIPCION: Realiza la secuencia de escribir datos en los registros del
modulador AD9853 a partir del registro seleccionado previamente con la
función carga_reg_ser.
PARAMETROS DE ENTRADA:
reg_ini: registro donde se va a escribir el primer byte.
nro_reg: Número de registros a escribir a partir del cargado como
dirección en la ejecución obligatoria anterior de la función carga_reg_ser.
PARAMETROS DE SALIDA: No hay
RESULTADO Y ERRORES: Entero -1 error; 0 todo bien
OBSERVACIONES: Los valores a escribir son los contenidos en el array de
caracteres global control_modem[], con ı́ndice igual al del registro
escrito.
****************************************************************************/
int escribe_ser(char reg_ini, char nro_reg) {
unsigned char un_byte, byte_s;
int n;
char m;

// Inicio del bucle de escritura que se repite tantas veces como registros
// se van a escribir, y viene indicado en el parámetro de entrada nro_reg
for (m = reg_ini; m < (reg_ini + nro_reg); m++) {
un_byte = control_modem[m];
//Desactivación de tri-state
byte_alto = byte_alto & 0xDF;
carga_pp(byte_alto, LATCH1, CHIP1);
for (n=0; n<8; n++) {
// datos, empezando por el bit mas significativo
if ((un_byte & 0x80)== NO) byte_alto = byte_alto | 0x40;// cero
else byte_alto = byte_alto & 0xBF; // uno
carga_pp(byte_alto, LATCH1, CHIP1);
un_byte = un_byte * 0x2; // Desplazamiento a la derecha
// linea de reloj a alto
byte_alto = byte_alto | 0x80;
carga_pp(byte_alto, LATCH1, CHIP1);
// linea de reloj a bajo
byte_alto = byte_alto & 0x7F;
carga_pp(byte_alto, LATCH1, CHIP1);
}
// Recepción del acknowledge desde el modem esclavo
// linea de datos a alta impedancia
byte_alto = byte_alto | 0x20; //Activación de tri-state
carga_pp(byte_alto, LATCH1, CHIP1);
// reloj a alto
byte_alto = byte_alto | 0x80;
carga_pp(byte_alto, LATCH1, CHIP1);
// lectura de la linea de datos
byte_s=DlPortReadPortUchar(pp_estado);
// reloj a bajo
byte_alto = byte_alto & 0x7F;
carga_pp(byte_alto, LATCH1, CHIP1);
if (byte_s & 0x8) return -1; // esclavo no envió acknowledge
}

//Desactivación de tri-state
byte_alto = byte_alto & 0xDF;
carga_pp(byte_alto, LATCH1, CHIP1);

// Stop
// linea de datos a bajo
byte_alto = byte_alto | 0x40; //Datos a cero (invierte el hardware)
carga_pp(byte_alto, LATCH1, CHIP1);
// reloj a alto
C.1 Aplicación modulAD 190

byte_alto = byte_alto | 0x80;


carga_pp(byte_alto, LATCH1, CHIP1);
// linea de datos a alto, condición de STOP
byte_alto = byte_alto & 0xBF; //Datos a uno (invierte el hardware)
carga_pp(byte_alto, LATCH1, CHIP1);
// reloj a bajo
byte_alto = byte_alto & 0x7F;
carga_pp(byte_alto, LATCH1, CHIP1);
// linea de datos a alta impedancia
byte_alto = byte_alto | 0x20; //Activación de tri-state
carga_pp(byte_alto, LATCH1, CHIP1);

return 0;
}

/****************************************************************************
FUNCION: activa_txe
DESCRIPCION: Realiza la secuencia de activación (puesta a uno) de la lı́nea TXE
del modulador AD9853. Se debe ejecutar una vez terminados de programar los
registros del integrado para habilitar el funcionamiento del mismo
PARAMETROS DE ENTRADA:
PARAMETROS DE SALIDA: No hay
RESULTADO Y ERRORES: Entero -1 error; 0 todo bien
OBSERVACIONES:
****************************************************************************/
int activa_txe (void) {
byte_alto = byte_alto | 0x10;
carga_pp(byte_alto, LATCH1, CHIP1);
return 0;
}

/****************************************************************************
FUNCION: desactiva_txe
DESCRIPCION: Realiza la desactivación (puesta a cero) de la linea TXE de control
del modulador AD9853. Es condición para programar los registros del chip
PARAMETROS DE ENTRADA:
PARAMETROS DE SALIDA: No hay
RESULTADO Y ERRORES: Entero -1 error; 0 todo bien
OBSERVACIONES:
****************************************************************************/
int desactiva_txe (void) {
byte_alto = byte_alto & 0xEF;
carga_pp(byte_alto, LATCH1, CHIP1);
return 0;
}

/****************************************************************************
FUNCION: reset_9853
DESCRIPCION: Realiza la secuencia de activar-desactivar la linea de reset
del modulador, como punto de partida para programar todos sus registros
a las condiciones de trabajo que se deseen
PARAMETROS DE ENTRADA:
PARAMETROS DE SALIDA: No hay
RESULTADO Y ERRORES: Entero -1 error; 0 todo bien
OBSERVACIONES:
****************************************************************************/
int reset_9853(void) {
byte_alto = byte_alto & 0xF7;
carga_pp(byte_alto, LATCH1, CHIP1);
Delay(0); // Regula la duración del pulso
byte_alto = byte_alto | 0x8;
carga_pp(byte_alto, LATCH1, CHIP1);
return 0;
}

/****************************************************************************
FUNCION: prog_hard
DESCRIPCION: Función base para la programación de los registros del integrado
C.1 Aplicación modulAD 191

PARAMETROS DE ENTRADA: reg_ini, primer registro a partir del cual se cargarán


datos en el chip.
char nro_reg, indica la cantidad de registros que se van a programar
a partir del primero, que se inicializa mediante la variable anterior.
PARAMETROS DE SALIDA:
RESULTADO Y ERRORES:
OBSERVACIONES: Se incluye una construcción "if" para diferenciar la carga
durante la primera inicialización, y los sucesivos cambios en la
programación del chip.
****************************************************************************/
int prog_hard(char reg_ini, char nro_reg) {
// Programación del hardware
if (inicio) {
carga_reg_ser(reg_ini);
escribe_ser(reg_ini, nro_reg);
}
else {
desactiva_txe();
carga_reg_ser(reg_ini);
escribe_ser(reg_ini, nro_reg);
activa_txe();
}
return 0;
}

/****************************************************************************
FUNCION: inicia_hard
DESCRIPCION: Inicialización de valores que no se modifican a lo largo de la
aplicación por ningún otra función, pero que son necesarios de cargar
a los registros del AD9853.
PARAMETROS DE ENTRADA:
PARAMETROS DE SALIDA:
RESULTADO Y ERRORES:
OBSERVACIONES:
****************************************************************************/
void inicia_hard() {
// Inicialización de la memoria de configuración
control_modem[RS_k]=0xFF;
control_modem[RS_t]=0x02; //RS OFF, Scrambler de 15 bits ON
control_modem[RAND_L]=0xFF; //Valores de inicio del scrambler todo unos
control_modem[RAND_H]=0xFF;

control_modem[LONG_PRE]=0x08; //Preámbulo de 4 bits


control_modem[PRE_0]=0xAA; //10101010
control_modem[PRE_1]=0xAA; //10101010
control_modem[PRE_2]=0xAA; //10101010
control_modem[PRE_3]=0xAA; //10101010
control_modem[PRE_4]=0xAA; //10101010
control_modem[PRE_5]=0xAA; //10101010
control_modem[PRE_6]=0xAA; //10101010
control_modem[PRE_7]=0xAA; //10101010
control_modem[PRE_8]=0xAA; //10101010
control_modem[PRE_9]=0xAA; //10101010
control_modem[PRE_A]=0xAA; //10101010
control_modem[PRE_B]=0x0A; //00001010

control_modem[CONF]=0x27; // Campo clave determinante del modo de funcionamiento


control_modem[GCB]=0xAA;
}

/****************************************************************************
FUNCION: frec_32
DESCRIPCION: Realiza el cálculo del valor a cargar en el registro de
frecuencia
PARAMETROS DE ENTRADA:
val_frec: Es el valor en Hz de la frecuencia a programar
n_bits: Número de bits del registro donde se cargará el valor.
reg: Registro donde cargar el valor calculado. Se necesita la dirección
C.1 Aplicación modulAD 192

"primera" del registro, es decir, la que corresponde a los bits menos


significativos: 0x16 para F0 y 0x1A para F1;
frec_ref: Valor en Hz de la frecuencia de reloj de referencia de la placa
PARAMETROS DE SALIDA: El valor calculado se graba en el array global
control_modem, que se utiliza como memoria intermedia entre las funciones
que calculan los valores y la función programa_hard, que es la que
realmente carga los datos en el integrado AD9853.
RESULTADO Y ERRORES: Ninguno
OBSERVACIONES: Esta función está dise~
nada para utilizarse en las direcciones
de los registros de frecuencia del chip. Si se ejecuta sobre otro registro
el resultado es imprevisible, ya que se carga el valor calculado sobre
ese registro.
Las direcciones de los registros de frecuencia del integrado AD9853 son:
F0: Direcciones 0x16 (lsb) hasta 0x19 (msb)
F1: Direcciones 0x1A (lsb) hasta 0x1D (msb)
****************************************************************************/
void frec_32(double val_frec, int n_bits, char reg, double frec_ref) {

static unsigned int valor;


static char byte, m, n;

// Cálculo del valor a programar en el registro


valor=(unsigned int)(val_frec * (pow (2.0, (double)n_bits))/(6.0 * frec_ref));

// Actualización de la memoria intermedia


m = reg;
for (n=0; n<4; n++, m++) {
byte = valor & 0xFF;
control_modem[m] = byte;
valor = valor >> 8; //Desplazamiento a la derecha un byte
}
}

/****************************************************************************
FUNCION: gen_bit_clk
DESCRIPCION: Realiza la programación del divisor que crea el reloj de bit
a partir de la frecuencia de referencia existente en la placa del modulador
PARAMETROS DE ENTRADA: .
div_1: número a programar en los divisores del oscilador de referencia
div_2: útil para calcular la velocidad de bit, ya que con él se incluye
el efecto de activar mediante el puente hardware JP3 3-4 la división
adicional por dos que introduce U7A.
frec_ref: double conteniendo la frecuencia de referencia utilizada
PARAMETROS DE SALIDA:
RESULTADO Y ERRORES: double con el valor final de reloj de bit programado.
OBSERVACIONES:
****************************************************************************/
double gen_bit_clk (int div_1, int div_2, double frec_ref) {
static unsigned short dos_bytes;
static unsigned char un_byte;
static int factor_div, n;
static double clk_bit;

// Cálculo del valor del reloj de bit


if (div_2==SI) n=2;
else n=1; //div_2==0
factor_div = div_1 * n;
clk_bit = frec_ref / (double)factor_div;

// Formateo para correcto funcionamiento del hardware


dos_bytes = (unsigned short)div_1;
dos_bytes = (dos_bytes ^ 0x7FF ) + 0x1; //Complemento a 2

// Primero se carga el byte menos significativo


byte_bajo= (unsigned char)(dos_bytes & 0xFF);
carga_pp(byte_bajo, LATCH1, CHIP0);
Delay(0.002);
C.1 Aplicación modulAD 193

// Después los últimos 3 bits más significativos


un_byte = (unsigned char)(dos_bytes >> 8) & 0x7;
byte_alto = byte_alto & 0xF8;
byte_alto = byte_alto | un_byte;
carga_pp(byte_alto, LATCH1, CHIP1);

return clk_bit;
}

/****************************************************************************
FUNCION: busca_esc
DESCRIPCION: Realiza una tarea de búsqueda de los parámetros de escalado de
la ganancia de cada etapa de interpolación en función del valor de
programación (sobremuestreo) de las mismas.
PARAMETROS DE ENTRADA: int I1, int I2, valor de la interpolación realizada
en cada una de las etapas.
PARAMETROS DE SALIDA:
RESULTADO Y ERRORES: Devuelve el valor resultante de ganancia parcial
correspondiente a los dos valores calculados.
Se actualiza el valor de las variables globales control_modem[INT1_SCALE]
y control_modem[INT2_SCALE], que sirven para programar la ganancia de los
interpoladores.
OBSERVACIONES: La carga del valor al que se actualizan las dos variables
globales dentro de los registros del AD9853 es responsabilidad de la
aplicación de usuario
****************************************************************************/
double busca_esc(int I1, int I2) {
static double gain_tot, gain_1;
static char int1, int2;

gain_tot = tabla_I1[I1].nom_gain * tabla_I2[I2].nom_gain;


if (gain_tot == 1.0) {
int1 = tabla_I1[I1].nominal;
int2 = tabla_I2[I2].nominal;
}
else {
gain_tot = tabla_I1[I1].alt_gain * tabla_I2[I2].nom_gain;
gain_1 = tabla_I1[I1].nom_gain * tabla_I2[I2].alt_gain;

if ((gain_tot < 1.0) && (gain_1 < 1.0)) {


gain_tot = tabla_I1[I1].nom_gain * tabla_I2[I2].nom_gain;
int1 = tabla_I1[I1].nominal;
int2 = tabla_I2[I2].nominal;
}
else if ((gain_tot > 1.0) && (gain_1 > 1.0)) {
if (gain_tot < gain_1) {
int1 = tabla_I1[I1].alt;
int2 = tabla_I2[I2].nominal;
}
else {
int1 = tabla_I1[I1].nominal;
int2 = tabla_I2[I2].alt;
gain_tot = gain_1;
}
}
else {
if (gain_tot > 1.0) {
int1 = tabla_I1[I1].alt;
int2 = tabla_I2[I2].nominal;
}
else {
int1 = tabla_I1[I1].nominal;
int2 = tabla_I2[I2].alt;
gain_tot = gain_1;
}
}
}
C.1 Aplicación modulAD 194

control_modem[INT1_SCALE] = int1 << 3;


control_modem[INT2_SCALE] = int2 << 2;

return gain_tot;
}

/****************************************************************************
FUNCION: interpolador
DESCRIPCION: Calcula el valor de interpolación de cada etapa para
sobremuestreo de los datos hasta acomodarlos a la frecuencia de reloj
del sistema dentro del AD9853
PARAMETROS DE ENTRADA: int div_1, int div_2, valores seleccionados en los
divisores.
int modulacion, tipo de modulación seleccionada
PARAMETROS DE SALIDA:
RESULTADO Y ERRORES:
0 No se produjo error
-1 Número resultante es primo "para los interpoladores" y por tanto
corresponde a un factor de interpolación total no válido
-2 El tipo de modulación es FSK. En este caso la función no tiene
ningún efecto.
-3 El tipo de modulación es QPSK y el valor de división total es
mayor de 651.
-4 El tipo de modulación es 16QAM y el valor de división total es
mayor de 325.

El valor calculado de factor de interpolación de cada etapa se queda


almacenado en las variables globales control_modem[INT1_RATE] y
control_modem[INT2_RATE]. La carga de estos dos valores dentro de los
registros del AD9853 es responsabilidad de la aplicación de usuario

OBSERVACIONES: Se actualizan las variables globales esc y esc_old de


escalado de la cadena de filtro de datos, útiles para reescalar los
coefificentes de la etapa FIR y compensar de este modo el camino
completo para que la ganancia total sea 1.
****************************************************************************/
int interpolador (int *div_1, int div_2, int modulacion) {
static int factor_I1I2, factor_I1, factor_I2;
static int n, hecho, correccion;
static short dos_bytes;

if (modulacion == FSK) return -2; //La función no tiene efecto

hecho=NO;
correccion=NO;
do {
// Cálculo del factor de interpolación global
if (div_2==SI) factor_I1I2 = *div_1 * 2;
else factor_I1I2 = *div_1; // División total realizada en generador de reloj de bit

if (modulacion == QPSK) {
factor_I1I2 = factor_I1I2 * 3; //QPSK
if (factor_I1I2 > 1953) {
if (div_2==SI) *div_1=325;
else *div_1=651;
correccion=33;
}
}
else {
factor_I1I2 = factor_I1I2 * 6; //16QAM
if (factor_I1I2 > 1953) {
if (div_2==SI) *div_1=162;
else *div_1=325;
correccion=66;
}
}

// Comprobación de que el valor no es "primo" para los interpoladores


C.1 Aplicación modulAD 195

for (n=0; n<229; n++) {


if ((primo_63[n] < factor_I1I2)&&( factor_I1I2 < primo_63[n+1])) {
hecho=SI;
break;
}
else if ((primo_63[n] == factor_I1I2)||(primo_63[n+1] == factor_I1I2)) {
correccion=SI;
*div_1= *div_1 - 1;
break;
}
else if (factor_I1I2>647) {
correccion=SI;
*div_1= *div_1 - 1;
break;
}
}
} while (!hecho);

// Cálculo de los factores especı́ficos


factor_I1 = sqrt(factor_I1I2) + 1;
if (factor_I1 > 31) factor_I1 = 31;
for (;;factor_I1--) {
factor_I2 = factor_I1I2 / factor_I1;
if ((factor_I1 * factor_I2 == factor_I1I2) || (factor_I2 > 63)) break;
factor_I2++;
if ((factor_I1 * factor_I2 == factor_I1I2) || (factor_I2 > 63)) break;
}
if (factor_I2 > 63) factor_I2 = 63;

// Aunque no esté bién calculado, el valor se actualiza siempre


control_modem[INT1_RATE] = factor_I1 << 2;
control_modem[INT2_RATE] = factor_I2 << 1;

// Cálculo de los dos factores de escala. El valor se almacena en la memoria de


// configuración
esc_old = 1 / esc;
esc = busca_esc(factor_I1, factor_I2);
// Falta escalar los 40 coeficientes del filtro FIR
esc = 1 / esc;

// if (factor_I1 * factor_I2 != factor_I1I2) return -1;


if (correccion) return -1;
else if (correccion==33) return -3;
else if (correccion==66) return -4;
else return 0;
}

/****************************************************************************
FUNCION: busca_equipo_mod
DESCRIPCION: Función que se ejecuta únicamente para comprobar la correcta
conexión de la placa de medición de BER
PARAMETROS DE ENTRADA:
PARAMETROS DE SALIDA:
RESULTADO Y ERRORES: int 1 si la placa funciona correctamente, 0 si no se
encuentra (porque no está alimentada, o no conectada al puerto paralelo)
OBSERVACIONES:
****************************************************************************/
int busca_equipo_mod(void) {
static unsigned char byte_s, cero, uno;

//Reescritura del byte_bajo


//carga_pp(byte_bajo, LATCH1, CHIP0);

//Escribimos cero
byte_alto = byte_alto & 0xDF; //Desactivación de tri-state
carga_pp(byte_alto, LATCH1, CHIP1);
byte_alto = byte_alto | 0x40; // cero
carga_pp(byte_alto, LATCH1, CHIP1);
C.1 Aplicación modulAD 196

// lectura de la linea de datos


byte_s=DlPortReadPortUchar(pp_estado);

// linea de datos a alta impedancia


byte_alto = byte_alto | 0x20; //Activación de tri-state
carga_pp(byte_alto, LATCH1, CHIP1);

if (byte_s & 0x8) cero = MAL;


else cero = BIEN;

// Escribimos uno
byte_alto = byte_alto & 0xDF; //Desactivación de tri-state
carga_pp(byte_alto, LATCH1, CHIP1);
byte_alto = byte_alto & 0xBF; // uno
carga_pp(byte_alto, LATCH1, CHIP1);

// lectura de la linea de datos


byte_s=DlPortReadPortUchar(pp_estado);

// linea de datos a alta impedancia


byte_alto = byte_alto | 0x20; //Activación de tri-state
carga_pp(byte_alto, LATCH1, CHIP1);

if (byte_s & 0x8) uno = BIEN;


else uno = MAL;

if ((cero == MAL) || (uno == MAL)) return NO;


else return SI;
}
C.2 Aplicación mediBER 197

C.2. Aplicación mediBER


Ficheros ber.c y ber hard.c
/****************************************************************************
INTERFAZ: Fichero fuente principal de la aplicación.
FICHERO: ber.c VERSION: 1.0
-----------------------------------------------------------------------------
AUTOR: Juan Luis Tébar FECHA: 22 Marzo del 2000
-----------------------------------------------------------------------------
DESCRIPCION: Programa de control de la place de generación de secuencias
pseudoaleatorias y medida de tasa de BER. El control se realiza a través
del puerto paralelo del PC.
****************************************************************************/
#include <ansi_c.h>
#include <formatio.h>
#include <cvirte.h>
#include <userint.h>
#include <utility.h>
#include "dlportio.h"
// Interfaz para acceder al hardware desde windows
#include "ber_def.h"
#include "ber.h"
#include "ber_hard.h"

//DECLARACION DE FUNCIONES
void inicializa(void);

//VARIABLES GLOBALES
static int panel_ber, panel_sec, err;
char puerto_control;
double tiempo_fin_test, tiempo_test;

// Envı́o de parámetros a los registros del chip DS2172


unsigned char control_bert[29];

// Bytes utilizados para la comunicación con la placa de BERT.


unsigned char byte_control, byte_datos;

// registros del puerto paralelo


unsigned long pp_datos; //Normalmente sólo escritura
unsigned long pp_estado; //lectura
unsigned long pp_control; //lectura y escritura

// Variables de ajuste dentro del bucle periódico. Se hacen globales para poder
// controlar el punto de ejecución al seleccionar algunas opciones de operacion
char hay_test, cambio_sec, primer_seg;

// Variables pasadas a globales para la generación del fichero de report


int err_ins;
double es, ses, dm, ber, esr, sesr, dmr, n_canales;
double bits_rx_total, bits_err_total, vel_datos;

// Paso de la secuencia de usuario al módulo hardware


unsigned long sec_usuario;

// Comprobación de la existencia fı́sica de la placa


char hay_placa_ber, primer_bucle;

int main (int argc, char *argv[]) {


// Inicio estándar de Labwindows y carga de los paneles de la aplicación
if (InitCVIRTE (0, argv, 0) == 0)
return -1; /* out of memory */
if ((panel_ber = LoadPanel (0, "ber.uir", BER)) < 0)
return -1;
if ((panel_sec = LoadPanel (0, "ber.uir", SEC)) < 0)
return -1;
C.2 Aplicación mediBER 198

// Utilizamos el puerto paralelo LPT1


puerto_control = 1;
inicializa();

// Consideramos que la placa está correctamente conectada en principio


hay_placa_ber = SI;
primer_bucle = SI;

// Inicio y actualización de las variables del entorno gráfico


hay_test = NO;
cambio_sec = NO;
TipoSecuencia(panel_ber, BER_TIPO_SECUENCIA, EVENT_COMMIT, 0, 0, 0);
DuracionTest(panel_ber, BER_DURACION_TEST, EVENT_COMMIT, 0, 0, 0);
ErrorAuto(panel_ber, BER_ERROR_AUTO, EVENT_COMMIT, 0, 0, 0);
StringSec(panel_ber, BER_TIPO_SECUENCIA, EVENT_COMMIT, 0, 0, 0);

// Arranque del entorno


DisplayPanel (panel_ber);
RunUserInterface ();
return 0;
}

/****************************************************************************
DESCRIPCION DE LAS FUNCIONES
****************************************************************************/
/****************************************************************************
FUNCION: inicializa
DESCRIPCION: Realiza la secuencia de inicialización de la aplicación
PARAMETROS DE ENTRADA: No
PARAMETROS DE SALIDA: No
RESULTADO Y ERRORES: Ninguno
OBSERVACIONES:
****************************************************************************/
void inicializa(void) {
unsigned char byte, n;

// Selección del puerto paralelo de control


if (puerto_control==1) pp_datos=LPT1;
else pp_datos=LPT2;
pp_estado=pp_datos+1;
pp_control=pp_datos+2;

// Inicialización del puerto paralelo


byte=0x0;
DlPortWritePortUchar(pp_datos, byte);
byte=DlPortReadPortUchar(pp_estado);
byte=DlPortReadPortUchar(pp_control);
byte=byte & 0xF0;
byte=byte | 0x8;
DlPortWritePortUchar(pp_control, byte);

// Arranque inicial del bert. Para que se cargen los parámetros por defecto
inicia_hard_bert();
}

/****************************************************************************
DESCRIPCION DE FUNCIONES CVICALLBACK
****************************************************************************/
/****************************************************************************
FUNCION: TipoSecuencia
DESCRIPCION: Selector de la secuencia utilizada al realizar el test de BER
PARAMETROS DE ENTRADA: Los tı́picos de las funciones callback de Labwindows
PARAMETROS DE SALIDA:
RESULTADO Y ERRORES: 0 todo OK
OBSERVACIONES: Si se cambia de secuencia mientras el test está arrancado,
éste se vuelve a reiniciar.
****************************************************************************/
C.2 Aplicación mediBER 199

int CVICALLBACK TipoSecuencia (int panel, int control, int event,


void *callbackData, int eventData1, int eventData2)
{
static int secuencia, habia_test;

if (hay_test) habia_test=SI;
else habia_test=NO;

switch (event) {
case EVENT_COMMIT:
// Cambio de variable para mensajes
cambio_sec = SI;
// Se detiene el test para reprogramar
StopTest(panel_ber, BER_STOP_TEST, EVENT_COMMIT, 0, 0, 0);
// Actualización de la configuración del bert
err = GetCtrlVal(panel_ber, BER_TIPO_SECUENCIA, &secuencia);
prog_sec(secuencia, sec_usuario);
// Si el test estaba corriendo se reinicia
if (habia_test) IniciaTest(panel_ber, BER_RUN_TEST, EVENT_COMMIT, 0, 0, 0);
// Cambio de variable para mensajes
cambio_sec = NO;
break;
case EVENT_RIGHT_CLICK:
MessagePopup ("Selector de \"Secuencia patrón\"",
"Permite la selección de la secuencia pseudoaleatoria o repetitiva\n"
"con la que se trabajará al realizar el tests.");
break;
}
return 0;
}

/****************************************************************************
FUNCION: DuracionTest
DESCRIPCION: Selección de la duración del test
PARAMETROS DE ENTRADA: Los tı́picos de las funciones callback de Labwindows
PARAMETROS DE SALIDA:
RESULTADO Y ERRORES: 0 todo OK
OBSERVACIONES: Actualización de la variable global que gobierna la duración
de los test "tiempo_fin_test"
****************************************************************************/
int CVICALLBACK DuracionTest (int panel, int control, int event,
void *callbackData, int eventData1, int eventData2)
{
static int min_test;

switch (event) {
case EVENT_COMMIT:
// Lectura del valor seleccionado.
err = GetCtrlVal(panel_ber, BER_DURACION_TEST, &min_test);
// Actualización de la variable global (representa el tiempo en
// segundos)
tiempo_fin_test = 60.0 * min_test;
break;
case EVENT_RIGHT_CLICK:
MessagePopup ("Selector de \"Duración del test\"",
"Selección del tiempo durante el que se realiza la prueba\n"
"de BER de entre unos perı́odos determinados.");
break;
}
return 0;
}

/****************************************************************************
FUNCION: ErrorAuto
DESCRIPCION: Activa en el DS2172 la inserción automática de errores para
obtener una tasa de BER determinada
PARAMETROS DE ENTRADA: Los tı́picos de las funciones callback de Labwindows
PARAMETROS DE SALIDA:
C.2 Aplicación mediBER 200

RESULTADO Y ERRORES: 0 todo OK


OBSERVACIONES:
****************************************************************************/
int CVICALLBACK ErrorAuto (int panel, int control, int event,
void *callbackData, int eventData1, int eventData2)
{
static unsigned char valor_err_auto;

switch (event) {
case EVENT_COMMIT:
// Lectura del valor seleccionado.
err = GetCtrlVal(panel_ber, BER_ERROR_AUTO, &valor_err_auto);
error_auto(valor_err_auto);
break;
case EVENT_RIGHT_CLICK:
MessagePopup ("Selector de \"Errores automáticos\"",
"Producción automática de errores hasta "
"conseguir la tasa de BER indicada.");
break;
}
return 0;
}

/****************************************************************************
FUNCION: SecUser
DESCRIPCION: Hace visible u oculta el panel donde se programa la secuencia
repetitiva de usuario.
PARAMETROS DE ENTRADA: Los tı́picos de las funciones callback de Labwindows
PARAMETROS DE SALIDA:
RESULTADO Y ERRORES: 0 todo OK
OBSERVACIONES:
****************************************************************************/
int CVICALLBACK SecUser (int panel, int control, int event,
void *callbackData, int eventData1, int eventData2)
{
static char panel_visible;

switch (event) {
case EVENT_COMMIT:
if (panel_visible) {
HidePanel(panel_sec);
panel_visible = NO;
}
else {
DisplayPanel (panel_sec);
panel_visible = SI;
}
break;
case EVENT_RIGHT_CLICK:
MessagePopup ("Pulsador \"Secuencia usuario\"",
"Hace visible u oculta el panel de selección de la secuencia "
"repetitiva de usuario.");
break;
}
return 0;
}

/****************************************************************************
FUNCION: InsertaError
DESCRIPCION: Provoca la inserción o transmisión intencionada de un único
error en la secuencia de salida.
PARAMETROS DE ENTRADA: Los tı́picos de las funciones callback de Labwindows
PARAMETROS DE SALIDA:
RESULTADO Y ERRORES: 0 todo OK
OBSERVACIONES:
****************************************************************************/
int CVICALLBACK InsertaError (int panel, int control, int event,
void *callbackData, int eventData1, int eventData2)
C.2 Aplicación mediBER 201

{
switch (event) {
case EVENT_COMMIT:
if (hay_test) {
inserta_error();
err_ins++; //Contador para informes
SetCtrlVal (panel_ber, BER_EVENTOS,
"\nError insertado por el usuario");
}
break;
case EVENT_RIGHT_CLICK:
MessagePopup ("Pulsador \"Insertar error\"",
"Inserción manual de un error en la secuencia de salida.");
break;
}
return 0;
}

/****************************************************************************
FUNCION: GrabaRes
DESCRIPCION: Genera un fichero de texto a modo de informe con los resultados
que actualente presentan los indicadores de la aplicación.
PARAMETROS DE ENTRADA: Función callback
PARAMETROS DE SALIDA:
RESULTADO Y ERRORES: 0 todo OK
OBSERVACIONES: El fichero generado se crea en modo escritura, de modo que si
existe un fichero anterior con el mismo nombre se perderá este último.
****************************************************************************/
int CVICALLBACK GrabaRes (int panel, int control, int event,
void *callbackData, int eventData1, int eventData2)
{
static char nombre_file[MAX_PATHNAME_LEN], proj_dir[MAX_PATHNAME_LEN];
static int pfile;
static char aux[MAX_LONG_STRING];

static int index;

switch (event) {
case EVENT_COMMIT:
GetProjectDir (proj_dir);
if (FileSelectPopup (proj_dir, "*.txt", "*.txt",
"Nombre del Fichero de Informe",
VAL_OK_BUTTON, 0, 1, 1, 0, nombre_file) > 0) {

// Abrimos el fichero donde se grabarán los resultados del test


pfile = OpenFile(nombre_file, VAL_READ_WRITE, VAL_TRUNCATE, VAL_ASCII);

// Texto del fichero de resultados del test


FmtFile (pfile, "%s",
"\tRESULTADOS DE LA PRUEBA DE MEDIDA DE TASA DE BER\n\n\n");
FmtFile (pfile, "%s<%s%s%s",
"Fecha del test (mes-dı́a-a~
no):\t\t\t", DateStr (), "\n");
FmtFile (pfile, "%s<%s%s%s",
"Hora del test:\t\t\t\t\t", TimeStr (), "\n\n");

// Valores programados
err = GetCtrlIndex (panel_ber, BER_TIPO_SECUENCIA, &index);
err = GetLabelFromIndex (panel_ber, BER_TIPO_SECUENCIA, index, aux);
FmtFile (pfile, "%s<%s%s%s",
"Tipo de secuencia utilizada:\t\t\t", aux, "\n");
err = GetCtrlIndex (panel_ber, BER_DURACION_TEST, &index);
err = GetLabelFromIndex (panel_ber, BER_DURACION_TEST, index, aux);
FmtFile (pfile, "%s<%s%s%s",
"Tiempo de duración programada del test:\t\t", aux, "\n");
err = GetCtrlIndex (panel_ber, BER_ERROR_AUTO, &index);
err = GetLabelFromIndex (panel_ber, BER_ERROR_AUTO, index, aux);
FmtFile (pfile, "%s<%s%s%s",
"Inserción de errores automáticos:\t\t", aux, "\n\n");
C.2 Aplicación mediBER 202

// Datos de interés
err = GetCtrlVal (panel_sec, SEC_STRING_SEC, aux);
FmtFile (pfile, "%s<%s%s%s",
"Secuencia de usuario programada:\t\t", aux, "\n");

Fmt (aux, "%s<%d", err_ins);


FmtFile (pfile, "%s<%s%s%s",
"Errores insertados manualmente:\t\t\t", aux, "\n\n");

// Valores resultantes
err = GetCtrlVal (panel_ber, BER_IND_TIEMPO_TEST, aux);
FmtFile (pfile, "%s<%s%s%s",
"Tiempo de duración real del test:\t\t", aux, "\n");

err = GetCtrlVal (panel_ber, BER_IND_TIEMPO_DISPON, aux);


FmtFile (pfile, "%s<%s%s%s",
"Tiempo de disponibilidad durante test:\t\t", aux, "\n");

// Fmt (aux, "%s<%f[p1]", vel_datos);


// FmtFile (pfile, "%s<%s%s%s%s",
// "Velocidad estimada de transmisión de datos:\t", aux, " bps", "\n");

Fmt (aux, "%s<%f[p0]", bits_rx_total);


FmtFile (pfile, "%s<%s%s%s",
"Número total de bits recibidos:\t\t\t", aux, "\n");

Fmt (aux, "%s<%f[p0]", bits_err_total);


FmtFile (pfile, "%s<%s%s%s",
"Número total de bits erróneos:\t\t\t", aux, "\n\n");

Fmt (aux, "%s<%f[p2]", es);


FmtFile (pfile, "%s<%s%s%s",
"Número de segúndos erróneos (ES):\t\t", aux, "\n");

Fmt (aux, "%s<%f[b4p2r]%s", esr, " %");


FmtFile (pfile, "%s<%s%s%s",
"% de segundos erróneos (ES):\t\t\t", aux, "\n");

Fmt (aux, "%s<%f[p0]", ses);


FmtFile (pfile, "%s<%s%s%s",
"Número de segúndos severamente erróneos (SES):\t", aux, "\n");

Fmt (aux, "%s<%f[b4p2r]%s", sesr, " %");


FmtFile (pfile, "%s<%s%s%s",
"% de segundos severamente erróneos (SES):\t", aux, "\n");

Fmt (aux, "%s<%f[p0]", dm);


FmtFile (pfile, "%s<%s%s%s",
"Número de minutos degradados (DM):\t\t", aux, "\n");

Fmt (aux, "%s<%f[b4p2r]%s", dmr, " %");


FmtFile (pfile, "%s<%s%s%s",
"% de minutos degradados (DM):\t\t\t", aux, "\n\n");

Fmt (aux, "%s<%f[b4p4e2]", ber);


FmtFile (pfile, "%s<%s%s%s",
"Tasa de bits erróneos (BER):\t\t\t", aux, "\n");

err = CloseFile (pfile);


}
break;
case EVENT_RIGHT_CLICK:
MessagePopup ("Pulsador \"Grabar resultados\"",
"Generación de un fichero de texto con los resultados del test.");
break;
}
return 0;
C.2 Aplicación mediBER 203

/****************************************************************************
FUNCION: IniciaTest
DESCRIPCION: Activación de las medidas.
PARAMETROS DE ENTRADA: Los tı́picos de las funciones callback de Labwindows
PARAMETROS DE SALIDA:
RESULTADO Y ERRORES: 0 todo OK
OBSERVACIONES:
****************************************************************************/
int CVICALLBACK IniciaTest (int panel, int control, int event,
void *callbackData, int eventData1, int eventData2)
{
switch (event) {
case EVENT_COMMIT:
// Actualización de variables del entorno
hay_test = SI;
primer_seg = SI;
// Inicio del contador de errores manuales para report
err_ins = 0;

// Detalles del entorno gráfico


if (cambio_sec == NO) {
ResetTextBox (panel_ber, BER_EVENTOS, "");
SetCtrlVal (panel_ber, BER_EVENTOS,
"Test iniciado por el usuario\n");
}
if (cambio_sec == SI) {
ResetTextBox (panel_ber, BER_EVENTOS, "");
SetCtrlVal (panel_ber, BER_EVENTOS,
"Test iniciado por cambio en la secuencia utilizada\n");
}
DefaultCtrl (panel_ber, BER_IND_TIEMPO_TEST);
DefaultCtrl (panel_ber, BER_IND_TIEMPO_DISPON);
DefaultCtrl (panel_ber, BER_IND_NRO_BITS);
DefaultCtrl (panel_ber, BER_IND_NRO_BITS_ERR);
DefaultCtrl (panel_ber, BER_IND_ES);
DefaultCtrl (panel_ber, BER_IND_SES);
DefaultCtrl (panel_ber, BER_IND_DM);
DefaultCtrl (panel_ber, BER_IND_BER);
// Cambios hardware para activar el test
inicia_test();
// Se resetea el temporizador
ResetTimer (panel_ber, BER_TIMER);
break;
case EVENT_RIGHT_CLICK:
MessagePopup ("Pulsador \"Iniciar Test\"",
"Activación de la secuencia de salida e inicio de las medidas.");
break;
}
return 0;
}

/****************************************************************************
FUNCION: StopTest
DESCRIPCION: Finalización de las medidas.
PARAMETROS DE ENTRADA: Los tı́picos de las funciones callback de Labwindows
PARAMETROS DE SALIDA:
RESULTADO Y ERRORES: 0 todo OK
OBSERVACIONES:
****************************************************************************/
int CVICALLBACK StopTest (int panel, int control, int event,
void *callbackData, int eventData1, int eventData2)
{
switch (event) {
case EVENT_COMMIT:
// Cambios hardware para detener el test
stop_test();
C.2 Aplicación mediBER 204

// Control de los mensajes


if (hay_test) {
if (tiempo_test < tiempo_fin_test) {
if (cambio_sec == NO) SetCtrlVal (panel_ber, BER_EVENTOS,
"\nTest detenido por el usuario");
}
}
// Actualización de variables del entorno
hay_test = NO;
break;
case EVENT_RIGHT_CLICK:
MessagePopup ("Pulsador \"Detener Test\"",
"Desactivación de la secuencia de salida y fin de las medidas.");
break;
}
return 0;
}

/****************************************************************************
FUNCION: Salida
DESCRIPCION: Finaliza la aplicación
PARAMETROS DE ENTRADA: Los tı́picos de las funciones callback de Labwindows
PARAMETROS DE SALIDA:
RESULTADO Y ERRORES: 0 todo OK
OBSERVACIONES:
****************************************************************************/
int CVICALLBACK Salida (int panel, int control, int event,
void *callbackData, int eventData1, int eventData2)
{
switch (event) {
case EVENT_COMMIT:
QuitUserInterface (0);
break;
case EVENT_RIGHT_CLICK:
MessagePopup ("Pulsador \"Salida Programa\"",
"Fin de aplicación y cierre del entorno gráfico.");
break;
}
return 0;
}

/****************************************************************************
FUNCION: StringSec
DESCRIPCION: Entrada de la secuencia arbitraria de ususario
PARAMETROS DE ENTRADA: Los tı́picos de las funciones callback de Labwindows
PARAMETROS DE SALIDA:
RESULTADO Y ERRORES: 0 todo OK
OBSERVACIONES:
****************************************************************************/
int CVICALLBACK StringSec (int panel, int control, int event,
void *callbackData, int eventData1, int eventData2)
{
static char sec[9], mensaje[80], *fin;
static double valor;
static int secuencia;

switch (event) {
case EVENT_COMMIT:
err = GetCtrlVal(panel_sec, SEC_STRING_SEC, sec);
sec_usuario = strtoul (sec, &fin, 16);
if (*fin != NULL) {
sprintf(mensaje,
"El valor %s no se puede convertir a número hexadecimal", fin);
MessagePopup ("¡ Error al convertir la secuencia !", mensaje);
DefaultCtrl (panel_sec, SEC_STRING_SEC);
}
err = GetCtrlVal(panel_ber, BER_TIPO_SECUENCIA, &secuencia);
if (secuencia == 34) TipoSecuencia(panel_ber,
C.2 Aplicación mediBER 205

BER_TIPO_SECUENCIA, EVENT_COMMIT, 0, 0, 0);


break;
case EVENT_RIGHT_CLICK:
MessagePopup ("Selector de \"Secuencia de usuario\"",
"Permite la introducción de la secuencia repetitiva que se "
"usa al seleccionar \nel \"Patrón de usuario\" en el selector "
"de secuencia patrón.");
break;
}
return 0;
}

/****************************************************************************
FUNCION: PulsaSecOk
DESCRIPCION: Cierra el panel de selección de la secuencia de usuario
PARAMETROS DE ENTRADA: Los tı́picos de las funciones callback de Labwindows
PARAMETROS DE SALIDA:
RESULTADO Y ERRORES: 0 todo OK
OBSERVACIONES:
****************************************************************************/
int CVICALLBACK PulsaSecOk (int panel, int control, int event,
void *callbackData, int eventData1, int eventData2)
{
switch (event) {
case EVENT_COMMIT:
SecUser (panel_ber, BER_PUL_SEC_USER, EVENT_COMMIT, 0, 0, 0);
break;
case EVENT_RIGHT_CLICK:
MessagePopup ("Pulsador \"CERRAR\"",
"Cierre del panel de selección de la secuencia de usuario.");
break;
}
return 0;
}

/****************************************************************************
FUNCION: Bucle
DESCRIPCION: Función principal de la aplicación. Se ejecuta automáticamente
cada segundo, y en ella se realizan varias tareas importantes como la
medición de bits y errores recibidos para calcular todos los indicadores
del test, ası́ como la vigilancia para determinar si la placa de hardware
está correctamente controlada
PARAMETROS DE ENTRADA: Los tı́picos de las funciones callback de Labwindows
PARAMETROS DE SALIDA:
RESULTADO Y ERRORES: 0 todo OK
OBSERVACIONES: Si se determina que la placa no se puede controlar, se detiene
el test y se inhabilitan los controles del entorno gráfico.
Los resultados calculados de tasa de BER y demás inicadores se
almacenan en variables globales para poder ser recuperadas al generar el
fichero de informe.
****************************************************************************/
int CVICALLBACK Bucle (int panel, int control, int event,
void *callbackData, int eventData1, int eventData2)
{
static double seg, min_t, min, horas_t, horas, dias;
static double tiempo_dis;
static double seg_dis, min_t_dis, min_dis, horas_t_dis, horas_dis, dias_dis;

static char txt_tiempo_test[40], txt_tiempo_dis[40],


txt_bits_rx[40], txt_bits_err[40];
static char txt_es[40], txt_ses[40], txt_dm[40], txt_ber[40];
//Se hacen globales para poder generar el fichero de report
// static double es, ses, dm, ber, esr, sesr, dmr;

static int secuencia;


static t_datos datos_estado;

static double bits_rx_dis[10], bits_err_dis[10], bits_rx_dm[60], bits_err_dm[60];


C.2 Aplicación mediBER 206

//Se hacen globales para generar el fichero de report


// static double bits_rx_total, bits_err_total;
static double ber_i, bits_rx_acumul, bits_err_acumul, es_acumul, es_mx[10];
static char es_i, ses_i, ses_acumul, ses_mx[10], n, index_dm;
static char alarma, disponibilidad, cambio_periodo, periodo_anterior;
static double ber_60, bits_rx_60, bits_err_60;

// Adaptación de la aplicación a velocidades de transmisión mayores de 64 kbps


static double es_i_0;

if (event == EVENT_TIMER_TICK) {
hay_placa_ber = busca_equipo_ber();
if (hay_placa_ber) {

if (primer_bucle == NO) {
primer_bucle = SI; // Control de ejecución del bucle

// Display en la pantalla de mensajes


SetCtrlVal (panel_ber, BER_EVENTOS,
"\nRecuperado el control de la placa de BER\n\n");

// Habilitación de los controles


err = SetCtrlAttribute (panel_ber, BER_TIPO_SECUENCIA, ATTR_DIMMED, 0);
err = SetCtrlAttribute (panel_ber, BER_DURACION_TEST, ATTR_DIMMED, 0);
err = SetCtrlAttribute (panel_ber, BER_ERROR_AUTO, ATTR_DIMMED, 0);
err = SetCtrlAttribute (panel_ber, BER_RUN_TEST, ATTR_DIMMED, 0);
err = SetCtrlAttribute (panel_ber, BER_STOP_TEST, ATTR_DIMMED, 0);
err = SetCtrlAttribute (panel_ber, BER_PUL_INSERT_ERR, ATTR_DIMMED, 0);
err = SetCtrlAttribute (panel_ber, BER_PUL_SEC_USER, ATTR_DIMMED, 0);
err = SetCtrlAttribute (panel_ber, BER_LED_SINCRO, ATTR_DIMMED, 0);
err = SetCtrlAttribute (panel_ber, BER_LED_UNOS, ATTR_DIMMED, 0);
err = SetCtrlAttribute (panel_ber, BER_LED_CEROS, ATTR_DIMMED, 0);
}

switch (hay_test) {
case SI:
tiempo_test++;
GetCtrlVal(panel_ber, BER_TIPO_SECUENCIA, &secuencia);
// Deshecho de la primera lectura de información desde el chip
if (primer_seg) {
primer_seg = NO;
cambio_periodo = NO;
// Limpiamos los registros del integrado
aplicacion_bert(&datos_estado, secuencia);
// Inicializamos las variables de estadı́stica
tiempo_test = tiempo_dis = 0.0;
datos_estado.bits_rx = 0.0;
datos_estado.bits_err = 0.0;
es = ses = dm = ber = bits_rx_total = bits_err_total = 0.0;
ber_i = ber_60 = 0.0;
disponibilidad = SI;
// Indica estado de disponibilidad del segundo anterior
periodo_anterior = DISPONIBLE;

for (n=0; n<10; n++) {


ses_mx[n] = 0;
es_mx[n] = 0;
bits_rx_dis[n] = 0.0;
bits_err_dis[n] = 0.0;
}
// Inicialización del almacenamiento de datos para determinación
//de la proporción de minutos degradados
index_dm = 0;
n_canales = 1; // Evita fallo al inicio del test
break;
}
// Resto del tiempo del test
// Lectura de registros del hardware
C.2 Aplicación mediBER 207

alarma = !aplicacion_bert(&datos_estado, secuencia);


// Calculo del parámetros instantáneos
ber_i = datos_estado.bits_err / datos_estado.bits_rx;
ses_i = (alarma || (ber_i > 0.001))? 1 : 0;
es_i = (datos_estado.bits_err > 0.0)? 1 : 0;
// Se pondera para velocidades de transmisión altas
es_i_0 = datos_estado.bits_err / n_canales;
es_i_0 = (es_i_0 > 1.0 )? 1.0 : es_i_0;

// Almacenamiento de datos para posterior procesado en estadı́sticas


for (n=8, ses_acumul=0, es_acumul=0, bits_rx_acumul=0.0,
bits_err_acumul=0.0 ; n>=0; n--) {
ses_mx[n+1] = ses_mx[n];
ses_acumul = ses_acumul + ses_mx[n];
es_mx[n+1] = es_mx[n];
es_acumul = es_acumul + es_mx[n];
bits_rx_dis[n+1] = bits_rx_dis[n];
bits_rx_acumul = bits_rx_acumul + bits_rx_dis[n];
bits_err_dis[n+1] = bits_err_dis[n];
bits_err_acumul = bits_err_acumul + bits_err_dis[n];
}
ses_mx[0] = ses_i;
ses_acumul = ses_acumul + ses_mx[0];
es_mx[0] = es_i_0; //es_i;
es_acumul = es_acumul + es_mx[0];
bits_rx_dis[0] = datos_estado.bits_rx;
bits_rx_acumul = bits_rx_acumul + bits_rx_dis[0];
bits_err_dis[0] = datos_estado.bits_err;
bits_err_acumul = bits_err_acumul + bits_err_dis[0];

// Determinación de la disponibilidad del enlace


if (disponibilidad) disponibilidad = (ses_acumul >= 10)? NO : SI;
else disponibilidad = (ses_acumul == 0)? SI : NO;

if (disponibilidad) {
switch (periodo_anterior) {
case DISPONIBLE:
tiempo_dis++;
es = es + es_i_0; //(double)es_i;
ses = ses + (double)ses_i;
// Cálculo del ber
bits_rx_total = bits_rx_total + datos_estado.bits_rx;
bits_err_total = bits_err_total + datos_estado.bits_err;
ber = bits_err_total / bits_rx_total;
// Almacenamiento para tasa de DM
if (!ses_i) {
bits_rx_dm[index_dm] = datos_estado.bits_rx;
bits_err_dm[index_dm] = datos_estado.bits_err;
index_dm++;
if (index_dm == 59) {
index_dm = 0;
for ( n=0, bits_rx_60=0.0, bits_err_60=0.0; n<60;
n++) {
bits_rx_60 = bits_rx_60 + bits_rx_dm[n];
bits_err_60 = bits_err_60 + bits_err_dm[n];
}
ber_60 = bits_err_60 / bits_rx_60;
if (ber_60 > 0.000001) dm = dm + 1.0;
}
}
break;
case NO_DISPONIBLE:
// Los 10 segundos anteriores se suman a las estadı́sticas
tiempo_dis = tiempo_dis + 10.0;
es = es + es_acumul;
ses = ses + (double)ses_acumul; //ses_acumul debe ser cero
// Cálculo del ber
bits_rx_total = bits_rx_total + bits_rx_acumul;
C.2 Aplicación mediBER 208

bits_err_total = bits_err_total + bits_err_acumul;


ber = bits_err_total / bits_rx_total;
// Datos para la tasa de DM, contando los 10 seg anteriores
for ( n=0; n<10; n++) {
bits_rx_dm[index_dm] = bits_rx_dis[n];
bits_err_dm[index_dm] = bits_err_dis[n];
index_dm++;
if (index_dm == 59) {
index_dm = 0;
for ( n=0, bits_rx_60=0.0, bits_err_60=0.0; n<60; n++)
{
bits_rx_60 = bits_rx_60 + bits_rx_dm[n];
bits_err_60 = bits_err_60 + bits_err_dm[n];
}
ber_60 = bits_err_60 / bits_rx_60;
if (ber_60 > 0.000001) dm = dm + 1.0;
}
}
break;
}
periodo_anterior = DISPONIBLE;
// Display en la pantalla de mensajes
SetCtrlVal (panel_ber, BER_EVENTOS, " * ");
}
else { // No hay disponibilidad
switch (periodo_anterior) {
case DISPONIBLE:
// Los 10 segundos anteriores se eliminan de las estadı́sticas
tiempo_dis = tiempo_dis - 9.0;
es = es + es_i_0 - es_acumul;//(double)es_i;
ses = ses + (double)ses_i - (double)ses_acumul;
// Cálculo del ber
bits_rx_total = bits_rx_total + datos_estado.bits_rx
- bits_rx_acumul;
bits_err_total = bits_err_total + datos_estado.bits_err
- bits_err_acumul;
ber = bits_err_total / bits_rx_total;
break;
case NO_DISPONIBLE:
// Todo sigue igual
break;
}
periodo_anterior = NO_DISPONIBLE;
// Display en la pantalla de mensajes
SetCtrlVal (panel_ber, BER_EVENTOS, "\nEsperando disponibilidad");
}

// Colores de leds
alarma ? SetCtrlVal (panel_ber, BER_LED_SINCRO, OFF)
: SetCtrlVal (panel_ber, BER_LED_SINCRO, ON);
datos_estado.todo_1 ? SetCtrlVal (panel_ber, BER_LED_UNOS, ON)
: SetCtrlVal (panel_ber, BER_LED_UNOS, OFF);
datos_estado.todo_0 ? SetCtrlVal (panel_ber, BER_LED_CEROS, ON)
: SetCtrlVal (panel_ber, BER_LED_CEROS, OFF);

// Calculo del tiempo de test en dias, horas, minutos y segundos


seg = fmod (tiempo_test, 60.0);
min_t = (tiempo_test - seg ) / 60.0;
min = fmod (min_t, 60.0);
horas_t = (min_t - min) / 60.0;
horas = fmod (horas_t , 24.0);
dias = (horas_t - horas) / 24.0;
// Presentación de tiempo de duración del test
DefaultCtrl (panel_ber, BER_IND_TIEMPO_TEST);
Fmt (txt_tiempo_test, "%s<%f[w1p0]%s%f[w2p0]%s%f[w2p0]%s%f[w2p0]%s",
dias, "d ", horas, "h ", min, "m ", seg, "s");
err = SetCtrlVal (panel_ber, BER_IND_TIEMPO_TEST, txt_tiempo_test);
// Si se alcanza el tiempo final, el test se para
C.2 Aplicación mediBER 209

if (tiempo_test >= tiempo_fin_test) {


StopTest(panel_ber, BER_STOP_TEST, EVENT_COMMIT, 0, 0, 0);
SetCtrlVal (panel_ber, BER_EVENTOS, "\nTest finalizado");
}

// Lo mismo para el tiempo de disponibilidad


seg_dis = fmod (tiempo_dis, 60.0);
min_t_dis = (tiempo_dis - seg_dis ) / 60.0;
min_dis = fmod (min_t_dis, 60.0);
horas_t_dis = (min_t_dis - min_dis) / 60.0;
horas_dis = fmod (horas_t_dis , 24.0);
dias_dis = (horas_t_dis - horas_dis) / 24.0;
// Presentación de tiempo de disponibilidad durante el test
DefaultCtrl (panel_ber, BER_IND_TIEMPO_DISPON);
Fmt (txt_tiempo_dis, "%s<%f[w1p0]%s%f[w2p0]%s%f[w2p0]%s%f[w2p0]%s",
dias_dis, "d ", horas_dis, "h ", min_dis, "m ", seg_dis, "s");
err = SetCtrlVal (panel_ber, BER_IND_TIEMPO_DISPON, txt_tiempo_dis);

// TASA ESR, SESR y DMR


esr = (es * 100) / tiempo_dis;
sesr =(ses * 100) / tiempo_dis;
dmr =(dm * 100) / (tiempo_dis / 60.0);

// Cálculo de la velocidad de transmisión


vel_datos = bits_rx_total / tiempo_dis;
n_canales = vel_datos / 64000.0;

// Entorno gráfico
DefaultCtrl (panel_ber, BER_IND_NRO_BITS);
Fmt (txt_bits_rx, "%s<%f[b4p6e2]", bits_rx_total);
err = SetCtrlVal (panel_ber, BER_IND_NRO_BITS, txt_bits_rx);

DefaultCtrl (panel_ber, BER_IND_NRO_BITS_ERR);


Fmt (txt_bits_err, "%s<%f[b4p6e2]", bits_err_total);
err = SetCtrlVal (panel_ber, BER_IND_NRO_BITS_ERR, txt_bits_err);

DefaultCtrl (panel_ber, BER_IND_ES);


Fmt (txt_es, "%s<%f[p1e1]%s%f[b4p2r]%s", es, " ", esr, "%");
err = SetCtrlVal (panel_ber, BER_IND_ES, txt_es);

DefaultCtrl (panel_ber, BER_IND_SES);


Fmt (txt_ses, "%s<%f[p1e1]%s%f[b4p3r]%s", ses, " ", sesr, "%");
err = SetCtrlVal (panel_ber, BER_IND_SES, txt_ses);

DefaultCtrl (panel_ber, BER_IND_DM);


Fmt (txt_dm, "%s<%f[p1e1]%s%f[b4p2r]%s", dm, " ", dmr, "%");
err = SetCtrlVal (panel_ber, BER_IND_DM, txt_dm);

DefaultCtrl (panel_ber, BER_IND_BER);


Fmt (txt_ber, "%s<%f[b4p4e2]", ber);
err = SetCtrlVal (panel_ber, BER_IND_BER, txt_ber);
break;
case NO: // No hay test
// Colores de leds
SetCtrlVal (panel_ber, BER_LED_SINCRO, OFF);
SetCtrlVal (panel_ber, BER_LED_UNOS, OFF);
SetCtrlVal (panel_ber, BER_LED_CEROS, OFF);
break;
}
}
else { // !hay_placa_ber
if (primer_bucle) {
primer_bucle = NO; // Control de ejecución del bucle

// Display en la pantalla de mensajes


ResetTextBox (panel_ber, BER_EVENTOS, "");
SetCtrlVal (panel_ber, BER_EVENTOS,
"Fallo del puerto de control.\nImposible controlar la placa de BER\n");
C.2 Aplicación mediBER 210

// Inhabilitación de los controles


err = SetCtrlAttribute (panel_ber, BER_TIPO_SECUENCIA, ATTR_DIMMED, 1);
err = SetCtrlAttribute (panel_ber, BER_DURACION_TEST, ATTR_DIMMED, 1);
err = SetCtrlAttribute (panel_ber, BER_ERROR_AUTO, ATTR_DIMMED, 1);
err = SetCtrlAttribute (panel_ber, BER_RUN_TEST, ATTR_DIMMED, 1);
err = SetCtrlAttribute (panel_ber, BER_STOP_TEST, ATTR_DIMMED, 1);
err = SetCtrlAttribute (panel_ber, BER_PUL_INSERT_ERR, ATTR_DIMMED, 1);
err = SetCtrlAttribute (panel_ber, BER_PUL_SEC_USER, ATTR_DIMMED, 1);
err = SetCtrlAttribute (panel_ber, BER_LED_SINCRO, ATTR_DIMMED, 1);
err = SetCtrlAttribute (panel_ber, BER_LED_UNOS, ATTR_DIMMED, 1);
err = SetCtrlAttribute (panel_ber, BER_LED_CEROS, ATTR_DIMMED, 1);
}
}
}
return 0;
}
C.2 Aplicación mediBER 211

/****************************************************************************
MODULO: Recopilación de funciones hardware para la aplicacion de control
del generador de secuencias pseudoaleatorias a partir del DS2172
FICHERO: ber_hard.c VERSION: 1.0
-----------------------------------------------------------------------------
AUTOR: Juan Luis Tébar Garcı́a jltebar@retemail.es
FECHA: 27 de Abril del 2000
-----------------------------------------------------------------------------
DESCRIPCION:
****************************************************************************/
#include <userint.h>
#include <ansi_c.h>
#include <utility.h>
#include "dlportio.h"
#include "ber_def.h"
// Defines de todo el proyecto
#include "ber_hard.h"

// Variables importadas del módulo principal


// Caracteres reservados para el envı́o de parámetros a los registros del chip DS2172
extern unsigned char control_bert[29];

// Bytes utilizados para la comunicación con el modulador. Se especifican como


// global al tenerlos que utilizar para la programación del generador de
// reloj de bit, además de para controlar el modulador
extern unsigned char byte_control, byte_datos;

// registros del puerto paralelo


extern unsigned long pp_datos; //Normalmente sólo escritura
extern unsigned long pp_estado; //lectura
extern unsigned long pp_control; //lectura y escritura

// Codificación de las funciones


/****************************************************************************
FUNCION: carga_pp
DESCRIPCION: Realiza la escritura de un byte en un registro de los circuitos
controlados mediante el puerto paralelo
PARAMETROS DE ENTRADA: dato: es el byte que se escribe
pcb: se refiere a la tarjeta destino: LATCH0 placa ber, LATCH1 placa mod
reg_pcb: registro concreto dentro de cada placa: CHIP0, ... , CHIP3
PARAMETROS DE SALIDA:
RESULTADO Y ERRORES: Entero -1 error; 0 todo bien
OBSERVACIONES: El puerto paralelo seleccionado para el envı́o depende del valor
de la variable global "puerto_control".
La escritura se realiza de forma que el valor a escribir esté en el
puerto antes de activar la carga, con el objetivo de no perturbar
aquellas salidas que afecten muy directamente al funcionamiento hardware
de los circuitos.
****************************************************************************/
int carga_pp (unsigned char dato, char pcb, char reg_pcb) {
static unsigned char byte;

//Escritura del dato en el puerto paralelo


DlPortWritePortUchar(pp_datos, dato);

//Selección del registro dentro de la placa


byte=DlPortReadPortUchar(pp_control);
byte=byte & 0xF0;
switch (reg_pcb) {
case CHIP0:
byte=byte | 0x8; // Selección de CHIP0
DlPortWritePortUchar(pp_control, byte);
break;
case CHIP1:
byte=byte | 0xC; // Selección de CHIP1
DlPortWritePortUchar(pp_control, byte);
break;
case CHIP2:
C.2 Aplicación mediBER 212

byte=byte | 0x0; // Selección de CHIP2 (Ya estaba seleccionado)


DlPortWritePortUchar(pp_control, byte);
break;
case CHIP3:
byte=byte | 0x4; // Selección de CHIP3
DlPortWritePortUchar(pp_control, byte);
break;
default: break;
}

// Activación de la linea chip_select en el registro en cuestión


if (pcb==LATCH0) {
byte=byte & 0xFC;
byte=byte | 0x1; // Selección de LATCH0
DlPortWritePortUchar(pp_control, byte);
}
if (pcb==LATCH1) {
byte=byte & 0xFC;
byte=byte | 0x2; // Selección de LATCH1
DlPortWritePortUchar(pp_control, byte);
}

// Dejamos el registro de control con los cuatro bits a 1


// ESTE ES EL MOMENTO EN QUE VERDADERAMENTE SE GRABA EL DATO DENTRO
// DE LOS REGISTROS, PUES SE CARGAN EN EL FLANCO DE SUBIDA
byte=byte & 0xFC; // valor final de reposo
DlPortWritePortUchar(pp_control, byte);

// Queda direccionado un registro inexistente


byte=byte & 0xF0;
byte=byte | 0x4; // Selección de CHIP3
DlPortWritePortUchar(pp_control, byte);

return 0;
}

/****************************************************************************
FUNCION: lee_par_bert
DESCRIPCION: Realiza la secuencia de leer datos a través del puerto paralelo,
a partir del registro seleccionado. Las instrucciones están adaptadas
al hardware de la placa de ber.
Los datos se leen a través del puerto de estado.
PARAMETROS DE ENTRADA:
dir: sirve para indicar la "dirección" desde donde se leen los datos, si
desde el bus de datos (sentido desde el pc de control), o desde el
punto de vista de la respuesta del DS2172.
BUS, 1 - se lee el dato puesto en el bus desde el pc de control
DS2172, 0 - se lee el dato puesto en el bus por el integrado DS2172.
reg_ini: registro del que se va a obtener el primer byte leı́do.
nro_reg: Número de registros a leer a partir del valor reg_ini.
PARAMETROS DE SALIDA: No hay
RESULTADO Y ERRORES:
OBSERVACIONES: Los parámetros de entrada reg_ini y nro_reg sólo tienen valor
en el caso de estarse leyendo registros del integrado. Si lo que se lee
es el valor del bus, únicamente se leerá un valor, y éste es justo el que
hay en el bus de datos.
El byte(s) leı́do se almacena siempre en la variable global byte_datos,
y además, si la lectura se realiza sobre los registros del DS2172, sobre
el array, también global, donde se guardan los valores de los contenidos
de los registros control_bert[reg_ini], y superiores si la lectura se
realiza sobre varios registros. En este caso, al final de la función, la
variable byte_datos contendrá el último valor leı́do
****************************************************************************/
int lee_par_bert(char dir, char reg_ini, char nro_reg) {
unsigned char byte_m, byte_l, m;

switch (dir) {
case DS2172: //datos desde DS2172
C.2 Aplicación mediBER 213

// Estado inicial. Bus en Tri-state y se anulan #CS, #WR, #RD, y ALE


byte_control = byte_control | 0x17;
byte_control = byte_control & 0xF7;
carga_pp (byte_control, LATCH0, CHIP0);

// Inicio del bucle de lectura, que se repite tantas veces como registros
// se van a leer, y viene indicado en el parámetro de entrada nro_reg
for (m = (unsigned)reg_ini; m < (reg_ini + nro_reg); m++) {
// Activación de ALE
byte_control = byte_control | 0x08;
carga_pp (byte_control, LATCH0, CHIP0);

// Bus transceiver activado. (carga de la dirección a leer)


byte_control = byte_control & 0xEF; //Tristate a cero
carga_pp (byte_control, LATCH0, CHIP0);

// Carga de la dirección en el DS2172


carga_pp (m, LATCH0, CHIP1);

// Activación del #CS


byte_control = byte_control & 0xFE;
carga_pp (byte_control, LATCH0, CHIP0);

// Carga de la dirección. ALE a bajo


byte_control = byte_control & 0xF7;
carga_pp (byte_control, LATCH0, CHIP0);

// Bus transceiver desactivado.


byte_control = byte_control | 0x10; //Tristate a uno
carga_pp (byte_control, LATCH0, CHIP0);

// Activación de la linea #RD


//(aquı́ es cuando se pone el dato en el bus)
byte_control = byte_control & 0xFB;
carga_pp (byte_control, LATCH0, CHIP0);

// Lectura del dato del bus


//Lectura del nibble mas significativo
byte_control = byte_control | 0x20;
carga_pp (byte_control, LATCH0, CHIP0);
byte_m = DlPortReadPortUchar(pp_estado);
byte_m = byte_m ^ 0x80;

//Lectura del nibble menos significativo


byte_control = byte_control & 0xDF;
carga_pp (byte_control, LATCH0, CHIP0);
byte_l = DlPortReadPortUchar(pp_estado);
byte_l = byte_l ^ 0x80;

//Arreglos para presentar el resultado


byte_l = byte_l >> 4;
byte_m = byte_m & 0xF0;
byte_m = byte_m | byte_l;

byte_datos = byte_m;
control_bert[m] = byte_m;

// Desactivación de la linea #RD


byte_control = byte_control | 0x04;
carga_pp (byte_control, LATCH0, CHIP0);

// Desactivación de #CS
byte_control = byte_control | 0x1;
carga_pp (byte_control, LATCH0, CHIP0);
}
break;

case BUS: //datos desde el bus de datos


C.2 Aplicación mediBER 214

//Triestate en la parte del DS2172 y habilitación de salida en U4


byte_control = byte_control | 0x27;
byte_control = byte_control & 0xEF;
carga_pp (byte_control, LATCH0, CHIP0);

//Lectura del nibble mas significativo


byte_control = byte_control | 0x20;
carga_pp (byte_control, LATCH0, CHIP0);
byte_m = DlPortReadPortUchar(pp_estado);
byte_m = byte_m ^ 0x80;

//Lectura del nibble menos significativo


byte_control = byte_control & 0xDF;
carga_pp (byte_control, LATCH0, CHIP0);
byte_l = DlPortReadPortUchar(pp_estado);
byte_l = byte_l ^ 0x80;

//Arreglos para presentar el resultado


byte_l = byte_l >> 4;
byte_m = byte_m & 0xF0;
byte_m = byte_m | byte_l;

byte_datos = byte_m;
}

return 0;
}

/****************************************************************************
FUNCION: escribe_par_bert
DESCRIPCION: Realiza la secuencia de escribir datos a partir del registro
seleccionado, una cantidad de registros igual al número de entrada
PARAMETROS DE ENTRADA:
reg_ini: registro donde se va a escribir el primer byte.
nro_reg: Número de registros a escribir a partir del valor reg_ini.
PARAMETROS DE SALIDA: No hay
RESULTADO Y ERRORES: Entero -1 error; 0 todo bien
OBSERVACIONES: Los valores a escribir son los contenidos en el array de
caracteres global control_bert[], con ı́ndice igual al del registro
escrito.
****************************************************************************/
int escribe_par_bert(char reg_ini, char nro_reg) {
unsigned char un_byte, m;
int n;

// Estado inicial. Se anulan #CS, #WR, #RD, y ALE


byte_control = byte_control | 0x7;
byte_control = byte_control & 0xF7;
carga_pp (byte_control, LATCH0, CHIP0);

// Bus transceiver activado. (vamos a escribir en el DS2172)


byte_control = byte_control & 0xEF; //Tristate a cero
carga_pp (byte_control, LATCH0, CHIP0);

// Inicio del bucle de escritura que se repite tantas veces como registros
// se van a escribir, y viene indicado en el parámetro de entrada nro_reg
for (m = (unsigned)reg_ini; m < (reg_ini + nro_reg); m++) {
// Activación de ALE
byte_control = byte_control | 0x08;
carga_pp (byte_control, LATCH0, CHIP0);

// Carga de la dirección en el DS2172


carga_pp (m, LATCH0, CHIP1);

// Activación del #CS


byte_control = byte_control & 0xFE;
carga_pp (byte_control, LATCH0, CHIP0);
C.2 Aplicación mediBER 215

// Carga de la dirección. ALE a bajo


byte_control = byte_control & 0xF7;
carga_pp (byte_control, LATCH0, CHIP0);

// Escritura en el bus del dato a cargar


un_byte = control_bert[m];
carga_pp (un_byte, LATCH0, CHIP1);

// Activación de la linea #WR


byte_control = byte_control & 0xFD;
carga_pp (byte_control, LATCH0, CHIP0);

// Desactivación de la linea #WR (aquı́ es cuando se escribe el dato)


byte_control = byte_control | 0x02;
carga_pp (byte_control, LATCH0, CHIP0);

// Desactivación de #CS
byte_control = byte_control | 0x1;
carga_pp (byte_control, LATCH0, CHIP0);
}

return 0;
}

/****************************************************************************
FUNCION: inicia_hard_bert
DESCRIPCION: Carga inicial de los registros del integrado
PARAMETROS DE ENTRADA: Ninguno
PARAMETROS DE SALIDA: Ninguno
RESULTADO Y ERRORES: 0, todo OK
OBSERVACIONES: Necesaria en la inicialización de la aplicación.
Posteriormente el resto de funciones actualiza los registros del integrado
****************************************************************************/
int inicia_hard_bert(void) {
char n;

// Inicialización de la memoria de configuración


// Secuencia inicial 2^21 - 1
control_bert[PATTERN_3] = 0xFF;
control_bert[PATTERN_2] = 0xFF;
control_bert[PATTERN_1] = 0xFF;
control_bert[PATTERN_0] = 0xFF;
control_bert[PATTERN_LENGTH] = 0x14;
control_bert[POLYNOMIAL_TAB] = 0x01;

// Configuración de partida
control_bert[PATTERN_CONTROL] = 0x20;

// No se insertan errores
control_bert[ERROR_INSERT] = 0x00;

// Se inicializa la cuenta de bits a cero


control_bert[BIT_COUNT_3] = 0x00;
control_bert[BIT_COUNT_2] = 0x00;
control_bert[BIT_COUNT_1] = 0x00;
control_bert[BIT_COUNT_0] = 0x00;

control_bert[BIT_ERR_COUNT_3] = 0x00;
control_bert[BIT_ERR_COUNT_2] = 0x00;
control_bert[BIT_ERR_COUNT_1] = 0x00;
control_bert[BIT_ERR_COUNT_0] = 0x00;

control_bert[PATTERN_RX_3] = 0x00;
control_bert[PATTERN_RX_2] = 0x00;
control_bert[PATTERN_RX_1] = 0x00;
control_bert[PATTERN_RX_0] = 0x00;

// Suponemos que todo está bien


C.2 Aplicación mediBER 216

control_bert[STATUS] = 0x00;

// Inhabilitamos la generación de interrupciones


control_bert[INT_MASK] = 0x00;
control_bert[TEST] = 0x00;

// Carga de los registros del integrado


for (n=PATTERN_3; n<=INT_MASK; n++) escribe_par_bert(n, 1);
escribe_par_bert(TEST, 1);

return 0;
}

/****************************************************************************
FUNCION: prog_sec
DESCRIPCION: Cambios en los registros internos del chip para modificar la
secuencia con la que se realizará el test de BER
PARAMETROS DE ENTRADA: int secuencia: Código de secuencia utilizada
unsigned long _4_bytes: valor de la secuencia repetitiva cuando se
selecciona la secuencia arbitraria de usuario.
PARAMETROS DE SALIDA:
RESULTADO Y ERRORES: 0, OK
OBSERVACIONES: Si la secuencia seleccionada no es la de usuario, el parámetro
de entrada _4_bytes es indiferente
****************************************************************************/
int prog_sec (int secuencia, unsigned long _4_bytes) {
static char longitud;
static unsigned long mas_bytes;

switch (secuencia) {
case 1: // Secuencia 2^3 - 1
control_bert[PATTERN_3] = 0xFF;
control_bert[PATTERN_2] = 0xFF;
control_bert[PATTERN_1] = 0xFF;
control_bert[PATTERN_0] = 0xFF;
control_bert[PATTERN_LENGTH] = 0x2;
control_bert[POLYNOMIAL_TAB] = 0x0;
// QRSS=0 y PATTERN SELECT=1
control_bert[PATTERN_CONTROL] = control_bert[PATTERN_CONTROL] & 0xBF;
control_bert[PATTERN_CONTROL] = control_bert[PATTERN_CONTROL] | 0x20;
escribe_par_bert(PATTERN_3, 7);
//TINV=RINV=0
control_bert[ERROR_INSERT] = control_bert[ERROR_INSERT] & 0x0F;
escribe_par_bert(ERROR_INSERT, 1);
break;
case 2: // Secuencia 2^4 - 1
control_bert[PATTERN_3] = 0xFF;
control_bert[PATTERN_2] = 0xFF;
control_bert[PATTERN_1] = 0xFF;
control_bert[PATTERN_0] = 0xFF;
control_bert[PATTERN_LENGTH] = 0x3;
control_bert[POLYNOMIAL_TAB] = 0x0;
// QRSS=0 y PATTERN SELECT=1
control_bert[PATTERN_CONTROL] = control_bert[PATTERN_CONTROL] & 0xBF;
control_bert[PATTERN_CONTROL] = control_bert[PATTERN_CONTROL] | 0x20;
escribe_par_bert(PATTERN_3, 7);
//TINV=RINV=0
control_bert[ERROR_INSERT] = control_bert[ERROR_INSERT] & 0x0F;
escribe_par_bert(ERROR_INSERT, 1);
break;
case 3: // Secuencia 2^5 - 1
control_bert[PATTERN_3] = 0xFF;
control_bert[PATTERN_2] = 0xFF;
control_bert[PATTERN_1] = 0xFF;
control_bert[PATTERN_0] = 0xFF;
control_bert[PATTERN_LENGTH] = 0x4;
control_bert[POLYNOMIAL_TAB] = 0x1;
// QRSS=0 y PATTERN SELECT=1
C.2 Aplicación mediBER 217

control_bert[PATTERN_CONTROL] = control_bert[PATTERN_CONTROL] & 0xBF;


control_bert[PATTERN_CONTROL] = control_bert[PATTERN_CONTROL] | 0x20;
escribe_par_bert(PATTERN_3, 7);
//TINV=RINV=0
control_bert[ERROR_INSERT] = control_bert[ERROR_INSERT] & 0x0F;
escribe_par_bert(ERROR_INSERT, 1);
break;
case 4: // Secuencia 2^6 - 1
control_bert[PATTERN_3] = 0xFF;
control_bert[PATTERN_2] = 0xFF;
control_bert[PATTERN_1] = 0xFF;
control_bert[PATTERN_0] = 0xFF;
control_bert[PATTERN_LENGTH] = 0x5;
control_bert[POLYNOMIAL_TAB] = 0x4;
// QRSS=0 y PATTERN SELECT=1
control_bert[PATTERN_CONTROL] = control_bert[PATTERN_CONTROL] & 0xBF;
control_bert[PATTERN_CONTROL] = control_bert[PATTERN_CONTROL] | 0x20;
escribe_par_bert(PATTERN_3, 7);
//TINV=RINV=0
control_bert[ERROR_INSERT] = control_bert[ERROR_INSERT] & 0x0F;
escribe_par_bert(ERROR_INSERT, 1);
break;
case 5: // Secuencia 2^7 - 1
control_bert[PATTERN_3] = 0xFF;
control_bert[PATTERN_2] = 0xFF;
control_bert[PATTERN_1] = 0xFF;
control_bert[PATTERN_0] = 0xFF;
control_bert[PATTERN_LENGTH] = 0x6;
control_bert[POLYNOMIAL_TAB] = 0x0;
// QRSS=0 y PATTERN SELECT=1
control_bert[PATTERN_CONTROL] = control_bert[PATTERN_CONTROL] & 0xBF;
control_bert[PATTERN_CONTROL] = control_bert[PATTERN_CONTROL] | 0x20;
escribe_par_bert(PATTERN_3, 7);
//TINV=RINV=0
control_bert[ERROR_INSERT] = control_bert[ERROR_INSERT] & 0x0F;
escribe_par_bert(ERROR_INSERT, 1);
break;
case 6: // Secuencia 2^7 - 1 Fractional T1 LB Activate
control_bert[PATTERN_3] = 0xFF;
control_bert[PATTERN_2] = 0xFF;
control_bert[PATTERN_1] = 0xFF;
control_bert[PATTERN_0] = 0xFF;
control_bert[PATTERN_LENGTH] = 0x6;
control_bert[POLYNOMIAL_TAB] = 0x3;
// QRSS=0 y PATTERN SELECT=1
control_bert[PATTERN_CONTROL] = control_bert[PATTERN_CONTROL] & 0xBF;
control_bert[PATTERN_CONTROL] = control_bert[PATTERN_CONTROL] | 0x20;
escribe_par_bert(PATTERN_3, 7);
//TINV=RINV=0
control_bert[ERROR_INSERT] = control_bert[ERROR_INSERT] & 0x0F;
escribe_par_bert(ERROR_INSERT, 1);
break;
case 7: // Secuencia 2^7 - 1 Fractional T1 LB Deactivate
control_bert[PATTERN_3] = 0xFF;
control_bert[PATTERN_2] = 0xFF;
control_bert[PATTERN_1] = 0xFF;
control_bert[PATTERN_0] = 0xFF;
control_bert[PATTERN_LENGTH] = 0x6;
control_bert[POLYNOMIAL_TAB] = 0x3;
// QRSS=0 y PATTERN SELECT=1
control_bert[PATTERN_CONTROL] = control_bert[PATTERN_CONTROL] & 0xBF;
control_bert[PATTERN_CONTROL] = control_bert[PATTERN_CONTROL] | 0x20;
escribe_par_bert(PATTERN_3, 7);
//TINV=RINV=1
control_bert[ERROR_INSERT] = control_bert[ERROR_INSERT] | 0x30;
escribe_par_bert(ERROR_INSERT, 1);
break;
case 8: // Secuencia 2^9 - 1 O.153 (tipo 511)
C.2 Aplicación mediBER 218

control_bert[PATTERN_3] = 0xFF;
control_bert[PATTERN_2] = 0xFF;
control_bert[PATTERN_1] = 0xFF;
control_bert[PATTERN_0] = 0xFF;
control_bert[PATTERN_LENGTH] = 0x8;
control_bert[POLYNOMIAL_TAB] = 0x4;
// QRSS=0 y PATTERN SELECT=1
control_bert[PATTERN_CONTROL] = control_bert[PATTERN_CONTROL] & 0xBF;
control_bert[PATTERN_CONTROL] = control_bert[PATTERN_CONTROL] | 0x20;
escribe_par_bert(PATTERN_3, 7);
//TINV=RINV=0
control_bert[ERROR_INSERT] = control_bert[ERROR_INSERT] & 0x0F;
escribe_par_bert(ERROR_INSERT, 1);
break;
case 9: // Secuencia 2^10 - 1
control_bert[PATTERN_3] = 0xFF;
control_bert[PATTERN_2] = 0xFF;
control_bert[PATTERN_1] = 0xFF;
control_bert[PATTERN_0] = 0xFF;
control_bert[PATTERN_LENGTH] = 0x9;
control_bert[POLYNOMIAL_TAB] = 0x2;
// QRSS=0 y PATTERN SELECT=1
control_bert[PATTERN_CONTROL] = control_bert[PATTERN_CONTROL] & 0xBF;
control_bert[PATTERN_CONTROL] = control_bert[PATTERN_CONTROL] | 0x20;
escribe_par_bert(PATTERN_3, 7);
//TINV=RINV=0
control_bert[ERROR_INSERT] = control_bert[ERROR_INSERT] & 0x0F;
escribe_par_bert(ERROR_INSERT, 1);
break;
case 10: // Secuencia 2^11 - 1 O.152 y O.153 (tipo 2047)
control_bert[PATTERN_3] = 0xFF;
control_bert[PATTERN_2] = 0xFF;
control_bert[PATTERN_1] = 0xFF;
control_bert[PATTERN_0] = 0xFF;
control_bert[PATTERN_LENGTH] = 0xA;
control_bert[POLYNOMIAL_TAB] = 0x8;
// QRSS=0 y PATTERN SELECT=1
control_bert[PATTERN_CONTROL] = control_bert[PATTERN_CONTROL] & 0xBF;
control_bert[PATTERN_CONTROL] = control_bert[PATTERN_CONTROL] | 0x20;
escribe_par_bert(PATTERN_3, 7);
//TINV=RINV=0
control_bert[ERROR_INSERT] = control_bert[ERROR_INSERT] & 0x0F;
escribe_par_bert(ERROR_INSERT, 1);
break;
case 11: // Secuencia 2^15 - 1 O.151
control_bert[PATTERN_3] = 0xFF;
control_bert[PATTERN_2] = 0xFF;
control_bert[PATTERN_1] = 0xFF;
control_bert[PATTERN_0] = 0xFF;
control_bert[PATTERN_LENGTH] = 0xE;
control_bert[POLYNOMIAL_TAB] = 0xD;
// QRSS=0 y PATTERN SELECT=1
control_bert[PATTERN_CONTROL] = control_bert[PATTERN_CONTROL] & 0xBF;
control_bert[PATTERN_CONTROL] = control_bert[PATTERN_CONTROL] | 0x20;
escribe_par_bert(PATTERN_3, 7);
//TINV=RINV=1
control_bert[ERROR_INSERT] = control_bert[ERROR_INSERT] | 0x30;
escribe_par_bert(ERROR_INSERT, 1);
break;
case 12: // Secuencia 2^17 - 1
control_bert[PATTERN_3] = 0xFF;
control_bert[PATTERN_2] = 0xFF;
control_bert[PATTERN_1] = 0xFF;
control_bert[PATTERN_0] = 0xFF;
control_bert[PATTERN_LENGTH] = 0x10;
control_bert[POLYNOMIAL_TAB] = 0x2;
// QRSS=0 y PATTERN SELECT=1
control_bert[PATTERN_CONTROL] = control_bert[PATTERN_CONTROL] & 0xBF;
C.2 Aplicación mediBER 219

control_bert[PATTERN_CONTROL] = control_bert[PATTERN_CONTROL] | 0x20;


escribe_par_bert(PATTERN_3, 7);
//TINV=RINV=0
control_bert[ERROR_INSERT] = control_bert[ERROR_INSERT] & 0x0F;
escribe_par_bert(ERROR_INSERT, 1);
break;
case 13: // Secuencia 2^18 - 1
control_bert[PATTERN_3] = 0xFF;
control_bert[PATTERN_2] = 0xFF;
control_bert[PATTERN_1] = 0xFF;
control_bert[PATTERN_0] = 0xFF;
control_bert[PATTERN_LENGTH] = 0x11;
control_bert[POLYNOMIAL_TAB] = 0x6;
// QRSS=0 y PATTERN SELECT=1
control_bert[PATTERN_CONTROL] = control_bert[PATTERN_CONTROL] & 0xBF;
control_bert[PATTERN_CONTROL] = control_bert[PATTERN_CONTROL] | 0x20;
escribe_par_bert(PATTERN_3, 7);
//TINV=RINV=0
control_bert[ERROR_INSERT] = control_bert[ERROR_INSERT] & 0x0F;
escribe_par_bert(ERROR_INSERT, 1);
break;
case 14: // Secuencia 2^20 - 1 O.153
control_bert[PATTERN_3] = 0xFF;
control_bert[PATTERN_2] = 0xFF;
control_bert[PATTERN_1] = 0xFF;
control_bert[PATTERN_0] = 0xFF;
control_bert[PATTERN_LENGTH] = 0x13;
control_bert[POLYNOMIAL_TAB] = 0x2;
// QRSS=0 y PATTERN SELECT=1
control_bert[PATTERN_CONTROL] = control_bert[PATTERN_CONTROL] & 0xBF;
control_bert[PATTERN_CONTROL] = control_bert[PATTERN_CONTROL] | 0x20;
escribe_par_bert(PATTERN_3, 7);
//TINV=RINV=0
control_bert[ERROR_INSERT] = control_bert[ERROR_INSERT] & 0x0F;
escribe_par_bert(ERROR_INSERT, 1);
break;
case 15: // Secuencia 2^20 - 1 O.151 QRSS
control_bert[PATTERN_3] = 0xFF;
control_bert[PATTERN_2] = 0xFF;
control_bert[PATTERN_1] = 0xFF;
control_bert[PATTERN_0] = 0xFF;
control_bert[PATTERN_LENGTH] = 0x13;
control_bert[POLYNOMIAL_TAB] = 0x10;
// QRSS=1 y PATTERN SELECT=1
control_bert[PATTERN_CONTROL] = control_bert[PATTERN_CONTROL] | 0x40;
control_bert[PATTERN_CONTROL] = control_bert[PATTERN_CONTROL] | 0x20;
escribe_par_bert(PATTERN_3, 7);
//TINV=RINV=0
control_bert[ERROR_INSERT] = control_bert[ERROR_INSERT] & 0x0F;
escribe_par_bert(ERROR_INSERT, 1);
break;
case 16: // Secuencia 2^21 - 1
control_bert[PATTERN_3] = 0xFF;
control_bert[PATTERN_2] = 0xFF;
control_bert[PATTERN_1] = 0xFF;
control_bert[PATTERN_0] = 0xFF;
control_bert[PATTERN_LENGTH] = 0x14;
control_bert[POLYNOMIAL_TAB] = 0x1;
// QRSS=0 y PATTERN SELECT=1
control_bert[PATTERN_CONTROL] = control_bert[PATTERN_CONTROL] & 0xBF;
control_bert[PATTERN_CONTROL] = control_bert[PATTERN_CONTROL] | 0x20;
escribe_par_bert(PATTERN_3, 7);
//TINV=RINV=0
control_bert[ERROR_INSERT] = control_bert[ERROR_INSERT] & 0x0F;
escribe_par_bert(ERROR_INSERT, 1);
break;
case 17: // Secuencia 2^22 - 1
control_bert[PATTERN_3] = 0xFF;
C.2 Aplicación mediBER 220

control_bert[PATTERN_2] = 0xFF;
control_bert[PATTERN_1] = 0xFF;
control_bert[PATTERN_0] = 0xFF;
control_bert[PATTERN_LENGTH] = 0x15;
control_bert[POLYNOMIAL_TAB] = 0x0;
// QRSS=0 y PATTERN SELECT=1
control_bert[PATTERN_CONTROL] = control_bert[PATTERN_CONTROL] & 0xBF;
control_bert[PATTERN_CONTROL] = control_bert[PATTERN_CONTROL] | 0x20;
escribe_par_bert(PATTERN_3, 7);
//TINV=RINV=0
control_bert[ERROR_INSERT] = control_bert[ERROR_INSERT] & 0x0F;
escribe_par_bert(ERROR_INSERT, 1);
break;
case 18: // Secuencia 2^23 - 1 O.151
control_bert[PATTERN_3] = 0xFF;
control_bert[PATTERN_2] = 0xFF;
control_bert[PATTERN_1] = 0xFF;
control_bert[PATTERN_0] = 0xFF;
control_bert[PATTERN_LENGTH] = 0x16;
control_bert[POLYNOMIAL_TAB] = 0x11;
// QRSS=0 y PATTERN SELECT=1
control_bert[PATTERN_CONTROL] = control_bert[PATTERN_CONTROL] & 0xBF;
control_bert[PATTERN_CONTROL] = control_bert[PATTERN_CONTROL] | 0x20;
escribe_par_bert(PATTERN_3, 7);
//TINV=RINV=1
control_bert[ERROR_INSERT] = control_bert[ERROR_INSERT] & 0x3F;
control_bert[ERROR_INSERT] = control_bert[ERROR_INSERT] | 0x30;
escribe_par_bert(ERROR_INSERT, 1);
break;
case 19: // Secuencia 2^25 - 1
control_bert[PATTERN_3] = 0xFF;
control_bert[PATTERN_2] = 0xFF;
control_bert[PATTERN_1] = 0xFF;
control_bert[PATTERN_0] = 0xFF;
control_bert[PATTERN_LENGTH] = 0x18;
control_bert[POLYNOMIAL_TAB] = 0x2;
// QRSS=0 y PATTERN SELECT=1
control_bert[PATTERN_CONTROL] = control_bert[PATTERN_CONTROL] & 0xBF;
control_bert[PATTERN_CONTROL] = control_bert[PATTERN_CONTROL] | 0x20;
escribe_par_bert(PATTERN_3, 7);
//TINV=RINV=0
control_bert[ERROR_INSERT] = control_bert[ERROR_INSERT] & 0x0F;
escribe_par_bert(ERROR_INSERT, 1);
break;
case 20: // Secuencia 2^28 - 1
control_bert[PATTERN_3] = 0xFF;
control_bert[PATTERN_2] = 0xFF;
control_bert[PATTERN_1] = 0xFF;
control_bert[PATTERN_0] = 0xFF;
control_bert[PATTERN_LENGTH] = 0x1B;
control_bert[POLYNOMIAL_TAB] = 0x2;
// QRSS=0 y PATTERN SELECT=1
control_bert[PATTERN_CONTROL] = control_bert[PATTERN_CONTROL] & 0xBF;
control_bert[PATTERN_CONTROL] = control_bert[PATTERN_CONTROL] | 0x20;
escribe_par_bert(PATTERN_3, 7);
//TINV=RINV=0
control_bert[ERROR_INSERT] = control_bert[ERROR_INSERT] & 0x0F;
escribe_par_bert(ERROR_INSERT, 1);
break;
case 21: // Secuencia 2^29 - 1
control_bert[PATTERN_3] = 0xFF;
control_bert[PATTERN_2] = 0xFF;
control_bert[PATTERN_1] = 0xFF;
control_bert[PATTERN_0] = 0xFF;
control_bert[PATTERN_LENGTH] = 0x1C;
control_bert[POLYNOMIAL_TAB] = 0x01;
// QRSS=0 y PATTERN SELECT=1
control_bert[PATTERN_CONTROL] = control_bert[PATTERN_CONTROL] & 0xBF;
C.2 Aplicación mediBER 221

control_bert[PATTERN_CONTROL] = control_bert[PATTERN_CONTROL] | 0x20;


escribe_par_bert(PATTERN_3, 7);
//TINV=RINV=0
control_bert[ERROR_INSERT] = control_bert[ERROR_INSERT] & 0x0F;
escribe_par_bert(ERROR_INSERT, 1);
break;
case 22: // Secuencia 2^31 - 1
control_bert[PATTERN_3] = 0xFF;
control_bert[PATTERN_2] = 0xFF;
control_bert[PATTERN_1] = 0xFF;
control_bert[PATTERN_0] = 0xFF;
control_bert[PATTERN_LENGTH] = 0x1E;
control_bert[POLYNOMIAL_TAB] = 0x02;
// QRSS=0 y PATTERN SELECT=1
control_bert[PATTERN_CONTROL] = control_bert[PATTERN_CONTROL] & 0xBF;
control_bert[PATTERN_CONTROL] = control_bert[PATTERN_CONTROL] | 0x20;
escribe_par_bert(PATTERN_3, 7);
//TINV=RINV=0
control_bert[ERROR_INSERT] = control_bert[ERROR_INSERT] & 0x0F;
escribe_par_bert(ERROR_INSERT, 1);
break;
case 23: // Secuencia 2^32 - 1
control_bert[PATTERN_3] = 0xFF;
control_bert[PATTERN_2] = 0xFF;
control_bert[PATTERN_1] = 0xFF;
control_bert[PATTERN_0] = 0xFF;
control_bert[PATTERN_LENGTH] = 0x1F;
control_bert[POLYNOMIAL_TAB] = 0x10;
// QRSS=0 y PATTERN SELECT=1
control_bert[PATTERN_CONTROL] = control_bert[PATTERN_CONTROL] & 0xBF;
control_bert[PATTERN_CONTROL] = control_bert[PATTERN_CONTROL] | 0x20;
escribe_par_bert(PATTERN_3, 7);
//TINV=RINV=0
control_bert[ERROR_INSERT] = control_bert[ERROR_INSERT] & 0x0F;
escribe_par_bert(ERROR_INSERT, 1);
break;
case 24: // Secuencia de todo unos
control_bert[PATTERN_3] = 0xFF;
control_bert[PATTERN_2] = 0xFF;
control_bert[PATTERN_1] = 0xFF;
control_bert[PATTERN_0] = 0xFF;
control_bert[PATTERN_LENGTH] = 0x00;
control_bert[POLYNOMIAL_TAB] = 0x00;
//QRSS=PATTERN SELECT=0
control_bert[PATTERN_CONTROL] = control_bert[PATTERN_CONTROL] & 0x9F;
escribe_par_bert(PATTERN_3, 7);
//TINV=RINV=0
control_bert[ERROR_INSERT] = control_bert[ERROR_INSERT] & 0x0F;
escribe_par_bert(ERROR_INSERT, 1);
break;
case 25: // Secuencia de todo ceros
control_bert[PATTERN_3] = 0xFF;
control_bert[PATTERN_2] = 0xFF;
control_bert[PATTERN_1] = 0xFF;
control_bert[PATTERN_0] = 0xFE;
control_bert[PATTERN_LENGTH] = 0x00;
control_bert[POLYNOMIAL_TAB] = 0x00;
//QRSS=PATTERN SELECT=0
control_bert[PATTERN_CONTROL] = control_bert[PATTERN_CONTROL] & 0x9F;
escribe_par_bert(PATTERN_3, 7);
//TINV=RINV=0
control_bert[ERROR_INSERT] = control_bert[ERROR_INSERT] & 0x0F;
escribe_par_bert(ERROR_INSERT, 1);
break;
case 26: // Secuencia alternada de unos y ceros
control_bert[PATTERN_3] = 0xFF;
control_bert[PATTERN_2] = 0xFF;
control_bert[PATTERN_1] = 0xFF;
C.2 Aplicación mediBER 222

control_bert[PATTERN_0] = 0xFE;
control_bert[PATTERN_LENGTH] = 0x01;
control_bert[POLYNOMIAL_TAB] = 0x00;
//QRSS=PATTERN SELECT=0
control_bert[PATTERN_CONTROL] = control_bert[PATTERN_CONTROL] & 0x9F;
escribe_par_bert(PATTERN_3, 7);
//TINV=RINV=0
control_bert[ERROR_INSERT] = control_bert[ERROR_INSERT] & 0x0F;
escribe_par_bert(ERROR_INSERT, 1);
break;
case 27: // Secuencia doble alternada de unos y ceros
control_bert[PATTERN_3] = 0xFF;
control_bert[PATTERN_2] = 0xFF;
control_bert[PATTERN_1] = 0xFF;
control_bert[PATTERN_0] = 0xFC;
control_bert[PATTERN_LENGTH] = 0x03;
control_bert[POLYNOMIAL_TAB] = 0x00;
//QRSS=PATTERN SELECT=0
control_bert[PATTERN_CONTROL] = control_bert[PATTERN_CONTROL] & 0x9F;
escribe_par_bert(PATTERN_3, 7);
//TINV=RINV=0
control_bert[ERROR_INSERT] = control_bert[ERROR_INSERT] & 0x0F;
escribe_par_bert(ERROR_INSERT, 1);
break;
case 28: // Secuencia de 3 unos en 24 ceros
control_bert[PATTERN_3] = 0xFF;
control_bert[PATTERN_2] = 0x20;
control_bert[PATTERN_1] = 0x00;
control_bert[PATTERN_0] = 0x22;
control_bert[PATTERN_LENGTH] = 0x17;
control_bert[POLYNOMIAL_TAB] = 0x00;
//QRSS=PATTERN SELECT=0
control_bert[PATTERN_CONTROL] = control_bert[PATTERN_CONTROL] & 0x9F;
escribe_par_bert(PATTERN_3, 7);
//TINV=RINV=0
control_bert[ERROR_INSERT] = control_bert[ERROR_INSERT] & 0x0F;
escribe_par_bert(ERROR_INSERT, 1);
break;
case 29: // Secuencia de 1 uno en 16 ceros
control_bert[PATTERN_3] = 0xFF;
control_bert[PATTERN_2] = 0xFF;
control_bert[PATTERN_1] = 0x00;
control_bert[PATTERN_0] = 0x01;
control_bert[PATTERN_LENGTH] = 0x0F;
control_bert[POLYNOMIAL_TAB] = 0x00;
//QRSS=PATTERN SELECT=0
control_bert[PATTERN_CONTROL] = control_bert[PATTERN_CONTROL] & 0x9F;
escribe_par_bert(PATTERN_3, 7);
//TINV=RINV=0
control_bert[ERROR_INSERT] = control_bert[ERROR_INSERT] & 0x0F;
escribe_par_bert(ERROR_INSERT, 1);
break;
case 30: // Secuencia de 1 uno en 18 ceros
control_bert[PATTERN_3] = 0xFF;
control_bert[PATTERN_2] = 0xFF;
control_bert[PATTERN_1] = 0xFF;
control_bert[PATTERN_0] = 0x01;
control_bert[PATTERN_LENGTH] = 0x07;
control_bert[POLYNOMIAL_TAB] = 0x00;
//QRSS=PATTERN SELECT=0
control_bert[PATTERN_CONTROL] = control_bert[PATTERN_CONTROL] & 0x9F;
escribe_par_bert(PATTERN_3, 7);
//TINV=RINV=0
control_bert[ERROR_INSERT] = control_bert[ERROR_INSERT] & 0x0F;
escribe_par_bert(ERROR_INSERT, 1);
break;
case 31: // Secuencia de 1 uno en 4 ceros
control_bert[PATTERN_3] = 0xFF;
C.2 Aplicación mediBER 223

control_bert[PATTERN_2] = 0xFF;
control_bert[PATTERN_1] = 0xFF;
control_bert[PATTERN_0] = 0xF1;
control_bert[PATTERN_LENGTH] = 0x03;
control_bert[POLYNOMIAL_TAB] = 0x00;
//QRSS=PATTERN SELECT=0
control_bert[PATTERN_CONTROL] = control_bert[PATTERN_CONTROL] & 0x9F;
escribe_par_bert(PATTERN_3, 7);
//TINV=RINV=0
control_bert[ERROR_INSERT] = control_bert[ERROR_INSERT] & 0x0F;
escribe_par_bert(ERROR_INSERT, 1);
break;
case 32: // Secuencia D4 bucle activado
control_bert[PATTERN_3] = 0xFF;
control_bert[PATTERN_2] = 0xFF;
control_bert[PATTERN_1] = 0xFF;
control_bert[PATTERN_0] = 0xF0;
control_bert[PATTERN_LENGTH] = 0x04;
control_bert[POLYNOMIAL_TAB] = 0x00;
//QRSS=PATTERN SELECT=0
control_bert[PATTERN_CONTROL] = control_bert[PATTERN_CONTROL] & 0x9F;
escribe_par_bert(PATTERN_3, 7);
//TINV=RINV=0
control_bert[ERROR_INSERT] = control_bert[ERROR_INSERT] & 0x0F;
escribe_par_bert(ERROR_INSERT, 1);
break;
case 33: // Secuencia D4 bucle desactivado
control_bert[PATTERN_3] = 0xFF;
control_bert[PATTERN_2] = 0xFF;
control_bert[PATTERN_1] = 0xFF;
control_bert[PATTERN_0] = 0xFC;
control_bert[PATTERN_LENGTH] = 0x02;
control_bert[POLYNOMIAL_TAB] = 0x00;
//QRSS=PATTERN SELECT=0
control_bert[PATTERN_CONTROL] = control_bert[PATTERN_CONTROL] & 0x9F;
escribe_par_bert(PATTERN_3, 7);
//TINV=RINV=0
control_bert[ERROR_INSERT] = control_bert[ERROR_INSERT] & 0x0F;
escribe_par_bert(ERROR_INSERT, 1);
break;
case 34: // Definida por el usuario
mas_bytes = _4_bytes;
// Determinación de la longitud de la secuencia de usuario
for (longitud = 31; ((!(mas_bytes & 0x80000000)) && (longitud > 0)); longitud--)
mas_bytes = mas_bytes << 1;
control_bert[PATTERN_LENGTH] = longitud;
control_bert[PATTERN_0] = _4_bytes & 0xFF;
_4_bytes = _4_bytes >> 8;
control_bert[PATTERN_1] = _4_bytes & 0xFF;
_4_bytes = _4_bytes >> 8;
control_bert[PATTERN_2] = _4_bytes & 0xFF;
_4_bytes = _4_bytes >> 8;
control_bert[PATTERN_3] = _4_bytes & 0xFF;

control_bert[POLYNOMIAL_TAB] = 0x00;
//QRSS=PATTERN SELECT=0
control_bert[PATTERN_CONTROL] = control_bert[PATTERN_CONTROL] & 0x9F;
escribe_par_bert(PATTERN_3, 7);
//TINV=RINV=0
control_bert[ERROR_INSERT] = control_bert[ERROR_INSERT] & 0x0F;
escribe_par_bert(ERROR_INSERT, 1);
break;
}
return 0;
}

/****************************************************************************
FUNCION: inserta_error
C.2 Aplicación mediBER 224

DESCRIPCION: Cambios en los registros internos para la inserción de un error


intencionadamente
PARAMETROS DE ENTRADA: Ninguno
PARAMETROS DE SALIDA: Ninguno
RESULTADO Y ERRORES: 0, OK
OBSERVACIONES:
****************************************************************************/
int inserta_error(void) {
// Modificamos el registro implicado
control_bert[ERROR_INSERT] = control_bert[ERROR_INSERT] | 0x8;
escribe_par_bert(ERROR_INSERT, 1);
control_bert[ERROR_INSERT] = control_bert[ERROR_INSERT] & 0xF7;
escribe_par_bert(ERROR_INSERT, 1);

return 0;
}

/****************************************************************************
FUNCION: inicia_test
DESCRIPCION: Cambios en los registros internos para la activación de la
secuencia de salida y el conteo de bits recibidos y bits erróneos
PARAMETROS DE ENTRADA: Ninguno
PARAMETROS DE SALIDA: Ninguno
RESULTADO Y ERRORES: 0, OK
OBSERVACIONES:
****************************************************************************/
int inicia_test(void) {
static int n;

// Carga del contenido del registro de pattern en el generador de pattern


// También reseteo de los registros BIT_COUNT y BIT_ERR_COUNT para poder realizar
// correctamente los cálculos de BER y demás indicaciones.
control_bert[PATTERN_CONTROL] = control_bert[PATTERN_CONTROL] & 0x6F; //TL=0, LC=0;
escribe_par_bert(PATTERN_CONTROL, 1);
control_bert[PATTERN_CONTROL] = control_bert[PATTERN_CONTROL] | 0x90; //TL=1, LC=1;
escribe_par_bert(PATTERN_CONTROL, 1);

// Lectura de los valores de BIT_COUNT y BIT_ERR_COUNT que tenı́a


//almacenados el integrado
lee_par_bert(DS2172, BIT_COUNT_3, 8);
// Como el valor no nos interesa lo borramos.
for (n=BIT_COUNT_3; n<(BIT_COUNT_3+8); n++) control_bert[n] = 0x00;

// Desactivación de las lı́neas TDIS y RDIS para habilitar el test


byte_control = byte_control & 0x3F;
carga_pp (byte_control, LATCH0, CHIP0);

return 0;
}

/****************************************************************************
FUNCION: stop_test
DESCRIPCION: Cambios en los registros internos para la desactivación de la
secuencia de salida.
PARAMETROS DE ENTRADA: Ninguno
PARAMETROS DE SALIDA: Ninguno
RESULTADO Y ERRORES: 0, OK
OBSERVACIONES:
****************************************************************************/
int stop_test(void) {
// Se detiene la operación del chip. TDIS y RDIS a uno
byte_control = byte_control | 0xC0;
carga_pp (byte_control, LATCH0, CHIP0);

return 0;
}

/****************************************************************************
C.2 Aplicación mediBER 225

FUNCION: error_auto
DESCRIPCION: Cambios en el registro interno del DS2172 para que inserte
errores automáticamente de forma que se obtenga una tasa de error arbitraria
PARAMETROS DE ENTRADA: char valor, con la tasa de BER artificial codificada
PARAMETROS DE SALIDA: No
RESULTADO Y ERRORES: 0, todo OK
OBSERVACIONES:
****************************************************************************/
int error_auto(unsigned char valor) {
// Nos aseguramos de que el parámetro de entrada no interfiere
valor = valor & 0x7;
// Modificamos el registro implicado
control_bert[ERROR_INSERT] = control_bert[ERROR_INSERT] & 0xF8;
control_bert[ERROR_INSERT] = control_bert[ERROR_INSERT] | valor;
escribe_par_bert(ERROR_INSERT, 1);

return 0;
}

/****************************************************************************
FUNCION: aplicacion_bert
DESCRIPCION: Lectura del registro de estado y de los contadores de bits
recibidos y erróneos para realimentar a la aplicación principal.
PARAMETROS DE ENTRADA:
int secuencia: código de la secuencia utilizada.
PARAMETROS DE SALIDA:
ptd, puntero a estructura t_datos, donde se guardan todos los resultados
RESULTADO Y ERRORES: char SI, si se determina que el chip está sincronizado
en función de las alarmas leı́das en el registro de estado, NO en caso
contrario. Depende de la secuencia que se esté utilizando.
OBSERVACIONES: La función determina sincronismo si se reciben todo unos, pero
la secuencia utilizada es esa misma, y tambien si se reciben todo ceros,
y la secuencia es de ceros. En caso contrario, estas dos circustancias
son consideradas como anómalas y producen que el resultado de la función
sea negativo.
****************************************************************************/
char aplicacion_bert(t_datos *ptd, int secuencia) {
char hay_sincronismo;

// Lectura del registro de estado


lee_par_bert(DS2172, STATUS, 2);
control_bert[INT_MASK] = 0x00;
escribe_par_bert(INT_MASK, 1);

// Actualiza las variables


ptd->todo_1 = control_bert[STATUS] & 0x40;
ptd->todo_0 = control_bert[STATUS] & 0x20;
ptd->busca_sincro = control_bert[STATUS] & 0x10;
ptd->error_dec = control_bert[STATUS] & 0x08;
ptd->con_ovf = control_bert[STATUS] & 0x04;
ptd->con_err_ovf = control_bert[STATUS] & 0x02;
ptd->sincro = control_bert[STATUS] & 0x01;

// Determinación del sincronismo del sistema


hay_sincronismo = ((ptd->sincro && !(ptd->todo_0) && !(ptd->todo_1))
|| (ptd->todo_0 && (secuencia == 25))
|| (ptd->todo_1 && (secuencia == 24)));

// El chip se ha sincronizado
if (hay_sincronismo) {
// Reseteo de los contadores
control_bert[PATTERN_CONTROL] = control_bert[PATTERN_CONTROL] & 0xEF;
escribe_par_bert(PATTERN_CONTROL, 1); // LATCH COUNT = 0
control_bert[PATTERN_CONTROL] = control_bert[PATTERN_CONTROL] | 0x10;
escribe_par_bert(PATTERN_CONTROL, 1); // LATCH COUNT = 1

// Lectura de los registros que alimentan a los indicadores


lee_par_bert(DS2172, BIT_COUNT_3, 12);
C.2 Aplicación mediBER 226

// Actualización de variables
ptd->bits_rx = (control_bert[BIT_COUNT_3] * 16777216.0) +
(control_bert[BIT_COUNT_2] * 65536.0) +
(control_bert[BIT_COUNT_1] * 256.0) +
(control_bert[BIT_COUNT_0] * 1.0);
ptd->bits_err= (control_bert[BIT_ERR_COUNT_3] * 16777216.0) +
(control_bert[BIT_ERR_COUNT_2] * 65536.0) +
(control_bert[BIT_ERR_COUNT_1] * 256.0) +
(control_bert[BIT_ERR_COUNT_0] * 1.0);

return SI;
}
// No hay sincronismo
else {
// Reseteo de los contadores
control_bert[PATTERN_CONTROL] = control_bert[PATTERN_CONTROL] & 0xEF;
escribe_par_bert(PATTERN_CONTROL, 1); // LATCH COUNT = 0
control_bert[PATTERN_CONTROL] = control_bert[PATTERN_CONTROL] | 0x10;
escribe_par_bert(PATTERN_CONTROL, 1); // LATCH COUNT = 1

return NO;
}
}

/****************************************************************************
FUNCION: busca_equipo_ber
DESCRIPCION: Función que se ejecuta únicamente para comprobar la correcta
conexión de la placa de medición de BER
PARAMETROS DE ENTRADA: No
PARAMETROS DE SALIDA: No
RESULTADO Y ERRORES: int 1 si la placa funciona correctamente, 0 si no se
encuentra (porque no está alimentada, o no conectada al puerto paralelo)
OBSERVACIONES:
****************************************************************************/
int busca_equipo_ber(void) {
// Escritura en el bus del dato a cargar
// byte_datos = 0x80;
byte_datos = 0xA5;
carga_pp (byte_datos, LATCH0, CHIP1);

// Lectura del valor que se acaba de escribir en la tarjeta de BER


lee_par_bert(BUS, 0, 0);

// if (byte_datos == 0x80) return SI;


if (byte_datos == 0xA5) return SI;
else return NO;
}
C.3 Ficheros de Matlab 227

C.3. Ficheros de Matlab


Fichero ad9853 srrc.m
% FICHERO DE SIMULACIÓN DE FILTRO FIR EN COSENO ALZADO EN EL AD9853
clear
% CAMBIO AL DIRECTORIO
cd d:\mis_documentos_d\matlab\pfc

% Definimos las constantes


alfa = 0.5;
BW = 0.5*(1+alfa);
PROC_GAIN=1;
SCALE = 511;
TAPS = 41;
FreqScale = 4;

stopband = 0.5*(1+alfa);
passband = 0.5*(1-alfa);

% Para plotear la funcion SRRC


freq_pts = 250;
df = stopband /(freq_pts - 1);
n = [0 : freq_pts-1];
fn = df*n;

% Definimos el eje Ttap


tap =[0 : TAPS-1];
t_taps= (1/FreqScale)*(tap - (TAPS-1)/2);

% Dividimos el eje de frecuencias entre 0 y BW en ’TAPS’ puntos


f = linspace (0,BW,TAPS);

%Calculo de la respuesta impulsiva h(t)


for i = 1 : TAPS % El resultado es un resultado h(t), luego el array debe de ser de tiempo

% fn es un array de [0:stopband], que son los valores para los que la integral no es nula
for m = 1 : freq_pts
array_1(m)= SRRCpos(fn(m), passband, stopband, alfa);
array_2(m)= cos( t_taps(i)*2*pi .*fn(m));
end
Array_temp = array_1 .* array_2;

h(i) = trapz(Array_temp);
end
% Borramos algunas variables temporales
clear Array_temp array_1 array_2 m i

htap = round (h .* (SCALE*PROC_GAIN/max(h))); plot (tap,htap) grid

% Rotulamos la grafica
xlabel(’TAP’);
ylabel(’htap’);
title(’ RESPUESTA IMPULSIVA SCCR ’);

% Escalamos la grafica
axis([0 40 min(htap)-10 max(htap)+10]);

% Calculo de respuesta en frecuencia


% Hacemos la fft
% Como tenemos 250 puntos en frecuencia calculamos la fft para 250 puntos
HTap = fft(htap,250);

% Calculamos el modulo
Modulo_H = abs(HTap(1:126));
%Modulo_H = abs(HTap(1:250));
% NOTA : se calcula el modulo solo de la mitad de los
% puntos, ya que el espectro es simetrico
C.3 Ficheros de Matlab 228

% Normalizamos (dividimos por el maximo)


Modulo_H = Modulo_H / max(Modulo_H);

% Pasamos a logaritmico
Modulo_H_dB = 20 * log10(Modulo_H);

% nueva figura para representar el espectro


figure(2)

% Escalamos el eje de frecuencia


%f = fn(1:250)* (FreqScale / stopband);
f = fn(1:126)* (FreqScale / stopband);

plot(f,Modulo_H_dB) grid

% Rotulamos la grafica
xlabel(’FREQUENCIA (fn)’);
ylabel(’Hn (dB)’);
title(’ RESPUESTA EN FRECUENCIA NORMALIZADA SCCR ’);

% Escalamos la grafica
axis([0 max(f) -65 max(Modulo_H_dB)+5]);
% Escalamos la grafica para detalle
%axis([0 1 -6 max(Modulo_H_dB)]);
C.3 Ficheros de Matlab 229

Fichero cic.m
% FICHERO DE SIMULACIÓN DE FILTRO FIR EN COSENO ALZADO COMPENSANDO
% LA CAIDA DE LAS ETAPAS CIC
clear

% Definimos las constantes


alfa = 0.5;

BW = 0.5*(1+alfa);
PROC_GAIN=1;
SCALE = 511;
TAPS = 41;
FreqScale = 4;

% Factor de interpolación
R = 6;
% Detalles de construcción interna del filtro CIC
N = 4; M = 1;
% Parámetro de ajuste
beta = 0.90;

stopband = 0.5*(1+alfa); passband = 0.5*(1-alfa);

% Para plotear la funcion SRRC


freq_pts = 250; df = stopband /(freq_pts - 1); n = [0 :
freq_pts-1]; fn = df*n;

% Definimos el eje Ttap


tap =[0 : TAPS-1]; t_taps= (1/FreqScale)*(tap - (TAPS-1)/2);

% Dividimos el eje de frecuencias entre 0 y BW en ’TAPS’ puntos


f = linspace (0,BW,TAPS);

%Calculo de la respuesta impulsiva h(t)


for i = 1 : TAPS % El resultado es un resultado h(t), luego el array debe de ser de tiempo

% fn es un array de [0:stopband], que son los valores para los que la integral no es nula
for m = 1 : freq_pts
array_1(m)= SRRCpos(fn(m), passband, stopband, alfa);
array_2(m)= cos( t_taps(i)*2*pi .*fn(m));
end
Array_temp = array_1 .* array_2;

h(i) = trapz(Array_temp);
end
% Borramos algunas variables temporales
clear Array_temp array_1 array_2 m i

htap = round (h .* (SCALE*PROC_GAIN/max(h)));

figure(1) plot (tap,htap) grid

% Escalamos la grafica
axis([0 40 min(htap)-10 max(htap)+10]);

% Rotulamos la grafica
xlabel(’TAP’);
ylabel(’htap’);
title(’ RESPUESTA IMPULSIVA SCCR’);

% Escalamos la grafica
axis([0 40 min(htap)-10 max(htap)+10]);

% Calculo de respuesta en frecuencia


% Hacemos la fft
% Como tenemos 250 puntos en frecuencia calculamos la fft para 250 puntos
HTap = fft(htap,250);
C.3 Ficheros de Matlab 230

% Calculamos el modulo
Modulo_H = abs(HTap(1:126));
%Modulo_H = abs(HTap(1:250));
% NOTA : se calcula el modulo solo de la mitad de los
% puntos, ya que el espectro es simetrico

% Normalizamos (dividimos por el maximo)


Modulo_H = Modulo_H / max(Modulo_H);

% Pasamos a logaritmico
Modulo_H_dB = 20 * log10(Modulo_H);

% nueva figura para representar el espectro


figure(2)

% Escalamos el eje de frecuencia


%f = fn(1:250)* (FreqScale / stopband);
f = fn(1:126)* (FreqScale / stopband);

plot(f,Modulo_H_dB) grid

% Rotulamos la grafica
xlabel(’FREQUENCIA (fn)’);
ylabel(’Hn (dB)’);
title(’ RESPUESTA EN FRECUENCIA NORMALIZADA SCCR ’);

% Escalamos la grafica
axis([0 max(f) -65 max(Modulo_H_dB)+5]);
% Escalamos la grafica para detalle
%axis([0 1 -6 max(Modulo_H_dB)]);

%%%%%%%%%%%%%%%%%Nuevos cálculos incluyendo compensación%%%%%%%%%%%%%%%%%%%%

%Calculo de la respuesta impulsiva h1(t);


for i = 1 : TAPS % El resultado es un resultado h(t), luego el array debe de ser de tiempo

% fn es un array de [0:stopband], que son los valores para los que la integral no es nula
for m = 1 : freq_pts
if fn(m)<(beta*BW)
si(m) = abs( hcic( 0, R, M, N ) / hcic( fn(m)/FreqScale, R, M, N ));
else
si(m) = 1;
end
array_1(m)= SRRCpos(fn(m), passband, stopband, alfa)*si(m);
array_2(m)= cos( t_taps(i)*2*pi .*fn(m));
end
Array_temp = array_1 .* array_2;

h1(i) = trapz(Array_temp);
end

% nueva figura para representar el espectro


figure(3)

h1tap = round (h1 .* (SCALE*PROC_GAIN/max(h1)));


plot (tap,h1tap)
grid

% Rotulamos la grafica
xlabel(’TAP’);
ylabel(’h1tap’);
title(’ RESPUESTA IMPULSIVA SCCR COMPENSADA’);

% Escalamos la grafica
axis([0 40 min(h1tap)-10 max(h1tap)+10]);
C.3 Ficheros de Matlab 231

% Calculo de respuesta en frecuencia de la RESPUESTA COMPENSADA


% Hacemos la fft
% Como tenemos 250 puntos en frecuencia calculamos la fft para 250 puntos
HTap_cic = fft(h1tap,250);

% Calculamos el modulo
Modulo_H_cic = abs(HTap_cic(1:126));

% Normalizamos (dividimos por el maximo)


Modulo_H_cic = Modulo_H_cic / max(Modulo_H_cic);

% Pasamos a logaritmico
Modulo_H_cic_dB = 20 * log10(Modulo_H_cic);

% nueva figura para representar el espectro


figure(4)

% Escalamos el eje de frecuencia


f_cic = fn(1:126)* (FreqScale / stopband);

plot(f_cic,Modulo_H_cic_dB) grid

% Rotulamos la grafica
xlabel(’FREQUENCIA (fn)’);
ylabel(’Hn (dB)’);
title(’ RESPUESTA EN FRECUENCIA COMPENSADA SCCR ’);

% Escalamos la grafica
axis([0 max(f_cic) -65 max(Modulo_H_cic_dB)+5]);
% Escalamos la grafica para detalle

%%%%%%%%%%%%%%%%%%%%%%%%% Todo en la misma gráfica%%%%%%%%%%%%%%%%%%%%%%

figure (5)
plot (tap,htap,tap,h1tap,’r’)
grid

% Rotulamos la grafica
xlabel(’TAP’);
ylabel(’htap , h1tap’);
title(’ RESPUESTA IMPULSIVA Y MODIFICADA SCCR ’);

% Escalamos la grafica
axis([0 40 min(htap)-10 max(htap)+10]);

figure(6)
plot(f,Modulo_H_dB,f,Modulo_H_cic_dB,’r’)
grid

% Rotulamos la grafica
xlabel(’FREQUENCIA (fn)’);
ylabel(’H (dB) , H precom (dB)’);
title(’ RESPUESTA EN FRECUENCIA NORMALIZADA Y MODIFICADA SCCR ’);

% Escalamos la grafica
axis([0 max(f) -65 max(Modulo_H_dB)+5]);
Bibliografı́a

[1] Inc. Analog Devices. High Speed Design Techniques. Prentice Hall, California USA,
2 edition, 1996.
[2] RF/SS. Sss-online. Compañı́a consultora, RF/Spread Spectrum Consulting, sss-
mag.com/dds.html, 1998.
[3] Solomon W. Golomb. Shift Register Sequences. Aegean Park Press, California, 1982.
[4] Recomendación UIT-T G.821. Caracterı́stica de error de una conexión digital inter-
nacional que funciona a una velocidad binaria inferior a la velocidad primaria y forma
parte de una red digital de servicios integrados. Technical report, UIT-T, 1996.
[5] Recomendación UIT-T G.826. Parámetros y objetivos de caracterı́stica de error para
trayectos digitales internacionales de velocidad binaria constante que funcionan a la
velocidad primaria o a velocidades superiores. Technical report, UIT-T, 1996.
[6] Harris. Technical report, harris semiconductors. Technical report, www.Harris.com,
1998.
[7] Analog. Analog devices. Technical report, www.analog.com, 2000.
[8] H. Nicholas III and H. Samueli. An analysis of the output spectrum of direct digital
frequency synthesizers in the presence of phase-accumulator truncation. Technical
report, 41 st Annual Frequency Control Symposium, 1987.
[9] Bernard Sklar. Digital Communications, fundamentals and applications. Prentice-
Hall International, New Jersey, 1988.
[10] Lhon G. Proakis. Digital Communications. McGraw-Hill International, USA, 2 edi-
tion, 1989.
[11] Alan V. Oppenheim y Ronald W. Schafer. Discrete-Time Signal Processig. Prentice-
Hall International, New Jersey, 1989.
[12] Analog Devices. Ad9853.pdf. Catálogo del fabricante, Analog Devices, 1999.
[13] Craig Peacock. Interfacing the standard parallel port. Portal de internet,
www.geocities.com/SiliconValley/Bay/8302/, Abril 1997-1999.
[14] Dallas Semiconductor. Ds2172.pdf. Catálogo del fabricante, Dallas Semiconductor,
1998.
[15] TTC. Fireberd 6000 user´s guide. Manual de usuario, Telecomunications Tecniques
Corporation, Germantown, Maryland, 1988.

232
BIBLIOGRAFÍA 233

[16] Petereson W. W. y Weldon E. J. Error Correcting Codes. MIT Press, Cambridge,


Mas, 1972.

[17] Mini-Circuits. Rf/if designers handbook. Catalog, Mini-Circuits, 1998.

También podría gustarte

pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy