Overview
Thelib/ui library is a pure rendering layer that draws OSSM screens into a U8g2 buffer. It has no hardware dependencies, no FreeRTOS, no mutexes — it takes a u8g2_t* pointer and draws pixels. Thread safety and display I/O are handled by the display service.
This separation means the library can run on native (x86) for automated visual testing without an ESP32.
Dependencies: U8g2, QRCode
Source: Software/lib/ui/src/
TextPage
TextPage is the primary struct for content-driven screens. It covers help pages, error screens, update status, WiFi setup, pairing — anything that’s mostly text with optional QR codes.
Rendering order
drawTextPage() renders in this order:
- Clear the full screen (header + page + footer)
- QR code — bottom-right corner, reduces available text width
- Title — bold font, followed by a horizontal separator line
- Subtitle — tries medium font first; falls back to bold; splits across two lines if still too wide
- Body — word-wrapped with
drawWrappedText()if a title is present; centered title-style (drawStr::title) if body is the only field - Bottom text — fixed at y=62
- Scroll indicator — right-edge scrollbar if
scrollPercent >= 0
Usage
Predefined pages
TextPages.h defines static TextPage instances in the ui::pages namespace. These reference strings from Strings.h:
Example definition:
Strings
All UI strings live inStrings.h under the ui::strings namespace. They are stored in flash using PROGMEM:
Progmem.h defines PROGMEM as a no-op on non-Arduino platforms, so strings compile on both ESP32 and native test builds.
Categories
Pattern arrays
Stroke engine pattern names and descriptions are indexed arrays:Menu items
MenuItems.h maps Menu:: enum values to display strings:
Images and icons
Icons (font glyphs)
Status icons use the Siji icon font. Glyphs are defined inDisplayConstants.h:
drawHeaderIcons() renders WiFi and BLE status in the top-right corner of the screen. Error states overlay additional pixels (exclamation marks) on the base glyph.
Logos (XBM bitmaps)
Logos arePROGMEM XBM byte arrays in Logos.h:
RDLogo— Research & Desire, 57x50 pixelsKMLogo— Kinky Makers, 50x50 pixels
LogoData struct and drawLogo():
Hello animation
HelloAnimation.h contains precomputed Y-position frames for the “OSSM” boot animation. Each frame specifies per-letter Y offsets:
drawHelloFrame() renders a single frame. The test suite stitches all frames into a GIF.
Other draw functions
The full rendering API (ui.h):
Helper namespaces in
DrawExtensions.h:
drawStr::centered()— horizontally centered textdrawStr::multiLine()— word-wrapped multi-line text with UTF-8 supportdrawStr::title()— bold centered text at fixed positiondrawShape::scroll()— scrollbar indicatordrawShape::settingBar()— labeled vertical bar with fill leveldrawShape::settingBarSmall()— compact vertical bar (no label)
Testing and visual output
The display library has native tests that render every screen variant and export images for visual review.Running tests
ImageMagick (
magick) must be installed for PNG conversion. Without it, PBM files are still generated but PNGs are skipped.How it works
- Tests create a software-only U8g2 SSD1306 128x64 display (no hardware, no-op I2C)
- Each test calls
ui::draw*()functions to render into the buffer savePBM()writes the buffer as a PBM P4 bitmap- After all tests complete, ImageMagick converts PBM to PNG (inverted colors, 400% scale)
- Hello animation frames are stitched into a GIF

