Skip to main content

TI-84 Plus CE Memory Map

The TI-84 Plus CE uses the eZ80’s 24-bit address space (16 MB addressable). The memory map is organized into distinct regions for Flash, RAM, and memory-mapped I/O peripherals.

Address Space Overview

0x000000 ┌─────────────────────────────────────────┐
         │        Flash Memory (4 MB)              │
         │  ┌─────────────────────────────────┐   │
0x000000 │  │ Boot Sector (64 KB)             │   │
         │  ├─────────────────────────────────┤   │
0x010000 │  │ OS Code and Data                │   │
         │  ├─────────────────────────────────┤   │
0x0C0000 │  │ Archive (Flash Variables)       │   │
         │  │ - Programs (.8xp)               │   │
         │  │ - AppVars (.8xv)                │   │
         │  │ - Lists, Matrices, etc.         │   │
         │  ├─────────────────────────────────┤   │
0x3B0000 │  │ Certificate (unused)            │   │
         │  └─────────────────────────────────┘   │
0x400000 ├─────────────────────────────────────────┤
         │     Unmapped Region 1 (9 MB)            │
         │     (pseudo-random reads)               │
0xD00000 ├─────────────────────────────────────────┤
         │          RAM (256 KB)                   │
         │  ┌─────────────────────────────────┐   │
0xD00000 │  │ User RAM                        │   │
         │  ├─────────────────────────────────┤   │
0xD40000 │  │ VRAM (~150 KB)                  │   │
         │  │ - LCD Framebuffer               │   │
         │  │ - Palette                       │   │
         │  └─────────────────────────────────┘   │
0xD65800 ├─────────────────────────────────────────┤
         │     Unmapped Region 2 (2.5 MB)          │
0xE00000 ├─────────────────────────────────────────┤
         │   Memory-Mapped I/O (2 MB)              │
         │  ┌─────────────────────────────────┐   │
0xE00000 │  │ Control Ports                   │   │
0xE10000 │  │ Flash Controller                │   │
0xE30000 │  │ LCD Controller                  │   │
0xF00000 │  │ Interrupt Controller            │   │
0xF20000 │  │ Timers (3× GPT)                 │   │
0xF50000 │  │ Keypad                          │   │
0xFF0000 │  │ Control Ports (alternate)       │   │
         │  └─────────────────────────────────┘   │
0xFFFFFF └─────────────────────────────────────────┘

Flash Memory (0x000000 - 0x3FFFFF)

Size: 4 MB (4,194,304 bytes)
Type: NOR Flash
Access: Read-only from user code (writes require unlock sequence)

Flash Regions

Address RangeSizeDescription
0x000000 - 0x00FFFF64 KBBoot sector (8× 8KB sectors)
0x010000 - 0x0BFFFF11× 64KBOS code and data
0x0C0000 - 0x3AFFFF~3 MBArchive (user programs/variables)
0x3B0000 - 0x3FFFFF320 KBCertificate storage (unused)

Flash Archive Layout

Flash archive is organized in 64 KB sectors. Each sector:
Offset  Content
+0      Sector status byte (0xFC = valid, 0xFF = empty)
+1      Entry 1: [flag][size_lo][size_hi][type1][type2]...
        Entry 2: [flag][size_lo][size_hi][type1][type2]...
        ...
        [0xFF = free space]
Entry structure:
[flag] [size_lo] [size_hi] [type1] [type2] [version]
[addr_lo] [addr_mid] [addr_hi] [namelen] [name...] [data...]
  • flag: 0xFC = valid, 0xF0 = deleted, 0xFE = temporary
  • size: 16-bit LE, byte count after 3-byte header
  • type1: Variable type (0x05 = program, 0x15 = appvar, etc.)
  • type2: Always 0x00
  • version: Typically 0x00
  • addr: 24-bit LE self-referential pointer to flag byte
  • namelen: Length of name (1-8 bytes)
  • name: Variable name bytes
  • data: Variable content (includes 2-byte size prefix for programs)

