TI-83 Plus ↔ Raspberry Pi Link

A link cable that doesn't exist

I wired a Raspberry Pi 4 straight to the link port on my TI-83 Plus — two GPIO pins, three wires, no official cable, no TI software anywhere in the loop. From the Pi it can now send and receive programs, install Flash applications, and run the entire monochrome assembly game library. All of it is driven from plain Python bit-banging two pins.

Two repos came out of it:

  • ti83-link — the Pi side. Link protocol, file formats, CLI tools.
  • ti83-basic-interpreter — a TI-BASIC interpreter with a desktop GUI that can push programs straight to the calculator.

Every documented value was wrong often enough to matter

This ended up being the real lesson of the project, more than the wiring. Every token value or protocol detail I took from documentation or from memory was wrong often enough to break something. Every value I read back off the calculator itself was right. So the rule became: don't trust the spec, trust the hardware.

  • 0x20 is not a space. It's the randM( token. Space is 0x29. A program built with 0x20 transfers with a perfect checksum, round-trips byte-for-byte identically, and then prints randM( on the screen instead of a space. Every automated check passed while the program was visibly wrong — only looking at the screen caught it.
  • The published protocol guide says each Flash data packet carries "four extra bytes at the beginning." It does not. That one only got resolved by reading a known-working open-source implementation instead of the docs.
  • EOT closes each variable's session, not the whole transfer. Sending a multi-variable group the documented way hangs the calculator dead after the first variable.
  • Four of eleven token values I remembered from earlier research were wrong, including < and ≠ swapped — which silently inverts comparison logic in anything that uses it.
Takeaway: a checksum-verified, byte-identical transfer proves the bytes arrived. It proves nothing about whether they're the right bytes. The only way to know was to type something on the calculator and read the bytes back.

Two open-collector lines and a handshake

The TI link port is two open-collector lines with 10 kΩ pull-ups built into the calculator. I emulate open-drain on the Pi by switching GPIO pin direction instead of switching pin state: released means the pin is a high-impedance input, asserted means it's an output held low. No pin is ever driven high, so no level shifters and no extra components are needed — just three wires: tip, ring, and ground.

RASPBERRY PI 4 GPIO16 (pin 36) GPIO12 (pin 32) GND TI-83 PLUS D0 (tip) D1 (ring) GND (sleeve) TIP RING SLEEVE / GND

The protocol itself is a fully interlocked handshake with no fixed baud rate: to send a bit, you pull one line low; the receiver acknowledges by pulling the other line low; then both release. Neither side ever has to guess timing, so a slow implementation is completely fine — this is all plain Python, and it moves at about 1 KB/s. File size stops being a practical constraint long before speed does.

Send, receive, and boot a whole game library

  • Send and receive calculator programs, pictures, and group files.
  • Install Flash applications — MirageOS was installed this way, which in turn unlocks the whole monochrome assembly game library that ships as MirageOS/Ion titles.
  • Write to both the calculator's 160 KB Flash archive and its 24 KB RAM.
  • Compile TI-BASIC source into the calculator's tokenized format.

A stuck bus that was really a stuck jumper

Hours went into a fault that looked exactly like a wiring short or a protocol bug: transmission errors, a bus that felt stuck, and a calculator that went sluggish and started dropping keypresses. It turned out to be one loose jumper wire at the Pi header.

The frozen-feeling calculator was actually the clue that broke the case. A TI-83+ that goes sluggish is blocked inside its own link-port routines, waiting on a bus it can't get control of — that's a bus symptom, not a calculator fault. Once I reseated the header, everything that looked like corruption or timing trouble just went away.

Scope: all of this was tested on exactly one TI-83 Plus and one Raspberry Pi 4. I have no idea what breaks on a TI-84 Plus, a different Pi revision, or a second calculator — treat it as verified for this specific pair of devices, not as a general spec.
← back to projects