domingo, 6 de mayo de 2018

MANIPULADOR ELECTRONICO SDL

ESPECIFICACIÓN SDL MANIPULADOR ELECTRÓNICO

INTRODUCCIÓN

La llave telegráfica se le ha denominado en castellano, tradicionalmente, manipulador. Manipular vine del latín manipulare y en su acepción de nombre, manipulador, en el diccionario de la RAE viene la siguiente definición "Aparato destinado a abrir y cerrar el circuito en las líneas telegráficas".
Para evitar confusiones entre manipulador llave y manipulador electrónico, keyer en inglés, vamos a referirnos como manipulador simplemente al circuito electrónico y como llave al dispositivo que abre y cierra el circuito para que el manipulador genere la secuencia de puntos y rayas a velocidad constante.

El manipulador se puede hacer con lógica discreta, bastante complicada, un circuito específico o con un microprocesador o microcontrolador. En este último caso en el que se va a usar programación en lugar de lógica cableada es donde viene a ser necesario usar una especificación clara y concisa que permita escribir un código que cumpla a rajatabla con la especificación.
Hay muchas formas de hacer una especificación, pero para programación viene muy bien usar SDL. Es un lenguaje gráfico que es fácil leer, tiene translación directa a código, C, PASCAL, ensamblador... y hay herramientas que permiten validar la especificación antes de tirar una sola línea de código.
Por esta razón he dedicado un tiempo considerable a diseñar un manipulador que cumpla con los modos más usados, IAMBICO A, B y ULTIMATIC. La ejecución final sobre un circuito concreto será objeto de otro trabajo, pero puede ser una placa Arduino si se consigue montar una multitarea por interrupciones o un microprocesador  cualquiera que disponga de varias entradas de interrupción, temporizadores, etc.. que nos permitan montar un sistema multitarea para ejecutar este código.
SDL puede funcionar de forma secuencial, pero su gran potencia viene de ser un lenguaje que permite trabajar con sistemas operativos multitarea y aunque en este caso solo hay una tarea, lo que no exige disponer de un SO multitarea, los mensajes son asíncronos y pueden surgir en cualquier momento y por tanto no es posible usar lazos tipo do whyle para temporizadores ya que se perderían eventos y el funcionamiento dejaría de ser correcto.
Hecha la introducción vamos a desgranar la especificación que está divididos en dos grandes grupos, el autómata y las funciones que son invocadas desde los distintos estados del autómata según surjan los eventos.

EVENTOS DE ENTRADA

Un manipulador de este tipo solo tiene sentido si se una una llave de dos palas. Por tanto hay 4 eventos posibles, pulsar una u otra pala y liberar una u otra pala. Estos 4 eventos se envían al sistema mediante un mensaje en el que se codifica cada evento. Por tanto hay un mensaje tipo pala cuyos argumentos serán la pala afectada, izda o dcha y el estado de ésta, pulsada o liberada.
Cada acción desencadenada por un cambio de estado de las palas lleva asociado de alguna manera una temporización, por tanto hay dos mensajes asociados a la temporización. Uno de salida para fijar el temporizador necesario y otro de entrada al sistema para indicarle qué temporizador ha desbordado o finalizado. Tenemos pues, un mensaje de salida SetTimer y otro de entrada TimeOUT.
Además de fijar temporizadores se tiene que interactuar con la electrónica para abrir o cerrar el circuito que va a generar el símbolo correspondiente. Esto se hace mediante un mensaje de salida cKey y cMute. Vamos a distinguir entre poner en emisión el circuito con el mensaje cKey y bloquear el audio con cMute.
El sistema requiere de ciertas conflagraciones y para ello vamos a usar un mensaje de entrada ConfigKeyer. Como respuesta a los cambios de conflagración y para monitorizar el funcionamiento del sistema hay una serie de mensajes específicos a pantalla que deberán de tratar de forma especifica, ignorándolos si no son útiles, en la solución física que se realice.
La figura adjunta resume  el sistema y los interfaces con el exterior.
Sistema de la especificación SDL del manipulador electrónico

Partimos de un estado inicial en el que el autómata estará en estado de reposo, las palas liberadas y los temporizadores parados. Este es el estado INICIO y se llega a él tras la inicialización de variables.


