Expand description
The Fabric Terminal’s wire protocol and screen, in one place: the link between a host and the terminal board (Board B, the Nexys A7-100T) that puts a LOGOS editor on a VGA screen, takes a keyboard on the board’s USB port, and runs each program on the fabric engine beside them.
The link is one UART, its bytes framed by SLIP (RFC 1055): a frame ends with SLIP_END, and an END or
SLIP_ESC inside a frame travels as ESC + SLIP_ESC_END / SLIP_ESC_ESC. A receiver that starts
mid-frame, or loses a byte, is back in step at the next END. A frame’s first byte is its kind:
host kinds travel host → board, board kinds board → host.
The screen is text: COLS × ROWS cells of 8 × 16 pixels on 640 × 480 at 60 Hz. A cell is 16 bits —
glyph (7 bits), blink, foreground and background from the 16-colour PALETTE — addressed row << 7 | col,
so no multiply sits in the pixel path. The bottom PANEL_ROWS rows belong to the activity panel the board
draws itself from the engine’s probes; text written there is covered.
Every byte and dimension the RTL uses is filled into its templates from here by fill_verilog, and a host
that is not Rust reads table_json (fabric_terminal --table). Nothing restates a value.
Modules§
Structs§
- Cell
- One cell: its attribute and glyph bytes as they travel and as the text buffer holds them.
- Slip
Decoder - A SLIP receiver: bytes in, whole frames out. An empty frame (two
ENDs in a row) is no frame; anESCfollowed by anything butESC_END/ESC_ESCdrops the frame it is in.
Constants§
- ACTIVITY_
FIELDS board::ACTIVITY’s payload, field by field: (name, bytes each, how many), every count big-endian. The per-block and per-cell clocks are one count per block slot and per cell slot of Board B’s engine.- BAUD
- The link’s baud rate: 100 clocks per bit at the board’s 100 MHz, and FTDI’s 3 MHz base divided by 3, so both ends run it exactly.
- BOARD_
HZ - The board clock in Hz.
- CLOCKS_
PER_ PIXEL - COLS
- Text columns.
- DEL_
GLYPH - The character slot 0x7F holds.
- ENGINE_
CLKS_ PER_ BIT - ENGINE_
CLOCK_ DIVIDER - The fabric engine’s clock divider from the board clock, and its UART’s clocks per bit: the board feeds the
engine’s loader through an internal UART at
BOARD_HZ / ENGINE_CLOCK_DIVIDER / ENGINE_CLKS_PER_BITbaud. - ENGINE_
FRAME_ MAX - The most engine bytes one
host::ENGINEframe carries: the board’s engine FIFO holds one frame. - FEATURE_
ENGINE board::PONG’s feature bit for an image with the fabric engine: ENGINE frames reach an engine that answers. Without it (the screen-and-keyboard shell) ENGINE bytes are taken and dropped.- FEATURE_
SMALL board::PONG’s feature bit for an image with the small-text plane andhost::WINDOW.- FEATURE_
TOTALS board::PONG’s feature bit for an image that keeps the run’s totals:host::TOTALSis answered.- FONT8_
ROWS - The small font: glyph
g’s rowris rowFONT8_ROWS[r]ofgin the 8×16 font — the rows that keep its round letters round, its digits whole and its box-drawing lines joined from one small row to the next. - GLYPHS
- Glyphs in the font ROM: a cell’s glyph field is 7 bits.
- GLYPH_
ROWS - Glyph height in pixels (width is 8).
- HEAT
- The heat ramp a tile or square is painted with, by level: level
kmeans the block or cell ran between 2^(k-1) and 2^k - 1 engine cycles in the last frame (level 0: not at all) — a frame holds at mostpanel_frame_samplesengine cycles, so 14 is the hottest a frame reaches. Dark blue through cyan, green, yellow and orange to red. - H_
TIMING - 640 × 480 at 60 Hz: (visible, front porch, sync, back porch) per axis in pixels / lines, sync active low, one pixel per 4 board clocks (25 MHz; monitors lock to it within the standard’s 0.7% of 25.175 MHz).
- PALETTE
- The 16 colours a cell can name, as the board’s 4-bit-per-channel DAC drives them (0xRGB), in CGA order.
- PANEL_
BLOCK_ COL - PANEL_
BLOCK_ ROW - PANEL_
BLOCK_ TILE - PANEL_
CELL_ COL - PANEL_
CELL_ ROW - PANEL_
CYCLES_ COL - PANEL_
DIGIT - PANEL_
GAUGE_ UNLIT - PANEL_
HEAP_ COL - PANEL_
HEAP_ LIT - PANEL_
LABEL_ ROW - PANEL_
OUTLINE - The panel’s other colours (0xRGB): the outline of the tile or square the engine is in, the cycle digits, and the gauges’ lit and unlit segments. Everything else in a panel region is black.
- PANEL_
ROWS - Rows at the bottom that the activity panel draws over.
- PANEL_
STACK_ COL - PANEL_
STACK_ LIT - PANEL_
TITLE_ ROW - The activity panel, drawn by the board from the fabric engine’s probes over the bottom
PANEL_ROWSrows. The host writes the panel’s text (title, labels) as ordinary cells; the board paints its graphics over the cells named here, every frame, with nothing from the host: - PONG_
FIELDS board::PONG’s payload, a byte each in this order; a two-byte count is high byte first.- PS2_
FRAMING_ ERROR - A PS/2 frame whose start bit was not 0 or stop bit not 1.
- PS2_
NO_ ACK - A host-to-device byte the device never acknowledged.
- PS2_
PARITY_ ERROR - A PS/2 byte whose odd parity did not hold.
- ROWS
- Text rows.
- SLIP_
END - SLIP frame delimiter.
- SLIP_
ESC - SLIP escape.
- SLIP_
ESC_ END - An
ENDinside a frame, afterESC. - SLIP_
ESC_ ESC - An
ESCinside a frame, afterESC. - SMALL_
COLS - SMALL_
FIRST_ ROW - The small-text plane: text-buffer rows
SMALL_FIRST_ROW..SMALL_FIRST_ROW + SMALL_ROWS, of which columns0..SMALL_COLShold cells. PUT, FILL and READ address them like any row;host::WINDOWputs them on screen. - SMALL_
ROWS - TOTALS_
FIELDS board::TOTALS’s payload, field by field, asACTIVITY_FIELDSis laid out.- UI_
GLYPHS - The characters the font holds below the printable range, slot
iholding characteri: light and double box lines, blocks and shades, arrows, markers and a tick — what a terminal UI draws with. Slots 0x20–0x7E are ASCII and slot 0x7F holdsDEL_GLYPH. A host maps a Unicode character to its slot by this table, andscripts/dev/gen-terminal-font.pybuilds the font ROM by it. - VERSION
- The protocol’s version, as
board::PONGreports it. - V_
TIMING
Functions§
- activity_
bytes - The length of
board::ACTIVITY’s payload. - cell_
address - A text-buffer address:
row << 7 | col. - clocks_
per_ bit - Clocks per UART bit on the board for
BAUD. - fill_
verilog - Fill a terminal Verilog template from this module:
__V_<NAME>__becomes a byte as a Verilog literal (8'hC0),__X_<NAME>__the hex a comment quotes (0xC0),__N_<NAME>__a decimal number,__C_<NAME>__a colour (12'hFFF),__PALETTE_CASE__the palette ascasearms (4'd1: palette = 12'h00A;),__HEAT_CASE__the heat ramp the same way, and__DIGIT_ROM_CASE__the font’s digit glyphs keyed{digit, row}. Panics on a placeholder this module does not define, so a template cannot name a value nobody owns. - glyph_
slot - The font slot that draws
ch: ASCII as itself,UI_GLYPHSandDEL_GLYPHby their slots, anything else as?. - heat_
level - The heat level a count of engine clocks paints: its bit length.
- panel_
frame_ samples - The most engine clocks one frame of the activity panel can count: snapshots are a frame apart on the engine’s
clock, so a frame’s counts span a frame’s board clocks over
ENGINE_CLOCK_DIVIDER, plus the one sample a snapshot can slip by. - slip_
encode - One frame as SLIP puts it on the wire: the escaped bytes, then
END. - table_
json - The whole protocol as JSON, for a host that is not Rust.
- totals_
bytes - The length of
board::TOTALS’s payload. - verilog_
numbers - The integer parameters the RTL takes from here:
__N_<NAME>__becomes the decimal number.