_______________________________________________________________________
/*
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