En el estado inicio se atiende solamente a mensajes de las palas, temporizador de fin de emisión y mensajes de configuración. Los mensajes de configuración son ignorados en el resto de los estados ya que no tiene sentido modificar el comportamiento del manipulador mientras se está procesando algún símbolo, está pulsada alguna llave o hay algún temporizador en curso.


Por rápido que pulsemos ambas palas, siempre llegará antes una que otra aunque solo sea por una cuestión de precedencia que se haya establecido en la solución electrónica, prioridad de las interrupciones HW, muestreo, etc. Así que nunca llegará un mensaje que diga que se han pulsado o liberado ambas palas a la vez.
Empezaremos por el mensaje de configuración:

Este mensaje puede traer el estado del modo QSK, WPM, MODO, WSPACE o WTTORX.
  • QSK puede valer 0 (QSKOFF) no QSK o 1 (QSKON) si QSK. 
  • WPM es un valor numérico entre 8 y 50 palabras por minuto.
  • MODO puede valer IAMBA (1) o IAMBB (2) o EULTIMATIC (3).
  • WSPACE puede valer WSPACEON (1) o WSPACEOFF (0).
  • WTTORX es un valor numérico de espera de final de emisión.
El mensaje TimeOUT no se analiza en detalle. El único temporizador en marcha cuando se está en este estado es el temporizador de fin de emisión.

En este estado se está a la espera que se pulse alguna pala. Si estuviera pulsada alguna de ellas se ignoran los eventos que puedan producirse hasta que no estén liberadas ambas palas.
Por tanto a la recepción de un mensaje Pala se analiza en al función TransicionaINICIO.

































Lo primero que se hace al entrar en la función TransicionaINICIO es analizar el mensaje de las palas mediante al función AnalizaPala. A la salida comprobamos el estado de las palas, si ambas palas están pulsadas o ambas están liberadas, se sale de esta función con la variable SEC (Símbolo En Curso) a cero. De lo contrario, solo una de las palas está pulsada, se sale de esta función con la variable SEC en PUNTO y la memoria de pala punto borrada o RAYA y la memoria de la pala raya borrada. Además se llama antes de salir a la función TX, que genera un mensaje de emisión que deberá ser tratado por el HW adecuadamente.































La función AnalizaPala valora qué acción se ha hecho. Qué pala se ha pulsado o liberado qué pala se ha pulsado primero, si es el caso y memoriza el estado de las palas en las variables de estado. La salida de esta función deja las variables de estado de acuerdo a la acción que se ha recibido en el mensaje.

La ficción  TX se encarga de fijar los temporizadores en función de si el símbolo a emitir  es un punto o una raya y genera el mensaje correspondiente de emisión.


 EL símbolo a emitir es un punto o una raya. La duración de estos símbolos difiere según una relación 1:3, siendo 1 el tiempo de un punto para la velocidad programada. TPUNTO vale 1200/WPM. Así que un punto es un TPUNTO emitiendo y un TPUNTO en reposo, mientras una raya es 3*TPUNTO emitiendo y un TPUNTO en reposo. Para que se produzca la emisión física de al señal se genera el mensaje cKey y para cortar el audio de RX se genera el mensaje cMute. Estos mensajes los tratará el HW en cada caso según la solución que se adopte por el diseñador. Por ejemplo puede ser una salida colector abierto que dispare un relé, para TX, un conmutador electrónico con un JFET en RX, etc...
En el caso que no tengamos activo el modo QSK se genera un temporizador extra con el tiempo de espera para RX, de tal forma que la señal cMute se quitará cuando venza este tiempo si no hay otro evento intermedio que reinicie el temporizador.
La solución HW tiene que tener en cuenta también que otras restricciones deban tenerse en cuenta, pero en general el manipulador entrega una señal de abre/cierra circuito a ritmo de la velocidad programada en palabras por minuto y de acuerdo al orden de pulsar/liberar las palas de la llave conectada al manipulador.

La salida de la función TransicionaINICIO  da paso al análisis del la variable SEC. Si al analizar las palas se vio un estado no previsto SEC == 0, por tanto se mantiene el autómata en el estado INICIO. SEC == PUNTO, se produce un cambio de estado a estado PUNTO o si SEC == RAYA, se produce un cambio de estado al estado RAYA. En estos dos cambios de estado se han generados los mensajes de emisión y se han lanzado dos temporizadores, uno que determina el tiempo que dura la emisión  del símbolo, PUNTO o RAYA y otro que determina al duración del símbolo y eventualmente también está en curso un temporizador TIMTORX de espera a RX cuyo valor es WTTORX.

