pico6502 Guia del Desarrollador

English

Nota: El proyecto pico6502 esta en fase de desarrollo inicial. El framework de drivers y el modelo de memoria estan completamente implementados y comparten la misma arquitectura que el picoZ80. Sin embargo, actualmente solo existe una persona BBC Model B de relleno — esta guia explica como construir sobre esa base para agregar sus propios drivers. Donde el pico6502 es arquitectonicamente identico al picoZ80, se proporcionan referencias cruzadas a la Guia del desarrollador picoZ80.

Vision general

El firmware del pico6502 esta estructurado de manera identica al firmware del picoZ80. Usa la misma arquitectura de doble nucleo RP2350B, el mismo modelo de memoria PSRAM, el mismo sistema de configuracion JSON y el mismo framework de drivers — las diferencias principales son:
  • M6502CPU.c / M6502CPU.h reemplazan a Z80CPU.c / Z80CPU.h como archivos principales de despacho y framework de drivers.
  • El 6502 no tiene un espacio de direcciones I/O separado — no hay array ioPtr[] ni seccion JSON iomap. Todos los perifericos se virtualizan como bloques tipo FUNC en el mapa de memoria de 64 KB.
  • La interfaz de bus PIO (M6502.pio) implementa reloj bifasico PHI1/PHI2 en lugar del modelo de reloj unico del Z80.
  • El directorio objetivo de compilacion es BaseM6502 en lugar de BaseZ80.
  • La clave de seccion CPU JSON es "6502" en lugar de "z80".
Todo lo demas — el patron de cola inter-nucleos, los callbacks del ciclo de vida de drivers (reset_ptr, poll_ptr, task_ptr), la tabla de registro virtualFuncMap[], las constantes de tipo de bloque de memoria, la struct t_6502PSRAM, el protocolo del coprocesador ESP32 y el sistema de compilacion — se comparte con el codebase del picoZ80.

Arbol de codigo fuente

Todo el codigo fuente se encuentra bajo projects/tzpuPico/ en la raiz del repositorio. El layout a continuacion resalta los archivos especificos del pico6502:
tzpuPico/
├── CMakeLists.txt                          Archivo de compilacion de nivel superior
├── src/
│   ├── CMakeLists.txt                      Archivo de compilacion a nivel fuente — agregar nuevos archivos de driver aqui
│   ├── M6502CPU.c                          *** ARCHIVO CLAVE: despacho 6502, framework drivers, virtualFuncMap
│   ├── M6502.pio                           Programas PIO: clock, addr, data, cycle, fetch, read, write, irq, nmi, so
│   ├── include/
│   │   ├── M6502CPU.h                      *** ARCHIVO CLAVE: todas las definiciones de tipo y macros 6502
│   │   └── drivers/
│   │       └── BBC/
│   │           └── ModelB.h               Header del driver BBC Model B (relleno inicial)
│   ├── drivers/
│   │   └── BBC/
│   │       └── ModelB.c                   *** DRIVER EJEMPLO/RELLENO (persona BBC Model B)
│   └── model/
│       ├── BaseM6502/
│       │   ├── CMakeLists.txt             Objetivos de compilacion por modelo
│       │   └── main.c                     Punto de entrada (lanzamiento Core 0 + Core 1)
│       └── Bootloader/
│           └── main.c                     Bootloader compartido (mismo del picoZ80)
└── esp32/
    └── main/
        └── ...                            Firmware ESP32 (compartido con picoZ80)

Diferencias clave con el picoZ80

Sin espacio de direcciones I/O separado

La diferencia arquitectonica mas importante es que el 6502 no tiene instrucciones IN/OUT ni senal IORQ. Cada periferico debe aparecer en algun lugar del mapa de memoria de 64 KB. En el picoZ80, los perifericos virtuales pueden registrarse via memioPtr[] (mapeados en memoria) o ioPtr[] (mapeados en I/O). En el pico6502 solo existe memioPtr[].

Struct t_6502PSRAM

// src/include/M6502CPU.h (simplificado)
typedef struct {
    uint8_t      RAM[MAX_MEMORY_BANKS * MEMORY_PAGE_SIZE]; // 64 bancos x 64 KB = 4 MB area RAM/ROM
    MemoryFunc   memPtr[MEMORY_PAGE_SIZE];                  // 64K redireccion lectura por byte (tipo PTR)
    MemoryFunc   memioPtr[MEMORY_PAGE_SIZE];                // 64K array handlers mapeados memoria (tipo FUNC)
    // NOTA: sin ioPtr[] — el 6502 no tiene espacio I/O separado
} t_6502PSRAM;

Firma de la funcion handler

// Handler llamado para bloques MEMBANK_TYPE_FUNC en cada acceso
typedef uint8_t (*MemoryFunc)(M6502CPU *cpu, bool read, uint16_t addr, uint8_t data);

// Parametros:
//   cpu  — puntero a la struct M6502CPU
//   read — true para ciclo lectura 6502 (RNW=1), false para ciclo escritura (RNW=0)
//   addr — direccion 16 bits que activo este handler
//   data — byte escrito (solo significativo cuando read=false)
// Retorno:
//   byte a colocar en el bus de datos (solo significativo cuando read=true)

Framework de drivers

El framework de drivers en M6502CPU.c es estructuralmente identico al del picoZ80. Consulte la seccion Guia del desarrollador picoZ80 — Framework de drivers para la descripcion completa.
picoZ80 pico6502 Notas
struct Z80CPU struct M6502CPU Mismos campos, mismo layout
Z80CPU_getVirtualFunc() M6502CPU_getVirtualFunc() Misma logica de busqueda
Z80CPU_cpu() M6502CPU_cpu() Punto de entrada del bucle Core 1
Z80CPU_readMem() M6502CPU_readMem() Despacho lectura memoria
Z80CPU_writeMem() M6502CPU_writeMem() Despacho escritura memoria
Z80CPU_readIO() Sin equivalente — el 6502 no tiene espacio I/O
Z80CPU_writeIO() Sin equivalente — el 6502 no tiene espacio I/O
cpu->_z80PSRAM cpu->_6502PSRAM Puntero a struct PSRAM

