domingo, 23 de junio de 2019

Plato el día: Pin frito

Buscando la razón por la que la baliza WSPR/FT8 de 28 MHz no aparecía reportada pude finalmente dedicar tiempo a investigar que pasó. Y pasó que el pin GPIO4 de donde se extrae la señal de RF estaba muerto, frito, inutilizado. Esta baliza opera solo con un filtro pasabajos antes de la antena, no tiene un amplificador ni protecciones especiales. No es ninguna sorpresa que haya quedado inutilizado por alguna descarga. Para revisar encontré muy util los utilitarios contenidos en el paquete pigpio y en particular el paquete gpiotest que es un programa en Python que permite evaluar el estado de un puerto GPIO, de su pull-up y la reacción a comandos. Confirmado, el pin GPIO4 no es capaz de modificar su estado ni de levantar el pull-up, frito. Quedaban varias alternativas, una es rotar el mismo nucleo a otra placa, hay una que ya tiene salida de antena para desarrollo aunque no el filtro pasabajos para 28 MHz. Otra era ver de utilizar otro pin. El beacon usa el paquete WsprryPi para el beacon de WSPR, pift8 para el de FT-8 y eventualmente (aunque no activado corrientemente) el programa iqsend y el pirtty. El último de ellos lo hice yo aunque igual que los pertenecientes al paquete rpitx está basado en los servicios de la librería librpitx. Investigando el código fuente pude detectar que la salida por el pin GPIO4 está "cableada" por software y no es un parámetro configurable. Sin embargo es posible alterar el pin desde donde sale el clock con una instrucción para habilitarlo y otra para deshabilitarlo. Habían dos alternativas, o modificar la librería librpitx para que fuera un parámetro opcional lo que potencialmente invalidaría todos los programas que la usan; o en cambio también puede hacerse el "hack" en los programas que usan la librería para hacer opcional la salida por otro pin. Elegí el segundo camino. La variedad de posibles pin no es muy grande, puede usarse GPIO4 y GPIO20 solamente. GPIO4 es el problema o sea que la alternativa es por GPIO20. Para entender un poco mas es interesante entender como puede generarse RF directamente desde la placa hasta frecuencias tan altas (mas de 1 GHz) que son comparables con el clock mismo de la máquina. Generar señales con el procesador es mas viejo que la injusticia, ya lo hacía en procesadores tipo Z80 para generar señales de audio. La técnica mas rudimentaria, y sencilla, es simplemente poner alternativamente en alto o bajo un puerto de salida digital, esperando un retardo controlable en su duración entre uno y otro "perdiendo tiempo" con un loop de software, básicamente contar al vicio un número suficientemente grande de veces. Con eso se saca una señal cuadrada cuya fundamental está dada por el período de alternancia y por lo tanto controlada por el programa. Una onda cuadrada es también rica en armónicos impares (3f, 5f, 7f, etc.).  Por eso se debe agregar un filtro pasabajos con corte por encima de la fundamental, normalmente aún el filtro mas simple (uno tipo RC) bastará para un resultado aceptable debido a la diferencia de frecuencia al primer armónico (espurea). Este método tiene dos problemas; uno es que se tiene que elegir entre que el procesador haga algo ademas de generar la señal o mantener la estabilidad de frecuencia de la señal generada, mejorar uno deteriora el otro. Normalmente se pueden conseguir resultados aceptables para frecuencias muy por debajo del clock del procesador por ésta vía (0.1 a 1%), con semejante margen pequeñas actividades adicionales cuidadosamente balanceadas (normalmente en lenguaje Assembler) permitían hacer algo mas que generar una señal de una frecuencia dada. En la medida que las placas embebidas incorporaron funciones de Timer manipulables con interrupciones se hizo posible generar señales con mucha precisión a frecuencias bastante mas altas; básicamente el atiempamiento está dada por el clock del procesador y no por un retardo de software al mismo tiempo que la sobrecarga para cambiar el estado en un sentido u otro es realmente mínimo y se realiza durante el servicio de la interrupción; normalmente el timer se opera a nivel mayormente hardware una vez programado por lo que los ciclos de CPU se pueden usar para cualquier otra cosa. El único límite a la frecuencia a generar es la resolución el timer y el tiempo de servicio de las interrupciones, por lo que se pueden alcanzar frecuencias de hasta un 5-20% del clock del procesador, un poco mas en algunas arquitecturas. Pero el enfoque que usa la librería rpitx (y todas las que la precedieron y de las que deriva) opera con un principio de funcionamiento diferente. Programa un gestor de DMA disponible en el chip BCM de la Raspberry y lo conecta directamente a un pin de salida; una vez hecha esa programación básica el procesador no tiene que intervenir mas para generar la señal (excepto para modificar su configuración, si está prendido u apagado, la frecuencia, etc.). Por lo que se puede seguir trabajando normalmente con el procesador con una mínima sobrecarga y generando señales de hasta 1 GHz (casi de la misma escala que el clock del procesador). El problema es que solo se puede programar esa conexión directa entre DMA y pines GPIO para un número limitado de pines; en éste caso solo son útiles el GPIO4 o GPIO20 pues no tienen otra asignación. Utilizar otros pines interferiría con servicios básicos como Ethernet o Wifi.
De vuelta a mi materia planteo el problema en el foro groups.io de soporte para rpitx y el consejo que me dá el autor Evariste (F5OEO) es básicamente que haga fork de los paquetes y haga la modificación yo mismo en una copia local. Desistido de modificar librpitx hice fork del paquete rpitx en mi espacio github [link]  e hice modificaciones en los paquetes tune, sendiq y pift8 que son los tres que necesito para la baliza en 28 MHz, el resto puedo vivir por ahora con usar GPIO4 pues son usados en otras placas que no tienen problemas. En todos los casos introduje la modificación para que sin cambiar el default GPIO4 pudiera alterarse con un argumento al llamado que usara otro pin como salida. En el mismo sentido modifiqué todos los paquetes que desarrollé o estoy desarrollando yo.
Pero queda el problema de WSPR para el cual uso un programa que no se basa en librpitx, sino que utiliza la gestión artesanal de DMA explicada antes originaria en los paquetes antecesores a rpitx. No es facil cambiar en ese caso que pin usa como salida porque hay que operar a nivel de registros del procesador (es posible, solo que lleva mas tiempo comprender bien que tocar y mucho mas probarlo). Por lo que tomé otra ruta. Hace algún tiempo había desarrollado una baliza WSPR para una placa Arduino asumiendo utilizar un DDS tipo AD9850 o un Si570, el proyecto nunca pasó de la etapa de boceto (uno de muchos otros tantos que terminan su trayectoria como garabatos en mi libreta). Pero tenía la carpeta con todos los antecedentes y algunas partes de código ya escritas. Una baliza de WSPR es muy simple, básicamente hay que transmitir 162 caracteres, cada uno pudiendo ser uno de 4 símbolos, cada símbolo está separado del anterior por un poco mas de 1 Hz y cada símbolo tarda un poco menos de 1 segundo; el total debe emitirse a partir del segundo 0 de los minutos pares y dura en total algo mas de 1' 45" en emitirse (para dar 15" a las estaciones receptoras para que decodifiquen antes del nuevo ciclo). Los 162 bytes codifican en forma redundantes tres datos, la característica (ej. LU7DID), el locator (ej. GF05) y la potencia en dBm. Teniendo la posibilidad de establecer la frecuencia de un DDS es trivial implementar la transmisión, mucho mas en un ambiente cuya hora está sincronizada por internet mediante el paquete ntp. La creación de los 162 bytes del mensaje son un poco mas ásperos. Antiguamente había un programa (wspr0) en el paquete WSJT-X que dado los valores de licencia, locator y potencia como argumentos los generaba, pero no lo encontré en las distribuciones mas recientes. Asi que busqué como hace el programa WSJT-X mismo para codificar ese mensaje, y durante la búsqueda encontré que otros ya había hecho lo mismo Alex  (OE5TKM) en el paquete wspr-beacon que si bien está diseñado para usar un DDS por hardware tiene todas las rutinas para dado un mensaje obtener su codificación en WSPR, tomé esos segmentos de código y escribí un programa llamado PiWSPR que está integrado a un proyecto mas grande y ambicioso llamado PixiePi (muy en sus comienzos aún) destinado a implementar un transceiver "Pixie" mayormente por software. Incidentalmente un transceiver Pixie es, en teoría, perfectamente capaz de transmitir no solo en WSPR sino también en FT8 provisto que su frecuencia pueda ser controlada en forma externa, algo que obviamente no se puede en la versión tradicional controlada a cristal pero que está muy a tiro si se reemplaza el cristal por un DDS implementado en hardware o software.
Como sea, pude volver a poner la baliza en el aire, emitiendo ahora con su salida desde el puerto GPIO20 (ligera corrección del cableado) en 28 MHz y ya empezaron a fluir los reportes tanto en WSPR como en FT8. Estos modos son maravillosos, la baliza emite con 10 mW solamente (!!) y es escuchada a miles de kilómetros aún con la banda de 10 metros en lo peor del ciclo solar completamente cerrada, que no se podrá hacer con ella en el máximo del ciclo solar. Bueno, será cuestión de probar entonces!

2 comentarios:

  1. Wao parece un escrito de Eisten , mucha información para digerir.Me alegra bastante que puedas seguir usando la placa , es como cuando se te quema la tarjeta de audio integrada en un pc o laptop y tienes que buscar otra alternativa para no darle de baja.

    ResponderEliminar
    Respuestas
    1. Asi es. Afortunadamente había alternativas técnicas y debo decir que fue muy divertido encontrarlas e implementarlas. 73 de Pedro LU7DID

      Eliminar