Pure renderingbibliotheek voor OSSM-weergaveschermen — tekstpagina's, tekenreeksen, pictogrammen en visuele tests
Overzicht
De lib/ui-bibliotheek is een pure renderinglaag die OSSM-schermen in een U8g2-buffer tekent. Ze heeft geen hardwareafhankelijkheden, geen FreeRTOS en geen mutexen - ze heeft alleen een u8g2_t*-aanwijzer nodig en tekent pixels. Threadveiligheid en weergave-I/O worden afgehandeld door de displayservice.
Deze scheiding betekent dat de bibliotheek native op x86 kan draaien voor geautomatiseerd visueel testen zonder ESP32.
Afhankelijkheden: U8g2, QRCode
Bron: Software/lib/ui/src/
TextPage
TextPage is de primaire structuur voor inhoudgestuurde schermen. Ze omvat helppagina's, foutschermen, updatestatus, WiFi-configuratie, koppelen - alles wat voornamelijk uit tekst bestaat met optionele QR-codes.
struct TextPage {
const char* title = nullptr;
const char* subtitle = nullptr;
const char* body = nullptr;
const char* bottomText = nullptr;
const char* qrUrl = nullptr;
uint8_t qrVersion = 3;
int qrScale = 2;
bool centerBody = false;
int scrollPercent = -1;
};Alle velden zijn optioneel. Stel alleen in wat u nodig heeft.
| Veld | Type | Doel |
|---|---|---|
title | const char* | Vetgedrukte tekst bovenaan, met een scheidingslijn eronder |
subtitle | const char* | Middelgrote of vetgedrukte tekst onder de titel; wordt automatisch gesplitst als deze te breed is |
body | const char* | Tekst met automatische regelafbreking; ondersteunt \n als regeleinde |
bottomText | const char* | Vastgemaakt aan de onderkant van het scherm (y=62) |
qrUrl | const char* | QR-code rechtsonder weergegeven; beperkt de tekstbreedte |
qrVersion | uint8_t | QR-versie (standaard 3) |
qrScale | int | QR-pixelschaal (standaard 2) |
centerBody | bool | De hoofdtekst centreren |
scrollPercent | int | Scrollindicator weergeven (0–100); -1 om te verbergen |
Rendervolgorde
drawTextPage() rendert in deze volgorde:
- Het volledige scherm wissen (koptekst + pagina + voettekst)
- QR-code — rechterbenedenhoek, verkleint de beschikbare tekstbreedte
- Titel — vetgedrukt lettertype, gevolgd door een horizontale scheidingslijn
- Ondertitel — probeert eerst het medium lettertype; valt terug naar vet; wordt over twee regels gesplitst als deze nog te breed is
- Hoofdtekst — met automatische regelafbreking via
drawWrappedText()als er een titel aanwezig is; gecentreerde titelstijl (drawStr::title) als de hoofdtekst het enige veld is - Onderste tekst — vast op y=62
- Scrollindicator — schuifbalk aan de rechterkant als
scrollPercent >= 0
Gebruik
// Use a predefined page
ui::drawTextPage(&u8g2, ui::pages::helpPage);
// Or build one inline
ui::TextPage page;
page.title = "Custom Title";
page.body = "Some content\nwith line breaks";
page.scrollPercent = 50;
ui::drawTextPage(&u8g2, page);Voorgedefinieerde pagina's
TextPages.h definieert statische TextPage-instanties in de ui::pages-naamruimte. Deze verwijzen naar tekenreeksen uit Strings.h:
| Pagina | Gebruikte velden |
|---|---|
helpPage | title, body, bottomText, qrUrl |
updateCheckingPage | body |
noUpdatePage | body, bottomText |
updatingPage | title, body |
errorPage | title |
wifiDisconnectedPage | title, body, bottomText, qrUrl |
wifiConnectedPage | title, body, bottomText |
pairingPage | title, body |
Voorbeelddefinitie:
static const TextPage helpPage = {
.title = helpTitle,
.body = helpBody,
.bottomText = helpBottom,
.qrUrl = helpQr,
};Tekenreeksen
Alle UI-tekenreeksen bevinden zich in Strings.h onder de naamruimte ui::strings. Ze worden met PROGMEM in flash opgeslagen:
static const char helpTitle[] PROGMEM = "Get Help";
static const char helpBody[] PROGMEM = "On Discord,\nor GitHub";Progmem.h definieert PROGMEM als een no-op op niet-Arduino-platforms, zodat tekenreeksen zowel op ESP32 als in native testbuilds worden gecompileerd.
Categorieën
| Categorie | Voorbeelden |
|---|---|
| Branding | researchAndDesire, kinkyMakers |
| Algemene gebruikersinterface | error, homing, idle, restart, settings, skip |
| Menu / modi | simplePenetration, strokeEngine, streaming, pairing, update, wifi |
| Bewegingsbediening | speed, stroke, sensation, depth, buffer, accel, max |
| Waarschuwingen | speedWarning, homingTookTooLong, strokeTooShort |
| Hulp | helpTitle, helpBody, helpBottom, helpQr |
| Update | updateChecking, noUpdateBody, updatingTitle, updatingBody |
| WiFi | wifiSetup, wifiBody, wifiBottom, wifiQr, wifiConnected |
| Koppelen | pairingTitle, pairingBody |
| Patronen | patternName0–patternName6, patternDesc0–patternDesc6 |
Patroonarrays
Namen en beschrijvingen van Stroke Engine-patronen zijn geïndexeerde arrays:
static const char* const strokeEngineNames[7] = {
patternName0, patternName1, patternName2,
patternName3, patternName4, patternName5,
patternName6,
};
static const char* const strokeEngineDescriptions[7] = {
patternDesc0, patternDesc1, patternDesc2,
patternDesc3, patternDesc4, patternDesc5,
patternDesc6,
};Menu-items
MenuItems.h wijst de Menu::-enumwaarden toe aan weergavetekenreeksen:
static const char* menuStrings[Menu::NUM_OPTIONS] = {
ui::strings::simplePenetration, ui::strings::strokeEngine,
ui::strings::streaming, ui::strings::pairing,
ui::strings::update, ui::strings::wifiSetup,
ui::strings::helpTitle, ui::strings::restart,
};Afbeeldingen en iconen
Pictogrammen (lettertypeglyphs)
Statuspictogrammen gebruiken het pictogramlettertype Siji. Glyphen worden gedefinieerd in DisplayConstants.h:
namespace IconGlyph {
constexpr uint16_t WIFI_OFF = 0xe218;
constexpr uint16_t WIFI_CONNECTING = 0xe219;
constexpr uint16_t WIFI_CONNECTED = 0xe21a;
constexpr uint16_t WIFI_ERROR = 0xe21b;
constexpr uint16_t BLE_CONNECTED = 0xe00b;
constexpr uint16_t BLE_SMALL = 0xe0b0;
constexpr uint16_t EXCLAMATION = 0xe0b3;
}drawHeaderIcons() geeft de WiFi- en BLE-status weer in de rechterbovenhoek van het scherm. Foutstatussen leggen extra pixels (uitroeptekens) over het basispictogram heen.
Logo's (XBM-bitmaps)
Logo's zijn PROGMEM XBM byte-arrays in Logos.h:
RDLogo— Research & Desire, 57x50 pixelsKMLogo— Kinky Makers, 50x50 pixels
Ze worden getekend via de LogoData-structuur en drawLogo():
struct LogoData {
const char* title;
const uint8_t* bitmap;
int w, h, x, y;
};Hello-animatie
HelloAnimation.h bevat frames met vooraf berekende Y-posities voor de "OSSM"-opstartanimatie. Elk frame specificeert Y-offsets per letter:
struct HelloFrame {
int heights[4]; // Y position for O, S, S, M
};drawHelloFrame() rendert een enkel frame. De testsuite voegt alle frames samen tot een GIF.
Andere tekenfuncties
De volledige weergave-API (ui.h):
| Functie | Doel |
|---|---|
drawTextPage() | Render een TextPage-structuur |
drawMenu() | Scrollbaar menu met selectiemarkering |
drawPlayControls() | Snelheids-/slag-/sensatiebalken voor bedieningsmodi |
drawPreflight() | Veiligheidscontrole vóór beweging (snelheidsknop op nul) |
drawHeaderIcons() | WiFi- en BLE-statuspictogrammen |
drawQR() | Op zichzelf staande QR-code |
drawHelloFrame() | Eén frame van de opstartanimatie |
drawLogo() | XBM-logo met titel |
Helpernaamruimten in DrawExtensions.h:
drawStr::centered()— horizontaal gecentreerde tekstdrawStr::multiLine()— tekst met meerdere regels en automatische regelafbreking, met UTF-8-ondersteuningdrawStr::title()— vetgedrukte, gecentreerde tekst op een vaste positiedrawShape::scroll()— schuifbalkindicatordrawShape::settingBar()— gelabelde verticale balk met vulniveaudrawShape::settingBarSmall()— compacte verticale balk (geen label)
Testen en visuele output
De weergavebibliotheek beschikt over native tests die elke schermvariant weergeven en afbeeldingen exporteren voor visuele beoordeling.
Testen uitvoeren
pio test -e test -f test_displayImageMagick (magick) moet worden geïnstalleerd voor PNG-conversie. Zonder dit worden er nog steeds PBM-bestanden gegenereerd, maar worden PNG's overgeslagen.
Hoe het werkt
- Tests creëren een volledig softwarematig U8g2 SSD1306 128x64-display (geen hardware, no-op-I2C)
- Elke test roept
ui::draw*()-functies op om in de buffer te renderen savePBM()schrijft de buffer als een PBM P4-bitmap- Nadat alle tests zijn voltooid, converteert ImageMagick PBM naar PNG (omgekeerde kleuren, schaal van 400%)
- Hello-animatieframes worden samengevoegd tot een GIF
Uitvoerstructuur
test/test_display/_output/
├── pbm/ # Raw bitmaps (generated by tests)
│ ├── textpage/
│ │ ├── combos/ # Field combinations (title+body, all fields, etc.)
│ │ ├── scroll/ # Scroll positions (0%, 50%, 100%)
│ │ ├── stress/ # Edge cases (UTF-8, long strings)
│ │ ├── qr/ # QR code variants
│ │ ├── body/ # Body rendering with/without title
│ │ ├── subtitle/ # Subtitle font sizing
│ │ ├── pages/ # All predefined pages
│ │ └── patterns/ # Stroke engine pattern descriptions
│ ├── header_icons/ # WiFi × BLE status combinations
│ ├── logos/ # RD logo, KM logo
│ ├── hello/ # Animation frames
│ ├── menu/ # Menu rendering variants
│ └── play_controls/ # Preflight, play modes
└── png/ # Same structure, converted to PNGTestdekking
| Testbestand | Wat het omvat |
|---|---|
test_textpage.cpp | TextPage-veldcombinaties, stresstests, QR, ondertiteloverloop, indeling van de hoofdtekst |
test_pages.cpp | Alle vooraf gedefinieerde pagina's, beschrijvingen van Stroke Engine-patronen |
test_scroll.cpp | Schuifbalk bij grenswaarden en randgevallen |
test_header_icons.cpp | Alle 20 WiFi × BLE-statuscombinaties |
test_logos.cpp | RD-logo, KM-logo |
test_hello.cpp | Alle frames van de Hello-animatie, GIF-generatie |
test_menu.cpp | Menu met verschillende aantallen items, lange tekst en regelafbreking |
test_play_controls.cpp | Bediening voor Preflight, Simple Penetration, Stroke Engine en Streaming |