Llegado a este punto se ha pulsado una pala válida, se han desencadenado las acciones que facilitan la emisión del símbolo correspondiente y se ha cambiado al estado correspondiente. Seguimos el análisis por el estado PUNTO, que funcionalmente es idéntico al estado RAYA.


En el estado PUNTO pueden suceder solo dos tipos de eventos, venza un temporizador de los que están en curso o cambie el estado de las palas. Un cambio en el estado de las palas puede ser, liberar la pala PUNTO ya que estamos en este estado por haberse pulsado previamente la pala punto o pulsar la pala RAYA, sin haber liberado la pala punto. Este mensaje se analiza como ya se vio anteriormente. El resultado del análisis del estado de las palas se memoriza su estado, pero no se produce cambio de estado del autómata puesto que hay un símbolo en curso y éste tiene que acabar previamente. Por tanto, en este estado se aceptan los cambios de estado de las palas pero se memorizan para su posterior tratamiento. Por ejemplo, si se libera la pala punto hay que esperar a que acabe la emisión del símbolo para cambiar al estado que corresponda una vez acabe la emisión del punto.

Bien, los temporizadores en curso a tener en cuenta son dos, el temporizador TIMERTX y SIMBOLO. El primero siempre acabará primero. Por tanto cuando acaba el temporizador TIMERTX se ejecuta la función RX y nos mantenemos en el estado.

La función RX simplemente pasa el circuito de salida a estado abierto, pero se controla también la señal cMute.

Si QSK == 1, entonces controlamos la señal cMute, en caso contrario solo la señal cKey.

Una vez vence el temporizador SIMBOLO hay que ver lo que se tiene que hacer en función del estado de las palas. Como ya se dijo, el estado de las palas está memorizado ya que se analizó el posible mensaje que se produjo mientras se está emitiendo el símbolo. Los estados de las palas pueden ser 4, ambas liberadas, ambas pulsadas, punto o raya pulsada. Por ejemplo, mientras se emite el punto podemos haber liberado la pala de punto y seguidamente pulsado la pala de raya, esta operación se ha memorizado y por tanto la podemos estudiar ahora que ha acabado la emisión del símbolo.
  • Ambas palas pulsadas: se emite el símbolo contrario al que está en curso, en este caso una raya mediante la función TXR. Analizamos si estamos en modo ULTIMATIC, en tal caso pasamos al estado ULTIMATIC y en caso contrario se pasa al esta IAMBIC. En ambos tipos de manipulador la primera vez que se detecta que ambas palas están pulsadas se pasa a emitir el símbolo contrario. En lo que difieren estos dos manipuladores es cómo se trata las repeticiones mientras están pulsadas ambas palas. En modo IAMBIC se alternan puntos y rayas y luego al liberar ambas palas hay una ligera diferencia entre el modo A y B del manipulador  IAMBIC. En manipulador ULTIMATIC lo que hace es emitir de forma continua el símbolo que corresponde a la última pala pulsada, mientras ambas se mantienen pulsadas.
  • No están pulsadas ambas palas, pero se ha pulsado y liberado durante al emisión del punto, la pala raya. Es difícil hacer esto, pero se tiene en cuenta por si sucediera. En este caso se ha memorizado que se pulsó muy poco tiempo la para raya, por tanto MPALAR == 1 y se tiene que emitir este símbolo, así que se ejecuta la función TXR, se inicia la emisión de una raya. Ahora se analiza el estado de ambas palas. Si la pala punto está pulsada, recordemos que hemos entrado en este camino porque no estaban pulsadas ambas palas y se ha pulsado momentáneamente la pala raya, continuamos en el estado punto, en caso contrario, no está pulsado el punto, se pasa al estado RAYA.
  • La pala raya no se pulsó, por tanto hay dos posibilidad es, que el punto siga pulsado, es decir hay que repetir el símbolo punto mediante TXP o que se haya liberado la pala punto. En el primer caso se emite un punto y se continua en el estado PUNTO, en el segundo caso, no hay pala punto pulsada, analizamos si WSPACE == WSPACEON. Esta variable nos indica si queremos añadir un espacio entre letras al final de la emisión del símbolo o no. Si se cumple la comparación se pasa al estado ESPERAESPACIO pero se lanza un temporizador  ESPACIO con una duración de 3*TPUNTO.

