Rolez Pocket
Rolez Pocket is a real-time PC system statistics display and visual experience device built for the LilyGO T-Display-S3. It connects to a Windows P...
Rolez Pocket
Category: Embedded Systems / PC Companion / System Monitoring / Visual Display
Platform: LilyGO T-Display-S3 (ESP32-S3) + Windows PC Companion App
Firmware: Arduino via PlatformIO | C++
Companion: Python (Windows system tray application)
Status: Active — Production Ready (v1.0)
Project Overview
Rolez Pocket is a real-time PC system statistics display and visual experience device built for the LilyGO T-Display-S3. It connects to a Windows PC via USB serial and renders a richly animated Neon City graphical scene on its 320x170 display that reacts dynamically to live PC performance metrics — CPU load, GPU usage, RAM usage, disk activity, network throughput, system temperature, volume level, and more.
The project consists of two tightly coupled components:
- ESP32-S3 Firmware — "Smart mode" firmware that reads JSON telemetry packets from the USB serial port and renders the Neon City visualisation at ~30fps using a custom sprite-based rendering engine
- Windows Companion App — A Python system-tray application that continuously samples Windows system metrics using
psutilandLibreHardwareMonitor, serialises them as JSON, and streams them to the device at 10Hz (100ms intervals)
The device also supports a "dumb display" mode where the PC (using a Godot application) renders the entire frame and streams raw RGB565 pixel data directly to the ESP32, which pushes it straight to the display — offloading all rendering to the PC.
Neon City Visual Scene
The Neon City is a custom-designed animated cityscape renderer implemented entirely in the ESP32-S3 firmware. Key characteristics:
- Rendered into a PSRAM-backed double-buffer sprite (prevents screen tearing)
- Targets ~30fps (33ms frame budget)
- Scene components include:
- Animated neon skyline buildings with glowing windows
- Dynamic foreground elements (traffic, street-level details)
- Atmospheric effects (rain, particles, scan lines)
- System metric visualisations embedded directly in the scene
- Colour palette driven by the ColorPalette utility module
Scene State System
The SceneState struct holds all current metric values and is updated from the incoming JSON serial stream. The NeonCity renderer reads this state every frame to:
- Vary visual intensity based on CPU/GPU load
- Change colour temperature with temperature readings
- Animate network traffic indicators with throughput data
- Modulate particle density with disk activity
Demo Mode
If no PC companion is connected for more than 2 seconds, the firmware automatically enters a simulation mode — generating synthetic metric data to keep the scene animated for demonstration purposes.
Windows Companion Application
Architecture
The companion app (rolez_companion.py) runs as a lightweight Windows system tray application built with pystray. It operates a background thread that continuously samples system metrics and writes them to a serial port connected to the T-Display-S3.
Metric Collection
| Metric | Source | Notes |
|---|---|---|
| CPU Usage (%) | psutil.cpu_percent() | Per-call sampling |
| RAM Usage (%) | psutil.virtual_memory() | Used / total |
| Disk Activity | psutil.disk_io_counters() | Read/write bytes delta |
| Network Throughput | psutil.net_io_counters() | Upload/download bytes/s |
| CPU Temperature | LibreHardwareMonitor (LHM) | Via subprocess / COM interface |
| GPU Usage (%) | LibreHardwareMonitor (LHM) | NVIDIA/AMD GPU load |
| GPU Temperature | LibreHardwareMonitor (LHM) | Degrees Celsius |
| System Volume | pycaw (Windows Core Audio) | Current output level 0-100% |
| Notification Count | Custom notification listener | Background Windows notification tap |
Serial Protocol
Metrics are serialised to compact JSON and transmitted at 10Hz (100ms) over USB CDC serial at 115200 baud:
{
"cpu": 45,
"ram": 62,
"disk": 12,
"net_up": 1024,
"net_dn": 8192,
"cpu_temp": 72,
"gpu": 38,
"gpu_temp": 65,
"vol": 75,
"notif": 2
}
COM Port Management
- Auto-detects the T-Display-S3 COM port by scanning available serial ports and identifying the device by USB VID/PID
- Falls back to user-configured port in
config.jsonif auto-detection fails - Auto-reconnects if the USB cable is disconnected and reconnected
System Tray Integration
- Runs minimised to the Windows system tray — no taskbar entry
- Right-click tray icon provides: Open Config, Refresh Connection, Exit
- System tray icon pulses/changes colour based on connection state
LibreHardwareMonitor Integration
- Interfaces with LibreHardwareMonitor (LHM) for temperature and GPU readings
- LHM path is configurable in
config.json(defaults to auto-discovery) - Gracefully degrades to 0 values if LHM is unavailable
Build / Packaging
build.batscript packages the companion into a standalone Windows executable using PyInstaller- Distributable .exe requires no Python installation on the target machine
Firmware Architecture
Smart Mode (Default)
USB Serial (JSON @ 10Hz)
└── SerialProtocol.poll() → SceneState update
└── SceneState.updateDerived() → derived animations/transitions
└── NeonCity.drawFrame() → sprite render → TFT push
Dumb Display Mode (Alternative)
USB Serial (raw RGB565 stream)
└── Dumb firmware receiver → pushes bytes directly to ST7789
Both firmware modes are supported in the same PlatformIO project via separate build environments:
env:rolez-pocket— Smart mode (JSON protocol, ESP32 renders)env:rolez-pocket-dumb— Dumb mode (PC renders, streams raw pixels)
Technical Architecture
Firmware
| Component | Detail |
|---|---|
| MCU | ESP32-S3 @ 240 MHz |
| Display | ST7789 1.9" IPS — 320x170 pixels (landscape) |
| Display Library | TFT_eSPI |
| Render Buffer | PSRAM-backed TFT_eSprite (double buffer) |
| Serial Protocol | USB-CDC at 115200 baud, JSON framing |
| JSON | ArduinoJson v7.3.1 — streaming deserializer |
| Target Frame Rate | ~30fps (33ms frame budget) |
| Memory | 16MB Flash / 8MB OPI PSRAM |
Companion App
| Component | Detail |
|---|---|
| Language | Python 3 |
| Metrics | psutil — CPU, RAM, Disk, Network |
| Hardware Temps | LibreHardwareMonitor (external process) |
| Audio | pycaw — Windows Core Audio API |
| Serial | pyserial — USB CDC serial output |
| System Tray | pystray + Pillow |
| Notifications | Custom Windows notification listener |
| Packaging | PyInstaller (standalone .exe) |
Configuration
companion/config.json:
{
"com_port": "auto",
"brightness": 255,
"lhm_path": "auto"
}
| Key | Description |
|---|---|
| com_port | "auto" for auto-detection, or explicit "COM12" |
| brightness | TFT brightness value 0-255 |
| lhm_path | Path to LibreHardwareMonitor.exe, or "auto" |
Use Cases
- Gaming rig secondary display showing real-time PC performance
- Developer workstation ambient system monitor
- Streaming setup hardware monitor (CPU, GPU, RAM visible at a glance)
- Desktop art piece — visually appealing animated scene driven by real system data
- Hardware enthusiast project combining PC telemetry with embedded art