Un I/O para ZX Spectrum

¿Tienes problemas con tu equipo?, preguntanos.

Moderador: Fundadores

Avatar de Usuario
dandare
Hermano de Lucifer
Hermano de Lucifer
Mensajes: 3718
Registrado: 09 Feb 2016, 15:09
Ubicación: I Register
Been thanked: 6 times

Re: Un I/O para ZX Spectrum

Mensaje por dandare »

El circuito que pones tiene varios problemas
  • 1) introduce muchísimos wait ante cualquier escritura al bus de I/O. Cada vez que haya un Out, por ejemplo para poner el border de un color, hacer sonar algo por el altavoz, o usar el chip AY o la paginación de memoria en el 128k. El uC tendría que leer los buses y decidir si liberar el wait o no, y eso tarda. Haría la mayoría de los juegos inutilizables.
    2) incluso aunque no tuviéramos el problema anterior (se puede solucionar con algo más de electrónica) sigue sin ser evidente que el uC pueda levantar la línea de wait a tiempo. La gestión de interrupciones es bastante lenta para los tiempos en los que nos movemos.
    3) tienes 24!! Flip flops. Eso son un montón de chips ;). Además, si tienes los flip flops en datos, para qué tienes el wait? (Realmente lo que te sobran son los 8 flipflop de datos)
Una aproximación para solucionar los outs seria hacer la decodificacion externa, y el circuito de wait también externo. Cuando se produzca una petición de Out al puerto adecuado, se genera automáticamente un wait y una int al uC. El uC puede acceder entonces al bus de datos, leer lo que quiera y liberar el wait.
También puede obviar el wait y hacer latch de datos, pero eso te complica la implementación de los INs


En el Dandanator v2, la gal se usa porque hay un interfaz kempston. La parte de comunicación con el pic es una OR de MREQ, WR, A14 y A15 que genera una interrupción en el uC.
El uC va contando esos pulsos para entender comandos. Hay una gestión de timeouts y un protocolo definido pero no se usan outs ni Ins, por eso la electrónica es tan simple.
Imagen
Imagen
pep
Seguidor infernal
Seguidor infernal
Mensajes: 29
Registrado: 20 Nov 2016, 00:46

Re: Un I/O para ZX Spectrum

Mensaje por pep »

Gracias por tus intervenciones Dandare, estoy aprendiendo un montón hablando contigo solo por plantearme hacer el interfaz ¿ves como tenía interés resucitar el hilo? ;-)
dandare escribió:El circuito que pones tiene varios problemas
1) introduce muchísimos wait ante cualquier escritura al bus de I/O. Cada vez que haya un Out, por ejemplo para poner el border de un color, hacer sonar algo por el altavoz, o usar el chip AY o la paginación de memoria en el 128k. El uC tendría que leer los buses y decidir si liberar el wait o no, y eso tarda. Haría la mayoría de los juegos inutilizables.
pues tienes razón, una solución sería implementarlo en lógica discreta, sería una simple función combinatoria en función de los bits de dirección A*
dandare escribió: 2) incluso aunque no tuviéramos el problema anterior (se puede solucionar con algo más de electrónica) sigue sin ser evidente que el uC pueda levantar la línea de wait a tiempo. La gestión de interrupciones es bastante lenta para los tiempos en los que nos movemos.
3) tienes 24!! Flip flops. Eso son un montón de chips ;). Además, si tienes los flip flops en datos, para qué tienes el wait? (Realmente lo que te sobran son los 8 flipflop de datos)
pues precisamente por eso estaban los flipflops, por si acaso no le diese tiempo al uC a activar WAIT a tiempo, la idea es que aunque tarde más tiempo y cambie el bus de datos o el de direcciones, estarían preservados en los flipflops, probablemente no hagan falta si el uC es lo suficientemente rápido o si la señal wait se activa con lógica discreta.

