Ya para mediados de la década de los setentas, tras el descubrimiento del transistor y el advenimiento de la electrónica de estado sólido, los avances espectaculares en la microelectrónica de alta integración habían permitido poner a la venta a costos increíblemente bajos “chips” semiconductores que contenían en esencia una unidad de procesamiento central completa, un CPU a bajo costo. La primera computadora que se podía construír en casa fue la Altair 8800, la cual hizo su aparición en 1975, pero cuyo costo superior a los mil dólares la ponía fuera del alcance de muchos aficionados y estudiantes de escuela secundaria y preparatoria interesados en este nuevo tipo de tecnología. Sin embargo, pronto hizo su aparición otro proyecto en 1976 basado en el microprocesador COSMAC CDP1802, un chip de 40 terminales vendido a un costo de 30 dólares fabricado por la empresa RCA (hoy extinta). Esta es una fotografía de dicho microprocesador:
El microprocesador 1802 podía ser conectado a cualquier combinación de memorias RAM y ROM pudiendo efectuarse un domiciliamiento de hasta 65,536 bytes (65k) de memoria. En su conjunto de instrucciones tenía incluída la capacidad para llevar a cabo operaciones programadas de entrada/salida de datos, acceso directo a la memoria RAM desde el mismo microprocesador, cuatro “banderas” (bits) de entrada verificables en cualquier momento por instrucciones de ramificación incluídas en el conjunto de instrucciones del microprocesador, y una matriz de registros en un acomodo 16×16 para ser usados ya fuese como contadores de programa múltiples, punteros de datos (apuntando hacia domicilios en el RAM en donde hay datos) o registros de datos. Otras características del chip 1802 eran la capacidad de poder operar con un voltaje que podía variar desde 3 volts y 12 volts de corriente directa (DC), compatibilidad con circuitos lógicos integrados de la familia TTL (Transistor Transistor Logic), e inclusive un reloj interno (había que facilitar un reloj externo para poder echar a funcionar el reloj del microprocesador).
En esos años, la gran mayoría de la gente estaba muy lejos de imaginarse que pronto llegarían los días en los cuales las computadoras caseras se volverían omnipresentes. En ese entonces, el impulso a estos primeros pasos fue dado por los aficionados a la electrónica a los cuales se les daba de poder construír en su propia casa su propia computadora, los cuales proporcionaron el mercado de arranque para darle ímpetu a la comercialización de la nueva tecnología. Había revistas de carácter popular, dirigidas a los aficionados a la técnica pero carentes de estudios avanzados en electrónica o informática, para los cuales se elaboraban artículos proporcionándoles la lista de componentes que tenían que adquirir en alguna tienda de artículos electrónicos como Radio Shack o que se podían comprar por correo, así como las instrucciones necesarias para poder emprender el proyecto personal de construcción de una computadora. La primera parte de uno de tales artículos apareció publicada en la edición de agosto de 1976 de la revista Popular Electronics bajo el título “BUILD THE COSMAC “ELF”: A low cost experimenter’s microcomputer”, elaborado por Joseph Weisbecker, cuya portada se muestra a continuación:
Por el valor instructivo de tal artículo, y con fines pedagógicos, se reproducirán aquí algunos de los elementos más importantes que aparecieron en dicho artículo. La computadora “Elf” (duende) utilizaba como componente principal el chip CPU COSMAC CDP1802.
Primero que nada, a continuación se reproducirá la apariencia física esquemática del semiconductor COSMAC CDP1802 (la indentación puesta por el fabricante en la parte superior del paquete plástico encapsulador rectangular era para permitirle a los usuarios el poder orientar al chip en su posición correcta evitando el error de montarlo al revés). Usaremos la simbolización que le fue dada a cada terminal por el mismo fabricante (desafortunadamente, esta simbolización varía de fabricante a fabricante, y dista mucho de ser una simbolización universal):
Dado el diagrama anterior, podemos proceder a dar una explicación sobre las funciones de cada una de las terminales del microprocesador 1802.
Primero que nada, para quienes están familiarizados con la ingeniería electrónica, será más que obvio que el microprocesador 1802 fue construído utilizando tecnología CMOS (Complementary Metal Oxide Semiconductor), una tecnología que requiere un consumo sumamente bajo de energía en contraste con otras tecnologías como la tecnología TTL (Transistor Transistor Logic). Esto se deduce de la identificación de las terminales 40 y 20 como Vdd y Vss, los cuales son los símbolos de los voltajes referenciados en la terminología de la familia de semiconductores CMOS, de este modo la terminal 40 se conecta a un voltaje positivo (el cual puede ser cualquier voltaje entre 3 volts y 12 volts) y la terminal 20 se conecta a un voltaje negativo o cero. Obsérvese que las dos terminales en las cuales hay que aplicar el voltaje que pondrá en funcionamiento al microprocesador están situadas físicamente en extremos opuestos, en las esquinas más distantes del chip. Como ya se dijo, el reloj del microprocesador requiere del uso de un cristal externo (simbolizado como XTAL) que tiene que ser conectado entre las terminales 1 y 39.
Las ocho terminales BUS del microprocesador (de la terminal 8 a la terminal 15) son utilizadas ya sea para depositar bytes en el bus de datos, o para recibir bytes del bus de datos. Puesto que se puede depositar información en bytes en el bus así como recibir información en bytes del mismo, estas ocho terminales son bidireccionales, indicando con esto que la información puede fluir del microprocesador hacia afuera o hacia adentro del microprocesador.
Por otro lado, las ocho terminales MA (Memory Adress) del microprocesador (de la terminal 25 a la terminal 32) son utilizadas para el domiciliamiento de la memoria RAM. Esto aclara un poco más el funcionamiento del microprocesador. En cierto punto en la ejecución del programa en lenguaje de máquina, el microprocesador deposita en el bus de la memoria un domicilio como 00010101, y si hay suficiente memoria RAM para que ese domicilio sea alcanzable, entonces la memoria RAM depositará en el bus de datos el byte que está contenido dentro del domicilio RAM 00010101, y el microprocesador tomará ese byte del bus de datos para darle algún uso interpretando al byte ya sea como una instrucción o como un dato.
Las terminales N0, N1 y N2 del microprocesador 1802 son utilizadas en conjunto por el microprocesador para seleccionar (bajo la guía de un programa elaborado en lenguaje de máquina) dispositivos externos de entrada/salida. Puesto que hay tres dígitos binarios disponibles, se pueden seleccionar hasta ocho dispositivos de entrada/salida. La combinación La combinación N0N1N2.=.000 se puede usar, por ejemplo, para seleccionar una impresora. La combinación N0N1N2.=.101 se puede usar, por ejemplo, para seleccionar un monitor. Y así sucesivamente.
Podemos ampliar el diagrama anterior del microprocesador 1802 con información un poco más detallada, dada por el mismo fabricante (la cual aunque está en inglés resulta entendible por las funciones involucradas):
A continuación se tiene el diagrama funcional de la computadora Elf basada en el microprocesador 1802 y sobre cuya operación estaremos hablando:
Diagrama funcional de bloque de la computadora Elf
Hasta 65K bytes de memoria, 91 instrucciones, y puertos variados de entrada/salida
pueden ser agregados conforme va creciendo el sistema
La clave para entender la computadora es la comprensión del método usado para llevar a cabo el domiciliamiento de la memoria. Al principio, este procedimiento puede parecer complicado, pero pronto se puede apreciar que no es tan difícil.
El chip 1802 contiene 16 registros de propósito general, cada uno capaz de almacenar 16 bits (dos bytes). Los registros son numerados de R a R en conformidad con el sistema de numeración hexadecimal, como se muestra en la siguiente figura (en los diagramas esquemáticos de los circuitos, y en la terminología computacional en general, es frecuente distinguir el número “cero” (0) de la letra mayúscula latina “O” mediante lo que se conoce como el “cero danés” Ø, un cero con una línea diagonal que lo atraviesa, y tal cosa estaremos haciendo aquí para habituarnos a esta costumbre):
Los 16 registros en el 1802 son designados de RØ a RF (hexadecimal)
Hay también un registro D de ocho bits que es utilizado para mover bytes de un lado a otro. En el conjunto de instrucciones del procesador 1802 mostrado en parte (más abajo) en la Tabla del Subconjunto de Instrucciones, obsérvese que el código de operaciones (Códigos Op) 8N copiará un byte de orden bajo del registro general hacia el registro D. Escribiendo esta instrucción como 81 en un programa causará que R1.Ø sea copiado hacia el registro D cuando una instrucción sea ejecutada. Podemos usar entonces la instrucción BF (BN en la tabla, con B y un dígito numérico hexadecimal) para copiar el byte D hacia RF.1. Toma dos bytes, 81 BF, el transferir un byte de R1.Ø a RF.1 mediante el registro de almacenamiento temporal D. El byte en el registro D puede ser usado también en operaciones aritméticas llevadas a cabo en los circuitos (internos) de la unidad de Aritmética y Lógica (ALU) del 1802.
Hay otros dos registros importantes etiquetados como N, P y X (Véase arriba el diagrama de bloque de la computadora básica). Cada uno de ellos puede almacenar un dígito de 4 bits que es usado para seleccionar uno de los 16 registros de propósito general. Por ejemplo, si se quiere hablar acerca del registro de propósito general seleccionado por el dígito hexadecimal en X, se le llamaría RX. Si lo que se desea es simplemente el byte de orden bajo de RX, llámesele RX.Ø. RN se referirá al registro de propósito general designado por el dígito de cuatro bits que está contenido en N; si el dígito es 4 entonces RN.=.4.
Los registros de propósito general pueden contener domicilios de la memoria de 16 bits. Supóngase que el registro R3 contiene el dato 0012. M3 se interpreta como la localidad de la memoria especificada por los contenidos de R3, y M(0012) significa directamente la locallidad de la memoria 0012. MX significa la localidad de la memoria domiciliada por los contenidos del registro general seleccionado por el dígito actualmente en X. Si X.=.3, entonces MX.=.M3; si R3.=.0012, entonces MX = M3 = M(0012).
La siguiente tabla nos proporciona una sinopsis sobre el propósito de cada uno de los registros del procesador 1802:
Registro | Bits | Descripción |
---|---|---|
D | 8 | Registro de Datos |
DF | 1 | Bandera de Datos, Data Flag (Llevar/Tomar Prestado) |
R(0-f) | 16 | Registros Generales |
P | 4 | Especifica cuál registro R es el contador del Programa |
X | 4 | Especifica cuál registro R apunta hacia datos |
I | 4 | Nibble alto del byte de instrucción, no accesible directamente |
N | 4 | Nibble bajo del byte de instrucción, no accesible directamente |
T | 8 | Contiene X y P durante interrupción, X es nibble alto, no accesible directamente |
IE | 1 | Habilitación de Interrupción (Interrupt Enable) |
Q | 1 | Flip-Flop de Salida |
Puesto que la computadora básica Elf tiene únicamente 256 bytes de memoria, podemos usar únicamente los bytes usualmente llamados bytes “de orden bajo” de los registros generales para domiciliar la memoria. En sistemas de memoria expandida, podemos usar los “bytes de orden alto” de los registros de propósito general para seleccionar páginas individuales de 256 bytes de memoria de acceso aleatorio (RAM). Se recuerda que un byte al contener 8 bits puede especificar únicamente 256 domicilios diferentes, mientras que una palabra binaria formada por dos bytes, o sea 16 bits, puede especificar una cantidad mucho mayor de domicilios, y bastaría con agregar al byte de orden bajo un “bit” de orden alto, el cual puede tomar los valores “0” y “1”, para especificar el doble de los domicilios, o sea 512 domicilios de memoria, usando para ello dos “páginas” de memoria RAM.
La memoria contiene tanto bytes de instrucciones (en lenguaje de máquina) como bytes de datos. Los bytes de instrucciones le dicen a la computadora qué hacer con los bytes de datos. Las instrucciones de un byte tienen dos dígitos hexadecimales, en donde los bits de orden alto 7, 6, 5 y 4 le dicen a la computadora qué tipo de operación debe llevarse a cabo. Los bits de orden bajo, 3, 2, 1 y Ø usualmente son puestos en el registro N cuando una nueva instrucción es procurada de la memoria.
Cualquiera de los 16 registros de propósito general pueden ser usados como un contador de programa . El contador de programa efectúa el domiciliamiento de los bytes de instrucción que hay en la memoria. Cada vez que una instrucción es buscada en la memoria, el contador de programa es incrementado automáticamente de modo tal que apunta hacia la siguiente instrucción que será procurada. Las instrucciones de ramificación (branch) pueden ser usadas para cambiar el domicilio en el contador de programa para permitir saltar (ramificar) hacia una parte diferente del programa cuando así se desee. El dígito en el registro P de cuatro bits especifica cuál registro de propósito general de 16 bits está siendo usado como contador de programa.
Puesto que muchas de las instrucciones del microprocesador 1802 son de únicamente un byte de extensión y requieren de dos ciclos de máquina, el primer ciclo siempre es una búsqueda de instrucción, o lectura de la memoria. La instrucción procurada es ejecutada durante el siguiente ciclo de máquina, que puede ser una lectura de la memoria, una escritura hacia la memoria, o un ciclo del tipo de transferencia de registro.
La ejecución del programa siempre consiste de una secuencia de ciclos de búsqueda-ejecución, y las dos líneas SC0 y SC1 (terminales 5 y 6 en el diagrama del procesador 1802) indican qué tipo de ciclo está siendo llevado a cabo de acuerdo con los siguientes criterios:
SC1 | SCØ | Tipo de ciclo de máquina |
0 | 0 | Búsqueda de instrucción |
0 | 1 | Ejecución de instrucción |
1 | 0 | Entrada/salida DMA |
1 | 1 | Interrupción |
El acceso directo a la memoria (DMA, Direct Memory Access) y la interrupción son tipos especiales de ciclos que serán discutidos posteriormente.
Antes de continuar con la discusión, veremos lo que ocurre desde la perspectiva de los diagramas de tiempos cuando se lleva a cabo un acceso directo a la memoria de acceso aleatorio RAM ya sea para leer de la memoria o para escribir hacia la memoria. Primero que nada, hay que seleccionar la localidad de la memoria que queremos accesar. Suponiendo una memoria RAM de un solo bit, esto se lleva a cabo “encendiendo” la línea de domiciliamiento (que llamaremos “seleccionar”) con un “1”, y una vez que se ha hecho tal cosa se puede leer o escribir hacia esa localidad que contiene un bit usando otra línea (que llamaremos “activar”), tras lo cual se puede desactivar la línea de seleccionamiento removiendo el “1” enviándolo al nivel “0” como se muestra en el siguiente diagrama de tiempos (obsérvese que estamos trazando un diagrama de tiempos “realista” que toma en cuenta el hecho de que en ningún circuito eléctrico es posible ir instantáneamente de un “0” a “1” ó de un “1” a un “0”, sino que hay un tiempo de subida o rise time así como un tiempo de bajada o fall time proporcionado en las especificaciones técnicas de todos los circuitos integrados, enfatizándose el hecho de que es precisamente el que los tiempos de ascenso y de descenso no sean iguales a cero lo que limita la velocidad teórica máxima a la cual puede trabajar cualquier circuito físico real):
En una situación real, usamos no una sino varias líneas para especificar el domiciliamiento de uno entre varios bits almacenados en la memoria RAM. Si lo que queremos es llevar a cabo una lectura de un bit almacenado en una memoria RAM que es domiciliada con ocho líneas etiquetadas desde AØ hasta A7, podemos hacerlo de una manera como la que se muestra a continuación (en el ejemplo, a la línea AØ se le pone un “1” subiéndola del “0” en el que estaba previamente, a la línea A1 también se le pone un “1” subiéndola del “0” en el que estaba previamente, a la línea A2 se le pone un “0” bajándola del “1” en el que estaba previamente, y así sucesivamente, hasta que el domicilio especificado que en el ejemplo vendría siendo 11010010):
En la literatura técnica, se acostumbra abreviar un diagrama de tiempos como el anterior, que ejemplifica la activación/desactivación simultánea de las varias líneas usadas para especificar el domiciliamiento de la memoria RAM, con un diagrama de tiempos como el siguiente:
Hecha la anterior aclaración, los diagramas de tiempos de la computadora Elf son mostrados en la siguiente figura:
Obsérvese que cada ciclo de máquina requiere de ocho pulsos de “reloj”. Las líneas TPA y TPB controlan varias funciones, tanto en como fuera de la computadora.
A continuación, y para poder entrar en mayores detalles, se reproduce el diagrama esquemático completo de la microcomputadora Elf. Este es el tipo de diagramas esquemáticos eléctricos que acostumbran utilizar los técnicos encargados de darle mantenimiento tanto a las computadoras de todo tipo como a los sistemas de instrumentación y control basados en el uso de algún microprocesador (se requiere ampliar la imagen para poder apreciar los detalles con mayor claridad):
Circuito completo para la computadora Elf
Obsérvese en este diagrama esquemático que la compuerta lógica NAND de tres terminales simbolizada como IC10A (un circuito ):
tiene sus tres terminales de entrada conectadas entre sí, lo cual implica que en realidad tal compuerta está siendo utilizada como un inversor NOT lógico.
Además del diagrama esquemático que muestra el circuito completo para la computadora Elf, se tiene el siguiente diagrama esquemático de los circuitos de control para la misma:
En el diagrama esquemático anterior, el circuito integrado LM309K no es un circuito integrado que lleve a cabo funciones lógicas de ningún tipo. Se trata de un regulador de voltaje y es por lo tanto un circuito integrado analógico. Casi nunca se muestra diagrama funcional alguno sobre los componentes eléctricos interiores (resistencias y transistores) al LM309K, en virtud de que hay diversos fabricantes para este tipo de circuito integrado y cada uno de ellos usa su propio diseño eléctrico para llevar a cabo las funciones de regulación de voltaje. El propósito del LM309K es tomar un voltaje en la terminal 1 que puede ser objeto de fluctuaciones, y entregar en la terminal 2 de salida un voltaje más constante a la salida libre de ruido eléctrico, el cual se manifiesta frecuentemente como un rizo superimpuesto sobre la corriente directa que sin el rizo sería un voltaje que permanece constante con el tiempo (o sea, una línea plana horizontal en el diagrama del voltaje con respecto al tiempo). En una fuente de poder convencional clásica en la cual se lleve a cabo una rectificación de media onda tomando como entrada una fuente senoidal de voltaje alterno y aplicándola a un diodo rectificador, si se aplica la señal con media rectificación a un condensador electrolítico se puede obtener casi un voltaje de corriente directa con un rizo superimpuesto sobre el mismo:
Y como se muestra en la figura de arriba, si el voltaje de corriente directa (DC) que lleva un rizo de corriente alterna (AC) superimpuesto sobre el mismo es enviado a un circuito de filtraje como el circuito tipo Π (pi) que se muestra arriba, se obtiene algo muy cercano a un voltaje de corriente directa. Las mismas consideraciones técnicas aplican en el caso de un rectificador de onda completa:
El regulador de voltaje LM309K, que siendo un circuito integrado al que por cuestiones de tamaño no se le puede meter un transformador de poder y ni siquiera un inductor L como el que se muestra en la figura de arriba, por sí solo no resulta suficiente para dar un voltaje bien regulado libre de rizo, y es por ello que se le agregan dos capacitores C1 y C2 de 10 microfarads cada uno, uno a la entrada y otro a la salida, para que actúen como filtros que reduzcan aún más el “rizo” de corriente alterna variante que pueda estar presente en lo que debe ser un voltaje de corriente directa que se debe mantener lo más constante posible.
En el diagrama esquemático del circuito completo de la computadora Elf, los circuitos integrados IC8 e IC9 ambos son interruptores (switch) de tipo bilateral en cantidad cuádruple (quad) modelo 4016 cuyo diagrama esquemático funcional se presenta a continuación:
Este circuito integrado es eléctricamente semejante (y compatible terminal a terminal) con el circuito integrado 4066 que ya se discutió previamente en una entrada previa titulada “La lógica de tres estados” (véase), y como puede apreciarse los dos circuitos integrados 4016 son utilizados en la microcomputadora Elf para establecer una conexión eléctrica o hacer “flotar” las entradas con respecto a las salidas proporcionando una desconexión eléctrica tri-state (en la lógica de tres estados) de las entradas con respecto a las salidas.
A continuación se reproduce la lista de partes requerida para ensamblar la computadora Elf. Obsérvese que ya a partir de la década de los setentas la construcción de equipos digitales basados en microprocesadores se basaba en reunir circuitos integrados de diversas funciones para conectarlos en forma apropiada de acuerdo a las instrucciones de los fabricantes, convirtiendo al diseñista en un ensamblador de “cajas negras” más que en un ingeniero electrónico preocupándose por las características de los transistores usados para implementar cada función lógica básica en la unidad de procesamiento central:
Listado de partesUna computadora Elf, construída y terminada de acuerdo a las especificaciones dadas en el artículo, tiene el siguiente aspecto:
C1, C2 - capacitor electrolítico de 10 μF, 16 volts
C3, C4 - capacitor de disco de 30 pF
IC1 - CDP1802 microprocesador COSMAC (RCA)
IC2, IC3 - circuito integrado 2101 de RAM estático (256×4)
IC4, IC5 - circuito integrado 4050 de buffer hex no-inversor
IC6, IC7 - display hexadecimal LED (H-P No. 5082-7340)
IC8, IC9 - circuito integrado 4016 switch quad bilateral
IC10 - circuito integrado 4023 compuerta NAND triple de tres entradas
IC11 - circuito integrado 4049 de buffer hex inversor
IC12 - circuito integrado 4013 flip-flop D dual
IC13 - circuito integrado LM309K regulador de voltaje de 5 volts
LED1 - diodo LED emisor de luz roja
R1 a R9 - resistencia de 47,000 ohms, 1/4 watt
R10 - resistencia de 470 ohms, 1/4 watt
R11 - resistencia de 10 megohms, 1/4 watt
S1 a S11 - switch de dos vías SPDT (single pole double throw)
S12 - interruptor de switch con un conjunto de contactos normalmente abiertos y normalmente cerrados
XTAL - cristal de cuarzo de 1 a 2 Megahertz
Miscelánea - tarjeta fenólica perforada para montaje de circuitos electrónicos de 5-1/2"×4" (14×10.1 cm) con un espaciamiento de 1" (2.54 cm) entre los agujeros, cuatro sockets para circuitos integrados de 14 terminales, tres sockets para circuitos integrados de 16 terminales, dos sockets para circuitos integrados de 22 terminales, un socket para un circuito integrado de 40 terminales (para el montaje del microprocesador), un conector para la fuente de poder de corriente directa, una fuente de poder de corriente directa de 9 volts 350 mA, soldadura, rieles de madera, etc.
El microprocesador 1802 tiene un circuito interno de reloj de fase sencilla (ha habido otros microprocesadores como el 6800 fabricado por Motorola y el 8080 fabricados por Intel que usaban pulsos de reloj de dos fases Φ1 y Φ2, llamados apropiadamente reloj de dos fases o two-phase clock). Conectando un cristal de cuarzo (identificado en los diagramas esquemáticos como XTAL) entre las terminales 1 y 39 del microprocesador 1802 (como se muestra arriba) hace que el reloj funcione de modo continuo sin interrupciones de ninguna especie. Si se desea (véanse los diagramas esquemáticos eléctricos), los componentes XTAL, C3, C4 y R11 pueden ser omitidos y se puede substituir todo con un reloj externo que envíe una serie de pulsos rectangulares con una variante de 5 volts entre las terminales 1 y tierra.
A cpntinuación se muestra el diagrama funcional del circuito integrado RAM 2101 usado para la memoria activa básica de la computadora Elf:
Este tipo de memoria tiene las terminales de entrada y de salida puestas por separado (a diferencia de otras memorias RAM como el circuito integrado 2111 en el cual las terminales de entrada pueden actuar también como terminales de salida, permitiendo la conexión directa de tales terminales de entrada/salida hacia el bus de datos). Para acceder a la memoria 2101, la terminal 19 (CE) debe ser puesta a tierra (nivel eléctrico bajo) y a la terminal 17 (CE2) se le debe aplicar el voltaje de la fuente (poniéndola a nivel alto) para habilitar el chip, esto tanto para leer como para escribir. Para leer de la memoria, a la terminal 20 R/WR se le aplica un nivel alto y la terminal 18 es puesta en nivel bajo. Un domicilio binario aplicado a las ocho terminales de los domicilios de entrada seleccionará cuatro celdas internas de almacenamiento poniendo los bits almacenados en esas celdas en las cuatro líneas de salida. Para escribir a la memoria, se empieza con un nivel alto aplicado a la terminal 20 R/WR tras lo cual el nivel en dicha terminal es cambiado a nivel bajo y regresado posteriormente a nivel alto. Todas las líneas de domiciliamiento deben permanecer estables antes, durante y después del estado bajo en la terminal 20 para que la operación de escritura pueda ser concluída. Haciendo la terminal 19 positiva o aterrizando a tierra la terminal 18 pondrá a “flotar” haciendo que se ignoren los comandos de escritura a la memoria. Haciendo la terminal 18 positiva flotará las salidas pero permitirá escribir a la memoria. Estas terminales adicionales resultan útiles cuando se usan buses comunes o sistemas de chip múltiples.
Durante cada ciclo de máquina, hay pulsos temporizadores (pulsos de tiempos) disponibles en las terminales TPA (Timing Pulse A) y TPB (Timing Pulse b) del 1802. TPA ocurre al inicio de cada ciclo de máquina y puede ser utilizado para fijar los tiempos del bit de orden alto de un domicilio de memoria de 16 bits hacia un registro de selección de páginas de memoria. Obsérvese que el 1802 envía fuera los domicilios de la memoria como dos bytes de 8 bits. El byte de orden alto aparece primero en las líneas de domiciliamiento de AØ a A7. Entonces el byte de orden bajo es puesto en las líneas AØ hasta A7 por el remanente del ciclo de máquina. Este byte de domiciliamiento de orden bajo puede, por sí solo, especificar una de las 256 localidades en la memoria mínima de 256 bytes.
TPB ocurre hacia el final del ciclo de máquina y es usado para temporizar (clock) un byte de la memoria RAM hacia un dispositivo de salida (tal como la carátula hexadeximal usada aquí). Un byte de entrada, a ser almacenado en la memoria RAM, es dirigido mediante acción de compuerta hacia el bus de datos por la duración del ciclo de entrada (escritura a la memoria) de modo tal que no se requiere un pulso temporizador para bytes de entrada.
La línea MREAD está baja (en nivel cero) durante cualquier ciclo de máquina de lectura de memoria (obsérvese que aquí se hace uso de lo que se conoce como lógica negativa, en donde es la ausencia de un “1” en lugar de la presencia del “1” es lo que activa la función, en este caso una operación de MEMORY READ o MREAD). Cuando la terminal está baja, abre las compuertas de datos de salida del RAM de 18 terminales (pins) de los circuitos integrados IC2 e IC3 (circuitos integrados MOS de memoria estática RAM 2101 capaces de poder almacenar cada uno de ellos un total de 256 palabras binarias de 4 bits, razón por la cual se requiere de dos chips RAM 2101 para poder almacenar 256 bytes de 8 bits por byte), permitiendo que el byte almacenado en la localidad de la memoria RAM domiciliada desde AØ hasta A7 aparezca en el bus de datos. El tiempo de acceso del RAM es tal que el byte de salida aparece en el bus antes de TPB. El byte del bus del RAM puede ser entonces temporizado hacia un registro interno del 1802, o temporizado hacia un registro externo (tal como la carátula hexadecimal) con TPB, dependiendo del tipo de instrucción que esté siendo ejecutada.
Cuando el 1802 está llevando a cabo un ciclo de instrucción que requiere que un byte sea almacenado en la memoria RAM, la línea MREAD es mantenida en nivel alto (en un “1”) para inhabilitar las compuertas de salida del bus del RAM. El microprocesador ocasiona entonces que el byte que está almacenado en la memoria sea dirigido mediante acción de compuerta hacia el bus durante el ciclo de escritura de memoria. Este byte puede venir de un registro interno del 1802 o de un dispositivo de entrada (por ejemplo, interruptores eléctricos), dependiendo del tipo de instrucción que está siendo ejecutada. El 1802 genera entonces un pulso de escritura de memoria MWRITE (de nueva cuenta, se usa lógica negativa para una operación de MEMORY WRITE o MWRITE) que ocasiona que el byte del bus sea almacenado en la localidad de la memoria RAM domiciliada desde AØ hasta A7.
Para poder llevar a cabo la programación de una computadora Elf (o cualquier otro modelo parecido) construída con el microprocesador 1802 en su lenguaje natural, en su lenguaje de máquina, es indispensable recurrir a los Códigos de Operación (Códigos Op ó Opcodes) que detallan para cada instrucción el efecto producido. Hay instrucciones que sólo requieren de un byte para poder ejecutarse, y hay instrucciones que requieren de dos bytes para poder llevarse a cabo. A continuación se tiene una tabla que nos proporciona una parte del conjunto de instrucciones de un byte del procesador 1802, las cuales por simplicidad están especificadas en los Códigos Op no en sistema binario sino en sistema hexadecimal:
Código Op (hex) | Explicación |
1N |
RN+1 30MM ir a MM
|
2N |
RN-1 31MM ir a MM si Q=1
|
8N |
RN,0–>D 39MM ir a MM si Q=0
|
9N | RN,1–>D 32MM ir a MM si D=00 |
AN | D–>RN.0 3AMM ir a MM si D != 00 |
BN | D–>RN.1 33MM ir a MM si DF=1 |
4N |
MN–>D, RN+1 38MM ir a MM si DF=0
|
5N |
D–>MN 34MM ir a MM si EF1=1
|
DN |
N–>P 3CMM ir a MM si EF1=0
|
EN |
N–>X 35MM ir a MM si EF2=1
|
7A |
0–>Q (LUZ OFF) 3DMM ir a MM si EF2=0
|
7B |
1–>Q (LUZ ON) 36MM ir a MM si EF3=1
|
F0 |
MX–>D 3EMM ir a MM si EF3=0
|
F1 |
MX ó D–>D 37MM ir a MM si EF4=1 (SWITCH IN)
|
F2 |
MX and D–>D 3FMM ir a MM si EF4=0 (SWITCH IN)
|
F3 |
MX xor D–>D F8KK KK–>D
|
F6 |
Recorrer D a la derecha, BIT 0–>DF F9KK KK ó D–>D
|
76 |
Rotar D a la derecha, DF–>B7,B0–>DF FAKK KK and D–>D
|
FE |
Recorrer D a la izquierda, BIT 7–>DF FBKK KK xor D–>D
|
7E |
Rotar D a la izquierda, DF–>B0,B7–>DF FDKK KK-D–>D,
CARRY–>DF |
F5 |
MX-D–>D, CARRY–>DF FFKK D-KK–>D, CARRY–>DF
|
F7 |
D-MX–>D, CARRY–>DF FCKK KK+D–>D, CARRY–>DF
|
F4 |
MX+D–>D, CARRY–>DF 7CKK KK+D+DF–>D,
CARRY–>DF |
Y a continuación se tiene otra tabla que nos proporciona una parte del conjunto de instrucciones de dos bytes del procesador 1802, las cuales también por simplicidad están especificadas en los Códigos Op no en sistema binario sino en sistema hexadecimal:
Código Op (hex) | Explicación |
30 MM | Ir a MM |
31 MM | Ir a MM si Q=1 |
39 MM | Ir a MM si Q=0 |
32 MM | Ir a MM si D=00 |
3A MM | Ir a MM si D != 00 |
33 MM | Ir a MM si DF=1 |
38 MM | Ir a MM si DF=0 |
34 MM | Ir a MM si EF1=1 |
3C MM | Ir a MM si EF1=0 |
35 MM | Ir a MM si EF2=1 |
3D MM | Ir a MM si EF2=0 |
36 MM | Ir a MM si EF3=1 |
3E MM | Ir a MM si EF3=0 |
37 MM | Ir a MM si EF4=1 (SWITCH IN) |
3F MM | Ir a MM si EF4=0 (SWITCH IN) |
F8 KK | KK–>D |
F9 KK | KK–>D ó D–>D (operación OR) |
FA KK | KK and D–>D (operación AND) |
FB KK | KK xor D–>D (operación OR EXCLUSIVO) |
FD KK | KK-D–>D, CARRY–>DF |
FF KK | D-KK–>D, CARRY–>DF |
FC KK | KK+D–>D, CARRY–>DF |
7C KK | KK+D+DF–>D, CARRY–>DF |
Nota: En el anexo puesto al final de esta obra titulado “Instrucciones del procesador 1802” se le proporciona al lector el listado completo del conjunto de instrucciones de dicho procesador. Además de ello, se le proporciona al lector otro anexo titulado “Tabla inversa de códigos op 1802” que proporciona el Código Op para cada instrucción de acuerdo a su mnemónica, algo que era posible hacer cuando el conjunto de instrucciones de un procesador no era excesivamente grande como los procesadores de la actualidad.
Usando los diagramas esquemáticos y las tablas de cada subconjunto de instrucciones, estamos en condiciones de discutir la lógica de la microcomputadora Elf. El domicilio del RAM es enviado fuera en las líneas AØ a A7. Tres líneas de bus bidireccionales tri-state (véase la entrada “La lógica de tres estados”) son usadas para transferir los bytes de datos hacia uno y otro lado entre los registros internos del 1802 y el RAM ubicado en los circuitos integrados IC2 e IC3. Un byte de RAM puede ser transferido a los visualizadores hexadecimales de siete segmentos IC6 e IC7 (conocidos frecuentemente como carátulas de display) a través del bus de datos, usando los circuitos integrados MOS 4050 identificados en los diagramas esquemáticos como IC4 e IC5 y los cuales no ejercen función lógica alguna sino solo son usados como drivers amplificadores de la potencia eléctrica para suministrar la corriente eléctrica requerida por las carátulas. Las visualizadores hexadecimales IC6 e IC7 contienen cada uno memorias de retención del tipo conocido como memoria de cerrojo o latches que vienen siendo flip-flops ordinarios del tipo RS (Set-Reset) también conocidos como cerrojos tipo SC (Set-Clear) para almacenar el byte a ser exhibido.
La frecuencia básica de reloj del procesador está determinada por el cristal de cuarzo XTAL, que no debe de rebasar los 2 Megahertz en este circuito. Las líneas MREAD y MWRITE controlan los ciclos de lectura y escritura del RAM, mientras que TPA (Timing Pulse A) y TPB (Timing Pulse B) proporcionan los pulsos temporizadores. TPA puede ser usada para retención de domicilios al usarse expansión de la memoria RAM, TPB puede ser usada para temporizar bytes hacia circuitos de salida. SCØ y SC1 indican el tipo de ciclo que está siendo llevado a cabo por el 1802.
Las líneas NØ, N1 y N2 del microprocesador 1802 son usadas para seleccionar dispositivos de entrada o salida. En la microcomputadora Elf, se puede hacer una selección entre cuatro dispositivos de entrada y cuatro dispositivos de salida. Las tablas que se muestran a continuación:
detallan los valores de NØ, N1 y N2 durante el ciclo de máquina en el cual una instrucción de entrada o de salida es ejecutada. Las instrucciones 69, 6A, 6B, 61, 62 y 63 son repuestos que pueden ser usados para añadir dispositivos de entrada/salida o puertos a la computadora. Cuando 6C es ejecutada, la línea N2 va hacia un estado lógico “1” y el byte del bus es escrito hacia la memoria RAM. Puesto que se trata de un ciclo de escritura, MREAD (usado para la lectura, tómese en cuenta la lógica negativa) estará en un nivel alto y la salida de la compuerta IC10C estará baja, poniendo el byte del interruptor de entrada tipo palanca en el bus de modo tal que pueda ser almacenado en la localidad de la memoria domiciliada por RX. Este byte de entrada también será puesto en el registro D del 1802.
Cuando se ejecuta una instrucción 64, N2 está en nivel alto y MREAD está baja, haciendo que la salida de IC10C sea alta, impidiendo que el byte del interruptor de entrada pueda llegar al bus. En cambio, la compuerta IC10B genera un pulso de reloj de salida con TPB que temporiza el byte de salida del RAM hacia la carátula hexadeximal.
Las cuatro líneas de banderas externas de entrada -EF1, EF2, EF3, y EF4- pueden ser jaladas hacia abajo por interruptores externos. Estas cuatro líneas pueden ser probadas por las instrucciones 34, 3C, 35, 3D, 36, 3E, 37 y 3F. Obsérvese en la figura de los circuitos de control para la computadora que el interruptor de botón INPUT, con su “ruido de rebote” extirpado (debounced) por porciones de IC11, está conectado a la línea EF4. Esto implica que EF4.=.1 cuando el interruptor S12 es oprimido, y EF4.=.0 cuando S12 está en su posición mormal.
La línea de salida Q puede ser puesta en nivel alto (el nivel “1” equivalente a 5 voltios) por una instrucción 7B, o reajustada hacia un nivel bajo por una instrucción 7A. El foquito LED Q se enciende cuando Q está en el nivel alto (alimentado por el voltaje de 5 volts).
Las líneas DMA IN, DMA OUT, y INTERRUPT pueden ser “jaladas” hacia abajo (hacia el nivel “cero” de cero volts o tierra) para hacer que estas operaciones ocurran.
Las líneas LOAD y RUN controlan la operación del microprocesador de acuerdo a las siguientes condiciones:
La explicación de lo anterior no tiene mucha ciencia, partiendo de la base de que no es posible estar cargando información a la memoria RAM al mismo tiempo que el procesador 1802 esté ejecutando operaciones (para las cuales el procesador necesita de acceso a la memoria RAM). No es posible llevar a cabo operaciones de carga LOAD y ejecución RUN a la vez. Si queremos cargar información a la memoria, es necesario poner a “dormir” al procesador aplicando un “0” lógico a su terminal RUN; pero también es necesario activar la terminal de carga. Sin embargo, puesto que se usa lógica negativa con LOAD, en vez de aplicar un “1” a la terminal LOAD tenemos que aplicarle un “0”. De este modo, con un “0” lógico (tierra eléctrica o ground) en la terminal RUN y un “0” lógico (tierra eléctrica) en la terminal LOAD, podemos cargar información a la memoria RAM sin interrupciones inesperadas ocasionadas por el procesador 1802 echándose a andar. Este es el modo de carga. Si lo que queremos es echar a andar el procesador después de que se haya cargado en la memoria RAM el programa que será ejecutado, la situación se invierte y tenemos que aplicar tanto un “1” lógico (5 volts positivos) en la terminal de RUN como un “1” lógico (5 volts positivos) en la terminal LOAD. Este es el modo de correr. Pero antes de poner a la máquina en movimiento, queremos poner al procesador en su condición de reajuste o reinicio, “limpiando” lo que haya quedado en sus registros internos con la ejecución previa de algún programa anterior, inhabilitando tanto la terminal LOAD poniéndole un “1” (5 volts positivos) como la terminal RUN poniéndole “0” (tierra). El procesador 1802 está diseñado para que cuando ambas funciones LOAD y RUN sean inhabilitadas el procesador lleve a cabo una “limpia” interna de sus registros y banderas poniéndose en condición prístina de arranque.
Los interruptores LOAD y RUN S1 y S2 en los diagramas esquemáticos controlan la operación de la computadora. Cuando ambos interruptores están en la posición de apagado (OFF), LOAD es 5 volts positivos y RUN está al potencial de tierra eléctrica (cero volts). Esto reajusta (o como se acostumbra decir usando el anglicismo técnico, “resetea”) el procesador 1802. No se generan pulsos temporizadores TPA ó TPB durante el estado de reajuste, y R0.=.0000, P.=.0, X.=.0 y Q.=.0 después de que el 1802 es “reseteado”. Cuando el interruptor de carga LOAD es puesto en la posición de encendido ON, LOAD toma un valor de “cero” lógico, forzando al sistema en el modo de carga. Con esto, podemos cargar una secuencia de bytes en la memoria RAM, empezando en el domicilio 0000, especificando los bytes hacia los interruptores de entrada de palanca (S4, S5, S6, S7, S8, s9, S10 y S11), uno a la vez, y operando el interruptor de entrada INPUT (con S4, por ejemplo, fijamos el estado lógico del “bit” 7, con S6 fijamos el estado lógico del “bit” 5, y con S11 fijamos el estado lógico del “bit” 0).
En el modo de carga, el 1802 no ejecuta instrucciones, permaneciendo a la espera de que un estado lógico de nivel bajo (“0”) aparezca en la línea DMA IN. Cuando esto ocurre, el 1802 ejecuta un ciclo de escritura a la memoria durante el cual el byte de los interruptores de entrada es almacenado en la memoria. RØ es usado para el domiciliamiento de la memoria durante el ciclo DMA IN. Después de que el byte de entrada es almacenado en el domicilio especificado por RØ, este registro es incrementado en uno, de modo tal que los bytes de entrada serán cargados secuencialmente en las distintas localidades de la memoria RAM. La línea SC1 se pone en nivel “alto” durante el ciclo DMA IN de modo tal que los circuitos de control “saben” cuándo el byte de entrada ha sido almacenado en la memoria RAM. En efecto, el procesador 1802 está virtualmente “desconectado” sin que se esté ejecutando ninguna instrucción, y el acceso a la memoria se está llevando a cabo directamente sin intermediación del procesador ejecutando algún tipo de instrucción, razón por la cual se habla de un “acceso directo a la memoria” (Direct Memory Access, DMA).
Oprimiendo y liberando el interruptor de entrada INPUT S12 “ajusta” (esto es, lo pone en estado alto) al flip-flop IC12 (el cual es un circuito integrado 4013, un flip-flop tipo D). La salida Q de esta etapa se va hacia un nivel de estado bajo, ocasionando el nivel bajo requerido en la línea DMA IN. El 1802 responde a esta requisición con un ciclo de escritura a la memoria durante el cual SC1 está en un nivel lógico alto. Durante este ciclo, MREAD está alto y, puesto que el interruptor LOAD S2 está también en posición de encendido, la señal N2/LOAD ocasiona que la compuerta IC10C se ponga en estado alto, dirigiendo mediante acción de compuerta el byte de entrada de los interruptores hacia el bus de datos y almacenándolo en la memoria RAM. Cuando SC1 se pone en estado lógico alto, también reajusta el circuito integrado IC12, lo cual ocasiona que DMA IN regrese a su estado “alto”. La computadora espera entonces al siguiente byte de los interruptores de entrada y la operación del interruptor LOAD.
Siguiendo a cada ciclo de acceso directo a la memoria DMA IN, el 1802 mantiene las líneas de domiciliamiento AØ a A7 al domicilio del byte que acaba de ser almacenado en la memoria RAM. MREAD también es mantenido en nivel bajo esperando al siguiente byte de entrada. Esto significa que el byte cargado previamente está siendo puesto por acción de compuerta hacia el bus (desde el RAM) mientras se espera el arribo del byte nuevo. Este byte de bus es temporizado continuamente hacia la carátula digital, puesto que el interruptor LOAD está manteniendo a IC10B abierto.
Una secuencia de bytes de programa puede ser cargada hacia el RAM empezando en MØ.=.M(0000) ajustando el interruptor LOAD a la posición de encendido ON, mientras que el interruptor de ejecución de programa RUN está puesto en la posición de apagado OFF. Se ajustan los ocho interruptores de entrada S4 a S11 al código deseado del byte (en hexadecimal), y se oprime momentáneamente el interruptor de entrada INPUT para almacenar cada byte en el RAM. El valor de este byte será mostrado en las dos carátulas hexadecimales IC6 e IC7. Se repite este procedimiento para cada byte que sea almacenado. Ajustando el interruptor de LOAD a la posición de apagado OFF pone al procesador 1802 de nuevo en el estado de reajuste en el cual R0.=.0000, P.=.0, X.=.0 y Q.=.0. Si se desea verificar lo que ha sido almacenado en la memoria RAM, se ajusta el interruptor MP de protección a la memoria S3 (para impedir una alteración a los datos que han sido puestos en el RAM) a la posición de encendido ON. De este modo, cada vez que se acciona el interruptor INPUT, los bytes sucesivos en el RAM, empezando con M(0000), serán mostrados.
Para cambiar un byte (en caso de que se haya incurrido en una equivocación o que se quiera modificar una instrucción o un dato), hay que dirigirse justo al byte que antecede al byte que será cambiado. Se pone el interruptor MP en la posición de apagado OFF (para poder alterar los contenidos de la memoria), se ajustan los interruptores de entrada de palanca al valor hexadecimal del nuevo byte, y se oprime momentáneamente el interruptor INPUT. Este nuevo byte será mostrado en las carátulas hexadecimales y almacenado en la localidad que sigue al byte antecedente en el cual se había comenzado. Hecho esto, se pone el interruptor de protección de la memoria MP en la posición de encendido OFF, tras lo cual se puede continuar operando el interruptor de entrada INPUT para secuenciar a lo largo del RAM sin modificar los bytes en la memoria.
Para dar inicio al ciclo ejecutivo de un programa, se ajustan los interruptores LOAD y RUN a la posición de apagado OFF (para efectuar el reajuste del 1802); tras lo cual se pone el interruptor RUN en la posición de encendido OFF. El contador de programa siempre está especificado por el dígito hexadecimal almacenado en el registro P (la letra “P” deviene precisamente de “Program counter”), que puede ser puesto en cero por reajuste de modo tal que el contador de programa siempre será inicialmente RØ. Se ajusta RØ a 0000 por “reseteado” de forma tal que la búsqueda de la primera instrucción, o la ejecución del programa, siempre comenzará en M(0000). Las instrucciones continuarán siendo procuradas de la memoria RAM y ejecutadas hasta que el interruptor RUN sea puesto en la posición de apagado OFF, reajustando la computadora a su estado de inicio. Es importante asegurarse de que el interruptor de protección a la memoria MP esté en la posición de apagado OFF cuando se corran programas, para que la operación de la computadora no sea inhibida.
En el artículo original en el que apareció el proyecto de construcción de la computadora Elf, apareció en una caja un artículo titulado “Introducción a la programación” que se reproduce en su integridad (los dos programas a los que hace referencia el artículo y para los cuales proporciona dos diagramas de flujo son discutidos en mayor detalle más abajo):
Introducción a la
programación
Una vez que se ha construído una computadora Elf, hay que aprender cómo cargar una secuencia de bytes en la memoria y entonces regresar y mostrar la secuencia. Escribiremos un programa sencillo que puede ser cargado en la memoria y ejecutado. Supóngase que queremos programar la computadora para encender el LED Q cada vez que el interruptor de entrada INPUT sea puesto a encendido. Primero, hay que trazar un diagrama de flujo que muestre la secuencia requerida de pasos (lo cual se lleva a cabo en la figura 7). Localícense las instrucciones correctas en la Tabla de Subconjunto de Instrucciones. Una instrucción 7A llevará a cabo el primer paso. Cárguese ésta instrucción en M(0000). Obsérvese que cuando el interruptor INPUT no está oprimido, EF4.=.0. Una instrucción 3F 00 de dos bytes ocasionará un salto (ramificación) de regreso a la instrucción 7A en M(0000) en tanto que el interruptor INPUT no sea operado (EF4.=.0). Esta condición es conocida como un "bucle", y el programa se mantendrá en este bucle mientras espera a que el interruptor INPUT sea oprimido. Cárguese 3F 00 en las localidades de la memoria M(0001) y M(0002) para llevar a cabo el segundo paso en el diagrama de flujo. Todas las instrucciones GO TO MM mostradas en la Tabla ponen a MM en el byte de bajo orden del contador del programa si existe una condición GO TO. En caso contrario, la siguiente instrucción es procurada por el 1802. Cargando una instrucción 7B de un byte en M(0003) se hace cargo del paso 3, mientras que una instrucción 30 01 ocasionará un salto a la instrucción 3F 00 en M(0001). Cárguese una instrucción 30 01 en M(0004) y M(0005) para completar el programa.. Se puede cargar este programa de seis bytes poniendo el interruptor LOAD en la posición ON, con RUN y MP puestos en OFF, ajustando los interruptores de palanca para el número hexadecimal 7A, y oprimiendo el interruptor INPUT. Libérese el interruptor INPUT, métase 3F y opérese de nuevo el interruptor INPUT. Cárguese entonces 00 y así sucesivamente hasta que el último byte, 01, haya sido cargado en M(0005). Si se comete una equivocación, ajústese MP a ON y opérese el interruptor de entrada hasta que se llegue al byte que precede inmediatamente la entrada equivocada. Ajústese MP a OFF, póngase el byte correcto, y opérese INPUT. Ajústese el interruptor MP de regreso a ON para proteger lo que haya sido almacenado en la memoria. Para echar a andar el programa, ajústese LOAD a la posición inferior para "resetear" el 1802 y ajústese el interruptor RUN a ON. Nada debe suceder hasta en tanto se oprima el interruptor INPUT, y al hacerlo el LED Q debe encenderse. Soltando el interruptor INPUT debe ocasionar que el LED se apague. Si lo desea, puede observar las señales de tiempos del 1802 en un osciloscopio mientras el programa está corriendo. Otro programa sencillo involucra contar el número de veces que el interruptor INPUT es operado y entonces encender el LED Q al finalizar el conteo. El diagrama de flujo se muestra en la figura 8. Cuando se carga y se corre este programa, nada sucederá hasta que el interruptor INPUT sea operado cinco veces, en cuyo punto el LED se encenderá y permanecerá encendido. Obsérvese en el paso 1 que se puede cambiar el número de veces que el interruptor INPUT es operado. El paso 6 simplemente lleva a cabo un bucle sobre sí mismo para terminar el programa después de que el interruptor INPUT ha sido operado el número especificado de veces. |
Estos son los diagramas de flujo de los dos programas mencionados en el artículo:
Figura 7
El programa enciende el LED Q cuando el interruptor INPUT es activado
Figura 8
El programa cuenta el número de veces que el interruptor INPUT es operado
Veamos el primer programa.
Cada byte del programa es almacenado sucesivamente en su propia localidad de la memoria RAM del modo siguiente:
7A
3F
ØØ
7B
3Ø
Ø1
El primer byte del programa (7A) es almacenado en la localidad de la memoria M(0001), el segundo byte (3F) es almacenado en la localidad de la memoria M(0001), y así sucesivamente. El programa ocupa seis localidades de la memoria. Al momento de echar a andar el programa con la opresión del botón RUN, el procesador procura la primera instrucción que es 7A. Si consultamos la tabla del subconjunto de instrucciones de 1 byte del procesador 1802, vemos que esta instrucción hace que el procesador ponga en su línea de salida Q un “0”, y esto hace que el foquito LED conectado eléctricamente a Q se apague (en caso de haber estado encendido) o se mantenga apagado. El procesador 1802 es lo suficientemente “listo” (por diseño, no por casualidad) de que esta instrucción es una instrucción de un solo byte, razón por la cual procede a tomar el siguiente byte en la localidad contigua de la memoria para interpretarlo como la siguiente instrucción a ser llevada a cabo. La siguiente instrucción en ser procurada por el procesador es 3F. Al encontrarse con esta instrucción, el procesador 1802 también es lo suficientemente “listo” (por diseño, no por casualidad) de que esta instrucción es una instrucción de dos bytes en lugar de un solo byte, razón por la cual procede a la localidad de la memoria M(002) para tomar el segundo byte de la instrucción y así formar la instrucción completa (resaltada arriba de color magenta) que es 3FMM (véase la tabla del subconjunto de instrucciones de dos bytes). Esta instrucción de dos bytes actúa sobre el valor lógico que se encuentra en la terminal <span style="text-decoration: overline;">EF4</span> del procesador (terminal 21 del circuito integrado), valor lógico que a su vez depende del hecho de que el botón INPUT (S12) esté o no oprimido. Si el botón INPUT no está oprimido, entonces EF4.=.0, lo cual provoca un salto de regreso hacia la primera localidad de la memoria en virtud de que MM.=.ØØ (hexadecimal) de acuerdo al segundo byte de la instrucción. Sin embargo, si el botón INPUT está siendo oprimido, la ejecución del programa pasa a la siguiente instrucción que es una instrucción 7B. Si consultamos la tabla del subconjunto de instrucciones de un byte del procesador 1802, vemos que esta instrucción hace que el procesador ponga en su línea de salida Q un “1”, y esto ocasiona que el foquito LED conectado eléctricamente a Q se encienda. Tras esto, el procesador continúa con la ejecución de la siguiente instrucción, la cual es una instrucción de dos bytes. Esta instrucción ordena un <i>salto incondicional</i> hacia la localidad de la memoria Ø1 (hexadecimal, 00000001 en binario) empezando de nuevo con la instrucción de dos bytes especificada al principio. De este modo, el propósito del programa queda claro: encender y mantener encendido el foquito LED Q mientras el interruptor botón INPUT se mantenga oprimido. Esta es una aplicación de un microprocesador no para la ejecución de un programa de cómputo que nos calcule la raíz cuadrada de un número sino de una aplicación interactiva de la máquina con el usuario en lo que se conoce como <i>tiempo real</i>. Este es el tipo de programación que se utiliza en aplicaciones de automatización y control, incluyendo robótica y mecatrónica. El procesador 1802 puede, desde luego, ser programado para actuar como una calculadora científica, permitiendo la extracción de la raíz cuadrada de un número, pero obviamente este es otro asunto que ciertamente requerirá de una mayor cantidad de instrucciones en número tal que la memoria RAM de 256 bytes resultará insuficiente para tal propósito.
Aunque el programa se ha dado empleando notación hexadecimal, en rigor de verdad no es eso lo que “lee” el procesador 1802, es lo que leemos nosotros ayudados por los visualizadores hexadecimales de siete segmentos. El procesador, al igual que cualquier otra computadora digital, solo “sabe” leer el lenguaje de los “unos” y “ceros”, de los “encendidos” y “apagados”, es lo que usa, es lo que maneja. Estrictamente hablando, el programa que vimos arriba es visto e interpretado por la computadora Elf del modo siguiente:
01111010
00111111
00111111
00000000
01111011
00000001
¡Y cada uno de estos bits tiene que ser metido individualmente en la memoria RAM de la computadora Elf mediante la acción de los interruptores de palanca S4 a S11!
Ciertamente, debe llegar un momento en el cual se vuelve deseable aumentar las capacidades de la máquina, agregando un teclado hexadecimal que permita meter bytes completos en localidades contiguas de la memoria sin necesidad de tener que especificar cada bit individual. La manera de lograr este tipo de cosas se verá posteriormente.
PROBLEMA: Explíquese en detalle el segundo programa proporcionado arriba para la computadora Elf.
El programa, escrito en notación hexadecimal, tal y como cada byte es metido en localidades sucesivas de la memoria a partir de la localidad M(0000), es el siguiente:
F8
Ø5
3F
Ø2
37
Ø4
FF
Ø1
3A
Ø2
7B
3Ø
ØA
Lo que la computadora Elf realmente maneja, en su lenguaje binario de máquina, es lo siguiente:
11111000
00000101
00111111
00000010
00110111
00000100
11111111
00000001
00111010
00000010
01111011
01100000
00001010
En el primer paso (inicio), con la instrucción de dos bytes F8 Ø5 (que leemos en la tabla del subconjunto de instrucciones de dos bytes como F8KK) se deposita el equivalente en binario del número 5 (o sea 00000101) en el registro D, simbolizado como la operación:
(Ø5) -> D
tras lo cual se pasa a la ejecución de la siguiente instrucción (paso 2) que también es una instrucción de dos bytes, 3F Ø2, y que de acuerdo a tal instrucción a través de la opresión de la tecla INPUT (enviando por ende un “1” a la línea EF4 del procesador, véase el diagrama esquemático de los circuitos de control) produce un salto condicionado a la localidad de la memoria Ø2 que es precisamente en donde empieza la segunda instrucción mientras la tecla INPUT no sea oprimida. En efecto, el procesador está atascado en un bucle perpetuo mientras la tecla INPUT no es oprimida. Pero si la tecla INPUT es oprimida, esto ocasiona que se pase a la ejecución de la siguiente instrucción (paso 3) que también es una instrucción de dos bytes, la instrucción 37 Ø4 que mantiene un segundo bucle perpetuo mientras la tecla INPUT no deje de se oprimida. Si la tecla INPUT deja de ser oprimida, se pasa a la ejecución de la siguiente instrucción, FF Ø1, especificada en la tabla del subconjunto de instrucciones de dos bytes como FFKK, que ejecuta la siguiente operación binaria:
D - Ø1 -> D
que es una operación de substracción que se lee como: “tomar el número binario que está almacenado en el registro D, restar 1 de dicho número, y depositar el resultado de la resta aritmética en el mismo registro D”. Puesto que al principio se había depositado el número 5 en el registro, dicho número ha sido reducido a 4. Ha empezado en efecto un conteo descensivo. Posteriormente, se pasa a la ejecución de la instrucción de dos bytes, 3A Ø2, que de acuerdo a la tabla del subconjunto de instrucciones de dos bytes checa si el registro D está vacío con ØØ (hexadecimal, 00000000 en binario). Puesto que no lo está al tener un 4 depositado en él, se produce un salto de regreso hacia el paso 2 en donde se estará checando con bucles perpetuos si la tecla de entrada INPUT es oprimida. Este proceso iterativo se repite hasta que el número original 5 ha sido reducido a Ø quedando el registro D vacío, en cuyo caso se pasa a la ejecución de la siguiente instrucción que, para variar, es una instrucción de un byte, 7B, poniendo un “1” en la línea de salida Q del procesador y encendiendo con ello el foquito LED Q. Hecho esto, se pasa a la ejecución de la instrucción final, 3Ø ØA, que ordena un salto incondicional hacia la localidad de la memoria ØA (hexadecimal, 00001010 en binario), poniendo a la computadora Elf en un estado de bucle perpetuo del que no saldrá hasta que la máquina no sea detenida manualmente. El programa, lo que hace, es llevar a cabo un conteo para indicar mediante opresiones sucesivas de la tecla INPUT cuál es el número que estaba depositado en el registro D. Con este programa la computadora Elf es, en efecto, un contador.
Habrá quien se pregunte a estas alturas: ¿qué caso tiene recordar el modus operandi de un proyecto para aficionados a la electrónica para el cual, aunque haya sido muy bueno para el aprendizaje de la programación en lenguaje de máquina, se requieren algunas partes que ya no están a la venta comercialmente (empezando con el mismo procesador 1802)? Empezaremos por el hecho de que la computadora Elf en sí era un vehículo invaluable para el aprendizaje en casa mediante la experimentación, en donde el “juguete” era el mejor maestro de todos, ya que en caso de equivocaciones uno siempre podía volver a empezar revisando todo desde el principio y aprendiendo. Y precisamente por esta razón, varios técnicos e ingenieros que empezaron con una computadora Elf su iniciación al mundo de las ciencias computacionales han elaborado emuladores de la computadora Elf, la mayoría de los cuales han hecho disponibles sin costo alguno a través de Internet, con los cuales se puede “programar” una computadora Elf mediante una buena simulación gráfica de la misma, y los resultados que se obtienen son los mismos que los que se obtendrían si tuviésemos una computadora Elf en casa. Un ejemplo de tales emuladores es el X-ELF 1802 Emulator de Mike Riley, cuya interfaz gráfica es la siguiente:
Así como este emulador hay muchos otros disponibles gratuitamente en Internet. Podemos, desde luego, tratar de empezar con un microprocesador actual, pero con su arquitectura compleja y su extenso conjunto de instrucciones, tal alternativa parecería ser una propuesta muy dura para quien apenas se está iniciando por vez primera en las ciencias computacionales.
PROYECTO: Procurar y descargar de algún sitio de Internet un emulador de la computadora Elf en cualquiera de sus versiones (TinyElf, Elf II, Super Elf, etcéctera), y echarla a andar con programas experimentales de prueba tales como los dos programas discutidos arriba en detalle, así como otros programas elaborados por el mismo lector con los cuales quiera experimentar programando en lenguaje de máquina, usando para ello el anexo puesto al final de esta obra titulado en el cual se proporcionan los códigos de operación (op-codes) de las instrucciones con las cuales trabaja el microprocesador COSMAC CDP 1802.