universidad nacional de ingenierÍa -...
TRANSCRIPT
UNIVERSIDAD NACIONAL DE INGENIERÍA
FACULTAD DE INGENIERÍA ELÉCTRICA Y ELECTRÓNICA
ANÁLISIS E IMPLEMENTACIÓN DE UN ALGORITMO DE MITIGACIÓN DEL EFECTO DOPPLER PARA RECEPTORES GPS, EN UN ARREGLO DE
COMPUERTAS LÓGICAS PROGRAMABLES EN CAMPO (FPGA), UTILIZANDO EL PROCESADOR SOFT LEON
TESIS
PARA OPTAR EL TÍTULO PROFESIONAL DE:
INGENIERO DE TELECOMUNICACIONES
PRESENTADO POR:
JEAN GERARD LEÓN HUACA
PROMOCIÓN
2011-I
LIMA – PERÚ 2015
ANÁLISIS E IMPLEMENTACIÓN DE UN ALGORITMO DE MITIGACIÓN DEL EFECTO DOPPLER PARA
RECEPTORES GPS, EN UN ARREGLO DE COMPUERTAS LÓGICAS PROGRAMABLES EN CAMPO (FPGA),
UTILIZANDO EL PROCESADOR SOFT LEON
Dedicatoria:
Agradezco a mis seres queridos como a
mis padres y hermanos. De la misma
manera agradezco el apoyo
proporcionados por mi asesor y el Dr.
Emmanuel Boutillón.
SUMARIO
La presente tesis trata sobre el análisis e implementación de un algoritmo de mitigación del
efecto Doppler para receptores GPS, en un Arreglo de Compuertas Lógicas Programables
en Campo (FPGA), utilizando el procesador Soft LEON, el cual ha sido realizado en base a
los conocimientos actuales sobre los algoritmos de seguimiento. Este algoritmo sigue la
señal adquirida y de esa forma realiza una correcta demodulación de la señal.
Este algoritmo consta de varios filtros de seguimiento de fase, frecuencia Doppler y retardo
del código PRN lo cual permite procesar la información y correge las señales recibidas.
Finalmente, la señal corregida es demodulada y es usada para la detección de la posición
del receptor orbitando en el espacio.
La implementación del algoritmo es fácilemente mejorada, debido a su programación en
lenguaje C, y como está embebido en un procesador para uso aero espacial, este tiene
robustez en caso de falla en el espacio.
ÍNDICE SUMARIO...…......................................................................................................................v
CAPÍTULO I
INTRODUCCIÓN ............................................................................................................... 1
1.1 Planteamiento del problema de tesis ...................................................................... 1
1.2 Objetivo general ....................................................................................................... 2
1.3 Objetivos específicos ................................................................................................ 2
1.4 Justificación .............................................................................................................. 2
1.5 Alcances y delimitaciones ........................................................................................ 3
1.6 Recapitulación .......................................................................................................... 3
CAPÍTULO II CONCEPTOS DE SISTEMA DE POSICIONAMIENTO GLOBAL ............................ 5
2.1 Introducción ............................................................................................................. 5
2.2 Componentes de un sistema GNSS ........................................................................ 5
2.3 Posicionamiento del sistema .................................................................................... 6
2.4 Fundamentos de espectro ensanchado ................................................................... 7
2.5 Señales del Sistema GPS ......................................................................................... 8
2.5.1 GPS L1 C/A .............................................................................................................. 8
2.5.2 GPS L5 .................................................................................................................... 10
2.5.3 Generación de los códigos C/A para GPS ............................................................ 10
2.6 Señales del Sistema Galileo ................................................................................... 10
2.6.1 Galileo E1 OS ......................................................................................................... 11
2.6.2 Galileo E5a ............................................................................................................. 11
2.6.3 Densidad Espectral de Potencia ........................................................................... 12
vii
2.7 Desafíos de la implementación en el espacio de un receptor GNSS .................. 12
2.7.1 Efecto Doppler ....................................................................................................... 12
2.7.2 Multitrayecto .......................................................................................................... 14
2.7.3 Interferencia ........................................................................................................... 14
2.7.4 Centelleo ionosférico .............................................................................................. 15
2.8 Procesamiento de la señal GNSS recibida ........................................................... 16
2.8.1 Principio de adquisición ........................................................................................ 17
2.8.2 Principio de seguimiento ....................................................................................... 18
CAPÍTULO III
ANALISIS DEL ALGORITMO DE MITIGACION DEL EFECTO DOPPLER PARA GPS PROPUESTO ................................................................................................ 21
3.1 Introducción ........................................................................................................... 21
3.2 Filtro de entrada .................................................................................................... 21
3.3 Correlación e integración ...................................................................................... 21
3.4 Lazo de seguimiento en fase y frecuencia ............................................................ 23
3.4.1 Discriminador de fase ............................................................................................ 24
3.4.2 Discriminador de frecuencia ................................................................................. 25
3.4.3 Filtro de lazo ........................................................................................................... 26
3.4.4 Oscilador controlado digitalmente (NCO) .......................................................... 27
3.5 Lazo de seguimiento del retardo de código ......................................................... 28
3.5.1 Discriminador de código ....................................................................................... 29
3.5.2 Factor de escala ...................................................................................................... 30
3.5.3 Oscilador controlado digitalmente (NCO) ........................................................... 31
3.6 Generador de códigos réplica ............................................................................... 31
3.7 Detectores de bloqueo ............................................................................................ 31
3.7.1 Detector de bloqueo de fase .................................................................................. 32
3.7.2 Detector de bloqueo de código .............................................................................. 32
3.7.3 Detector de bloqueo falso ...................................................................................... 34
viii
3.8 Detección de la transición de los bits de datos .................................................... 35
3.9 Demodulación de la señal ...................................................................................... 36
CAPÍTULO IV
IMPLEMENTACIÓN DEL ALGORITMO DE MITIGACIÓN DEL EFECTO DOPPLER PARA GPS EN UN FPGA ............................................................................ 37
4.1 Introducción ........................................................................................................... 37
4.2 El Procesador LEON ............................................................................................. 37
4.3 Arquitectura del Procesador LEON .................................................................... 39
4.3.1 El procesador LEON con arquitectura SPARC V8 ........................................... 39
4.3.2 Interfaces de memoria ........................................................................................... 39
4.3.3 Registro de estado del AHB .................................................................................. 40
4.3.4 Enlaces SpaceWire ................................................................................................. 40
4.3.5 Unidad temporizadora .......................................................................................... 40
4.3.6 Control de interrupción ........................................................................................ 40
4.3.7 UART ...................................................................................................................... 40
4.3.8 Puerto entrada/salida de propósito general ........................................................ 40
4.3.9 Ethernet .................................................................................................................. 41
4.3.10 Controlador de Área de Red (CAN-2.0) .............................................................. 41
4.3.11 Controlador VGA .................................................................................................. 41
4.3.12 Interfaz de teclado PS/2 ......................................................................................... 41
4.3.13 Generador de reloj ................................................................................................. 41
4.4 Características del Procesador LEON ................................................................. 41
4.4.1 Tolerancia a fallas .................................................................................................. 41
4.4.2 Librería GRLIB ..................................................................................................... 41
4.4.3 Creación de Código C ............................................................................................ 42
4.5 Entorno de desarrollo ............................................................................................ 42
4.5.1 Plugin del Procesador LEON para el entorno Eclipse ....................................... 42
4.5.2 GRMON (Gaisler Research Monitor) ................................................................. 42
ix
4.6 Arquitectura propuesta ......................................................................................... 44
4.7 Escenario de pruebas ............................................................................................. 45
4.7.1 Herramientas utilizadas ........................................................................................ 45
4.7.2 Síntesis del Procesador LEON en el FPGA ......................................................... 46
4.7.3 Configuración de la transmisión serial ................................................................ 48
4.7.4 Generación de la señal GPS desde el computador .............................................. 54
CAPÍTULO V
ANÁLISIS DE RESULTADOS ........................................................................................ 59
5.1 Síntesis del Procesador LEON en la Tarjeta Digilent Spartan 3E-1600
Development Board ........................................................................................................... 59
5.2 Implementación del algoritmo de seguimiento en el Procesador LEON .......... 59
CONCLUSIONES Y RECOMENDACIONES .............................................................. 63
ANEXO A
HOJA DE DATOS DE LA DIGILENT SPARTAN 3E-1600 DEV. BOARD .............. 64
ANEXO B
CÓDIGO BARE C DEL ALGORITMO DE SEGUIMIENTO GNSS ........................ 66
ANEXO C
CÓDIGO C DEL GENERADOR DE SEÑALES GPS ................................................ 135
ANEXO D
CÓDIGO C DE LA TRANSMISIÓN SERIAL ............................................................ 145
BIBLIOGRAFÍA ............................................................................................................. 151
ÍNDICE DE FIGURAS Figura 2.1 Componentes de un sistema GNSS 6
Figura 2.2 Proceso de generación de la señal con espectro ensanchado 8
Figura 2.3 Constelación del sistema GPS 9
Figura 2.4 DEP de la señal GPS L1 C/A 9
Figura 2.5 Generador de código C/A 10
Figura 2.6 Densidad espectral de potencia para BOC(1,1) 13
Figura 2.7 Frecuencia Doppler recibida por un receptor GNSS 14
Figura 2.8 Señal reflejada y bloqueada por un satélite (obstáculo) 15
Figura 2.9 Distribución Nakagami-m para m=2 17
Figura 2.10 Proceso de adquisición de la señal 18
Figura 2.11 Primer método del algoritmo de adquisición 19
Figura 2.12 Segundo método del algoritmo de adquisición 19
Figura 2.13 Sistema de seguimiento típico 20
Figura 3.1 Etapa de correlación 22
Figura 3.2 Correlación e integración de la señal 23
Figura 3.3 Salida de los diferentes discriminadores del filtro de lazo Costas 24
Figura 3.4 Comparación de la salida de los diferentes discriminadores de frecuencia 26
Figura 3.5 Filtro de lazo para el filtrado de señal y frecuencia 27
Figura 3.6 Diagrama del cálculo de la banda de ruido 27
Figura 3.7 Sistema global de filtro de fase y frecuencia 28
Figura 3.8 NCO de la portadora 28
Figura 3.9 Comparación de la salida de los diferentes discriminadores de código 30
Figura 3.10 Salida completa del discriminador de código 30
Figura 3.11 Generación del factor de escala 31
Figura 3.12 Generación de ����� a través de un oscilador controlado
digitalmente (NCO) 31
Figura 3.13 Generación de los códigos PRN 32
xi
Figura 3.14 Detector de bloqueo de fase 33
Figura 3.15 Detector de bloqueo de código 34
Figura 3.16 Relación entre el valor de bloqueo y la tasa C/N0 estimada. 34
Figura 3.17 Demodulación de la señal 36
Figura 4.1 Diagrama de bloques del procesador LEON3 para una tarjeta
Spartan3 1500 39
Figura 4.2 Entorno de desarrollo de una aplicación para el procesador LEON
en Eclipse. 43
Figura 4.3 Conexión al procesador LEON a través de un puerto serial utilizando
GrmonRCP 43
Figura 4.4 Arquitectura propuesta para el sistema de seguimiento 44
Figura 4.5 Diagrama del escenario de pruebas del algoritmo de seguimiento 45
Figura 4.6 Escenario de pruebas del algoritmo de seguimiento 46
Figura 4.7 Ventana principal de la configuración del Procesador LEON 46
Figura 4.8 Ventana de configuración de la unidad de punto flotante. 47
Figura 4.9 Ventana de Xilinx ISE 48
Figura 4.10 Opción Synthesize-XST en Xilinx ISE 48
Figura 4.11 Diagrama de bloques del APBUART 49
Figura 4.12 Registro de datos del APBUART 49
Figura 4.13 Registro de estado del APBUART 50
Figura 4.14 Registro de control del APBUART 51
Figura 4.15 Registro escalador del APBUART 51
Figura 4.16 Trama de datos de un envío serial para una tramas de datos sin
paridad (a) y con paridad (b) 52
Figura 4.17 Configuración del puerto serial en el computador 54
Figura 4.18 Salida del programa de adquisición de señales GNSS 56
Figura 4.19 Detección del desfasaje y la frecuencia Doppler para la señal
con PRN 1 57
Figura 4.20 Detección del desfasaje y la frecuencia Doppler para la señal
con PRN 2 57
Figura 4.21 Detección del desfasaje y la frecuencia Doppler para la señal
con PRN 15 58
Figura 5.1 Seguimiento de la frecuencia 61
xii
Figura 5.2 Gráfica desviación estándar de la frecuencia Doppler (Hz)
vs el valor C/N0 estimado (dB-Hz) 62
Figura 5.3 Gráfica desviación estándar del retardo (us) vs el valor C/N0
estimado (dB-Hz) 62
ÍNDICE DE TABLAS Tabla 2.1 Tamaño de los códigos para la señal Galileo E5a 12
Tabla 3.1 Discriminadores de fase para un filtro de lazo Costas 24
Tabla 3.2 Discriminadores de frecuencia 25
Tabla 3.3 Discriminadores de código 29
Tabla 4.1 Registros del APBUART 49
Tabla 4.2 Valores a ingresar en el archivo “Parameters.txt” 55
Tabla 4.3 Señales GPS de prueba 56
Tabla 5.1 Resultados de la síntesis del Procesador LEON 59
Tabla 5.2 Parámetros de la prueba 60
Tabla 5.3 Resultados de la implementación del algoritmo de seguimiento en el
Procesador LEON 60
CAPÍTULO I INTRODUCCIÓN
1.1 Planteamiento del problema de tesis
Un satélite posee una posición en el espacio, es decir el lugar donde se encuentra, y una
actitud, la cual es la rotación de objeto específico respecto a un objeto de referencia el cual
ha sido bien definido en el espacio [1]. La actitud es determinada por el satélite gracias a
los giroscopios, sensores de luz y tierra. En la actualidad, la posición de los satélites es
determinada por los radares en la estación terrena. Sin embargo, la implementación de
estos radares es a la vez cara y poco precisa, dando a cada satélite un gran volumen por el
cual se puede localizar la posición del satélite (con aristas de pocos kilómetros), y
reduciendo la densidad de los satélites.
Por esta razón, se implementó un sistema que permita dar una posición precisa logrando la
extensión de los receptores GNSS (Sistema Global de Navegación por Satélite) desde la
Tierra (el conocido GPS) al espacio. En el año 1998, se desarrolló un nuevo enfoque que
permita aprovechar las ventajas de los receptores GNSS (en forma específica GPS) para la
implementación en satélites [2].
Se escogió como primera opción la implementación de un Sistema GNSS sobre un satélite
debido a las múltiples ventajas que posee: autonomía, reducidos costos de operación,
mayor precisión, control más eficiente de la posición en el espacio, menor consumo de
energía, mayor duración de las misiones y más satélites en el mismo volumen [3].
Sin embargo, debido a la alta velocidad de desplazamiento de los satélites de Órbita Baja
Terrestre (LEO) (aproximadamente 50 minutos respecto a las 6 horas de rotación alrededor
de la tierra), el efecto Doppler que afecta la señal recibida es del orden de magnitud más
grande que el efecto Doppler sobre la Tierra [2]. En consecuencia, se necesita un desarrollo
especial para un receptor LEO GNSS.
En la actualidad, existen dos Sistemas GNSS completamente implementados, los cuales
son el Sistema de Posicionamiento Global (GPS) y GLONASS (Sistema de Navegación
Global por Satélite). Además, existen dos sistemas de navegación que están en desarrollo:
2
el Sistema de Navegación Galileo (Unión Europea) [4] y el Sistema Compass o Beidou
(China) [5]. Dentro de las etapas de desarrollo del sistema Galileo y el sistema Compass, el
Sistema Galileo tendrá compatibilidad con el Sistema GPS, por ejemplo el uso de similares
rango de frecuencia entre los dos sistemas, logrando así un mayor número de satélites para
realizar sus cálculos. Por lo tanto, se espera que el Sistema Galileo se utilice a nivel
mundial en dispositivos receptores tales como teléfonos móviles, computadoras personales,
etc.
Desde el año 2000, se han desarrollado varios proyectos de investigación en la comunidad
científica sobre receptores GNSS para microsatélites (cuyo peso es entre 10 a 100 Kg), en
diferentes países como Italia, Australia, China y Francia [6] [7] [8] [9] [10] . Sin embargo,
la mayoría de ellos sólo plantean la implementación de una interfaz a nivel físico,
ocasionando grandes gastos a largo plazo en recursos económicos, personal técnico y
tiempo para la actualización y corrección de fallas del dispositivo. Como consecuencia
directa de esto, los componentes del receptor GNSS del microsatélite serán rápidamente
desactualizados.
Debido a esto, el presente estudio tiene como finalidad la implementación de un sistema de
seguimiento para un receptor GNSS a nivel hardware – software, el cual posee una parte
del algoritmo de seguimiento dentro de un dispositivo (procesador) como software y a
través de la configuración del procesador en VHDL, lo cual servirá para acelerar algunos
procesos que no son eficientes a nivel de software.
1.2 Objetivo general
Estudiar, analizar, simular, optimizar e implementar un algoritmo de seguimiento GNSS
para pequeños satélites.
1.3 Objetivos específicos
La presente tesis tiene como objetivos específicos lo siguiente:
� Implementación y optimización del algoritmo de seguimiento en lenguaje C dentro del
Procesador LEON.
� Configuración y síntesis del Procesador LEON en VHDL.
� Implementar el algoritmo de seguimiento en un FPGA Digilent Spartan 3E-1600
Development Board.
1.4 Justificación
El contar con un sistema hardware-software que permita implementar un sistema de
seguimiento para receptores GNSS, el cual estará orientado a pequeños satélites,
3
beneficiará a la comunidad académica ya que cubrirán tópicos que no han sido
mayormente analizados en detalle y se están pasando por alto en otras investigaciones,
como son la flexibilidad del sistema, permitir la incorporación de otros sistemas GNSS y la
reducción de costos de implementación a largo plazo.
1.5 Alcances y delimitaciones
La presente tesis tiene los siguientes alcances:
� Proporcionar un sistema de seguimiento a nivel de hardware-software (código C dentro
de un Procesador y configuración del Procesador en VHDL).
� Proporcionar flexibilidad de modificación del código C lo cual permita adaptarlo a otros
sistemas GNSS (Galileo, Compass o GLONASS), dejando las implementaciones de estos
sistemas GNSS a futuros trabajos de investigación.
Sin embargo, la presente tesis tiene las siguientes delimitaciones:
� Solamente se analizará la etapa de seguimiento de un receptor GNSS, dejando las otras
etapas a futuros trabajos de investigación.
� Se analizará solamente el efecto Doppler en el receptor GNSS debido a que es el mayor
responsable de la degradación de las señales recibidas.
� Estará orientada a GPS debido a que es el sistema GNSS mayormente usado; sin
embargo, se van a dar ciertas modificaciones que se pueden realizar para realizar la
implementar en el sistema Galileo.
1.6 Recapitulación
En el Capítulo I se plantea la problemática a estudiar, el objetivo general y los específicos
de la tesis, la justificación por la cual se elige este tema y sus alcances y limitaciones. En el
Capítulo II se tratará acerca de los fundamentos de los sistemas GNSS como son los
componentes de un sistema GNSS, posicionamiento del receptor, la señales utilizadas en
los sistemas GPS y Galileo, la estructura de la señal GNSS recibida, componentes de un
receptor GNSS y los fundamentos de las etapas de adquisición y seguimiento. En el
Capítulo III se desarrollará el algoritmo de seguimiento propuesto y además se darán los
lineamientos para la adaptación al sistema Galileo. En el Capítulo IV se tratará acerca de la
arquitectura hardware-software utilizada en la implementación del sistema y como la etapa
de hardware interactúa con el software que está implementado dentro del procesador.
Además, se detallará el escenario de pruebas que se ha utilizado para probar el
funcionamiento del algoritmo. En el Capítulo V se analizarán los resultados obtenidos del
escenario de pruebas del algoritmo. Finalmente, en Conclusiones y Recomendaciones, se
4
dará a conocer las conclusiones del proyecto y se plantearán trabajos futuros en base a la
investigación realizada.
CAPÍTULO II CONCEPTOS DE SISTEMA DE POSICIONAMIENTO GLOBAL
2.1 Introducción
Durante los últimos 15 años han existido y existen muchos tópicos interesantes dentro de
los Sistemas GNSS, como son:
a) La puesta en operación del sistema GPS en 1993, cuando 24 satélites GPS estuvieron
operando en órbitas asignadas y disponibles tanto para uso militar como para uso civil.
b) El nuevo sistema europeo satelital Galileo.
c) La modernización de los sistemas satelitales de los Estados Unidos de Norteamérica,
GPS.
d) La reconstrucción del sistema de satélites rusos GLONASS.
Debido a esto, la definición de sistemas GNSS es la interoperatividad y compatibilidad
técnica entre los diversos sistemas de navegación, como son GPS, Galileo y Glonass, para
ser usados en el campo civil sin tener en cuenta las barreras limítrofes propias de cada país
a fin de promover el bienestar y comodidad de la sociedad [11].
2.2 Componentes de un sistema GNSS
El sistema GNSS consiste de tres segmentos [12]:
a) Segmento de espacio: Consiste de un grupo o constelación de satélites1 en órbita que
circulan la Tierra aproximadamente dos veces al día. A fín de proveer una cobertura
adecuada de las señales en tierra, debe haber entre 20 y 30 satélites dentro de una
constelación y deben estar distribuidos entre tres y seis diferentes planos orbitales.
b) Segmento de control: Consiste de un sistema de estaciones de seguimiento localizadas
alrededor del mundo, las cuales constantemente recepcionan las señales de los satélites.
Estas usan esta información para calcular las órbitas exactas y las correcciones de la deriva
del reloj2 para todos los satélites y transmite la información al satélite respectivo.
1 Algunos autores prefieren llamar a los satélites vehículo espacial (SV) en vez de satélite. 2 Se entiende por deriva de reloj a un conjunto de fenómenos que ocasionan una desincronización de un reloj respecto a los otros. En el espacio suele ocurrir debido a la dilatación del tiempo. Para mayor información consultar [23].
6
c) Segmento de usuario: Consiste de los receptores GNSS y los usuarios. Los receptores
GNSS reciben las señales de los satélites y con esa información obtienen su posición,
velocidad y tiempo estimado.
En la figura 2.1 se observa cada uno de los componentes del sistema GNSS. El segmento
de espacio cuenta con una etapa: la constelación de satélites. El segmento de control cuenta
con tres etapas: red de estaciones de monitoreo, estaciones de control y estaciones de
subida. El segmento de usuario cuenta con cuatro etapas: antena, receptor, procesador de
rango y procesador de navegación.
Figura 2.1 Componentes de un sistema GNSS
La función que cumple el segmento de usuario son las siguientes [13]:
a) La antena convierte las señales de radio a señales eléctricas.
b) El receptor demodula las señales usando un reloj el cual le proporciona un tiempo de
referencia.
c) El procesador de rango utiliza los algoritmos de adquisición y seguimiento para
determinar la distancia entre la antena a cada uno de los satélites de las cuales provienen
las señales recibidas.
d) El procesador de navegación utiliza la medición de distancia para calcular la posición,
velocidad y tiempo del receptor.
2.3 Posicionamiento del sistema
Una posición de un objeto utilizando el sistema GNSS es determinado por el cálculo de la
distancia en tres dimensiones. El tiempo de llegada de la señal ��� es determinado por el
reloj receptor, mientras que el tiempo de transmisión �� de cada señal es determinado
7
utilizando sus ranging code3 y la información del mensaje.
Cuando el receptor y los satélites están sincronizados, el alcance ρ desde el satélite hasta el
receptor se obtiene del producto de la velocidad de la luz y de la diferencia entre el tiempo
de llegada y el tiempo de transmisión de la señal. De esta forma, el alcance ρ es expresado
según la ecuación (2.1).
� = ���,� − ��,��� ( 2.1)
Donde el índice j es utilizado para denominar el número del satélite o el canal receptor. En
este modelo, no son considerados los errores de la fuente de transmisión [13].
Sin embargo, el receptor y el satélite no están realmente sincronizados, por lo cual la
diferencia entre ��� y �� es una función que depende del alcance del satélite al receptor y
del desplazamiento del reloj del receptor, tal como se muestra en la ecuación (2.2).
��� = ���,� − ��,��� + � ∗ � ( 2.2)
Donde b sería el desplazamiento del reloj y ��� es conocido como el pseudo alcance [14].
Finalmente, se debe considerar que la cantidad mínima de satélites para realizar el
posicionamiento del receptor son cuatro [15].
2.4 Fundamentos de espectro ensanchado
Un sistema de espectro ensanchado posee las siguientes características [14]:
a) La información es modulada en la portadora de tal forma que posea un gran ancho de
banda respecto a la tasa de transmisión de la información.
b) El transmisor utiliza una señal determinística para modular la señal de la información y
de esa forma ensanchar el espectro de la señal transmitida. A esta señal determinística se le
conoce como código PRN (ruido pseudo aleatorio).
c) El receptor realiza la correlación de la señal recibida con una copia del código PRN en
el proceso de modulación de la información.
En la figura 2.2 se muestra el proceso de generación de la señal con espectro ensanchado.
Respecto a los códigos PRN, estos son una secuencia finita de bits las cuales deben
cumplir las siguientes condiciones4 [14] [16] [17]:
a) Propiedad de balance: En cada periodo de un código PRN, la diferencia de la cantidad
de símbolos ‘+1’ respecto a la cantidad de símbolos ‘-1’ es 1.
3 Se llama ranging code al identificador que es enviado desde el transmisor y es utilizado para determinar el tiempo de transmisión que una señal demora desde el transmisor hacia el receptor. 4 Estas propiedades se les conocen también como propiedades de Golomb. Sin embargo, existen más propiedades de los códigos PRN, para mayor información consultar [15].
8
b) Ejecución: Se llama ejecución de longitud k a una secuencia de k idénticos dígitos, es
decir sea la secuencia ���, ����, … , ������ en cualquier secuencia de código PRN tal que ���� ≠ �� = ⋯ = ������ ≠ ����.
Figura 2.2 Proceso de generación de la señal con espectro ensanchado
En cualquier código PRN, la mitad de las ejecuciones tienen longitud 1, la cuarta parte de
las ejecuciones tienen longitud 2, la octava parte de las ejecuciones tienen longitud 3, la
dieciseisava parte de las ejecuciones tienen longitud 4 y así sucesivamente hasta que estas
fracciones den un número entero de ejecuciones. También, en cada caso, el número de
ejecuciones de -1’s es igual al número de ejecuciones de +1’s.
c) Autocorrelación: La autocorrelación de la secuencia PRN de longitud N está dado por
la ecuación (2.3).
#�$ = % 1 − |$| (1) + 1* , +,-, |$| ≤ /0− 1) , +,-, /0 ≤ |$| ≤ �) − 1 /0 ( 2.3)
2.5 Señales del Sistema GPS
El Sistema GPS fue creado por el Departamento de Defensa de los Estados Unidos.
Consiste de 24 satélites posicionados en seis planos orbitales de la Tierra con un radio
orbital aproximado de 26600 Km. En la figura 2.3 se muestra una representación de la
constelación del Sistema GPS.
A continuación se presentan las principales señales del Sistema GPS.
2.5.1 GPS L1 C/A
La señal GPS L1 C/A se emite en la frecuencia: fL1=1575.42MHz = 154*10.23MHz,
siendo 10.23 MHz la frecuencia de referencia de los relojes atómicos ubicados en los
satélites a bordo.
La señal GPS L1 C/A se modula con un código de dispersión de 1023 chips a 1.023 MHz y
un pseudo-periodo de 1 ms. El código de dispersión posee una longitud de onda de 293 m
9
Figura 2.3 Constelación del sistema GPS
y es una secuencia pseudo aleatoria con buena auto correlación y propiedades de
ortogonalidad. Este código es una secuencia de Oro (Gold Code) y puede ser reconstituida
localmente por un generador de código. La señal GPS L1 C/A es llamada también BPSK-
R(1). El valor ‘1’ de BPSK-R(1) se toma respecto a un valor de referencia, que en este
caso es la frecuencia de 1.023 MHz.
Su Densidad Espectral de Potencia (DEP) en banda base es mostrado en la figura 2.4 y la
envolvente del PSD es representada según la ecuación (2.4).
12 3⁄ �5 = /2 . �78�9�5/2 ( 2.4)
Figura 2.4 DEP de la señal GPS L1 C/A
10
2.5.2 GPS L5
La señal GPS L5 se emite en la frecuencia: fL5=1176.45MHz = 115*10.23MHz.
La señal GPS L5 es una modulación QPSK compuesta de dos modos:
� Modo en fase, conteniendo el mensaje de navegación.
� Modo en cuadratura, no conteniendo datos.
A señal GPS L5 tiene un periodo de 10 ms y está codificado por un código de corrección
de errores. El periodo de los bits del mensaje de navegación es de 20 ms.
2.5.3 Generación de los códigos C/A para GPS
Para la generación de los códigos C/A para GPS se tiene el esquema mostrado en la figura
2.5 [15].
Figura 2.5 Generador de código C/A
Como se puede apreciar, el generador de código C/A es la suma de dos señales G1 y G2.
Las señales G1 y G2 son obtenidas mediante la operación xor de los valores almacenados
dentro de sus respectivos registros. Finalmente, se debe recalcar que cada código C/A es
diferente para cada satélite GPS.
2.6 Señales del Sistema Galileo
El Sistema Galileo es un sistema de posicionamiento global desarrollado por la Unión
Europea, del cual estará disponible para el año 2014. Este consistirá de 30 satélites (27
operacionales y 3 de repuesto) posicionados en la órbita MEO con un semieje mayor
11
promedio de 29601.297 Km.
A continuación se presentan las principales señales del Sistema Galileo.
2.6.1 Galileo E1 OS
La señal Galileo E1 OS se emite en la frecuencia: fE1=1575.42MHz
Además, la expresión analítica de la señal Galileo E1 OS para el k ésimo satélite está dado
por la ecuacion (2.5).
��� = √; ∙ ��� ∙ =�� ∙ ���� ∙ >� 9?@A�B� ( 2.5)
Donde:
� √;: amplitud de la señal compleja
� =�� : señal de datos
� ��� : código de dispersión
� ���� : subportadora, ���� = �7C8��78 2E5�0� o ���� = �7C8��F� 2E5�0�
� 5�0: frecuencia de la subportadora
� 5G: frecuencia de la portadora
� H: fase de la señal
Este tipo de señal es llamada también BOC(m,n) con n = fKL fMN⁄ y m = fL fMN⁄ , siendo fMN
la frecuencia de referencia del código de dispersión GPS L1 C/A: fMN=1.023 MHz. Por
ejemplo, la señal BOC(1,1) tiene una frecuencia de subportadora fKL=1.023 MHz y código
de dispersión fL=1.023 MHz.
La señal Galileo E1 OS es la combinación de dos modulaciones BOC. Esta señal es
conocida también como CBOC(3,1,1/11) y está en función de las modulaciones BOC(1,1)
y BOC(6,1). Esta señal tiene un código de dispersión de 4092 chips a 1.023 MHZ y un
pseudo periodo de 4 ms.
Finalmente, su densidad espectral de potencia en función de BOC(1,1) y BOC (6,1) se
muestra en la ecuación (2.6).
Φ2QR2�5 = 1011 ΦQR2��,� �5 + 111 ΦQR2�T,� �5 ( 2.6)
2.6.2 Galileo E5a
La señal Galileo E5a se emite en la frecuencia: fE5a=1176.45MHz.
La señal Galileo E5a es una modulación QPSK compuesta de dos modos:
� Modo en fase conteniendo el mensaje de navegación: Galileo Ea5-I
� Modo en cuadratura no conteniendo datos: Galileo Ea5-Q
12
Los códigos de dispersión de la señal Galileo Ea5 tienen una frecuencia de 10.23MHz, una
longitud de 10230 chips y un pseudo-periodo de 1 ms. Cada modo es entonces un BPSK-R
(10).
El mensaje de navegación sobre Galileo Ea5-I se emite en una secuencia binaria a 50 b.s-1.
Además, los dos modos, Galileo Ea5-I y Galileo Ea5-Q, se modulan como códigos
secundarios. En la tabla 2.1 se muestra una ampliación de lo explicado [4].
Tabla 2.1 Tamaño de los códigos para la señal Galileo E5a
Componente Periodo de pseudo
código (ms)
Tamaño del código
primario (chips)
Tamaño del código
secundario (chips)
E5a-I 20 10230 20
E5a-Q 100 10230 100
2.6.3 Densidad Espectral de Potencia
La densidad espectral de potencia de la modulación BOC en banda base está dado por la
ecuación (2.7).
UQR2�5 =VWWWXWWWY 50 Zsin ( E525�0* sin (E550 *
E5 cos ( E525�0* _9
, 8 = 25�050 +,-50 Zsin ( E525�0* sin (E550 *
E5 cos ( E525�0* _9
, 8 = 25�050 7`+,- ( 2.7)
En la figura 2.6 se muestra la densidad espectral de potencia para la modulación BOC(1,1).
Como se puede observar, la densidad espectral de potencia es diferente a la densidad
espectral de potencia de la señal GPS L1 C/A en cuanto a la cantidad de lóbulos
principales (GPS L1 C/A posee un lóbulo principal y BOC(1,1) posee dos lóbulos
principales).
2.7 Desafíos de la implementación en el espacio de un receptor GNSS
La señal GNSS es afectada por múltiples interferencias las cuales van a degradar la calidad
de recepción de la señal. En esta sección del capítulo se revisarán alguna de las principales
interferencias que ocurren en los receptores GNSS a nivel de órbitas LEO.
2.7.1 Efecto Doppler
El efecto Doppler es producido por el movimiento relativo del satélite GNSS respecto al
13
usuario o receptor. La velocidad v se calcula utilizando la información de las efemérides5 y
el modelo de la órbita del receptor. En la figura 2.7 se muestra la curva de la frecuencia
Doppler recibida por un receptor GNSS la cual depende del tiempo. Además, a medida que
el satélite esté más próximo al receptor, la frecuencia Doppler disminuirá; y a medida que
el satélite esté más lejos del receptor, la frecuencia Doppler aumentará [15].
Figura 2.6 Densidad espectral de potencia para BOC(1,1)
Se puede aproximar la frecuencia 5� utilizando la ecuación clásica Doppler, la cual se
muestra en la ecuación (2.8).
5� = 5a b1 − �cd ∙ , � e ( 2.8)
Donde 5a es la frecuencia transmitida por el satélite, cd es la velocidad relativa del satélite
respecto al receptor GNSS, , es el vector unitario que sigue la dirección de la línea de vista
del receptor al satélite y c es la velocidad de la luz.
Para un receptor en órbita LEO, el rango de la frecuencia Doppler es desde -42 KHz hasta
42 KHz, lo cual es bastante respecto al rango de la frecuencia Doppler en tierra que es
desde -4KHz hasta 4 KHz. Sin embargo, la ventaja del receptor en el espacio respecto a un
receptor en tierra es que el movimiento del receptor es muy predecible, lo cual el patrón de
búsqueda puede ser considerablemente reducido utilizando los datos del almanaque6 GNSS
[18].
5 Es una tabla de valores que proporciona la posición de los objetos en el espacio. 6 Los datos del almanaque es la información sobre la posición de los satélites. Cada satélite transmite información de posición sobre todos los satélites. El receptor almacena la información de manera que pueda determinar su propia posición. Los satélites tardan aproximadamente 12,5 minutos en transmitir los datos de posición al receptor.
14
Figura 2.7 Frecuencia Doppler recibida por un receptor GNSS
El efecto Doppler tiene un importante efecto en el sistema de seguimiento por lo cual el
sistema de seguimiento debe ser lo suficientemente robusto y veloz para detectarlo y
seguirlo ante cualquier cambio en la frecuencia Doppler, ya que la tasa de cambio de la
frecuencia Doppler es normalmente ±62 Hz.s-1.
2.7.2 Multitrayecto
El multitrayecto puede suceder si la señal se refleja en la superficie del equipo receptor.
Además, debido a que los satélites tienen formas complejas y el diseñador sólo se ha
preocupado en obtener una buena antena, el efecto multitrayecto podría ser perjudicial por
una mala ubicación de la antena dentro del receptor [19].
También existe otra forma, aunque no es tan común, de conseguir el efecto multitrayecto.
Este caso sucede si la señal a recibir pasa a través de un obstáculo, por ejemplo un satélite,
y este refleje la señal a recibir, siendo este caso el más crítico para el sistema receptor. En
la figura 2.8 se ilustra el caso en el cual se transmiten dos señales, sin embargo una de ellas
es bloqueada por un satélite y la otra es reflejada en múltiples señales debido a la presencia
de un satélite que actúa como obstáculo.
2.7.3 Interferencia
Debido a que los receptores GNSS procesan la información en base a una señal RF, estas
señales son vulnerables a interferencias RF, ya sea en forma involuntaria o intencional7. La
interferencia normalmente se clasifica como interferencia de banda ancha e interferencia
de banda angosta. Esta definición depende del ancho de banda de la señal GNSS, siendo
interferencia de banda ancha cuando el ancho de banda de la interferencia es más grande
que el ancho de banda de la señal GNSS e interferencia de banda angosta cuando el ancho
7 Una interferencia intencional se conoce como jamming.
15
de banda de la interferencia es menor que el ancho de banda de la señal GNSS.
También puede darse el caso que exista interferencia entre señales del mismo tipo, por
ejemplo dos señales GPS interfiriéndose entre sí en la etapa de recepción. A este tipo de
interferencia se conoce como interferencia intrasistema.
Figura 2.8 Señal reflejada y bloqueada por un satélite (obstáculo)
Además de la interferencia intrasistema, puede darse el caso en que una señal de otro
sistema GNSS interfiera con la señal GNSS deseada, por ejemplo una señal del sistema
Galileo interfiera con otra señal del sistema GPS. Este tipo de interferencia se le llama
interferencia entre sistemas.
2.7.4 Centelleo ionosférico
La ionósfera es una capa de la atmósfera de la Tierra que comienza a partir de los 50 km de
altura hasta varios kilómetros de la Tierra. En esta capa, la radiación solar incidente separa
una fracción de componentes neutros en iones cargados positivamente y electrones libres.
Además, la máxima densidad de electrones libres ocurre a 350 km [15].
Sin embargo, las irregularidades en la ionósfera pueden generar, dependiendo de la altitud
del receptor GNSS y la elevación aparente de los satélites GNSS, un rápido
desvanecimiento en el nivel de potencia de la señal recibida, causando un aumento del
error de posicionamiento en varias decenas de metros. Este fenómeno se conoce como
centelleo ionosférico y ocasiona problemas de seguimiento de uno o varios satélites por
cortos periodos de tiempo. Además, el centelleo ionosférico es común y más severo
durante el ciclo solar, el cual dura aproximadamente 11 años.
16
El centelleo ionosférico causa una perturbación tanto en la amplitud como en la fase de la
señal. El modelo de la señal recibida en presencia de centelleo es mostrado en la ecuación
(2.9) [15].
-�� = √2f ∙ gf ∙ ��� cos�h� + i + gi + 8�� ( 2.9)
Donde:
� f es la potencia de la señal recibida.
� h es frecuencia de la portadora (rad/s).
� ��� es la señal normalizada transmitida.
� i es la fase de la señal transmitida.
� 8�� es ruido.
� √gf es un valor escalar que caracteriza el desvanecimiento en la amplitud debido al
centelleo.
� gi es la variación de la fase debido al centelleo (rad). gf se modela generalmente siguiendo la distribución Nakagami-m cuya función de
densidad de probabilidad está dado por la ecuación (2.10) [20].
+�gf = 2`jgfj�k.lΓ�` >�jno, gf ≥ 0 ( 2.10)
Cuya media es 1 y varianza es 1 `⁄ . La intensidad de la amplitud de desvanecimiento
debido al centelleo ionosférico se caracteriza mediante el índice Uq, el cual es la inversa de
la desviación estándar de gf y cuyo valor está dado en la ecuación (2.11).
Sin embargo, debido a la propiedad de la distribución Nakagami-m, el índice Uq debe ser
menor o igual a √2.
Uq = 1√` ( 2.11)
En la figura 2.9 se muestra la distribución Nakagami-m para m = 2.
La variación de la fase debido al centelleo ionosférico se modela normalmente como una
distribución gaussiana, tal como se muestra en la ecuación (2.12).
+�gi = 1√2Ers >�nst9uvt ( 2.12)
Donde rs es la desviación estándar de la variación de la fase.
2.8 Procesamiento de la señal GNSS recibida
Un receptor capta múltiples señales GNSS, las cuales llegan con diferentes frecuencias
17
Doppler, diferentes retardos y diferentes atenuaciones. En la ecuación (2.13) se muestra la
recepción de un receptor GNSS.
Figura 2.9 Distribución Nakagami-m para m=2
��8 = w xyzy�8/� − $y �y�8/� − $y >��9?�@{|�}~ �a���|
y∈��,⋯,@�+ ��8/�
( 2.13)
Donde:
� $y: Retardo de la señal del satélite α debido a la propagación de la señal
� xy: Atenuación de la señal del satélite α
� zy: Secuencia de bits (datos) del satélite α
� �y: Señal PRN del satélite α
� �k: Fase de la portadora
� 5�y: Frecuencia Doppler del satélite α
� ��: Frecuencia intermedia
� /�: Tasa de muestreo de la señal
� �: Ruido aditivo gaussiano
En esta sección del capítulo, se explican los conceptos básicos de las etapas de adquisición
y seguimiento. En el capítulo 3 se explicará con mayor detalle cómo se procesa la señal
GNSS recibida frente al efecto Doppler dentro del sistema de seguimiento.
2.8.1 Principio de adquisición
La etapa de adquisición permite encontrar una buena estimación de la frecuencia Doppler 5�� y del retardo de la señal $̂ para cada satélite.
18
Un ejemplo de búsqueda se muestra en la figura 2.10, en la cual se busca la señal en una
grilla formada por las frecuencias y los retardos de código de la señal [19]. En este método
se realiza la búsqueda manteniendo la frecuencia fija y buscando a través de todos los
posibles retardos hasta encontrar el que tenga mayor valor. A este método se conoce como
búsqueda serial.
Figura 2.10 Proceso de adquisición de la señal
Sin embargo, el método de búsqueda serial es muy lento y puede tomar una cantidad
considerable de minutos para detectar la presencia de la señal.
Por otra parte, existen otros métodos más eficaces los cuales permiten detectar la señal en
un menor tiempo. Por ejemplo se encuentra el método de adquisición utilizando la
transformada rápida de Fourier (FFT) desarrollado por D. Akopian, el cual analiza los
inconvenientes de un receptor GPS basado en FFT y propone un FFT más eficiente,
reduciendo cálculos innecesarios y produciendo una respuesta más rápida. Para este caso
propone dos métodos [21]:
El primer método procesa en forma serial la señal y agrupa la búsqueda para varias
frecuencias alrededor de una sola afín de optimizar el número de cálculos. Además se usa
una matriz de corrección de Doppler. El diagrama del algoritmo se presenta en la figura
2.11.
El segundo método elimina la necesidad del uso de una matriz de corrección Doppler, sin
embargo hace uso de una FFT de tamaño variable. El diagrama del algoritmo se presenta
en la figura 2.12.
2.8.2 Principio de seguimiento
Una vez obtenidos los parámetros estimados de la frecuencia Doppler 5�� y del retardo de la
19
señal $̂ del sistema de adquisición, estos valores entran al sistema de seguimiento como
parámetros iniciales. Esta fase permite demodular el mensaje de navegación satelital y
medir los pseudo alcances.
Figura 2.11 Primer método del algoritmo de adquisición
Figura 2.12 Segundo método del algoritmo de adquisición
El sistema de seguimiento realiza el seguimiento de los cambios del retardo de código, fase
y la frecuencia Doppler para obtener una estimación más precisa de estos parámetros a
través del tiempo. Los cambios de la fase y la frecuencia Doppler estimados sirven para
corregir los errores de la portadora y, de esta forma, decodificar el mensaje. El estimado
del retardo de código sirve para calcular el pseudo alcance y, de esta forma, obtener la
posición del receptor.
Compensación de la frecuencia (frecuencia sin
corregir)
Re-arreglo en una matriz
FFT de
filas
Compensación en frecuencia
epoch
FFT de columnas
FFT de la réplica
Corrección del código Doppler
IFFT de las
columnas
Entrada �� Salida
Ent
rada
�� FFT de tamaño )�)9 para la longitud de la integración coherente
Posibles ámbitos de los bucles: 1. Satélites 2. Compensación de la
frecuencia (frecuencia sin corregir)
Re-arreglo en una matriz
Tratamiento no
coherente
Corrección del código Doppler
IFFT de las
columnas
Réplica de desplazamiento y multiplicación
Salida
20
En la figura 2.13 se muestra un sistema de seguimiento típico. En este sistema se utilizan
filtros de realimentación para obtener los estimados de los parámetros.
Figura 2.13 Sistema de seguimiento típico
Un filtro de realimentación básico tiene tres componentes: unidad de mezcla, unidad de
control y unidad de realimentación. La unidad de mezcla utiliza el valor estimado obtenido
del filtro ,� y la entrada al sistema , para obtener una señal que está en función del error
del parámetro estimado a seguir �. Luego, la señal � se ingresa hacia la unidad de control,
la cual usará un discriminador para obtener una señal de error �G. Finalmente, la señal �G
se ingresa hacia la unidad de realimentación, la cual usa la señal ingresada para actualizar
el valor estimado ,�.
El módulo de correlación permite seguir las variaciones en frecuencia y fase mediante el
seguimiento de picos máximos del proceso de correlación entre la réplica del código,
obtenido del generador de réplica del código PRN, y tres señales que provienen de la señal
recibida y han sido adelantadas o retrasadas en el tiempo: una señal adelantada (Early), una
señal igual a la señal recibida (Prompt) y una señal que ha sido retrasada (Late).
CAPÍTULO III ANALISIS DEL ALGORITMO DE MITIGACION DEL EFECTO DOPPLER
PARA GPS PROPUESTO 3.1 Introducción
Dentro de un sistema receptor GNSS, el receptor GNSS debe generar un código PRN
idéntico al código PRN de la señal recibida para realizar la correlación. Cuando las fases
de la señal GNSS y del código PRN generado coinciden, se produce un valor máximo en la
correlación. Sin embargo, cuando el desfasaje entre ellos es mayor que un chip o un bit
dentro de un código PRN, se produce un valor mínimo en la correlación. Este método es
utilizado para detectar la señal GNSS en el proceso de seguimiento.
Sin embargo, debido al efecto Doppler y al ruido del canal, se produce la distorsión de la
señal recibida y, por consiguiente, el sistema de seguimiento debe realizar el seguimiento
de la frecuencia Doppler y la corrección de la señal recibida. De esta forma se obtiene la
demodulación de la señal GNSS.
3.2 Filtro de entrada
Antes de realizar el procesamiento de la señal GNSS recibida, esta señal debe pasar por un
filtro FIR pasa bajo, el cual se va a encargar de filtrar las señales arriba de la frecuencia de
los lóbulos principales de las señales GPS L1 C/A y Galileo E1 OS. En la ecuación (3.1) se
muestra la función de transferencia del filtro. Este filtro tiene una frecuencia de corte en
2.5 MHz aproximadamente.
��� = 0.0399 � 0.0498��� � 0.1127��9 � 0.0136��� � 0.3093��q
� 0.5277��l � 0.3093��T � 0.0136��� � 0.1127���
� 0.0498��� � 0.0399���k
( 3.1)
3.3 Correlación e integración
Una vez generados los códigos PRN réplicas en el receptor, se realiza la correlación e
integración de las señales recibidas.
La correlación es una operación matemática en la cual se utilizan dos señales para producir
una tercera señal. Para generar la tercera señal, una de las señales se desplaza a lo largo de
la otra señal, la cual permanece fija. La fórmula matemática de la correlación se muestra en
22
la ecuación (3.2).
-��� = w ,�8� ∙ ��8 � �����
� k, � ∈ ���) � 1 , �) � 1 � ( 3.2)
Debido a las propiedades del código PRN, se puede detectar la forma de onda de la señal
incluso en presencia de ruido.
Para lograr tal fin, se utilizan tres códigos PRN las cuales se correlacionan con las señales
de entrada. Estos códigos PRN se conocen como códigos ;Gd¡jG, ;¢�d£¤, ;£�¢ y están
espaciados cada uno en ±1/2 chip. Esto permite saber si la señal está adelantada o retrasada
en el tiempo.
La figura 3.1 ilustra la correlación de estos tres códigos PRN con la señal entrante. Cuando
la señal muestre un valor 1 en la correlación con ;Gd¡jG, la señal recibida estará
sincronizada y no presenta error. Sin embargo, puede suceder que la señal entrante
presente valor 1 en la correlación diferente del código ;Gd¡jG y exista error. También,
puede suceder que se presenten dos valores máximos en la correlación que sean diferentes
de 1. En cualquiera de los dos casos, se está produciendo un mal seguimiento y es debido a
que la señal sufrió una alteración en el canal de transmisión. Por lo tanto la señal GNSS
debe ser corregida y sincronizada con el código PRN ;Gd¡jG [15].
Para disminuir el error de la señal, se implementa el sistema de integración. En este
sistema, existen dos tipos de integraciones: la primera integración, la cual tiene una
duración de 1ms; y la segunda integración, la cual tiene una duración variable.
Figura 3.1 Etapa de correlación
23
La duración de la segunda integración depende del instante de sincronización
�8��,8�U¥8�ℎ-F y del tiempo de integración /��. Sin embargo, la duración de la segunda
integración debe ser entre 1 ms y 5 ms, esto se hace con el fin de que no sea ni tan pequeño
ni tan grande respecto a la duración de una señal GNSS, por ejemplo la señal GPS L1 C/A
tiene un periodo de 20 ms el periodo.
Finalmente, se obtienen seis salidas:
� I¨, I©, Iª, Q¨, Q© y Qª: Son las salidas de la segunda integración.
� I©�¬K y Q©�¬K: Son las salidas de la integración a 1 ms
El diagrama completo del sistema de correlación e integración se muestra en la figura 3.2.
3.4 Lazo de seguimiento en fase y frecuencia
Esta etapa realiza el seguimiento de la señal en banda base a través de un filtro de lazo
cerrado de fase PLL y a través de un filtro de lazo cerrado de frecuencia FLL. El PLL es
más preciso que el FLL y reproduce la fase exacta de la señal; sin embargo el PLL es más
sensitivo a la dinámica de la señal recibida que el FLL. Por otro lado, el FLL solo logra
una aproximación de la frecuencia de la señal.
Como se explicó en el capítulo 2, el sistema de seguimiento tiene una unidad de control, el
cual usa un discriminador. En nuestro caso, debemos utilizar dos discriminadores:
discriminador de fase y discriminador de frecuencia. En la siguiente sección se tratará el
discriminador de código.
Figura 3.2 Correlación e integración de la señal
24
3.4.1 Discriminador de fase
En caso del seguimiento de una señal compuesta, se utiliza un filtro de lazo Costas como
PLL si se desea que el sistema sea inmune a las rotaciones de fase de π rad [15]. En la
figura 3.3 se muestran los discriminadores de fase utilizados en un filtro de lazo Costas
[15] [19].
De la relación de los discriminadores de fase mostrados en la tabla 3.1, se utiliza el último
discriminador debido a su independencia de la amplitud de la señal, posee la salida óptima
para altas y bajas SNR, y no produce errores de división entre cero. A pesar que la carga
computacional del discriminador sea alta respecto a los otros discriminadores, ese factor se
compensa con la capacidad de procesamiento del dispositivo. En la figura 3.3 se muestra la
salida de los cuatro discriminadores.
Figura 3.3 Salida de los diferentes discriminadores del filtro de lazo Costas
Tabla 3.1 Discriminadores de fase para un filtro de lazo Costas
Discriminador
Salida de
error de
fase
Características
®¯ × ±®¯ sin�2i
� Cercano al valor óptimo para bajo SNR.
� Envolvente proporcional a la amplitud al cuadrado de
la señal.
� Moderada carga computacional.
®¯× ¯²³´�±®¯ sini
� Cercano al valor óptimo para alto SNR.
� Envolvente proporcional a la amplitud de la señal.
� Mínima carga computacional.
25
®¯ ±®¯⁄ tani
� No es tan bueno como los anteriores pero funciona
bien para altas y bajas SNR.
� Envolvente no dependiente de la amplitud de la señal.
� Alta carga computacional.
� Error al dividir por cero en ±90o.
·¸¹�º�®¯ ±®¯⁄ i
� Óptimo a bajas y altas SNR.
� Envolvente no dependiente de la amplitud de la señal.
� Posee la más alta carga computacional.
3.4.2 Discriminador de frecuencia
El discriminador de frecuencia es más robusto a los errores debido a las transiciones de los
bits de datos en la fase de transición. Es decir, el discriminador de frecuencia permite al
sistema de seguimiento seguir la señal hasta el momento de la transición de los bits,
cuando el mensaje es encontrado. En la tabla 3.2 se muestran los diferentes tipos de
discriminadores de frecuencia [15] [19].
De la relación de discriminadores de frecuencia mostrados en la tabla 3.2, se utiliza el
último discriminador debido a su independencia de la amplitud de la señal y posee la salida
óptima para altas y bajas SNR. A pesar que la carga computacional del discriminador sea
alta respecto a los demás, ese factor se compensa con la capacidad de procesamiento del
dispositivo. En la figura 3.4 se muestra la salida de los tres discriminadores para un /�� de
10 ms.
Tabla 3.2 Discriminadores de frecuencia
Discriminador
Salida de
error de
frecuencia
Características
�»�¼¼½²´¾
sin�gi
/��
� Cercano al valor óptimo para bajo SNR.
� Envolvente proporcional a la amplitud al
cuadrado de la señal.
� Mínima carga computacional.
�»�¼¼ × ¯²³´���¾ ½²´¾
sin�2gi /��
� Cercano al valor óptimo para alto SNR.
� Envolvente proporcional a la amplitud de la
señal.
� Moderada carga computacional.
26
·¸¹�º���¾ �»�¼¼⁄ ½²´¾ gi/��
� Óptimo a bajas y altas SNR.
� Envolvente no dependiente de la amplitud de
la señal.
� Posee la más alta carga computacional.
Donde:
� �»�¼¼ = ±®�´ − º� ∗ ®�´� � ±®�´� ∗ ®�´ � º� � ��¾ = ±®�´ � º� ∗ ±®�´� � ®�´ � º� ∗ ®�´� Y
� ±®�´ � º�, ±® en el instante �´ � º . ½²´¾
� ±®�´�, ±® en el instante ´. ½²´¾ Siendo ½²´¾ el tiempo de integración de la señal.
Figura 3.4 Comparación de la salida de los diferentes discriminadores de frecuencia
3.4.3 Filtro de lazo
El filtro de lazo FPLL reduce el ruido a fin de producir una estimación confiable del error
entre la señal recibida y la réplica del código PRN. En la figura 3.5 se muestra el filtro de
lazo a usar. Las entradas a este filtro son el discriminador de fase ¿--fÀÀ y el
discriminador de frecuencia ¿--�ÀÀ, obteniendo como salida h¢dd¡d [15].
El filtro a utilizar es un filtro de tercer orden y depende de la banda de ruido del filtro Á�G.
La banda de ruido de un sistema lineal, con función de transferencia ��Â2E5 , es el ancho
de banda (en Hertz) de un filtro pasa bajo rectangular ficticio con la misma área que tiene |��Â2E5 |9.
La figura 3.6 muestra un filtro pasa bajo con una función de transferencia ��Â2E5 y el
filtro pasa bajo rectangular ficticio el cual servirá para calcular la banda de ruido del filtro.
27
Figura 3.5 Filtro de lazo para el filtrado de señal y frecuencia
Figura 3.6 Diagrama del cálculo de la banda de ruido
Primeramente se realiza el cálculo del área bajo |��Â2E5 |9. En la ecuación (3.3) se
muestra el cálculo del área bajo |��Â2E5 |9.
,->,à = Ä |��Â2E5 |9=5Å�Å ( 3.3)
Ahora, si se fija el filtro pasa bajo ficticio con altura ��0 y ancho 2Á�G, el área bajo ese
filtro sería lo mostrado en la ecuación (3.4).
,->,@�£d¡ @�0�0�¡ = 2Á�G��0 ( 3.4)
Igualando las ecuaciones (3.3) y (3.4) se obtiene el valor del ancho de banda de ruido, el
cual es mostrado en la ecuación (3.5).
Á�G = 12��0 Ä |��Â2E5 |9=5Å�Å (3.5)
Finalmente, los parámetros del filtro en función de Á�G se calculan de la siguiente forma: hkG = Á�G 0.7845⁄ , hk@ = Á�G 0.53⁄ , ,9 = 1.414, ,� = 1.1 y �� = 2.4. Finalmente, el
diagrama general del discriminador y del filtro de lazo FPLL se muestra en la figura 3.7.
3.4.4 Oscilador controlado digitalmente (NCO)
El oscilador controlado digitalmente NCO provee señales con una frecuencia normalizada.
En este caso se utiliza el NCO debido a que la salida del filtro de lazo es un pulso en
28
�-F�� = �o�8 − 1�Æo�8� − �o�8�Æo�8 − 1� =F� = �o�8 − 1��o�8� − Æo�8 − 1�Æo�8� Figura 3.7 Sistema global de filtro de fase y frecuencia
radianes y este error debe ser normalizado en el tiempo. En el sistema mostrado en la
figura 3.8, la salida del NCO, ΦÇ G, se multiplica con la señal de entrada para obtener la
corrección de fase.
Figura 3.8 NCO de la portadora
Donde:
� �=���: Frecuencia Doppler encontrada en la fase de adquisición.
� h¢dd¡d: Salida del filtro de lazo FPLL.
� �0¡dd: Corrección de frecuencia en caso de colisión sobre una frecuencia equivocada.
� ��� : Señal de entrada.
3.5 Lazo de seguimiento del retardo de código
En esta etapa se realiza, siguiendo lo explicado en la sección 2.10, el desarrollo del filtro
de lazo de seguimiento de retardo de código. Este módulo sigue la fase del código PRN y
29
compensa el cambio del pseudo periodo debido al efecto Doppler.
3.5.1 Discriminador de código
Existen principalmente dos tipos de discriminadores de código: el discriminador de código
coherente y el discriminador de código no coherente. Los discriminadores de código
coherentes son una combinación lineal de una señal y requieren menos carga
computacional, sin embargo son menos precisos en las salidas. Los discriminadores de
código no coherentes no son una combinación lineal de las señales y requieren mayor
carga computacional respecto a los discriminadores coherentes, sin embargo poseen mayor
precisión que los discriminadores coherentes. También existe una combinación de estos
dos tipos los cuales son llamados discriminadores de código cuasi coherentes. En la tabla
3.3 se muestran los diferentes tipos de discriminadores de código [15] [19].
Tabla 3.3 Discriminadores de código
Discriminador Características
ºÈ (±É − ±Ê±®+ É − Ê® *
� Potencia cuasi coherente del producto interno.
� Uso los tres correlacionadores (Early, Late y Prompt).
� Baja carga computacional.
� En ausencia de ruido, produce un valor cercano a la salida del
error verdadero si se tiene como entrada un error entre +0.5 y –
0.5 chip.
ºË ÉË − ÊËÉË + ÊË
� Potencia no coherente Early – Late.
� Moderada carga computacional.
� En ausencia de ruido, produce un valor similar al anterior
discriminador si se tiene como entrada un error entre +0.5 y –0.5
chip.
ºË É − ÊÉ + Ê
� Envolvente Early – Late no coherente independiente de la
amplitud de la señal.
� Alta carga computacional.
� En ausencia de ruido, produce el valor de error verdadero si se
tiene como entrada un error entre +0.5 y – 0.5 chip.
� Se vuelve inestable para una entrada de error en ±1.5 chip.
Donde:
30
� Ì = ͱÉË + ÉË
� Î = ͱÊË + ÊË
De la relación de discriminadores de código mostrados en la tabla 3.3, se utiliza el último
discriminador debido a que es el más preciso para obtener el error de retardo de código.
Sin embargo, a pesar que la carga computacional del discriminador sea alta respecto a los
demás discriminadores de código, ese factor se compensa con la capacidad de
procesamiento del dispositivo. En la figura 3.9 se muestra la salida de los tres
discriminadores.
Figura 3.9 Comparación de la salida de los diferentes discriminadores de código
Finalmente, el valor de salida del discriminador ¿--zÀÀ se multiplica por el factor 4Á�0,
siendo Á�0 el ancho de banda del ruido del filtro (medido en Hz). Además, el valor de Á�0
depende de la salida del detector de bloqueo de fase. Finalmente, la salida es h0¡�¢¢dd¡d.
La figura 3.10 ilustra lo explicado.
Figura 3.10 Salida completa del discriminador de código
3.5.2 Factor de escala
En la figura 3.11 se muestra el diagrama de la generación de Φ�����Ï.
El error generado por el FPLL debe ser corregido por un factor de escala el cual depende
de la frecuencia de modulación de la señal GNSS 5k y la frecuencia del código PRN 50¡�¢.
31
La salida Φ�����Ï se normaliza por TÑ, el cual es el periodo de muestreo. En la ecuación
(3.6) se muestra la función Φ�����Ï.
Figura 3.11 Generación del factor de escala
Φ�����Ï = 50¡�¢2E5k /d�2E�=��� + 2E�0¡dd + h¢dd¡d ( 3.6)
3.5.3 Oscilador controlado digitalmente (NCO)
Finalmente, para obtener los códigos ;Gd¡jG, ;¢�d£¤, ;£�¢ primero se pasan las señales de
entrada Φ�����Ï y h0¡�¢ ¢dd¡d a través de un oscilador controlado digitalmente NCO y,
junto con la frecuencia del código, se obtiene la salida ΦÇ 0¡�¢. En la figura 3.12 se muestra
el proceso explicado anteriormente.
Figura 3.12 Generación de �Ç ���� a través de un oscilador controlado digitalmente (NCO)
3.6 Generador de códigos réplica
Finalmente, ΦÇ 0¡�¢ se almacena en memoria y a través de un shift register, utilizando el
espaciamiento entre cada código (=0¡dd), se obtienen los códigos ;Gd¡jG, ;¢�d£¤, ;£�¢. =0¡dd es la fracción de un chip y debe ser un múltiplo de la frecuencia de muestreo. En la
figura 3.13 se muestra el diagrama del generador de códigos réplica.
3.7 Detectores de bloqueo
En un sistema GNSS, debemos conocer si la señal está siendo seguida o no, a pesar que se
haya incluido el modulo del sistema de seguimiento dentro del receptor. Por lo tanto, los
detectores de bloqueo servirán para cumplir tal función. Si el detector de bloqueo detecta
32
Figura 3.13 Generación de los códigos PRN
alguna salida que esté fuera del rango definido, el detector de bloqueo tratará de corregirlo.
3.7.1 Detector de bloqueo de fase
Para adaptar los parámetros del filtro, necesitamos recolectar dos tipos de información: el
bloqueador de fase optimista y el bloqueador de fase pesimista.
El bloqueador de fase optimista decide rápido y su cambio de decisión es lento, sin
embargo la salida no es tan confiable como el bloqueador de fase pesimista, el cual decide
más lento que el bloqueador de fase optimista pero cambia más rápido que el bloqueador
de fase optimista [15].
El funcionamiento del detector de bloqueo de fase es de la siguiente forma: Cuando se
active el bloqueo de fase, �o �j� será de valor máximo y Æo �j� será de valor mínimo. Esto
se realiza debido que la fase de la envolvente de la señal está más cercano al eje I y cuando
ocurre el jitter en la fase, la fase de la envolvente oscilará alrededor del eje I.
En la figura 3.14 se muestra el diagrama completo del detector de bloqueo de fase. En esta
etapa, las señales �o �j� y Æo �j� pasan por un filtro pasa bajo y la señal �o �j� se
multiplica con un factor de escala �9 dando dos tipos de salidas, las cuales llamaremos A y
B respectivamente.
Luego, las entradas A y B pasan por un comparador y, dependiendo de los valores
obtenidos, se decide si el valor de A es mayor o menor que B. Si el valor de A es mayor
que el valor de B, el bloqueo de fase optimista se activa y si el valor de A es menor o igual
al valor de B, el bloqueo de fase pesimista se desactiva.
Además, se incorporan dos contadores f� y f9 los cuales sirven para activar el bloqueador
de fase optimista y desactivar el bloqueador de fase pesimista en caso se alcance una
cantidad superior a un valor fijo.
Los valores típicos a utilizar son: �� = 0,0247, �9 = 0,666, Ào = 50 y ÀR = 240.
3.7.2 Detector de bloqueo de código
El detector de bloqueo de código es un estimador C/N0, el cual se utilizará en el detector
de bloqueo falso. Una falta de bloqueo del código puede producir una falla en la
33
estimación de la relación C/N0 y producir una inestabilidad del sistema.
Figura 3.14 Detector de bloqueo de fase
Dentro de esta etapa, el sistema compara la potencia recibida de dos fuentes diferentes: una
fuente en banda ancha y la otra en banda estrecha. En la ecuación (3.7) se muestra el
cálculo de la potencia en banda ancha y en la ecuación (3.8) se muestra el cálculo de la
potencia en banda estrecha [22].
ÒÁf� = (w ��9 + Æ�9Ó� � *� ( 3.7)
)Áf� = (w ��9Ó� � *� + (w Æ�9Ó
� � *� ( 3.8)
Donde:
� �: Salida de la etapa de integración a 1 ms (�o �j�).
� Æ: Salida de la etapa de integración a 1 ms (Æo �j�).
� Ô: Periodo de suma.
Para el caso de una señal GPS C/A, el valor de M es 20 debido a que se tienen que sumar
periodos de 1 ms cada uno para obtener el periodo de la señal GPS C/A. Para el caso del
sistema Galileo E1 OS, 20 ms corresponden a 5 periodos del código CBOC (3,1,1/11).
Luego, se toma la relación de las potencias )Áf� y ÒÁf�, y los resultados obtenidos se
suman para obtener el valor del detector de bloqueo. La ecuación (3.9) muestra lo
explicado anteriormente.
Õ̂�o = 1Ö w )Áf�ÒÁf�×� � ( 3.9)
Donde Ö tiene el valor de 50 y de esta forma se obtendría un periodo de 20*50 ms = 1 s.
Para obtener el valor de la tasa C/N0 estimada se sigue la relación dada en la ecuación
(3.10). En la figura 3.15 se muestra el diagrama de bloques del detector de bloqueo de
34
código.
Donde / es igual a 1 ms.
;)kØ = 10 log�k (1/ Õ̂�o − 1Ô − Õ̂�o* ( 3.10)
Figura 3.15 Detector de bloqueo de código
En la figura 3.16 se muestra la relación entre el valor de bloqueo y la tasa C/N0 estimada y
Figura 3.16 Relación entre el valor de bloqueo y la tasa C/N0 estimada.
3.7.3 Detector de bloqueo falso
La implementación del detector de bloqueo falso es necesario en caso que el sistema de
seguimiento esté trabajando con una frecuencia falsa, la cual ronda alrededor de los 100 Hz
respecto a la frecuencia verdadera. Además, otra razón es debido a que el detector de
bloqueo de fase no detecta la falsa frecuencia en el siguiente caso:
� Bloqueo de fase optimista: falso
� Bloqueo de fase pesimista: falso.
Esto se produce debido a que la salida del discriminador de frecuencia es generalmente de
un valor bajo y el filtro no puede procesar el error de frecuencia correctamente, obteniendo
una incorrecta recuperación del mensaje de la señal.
El detector de bloqueo falso consiste en comparar la tasa C/N0 estimada con respecto a un
umbral donde el detector de fase falle en alcanzar la fase de bloqueo o cuando la detección
35
de las transiciones falle. Para obtener la salida de la frecuencia corregida se integra los
valores de h0¡�¢¢dd¡d, tal como se muestra en la ecuación (3.11).
�0¡dd = 5k50¡�¢1Ö w h0¡�¢¢dd¡d�7 ×
� � ( 3.11)
Un valor común para la integración de h0¡�¢¢dd¡d es 1s. Además, como se están trabajando
con muestras con un periodo de 5 ms, entonces el valor de Ö será 200. @Û@ÜÝ{Þ es un factor de escala de la frecuencia de modulación respecto a la frecuencia del
código PRN de la señal GNSS.
3.8 Detección de la transición de los bits de datos
Este módulo es utilizado solamente por la señal GPS L1 C/A debido a que señal Galileo E1
OS tiene los modos piloto y datos.
Si la tasa C/N0 está por debajo de los 35-36 dBHz, el método de búsqueda de tiempo de
transición mediante histogramas falla. Debido a esto, en esta etapa se propone un método
basado en búsqueda de energía de la señal. Este método tiene la ventaja de obtener una
rápida convergencia hacia un valor óptimo y una rápida actualización en tiempo real del
instante de transición de los integradores. Además, este método reduce la duración de la
fase de transición, debido a que la salida de los discriminadores son valores extremos si los
integradores acumulan códigos PRN rápidamente sobre la transición del bit. La rápida
acumulación de códigos PRN es causado por la inversión de polaridad de los códigos PRN.
Por lo tanto, la convergencia en tiempo real del instante de transición permite sincronizar
en tiempo real los integradores y por consiguiente reducir los valores extremos de los
discriminadores.
Ahora, el método de búsqueda energía funciona de la siguiente manera:
Por cada muestra �o �j� y Æo �j� en un instante n, �� y Æ� respectivamente, se tienen las
ecuaciones (3.12) y (3.13).
U~ = w ������� k ( 3.12)
Uß = w Æ������ k ( 3.13)
Estas dos salidas se utilizan para obtener el módulo U� tal como se muestra en la ecuación
(3.14).
U� = ÍU~9 + Uß9 ( 3.14)
36
Si se desea hacer 20 veces este proceso, se obtendrá 20 posibles alternativas ��� en el
instante de transición de los datos. Ya que existen 20 pseudo periodos de código dentro de
cada bit de información, se deben sumar todas esas 20 posibles alternativas tal como se
muestra en la ecuación (3.15).
��� = w U�,�9k� ( 3.15)
De esa forma se obtiene la alternativa que posea mayor nivel de energía. Cuando aquel
nivel se estabilice durante un tiempo lo suficientemente largo (por lo menos 1 segundo), se
obtendrá el instante de transición y por lo tanto se podrá realizar una adecuada
sincronización. La ecuación (3.16) resume lo explicado.
7 = �|Ã�� j�à�à (3.16)
Finalmente, se debe utilizar un filtro pasa bajo con el fin de variar dinámicamente el
instante de transición. Una alternativa es mostrada en la ecuación (3.17).
�8��,8�U¥8�ℎ-F = 14 w 7£�£ k ( 3.17)
3.9 Demodulación de la señal
En esta última etapa, la señal �o �j� se integra por un periodo de 20 ms y finalmente pasa a
un bloque de decisión el cual posee dos salidas:
� Si la entrada es mayor o igual a cero, su salida es ‘0’.
� Si su entrada es menor que cero, su salida es ‘1’.
De esta forma, se obtiene la información deseada.
Finalmente, la figura 3.17 muestra el diagrama de bloques de la demodulación de la señal.
Figura 3.17 Demodulación de la señal
CAPÍTULO IV IMPLEMENTACIÓN DEL ALGORITMO DE MITIGACIÓN DEL EFECTO
DOPPLER PARA GPS EN UN FPGA 4.1 Introducción
El uso de procesadores a nivel de software en sistemas embebidos ha proporcionado una
gran ventaja respecto a los procesadores a nivel de hardware, debido a que permite su
portabilidad a diferentes dispositivos. En la actualidad existen una gran variedad de estos
tipos de procesadores, siendo el Procesador LEON uno de los más utilizados para
aplicaciones espaciales.
Los procesadores a nivel de software permiten incluir programas escritos en lenguaje
C/C++ para poder ser ejecutados gracias a la creación de los compiladores cruzados,
permitiendo de esta forma que el programador se preocupe en cómo opera el algoritmo y
no se preocupe tanto por su implementación en hardware.
En este capítulo se tratará acerca del Procesador LEON, la implementación del algoritmo
de mitigación del efecto Doppler y el escenario de prueba del algoritmo.
4.2 El Procesador LEON
SPARC (Scalable Processor ARChitecture o Arquitectura de Procesador Escalable) es una
arquitectura CPU basado en el conjunto de instrucciones (ISA), derivado del conjunto de
instrucciones reducido para computadoras (RISC). SPARC permite ser implementado en
una amplia gama de chips y sistemas y está orientada a diferentes aplicaciones, desde uso
comercial hasta trabajos de ingeniería.
El procesador del SPARC posee tres componentes:
� Unidad de punto flotante (FPU): Tiene 32 registros de punto flotante de 32 bits. Un
valor de doble precisión ocupa un par de registros correlativos, y un valor de cuádruple
precisión ocupa un grupo alineado de 4 registros.
Las instrucciones de carga/descarga en punto flotante son utilizadas para mover los datos
entre la FPU y la memoria. Las direcciones de memoria son calculadas por la IU.
� Coprocesador (CP): El coprocesador tiene su propio conjunto de registros que son de 32
bits. Este módulo sirve para utilizar funciones que no contiene el procesador y su uso es
38
opcional.
� Unidad entera (IU): Ejecuta instrucciones aritméticas enteras y calcula las direcciones
de memoria para la carga y almacenamiento de información. También, este componente
mantiene el contador de programa y la ejecución de las instrucciones de control para la
Unidad de punto flotante (FPU) y el Coprocesador (CP).
Además, cada componente del SPARC posee sus propios registros. Para mayor
información sobre SPARC, consultar [23].
La especificación Arquitectura Avanzada para Bus de Microcontroladores AMBA define
un estándar de comunicación sobre chips para microcontroladores embebidos de alto
rendimiento.
El estándar define tres tipos de buses:
� Bus Avanzado de Alto Rendimiento (AHB): Este bus es para módulos del sistema que
requieran un alto rendimiento y trabajen a altas frecuencias de reloj.
� El bus AHB actúa como un backbone y soporta de forma eficiente la conexión de
procesadores, memorias internas y externas y periféricos con funciones macroceldas de
baja potencia.
� Bus Avanzado del Sistema (ASB): Este bus es para módulos de sistema de alto
rendimiento y es adecuado cuando no se requiera de un alto rendimiento comparado con el
bus AHB. El bus ASB soporta los mismos periféricos que el bus AHB.
� Bus Avanzado para Periféricos (APB): Este bus es para periféricos de baja potencia. El
bus APB ha sido optimizado para un mínimo consumo de energía y una reducida
complejidad de las interfaces para la conexión con los periféricos. Además, puede ser
usado con el bus AHB o ASB.
Para mayor información sobre la especificación AMBA consultar [24].
El Procesador LEON es un modelo sintetizable VHDL de un procesador de 32 bits el cual
está acorde con la arquitectura SPARC Versión 8. Este procesador está especialmente
diseñado para aplicaciones embebidas con varias características para sistemas sobre chip,
como instrucciones separadas en la caché de datos, multiplicador y divisor en hardware,
dos temporizadores de 24 bit, dos UART, función de baja potencia, watchdog, puertos de
entrada/salida y un controlador de memoria flexible. También el procesador LEON tiene la
opción de agregar múltiples módulos a través del sistema de buses AMBA 2.0 AHB y
soporta la tecnología Plug and Play.
39
4.3 Arquitectura del Procesador LEON
El Procesador LEON puede ser visto como un diagrama de bloques, tal como se observa en
la figura 4.1 para el caso de una tarjeta Spartan3-1500. La arquitectura del Procesador
LEON está constituida por el Procesador LEON y un conjunto de bloques IP (Propiedad
Intelectual) conectados a través de los buses AMBA AHB/APB.
Figura 4.1 Diagrama de bloques del procesador LEON3 para una tarjeta Spartan3 1500
El diseño es alrededor del bus AMBA donde el procesador LEON3 y otros dispositivos de
alto ancho de banda son utilizados. Se accede a la memoria externa a través de un
controlador combinado de memoria PROM/IO/SRAM/SDRAM. El diseño es altamente
configurable y existen varias características que pueden ser eliminadas si se desea.
La mayor parte del diseño es provista como código fuente a través de la licencia GNU
GPL. Sin embargo, la unidad de punto flotante (GRFPU-Lite) y el enlace SpaceWire está
disponible bajo una licencia comercial y o una licencia de evaluación.
4.3.1 El procesador LEON con arquitectura SPARC V8
Existe una plantilla de diseño del procesador LEON la cual está basada en la arquitectura
SPARC V8. El núcleo del procesador puede ser configurado a través de una configuración
con interfaz de usuario gráfica. La unidad de soporte de depurado del LEON3 (DSU3) está
habilitado por defecto, lo cual permite descargar y depurar los programas a través de un
puerto serial o JTAG. [25]
4.3.2 Interfaces de memoria
La memoria externa es conectada a través de una interfaz que utiliza un controlador de
40
memoria PROM/IO/SRAM/SDRAM (MCTRL). En el caso de una tarjeta Spartan3 1500
se tiene 8 Mbyte de memoria PROM flash y 64 Mbyte de memoria SDRAM, y la memoria
SRAM así como las señales de entrada/salida están disponibles sobre las extensiones de los
conectores.
4.3.3 Registro de estado del AHB
El registro de estado del AHB captura las respuestas de error sobre el bus AHB y bloquea
las direcciones de falla y el dispositivo maestro activo. Aquellos valores permiten al
programa recuperarse de eventos fallidos del sistema.
4.3.4 Enlaces SpaceWire
El sistema puede ser configurado hasta con 3 enlaces SpaceWire y cada enlace es
controlado de forma separada a través del bus APB. Este enlace transfiere la información
transmitida y recibida a través de una transferencia DMA sobre AHB. El enlace SpaceWire
puede ser configurado con soporte RMAP en hardware.
4.3.5 Unidad temporizadora
La unidad temporizadora consiste de un escalador común y hasta siete temporizadores
individuales. El temporizador puede trabajar en modo periódico o en modo de un disparo.
El modo periódico el contador del temporizador opera continuamente cada vez que el
contador alcance el valor cero.
El modo de un disparo el contador del temporizador deja de operar cuando el contador
alcance el valor cero y espera que se ingrese un nuevo valor en el contador.
Además, uno de los temporizadores puede ser configurado como watchdog. El watchdog
permite al procesador recuperarse de algún mal funcionamiento.
4.3.6 Control de interrupción
El control de interrupciones manipula hasta quince interrupciones en dos niveles de
prioridad. La interrupción es automáticamente asignada y routeada al controlador a través
del sistema plug and play de GRLIB.
4.3.7 UART
Uno o dos UARTs pueden ser configurados en el diseño. El UART tiene tamaños FIFO
configurables y tiene generadores de la tasa de baudios.
4.3.8 Puerto entrada/salida de propósito general
Un puerto entrada/salida de propósito general (GPIO) es provisto en el diseño. El puerto
puede ser desde 1 hasta 32 bits de ancho, y cada bit puede ser configurado dinámicamente
como entrada o salida. El GPIO también genera interrupciones desde dispositivos externos.
41
4.3.9 Ethernet
Una interfaz Ethernet puede ser habilitado. La interfaz Ethernet soporta una operación en
10/100 Mbit ya sea en half-duplex o full-duplex. Una interfaz de depuración basada en
Ethernet (EDCL) puede ser habilitada.
4.3.10 Controlador de Área de Red (CAN-2.0)
El Controlador de Área de Red CAN es bus de comunicación serial diseñado para la
industria automotriz. Este bus es inmune a la interferencia eléctrica y puede auto
diagnosticarse y reparar el error de la información [26].
Para el procesador LEON, una o dos interfaces CAN-2.0 pueden ser habilitadas. Esta
interfaz está basada en el núcleo CAN desde OpenCores, con mejoras adicionales.
4.3.11 Controlador VGA
Un controlador de video basado en texto puede ser habilitado. El controlador puede
mostrar una pantalla de 80x48 caracteres sobre un monitor de 640x480.
4.3.12 Interfaz de teclado PS/2
Una interfaz de teclado PS/2 puede ser opcionalmente activado. Este proporciona los scan
codes desde un teclado y tiene un FIFO de 16 bytes.
4.3.13 Generador de reloj
El núcleo del generador de reloj portable es utilizado para generar el procesador y el reloj
de la SDRAM. El generador de reloj puede generar una frecuencia arbitraria multiplicando
o dividiendo la frecuencia de 50 MHz de la placa. El factor de escala del reloj puede ser
configurado.
4.4 Características del Procesador LEON
A continuación se detallan las principales características del Procesador LEON.
4.4.1 Tolerancia a fallas
Es decir, tiene un sistema adecuado de protección de la memoria y de los registros, lo cual
lo hace ideal para aplicaciones dentro del campo militar y aeroespacial. Sin embargo, la
licencia para el Procesador LEON con tolerancia a fallas (LEON3-FT) está disponible bajo
una licencia comercial.
4.4.2 Librería GRLIB
Es un conjunto integrado por núcleos IP reusables, diseñados para el desarrollo de
Sistemas sobre Chip (SoC). Los núcleos IP son centralizados alrededor del bus común
(AMBA) y usa el método coherente para simulación y síntesis.
42
4.4.3 Creación de Código C
Un compilador cruzado (cross compiler) es una herramienta de software el cual convierte
el código fuente de la aplicación en código máquina para un procesador determinado cuya
arquitectura y conjunto de instrucciones son diferentes respecto al procesador donde se está
ejecutando la compilación. Para el desarrollo de sistemas embebidos es típico el uso de
este tipo de compiladores [27].
El Procesador LEON soporta código C/C++ a través de BCC (Bare Cross Compiler). El
compilador BCC está basado en las herramientas del compilador GNU y en las librerías C
Newlib. Además, soporta operaciones de punto flotante a nivel de hardware y software así
como las instrucciones de multiplicación y división en la arquitectura SPARC V8 [28].
BCC consiste de los siguientes paquetes:
1. Compilador GNU GCC C/C++ v3.4.4. y v4.4.2.
2. Librería C Newlib v1.13.1.
3. Rutinas de entrada/salida de bajo nivel para el procesador LEON3, incluyendo soporte
de interrupciones.
4. Micro núcleo IP de la Pila TCP/IP.
5. Depurador GDB v.4 con aplicaciones para el usuario para el Depurador de
Visualización de Datos (DDD), el cual muestra los resultados de la depuración con
gráficos en pantalla.
6. Compilador Mkprom para LEON3/4.
7. Soporte para Linux y Windows (a través de Cygwin).
4.5 Entorno de desarrollo
Actualmente se encuentran disponibles programas para desarrolladores provistos por la
empresa Gaisler, creadora del Procesador LEON [29] [30].
4.5.1 Plugin del Procesador LEON para el entorno Eclipse
Este plugin permite el desarrollo y depuración de aplicaciones en lenguaje C elaborados
para el procesador LEON. También incluye la depuración utilizando GRMON, el cual es
usando una conexión con el procesador LEON implementado en el FPGA, o utilizando
TSIM, el cual es la simulación del procesador LEON en una computadora en caso no se
disponga un FPGA para la implementación del procesador LEON. En la figura 4.2 se
muestra el entorno de desarrollo en Eclipse.
4.5.2 GRMON (Gaisler Research Monitor)
GRMON es un monitor de depuración para el Procesador LEON y para los diseños SoC
43
basados en la librería GRLIB IP. GRMON incluye las siguientes funcionalidades: [29]
Figura 4.2 Entorno de desarrollo de una aplicación para el procesador LEON en Eclipse.
� Acceso de lectura/escritura para todos los registros del sistema y memoria.
� Desensamblador incorporado y gestión del buffer de seguimiento.
� Descarga y ejecución de aplicaciones LEON.
� Gestión de los puntos de ruptura (breakpoint) y puntos de observación (watchpoint).
� Conexión remota al depurador GNU (GDB).
� Soporte para enlaces de depuración utilizando USB, JTAG, RS232, PCI, Ethernet y
SpaceWire.
Figura 4.3 Conexión al procesador LEON a través de un puerto serial utilizando GrmonRCP
44
Sin embargo, GRMON es una aplicación que se utiliza en un terminal (Linux o Windows),
por lo cual se ha creado una aplicación de depuración con interfaz gráfica. Esta aplicación
se llama GrmonRCP y está basado en Eclipse. Esta aplicación está disponible como una
aplicación independiente de GRMON.
En la figura 4.3 se muestra la interfaz de GrmonRCP cuando se configura una conexión
con el procesador LEON a través de un puerto serial. Se observa que en la ventana de
nombre “Choose Target configuration” se escoge el tipo de depuración y la interface a
utilizar para la conexión. Además, se debe seleccionar la ruta del dispositivo y la tasa de
transmisión.
4.6 Arquitectura propuesta
En la figura 4.4 se muestra la arquitectura para el receptor GNSS utilizando el Procesador
LEON3. Se observa que el algoritmo de seguimiento está dentro del Procesador LEON3 y
para tal fin se debe programar el algoritmo en código C. Además, se debe realizar la
síntesis del código VHDL del Procesador LEON3 para la tarjeta a utilizar así como
configurar los registros para la recepción de los datos a través del puerto serial.
Figura 4.4 Arquitectura propuesta para el sistema de seguimiento
Como se puede observar, el código del sistema de seguimiento al estar embebido en el
Procesador LEON3 se puede corregir fácilmente si existe alguna falla en la ejecución del
sistema.
45
4.7 Escenario de pruebas
El escenario de pruebas está conformado por los siguientes componentes:
� Computadora de escritorio: Permite transmitir los datos de entrada hacia el FPGA
mediante puerto serial.
� Laptop: Permite cargar el código del algoritmo al FPGA.
� Tarjeta FPGA: Dispositivo que realizará el procesamiento de la señal. El Procesador
LEON3 ya se encuentra incorporado al FPGA y el FPGA que se usó en este escenario fue
el Digilent Spartan 3E-1600 Development Board (ver ANEXO A).
En la figura 4.5 se muestra un esquema del escenario de pruebas. La laptop, mediante una
comunicación JTAG, permite conectarse al procesador LEON implementado en el FPGA y
de esa forma carga el algoritmo de seguimiento (ver ANEXO B). Mediante una
comunicación serial, se envía la señal GPS hacia el FPGA desde la computadora de
escritorio. A medida que el FPGA va procesando la señal GPS, este va enviando el
seguimiento de la frecuencia Doppler, la fase y retardo de código hacia la Computadora
personal.
Figura 4.5 Diagrama del escenario de pruebas del algoritmo de seguimiento
En la figura 4.6 se muestra una fotografía del escenario de pruebas del algoritmo de
seguimiento.
4.7.1 Herramientas utilizadas
� Eclipse Helios Release 2: Entorno de desarrollo para aplicaciones C.
� Codeblocks 10.01: Entorno de desarrollo para aplicaciones C.
� GRMON 2.0.39 versión académica
� GrmonRCP 0.9.20
� LnxCOMM 1.0
� Compilador cruzado BCC para LEON3/4 gcc-3.4.4 y gcc 4.4.2
� Xilinx ISE Webpack 10.1
� Laptop con sistema operativo Windows 7 de 64 bits
Laptop Tarjeta FPGA Computadora de escritorio
Comunicación JTAG
Comunicación Serial
46
� Computadora con sistema operativo ArchLinux 32 bits
Figura 4.6 Escenario de pruebas del algoritmo de seguimiento
4.7.2 Síntesis del Procesador LEON en el FPGA
Antes de realizar la síntesis se deben configurar los archivos VHDL del Procesador LEON.
Para las pruebas del algoritmo de seguimiento se utilizará la versión 3 del Procesador
LEON y el Procesador de Punto Flotante GRFPU-Lite.
Primeramente se debe descargar el GRLIB de la página de la empresa Gaisler y los netlist
del GRFPU-Lite. Todos los archivos de GRFPU-Lite deben estar dentro de la carpeta de
GRLIB.
Luego, se ingresa al directorio “grlib-gpl-1.3.0-b4133/designs/leon3-digilent-xc3s1600e” y
se escribe el comando “make xconfig” en el terminal, lo cual mostrará la ventana de
configuración del procesador LEON. La ventana de configuración del procesador LEON se
muestra en la figura 4.7.
Figura 4.7 Ventana principal de la configuración del Procesador LEON
Se observa que la ventana de configuración tiene múltiples opciones como la configuración
del procesador, de los buses AMBA, del reloj y de los periféricos. Los valores que figuran
en el procesador son valores por defecto, sin embargo la configuración por defecto no
Laptop
FPGA con el Procesador LEON.
Computadora
47
incluye la unidad de punto flotante.
Para agregar la unidad de punto flotante, se selecciona la opción “Processor” y dentro de
esa ventana se selecciona la opción “Floating-point unit”.
En la figura 4.8 se muestra la ventana de configuración de la unidad de punto flotante. Se
activa la opción “Enable FPU”, se selecciona GRFPU-Lite en “FPU core” y finalmente se
activa el uso de VHDL netlist.
Figura 4.8 Ventana de configuración de la unidad de punto flotante.
Ahora, para iniciar la síntesis del procesador LEON se escribe el comando “make ise” en el
Terminal. Este proceso puede tardar hasta una hora y debe acabar sin errores, caso
contrario se debe verificar los valores ingresados en la configuración.
Ahora, para ejecutar la verificación de la síntesis se escribe el comando “make ise-launch”
y debe mostrase la ventana Xilinx ISE. En la figura 4.9 se muestran los archivos .vhd del
Procesador LEON en el Xilinx ISE.
Para poder realizar la síntesis del procesador LEON en la ventana de Xilinx ISE, se
selecciona la opción Run de la opción Synthesize-XST, tal como se muestra en la figura
4.10.
Una vez terminada la síntesis se continúa con las opciones siguientes:
� Implement Design, realiza el diseño del programa para el FPGA. Une los diferentes
proyectos VHDL creados y realiza el mapeo y enrutamiento de los módulos creados.
� Generate Programming File, genera el archivo .bit el cual será utilizado para incrustarlo
en el FPGA.
48
� Configure Target Device, selecciona el tipo de conexión con el FPGA y carga el archivo
.bit al FPGA.
Figura 4.9 Ventana de Xilinx ISE
Figura 4.10 Opción Synthesize-XST en Xilinx ISE
4.7.3 Configuración de la transmisión serial
La transmisión y recepción de datos a través del puerto serial en un FPGA y utilizando el
Procesador LEON3 es gracias al módulo APBUART, el cual es el UART para el Bus
AMBA APB [25].
El UART soporta trama de datos con 8 bits de datos, un bit de paridad (opcional) y un bit
de parada. Para generar la tasa de transmisión, cada UART tiene un divisor de 12 bits, el
49
cual es programable. También soporta un control de flujo a nivel de hardware a través de
las señales handshake RTSN/CTSN. Finalmente, dos FIFOs son usados para la
transferencia de datos entre el bus y el UART.
En la figura 4.11 se muestra el diagrama de bloques del APBUART.
Figura 4.11 Diagrama de bloques del APBUART
a) Registros del APBUART
El módulo es controlado a través de registros, los cuales fueron mapeados en el espacio de
dirección del APB. En la Tabla 4.1 se muestran los registros del módulo APBUART.
Tabla 4.1 Registros del APBUART
Dirección de desplazamiento en el APB Registro
0x0 Registro de datos del APBUART
0x4 Registro de estado del APBUART
0x8 Registro de control del APBUART
0xC Registro de escala del APBUART
En la figura 4.12 se muestra el Registro de datos del APBUART. Este registro posee
solamente un campo:
� Dato de lectura o escritura en el FIFO: Este campo posee una longitud de 8 bits y
almacena los datos recibidos o a ser transmitidos por el APBUART.
Figura 4.12 Registro de datos del APBUART
50
En la figura 4.13 se muestra el Registro de estado del UART. Este registro posee trece
campos:
� Dato listo (DR): Indica que un nuevo dato está disponible en el receptor.
� Registro de desplazamiento vacío (TS): Indica que el registro de desplazamiento del
transmisor está vacío.
� FIFO transmisor vacío (TE): Indica que el FIFO transmisor está vacío.
� Sentencia Break recibida (BR): Indica que la sentencia BREAK ha sido recibida.
� Sobrecarga (OV): Indica que uno o más caracteres se han perdido en la sobrecarga de
información en el FIFO.
� Error de paridad (PE): Indica que fue detectado un error de paridad.
� Error en la trama (FE): Indica que fue detectado un error en la trama.
� FIFO medio lleno en el transmisor (TH): Indica que el FIFO del transmisor tiene
información de un tamaño menor que el tamaño completo.
� FIFO medio lleno en el receptor (RH): Indica que menos de la mitad de los datos en el
FIFO del receptor están en modo de espera.
� FIFO lleno en el transmisor (TF): Indica que el FIFO del transmisor está lleno.
� FIFO lleno en el receptor (RF): Indica que el FIFO del receptor está lleno.
� Contador en el FIFO del transmisor (TCNT): Indica el número de trama de datos en el
FIFO del transmisor.
� Contador en el FIFO del receptor (RCNT): Indica el número de trama de datos en el
FIFO del receptor.
Figura 4.13 Registro de estado del APBUART
En la figura 4.14 se muestra el Registro de Control del UART. Este registro posee once
campos:
� Receptor activo (RE): Si se selecciona en 1, habilita el receptor.
� Transmisor activo (TE): Si se selecciona en 1, habilita el transmisor.
� Interrupción del receptor activado (RI): Si se selecciona en 1, las interrupciones son
activadas cuando una trama es recibida.
� Interrupción del transmisor activado (TI): Si se selecciona en 1, las interrupciones son
activadas cuando una trama es transmitida.
� Paridad seleccionada (PS): Selecciona el tipo de paridad (0=paridad par, 1=paridad
51
impar).
� Paridad activada (PE): Si se selecciona en 1, activa la generación y la verificación de la
paridad.
� Control de flujo (FL): Si se selecciona en 1, activa el control de flujo por CTS/RTS.
� Loop back (LB): Si se selecciona en 1, el modo loop back será habilitado.
� Reloj externo (EC): Si se selecciona en 1, el escalador del UART será temporizado por
un reloj externo (UARTI.EXTCLK) en vez del reloj del sistema. La frecuencia del reloj
externo debe ser menor que la mitad de la frecuencia del reloj del sistema.
� Interrupción del FIFO en el transmisor activado (TF): Cuando se selecciona en 1, el
nivel de interrupción del FIFO del transmisor será activado.
� Interrupción del FIFO en el receptor activado (RF): Cuando se selecciona en 1, el nivel
de interrupción del FIFO del receptor será activado.
Figura 4.14 Registro de control del APBUART
En la figura 4.15 se muestra el Registro escalador del UART. Este registro posee
solamente un campo:
� Valor de recarga del escalador: Cada UART tiene un escalador de 12 bits para generar la
tasa de baudios deseada. El escalador es temporizado por el reloj del sistema y genera un
pulso en el UART cada vez que este subdesborda8. Esto es recargado con el valor del
registro de recarga del escalador del UART después de cada subdesbordamiento. La
frecuencia del tick del UART resultante sería 8 veces la tasa de baudios deseada.
Figura 4.15 Registro escalador del APBUART
b) Transmisión en el puerto serial
El transmisor está habilitado a través del bit TE en el registro de control del UART. Los
datos que serán transmitidos son almacenados en el FIFO mediante la escritura en el
registro de datos. Además, el tamaño del FIFO es configurable. Cuando el puerto serial
está listo para transmitir, los datos son transmitidos desde el FIFO transmisor hacia el
8 El subdesbordamiento sucede cuando la información que llega es a una tasa de transmisión menor de la que el receptor tiene, por lo tanto si el receptor hace una solicitud de lectura de información este estaría leyendo una información nula.
52
registro de desplazamiento del transmisor y convertidos a un flujo serial sobre el pin de
salida serial del transmisor (TXD). Este automáticamente envía un bit de inicio, seguido de
ocho bits de datos, un bit de paridad (opcional) y un bit de parada. El bit menos
significativo es enviado primero. En la figura 4.16 se muestra la trama de datos de un envío
serial con y sin bit de paridad.
(a) Trama de datos sin paridad
(b) Trama de datos con paridad
Figura 4.16 Trama de datos de un envío serial para una tramas de datos sin paridad (a) y con paridad (b)
Seguido del bit de parada, si un nuevo carácter no está disponible en el FIFO transmisor, la
salida de los datos de transmisión serial permanece en valor alto y el bit del registro de
desplazamiento del transmisor vacío (TS) será seleccionado en registro de estado del
UART. La transmisión se reanuda y el TS se vacía cuando un nuevo carácter es cargado en
el FIFO transmisor. Cuando el FIFO está vacío el bit TE es seleccionado en el registro de
estado del UART. Si el transmisor es deshabilitado, este automáticamente detiene
cualquier transmisión activa incluyendo el carácter que esté siendo sacado del registro de
desplazamiento del transmisor.
El bit de estado TF del registro de estado del UART es seleccionado en 1 si el FIFO
transmisor esté lleno y el bit TH es seleccionado en 1 cada vez que el FIFO esté con una
cantidad de datos de menor de la mitad de su capacidad. El bit de control TF del registro de
control del UART habilita las interrupciones del FIFO cuando se selecciona. El registro de
estado también contiene un contador (TCNT) mostrando el número actual de entrada de
datos en el FIFO.
Si el flujo de control está activado, la entrada CTSN debe ser bajo a fin que el carácter sea
transmitido. Si este es denegado a mitad de la transmisión, el carácter en el registro de
desplazamiento es transmitido y la salida serial del transmisor permanecerá inactivo hasta
que CTSN sea aceptado de nuevo. Si el CTSN está conectado a un receptor RTSN, la
sobrecarga puede ser prevenida.
c) Recepción en el puerto serial
El receptor está habilitado para la recepción de datos a través del bit Receptor Activo (RE)
53
en el registro de control del UART. El receptor busca una transición desde un valor alto
hacia un valor bajo de un bit de inicio sobre la entrada de recepción serial. Si una
transición es detectada, el estado de la señal de entrada es muestreado una mitad del reloj
de bit después. Si la entrada serial es muestreada en alto, el bit de inicio es inválido y la
búsqueda para un bit de inicio válido continúa. Si la entrada serial está todavía en bajo, se
asume un bit de inicio y el receptor continúa muestreando la entrada serial en un bit cada
intervalo de tiempo (en el centro teórico del bit) hasta el número de bits de datos apropiado
y el bit de paridad ha sido ensamblado y un bit de parada ha sido detectado. La entrada
serial es desplazada a través de un registro de desplazamiento de 8 bits, donde todos los
bits deben tener el mismo valor antes que el nuevo valor sea tomado en cuenta, formando
un filtro pasa bajo con una frecuencia de corte de un octavo de la frecuencia de reloj del
sistema.
El receptor también tiene un FIFO configurable el cual es idéntico al FIFO del transmisor.
Durante la recepción, el bit menos significativo es recibido primero. Los datos son luego
enviados al FIFO del receptor y el bit de datos listos (DR) es seleccionado en el registro de
estado del UART tan pronto como el FIFO contenga al menos una trama de datos. Los bits
de paridad, tramado y sobrecarga son seleccionados en la frontera del byte receptor, al
mismo tiempo cuando el bit de Receptor Listo (RE) es seleccionado. La trama de datos no
es almacenada en el FIFO si un error es detectado. También, los nuevos bits de estado de
error son ordenados con los viejos valores antes que ellos sean almacenados en el registro
de estado. De esta forma, estos datos no son limpiados hasta que son escritos con ceros
desde el bus AMBA APB. Si el FIFO del receptor y el registro de desplazamiento están
llenos cuando un nuevo bit de inicio es detectado, entonces el carácter mantenido en el
registro de desplazamiento del receptor será perdido y el bit de sobrecarga será
seleccionado en el registro de estado del UART. Si el flujo de control es habilitado,
entonces el RTSN será negado (señal en alto) cuando un bit de inicio válido es detectado y
el FIFO receptor esté lleno.
d) Configuración de la transmisión desde el computador
En el lado del computador se utilizará la aplicación LnxCOMM, el cual posee librerías en
C las cuales permitirán configurar fácilmente el puerto serial a transmitir [31]. Para
configurar una transmisión de un puerto serial en C, se programará tal como se muestra en
la figura 4.17 (ver ANEXO D). Primeramente, se debe crear un manipulador del puerto
serial el cual será el puente entre el puerto serial y el programa desarrollado. Luego, se
54
debe abrir el puerto serial a utilizar en la transmisión y se debe realizar la configuración de
la tasa de transmisión y la paridad. En este caso se utilizará una tasa de transmisión de
38400 baudios y una paridad 8N1 (8 bits de datos, ningún bit de paridad y 1 bit de parada).
Para el modelo de FPGA (Digilent Spartan 3E-1600 Development Board) utilizado en las
simulaciones, este no soporta control de flujo a nivel de hardware, por lo cual se tiene que
mantener un flujo constante de datos al momento de transmisión y recepción. Debido a
esto la configuración del control de flujo se desactivará. Luego, se abrirá un archivo para
guardar la información recibida por el puerto serial.
Figura 4.17 Configuración del puerto serial en el computador
Ahora, antes de iniciar la transmisión, se debe configurar la misma tasa de baudios, la
paridad y control de flujo en el receptor (FPGA).
Finalmente, se procederá con el envío de datos de la información utilizando el comando
write_port. Este comando permite el envío de la información con una longitud de bits
determinada. Como se va a mantener un flujo constante de datos, se opta por enviar una
cantidad de datos repetitivos cuando no se tenga que enviar información. Para mayor
información sobre la transmisión serial consultar [31].
4.7.4 Generación de la señal GPS desde el computador
La señal GPS a simular se genera conforme a lo explicado en la ecuación (2.13). Dentro
del archivo “Parameters.txt” se guardan los parámetros para diferentes señales GPS y la
relación C/N0 del sistema. La estructura del archivo “Parameters.txt” es lo mostrado en la
HANDLE fd; // Manejador del puerto serial
FILE *SignalFile; // Creación de un puntero hacia un archivo
FILE *pFile; // Creación de un puntero hacia un archivo
fd = Open_Port("/dev/ttyUSB0"); // Abrir el puerto serial
// En el caso de un MS Windows fd=Open_Port("COMX");
// donde X puede ser 1,2,3,..
Configure_Port(fd,B38400,"8N1"); // Configurar puerto serial con una paridad
Set_Hands_Haking(fd,2); // Configurar el control de flujo (opcional)
/* Abrir el archivo de la señal */
SignalFile = fopen(NameSignalFile, "rb");
/* Abrir los archivos para guardar los resultados */
pFile = fopen(NameEstimatedDopplerFile, "w");
55
tabla 4.2. Para mayor detalle del código consultar el ANEXO C.
Luego, un programa generará la señal GPS y lo guardará en un archivo .bin, el cual es un
archivo donde la información de cada dato se guarda en 8 bits. Para poder verificar que la
señal se ha generado de forma adecuada, se utilizará un programa que simula un algoritmo
Tabla 4.2 Valores a ingresar en el archivo “Parameters.txt”
Valores
C/N0 C/N0 de inicio C/N0 de fin
Señal 1 Código PRN de
la señal 1
Retardo en el
tiempo de la
señal 1 (s)
Frecuencia
Doppler (Hz)
de la señal 1
Ganancia de la
señal 1
… … …. …. …
Señal n Código PRN de
la señal n
Retardo en el
tiempo de la
señal n (s)
Frecuencia
Doppler (Hz)
de la señal n
Ganancia de la
señal n
de adquisición GPS. Este programa fue proporcionado por la Université de Bretagne Sud, a
través del Dr. Emmanuel Boutillon, y se basa en un algoritmo desarrollado por esta
universidad donde utilizan Transformadas Rápidas de Fourier en la adquisición. Para
mayores detalles sobre el algoritmo de adquisición, consultar [32] y [33].
Por ejemplo, para generar una señal GPS con las características de la tabla 4.3, la figura
4.18 muestra la salida del algoritmo de adquisición utilizando como señal de prueba el
archivo .bin generado por el programa generador de señales GPS, los cuales muestran el
código PRN de cada señal y sus respectivas frecuencias Doppler, desfasaje y número de
integraciones no coherentes. En la figura 4.19, figura 4.20 y figura 4.21 se muestran la
detección del desfasaje y frecuencia Doppler de cada señal GPS con su respectivo código
PRN utilizando como parámetro el valor máximo de la función de autocorrelación de cada
señal (ACF) y los picos máximos de la función de autocorrelación se encuentran marcados
con un círculo rojo.
Esta etapa es una de las más importantes para la prueba del algoritmo de seguimiento,
debido a que una mala adquisición de las señales GNSS no permitirá seguir
adecuadamente la señal. La salida de esta etapa servirá para dar valores iniciales a la
56
frecuencia Doppler, retardo y número de integraciones del código PRN de la señal GNSS.
Tabla 4.3 Señales GPS de prueba
Valores
C/N 40 40
Señal 1 1 0.00015 156 1
Señal 2 2 0.0002 110 0.8
Señal 3 9 0.0004 130 0.8
Señal 4 12 0.0003 120 0.8
Señal 5 7 0.0002 140 0.7
Señal 6 15 0.0001 150 0.9
Señal 7 26 0.0001 120 0.5
Figura 4.18 Salida del programa de adquisición de señales GNSS
>>Lecture Fichier signal
Lecture OK
(01 02 03 04 05 06 07 08 09 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27
28 29 30 31 32)
Bilan de la phase d'acquisition
-----------------------------------------------------------------
| PRN | Doppler (Hz) | Desfasaje (Muestras) | Nbr de int no-coh |
-----------------------------------------------------------------
| 01 | +1.56250e+02 | 6.140e+02 | 2 |
| 02 | +1.56250e+02 | 8.180e+02 | 2 |
| 15 | +1.56250e+02 | 4.090e+02 | 2 |
-----------------------------------------------------------------
57
Figura 4.19 Detección del desfasaje y la frecuencia Doppler para la señal con PRN 1
Figura 4.20 Detección del desfasaje y la frecuencia Doppler para la señal con PRN 2
-5 -4 -3 -2 -1 0 1 2 3 4 5-30
-20
-10
0Satélite PRN : 1
Doppler (kHz)
AC
F (
dB)
0 500 1000 1500 2000 2500 3000 3500 4000 4500-40
-30
-20
-10
0
Desfasaje (muestras)
AC
F (
dB)
-5 -4 -3 -2 -1 0 1 2 3 4 5-30
-20
-10
0Satélite PRN : 2
Doppler (kHz)
AC
F (
dB)
0 500 1000 1500 2000 2500 3000 3500 4000 4500-40
-30
-20
-10
0
Desfasaje (muestras)
AC
F (
dB)
58
Figura 4.21 Detección del desfasaje y la frecuencia Doppler para la señal con PRN 15
-5 -4 -3 -2 -1 0 1 2 3 4 5-30
-20
-10
0Satélite PRN : 15
Doppler (kHz)
AC
F (
dB)
0 500 1000 1500 2000 2500 3000 3500 4000 4500-40
-30
-20
-10
0
Desfasaje (muestras)
AC
F (
dB)
CAPÍTULO V ANÁLISIS DE RESULTADOS
5.1 Síntesis del Procesador LEON en la Tarjeta Digilent Spartan 3E-1600
Development Board
Los resultados de la síntesis son mostrados en la tabla 5.1. Se observa que el porcentaje de
los componentes utilizados en el FPGA no sobrepasan el 40%, por lo cual habría recursos
físicos disponibles para poder realizar una implementación de algún componente en el
FPGA.
Tabla 5.1 Resultados de la síntesis del Procesador LEON
Utilización lógica Usado Disponible Utilización
(%)
Número de Slices 125 14752 1
Número de LUTs (Look-Up Tables)
de 4 entradas 219 29504 1
Número de bonded IOBs 98 250 39
5.2 Implementación del algoritmo de seguimiento en el Procesador LEON
Se realizaron diversas pruebas del funcionamiento del algoritmo de seguimiento utilizando
diferentes relaciones C/N0, retardos y frecuencias Doppler diferentes.
Para la prueba del algoritmo se utilizaron los parámetros mostrados en la tabla 5.2. La tabla
5.2 muestra la tasa C/N0 utilizada así como el retardo que insertó en las pruebas y la
frecuencia Doppler que se utilizó. El canal de transmisión es un canal gaussiano y las
pruebas fueron para una transmisión de 30 segundos.
En la tabla 5.3 se muestran los resultados obtenidos como son las desviaciones estándar de
la salida del seguimiento de la frecuencia Doppler y del retardo para cada tasa C/N0.
Además, se muestran la media y mediana del retardo y de la estimación de la tasa C/N0
para cada tasa C/N0.
60
La duración de cada prueba fue de 15 minutos como mínimo. Como se puede observar la
duración de la prueba del algoritmo es alta.
Se observa que la mayoría de las desviaciones estándar de la frecuencia Doppler son
menores a 0.88 Hz y la mayoría de las desviaciones estándar del retardo son menores a 40
us. El estimador C/N0 obtuvo los resultados que en su mayoría son diferentes a los
ingresados por la señal y esto es debido a la interferencia de las demás señales, el retardo y
el efecto Doppler.
En la figura 5.1 se observa que durante las primeras fracciones de segundo, la estimación
de la frecuencia Doppler estaba alrededor de 162 Hz, sin embargo, el sistema logro seguir
a la frecuencia Doppler de entrada, el cual era de 156 Hz.
Tabla 5.2 Parámetros de la prueba
Parámetro Valor
C/N0 (dB-Hz) 40-42 con un paso de 0.5
PRN 1
Retardo (us) 150
Frecuencia Doppler (Hz) 156
Canal Canal gaussiano.
Tiempo de prueba (s) 30
Tabla 5.3 Resultados de la implementación del algoritmo de seguimiento en el Procesador LEON
C/N0
(dB-
Hz)
Desviación
estándar
Doppler
(us)
Media
retardo
(us)
Mediana
Retardo
(us)
Desviación
estándar
del retardo
(us)
Media
C/N0
(dB-
Hz)
Mediana
C/N0
(dB-Hz)
Desviación
estándar
C/N0 (dB-
Hz)
40 0,43 142,08 150,49 31,51 39,56 39,51 1,27
40 0,75 145,52 151,83 43,37 36,50 36,87 0,98
40 0,65 145,10 151,45 36,10 34,54 34,47 1,15
40 0,45 148,67 153,36 27,97 36,63 36,68 0,89
40,5 0,52 143,01 151,51 25,56 41,03 40,81 1,08
40,5 0,62 141,56 150,36 26,60 40,78 40,70 0,80
61
40,5 0,37 149,20 153,72 27,21 37,45 37,42 0,80
40,5 0,41 149,43 153,33 26,71 36,88 36,89 0,95
41 0,63 134,29 142,79 30,21 41,09 41,24 1,30
41 0,31 146,61 151,86 30,10 38,18 38,33 1,14
41 0,32 145,25 150,54 28,54 39,10 39,22 1,42
41 0,37 140,07 149,92 29,22 41,34 41,27 1,48
41,5 0,34 145,31 152,81 23,92 41,88 41,70 0,85
41,5 0,27 150,00 153,84 23,70 39,12 39,25 1,15
41,5 0,32 146,66 153,08 25,38 41,35 41,35 1,17
41,5 1,26 148,98 153,95 34,07 33,70 33,94 1,16
42 0,31 145,35 152,89 25,03 42,30 42,27 1,65
42 0,26 150,51 153,75 29,29 39,16 39,26 1,03
42 0,24 150,11 153,68 26,74 39,80 39,78 0,69
42 0,25 147,87 153,23 21,45 41,45 41,42 0,87
Figura 5.1 Seguimiento de la frecuencia
Las figuras 5.2 y 5.3 muestran los resultados obtenidos de las pruebas de desempeño del
algoritmo deducibles de la tabla 5.3. En la figura 5.2 se muestra la gráfica de la mediana de
C/N0 vs la desviación estándar de la frecuencia Doppler. Se observa que a medida que va
aumentando la relación C/N0 va disminuyendo la desviación estándar de la frecuencia
Doppler.
De igual manera, en la figura 5.3 se muestra la gráfica de la mediana de C/N0 vs la
desviación estándar del retardo. Se observa que a medida que va aumentando la relación
C/N0 va disminuyendo la desviación estándar del retardo.
De estas dos últimas gráficas se comprueba el buen desempeño que ofrece el algoritmo de
0 1 2 3 4 5 6 7 8 9 10153
154
155
156
157
158
159
160
161
162
163
Time (s)
Est
imat
ed D
oppl
er (
Hz)
62
seguimiento en las pruebas. Por lo cual las mejoras a realizarse serían para reducir el
tiempo de procesamiento del algoritmo de seguimiento.
Figura 5.2 Gráfica desviación estándar de la frecuencia Doppler (Hz) vs el valor C/N0 estimado (dB-Hz)
Figura 5.3 Gráfica desviación estándar del retardo (us) vs el valor C/N0 estimado (dB-Hz)
0,00
0,20
0,40
0,60
0,80
1,00
1,20
1,40
33,00 35,00 37,00 39,00 41,00 43,00
Sig
ma
Dop
pler
(H
z)
C/N0 estimado (dB-Hz)
0,005,00
10,0015,0020,0025,0030,0035,0040,0045,0050,00
33,00 35,00 37,00 39,00 41,00 43,00
Sig
ma
Ret
ardo
(us)
C/N0 estimado (dB-Hz)
CONCLUSIONES Y RECOMENDACIONES Conclusiones
1. Teniendo como resultado la disminución de la desviación estándar de la frecuencia
Doppler y del retardo a medida que aumenta la relación C/N0, se concluye que el
algoritmo de seguimiento desarrollado en la tesis cumple los requerimientos básicos de
un algoritmo de seguimiento GNSS en el espacio.
2. Además, teniendo en cuenta que el procesador LEON funciona adecuadamente e
incluso ocupa menos del 50% de los recursos del FPGA, se concluye que el procesador
no consume recursos importantes y se podría implementar en dispositivos de menos
recursos.
3. Teniendo como resultado un alto tiempo de procesamiento del algoritmo, se concluye
que aún el tiempo de procesamiento del algoritmo es aún insuficiente y es necesario
disminuirlo.
Recomendaciones
1. Se recomienda realizar la implementación en VHDL de las etapas del algoritmo de
seguimiento como continuación del tema de tesis, debido a que algunos módulos del
algoritmo de seguimiento requieren mucho tiempo de procesamiento de las señales
GNSS. La implementación sería principalmente en el módulo de correlación e
integración, los cuales requieren mayores recursos de hardware.
2. Se recomienda realizar la implementación de las demás etapas del receptor GNSS para
futuros temas de tesis, como son el algoritmo de adquisición y el algoritmo para el
cálculo de la actitud. De esta forma se obtendría el diseño completo de un receptor
GNSS.
3. Debido a que el algoritmo de seguimiento para GPS desarrollado es escalable. Se
sugiere adaptar este algoritmo a otros sistemas como GLONASS o Beidou. De esa
forma se obtendría una mayor precisión en el cálculo de la posición del receptor debido
al aumento del número de satélites porporcionado por cada sistema GNSS.
65
Digilent Spartan 3E-1600 Development Board
IC: XC3S1600E Spartan 3E FPGA Analog Devices ADM3232EARNZ RS-232 Line Driver/Receiver
Connector(s):
100-pin Hirose FX2 connector Three 6-pin Pmod connectors DB15HD VGA Two DB9 RS-232 connectors RJ-45 Ethernet 16-pin header for optional LCD modules SMA connector for high-speed clock input
Programming:
JTAG programming via on-board USB2 port, external parallel or USB cables. The FPGA supports numerous configuration options including on-board platform flash, SPI flash, and parallel flash.
• Xilinx XC3S1600E FPGA • Xilinx XCF04 Platform Flash for
storing FPGA configurations • ST Microelectronics M25P16
16Mbit Serial Flash • Intel TE28F128 (or JS28F128)
128Mbit StartaFlash • Linear Technologies Power
Supplies • Texas Instruments TPS75003
Triple-Supply Power Management IC
• SMSC LAN83C185 Ethernet PHY • Micron 256Mbit DDR SDRAM
The Spartan 3E-1600 Development Board provides a powerful and highly advanced self-contained development platform for designs targeting the Spartan 3E FPGA from Xilinx. It features a 1600K gate Spartan 3E capable of implementing large complex digital systems including the 32-bit MicroBlaze RISC soft processor with DDR interfaces. The board features JTAG programming via on-board USB2 port, external parallel or USB cables. The FPGA supports configuration via the on-board Xilinx platform flash, Intel StrataFlash, ST Microelectonics Serial Flash and numerous additional options. It is fully compatible with all versions of the Xilinx ISE tools including the free WebPack. The board ships with a power supply and USB cable for programming so designs can be implemented immediately with no hidden costs. The Spartan 3E-1600 Development Board is also compatible with the Xilinx Embedded Development Kit (EDK) featuring the 32-bit MicroBlaze RISC processor. The PicoBlaze soft processor core is also supported via ISE.
67
“main.c”
1. #include <asm-leon/irq.h>
2. #include <stdio.h>
3. #include <stdlib.h>
4. #include <string.h>
5. #include <math.h>
6. #include "address.h"
7. /* Functions */
8. #include "Constants.h"
9. #include "structures_recepteur.h"
10. #include "code_gene_GPS.h"
11. #include "initRecepteur.h"
12. #include "falseLockDetector.h"
13. #include "localCodeGenerator.h"
14. #include "dopplerEstime.h"
15. #include "fpll.h"
16. #include "code_discriminator.h"
17. #include "integrator.h"
18. #include "dataDemodulation.h"
19. #include "bitSynchro.h"
20. #include "codeLockDetector.h"
21. #include "correlateurComplet.h"
22. #include "localCarrierGenerator.h"
23. #include "filter.h"
24. #include "codeNCO.h"
25. #include "canal_Bruit.h"
26. /**************************************/
27. /* Recepteur GNSS */
28. /**************************************/
29. int main(){
30. int reg;
31. int *UART;
32. UART = (int*) 0x80000100;
68
33. UART[0] = UART[0] & 0xFFFFFF00;
34. reg = UART[0];
35. reg = reg & 0xFFFFFF00;
36. reg = UART[1];
37. reg = UART[2];
38. reg = reg | 0x00000043;
39. reg = reg & 0xFFFFFF43;
40. UART[2] = reg;
41. double data_base=0.0;
42. double data_exp=0.0;
43. double data1=0.0;
44. precepteurS = &recepteurS;
45. scanf("%12lf",&data_base);
46. data1=data_base;
47. printf("%+12.9lf\n",data_base);
48. scanf("%12lf",&data_exp);
49. printf("%+12.8lf\n",data_exp);
50. data1 = data1*pow(10,data_exp);
51. precepteurS->Sreceive_data._DopplerEstime = data1;
52. scanf("%12lf",&data_base);
53. data1=data_base;
54. printf("%+12.9lf\n",data_base);
55. scanf("%12lf",&data_exp);
56. printf("%+12.8lf\n",data_exp);
57. data1 = data1*pow(10,data_exp);
58. precepteurS->Sreceive_data._DephasageEstime = data1;
59. //scanf("%s",data);
60. scanf("%12lf",&data_base);
61. data1=data_base;
62. printf("%+12.9lf\n",data_base);
63. scanf("%12lf",&data_exp);
64. printf("%+12.8lf\n",data_exp);
65. data1 = data1*pow(10,data_exp);
69
66. precepteurS->Sreceive_data._NbIntegration = data1;
67. scanf("%12lf",&data_base);
68. data1=data_base;
69. printf("%+12.9lf\n",data_base);
70. scanf("%12lf",&data_exp);
71. printf("%+12.8lf\n",data_exp);
72. data1 = data1*pow(10,data_exp);
73. precepteurS->Sreceive_data._PRN = (int)data1;
74. scanf("%12lf",&data_base);
75. data1=data_base;
76. printf("%+12.9lf\n",data_base);
77. scanf("%12lf",&data_exp);
78. printf("%+12.8lf\n",data_exp);
79. data1 = data1*pow(10,data_exp);
80. precepteurS->Sreceive_data._Time_NS = data1;
81. /** --------------------- Functions ------------------- **/
82. precepteurS = initFilter(precepteurS);
83. precepteurS = acquisition_parameters(precepteurS);
84. precepteurS = initGene(precepteurS);
85. precepteurS = initCorrelateur(precepteurS);
86. precepteurS = initCodeLockDetector(precepteurS);
87. precepteurS = initPhaseLockDetector(precepteurS);
88. precepteurS = initIntegrator(precepteurS);
89. precepteurS = initBitSynchro(precepteurS);
90. precepteurS = initDiscri(precepteurS);
91. precepteurS = initFiltreFPLL(precepteurS);
92. precepteurS = initCodeDiscriminator(precepteurS);
93. precepteurS = initFalseLockDetector(precepteurS);
94. precepteurS = initCodeNCO(precepteurS);
95. precepteurS = initLocalCodeGenerator(precepteurS);
96. precepteurS = initDataDemodulation(precepteurS);
97. precepteurS = initDoppleEstime(precepteurS);
98. FCanalBruit(precepteurS);
70
99. return 0;
100. }
“address.h”
1. #ifndef __address_h__
2. #define __address_h__
3. #ifndef LEON3
4. #define LEON3
5. #endif
6. #ifdef LEON3
7. #define ICLEAR 0x20c
8. #define IMASK 0x240
9. #define IFORCE 0x208
10. #else
11. #define ICLEAR 0x9c
12. #define IMASK 0x90
13. #define IFORCE 0x98
14. #endif
15. #endif
“bitSynchro.h”
1. #ifndef BITSYNCHRO_H_
2. #define BITSYNCHRO_H_
3. struct recepteur *FbitSynchro(struct recepteur *precepteurS){
4. int i;
5. /* Mémorisation du module de la voie prompt */
6. precepteurS->Sbitsynchro._IndexData = (int)precepteurS-
>Scorrelateur_prompt.SynchroBit_Rxx[0];
7. precepteurS->Sbitsynchro._CodeLock = precepteurS-
>Scodelock_detector.CodeLock;
8. precepteurS->Sbitsynchro.DataBufferRe[precepteurS->Sbitsynchro._IndexData]
= precepteurS->Scorrelateur_prompt.SynchroBit_Rxx[1];
9. precepteurS->Sbitsynchro.DataBufferIm[precepteurS->Sbitsynchro._IndexData]
= precepteurS->Scorrelateur_prompt.SynchroBit_Rxx[2];
10. if (precepteurS->Sbitsynchro.Synchro == 0){
71
11. /* Intégration du buffer tournant */
12. precepteurS->Sbitsynchro.IntegrationRe = 0;
13. precepteurS->Sbitsynchro.IntegrationIm = 0;
14. for (i = 0 ;i<20;i++){
15. precepteurS->Sbitsynchro.IntegrationRe += precepteurS-
>Sbitsynchro.DataBufferRe[i];
16. precepteurS->Sbitsynchro.IntegrationIm += precepteurS-
>Sbitsynchro.DataBufferIm[i];
17. }
18. /* Calcul du module résultant */
19. precepteurS->Sbitsynchro.Module = sqrt(pow(precepteurS-
>Sbitsynchro.IntegrationRe,2.0)+pow(precepteurS-
>Sbitsynchro.IntegrationIm,2.0));
20. // Gestion de l'index du buffer circulaire
21. if (precepteurS->Sbitsynchro._IndexData == 19){
22. precepteurS->Sbitsynchro.LockRecherche = 1;
23. precepteurS->Sbitsynchro.IndexBuffer = 0;
24. /* Recherche du maximum d'energie */
25. // 1re condition de recherche de l'instant de synchronisation
26. for (i = 0 ;i<20;i++){
27. if (precepteurS->Sbitsynchro.AccBuffer[i] > precepteurS-
>Sbitsynchro.AccBuffer[precepteurS->Sbitsynchro.IndiceMax]){
28. precepteurS->Sbitsynchro.IndiceMax = i;
29. precepteurS->Sbitsynchro.NbHits = 0;
30. }
31. }
32. precepteurS->Sbitsynchro.NbHits += 1;
33. precepteurS->Sbitsynchro.TabMoyenne[precepteurS-
>Sbitsynchro.IndiceMoyenne] = precepteurS->Sbitsynchro.IndiceMax;
34. if (precepteurS->Sbitsynchro.IndiceMoyenne == Const_TailleFiltre - 1)
35. precepteurS->Sbitsynchro.IndiceMoyenne = 0;
36. else
37. precepteurS->Sbitsynchro.IndiceMoyenne += 1;
72
38. // Filtrage
39. precepteurS->Sbitsynchro.AccMoyenne = 0;
40. for (i=0;i<Const_TailleFiltre;i++)
41. precepteurS->Sbitsynchro.AccMoyenne += precepteurS-
>Sbitsynchro.TabMoyenne[i];
42. precepteurS->Sbitsynchro._InstantSynchro = (int)((double)precepteurS-
>Sbitsynchro.AccMoyenne/(double)Const_TailleFiltre);
43. #ifdef OUTPUTFILE
44. //fprintf(thread_data_recepteur->bitsynchro_struct->pFile1,"IndiceMax :
%d : InstantSynchro : %d\n",thread_data_recepteur->bitsynchro_struct-
>IndiceMax,thread_data_recepteur->bitsynchro_struct->_InstantSynchro);
45. send_data_int(precepteurS->Sbitsynchro.IndiceMax);
46. send_data_int(precepteurS->Sbitsynchro._InstantSynchro);
47. #endif
48. precepteurS->Sbitsynchro.InstantSynchro = precepteurS-
>Sbitsynchro._InstantSynchro;
49. precepteurS->Sbitsynchro.DataDemodulation_InstantSynchro =
precepteurS->Sbitsynchro._InstantSynchro;
50. precepteurS->Sbitsynchro.CodeLock_InstantSynchro = precepteurS-
>Sbitsynchro._InstantSynchro;
51. }
52. else
53. precepteurS->Sbitsynchro.IndexBuffer += 1;
54. // Accumulation de l'intégration avec les précédents résultats
55. if (precepteurS->Sbitsynchro.LockRecherche){
56. precepteurS->Sbitsynchro.AccBuffer[precepteurS-
>Sbitsynchro.IndexBuffer] += precepteurS->Sbitsynchro.Module;
57. }
58. }
59. else
60. if (precepteurS->Sbitsynchro._CodeLock == 0){
61. //initBitSynchro();
62. for (i=0;i<20;i++)
73
63. precepteurS->Sbitsynchro.AccBuffer[i] = 0;
64. precepteurS->Sbitsynchro.LockRecherche = 0;
65. precepteurS->Sbitsynchro.IndiceMax = 0;
66. precepteurS->Sbitsynchro._IndexData = 0;
67. precepteurS->Sbitsynchro.NbHits = 0;
68. precepteurS->Sbitsynchro.Synchro = 0;
69. precepteurS->Sbitsynchro.IndexBuffer = 0;
70. precepteurS->Sbitsynchro.IndiceMoyenne = 0;
71. for (i=0;i<Const_TailleFiltre;i++)
72. precepteurS->Sbitsynchro.TabMoyenne[i] = 0;
73. precepteurS->Sbitsynchro.FalseLockDetector_SynchroLock[0] =
precepteurS->Sbitsynchro.Synchro;
74. precepteurS->Sbitsynchro.FalseLockDetector_SynchroLock[1] = 0;
75. }
76. if (precepteurS->Sbitsynchro.NbHits >=50){
77. if (precepteurS->Sbitsynchro._CodeLock == 1){
78. if (precepteurS->Sbitsynchro.Synchro == 0){
79. precepteurS->Sbitsynchro.Synchro = 1;
80. precepteurS->Sbitsynchro.FalseLockDetector_SynchroLock[0] =
precepteurS->Sbitsynchro.Synchro;
81. precepteurS->Sbitsynchro.FalseLockDetector_SynchroLock[1] = 0;
82. }
83. }
84. else{
85. precepteurS->Sbitsynchro.NbHits = 0;
86. precepteurS->Sbitsynchro.Synchro = 0;
87. precepteurS->Sbitsynchro.FalseLockDetector_SynchroLock[0] =
precepteurS->Sbitsynchro.Synchro;
88. precepteurS->Sbitsynchro.FalseLockDetector_SynchroLock[1] = 1;
89. }
90. }
91. FdataDemodulation(precepteurS);
92. return precepteurS;
74
93. }
94. #endif /* BITSYNCHRO_H_ */
“canal_Bruit.h”
1. #ifndef CANAL_BRUIT_H_
2. #define CANAL_BRUIT_H_
3. void FCanalBruit(struct recepteur *precepteurS){//, int *UART){
4. int i;
5. int samples;
6. double _I,_Q;
7. double data_base;
8. double data_exp;
9. double data1;
10. double data;
11. samples = (int)(precepteurS->Sreceive_data._Time_NS/122.05);
12. precepteurS->clockGNSS = (int)1000000000/122.05;
13. for(i=0;i<samples;i++){
14. scanf("%12lf",&data_base);
15. data1=data_base;
16. printf("%+12.9lf\n",data_base);
17. scanf("%12lf",&data_exp);
18. printf("%+12.8lf\n",data_exp);
19. data1 = data1*pow(10,data_exp);
20. _I = data1;
21. scanf("%12lf",&data_base);
22. data1=data_base;
23. printf("%+12.9lf\n",data_base);
24. scanf("%12lf",&data_exp);
25. printf("%+12.8lf\n",data_exp);
26. data1 = data1*pow(10,data_exp);
27. _Q = data1;
28. precepteurS->Scanal.I_out = _I;
29. precepteurS->Scanal.Q_out = _Q;
30. if(i%precepteurS->clockGNSS == 0)
75
31. falseLock5(precepteurS);
32. FcodeNCO(precepteurS);
33. Ffilter(precepteurS);
34. for(i=0;i<2;i++){
35. scanf("%12lf",&data);
36. if(precepteurS->estado[i] == 1){
37. printf("%+12.9lf\n",precepteurS->data_base[i]);
38. scanf("%12lf",&data);
39. printf("%+12.8lf\n",precepteurS->data_exp[i]);
40. }
41. else{
42. printf("%+12.9lf\n",data);
43. scanf("%12lf",&data);
44. printf("%+12.8lf\n",data);
45. }
46. precepteurS->estado[i] = 0.0;
47. }
48. }
49. }
50. #endif /* CANAL_BRUIT_H_ */
“code_Discriminator.h”
1. #ifndef CODE_DISCRIMINATOR_H_
2. #define CODE_DISCRIMINATOR_H_
3. /** StateMacBandwidth **/
4. struct recepteur *StateMacBandwidth(struct recepteur *precepteurS){
5. // Section 4.9 Expert Report (Bnc)
6. //Machine d'état
7. precepteurS->Scode_discriminateur._OptimisticPhaseLock = precepteurS-
>Scodelock_detector.CodeDiscriLock[0];
8. precepteurS->Scode_discriminateur._PessimisticPhaseLock = precepteurS-
>Scodelock_detector.CodeDiscriLock[1];
9. if (precepteurS->Scode_discriminateur._OptimisticPhaseLock == 1){
10. if (precepteurS->Scode_discriminateur._PessimisticPhaseLock == 1){
76
11. if (precepteurS->Scode_discriminateur.Bdll>0.1)
12. precepteurS->Scode_discriminateur.Bdll-=0.001;
13. }
14. else
15. precepteurS->Scode_discriminateur.Bdll=1.0;
16. }
17. else
18. precepteurS->Scode_discriminateur.Bdll=2.0;
19. return precepteurS;
20. }
21. /** Discriminator **/
22. struct recepteur *Discriminator(struct recepteur *precepteurS){
23. precepteurS->Scode_discriminateur._PromptReRxxInt = precepteurS-
>Sintegrator.PromptRxxInt[0];
24. precepteurS->Scode_discriminateur._PromptImRxxInt = precepteurS-
>Sintegrator.PromptRxxInt[1];
25. precepteurS->Scode_discriminateur._EarlyReRxxInt = precepteurS-
>Sintegrator.EarlyRxxInt[0];
26. precepteurS->Scode_discriminateur._EarlyImRxxInt = precepteurS-
>Sintegrator.EarlyRxxInt[1];
27. precepteurS->Scode_discriminateur._LateReRxxInt = precepteurS-
>Sintegrator.LateRxxInt[0];
28. precepteurS->Scode_discriminateur._LateImRxxInt = precepteurS-
>Sintegrator.LateRxxInt[1];
29. #ifdef OUTPUTFILE
30. send_data_double(precepteurS->Scode_discriminateur._PromptReRxxInt);
31. send_data_double(precepteurS->Scode_discriminateur._EarlyReRxxInt);
32. send_data_double(precepteurS->Scode_discriminateur._LateReRxxInt);
33. #endif
34. // Test d'un autre discriminateur page 174 Kaplan : Noncoherent early minus late
35. // Section 4.4.1 Expert Report
36. precepteurS->Scode_discriminateur.E = sqrt(pow(precepteurS-
>Scode_discriminateur._EarlyReRxxInt, 2.0) + pow(precepteurS-
77
>Scode_discriminateur._EarlyImRxxInt, 2.0));
37. precepteurS->Scode_discriminateur.L = sqrt(pow(precepteurS-
>Scode_discriminateur._LateReRxxInt, 2.0) + pow(precepteurS-
>Scode_discriminateur._LateImRxxInt, 2.0));
38. precepteurS->Scode_discriminateur.EplusL = precepteurS-
>Scode_discriminateur.E + precepteurS->Scode_discriminateur.L;
39. if (precepteurS->Scode_discriminateur.EplusL != 0)
40. precepteurS->Scode_discriminateur.Discri = 0.5*(precepteurS-
>Scode_discriminateur.E - precepteurS-
>Scode_discriminateur.L)/precepteurS->Scode_discriminateur.EplusL;
41. else
42. precepteurS->Scode_discriminateur.Discri = 0;
43. // Filtre
44. // Section 4.4.2 Expert Report
45. precepteurS->Scode_discriminateur.DiscriFiltre = 4*precepteurS-
>Scode_discriminateur.Bdll/Const_Fe_re*precepteurS-
>Scode_discriminateur.Discri;
46. #ifdef OUTPUTFILE
47. //fprintf(my_data->code_discriminateur_struct->pFile1,"%g\n",my_data-
>code_discriminateur_struct->Discri);
48. //VDLLFile<<Discri<<std::endl;
49. send_data_double(precepteurS->Scode_discriminateur.Discri);
50. //fprintf(my_data->code_discriminateur_struct->pFile2,"%g\n",my_data-
>code_discriminateur_struct->Bdll);//BDLLFile<<Bdll<<std::endl;
51. send_data_double(precepteurS->Scode_discriminateur.Bdll);
52. #endif
53. /* Sortie du discriminateur de code */
54. precepteurS->Scode_discriminateur.NCO_VeDLL = precepteurS-
>Scode_discriminateur.DiscriFiltre;
55. precepteurS->Scode_discriminateur.DopplerEstimator_VeDLL = precepteurS-
>Scode_discriminateur.DiscriFiltre;
56. precepteurS->Scode_discriminateur.FalseLockDetector_VeDLL = precepteurS-
>Scode_discriminateur.DiscriFiltre;
78
57. // Le discri du Kaplan a l'air plus performant que celui de M3S
58. return precepteurS;
59. }
60. /** ----------------- Init Code Discriminator ----------------- **/
61. struct recepteur *Fcode_discriminator(struct recepteur *precepteurS){
62. if(precepteurS->Sintegrator.DumpEnable == 1){
63. /* StateMacBandwidth */
64. StateMacBandwidth(precepteurS);
65. /* Discriminator */
66. Discriminator(precepteurS);
67. Ffpll(precepteurS);
68. FfalseLock(precepteurS);
69. }
70. return precepteurS;
71. }
72. #endif /* CODE_DISCRIMINATOR_H_ */
“code_gene_GPS.h”
1. #include <stdio.h>
2. #include <stdlib.h>
3. void ones(int *t,int n){
4. int i;
5. for(i=0;i<n;i++)
6. *(t+i)=1;
7. }
8. int xor(int a,int b){
9. if(a==b)
10. return 0.0;
11. else
12. return 1.0;
13. }
14. void code_gene_GPS(struct recepteur *precepteurS)
15. {
16. int CoupleSV[32][2]={{2,6},{3,7},{4,8},{5,9},{1,9},{2,10},{1,8},{2,9},{3,10},
79
{2,3},{3,4},{5,6},{6,7},{7,8},{8,9},{9,10},{1,4},{2,5},{3,6},{4,7},
{5,8},{6,9},{1,3},{4,6},{5,7},{6,8},{7,9},{8,10},{1,6},{2,7},{3,8},{4,9}};
17. int vecteur[10];
18. int *t = &vecteur[0];
19. int codeG1[1023];
20. int *t1 = &codeG1[0];
21. int codeG2[1023];
22. int *t2 = &codeG2[0];
23. int dec;
24. int i,j;
25. int temp,temp1;
26. int SV = precepteurS->Sacquisition.PRN;
27. /* Generation of code G1*/
28. ones(t,10);
29. for(i=0;i<1023;i++){
30. *(t1+i)=*(t+9);
31. for(j=0;j<10;j++){
32. if(j==0){
33. temp = *t;
34. *t=xor(*(t+2),*(t+9));
35. }
36. else{
37. temp1 = *(t+j);
38. *(t+j) = temp;
39. temp = temp1;
40. }
41. }
42. }
43. /* Generation of code G2 */
44. ones(t,10);
45. for(i=0;i<1023;i++){
46. *(t2+i)=xor(*(t+(int)CoupleSV[SV-1][0]-1),*(t+(int)CoupleSV[SV-1][1]-1));
47. dec = xor(xor(xor(*(t+1),*(t+2)), xor(*(t+5),*(t+7))), xor(*(t+8),*(t+9)));
80
48. for(j=0;j<10;j++){
49. if(j==0){
50. temp = *t;
51. *t=dec;
52. }
53. else{
54. temp1 = *(t+j);
55. *(t+j) = temp;
56. temp = temp1;
57. }
58. }
59. }
60. /* Generation of code GPS */
61. for(i=0;i<1023;i++){
62. precepteurS->Slocal_code_generator.TabCode[i]=2*xor(*(t1+i),*(t2+i))-1;
63. }
64. }
“codeLockDetector.h”
1. #ifndef CODELOCKDETECTOR_H_
2. #define CODELOCKDETECTOR_H_
3. /** CodeLock detector **/
4. struct recepteur *Fcodelock_detector(struct recepteur *precepteurS){
5. int j;
6. if(precepteurS->Sintegrator.RazIntP ==1){
7. /* C/N0 estimator */
8. // Spilker Vol.1 page 390
9. // Section 4.6.2 Expert Report
10. precepteurS->Scodelock_detector._IndexData = (int)precepteurS-
>Scorrelateur_prompt.CodeLock_Rxx[0];
11. precepteurS->Scodelock_detector._PromptReRxxInt = precepteurS-
>Scorrelateur_prompt.CodeLock_Rxx[1];
12. precepteurS->Scodelock_detector._PromptImRxxInt = precepteurS-
>Scorrelateur_prompt.CodeLock_Rxx[2];
81
13. precepteurS->Scodelock_detector._InstantSynchro = precepteurS-
>Sbitsynchro.CodeLock_InstantSynchro;
14. if (precepteurS->Scodelock_detector._IndexData == precepteurS-
>Scodelock_detector._InstantSynchro){
15. precepteurS->Scodelock_detector.AccWBP = 0.0;
16. precepteurS->Scodelock_detector.AccNBPI = 0.0;
17. precepteurS->Scodelock_detector.AccNBPQ = 0.0;
18. for (j=0;j<20;j++){
19. precepteurS->Scodelock_detector.AccWBP += pow(precepteurS-
>Scodelock_detector.TabI[j],2.0)+pow(precepteurS-
>Scodelock_detector.TabQ[j],2.0);
20. precepteurS->Scodelock_detector.AccNBPI += precepteurS-
>Scodelock_detector.TabI[j];
21. precepteurS->Scodelock_detector.AccNBPQ += precepteurS-
>Scodelock_detector.TabQ[j];
22. }
23. precepteurS->Scodelock_detector.WBP[precepteurS-
>Scodelock_detector.k] = precepteurS->Scodelock_detector.AccWBP;
24. precepteurS->Scodelock_detector.NBP[precepteurS-
>Scodelock_detector.k] = pow(precepteurS-
>Scodelock_detector.AccNBPI,2.0) + pow(precepteurS-
>Scodelock_detector.AccNBPQ,2.0);
25. if (precepteurS->Scodelock_detector.WBP[precepteurS-
>Scodelock_detector.k] != 0){
26. precepteurS->Scodelock_detector.NP[precepteurS-
>Scodelock_detector.k] = precepteurS-
>Scodelock_detector.NBP[precepteurS-
>Scodelock_detector.k]/precepteurS-
>Scodelock_detector.WBP[precepteurS->Scodelock_detector.k];
27. if (precepteurS->Scodelock_detector.NMoy<50)
28. precepteurS->Scodelock_detector.NMoy += 1;
29. if (precepteurS->Scodelock_detector.k>=49)
30. precepteurS->Scodelock_detector.k =0;
82
31. else
32. (precepteurS->Scodelock_detector.k)++;
33. precepteurS->Scodelock_detector.AccNP = 0.0;
34. for (j=0;j<50;j++){
35. precepteurS->Scodelock_detector.AccNP += precepteurS-
>Scodelock_detector.NP[j];
36. }
37. precepteurS->Scodelock_detector.Fraction = (precepteurS-
>Scodelock_detector.AccNP/precepteurS->Scodelock_detector.NMoy-
1.0)/(20.0-precepteurS->Scodelock_detector.AccNP/precepteurS-
>Scodelock_detector.NMoy);//u_NP = AccNP/NMoy
38. if (precepteurS->Scodelock_detector.Fraction < 0)
39. precepteurS->Scodelock_detector._C_N_estimated = -100.0;
40. else
41. precepteurS->Scodelock_detector._C_N_estimated =
10*log10(1.0/(1.0/1000.0)*precepteurS-
>Scodelock_detector.Fraction);//T = 1/1000
42. #ifdef OUTPUTFILE
43. send_data_double(precepteurS->Scodelock_detector._C_N_estimated);
44. #endif
45. }
46. }
47. precepteurS->Scodelock_detector.TabI[precepteurS-
>Scodelock_detector._IndexData] = precepteurS-
>Scodelock_detector._PromptReRxxInt;
48. precepteurS->Scodelock_detector.TabQ[precepteurS-
>Scodelock_detector._IndexData] = precepteurS-
>Scodelock_detector._PromptImRxxInt;
49. /* Phase Lock Estimator */
50. // Kaplan page 233-234
51. //Echantillonnage tout les 20 ms
52. // Section 4.6.1 Expert Report
53. if (precepteurS->Scodelock_detector._IndexData == precepteurS-
83
>Scodelock_detector._InstantSynchro){
54. precepteurS->Scodelock_detector.AbsPromptReRxxInt =
abs(precepteurS->Scodelock_detector._PromptReRxxInt);
55. precepteurS->Scodelock_detector.AbsPromptImRxxInt =
abs(precepteurS->Scodelock_detector._PromptImRxxInt);
56. // Low Pass Filter
57. // Real (Iprompt)
58. precepteurS->Scodelock_detector.LPFResultRe_previous = precepteurS-
>Scodelock_detector.LPFResultRe;
59. precepteurS->Scodelock_detector.LPFinterRe = Const_K1*(precepteurS-
>Scodelock_detector.AbsPromptReRxxInt - precepteurS-
>Scodelock_detector.LPFResultRe_previous);
60. precepteurS->Scodelock_detector.LPFResultRe = (precepteurS-
>Scodelock_detector.LPFinterRe + precepteurS-
>Scodelock_detector.LPFResultRe_previous);
61. precepteurS->Scodelock_detector.A = precepteurS-
>Scodelock_detector.LPFResultRe/Const_K2;
62. // Imaginary (Qprompt)
63. precepteurS->Scodelock_detector.LPFResultIm_previous = precepteurS-
>Scodelock_detector.LPFResultIm;
64. precepteurS->Scodelock_detector.LPFinterIm = Const_K1*(precepteurS-
>Scodelock_detector.AbsPromptImRxxInt - precepteurS-
>Scodelock_detector.LPFResultIm_previous);
65. precepteurS->Scodelock_detector.LPFResultIm = precepteurS-
>Scodelock_detector.LPFinterIm + precepteurS-
>Scodelock_detector.LPFResultIm_previous;
66. precepteurS->Scodelock_detector.B = precepteurS-
>Scodelock_detector.LPFResultIm;
67. if(precepteurS->Scodelock_detector.A > precepteurS-
>Scodelock_detector.B){
68. // YES Branch
69. precepteurS->Scodelock_detector._OptimisticPhaseLock = 1;
70. precepteurS->Scodelock_detector.Pcount[2] = 0;
84
71. if(precepteurS->Scodelock_detector.Pcount[1] > Const_Lp)
72. precepteurS->Scodelock_detector._PessimisticPhaseLock = 1;
73. else
74. precepteurS->Scodelock_detector.Pcount[1] += 1;
75. }
76. else{
77. // No Branch
78. precepteurS->Scodelock_detector._PessimisticPhaseLock = 0;
79. precepteurS->Scodelock_detector.Pcount[1] = 0;
80. if(precepteurS->Scodelock_detector.Pcount[2] > Const_Lo)
81. precepteurS->Scodelock_detector._OptimisticPhaseLock = 0;
82. else
83. precepteurS->Scodelock_detector.Pcount[2] += 1;
84. }
85. }
86. precepteurS->Scodelock_detector.C_N_estimated = precepteurS-
>Scodelock_detector._C_N_estimated;
87. precepteurS->Scodelock_detector.CodeLock = precepteurS-
>Scodelock_detector._OptimisticPhaseLock;
88. precepteurS->Scodelock_detector.CodeDiscriLock[0] = precepteurS-
>Scodelock_detector._OptimisticPhaseLock;
89. precepteurS->Scodelock_detector.CodeDiscriLock[1] = precepteurS-
>Scodelock_detector._PessimisticPhaseLock;
90. precepteurS->Scodelock_detector.PhaseLock[0] = precepteurS-
>Scodelock_detector._OptimisticPhaseLock;
91. precepteurS->Scodelock_detector.PhaseLock[1] = precepteurS-
>Scodelock_detector._PessimisticPhaseLock;
92. precepteurS->Scodelock_detector.FalseLockDetector_PhaseLock[0] =
precepteurS->Scodelock_detector._OptimisticPhaseLock;
93. precepteurS->Scodelock_detector.FalseLockDetector_PhaseLock[1] =
precepteurS->Scodelock_detector._PessimisticPhaseLock;
94. precepteurS->Scodelock_detector.FalseLockDetector_EstimatedCN0 =
precepteurS->Scodelock_detector._C_N_estimated;
85
95. FbitSynchro(precepteurS);
96. }
97. return precepteurS;
98. }
99. #endif /* CODELOCKDETECTOR_H_ */
“codeNCO.h”
1. #ifndef CODENCO_H_
2. #define CODENCO_H_
3. struct recepteur *FcodeNCO(struct recepteur *precepteurS){
4. // Aide de la FPLL
5. precepteurS->ScodeNCO.CodeFPLL =
(double)Const_Rca/(2*M_PI*Const_f0)*(precepteurS->ScodeNCO.DopplerIni
+ precepteurS->ScodeNCO._VeFPLL);
6. precepteurS->ScodeNCO.CodeNCO = precepteurS->ScodeNCO._VeDLL +
precepteurS->ScodeNCO.CodeFPLL;
7. precepteurS->ScodeNCO.CodeIndexPrompt = precepteurS-
>ScodeNCO.CodeNCO + Const_Rc_re + precepteurS-
>ScodeNCO.CodeIndexPrompt;
8. #ifdef OUTPUTFILE
9. if(precepteurS->ScodeNCO.CodeFPLL != precepteurS-
>ScodeNCO.CodeFPLL_previous){
10. precepteurS->ScodeNCO.CodeFPLL_previous = precepteurS-
>ScodeNCO.CodeFPLL;
11. //fprintf(precepteurS->ScodeNCO.pFile1,"%g\n",precepteurS-
>ScodeNCO.CodeFPLL);//CodeNCOFile<<CodeFPLL<<std::endl;
12. printf("%g",precepteurS->ScodeNCO.CodeFPLL);
13. }
14. #endif
15. if(precepteurS->ScodeNCO.CodeIndexPrompt>=Const_LongueurCode)
16. precepteurS->ScodeNCO.CodeIndexPrompt -= Const_LongueurCode;
17. precepteurS->ScodeNCO.CodeIndexEarly = precepteurS-
>ScodeNCO.CodeIndexPrompt + Const_DistanceCorrelateur*Const_Rc_re;
18. if(precepteurS->ScodeNCO.CodeIndexEarly>=Const_LongueurCode)
86
19. precepteurS->ScodeNCO.CodeIndexEarly -= Const_LongueurCode;
20. precepteurS->ScodeNCO.CodeIndexLate = precepteurS-
>ScodeNCO.CodeIndexPrompt - Const_DistanceCorrelateur*Const_Rc_re;
21. if(precepteurS->ScodeNCO.CodeIndexLate < 0)
22. precepteurS->ScodeNCO.CodeIndexLate += Const_LongueurCode;
23. precepteurS->ScodeNCO.LocalCodeGenerator_CodeIndexEarly = precepteurS-
>ScodeNCO.CodeIndexEarly;
24. precepteurS->ScodeNCO.LocalCodeGenerator_CodeIndexPrompt =
25. precepteurS->ScodeNCO.CodeIndexPrompt;
26. precepteurS->ScodeNCO.LocalCodeGenerator_CodeIndexLate = precepteurS-
>ScodeNCO.CodeIndexLate;
27. precepteurS->ScodeNCO._VeFPLL = precepteurS-
>SfiltreFPLL.NCO_VeFPLL;
28. precepteurS->ScodeNCO._VeDLL = precepteurS-
>Scode_discriminateur.NCO_VeDLL;
29. FlocalCode(precepteurS);
30. return precepteurS;
31. }
32. #endif /* CODENCO_H_ */
“Constants.h”
1. #ifndef CONSTANTS_H_
2. #define CONSTANTS_H_
3. /******************************************************************/
4. /** Global Variables **/
5. /******************************************************************/
6. /*********************************************/
7. /** Constants **/
8. /*********************************************/
9. /** --------------- Files ----------------- **/
10. // Sortie des resultats vers fichiers texte
11. //#define OUTPUTFILE
12. // Enregistrement des sortie des correlateurs vers les fichiers "ReRxx.dat" et
13. "ImRxx.dat"
87
14. //#define RXXOUTPUTFILE
15. // Enregistrement des sortie des intégrateurs vers les fichiers "ReRxxInt.dat" et
16. "ImRxxInt.dat"
17. //#define RXXINTOUTPUTFILE
18. //#define DATAOUTPUTFILE
19. /** --------- Numerical Values ------------ **/
20. // Frequence de la sous-porteuse
21. // Fsc = Rca*n
22. static const int Const_n = 1;
23. // Frequence du code
24. // Fc = Const_Rca*m
25. static const int Const_m = 1;
26. #ifdef BPSK
27. #define Const_MultPorteuse Const_m
28. #else
29. #define Const_MultPorteuse Const_n
30. #endif
31. #define Const_Fe_re (4*2048000.0*Const_MultPorteuse)
32. #define Const_Periode_re (1.0/Const_Fe_re)
33. static const int Const_NbIntegrationMax = 20;
34. // Phase Lock Detector
35. static const double Const_K1 = 0.0247;
36. static const double Const_K2 = 1.5;
37. static const int Const_Lp = 50;
38. static const int Const_Lo = 240;
39. // BitSynchro (Spilker Vol1 page 395)
40. //static const int Const_NBS1 = 25;
41. //static const int Const_NBS2 = 10;
42. static const int Const_TailleFiltre = 4;
43. // Fréquence de la modulation
44. #define Const_f0 (1.5754*pow(10.0,9.0))
45. // Rythme de référence du code C/A (en chip par seconde)
46. static const double Const_Rca = 1023000.00;
88
47. // Taille des FFT de l'algo d'quisition
48. static const double TailleFFT = 4096.0;
49. // Filtres de boucles
50. //-------------------
51. // Bande de boucle:
52. // 21/07/2008 :
53. // La bande de boucle (1.0) a été adaptée pour le cas particulier oú on a également
54. enlevé
55. // la Doppler afin de travailler en bande de base. L'effet du Doppler se ressent
56. toujours
57. // sur le code mais plus sur la porteuse. La bande doit donc être 'relachée afin de
58. pouvoir
59. // suivre les variation sur le code sans l'aide de la porteuse.
60. // La valeur normale est 0.1
61. static const double Const_Bdll=1.0; // Bande de la DLL (en Hz)
62. static const double Const_a2 = 1.414;
63. static const double Const_a3 = 1.1;
64. static const double Const_b3 = 2.4;
65. // Constantes du récepteur
66. // Longueur du code
67. static const int Const_LongueurCode = 1023;
68. // Période en pico-secondes
69. #define Const_Periode_re_ps ((int)Const_Periode_re*pow(10.0,12.0))
70. #define Const_Periode_re_fs ((int)Const_Periode_re*pow(10.0,15.0))
71. // Générateur local du code
72. #define Const_Rc_em ((double)Const_m*Const_Rca/(Const_Fe_em))
73. #define Const_Rc_re ((double)Const_m*Const_Rca/(Const_Fe_re))
74. // Distance entre les correlateurs
75. //--------------------------------
76. // Exprimées en nombre de chip à la fréquence d'échantillonnage du recepteur
77. static const int Const_DistanceCorrelateur = 3;
78. #endif /* CONSTANTS_H_ */
89
“correlateurComplet.h”
1. #ifndef CORRELATEURCOMPLET_H_
2. #define CORRELATEURCOMPLET_H_
3. /** Correlateur Prompt **/
4. struct recepteur *FcorrelateurPrompt(struct recepteur *precepteurS){
5. precepteurS->Scorrelateur_prompt._I = precepteurS-
>Slocal_carrier_generator.Iout;
6. precepteurS->Scorrelateur_prompt._Q = precepteurS-
>Slocal_carrier_generator.Qout;
7. precepteurS->Scorrelateur_prompt.NCO_Calcul = 1;
8. // Lecture de l'indice des chips
9. precepteurS->Scorrelateur_prompt._CodeIndex_previous = precepteurS-
>Scorrelateur_prompt._CodeIndex;
10. precepteurS->Scorrelateur_prompt._CodeIndex = precepteurS-
>Scorrelateur_prompt.PromptI[0];
11. precepteurS->Scorrelateur_prompt._CodeLocalI = precepteurS-
>Scorrelateur_prompt.PromptI[1];
12. // Determination de la condition de reset des intégrateurs
13. if(precepteurS->Scorrelateur_prompt._CodeIndex == 0 && precepteurS-
>Scorrelateur_prompt._CodeIndex_previous !=0)
14. precepteurS->Scorrelateur_prompt.RazInt = 1;
15. else
16. precepteurS->Scorrelateur_prompt.RazInt = 0;
17. // Correlation
18. precepteurS->Scorrelateur_prompt.MultI = precepteurS-
>Scorrelateur_prompt._I*(double)(precepteurS-
>Scorrelateur_prompt._CodeLocalI);
19. precepteurS->Scorrelateur_prompt.MultQ = precepteurS-
>Scorrelateur_prompt._Q*(double)(precepteurS-
>Scorrelateur_prompt._CodeLocalI);
20. precepteurS->Sintegrator.RazIntP = precepteurS->Scorrelateur_prompt.RazInt;
21. if(precepteurS->Scorrelateur_prompt.RazInt == 1){
22. // Ecriture des correlateurs et reset de l'integrateur
90
23. precepteurS->Scorrelateur_prompt.PromptRxx[0] = (int)precepteurS-
>Scorrelateur_prompt.IndexData;
24. precepteurS->Scorrelateur_prompt.PromptRxx[1] = precepteurS-
>Scorrelateur_prompt.CumulReRxx;
25. precepteurS->Scorrelateur_prompt.CodeLock_Rxx[0] = (int)precepteurS-
>Scorrelateur_prompt.IndexData;
26. precepteurS->Scorrelateur_prompt.CodeLock_Rxx[1] = precepteurS-
>Scorrelateur_prompt.CumulReRxx;
27. precepteurS->Scorrelateur_prompt.SynchroBit_Rxx[0] = (int)precepteurS-
>Scorrelateur_prompt.IndexData;
28. precepteurS->Scorrelateur_prompt.SynchroBit_Rxx[1] = precepteurS-
>Scorrelateur_prompt.CumulReRxx;
29. precepteurS->Scorrelateur_prompt.DataDemodulation_Rxx[0] =
(int)precepteurS->Scorrelateur_prompt.IndexData;
30. precepteurS->Scorrelateur_prompt.DataDemodulation_Rxx[1] = precepteurS-
>Scorrelateur_prompt.CumulReRxx;
31. precepteurS->Scorrelateur_prompt.DataDemodulation_Rxx[2] = precepteurS-
>Scorrelateur_prompt.CumulImRxx;
32. precepteurS->Scorrelateur_prompt.CumulReRxx = precepteurS-
>Scorrelateur_prompt.MultI;
33. precepteurS->Scorrelateur_prompt.PromptRxx[2] = precepteurS-
>Scorrelateur_prompt.CumulImRxx;
34. precepteurS->Scorrelateur_prompt.CodeLock_Rxx[2] = precepteurS-
>Scorrelateur_prompt.CumulImRxx;
35. precepteurS->Scorrelateur_prompt.SynchroBit_Rxx[2] = precepteurS-
>Scorrelateur_prompt.CumulImRxx;
36. precepteurS->Scorrelateur_prompt.CumulImRxx = precepteurS-
>Scorrelateur_prompt.MultQ;
37. if(precepteurS->Scorrelateur_prompt.IndexData>=Const_NbIntegrationMax-1)
38. precepteurS->Scorrelateur_prompt.IndexData = 0;
39. else
40. precepteurS->Scorrelateur_prompt.IndexData += 1;
41. }
91
42. else{
43. // Integrate
44. precepteurS->Scorrelateur_prompt.CumulReRxx += precepteurS-
>Scorrelateur_prompt.MultI;
45. precepteurS->Scorrelateur_prompt.CumulImRxx += precepteurS-
>Scorrelateur_prompt.MultQ;
46. }
47. return precepteurS;
48. }
49. /** Correlateur Early **/
50. struct recepteur *FcorrelateurEarly(struct recepteur *precepteurS){
51. precepteurS->Scorrelateur_early._I = precepteurS-
>Slocal_carrier_generator.Iout;
52. precepteurS->Scorrelateur_early._Q = precepteurS-
>Slocal_carrier_generator.Qout;
53. precepteurS->Scorrelateur_early._CodeIndex_previous = precepteurS-
>Scorrelateur_early._CodeIndex;
54. precepteurS->Scorrelateur_early._CodeIndex = precepteurS-
>Scorrelateur_early.EarlyI[0];
55. precepteurS->Scorrelateur_early._CodeLocalI = precepteurS-
>Scorrelateur_early.EarlyI[1];
56. // Détermination de la condition de reset des intégrateurs
57. if(precepteurS->Scorrelateur_early._CodeIndex == 0 && precepteurS-
>Scorrelateur_early._CodeIndex_previous != 0)
58. precepteurS->Scorrelateur_early.RazInt = 1;
59. else
60. precepteurS->Scorrelateur_early.RazInt = 0;
61. // Correlation
62. precepteurS->Scorrelateur_early.MultI = precepteurS-
>Scorrelateur_early._I*precepteurS->Scorrelateur_early._CodeLocalI;
63. precepteurS->Scorrelateur_early.MultQ = precepteurS-
>Scorrelateur_early._Q*precepteurS->Scorrelateur_early._CodeLocalI;
64. if(precepteurS->Scorrelateur_early.RazInt == 1){
92
65. // Ecriture des correlateurs et reset de l'integrateur
66. precepteurS->Scorrelateur_early.EarlyRxx[0] = precepteurS-
>Scorrelateur_early.CumulReRxx;
67. precepteurS->Scorrelateur_early.CumulReRxx = precepteurS-
>Scorrelateur_early.MultI;
68. precepteurS->Scorrelateur_early.EarlyRxx[1] = precepteurS-
>Scorrelateur_early.CumulImRxx;
69. precepteurS->Scorrelateur_early.CumulImRxx = precepteurS-
>Scorrelateur_early.MultQ;
70. }
71. else{
72. // Integrate
73. precepteurS->Scorrelateur_early.CumulReRxx += precepteurS-
>Scorrelateur_early.MultI;
74. precepteurS->Scorrelateur_early.CumulImRxx += precepteurS-
>Scorrelateur_early.MultQ;
75. }
76. return precepteurS;
77. }
78. /** Correlateur Late **/
79. struct recepteur *FcorrelateurLate(struct recepteur *precepteurS){
80. precepteurS->Scorrelateur_late._I = precepteurS->Slocal_carrier_generator.Iout;
81. precepteurS->Scorrelateur_late._Q = precepteurS-
>Slocal_carrier_generator.Qout;
82. // Lecture de l'indice des chips
83. precepteurS->Scorrelateur_late._CodeIndex_previous = precepteurS-
>Scorrelateur_late._CodeIndex;
84. precepteurS->Scorrelateur_late._CodeIndex = precepteurS-
>Scorrelateur_late.LateI[0];
85. precepteurS->Scorrelateur_late._CodeLocalI = precepteurS-
>Scorrelateur_late.LateI[1];
86. // Détermination de la condition de reset des intégrateurs
87. if(precepteurS->Scorrelateur_late._CodeIndex == 0 && precepteurS-
93
>Scorrelateur_late._CodeIndex_previous != 0)
88. precepteurS->Scorrelateur_late.RazInt = 1;
89. else
90. precepteurS->Scorrelateur_late.RazInt = 0;
91. // Correlation
92. precepteurS->Scorrelateur_late.MultI = precepteurS-
>Scorrelateur_late._I*precepteurS->Scorrelateur_late._CodeLocalI;
93. precepteurS->Scorrelateur_late.MultQ = precepteurS-
>Scorrelateur_late._Q*precepteurS->Scorrelateur_late._CodeLocalI;
94. if(precepteurS->Scorrelateur_late.RazInt == 1){
95. // Ecriture des correlateurs et reset de l'integrateur
96. precepteurS->Scorrelateur_late.LateRxx[0] = precepteurS-
>Scorrelateur_late.CumulReRxx;
97. precepteurS->Scorrelateur_late.CumulReRxx = precepteurS-
>Scorrelateur_late.MultI;
98. precepteurS->Scorrelateur_late.LateRxx[1] = precepteurS-
>Scorrelateur_late.CumulImRxx;
99. precepteurS->Scorrelateur_late.CumulImRxx = precepteurS-
>Scorrelateur_late.MultQ;
100. }
101. else{
102. // Integrate
103. precepteurS->Scorrelateur_late.CumulReRxx += precepteurS-
>Scorrelateur_late.MultI;
104. precepteurS->Scorrelateur_late.CumulImRxx += precepteurS-
>Scorrelateur_late.MultQ;
105. }
106. return precepteurS;
107. }
108. /** --------------- Correlateur Complet ---------------- **/
109. struct recepteur *FcorrelateurComplet(struct recepteur *precepteurS){
110. /* Correlateur Prompt */
111. FcorrelateurPrompt(precepteurS);
94
112. /* Correlateur Early */
113. FcorrelateurEarly(precepteurS);
114. /* Correlateur Late */
115. FcorrelateurLate(precepteurS);
116. Fintegrator(precepteurS);
117. Fcodelock_detector(precepteurS);
118. return precepteurS;
119. }
120. #endif /* CORRELATEURCOMPLET_H_ */
“dataDemodulation.h”
1. #ifndef DATADEMODULATION_H_
2. #define DATADEMODULATION_H_
3. struct recepteur *FdataDemodulation(struct recepteur *precepteurS){
4. int i;
5. // Section 4.8 Expert Report
6. precepteurS->Sdata_demodulation._IndexData = (int)precepteurS-
>Scorrelateur_prompt.DataDemodulation_Rxx[0];
7. precepteurS->Sdata_demodulation._PromptReRxx = precepteurS-
>Scorrelateur_prompt.DataDemodulation_Rxx[1];
8. precepteurS->Sdata_demodulation._PromptImRxx = precepteurS-
>Scorrelateur_prompt.DataDemodulation_Rxx[2];
9. precepteurS->Sdata_demodulation._InstantSynchro = precepteurS-
>Sbitsynchro.DataDemodulation_InstantSynchro;
10. if (precepteurS->Sdata_demodulation._IndexData == precepteurS-
>Sdata_demodulation._InstantSynchro){
11. precepteurS->Sdata_demodulation.AccPromptRe = 0.0;
12. precepteurS->Sdata_demodulation.AccPromptIm = 0.0;
13. for (i=0; i<Const_NbIntegrationMax;i++){
14. precepteurS->Sdata_demodulation.AccPromptRe += precepteurS-
>Sdata_demodulation.TablePromptRe[i];
15. precepteurS->Sdata_demodulation.AccPromptIm += precepteurS-
>Sdata_demodulation.TablePromptIm[i];
16. }
95
17. if (precepteurS->Sdata_demodulation.AccPromptRe >= 0)
18. precepteurS->Sdata_demodulation._DataBit = 1;
19. else
20. precepteurS->Sdata_demodulation._DataBit = 0;
21. //_DataBit = -1;
22. #ifdef DATAOUTPUTFILE
23. send_data_int(precepteurS->Sdata_demodulation._DataBit);
24. send_data_double(precepteurS->Sdata_demodulation.AccPromptRe);
25. send_data_double(precepteurS->Sdata_demodulation.AccPromptIm);
26. #endif
27. #ifdef GENERATEUR_SYSTEMC
28. thread_data_recepteur->data_demodulation_struct->DataBit =
29. thread_data_recepteur->data_demodulation_struct-
>_DataBit;//DataBit.write(_DataBit);
30. #endif
31. }
32. precepteurS->Sdata_demodulation.TablePromptRe[precepteurS-
>Sdata_demodulation._IndexData] = precepteurS-
>Sdata_demodulation._PromptReRxx;
33. precepteurS->Sdata_demodulation.TablePromptIm[precepteurS-
>Sdata_demodulation._IndexData] = precepteurS-
>Sdata_demodulation._PromptImRxx;
34. return precepteurS;
35. }
36. #endif /* DATADEMODULATION_H_ */
“dopplerEstime.h”
1. #ifndef DOPPLERESTIME_H_
2. #define DOPPLERESTIME_H_
3. struct recepteur *FdopplerEstime(struct recepteur *precepteurS){
4. int i;
5. // Sections 4.4.3 and 4.4.4 Expert Report
6. precepteurS->Sdoppler_estime._VeFPLL = precepteurS-
>SfiltreFPLL.DopplerEstimator_VeFPLL;
96
7. precepteurS->Sdoppler_estime._VeDLL = precepteurS-
>Scode_discriminateur.DopplerEstimator_VeDLL;
8. // Estimation du Doppler par la phase
9. precepteurS->Sdoppler_estime.PhaseCorr = precepteurS-
>Sdoppler_estime.DopplerIni + precepteurS->Sdoppler_estime._VeFPLL;
10. precepteurS->Sdoppler_estime.DopplerPhase = precepteurS-
>Sdoppler_estime.PhaseCorr*Const_Fe_re/(2.0*M_PI);
11. #ifdef OUTPUTFILE
12. //fprintf(thread_data_recepteur->doppler_estime_struct-
>pFile1,"%g\n",thread_data_recepteur->doppler_estime_struct->DopplerPhase);
13. send_data_double(precepteurS->Sdoppler_estime.DopplerPhase);
14. #endif
15. precepteurS->estado[0] = 1.0;
16. if(precepteurS->Sdoppler_estime.DopplerPhase == 0.0){
17. precepteurS->data_exp[0] = 0.0;
18. precepteurS->data_base[0] = 0.0;
19. }
20. else{
21. precepteurS->data_exp[0] = floor(log10(fabs(precepteurS-
>Sdoppler_estime.DopplerPhase)));
22. precepteurS->data_base[0] = precepteurS-
>Sdoppler_estime.DopplerPhase/pow(10,precepteurS->data_exp[0]);
23. }
24. // Estimation du Doppler par le code
25. precepteurS->Sdoppler_estime.CodeFPLL =
Const_Rc_re/(2*M_PI*Const_f0)*(precepteurS->Sdoppler_estime.DopplerIni +
precepteurS->Sdoppler_estime._VeFPLL);
26. precepteurS->Sdoppler_estime.CodeNCO = precepteurS-
>Sdoppler_estime._VeDLL + precepteurS->Sdoppler_estime.CodeFPLL;
27. precepteurS->Sdoppler_estime.NChip_par_periode = precepteurS-
>Sdoppler_estime.CodeNCO + Const_Rc_re;
28. precepteurS->Sdoppler_estime.Fcode = precepteurS-
>Sdoppler_estime.NChip_par_periode * Const_Fe_re;
97
29. precepteurS->Sdoppler_estime.EstDopplerCode = Const_f0*(precepteurS-
>Sdoppler_estime.Fcode - Const_n*Const_Rca)/(Const_n*Const_Rca);
30. precepteurS->Sdoppler_estime.TabDoppler[precepteurS-
>Sdoppler_estime.IndexDoppler] = precepteurS-
>Sdoppler_estime.EstDopplerCode;
31. if (precepteurS->Sdoppler_estime.IndexDoppler>=99)
32. precepteurS->Sdoppler_estime.IndexDoppler = 0;
33. else
34. precepteurS->Sdoppler_estime.IndexDoppler += 1;
35. precepteurS->Sdoppler_estime.AccDoppler = 0.0;
36. for (i = 0; i <100; i++)
37. precepteurS->Sdoppler_estime.AccDoppler += precepteurS-
>Sdoppler_estime.TabDoppler[i];
38. precepteurS->Sdoppler_estime.DopplerCode = precepteurS-
>Sdoppler_estime.AccDoppler / 100.0;
39. #ifdef OUTPUTFILE
40. //fprintf(thread_data_recepteur->doppler_estime_struct-
>pFile2,"%g\n",thread_data_recepteur->doppler_estime_struct->DopplerCode);
41. send_data_double(precepteurS->Sdoppler_estime.DopplerCode);
42. #endif
43. precepteurS->estado[1] = 1.0;
44. if(precepteurS->Sdoppler_estime.DopplerCode == 0.0){
45. precepteurS->data_exp[1] = 0.0;
46. precepteurS->data_base[1] = 0.0;
47. }
48. else{
49. precepteurS->data_exp[1] = floor(log10(fabs(precepteurS-
>Sdoppler_estime.DopplerCode)));
50. precepteurS->data_base[1] = precepteurS-
>Sdoppler_estime.DopplerCode/pow(10,precepteurS->data_exp[1]);
51. }
52. return precepteurS;
53. }
98
54. #endif /* DOPPLERESTIME_H_ */
“falseLockDetector.h”
1. #ifndef FALSELOCKDETECTOR_H_
2. #define FALSELOCKDETECTOR_H_
3. /** FalseLock Detector 2 **/
4. struct recepteur *falseLock2(struct recepteur *precepteurS){
5. precepteurS->Sfalselock_detector._OptimisticPhaseLock = precepteurS-
>Scodelock_detector.FalseLockDetector_PhaseLock[0];
6. precepteurS->Sfalselock_detector._PessimisticPhaseLock = precepteurS-
>Scodelock_detector.FalseLockDetector_PhaseLock[1];
7. return precepteurS;
8. }
9. /** FalseLock Detector 3 **/
10. struct recepteur *falseLock3(struct recepteur *precepteurS){
11. precepteurS->Sfalselock_detector._EstimatedCN0 = precepteurS-
>Scodelock_detector.FalseLockDetector_EstimatedCN0;
12. return precepteurS;
13. }
14. /** FalseLock Detector 4 **/
15. struct recepteur *falseLock4(struct recepteur *precepteurS){
16. precepteurS->Sfalselock_detector._SynchroLock = precepteurS-
>Sbitsynchro.FalseLockDetector_SynchroLock[0];
17. precepteurS->Sfalselock_detector._FalseLock = precepteurS-
>Sbitsynchro.FalseLockDetector_SynchroLock[1];
18. return precepteurS;
19. }
20. /** FalseLock Detector 5 **/
21. struct recepteur *falseLock5(struct recepteur *precepteurS){
22. int i;
23. (precepteurS->Sfalselock_detector.Contador)++;
24. if ((precepteurS->Sfalselock_detector._SynchroLock == 1) || (precepteurS-
>Sfalselock_detector._FalseLock == 1) || (precepteurS-
>Sfalselock_detector._PessimisticPhaseLock == 1)){
99
25. if (precepteurS->Sfalselock_detector._EstimatedCN0<25.0){
26. // False Lock
27. precepteurS->Sfalselock_detector.AccVeDLL = 0.0;
28. for(i=0; i<200;i++)
29. precepteurS->Sfalselock_detector.AccVeDLL += precepteurS-
>Sfalselock_detector.TableVeDLL[i];
30. precepteurS->Sfalselock_detector.MoyVeDll = precepteurS-
>Sfalselock_detector.AccVeDLL/precepteurS-
>Sfalselock_detector.NbDataStock;
31. precepteurS->Sfalselock_detector.Ferr = precepteurS-
>Sfalselock_detector.MoyVeDll*Const_f0*Const_Fe_re/Const_Rca;
32. precepteurS->Sfalselock_detector.FreqCorr = precepteurS-
>Sfalselock_detector.Ferr;
33. }
34. }
35. return precepteurS;
36. }
37. /** FalseLock Detector 1 **/
38. struct recepteur *falseLock1(struct recepteur *precepteurS){
39. precepteurS->Sfalselock_detector._VeDLL = precepteurS-
>Scode_discriminateur.FalseLockDetector_VeDLL;
40. precepteurS->Sfalselock_detector.TableVeDLL[precepteurS-
>Sfalselock_detector.IndexTableVdll] = precepteurS-
>Sfalselock_detector._VeDLL;
41. if (precepteurS->Sfalselock_detector.IndexTableVdll<199){
42. (precepteurS->Sfalselock_detector.IndexTableVdll)++;
43. }
44. else
45. precepteurS->Sfalselock_detector.IndexTableVdll = 0;
46. if (precepteurS->Sfalselock_detector.NbDataStock < 200)
47. precepteurS->Sfalselock_detector.NbDataStock = precepteurS-
>Sfalselock_detector.NbDataStock + 1;
48. return precepteurS;
100
49. }
50. /** ----------------- Init False Lock Detector ----------------- **/
51. struct recepteur *FfalseLock(struct recepteur *precepteurS){
52. if(precepteurS->Sintegrator.DumpEnable == 1){
53. falseLock1(precepteurS);
54. falseLock2(precepteurS);
55. falseLock3(precepteurS);
56. falseLock4(precepteurS);
57. }
58. return precepteurS;
59. }
60. #endif /* FALSELOCKDETECTOR_H_ */
“filter.h”
1. #ifndef FILTER_H_
2. #define FILTER_H_
3. struct recepteur *Ffilter(struct recepteur *precepteurS){
4. int i;
5. precepteurS->Sreceiver_filter._I = precepteurS->Scanal.I_out;
6. precepteurS->Sreceiver_filter._Q = precepteurS->Scanal.Q_out;
7. for(i=9;i>=0;i--){
8. precepteurS->Sreceiver_filter.TabFilterRe[i+1] = precepteurS-
>Sreceiver_filter.TabFilterRe[i];
9. precepteurS->Sreceiver_filter.TabFilterIm[i+1] = precepteurS-
>Sreceiver_filter.TabFilterIm[i];
10. }
11. precepteurS->Sreceiver_filter.TabFilterRe[0] = precepteurS->Sreceiver_filter._I;
12. precepteurS->Sreceiver_filter.TabFilterIm[0] = precepteurS-
>Sreceiver_filter._Q;
13. precepteurS->Sreceiver_filter.AccFilterRe = 0.0;
14. precepteurS->Sreceiver_filter.AccFilterIm = 0.0;
15. for(i=0;i<11;i++){
16. precepteurS->Sreceiver_filter.AccFilterRe += precepteurS-
>Sreceiver_filter.TabFilterRe[i]*precepteurS->Sreceiver_filter.TabCoeff[i];
101
17. precepteurS->Sreceiver_filter.AccFilterIm += precepteurS-
>Sreceiver_filter.TabFilterIm[i]*precepteurS->Sreceiver_filter.TabCoeff[i];
18. }
19. precepteurS->Sreceiver_filter.I_out = precepteurS-
>Sreceiver_filter.AccFilterRe;
20. precepteurS->Sreceiver_filter.Q_out = precepteurS-
>Sreceiver_filter.AccFilterIm;
21. FlocalCarrierGenerator(precepteurS);
22. return precepteurS;
23. }
24. #endif /* FILTER_H_ */
“fpll.h”
1. #ifndef FPLL_H_
2. #define FPLL_H_
3. /** Carrier Discriminator **/
4. struct recepteur *FfreqDiscri(struct recepteur *precepteurS){
5. precepteurS->Scarrier_discriminator.PromptReRxx_Previous = precepteurS-
>Scarrier_discriminator.PromptReRxx_Now;
6. precepteurS->Scarrier_discriminator.PromptReRxx_Now = precepteurS-
>Sintegrator.FreqDiscri_PromptRxx[0];
7. precepteurS->Scarrier_discriminator.PromptImRxx_Previous = precepteurS-
>Scarrier_discriminator.PromptImRxx_Now;
8. precepteurS->Scarrier_discriminator.PromptImRxx_Now = precepteurS-
>Sintegrator.FreqDiscri_PromptRxx[1];
9. precepteurS->Scarrier_discriminator.Dot = precepteurS-
>Scarrier_discriminator.PromptReRxx_Previous*precepteurS-
>Scarrier_discriminator.PromptReRxx_Now + precepteurS-
>Scarrier_discriminator.PromptImRxx_Previous*precepteurS-
>Scarrier_discriminator.PromptImRxx_Now;
10. precepteurS->Scarrier_discriminator.Cross = precepteurS-
>Scarrier_discriminator.PromptReRxx_Previous*precepteurS-
>Scarrier_discriminator.PromptImRxx_Now - precepteurS-
>Scarrier_discriminator.PromptImRxx_Previous*precepteurS-
102
>Scarrier_discriminator.PromptReRxx_Now;
11. if (precepteurS->Scarrier_discriminator.Dot == 0.0)
12. precepteurS->Scarrier_discriminator._VeFLL = 0.0;
13. else
14. // Correction le 19/10/2007
15. precepteurS->Scarrier_discriminator._VeFLL = (atan(precepteurS-
>Scarrier_discriminator.Cross/precepteurS-
>Scarrier_discriminator.Dot))/((double)precepteurS->_NbIntegration/1000.0);
16. precepteurS->Scarrier_discriminator.ErreurFrequenceFLL = precepteurS-
>Scarrier_discriminator._VeFLL/(2.0*M_PI);
17. #ifdef OUTPUTFILE
18. //fprintf(thread_data_recepteur->carrier_discriminator_struct-
>pFile1,"%g\n",thread_data_recepteur->carrier_discriminator_struct-
>ErreurFrequenceFLL);//ErreurFrequence<<ErreurFrequenceFLL<<std::endl;
19. send_data_double(precepteurS->Scarrier_discriminator.ErreurFrequenceFLL);
20. #endif
21. precepteurS->Scarrier_discriminator.VeFLL = precepteurS-
>Scarrier_discriminator._VeFLL;
22. return precepteurS;
23. }
24. struct recepteur *FphaseDiscri(struct recepteur *precepteurS){
25. precepteurS->Scarrier_discriminator._PromptReRxx = precepteurS-
>Sintegrator.PhaseDiscri_PromptRxx[0];
26. precepteurS->Scarrier_discriminator._PromptImRxx = precepteurS-
>Sintegrator.PhaseDiscri_PromptRxx[1];
27. if (precepteurS->Scarrier_discriminator._PromptReRxx == 0.0)
28. precepteurS->Scarrier_discriminator._VePLL = 0.0;
29. else
30. // Test d'un discri trouvé dans GNSS_SDR 20/07/2008
31. // Code precdent
32. precepteurS->Scarrier_discriminator._VePLL = atan(precepteurS-
>Scarrier_discriminator._PromptImRxx/precepteurS-
>Scarrier_discriminator._PromptReRxx);
103
33. precepteurS->Scarrier_discriminator.VePLL = precepteurS-
>Scarrier_discriminator._VePLL;
34. #ifdef OUTPUTFILE
35. //fprintf(thread_data_recepteur->carrier_discriminator_struct-
>pFile2,"%g\n",thread_data_recepteur->carrier_discriminator_struct-
>_VePLL);//ErreurPhase<<_VePLL<<std::endl;
36. send_data_double(precepteurS->Scarrier_discriminator._VePLL);
37. #endif
38. return precepteurS;
39. }
40. /** Filtre FPLL **/
41. struct recepteur *FstateMacBandWidth(struct recepteur *precepteurS){
42. // Machine à état
43. precepteurS->SfiltreFPLL._OptimisticPhaseLock = precepteurS-
>Scodelock_detector.PhaseLock[0];
44. precepteurS->SfiltreFPLL._PessimisticPhaseLock = precepteurS-
>Scodelock_detector.PhaseLock[1];
45. if (precepteurS->SfiltreFPLL._OptimisticPhaseLock){
46. if (precepteurS->SfiltreFPLL._PessimisticPhaseLock){
47. if (precepteurS->SfiltreFPLL.Bfll>5.0){
48. //Bpll-=0.01;
49. precepteurS->SfiltreFPLL.Bfll-=0.01;
50. }
51. }
52. else{
53. precepteurS->SfiltreFPLL.Bpll=10.0;
54. precepteurS->SfiltreFPLL.Bfll=10.0;
55. }
56. }
57. else{
58. precepteurS->SfiltreFPLL.Bpll=18.0;
59. precepteurS->SfiltreFPLL.Bfll=18.0;
60. }
104
61. precepteurS->SfiltreFPLL.w0f = precepteurS->SfiltreFPLL.Bfll/0.53;//Section
4.3.3 Expert Report
62. precepteurS->SfiltreFPLL.GainFreqAcc = pow(precepteurS-
>SfiltreFPLL.w0f,2.0);
63. precepteurS->SfiltreFPLL.GainFreqVel = Const_a2*precepteurS-
>SfiltreFPLL.w0f;
64. precepteurS->SfiltreFPLL.w0p=precepteurS->SfiltreFPLL.Bpll/0.7845;
65. precepteurS->SfiltreFPLL.GainPhJit = pow(precepteurS->SfiltreFPLL.w0p,3.0);
66. precepteurS->SfiltreFPLL.GainPhAcc = Const_a3*pow(precepteurS-
>SfiltreFPLL.w0p,2.0);
67. precepteurS->SfiltreFPLL.GainPhVel = Const_b3*precepteurS-
>SfiltreFPLL.w0p;
68. precepteurS->SfiltreFPLL.GainAcc = 0.5;
69. precepteurS->SfiltreFPLL.GainVel = 0.5;
70. precepteurS->SfiltreFPLL.GainTint = precepteurS-
>_NbIntegration*Const_LongueurCode/(double)(Const_n*Const_Rca);
71. return precepteurS;
72. }
73. struct recepteur *FfiltreFPLL(struct recepteur *precepteurS){
74. precepteurS->SfiltreFPLL._VeFLL = precepteurS-
>Scarrier_discriminator.VeFLL;//Figure 4-11 Expert Report
75. precepteurS->SfiltreFPLL.f1 = precepteurS-
>SfiltreFPLL.GainFreqVel*precepteurS->SfiltreFPLL._VeFLL*precepteurS-
>SfiltreFPLL.FLL;
76. precepteurS->SfiltreFPLL.f2 = precepteurS-
>SfiltreFPLL.GainFreqAcc*precepteurS->SfiltreFPLL._VeFLL*precepteurS-
>SfiltreFPLL.FLL*precepteurS->SfiltreFPLL.GainTint;
77. //PLL
78. precepteurS->SfiltreFPLL._VePLL = precepteurS-
>Scarrier_discriminator.VePLL;
79. precepteurS->SfiltreFPLL.p1 = precepteurS-
>SfiltreFPLL.GainPhJit*precepteurS->SfiltreFPLL._VePLL*precepteurS-
>SfiltreFPLL.GainTint;
105
80. precepteurS->SfiltreFPLL.p2 = precepteurS-
>SfiltreFPLL.GainPhAcc*precepteurS->SfiltreFPLL._VePLL;
81. precepteurS->SfiltreFPLL.p3 = precepteurS-
>SfiltreFPLL.GainPhVel*precepteurS->SfiltreFPLL._VePLL;
82. precepteurS->SfiltreFPLL.fil1_previous = precepteurS->SfiltreFPLL.fil1;
83. precepteurS->SfiltreFPLL.fil1 = precepteurS->SfiltreFPLL.f2 + precepteurS-
>SfiltreFPLL.p1 + precepteurS->SfiltreFPLL.fil1_previous;
84. precepteurS->SfiltreFPLL.fil2 = precepteurS-
>SfiltreFPLL.GainAcc*(precepteurS->SfiltreFPLL.fil1 + precepteurS-
>SfiltreFPLL.fil1_previous);
85. precepteurS->SfiltreFPLL.fil3 = precepteurS-
>SfiltreFPLL.GainTint*(precepteurS->SfiltreFPLL.p2 + precepteurS-
>SfiltreFPLL.fil2 + precepteurS->SfiltreFPLL.f1);
86. precepteurS->SfiltreFPLL.fil4_previous = precepteurS->SfiltreFPLL.fil4;
87. precepteurS->SfiltreFPLL.fil4 = precepteurS->SfiltreFPLL.fil3 + precepteurS-
>SfiltreFPLL.fil4_previous;
88. precepteurS->SfiltreFPLL.fil5 = precepteurS-
>SfiltreFPLL.GainVel*(precepteurS->SfiltreFPLL.fil4 + precepteurS-
>SfiltreFPLL.fil4_previous);
89. precepteurS->SfiltreFPLL._VeFPLL = Const_Periode_re*(precepteurS-
>SfiltreFPLL.fil5 + precepteurS->SfiltreFPLL.p3);
90. precepteurS->SfiltreFPLL._FreqCorr = precepteurS-
>Sfalselock_detector.FreqCorr;
91. precepteurS->SfiltreFPLL.CorrVeFPLL =
92. 2.0*M_PI*Const_Periode_re*precepteurS->SfiltreFPLL._FreqCorr;
93. precepteurS->SfiltreFPLL._VeFPLL += precepteurS-
>SfiltreFPLL.CorrVeFPLL;
94. precepteurS->SfiltreFPLL.NCO_VeFPLL = precepteurS-
>SfiltreFPLL._VeFPLL;
95. precepteurS->SfiltreFPLL.LocalCarrierGenerator_VeFPLL = precepteurS-
>SfiltreFPLL._VeFPLL;
96. precepteurS->SfiltreFPLL.DopplerEstimator_VeFPLL = precepteurS-
>SfiltreFPLL._VeFPLL;
106
97. #ifdef OUTPUTFILE
98. //fprintf(thread_data_recepteur->filtreFPLL_struct-
>pFile1,"%g\n",thread_data_recepteur->filtreFPLL_struct-
>Bfll);//BfllFile<<Bfll<<std::endl;
99. send_data_double(precepteurS->SfiltreFPLL.Bfll);
100. //fprintf(thread_data_recepteur->filtreFPLL_struct-
>pFile2,"%g\n",thread_data_recepteur->filtreFPLL_struct->_VeFPLL);
101. send_data_double(precepteurS->SfiltreFPLL._VeFPLL);
102. #endif
103. return precepteurS;
104. }
105. /** Thread main **/
106. struct recepteur *Ffpll(struct recepteur *precepteurS){
107. FfreqDiscri(precepteurS);
108. FphaseDiscri(precepteurS);
109. FstateMacBandWidth(precepteurS);
110. FfiltreFPLL(precepteurS);
111. FdopplerEstime(precepteurS);
112. return precepteurS;
113. }
114. #endif /* FPLL_H_ */
“initRecepteur.h”
1. #ifndef INITRECEPTEUR_H_
2. #define INITRECEPTEUR_H_
3. /** ---------- Acquiring the parameters -------- **/
4. struct recepteur *acquisition_parameters(struct recepteur *precepteurS){
5. precepteurS->Sacquisition.NCO_DopplerEstime = precepteurS-
>Sreceive_data._DopplerEstime;
6. precepteurS->Sacquisition.LocalCarrierGenerator_DopplerEstime =
7. precepteurS->Sreceive_data._DopplerEstime;
8. precepteurS->Sacquisition.DopplerEstimator_DopplerEstime = precepteurS-
>Sreceive_data._DopplerEstime;
9. precepteurS->Sacquisition.DephasageEstime = precepteurS-
107
>Sreceive_data._DephasageEstime;
10. precepteurS->Sacquisition.PRN = precepteurS->Sreceive_data._PRN;
11. return precepteurS;
12. }
13. /** ------------ Creating the filter ------------ **/
14. struct recepteur *initFilter(struct recepteur *precepteurS){
15. float Coeff[]={0.0399,0.0498,-0.1127,-0.0136,0.3093,0.5277,0.3093,-0.0136,-
16. 0.1127,0.0498,0.0399};
17. int i;
18. // Lecture d'un ficher
19. for(i=0;i<11;i++)
20. precepteurS->Sreceiver_filter.TabCoeff[i] = Coeff[i];
21. for(i=0;i<11;i++){
22. precepteurS->Sreceiver_filter.TabFilterRe[i] = 0.0;
23. precepteurS->Sreceiver_filter.TabFilterIm[i] = 0.0;
24. }
25. precepteurS->Sreceiver_filter.Iprev = 0;
26. precepteurS->Sreceiver_filter.Qprev = 0;
27. return precepteurS;
28. }
29. /** ------- Init the Local Carrier Generator ------- **/
30. struct recepteur *initGene(struct recepteur *precepteurS){
31. precepteurS->Slocal_carrier_generator.AccPhaseCarrier = 0;
32. precepteurS->Slocal_carrier_generator._CarrierNCOCorr = 0;
33. precepteurS->Slocal_carrier_generator._VeFPLL = 0;
34. precepteurS->Slocal_carrier_generator.Iprev = 0.0;
35. precepteurS->Slocal_carrier_generator.Qprev = 0.0;
36. precepteurS->_NbIntegration = precepteurS->Sreceive_data._NbIntegration;
37. precepteurS->_CarrierPhiIni = 0.0;
38. precepteurS->Slocal_carrier_generator.DopplerIni =
2.0*M_PI*Const_Periode_re*precepteurS-
>Sacquisition.LocalCarrierGenerator_DopplerEstime;
39. return precepteurS;
108
40. }
41. /** ------------- Correlateur Complet ------------- **/
42. /** initialization of variables **/
43. struct recepteur *initCorrelateur(struct recepteur *precepteurS){
44. /* Correlateur Prompt */
45. precepteurS->Scorrelateur_prompt._CodeIndex_previous = 0;
46. precepteurS->Scorrelateur_prompt._CodeIndex = 0;
47. precepteurS->Scorrelateur_prompt.PromptI[0] = 0;
48. precepteurS->Scorrelateur_prompt.PromptI[1] = 0;
49. precepteurS->Scorrelateur_prompt.IndexData = 0;
50. precepteurS->Scorrelateur_prompt._CodeLocalI = 0;
51. precepteurS->Scorrelateur_prompt.CumulReRxx = 0;
52. precepteurS->Scorrelateur_prompt.CumulImRxx = 0;
53. precepteurS->Scorrelateur_prompt.RazInt = 0;
54. /* Correlateur Early */
55. precepteurS->Scorrelateur_early._CodeIndex_previous = 0;
56. precepteurS->Scorrelateur_early._CodeIndex = 0;
57. precepteurS->Scorrelateur_early.EarlyI[0] = 0;
58. precepteurS->Scorrelateur_early.EarlyI[1] = 0;
59. precepteurS->Scorrelateur_early._CodeLocalI = 0;
60. precepteurS->Scorrelateur_early.CumulReRxx = 0;
61. precepteurS->Scorrelateur_early.CumulImRxx = 0;
62. precepteurS->Scorrelateur_early.RazInt = 0;
63. /* Correlateur Late */
64. precepteurS->Scorrelateur_late._CodeIndex_previous = 0;
65. precepteurS->Scorrelateur_late._CodeIndex = 0;
66. precepteurS->Scorrelateur_late.LateI[0] = 0;
67. precepteurS->Scorrelateur_late.LateI[1] = 0;
68. precepteurS->Scorrelateur_late._CodeLocalI = 0;
69. precepteurS->Scorrelateur_late.CumulReRxx = 0;
70. precepteurS->Scorrelateur_late.CumulImRxx = 0;
71. precepteurS->Scorrelateur_late.RazInt = 0;
72. return precepteurS;
109
73. }
74. /** ----------- Init CodeLock Detector ---------- **/
75. struct recepteur *initCodeLockDetector(struct recepteur *precepteurS){
76. int j;
77. precepteurS->Scodelock_detector._InstantSynchro = 0;
78. for (j=0;j<20;j++)
79. {
80. precepteurS->Scodelock_detector.TabI[j] =0.0;
81. precepteurS->Scodelock_detector.TabQ[j] =0.0;
82. }
83. for (precepteurS->Scodelock_detector.k=0;precepteurS-
84. >Scodelock_detector.k<50;(precepteurS->Scodelock_detector.k)++)
85. {
86. precepteurS->Scodelock_detector.WBP[precepteurS->Scodelock_detector.k]
87. = 0.0;
88. precepteurS->Scodelock_detector.NBP[precepteurS->Scodelock_detector.k] =
89. 0.0;
90. //NBD[k] = 0.0;
91. precepteurS->Scodelock_detector.NP[precepteurS->Scodelock_detector.k] =
92. 0.0;
93. }
94. precepteurS->Scodelock_detector.AccWBP = 0.0;
95. precepteurS->Scodelock_detector.AccNBPI = 0.0;
96. precepteurS->Scodelock_detector.AccNBPQ = 0.0;
97. precepteurS->Scodelock_detector.AccNP = 0.0;
98. precepteurS->Scodelock_detector.NMoy = 0.0;
99. precepteurS->Scodelock_detector.k=0;
100. precepteurS->Scodelock_detector._OptimisticPhaseLock = 0;
101. precepteurS->Scodelock_detector._PessimisticPhaseLock = 0;
102. return precepteurS;
103. }
104. /** ------------ Init PhaseLock Detector ----------- **/
105. struct recepteur *initPhaseLockDetector(struct recepteur *precepteurS){
110
106. // Phase Lock detector
107. precepteurS->Scodelock_detector.LPFResultRe = 0.0;
108. precepteurS->Scodelock_detector.LPFResultIm = 0.0;
109. precepteurS->Scodelock_detector.Pcount[0] = 0;
110. precepteurS->Scodelock_detector.Pcount[1] = 0;
111. precepteurS->Scodelock_detector.Pcount[2] = 0;
112. precepteurS->Scodelock_detector._OptimisticPhaseLock = 0;
113. precepteurS->Scodelock_detector._PessimisticPhaseLock = 0;
114. return precepteurS;
115. }
116. /** ------------- Init Integrator ------------- **/
117. struct recepteur *initIntegrator(struct recepteur *precepteurS){
118. int i;
119. precepteurS->Sintegrator.CompteInt = 0;
120. precepteurS->Sintegrator.DumpEnable = 0;
121. precepteurS->Sintegrator._InstantSynchro = 0;
122. for (i=0; i<Const_NbIntegrationMax;i++)
123. {
124. precepteurS->Sintegrator.TablePromptRe[i] = 0.0;
125. precepteurS->Sintegrator.TablePromptIm[i] = 0.0;
126. precepteurS->Sintegrator.TableEarlyRe[i] = 0.0;
127. precepteurS->Sintegrator.TableEarlyIm[i] = 0.0;
128. precepteurS->Sintegrator.TableLateRe[i] = 0.0;
129. precepteurS->Sintegrator.TableLateIm[i] = 0.0;
130. }
131. precepteurS->Sintegrator.Integration = 1;
132. precepteurS->Sintegrator.InInter = 0;
133. precepteurS->Sintegrator.DebutIntegration = 0;
134. precepteurS->Sintegrator.FinIntegration = 4;
135. return precepteurS;
136. }
137. /** -------------- Init BitSynchro --------------- **/
138. struct recepteur *initBitSynchro(struct recepteur *precepteurS){
111
139. int i;
140. for(i=0;i<20;i++)
141. precepteurS->Sbitsynchro.AccBuffer[i] = 0;
142. precepteurS->Sbitsynchro.LockRecherche = 0;
143. precepteurS->Sbitsynchro.IndiceMax = 0;
144. precepteurS->Sbitsynchro._IndexData = 0;
145. precepteurS->Sbitsynchro.NbHits = 0;
146. precepteurS->Sbitsynchro.Synchro = 0;
147. precepteurS->Sbitsynchro.IndexBuffer = 0;
148. precepteurS->Sbitsynchro.IndiceMoyenne = 0;
149. precepteurS->Sbitsynchro.CodeLock_InstantSynchro = 0.0;
150. for(i=0;i<Const_TailleFiltre;i++)
151. precepteurS->Sbitsynchro.TabMoyenne[i] = 0;
152. for(i=0;i<20;i++){
153. precepteurS->Sbitsynchro.DataBufferRe[i] = 0.0;
154. precepteurS->Sbitsynchro.DataBufferIm[i] = 0.0;
155. }
156. return precepteurS;
157. }
158. /** --------- Init Code Discriminator --------- **/
159. struct recepteur *initCodeDiscriminator(struct recepteur *precepteurS){
160. precepteurS->Scode_discriminateur.Bdll = 1.0;
161. return precepteurS;
162. }
163. /** ------------- Init CarrierDiscriminator ------------- **/
164. struct recepteur *initDiscri(struct recepteur *precepteurS){
165. precepteurS->Scarrier_discriminator.PromptReRxx_Now = 0.0;
166. precepteurS->Scarrier_discriminator.PromptImRxx_Now = 0.0;
167. precepteurS->Scarrier_discriminator.Enable = 0;
168. return precepteurS;
169. }
170. /** ------------- Init False Lock Detector --------------- **/
171. struct recepteur *initFalseLockDetector(struct recepteur *precepteurS){
112
172. precepteurS->Sfalselock_detector.Ferr = 0.0;
173. for(precepteurS->Sfalselock_detector.IndexTableVdll=0; precepteurS-
>Sfalselock_detector.IndexTableVdll<200;(precepteurS-
>Sfalselock_detector.IndexTableVdll)++)
174. precepteurS->Sfalselock_detector.TableVeDLL[precepteurS-
>Sfalselock_detector.IndexTableVdll] = 0.0;
175. precepteurS->Sfalselock_detector.IndexTableVdll = 0;
176. precepteurS->Sfalselock_detector.Contador = 0;
177. return precepteurS;
178. }
179. /** ------------------ Init FiltreFPLL ------------------- **/
180. struct recepteur *initFiltreFPLL(struct recepteur *precepteurS){
181. /* Init Carrier Discriminator */
182. precepteurS->Scarrier_discriminator.PromptReRxx_Now = 0.0;
183. precepteurS->Scarrier_discriminator.PromptImRxx_Now = 0.0;
184. precepteurS->Scarrier_discriminator.Enable = 1;
185. /* Init filtre FPLL */
186. precepteurS->SfiltreFPLL._OptimisticPhaseLock = 0;
187. precepteurS->SfiltreFPLL._PessimisticPhaseLock = 0;
188. // FLL = 0.0 pour un filtre de PLL seul
189. // FLL = 1.0 pour un filtre FPLL
190. precepteurS->SfiltreFPLL.FLL = 1.0;
191. // Init des variables intermédiaires du filtre
192. precepteurS->SfiltreFPLL.f1 = 0;
193. precepteurS->SfiltreFPLL.f2 = 0;
194. precepteurS->SfiltreFPLL.p1 = 0;
195. precepteurS->SfiltreFPLL.p2 = 0;
196. precepteurS->SfiltreFPLL.p3 = 0;
197. precepteurS->SfiltreFPLL.fil1 = 0;
198. precepteurS->SfiltreFPLL.fil1_previous = 0;
199. precepteurS->SfiltreFPLL.fil2 = 0;
200. precepteurS->SfiltreFPLL.fil3 = 0;
201. precepteurS->SfiltreFPLL.fil4 = 0;
113
202. precepteurS->SfiltreFPLL.fil4_previous = 0;
203. precepteurS->SfiltreFPLL.fil5 = 0;
204. //Init des caractéristiques du filtre
205. precepteurS->SfiltreFPLL.Bpll=18.0;
206. precepteurS->SfiltreFPLL.Bfll=18.0;
207. precepteurS->SfiltreFPLL.w0f = precepteurS->SfiltreFPLL.Bfll/0.53;
208. precepteurS->SfiltreFPLL.GainFreqAcc = pow(precepteurS-
>SfiltreFPLL.w0f,2.0);
209. precepteurS->SfiltreFPLL.GainFreqVel = Const_a2*precepteurS-
>SfiltreFPLL.w0f;
210. precepteurS->SfiltreFPLL.w0p=precepteurS->SfiltreFPLL.Bpll/0.7845;
211. precepteurS->SfiltreFPLL.GainPhJit = pow(precepteurS->SfiltreFPLL.w0p,3.0);
212. precepteurS->SfiltreFPLL.GainPhAcc = Const_a3*pow(precepteurS-
>SfiltreFPLL.w0p,2.0);
213. precepteurS->SfiltreFPLL.GainPhVel = Const_b3*precepteurS-
>SfiltreFPLL.w0p;
214. precepteurS->SfiltreFPLL.GainAcc = 0.5;
215. precepteurS->SfiltreFPLL.GainVel = 0.5;
216. precepteurS->SfiltreFPLL._FreqCorr = 0.0;
217. return precepteurS;
218. }
219. /** ------------- Init Code NCO ------------- **/
220. struct recepteur *initCodeNCO(struct recepteur *precepteurS){
221. precepteurS->ScodeNCO._DopplerEstime = precepteurS-
>Sacquisition.NCO_DopplerEstime;
222. precepteurS->ScodeNCO._DephasageEstime = precepteurS-
>Sacquisition.DephasageEstime;
223. precepteurS->ScodeNCO._VeDLL = 0;
224. precepteurS->ScodeNCO._VeFPLL = 0;
225. precepteurS->ScodeNCO.DopplerIni =
2.0*M_PI*Const_Periode_re*precepteurS->ScodeNCO._DopplerEstime;
226. //CodeIndexPrompt = (2048.0-DephasageEstime)/2.0-5.0*Const_Rc_re;
227. precepteurS->ScodeNCO.CodeIndexPrompt = 2.0*Const_LongueurCode –
114
precepteurS->ScodeNCO._DephasageEstime*1023.0/TailleFFT-
5.0*Const_Rc_re;
228. //CodeIndexPrompt = (2048.0-750.0)/2.0-5.0*Const_Rc_re;
229. precepteurS->ScodeNCO._VeFPLL = 0;
230. precepteurS->ScodeNCO._VeDLL = 0;
231. precepteurS->SfiltreFPLL.NCO_VeFPLL = 0.0;
232. precepteurS->Scode_discriminateur.NCO_VeDLL = 0.0;
233. return precepteurS;
234. }
235. /** -------------- Init Local Code Generator -------------- **/
236. struct recepteur *initLocalCodeGenerator(struct recepteur *precepteurS){
237. code_gene_GPS(precepteurS);
238. precepteurS->Slocal_code_generator.ChipEarly = precepteurS-
>Slocal_code_generator.TabCode[0];
239. precepteurS->Slocal_code_generator._CodeIndexPrompt = 0;
240. precepteurS->Slocal_code_generator._CodeIndexEarly = 0;
241. precepteurS->Slocal_code_generator._CodeIndexLate = 0;
242. return precepteurS;
243. }
244. /** ---------------- Init Data Demodulation ---------------- **/
245. struct recepteur *initDataDemodulation(struct recepteur *precepteurS){
246. int i;
247. precepteurS->Sdata_demodulation._InstantSynchro = 0;
248. for (i=0; i<Const_NbIntegrationMax;i++){
249. precepteurS->Sdata_demodulation.TablePromptRe[i] = 0.0;
250. precepteurS->Sdata_demodulation.TablePromptIm[i] = 0.0;
251. }
252. return precepteurS;
253. }
254. /** ----------------- Init Doppler Estime ------------------- **/
255. struct recepteur *initDoppleEstime(struct recepteur *precepteurS){
256. int i;
257. for (i=0; i<100;i++)
115
258. precepteurS->Sdoppler_estime.TabDoppler[i] = 0.0;
259. precepteurS->Sdoppler_estime.IndexDoppler = 0;
260. precepteurS->Sdoppler_estime._VeFPLL = 0.0;
261. precepteurS->Sdoppler_estime._VeDLL = 0.0;
262. precepteurS->Sdoppler_estime._DopplerEstime = precepteurS-
>Sacquisition.DopplerEstimator_DopplerEstime;
263. precepteurS->Sdoppler_estime.DopplerIni =
2.0*M_PI*Const_Periode_re*precepteurS->Sdoppler_estime._DopplerEstime;
264. for(i=0; i<2; i++){
265. precepteurS->estado[i] = 0.0;
266. precepteurS->data_base[i] = 0.0;
267. precepteurS->data_exp[i] = 0.0;
268. }
269. return precepteurS;
270. }
271. #endif /* INITRECEPTEUR_H_ */
“integrator.h”
1. #ifndef INTEGRATOR_H_
2. #define INTEGRATOR_H_
3. struct recepteur *Fintegrator(struct recepteur *precepteurS){
4. int i;
5. //my_data->bitsynchro_struct->InstantSynchro = 0.0;
6. if(precepteurS->Sintegrator.RazIntP ==1){
7. precepteurS->Sintegrator._IndexData = (int)precepteurS-
>Scorrelateur_prompt.PromptRxx[0];
8. precepteurS->Sintegrator._PromptReRxx = precepteurS-
>Scorrelateur_prompt.PromptRxx[1];
9. precepteurS->Sintegrator._PromptImRxx = precepteurS-
>Scorrelateur_prompt.PromptRxx[2];
10. precepteurS->Sintegrator._EarlyReRxx = precepteurS-
>Scorrelateur_early.EarlyRxx[0];
11. precepteurS->Sintegrator._EarlyImRxx = precepteurS-
>Scorrelateur_early.EarlyRxx[1];
116
12. precepteurS->Sintegrator._LateReRxx = precepteurS-
>Scorrelateur_late.LateRxx[0];
13. precepteurS->Sintegrator._LateImRxx = precepteurS-
>Scorrelateur_late.LateRxx[1];
14. precepteurS->Sintegrator._NbIntegration = precepteurS->_NbIntegration;
15. precepteurS->Sintegrator._InstantSynchro = precepteurS-
>Sbitsynchro.InstantSynchro;
16. if(precepteurS->Sintegrator.Integration == 1){
17. if (precepteurS->Sintegrator.DebutIntegration == precepteurS-
>Sintegrator._IndexData){
18. precepteurS->Sintegrator.CompteInt = 0;
19. precepteurS->Sintegrator.DumpEnable = 1;
20. }
21. else{
22. precepteurS->Sintegrator.CompteInt += 1;
23. precepteurS->Sintegrator.DumpEnable = 0;
24. }
25. }
26. else{
27. precepteurS->Sintegrator.CompteInt = 0;
28. precepteurS->Sintegrator.DumpEnable = 0;
29. }
30. if (precepteurS->Sintegrator.DebutIntegration == precepteurS-
>Sintegrator._IndexData){
31. // Calcul de l'intervalle d'intégration
32. precepteurS->Sintegrator.NbSample = precepteurS-
>Sintegrator.DebutIntegration;
33. for (i=1; i<(precepteurS->Sintegrator._NbIntegration);i++){
34. precepteurS->Sintegrator.NbSample += 1;
35. if (precepteurS->Sintegrator.NbSample >= Const_NbIntegrationMax)
36. precepteurS->Sintegrator.NbSample -= Const_NbIntegrationMax;
37. precepteurS->Sintegrator.Intervalle[i] = precepteurS-
>Sintegrator.NbSample;
117
38. }
39. precepteurS->Sintegrator.FinIntegration = precepteurS-
>Sintegrator.Intervalle[precepteurS->Sintegrator._NbIntegration-1];
40. // Test de l'intervalle
41. for (i=1; i<(precepteurS->Sintegrator._NbIntegration);i++){
42. precepteurS->Sintegrator.InInter = 0;
43. if(precepteurS->Sintegrator.Intervalle[i] == precepteurS-
>Sintegrator._InstantSynchro){
44. precepteurS->Sintegrator.InInter = 1;
45. break;
46. }
47. }
48. if (precepteurS->Sintegrator.InInter == 1){
49. precepteurS->Sintegrator.Integration = 0;
50. precepteurS->Sintegrator.DebutIntegration = precepteurS-
>Sintegrator._InstantSynchro;
51. }
52. else{
53. precepteurS->Sintegrator.Integration = 1;
54. precepteurS->Sintegrator.DebutIntegration += precepteurS-
>Sintegrator._NbIntegration;
55. if(precepteurS-
>Sintegrator.DebutIntegration>=Const_NbIntegrationMax)
56. precepteurS->Sintegrator.DebutIntegration -= Const_NbIntegrationMax;
57. }
58. }
59. if (precepteurS->Sintegrator.DumpEnable == 1){
60. precepteurS->Sintegrator.AccPromptRe = 0.0;
61. precepteurS->Sintegrator.AccPromptIm = 0.0;
62. precepteurS->Sintegrator.AccEarlyRe = 0.0;
63. precepteurS->Sintegrator.AccEarlyIm = 0.0;
64. precepteurS->Sintegrator.AccLateRe = 0.0;
65. precepteurS->Sintegrator.AccLateIm = 0.0;
118
66. for (i=0; i<Const_NbIntegrationMax;i++){
67. precepteurS->Sintegrator.AccPromptRe += precepteurS-
>Sintegrator.TablePromptRe[i];
68. precepteurS->Sintegrator.AccPromptIm += precepteurS-
>Sintegrator.TablePromptIm[i];
69. precepteurS->Sintegrator.AccEarlyRe += precepteurS-
>Sintegrator.TableEarlyRe[i];
70. precepteurS->Sintegrator.AccEarlyIm += precepteurS-
>Sintegrator.TableEarlyIm[i];
71. precepteurS->Sintegrator.AccLateRe += precepteurS-
>Sintegrator.TableLateRe[i];
72. precepteurS->Sintegrator.AccLateIm += precepteurS-
>Sintegrator.TableLateIm[i];
73. }
74. precepteurS->Sintegrator.PromptRxxInt[0] = precepteurS-
>Sintegrator.AccPromptRe/precepteurS->Sintegrator._NbIntegration;
75. precepteurS->Sintegrator.PromptRxxInt[1] = precepteurS-
>Sintegrator.AccPromptIm/precepteurS->Sintegrator._NbIntegration;
76. precepteurS->Sintegrator.EarlyRxxInt[0] = precepteurS-
>Sintegrator.AccEarlyRe/precepteurS->Sintegrator._NbIntegration;
77. precepteurS->Sintegrator.EarlyRxxInt[1] = precepteurS-
>Sintegrator.AccEarlyIm/precepteurS->Sintegrator._NbIntegration;
78. precepteurS->Sintegrator.LateRxxInt[0] = precepteurS-
>Sintegrator.AccLateRe/precepteurS->Sintegrator._NbIntegration;
79. precepteurS->Sintegrator.LateRxxInt[1] = precepteurS-
>Sintegrator.AccLateIm/precepteurS->Sintegrator._NbIntegration;
80. precepteurS->Sintegrator.FreqDiscri_PromptRxx[0] = precepteurS-
>Sintegrator.AccPromptRe/precepteurS->Sintegrator._NbIntegration;
81. precepteurS->Sintegrator.FreqDiscri_PromptRxx[1] = precepteurS-
>Sintegrator.AccPromptIm/precepteurS->Sintegrator._NbIntegration;
82. precepteurS->Sintegrator.PhaseDiscri_PromptRxx[0] = precepteurS-
>Sintegrator.AccPromptRe/precepteurS->Sintegrator._NbIntegration;
83. precepteurS->Sintegrator.PhaseDiscri_PromptRxx[1] = precepteurS-
119
>Sintegrator.AccPromptIm/precepteurS->Sintegrator._NbIntegration;
84. #ifdef RXXINTOUTPUTFILE
85. //fprintf(thread_data_recepteur->integrator_struct-
>pFile3,"%g\n",thread_data_recepteur->integrator_struct-
>PromptRxxInt[0]);//ReRxxIntFile<<(AccPromptRe/NbIntegration)<<endl;
86. send_data_int(precepteurS->Sintegrator.PromptRxxInt[0]);
87. //fprintf(thread_data_recepteur->integrator_struct-
>pFile4,"%g\n",thread_data_recepteur->integrator_struct-
>PromptRxxInt[1]);//ImRxxIntFile<<(AccPromptIm/NbIntegration)<<endl;
88. send_data_int(precepteurS->Sintegrator.PromptRxxInt[1]);
89. #endif
90. }
91. #ifdef RXXOUTPUTFILE
92. //fprintf(thread_data_recepteur->integrator_struct-
>pFile1,"%g\n",thread_data_recepteur->integrator_struct-
>_PromptReRxx);//ReRxxFile<<_PromptReRxx<<std::endl;
93. send_data_double(precepteurS->Sintegrator._PromptReRxx);
94. //fprintf(thread_data_recepteur->integrator_struct-
>pFile2,"%g\n",thread_data_recepteur->integrator_struct-
>_PromptImRxx);//ImRxxFile<<_PromptImRxx<<std::endl;
95. send_data_double(precepteurS->Sintegrator._PromptImRxx);
96. #endif
97. precepteurS->Sintegrator.TablePromptRe[precepteurS-
>Sintegrator.CompteInt] = precepteurS->Sintegrator._PromptReRxx;
98. precepteurS->Sintegrator.TablePromptIm[precepteurS-
>Sintegrator.CompteInt] = precepteurS->Sintegrator._PromptImRxx;
99. precepteurS->Sintegrator.TableEarlyRe[precepteurS->Sintegrator.CompteInt]
= precepteurS->Sintegrator._EarlyReRxx;
100. precepteurS->Sintegrator.TableEarlyIm[precepteurS->Sintegrator.CompteInt]
= precepteurS->Sintegrator._EarlyImRxx;
101. precepteurS->Sintegrator.TableLateRe[precepteurS->Sintegrator.CompteInt]
= precepteurS->Sintegrator._LateReRxx;
102. precepteurS->Sintegrator.TableLateIm[precepteurS->Sintegrator.CompteInt]
120
= precepteurS->Sintegrator._LateImRxx;
103. Fcode_discriminator(precepteurS);
104. }
105. return precepteurS;
106. }
107. #endif /* INTEGRATOR_H_ */
“localCarrierGenerator.h”
1. #ifndef LOCALCARRIERGENERATOR_H_
2. #define LOCALCARRIERGENERATOR_H_
3. struct recepteur *FlocalCarrierGenerator(struct recepteur *precepteurS){
4. double I, Q;
5. I = precepteurS->Sreceiver_filter.I_out;
6. Q = precepteurS->Sreceiver_filter.Q_out;
7.
8. if(precepteurS->SfiltreFPLL._VeFPLL != 0)
9. precepteurS->Slocal_carrier_generator._VeFPLL = precepteurS-
>SfiltreFPLL._VeFPLL;
10. precepteurS->Slocal_carrier_generator._CarrierNCOCorr = precepteurS-
>Slocal_carrier_generator.DopplerIni + precepteurS-
>Slocal_carrier_generator._VeFPLL;
11. precepteurS->Slocal_carrier_generator.AccPhaseCarrier += precepteurS-
>Slocal_carrier_generator._CarrierNCOCorr;
12. precepteurS->Slocal_carrier_generator.CorrectionPhase = precepteurS-
>Slocal_carrier_generator.AccPhaseCarrier + precepteurS->_CarrierPhiIni;
13. precepteurS->Slocal_carrier_generator.CarrierCos = cos(precepteurS-
>Slocal_carrier_generator.CorrectionPhase);
14. precepteurS->Slocal_carrier_generator.CarrierSin = sin(precepteurS-
>Slocal_carrier_generator.CorrectionPhase);
15. precepteurS->Slocal_carrier_generator._Iout = I*(precepteurS-
>Slocal_carrier_generator.CarrierCos) +Q*(precepteurS-
>Slocal_carrier_generator.CarrierSin);
16. precepteurS->Slocal_carrier_generator._Qout = -I*(precepteurS-
>Slocal_carrier_generator.CarrierSin) + Q*(precepteurS-
121
>Slocal_carrier_generator.CarrierCos);
17. precepteurS->Slocal_carrier_generator.Iout = precepteurS-
>Slocal_carrier_generator._Iout;
18. precepteurS->Slocal_carrier_generator.Qout = precepteurS-
>Slocal_carrier_generator._Qout;
19. FcorrelateurComplet(precepteurS);
20. return precepteurS;
21. }
22. #endif /* LOCALCARRIERGENERATOR_H_ */
“localCodeGenerator.h”
1. #ifndef LOCALCODEGENERATOR_H_
2. #define LOCALCODEGENERATOR_H_
3. struct recepteur *FlocalCode(struct recepteur *precepteurS){
4. precepteurS->Slocal_code_generator._CodeIndexEarly = precepteurS-
>ScodeNCO.LocalCodeGenerator_CodeIndexEarly;
5. precepteurS->Slocal_code_generator._CodeIndexPrompt = precepteurS-
>ScodeNCO.LocalCodeGenerator_CodeIndexPrompt;
6. precepteurS->Slocal_code_generator._CodeIndexLate = precepteurS-
>ScodeNCO.LocalCodeGenerator_CodeIndexLate;
7. precepteurS->Scorrelateur_early.EarlyI[0] = precepteurS-
>Slocal_code_generator._CodeIndexPrompt;
8. precepteurS->Scorrelateur_early.EarlyI[1] = precepteurS-
>Slocal_code_generator.TabCode[precepteurS-
>Slocal_code_generator._CodeIndexEarly];
9. precepteurS->Slocal_code_generator.ChipEarly = precepteurS-
>Slocal_code_generator.TabCode[precepteurS-
>Slocal_code_generator._CodeIndexEarly];
10. precepteurS->Scorrelateur_prompt.PromptI[0] = precepteurS-
>Slocal_code_generator._CodeIndexPrompt;
11. precepteurS->Scorrelateur_prompt.PromptI[1] = precepteurS-
>Slocal_code_generator.TabCode[precepteurS-
>Slocal_code_generator._CodeIndexPrompt];
12. precepteurS->Slocal_code_generator.ChipPrompt = precepteurS-
122
>Slocal_code_generator.TabCode[precepteurS-
>Slocal_code_generator._CodeIndexPrompt];
13. precepteurS->Scorrelateur_late.LateI[0] = precepteurS-
>Slocal_code_generator._CodeIndexPrompt;
14. precepteurS->Scorrelateur_late.LateI[1] = precepteurS-
>Slocal_code_generator.TabCode[precepteurS-
>Slocal_code_generator._CodeIndexLate];
15. precepteurS->Slocal_code_generator.ChipLate = precepteurS-
>Slocal_code_generator.TabCode[precepteurS-
>Slocal_code_generator._CodeIndexLate];
16. return precepteurS;
17. }
18. #endif /* LOCALCODEGENERATOR_H_ */
“structures_recepteur.h”
1. #ifndef STRUCTURES_RECEPTEUR_H_
2. #define STRUCTURES_RECEPTEUR_H_
3. #include "Constants.h"
4. /** ------------------------------------------------- **/
5. /** ---------------- Receive data ---------------- **/
6. struct receive_data{
7. double _DopplerEstime, _DephasageEstime, _NbIntegration;
8. int _PRN;
9. double _Time_NS;
10. };
11. /** ---------------- Canal struct ---------------- **/
12. struct canal{
13. double I_out;
14. double Q_out;
15. };
16. /** ---------- Receiver filter struct ------------ **/
17. struct receiver_filter{
18. double I;
19. double Q;
123
20. double I_out;
21. double Q_out;
22. /* Variables internas */
23. double _I,_Q;
24. double AccFilterRe, AccFilterIm;
25. double Iprev, Qprev;
26. double TabCoeff[11], TabFilterRe[11], TabFilterIm[11];
27. };
28. /** ------------- Acquisition struct ------------- **/
29. struct acquisition{
30. double NCO_DopplerEstime;
31. double LocalCarrierGenerator_DopplerEstime;
32. double DopplerEstimator_DopplerEstime;
33. double DephasageEstime;
34. int PRN;
35. };
36. /** ------------Local Carrier Generator ---------- **/
37. struct local_carrier_generator{
38. double Iin, Qin;
39. double CarrierPhiIni;
40. double VeFPLL;
41. double Iout, Qout;
42. /* Variables internas */
43. double _VeFPLL;
44. double AccPhaseCarrier, CorrectionPhase;
45. double CarrierCos, CarrierSin;
46. double _Iout, _Qout;
47. double _CarrierNCOCorr;
48. double DopplerIni;
49. double _DopplerEstime;
50. double Iprev,Qprev;
51. double Iprev2,Qprev2;
52. };
124
53. /** ------------ Correlateur Complet ------------- **/
54. /** Correlateur Prompt **/
55. struct correlateur_prompt{
56. double I,Q;
57. int PromptI[2];//PromptI[0] = front
58. // Demande de calcul au NCO
59. int NCO_Calcul;//bool
60. // Canal vers l'integrateur
61. double PromptRxx[3];//PromptRxx[0] = front
62. // Canal vers le détecteur de Code Lock
63. double CodeLock_Rxx[3];//CodeLock_Rxx[0] = front
64. // Canal vers la synchro bit
65. double SynchroBit_Rxx[3];//SynchroBit_Rxx[0] = front
66. // Canal vers la démodulation des bits
67. double DataDemodulation_Rxx[3];//DataDemodulation_Rxx[0] = front
68. /* Variables internas */
69. int _CodeIndex, _CodeIndex_previous;
70. int IndexData;
71. double MultI, MultQ;
72. double _I, _Q;
73. double _CodeLocalI;
74. double CumulReRxx;
75. double CumulImRxx;
76. int RazInt;
77. };
78. /** Correlateur Early **/
79. struct correlateur_early{
80. double I,Q;
81. int EarlyI[2];// EarlyI[0] = front
82. double EarlyRxx[2];// EarlyRxx[0] = front
83. /* Variables internas */
84. int _CodeIndex, _CodeIndex_previous;
85. double MultI, MultQ;
125
86. double _I, _Q;
87. double _CodeLocalI;
88. double CumulReRxx;
89. double CumulImRxx;
90. int RazInt;
91. };
92. /** Correlateur Late **/
93. struct correlateur_late{
94. double I,Q;
95. int LateI[2];// LateI[0] = front
96. double LateRxx[2];// LateRxx[0] = front
97. /* Variables internas */
98. int _CodeIndex, _CodeIndex_previous;
99. double MultI, MultQ;
100. double _I, _Q;
101. double _CodeLocalI;
102. double CumulReRxx;
103. double CumulImRxx;
104. int RazInt;
105.
106. };
107. /** ------------- CodeLock Detector -------------- **/
108. struct codelock_detector{
109. double PromptRxxInt;
110. int InstantSynchro;
111. double C_N_estimated;
112. int CodeLock;// bool
113. int CodeDiscriLock[2];// bool
114. int PhaseLock[2];// bool
115. int FalseLockDetector_PhaseLock[2];// bool
116. double FalseLockDetector_EstimatedCN0;
117. /* Variables internas */
118. double WBP[50], NBP[50], NP[50];
126
119. double TabI[20], TabQ[20];//Const_NbIntegrationMax = 20
120. int InitInt;//bool
121. int _InstantSynchro;
122. double AccWBP, AccNBPI, AccNBPQ, AccNP;
123. double Fraction;
124. int j, k;
125. double NMoy;
126. // Phase Lock detector
127. double LPFResultRe;
128. double LPFResultIm;
129. int Pcount[3];
130. /* Más variables internas */
131. enum {Idle, WaitPhaseLock, WaitLockLoss} StateLock;
132. int _IndexData;
133. double _PromptReRxxInt, _PromptImRxxInt;
134. double AbsPromptReRxxInt,AbsPromptImRxxInt;
135. double LPFResultRe_previous, LPFinterRe, A;
136. double LPFResultIm_previous, LPFinterIm, B;
137. int _OptimisticPhaseLock, _PessimisticPhaseLock;//bool
138. double _C_N_estimated;
139. /* Más variables internas */
140. double _PromptReRxx, _PromptImRxx;
141. double _EarlyReRxx, _EarlyImRxx;
142. double _LateReRxx, _LateImRxx;
143. double AccPromptRe, AccPromptIm;
144. double AccEarlyRe, AccEarlyIm;
145. double AccLateRe, AccLateIm;
146. int _NbIntegration;
147. int NbSample;
148. };
149. /** ---------------- Integrator ------------------ **/
150. struct integrator{
151. double PromptRxx;
127
152. double EarlyRxx;
153. double LateRxx;
154. int NbIntegration;
155. int InstantSynchro;
156. double PromptRxxInt[2];
157. double EarlyRxxInt[2];
158. double LateRxxInt[2];
159. // Canal vs FPLL
160. double FreqDiscri_PromptRxx[2];
161. double PhaseDiscri_PromptRxx[2];
162. /* Variables internas */
163. double TablePromptRe[20], TablePromptIm[20];//Const_NbIntegrationMax = 20
164. double TableEarlyRe[20], TableEarlyIm[20];//Const_NbIntegrationMax = 20
165. double TableLateRe[20], TableLateIm[20];//Const_NbIntegrationMax = 20
166. int _IndexData;
167. int CompteInt, i;
168. int DumpEnable;// bool
169. int _InstantSynchro;
170. int Integration, InInter;// bool
171. int DebutIntegration, FinIntegration;
172. int Intervalle[20];//Const_NbIntegrationMax = 20
173. int RazIntP, RazIntE, RazIntL;
174. /* Más variables internas */
175. double _PromptReRxx, _PromptImRxx;
176. double _EarlyReRxx, _EarlyImRxx;
177. double _LateReRxx, _LateImRxx;
178. double AccPromptRe, AccPromptIm;
179. double AccEarlyRe, AccEarlyIm;
180. double AccLateRe, AccLateIm;
181. int _NbIntegration;
182. int NbSample;
183. };
184. /** ----------------- Bitsynchro ------------------**/
128
185. struct bitsynchro{
186. double PromptRxx;
187. int CodeLock;//bool
188. int InstantSynchro;
189. int DataDemodulation_InstantSynchro;
190. int CodeLock_InstantSynchro;
191. int FalseLockDetector_SynchroLock[2];//bool
192. /* Variables internas */
193. int _CodeLock;//bool
194. int Synchro, LockRecherche;//bool
195. int _InstantSynchro;
196. double Module;
197. double DataBufferRe[20];
198. double DataBufferIm[20];
199. int _IndexData;
200. double AccBuffer[20];
201. int IndiceMax, IndexBuffer;
202. int NbHits;
203. double IntegrationRe, IntegrationIm;
204. double IntegrationRe_previous, IntegrationIm_previous;
205. int TabMoyenne[4], IndiceMoyenne, AccMoyenne;
206. };
207. /** ------------- Code Discriminateur ------------- **/
208. struct code_discriminateur{
209. double PromptRxx;
210. double EarlyRxx;
211. double LateRxx;
212. int CodeDiscriLock;//bool
213. double NCO_VeDLL;
214. double DopplerEstimator_VeDLL;
215. double FalseLockDetector_VeDLL;
216. /* Variables internas */
217. double Bdll;
129
218. int _OptimisticPhaseLock, _PessimisticPhaseLock;//bool
219. double _PromptReRxxInt, _PromptImRxxInt;
220. double _EarlyReRxxInt, _EarlyImRxxInt;
221. double _LateReRxxInt, _LateImRxxInt;
222. #ifdef TEST2DISCRI
223. double Re_EmL, Im_EmL;
224. double ConjPromptImRxx;
225. double ReVeDLL, ImVeDLL;
226. double Power, Norm;
227. double ErrorPowerNormalized;
228. double CodeDoppler;
229. #endif
230. double E, L, EplusL, Discri, DiscriFiltre;
231. #ifdef TEST2DISCRI
232. FILE * pFile6;//std::ofstream VDLLFile2;
233. #endif
234. };
235. /** ------------- FalseLock Detector -------------- **/
236. struct falselock_detector{
237. int PhaseLock;//bool
238. int SynchroLock;//bool
239. double VeDLL;
240. double EstimatedCN0;
241. double FreqCorr;
242. /* Variables internas */
243. double TableVeDLL[200];
244. int NbDataStock;
245. double _EstimatedCN0;
246. int _SynchroLock, _FalseLock;//bool
247. int _OptimisticPhaseLock, _PessimisticPhaseLock;//bool
248. double _VeDLL;
249. int IndexTableVdll;
250. double AccVeDLL, MoyVeDll;
130
251. double Ferr;
252. int Contador;
253. };
254. /** ------------ Carrier Discriminator ------------ **/
255. struct carrier_discriminator{
256. double FreqDiscri_PromptRxx;
257. double PhaseDiscri_PromptRxx;
258. double VeFLL;
259. double VePLL;
260. /* Variables internas */
261. double _VeFLL;
262. double _VePLL;
263. double PromptReRxx_Previous, PromptReRxx_Now;
264. double PromptImRxx_Previous, PromptImRxx_Now;
265. double _PromptReRxx, _PromptImRxx;
266. double Dot, Cross;
267. double ErreurFrequenceFLL;
268. int Enable;// bool
269. };
270. /** ----------------- Filtre FPLL ----------------- **/
271. struct filtreFPLL{
272. int CodeLock;// bool
273. int PhaseLock;// bool
274. double FreqCorr;// bool
275. double NCO_VeFPLL;
276. double LocalCarrierGenerator_VeFPLL;
277. double DopplerEstimator_VeFPLL;
278. /* Variables internas */
279. int _OptimisticPhaseLock, _PessimisticPhaseLock;//bool
280. double f1, f2, p1, p2, p3;
281. double fil1, fil1_previous, fil2, fil3;
282. double fil4, fil4_previous, fil5;
283. double _VeFLL, _VePLL, _VeFPLL;
131
284. // Bande de boucle:
285. //double Bdll; // Bande de la DLL (en Hz)
286. double Bpll; // Bande de la PLL (en Hz)
287. double Bfll; // Bande de la FLL (en Hz)
288. // Calcul des paramètres de la FLL
289. // Filtre du 2ème ordre
290. double w0f;
291. double GainFreqAcc, GainFreqVel;
292. // Calcul des paramètres de la PLL
293. // Filtre du 3ème ordre
294. double w0p;
295. double GainPhJit, GainPhAcc, GainPhVel;
296. double GainAcc, GainVel;
297. double GainTint;
298. double FLL;
299. double _FreqCorr, CorrVeFPLL;
300. };
301. /** ------------------ Code NCO ------------------- **/
302. struct codeNCO{
303. int NCO_Calcul;//bool
304. double VeDLL;
305. double VeFPLL;
306. int LocalCodeGenerator_CodeIndexEarly;
307. int LocalCodeGenerator_CodeIndexPrompt;
308. int LocalCodeGenerator_CodeIndexLate;
309. double DopplerEstime;
310. double DephasageEstime;
311. /* Variables internas */
312. double _VeDLL, _VeFPLL;
313. double CodeIndexEarly, CodeIndexPrompt, CodeIndexLate;
314. double _DopplerEstime, _DephasageEstime;
315. double CodeFPLL, CodeNCO;
316. double DopplerIni;
132
317. double CodeFPLL_previous;
318. #ifdef MTI_SYSTEMC
319. double _Rc_re;
320. #endif
321. };
322. /** ------------ Local Code Generator --------------**/
323. struct local_code_generator{
324. /* Variables internas */
325. int ChipEarly, ChipPrompt, ChipLate;
326. int _CodeIndexPrompt, _CodeIndexEarly, _CodeIndexLate;
327. //int _PRN;
328. //char buffer[5];
329. //int i;
330. //char str[200];
331. int TabCode[1023];
332. //int Coeff;
333. };
334. /** ------------- Data Demodulation --------------- **/
335. struct data_demodulation{
336. int InstantSynchro;
337. double DataDemodulation_Rxx[3];
338.
339. #ifdef GENERATEUR
340. int DataBit;
341. #endif
342. /* Variables internas */
343. int _IndexData;
344. int _InstantSynchro;
345. double TablePromptRe[20],TablePromptIm[20] ;
346. double AccPromptRe, AccPromptIm;
347. int _DataBit;
348. double _PromptReRxx, _PromptImRxx;
349. };
133
350. /** --------------- Doppler Estime ---------------- **/
351. struct doppler_estime{
352. double VeFPLL;
353. double VeDLL;
354. double DopplerEstime;
355. double DopplerPhase, DopplerCode;
356. /* Variables internas */
357. double _VeDLL, _VeFPLL;
358. double TabDoppler[100];
359. int IndexDoppler;
360. double PhaseCorr;
361. double CodeFPLL, CodeNCO, NChip_par_periode, Fcode, EstDopplerCode;
362. double AccDoppler;
363. double DopplerIni;
364. double _DopplerEstime;
365. };
366. /****************************************************/
367. /** ---------------Recepteur Struct -------------- **/
368. /****************************************************/
369. struct recepteur{
370. //struct serial_conf Sserial_conf;
371. struct receive_data Sreceive_data;
372. struct canal Scanal;
373. struct receiver_filter Sreceiver_filter;
374. struct acquisition Sacquisition;
375. struct local_carrier_generator Slocal_carrier_generator;
376. struct correlateur_prompt Scorrelateur_prompt;
377. struct correlateur_early Scorrelateur_early;
378. struct correlateur_late Scorrelateur_late;
379. struct codelock_detector Scodelock_detector;
380. struct bitsynchro Sbitsynchro;
381. struct integrator Sintegrator;
382. struct data_demodulation Sdata_demodulation;
134
383. struct code_discriminateur Scode_discriminateur;
384. struct falselock_detector Sfalselock_detector;
385. struct carrier_discriminator Scarrier_discriminator;
386. struct filtreFPLL SfiltreFPLL;
387. struct codeNCO ScodeNCO;
388. struct local_code_generator Slocal_code_generator;
389. struct doppler_estime Sdoppler_estime;
390. int _NbIntegration;
391. double _CarrierPhiIni;
392. int clockGNSS;
393. double data_base[2];
394. double data_exp[2];
395. double estado[2];
396. };
397. struct recepteur recepteurS, *precepteurS;
398. #endif /* STRUCTURES_RECEPTEUR_H_ */
136
“main.c”
1. #include "gnss.h"
2. int main(int argc, char *argv[])
3. {
4. int i,j;
5. int n;
6. int index1,index2;
7. int xi;
8. int8_t a[2];
9. double yi_I,yi_Q;// in-phase and in-quadrature output
10. double interval;
11. // Noise addition
12. double time_ac;//actual time (seconds)
13. #ifdef NOISEADDITION
14. double time_si;
15. double C_N0dB;
16. double Pth;
17. double C;
18. double N0;
19. double rand1, rand2, randn;
20. #endif
21. printf("-------------------------------------------------------------------------------\n");
22. printf("| GPS L1 C/A Signal Generator |\n");
23. printf("-------------------------------------------------------------------------------\n");
24. /** -------------------- Pointers -------------------- **/
25. struct transmitter *ptransmitterS = &transmitterS;
26. ptransmitterS->pFile1 = fopen(NameParameters,"r");
27. #ifdef OUTPUTFILE
28. ptransmitterS->pFile2 = fopen(NameSignalFile,"wb");
29. ptransmitterS->pFile3 = fopen(NameSignalData,"w");
30. #endif
31. FreadFile(ptransmitterS);
32. for(i=0;i<n_satellites;i++){
137
33. codeGeneGPS(ptransmitterS,i);
34. }
35. /** Creation of the seed **/
36. srand(time(NULL));//variable seed
37. //srand(1);//fixed seed
38. /** Data generation **/
39. for(j=0;j<n_satellites;j++){
40. for(i=0;i<n_bits;i++){
41. ptransmitterS->Data[i][j] = 2*(rand()%2) - 1;
42. fprintf(ptransmitterS->pFile3,"%i ",ptransmitterS->Data[i][j]);
43. }
44. fprintf(ptransmitterS->pFile3,"\n");
45. }
46. n = n_bits*fs1*timeperbit;//number of samples
47. interval = fcode/fs1;//interval between samples
48. yi_I = 0;
49. yi_Q = 0;
50. #ifdef NOISEADDITION
51. time_si = timeperbit*n_bits;
52. #endif
53. for(j=0;j<n_satellites;j++)
54. ptransmitterS->Delay_samples[j] = (int)(ptransmitterS->Delay[j]*fs1);//
Convertion time to samples per time
55. /** Signal generation **/
56. for(i=0;i<n;i++){
57. for(j=0;j<n_satellites;j++)
58. if(i>=ptransmitterS->Delay_samples[j])
59. if(i<n-ptransmitterS->Delay_samples[j]){
60. xi = (int)floor((i-ptransmitterS->Delay_samples[j])*interval);
61. index1 = xi%n_code;
62. index2 = (int)floor((double)xi/(n_chipsperbit*n_code));
63. time_ac = i/fs1;
64. yi_I = yi_I + (double)(ptransmitterS->Gain[j]*ptransmitterS-
138
>Data[index2][j]*ptransmitterS-
>TabCode[index1][j]*cos(2*M_PI*(fi+ptransmitterS-
>Doppler[j])*time_ac));
65. yi_Q = yi_Q + (double)(ptransmitterS->Gain[j]*ptransmitterS-
>Data[index2][j]*ptransmitterS-
>TabCode[index1][j]*sin(2*M_PI*(fi+ptransmitterS-
>Doppler[j])*time_ac));
66. }
67. #ifdef NOISEADDITION
68. /** Noise addition **/
69. C_N0dB = ptransmitterS->CN_Start - (ptransmitterS->CN_Start-
ptransmitterS->CN_End)*i/(time_si*fs1);
70. C = 0.5;
71. N0 = C*pow(10.0,-C_N0dB/10.0);
72. Pth = sqrt(fs1*N0);
73. /** For in-phase signal **/
74. rand1 = (double)rand()/(double)RAND_MAX;
75. if(rand1 == 0.0)
76. rand1 = 0.000001;
77. rand2 = (double)rand()/(double)RAND_MAX;
78. if(rand2 == 0.0)
79. rand2 = 0.000001;
80. /* Normal Distribution */
81. randn = sqrt(-2*log(rand1))*cos(2*M_PI*rand2);
82. yi_I = yi_I + (double)Pth*randn;
83. /** For in-quadrature signal **/
84. rand1 = (double)rand()/(double)RAND_MAX;
85. if(rand1 == 0.0)
86. rand1 = 0.000001;
87. rand2 = (double)rand()/(double)RAND_MAX;
88. if(rand2 == 0.0)
89. rand2 = 0.000001;
90. /* Normal Distribution */
139
91. randn = sqrt(-2*log(rand1))*cos(2*M_PI*rand2);
92. yi_Q = yi_Q + (double)Pth*randn;
93. #endif
94. /** Save the signal into a Bin file as int8 **/
95. #ifdef OUTPUTFILE
96. a[0] = (int8_t)(quantization*yi_I);
97. a[1] = (int8_t)(quantization*yi_Q);
98. fwrite(a,1,sizeof(a),ptransmitterS->pFile2);
99. #endif
100. yi_I = 0;
101. yi_Q = 0;
102. }
103. return 0;
104. }
“codeGeneGPS.c”
1. #include "codeGeneGPS.h"
2. void ones(int *t,int n){
3. int i;
4. for(i=0;i<n;i++)
5. *(t+i)=1;
6. }
7. int xor(int a,int b){
8. if(a==b)
9. return 0;
10. else
11. return 1;
12. }
13. void codeGeneGPS(struct transmitter *ptransmitterS, int num){
14. int CoupleSV[32][2]={{2,6},{3,7},{4,8},{5,9},{1,9},{2,10},{1,8},{2,9},{3,10},
{2,3},{3,4},{5,6},{6,7},{7,8},{8,9},{9,10},{1,4},{2,5},{3,6},{4,7},{5,8},{6,9},
{1,3},{4,6},{5,7},{6,8},{7,9},{8,10},{1,6},{2,7},{3,8},{4,9}};
15. int vecteur[10];
16. int *t = &vecteur[0];
140
17. int codeG1[1023];
18. int *t1 = &codeG1[0];
19. int codeG2[1023];
20. int *t2 = &codeG2[0];
21. int dec;
22. int i,j;
23. int temp,temp1;
24. int SV = ptransmitterS->PRN[num];
25. /* Generation of code G1*/
26. ones(t,10);
27. for(i=0;i<1023;i++){
28. *(t1+i)=*(t+9);
29. for(j=0;j<10;j++){
30. if(j==0){
31. temp = *t;
32. *t=xor(*(t+2),*(t+9));
33. }
34. else{
35. temp1 = *(t+j);
36. *(t+j) = temp;
37. temp = temp1;
38. }
39. }
40. }
41. /* Generation of code G2 */
42. ones(t,10);
43. for(i=0;i<1023;i++){
44. *(t2+i)=xor(*(t+(int)CoupleSV[SV-1][0]-1),*(t+(int)CoupleSV[SV-1][1]-1));
45. dec = xor(xor(xor(*(t+1),*(t+2)), xor(*(t+5),*(t+7))), xor(*(t+8),*(t+9)));
46. for(j=0;j<10;j++){
47. if(j==0){
48. temp = *t;
49. *t=dec;
141
50. }
51. else{
52. temp1 = *(t+j);
53. *(t+j) = temp;
54. temp = temp1;
55. }
56. }
57. }
58. /* Generation of code GPS */
59. for(i=0;i<1023;i++){
60. ptransmitterS->TabCode[i][num]=2*xor(*(t1+i),*(t2+i))-1;
61. }
62. }
“codeGeneGPS.h”
1. /** codeGeneGPS.c
2. * Author: Jean León
3. * Date: Nov 8, 2012
4. * Description:
5. * This function generates the PRN code for GPS.
6. * This function was extracted from Kaplan p.129.
7. **/
8. #include "gnss.h"
9. void codeGeneGPS(struct transmitter *ptransmitterS, int num);
“constants.h”
1. #include <math.h>
2. #define OUTPUTFILE
3. #define NOISEADDITION
4. #ifdef OUTPUTFILE
5. static const char *NameParameters = "Parameters.txt";
6. static const char *NameSignalFile = "Result/Result.bin";//SignalGNSS_SDR.bin";
7. static const char *NameSignalData = "Result/DataGenerated.txt";
8. #endif
9. /** --------- Numerical Values ------------ **/
142
10. #define fcode ((double)1.023*pow(10,6))// F_CAcode = 1.023 MHz
11. #define fs ((double)1540*10.23*pow(10,6))// fs = 10*(154*10.23MHz)
12. #define fs1 ((double)20*pow(10,6))// Fs = 20 MHz
13. #define fi ((double)5.02*pow(10,6))// IF = 5.02 MHz
14. #define timeperbit ((double)20*pow(10,-3))// time per bit = 20 ms
15. #define n_chipsperbit 20 // chips per bit = 20
16. //static const int n_code = 1023;// size of PRN code = 1023
17. #define n_samplespercode 15400// samples per code
18. #define n_bits 10
19. #define n_satellites 7
20. #define n_code 1023
21. #define quantization ((double)(127/32))
“gnss.h”
1. /** gnss.h
2. * GPS L1 C/A generator v1.0
3. * Author: Jean León
4. * Date: Nov 28, 2012
5. * Description:
6. * This file contains all the basic libraries and headers to be used in this program.
7. **/
8. #include <time.h>
9. #include <stdio.h>
10. #include <stdlib.h>
11. #include <math.h>
12. #include <string.h>
13. #include <sys/stat.h>
14. #include <stdint.h>
15. #include "constants.h"
16. #include "structures.h"
“readFile.c”
1. /** readFile.c
2. * GPS L1 C/A generator v1.0
3. * Author: Jean León
143
4. * Date: Nov 28, 2012
5. * Description:
6. * This function reads a Txt file (Parameters.txt) which contains all the parameters
to generate the signal.
7. **/
8. #include "readFile.h"
9. void FreadFile(struct transmitter *ptransmitterS){
10. int i;
11. fscanf(ptransmitterS->pFile1,"%lf",&(ptransmitterS->CN_Start));
12. fscanf(ptransmitterS->pFile1,"%lf",&(ptransmitterS->CN_End));
13. printf("CN_start: %lf CN_end: %lf\n",ptransmitterS->CN_Start,ptransmitterS-
>CN_End);
14. for(i=0;i<n_satellites;i++){
15. fscanf(ptransmitterS->pFile1,"%i",&(ptransmitterS->PRN[i]));
16. fscanf(ptransmitterS->pFile1,"%lf",&(ptransmitterS->Delay[i]));
17. fscanf(ptransmitterS->pFile1,"%lf",&(ptransmitterS->Doppler[i]));
18. fscanf(ptransmitterS->pFile1,"%lf",&(ptransmitterS->Gain[i]));
19. printf("PRN: %i Delay: %lf Doppler: %lf Gain: %lf\n",ptransmitterS-
>PRN[i],ptransmitterS->Delay[i],ptransmitterS->Doppler[i],ptransmitterS-
>Gain[i]);
20. }
21. }
“readFile.h”
1. /** readFile.h
2. * GPS L1 C/A generator v1.0
3. * Author: Jean León
4. * Date: Nov 28, 2012
5. * Description:
6. * This function reads a Txt file (Parameters.txt) which contains all the parameters
to generate the signal.
7. **/
8. #include "gnss.h"
9. void FreadFile(struct transmitter *ptransmitterS);
144
“structures.h”
1. struct transmitter{
2. /* Input variables */
3. //int n_bits;
4. int PRN[n_satellites];
5. double Doppler[n_satellites];
6. double Delay[n_satellites];
7. double Gain[n_satellites];
8. double CN_Start;
9. double CN_End;
10. int TabCode[n_code][n_satellites];
11. int Time_NS;
12. int Data[n_bits][n_satellites];
13. int Delay_samples[n_satellites];
14. FILE *pFile1;
15. FILE *pFile2;
16. FILE *pFile3;
17. };
18. struct transmitter transmitterS;
146
“main.c”
1. /*
2. * File: main.c
3. * Author: Jean León
4. * Description: This program sends the signal file to the LEON Processor by serial
port.
5. */
6. #define __LINUX_COM__ // If you are using a Linux distribution
7. // #define __WINDOWS_COM__ // In case of you are using a Windows
distribution
8. #include "com/serial.h"
9. #include <stdlib.h>
10. #include <string.h>
11. #include <math.h>
12. #include "send_data.h"
13. static const char *NameSignalFile = "Result.bin";// Path of the signal file
14. static const char *NameEstimatedDopplerFile = "Results/EstimatedDoppler.dat";//
15. Output file of the results
16. static const char *NameEstimatedDopplerCodeFile =
17. "Results/EstimatedDopplerCode.dat";// Output file of the results
18. int main(){
19. HANDLE fd;
20. FILE *SignalFile;
21. char _TabSigChar[10000];
22. int IncChar;
23. FILE *pFile[2];
24. /* Values obtained in the acquisition phase */
25. double dopplerEstime;
26. double dephasageEstime;
27. double nbIntegration;
28. double prn;
29. double timeNS; // Simulation time (ns)
30. double temp;
147
31. double data_received;
32. int i;
33. int j;
34. int samples;
35. IncChar = 0;
36. fd=Open_Port("/dev/ttyUSB0");// Open the serial port
37. // In case of Windows: fd=Open_Port("COMX");
38. // where X could be 1,2,3,..
39. Configure_Port(fd,B38400,"8N1"); // Setting the serial port.
40. Set_Hands_Haking(fd,2); // Setting the control flow (optional)
41. /* Open the signal file */
42. SignalFile =fopen(NameSignalFile, "rb");
43. /* Open Doppler Estime file*/
44. pFile[0] = fopen(NameEstimatedDopplerFile, "w");
45. /* Open Doppler code file*/
46. pFile[1] = fopen(NameEstimatedDopplerCodeFile,"w");
47. if(SignalFile == NULL){
48. printf("Canal.c : Ficher Signal %s not found\n",NameSignalFile);
49. exit(0);
50. }
51. else
52. printf("Canal.c : Ficher Signal %s opened\n",NameSignalFile);
53. /** Starting sending the initial values **/
54. /** Doppler Estime **/
55. dopplerEstime = 156.25;
56. dato_recibido = Fsend_data(fd,dopplerEstime,0);
57. printf("Doppler Estime: %lf\n",dato_recibido);
58. /** Dephasage Estime **/
59. dephasageEstime = 1205;
60. dato_recibido = Fsend_data(fd,dephasageEstime,1);
61. printf("Dephasage Estime: %lf\n",dato_recibido);
62. /** Nb Integration **/
63. nbIntegration = 1.0;
148
64. dato_recibido = Fsend_data(fd,nbIntegration,1);
65. printf("Nb Integration: %lf\n",dato_recibido);
66. /** PRN **/
67. prn = 9.0;
68. dato_recibido = Fsend_data(fd,prn,1);
69. printf("PRN: %lf\n",dato_recibido);
70. /** Time ns **/
71. timeNS = 10000000.0;
72. dato_recibido = Fsend_data(fd,timeNS,1);
73. printf("Time(ns): %lf\n",dato_recibido);
74. samples = (int)timeNS/122.05;
75. printf("\n");
76. printf("************** Starting transmission ****************\n");
77. printf("\n");
78. for(j=0;j<samples;j++){
79. if(IncChar == 0){
80. fread(_TabSigChar,10000,1,SignalFile);
81. }
82. temp=(double)_TabSigChar[IncChar++];
83. data_received = Fsend_data(fd,temp,1); // Sends the I component of the signal
84. //printf("I: %lf ",data_received);
85. temp=(double)_TabSigChar[IncChar++]; // Sends the Q component of the
signal
86. data_received = Fsend_data(fd,temp,1);
87. //printf("Q: %lf\n",data_received);
88. printf(" <-Samples \r %d",j+1);
89. for(i=0;i<2;i++){
90. temp = 1.111;
91. dato_recibido = Fsend_data(fd,temp,1);
92. if(dato_recibido == temp)
93. dato_recibido = 0.0;
94. else
95. fprintf(pFile[i],"%g\n",data_received);// Save the data in the indicated file
149
96. }
97. if(IncChar >= 10000)
98. IncChar = 0;
99. }
100. Close_Port(fd); // Close the serial port
101. return 0;
102. }
“send_data.h”
1. /*
2. * File: send_data.h
3. * Author: Jean León
4. * Description: This program reads and write data to the serial port.
5. * For only test the program, the data is sent using scientifc notation, but
could be send in other way.
6. * For the first value to be sent, Gets_Port is only used once, but Gets_Port
must be used twice for the next transmissions.
7. */
8. double Fsend_data(HANDLE fd, double num, int indice){
9. double exp;
10. double base;
11. char data_base[12];
12. char data_exp[12];
13. char cad2_base[13];
14. char cad2_exp[13];
15. if(num == 0.0){
16. exp = 0.0;
17. base = 0.0;
18. }
19. else{
20. exp = floor(log10(fabs(num)));
21. base = num/pow(10,exp);;
22. }
23. sprintf(data_base,"%+12.9lf\r",base);// send the base of the data
150
24. Write_Port(fd,data_base,13);// Escritura en el puerto serie.
25. if(indice == 1){
26. while(Kbhit_Port(fd)<13);
27. Gets_Port(fd,cad2_base,13);// Reads the serial port
28. }
29. while(Kbhit_Port(fd)<13);
30. Gets_Port(fd,cad2_base,13);//
31. sprintf(data_exp,"%+12.8lf\r",exp);// Send the exponent of the data
32. Write_Port(fd,data_exp,13);
33. while(Kbhit_Port(fd)<13);
34. Gets_Port(fd,cad2_exp,13);// Reads the serial port
35. while(Kbhit_Port(fd)<13);
36. Gets_Port(fd,cad2_exp,13);// Reads the serial port
37. //printf("Data received: %f*10^(%f)\n",atof(cad2_base),atof(cad2_exp));
38. return atof(cad2_base)*pow(10,atof(cad2_exp));
39. }
BIBLIOGRAFÍA
[1] C. Wang y G. Lachapelle, «GPS Attitude Determination Reliability Performance
Improvement Using Low cost Receivers,» Journal of Global Positioning Systems, pp.
85-95, 2002.
[2] F. Bauer, K. Hartman y E. G. Lightsey, «Spaceborne GPS Current Status and Future
Visions,» de 1998 IEEE Aerospace Conference, Snowmass, 1998.
[3] E. G. Lightsey, «Development and Flight Demonstration of a GPS Receiver for
Space,» UMI, Ann Arbor, 1997.
[4] E. Comission, «European GNSS (Galileo) Open Service: Signal in Space: Interface
Control Document,» Office of the European Union, 2010.
[5] S. Hongwei, L. Zhigang y P. Feng, «Development of Satellite Navigation in China,»
de IEEE International Frequency Control Symposium, 2007 Joint with the 21st
European Frequency and Time Forum, Geneva, 2007.
[6] P. Tortora, «A GPS based attitude determination algorithm for the spin-stabilized
microsatellite UNISAT,» Acta Astronautica, vol. 47, nº 2-9, pp. 139-146, 2000.
[7] A. S. &. T. (AST), «Andrews Technical Services,» Andrews Space & Technology
(AST), 2001. [En línea]. Available: http://www.spaceandtech.com. [Último acceso: 3
Mayo 2013].
[8] B. Fraser, C. Russell, J. Means, F. Menk y C. Waters, «FedSat - An Australian
research microsatellite,» Advances in Space Research, vol. 25, nº 7-8, pp. 1325-1336,
2000.
[9] H. Zhang y M. Unwin, «The Use of GPS Receiver on Tsinghua-1 Microsatellite,» de
Proceedings of the International Symposium on Digital Earth, Beijing, 1999.
[10] M. Grondin, M. Belasic, L. Ries, J.-L. Issler, P. Bataille, L. Jobey y G. Richard, «A
New Operational Low cost GNSS Software Receiver for Microsatellites,» de 2010 5th
ESA Workshop on Satellite Navigation Technologies and European Workshop on
152
GNSS Signals and Signal Processing (NAVITEC), Noordwijk, 2010.
[11] Y. Feng, «Combined Galileo and GPS: A Technical Perspective,» Journal of Global
Positioning Systems, vol. 2, nº 1, pp. 67-72, 2003.
[12] D. Devly y S. Cobb, GNSS for Vehicle Control, Norwood: Artech House, 2010.
[13] P. Groves, Principles of GNSS, Inertial, and Multisensor Integrated Navigation
Systems, Artech House, 2008.
[14] M. Braasch y A. Van Dierendock, «GPS Receiver Architectures and Measurements,»
Proceedings of the IEEE, vol. 87, nº 1, pp. 48-64, 1999.
[15] E. Kaplan y C. Hergarty, Understanding GPS: Principles and Applications, Norwood:
Artech House, 2006.
[16] A. Mitra, «On the Properties of Pseudo Noise Sequences with a Simple Proposal of
Randomness Test,» International Journal of Electrical and Computer Engineering,
vol. 3, nº 3, pp. 164-169, 2008.
[17] U. N. O. f. O. S. A. «Education Curriculum: Global Navigation Satellite Systems,»
United Nations, New York, 2012.
[18] A. Dion, V. Calmettes y E. Boutillon, «Reconfigurable GPS-Galileo receiver for
satellite based applications,» de 2008 National Technical Meeting of The Institute of
Navigation, San Diego, 2008.
[19] S. Gleason y D. Gebre-Egzihaber, GNSS Applications and Methods, Norwood:
Artech House, 2009.
[20] R. Conker, B. El-Arini, C. Hegarty y T.-Y. Hsiao, «Modeling the Effects of
Ionospheric Scintillation on GPS/SBAS Availability,» MITRE, McLean, 2000.
[21] D. Akopian, «Fast FFT based GPS satellite acquisition methods,» IEE Proceedings -
Radar, Sonar and Navigation, vol. 152, nº 4, pp. 277-286, 2005.
[22] B. Parkinson y J. Spilker, Global Positioning System: Theory and Applications, AIAA
Inc., 1996.
[23] SPARC International Inc., «The SPARC Architecture Manual - Version 8,» SPARC
International Inc., Menlo Park, 1992.
[24] ARM Limited, «AMBA Specification (Rev 2.0),» ARM Limited, Cambridge, 1999.
[25] J. Gaisler y M. Isomäki, «LEON3 GR-XC3S-1500 Template Design,» Gaisler
153
Research, Goteborg, 2006.
[26] S. Corrigan, «Introduction to Controller Area Network (CAN),» Texas Instruments,
Dallas, 2005.
[27] K. V. Shibu, Introduction to Embedded Systems, Delhi: Tata McGraw Hill, 2009.
[28] J. Gaisler y K. Eisele, «BCC - Bare-C Cross-Compiler User's Manual,» Aeroflex
Gaisler AB, Goteborg, 2013.
[29] Aeroflex Gaisler AB, «GRMON User's Manual,» Aeroflex Gaisler AB, Goteborg,
2013.
[30] Aeroflex Gaisler, «Eclipse C/C++ IDE plugin for LEON software development,»
Aeroflex Gaisler AB, [En línea]. Available:
http://www.gaisler.com/index.php/products/operating-
systems/bcc?option=com_content&task=view&id=292&Itemid=31. [Último acceso:
11 Agosto 2013].
[31] F. Pujaico Rivera, «LnxCOMM,» TrucomanX, 3 Junio 2008. [En línea]. Available:
http://lnxcomm.sourceforge.net/. [Último acceso: 16 Julio 2013].
[32] V. Calmettes, A. Dion, E. Boutillon y E. Liegeon, «Fast Acquisition Unit for
GPS/Galileo Receivers in Space Enviroment,» de Proceedings of the 2008 National
Technical Meeting of The Institute of Navigation, San Diego, 2008.
[33] A. Dion, E. Boutillon, V. Calmettes y E. Liegon, «A Flexible Implementation of a
Global Navigation Satellite System (GNSS) Receiver for On-Board Satellite
Navigation,» de 2010 Conference on Design and Architectures for Signal and Image
Processing (DASIP), Edinburgh, 2010.
[34] J. Awange, Environmental Monitoring Using GNSS, Verlag: Springer, 2012.