De todas formas no harían falta tantos flipflops, si mal no recuerdo el z80 solo direcciona 256 puertos de E/S mediante el byte bajo de dirección, así que solo necesitaría 8 flipflops para el bus de direcciones y otros 8 para el de datos, y si elijo el puerto del interfaz convenientemente incluso menos.

En cualquier caso merece la pena probar el punto 2), si un uC puede levantar a tiempo WAIT, es decir, si es capaz de escribir en el pin WAIT tan rapido como para activar la señal a tiempo, si es capaz un diseño que active WAIT tan pronto detecte IORQ funcionaría (a costa del problema que mencionas en 1) si tiene que decodificar el puerto el propio uC la cosa se complica porque es más tiempo a sumar, seguramente lo más sencillo sea definir la decodificación de puerto y activación de WAIT mediante lógica discreta y dejar al uC simplemente interpretar comandos y datos, tal y como mencionas en el párrafo siguiente.
dandare escribió: Una aproximación para solucionar los outs seria hacer la decodificacion externa, y el circuito de wait también externo. Cuando se produzca una petición de Out al puerto adecuado, se genera automáticamente un wait y una int al uC. El uC puede acceder entonces al bus de datos, leer lo que quiera y liberar el wait.
También puede obviar el wait y hacer latch de datos, pero eso te complica la implementación de los INs
usar latches sí que lo coomplica sí... de hecho había pensado en multiplexar los flipflops y tener 2 circuitos independientes en el uC, uno de entrada y otro de salida... un dispendio de recursos! ;-)
dandare escribió: En el Dandanator v2, la gal se usa porque hay un interfaz kempston. La parte de comunicación con el pic es una OR de MREQ, WR, A14 y A15 que genera una interrupción en el uC.
El uC va contando esos pulsos para entender comandos. Hay una gestión de timeouts y un protocolo definido pero no se usan outs ni Ins, por eso la electrónica es tan simple.
¿por qué incluyes en el OR MREQ, A14 y A15? entiendo que quieres interceptar accesos a la memoria por alguna razón, quizá para volcar datos, pero me extraña que no uses IOREQ, imagino que porque la comunicación con tu interfaz no se basa en peticiones de IO mediante OUTs e INs sino lo que dices de contar pulsos ¿que te aporta ese sistema? ya has dicho que la electrónica es más simple pero ¿compensa para esa simpleza la complicación de implementar un protocolo de comandos? ¿está publicado el codigo de la GAL y del uC del dandanator? me ha picado la curiosidad de ver como lo haces... ;-)
Avatar de Usuario
dandare
Hermano de Lucifer
Hermano de Lucifer
Mensajes: 3718
Registrado: 09 Feb 2016, 15:09
Ubicación: I Register
Been thanked: 6 times

Re: Un I/O para ZX Spectrum

Mensaje por dandare »

pep escribió:Gracias por tus intervenciones Dandare, estoy aprendiendo un montón hablando contigo solo por plantearme hacer el interfaz ¿ves como tenía interés resucitar el hilo? ;-)
De nada compañero, para eso están los foros. Muchos otros compañeros me han ayudado y dado información desde que estoy por aquí :)
pep escribió: ...el z80 solo direcciona 256 puertos de E/S mediante el byte bajo de dirección, así que solo necesitaría 8 flipflops para el bus de direcciones y otros 8 para el de datos...
El Z80 puede escribir y leer de FFFF puertos, aunque la mitad (todos los pares) están "cogidos" por la ULA :| y otros muchos por decodificaciones parciales históricas como la de kempston que es A5=0 . Un ejemplo claro es el control de memoria en un +2a/+3, usa los puertos 7FFD y 1FFD para cosas distintas.
pep escribió: ¿por qué incluyes en el OR MREQ, A14 y A15? entiendo que quieres interceptar accesos a la memoria por alguna razón, quizá para volcar datos, pero me extraña que no uses IOREQ, imagino que porque la comunicación con tu interfaz no se basa en peticiones de IO mediante OUTs e INs sino lo que dices de contar pulsos ¿que te aporta ese sistema? ya has dicho que la electrónica es más simple pero ¿compensa para esa simpleza la complicación de implementar un protocolo de comandos? ¿está publicado el codigo de la GAL y del uC del dandanator? me ha picado la curiosidad de ver como lo haces... ;-)
Por economia de componentes. Yo creo que sí compensa esta simplificación. Los primeros kits salieron a 12,5€ y eso que los componentes no eran chinos y se pidieron de pocos en pocos. Si hubiéramos ido a lo más barato, posiblemente podrían estar cerca de los 8€.