Escribir un nuevo driver

El proceso para escribir un driver pico6502 es identico al del picoZ80 descrito en la Guia del desarrollador picoZ80 — Escribir un nuevo driver. Los seis pasos son los mismos:
  1. Crear un archivo header en src/include/drivers/<Family>/MyDriver.h
  2. Crear un archivo de implementacion en src/drivers/<Family>/MyDriver.c
  3. Agregar el archivo fuente a src/CMakeLists.txt
  4. Incluir el driver en M6502CPU.c bajo una guardia #ifdef INCLUDE_<FAMILY>_DRIVERS
  5. Registrar el driver en virtualFuncMap[] en M6502CPU.c
  6. Agregar una entrada de driver JSON en config.json
La diferencia clave es que en lugar de un parametro Z80CPU *cpu, todas las funciones reciben un parametro M6502CPU *cpu, y se accede a la PSRAM via cpu->_6502PSRAM en lugar de cpu->_z80PSRAM. No hay slots ioPtr[] para instalar — todos los perifericos virtuales se registran en memioPtr[].

Plantilla de driver minima

// src/include/drivers/BBC/VIA6522.h
#ifndef VIA6522_H
#define VIA6522_H
#include "M6502CPU.h"
int VIA6522_Init(M6502CPU *cpu, t_drvConfig *drvConfig, int pass);
#endif
// src/drivers/BBC/VIA6522.c
#include "../../include/M6502CPU.h"
#include "../../include/drivers/BBC/VIA6522.h"

typedef struct {
    uint8_t  regs[16];
    bool     irqPending;
} t_VIA6522State;

static t_VIA6522State ViaState = { .irqPending = false };

static uint8_t VIA6522_Handler(M6502CPU *cpu, bool read, uint16_t addr, uint8_t data)
{
    uint8_t reg = addr & 0x0F;
    if(read) return ViaState.regs[reg];
    ViaState.regs[reg] = data;
    return 0;
}

static uint8_t VIA6522_Reset(M6502CPU *cpu)
{
    memset(&ViaState.regs, 0, sizeof(ViaState.regs));
    ViaState.irqPending = false;
    return 0;
}

int VIA6522_Init(M6502CPU *cpu, t_drvConfig *drvConfig, int pass)
{
    if(pass == 0) return (strcasecmp(drvConfig->name, "via6522") == 0) ? 1 : 0;
    for(uint16_t addr = 0xC000; addr <= 0xC00F; addr++)
        cpu->_6502PSRAM->memioPtr[addr] = VIA6522_Handler;
    cpu->reset_ptr = VIA6522_Reset;
    debugf("VIA6522: Inicializado en 0xC000–0xC00F\n");
    return 1;
}

Registro en virtualFuncMap

static const t_VirtualFuncMap virtualFuncMap[] = {
    { "BBCModelB", BBCModelB_Init },   // entrada existente
    { "via6522",   VIA6522_Init   },   // su nuevo driver
    { NULL, NULL }                     // terminador
};

Patrones de hooks de memoria

Como el 6502 no tiene espacio I/O, todos los patrones de hooks usan memioPtr[]. Los patrones son los mismos descritos en la Guia del desarrollador picoZ80 — Patrones de hooks de memoria.

Errores comunes

  • Instalar un handler en ioPtr en lugar de memioPtr. El pico6502 no tiene array ioPtr[]. Todos los handlers de perifericos van en memioPtr[].
  • Esperar una llamada de despacho I/O. No existe M6502CPU_readIO() ni M6502CPU_writeIO().
  • Bloquear en un handler. Cualquier llamada a debugf, sleep_ms o fopen desde un handler bloqueara el Core 1 y corrompera el timing de bus del 6502.
  • Nombre virtualFuncMap no coincidente. El campo JSON "name" se compara sin distincion de mayusculas/minusculas con la tabla virtualFuncMap[].
  • Olvidar establecer el tipo de bloque a FUNC. Instalar un handler en memioPtr[] no tiene efecto si las entradas _membankPtr[] correspondientes aun muestran MEMBANK_TYPE_RAM o MEMBANK_TYPE_ROM.

Sitios de referencia

Recurso Enlace
Pagina del proyecto pico6502 /pico6502/
Manual de usuario pico6502 /pico6502-usermanual/
Guia tecnica pico6502 /pico6502-technicalguide/
Guia del desarrollador picoZ80 /picoz80-developersguide/
Pagina del proyecto picoZ80 /picoz80/
Hoja de datos RP2350 datasheets.raspberrypi.com
Hoja de datos MOS 6502 archive.org

Aviso regulatorio inalambrico

Este dispositivo incorpora un modulo inalambrico ESP32-S3-PICO-1 que transmite en la banda ISM de 2,4 GHz, convirtiendolo en un emisor intencional segun las regulaciones de radiofrecuencia a nivel mundial.
Limitaciones importantes
  • Los dispositivos ensamblados no deben ser vendidos o distribuidos a terceros sin autorizacion de equipo propia.
  • La construccion para uso personal en cantidades limitadas esta generalmente permitida bajo disposiciones para aficionados (ej. FCC § 15.23).
Responsabilidad del constructor
Es responsabilidad exclusiva del constructor asegurarse de que cualquier dispositivo construido a partir de estos disenos cumpla con todas las regulaciones de radiofrecuencia aplicables en su jurisdiccion.