Display Configuration
Cuttlefish UI talks to physical displays through a display block in your cuttlefish.config.ts. You pick a built-in display profile (or name a driver) and tell Cuttlefish which pins it’s wired to; when you build, it generates the right driver code for you.
This page covers the common profiles, the full list of configuration fields, touch input, and — for unusual displays — how to wire up a brand-new driver.
Minimal SPI example (ILI9341)
import type { CuttlefishConfig } from '@typecad/cuttlefish/api';
const config: CuttlefishConfig = {
entry: './src/app.ui',
target: 'esp32',
mcu: '@typecad/mcu-esp32',
board: '@typecad/board-esp32-devkit',
framework: '@typecad/framework-arduino',
frameworkData: { buildTarget: 'esp32:esp32:esp32' },
output: { framework: 'arduino', optimize: 'size', outDir: './out' },
display: {
profile: 'ili9341-spi',
cs: 5,
dc: 21,
rst: 22,
backlight: 17,
antialias: true,
},
};
export default config;Minimal I2C example (SSD1309 OLED)
display: {
profile: 'ssd1309-i2c',
bus: 'I2C',
address: 0x3C, // common OLED I2C address
reset: -1, // -1 if no reset pin wired
rotation: 0,
}Profile fields
| Field | Type | Description |
|---|---|---|
profile | string | Built-in profile name (e.g. "ili9341-spi") — fills in driver, width, height, colorFormat, rotation |
driver | string | Display driver id (e.g. "ili9341") — set explicitly to override the profile |
width / height | number | Display dimensions in pixels (after rotation) |
colorFormat | "rgb565" | "mono" | Color depth |
rotation | number | 0 = portrait, 1 = landscape, 2-3 = inverted |
backlight | number | Backlight pin (optional) |
cs / dc / rst | number | SPI wiring pins |
bus | string | Bus identifier ("SPI" or "I2C") |
address | number | I2C address (I2C displays) |
reset | number | Reset pin for I2C displays (-1 if unwired) |
spiFrequency | number | SPI frequency override |
colorOrder | string | Pixel color order (e.g. "bgr") |
invertDisplay | boolean | Invert panel colors |
antialias | boolean | Enable text antialiasing |
themeCss | string | Path to an extra CSS file with theme rules |
themeClass | string | Class name selecting a build-time theme variant |
scroll | { dragScale: number } | Scroll-drag tuning |
touch | object | Touch-input config (see below) |
Built-in profiles
| Profile | Driver | Dimensions | Color | Notes |
|---|---|---|---|---|
ili9341-spi | ili9341 | 320×240 | RGB565 (a compact color format) | Landscape; add touch via touch config |
st7796-spi | st7796 | 480×320 | RGB565 | ST7796S TFT; native 320×480, rotated landscape |
ssd1309-i2c | ssd1309 | 128×64 | Mono | SSD1309-class OLED over I2C |
Registered display drivers
Beyond the built-in profiles, the transpiler registers drivers you can target directly by setting driver (and width/height/colorFormat):
| Driver | Targets |
|---|---|
ili9341 | ILI9341 SPI TFT (RGB565) |
st7796 | ST7796S SPI TFT (RGB565 / RGB666) |
ssd1309 | SSD1309 OLED (1-bit mono, I2C, page-buffered) |
ssd1680 | SSD1680-class e-ink (1-bit, deferred partial refresh) |
sdl | Native desktop window (RGB888) — for development without hardware |
Touch input
Add a touch block to enable touch. Three built-in libraries are supported, plus a custom adapter path.
XPT2046_Touchscreen (SPI resistive)
touch: {
library: 'XPT2046_Touchscreen',
cs: 14,
irq: 2, // optional
calibration: { xMin: 375, xMax: 3950, yMin: 200, yMax: 3750 },
minPressure: 10,
}Adafruit_TouchScreen (analog resistive)
touch: {
library: 'Adafruit_TouchScreen',
analogPins: { xp, yp, xm, ym, rx },
calibration: { xMin, xMax, yMin, yMax },
minPressure: 10,
}Adafruit_STMPE610 (SPI or I2C capacitive)
touch: {
library: 'Adafruit_STMPE610',
cs: 14,
calibration: { xMin, xMax, yMin, yMax },
minPressure: 10,
}Custom adapter
touch: {
adapter: './my-touch-adapter',
calibration: { xMin, xMax, yMin, yMax },
minPressure: 10,
}Calibration
calibration maps raw touch-controller readings to display pixels: { xMin, xMax, yMin, yMax }. minPressure filters out feather-light touches.
⚙️ Advanced details — writing a new display driver
For drivers not in the built-in set, register an adapter at build time. The runtime contract every adapter must satisfy is the core display API:
display_init()display_fillScreen(color)display_startWrite()/display_endWrite()display_setAddrWindow(x, y, w, h)display_writePixels(pixels, count)display_partial_refresh(x, y, w, h)
Register with registerDisplayAdapter(driver, generator) and provide a DisplayProfile so the transpiler knows the dimensions and color format. For the generator interface, see the display-adapter source in the @typecad/cuttlefish package.
Next: Authoring API for the ui.* functions and the .ui file format.
On This Page