Computadora casera de la placa AON

Recientemente, han aparecido en Habré varios artículos sobre computadoras caseras creadas a partir de varios componentes no estándar. También decidí hablar sobre mi computadora, creada en 1993. A raíz del entusiasmo general por sinclair, quería tener una computadora de 8 bits completamente original basada en z80 y, además, crear un software para ella, comenzando desde el sistema operativo y terminando con juguetes. Lo que salió de eso, leer debajo del corte.

La primera pregunta que surgió al crear su computadora fue la cuestión de la arquitectura. Decidí que sería lo suficientemente compacto, basado en el procesador z80, sin mostrar una imagen en un televisor, pero con una pantalla de texto LCD, un teclado bastante grande, salida de sonido en forma de tweeter de tono único (estándar en ese momento para la mayoría de las computadoras) y un puerto RS232 para conectar a otras computadoras con fines de programación y depuración.

Sin embargo, había un problema donde obtener una placa de circuito impreso para un circuito completamente original, porque en 1993 los chinos aún no habían producido placas para todo el mundo, y era muy costoso ordenar el desarrollo y la producción en la fábrica. Y luego volví mi atención a los tableros de los que se hicieron las identificaciones de llamadas: identificaciones automáticas de llamadas. Estaban a la venta en el mercado de Mitinsky, tuvieron la oportunidad de instalar los componentes que necesitaba, pero que necesitaba mejorar. A la venta había varias variedades de placas de circuito impreso de las cuales, si mi memoria me sirve, elegí una placa llamada "Rus".

Permítanme recordarles a los jóvenes lectores qué era AON. Era un teléfono con marcación de botones (por cierto, en ese momento era bastante bueno, ya que la mayoría de los teléfonos tenían un disco giratorio), que constaba de 12 botones y un indicador luminoso de 9 bits y 7 segmentos, en el que se mostraba el número de teléfono, si fue posible determinar y alguna otra información. La placa AON contenía un procesador z80, un puerto paralelo 58055, un circuito decodificador, un temporizador 58053, una ROM de 32 kilobytes (con borrado ultravioleta), una RAM estática de 8 kilobytes, la parte analógica conectada a la línea telefónica y, posiblemente, algo más, lo que olvidé en los últimos años.

El teclado de 12 botones y el indicador disponible en el identificador de llamadas no me convenían categóricamente, ya que normalmente no podían ingresar información o mostrarla (en particular letras). Por lo tanto, se decidió utilizar un teclado casero de 40 botones y una pantalla LCD de texto de 24 líneas y 2 líneas, que luego apareció a la venta. Para conectar el teclado y la pantalla LCD, fue necesario modificar el esquema AON. Lo primero que hice fue tirar toda la parte analógica asociada con la línea telefónica, o mejor dicho, simplemente no la sellé. Al mismo tiempo, se liberaron las patas de salida en el decodificador, que seleccionó el indicador de descarga y las patas en el puerto paralelo 58055. La pantalla LCD requería 4 líneas para transmitir información, pero para el teclado era necesario usar un decodificador.Dado que 40 botones en el teclado estaban dispuestos en una matriz de 5 filas de 8 piezas, se decidió conectar estos 8 botones al decodificador para que pudieran escanearse proporcionando diferentes combinaciones de tres líneas a la entrada del decodificador y leyendo 5 valores de las filas de botones usando el KR580VB55. Por lo tanto, un código de escaneo del botón presionado en el teclado tenía un tamaño de un byte, donde los primeros tres bits determinaron la columna en la que se presionó el botón, y los 5 bits restantes indicaron en qué fila se presionó este botón (o varios botones a la vez) . Además, consideré que 8 kilobytes de RAM no serían suficientes y lo reemplacé con 32 kilobytes. Al mismo tiempo, tuve que volver a soldar un par de pistas en la placa de circuito impreso, afortunadamente, las cajas de RAM de 8 y 32 kilobytes eran casi idénticas en pinout. De este modo,Obtuve 32 kilobytes de ROM y 32 kilobytes de RAM (recuerdo que el z80 puede direccionar un máximo de 64 kilobytes, por lo que utilicé el espacio de direcciones al máximo). Además, dos líneas más de 58055 se dirigieron al puerto serie RS232, que es necesario para conectarse a otra computadora. Puse toda esta economía en el caso del probador. El resultado es este diseño:

imagen