El dandanator mini funciona tomando el control del espacio rom del spectrum, así que la memoria eeprom tiene que responder a peticiones a ese rango de direcciones. Esto hace que necesite una OR de MREQ, RD, A14 y A15. Además, si quiero escribir en la eeprom para modificarla desde el spectrum, necesito también hacer una OR de MREQ, WR, A14 y A15. Esto cabe en un sólo chip 74HCT32 o en un CD4072, así que usé la salida del OR de escritura para mandar comandos al PIC. Por regla general nadie debería de escribir en zona rom, aunque algunos lo hacen, y es bastante manejable hacerlo así.

El código de la gal y el del uc están publicados, así como el del asm del Z80 (creo que no está la última versión de estos, a ver si las subo).
Es un proyecto de dominio publico, tanto en software como en hw.

Te adjunto la descripción de los comandos que admite el dandanator mini (están en el código también)

Código: Seleccionar todo

// Special Command code to execute (all special commands are 4-steps: Command Code, Command Data 1, Command Data 2, Fast Execute) 
// Command Code, Data 1 and Data 2
// Data1, Data2 and Fast Execute MUST be on next consecutive 132us windows to Command (4 windows total). Otherwise Special Command will be ignored
// All data must arrive in pulses separated by at least 8us and no more than 30us. 
// Detecting a command is done by timing out the pulses. After 32us without a pulse, the command, consisting in the number of received pulses, is processed.

