Manufactura industrial
Internet industrial de las cosas | Materiales industriales | Mantenimiento y reparación de equipos | Programación industrial |
home  MfgRobots >> Manufactura industrial >  >> Manufacturing Technology >> Proceso de manufactura

Programador informático de tablero de pruebas

Componentes y suministros

Arduino UNO
× 1

Acerca de este proyecto

¿Qué es este proyecto?

Esta es una extensión del proyecto de computadora de tablero de 8 bits de Ben Eater. He disfrutado inmensamente siguiendo los videos de Ben sobre cómo construir una computadora de tablero y construir mi propia versión. Si no ha seguido a Ben, le recomiendo encarecidamente ver sus videos antes de leerlos; este proyecto tendrá muy poco sentido sin el contexto.

Después de construir la computadora, rápidamente quedó claro que si tuviera que alternar manualmente un programa a través de interruptores DIP cada vez que lo encendiera, no tendría mucho uso. Incluso alternar en solo 16 bytes una y otra vez envejece muy rápido. También estaba planeando extender la memoria a 256 bytes y eso solo sería útil si de alguna manera los programas se pudieran cargar y guardar.

¿Qué puedo hacer con él?

  • Guarde un programa desde la RAM de la computadora de la placa de pruebas
  • Cargue un programa en la RAM de la computadora de la placa de pruebas
  • Ejecutar automáticamente un programa guardado cuando se inicia la computadora de tablero
  • Inspeccione y modifique el contenido de la memoria a través de una conexión en serie
  • Programe la computadora protoboard en lenguaje ensamblador
  • Desarmar el contenido de la memoria
  • Instrucción de un solo paso por instrucción
  • Establecer puntos de interrupción y ejecutar hasta el punto de interrupción

Aquí hay un video que demuestra estas características. Disculpe la calidad del video. De ninguna manera soy un creador de contenido de video profesional:

¿Cómo funciona?

Tenía algunos objetivos en mente al hacer este proyecto:

  • Se requiere la menor cantidad de hardware posible para construirlo
  • La menor cantidad posible de cambios en la propia computadora de la placa de pruebas

Al principio pensé en usar una EEPROM para almacenar programas y luego algún tipo de lógica para transferir programas desde la EEPROM a la RAM de la computadora. Sin embargo, idear la lógica de transferencia resultó ser más complicado de lo que podía manejar (soy más un tipo de software, aunque realmente disfruto trabajar cerca del hardware). Resulta que soy un gran fanático de Arduino, así que en algún momento comencé a pensar en reemplazar la lógica de transferencia con un Arduino. Me tomó un tiempo convencerme de que usar un Arduino no era una trampa (después de todo, incluso el Arduino UNO es mucho más poderoso que la propia computadora), pero estoy contento con el resultado, así que he hecho las paces.

Entonces, ¿qué necesita Arduino para poder hacer? Bueno, necesita poder leer datos de la memoria y escribir datos en la memoria. La forma más fácil y menos intrusiva (para la computadora) de hacerlo es usar la misma interfaz que ya tiene el módulo de memoria:el bus y las señales de control. Los pines de E / S digitales de Arduino son bidireccionales, por lo que conectar 8 de ellos directamente al bus permite que Arduino lea y escriba en el bus. Para que el módulo RAM lea o escriba en el bus, todo lo que se necesita es configurar las señales MI / RI / RO en consecuencia. Ahora, esas señales generalmente son impulsadas por las EEPROM de la lógica de control, por lo que hacer que Arduino también las controle podría generar conflictos y posibles situaciones de cortocircuito. Sin embargo, las EEPROMS AT28C16 utilizadas por Ben tienen una entrada Chip Enable (CE) que coloca todas las salidas de datos en un estado de alta z, lo que luego permite que Arduino manipule las señales. Para leer la RAM, Arduino debe hacer lo siguiente:

  • establecer alta la señal CE de la EEPROM (es decir, deshabilitar la lógica de control)
  • generar la primera dirección que se leerá en el bus
  • configure la señal MI alta y espere una transición de reloj bajo-alto
  • configure MI bajo y RO alto y espere una transición de reloj bajo-alto
  • leer el byte de datos del bus
  • repita desde el paso 2 para las 16 direcciones
  • establecer baja la señal CE de la EEPROM (es decir, volver a habilitar la lógica de control)