Una vez que se realizó el hardware, llegó el momento de crear software. Aquí debe tenerse en cuenta que el proceso de su creación no se parecía en absoluto a lo que parece hoy. En primer lugar, la mayor parte se escribió en ensamblador z80 (aunque en ese momento casi todos los programas para tales sistemas se escribieron en ensamblador, bueno, excepto BASIC). Para la compilación del ensamblador en la primera etapa, mi amigo me ayudó, que tenía una computadora Profi, un clon sinclair, pero con TR-DOS a bordo. Luego comencé a usar mi PC IBM, que era OS / 2, que ejecutaba MS-DOS en una ventana separada, en la cual, a su vez, se lanzó el emulador TR-DOS, en el que se realizó la compilación. Debo decir que cuando el software creció notablemente, el proceso de compilación y ensamblaje tomó diez minutos. El segundo problema fueque no existían herramientas de depuración y, por lo tanto, era necesario descargar todo cada vez en mi computadora casera y verificar cómo funciona (lo primero que tenía que hacer era un programa para trabajar RS232 a 9600 bits por segundo para descargar). Y finalmente, debe decirse que después de depurar la imagen de la ROM, fue necesario escribirla en esta ROM misma, ya que previamente había borrado lo que ya estaba escrito allí. El borrado se realizó usando una lámpara ultravioleta para broncearse a través de una ventana especial en la carcasa del microcircuito, que luego se cubrió con un papel adhesivo negro especial, que sirve para sellar el orificio en el lado de un disquete de 5 pulgadas para protegerlo de la escritura. Además, como no tenía un programador, para escribir una nueva versión del software en ROM, cada vez que tenía que ir con mi amigo al otro extremo de Moscú,quien tuvo este programador. Aquí es necesario aclarar la pregunta, ¿cómo fue posible depurar la imagen de la ROM sin cargarla en esta ROM? Había una dirección base para esto, que utilizaba todo mi software, cambiando las direcciones en 32 kilobytes. Es decir, se cargó una nueva imagen de ROM en la RAM y se depuró allí, y después de la depuración, la dirección base se estableció en cero, todo se compiló nuevamente, y fui a un amigo para escribir una nueva versión en ROM.todo fue compilado nuevamente y fui a un amigo para escribir una nueva versión en ROM.todo fue compilado nuevamente y fui a un amigo para escribir una nueva versión en ROM.

Cuando se depuró el proceso de "codificación" - "depuración" - "firmware", surgió la cuestión de escribir un sistema operativo. El sistema operativo tenía que admitir la entrada del teclado, mostrar información en una pantalla LCD, admitir la salida de diferentes sonidos y hacer todo esto en paralelo, si es posible, es decir, realizar múltiples tareas. Para todo esto, se eligió la siguiente arquitectura: en el sistema operativo había tres tipos de tareas: varias tareas en tiempo real con la máxima prioridad, una tarea de usuario que interactuaba con la persona misma y tareas en segundo plano que funcionaban cuando el procesador estaba inactivo. Colgué tareas con la máxima prioridad en la interrupción, que fue generada por el temporizador KR580VI53 10 veces por segundo. Cabe decir que en la identificación de llamadas, las interrupciones se generaron 400 veces por segundo, porque era necesario actualizar el indicador con mucha frecuencia parapara que una persona no note parpadeo. Además de actualizar el indicador en interrupciones, se sondeó el teclado para buscar la tecla presionada. Una interrupción tan frecuente en AON condujo al hecho de que la mayor parte del tiempo del procesador se dedicó a interrupciones, y quería que mi computadora hiciera algo más útil. Como instalé una pantalla LCD como dispositivo de visualización de información, que tenía su propia memoria y no necesitaba una actualización dinámica, ya no era necesaria esa frecuencia de interrupción. Se estableció experimentalmente que 10 interrupciones por segundo son suficientes para sondear el teclado.que la mayor parte del tiempo del procesador se dedicó a interrupciones, y quería que mi computadora hiciera algo más útil. Como instalé una pantalla LCD como dispositivo de visualización de información, que tenía su propia memoria y no necesitaba una actualización dinámica, ya no era necesaria esa frecuencia de interrupción. Se estableció experimentalmente que 10 interrupciones por segundo son suficientes para sondear el teclado.que la mayor parte del tiempo del procesador se dedicó a interrupciones, y quería que mi computadora hiciera algo más útil. Como instalé una pantalla LCD como dispositivo de visualización de información, que tenía su propia memoria y no necesitaba una actualización dinámica, ya no era necesaria esa frecuencia de interrupción. Se estableció experimentalmente que 10 interrupciones por segundo son suficientes para sondear el teclado.

Por lo tanto, las tareas en tiempo real se lanzaron en cada interrupción y colocaron nueva información en una cola de eventos especiales. Los eventos fueron de varios tipos y contenían información correspondiente al tipo de evento, por ejemplo, el evento "botón presionado" contenía un código de escaneo. En realidad, una de las tareas prioritarias que comenzaron en cada interrupción fue la tarea de sondear el teclado y eliminar mediante programación el rebote de contacto. Además de esta tarea, también había tareas prioritarias: temporizadores que la tarea del usuario podía establecer y que, después de un tiempo específico, pusieron en cola el evento correspondiente, hubo alarmas que funcionaron en un momento, reloj y calendario determinados, y también hubo una tarea que reproducía música usando programación KR580VI53, y la entrada a la misma se alimentó con datos en forma de notas. De este modo,la tarea del usuario podría simplemente comenzar a reproducir música y hacer otras cosas.

