Introducción
En este episodio vamos a descubrir el DUINO PROTOCOL ANALYZER de nuestra computadora 20c. Esta placa nos va a permitir conectar un Arduino Mega para poder utilizarlo como analizador de protocolos para los 3 buses de la 20c, el ADDRESS BUS, el DATA BUS y el EXPANSION BUS.
Vamos a estudiar cómo funciona la placa, cómo conectar nuestro Arduino Mega, cómo crear un programa para el Arduino que nos permita analizar los buses de la 20c explicando qué direcciones vemos y hasta qué instrucciones de código máquina se están ejecutando.
Recrearemos esta placa PCB desde cero y terminaremos con un experimento que nos permitirá ver cómo funciona el bus de nuestra computadora.
Descripción general del DUINO PROTOCOL ANALYZER
Nuestra Placa DUINO PROTOCOL ANALYZER sirve para interpretar los pulsos eléctricos que tenemos en los 3 buses principales de nuestra computadora 20c; el ADDRESS BUS, el DATA BUS y el EXPANSION BUS.
Descripción de Funcionamiento de los buses
Los buses en nuestra computadora 20c, y en toda computadora de 8 bits basada en el procesador 6502, funcionan enviando pulsos eléctricos de entre 0v y 5v. Para ser precisos funcionan con niveles de CMOS en los cuáles cualquier voltaje superior a 2,4 volts es tomado como un uno y cualquier inferior a 0,4 como un 0. En la tabla basada en el datasheet del procesador 6502, Vss es nuestro pin de ground que asumimos en +0v.
La computadora entonces no ve nunca ceros y uno sino variaciones de voltajes, para nuestra interpretación y poder de esta forma aplicar funciones lógicas vamos a decir que un voltaje de Vss+2.4v es un High o 1 y que un voltaje menor a Vss+0.4 es un Low o 0.
Los chips de la computadora se sincronizan entre sí con un clock, que ya vimos en el episodio anterior. Cuando se marca un pulso de clock se leen los valores de todos los buses y se asumen simultáneos.
Por ejemplo, en un pulso determinado de reloj podemos leer estos valores en los buses:
ADDRESS BUS = 1000 0000 0000 0000 (A15-A0)
DATA BUS = 1010 1001 (D7-D0)
EXPANSION BUS = pin de sincronía SYN en 1
Vamos a interpretar estos datos, el valor del address bus pasado de binario a hexadecimal es $8000
El valor del data bus en hexadecimal es $A9
Cuando el pin de sincronía SYN está en 1 el procesador 6502 está en un ciclo de OPCODE FETCH, con estos nos referimos a que está buscando una instrucción y la misma va a tener su código de operación u OPCODE en el bus de datos.
En el bus de datos vemos el valor $A9, si buscamos el mismo entre las instrucciones del procesador 6502 veremos que el mismo corresponde a la instrucción de cargar el acumulador con el valor que se encuentre en el próximo ciclo de reloj en el bus de datos, esta instrucción es LDA en modo inmediato.
Si fuéramos a ver el próximo pulso de reloj leeremos en los buses:
ADDRESS BUS = 1000 0000 0000 0001 (A15-A0)
DATA BUS = 0100 0010 (D7-D0)
EXPANSION BUS = pin de sincronía SYN en 0
Lo cual corresponde a la dirección de memoria $8001 (la siguiente de la anterior) el valor $42 y el pin de SYN en 0 lo que indica que lo que está en el bus de datos son datos y la instrucción anterior LDA, que ya leimos, los estaba esperando.
Estos dos bytes que leímos del bus de datos se interpretan como el código en assembler.
LDA #$42
Y en código máquina como A942
Y se ven en memoria como:
ADDRESS | DATA |
$8000 | $A9 |
$8001 | $42 |
Y en el bus como voltajes.
Cómo funciona la placa DUINO PROTOCOL ANALYZER
Nuestra placa lo único que hace es conectar los pines de bus de nuestra 20c con pines presentes en un development board Arduino Mega.
Vamos a tener 16 pines para el ADDRESS BUS, 8 pines para DATA BUS, y 16 PINES para el EXPANSION BUS. Podemos ver como los pines están conectados entre sí en la siguiente tabla:
En particular nosotros mapeamos los pines del Arduino Mega de la siguiente manera
Así quedaría conectado nuestro Arduino Mega a la Placa DUINO PA.
El pin E1/CLK lo conectamos al pin 2 del Arduino Mega en lugar de al más lógico pin 40, esto lo hacemos así ya que vamos a querer capturar toda la información que hay en el bus al momento que el pin de CLOCK esté en el valor +5v o 1, eso sólo lo vamos a poder hacer si generamos una interrupción en dicho pin pero el arduino no nos deja tener interrupciones en cualquier pin sino sólo en los pines 2,3,18,19,20 y 21.
Para que nuestro Arduino Mega interprete los valores eléctricos del bus como ceros y unos y nos pueda dar información de que está pasando vamos a tener que realizar un pequeño programa.
Setup Arduino
Si nunca utilizamos un arduino antes de poder ejecutar nuestro primer programa vamos a tener que instalar el Arduino IDE, el cual nos va permitir ejecutar programas en nuestro arduino Mega
El mismo lo descargamos de www.arduino.cc
Ni bien abrimos nuestro IDE vamos a tener que configurar nuestro arduino mega, luego de conectarlo al puerto USB de nuestra computadora.
Para esto nos dirigimos a la ventanita superior que observamos y elegimos el puerto donde está conectado nuestro arduino y le especificamos que es un mega.
Ahora debemos cargar en el Arduino los programas que queremos experimentar para esto apretamos el botón con forma de flecha.
Los programas los podemos encontrar en el github de OsoLabs para este episodio, los mismos son 001_Arduino_Basico y 001_Arduino_DUINO_PA.
Por último para activar la salida de los programas y ver cómo funcionan tenemos que conectar el Serial Monitor del Arduino IDE, yendo a tools -> Serial Monitor
Primer Programa para capturar outputs
En este programa vamos a ver cómo leer los buses de nuestra computadora, sincronizarlos con el reloj de la misma para ver una línea de información por cada tick del reloj, convertir los pulsos eléctricos a unos y ceros y finalmente verlos en la pantalla.
Para esto vamos a usar nuestro primer programa de Arduino que vamos a llamar 001_Arduino_Basico. La forma de editarlo es conseguir el programa Arduino IDE y tipear el programar o bajarlo del github de este episodio.
Para ejecutar nuestro programa vamos a realizar algunos simples pasos:
- Definir cuáles pines del Arduino Mega son los Buses
- Inicializar el Arduino
- Sincronizarlos con el Reloj
- Transformar los voltajes a unos y ceros
- Mostrarlos en Pantalla
Definir Buses
La línea 1 es un comentario,
La línea 2 en el diagrama nos define la variable ADDR como un array en el cual vamos a tener los números impares del 23 al 53, estos coinciden con los pines del Arduino Mega que tenemos conectados a los pines A15 hasta A0 del bus de datos.
La línea 3 define la variable DATA como un array donde los números pares del 36 al 22 coinciden con los pines D7 a D0 del bus de datos.
La línea 4 define la variable EXP como un array en el cual vamos a tener los números consecutivos del 62 al 69 para representar los pines del bus de Expansión E15 a E8 y los pines pares del 52 al 38 para representar los pines del bus de Expansión E7 a E0.
Con la excepción del pin de CLOCK que como ya dijimos va a ser el pin 2 en lugar del in 40 para poder agregarle una interrupción. Por esto definimos una constante con el nombre del CLOCK y el valor 2 correspondiente al pin 2 del Arduino Mega.
Inicializar el Arduino y Sincronizar con el Clock
Vamos a definir la función obligatoria setup() en dónde vamos a inicializar diversas variables.
La línea 8 define la función de setup, función obligatoria del arduino.
Las líneas 9 a 11 leen el contenido del array ADDR y configuran cada uno de esos pines en modo INPUT para leer la información que vaya a estar en los mismos.
Las líneas 12 a 14 leen el contenido del array DATA y configuran cada uno de esos pines en modo INPUT para leer la información que vaya a estar en los mismos.
Las líneas 15 a 17 leen el contenido del array EXP y configuran cada uno de esos pines en modo INPUT para leer la información que vaya a estar en los mismos.
La línea 18 configura en en pin de CLOCK como INPUT
Las líneas 19 a 21 son un comentario.
La línea 22 crea en el Arduino mega una interrupción con la instrucción attachInterrupt donde le dice como primer argumento que elija el pin CLOCK para analizar en base a que pin hacer la interrupción, como segundo argumento que ejecute la función onClock y como último argumento que la ejecute cuando los valores del pin CLOCK vayan de 0V a +5V o lo que conocemos como rising edge.
Línea 23 Definimos que queremos que el Arduino se comunique a través del puerto serial a una velocidad de 115200 bps.
Transformar los voltajes a unos y ceros y Mostrarlos en Pantalla
La siguiente función es la que realiza toda la magia. Esta es la función onClock la cual se encarga de leer los voltajes de los buses y mostrarlos en pantalla. Esta función se va a ejecutar cada vez que el pulso del reloj vaya de 0v a +5v desde el pin 2 del expansion BUS al pin 2 del Arduino Mega gracias a que creamos una interrupción que ejecuta esta función en la línea 22.
Línea 26 define el nombre de la función como onClock
Línea 27 define una variable output como array de 15 caracteres la cual vamos a utilizar para formatear la forma de mostrar información en la línea 49
Línea 28 definimos un entero sin signo con nombre address en esta vamos a almacenar todos los bits del ADDRESS BUS desde el más significativo A15 al menos A0
Línea 29 comenzamos un bucle for que va a correr 16 veces
Línea 30 leemos un bit del bus de ADDRESS, en cada iteración será el número que corresponda a ADDR[i] si i es cero será por ejemplo el valor del pin 23 del Arduino Mega correspondiente al pin del Address Bus A15. El signo de interrogación ? seguido de 1:0 nos hará guardar en la variable bit el número 1 en caso de ser verdadero (+5v) o 0 en caso de ser falso (+0v)
Línea 31 imprimimos ese bit en a través de la conexión Serial
Línea 32 corremos todos los bits que tuviéramos en la variable address a la izquierda y agregamos en el lugar vacío al bit que recién leímos (lugar menos significativo)
Línea 33 cerramos el bucle for
Línea 34 imprimimos un espacio para separar el contenido
Línea 35 a 41 hacemos lo mismo con el bus de datos
Línea 42 a 48 hacemos lo mismo con el bus de Expansión
Línea 49 definimos el formato de salida a imprimir dentro de la variable output poniendo como un número hexadecimal de 4 caracteres al bus de ADDRESS, como un hexadecimal de 2 caracteres al bus de DATA y hexadecimal de 4 caracteres al bus de EXPANSION
Línea 50 Imprimimos la variable output en la consola serial y saltamos a la siguiente línea
Línea 51 cerramos la función onClock
Default Loop
Líneas 52 a 54 generamos la función default del arduino de loop pero vacía ya que no la utilizamos por leer basados en las interrupciones generadas por en el pin 2 por el timing del CLOCK.
Ejemplo de output
Aqui podemos observar
- Los 16 números en binario correspondientes al ADDRESS BUS ordenados como A15 a A0.
- Los 8 números en binario correspondientes al DATA BUS ordenados como D7 a D0.
- Los 16 números en binario correspondientes al EXPANSION BUS ordenados como E15 a E0.
- Los 4 números en hexadecimal representando al ADDRESS BUS
- Los 2 números en hexadecimal representando al DATA BUS
- Los 4 números en hexadecimal representando al EXPANSION BUS
Segundo Programa para mostrar instrucciones ejecutadas
Con este programa vamos a interpretar la información anterior y poder ver:
- La información en hexadecimal,
- Qué dirección de memoria estamos viendo,
- Si estamos haciendo una lectura o una escritura,
- Dilucidar si estamos o no ante un OPCODE de instrucción en el DATA BUS o sólo datos.
- Interpretar en caso de ser una instrucción qué instrucción es.
- Mostrar el caso especial de realizar un reset
- Mostrar que chip estamos escribiendo si ROM, RAM, o alguno de I/O
Definir Buses
Línea 1 es un comentario
Línea 2 en el diagrama nos define la variable ADDR como un array en el cual vamos a tener los números impares del 23 al 53, estos coinciden con los pines del Arduino Mega que tenemos conectados a los pines A15 hasta A0 del bus de datos.
La línea 3 define la variable DATA como un array donde los números pares del 36 al 22 coinciden con los pines D7 a D0 del bus de datos.
La línea 4 define la variable EXP como un array en el cual vamos a tener los números consecutivos del 62 al 69 para representar los pines del bus de Expansión E15 a E8 y los pines pares del 52 al 38 para representar los pines del bus de Expansión E7 a E0. Con la excepción del pin de CLOCK que como ya dijimos va a ser el pin 2 en lugar del in 40 para poder agregarle una interrupción. Por esto definimos una constante con el nombre del CLOCK y el valor 2 correspondiente al pin 2 del Arduino Mega.
Vamos a definir algunos pines extras del EXPANSION BUS.
Línea 6 define el pin 38 como pin de RESET, cuando este pin tenga el valor +0v significa que estamos presionando el botón de reset de la placa del procesador.
Línea 7 define el pin 2 como pin de CLOCK, este pin en sus transiciones de +0v a +5v y +0v marca un ciclo de reloj
Línea 8 define el pin 42 como pin de READ_WRITE, cuando el pin esté en +0v estamos antes una escritura y cuando esté en +5v una lectura.
Línea 9 define el pin 68 como pin de SYNC, cuando el pin esté en +0v en el DATA BUS hay datos y cuando esté en +5v en el DATA BUS hay instrucciones.
Inicializar el Arduino y Sincronizar con el Clock
Vamos a definir la función obligatoria setup() en dónde vamos a inicializar diversas variables.
La línea 11 define la función de setup, función obligatoria del arduino.
Las líneas 12 a 15 leen el contenido del array ADDR y del array EXP configurando cada uno de esos pines en modo INPUT para leer la información que vaya a estar en los mismos.
Las líneas 16 a 18 leen el contenido del array DATA y configuran cada uno de esos pines en modo INPUT para leer la información que vaya a estar en los mismos.
La línea 19 configura en en pin de CLOCK como INPUT.
La línea 20 configura en en pin de READ_WRITE como INPUT.
La línea 21 configura en en pin de SYNC como INPUT.
La línea 22 configura en en pin de RESET como INPUT.
La línea 23 es un comentario.
La línea 24 crea en el Arduino mega una interrupción con la instrucción attachInterrupt donde le dice como primer argumento que elija el pin CLOCK, como segundo argumento que ejecute la función onClock y como último argumento que la ejecute cuando los valores vayan de 0V a +5V o lo que conocemos como rising edge.
Línea 25 definimos que queremos que el Arduino se comunique a través del puerto serial a una velocidad de 115200 bps.
Transformar los voltajes a unos y ceros y Mostrarlos en Pantalla
La siguiente función, nuevamente, es la que realiza toda la magia. Esta es la ya conocida función onClock la cual se encarga de leer los voltajes de los buses y mostrarlos en pantalla. La misma se va a ejecutar cada vez que el pulso del reloj vaya de 0v a +5v desde el pin 2 del expansion BUS al pin 2 del Arduino Mega gracias a que creamos una interrupción que ejecuta la misma en las línea 24.
Línea 28 define el nombre de la función como onClock
Línea 29 define una variable SYNC_VALUE donde vamos a guardar el valor S si están en +5v y n si está en +0v. Si la variable es S entonces en el bus de datos tenemos el código de la instrucción a ejecutar.
Línea 30 define una variable RESET_VALUE donde vamos a guardar el valor n si están en +5v y R si está en +0v. Si la variable es R entonces la placa del procesador está recibiendo la señal para comenzar a ejecutar un reset.
Línea 31 define una variable READ_WRITE_VALUE donde vamos a guardar el valor r si están en +5v y W si está en +0v. Si la variable es r entonces estamos haciendo una lectura si es W estamos haciendo una escritura.
Línea 32 define una variable output como array de 40 caracteres la cual vamos a utilizar para dar formato a la información a mostrar en la línea 48
Línea 33 definimos un entero sin signo con nombre address en este vamos a juntar todos los bits del ADDRESS BUS desde el más significativo A15 al menos A0
Línea 34 comenzamos un bucle for que va a correr 16 veces
Línea 35 leemos un bit del bus de ADDRESS, en cada iteración será el número que corresponda a ADDR[i] si i es cero será por ejemplo el valor del pin 23 del Arduino Mega correspondiente al pin del Address Bus A15. El signo de interrogación ? seguido de 1:0 nos hará guardar en la variable bit el número 1 en caso de ser verdadero (+5v) o 0 en caso de ser falso (+0v).
Línea 36 imprimimos ese bit en a través de la conexión Serial.
Línea 37 corremos todos los bits que tuviéramos en la variable address a la izquierda y agregamos en el lugar vacío al bit que recién leímos (lugar menos significativo).
Línea 38 cerramos el bucle for.
Línea 39 imprimimos un espacio para separar el contenido
Línea 40 a 45 hacemos lo mismo con el bus de datos
Línea 46 corremos la función sync_string la cuál en base a las variables SYNC_VALUE, RESET_VALUE y data va a guardar en la variable de tipo caracter instruction la instrucción que se ejecutó en el procesador si estamos en un ciclo de instrucción o la palabra RESET si se está presionando el botón de reset.
Línea 47 corremos la función find_chip que toma como parámetros los bits del address bus y nos va a decir a qué chip de la 20c (ROM, RAM, VIA1, etc) nos estamos dirigiendo.
Línea 48 definimos el formato de salida a imprimir dentro de la variable output poniendo:
- un número hexadecimal de 4 caracteres con el bus de ADDRESS,
- un caracter si es una lectura o escritura,
- un caracter si estamos en un ciclo de SYNC también llamado ciclo de fetch de opcode,
- un número hexadecimal de 2 caracteres con el bus de DATA,
- Cinco caracteres para definir el chip que estamos usando
- la instrucción que estamos ejecutando si es un ciclo de SYNC, o la palabra RESET si estamos tocando el botón de reset o nada en caso de encontrarnos en un ciclo de datos
Línea 49 imprimimos la variable output y saltamos una línea.
Línea 50 cerramos la función onClock
Encontrando que instrucción estamos ejecutando
La función sync_string se encarga de decirnos qué instrucciones estamos ejecutando teniendo en cuenta 3 parámetros:
- si estamos o no en un ciclo SYNC,
- si estamos o no en un ciclo de RESET y
- los datos del bus de datos.
Línea 53 definimos la función sync_string
Línea 54 – 56 si la variable RESET tiene la letra R estamos en un ciclo de reset y por lo tanto devolvemos la palabra RESET
Línea 57 si la variable SYNC_VALUE tiene la letra S estamos en un ciclo de opcode fetch por lo tanto en el bus de datos vamos a tener el opcode de la instrucción que vamos a ejecutar.
Línea 58 creamos un case con los datos del bus de datos en la variable DATA, el case es una instrucción que nos deja comparar varios valores constantes contra la variable y devolver una respuesta distinta dependiendo de cada valor. En nuestro caso devolveremos el nombre de la instrucción ejecutada usando como entrada el opcode de la misma.
Línea 59 por ejemplo corremos case para qué si la variable data tiene los valores hexadecimales 0x00 devuelve el string que representa a la instrucción BREAK en este caso BRK.
Línea 61 a 300 seguimos analizando la variable data para ver distintas instrucciones.
Línea 301 – 302 creamos el caso default por si no encontramos el valor de data en ninguno de nuestros case
Línea 305 terminamos el IF devolviendo un string vacío si no estábamos en un ciclo de SYNC
Encontrando con que chip nos estamos comunicando
Nuestra 20c tiene diferentes chips como ser ROM, RAM, chips de I/O. Para que el procesador pueda hablar con cada uno de ellos vamos a utilizar una dirección del ADDRESS BUS diferente. La función find_chip nos devuelve un string con el nombre del chip dependiendo qué dirección estamos usando.
Línea 310 define la función find chip aceptando todos los bits del bus de address como parámetro
Línea 311-312 si el address es mayor a 0x8000 devuelve que es el chip de ROM
Línea 313-314 si el address es mayor a 0x0100 y menor a 0x0200 devuelve que es el STACK un área especial de la memoria.
Línea 315-316 si el address es mayor a 0x0000 y menor a 0x4000 devuelve que es el chip RAM.
Línea 317-318 si el address es mayor a 0x6000 y menor a 0x7000 devuelve que es el chip de I/O VIA1.
Línea 319-320 si el address es mayor a 0x7000 y menor a 0x8000 devuelve que es el chip de I/O VIA2.
Línea 321-322 si el número es distinto a los indicados anteriormente devuelve que no conoce al chip.
Default Loop
Líneas 326 a 327 generamos la función default del arduino de loop pero vacía, ya que no la utilizamos por leer basados en las interrupciones generadas por el pin 2 con el timing del CLOCK.
Ejemplo de output
Aquí podemos observar
- 16 números en binario representando el ADDRESS BUS ordenados desde A15 a A0
- 8 números en binario representando el DATA BUS ordenados desde D7 a D0
- 4 números en hexadecimal representando el ADDRESS BUS.
- 1 caracter representando una lectura como “r” o una escritura como letra “W”
- 1 caracter representando un ciclo de opfetch como “S” o un ciclo de datos como letra “n”
- 2 números en hexadecimal representando el DATA BUS.
- 5 caracteres representando que chip estamos dirigiéndonos
- 10 caracteres explicando que instrucción estamos buscando del data bus en caso de que SYNC sea +5v (S en nuestro output)
Circuito de la Placa DUINO PROTOCOL ANALYZER de la 20c
El siguiente gráfico muestra el circuito que explica el funcionamiento del DUINO PROTOCOL ANALYZER
El circuito posee los siguientes elementos:
Pin HEADER PZ254
Este pin header tiene 34 pines y vamos a utilizarlo para conectarnos a las terminales superiores de nuestro Arduino Mega.
Pin HEADER H12,H16 y H18
Estos son 3 pin headers de 8 pines que nos servirán para terminar las conexiones a nuestro Arduino Mega y darle soporte estructural al mismo cuando nos conectamos a él
Pin HEADER H3,H13
Estos son 2 pin headers de 16 pines que nos servirán para conectarnos al ADDRESS BUS y al EXPANSION BUS
Pin HEADER H1
Un pin header de 8 pines que nos servirá para conectarnos al DATA BUS
HEADERs H6 y H14 POWER y GROUND
Estos headers poseen dos pines y están conectados a las capas de 5V y de GROUND respectivamente. Tenemos dos de estos conectores, uno en cada esquina de la placa.
AGUJEROS para TORNILLOS
Para poder fijar nuestra placa a distintos lugares la misma cuenta con 6 agujeros para tornillos de 3mm o M3.
NETLIST
Los componentes están conectados entre sí a través de un objeto llamado netlist el cual nos permite tener diagramas más limpios.
Este funciona de forma tal que todo lo que tenga el mismo nombre pertenece al mismo netlist y deberá estar conectado junto cuando hagamos el PCB (con traces).
En nuestro ejemplo todas las conexiones CLOCK estarán conectadas por traces en el PCB
PCB de la Placa DUINO PROTOCOL ANALYZER de la 20c
El siguiente PCB explica cómo se ubican los elementos y traces para conectar nuestro circuito. El PCB es de 4 capas teniendo en la capa llamada TOP todas las conexiones de nuestros netlist a través de traces, los cuáles son finas líneas de cobre que conectan los mismos como si fueran cables.
Tenemos dos capas especiales llamadas 5v y GROUND donde conectaremos las conexiones de power y ground o masa. Al usar estas conexiones en capas separadas nos ahorramos muchos centímetros de traces que deberían conectarse a pines con los voltajes de 5V y GROUND y podemos conectar directamente estos pines a la capa correspondiente.
LAYER 5V
LAYER GROUND
Otra ventaja de tener una capa entera para GROUND es poder aislar el ruido eléctrico de las conexiones entre componentes.
Por último tenemos la capa de BOTTOM donde se sueldan nuestros componentes y tenemos conexiones adicionales.
Modelado 3D
Cuando terminamos de realizar nuestra Placa debemos proceder al modelado 3D de la misma para observar cómo queda y si nos gusta el lugar donde pusimos cada componente.
Generación de archivos fuente
Para poder mandar a fabricar nuestro PCB deberemos contar con al menos 3 archivos:
- Archivo .gerber donde le indicamos al fabricante como armar nuestra placa
- Archivo BOM o Bill of materials donde se encuentran todos los componentes que forman nuestra placa con el código de producto del fabricante.
- Archivo Pick and Place donde le indicamos al fabricante cómo ubicar los componentes en nuestra placa PCB.
Estos archivos los van a encontrar previamente generados en el github de Osolabs. También incluimos archivos para poder editar el circuito con el software EasyEDA o Altium Designer.
Con estos tres archivos vamos a poder fabricar nuestra placa
Gerber_v03_PROTOCOL_ANALYZER_DUINO_4Plane_2025-04-02.zip Este archivo contiene todos los planos para poder generar nuestra placa PCB.
BOM_v03_PROTOCOL_ANALYZER_DUINO_4Plane_v03_PROTOCOL_ANALYZER_DUINO_4Plane_2025-04-02.xls Contiene todos los componentes de nuestra placa y el código del fabricante que identifica a ese componente.
PickAndPlace_v03_PROTOCOL_ANALYZER_DUINO_4Plane_2025-04-02.xlsx
Indica en qué parte del PCB va cada componente y en qué capa debe ubicarse.
Los siguientes archivos se proveen para poder editar el circuito
3DModel_duino_pa_front.png
Es una imágen con la parte de atrás de nuestra placa modelada en 3D
3DModel_duino_pa_back.png
Es una imágen con la parte de adelante de nuestra placa modelada en 3D
Altium_Circuit_1_v03_02_PROTOCOL_ANALYZER_DUINO_4Plane.schdoc
Contiene el diseño del circuito editable con el programa Altium Designer.
Altium_PCB_v03_02_PROTOCOL_ANALYZER_DUINO_4Plane.pcbdoc
Contiene el diseño del PCB editable con el programa Altium Designer.
PCB_v03_PROTOCOL_ANALYZER_DUINO_4Plane_2025-04-02.pdf
Es un PDF con un dibujo de cada capa del PCB
ProDoc_v03_02_PROTOCOL_ANALYZER_DUINO_4Plane_2025-05-19.epro
Archivo para EasyEDAPro con el circuito y el PCB el cual puede editarse.
SCH_v03_PROTOCOL_ANALYZER_DUINO_4Plane_2025-04-02.pdf
Es un PDF con los circuitos lógicos de la placa
Preparación de las Placa DUINO PROTOCOL ANALYZER
Al recibir nuestra placa de la fábrica y antes de comenzar a utilizar la misma y al momento que la sacamos de la caja, hay algunas tareas que deberemos hacer para poder hacer uso al máximo de la misma:
- Remover los bordes de manipulación de la placa
- Limpiar placa con alcohol isopropílico
- Conectar el Arduino Mega con la Placa DUINO PROTOCOL ANALYZER
Alinear bien los pines del DUINO PA con los sockets del arduino Mega
- Conectar el cable USB 2.0 tipo A que va a ir a nuestra computadora en el Arduino Mega
- Conectar a la parte superior de alguna placa de la 20c
Guía de Conexión de la placa DUINO PROTOCOL ANALYZER de la 20c
Vamos a explicar como conectar los distintos componentes de la placa para dejar esta lista para funcionar en una maqueta. Esta es una configuración con todas las placas que vamos a utilizar aunque todavía no las hayamos visto. Puedes tener esta sección como referencia para cuando ensambles toda la 20c.
DUINO PROTOCOL ANALYZER
Para configurar la placa de DUINO PROTOCOL ANALYZER vamos a realizar las siguientes conexiones.
- Conectamos el Arduino Mega a los pines internos del DUINO PROTOCOL ANALYZER.
- Conectamos un cable USB 2.0 tipo A al Arduino Mega
- Conectamos el mismo cable a nuestra Notebook.
- Conectar los pines de BUSes de la Placa DUINO PA a la parte superior de alguna de las placas que usamos en nuestra maqueta.
Experimento – Probando el DUINO PROTOCOL ANALYZER con el Proceso de RESET y la instrucción NOP
Vamos a realizar nuevamente este experimento probando nuestro DUINO PROTOCOL ANALYZER pero esta vez mostrando en mucho detalle cuando se realiza un Reset y cómo se ejecuta la instrucción NOP.
Repasamos cómo se ve la configuración de la instrucción NOP y la base del experimento.
Le vamos a indicar a Mano a nuestro CPU 6502 que ejecute la instrucción de no operación NOP, la misma está codificada como EA en las instrucciones del lenguaje máquina del 6502.
EA se traduce en binario cómo 1110 1010 y esto es lo que va a esperar nuestro procesador en sus pines de data para poder leer esa instrucción. Para poder hacerlo vamos a conectar 8 resistencias a nuestros pines de datos de la siguiente forma:
Aquí podemos ver nuestra placa DUINO conectada a un cable USB que lleva a nuestra LAPTOP, la placa de CPU 6502, la placa de CLOCK y un BREADBOARD con la instrucción cableada EA.
Cargaremos el Programa 001_Arduino_DUINO_PA en nuestro Arduino Mega y luego abriremos el Serial Monitor.
Si corremos una secuencia de reset tocando el botón de RESET del la placa CPU 6502 y observamos el resultado, veremos cómo ejecuta el reset en 7 ciclos de reloj y buscará en las posiciones de memoria FFFC y FFFD donde está el vector (otra posición de memoria) que posee la primera instrucción a ejecutar. Tarda 7 ciclos ya que en RESET no es ni más ni menos que una instrucción BRK o BREAK cargada por hardware a través del pin de RESET.
El reset debe ser mantenido en 0v por lo menos durante dos ciclos de reloj para que sea reconocido.
Reset seguido de lectura de instrucciones NOP
- Conectamos el pin CLK del header CLOCK_555_OUT
- Seleccionemos el switch para el reloj paso a paso.
- Presionemos el botón de reset de nuestro CPU y dejemoslo presionado.
- Presionar 3 veces el botón de STEP BUTTON de nuestra placa de CLOCK
- Soltar el botón de RESET de nuestro CPU
- Continuemos presionando el botón de STEP BUTTON de nuestra placa de CLOCK y veremos que cada vez que lo hacemos avanza un ciclo en nuestro CPU, algunas instrucciones ocupan un ciclo de reloj y otras más
- Observamos en detalle los datos que nos da nuestro DUINO PROTOCOL ANALYZER a través del Arduino Mega.
Análisis de los buses
Vamos a utilizar el script 001_Arduino_DUINO_PA y analizaremos el output de nuestro experimento.
Repasemos el OUTPUT
Aqui podemos observar
- 16 números en binario representando el ADDRESS BUS ordenados desde A15 a A0
- 8 números en binario representando el DATA BUS ordenados desde D7 a D0
- 4 números en hexadecimal representando el ADDRESS BUS.
- 1 caracter representando una lectura como “r” o una escritura como letra “W”
- 1 caracter representando un ciclo de opfetch como “S” o un ciclo de datos como letra “n”
- 2 números en hexadecimal representando el DATA BUS.
- 5 caracteres representando que chip estamos dirigiéndonos
- 10 caracteres explicando que instrucción estamos buscando del data bus en caso de que SYNC sea +5v (S en nuestro output)
En las primeras tres líneas podemos leer la palabra RESET eso significa que tenemos el botón de reset presionado.
Luego contamos 7 ciclos de reloj que es lo que dura un reset y vemos que en los próximos dos ciclos buscamos el vector de reset en las direcciones FFFC y FFFD.
Como tenemos cableado el data bus siempre vamos a recibir 11101010 que es el equivalente hexadecimal a EA por eso al leerlo dos veces el program counter va a apuntar a la dirección EAEA.
La próxima instrucción leída del data bus es la instrucción EA la cual significa la no operación NOP, sabemos que es un código de operación porque el flag S de SYNC está activado en nuestro bus de expansion significando un ciclo de opfetch.
Esta operación tarda dos ciclos de reloj en ejecutarse por eso podemos ver pares de direcciones EAEB EAEB, EAEC, EAEC, etc.
Cada vez que la instrucción es ejecutada y pasan los dos ciclos en program counter se incrementa en uno como podemos ver EAEB, EAEC, EAED, etc.
El ciclo de ejecución de la primera instrucción es la siguiente:
- EAEA lee del databus el opcode hay +5V en el pin de SYNC lo interpreta como una instrucción Incrementa el program counter.
- Ejecuta la instrucción EA o sea NOP de no operación (ciclo 1 de 2) y pone EAEB en el address bus
- Termina de ejecutar la instrucción NOP (ciclo 2 de 2) y trae la próxima instrucción de la dirección EAEB que sigue en el address bus. Incrementa el program counter.
Y asi sigue.
También podemos ver que nos indica que el chip ROM está siendo usado pero en realidad no tenemos ningún chip ROM!! . Esto es porque nuestro programa interpreta que siempre que el pin A15 sea 1 o +5v estaremos hablando con el chip ROM.
Esto será muy útil cuando analizemos el chip ROM en un próximo episodio.
Conclusiones
La Placa DUINO PROTOCOL ANALYZER nos va a permitir utilizar un Arduino Mega como si fuera un analizador de Protocolos, pudiendo ver el contenido de cada bus y la interpretación del funcionamiento del mismo traduciendo las instrucciones.
La placa DUINO PROTOCOL ANALYZER en funcionamiento
Para ver visualmente cómo conectar la placa DUINO PROTOCOL ANALYZER a la 20c les dejo como siempre un video en detalle de la serie. En este vamos a ver cómo se conectan los pines, y nuestro experimento en forma visual indicando.
Referencias
A continuación les dejo algunos links donde profundizar el tema:
WEBSITE
Aquí está el sitio de OsoLabs con todos los videos y artículos.
VIDEOS
Aquí el video correspondiente a este capítulo y la lista de todos los videos de esta serie.
https://www.osolabs.tech/the20c
ARTICULOS
Aquí podrán encontrar todos los artículos sobre La 20c:
https://blog.espaciotec.com.ar
https://www.osolabs.tech/the20c
CÓDIGO y DISEÑO DE PLACAS PCB
Todos los ejemplos de código de este artículo los pueden encontrar en:
https://github.com/osolabstech/The20c
OTROS RECURSOS
Y como siempre la serie de Ben Eater del 6502 que es excelente:
Build a 6502 computer | Ben Eater
Como la serie donde vemos todos los jueguetes y periféricos de la Commodore que siempre quisimos tener, Los chiches de la Commodore tanto en video como en artículos
https://www.osolabs.tech/los-chiches-de-la-commodore
Y la serie donde comparamos en 6502 contra el 6510 utilizando breadboards.
https://www.osolabs.tech/6502vs6510
6502 vs 6510 estudio detallado y comparación – YouTube