TERM¶
Terminal
Introduction¶
A Picocomputer program reads and writes text through stdin,
stdout, and stderr, the standard streams of C. printf()
prints to the console and fgets() reads a line from it, as in any C
program. The streams are not tied to one screen and one keyboard. On an
RP6502-PICO, a user can work with the same program from a VGA monitor
and a keyboard, from a USB serial terminal, and over telnet, all at
once. The RP6502-EMU can also connect the streams to the stdin,
stdout, and stderr of the computer that runs it.
This page covers three closely related parts. The console manifold connects the streams to the terminals. The line editor lets the user edit a line before pressing Enter, with no editing code in the program, and a program can keep running while the user types. The terminal of the VGA system draws the console, and its escape sequences let a program move the cursor, color its text, and draw boxes.
Console Manifold¶
A terminal is a device that a user types into and reads from. The
console is the main terminal, connected to stdin, stdout,
stderr, CON:, and TTY:. On an RP6502-PICO, the monitor
also runs on the console, for configuration and for loading ROMs.
Several terminals can be attached to the console at once, and the machine combines them into one console. This is the console manifold. Input from every terminal goes to the console, and the output of the console goes to every terminal.
Every machine has the VGA terminal with a keyboard. The other terminals depend on the machine:
RP6502-PICO. A terminal program on another computer connects to the USB port of the VGA module as a USB serial terminal. When the RIA is a Pi Pico 2 W, a telnet client connects over the network as a telnet terminal. Console on the RP6502-PICO page describes both.
RP6502-EMU. The emulator connects the console to the
stdin,stdout, andstderrof the computer that runs it. Its options choose how, and In a Toolchain on the RP6502-EMU page describes them. When VS Code runs the emulator,stdoutandstderrappear in the Debug Console of VS Code.RP6502-FPGA and RP6502-WEB. The VGA terminal with a keyboard is the only terminal.
Read Line¶
A cooked read returns a complete line. The user has edited freely with backspace, arrow keys, and optionally command completion and history; the editor flushes the line when Enter is pressed. A raw read returns bytes as they arrive, keystroke by keystroke, with no echo and no editing. The line editor of the RIA implements cooked input.
A modern operating system layers canonical input and translated output over something configurable like termios. A full termios is too heavy for an 8-bit system, so the two modes worth having arrive as separate device names instead.
Reading stdin is cooked and blocks until the user presses Enter.
stdout and stderr block too, inserting a carriage return before
any newline that lacks one; all of the data is always sent, and a write
blocks until it has fully drained into the output FIFOs. That is what a
C programmer expects, and a poor fit for a multitasking 6502 program.
Two alternate file paths offer non-blocking variants of the same
channels:
CON:— non-blocking cooked input.read()returns 0 while the user is still editing and returns the full newline-terminated line once the editor flushes. Writes may send less than you asked for.TTY:— non-blocking raw input, with no canonical input and no newline translation.read()returns whatever bytes are queued. This is what the RIA TX and RX registers provide, packaged as stdio.
CON: is locked to file descriptor 3 and TTY: to file descriptor
4, and neither can be closed. A second open returns the same file
descriptor as the first, and a close succeeds as a no-op.
Terminal Size¶
A program that fits its output to the console, such as MS-BASIC, needs the width and the height of the console. At the start of each line that the line editor reads, it asks the terminals for the size with a Cursor Position Report (CPR) sequence. After the line editor reads a line, the program gets the size from RIA_ATTR_RLN_WIDTH and RIA_ATTR_RLN_HEIGHT. The monitor of an RP6502-PICO fits its output to the same size.
The question goes to every terminal on the console manifold, so the size is right only when one terminal answers. On an RP6502-PICO, the VGA terminal stops answering while a USB serial or telnet terminal is connected. When a USB serial terminal and a telnet terminal are both connected and both answer, the line editor might get the wrong size. If the word wrap or the paging of a program looks wrong, check which terminals are connected.
A program that is built for a fixed size can set the size instead. Write non-zero values to RIA_ATTR_RLN_WIDTH and RIA_ATTR_RLN_HEIGHT. With both set, the line editor does not ask the terminals. Write 0 to go back to detection. Both attributes return to 0 when the ROM stops.
Non-blocking Read Line¶
Between the activating read and the line flush, the application can inspect and modify the editor’s state. That is what makes features like history recall, tab completion, and multi-field form navigation possible. The hooks are RLN_LASTKEY, RLN_PEEK, and RLN_POKE.
The basic pattern:
Open the channel.
open("CON:", O_RDWR)returns a file descriptor.Set the input cap (optional). Write
RIA_ATTR_RLN_LENGTH. Different prompts, or different fields in a form, can use different caps. The default is 254.Pin the terminal size (optional). Write
RIA_ATTR_RLN_WIDTHandRIA_ATTR_RLN_HEIGHTwhen the layout is built for a fixed canvas. See Terminal Size.Loop on ``read()`` until the line flushes.
The first call always returns 0 and activates the editor at the current cursor position and SGR state. Position the cursor before this read.
A non-zero return means the line is complete. Pull it whole with a buffer at least
RIA_ATTR_RLN_LENGTH+ 1 bytes long, or drain it in fragments until you see the newline.On the first pass after activation, call
ria_rln_poke()to pre-load any text you want to appear in the line. The poked bytes are echoed by the editor as if the user had typed them.Optionally check for Ctrl-C via
RIA_ATTR_SIGINTor the RIA SIGINT IRQ. To leave cooked input cleanly, poke\x03to print a visible^C, or poke\rto flush silently. Then wait forread()to return the line.ria_rln_lastkey()reports the last keystroke and whether the editor consumed it as an editing action. Whenaction == 0the editor passed the key through. That is the application’s chance to handle Tab, function keys, arrow keys for history or form navigation, and any other keys it claims. The line editor keeps no history while a program reads a line, so Up and Down always haveaction == 0. Callria_rln_peek()to get the current input text and cursor position. Respond by poking literal characters or ANSI sequences (CUF,CUB,ICH,DCH) back into the editor.
Read ``RIA_ATTR_RLN_WIDTH`` and ``RIA_ATTR_RLN_HEIGHT`` to obtain the dynamic size after the read line completes.
A poke edits as typing does, except that a control byte ends the input,
as RLN_POKE describes. Poke \r to pull the
buffer out without the user pressing Enter, for example when Tab should
jump to the next field of a form. The editor
flushes through read() like any other line, and the application can
move on, entering the next field with a fresh read() and
ria_rln_poke() to restore its prior contents.
Terminal¶
The VGA system includes a color terminal that draws the console. Mode 0 on the VGA page describes where the terminal goes on the canvas, its 80 or 40 columns, and how a picture on a plane behind it shows through.
Like the Linux console, the terminal identifies itself as a VT102 and implements most of the escape sequences of the Linux console, with additions from ECMA-48, xterm, later DEC terminals, kitty, and SyncTERM. To Do lists where it falls short, and the tables below list the sequences.
Text is in the 8-bit code page of RIA_ATTR_CODE_PAGE, one byte for each character. The terminal does not decode UTF-8.
Some older terminals could not keep up at full speed, so a program sent padding or waited after a slow operation such as a screen clear, or paused when the terminal sent XOFF. This terminal keeps up with the console at full speed, even through a screen clear, so a program needs no flow control, padding, or delays.
To Do¶
These sequences of the VT102 and the Linux console are missing or work differently. Each one is on the to-do list.
VT102:
FF (
0x0C) clears the screen and homes the cursor. A VT102 moves the cursor down a line, as LF does, and so do the Linux console and xterm.Insert mode (
CSI 4 h) and newline mode (CSI 20 h), the ECMA-48 modes thatCSI handCSI lset without a?, are missing. A program that expects a VT102 and inserts text with insert mode overwrites text instead. ICH (CSI n @) inserts characters.VT (
0x0B), which moves the cursor down a line, as LF does.DECID (
ESC Z), which asks for the same reply as Primary DA.Double-height and double-width lines (
ESC # 3toESC # 6), and DECALN (ESC # 8), which fills the screen with E.Cursor-key mode (
?1) and the keypad modes (ESC =andESC >), which change what the arrow keys and the keypad send.Reverse video for the whole screen (
?5).Keyboard autorepeat (
?8) and the keyboard LEDs (CSI q).
Linux console:
The null and user mappings (
ESC ( UandESC ( K).The palette sequences (
OSC PandOSC R).Mouse reporting (
?9and?1000).HPR (
CSI a) and VPR (CSI e), which move the cursor right and down relative to its position.ED 3 (
CSI 3 J), which erases the scrollback.SGR 10-12, which select the font mapping.
The private sequences of Linux (
CSI ]).
kitty:
SGR 59, which resets the underline color that SGR 58 sets.
C0 Control Codes¶
NUL (0x00) and BEL (0x07) are silently accepted no-ops.
^ |
C0 |
Abbr |
Name |
Effect |
|---|---|---|---|---|
^H |
0x08 |
BS |
Backspace |
Move cursor left one cell. |
^I |
0x09 |
HT |
Tab |
Move cursor right to next tab stop (default every 8 columns); clamps at right margin. |
^J |
0x0A |
LF |
Line Feed |
Move down one row; scroll if at bottom margin. |
^L |
0x0C |
FF |
Form Feed |
Clear screen and home cursor. |
^M |
0x0D |
CR |
Carriage Return |
Move cursor to column 1. |
^N |
0x0E |
SO |
Shift Out |
Switch to the alternate charset slot (G1). See Charset Designation. |
^O |
0x0F |
SI |
Shift In |
Switch to the primary charset slot (G0). See Charset Designation. |
^X |
0x18 |
CAN |
Cancel |
Abort an in-progress escape sequence (silent). |
^Z |
0x1A |
SUB |
Substitute |
Abort an in-progress escape sequence and print |
^[ |
0x1B |
ESC |
Escape |
Start an escape sequence. |
Fe Escape Sequences¶
Code |
Abbr |
Name |
Effect |
|---|---|---|---|
ESC c |
RIS |
Reset to Initial State |
Hard reset: SGR, cursor, alt screen, tab stops, colors. |
ESC D |
IND |
Index |
Move cursor down one row; scroll at bottom margin. |
ESC E |
NEL |
Next Line |
CR + IND. |
ESC M |
RI |
Reverse Index |
Move cursor up one row; scroll at top margin. |
ESC H |
HTS |
Horizontal Tab Set |
Set a tab stop at the current column. |
ESC 7 |
DECSC |
Save Cursor |
Save cursor position, SGR, charset state, and origin mode. |
ESC 8 |
DECRC |
Restore Cursor |
Restore the state saved by DECSC; homes if no save. |
ESC [ |
CSI |
Control Sequence Inducer |
Begins a CSI sequence (see CSI subsections below). |
ESC ] |
OSC |
Operating System Command |
Begins an OSC sequence. See OSC Sequences. |
ESC ( |
— |
Load primary charset |
Load a font into the G0 slot. See Charset Designation. |
ESC ) |
— |
Load alternate charset |
Load a font into the G1 slot. See Charset Designation. |
ESC # c |
— |
DEC line attribute |
Recognized; one byte swallowed (DECALN not implemented). |
ESC N |
SS2 |
Single Shift Two |
Recognized; one byte swallowed. No SS2 commands implemented. |
ESC O |
SS3 |
Single Shift Three |
Recognized; one byte swallowed. No SS3 commands implemented. |
Charset Designation¶
The terminal keeps two character-set slots, named G0 and G1. You load a font into each slot independently, then switch which slot is active at any time. This lets you mix regular text with the DEC line-drawing characters (corners, tees, and lines) without an escape sequence per character. Load the line-drawing font into G1 once, then toggle between G0 and G1 as you go.
Load a font into a slot. The byte after the sequence selects which font to load:
Sequence |
Font loaded |
|---|---|
ESC ( B |
US ASCII (default) into G0. |
ESC ( 0 |
DEC Special Graphics into G0. |
ESC ) B |
US ASCII (default) into G1. |
ESC ) 0 |
DEC Special Graphics into G1. |
Any other byte after ESC ( or ESC ) is silently consumed.
Switch the active slot. Send one byte:
Code |
Effect |
|---|---|
SI (^O) |
Make G0 the active charset. |
SO (^N) |
Make G1 the active charset. |
Both slots are US ASCII at startup, so until you load something into G1 you can ignore this entire feature.
CSI — Cursor Movement¶
CSI sequences default missing numbers to 0. Some functions, especially cursor movement, treat 0 as 1 to remain useful without parameters.
Code |
Abbr |
Name |
Effect |
|---|---|---|---|
CSI n A |
CUU |
Cursor Up |
Move n rows up. |
CSI n B |
CUD |
Cursor Down |
Move n rows down. |
CSI n C |
CUF |
Cursor Forward |
Move n columns right. |
CSI n D |
CUB |
Cursor Back |
Move n columns left. |
CSI n E |
CNL |
Cursor Next Line |
Move n rows down, to column 1. |
CSI n F |
CPL |
Cursor Previous Line |
Move n rows up, to column 1. |
CSI n G |
CHA |
Cursor Horizontal Absolute |
Move to column n (1-indexed). |
CSI n ` |
HPA |
Horizontal Position Absolute |
Alias of CHA. |
CSI n d |
VPA |
Vertical Position Absolute |
Move to row n (1-indexed); column unchanged. |
CSI n ; m H |
CUP |
Cursor Position |
Move to row n, column m (1-indexed). |
CSI n ; m f |
HVP |
Horizontal Vertical Position |
Alias of CUP. |
CSI s |
SCP |
Save Cursor Position |
SCO-style: save cursor x / y and origin mode. |
CSI u |
RCP |
Restore Cursor Position |
Restore the state saved by SCP. |
CSI — Editing¶
Code |
Abbr |
Name |
Effect |
|---|---|---|---|
CSI n @ |
ICH |
Insert Character |
Insert n blank cells; line shifts right. |
CSI n P |
DCH |
Delete Character |
Delete n cells; line shifts left. |
CSI n X |
ECH |
Erase Character |
Erase n cells in place; cursor unchanged. |
CSI n L |
IL |
Insert Line |
Insert n blank lines at cursor row. |
CSI n M |
DL |
Delete Line |
Delete n lines at cursor row. |
CSI — Erase¶
Code |
Abbr |
Name |
Effect |
|---|---|---|---|
CSI n J |
ED |
Erase in Display |
|
CSI n K |
EL |
Erase in Line |
|
CSI — Scrolling and Margins¶
Code |
Abbr |
Name |
Effect |
|---|---|---|---|
CSI n S |
SU |
Scroll Up |
Scroll viewport up n lines. |
CSI n T |
SD |
Scroll Down |
Scroll viewport down n lines. |
CSI t ; b r |
DECSTBM |
Set Top / Bottom Margins |
Define vertical scroll region (1-indexed); homes the cursor. |
CSI — Tabs¶
Tab stops are also set with ESC H (HTS) and reset by RIS.
Code |
Abbr |
Name |
Effect |
|---|---|---|---|
CSI n I |
CHT |
Cursor Horizontal Tab |
Advance n tab stops. |
CSI n Z |
CBT |
Cursor Backward Tab |
Retreat n tab stops. |
CSI n g |
TBC |
Tab Clear |
|
CSI — Status and Reports¶
Code |
Abbr |
Name |
Effect |
|---|---|---|---|
CSI n c |
DA |
Primary Device Attributes |
Responds with |
CSI > n c |
— |
Secondary DA |
Recognized; no reply. |
CSI = n c |
— |
Tertiary DA |
Recognized; no reply. |
CSI 5 n |
DSR |
Device Status Report |
Responds with |
CSI 6 n |
CPR |
Cursor Position Report |
Responds with |
CSI n t |
— |
Window manipulation |
Silently absorbed (no window manager). |
CSI — Reset and Cursor Style¶
Code |
Abbr |
Name |
Effect |
|---|---|---|---|
CSI ! p |
DECSTR |
Soft Terminal Reset |
Reset SGR, cursor, origin mode, autowrap, charset, and saved cursor. Preserves OSC colors, tab stops, and screen contents. |
CSI Ps SP q |
DECSCUSR |
Set Cursor Style |
0 = host default, 1 / 2 = block, 3 / 4 = underline, 5 / 6 = bar. |
DEC Private Modes¶
Set with CSI ?n h, reset with CSI ?n l. Multiple modes
may be combined in one sequence (semicolon-separated parameters).
Mode 33 is for ANSI art. In the text mode of an IBM PC, one bit of the attribute byte of each character makes it blink. Some ANSI art was drawn with blinking turned off in the display adapter, so that bit brightened the background instead and gave 16 background colors. This is called iCE color. Mode 33, from SyncTERM, makes SGR 5 and 6 brighten the background in the same way.
n |
Abbr |
Name |
Effect |
|---|---|---|---|
6 |
DECOM |
Origin Mode |
Cursor addressing relative to scroll region; homes the cursor on change. |
7 |
DECAWM |
Autowrap |
Wrap at right margin. |
12 |
AT&T 610 |
Cursor visibility |
Set: show cursor. Reset: hide cursor. |
25 |
DECTCEM |
Cursor visibility |
Set: show cursor. Reset: hide cursor. |
33 |
— |
iCE colors |
Set: SGR 5 / 6 brightens background (iCE colors). Reset: SGR 5 / 6 means blink (default). |
47 |
— |
Legacy alt screen |
Swap to / from the alt screen buffer. |
1047 |
— |
Alt screen |
Swap; clears the alt buffer on exit. |
1049 |
— |
Alt screen + save |
Modern app default: saves cursor on entry, swaps, clears on entry, restores cursor on exit. |
SGR Parameters¶
Send multiple parameters separated by ;. CSI m with no
parameters resets all attributes.
n |
Name |
Effect |
|---|---|---|
0 |
Reset |
White (7) foreground, black (0) background, all attributes off. |
1 |
Bold |
Brighter foreground (colors 0-7 → 8-15). |
2 |
Faint |
Halve foreground channel brightness. |
3 |
Italic |
Only ASCII 32-127. |
4 |
Underline |
— |
5 |
Blink (slow) |
Blinks foreground. With iCE colors mode ( |
6 |
Blink (rapid) |
Same as 5 at double the blink rate. |
7 |
Reverse video |
Swap foreground and background. |
8 |
Conceal |
Foreground = background. |
9 |
Strikethrough |
— |
21 |
Double underline |
Per Linux console. |
22 |
Normal intensity |
Cancels both bold (1) and faint (2). |
23 |
Italic off |
— |
24 |
Underline off |
Clears both single and double underline. |
25 |
Blink off |
Clears the blink attribute. |
27 |
Reverse off |
— |
28 |
Conceal off |
— |
29 |
Strikethrough off |
— |
30-37 |
Set foreground color |
Colors 0-7. |
38 |
Set foreground color |
|
39 |
Default foreground |
Color 7 (white). |
40-47 |
Set background color |
Colors 0-7. |
48 |
Set background color |
|
49 |
Default background |
Color 0 (transparent black). |
53 |
Overline |
— |
55 |
Overline off |
— |
58 |
Underline color |
Same format as 38. |
90-97 |
Bright foreground |
Colors 8-15. |
100-107 |
Bright background |
Colors 8-15. |
OSC Sequences¶
Operating System Command sequences set dynamic terminal colors.
The color argument must be #rrggbb; other xterm color formats
(X11 names, rgb:) are not accepted. Each sequence is
terminated by BEL (0x07) or ST (ESC \).
Code |
Effect |
|---|---|
OSC 10 ; #rrggbb ST |
Set default foreground color. |
OSC 11 ; #rrggbb ST |
Set default background color. |
OSC 12 ; #rrggbb ST |
Set cursor color. |
OSC 110 ST |
Reset default foreground color. |
OSC 111 ST |
Reset default background color. |
OSC 112 ST |
Reset cursor color. |