Flash Timing

Parallel Flash (Older Models)

  • Default: 10 cycles per read
  • Configurable: Via port 0xE10005 (flash wait states)
  • Unmapped region: 258 cycles

Serial Flash (Newer Models)

  • Cache hit: 2-3 cycles
  • Cache miss: 197 cycles
  • Cache: 2-way set-associative, 128 sets, 32-byte lines
  • Unmapped region: 2 cycles
Enable serial flash mode:
emu.set_serial_flash(true);

RAM (0xD00000 - 0xD657FF)

Size: 414,720 bytes (256 KB user + ~150 KB VRAM)
Type: SRAM
Access: Read/write, 4 cycles read, 2 cycles write

RAM Regions

Address RangeSizeDescription
0xD00000 - 0xD3FFFF256 KBUser RAM (variables, stack, buffers)
0xD40000 - 0xD657FF~150 KBVRAM (framebuffer + palette)

Important RAM Addresses

AddressSizeDescription
0xD000801TI-OS flags byte
0xD000881APD flags (bit 2 = APD enable)
0xD000C41MathPrint flag (bit 5)
0xD005962curRow (cursor row)
0xD005982curCol (cursor column)

VRAM Layout (0xD40000+)

The LCD controller reads VRAM to generate the display:
0xD40000  ┌─────────────────────────────────┐
          │  Framebuffer 1 (153,600 bytes)  │
          │  320×240 × 16-bit RGB565        │
0xD65800  └─────────────────────────────────┘
          │  Palette (512 bytes)            │
          │  256 entries × 16-bit BGR1555   │
          └─────────────────────────────────┘
Framebuffer format:
  • Resolution: 320×240 pixels
  • Color depth: 16 bits per pixel (RGB565 or indexed via palette)
  • Layout: Linear, row-major
  • Address: LCD.UPBASE register (typically 0xD40000)
Palette format:
  • Entries: 256 colors
  • Format: BGR1555 (bit 15 unused, 5 bits per channel)
  • Address: LCD.UPBASE + 0x200 (when palette enabled)

Memory-Mapped I/O (0xE00000 - 0xFFFFFF)

Size: 2 MB
Access: Read/write via load/store instructions or IN0/OUT0

Device Map

Address RangeDeviceKey Registers
0xE00000 - 0xE0FFFFControl PortsCPU speed, power, battery
0xE10000 - 0xE1FFFFFlash ControllerWait states, unlock
0xE30000 - 0xE300FFLCD ControllerTiming, control, base address
0xF00000 - 0xF0001FInterrupt ControllerEnable, status, acknowledge
0xF20000 - 0xF2003FTimers (3×)Counter, match, control
0xF50000 - 0xF5003FKeypadData, control, status
0xF80000 - 0xF800FFRTCSeconds, load, control
0xFF0000 - 0xFF00FFControl (alt)Same as 0xE00000 via IN0/OUT0

Control Ports (0xE00000 / 0xFF0000)

Accessed via memory or IN0/OUT0 instructions:
PortFunctionValues
0x00Power controlBit 6 = power off
0x01CPU speed0=6MHz, 1=12MHz, 2=24MHz, 3=48MHz
0x02Battery statusADC readout
0x03Device typeFlash type, USB ID
0x05Control flagsBit 4 = LCD enable
0x06Protected portsBit 2 = unlock protected ports
0x28Flash unlockBit 2 = flash write enabled

Flash Controller (0xE10000)

OffsetFunctionDescription
0x00Flash enableEnable flash access
0x01Flash sizeSize configuration
0x02Flash mapMemory map selection
0x05Wait statesRead timing (0-15 cycles)

LCD Controller (0xE30000)

OffsetRegisterDescription
0x00-0x0FTimingTCON timing parameters
0x10ControlMode, enable, bits per pixel
0x18Interrupt maskEnable line compare interrupt
0x1CInterrupt statusLine compare flag
0x20UPBASEUpper panel base address (framebuffer)
0x24LPBASELower panel base (unused on CE)