Y eso es. Escribir contenido de RAM es muy similar, el Arduino solo necesita escribir en el bus y establecer RI alto en lugar de RO. Por supuesto, hay algunos problemas técnicos que deben resolverse, pero el mecanismo básico anterior es el corazón de este proyecto.

¿Qué cambios debo hacer en la computadora de la placa de pruebas?

Hay dos cambios que deben realizarse:

  • Coloque resistencias desplegables en las salidas de datos de la EEPROM lógica de control
  • Desactive (o reinicie continuamente) el contador de anillo mientras la EEPROM está desactivada

Resistencias desplegables

Las resistencias pull-down son necesarias porque una vez que la EEPROM está desactivada, las resistencias pull-up de las puertas lógicas a las que están conectadas las señales de control (como AO / AI / EO ...) elevarán esas señales. Eso significaría que varios registros estarían escribiendo en el autobús, lo que provocaría conflictos.

Las resistencias pull-up en las entradas de las puertas 74LS son de alrededor de 10k. Por lo tanto, las resistencias desplegables deben ser lo suficientemente pequeñas para que el voltaje baje a un territorio bajo. Para la mayoría de las líneas de señal utilicé resistencias de 3.3 kOhm. Sin embargo, hay dos excepciones:primero, la señal "SU" está conectada a 8 puertas OR exclusivas, lo que significa que la resistencia de pull-up efectiva es 10kOhm / 8 =1.25kOhm. Una resistencia pull-down tendría que ser significativamente menor que 1k para tirar tan bajo. Afortunadamente, la señal SU (resta) no controla ninguna interacción con el bus, por lo que podemos ignorarla y no tener una resistencia desplegable. En segundo lugar, el CE (habilitación del contador) necesitaba una resistencia desplegable de 1k; los valores más grandes provocaban un comportamiento aleatorio del contador del programa en algunos casos.

Me resultó más fácil agregar las resistencias desplegables en la placa que contiene todos los LED azules, es decir, entre los ánodos LED (que están conectados a las salidas EEPROM) y GND.

[No pude colocar las resistencias aquí para las señales HLT / MI / RI, así que las agregué en otras ubicaciones en la placa]

Restablecimiento del contador de anillo

La otra modificación es restablecer el contador de anillo. Técnicamente, esto no es realmente necesario para permitir guardar / cargar programas, pero permite una transferencia fluida del control del Arduino a la lógica de control. El punto es mantener el contador de anillo en 0 mientras CE sea alto (es decir, la lógica de control esté deshabilitada). Cuando el Arduino cambia CE de nuevo a bajo (habilitando la lógica de control), el contador de anillo estará en cero y la computadora de la placa de pruebas comenzará a ejecutar la siguiente instrucción.

Para mi compilación, no tuve que hacer nada para esto porque estoy usando una salida EEPROM para restablecer el contador de anillo. Esto mejora el rendimiento al restablecer el contador de anillo tan pronto como finaliza una instrucción. También me da automáticamente el reinicio del contador de anillo cuando la lógica de control EEPROM se desactiva:la resistencia desplegable en la salida de la EEPROM hará que la señal sea baja, lo que reinicia el contador de anillo.

Si está utilizando la implementación de Ben de un contador de anillo fijo de 5 pasos, creo que la siguiente extensión de su circuito de reinicio debería reiniciar el contador cuando si CE es alto (haga clic en las flechas izquierda / derecha a continuación para cambiar entre el circuito original de Ben y el versión extendida):

Como puede ver, requiere 3 puertas NAND más, es decir, un chip 74LS00 más. Tenga en cuenta que no he probado este enfoque, pero debería funcionar hasta donde puedo ver.

Esta modificación no es absolutamente necesaria; puede omitirla al principio. La carga y el guardado, así como el monitor / ensamblador / desensamblador, seguirán funcionando bien. Sin embargo, cualquier acción que requiera la transferencia de control del Arduino a la lógica de control no funcionará. Lo más notable es que se ejecutan automáticamente los programas guardados al inicio, así como los pasos únicos y se ejecutan en el depurador.

