Skip to content

System MCU

The MCU is an RP2350, specifically a Pimoroni PGA2350, which handles system critical functions that cannot be delegated to a card. This includes:

  • Keyboard/Mouse input (via USB)
  • SNES Controllers
  • Configurable Timers (including interrupts)
  • OS Drive (SD Card)
  • System Configuration (including card configuration)
  • Banked System RAM (256k)

It adopts the command/data address split where the top half of the address space is for commands and the bottom is for data (RAM), of which 256k is available per page. This is due to how much SRAM is available on the RP2350.

Keyboard

Register RW Address
Get Next Key R- 0x FFF4 0010
Status R- 0x FFF4 0011
IRQ Enable RW 0x FFF4 0012
IRQ Clear -W 0x FFF4 0013

Banked System RAM

System RAM functions similar to Banked Smart RAM. It provides 8MB of RAM broken up into 32 256k pages which are presented at the lower half of the address range.

Register RW Address
Page LSB RW 0x FFF4 0000
Page MSB RW 0x FFF4 0001
# Pages LSB R- 0x FFF4 0002
# Pages MSB R- 0x FFF4 0003
Support RW 0x FFF4 0004
Status R- 0x FFF4 0005
IRQ Enable RW 0x FFF4 0006
IRQ Clear -W 0x FFF4 0007
Stride Address LSB RW 0x FFF4 0008
Stride Address MSB RW 0x FFF4 0009
Stride Config RW 0x FFF4 000A
Stride RW 0x FFF4 000B

Mouse

Register RW Address
X LSB R-
X MSB R-
Y LSB R-
Y MSB R-
Status R-
IRQ Enable RW
IRQ Clear -W

Controllers

Register RW Address
Status R-
IRQ Enable RW
IRQ Clear -W

Timers

System Configuration

Configuration which can simply be stored on the SD card in a text file, is used on system boot and, forgive the term, functions as a registry if information. This includes installed cards and their desired memory address ranges as well as their type and, based on the type, metadata about the card. I was wanting to avoid having to have a system-side notion of baked in card types, but we need at least 1 - memory.

Bus/Card Configuration

At minimum, this maps physical slots to addresses and established wait states. All cards will need 3 these pieces of information before they should be used in the system.

This allows for using any kind of card in any slot at any card range, noting that there are recommend memory addresses for the more common or critical cards (memory and video). Certain cards also have specific configuration parameters. I wanted to keep this rather loose and flexible but for some cards it was unavoidable to keep the card implementation simpler.

Thus each card will have a card type:

| Value | Type |

| 0x00 | Basic RAM | | 0x01 | Smart RAM | | 0x02 | Cartridge (ROM or ROM & RAM) | ... | 0xFF | Other/General |

Basic RAM

Basic RAM is banked memory that runs at a vendor-specific bus divisor. The only read/write command register is bank select and is guaranteed to run at the bus division with no stalls on page flips. It does not support any additional features, but is predictable (and should be fast).

SRAM with basic decoding is what most cards would likely be.

Required information to configure is number of pages and the bus divisor.

If the number of pages, somehow, is more than 256, applications will need to be aware when changing pages since basic RAM changes pages immediately when writing to the low bank or hi bank register.

Smart RAM

Smart RAM is banked memory that is often larger and can use cheaper, bigger, but slower, memory. One suggested reference design is using an RP2350 with PSRAM. Bank switching here takes a long time such that programs need to leverage command registers.

One benefit is that it can support stride reads and writes.

Smart RAM can be queried directly for capability though defaults should be provided that allow for booting the system in a stable state.

Cartridge

A cartridge is ROM that optionally can also include RAM as well as coprocessors and accelerators. Because the system can boot directly into a cartridge into application code, whether or not the cartridge splits the address space into command/data or just has one big block of data (or something else) is up to the cartridge maker.

If an application fits in 512k of ROM, it doesn't need banking, for instance.

Cartridges are transient and a slot needs to be configured to accept a cartridge and include a boot flag in the config. This tells the system whether or not to boot to the cartridge on startup. If the boot flag is set, on startup, it will look at the first 4 bytes for the words CART. If found, it will jump to the next byte to begin code execution.