El trabajo útil en mi computadora fue realizado por una tarea de usuario que fue impulsada por eventos. Una vista típica de tal tarea se parecía a:

while(true) {
  Event e;

  GetEvent(e);

  /* process event */
}


Aquí la función GetEvent (e) esperó a que el evento apareciera en la cola y, cuando apareció, completó la estructura del evento. Está claro que, de acuerdo con un determinado evento, el programa podría salir de un bucle infinito y transferir el control nuevamente al monitor del sistema, que lanzó las tareas del usuario. Dado que los eventos en la tarea del usuario generalmente se procesaron rápidamente, el programa esperó a que apareciera un nuevo evento en el procedimiento GetEvent (e). Para utilizar de alguna manera esta expectativa, se introdujeron tareas en segundo plano que el programa de usuario podía ejecutar y que funcionaba de forma independiente. Es decir, cuando se produce una interrupción del temporizador, las tareas en tiempo real se completaron primero colocando eventos en la cola, luego, después de la interrupción, la tarea del usuario procesó todos los eventos de la cola y el tiempo restante hasta la próxima interrupción se asignó a las tareas en segundo plano.Hoy, tal esquema parece natural, pero en 1993 fue muy progresivo.

Hubo otro problema relacionado con el hecho de que la pantalla LCD no podía mostrar letras rusas. Esto se debió al hecho de que tales indicadores acaban de aparecer en nuestro mercado y nadie los ha rusificado específicamente. Naturalmente, no había bibliotecas para trabajar con ellos, pero solo había una especificación y descripción de los comandos. Por lo tanto, todo el trabajo de inicialización y trabajo con él tuvo que ser escrito desde cero. Resolví el problema con la rusificación de la siguiente manera: se escribió un procedimiento especial, cuya entrada era una cadena con texto en ruso que debía mostrarse. Este procedimiento reemplazó todas las letras rusas que eran similares al latín con las letras latinas correspondientes, y las que eran imposibles de reemplazar se crearon sobre la marcha utilizando imágenes personalizadas que se podían descargar en la pantalla LCD. Se debería notarque contenía ocho de esas imágenes de usuario y, en consecuencia, en el texto ruso no podía haber más de ocho letras, análogas de las cuales no estaban en el alfabeto latino. Pero generalmente era suficiente. Otra oportunidad divertida que usé fue que si cambias las imágenes de usuario para un personaje, obtienes una animación divertida. Aproveché esta oportunidad en el juego de zapadores, que analizaré a continuación, donde la bandera sobre la mina ha ondeado al viento y la bomba explota.Aproveché esta oportunidad en el juego de zapadores, que analizaré a continuación, donde la bandera sobre la mina ha ondeado al viento y la bomba explota.Aproveché esta oportunidad en el juego de zapadores, que analizaré a continuación, donde la bandera sobre la mina ha ondeado al viento y la bomba explota.

Ahora te contaré sobre esas tareas de usuario que creé para mi computadora. Cuando comencé a crearlos, rápidamente me di cuenta de que escribirlos en ensamblador, como todos lo hicieron en ese momento para sistemas como sinclair, es bastante triste. Como programé C en una PC IBM, pensé si es posible programar en C y en mi computadora. Después de algunas búsquedas, encontré un compilador del lenguaje C para TR-DOS, además, en su versión clásica de K&R. Este compilador era bastante primitivo, por ejemplo, no verificó si el número de parámetros pasados ​​al procedimiento correspondía a su número real, sin mencionar la verificación de sus tipos. Pero si pudiera usar este compilador para mi computadora, sería un gran progreso. El problema era cómo adaptar el código recibido por este compilador para mi computadora.Aquí seguí el camino clásico, que ya nos hemos olvidado, y en 1993 todavía lo recordaban. De esta forma, se compilaba el código fuente no directamente en el archivo objeto, sino en el código fuente del ensamblador. Por lo tanto, solo era necesario escribir macros que permitieran llamar a los procedimientos del ensamblador compilados a partir del código y viceversa, con la transferencia correcta de parámetros, lo que se hizo. El uso de este compilador, además de la conveniencia de trabajar con código, proporcionó otra gran ventaja: se hizo posible trabajar con multiplicación / división de enteros (recuerdo que el z80 no tiene comandos de multiplicación y división de enteros), y también (¡y mira!), La capacidad de trabajar con números punto flotante. Sin embargo, para esto tuve que lidiar con la biblioteca adjunta al compilador,ya que todas las operaciones matemáticas después de la compilación se realizaron como una llamada a esta biblioteca. El problema era que esta biblioteca usaba variables temporales que el compilador colocaba en el modelo de memoria específico de TR-DOS, que, por supuesto, no correspondía completamente con el modelo de memoria de mi computadora. Tuve que buscar todas esas variables temporales y rehacerlas para las direcciones que se ajustan a mi RAM. Pero como beneficio adicional, obtuve muchas funciones estándar como seno y coseno, que utilicé en mis tareas, que analizaré a continuación.Tuve que buscar todas esas variables temporales y rehacerlas para las direcciones que se ajustan a mi RAM. Pero como beneficio adicional, obtuve muchas funciones estándar como seno y coseno, que utilicé en mis tareas, que analizaré a continuación.Tuve que buscar todas esas variables temporales y rehacerlas para las direcciones que se ajustan a mi RAM. Pero como beneficio adicional, obtuve muchas funciones estándar como seno y coseno, que utilicé en mis tareas, que analizaré a continuación.