// COMMANDS :
//---------------------------------------------------------------------------------------
// Command 0    : Not implemented (can't be)
// Command 1-32 : Bank Switch to 0-31 (1-32 pulses)
// Command 33   : Bank Switch to Internal ROM (Internal is recognized as Bank 33)
#define CMD_INTERNALROM_DISABLECMD 34
// Command 34   : Bank Switch to Internal ROM & Disable further Commands
// Command 35   : Reserved
#define CMD_RESET 36
// Command 36   : Generate a Reset
#define CMD_NMI 37
// Command 37   : Generate a NMI
// Command 38   : Reserved
#define CMD_SET_RESETSLOT 39
// Command 39   : Set Reset Slot. Current Slot is selected in case of an Spectrum-Triggered Reset. Cleared on ANY reset (even PIC-Triggered resets).
//--------------------------------------------------------------
#define CMD_SP_FASTCHANGE 40
// Special Command 40   : Fast Change & Action
//                      : Data 1 : Bank Number (1-33,35) - 35 means previous bank   
//                      : Data 2 : Action to perform
//                               : bit 3 - Disable Commands
//                               : bit 2 - Lock Commands   
//                               : bit 1 - NMI
//                               : bit 0 - Reset
//                               : bits 4-7 - Reserved MUST be 0
//--------------------------------------------------------------
#define CMD_SP_STOREBOOTBANK 41
// Special Command 41   : Store Bank Number for Boot
//                      : Data 1 : Bank Number (1-33)
//                      : Data 2 : Boot Type value
//                               : 0 - Standard Launch (normal boot)
//                               : 1 - Forced Launch 1 (boot with Switch 1 pressed)
//                               : 2 - Forced Launch 2 (boot with Switch 2 pressed)
//--------------------------------------------------------------
#define CMD_SP_SW1MODE 42
// Special Command 42   : Modify Switch 1 Behaviour
//                      : Data 1 : Bank Number (1-33) - PostScaler Window extra values (0..n)
//                      : Data 2 : Behaviour + Pulse Type
//                               : bits 0..2 - Behavior Value / Detection window multiplier (n+Data1)*50ms
//                                           - 0 : Disable
//                                           - 1 : Enable as Select ROM n + RESET
//                                           - 2 : Enable as ROM n + NMI + Enable Commands
//                                           - 3 : Enable as RESET
//                                           - 4 : Enable as NMI
//                                           - 5 : Lock Commands
//                                           - 6 : Disable Commands
//                                           - 7 : Enable as Select ROM n + RESET + Enable & Unlock Commands
//                               : bit 3..4  - Pulse Type Value
//                                           - 0 : Short Click
//                                           - 1 : Long Click
//                                           - 2 : Double Click
//                                           - 3 : Double Click Detection window (50ms intervals)
//                               : bits 5..7 - Reserved MUST be 0 
//--------------------------------------------------------------
#define CMD_SP_SW2MODE 43
// Special Command 43   : Modify Switch 2 Behaviour
//                      : Data 1 : Bank Number (1-33)
//                      : Data 2 : Behaviour + Pulse Type
//                               : bits 0..2 - Behavior Value
//                                           - 0 : Disable
//                                           - 1 : Enable as Select ROM n + RESET
//                                           - 2 : Enable as ROM n + NMI + Enable Commands
//                                           - 3 : Enable as RESET
//                                           - 4 : Enable as NMI
//                                           - 5 : Lock Commands
//                                           - 6 : Disable Commands
//                                           - 7 : Enable as Select ROM n + RESET + Enable & Unlock Commands
//                               : bit 3..4  - Pulse Type Value (note only switch 1 responds to long/double click)
//                                           - 0 : Short Click
//                                           - 1 : Reserved
//                                           - 2 : Reserved
//                                           - 3 : Reserved
//                               : bits 5..7 - Reserved MUST be 0 
//--------------------------------------------------------------
#define CMD_SP_STOREDATA 44
// Special Command 44   : Store Data in PIC eeprom
//                      : Data 1 : PIC Eeprom Address 0-252 (3 upper bytes are reserved for boot actions)
//                      : Data 2 : Data to Store (0-255) 
//--------------------------------------------------------------
#define CMD_SP_RETRIEVEDATA 45
// Special Command 45   : Retrieve PIC Eeprom or RAM Stored Data as NMI Pulses
//                      : Data 1: Data Address 0-255
//                      : Data 2: 1 for Eeprom, 2 for RAM Disk
//--------------------------------------------------------------
#define CMD_SP_LOCKUNLOCKDISABLE 46
// Special Command 46   : Lock, Unlock
//                      : Data 1: 1 for Lock, 16 for Enable&Unlock,31 for Disable - Warning unable to restore from Software if Disabled
//                      : Data 2: Repeat Data 1
//--------------------------------------------------------------
#define CMD_SP_PICREBOOT 47
// Special Command 47   : Reboot PIC
//                      : Data 1: 40
//                      : Data 2: 40
//--------------------------------------------------------------
#define CMD_EEP_PROGRAM 48
// Special Command 48   : Enter external eeprom programming mode to page according to JEDEC specifications 
//                      : Data 1: 1 for byte write, 16 for sector erase, 32 for sector write 
//                      : Data 2: Sector affected (SST39SF040 has 128 4k sectors)
//--------------------------------------------------------------
#define CMD_SP_CMDALLOW 49
// Special Command 49   : Allow two extra banks for receiving commands on boot. By default, only bank 0 enables commands on boot. These will be stored in non-volatile memory
//                      : Data 1 - Bank Number (1-32)
//                      : Data 2 - Store on position (1-2)
//--------------------------------------------------------------     
De todas formas, esta es mi aproximación para conectar un ordenador con un uC, que no hay por qué hacerlo así :D.
Imagen
Imagen
Responder

Volver a “Consultas”