¿Cómo configuro el Arduino?

Cargue el boceto del archivo GIT al Arduino y conecte el Arduino a la computadora de la placa de pruebas de la siguiente manera:

  • Pin Arduino 5V ( no Vin!) Al riel de 5V en la placa de pruebas
  • Pin GND de Arduino a pin GND en la placa de pruebas
  • Pines digitales Arduino 2-9 a bus 0-7
  • Pin digital Arduino 10 para controlar la salida lógica EEPROM que controla RO
  • Pin digital Arduino 11 para controlar la salida EEPROM lógica que controla RI
  • Pin digital Arduino 12 para controlar la salida EEPROM lógica que controla MI
  • Pin analógico Arduino 0 a señal CLOCK
  • Pin analógico de Arduino 3 a CE (pin 18) de todos EEPROM lógicas de control y a través de una resistencia de 10k a + 5v

Aparte de eso, deberá conectar los pines de entrada analógica 1 y analógica 2 de Arduino a los interruptores DIP y botones pulsadores como se muestra en los esquemas (para obtener más detalles, consulte el archivo Fritzing adjunto).

Para obtener una versión absolutamente mínima (pero aún funcional), puede hacer lo siguiente:

  • Agregue resistencias desplegables de 3.3kOhm a los pines de salida EEPROM que controlan AO, CO, EO, IO, RO
  • Omita las instrucciones de "Reinicio del contador de anillo" anteriores
  • Haga el cableado de Arduino a la computadora de la placa de pruebas como se muestra arriba (puede omitir la resistencia de 10k en el último paso si lo desea)
  • Conecte el pin analógico 1 y el pin analógico 2 a GND

Para usar los botones de carga / guardado, todo lo que necesita hacer es conectar los botones, interruptores DIP y resistencias asociadas a los pines analógicos 1 y 2 de acuerdo con los esquemas.

Para usar la función de inicio automático, Arduino necesita mantener el contador del programa en y el contador de anillo en 0 durante el reinicio y mientras se transfiere el programa. La resistencia pull-up entre el pin analógico 3 y + 5V mantiene la lógica de control deshabilitada (y por lo tanto el contador del programa en 0) mientras el Arduino se reinicia. Para el contador de anillo, siga las instrucciones para "Restablecer el contador de anillo" que se encuentran más arriba.

¿Cómo cargo y guardo programas?

La configuración mínima anterior le permitirá controlar el Arduino a través de la interfaz en serie. Para comunicarse con Arduino, necesitará un programa de terminal como Putty o TeraTerm. El monitor en serie en el software Arduino también funcionará, pero la separación entre el área de entrada y salida en el monitor en serie lo hace un poco torpe en este escenario.

  • Encienda la computadora de la placa de pruebas
  • Conecte una PC al Arduino a través del cable USB
  • Inicie el programa del terminal y configure a 9600 baudios, 8 bits, sin paridad, 1 bit de parada
  • Presione ESC en la ventana del terminal para ingresar al modo Monitor
  • Debería ver un "." como símbolo del sistema
  • Escriba "h" y presione Intro para obtener una lista de los comandos admitidos.

Con la configuración mínima, debería poder utilizar los comandos "m", "M", "C", "l" y "s". Estos le permiten ver el contenido de la memoria, modificar el contenido de la memoria y cargar y guardar programas.

Para guardar o cargar un programa a través del botón:

  • Apague el reloj de la computadora de la placa de pruebas
  • Configure los interruptores DIP para seleccionar el número de archivo bajo el cual se deben guardar los datos.
  • Presione el botón "guardar" o "cargar". El LED conectado a CE se encenderá, indicando que Arduino ha tomado el control
  • Encienda el reloj de la computadora de tablero. Debería ver el Arduino recorriendo las direcciones (observe los LED del registro de direcciones de memoria)
  • Espere hasta que los LED del bus dejen de parpadear y los LED del registro de dirección de memoria muestren 1111
  • Apague el reloj de la computadora de tablero. El LED conectado a CE se apagará, indicando que el control se ha vuelto a la lógica de control