En el estado ESPERAESPACIO se aceptan los mensajes de las palas, para memorizar su estado y cual se pulsó primero. Tengamos en cuenta que este estado dura 3 puntos y por tanto es posible que de tiempo a dar dos pulsaciones, una de punto y otra de raya. Esto es muy posible con un manipulador de una sola pala ya que n dos movimientos se hace esta secuencia. Por tanto saber qué pala se pulsó primero es importante.
El otro mensaje que se acepta es el de temporización. El temporizador en curso nos da el tiempo de espera para iniciar la emisión del siguiente símbolo. Si se pulsa alguna pala se analiza como ya se vio con la función AnalizaPala. Como vimos memoriza las acciones de las palas. Cuando venza el temporizador hay que decidir qué hacer. Para ello se usa la función MemEsperaEspacio. Del resultado de este análisis puede ser que no se haya pulsado ninguna pala, por tanto se pasa al estado INICIO o que se haya pulsado al menos una y se tiene que iniciar la emisión y pasar al estado correspondiente de punto o raya.
La función MemEsperaEspacio va a ir estudiando los distintos casos y pondrá en emisión, si corresponde, almacenando en la variable SEC lo que haga.
  • Si ambas palas están pulsadas o han estado pulsadas en algún momento, se inicia la emisión por la que se pulsó primero, borrando la memoria de la que se atiende.
  • Si no están pulsadas ambas palas se comprueba si está pulsada o se ha pulsado momentáneamente el punto. Se ser así se emite un punto y se fija SEC a PUNTO.
  • Si no se cumple ninguno de los casos anteriores se comprueba se está o se ha pulsado la pala RAYA. En tal caso se emite una raya y la variable SEC se pone a RAYA. En caso contrario no se hace nada y la variable SEC  vale cero. 
Al salir de esta función, en el estado ESPERAESPACIO, se analiza la variable SEC y en función de su valor se transita al estado que corresponda, INICIO, PUNTO o RAYA.

El estado RAYA funciona de la misma manera que el estado punto, solo que se centra en la pala RAYA. Es funcionalmente simétrico al estado punto.
Tanto el estado punto como el estado raya tienen salida hacia los estados IAMBIC o ULTIMATIC en función de lo programado en la variable MODO.

El modo IAMBICO se caracteriza porque repite de forma alternada puntos y rayas mientras ambas palas están pulsadas. En este modo y durante la ejecución del símbolo en curso se aceptan mensajes de las palas, como hemos visto en casos anteriores. Al acabar el temporizador en curso se desencadenan las acciones que pueden provocar cambios de estado.




Al acabar el temporizador TIMERTX se pasa a RX como hemos visto en casos anteriores. Es cuando acaba el temporizador SIMBOLO cuando hay que analizar el estado de las palas. Si ambas están pulsadas se continua con la alternancia de símbolos mediante la función TXInvertido.
Esta función analiza el estado de la variable SEC y transmite el símbolo contrario que tenga almacenado. Cambia al nuevo símbolo y así sucesivamente mientras ambas palas estén pulsadas.

Si ambas palas no están pulsadas hay tres posibilidades. Una pala pulsada, punto o raya y ninguna pala pulsada. En el caso de haber una sola pala pulsada se emite el símbolo correspondiente y se pasa al estado del símbolo que se emite, PUNTO o RAYA. En este caso se detiene la alternancia y se continua con la pala pulsada. Por ejemplo la Y es -.-- se puede hacer pulsando la raya, luego el punto y cuando está dando la raya que sigue al punto se levanta la pala punto y de esta forma se vuelve a emitir una raya. Esta forma de manipular no emplea la función memoria. Esta letra se puede hacer de otra forma aprovechando la memoria de pala, haciendo una pulsación corta de la pala punto mientras se está emitiendo la primera raya, pero en este caso no se entraría en el modo IAMBIC que tiene sus peculiaridades.
Si una vez que recibe el mensaje de fin de temporizador SIMBOLO ambas palas están levantadas, se sale del modo IAMBIC, pero dependiendo de si se está en modo A o B la forma de salir es distinta.

