sábado, 22 de octubre de 2011

Integrando N1MM con OmniRig (MM2OR) de LU7HZ

En unos dias de reposo que me vi forzado a tomar pude progresar en depurar a un nivel operable la integración del CAT entre N1MM y OmniRig hecha en base a software. Recapitulando el problema, N1MM está preparado para controlar una gama muy extensa de equipos, normalmente por medio de la interfaz serie de la PC donde corre el programa. Esta interfaz permite controlar el modo, la frecuencia, el VFO y la operación SPLIT. Es increiblemente util porque asegura que el log captura la frecuencia donde se realiza el QSO, lo que de por si no es "tan" importante, pues excepto algunos concursos (creo que el Russian DX puede ser un ejemplo al respecto) no hay una exigencia real de registrar la frecuencia exacta. Bastará utilizar, por ejemplo, 28000 para cualquier contacto realizado en la banda de 10 Mts entre 28000 y 28999. Sin embargo, es muy util que se registre automáticamente la frecuencia en caso de un cambio de banda; es frecuente (al menos en mi caso) olvidarse de registrar manualmente el cambio de frecuencia y en ese caso la información sobre multiplicadores es erronea tanto en el bandplan, como en el registro de multiplicadores y también en la ventana de nuevos contactos. En los concursos que lo permiten es muy versatil además poder sintonizar con el bandmap, que cualquier cambio manual en el transceiver se refleje en el bandmap y poder utilizar las facilidades de swap entre rig1 y rig2, que yo sustituyo en mi configuración SO2R/SO2V con el programa PMSO2V que oportunamente comentara en una entrada anterior. El precio de tanta maravilla es que el N1MM toma para si los puertos serie y no hay posibilidad que otro programa opere sobre ellos para comunicarse con el transceiver. La exclusividad puede solucionarse con programas llamados "splitter" que esencialmente toman el puerto serie para si y ofrecen interfaces virtuales para que usen los programas de tal manera que lo que transcurre por el puerto es enviado a todos los programas y viceversa. Lamentablemente N1MM no opera bien con estos programas porque al recibir frames de respuesta de el transceiver a un pedido que no hizo tiene serios problemas y el funcionamiento tanto del N1MM mismo como de su operación sobre el transceiver se torna errático y por cierto inusable.
En mi configuración SO2R/SO2V dependo de programas externos para procesamiento digital de las señales (filtrado), control de frecuencia, interfaz con DXAtlas y en el caso de modos digitales el poder controlar con los mismos la sintonia fina del transceiver, esencial en modos como RTTY o PSK31 con sintonia sobre un waterfall gráfico. La respuesta de N1MM es utilizar sus propios programas para digitales, pero en mi opinión es una opción bastante inflexible (parrafaseando a Henry Ford "...se puede elegir cualquier programa para hacer digitales, siempre que estos sean los del N1MM").
En mi estación he elegido OmniRig como plataforma de integración de servicios de CAT para todos los transceivers. OmniRig provee a los programas una interfaz standard (un API) implementado como un objeto COM y gestiona en forma centralizada la comunicación con el (o los) transceivers.
Una de las ventajas de AALog (AATest) es que justamente hace opcionalmente su sintonía usando OmniRig, desafortunadamente todo el resto del funcionamiento de este programa es demasiado limitado, la integridad de los datos está bajo riesgo y el soporte de los autores es sub-standard.
¿Que hacer cuando dos programas que son útiles están intrinsecamente diseñados con una arquitectura que impide usarlos en conjunto?. Integrarlos, ... ¿que otra cosa?.
Implementé entonces el programa MM2OR (N1MM to OmniRig), la idea es muy simple, la implementación probó por un número de razones ser bastante mas trabajosa.
El programa lee un puerto serie (configurable) esperando comandos de CAT y provee respuestas como si fuera un transceiver. Los datos para estas respuestas los obtiene del transceiver real mediante llamadas al OmniRig. De la misma forma se procede cuando lo que se entrega es un comando para operar sobre el transceiver (por ejemplo cambiar la frecuencia o el modo) aunque típicamente este tipo de comandos no producen respuesta.
En realidad N1MM funciona en un lazo cerrado de realimentación, continuamente hace "polling" del estado del transceiver; cuando algún comando o acción cambia el estado simplemente se dispara el comando y se espera que esta acción sea reflejada en los frames de estado.
El primer enfoque que tomé fue tratar de armar las respuestas leyendo los datos individuales que forman el frame, esto me llevó a una via muerta, no todos los valores que aparecen en los frames están disponibles en OmniRig como parte del API standard, entontré además importantes diferencias entre lo que decía el manual y lo que realmente contesta el transceiver (supongo que diferencias en el nivel del firmware).
Opté por volver a empezar y utilizar una facilidad de OmniRig de enviar un comando completo al transceiver y obtener la respuesta que este entrega en forma totalmente transparente (llamada Custom Command por su autor). Con una técnica de programación llamada "callback" es posible manejar que la respuesta del transceiver sea finalmente entregada al puerto serie (forma de conectarse con N1MM).
Encontré, además, detalles de implementación en el N1MM que no están documentados pero que pueden motivar que éste no entienda las respuestas aunque estas sean correctas. Por ejemplo, N1MM envia en secuencia inmediata los dos comandos de requerimiento de status (0x10 y 0xfa en los equipos Yaesu), ... y espera las respuestas también en secuencia inmediata. Si se contesta primero uno y luego otro en la secuencia recibida simplemente es ignorado por N1MM.
La forma para hacer que dos programas que utilizan puertos serie se comuniquen pasa por una solución de hardware, tener dos puertos serie y hacer que ambos estén conectados con un "null modem" (un cable que tiene "cruzados" las lineas de transmisión y recepción); si bien es viable en este caso esta solución no es práctica, para controlar dos transceivers se necesitan 4 puertos serie por hardware. Otra solución es utilizar un "null modem" virtual por software como Com0Com. Basicamente opera de la misma forma pero sin involucrar hardware, define dos interfaces de puerto serie virtuales de forma que los programas se comuniquen con cada una, todos los datos son pasados en forma transparente en ambos sentidos.
Se pueden definir tantos "pares" como se necesite, en este caso se necesitan dos pares.
Desafortunadamente N1MM solo trabaja con puertos series entre COM1 y COM8 (y los autores ya han establecido que no cambiarán esto), lo que crea alguna dificultad porque normalmente COM1 a COM3 están utilizados en las PC (por lo menos en mi caso), COM4 y COM5 son utilizados por OmniRig para comunicarse con los transceivers. Quedan tres puertos COM6,COM7 y COM8 donde se necesitan cuatro. Com0Com afortunadamente permite asignar nombres arbitrarios a los puertos, por lo que COM7 y COM8 los uso en los extremos que comunica el N1MM al mismo tiempo que los extremos conectado por MM2OR con nombres como CNBC0 y CNBC1 (o cualquier otro que venga al caso).
¿Otras rarezas?.. para hacer dulce. Por ejemplo el transceiver FT890 requiere dos (2) stop bits o no funciona, es decir un raro 8N2. Por otra parte N1MM no maneja bien demasiados datos juntos, o sea que hay que atiempar el envio desde el programa, no estoy seguro si se trata de una caracteristica de operar con un null modem virtual (mucho mas rápido por operar en memoria) o se trata de alguna limitación de las librerias que usa N1MM internamente para implementar la comunicación serie.
Dado que cada transceiver tiene sus propias sutilezas quise evitar hacer un software con una lógica excesivamente complicada por todas las decisiones tales como que si es un FT100 hacé tal cosa, pero si es un FT890 hacé otra, si es un FT840 o un FT890 hacé tal cosa pero si es un FT100 hacé otra....
Para solucionar este problema implementé una arquitectura, basada en el patrón llamado "adapter", donde la lógica de manejo general del programa, su interfaz gráfica, la gestión del puerto serie y de OmniRig esté en el programa principal. Al mismo tiempo toda la lógica propia de la interpretación de comandos y armado de las respuestas de cada transceiver queda encapsulada en un módulo externo llamado dynamic load library (dll) . Al momento he implementado para el FT100, FT840 y FT890 quedando para el futuro las correspondientes al IC706MKII y el FT817 que no son normalmente usados en una configuración concursera. La dll apropiada puede ser seleccionada como parte de la configuración; por ahora editando el archivo .INI de configuración, sin ninguna facilidad especial en el GUI que eventualmente tendré que incorporar.
Las pruebas de sistema que tuve la oportunidad, brevemente pues no puedo estar mucho tiempo, son satisfactorias y efectivamente todos los programas actúan en forma coordinada y simultanea. Por supuesto que es necesario hacer pruebas mas extensas, con casos de prueba un poco mas formales y también ciertas pruebas de performance. Pero la palabra final la tendrá la utilización bajo condiciones de concurso reales.
El Campeonato Argentino de HF (CAHF) en su próxima fecha será el ámbito de prueba con vista al tan esperado CQ WW SSB la semana siguiente. Uno menos que hacia rato tenia pendiente de cerrar, vamos a ver como resulta en la cancha.

No hay comentarios:

Publicar un comentario

Buscar este blog

Páginas vistas en total