Para ejecutar automáticamente un programa al inicio (asegúrese de tener todos los circuitos necesarios en su lugar), simplemente configure los interruptores DIP en el número de archivo bajo el cual se guarda el programa y encienda la computadora (o presione el botón de reinicio). Hay dos casos especiales:si todos los interruptores DIP están apagados, la computadora se inicia con regularidad, sin inicio automático. Si todos los interruptores DIP están encendidos, Arduino entra en modo Monitor directamente al inicio.

¿Cómo utilizo el ensamblador y el desensamblador?

Para utilizar las funciones de ensamblador / desensamblador y depurador, primero deberá modificar el programa en Arduino para que se ajuste a su configuración específica. Busque la sección en el código fuente que define la estructura opcodes_4bit:

  struct opcodes_struct opcodes_4bit [] ={{"NOP", B00000000, 0, false}, {"LDA", B00010000, 2, true}, ... {".OR", B11111110, 0, true}, // establece la dirección de inicio {".BY", B11111111, 0, true}, // define un byte de datos {NULL, 0, 0, false}};  

Cada línea especifica un código de operación:

  • El primer campo es el mnemónico ("LDA"). Para direccionamiento inmediato, incluya un "#" en el mnemónico. Entonces, lo que Ben llama "LDI" se llamaría "LDA #" aquí. ¿Puedes decir que crecí programando ensamblador 6510 en un C64?
  • El segundo campo es el código de operación en sí. Los cuatro bits inferiores siempre deben ser 0 (excepto para los códigos de operación especiales .OR y .BY, ver más abajo)
  • El tercer campo es el número de ciclos que el código de operación tarda en ejecutarse (esto es además de los ciclos de recuperación). Por ejemplo, en mi implementación, LDA tiene el código de operación 0001 y requiere un total de cuatro ciclos para ejecutarse, dos de los cuales son el ciclo de recuperación. Si siguió las instrucciones de Ben (donde todos los códigos de operación usan 5 ciclos), este debería ser siempre 3.
  • El último campo especifica si este código de operación requiere un argumento. Por ejemplo, LDA requiere un argumento pero OUT no.

Deberá ajustar esta lista para reflejar los códigos de operación que ha implementado para su computadora de tablero. Las dos últimas líneas son códigos de operación especiales utilizados por el ensamblador y deben dejarse como están.

Después de ingresar todos sus códigos de operación, cargue el software en Arduino. Conecte su terminal y entre en modo Monitor (ya sea presionando ESC en la ventana del terminal o configurando todos los interruptores DIP en la posición de encendido). Ahora debería poder desmontar su programa. Al escribir solo "d" en el monitor, comenzará a desmontarse en la dirección 0.

El ensamblador es mínimo pero funciona bastante bien. Escriba "a" para comenzar a ensamblar en la dirección 0. Las convenciones son:

  • Si una línea comienza no comienza con un espacio en blanco, entonces debe comenzar con una definición de etiqueta. Las etiquetas deben comenzar con un carácter alfabético seguido de caracteres alfanuméricos, pueden tener un máximo de 3 caracteres y distinguen entre mayúsculas y minúsculas.
  • Después del primer espacio en blanco de una línea, el ensamblador espera un mnemónico (LDA, STA, OUT ...).
  • El mnemónico especial ".BY" especifica directamente un byte de datos que se almacenará en la ubicación actual.
  • El mnemónico especial ".OR" le dice al ensamblador que continúe ensamblando en una nueva dirección.
  • Si un argumento comienza con un carácter alfabético, se asume que es una etiqueta.
  • Se espera que cualquier argumento numérico sea un número decimal. Para especificar hexadecimal, preceda el argumento con un "$". Por ejemplo, para cargar un número FF hexadecimal en el registro A, use "LDA # $ FF".
  • Cualquier cosa después de ";" se asume que es un comentario y se ignora.

Por ejemplo, el código de Fibonacci se puede ingresar de la siguiente manera:

  primer LDA # 0; x =0 STA x LDA # 1; y =1 STA y lp ADD x; z =y + x STA z JC primero; reiniciar si se desborda HACIA FUERA; imprimir z LDA y; x =y STA x LDA z; y =z STA y JMP lp; bucle x .BY 0 y .BY 0 z .BY 0  

¿Cuáles son las limitaciones?

Para ahorrar espacio RAM en el Arduino, el ensamblador funciona como un ensamblador de 1 paso (de lo contrario, Arduino tendría que almacenar en búfer todo el código fuente). El ensamblador escribe los códigos de operación en la memoria de la computadora protoboard a medida que se ingresan. Esto significa que el ensamblaje se ralentiza por la velocidad del reloj de la computadora de la placa de pruebas. Si copia y pega texto en la ventana de la terminal, puede provocar la pérdida de caracteres, ya que Arduino no puede seguir el ritmo de los caracteres que llegan a 9600 baudios (porque pasa demasiado tiempo esperando el reloj de la computadora). Para solucionarlo, reduzca la velocidad en baudios o use TeraTerm, que proporciona una configuración para especificar un retraso entre los caracteres enviados. La otra solución es aumentar la velocidad del reloj en la computadora del tablero. Mi reloj sube a 160 kHz y a esa velocidad puedo copiar y pegar código a 9600 baudios sin problemas.

En su configuración predeterminada, el boceto de Arduino puede manejar frecuencias de reloj en la computadora de tablero de hasta aproximadamente 1-2 kHz (tal vez un poco más). Tenga en cuenta que el reloj de Ben en su configuración predeterminada no pasa de 500 Hz. Si su reloj es más rápido, busque el #ifdef FAST_IO cambiar en el código. Encender FAST_IO debería hacer que Arduino funcione con velocidades de reloj de hasta 250 kHz. Lo he probado hasta 160 kHz. Probablemente sería posible admitir velocidades más altas implementando los bucles de tiempo crítico directamente en el ensamblador, pero honestamente, una velocidad de reloj de 160 kHz ya se siente demasiado rápida en la computadora de tablero con sus capacidades limitadas. Asegúrese de leer los comentarios correspondientes en el código antes de encender FAST_IO.

El Arduino tiene 1k de EEPROM y, por lo tanto, puede contener 1024/16 =64 programas diferentes. En realidad es 63 ya que se reservan 16 bytes para guardar los datos de configuración. Eso no es mucho, pero probablemente lo suficiente para contener todos los programas que se le ocurran. Solo los programas número 0-15 de esos se pueden seleccionar a través de los interruptores DIP (1-14 para inicio automático) pero los comandos "s" y "l" funcionarán con el rango completo 0-62.

Parece un poco desordenado. ¿Puedes arreglarlo?

¡Sí! En mi versión final aquí, en realidad solo usé el chip Atmega 328P desnudo (junto con un cristal de 16MHz y condensadores) en lugar de un Arduino UNO. El regulador de voltaje en el UNO no es necesario aquí ya que el Arduino está usando directamente los 5V de nuestra fuente de alimentación de todos modos. La única pérdida es que ahora tenemos que usar un convertidor de USB a serie (FTDI o similar) separado para hablar con Atmega. El aspecto general de eso encaja mucho mejor con el resto de la computadora de tablero:

Otra optimización es eliminar el cargador de arranque de Arduino / Atmega. Eso elimina el retraso de 2 segundos mientras se inicia el gestor de arranque Arduino. Publicaré instrucciones sobre cómo hacerlo si la gente está interesada. ¡Házmelo saber en los comentarios!

Código

Programador informático de tablero
El boceto de Arduino para el programador de computadora de placa de pruebas https://github.com/dhansel/programmer

Esquemas

drive_pD8k28E85v.fzz

Proceso de manufactura

  1. Ratón de la computadora
  2. Control de un efecto con sensores reales
  3. Arduino Spybot
  4. FlickMote
  5. Televisión casera B-Gone
  6. Reloj maestro
  7. Encuéntrame
  8. Arduino Power
  9. Tech-TicTacToe
  10. Arduino Cuadrúpedo
  11. Estación meteorológica ThingSpeak Arduino