Empecé con la Commodore de chico, sigo con la Commodore de grande.
Programo para 6502, Arduino, Raspberry y algunos algoritmos de Bioinfomática, algo en C++, algo en Python, algo en Assembler.
Fanático de la electrónica home brew desde breadboard a diseñar PCBs propios.
Armé la 20c y OsoLabs https://www.osolabs.tech
Mi GitHub para quien quiera sumarse a los proyectos y chusmear código:
https://github.com/carlinhocr/
Desde Argentina al Mundo
En esta ocasión vamos a estudiar a un gran amigo que nos dejó excelentes recuerdos a la hora de obtener vidas infinitas en nuestros videojuegos, El Reset o Jabonera.
Vamos a estudiar que hacía, como funciona por dentro, que circuitos tenía y cómo lograr poner vidas infinitas en alguno de nuestros videojuegos favoritos.
Qué es el reset
El reset es un dispositivo que nos dejaba llamar al circuito de reset del procesador 6510 sin tener que apagar el mismo y sin la necesidad de borrar la memoria y comenzar desde cero. De esta forma podemos modificar posiciones de memoria con un programa cargado en la misma.
Su forma más típica es la de un cartucho blanco con un botón rojo que se conecta al puerto de usuario.
El puerto de usuario posee el siguiente pinout
Estamos interesados en dos pines específicos el pin 12 de ground o tierra que nos va a poder dar valores LOW o cero y el PIN 3 o Reset. Algunos diseños también usan el pin 1, el pin N o el pin A como ground.
El PIN 3 está conectado a través del PCB del Commodore 64 directamente con el Pin 40 o de Reset del Procesador 6510. El Botón de reset activa el reset del procesador.
Así se ve la conexión de ambos resaltada en azul donde vemos la conexión del Pin 3 del puerto de usuario al pin 40 del procesador 6510. También existe otro modelo de reset que está conecta al puerto serial y hasta puede estar conectado en la disquetera.
La línea de reset se mantiene en High cercano a los 5 Volts gracias a una resistencia de 1Kilo ohms que conecta la línea de reset con los 5 Volts del mother, en el diagrama R36.
Cómo funciona el reset internamente
El botón de reset internamente es un circuito que conecta el pin 3 de reset al pin 12 de ground a través de un botón de push que se encuentra normalmente abierto, al presionarlo y unirlo al pin 12 de ground hace que el pin 3 del user port conectado al pin 40 del procesador reciba un voltaje de low (menor a 0,4 Volts).
En esta foto podemos ver el pin 1 unido al pin 3 (recordar que una alternativa de pin de grund era el uno) y un botón para reset conectados a un placa que expande el puerto de usuario.
En nuestras latitudes (33 grados sur) hemos encontrado directamente cables soldados al botón y a los dos pines del user port de la mother lo que no solemos recomendar.
En nuestros pagos esta es la típica jabonera a la que estamos acostumbrados, la que conectamos al User port.
La misma posee un botón conectado a los pines 3 como reset y 12 como Ground a través de dos alambres.
Si medimos con un osciloscopio cada vez que presionamos el reset vemos como la línea del reset conectada al pin 3 baja a 0 volts. En la imagen el probe o punta de testeo del osciloscopio está conectado al pin 3 de reset y el cable de ground al pin 12.
Al recibir un low en el pin 40 del procesador se activa la rutina de reset del 6510 que en este caso va hasta la posición de memoria $FFFC y $FFFD y se fija que dirección de memoria está aquí adentro y va a ejecutar ese programa.
En el caso de la Commodore 64 va a la rutina que está en la posición $FCE2 y ejecuta el siguiente programa:
Esta rutina inicializa la commodore sin borrar la memoria:
Primero carga el valor $FF al registro X para luego configurar el stack pointer,
Deshabilita las interrupciones prendiendo el flag de interrupciones,
Configura el stack pointer en FF dejándole listo en $01FF,,
Borra el flag de modo decimal del procesador,
Se fija si existe algún cartucho con autostart y si existe este lo ejecuta (a partir de la posición $8000),
Si no había cartucho llama a las rutinas de inicialización IOINIT (inicialización de dispositivos),, RAMTAS (inicilaiza y testea la RAM), RESTOR (configura los vectores como ser también el de reset $FFFCy $FFFD), y por último CINT que inicializa la pantalla,,
Limpia el flag de interrupciones habilitándolas nuevamente y
Arranca el programa de Basic a través de la posición de memoria $A000.
Finalmente vemos que nos deja en el prompt de basic pero con el programa que estuviera en memoria a la hora de pulsar el botón de reset todavía cargado en la misma.
¿Cómo lo usamos?
Primero cargamos un programa a memoria desde disco o cassette y ni bien este terminó de cargar pulsamos el botón de reset.
Si el programa que había en memoria es un programa en basic debemos antes de usarlo restaurar los punteros al código y memoria del mismo. Esto se realiza con los siguientes comandos.
(pO = p [Shift] o; pE = p [Shift] e) estas son las abreviaturas de poke para po y peek para pe
Luego de esto podemos correr el programa Basic, listarlo con LIST o grabarlo a disco.
Si lo que tenemos es un programa en código máquina, como por ejemplo un juego, podemos verlo con un monitor de código máquina o por si ejemplo si tenemos el wonderboy y queremos ponerle como truco vidas infinitas tipeamos los siguientes comandos desde el basic.
POKE 2676,238
SYS 2112
El comando Poke modifica la posición de memoria de las vidas y el comando SYS es una llamada a ejecutar el programa que está en la dirección 2112 que es el comienzo del juego.
Conclusión
Y de esta forma funciona nuestra querida Jabonera que tanto hemos usado para poder interrumpir alguno que otro videojuego y ahora sí ,con vidas infinitas, poder terminarlo. Un circuito muy simple y uno de nuestros clásicos chiches de Commodore.
Estudio visual
Para poder estudiar visualmente cómo funciona el Reset Jabonera, les dejo este video que complementa al artículo.
Referencias
A continuación les dejo algunos links donde profundizar el tema:
VIDEOS
El Reset Jabonera – Lo Chiches de la Commodore 64 Parte 1
¡Bienvenidos! Estamos empezando una nueva serie llamada Los Chiches de la Commodore 64. Nuestra querida Commodore nos dio muchas alegrías pero ella no podría haber hecho todo sola, por eso, siempre se valió de algunos Chiches.
En esta nueva serie vamos a estudiar cuáles son esos chiches, como funcionan por dentro y como usarlos.
Qué son los Chiches
Los Chiches son todos aquellos dispositivos clásicos y modernos que nos ayudan a usar la Commodore como por ejemplo la Famosa Jabonera de Reset, el sd2iec, los joysticks, el lápiz óptico, los adaptadores para el mouse, los cartuchos, los death test, las expansiones de memoria, módems tradicionales, modem wifi. Y podría seguir mucho tiempo más.
Siempre fueron un pequeño misterio cómo funcionan por dentro, de qué circuitos de la máquina se valen y sobre todo ¡Cómo se usan! ¡Más de uno tiene alguna función oculta que todavía al día de hoy no descubrimos!.
Qué vamos a ver
En este viaje vamos a estudiar:
Nuevos dispositivos de entrada salida como ser:
Adaptadores VGA como el Apollo 64+.
Sd2iec para conectar una sd card a tu Commodore.
Pi1541 para tener una 1541 con sdcard que respete todos los vericuetos e idiosincrasias de nuestra querida 1541.
El clásico Sánguche (leer con voz de yo quiero un sangucheee) S-Video a RGB a HDMI.
Dispositivos modernísimos como ser:
El cartucho Ultimate II+, una gran navaja suiza.
Modem wifi para acceder a una bbs a través de Internet.
VersaCart para poder armar tu propio cartucho.
La Ram Expansion Unit (REU) a través de una raspberry pi.
Joysticks modernos con microswitches.
IRQHack.
Dispositivos Clásicos como ser:
La Jabonera de Reset.
El cartucho CPM.
El clásico modem de Commodore.
La REU de ampliación de memoria 1750.
Joystick Colossus.
Turbo Cartridge.
FastLoad.
No te preocupes si no entendiste ni la mitad de los acrónimos, esta serie es para vos.
Bienvenidos
En fin tenemos para divertirnos un buen rato y aprender cada día más de nuestra querida Commodore 64. Así que para todos los que siempre quisieron saber cómo funcionan esos maravillosos chiches que usa nuestra Commodore, así como para los que recién los están descubriendo ahora, les pido que me acompañen en esta nueva aventura.
Saludos
Carlinho de OsoLabs
En Video
Aquí puede encontrar el video Introductorio para la nueva serie.
Continuamos este estudio comparativo del 6502 vs el 6510 conectando un LCD de 16 caracteres x 2 líneas y programándolo con un mensaje. Vamos a estudiar cómo conectar un VIA 6522 y un CIA 6526 al lcd HD4470U de Hitachi y utilizando nuestro 6502 y nuestro 6510 mostrar el texto “OsoLabs” en el display en dos maquetas breadboard simultáneas.
El LCD Hitachi HD44780U
Nuestro principal display es el LCD de Hitachi el mismo posee el siguiente diagrama esquemático.
Este LCD tiene 16 caracteres que se pueden mostrar en dos líneas y cada carácter puede ser de 5×8 o 5×10 puntos. Posee internamente el dibujo o font de varios tipos de caracteres que se eligen con valores correspondientes mayormente al ASCII. Estos caracteres incluyen el alfabeto tradicional, caracteres japoneses y símbolos. El LCD puede ser controlado por un procesador de 4 bits o uno de 8 bits, nosotros lo utilizaremos en modo 8 bits por estar usando la línea 6502/6510.
En cuanto a velocidad es compatible con un bus de datos de hasta 2Mhz, nosotros vamos a estar utilizando hasta 1Mhz el máximo de velocidad de nuestro 6510.
PinOut del LCD
El siguiente esquema muestra y explica el pin-out
VSS (Ground): conexión a tierra de nuestro LCD
VDD: conexión a 5 Volts +
VE: Pin de contraste, se conecta normalmente a un potenciómetro en su pin de polo y el otro pin va directo a tierra.
Register Select RS: Nos permite elegir si escribir al Instruction Register usando el valor 0 o al Data Register usando el valor 1
Read/Write : Permite escribir si el valor es cero y leer si el valor es 1
Enable: Comienza la lectura o escritura sacando los pines DB7 a DB0 de su modo de triestado.
DB7 a DB0: Bus datos para escribir o leer. En el modo de operación de 4 bits sólo se usando los pines DB7 a DB4
A : Ánodo (pin positivo +5 Volts) para encender la luz de backlight
K: Cátodo (pin negativo 0 Volts) para encender la luz de backlight
Cómo leer y cómo escribir nuestro LCD
Hay tres pines que funcionan para poder leer o escribir los registros internos y la pantalla de nuestro LCD, estos son RS, RW y E. En la siguiente Tabla especificamos cómo realizar cada operación.
RS = 0 /R/W = 0 E=1 permiten enviar una instrucción al LCD, escribiendo el instruction register
RS = 1 /R/W = 0 E=1 permiten enviar datos al LCD, escribiendo el data register.
Generalmente el valor del pin Enable se usa como un Toggle o pulso y este se dispara cuando ya tengo todos los datos de los demás pines (RS, RW y DB7 a DB0) estables y con valores correctos.
Instrucciones internas del LCD
El LCD posee instrucciones internas que sirven para desde limpiar la pantalla o elegir el ancho de los caracteres hasta encender o apagar el display, las mismas estan explicadas en la siguiente tabla:
El formato de estas instrucciones es:
Valor del pin RS,
Valor del pin /R/W,
Una cantidad de ceros y luego un 1 para identificar la instrucción en los pines DB7 a DB0,
El resto después del 1 que identifica la instrucción, son los parámetros de la misma.
Por ejemplo la instrucción Display on/off control que controla tres funciones de nuestros display está codificada de la siguiente forma:
RS
/R/W
DB7
DB6
DB5
DB4
DB3
DB2
DB1
DB0
0
0
0
0
0
0
1
D
C
B
El valor RS es cero para indicar que estamos escribiendo al instruction register del LCD
El valor /R/W es cero para indicar que es una escritura
La instrucción está indicada por los pines DB7 a DB3 y es 00001
El pin DB2 es un parámetro que indica si prender o apagar el display
El pin DB1 es un parámetro que indica si está prendido o no el cursor
El pin DB0 es un parámetro que indica si el cursor parpadea o no
Si quisiéramos que el display esté prendido, mostrando el cursor y que este no parpadee enviaríamos la siguiente secuencia
RS
/R/W
DB7
DB6
DB5
DB4
DB3
DB2
DB1
DB0
0
0
0
0
0
0
1
1
1
0
Inicializar nuestro LCD
Para poder empezar a enviar letras a nuestro LCD primero debemos inicializarlo, el datasheet nos indica una secuencia de inicialización que vamos a analizar.
El primer paso es conectar al suministro eléctrico de 5 volts a nuestro LCD, para esto no necesitamos ninguna instrucción solo conectar correctamente los cables.
El segundo paso es enviar la instrucción Function Set que en este caso elige la operación del display como 8 bits (usa todos los pines de DB7 a DB0), una sóla línea y formas de caracteres de 5×8 puntos.
RS
/R/W
DB7
DB6
DB5
DB4
DB3
DB2
DB1
DB0
0
0
0
0
1
1
0
0
N/A
N/A
El tercer paso es enviar la instrucción Display on/off control donde indicamos prender el display, mostrar el curso y que este no parpadee.
RS
/R/W
DB7
DB6
DB5
DB4
DB3
DB2
DB1
DB0
0
0
0
0
0
0
1
1
1
0
El cuarto paso y último paso en la inicialización es enviar la instrucción Entry Mode Set para decidir cómo es que vamos a mostrar los caracteres en este caso decidimos que después de mostrar una letra corra el cursor un lugar a la derecha
RS
/R/W
DB7
DB6
DB5
DB4
DB3
DB2
DB1
DB0
0
0
0
0
0
0
0
1
1
0
Finalmente ya estamos listos para escribir nuestra primera letra.
Escribiendo una letra en nuestro LCD
Al tener preparado ya nuestro LCD para recibir nuestra primera letra, el mismo espera la información en código ascii explicitado en los pines del DB7 al DB0 por ejemplo, a continuación la tabla de caracteres del lcd.
Para escribir la letra H mayúscula por ejemplo vemos que la combinación es 0100 1000 com lo que deberemos enviar estos valores:
RS
/R/W
DB7
DB6
DB5
DB4
DB3
DB2
DB1
DB0
1
0
0
01
0
0
1
0
0
0
El valor RS es 1 para indicar que estamos escribiendo al data register del LCD
El valor /R/W es 0 para indicar que es una escritura
En los pines DB7 a DB0 espera el dato a escribir en memoria y es 01001000
Cómo funciona el CIA en la Commodore 64
La Commodore 64 posee dos CIA 6526 pero ninguno está conectado a un LCD, utilizando al chip VIC2 y un modulador de RF la Commodore puede comunicarse con monitores con su salida de video y a televisores con su salida RF, en una futura entrega vamos a desarrollar el funcionamiento del chip VIC2.
Estudio visual
Para poder estudiar visualmente como conectar el LCD a nuestros procesadores y CIAs/VIAs y como programarlo en assembler para mostrar un mensaje les dejo esta video que complementa al artículo.
Hola, en esta entrega vamos a estudiar el MOS 6526 también conocido como CIA o complex adapter interface. Son los famosos chips que usa la Commodore 64 entre el procesador y el teclado, ports de usuario y ports de joystick (control port 1 y 2) entre otras conexiones.
¿Por qué necesito algo entre el cpu 6510 y un periférico?
Los procesadores tienen como características ser muy rápidos, estamos hablando de 1 millón de operaciones o ciclos de reloj por segundo en el caso del 6510. Un periférico como el datasette o la disquetera está en el orden de 300 bytes por segundo de transferencia.
Si el procesador tuviera que esperar cada acceso de información disponible sería toda la computadora extremadamente lenta, por eso ponemos un chip en el medio para que medie entre el procesador y los periféricos.
Este chip tiene como función recibir la información que el 6510 le envía, mantenerla disponible y pasarla al periférico cuando este la requiera; también recibir la información desde el periférico, mantenerla y avisar al procesador que tiene información disponible para él. De esta forma el bus de datos se mantiene libre hasta que el procesador tenga que comunicarse con el periférico.
El CIA – Complex Interface Adapter MOS 6526
Pinout
Los pines, VCC, RS0 a RS3, /RES, DB0 a DB7, PHI2, R/W, /IRQ presentan funcionamientos similares al VIA MOS 6522, pero primero vamos a dar detalles de funcionamiento de los pines presentes sólo en el CIA. Cuando en el diagrama un puerto comienza con una / leer como BARRA y significa que este pin es Active Low.
/PC y /FLAG se utilizan juntos para realizar un handshake entre el procesador y el CIA, también el pin /FLAG sólo ,puede utilizarse para recibir una señal de otro 6526 y quedar marcado como flag de interrupción encadenando ambos CIA. El pin /PC es output y pin /FLAG es input siempre.
TOD este pin requiere una conexión externa de 60Hz o 50Hz con un nivel programable de TTL para mantener el reloj interno del CIA.
CNT puede recibir pulsos para usar como un contador en Timer A o Timer B o ser output y escribir pulsos del timer A o B.
SP Es un pin de input o output donde los BITS del puerto serial del chip son escritos. El Serial Data Register se conecta con el Shift Register y cuando recibe un pulso en el pin CNT hace un shift out del Shift Register un bit a la vez en el pin SP, esto lo hace por 8 pulsos o 8 bits del registro momento en el cual se genera una interrupción para avisar que se pueden enviar más datos.
/CS el CIA posee un sólo pin que funciona como Chip Select, al estar en Low el chip responde a los datos en DB0 a DB7
Aquí repasamos los pines con funcionamiento similar al VIA
VSS y VCC/VDD son los pines de Ground y 5 Volts respectivamente
PA0 a PA7 Port Address A: son pines de datos bidireccionales (input y output) para el primer puerto de periféricos el A, el periférico se comunica con el 6526 por esos pines.
PB0 a PB7 Port Address B: son pines de datos bidireccionales (input y output) para el segundo puerto de periféricos el B, el periférico se comunica con el 6526 por esos pines.
RS0 a RS3 son pines que permiten seleccionar qué registro interno del CIA se accede cuándo el procesador lee o escribe los puertos de datos D0 a D7
RESB puerto de reset, el 6526 necesita de un reset cuando el 6510 es prendido por primera vez o pasa por un reset, en este pin recibe la señal. (Active Low).
DB0 a DB7 Data Bus: en estos pines el procesador 6510 se comunica con el 6526 para leer o escribir datos y acceder a cualquiera de los registros internos del CIA.
PHI2 en este pin se recibe la señal de reloj que es la misma que tiene el 6510, al estar diseñado el 6526 para trabajar con estos procesadores todo el timing interno funciona coordinadamente con toda la línea 6500.
RWB en este pin específico, se indica si se está realizando una lectura (high) o una escritura (low) a los pines D0 a D7.
IRQB este pin cuando está en estado low crea una interrupción al procesador para que este tome información del puerto de periférico que corresponde.
Registros
Los registros varían para reflejar la diferencia en algunas funciones con respecto al VIA que ya estudiamos, el CIA posee 16 registros diferentes aquí los detalles de algunos de ellos.
Este chip posee 16 registros internos que permiten entre otras funciones:
Seleccionar si los pines del canal de datos son de input o output
Almacenar la información que entrega o recibe el procesador de modo de mantener el canal de datos vacío pero la información preservada.
Elegir si el CIA puede o no interrumpir al procesador cuando tiene información para entregar.
Si queremos usar por ejemplo los puertos del PB0 al PB7 como output para darle información al periférico debemos primero seleccionar el Data Direction Register B. El mismo se selecciona a través de los puertos RS0 a RS3 en este caso poniendo los pines con los valores de 0v o Ground (<0.4 volts) en caso de tener un 0 en la tabla siguiente o 5v en caso de tener un valor 1:
RS3= 0 RS2= 0 RS1= 1 RS0= 1
Esto corresponde con el valor 3 del Register Number (0011), nótese que es diferente al VIA que espera un valor de 0010 o sea de 2 para el data register B.
Luego de esta selección el procesador debe escribir el valor deseado a través de los pines D0 a D7. Para poner un pin en OUTPUT el valor deberá ser 1 y en INPUT deberá ser cero. Si quisiera poner todos los pines como output el procesador escribirá 1111 1111.
Luego el procesador debe enviar la información que quiere mandar de output al periférico para esto se utiliza el registro Output Register. En nuestro caso usaremos el Output Register B para seleccionarlo en los pines RS3 a RS0 poner los siguientes valores:
RS3= 0 RS2= 0 RS1= 0 RS0= 1
Que corresponden al valor de registro uno (0001), fijense que es diferente al valor usado en el VIA que era de cero (0000).
Si quisiera tener como valores de Salida en PB7 a PB0 los valores 10101010 debería escribir estos mismos en el registros enviando esta información por los pines D7 a D0.
Estos puertos soportan input latching, que es una característica por la cual el puerto conserva el valor de input que recibió desde el periférico aunque el mismo no refresque la señal. Los datos se mantienen (aunque cambien los valores en los pines PB0 a PB7) mientras el flag CB1 de interrupción este set y se borran cuando este flag es desactivado.
Handshaking
El CIA puede hacer handshaking usando el pin /PC como output y el /FLAG como input. /PC va a ir a valor cero o low por un ciclo de tiempo P después de una lectura o escritura del Puerto B. Esta señal puede usarse para indicar “data ready” en el puerto B o “data accepted” en el mismo puerto dependiendo si se trató de una lectura o una escritura respectivamente.
Se puede hacer handshake en transferencia de 16 bits usando ambos puertos A y B siempre leyendo o escribiendo primero al puerto A.
Cualquier señal low al pin /FLAG va a disparar una interrupción del bit FLAG, se puede usar como un puerto genérico para recibir interrupciones o se puede conectar al puerto /PC de otro CIA para recibir el low de ese pin y saber que sucedió un handshake en el puerto B de ese otro CIA (CIA 2 por ejemplo)
Timers
Los timers A y B del CIA pueden ser arrancados y parados a voluntad usando el control register A o el B respectivamente.
Reloj
También como funciones adicionales presenta un reloj Time of Day (TOD). El TOD es un reloj de 24 horas con una graduación de una décima de segundo. Está organizado en 4 registros (que se seleccionan con los pines RS0 a RS3), décimas de segundo, segundos, minutos y horas. El mismo necesita en el pin TOD la conexión con un clock de 60 Hz o 50 Hz.
Contador
Otra función adicional es contar los pulsos del pin de reloj recibidos en PHI2 en TIMER A o TIMER B o los pulsos recibidos en el pin CNT.
Puerto Serial (Shift Register)
El CIA también posee un puerto serial sincrónico de 8 bits con un buffer de 8 bits. Un bit de control selecciona si se va a recibir un input o output.
En modo input los datos recibidos en el pin SP se ingresan a un shift register cuando se recibe una transición de low a high en el pin CNT. Luego de 8 CNT los datos en el shift register se copian al Serial Data Register y una interrupción es generada. El procesador va a leer los 8 bits contenidos en el Serial Data Register a través de los pines D0 a D7.
En modo output el TIMER A se usa como generador de baudios. Los datos se envían por el pin de SP. La tasa máxima de transferencia en baudios es PHI2 dividido por 4. La transmisión va a empezar después de escribir al Serial Data Register, la señal del TIMER A aparece como pulsos de output en el pin CNT y los datos se escriben al Shift Register y luego saldrán uno a uno por el pin SP cuando un pulso CNT ocurra. Luego de 8 pulsos CNT se genera una interrupción para indicar que se pueden mandar más datos.
Si el procesador carga datos en el Serial Data Register antes de que se produzca la interrupción cuando esta se produzca y se transmitan los datos el Shift Register va a ser cargado automáticamente luego de la transmisión. Si el procesador se mantiene en forma constante 1 byte adelantado al consumo del Shift Register la transmisión será continua.
Los datos son transmitidos con el Most Significant Bit primero.
Cómo funciona el CIA en la Commodore 64
La Commodore 64 posee dos CIA conocidos en el mother como U1 y U2, aquí podemos ver su conexión esquemática con otras partes de la computadora:
Esquema de conexión
Funciones CIA 1 (U1)
Las funciones de la CIA 1 incluyen el control del teclado, control de dos puertos de joystick, el control de los dispositivos tipo paddle (potenciómetro como para el Arkanoid) y la lectura de datos del datasette conectado al pin de Cassette RD.
Los 8 pines del Port A están seteados como input y conectados a los 8 conectores de columnas del conector de teclado CN1. Los pines del del Port B están seteados como inputs y conectados a los 8 conectores de filas del conector de teclado CN1 (20 pines machos).
Las cuatros direcciones del Control Port 2 (JOYB0, JOYB1 ,JOYB2 y JOYB3) y el pin de botón BTNB están conectadas al puerto A. Las cuatros direcciones del Control Port 1 (JOYA0, JOYA1 ,JOYA2 y JOYA3) y el pin de botón BTNB están conectadas al puerto B. Si están cruzados los A y los B !
Funciones CIA 2 (U2)
Este posee dos funciones principales que son la conexión al puerto de Usuario, la conexión al bus serial de la commodore, conexión al puerto RS-232, la configuración del VIC (selección de la posición de la memoria interna) y el control de las interrupciones no enmascarables NMI.
El Port B está enteramente conectado al User Port al cuál también se conecta el pin 2 del Port A. El Port A en sus conexiones desde el pin PA7 a PA3 están dedicados al puerto serie.
Direccionamiento de Ambos CIA
Para acceder a los CIA vamos a usar los puerto RS3 a RS0 que están conectados a los puertos de direccionamiento A3 a A0 del 6510. De esta forma podemos acceder a los registros del CIA 1 con las direcciones de DC00 a DC0F y al CIA 2 con las direcciones de DD00 a DD0F
Los pines de chip enable de cada CIA (recordemos que esperan un resultado de 0 volts o LOW) están conectados a la PLA ( a través del pin 1 de I/O) y a dos chips 74LS239 que son decodificadores y entre ambos conectan la CIA, el VIC y el SID.
El chip select no va a funcionar a menos que también se reciba la señal high del clock Phi2 al mismo tiempo.
El CIA responde al 6510 cuando el ciclo del reloj PHI2 va de low a high y a low nuevamente , esto toma aproximadamente unos 1000 nanosegundos. Durante ese tiempo el pin de CS (chip select) es mantenido en Low y si el pin de R/W es high ocurre una lectura y si es low ocurre una escritura, los pines RS reciben una dirección a un registro interno con el databus dando o recibiendo datos.
Teniendo en cuenta el diagrama de timing para que los datos sean válidos y por ejemplo puedan ser leídos, el 6510 tiene acceder al CIA mientras el pin CS esté en low, el registro interno sea direccionado por los register select RS3 a RS0, PHI2 debe estar high y los datos tienen que ser válidos (mantenidos correctamente en el tiempo).
En Resumen
Nuestros dos CIAs manejan teclado, joystick, timers, lectura de datasette, puerto de usuario, paddles y comunicaciones seriales.
El CIA en funcionamiento
Para ver visualmente como conectar un CIA al 6510 y setearlo como output y también en su función de uso de reloj les dejo como siempre un video en detalle de la serie.
En este vamos a ver cómo se conectan los pines, que código máquina escribir para comunicarnos con los registros internos y un ejemplo de output.
Hola, en esta entrega vamos a estudiar que usan los procesadores para hablar con los periféricos (datasette, disquetera) sin tener que estar constantemente congelados esperando una respuesta de ellos.
¿Por qué necesito algo entre el 6502/6510 y un periférico?
Los procesadores tienen como características ser muy rápidos, estamos hablando de 1 millón de operaciones o ciclos de reloj por segundo en el caso del 6510. Un periférico como el datasette o la disquetera está en el orden de 300 bytes por segundo de transferencia.
Si el procesador tuviera que esperar cada acceso de información disponible sería toda la computadora extremadamente lenta, por eso ponemos un chip en el medio para que hable con el procesador y los periféricos.
Este chip tiene como función recibir la información que el 6510 le envía, mantenerla y pasarla al periférico y también recibir la información desde el periférico, mantenerla y avisar al procesador que tiene información disponible para él. De esta forma el bus de datos se mantiene libre hasta que el procesador tenga que comunicarse con el VIA.
El VIA – Versatile Interface Adapter
El MOS 6522 conocido también como VIA es un chip que nos permite tener comunicación con dos puertos para periféricos (A y B) que manejen hasta 8 bits de información en el canal de datos cada uno, la misma cantidad que manejan el 6502 y el 6510 en su bus de datos.
Cada puerto tiene capacidad de mantener la información recibida por el periférico (input latching) y cada bit de los puertos puede ser seleccionado como input o output, lo que permite una comunicación directa y bidireccional entre el procesador y el periférico.
Este chip posee 16 registros internos que permiten entre otras funciones:
Seleccionar si los pines del canal de datos son de input o output
Almacenar la información que entrega o recibe el procesador de modo de mantener el canal de datos vacío pero la información preservada.
Elegir si el VIA puede o no interrumpir al procesador cuando tiene información para entregar.
Pinout del VIA
El VIA posee 40 pines que permiten desde realizar direccionamiento, seleccionar o no el chip, hacer un reset, interrumpir al procesador y comunicarse con los periféricos. Cuando algún puerto tenga como última letra una B larga, en este diagrama significa BARRA, leer como si tuviera una barra encima o sea que el pin es Active Low, se activa cuando el voltaje va a cero (<0,4v en este caso)
VSS y VDD/VCC son los pines de Ground y 5 Volts respectivamente
PA0 a PA7 son pines de datos bidireccionales (input y output) para el primer puerto de periféricos el A, el periférico se comunica con el 6522 por esos pines.
PB0 a PB7 son pines de datos bidireccionales (input y output) para el segundo puerto de periféricos el B, el periférico se comunica con el 6522 por esos pines.
CB1 y CB2 son pines de control del puerto B permitiendo cosas como decidir en base a sus input si interrumpe o no al procesador
CA1 y CA2 son pines de control del puerto A permitiendo cosas como decidir en base a sus input si interrumpe o no al procesador
RS0 a RS3 son pines que permiten seleccionar que registro interno del VIA se accede cuándo el procesador lee o escribe los puertos de datos D0 a D7
RESB puerto de reset, el 6522 necesita de un reset cuando el 6502 es prendido por primera vez o pasar por un reset en este pin recibe la señal. (Active Low).
D0 a D7 en estos pines el procesador 6502/6510 se comunica con el 6522 para leer o escribir datos y acceder a cualquiera de los registros internos del VIA.
PHI2 en este pin se recibe la señal de reloj que es la misma que usa el 6502, al estar diseñado el 6522 para trabajar con estos procesadores todo el timing interno funciona coordinadamente con esta línea de procesadores.
CS1 y CS2B ambos pines son usados para seleccionar al chip (pines de chip enabled) cuando el CS1 es high y el CS2 es low el chip sabe que se están comunicando con él y lee o escribe en el bus de datos respectivamente.
RWB este pin específico se está realizando una lectura (high) o una escritura (low) a los pines D0 a D7.
IRQB este pin cuando está en estado low crea una interrupción al procesador para que este tome información del puerto de periférico que corresponde.
Función de input/output
La función de input output del VIA esta programada a través de los registros internos del chip.
Si queremos usar por ejemplo los puertos del PB0 al PB7 como output para darle información al periférico debemos primero seleccionar el Data Direction Register B. El mismo se selecciona a través de los puertos RS0 a RS3 en este caso poniendo los pines con los valores de 0v o Ground (<0.4 volts) en caso de tener un 0 en la tabla siguiente o 5v en caso de tener un valor 1:
RS3= 0 RS2= 0 RS1= 1 RS0= 0
Esto corresponde con el valor 2 del Register Number (DDR B). Luego de esta selección el procesador debe escribir el valor deseado a través de los pines D0 a D7. Para poner un pin en OUTPUT el valor deberá ser 1 y en INPUT deberá ser cero. Si quisiera poner todos los pines como output el procesador escribirá 1111 1111.
Luego el procesador debe enviar la información que quiere mandar de output al periférico para esto se utiliza el registro Output Register. En nuestro caso usaremos el Output Register B para seleccionarlo en los pines RS3 a RS0 poner los siguientes valores:
RS3= 0 RS2= 0 RS1= 0 RS0= 0
Que corresponden al valor de registro cero. Si quisiera tener como valores de Salida en PB7 a PB0 los valores 10101010 debería escribir estos mismos en el registros enviando esta información por los pines D7 a D0.
Estos puertos soportan input latching, que es una característica por la cual el puerto conserva el valor de input que recibió desde el periférico aunque el mismo no refresque la señal. Los datos se mantienen (aunque cambien los valores en los pines PB0 a PB7) mientras el flag CB1 de interrupción este set y se borran cuando este flag es desactivado. Para controlar si usamos o no input latching o si los pines solo reflejan el valor eléctrico que poseen en el instante usamos el registro C, Peripheral Control Register. Lo mismo aplica para el Port A.
Funciones adicionales
El VIA también provee dos timers y un Shift Register de paralelo a serial / serial a paralelo.
Timers
El Timer 1 es un contador de cuenta regresiva de 16 bits que se carga usando los registros 4 y 5 donde primero se carga la información en dos registros de tipo latch, recordando el chip la misma y luego se pasa la información a los registros del contador. Cuando este llega a cero se produce una interrupción y se pone a ground el pin de IRQB.
El Timer 2 es un contador por intervalo en el cual desde que se carga su valor inicial comienza a contar o puede también contar los pulsos recibidos en el pin PB6 del Puerto B.
Los modos de ambos Timers se setean con el registro B el Auxiliar Control Register.
Shift Register
El shift register es un registro que va a rotar los 8 bits que posee a través del pin CB2 o puede cargarse (input) a través del pin CB1 o también vaciarse (output) a través del mismo pin CB1. Muy útil para hacer conversiones serial/paralelo paralelo/serial.
El timing del shift register puede ser controlado por el Timer 2, el reloj del sistema PHI2 o un reloj externo.
Cómo funciona el de la Commodore 64 el VIA
¿Dónde usaba Commodore al VIA?
Commodore usó el VIA en diferentes productos no así en la Commodore 64 donde uso el CIA o MOS 6526 que revisaremos en un próximo artículo. Podemos ver a continuación los motherboard del VIC 20 y la disquetera 1541 donde sí fue utilizado.
El VIA en funcionamiento
Para ver visualmente como conectar un VIA al 6502 y al 6510 les dejo como siempre un video en detalle de la serie. En este vamos a ver cómo se conectan los pines, que código máquina escribir para comunicarnos con los registros internos y un ejemplo de output utilizando Leds. Todo programado directamente en código máquina.
Hola, en esta entrega vamos a estudiar al Procesador MOS 6503 una verdadera rareza. Se trata de un procesador de la familia del 6502 y del 6510 pero con muchos menos pines (28 en lugar de 40) y la capacidad de direccionar solo 4kb de memoria ram.
Cosas en común con la familia 6500
Este 6503 tiene algunas cosas fundamentales en común con la familia del 6500 sin las cuales cualquier desarrollo en esta plataforma sería muy pero muy difícil.
La primera es el código máquina, este posee las mismas instrucciones a las que ya estamos acostumbrados en nuestros 6502 y 6510, poseyendo también los mismos modos de direccionamiento de memoria.
El timing del mismo está dentro de lo esperado para la familia pudiéndose comunicar con los VIA y CIA si se sincronizan los relojes de estos chips entre sí.
La cantidad de registros y la forma de accederlos se mantienen para toda la familia estos son los familiares A, X e Y, el Status Register y el Stack Pointer, los 5 registros, de 8 bits y el Program Counter de 16 bits.
Tomando en cuenta el análisis de Jim Butterfield – Wikipedia un prócer del lenguaje en código máquina para Commodore el 6503 es sólo un 6502 con menos pines e idéntico funcionamiento.
También posee 8 bits bidireccionales de datos. Todavía podemos encontrar procesadores compatibles como el Synertek 6503
Pin-Out y diferencias
Aquí salta a la vista la diferencia más grande ya que ¡A este chip le han robado unas patitas! Sí, su formato es DIP28 en lugar de los ya tradicionales DIP40 que nos acostumbraron el 6502 y el 6510. ¿Y dónde es que nos faltan esas patitas? Ni más ni menos que en el address bus.
Este posee solo 12 pines (pin AB0 a AB11) en lugar de los tradicionales 16 direccionando solo 2ˆ12 bytes, o sea 4096 bytes o 4 kb para direcciones de memoria.
Aquí hay que tener especial cuidado al armar alguna placa que tenga chips que esperen 15 o 16 bits en su direccionamiento, en las mismas tenemos que asegurarnos que esos pines no queden flotando (no conectados ni a ground ni a 5v). Típicamente en una maqueta de breadboards pueden conectar los pines sobrantes a ground o 5v dependiendo si queremos 0 o 1 para ese bit en particular.
/RESPin de reset, este pin sirve para realizar un reset del procesador cuando se conecte a 0v. El reset tomará 7 ciclos de reloj y buscará en las posiciones de memoria $0FFC y $0FFD donde está el vector (otra posición de memoria) que posee la primera instrucción a ejecutar. El reset debe ser mantenido en 0v por lo menos durante dos ciclos de reloj para que sea reconocido. Nótese que no usamos las tradicionales $FFFC y $FFFD.
VSSPin de Ground, este pin se conecta al common ground del diseño.
PHI1 o 01 (OUT)Pin de Salida de Reloj, el mismo es una salida de reloj para conectar a otros dispositivos. El PHI1 es típicamente la señal del PHI2 pero invertida.
/IRQ Pin de interrupción. Al conectar este pin a 0V, si las interrupciones están habilitadas, el procesador guardará el contenido de los registros actuales y buscará en las posiciones de memoria 0FFE y 0FFF donde está el vector (otra posición de memoria) que posee la primera instrucción a ejecutar para atender a esta interrupción. Nótese que no usamos las tradicionales $FFFE y $FFFF.
/NMI Pin de interrupción no enmascarable. Al conectar este pin a 0V el procesador guardará el contenido de los registros actuales y buscará en las posiciones de memoria 0FFA y 0FFB donde está el vector (otra posición de memoria) que posee la primera instrucción a ejecutar para atender a esta interrupción. Este tipo de interrupción es incondicional y siempre será honrada. Nótese que no usamos las tradicionales $FFFA y $FFFB.
VCCPin de Energía. El procesador típicamente trabaja con +5v ± 5% de sobre o sub fluctuación en el voltaje.
AB0 a AB11 Pines del Bus de Direccionamiento. Son pines bidireccionales que permiten recibir las direcciones de los dispositivos a los cuales comunicarse (memorias, otros chip en la placa, registros de I/O, etc). Al ser un bus de 12 bits direcciona hasta 4096 bytes o desde $0000 hasta $0FFF.
DB0 a DB7 Pines del Bus de datos, Este es un bus bidireccional que permite recibir y escribir datos junto con el bit de R/W a memorias y registros de I/O.
R/WPin de Lectura/Escritura. Este pin indica si el procesador está realizando una lectura o una escritura. Cuando se encuentra en 1 o en estado High el procesador está realizando una lectura cuando está en 0 o estado Low una escritura.
PHI0 o 00 (IN)Pin de entrada de Reloj, Este pin permite conectar un reloj interno al procesador para sincronizarse con otros dispositivos.
PHI2 o 02 (OUT)Pin de Salida de Reloj, el mismo es una salida de reloj para conectar a otros dispositivos.
Cómo funciona en la Commodore 64
El 6503 no se utilizó en la Commodore 64, ni en ninguna computadora Commodore conocida, fue hecho por MOS Technologies para dar un 6502 con un paquete de 28 pines, lo cual era más barato tanto en espacio de pcb utilizado como en costo del chip.
El 6503 en acción
Bueno aca les dejo un video del 6503 en acción donde vamos a explicar como funciona cada uno de sus pines, programarlo a mano utilizando resistencias con la instrucción de código máquina EA (correspondiente a NOP o no operación) y estudiar que pasa por sus pines y qué direcciones usa al bootear,
Continuamos este estudio comparativo del 6502 vs el 6510 en este caso descubriendo la principal diferencia entre el 6510 y el 6502 los pines de Input/Output que posee el 6510 y no posee el 6502.
Les dejo el link al articulo anterior en la serie, y al final como siempre los links a todos los artículos de la misma.
La I/O ports son 6 puertos/pines/registros que pueden funcionar como Input o como Output en el procesador 6510.
P0 a P5 Pines de I/O Port. Este procesador en su más marcada diferencia presenta en estos pines 6 conexiones bidireccionales con periféricos como si fuera un pequeño 6522 VIA o un 6526 CIA.
Cómo se utilizan
Para poder utilizarlos se debe especificar si los vamos a usar como Input o Output. Esto se hace de una forma muy particular. El procesador 6510 a diferencia de todo el resto de la línea 6500 utiliza para sí dos direcciones de memoria que nunca pueden ser parte de la RAM o ROM y son las primeras dos direcciones la $0000 y la $0001.
La dirección $0000 es llamado DATA DIRECTION Register. En este vamos a especificar para cada uno de los seis pines si lo queremos utilizar como Input o como Output. Si el valor es 0 queda como Input y si es 1 queda como output. Si lo vamos utilizar como Input conectarlo con una resistencia a 0 Volts o +5 Volts mientras no se utilice para no tener inputs flotando. Esta especificación se realiza escribiendo un byte a la dirección $0000.
Bit
Pin
Input/Output
0
0
0/1
1
1
0/1
2
2
0/1
3
3
0/1
4
4
0/1
5
5
0/1
6
No Utilizado
No Utilizado
7
No Utilizado
No Utilizado
Por ejemplo si quisiéramos habilitar el pin 2 y el 4 como Output y el resto como Inputs deberíamos escribir el número binario %00010100 correspondiente al hexadecimal $18. Podríamos configurar al 6510 con la siguiente instrucción en assembler
lda #%00010100 ; cargamos al acumulador el número en binario
; antecedido por % para indicar que está em binário
; y # para indicar que es un número y no una posición
; de memoria
sta $00 ;guardamos el contenido del acumulador en el
;registro interno de memoria DATA DIRECTION REGISTER
Si ahora queremos leer la información de los I/O registers necesitamos utilizar otra dirección de memoria la $0001 también llamado de I/O port register.
Bit
Pin
Input/Output
0
0
0/1
1
1
0/1
2
2
0/1
3
3
0/1
4
4
0/1
5
5
0/1
6
No Utilizado
No Utilizado
7
No Utilizado
No Utilizado
Podemos cargar los valores de este registro al acumulador con el siguiente comando para leer por ejemplo:
Lda $01 ; lee el I/O port register
Sta $0400 ; escribe el contenido del acumulador en la posición
; de memoria $0400
Para poder escribir en este registro y por consecuencia cambiar el valor de los pines con valor 1 a +5 Volts o High usamos el siguiente programa assembler.
lda #%00111111 ;va a escribir todos los bits del I/O port para que
;sus pines sean +5 Volts
sta $01 ;escribir el registro
Cómo funciona en la Commodore 64
La Commodore 64 y su procesador 6510 pueden direccionar hasta 65536 direcciones de memoria, los famosos 64KB, pero ¿cuántos kb tenemos en la Commodore?
Kbytes
Función
64
RAM
8
BASIC ROM
8
KERNAL ROM
4
Character Generator
4
I/O (Vic II, SID, CIA 1 y 2, Puerto de Cartucho)
Esto nos da 64+8+8+4+4 = 88Kb para direccionar, lo cual es un problema ya que tendríamos 24Kb que no podrían ser direccionados, ahí entran los I/O Ports para ayudarnos.
Estos cumplen dos funciones: manejar parte del datasette y direccionar esta memoria extra para que puedan caber las 65536 direcciones.
Los puertos en cuanto a su configuración de Input o Output así se encuentran configurados en la Commodore.
Bit
Pin
Input/Output
Nombre en C64
0
0
1 output
LORAM
1
1
1 output
HIRAM
2
2
1 output
CHAREN
3
3
1 output
Cassette Write
4
4
0 input
Cassette Sense
5
5
1 output
Cassette Motor
6
No Utilizado
No Utilizado
No Utilizado
7
No Utilizado
No Utilizado
No Utilizado
Manejo de Memoria
Memorias que se superponen, como vimos anteriormente veamos cómo es que estas memorias se están superponiendo y en qué direcciones.
Nombre
Direcciones
Kbytes
Función 1
Función 2
Función 3
Low Memory
$0000-$9FFF
40kb
RAM
BASIC
$A000-$BFFF
8kb
RAM
BASIC ROM
High Memory
$C000-$CFFF
4kb
RAM
I/O
$D000-$DFFF
4kb
RAM
I/O
CHAR ROM
KERNAL
$E000-$FFFF
8kb
RAM
KERNAL ROM
Como se superponen estas memorias se controla principalmente con los I/O ports de P0 a P2.
P0 – Bit 0 del registro $0001, LOW RAM. Si este bit es 0 tenemos acceso a la RAM si es 1 a la BASIC ROM. ¿Cuándo lo apago? ,cuando creo un programa en código máquina con lo que aprovecho 8kb extras de ram.
P1 – Bit 1 del registro $0001, HIGH RAM. Si este bit es 0 tenemos acceso a la RAM si es 1 al KERNAL ROM. ¿Cuándo lo apago? ,cuando creo un programa en código máquina y no necesito ninguna rutina del KERNAL con lo que aprovecho 8kb extras de ram
P2 – Bit 2 del registro $0001, LOW RAM. Si este bit es 0 tenemos acceso a los I/O devices (VIC II, SID, CIA, etc) si es 1 a la ROM de character generation donde se almacenan los 2 juegos de caracteres de la commodore. Generalmente nunca debemos acceder a la ROM del CHAR GEN ya que el VIC II puede acceder a esta directamente para dibujar los caracteres en pantalla. Un motivo válido para acceder es leerla para copiarla en memoria y modificar el juego de caracteres.
Aquí tenemos otro gráfico que muestra mejor la configuración de los 3 registros y que efectos tendrían en memoria.
A continuación les incluyo un programa en BASIC que les va a permitir apagar momentáneamente el basic y el kernel escribir y leer en la RAM oculta y volver a activar el basic y el kernel sacado del libro PEEKS & POKES para Commodore 64.
Para leer la RAM escondida usar:
PRINT USR(ADDRESS).
Para escribir haciendo un POKE usar:
SYS 715,ADDRESS,BYTE
Y este es el programa en código máquina con su loader en basic:
10 DATA 165,20,72,165,21,72,32,247,183,120,165,141,252,133
20 DATA 1,160,0,177,20,168,165,1,9,3,133,1,88,104,133,21
30 DATA 104,133,20,76,162,179,32,253,174,32,138,173,32,247
40 DATA 183,32,253,174,32,158,183,165,1,41,252,133,1,138
50 DATA 160,0,145,20,165,1,9,3,133,1,96
60 FOR 1=678 TO 747: READ A: POKE I, A: NEXT I
70 POKE 785,166:POKE 786,2
Manejo de Datasette
El datasette es manejado por 3 puertos del 6510 y la CIA. Los I/O Ports P3 a P5 están conectados a las funciones de CASSETTE Write, CASSETTE Sense, y CASSETTE Motor.
P3 – Bit 3 del registro $0001, Cassette Write. Este puerto es el que se utiliza cuando vamos a grabar información al cassette enviando pulsos con la información a grabar a través de este pin.
P4 – Bit 4 del registro $0001, Cassette Sense. Este puerto mide si alguna tecla fue presionada en el datasette. Cuando vemos el famoso mensaje “PRESS PLAY ON TAPE” el procesador está esperando que presionemos la tecla play en el datasette. Al presionar esta tecla y como el puerto es un input se lee un 0 Volts y el datasette sabe que una tecla fue presionada. Como podemos presionar 3 teclas en el datasette (play, rewind, forward) y sólo tenemos una línea de Casette Sense se produce el efecto curioso de que si presionamos rewind o forward la Commodore piensa que presionamos play y trata de cargar el programa de casette.
P5 – Bit 5 del registro $0001, Cassette Motor. Este puerto activa el motor del datasette cuando se presiona una tecla en el datasette, si alguna vez hicieron la prueba de presionar el botón de play y nada funciona si no está conectado a la Commodore no es sólo por una falta de power sino por que la tecla play no hace nada sólo el pin P5 activa el motor del datasette.
Si estudiamos el circuito exacto conectado a este puerto vemos que en realidad el procesador no prende el motor si no que activa un transistor que switchea 9 Volts para que estos sí vayan al conector del datasette y alimenten el motor
Para completar la discusión del datasette nos falta sólo el puerto de cassette read pero este está conectado al puerto /flag de la CIA1 y está fuera del contexto de los puerto I/O del 6510 y será analizado en un próximo artículo.
Estudiando los I/O Ports visualmente
Para poder estudiar visualmente cómo se conectan y funcionan los I/O ports del 6510 les dejo este video que complementa al artículo.
Continuamos este estudio comparativo del 6502 vs el 6510 en este caso creando nuestro primer programa en código máquina y grabándolo en una EEPROM, de esta forma vamos a indicarle al procesador que lea y ejecute el programa desde memoria.
Les dejo el link al articulo anterior en la serie, y al final como siempre los links a los artículos de la misma.
Para poder avanzar en nuestro estudio de los procesadores vamos crear un programa en código máquina que vamos a almacenar en una memoria de sólo lectura. Esto es una eeprom Electrically Erasable Programable Read Only Memory, la cuál vamos a grabar fuera de nuestro breadboard utilizando un grabador de eeprom que el procesador va a tratar como si fuera una memoria de sólo lectura, leyendo instrucciones y datos de la misma pero nunca escribiendolos.
En nuestro caso el chip a utilizar es el AT28C256 de ATMEL. Este chip posee 32768 registros de 8 bits cada uno, por lo que podemos tener hasta 32k bytes de información en este tipo de memorias. El 256K se refiere a 256 K bits que son 32k Bytes (256/8).
Pinout de AT28C256
Este chip viene en formato DIP (Dual Inline Pins) de 28 pines (que parecido a las ROMs del Commodore, ¿capáz que podemos usarlas para algo más adelante ….?)
A14 – A0: Estos pines nos permiten seleccionar qué registro de ocho bits queremos acceder dentro de nuestra memoria, al ser 15 pines podemos direccionar 2ˆ15 = 32768 registros de 8 bits. Estos pines se conectan al bus de direccionamiento.
I/O 0 a I/O 7: Los pines de I/O es donde vamos a ver el contenido de cada registro previamente seleccionado para leer la memoria, o donde vamos a enviar los datos que tenemos para escribir la memoria. Estos pines se conectan al bus de datos.
VCC: En este pin es donde el chip espera una alimentación de +5Volts
GND: Este es el pin de referencia a tierra del chip
/WE: El pin de write enable al recibir una señal de low o 0 Volts permite grabar en los registros de la memoria. Como la estamos utilizando como una ROM conectamos este pin directamente a +5 Volts para que sea de sólo lectura. La barra / significa que este pin es active low con lo cual espera 0 Volts para activarse
/OE: El pin de output enable conecta o desconecta los pines de I/O del bus de datos. Si el pin está en +5 Volts la memoria se desconecta del bus de datos poniendo sus pines de datos en un estado de alta impedancia. La barra / significa que este pin es active low con lo cual espera 0 Volts para activarse
/CE: El pin de chip enable conecta o desconecta los pines del chip para una lectura o escritura trabajando en conjunto con /OE y /WE. Es active low con lo cual espera 0 Volts para activarse
Cómo leer y cómo escribir
Para poder leer o escribir tenemos que realizar una combinación de 3 pines /WE /OE /CE
Lectura
Para realizar una lectura deberemos primero poner en el bus de direccionamiento el address de la memoria que queremos acceder y acto seguido poner los pines:
/WE en +5 Volts (High)
/OE en 0 Volts (Low)
/CE en 0 Volts (Low)
En el bus de Datos tendremos la información asociada a la dirección que pusimos en el address bus..
Escritura
Para realizar una escritura deberemos primero poner en el bus de direccionamiento el address de la memoria que queremos escribir, luego en el bus de datos la información a grabar y acto seguido poner los pines:
/WE en 0 Volts (Low)
/OE en +5 Volts (High)
/CE en 0 Volts (Low)
El /WE o el /CE deberá ser un pulso.
Cómo seleccionamos la memoria desde el procesador
El 6502 y el 6510 pueden direccionar hasta 65536 registros de 8 bits cada uno o 64K como nos gusta llamarlos. Esto nos dejaría utilizar hasta 2 chips EEPROM de 32k cada uno.
Las direcciones que maneja el procesador van desde la $0000 hasta la $FFFF, siempre en hexadecimal como indicamos al anteponer el signo pesos. Si quisiéramos repartir estas direcciones entre 2 chips podríamos asignar de $0000 a $7FFF para el primero y de $8000 a $FFFF para el segundo.
Vamos a ver como se ven estas direcciones en binario para observar si podemos sacar algún patrón útil.
Espacio de Direccionamiento
Hexa
Binario
Inferior
$0000
0000 0000 0000 0000
Inferior
$0001
0000 0000 0000 0001
Inferior
………………
………………………
Inferior
$7FFE
0111 1111 1111 1110
Inferior
$7FFF
0111 1111 1111 1111
Podemos observar que el primer bit en Binario es cero. Para direccionar todos los registros de la eeprom necesitamos 15 pines del A0 al A14 con lo que nos sobra el pin A15. Para poner en modo de lectura solamente al chip podríamos entonces conectar en forma permanente los pines:
/WE en +5 Volts (High)
/OE en 0 Volts (Low)
Y el pin /CE podemos conectarlo directamente al pin A15 así cuando esté en 0 Volts (Low) el chip eeprom estará seleccionado y podremos leerlo. Vayamos ahora a ver el segundo espacio de direccionamiento.
Espacio de Direccionamiento
Hexa
Binario
Superior
$8000
1000 0000 0000 0000
Superior
$8001
1000 0000 0000 0001
Superior
………………
………………………
Superior
$FFFE
1111 1111 1111 1110
Superior
$FFFF
1111 1111 1111 1111
En este caso el pin A15 queda con un valor de 1 o +5 Volts (High) no podríamos conectarlo directamente al pin de /CE ya que no se activaría por ser Active Low el pin. Lo que deberíamos hacer es invertir el valor de 1 a 0 y propongo hacerlo con una compuerta NAND.
Una compuerta NAND tiene la siguiente tabla de verdad que es la opuesta a una compuerta AND.
Input A
Input B
Resultado
LOW
LOW
HIGH
LOW
HIGH
HIGH
HIGH
LOW
HIGH
HIGH
HIGH
LOW
Con lo que si conectamos en la misma compuerta NAND como input A la salida en +5 Volts (HIGH) del pin A15 y como input B también la salida en +5 Volts (HIGH) del pin A15 el resultado será un 0 Volts (LOW) que permitirá activar el pin /CE de chip enable.
Para esto podemos utilizar un clásico chip como ser el 74HC00 que posee cuatro compuertas NAND de dos inputs cada una.
Y así quedaría montado en un breadboard.
Primer Programa en Código Máquina
Nuestra eeprom tiene que tener grabada alguna información para que nos resulte útil, por lo que vamos a cargarle un programa en código máquina. En nuestro primer programa vamos a llenar toda la memoria con la instrucción EA, esta es la instrucción de no operación la cual le dice al procesador que no realice nada durante 2 ciclos de reloj.
Este número hexa EA se corresponde con el binario 11101010 la cual utiliza 8 bits, el procesador va a estar en el ciclo de búsqueda de instrucción leyéndolo de nuestra eeprom. Utilizando el siguiente programa python podemos generar un archivo binario que llena completamente las 32768 posiciones de memoria de 8 bits de nuestra memoria eeprom.
rom = bytearray([0xea] *32768) # crea un array de 32768 ea
with open(“rom004.bin”,”wb”) as out_file: # wb significa escribir archivo binario
out_file.write(rom)
Este programa al ser ejecutado con el comando:
$ python3 ./nombre_del_programa.py
Creará un archivo rom004.bin lleno de bytes EA, que podremos ver con el programa hexdump:
% hexdump -C rom004.bin
00000000 ea ea ea ea ea ea ea ea ea ea ea ea ea ea ea ea |…………….|
*
00008000
Todas las 32768 posiciones de memoria (del 0000 al 8000) están llenas con la instrucción de no operación EA. No es un programa muy útil pero si imita muy bien la codificación con resistencias de la instrucción EA hardcodeada en nuestro artículo anterior.
Cómo Se Graba una EEPROM
Ya que tenemos nuestro primer programa como un archivo binario de 32768 bytes, solo nos resta grabar el mismo en una EEPROM y esto se realiza con un grabador de eeproms. En este ejemplo vamos a usar un TL866 II Plus.
Este programador de eeprom es muy sencillo de utilizar a través del programa minipro, al mismo se le indica qué tipo de chip eeprom vamos a grabar y que archivo queremos grabar.
Antes de comenzar a grabar se inserta el chip eeprom en el zócalo zif y se conecta todo por usb a nuestra computadora.
En la siguiente imagen podemos ver como es el ciclo completo desde que ejecutamos el programa python hasta grabar la eeprom.
¿Y qué pasa entonces?
El procesador va a encender y buscar en las posiciones $FFFC y $FFFD la dirección de la primera instrucción a ejecutar ordenados como Low Byte y High Byte. Al haber grabado toda la memoria con la instrucción $EA encontrará con $EA en la posición de memoria $FFFC, luego irá a la posición $FFFD y cargará $EA.
$FFFC contiene $EA = %1110 1010
$FFFD contiene $EA = %1110 1010
Si lo ordenamos por los pines del address bus veríamos:
A15
A14
A13
A12
A11
A10
A9
A8
A7
A6
A5
A4
A3
A2
A1
A0
1
1
1
0
1
0
1
0
1
1
1
0
1
0
1
0
El Pin A A15 es un 1 que a través de la compuerta NAND se transforma en 0 equivalente a 0 Volts o Low, y como está conectado al pin /CE nuestra EEPROM se activará.
Con esto cargará el Program Counter con la primera posición de nuestro programa ficticio que será $EAEA y buscará el código de la próxima instrucción a ejecutar que será EA ya que es lo único que tenemos en el bus de datos.
Esta ejecución durará dos ciclos de reloj y luego el program counter avanzará a EAEB y volverá a leer el bus de datos en búsqueda de la próxima instrucción que seguirá siendo EA y así continuará.
.
Segundo Programa en Código Máquina
Casi siempre queremos indicar en qué dirección de memoria comenzar el programa y vimos en un artículo anterior que al tener un reset el 6502 y el 6510 buscan la primera instrucción en las direcciones $FFFC para el low byte y $FFFD para el high byte.
Con una pequeña modificación podemos hacer que nuestro programa comience a ejecutar en por ejemplo la dirección $8000.
rom = bytearray([0xea] *32768) # crea un array de 32768 ea
#modificamos dos bytes de nuestro array de EAs
rom[0x7ffc] = 0x00 # low byte que va a ser leído como $FFFC con el contenido $00 para formar la dirección $8000
# 0x7ffd va a ser leído como FFFD por tel procesador ya que estamos usando A15 como chip enable pero la EEPROM solo tiene 15 pines hasta A14
rom[0x7ffd] = 0x80 # high byte que va a ser leido para formar la dirección $8000
with open(“rom005.bin”,”wb”) as out_file:
out_file.write(rom)
Creará un archivo rom005.bin lleno de bytes EA, pero que contiene la dirección $8000 en las posiciones $FFFC y $FFFD en formato low byte primero (little endian) que podremos ver con el programa hexdump:
% hexdump -C rom005.bin
00000000 ea ea ea ea ea ea ea ea ea ea ea ea ea ea ea ea |…………….|
*
00007ff0 ea ea ea ea ea ea ea ea ea ea ea ea 00 80 ea ea |…………….|
00008000
¿Y qué pasa entonces?
El procesador va a encender e ir a las posiciones $FFFC y $FFFD, activará el pin /CE en low a través de la configuración realizada en la compuerta NAND
$FFFC contiene $00 = %0000 0000
$FFFD contiene $80 = %1100 0000
Si lo ordenamos por los pines del address bus veríamos:
A15
A14
A13
A12
A11
A10
A9
A8
A7
A6
A5
A4
A3
A2
A1
A0
1
1
0
0
0
0
0
0
0
0
0
0
0
0
0
0
Luego cargará $00 ya que ya que es el dato presente en la posición de memoria $FFFC, luego irá a la posición $FFFD y cargará $80. Con estos dos datos modificará el program counter a $8000 y comenzará a leer instrucciones de $8000. Claro que sólo leer $EA ya que es lo que está grabado pero luego de leerlo irá a $8001 y seguirá incrementando el Program Counter de a una unidad.
Un gran y simple programa para poder enfocarnos en cómo leer desde EEPROM un programa en código máquina.
Cómo funciona en la Commodore 64
La Commodore 64 posee 4 ROMS, 3 dentro de la placa madre y otra externa y variable:
El Basic ROM de 8 KB implementado con un chip MOS 2364A y ubicada en las direcciones de memorias $A000 – $BFFF. Esta ROM posee las rutinas de las instrucciones del lenguaje BASIC 2.0 que usamos en la Commodore.
El Kernal ROM de 8 KB implementado con un chip MOS 2364A y ubicada en las direcciones de memorias $E000 – $FFFF. Esta ROM posee las rutinas de más bajo nivel de la Commodore como ser las rutinas de ejecución de las primera instrucción, escrituras a pantallas, sonido.
El Character ROM de 4 KB implementado con un chip MOS 2332A y ubicada en las direcciones de memorias $D000 $DFFF. Esta ROM posee el diseño de los caracteres que vemos en la pantalla, cada caracter ocupa 8 bytes siendo una grilla de 8×8 (8 líneas de 8 bits cada una). La Commodore 64 implementa 2 juegos de caracteres de 256 caracteres cada uno.
La cuarta ROM es la más desconocida de todas ya que es cualquier cartucho que conectemos a la Commodore 64, los mismos están ubicados en las direcciones ROM High ($A000 – $BFFF o $E000 – $FFFF) y ROM Low ($8000-$9FFF) y son mapeados dentro de la memoria por el kernall durante el proceso de inicialización de la Commodore 64.
Codificando desde EEPROM visualmente
Para poder estudiar visualmente como grabar una EEPROM y hacer que el procesador ejecute un programa en código máquina desde la misma les dejo esta video que complementa al artículo.
Continuamos este estudio comparativo del 6502 vs el 6510 tratando de descubrir cómo es que el procesador accede a las instrucciones en código máquina, las lee, interpreta y ejecuta. También vamos a ver como codear nuestra primera instrucción directamente usando resistencias y el bus de datos del procesador.
Les dejo el link al articulo anterior en la serie, y al final como siempre los links a los artículos de la misma.
Un procesador no utiliza internamente ninguno de los lenguajes de alto nivel que solemos utilizar como por ejemplo sería el Basic en la Commodore, ni siquiera usa Assembler. Internamente un procesador solo tiene esquemas de transistores que responden a distintas combinaciones de unos y ceros, lo que denominamos el código máquina.
Set de instrucciones del 6502 y el 6510
El código máquina de ambos procesadores posee las mismas instrucciones de assembler de 6500 con lo que los programas de uno funcionan perfectamente en el otro. La siguiente tabla muestra un resumen de todas las instrucciones del procesador.
Y en la siguiente tabla tenemos todas las instrucciones del 6502 y el 6510 codificadas por su representación en hexadecimal o binario.
Podemos encontrar en esta tabla, por ejemplo, una instrucción muy común como es la LDA # que carga el registro del acumulador con un número de 8 bits que indicamos a continuación del símbolo #. Esta instrucción se encuentra en la Fila A Columna 9 en nuestra tabla.
El procesador para reconocerla espera ver al momento de buscar una instrucción en el bus de datos los valores 10101001 (correspondientes al hexadecimal A9) en los pines de datos del D7 al D0 de nuestros procesadores. Correspondientes a los pines 26 al 33 para el 6502 y del 30 al 37 para el 6510.
De dónde lee las instrucciones el procesador
Cuando prendemos por primera vez un procesador 6502 o 6510, el procesador busca siempre en las mismas direcciones de memoria un lugar donde le digamos dónde se ubica la primera instrucción del programa que queremos ejecutar. En el caso de estos procesadores puede buscar en sólo 3 lugares dependiendo cómo se esté realizando la inicialización de los mismos.
$FFFA-$FFFB si se recibe una interrupción no enmascarable (pin /NMI)
$FFFC-$FFFD si se recibe un reset (pin /RESET)
$FFFE-$FFFF para una interrupción (pin /IRQ o instrucción de código máquina break $00)
La selección de cuál de estos vectores (que así se llaman las direcciones de memoria donde se espera haya otra dirección de memoria) se activa es básicamente que pin de estos tres recibe un LOW, teniendo precedencia, primero /RESET, luego /NMI y finalmente /IRQ o break en caso de recibirlo los 3 a la vez.
Recordemos que las direcciones son de 16 bits ya que el 6502 puede direccionar hasta 65532 direcciones (2 a la potencia 16) ya que la memoria contiene datos sólo de 8 bits vamos a necesitar dos posiciones de memoria para cargar la dirección de nuestro primer programa, por eso para reset utilizamos la posición $FFFC y $FFFD. El procesador sólo necesita la primera posición de memoria y sabe que tiene que ir a buscar la segunda dirección.
Estas posiciones se graban con la característica de ser little endian, lo que significa que guardamos el byte menos significativo primero. Por Ejemplo si queremos guardar la dirección $0E00 como la primera de nuestro programa deberemos guardarla en memoria como 00 0E
Por lo que si quisieramos guardar la posición de memoria $0E00 cuando nuestro procesador realice un reset debemos almacenar el low byte $00 en la posición de memoria $FFFC y el high byte $0E en la posición $FFFD.
Posición de Memoria
Contenido
FFFC
00
FFFD
0E
Nuestra primera Instrucción, la no instrucción NOP
Como primera instrucción vamos a utilizar NOP, esta es la instrucción de no operación, le dice al procesador que no realice nada durante 2 ciclos de reloj. Si la buscamos en nuestra tabla vamos a ver que está en la fila E y la columna A o sea $EA, agrego el símbolo pesos para indicar que se trata de un número en hexadecimal.
Este número hexa se corresponde con el binario 11101010 y el procesador va a estar en el ciclo de búsqueda de instrucción esperándolo en los puertos de datos de nuestro procesador. Por lo que deberemos codificar para cada pin del procesador 6502 y para el 6510 respectivamente:
6502
6510
Pin 33 D0 = 0
Pin 37 D0 = 0
Pin 32 D1 = 1
Pin 36 D1 = 1
Pin 31 D2 = 0
Pin 35 D2 = 0
Pin 30 D3 = 1
Pin 34 D3 = 1
Pin 29 D4 = 0
Pin 33 D4 = 0
Pin 28 D5 = 1
Pin 32 D5 = 1
Pin 27 D6 = 1
Pin 31 D6 = 1
Pin 26 D7 = 1
Pin 30 D7 = 1
Normalmente el procesador elegirá un address de memoria y el chip de memoria le entregará los datos con las instrucciones correspondientes y estos valores binarios. Por ejemplo el procesador puede ir al address $0E00 y un chip de memoria entregarle el valor de 8 bits $EA contenido en esa dirección, luego de lo cual el procesador interpretará esta instrucción y la ejecutará.
Cargando la instrucción para que la lea el procesador, con un truquito.
En nuestra primera aproximación a codificar el 6502 y el 6510 “a mano” lo que vamos a hacer es fijar el bus de datos con los valores de la instrucción EA, conectando los pines del bus de datos D7 a D0 de la siguiente forma.
Utilizando una resistencia de 1k conectaremos cada pin que en el diagrama tenga un cero a tierra o low y cada uno que tenga un uno a 5V o al canal high. El número parece al revés que EA = 11101010 debido a que el pin de más a la derecha es D7 (el más significativo) y el de más a la izquierda D0 (el menos significativo).
De esta forma siempre que el procesador quiera cargar una instrucción y pasa a modo de ejecución va a cargar nuestra instrucción EA y sólo esa instrucción ya que es lo único que va a estar en el bus de datos.
Y qué pasa entonces
El procesador va a bootear e ir a las posiciones $FFFC y cargará $EA ya que es lo único que tiene en el bus de datos y luego a la posición $FFFD y cargará $EA que es lo único que tiene en el bus de datos claro ya que esta hardcodeado con las resistencias.
Con esto cargará el Program Counter con la primera posición de nuestro programa ficticio que será $EAEA y buscará el código de la próxima instrucción a ejecutar que será $EA ya que es lo único que tenemos en el bus de datos. Esta ejecución durará dos ciclos de reloj y luego el program counter avanzará a $EAEB y volverá a leer el bus de datos en búsqueda de la próxima instrucción que seguirá siendo $EA y así continuará.
Un gran programa para poder enfocarnos en cómo funciona de la forma más básica la carga en binario de una instrucción en código máquina.
Cómo funciona en el Commodore 64
Al encender la Commodore 64 un circuito de reset entra en acción. El mismo está compuesto por un integrado de tipo timer 556 que es ni más ni menos que dos timer 555 en el mismo chip, con todos los conectores de un 555 en los pines de la izquierda y de otro 555 en los pines de la derecha.
A continuación tenemos una foto de parte del circuito en una Commodore 64 real y un esquema del circuito eléctrico que vamos a analizar.
Análisis del Circuito de Reset
El 556 (componente U20) está cableado en forma monoestable lo que significa que por cada vez que es activado a través de su pin de trigger envía un pulso a través de su pin de output. Este circuito es activado solo al encender la computadora y después no vuelve a funcionar en la Commodore. Al ser dos timers 555 vamos a mirar la parte derecha del mismo, los pines con el número 2 que son los que forman parte del circuito de reset.
Primero tenemos que estudiar la parte del circuito que activa al 556 a través de su pin de trigger, este pin se activa solo cuando el pin de trigger recibe un voltaje menor de ⅓ del voltaje total.
Al encender la Commodore la carga del capacitor c105 es cero con lo que el voltaje en el pin TRIG es menor a ⅓ del voltaje total y un pulso es emitido. El capacitor C105 se carga a través de una resistencia de 1 Mega Ohms hasta que llega a los 5 volts lentamente y el pin TRIG deja de tener un voltaje menor a ⅓ del voltaje total con lo que el estímulo para activarse deja de existir para no volver nunca a un valor low mientras dure la Commodore encendida.
.
Cuando el capacitor c24 se carga a ⅔ del voltaje total se activa el pin de Discharge y el 556 corta el pulso que estaba emitiendo.
Si queremos calcular aproximadamente cuanto dura el estímulo del pulso, podemos aplicar la formula para saber cuánto tarde un capacitor de 0.1 microfaradios en cargar a través de una resistencia de 1 Millón de Ohms
Constante de Tiempo = Resistencia en Ohms x Capacitancia en Faradios
=47000 ohms x 0.00001 faradios = 0,47 segundos
El tiempo para la carga total es de Constante de tiempo x 5 = 0,47 seg x 5 = 2,35 segundos
Pero no necesitamos que se llene completamente el capacitor en 5 Volts solo hasta que llegue a 2.33 volts o dos tercios del valor que es aproximadamente dos quintos del tiempo de carga total con lo que el pulso de output se mantiene por ⅖ * 2.35 seg = 0,94 segundos.
Pero esta salida de pin de Output es HIGH y cuando el impulso es disparado por el 556 el mismo pasa por un inversor para salir LOW y conectado a la línea de RESET, que está conectada al 6510 en su pin /RESET ocasionando un reset del procesador.
Esta salida del inversor está conectado a una resistencia a 5Volts también llamada resistencia pull-up que mantiene el valor de la salida en HIGH evitando el reset siempre y cuando el inversor no reciba un nuevo output que sabemos no pasará por que el capacitor c105 mantiene los valores arriba de ⅓ del voltaje total.
Que ocasiona un pulso de reset en el 6510 y sus periféricos
Cualquier chip (sid, cia, etc), bus (IEC, etc) o dispositivo conectado a un bus (disketteras) que estén conectados a esta línea de reset comenzarán sus propias inicializaciones.
Al haber ejecutado un reset el procesador 6510 buscará la dirección de memoria para su primera instrucción en las direcciones $FFFC y $FFFD low y high byte respectivamente.
Estudiando el mapa de memoria del Commodore 64 veremos que eso nos lleva a la dirección $FCE2 la primera línea de la rutina de Power On del Commodore 64, como se referencia en libro Mapping The Commodore 64
La siguiente rutina de Kernel es la que se ejecuta.
Esta rutina activa el flag de deshabilitar interrupciones, programa el stack pointer para estar vacio con la dirección $01FF, deshabilita el modo decimal del procesador, busca si existe un cartucho en el puerto de expansión y si se encuentra le da al programa del cartucho el control de la Commodore, si no continúa con las rutinas de inicialización del kernel, inicializa los chips SID y CIA, inicializa la RAM, inicializa el VIC, limpia el flag de deshabilitar interrupciones y comienza el intérprete BASIC.
Con esta clásica pantalla azul concluye nuestro pequeño resumen de como arranca nuestro Commodore 64.
Codificando la primera instrucción visualmente
Para poder estudiar visualmente como codificar la instrucción EA con resistencias y ver cómo busca las instrucciones el 6502 y el 6510 les dejo esta video que complementa al artículo.
Vamos a empezar este estudio comparativo del 6502 vs el 6510 con una descripción del para qué sirve cada patita de estos chips (que básicamente es el pin out). Nos va a servir de guía para poder hablar de las diferencias que tienen estos chips entre sí
Les dejo el link al articulo anterior en la serie, y al final como siempre los links a todos los artículos de la misma.
Ambos chips fueron creados por MOS Technologies y muy utilizados en el final de los 70 y principios de los 80. El 6510 ya no se fabrica más en la actualidad (escribiendo estas notas en Junio del 2023) sobreviviendo sólo en los corazones de millones de Commodore 64 y en los corazones de miles de Commodorianos.
El 6502 todavía sigue siendo muy utilizado teniendo versiones actuales de USM y de WDC siendo la versión actual la 65C02 que agrega algunas instrucciones extras de assembler y baja mucho el consumo eléctrico.
Arquitectura
Ambos procesadores son procesadores de 8 bits y comparten muchísimas cosas en común. La arquitectura interna de estos procesadores es idéntica y está dividida en dos partes una sección con los registros y otra con las operaciones de control, las señales que provocan transferencias de datos están en la sección de control.
Set de instrucciones
El código máquina de ambos procesadores posee las mismas instrucciones de assembler de 6500 con lo que los programas de uno funcionan perfectamente en el otro.
Agrego algunas instrucciones extras del modelo 65C02 (las marcadas con punto en la siguiente tabla) que NO recomiendo usar para poder mantener compatibilidad con el 6510 y el 6502 originales pero que ahorran algunos pasos al no tener, por ejemplo, que pasar por el acumulador para guardar el registro X en el stack con la instrucción PHX. El 65C02 es una versión más moderna del MOS 6502 siendo una ventaja el ser fully static por lo que se puede parar el clock y los registros no pierden sus valores.
Velocidad de Reloj
Los procesadores 6502 y 6510 originales soportan una velocidad de reloj de hasta 1Mhz, teniendo luego el 8502 que soporta hasta 2Mhz (usado en el modo 64 de la Commodore 128)
Registros
La cantidad de registros y la forma de accederlos se mantienen para toda la familia estos son los familiares A, X e Y, el Status Register y el Stack Pointer los 5 de 8 bits y el Program Counter de 16 bits.
Modos de direccionamiento
Ambos chips funcionan de idéntica forma al relacionar la memoria y sus registros presentando modos de direccionamiento diferentes ya sea si uno quiere cargar directamente de memoria, o un número literal al acumulador, en forma indexada los datos y aplicar funciones que trabajan con el acumulador sin tocar memoria.
Bus de Direccionamiento y Bus de Datos
Ambos procesadores poseen 16 líneas de direccionamiento de datos (pines) pudiendo manejar entre memoria y registros de I/O hasta 64Kb (2ˆ16 = 65536 bytes).
Pin-Out y diferencias
Aquí salta a la vista la diferencia más grande ya que el 6510 posee 6 pines adicionales que puede ser utilizados como interfaz de Input/Output para comunicarse con periféricos ya que estos son bidireccionales.
Para manejar estos pines el 6510 utiliza las direcciones 0 y 1 donde especifica en la cero si son inputs (pone un cero) o output (pone un 1) y en el dirección 1 los valores de los mismos, ya sea recibidos de un periférico y escritos por el procesador para consumo externo.
Pin-Out 6502
Este chip posee un formato DIP 40 con las siguientes funciones en sus pines
VPB Pin de La B significa Bar o Barra para que este pin se active el voltaje tiene que ser Low o 0v
RDY El pin ready se utiliza para decirle al microprocesador que tiene que frenar y mantener al mismo en el estado actual, para activarlo y que frene el pin espera un estado low. Por ejemplo al recibir un estado Low (o volts) en el pin todas las líneas de output van a mantener los valores de corriente que tenían mostrando qué dirección estaban buscando.
PHI1 o 01 (OUT) Pin de Salida de Reloj, el mismo es una salida de reloj para conectar a otros dispositivos. El PHI1 es típicamente la señal del PHI2 pero invertida
IRQB Pin de interrupción. Al conectar este pin a 0V, si las interrupciones están habilitadas, el procesador guardará el contenido de los registros actuales y buscará en las posiciones de memoria FFFE y FFFF donde está el vector (otra posición de memoria) que posee la primera instrucción a ejecutar para atender a esta interrupción
MLB El pin de Memory lock se usa para mantener la integridad de las instrucciones Read-Modify-Write en un sistema multiprocesador. Cuando presenta un valor Low o 0 volts indicate que algún otro circuito debe arbitrar el ciclo del bus.
NMIB Pin de interrupción no enmascarable. Al conectar este pin a 0V el procesador guardará el contenido de los registros actuales y buscará en las posiciones de memoria FFFA y FFFB donde está el vector (otra posición de memoria) que posee la primera instrucción a ejecutar para atender a esta interrupción. Este tipo de interrupción es incondicional y siempre será honrada.
SYNC Pin de sincroníaEl ciclo del procesador donde trae el código de operación (OpCode) se indican con el pin SYNC en high. Cuando el procesador busca un código del operación el pin queda en high y queda high por todo el resto del ciclo
VDD o VCC Pin de Energia. El procesador típicamente trabaja con +5v
AB0 a AB11 Pines del Bus de Direccionamiento. Son pines bidireccionales que permiten recibir las direcciones de los dispositivos a los cuales comunicarse (memorias, otros chip en la placa, registros de I/O, etc). Al ser un bus de 12 bits direcciona hasta 4096 bytes o desde $0000 hasta $1000
VSS Pin de Ground, este pin se conecta al common ground del diseño.
DB0 a DB7 Pines del Bus de datos, Este es un bus bidireccional que permite recibir y escribir datos junto con el bit de R/W a memorias y registros de I/O
R/WB Pin de Lectura/Escritura. Este pin indica si el procesador está realizando una lectura o una escritura. Cuando se encuentra en 1 o en estado High el procesador está realizando una lectura cuando está en 0 o estado Low una escritura.
NC No Connect, este es un pin que no se debe conectar ya que no está conectado a nada dentro del procesador
BE Pin de Bus Enable, cuando este pin esta High los pines de address, data y RW están activos, cuando está low quedan con impedancia alta sacando al procesador del bus.
PHI2 o 02 (OUT) Pin de Salida de Reloj, el mismos es una salida de reloj para conectar a otros dispositivos
SOB Pin de Set Overflow. Este pin cuando recibe un cambio de high a low prende el bit de Overflow en el Status Register del procesador (bit 6). No se uso mucho en el pasado y no se recomienda su uso.
PHI0 o 00 (IN) Pin de entrada de Reloj, Este pin permite conectar un reloj interno al procesador para sincronizarse con otros dispositivos.
RESB Pin de reset, este pin sirve para realizar un reset del procesador cuando se conecte a 0v. El reset tomará 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. El reset debe ser mantenido en 0v por lo menos durante dos ciclos de reloj para que sea reconocido.
Pin-Out 6510
Pines diferentes al 6502
PHI1 o 01 (IN) Pin de entrada de Reloj, Este pin permite conectar un reloj interno al procesador para sincronizarse con otros dispositivos. En el 6502 era el PHI0 y el 6510 sólo tiene 2 pines con respecto al reloj en lugar de los 3 que posee el 6502.
AEC Pin de Address Enable Control, se comporta de forma similar al pin de Bus Enable del 6502. Cuando este pin esta High los pines de address, data y RW están activos, cuando está low quedan con impedancia alta sacando al procesador del bus. Esto permite desarrollar sistemas con acceso directo a memoria por parte de otros chips o periféricos (DMA).
P0 a P5 Pines de I/o Port. Este procesador en su más marcada diferencia presenta en estos pines 6 conexiones bidireccionales con periféricos como si fuera un pequeño VIA o CIA. Vamos a explorar como funciona en detalle en un futuro artículo y video.
Pines idénticos al 6502
RDY El pin ready se utiliza para decirle al microprocesador que tiene que frenar y mantener al mismo en el estado actual, para activarlo y que frene el pin espera un estado low. Por ejemplo al recibir un estado Low (o volts) en el pin todas las líneas de output van a mantener los valores de corriente que tenían mostrando qué dirección estaban buscando.
IRQ/ Pin de interrupción. Al conectar este pin a 0V, si las interrupciones están habilitadas, el procesador guardará el contenido de los registros actuales y buscará en las posiciones de memoria FFFE y FFFF donde está el vector (otra posición de memoria) que posee la primera instrucción a ejecutar para atender a esta interrupción
NMI/ Pin de interrupción no enmascarable. Al conectar este pin a 0V el procesador guardará el contenido de los registros actuales y buscará en las posiciones de memoria FFFA y FFFB donde está el vector (otra posición de memoria) que posee la primera instrucción a ejecutar para atender a esta interrupción. Este tipo de interrupción es incondicional y siempre será honrada.
VDD o VCC Pin de Energía. El procesador típicamente trabaja con +5v
AB0 a AB11 Pines del Bus de Direccionamiento. Son pines bidireccionales que permiten recibir las direcciones de los dispositivos a los cuales comunicarse (memorias, otros chip en la placa, registros de I/O, etc). Al ser un bus de 12 bits direcciona hasta 4096 bytes o desde $0000 hasta $1000
VSS Pin de Ground, este pin se conecta al common ground del diseño.
DB0 a DB7 Pines del Bus de datos, Este es un bus bidireccional que permite recibir y escribir datos junto con el bit de R/W a memorias y registros de I/O
R/W Pin de Lectura/Escritura. Este pin indica si el procesador está realizando una lectura o una escritura. Cuando se encuentra en 1 o en estado High el procesador está realizando una lectura cuando está en 0 o estado Low una escritura.
PHI2 o 02 (OUT) Pin de Salida de Reloj, el mismos es una salida de reloj para conectar a otros dispositivos
/RES Pin de reset, este pin sirve para realizar un reset del procesador cuando se conecte a 0v. El reset tomará 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. El reset debe ser mantenido en 0v por lo menos durante dos ciclos de reloj para que sea reconocido
Conectando al 6502 y al 6510
Para poder ver visualmente como es el esquema de conexión de pines de ambos procesadores les dejo un video donde vamos a repasar para que sirve cada pin y como conectarlo a un breadboard para en futuros videos poder programar ambos procesadores.