IR Bridge

Ericsson MC218 ↔ Flipper Zero ↔ LLM


A working bridge that lets an Ericsson MC218 — a 1999 palmtop running EPOC Release 5 — chat with a large language model via infrared. The user types a question on the Psion keyboard; a native OPX encodes and transmits the entire message in a single IR burst (~100 ms for "HELLO"); a Flipper Zero decodes the raw signal and relays it over UART to an ESP32 WiFi devboard, which queries an LLM API; and the response travels back the same path to appear on the palmtop's screen.

The MC218 uses a proprietary serial connector that has been out of production for twenty-five years. This project eliminates the need for any cable by re-purposing the Psion's built-in IrDA transceiver hardware for a custom 38 kHz IR protocol. No IrDA software stack is involved on the transmit side; instead, a native OPX drives the SIR modulator at a baud rate chosen so that the resulting pulse train is indistinguishable from a 38 kHz consumer-IR carrier. The ESP32 WiFi devboard plugs directly into the Flipper, making the entire setup cable-free. No additional IR hardware is required: the Psion's IrDA LED and the Flipper's TSOP receiver are used directly, pointed at one another at a distance of ten to thirty centimetres.

Architecture

The signal chain:

Ericsson MC218
EPOC R5, IrDA, OPX+OPL
IR Flipper Zero
TSOP 38kHz, IR Bridge FAP
UART ESP32-S2
WiFi devboard, GPIO header
WiFi / TLS LLM
OpenRouter API

Psion → Flipper.  SIR @ 38400 baud → 38 kHz carrier. Ternary encoding: 3 digits per character. "HELLO" ≈ 100 ms total.

Flipper → Psion.  Pulse-width IR @ 36 kHz carrier. TTY:B @ 4800 baud. EOT = 0x04, max 200 chars. ~120 ms per byte.

Key insight: 38400 baud bit period (26 µs) ≈ 38 kHz period (26.3 µs) — the TSOP locks on cleanly.

The Psion transmits using a native OPX (C++ DLL) that drives the IrDA UART at 38400 baud — a rate whose bit period (26 µs) matches the 38 kHz carrier expected by the Flipper's TSOP receiver. Each byte 0x00 produces nine SIR pulses at ~38 kHz (a "mark"), while 0xFF produces silence (a "space"). An entire message is encoded as mark/space durations in a single buffer and transmitted in one SIR frame — "HELLO" takes roughly 100 ms. The Flipper decodes the raw timing array, assembles the text, and forwards it over UART to the ESP32 WiFi devboard. The ESP32 queries the LLM via WiFi; the Flipper then re-encodes the response as pulse-width IR at 36 kHz carrier and transmits it back; the Psion reads this on its IrDA serial port (TTY:B) at 4800 baud.

Protocol

Psion → Flipper (38 kHz carrier, ternary).  The entire message is transmitted in a single SIR frame at 38400 baud. At this rate, each bit period is ~26 µs — nearly identical to the 38 kHz period (26.3 µs) that the Flipper's TSOP infrared receiver is tuned to. A byte of 0x00 generates nine SIR pulses at ~38 kHz (carrier "on"); a byte of 0xFF generates no pulses (carrier "off"). By alternating runs of these bytes the OPX constructs mark/space pairs whose durations encode ternary digits. Each character uses three digits (base-3: A=0, B=1, … Z=25, space=26). A header mark (~8 ms) opens the frame; then for each digit a short mark (~1 ms) is followed by a space whose length encodes the value.

Why 38400 baud? The Flipper's TSOP infrared receiver has a bandpass filter tuned to 38 kHz. Ordinary IrDA at 4800 or 9600 baud produces SIR pulses at the wrong repetition rate; the TSOP detects them unreliably, if at all. At 38400 baud, the pulse repetition rate matches the TSOP's design frequency, so the receiver locks on cleanly — turning the IrDA port into a standard 38 kHz IR transmitter. This is not IrDA communication: the project uses only the IrDA transceiver hardware (LED and SIR pulse shaper), while the protocol above it is entirely custom.

Symbol Mark (0x00 bytes) Space (0xFF bytes)
Header32 (~8.3 ms)16 (~4.2 ms)
Digit 04 (~1.0 ms)4 (~1.0 ms)
Digit 14 (~1.0 ms)8 (~2.1 ms)
Digit 24 (~1.0 ms)12 (~3.1 ms)
Trail4 (~1.0 ms)

Flipper-side thresholds: digit 1 ≥ 1.5 ms, digit 2 ≥ 2.5 ms, header ≥ 4 ms. One character = three ternary digits = ~5 ms. A five-letter word transmits in roughly 100 ms including SIR frame overhead.

