Hola.
Me ha parecido un reto estupendo hacer esa tarea que emite un texto en morse. Más abajo va el código, pero os sugiero que comencéis viendo el vídeo para que os hagáis una idea de cómo funciona:
https://www.dropbox.com/s/bp7sx4yie0...Morse.MP4?dl=0
He hecho una tare que puede funcionar como una tarea simple, en cuyo caso emite el mensaje "HOLA MUNDO" que repite una y otra vez indefinidamente. La emisión morse se hace mediante destellos del luz (flash) y simultáneamente con pitidos (bip bip). Además puede funcionar como una subtarea. En el primer parámetro (%par1) se pone la palabra o frase a emitir en morse. En el segundo parámetro (%par2) se pueden poner las letras L (luz) y/o S (sonido) para elegir el canal o canales de salida; también se puede añadir una letra R para repetir indefinidamente la transmisión del mensaje, o bien la letra R seguida de un número para indicar el número de repeticiones (R25); todos estos parámetros se separan por comas. Por defecto el valor de %par2 es "
L,S,R"
Por cierto, sin root yo no he tenido ningún problema con la acción ANTORCHA (encender/apagar), funciona perfectamente (S.Galaxy S7 con Android 8.0.0)
La tarea tiene dos matrices principales. La primera se llama
%alfabeto y contiene los 46 caracteres que se pueden traducir a morse, más un último elemento que servirá para señalizar el final de la transmisión (en morse, al terminar una transmisión se añade un código especial para indicar que ya se acabó, no habrá continuación). Los elementos de esta matriz son los siguientes:
A|B|C|D|E|F|G|H|I|J|K|L|M|N|Ñ|O|P|Q|R|S|T|U|V|W|X| Y|Z|0|1|2|3|4|5|6|7|8|9|.|,|?|"|/|-|’|:| |-FIN
Se ha usado una separación por barras porque la coma es un carácter o elemento a utilizar.
De forma paralela hay otra matriz homóloga con los signos morse. Se llama
%alfamorse y contiene el mismo alfabeto, en morse, con los siguientes elementos:
*-|-***|-*-*|-**|*|**-*|--*|****|**|*---|-*-|*-**|--|*|--*--|---|*--*|--*-|*-*|***|-|**-|***-|*--|-**-|-*--|--**|-----|*----|**---|***--|****-|*****|-****|--***|---**|----*|*-*-*-|-*-*--|--**--|*-**-*|-**-*|-****-|---***|*----*|silencio|*-*-*
Veréis que he sustituido los puntos por asteriscos, que son más visibles.
El proceso empieza cogiendo del texto inicial (HOLA MUNDO), el primer carácter (H). Localiza la posición de ese carácter en la primera matriz (8) y luego usa la segunda matriz para coger el elemento de la misma posición (8), que es la traducción a morse (****) de ese carácter (H).
Una vez que se tiene el grupo de puntos y rayas que corresponden al carácter, la tarea hace un segundo bucle para procesar cada uno de esos signos. Y luego se pasa al siguiente carácter de la frase.
Al terminar de procesar cada carácter, un Flash muestra la parte del texto que ya se ha emitido, para orientación de quienes no sabemos morse. De esta forma tenemos cierta constancia de lo que se está emitiendo. Hubiera sido mejor hacer esto con una escena, pero no he querido complicarme.
Tras emitir el texto completo, se añade el código de "fin-de-transmisión", que es el último elemento de la matriz ( *-*-* ). Actualmente está un poco en desuso, pero en la telegrafía clásica tenía mucho sentido, y yo lo he mantenido.
Luego, la tarea comprueba si hay que repetir la emisión, en cuyo caso vuelve a empezar.
En telegrafía clásica también se transmitía un encabezamiento o prólogo previo al mensaje. Ese encabezamiento indicaba la estación de destino a la que se dirigía el mensaje y también la estación remitente que lo enviaba. Esto no es aplicable en nuestro caso.
En la matriz morse, podéis ver que en el elemento penúltimo he puesto la palabra "
silencio", lo cual es una anomalía que explico enseguida (luego he visto que Willy había usado un truco similar en su tarea).
El morse no es binario sino ternario. Hay puntos, rayas y silencios. Entre cada dos palabras escritas hay un espacio, que en morse se traduce como un silencio de una duración determinada. Resultaba un poco confuso chequear en la primera matriz el carácter espacio (porque es invisible) y he preferido chequear en la segunda matriz esta palabra bien llamativa para que la tarea sepa que -al encontrar esa palabra- debe hacer una espera sin emitir nada.
Después de haber completado la tarea, al ver la de Willy me he dado cuenta de que la suya es mejor en un concepto de diseño: Willy procesa todo el texto traduciendolo y preparando el código de salida (puntos y rayas), y luego de que ya ha completado la traducción es cuando empieza a emitir. Eso hace que la emisión sea más ágil, porque no necesita ir traduciendo al mismo tiempo que emite como he hecho yo. Por contra, mi sistema tiene la ventaja de que va mostrando por pantalla el texto simultáneo a la emisión morse.
La tarea es típica mía, mastodóntica (65 acciones), de las cuales hay algunas prescindibles, pero las he puesto porque me ayudan a organizarlo todo. Hay tres bloques de acciones bien diferenciados:
A) Acciones iniciales preparatorias.
B) Bucle principal que procesa los caracteres de la frase, los traduce y emite en morse.
C) Coletilla para añadir el código "fin-de-transmisión" y para controlar si hay que repetir.
Cada uno de estos bloques está dentro de un grupo
Si (If) -
Fin Si (End if). No están ahí para chequear el cumplimiento de una condición, no. Solo los he puesto porque en la parte derecha de la acción
Si (If) hay un "pico" que permite replegar/ocultar todo el contenido de ese grupo de acciones, y si tocas de nuevo ahí vuelven a desplegarse/visualizarse todas las acciones que antes estaban ocultas. Creo que es una buena estrategia para tareas muy largas, como ésta, porque es una ventaja tener visible solo la parte en la que estás trabajando, y oculto el resto.
Seguramente Willy podría rehacer la tarea con la mitad de las acciones. Y supongo que también se podría mejorar mucho añadiendo expresiones regulares o javascript. O también exportándola como aplicación.
En la tarea he aprovechado muchas etiquetas para poner comentarios sobre las acciones. No os despistéis con eso, son líneas que comienzan con "<" y preceden a la acción a la que está asociado ese texto. Las acciones reales siempre tienen al principio de línea la letra A(acción) y un número.
Más detalles: el alfabeto morse no contiene todos los caracteres que usamos normalmente. Para empezar, no distingue entre mayúsculas y minúsculas. Carece de acentos, diéresis y otras zarandajas. Sí tiene los 10 dígitos y unos cuantos signos de puntuación, los más básicos. Recientemente se ha añadido la letra eñe, pero creo que su uso es todavía muy escaso incluso en entornos hispanos, y sigue habiendo quien no la considera como "letra oficial". La tarea incluye acciones para detectar los caracteres que no se pueden traducir a morse. El texto de entrada puede estar en mayúsculas o minúsculas, es indistinto.
En la wikipedia y otras páginas podéis informaros sobre lo que duran los puntos, las rayas, las pausas entre letras, y otras cuestiones técnicas o históricas. También hay páginas web en las que escribes un texto y te lo "traducen" a puntos y rayas. En algunas como la siguiente también puedes "emitir" eso mediante luces y/o sonidos.
https://morsecode.scphillips.com/translator.html
Ahí puedes poner tu frase favorita y descargarte el archivo de sonido o bien grabar un vídeo para enviárselo a tu cuñado. También puedes grabar un SOS para luego emitirlo en bucle con el reproductor multimedia.
Comparado con esa página, mi tarea es lenta y torpe, como si estuviera emitiendo un telegrafista principiante. Espero que funcione suficientemente bien para que pueda ser comprendido por un telegrafista. Hay páginas que traducen texto a morse e incluso hay alguna que traduce morse (puntos y rayas) a texto, pero no he encontrado ninguna que "escuche" morse, ni nada parecido. Tampoco conozco a ningún telegrafista que pueda escuchar y diga si se entiende algo.
Ha sido divertido como reto o ejercicio de verano, eso es todo. Si alguien quiere más explicaciones, o el fichero XML con la tarea exportada, que lo diga. Si alguien quiere mejorarla o adaptarla, me parecerá genial. Saludos.
MiscMorse (203)
<Esta tarea convierte un texto en código morse y lo emite por el flash de la cámara y/o mediante sonidos (bip). Primera parte: acciones preparatorias.>
A1: Si (if) [ 1 ~ 1 ]
<El primer parametro es el texto a procesar; si no se indica nada, se usar el texto "HOLA MUNDO".>
A2: Establecer variable [ Nombre:%par1 A:Hola Mundo Recurse Variables:Apagado Calcular:Apagado Añadir:Apagado ] Si (if) [ %par1 No ajust. ]
A3: Convertir Variable [ Nombre:%par1 Función:A Mayúsculas Almacenar Resultado en: ]
<El segundo parametro define el modo de funcionamiento según algunos caracteres clave, separados por comas: L(luz);S(sonido); R35(repetir 35 veces el mensaje); R0(repetir indefinidamente); por omisin se usará "L, S,R0".>
A4: Establecer variable [ Nombre:%par2 A:L,S,R Recurse Variables:Apagado Calcular:Apagado Añadir:Apagado ] Si (if) [ %par2 No ajust. ]
A5: Establecer variable [ Nombre:%par2 A:L,S,%par2 Recurse Variables:Apagado Calcular:Apagado Añadir:Apagado ] Si (if) [ %par2 !~ *L* & %par2 !~ *S* ]
<Esta variable contiene la duración por defecto (en milisegundos) de un punto morse.>
A6: Establecer variable [ Nombre:%mspunto A:100 Recurse Variables:Apagado Calcular:Encendido Añadir:Apagado ]
<Las siguientes acciones averiguan el número de repeticiones del mensaje morse a emitir>
A7: Establece Array [ Matriz de Variables (array):%pardos Values:%par2 Separador:, ]
<indicativo de repeticiones?>
A8: Si (if) [ %pardos(#?R*) > 0 ]
<R seguido de algo?>
A9: Si (if) [ %pardos(#?R) = 0 ]
A10: Establecer variable [ Nombre:%repeticiones A:%pardos(#?R*) Recurse Variables:Apagado Calcular:Apagado Añadir:Apagado ]
A11: Establecer variable [ Nombre:%repeticiones A:%pardos(%repeticiones) Recurse Variables:Apagado Calcular:Apagado Añadir:Apagado ]
A12: Buscar y Reemplazar Contenido de Variable [ Variable:%repeticiones Buscar:R Ignorar Caso:Apagado Multilínea:Apagado Una sola coincidencia:Apagado Almacenar Coincidencias En: Reemplazar Coincidencias:Encendido Reemplazar Con: ]
A13: Establecer variable [ Nombre:%repeticiones A:%repeticiones Recurse Variables:Apagado Calcular:Encendido Añadir:Apagado ]
A14: Fin si (End if)
A15: Fin si (End if)
<A|B|C|D|E|F|G|H|I|J|K|L|M|N|Ñ|O|P|Q|R|S|T|U|V|W|X |Y|Z|0|1|2|3|4|5|6|7|8|9|.|,|?|"|/|-|’|:| |-FIN>
A16: Establece Array [ Matriz de Variables (array):%alfabeto Values:A|B|C|D|E|F|G|H|I|J|K|L|M|N|Ñ|O|P|Q|R|S|T|U |V|W|X|Y|Z|0|1|2|3|4|5|6|7|8|9|.|,|?|"|/|-|’|:| |-FIN Separador:| ]
<*-|-***|-*-*|-**|*|**-*|--*|****|**|*---|-*-|*-**|--|*|--*--|---|*--*|--*-|*-*|***|-|**-|***-|*... etc>
A17: Establece Array [ Matriz de Variables (array):%alfamorse Values:*-|-***|-*-*|-**|*|**-*|--*|****|**|*---|-*-|*-**|--|*|--*--|---|*--*|--*-|*-*|***|-|**-|***-|*--|-**-|-*--|--**|-----|*----|**---|***--|****-|*****|-****|--***|---**|----*|*-*-*-|-*-*--|--**--|*-**-*|-**-*|-****-|---***|*----*|silencio|*-*-* Separador:| ]
A18: Probar Variable [ Tipo:Longitud Datos:%par1 Almacenar Resultado en:%longtexto ]
<Comienza a procesar el mensaje>
A19: Establecer variable [ Nombre:%numcaracter A:1 Recurse Variables:Apagado Calcular:Encendido Añadir:Apagado ]
A20: Establecer variable [ Nombre:%procesados A: Recurse Variables:Apagado Calcular:Apagado Añadir:Apagado ]
A21: Establecer variable [ Nombre:%procesados A:%repeticiones - Recurse Variables:Apagado Calcular:Apagado Añadir:Apagado ] Si (if) [ %repeticiones > 0 ]
A22: Fin si (End if)
<Segunda parte y principal: el bucle que procesa cada uno de los caracteres de la frase>
A23: Si (if) [ 1 ~ 1 ]
<Bucle caracteres>
A24: Sección de Variable [ Nombre:%par1 Desde:%numcaracter Longitud:1 Encajar:Apagado Almacenar Resultado en:%caracter ]
<Salto fin de mensaje>
A25: Establecer variable [ Nombre:%posarray A:%alfabeto(#?%caracter) Recurse Variables:Apagado Calcular:Apagado Añadir:Apagado ]
A26: Establecer variable [ Nombre:%caracter A:# Recurse Variables:Apagado Calcular:Apagado Añadir:Apagado ] Si (if) [ %posarray = 0 ]
A27: Ir a acción [ Tipo:Etiqueta Acción Número:1 Etiqueta:Fin del grupo morse y del caracter ] Si (if) [ %posarray = 0 ]
A28: Establecer variable [ Nombre:%morsegrupo A:%alfamorse(%posarray) Recurse Variables:Apagado Calcular:Apagado Añadir:Apagado ]
<Espacio entre palabras implica una pausa en la secuencia morse>
A29: Si (if) [ %morsegrupo ~ silencio ]
A30: Esperar [ MS:%mspunto*4 Segundos:0 Minutos:0 Horas:0 Días:0 ]
A31: Else
A32: Probar Variable [ Tipo:Longitud Datos:%morsegrupo Almacenar Resultado en:%signosgrupo ]
A33: Establecer variable [ Nombre:%numsigno A:1 Recurse Variables:Apagado Calcular:Encendido Añadir:Apagado ]
<Bucle signos morse>
A34: Sección de Variable [ Nombre:%morsegrupo Desde:%numsigno Longitud:1 Encajar:Apagado Almacenar Resultado en:%signo ]
A35: Establecer variable [ Nombre:%duracionsigno A:0 Recurse Variables:Apagado Calcular:Encendido Añadir:Apagado ]
A36: Establecer variable [ Nombre:%duracionsigno A:%mspunto Recurse Variables:Apagado Calcular:Encendido Añadir:Apagado ] Si (if) [ %signo ~ * ]
A37: Establecer variable [ Nombre:%duracionsigno A:4*%mspunto Recurse Variables:Apagado Calcular:Encendido Añadir:Apagado ] Si (if) [ %signo ~ - ]
A38: Ir a acción [ Tipo:Etiqueta Acción Número:1 Etiqueta:Fin del grupo morse y del caracter ] Si (if) [ %duracionsigno = 0 ]
A39: Antorcha [ Establecer:Encendido ] Si (if) [ %pardos(#?L) > 0 ]
A40: Si (if) [ %pardos(#?S) > 0 ]
A41: Bip [ Frecuencia:8000 Duración:%duracionsigno Amplitud:50 Stream:3 ]
A42: Else
A43: Esperar [ MS:%duracionsigno Segundos:0 Minutos:0 Horas:0 Días:0 ]
A44: Fin si (End if)
A45: Antorcha [ Establecer:Apagado ] Si (if) [ %pardos(#?L) > 0 ]
A46: Esperar [ MS:%mspunto/2 Segundos:0 Minutos:0 Horas:0 Días:0 ]
A47: Sumar a variable [ Nombre:%numsigno Valor:1 Módulo (wrap around):0 ]
A48: Ir a acción [ Tipo:Etiqueta Acción Número:1 Etiqueta:Bucle signos morse ] Si (if) [ %numsigno < %signosgrupo | %numsigno = %signosgrupo ]
A49: Esperar [ MS:%mspunto*2 Segundos:0 Minutos:0 Horas:0 Días:0 ]
A50: Fin si (End if)
<Fin del grupo morse y del caracter>
A51: Establecer variable [ Nombre:%procesados A:%procesados%caracter Recurse Variables:Apagado Calcular:Apagado Añadir:Apagado ]
A52: Flash [ Texto:%procesados Largo:Apagado ]
A53: Sumar a variable [ Nombre:%numcaracter Valor:1 Módulo (wrap around):0 ]
A54: Ir a acción [ Tipo:Etiqueta Acción Número:1 Etiqueta:Bucle caracteres ] Si (if) [ %numcaracter < %longtexto | %numcaracter = %longtexto ]
A55: Fin si (End if)
<Tercera y última parte. Acciones finales tras el bucle principal.>
A56: Si (if) [ 1 ~ 1 ]
<Añadir la señal de "Fin de mensaje">
A57: Si (if) [ %numcaracter = %longtexto+1 ]
A58: Establecer variable [ Nombre:%caracter A:-FIN Recurse Variables:Apagado Calcular:Apagado Añadir:Apagado ]
A59: Ir a acción [ Tipo:Etiqueta Acción Número:1 Etiqueta:Salto fin de mensaje ]
A60: Fin si (End if)
A61: Esperar [ MS:%mspunto*7 Segundos:0 Minutos:0 Horas:0 Días:0 ]
<Mirar a ver si hay que repetir el mensaje>
A62: Ir a acción [ Tipo:Etiqueta Acción Número:1 Etiqueta:Comienza a procesar el mensaje ] Si (if) [ %pardos(#?R) > 0 ]
A63: Restar de variable [ Nombre:%repeticiones Valor:1 Módulo (wrap around):0 ]
A64: Ir a acción [ Tipo:Etiqueta Acción Número:1 Etiqueta:Comienza a procesar el mensaje ] Si (if) [ %repeticiones > 0 ]
A65: Fin si (End if)