_______________________________________________________________________
   /*
      ATDT MAGAZINE ::::::::::::::::::::::::::::::::::::::::::::::::::::::
      ::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
      ::::::::::::::::::::::::::::::::::::::::::::::::::::::::::[0x03-12]:
      NUMERO 0x03:::::::::::::::::::::::::::::::::::::::::::::::::::::::::

                         "Retrotem: Term multimedia para C64"por pastbytes
   */

   ========================================================================
   Introduccion

   Hace poco mas de 1 año, mas precisamente en febrero de 2020, comenzaba
   un pequeño experimento que se convirtio en un proyecto que tuvo varios
   logros tecnicos interesantes.
   Retroterm es una terminal para Commodore 64, pero es una terminal muy
   particular. Conectandose a un BBS estandar es una terminal muy simple,
   que solo tiene envio y recepcion de texto. Pero cuando se conecta a un
   BBS especial, es capaz de hacer streaming de audio PCM (digitalizado)
   con una calidad de 4 bits y un muestreo de 11520 Hz, mostrar imagenes en
   16 colores, o recibir bloques de datos a maxima velocidad, para por
   ejemplo descargar programas directamente a memoria RAM. Todo esto es
   posible gracias a que Retroterm funciona siempre a una velocidad de
   57600 bps, y a un protocolo propio que llamamos TURBO56K.

                .oooooo.       .ooo         .o
               d8P'  `Y8b    .88'         .d88
              888           d88'        .d'888
              888          d888P"Ybo. .d'  888
              888          Y88[   ]88 88ooo888oo
              `88b    ooo  `Y88   88P      888
               `Y8bood8P'   `88bod8'      o888o


   Commodore 64, procesadores y RS232

   Pero volvamos al inicio. Cuatro años antes de la primera version, en
   2016, habiamos logrado enviar y recibir por RS232 a 57600 bps, y enviar
   a 115200 bps. Para poner esto en contexto, la Commodore 64 es una
   computadora de 1982, con 64K de memoria RAM y un procesador compatible
   con el MOS 6502, corriendo a una velocidad de 1 MHz. Analicemos esto. Un
   procesador hace todo al ritmo de una señal de reloj que le marca la
   velocidad de ejecucion. Cada operacion que realiza el procesador esta
   sincronizada con ese reloj, y tener un reloj de 1 MHZ implica que hay 1
   millon de ciclos de reloj por segundo. La mayoria de las instrucciones
   de este procesador se ejecutan entre 2 y 4 ciclos de reloj. Suponiendo
   que las instrucciones usaran 3 ciclos de reloj, esto significaria que en
   1 segundo podriamos ejecutar 1000000 de ciclos / 3, esto es 333333
   instrucciones.
   Y por que es importante esto? Veamos. 57600 bits por segundo no parece
   mucho, uno pensaria que con un procesador de 1 MHz podria manejarlo sin
   problemas. Pero resulta que la Commodore 64 no tiene un chip encargado
   del puerto RS232, entonces debe hacer tanto el envio como la recepcion
   por software. En RS232 se envian bytes en serie, un bit tras otro, donde
   cada bit tiene una duracion exacta. Para recibir este byte, el
   procesador debe detectar la llegada del dato, y empezar a temporizar la
   duracion de cada bit, leyendo desde el puerto cada uno de los bits en el
   momento exacto, y almacenandolos en memoria hasta completar el byte.
   Esto significa que el procesador debe estar dedicado a leer los bits
   desde el puerto serie, mientras se mantiene sincronizado con esos datos,
   por lo que en principio no puede hacer nada mas.
   Ahora volviendo a la velocidad, a 57600 bits por segundo cada bit dura
   17 ciclos de reloj, lo cual deja ejecutar al procesador un promedio de
   casi 6 instrucciones por bit. Este numero sale de dividir 1 millon de
   ciclos de reloj que hay en 1 segundo, por 57600 bits que se pueden
   enviar en ese mismo tiempo, esto es 1000000 / 57600 = 17,361 ciclos de
   reloj por bit. Ahora 1 MHz ya no parece tanto. Sin embargo, a pesar de
   que el procesador tiene el tiempo justo para recibir los datos, todavia
   puede manejarlo sin problemas. La dificultad esta en que los datos
   pueden llegar en cualquier momento, y esto impide que el procesador
   pueda hacer otras tareas, ya que siempre debe estar atento a la llegada
   de un byte.

   Terminales, velocidad y recepcion

   Ademas de enviar y recibir datos por el puerto serie, una terminal debe
   como minimo leer el teclado e imprimir en pantalla. Es necesario
   encontrar una manera de poder realizar todas esas tareas repartiendo el
   tiempo de procesador disponible. Algunas terminales realizan el envio y
   recepcion "en simultaneo" con el resto de las funciones, pero esto
   limita la comunicacion a un maximo de 1200 o 2400 bps, ya que por encima
   de estas velocidades la perdida de precision es muy grande. Otro metodo
   consiste en modificar ligeramente el cableado de los modems para usar
   asistencia de hardware tanto en envio como en recepcion, pero esto solo
   funciona a 9600 bps y debe tener soporte especifico tanto del modem como
   de la terminal. El metodo que elegimos para Retroterm es el de la
   dedicacion exclusiva a la comunicacion, esto es, que durante el envio y
   la recepcion el procesador no hara otra cosa, lo que nos permite
   alcanzar los 57600 bps. Pero para lograr esto, tenemos que poder elegir
   el momento en que enviamos y recibimos, y la solucion es usar las lineas
   RTS y CTS del RS232. La funcion original de RTS y CTS no era la misma
   que en la actualidad, ya que eran señales pensadas para la comunicacion
   entre DTE (computadora) y DCE (modem). Desde la decada de 1990 estas
   lineas se usan para la comunicacion entre terminales. Hoy RTS es usada
   por la terminal para indicar a la otra parte que esta lista para recibir
   datos, y en caso de no poder recibir, simplemente desactiva RTS. De esta
   manera, ya tenemos el mecanismo para controlar cuando llegan los datos,
   pero ahora debemos decidir cuando nos conviene recibirlos.
   Muchas de las computadoras de la decada de 1980 estaban diseñadas
   especificamente para un sistema de television, ya que se pensaron para
   conectarse a un televisor en la mayoria de los casos. De estas maquinas,
   algunas tenian memoria de pantalla independiente de la RAM principal, y
   otras tenian la memoria de video compartida con la RAM del procesador.
   La Commodore 64 pertenece a estas ultimas, tiene un chip de video que
   puede acceder a 16K de memoria principal para almacenar los datos de
   pantalla, sean graficos o texto. Si bien esto tiene algunas ventajas,
   tambien tiene la desventaja de que el procesador y el chip de video
   compiten por el uso de la memoria. Cuando el chip de video debe generar
   una imagen, algo que hace 50 o 60 veces por segundo dependiendo del
   sistema de TV, debe detener al procesador para poder leer los datos de
   texto o graficos, ya que no pueden acceder ambos simultaneamente. Esto
   ocurre varias veces durante la generacion de la imagen, excepto cuando
   se esta dibujando alguno de los bordes de la pantalla, o cuando se
   deshabilita la generacion de video. Ya que durante los bordes el
   procesador puede estar seguro de no tener interrupciones por parte del
   chip de video, elegimos comenzar la recepcion de datos apenas empieza a
   dibujarse el borde inferior de la pantalla. De esta manera, ya tenemos
   como indicar que estamos listos para recibir datos, y tenemos decidido
   cuando recibirlos.

   Primeras versiones y velocidad en modo normal

   La primera version de Retroterm fue un ejecutable de 626 bytes, de los
   cuales los dos primeros bytes son la direccion de carga, y del resto,
   122 estan sin usar, ya que corresponden al codigo de streaming de audio
   PCM que aun no estaba habilitado. En esta version se definio la
   estructura basica del programa, que con algunas variaciones aun se
   mantiene. Una parte del codigo se ejecuta sincronizado con el chip de
   video, el cual permite disparar una interrupcion en una linea de video
   determinada. Ya vimos que nos convenia comenzar la recepcion cuando se
   empieza a dibujar el borde inferior de la pantalla, por lo que
   configuramos el chip para dispararla en la linea 251. En esta rutina de
   interrupcion, se recibe 1 byte, se envia 1 byte, se ingresa cualquier
   byte recibido a un buffer de impresion, se envia cualquier caracter
   leido desde el teclado, se procesa el parpadeo del cursor, y se termina
   llamando a la rutina de la ROM encargada de leer el teclado. En el
   programa principal, un bucle infinito se encarga de imprimir cualquier
   caracter ingresado al buffer. Tanto la lectura del teclado como la
   impresion en pantalla se hacian con codigo propio de la ROM del sistema.
   Una caracteristica distintiva de Retroterm que tambien se ejecuta
   durante la interrupcion es el sonido de impresion en pantalla, que es un
   homenaje a la pelicula War Games.
   En este punto, ya teniamos una terminal basica capaz de comunicarse a
   57600 bps usando RTS/CTS, pero enviando y recibiendo solo 1 caracter por
   cuadro de video, es decir 50 o 60 caracteres por segundo dependiendo del
   sistema de TV de la maquina. Si tenemos en cuenta que cada byte se
   compone de 10 bits (start, 8 bits de datos, stop), 50 caracteres por
   segundo seria equivalente a una velocidad constante de 500 bits por
   segundo. Ya que la velocidad mas usada en la Commodore 64 para modems
   modernos es de 1200 bps, elegimos recibir 3 caracteres por cuadro, lo
   que nos da una velocidad equivalente a 1500 bps en PAL y 1800 bps en
   NTSC, suficiente para superar los 1200 bps. Estos numeros salen de
   multiplicar 3 caracteres por cuadro x 50 cuadros por segundo en PAL x 10
   bits por byte, que nos da 1500 bps. En NTSC el calculo seria: 3 x 60 x
   10 = 1800 bps. Como Retroterm se penso como un cliente donde en
   principio no se envian grandes cantidades de datos, la transferencia no
   es simetrica, siendo menor la velocidad de envio, que sigue siendo de 50
   caracteres por segundo en PAL (equivalente a 500 bps) y de 60 cps en
   NTSC (equivalente a 600 bps).

   El protocolo TURBO56K entra en escena

   Como ya explicamos, en la Commodore 64 tenemos la desventaja de que el
   procesador sea interrumpido por el chip de video durante la generacion
   de la imagen, lo cual nos obliga a tener que hacer la recepcion durante
   el dibujado del borde. Pero que pasaria si pudieramos evitar esto?
   Podriamos disponer del 100% del tiempo del procesador para recibir bytes
   en una transferencia continua. Y que tan alta podria ser esta
   transferencia? Veamos. A 57600 bps estariamos recibiendo 5760 bytes por
   segundo, si quisieramos recibir 64 Kbytes de datos (la cantidad total de
   memoria RAM que tiene la Commodore 64), podriamos hacerlo en 65536/5760
   = 11,37 segundos. Esta seria la velocidad maxima teorica, sin pausas
   entre bytes. Ahora empiezan a verse las ventajas de trabajar siempre a
   57600 bps, pero para lograr esto deberiamos eliminar la interferencia
   del chip de video, y esto solo es posible deshabilitando la generacion
   de la imagen, es decir, tendriamos que quedarnos sin video.
   La primera decision que se tomo fue que Retroterm tuviera dos modos de
   operacion, el que vimos hasta ahora seria el modo normal, con 1 caracter
   enviado y 3 caracteres recibidos por cuadro. El otro modo de operacion
   seria el modo turbo, donde se apagaria la pantalla y se alcanzaria una
   transferencia maxima. Habia que encontrar una manera de seleccionar el
   modo de operacion, y la solucion fue crear un protocolo que permitiera
   la navegacion en BBS PETSCII (con el juego de caracteres de la Commodore
   64) y a la vez posibilitara activar funciones especiales de la terminal.
   Despues de analizar el juego de caracteres, se eligio reservar el codigo
   255 para entrar a modo comando, por ser un caracter duplicado y por lo
   tanto no utilizado. Si la terminal recibe un caracter con ese valor,
   automaticamente entra en modo comando, y comienza a interpretar los
   bytes como comandos y parametros. Si estando en este modo recibe un byte
   de valor 254, volvera al modo normal, y comenzara a imprimir en pantalla
   el texto recibido.

   Comandos, parametros y modos de video

   El primer comando implementado fue la transferencia de un bloque de
   bytes directo a memoria, en principio para poder mostrar pantallas
   graficas (bitmaps), ya que Retroterm no iba a ser una terminal, sino un
   programa para hacer presentaciones controladas remotamente. Ese es el
   origen de la orientacion multimedia de la terminal.
   Para mostrar una imagen son necesarias 2 o 3 transferencias dependiendo
   del modo bitmap elegido, que puede ser multicolor (3 transferencias) o
   alta resolucion (2 transferencias), y luego configurar el chip de video
   para activar el modo de video correspondiente. Esto llevo a agregar 3
   nuevos comandos, uno para activar la pantalla de alta resolucion, otro
   para activar la pantalla multicolor, y otro para volver al modo texto.
   El comando de transferencia originalmente requeria 4 bytes de parametros
   indicando la direccion de inicio en la memoria donde se almacenaria el
   bloque de bytes transferido, y otros dos bytes indicando la cantidad de
   bytes a recibir. Con el tiempo esta operacion se dividio en etapas, un
   comando que indicaria la direccion inicial, que quedaria almacenada como
   un puntero interno de la terminal, y otro comando que indicaria la
   cantidad de bytes a transferir e iniciaria la transferencia. Durante la
   transferencia se apaga automaticamente la pantalla, y se vuelve a
   habilitar al finalizar. De esta manera pueden convivir un modo de texto
   con una transferencia razonable, y un modo de transferencia rapida con
   la pantalla apagada por unos segundos.
   Los comandos que seleccionan el modo de video tienen como parametros los
   colores de fondo y borde de la pantalla, por lo que no estamos limitados
   a una terminal con texto sobre fondo negro.
   Pensando en el futuro, se agregaron comandos alternativos para ajustar
   el puntero a memoria para las transfencias, sin especificar direcciones
   absolutas. Esto se hizo para apuntar a las 3 areas de memoria que maneja
   el chip de video: la memoria de texto, la memoria de color, y la memoria
   de bitmap. De esta manera nos independizamos de la implementacion de la
   terminal, ya que la pantalla puede tener una direccion diferente en
   distintas maquinas (una Commodore 128 en modo nativo, por ejemplo), y
   nos abre la posibilidad de implementar varias paginas de texto en el
   futuro.
   Y por supuesto, el uso mas evidente de los comandos de transferencias es
   la descarga de programas directamente a memoria. Esto tiene la ventaja
   de poder ejecutar el programa descargado simplemente saliendo de la
   terminal, siempre que el programa no haya sobreescrito el espacio de la
   misma.

   Streaming de audio PCM, la transferencia llevada al limite

   Originalmente las transferencias de datos se hacian con la maxima
   transferencia posible, pero esto apenas dejaba tiempo para procesar el
   byte recibido, almacenarlo en memoria, incrementar el puntero y decidir
   si se habia transferido la cantidad de bytes especificada. Todas esas
   tareas debian realizarse entre la recepcion del ultimo bit y el comienzo
   del siguiente byte. Recordemos que no habia pausas entre bytes. Debido a
   esta dificultad y a algunos errores de recepcion ocasionales se decidio
   hacer una transferencia byte por byte activando y desactivando RTS. Esto
   hizo muy seguras las transferencias pero tambien ligeramente mas lentas
   que el maximo teorico.
   La maxima transferencia posible de 5760 bytes por segundo hizo que
   surgiera la pregunta: y si transferimos audio digitalizado directamente
   al chip de sonido? 5760 bytes por segundo nos daria una calidad de 5760
   Hz, insuficiente para musica pero suficiente para representar la voz. Si
   pudieramos recibir un byte y colocarlo inmediatamente en la salida de
   sonido antes de que llegue el siguiente, tendriamos una transmision en
   vivo de audio digitalizado. En poco tiempo, luego de crear una rutina de
   recepcion especifica para esa funcion, se logro ajustar la temporizacion
   para recibir el audio correctamente. El audio PCM es el que conocemos
   como audio digitalizado, donde se representa el sonido con muestras de
   determinada calidad. Por ejemplo el audio de un CD tiene una calidad de
   16 bits, con un muestreo de 44100 Hz, es decir que en un segundo de
   audio hay 44100 muestras, cada una representada por 2 bytes. El metodo
   mas comun que usa la Commodore 64 para reproducir audio PCM es colocar
   cada muestra en el control de volumen, que tiene 16 niveles, esto es, un
   volumen de 4 bits. Si enviamos 5670 bytes por segundo, cada una de esas
   muestras debe colocarse en el volumen luego de recibidas. Pero si el
   volumen es de 4 bits, estamos desperdiciando la mitad de cada byte.
   El siguiente experimento fue compactar el audio de manera de almacenar 2
   muestras de 4 bits por byte, lo cual duplicaba la transferencia, ya que
   ahora transferiamos el doble de datos. Esto hizo que la cantidad de
   muestras por segundo aumentara a 5760 x 2 = 11520. Que significa esto?
   Que ahora podiamos enviar audio en vivo a una calidad de 4 bits y con un
   muestreo de 11,5 KHz, exagerado para la voz y suficientemente razonable
   para que la musica sea reconocible.
   Ahora no solo habia que lograr recibir un byte, sino que durante la
   propia recepcion habia que colocar 2 muestras en la salida de sonido,
   una al empezar el byte y otra por la mitad, de manera de tener un
   muestreo mas o menos estable. Si bien requirio muchas pruebas y ajustes,
   esto tambien se logro sin detener en ningun momento la recepcion, que
   ocurre con la maxima transferencia posible, sin pausas entre bytes.

   Conclusion

   Retroterm, como dije varias veces, fue un pequeño experimento que se
   salio de control. Hoy es un proyecto que genero una terminal multimedia,
   un nuevo tipo de BBS para aprovechar esas caracteristicas, y un
   protocolo que continuamente se sigue actualizando. Al momento de
   escribir esto tenemos en las etapas finales de desarrollo una nueva
   version de la terminal y otra del BBS, con su correspondiente ampliacion
   del protocolo TURBO56K. La nueva version abandona las rutinas de
   impresion del sistema, implementando codigo propio. Esto se hizo para
   poder definir una ventana de texto que limite la region de pantalla
   donde se puede imprimir. Hay comandos para definir estas ventanas, y
   ahora la terminal tiene la capacidad de trabajar en pantalla dividida,
   mostrando en la parte superior una imagen grafica y en la inferior un
   texto, con el limite divisorio definible por comando. Tambien se agrego
   un comando para un nuevo tipo de streaming que envia en vivo los valores
   a colocar en los registros del chip de sonido, para poder reproducir
   musica ".sid" sin tener que descargarla a memoria.
   Cuando comence esto como un simple experimento, pense que no pasaria
   mucho tiempo antes de perder el interes y pasar a otro proyecto, pero un
   año despues todavia surgen ideas interesantes para probar. Tambien hay
   que decir que las cosas podian haber salido mal desde el principio, y
   tal vez este proyecto no habria llegado muy lejos. En el camino se fue
   sumando gente para las pruebas, para poner los BBS en linea, y para la
   programacion, tanto de la terminal como del BBS. Hace mucho tiempo que
   este proyecto dejo de ser el trabajo de una sola persona.
   Y en el futuro, cuando no haya mucho mas que explorar en una C64, puede
   que haya versiones para otras plataformas, muy probablemente Commodore
   128, y puede que hasta maquinas tan diferentes como las MSX.

   ========================================================================
   FILES:
         -> bin/RTERM011-MDM.prg   (para MODEM WIFI en C64)
         -> bin/RTERM011-CART-VICE.prg (para TURBO232 o VICE)

   ========================================================================

   Pagina del proyecto: www.pastbytes.com/retroterm
   Email de contacto:   [email protected]
   Pastbytes > Usuario y programador de computadoras desde 1986 /
               Usuario de Amiga desde 1992 / Retrocomputacion



   ______________________________________________________________________________
   !EOF -> atdt-zine-0x03-12.txt