=============================================================================== RTTY DECODIFICADOR EXPERIMENTAL DE DATOS FSK. PARA LINUX + TARJETA DE SONIDO (Por Jesús Arias, EB1DIX) =============================================================================== 1. Motivación de este programa. 2. Algoritmos. 2.1 Demodulación FSK. 2.2 Algoritmo de los filtros. 2.3 Recuperación de los bits. DPLL. 2.4 Recuperación de datos asíncronos (Baudot, ASCII). 2.5 Otros formatos. HDLC. 2.6 Comunicación entre procesos. 3. Requisitos mínimos de cálculo. 4. Compilación. 5. El programa de transmisión FSK. 5.1 Generación de la portadora y la modulación FSK. ------------------------------------------------------------------------------- 1. Motivación de este programa. Hace ya mucho tiempo que pretendía decodificar las transmisiones Baudot que escuchaba en HF. Años atrás pensaba que la única solución posible para ello sería la compra o construcción de un demodulador analógico que se conectaría al puerto serie del PC. De hecho regularmete encontraba esquemas de circuitos de este tipo en revistas como "Elektor" o similares, pero los intentos que realizamos en este sentido tanto yo como EB1GXM fueron fallidos. Daba la impresión que los decodificadores basados en circuitos PLL como el XR2211 eran difíciles de ajustar, y muy sensibles al ruido. En ese sentido creo haber leido un comentario de un radioaficionado que se quejaba amargamente de la baja calidad de los demoduladores modernos, fabricados con circuitos integrados, mientras que los viejos equipos para RTTY, basados en filtros pasivos LC, en su opinión daban mejores resultados. Luego llegó el programa HAMCOMM de DL5YEC, donde la interfaz con el PC era un simple comparador y la CPU se encargaba de la demodulación. Sospecho que las frecuencias de marca y espacio se detectaban mediante contaje. De todos modos los resultados de este programa seguían siendo decepcionates en cuanto la señal estaba ligeramente contaminada por ruido. Finalmente, en la era de lo digital, lo propio parecería ser el uso de un procesador digital de señal (DSP) para demodular los tonos FSK. Personalmente no había conocido los DSP hasta hace un par de años, cuando compré el Starter-Kit del TMS320C3X de Texas Instruments. La documentación de este DSP traía numerosos ejemplos de algoritmos aplicados al tratamiento de señal. Este DSP parecía la solución más apropiada para la demodulación FSK, pero una estimación de la potencia de cálculo necesaria me mostró que el procesador del PC (un Pentium-100) era más que suficiente para mis propósitos. El único uso del PC y una tarjeta de sonido era atractiva, ya que esto suponía que otros radioaficionados en mi misma situación no necesitarían ningún equipo específico para recibir transminiones FSK. ------------------------------------------------------------------------------- 2. Algoritmos 2.1 Demodulación FSK. El algoritmo empleado para la demodulación es bastante simple. Está inspirado en un esquema hardware con filtros activos, que hice en su día pero que nunca llegué a construir. La idea básica es la de comparar las amplitudes de las portadoras de Marca y Espacio. Para ello se aplican a la señal de entrada dos filtros pasa-banda en paralelo. Uno de ellos deja pasar la frecuencia de Marca y otro la de Espacio. A continuación se obtiene el valor "rms" de ambas señales, para lo que simplemente se elevan al cuadrado cada una de ellas y se filtran mediante un filtro pasa-bajos. Finalmente se restan los valores "rms" de las señales de marca y de espacio. Si el resultado es negativo el valor lógico es "O" y si es positivo "1". En este esquema se puede utilizar un único filtro pasa-bajos si la resta se realiza antes del filtrado. (Ver el diagrama de bloques en el fichero demod.ps) --------------------------------------- 2.2 Algoritmo de los filtros. Los tres filtros del demodulador son del tipo Respuesta Impulsional Infinita (IIR). El algoritmo de cálculo es el que sigue: y[n]= a_0 * x[0] + a_1 * x[1] + .......... + a_n * x[n] + b_0 * y[0] + b_1 * y[1] + .......... + b_n-1 * y[n-1] Donde x[0],x[1],...x[n] son los últimos n valores de las muestras de entrada del filtro, y[0],y[1],...,y[n-1] son las últimas n-1 muestras de la salida y a_i y b_i son los coeficientes que definen las características del filtro. El número de coeficientes (n) está directamente relacionado con el orden del filtro. En este caso n=6, con lo que el filtro pasa-bajos tiene una respuesta con un corte de 120 dB/década y los filtros pasa-banda de 60 dB/década. Los valores concretos de los coeficientes se han obtenido a partir del programa "mkfilter" de A.J. Fisher . Se han tabulado los coeficientes para un número grande de frecuencias y anchos de banda, de modo que desde el programa resulta muy fácil cambiar de filtro. (Mucho más fácil que en un decodificador hardware) --------------------------------------- 2.3 Recuperación de los bits. DPLL. Para sincronizar el PC con los bits de los datos que está recibiendo se utiliza una rutina que simula el funcionamiento de un circuito DPLL. Se trata de un contador que va contando muestras demoduladas hasta que se completa la duración total del bit. Si durante este contaje se detecta un cambio de signo de la señal demodulada se adelanta o atrasa el contador una pequeña cantidad (1/32 del tiempo del bit), en el sentido de hacer que la siguiente frontera de bit quede aproximadamente en el centro del contaje. De este modo cuando la rutina retorna la última muestra está tomada en un entorno del centro del bit. El contador de esta rutina emplea una variable estática de coma flotante, y los errores debidos a la discretización del tiempo se acumulan para el siguiente bit. Así, aunque la duración de un bit no sea de un número entero de muestras, se pueden recuperar los bits de forma fiable. --------------------------------------- 2.4 Recuperación de datos asíncronos (Baudot, ASCII). El signo de las muestras de salida del demodulador indica el nivel lógico (0 o 1) de la señal. La recuperación de datos del tipo Baudot o ASCII es relativamente directa. En primer lugar se espera una transición de alto a bajo en las muestras demoduladas. Esta transición marca el comiendo del bit de START de una palabra de 5 bits (Baudot) o de 7 u 8 bits (ASCII). A continuación se leen tantas muestras como tiene la duración de medio bit. A partir de este momento se llama a la rutina DPLL para recuperar cada uno de los bits de datos, de paridad, si la hay, y de stop. Los bits de paridad se comparan con su valor correcto y se genera un error de paridad (

) si no coinciden. Si el bit o los bits de stop no valen 1 se genera un error de "Framming" (). También se pueden dar de forma combinada ambos errores (). Si los datos son de 5 bits se usará el código Baudot, por lo que es necesario hacer una conversión de datos Baudot a ASCII. Si por el contrario los datos son de 7 u 8 bits no es necesaria ninguna conversión. --------------------------------------- 2.5 Otros formatos. HDLC Además de los datos asíncronos también se pueden decodificar paquetes de datos en formato HDLC. En este formato se emplea un código NRZI, en el que los ceros se representan por cambios en la señal y los unos por la ausencia de cambios. Los paquetes HDLC también son peculiares por estar delimitados por dos "Flags" <01111110>, y por convertir los datos de modo que entre dos flags no puede nunca darse de forma fortuita un byte igual que el del flag. Para ello el transmisor inserta un cero en el flujo de bits cuando ya ha transmitido 5 unos seguidos. En el receptor se deben eliminar estos ceros de los datos. Además cada paquete de datos termina en dos bytes de CRC, que deben ser comprobados para detectar errores. Para comprobar el CRC he utilizado una rutina copiada del Kernel del Linux, que a su vez procede del programa WAMPES. --------------------------------------- 2.6 Comunicación entre procesos. El decodificador RTTY consta en realidad de dos programas: El decodificador propiamente dicho y un programa de monitor/control. Este último programa tiene un entrono gráfico basado en la librería XForms. Desde él podemos seleccionar las frecuencias de Marca y Espacio de los filtros, el ancho de banda de los filtros, el formato de los datos (bits de datos, stop, paridad) y la velocidad de los datos. Además en dos ventanas se muestra el espectro de la señal de entrada y la forma de la señal demodulada. Está última gráfica consta en realidad de muchas trazas superpuestas y se suele llamar "diagrama de ojo". La comunicación entre estos dos programas se hace a través de un segmento de memoria compartida entre procesos, en el que se encuentran la mayoría de las variables de interés. Para que esto sea posible el kernel del Linux debe incluir la opción "System V IPC". ------------------------------------------------------------------------------- 3. Requisitos mínimos de cálculo. El cálculo de los filtros se realiza con aritmética de coma flotante y supone sin duda la mayor limitación para ejecutar este programa en ordenadores lentos. Una estimación de la potencia de cálculo se obtiene del recuento de las operaciones de aritmética de coma flotante de los filtros, que nos dan: Filtros Pasa-Banda (x2) 8 Sumas/Restas 7 Multiplicaciones ------------------------ 30 SubTotal Filtro Pasa-Bajos 9 Sumas/Restas 9 Multiplicaciones ------------------------ 18 SubTotal ------------------------ 48 Total O sea: que por cada muestra hay que relizar 48 operaciones de coma flotante. Como la frecuencia de muestreo es de 11025 Hz esto supone 48 x 11025 = 529200 Flop/seg (~0.5 MegaFlop/segundo). Como se puede ver los requisitos de velocidad no son muy estrictos. De hecho en un Pentium-100 apenas supone un 5 % del tiempo de CPU total, con lo que el ordenador apenas si se entera de que está decodificando RTTY. En cuanto a memoria no se necesita mucho, y la gran mayoría (unos 200 Kb) está destinada para la tabla que almacena los coeficientes de los filtros. -------------------------------------------------------------------------------- 4. Compilación. Para compilar estos programas debemos en primer lugar disponer de la librería "XForms". Yo he usado la versión 0.88, pero seguramente el programa puede funcionar con versiones más viejas. Si se quiere experimentar con los filtros será también necesario el programa "mkfilter", que puede obtenerse de: http://www.cs.york.ac.uk/~fisher/mkfilter Tengase en cuenta que será necesario recalcular los coeficientes de los filtros si se cambia la frecuencia de muestreo del audio. (fichero common.h) Para simplemente compilar el programa con los coeficientes por defecto basta con ejecutar: make Si este comando se completa sin errores creará los siguientes programas: rtty El decodificador de RTTY rtty_c El programa de control del decodificador rtty_o El Programa transmisor de FSK (ver a continuación) Para lanzar la decodificación basta con ejecutar el programa "rtty" y este a su vez lanzará el programa "rtty_c" como un proceso hijo. Mediante alguno de los muchos programas "Mixer" se debe seleccionar la entrada de audio de la tarjeta de sonido (normalmente Line-IN, El microfono sólo funciona aceptablemente para velocidades bajas). ------------------------------------------------------------------------------- 5. El programa de transmisión FSK. Por último también se incluye un programa para generar una señal FSK a partir de los datos ASCII de 8 bits del fichero que se indique. La sintaxis es: rtty_o f0 f1 baud fichero Donde f0 es la frecuencia del Espacio, f1 la de la Marca, baud la velocidad en bits/seg y por último fichero es el path hasta un fichero para transmitir. Ejemplo: rtty_o 1000 1850 150 doc.txt --------------------------------------- 5.1 Generación de la portadora y la modulación FSK. La generación de una señal sinusoidal sin necesidad de recurrir a las funciones trigonométricas de forma repetitiva es algo sencillo. Basta con plantearse el problema de rotar un vector en un plano un ángulo fijo dFi: Vector unitario de partida: V = (Vx=1, Vy=0) rotación: NV = Rot (V) / cos(dFi) -sen(dFi) \ / Vx \ (NVx , NVy) = | | | | \ sen(dFi) cos(dFi) / \ Vy / NVx = cos(dFi)*Vx - sen(dFi)*Vy NVy = sen(dFi)*Vx + cos(dFi)*Vy Los valores de cos(dFi) y sen(dFi) son fijos y basta con calcularlos una ver al principio del programa. Por lo tanto la generación de la siguiente muestra de la portadora necesita sólo de 4 multiplicaciones, una suma y una resta, osea: 6 Flops. La señal de la portadora será la componente x del vector V. El paso angular dFi depende de la relación entre la frecuencia que se quiere generar y la frecuencia de muestreo de la siguiente forma: dFi = 360 * f/fs (en grados °) Así por ejemplo, para obtener una frecuencia de 1000 Hz con una frecuencia de muestreo de 11025 Hz dFi será: 360*1000/11025 = 32.65° Aún queda un problema: La amplitud de la portadora puede variar debido a las imprecisiones del cálculo en coma flotante, y a la larga la portadora puede atenuarse o crecer. Para evitar este problema se impone una corrección de la amplitud de la siguiente forma: factor = 2 - ( Vx² + Vy² ) Vx = Vx * factor Vy = Vy * factor Esta corrección supone otros 6 Flops de cálculo. Finalmente para generar una modulación FSK basta con conmutar los valores de cos(dFi) y sen(dFi) por los de una portadora de frecuencia distinta dependiendo de los bits de los datos.