Tachibana
Language: English

OricTel — full feature list

Minitel 1B terminal for the Oric 1 / Atmos · C + 6502 assembly (cc65) · EUPL 1.2 license

This page lists every OricTel feature, with an explanation of each. The GitHub repository is the authoritative, up-to-date source; the user manual and the architecture documentation cover usage and internals.

Contents

1. Videotex decoder

The heart of OricTel is a decoder for the Teletel/Antiope Videotex protocol (STUM 1B), implemented as a full state machine.

State machine

Handles ESC, CSI (with parameters), US, SS2, REP (repeat), SEP, and the PRO1/PRO2/PRO3 protocol modes. Cursor positioning (US row/column), moves, erases, carriage return.

PRO2 / PRO3 modes

Roll mode, lowercase, keyboard switches, extended/cursor keyboard. The left/right arrows only send cursor sequences (ESC[D / ESC[C) if the server has enabled cursor mode (PRO3), just like a real Minitel 1B.

Terminal identification

ENQ/ENQROM identification is deliberately silent: modern servers (MiniPavi) echo the reply into the input field instead of consuming it — the same behaviour as the reference emulator miedit.

2. HIRES display

Resolution & grid

HIRES 240×200 pixels, i.e. 40 columns × 25 rows (6×8-pixel cells). Video inversion via bit 7, Oric serial attributes set per scanline. All 25 rows of the page belong to the server; the status bar lives on the 3 text rows the Oric still displays below the HIRES area.

Assembly rendering engine

6502 blits (blit_cell8 ~190 cycles per cell vs ~2,000 in C, blit_run for runs of cells, blit_cell4x2 for double height). Refresh by “dirty” spans: each modified row remembers the touched column range, and rendering is budgeted at one row per pass from the main loop, which yields as soon as a byte is waiting in reception. Costs measured in 6502 cycles (make bench-render): render pass ~151,000, realistic coloured text row ~79,000, single-cell update ~30,000 — a full page takes 2 to 4 s of rendering against ~8 s of arrival at 1200 baud.

Oric-1 and Atmos compatible

The HIRES switch detects the ROM at startup: jsr $EC33 on BASIC 1.1 (Atmos), jsr $F8E3 on BASIC 1.0 (Oric-1). On-target tests are run with both ROMs.

3. Character sets

G0 / G1 / G2

G0/G1 switching via SI/SO; G2 characters via SS2.

4. Per-cell attributes

Complete attributes

Ink colour (0-7), background colour (0-7), flash, video inverse, underline / mosaic separation, conceal, and size: normal, double height, double width, double size. A hybrid colour heuristic approximates the Minitel's per-cell colours using the Oric's serial attributes: attributes placed on empty cells with look-ahead (colour of the following text), mosaics in solid colour when the attribute matches, luminance dithering as a fallback.

5. Rendering modes (CTRL+D)

The Oric cannot colour each cell individually like the Minitel; OricTel offers three hot-swappable strategies:

ModeBehaviour
AUTO (default)Best compromise, decided line by line: attribute colours where the line allows, luminance dithering for dense multi-colour zones, white rendering for unsuitable lines.
DITHERINGAll density dithering: the brightness hierarchy of colours is preserved as textured “greyscale”.
RAWAll white on black: maximum shape legibility, no colour.

6. Connection

AT modem (the only method)

OricTel drives a Hayes modem via the ACIA 6551 at $0380 (PicoWiFiModemUSB, real or emulated by Phosphoric --serial modem/picowifi): ATZ (reset) then ATDT host:port (dialling = TCP connection). The server is chosen from the menu, so you can switch without restarting the emulator.

WiFi config from the Oric

On a real LOCI + PicoWiFiModemUSB setup, the “WiFi Config” menu configures everything from the Oric: scan (AT$SCAN) for in-range 2.4 GHz networks, selection, password entry (masked), then association (AT$SSID=/AT$PASS=/ATC1) and saving to the Pico's NVRAM (AT&W).

WebSocket bridge

orictel_bridge.py (Python asyncio) relays TCP (port 3615) to a WebSocket Minitel server (ws://3617.fr/ws). Transparent binary relay, single-client, statistics, -v mode.

Link robustness

Modem left online (Oric reset, emulator closed without hanging up): the missing “OK” after ATZ is detected, OricTel hangs up (+++, ATH) and replays ATZ before dialling. Without “CONNECT”, an explicit failure screen offers Retry / Another server / Enter anyway, instead of a blind session. Carrier loss: the modem's NO CARRIER, confirmed by 4 s of silence, opens the “CARRIER LOST” screen with “1 Reconnect” — no silent redial. Delays are counted on the VIA 6522 Timer 2, a real time base. Validated with a physical PicoWiFiModemUSB on PAVI 3617.

7. Minitel servers

ServerAddressNotes
PAVI 3617pavi.3617.fr:3617recommended, Teletel home page
MiniPavigo.minipavi.fr:516multi-service gateway
Otherfree entry host:portoption 3 of the server menu

8. Minitel keyboard

OricTel runs on the Oric-1 and Atmos. Function keys use CTRL+letter (both machines) or FUNCT+letter (Atmos only).

Minitel functionOric-1 & AtmosAtmos onlyCode sent
SendRETURNSEP $41
BackCTRL+R or UP arrowFUNCT+RSEP $42
RepeatCTRL+EFUNCT+ESEP $43
GuideCTRL+GFUNCT+GSEP $44
CancelCTRL+AFUNCT+ASEP $45
IndexCTRL+SFUNCT+SSEP $46
CorrectionDELETESEP $47
NextCTRL+NFUNCT+NSEP $48
Connect/EndCTRL+CFUNCT+CSEP $49
Left/Right arrowsLEFT/RIGHT arrowESC[D / ESC[C (PRO3 cursor mode)

Local shortcuts (send nothing to the server): CTRL+D switches the rendering mode, CTRL+L clears the screen locally, CTRL+F resets the serial link (ACIA). ESC is the escape key: in session, ESC then ESC hangs up and returns to the menu; in a menu or an input field, ESC cancels; on the main menu, ESC exits OricTel to BASIC.

9. Screen & status

Display area

Rows 0-24: the server's Videotex page (40 columns), row 0 included — OricTel no longer writes anything there, like a real Minitel. Cursor: blinking bar under the current cell when the server enables it (input fields). Splash screen at startup with an AY-3-8912 jingle.

Status bar (3 text rows below HIRES)

 C  PAVI 3617         00:12  AUTO  ESC      <- state (cyan)
ESC: quitter? ESC=menu autre=reprendre      <- messages (yellow)
^A Annul ^R Retour ^S Somm ^N Suite         <- help (white)

Inverted C = data received recently (connected), F = no data for 30 s (link probably down); then the chosen server, the session timer (mm:ss) and the current rendering mode (AUTO/TRAME/BRUT). The middle row carries messages (ESC prompt, ACIA reset), the last one the key help.

10. Technical specifications

Serial (ACIA 6551)

ACIA 6551 at the LOCI base ($0380). Registers: data $0380, status/reset $0381, command $0382, control $0383. Control $18 (1200 baud, 8N1, internal clock), command $0B (DTR, RX IRQ disabled, RTS low without TX IRQ). Pure polling of the STATUS register, no ACIA IRQ; the init and every byte access are SEI/PLP-protected (MIA constraint of the real LOCI). Non-blocking software transmit queue drained by the main loop. The LOCI firmware puts a 32-byte ring in front of the register: ~250,000 cycles of tolerance between two reads at 1200 baud. As the /DCD bit does not follow the call state on LOCI, carrier loss is detected through the NO CARRIER response.

Memory

TAP ~28 KB (CODE 25.5 KB, RODATA 2.3 KB, BSS 7.7 KB); code+data below $9800; status-bar character set $9800-$9BFF; cc65 stack $9C00-$9FFF (1 KB); HIRES framebuffer $A000-$BF3F; 3 text rows $BF68-$BFDF.

Protocol & performance

Teletel/Antiope Videotex (STUM 1B). Budget of one byte at 1200 baud: 8,333 cycles. Measured: vtx_process() ~2,600 cycles per byte, render pass ~151,000 cycles (18.8 byte-times), single-cell update ~30,000 (3.6). Validity reference: the JS emulator miedit/telenet; fidelity checked against real servers (make test-servers, PAVI 3617 and MiniPavi).

11. Build & run

make                # build orictel.tap
make dsk            # Sedoric floppy orictel.dsk (MFM_DISK, bootable)
make test           # host + target tests (Videotex, ACIA/SMC, AT modem, keyboard, UI, menus, carrier, bridge)
make fuzz           # Videotex decoder fuzzing (ASAN/UBSAN)
make coverage       # host gcov coverage
make bench-render   # HIRES rendering benchmark in 6502 cycles
make test-servers   # decoding fidelity against real servers (dongle required)
make run            # run under Phosphoric in AT modem mode
make run-loci       # physical PicoWiFiModemUSB on /dev/ttyACM*
make run-ws         # run the WebSocket bridge + the emulator
make run-dsk        # Microdisc boot of the Sedoric floppy

Prerequisites: cc65 (≥ 2.19), Python 3.8+ with websockets ≥ 12.0 (bridge only), the Phosphoric emulator (or a physical LOCI/PicoWiFiModemUSB), and the Oric ROMs (basic11b.rom for Atmos, basic10.rom for Oric-1). Test suite: 344 checks, including menu walkthroughs and an on-target measurement of the carrier-loss delay.

12. Known limitations

← Back to OricTel · Technical documentation →