La función CheckIAMBIC se encarga de analizar el estado de las palas y decide el modo de salir. Si estamos en modo IAMBIC A, se analiza si está fijada la variable WSPACE. Si esta variable está en WSPACEON entonces se llama a la función TimerEspacio que ya vimos antes. Si no esta en WSPACEON entonces no se hace nada, la variable AUX se coloca a un valor de 3 (no definido) para indicar que hay que hacer nada. Si por el contrario estamos en estado IAMBIC B, este estado se caracteriza por añadir un símbolo extra contrario al último que se emitió. En este caso se llama a la función TxInvertido que inicia la emisión del símbolo contrario y fija la variable AUX en PUNTO o RAYA, ya vimos el funcionamiento de esta función.

Al regresar de la función CheckIAMBIC se analiza la variable AUX y si vale 0 se pasa al estado ESPERAESPACIO ya que se lanzó el temporizador ESAPCIO si vale 3 significa que no hay que esperar y se pasa al estado INICIO directamente, si vale PUNTO o RAYA significa que estamos en modo B y por tanto hay que ir al estado ESPERAIAMB donde nos quedamos mientras se emite el símbolo extra en curso. EL estado ESPERAESPACIO ya lo hemos visto y no cambia nada. El estado ESPERAIAMB es un paso intermedio para dar curso al símbolo extra de IAMBIC B.
 En el estado ESPERAIAMB volvemos a aceptar los mensajes de las palas que se almacenan como ya vimos y hasta que no llega el temporizador no se toman acciones. El temporizador recibido se analiza en al función EsperaIamB. Si el temporizador es de fin de TX, TIMERTX, entonces se para a RX y nos mantenemos en el mismo estado. Si el temporizador es el de SIMBOLO ya tomamos acción en función de si se ha pulsado alguna pala o el estado de WSPACE.
Si no se ha pulsado ninguna pala y WSPACE == WSPACEON, entonces se lanza el temporizador ESAPCIO y se pasa al estado ESPERAESPACIO, si WSPACE == WSPACEOFF se pasa al estado INICIO directamente y si se ha pulsado alguna pala se ejecuta el símbolo correspondiente, pasando al estado PUNTO o RAYA según el símbolo en curso.
La función EsperaIamB analiza el estado de las palas. Mediante la variable AUX informa de la acción a tomar y a la salida se evalúa el estado de AUX.
No es estrictamente necesario usar una función para estas acciones, pero por limitaciones de la herramienta de simulación SDL es necesario hacer estas llamadas a función en lugar de meter todo junto.
Además luego es más sencillo analizar fallos en pequeños trozo de código en lugar de funciones muy grandes con varios switch case, if else anidados.


En el caso de tener el modo ULTIMATIC, en lugar de pasar al estado IAMBIC desde los estados PUNTO o RAYA se pasa al estado ULTIMATIC. Solo con este pequeño cambio de camino es suficiente para implementar un nuevo manipulador, el tipo ultimatic, en lugar del manipulador iambico.


En este modo volvemos a usar el mismo procedimiento. Mientras se está en el estado ULTIMATIC se está emitiendo un símbolo y por tanto almacenamos las acciones de las palas para luego evaluar. Cuando vence TIMERTX pasamos a RX, pero permanecemos en el estado ULTIMATIC y cuando vence SIMBOLO se analizan las palas. Si ambas palas permanecen pulsadas se repite el símbolo, esta es la diferencia sustancial con el iambico y es que no alterna.
Si por el contrario no están pulsadas ambas palas se llama a la función PalasUltimatic donde se analiza el estado de las palas.
La función PalasUltimatic es muy similar a la ya vista para IANBICO pero no tiene que distinguir nada más de si hay una o ninguna pala y si WSPACE está a ON u OFF.

Ya ha quedado analizado el 100% de la especificación, ahora es el momento de codificar sobre una placa HW determinada y comprobar el funcionamiento en modo real.

La herramienta de simulación, Pragma Dev Studio, permite analizar los casos uno por uno generando los mensajes y comprobando la respuesta para ver si es lo esperado. Es un trabajo un poco pesado, pero es de gran ayuda ver si la especificación cumple con lo esperado o no. Depurar un SW en el que no hay una mínima garantís de estar bien pensado introduce una dificultad extra. Funciona mal por estar mal codificado o es porque la idea no es correcta. Llegado a este punto se empiezan con los parches que acaban haciendo un código "infumable" y pasados unos días, semanas o meses ni nosotros mismos lo comprendemos.