Flipper → Psion (pulse-width IR + EOT).  Each ASCII byte is encoded as eight mark/space pairs at 36 kHz carrier. A start mark of 50 ms, data marks of 8 ms (for 0) or 16 ms (for 1), and an end mark of 75 ms, with 3 ms spaces between all marks. The Psion's SIR decoder on TTY:B at 4800 baud interprets the resulting byte values: ≥ $E0 = bit 1, ≤ $90 = bit 0, values between = marker. End of message is byte 0x04 (ASCII EOT). Maximum response length: 200 characters. Transmission speed: ~120 ms per byte, ~24 seconds for a full 200-character response.

SymbolMark duration
Start50 ms
Bit 08 ms
Bit 116 ms
End75 ms
Space between marks3 ms

Flipper ↔ ESP32 (UART).  115200 baud, 8N1, newline-terminated ASCII over the Flipper GPIO header.

DirectionFrameMeaning
Flipper → ESP32Q:<text>\nLLM query
ESP32 → FlipperR:<text>\nLLM response
ESP32 → FlipperS:<status>\nStatus
ESP32 → FlipperE:<reason>\nError

Hardware

ComponentNotes
Ericsson MC218EPOC Release 5, OPL + OPX. Built-in IrDA port.
Flipper ZeroStock firmware with IR subsystem.
ESP32-S2 WiFi DevboardOfficial Flipper devboard, plugs into GPIO header. No wires.

No additional IR hardware is needed. The ESP32 devboard plugs directly into the Flipper — no soldering, no cables. Point the Psion's IrDA window at the Flipper's IR transceiver, ten to thirty centimetres apart.

Building

Flipper application.

cd flipper/ir_bridge
ufbt build
# Copy ir_bridge.fap to
# Flipper SD: /ext/apps/Infrared/

ESP32 firmware.  Set your WiFi credentials and OpenRouter API key in esp32/simple_bridge/simple_bridge.ino, then:

arduino-cli compile --fqbn esp32:esp32:esp32s2 \
  esp32/simple_bridge/simple_bridge.ino
arduino-cli upload --fqbn esp32:esp32:esp32s2 \
  --port /dev/cu.usbmodem01 \
  esp32/simple_bridge/simple_bridge.ino

Psion OPX + OPL.  The OPX (native C++ DLL) is built with the EPOC Release 5 C++ SDK under Wine. A pre-built binary is available in release/irflash.opx. The OPL programme is compiled with OPLTRAN.EXE:

# OPX: built via GCC ARM cross-compiler
# (see opx/ for source and build scripts)
# Pre-built: release/irflash.opx

# OPL:
unix2dos psion/chat_a.opl
wine path/to/OPLTRAN.EXE "C:\chat_a.opl"

# Copy irflash.opx to MC218:
#  D:\System\Opx\IRFLASH.OPX
# Copy chat_a.opo to MC218
# via CF card

The OPX auto-loads via DECLARE OPX — no LOADM needed on EPOC R5.

Usage

Plug the ESP32 WiFi devboard into the Flipper GPIO header. Flash the IR Bridge FAP to the Flipper and launch it from the Infrared category. On the Psion, run chat_a.opo, type a message (A–Z and spaces), and press Enter. The OPX encodes and transmits the entire message in a single IR burst — typically under 100 ms. The Flipper decodes the raw signal, forwards it to the ESP32, which queries the LLM via WiFi; the response arrives back on the Psion's screen.

ButtonAction
UpSend "ABC" to Psion (test)
DownSend "Hello" to Psion (test)
OKSend received message to LLM
LeftClear display / reset state
BackExit application

Known Limitations

The Psion transmit alphabet is restricted to A–Z and space; there are no numerals or punctuation. LLM responses are capped at 200 characters by the IR transmit buffer constraint (MAX_TIMINGS_AMOUNT=1024). Flipper → Psion speed is approximately 24 seconds for 200 characters (4800 baud SIR limit). The OPX uses the IrDA UART hardware but does not implement the IrDA protocol. Port contention: the OPX must be closed before TTY:B can receive; chat_a handles this automatically.

Repository

Source code and documentation at github.com/R2BPW/psion-flipper-bridge.

psion/
  chat_a.opl              OPL chat (OPX TX + TTY:B RX)
  irchat_opx.opl          legacy chat (original version)

opx/
  irflash_sir.cpp         OPX source (38400 baud)
  irflash.h               OPX C++ header
  irflash.mmp             Symbian build file
  IRFLASH.OXH             OPL interface header

flipper/ir_bridge/
  ir_bridge.c             Flipper Zero FAP source
  application.fam         app manifest

esp32/
  simple_bridge/
    simple_bridge.ino     ESP32 LLM bridge (WiFi, OpenRouter)
  llm_bridge/
    llm_bridge.ino        ESP32 LLM bridge with RPC opcodes

release/
  irflash.opx             compiled OPX for MC218
  ir_bridge.fap           compiled Flipper FAP
  IRFLASH.OXH             OPX header (copy to MC218)

docs/
  PROTOCOL.md             protocol specification
  HARDWARE.md             hardware notes
  OPL_NOTES.md            EPOC OPL compilation
  SPEEDUP.org             speed optimization notes