Interrupt Controller (0xF00000)

OffsetFunctionBits
0x00Enable lowInterrupts 0-7 enable
0x04Enable midInterrupts 8-15 enable
0x08Enable highInterrupts 16-23 enable
0x10Status lowPending interrupts 0-7
0x14Status midPending interrupts 8-15
0x18Status highPending interrupts 16-23
Interrupt sources:
  • Bit 0: ON key
  • Bit 1: Timer 1
  • Bit 2: Timer 2
  • Bit 3: Timer 3
  • Bit 4: RTC
  • Bit 5: Keypad
  • Bit 6: LCD
  • … (24 sources total)

Timers (0xF20000)

Three identical general-purpose timers at offsets 0x00, 0x10, 0x20:
OffsetRegisterDescription
+0x00CounterCurrent counter value (32-bit)
+0x04Reset valueReload value (32-bit)
+0x08Match 1Interrupt trigger 1 (32-bit)
+0x0CMatch 2Interrupt trigger 2 (32-bit)
+0x10ControlEnable, mode, interrupt enable

Keypad (0xF50000)

OffsetRegisterDescription
0x00DataKey scan data (16-bit)
0x02ControlMode (scan/idle/single)
0x04StatusInterrupt status
Key matrix: 8 rows × 7 columns
Row 0: [DOWN] [LEFT] [RIGHT] [UP] - - -
Row 1: [ENTER] [+/-] [.] [0] [1] [2] [3]
Row 2: [4] [5] [6] [7] [8] [9] -
Row 3: [,] [SIN] [APPS] [X,T,θ,n] - [STAT] [PRGM]
Row 4: [COS] [)] [(] [{x^-1}] [TAN] [^] -
Row 5: [×] [√] [LOG] [x²] [LN] [STO] -
Row 6: [÷] [ON] [÷] [CLEAR] [-] [DEL] [2nd]

RTC (0xF80000)

OffsetRegisterDescription
0x00SecondsCurrent time (32-bit)
0x04AlarmAlarm time (32-bit)
0x08ControlInterrupt enable, load trigger
0x0CLoad statusBit flags for pending loads

Memory Protection

The eZ80 supports memory protection via control ports:

Privileged/Unprivileged Code

  • Privileged: PC ≤ privileged boundary (port 0x1E)
  • Unprivileged: PC > privileged boundary
Restrictions for unprivileged code:
  • Cannot write to flash
  • Cannot write to protected RAM range (ports 0x08-0x0A)
  • Cannot write below stack limit (port 0x0B)
Violations trigger NMI (non-maskable interrupt)

Protected Registers

  • Port 0x06 bit 2: Must be set to access privileged ports
  • Port 0x28 bit 2: Must be set for flash writes (after unlock sequence)

Address Decoding

The bus uses the top nibble (bits 23-20) for coarse routing:
fn decode_address(addr: u32) -> MemoryRegion {
    match addr >> 20 {
        0x0..=0xB => Flash,       // 0x000000-0xBFFFFF (mirrors after 4MB)
        0xC       => Unmapped,    // 0xC00000-0xCFFFFF
        0xD       => {
            if addr < 0xD65800 {
                if addr >= 0xD40000 { Vram } else { Ram }
            } else { Unmapped }
        }
        0xE..=0xF => Ports,       // 0xE00000-0xFFFFFF
        _         => Unmapped,
    }
}

Cycle Timing Summary

Access TypeCyclesNotes
Flash read (parallel)10Configurable via port 0xE10005
Flash read (serial hit)2-3Cache-dependent
Flash read (serial miss)197Cache line fetch
RAM read4Fixed
RAM write2Fixed
Port read2-4Depends on device (see port map)
Port write2-4Delay + rewind mechanism
Unmapped (parallel)258Open bus
Unmapped (serial)2Fast rejection

Next Steps

Build docs developers (and LLMs) love