La dificultad que introduce un autómata, con muchos estados y mensajes que van y vienen, nos debe llevar a plantearnos seriamente hacer un análisis previo exaustivo. Si no se dispone de una herramienta de simulación/validación es de gran ayuda el análisis crítico de otros para ver si se comprende todo lo especificado y cumple con lo previsto.

Pasar de SDL a C es algo laborioso pero "trivial". Otro asunto es generar mensajes asíncronos que respondan a los eventos HW sin que éstos se pierdan. Un sistema de muestreo puede funcionar si la granularidad del muestreo es suficientemente pequeña como para asegurarnos que no se pierda ningún evento, pero para que esto sea viable es necesario que el tiempo de ejecución del código entre muestras sea suficientemente bajo. Si solo pensamos en un manipulador que va a dar una señal abierto/cerrado a otro HW es posible usar una CPU lenta y podremos usar un sistema de muestro sin grandes complicaciones. Si por el contrario el manipulador es parte del SW de otro sistema más complejo como pueda ser un TRX que tiene que atender a otros muchos eventos, como calcular y programar las frecuencias de emisión o recepción según se a el caso, salidas a pantalla, etc.. es posible que el tiempo que esté ocupada la CPU en algunos procesos exceda con creces el mínimo necesario para muestrear sin que se pierdan eventos. Pensemos que a 20 palabras por minuto un punto dura 120ms. si una puslación de un punto por tanto debe durar menos de este tiempo y debemos ser capaces en este tiempo de capturar los cambios de las palas y hacer el resto de tareas. Por tanto, en casos así es mucho mejor que los eventos HW sean atendidos por interrupciones de tal forma que se capturen, se encolen y sean atendidos cuando sea posible. Es evidente que si aún así el tiempo de ejecución supera los 120ms no podremos emitir a 20ppm, pero si los eventos se recogen en tiempo real y se atienden a tiempo de no violar los tiempos definidos por la velocidad de transmisión, entonces tendremos un sistema eficiente.

HW

Como era de esperar, este manipulador será parte del HW radio HISPALIS y por tanto, hay que tener en cuenta que el display no puede bloquear en ningún momento la evolución de los eventos. La pantalla necesita 5ms por cada carácter que sea necesario sacar a pantalla, es decir, 16*2*5=160ms para refrescar totalmente al pantalla. Es absurdo sacar información a pantalla que ya está pero aún así, si la salida a pantalla bloquea la CPU durante 50ms, seguro que perdemos información. La salida a pantalla se hace mediante interrupciones de tal forma que solo se ocupa la CPU unas decenas de  microsegundos cada vez que se saca un octeto a pantalla, igualmente las palas se llevan a dos patillas que genera una interrupción independiente por flanco. De esta forma solo se gastan unos pocos microsegundos en detectar el movimiento de una pala y se genera un mensaje con la pala y el cambio que hubo, pulsada o liberada. Los temporizadores están gobernados por un temporizador HW de la CPU de tal forma que produce una interrupción cada 2ms. De esta forma se tiene un sistema de tiempos con 2ms de granularidad, cada 3 interrupciones se manda un octeto a pantalla, si es que hay algo para sacar a pantalla, se actualizan los temporizadores SW en curso y si vence alguno se genera un mensaje indicando qué temporizador ha vencido. Todo este HW convive con los pulsadores del teclado que generan igualmente interrupciones para codificar un mensaje indicando la tecla y estado, pulsada o liberada, el encoder rotativo que genera pulsos y por cada flanco se genera un evento para determinar si avanza en sentido horario o antihorario y genera el mensaje correspondiente, el PTT igualmente determina cuando se pasa a TX o RX en modo fonía, finalmente el puerto serie genera interrupciones para capturar los datos recibidos y generar el correspondiente mensaje o para leer el siguiente octeto a enviar por el puerto RS232. Es evidente que un sistema por muestreo no es lo suficientemente eficiente como para atender a tantos eventos. Los mensaje sinembargo se generan en tiempo real, consumiendo algo de tiempo de CPU y son atendidos por un planificador en función de su prioridad. Sin ser un sistema multitarea en tiempo real se comporta como tal.


No hay comentarios:

Publicar un comentario

Espero que te sea útil. Te agradezco la crítica constructiva y todo tipo de comentarios no ofensivos, despectivos o mal intencionados