Esto puede hacer todo lo que hacía el CPC-CPLINK original, pero ahora cuenta con FIFOs profundas de 1024 bytes y la capacidad de enviar datos mediante imágenes ROM de vuelta al Amstrad CPC.
Por el momento, esto sigue en pleno desarrollo, pero podéis ver su capacidad en el siguiente vídeo, donde la pelota se está renderizando en la PI Zero y enviando al CPC para mostrarse en pantalla.
Que comience el debate sobre «qué hace que sea un CPC»
Pero está genial.
Para quienes no recuerden el CPC-CPLINK:
Se trata de una tarjeta que permite conectar un coprocesador externo, como una RaspberryPi, directamente a cualquier ordenador Amstrad CPC.
La tarjeta proporciona una interfaz paralela fácil de usar entre los procesadores mediante hardware First-In First-Out (FIFO) y un sencillo protocolo de software de paso de mensajes. Incluye componentes de cambio de nivel de voltaje para que se puedan conectar directamente coprocesadores tanto de 3V3 como de 5V. Lo más probable es que el coprocesador sea una RaspberryPi, pero la interfaz es adecuada para otros procesadores y sistemas, incluidos Arduinos, Teensy y microcontroladores PIC.
El objetivo principal era aumentar el rendimiento de datos desde la PI hacia el CPC.
Sí, el CPC-CPLINK2 cuenta con FIFOs más profundas (ahora 1024 en comparación con 16), pero esto realmente no cambia la velocidad de las peticiones de E/S desde el CPC.
Para mejorar la velocidad, añadí un GPIO adicional llamado «ROM Not FIFO» (RNF). Cuando este se pone en HIGH, se llena una pseudo-ROM en la Pico en lugar de la FIFO. Luego se activa un bit adicional en el registro de estado actual para indicar que hay datos en la ROM (en realidad hay 2 ROM disponibles). A continuación, el CPC solo tiene que seleccionar la ROM (OUT &DFXX, NN) y copiar los datos (es decir, LDI).
Por lo tanto, es totalmente retrocompatible con el CPC-CPLINK original, pero incluye este pequeño truco adicional para transferir un poco más de datos desde la PI hacia el CPC.
Gracias, de verdad que me lo estoy pasando genial con esto. Conseguí mi CPC 664 original cuando tenía 16 años, antes de que saliera el 6128 (vamos, hace ya un montón de tiempo), y todavía lo sigo usando a día de hoy. Este tipo de proyectos me permite seguir explorando y entendiendo el Amstrad CPC. Lo sigo disfrutando tanto como cuando tenía 16.
¿puedes proporcionar la documentación de programación en esta etapa? así podré crear una clase para que uses NTC BASIC con ella — ¡me encantaría ver la demo City3D funcionando usando la Pi como coprocesador!
Una evolución de la demo City3D programada en NTC BASIC: sobrevuela Auckland, Nueva Zelanda
Algunas estadísticas:
Sobrevuela Auckland, Nueva Zelanda, en modo wireframe (malla de alambre), en un Amstrad CPC con 4 MB de expansión de RAM. La ciudad entera está en la memoria: 233.935 edificios; 43.082 líneas de carreteras, vías férreas, costa y agua; 50.040 árboles; la Sky Tower; el Harbour Bridge y los volcanes; procedente de OpenStreetMap, 409 km².
REQUISITOS
CPC 6128 o 464 (Z80, 4 MHz), expansión de 4 MB de RAM (200 páginas de RAM o más)
UniDOS con un nodo de almacenamiento masivo (IDE, SD…): AUCKLAND.DAT ocupa 3,8 MB
(sin la lectura por bloques de UniDOS carga byte a byte: demasiado lento)
WinAPE también funciona: unidad IDE = AUCKLAND.IMG, ROMs de UniDOS, 4 MB de RAM
Archivos: AUCKLAND.BIN (el programa, 35K) y AUCKLAND.DAT (los datos), en la misma unidad. RUN"AUCKLAND
He subido todo el análisis y las herramientas, incluyendo pronto el código en C para Raspberry Pi (que deberías poder adaptar). También puedes pasarle a Claude el NTC BASIC completo con la demo y podrá reprogramar la parte del CPC para usar la parte de la Pi si lo necesitas.
Código, protocolo, etc. para CP-CPCLINK2, que debería ser «casi» plug-and-play:
Demo de Auckland para CPC (sin CP-CPCLINK2, pero… necesita 4 MB de RAM + UniDOS):
Versión para CP-CPLINK2 (puede que necesite algunos retoques ya que todavía no tengo la tarjeta, pero… ¡debería funcionar sin nada de RAM extra!)
De parte de Claude:
He escrito la versión para coprocesador: el motor en C, un protocolo para la ventana de ROM que sirve la tarjeta y la parte del CPC. La tarjeta almacena AUCKLAND.DAT y el CPC ya no necesita una ampliación de RAM. Está en auckland.zip dentro de coprocessor/, y en el árbol de NTC como tools/s3dpi y src/bas/aucklink. El Z80 dibuja las listas de líneas de la tarjeta exactamente igual que la referencia en C (cmp.png: Z80 a la izquierda, C a la derecha).
Velocidad medida: la tarjeta se encarga del 3D, por lo que el frame del CPC consiste en copiar la lista fuera de la ROM (unos 45 ms) más dibujarla:
Vista
Líneas
Lista
Frame CPC
fps
Start
440
1.7K
0.29 s
3.4
Harbour Bridge
300
1.3K
0.22 s
4.5
Devonport
1270
5.6K
0.86 s
1.2
Sky Tower
1400
7.7K
1.13 s
0.9
Eso es de 4 a 10 veces la base de 0,2–0,4 fps. Dibujar líneas con gfx_line se lleva ahora casi todo el tiempo del CPC, así que es lo siguiente a optimizar. Un presupuesto de líneas (B) más bajo sacrifica detalle a cambio de velocidad. La parte de la tarjeta tarda 0,03–0,2 ms por frame en un PC; aún no lo he medido en una RP2040.
Cómo funciona el enlace:
El CPC envía un pequeño paquete F por frame: cabeceo (pitch), alabeo (roll) y guiñada (yaw) (-1, 0 o 1), velocidad, salto de frames (frame skip) y presupuesto de líneas. También hay paquetes para saludar, saltar a una vista y obtener el nombre de una vista.
La ROM de la tarjeta tiene un bloque de estado en #C100: «S3DP» cuando está lista, un número de secuencia, qué lista es la más reciente, recuento de líneas, altitud, brújula y un mensaje. En #C200 y #E000 se ubican dos listas de dibujo de 7,5K.
Una lista son 3 bytes por punto (MOVE o DRAW con x 0–319 e y 0–199), más códigos PEN y END de 1 byte. Cada punto ya está recortado (clipped) a la pantalla.
En cada frame, el CPC espera a que cambie el número de secuencia, copia la lista más reciente, envía el siguiente paquete F y luego dibuja. La tarjeta genera el siguiente frame mientras el CPC dibuja el actual, rellenando la lista que el CPC no esté leyendo.
El código C usa exclusivamente enteros, así que un RP2040 sin FPU va de sobra:
s3dpi.c / s3dpi.h: el motor, con los mismos tiles, distancias de LOD, proyección y presupuesto de líneas que la versión de Z80.
card.c / card.h: la parte de la tarjeta. El firmware de la tarjeta pasa cada paquete a card_command() y sirve rom[] como su ROM de 16K.
sim.c: ejecuta todo el enlace en un solo programa y genera imágenes más un archivo de lista.
host.c: el motor por sí solo, con mediciones de tiempo.
Lo que no se sabrá hasta que salga la documentación de CPLINK2:
Puertos: los puertos de E/S reales. Link.cls usa sustitutos al estilo M4: bytes a #FE00, activación (kick) en #FC00.
Número de ROM: el sustituto es la ROM 6.
Dónde residen los datos: si están en la tarjeta, la placa necesita 4 MB o más de memoria flash. La flash del RP2040 está mapeada en 0x10000000, y s3d_open recibe un puntero a los datos. Como alternativa, el motor se ejecuta en un PC o Raspberry Pi al otro extremo del enlace, y la tarjeta solo se encarga de subir los paquetes y bajar las listas de 7,5K.
Probado hasta ahora: únicamente el enlace simulado (sim.c) y el Z80 dibujando una lista generada por sim.c.
Se ve genial. En este momento me estoy centrando en hacer que CPC-CPLINK2 funcione y en que sea lo más robusto posible. Le echaré un vistazo a esto cuando tenga tiempo. Todo lo que necesitas saber sobre cómo usar CPC-CPLINK2 está en esta diapositiva, incluidos los puertos de E/S y los números de ROM.