El primer programa que se creó con el compilador de C fue un programa para verificar el correcto funcionamiento de la RAM. Este programa revisó toda la RAM, escribió y luego leyó varios patrones y comparó el resultado. Además, todo el proceso se mostró en la pantalla LCD, lo que también confirmó el correcto funcionamiento de los procedimientos asociados. Está claro que esto fue solo una prueba de la pluma antes de escribir programas más interesantes. Lo siguiente que hice fue crear un editor hexadecimal para modificar el contenido de la RAM. Este editor ya poseía posibilidades bastante amplias, que incluían no solo ver y editar celdas de memoria, sino también buscar bytes interesantes en la RAM. En particular, se hizo posible escribir pequeños programas directamente en RAM en códigos de máquina. Para probar las capacidades de sonido de su computadora,Creé un programa como una "caja de música" que tocaba varias melodías (recuerdo que las melodías se grabaron como notas). Además, se escribió un programa para el juego "toros y vacas", donde se le pidió a una persona que adivinara un número aleatorio de cuatro dígitos concebido por una computadora (sí, también hice un generador de números aleatorios). En este programa, tuve que crear una lista de desplazamiento con un historial de números ya ingresados, ya que era imposible mostrar una lista particularmente larga en dos líneas. El siguiente programa creado fue un clásico "zapador" en un campo de 16x16. Como solo tenía dos líneas a mi disposición, me desplacé, agregué acompañamiento musical y animación de una bandera ondeando al viento y haciendo estallar bombas. Además, para la meditación, hice un programa que mostraba gusanos arrastrándose en una dirección aleatoria,usando la capacidad de subir imágenes personalizadas a la pantalla. Bueno, ¿y dónde sin el clásico tic-tac-toe? En ellos probé el algoritmo minimax, es decir, la computadora calculó (bastante rápido) todas las opciones y nunca las perdió. Como mi sistema operativo soportaba alarmas, hora y un calendario, hice un programa de usuario que configuraba la hora, la fecha y varias alarmas que, cuando llegaban a la hora establecida, tocaban diferentes melodías. Y finalmente, la corona de la creación en mi computadora es un programa para calcular la trayectoria del movimiento en el problema de dos cuerpos gravitacionales. Es decir, para una posición inicial dada y la velocidad del cuerpo, así como la masa del centro de atracción,Se resolvió el problema de la integración numérica de un sistema de dos ecuaciones diferenciales ordinarias no lineales de segundo orden con un paso de integración dado. Para esto, agregué un procedimiento que integraba numéricamente estas ecuaciones. Todas las variables tenían formato de coma flotante doble. Aquí enfatizo una vez más que en el procesador z80 no solo hay soporte de hardware para trabajar con coma flotante, sino también la multiplicación / división habitual de enteros, todo se hizo mediante programación. Esta integración funcionó muy lentamente, aproximadamente un paso por segundo, ¡pero funcionó!pero también la habitual multiplicación / división de enteros, todo se hizo mediante programación. Esta integración funcionó muy lentamente, aproximadamente un paso por segundo, ¡pero funcionó!pero también la habitual multiplicación / división de enteros, todo se hizo mediante programación. Esta integración funcionó muy lentamente, aproximadamente un paso por segundo, ¡pero funcionó!

Lo que aún quería implementar, pero no funcionó: en primer lugar, la asignación dinámica / desasignación de memoria, para que pudiera administrar de manera flexible los recursos de cada tarea. Además, la grabación / lectura en cinta no se implementó, como se hizo en Sinclair. Pero en general, estuve satisfecho con lo que pude hacer. Destaco que todo lo anterior estaba en una ROM de 32 kilobytes, el tamaño actual de un correo electrónico no tan grande.

Puedes ver mi computadora en acción aquí:




Y descargue su software aquí

All Articles