Skip to content

Latest commit

 

History

History
428 lines (302 loc) · 12.9 KB

File metadata and controls

428 lines (302 loc) · 12.9 KB

Developer Documentation

Welcome to the KNOMI V2 developer documentation. This directory contains technical deep-dives, implementation details, and customization guides for developers who want to understand, modify, or extend the firmware.


📚 Documentation Overview

Core Architecture

Document Description Topics Covered
UI_CUSTOMIZATION.md Complete guide to LVGL UI customization Layer architecture, widgets, GIF integration, color themes, performance optimization
PRINT_PROGRESS_FEATURE.md Print progress system deep-dive PSRAM management, layer compositing, Moonraker integration, tool indicators
HYBRID_DISPLAY.md State machine & screen switching Display states, state transitions, GIF management, Klipper integration
DISPLAY_SLEEP_IMPLEMENTATION.md Power management system Sleep modes, hooks, timer management, API implementation

🎯 Quick Start for Developers

New to KNOMI Development?

Start here:

  1. UI_CUSTOMIZATION.md - Learn the layer architecture and LVGL basics
  2. HYBRID_DISPLAY.md - Understand how screens switch automatically
  3. PRINT_PROGRESS_FEATURE.md - See how dynamic overlays work

Want to Add Features?

Goal Read This Key Sections
Add a new screen HYBRID_DISPLAY.md State machine, transitions
Customize GIFs UI_CUSTOMIZATION.md Filesystem GIFs, C-array GIFs
Modify progress display PRINT_PROGRESS_FEATURE.md Layer architecture, PSRAM
Add power management DISPLAY_SLEEP_IMPLEMENTATION.md Sleep hooks, timers
Change color themes UI_CUSTOMIZATION.md Tool colors, gradients

🏗️ Architecture Overview

System Layers

┌─────────────────────────────────────────────────────┐
│  Moonraker API (Klipper Integration)                │
│  - Printer state, temperatures, progress            │
└───────────────────────┬─────────────────────────────┘
                        │
                        ▼
┌─────────────────────────────────────────────────────┐
│  State Machine (Hybrid Display)                     │
│  - Idle, Homing, Heating, Printing, Complete        │
│  - Automatic screen transitions                     │
└───────────────────────┬─────────────────────────────┘
                        │
                        ▼
┌─────────────────────────────────────────────────────┐
│  LVGL UI Layer System                               │
│  - Background GIFs (PSRAM)                          │
│  - Static overlays (PNG rings)                      │
│  - Dynamic widgets (arcs, labels)                   │
└───────────────────────┬─────────────────────────────┘
                        │
                        ▼
┌─────────────────────────────────────────────────────┐
│  Display Hardware (GC9A01)                          │
│  - 240x240 circular TFT                             │
│  - 80MHz SPI, 60fps rendering                       │
└─────────────────────────────────────────────────────┘

🔑 Key Concepts

1. Layer Architecture

The KNOMI UI uses a 4-layer compositing system:

Layer 3: Text Labels (Foreground)
Layer 2: Progress Arc (Semi-transparent black)
Layer 1: Static Ring (Colorful PNG)
Layer 0: Animated GIF (Background from PSRAM)

Why? This allows dynamic overlays on animated backgrounds without redrawing the entire screen—critical for 60fps performance.

Learn more: UI_CUSTOMIZATION.md


2. Hybrid Display (State Machine)

The display automatically switches between modes based on printer state:

  • Idle → Tool-specific GIF
  • Homing → Homing animation
  • Heating → Temperature sliders
  • Printing → Progress overlay
  • Complete → Success checkmark

No user input needed—the display adapts in real-time.

Learn more: HYBRID_DISPLAY.md


3. PSRAM Optimization

Large GIF files (100-500KB) are loaded into PSRAM (8MB external RAM) instead of internal SRAM:

Benefits:

  • ✅ Keeps internal RAM free for LVGL rendering
  • ✅ Fast recreation (data persists after screen switch)
  • ✅ No filesystem re-reads

Learn more: PRINT_PROGRESS_FEATURE.md


4. Tool Detection & Multi-Display

Each KNOMI display detects its tool number from hostname:

knomi-t0.local → Tool 0
knomi-t1.local → Tool 1
...
knomi-t5.local → Tool 5

This enables:

  • Tool-specific GIFs (e.g., tool_0.gif for T0)
  • Tool-specific colors (e.g., red for T0, green for T1)
  • Synchronized sleep/wake across all 6 displays

Learn more: UI_CUSTOMIZATION.md


🛠️ Development Environment

Prerequisites

  • PlatformIO (VSCode extension recommended)
  • ESP32 toolchain (auto-installed by PlatformIO)
  • SquareLine Studio (optional, for UI design)
  • LVGL 8.3.7 (included in project)

Build & Flash

# Clone repository (firmware branch)
git clone -b firmware https://github.com/PrintStructor/knomi-toolchanger.git
cd knomi-toolchanger

# Build firmware
pio run -e knomiv2

# Flash firmware
pio run -e knomiv2 -t upload

# Flash filesystem (GIFs)
pio run -e knomiv2 -t uploadfs

# Monitor serial output
pio device monitor -b 115200

📝 Code Style Guide

File Organization

src/
├── ui/                     # SquareLine Studio exports (auto-generated)
│   ├── screens/            # Screen definitions
│   ├── images/             # Static assets (C-arrays)
│   ├── fonts/              # Custom fonts
│   └── ui.c/h              # Main UI entry point
├── ui_overlay/             # Custom logic & overlays
│   ├── lv_print_progress_update.cpp    # Print progress system
│   ├── lv_moonraker_change_screen.cpp  # State machine
│   └── lv_theme_color.cpp              # Color themes
├── gif/                    # Built-in GIF animations (C-arrays)
├── power_management/       # Display sleep system
└── main.cpp                # Firmware entry point

Naming Conventions

LVGL Objects:

  • Prefix with ui_ for SquareLine exports: ui_label_printing_progress
  • Prefix with lv_ for custom LVGL code: lv_goto_idle_screen()

Functions:

  • Snake_case for C/C++ functions: update_print_progress()
  • Verb-first for actions: delete_ui_bg_gif(), show_ui_bg_ring()

Constants:

  • ALL_CAPS for defines: DISPLAY_IDLE_TIMEOUT_SEC
  • Prefix with LV_ for LVGL enums: LV_MOONRAKER_STATE_IDLE

🧪 Testing & Debugging

Serial Debugging

Enable verbose logging:

// In main.cpp or lvgl_usr.cpp
#define DEBUG_PRINT_PROGRESS 1
#define DEBUG_STATE_MACHINE  1
#define DEBUG_PSRAM          1

Monitor output:

pio device monitor -b 115200

Expected logs:

[Progress] Loaded GIF: 123456 bytes into PSRAM
[Progress] Background Ring created
[Progress] Update: 42% (Layer 42/120)
[State] Transition: IDLE → PRINTING
[Sleep] WAKING FROM SLEEP (trigger: state_change)

Performance Profiling

Check FPS:

// In lvgl_usr.cpp
void loop() {
    lv_task_handler();
    static uint32_t last_fps_check = 0;
    if (millis() - last_fps_check > 5000) {  // Every 5 seconds
        uint32_t fps = lv_refr_get_fps_avg();
        Serial.printf("LVGL FPS: %d\n", fps);
        last_fps_check = millis();
    }
}

Target: 55-60 FPS (at 80MHz SPI)


Memory Debugging

Check PSRAM usage:

Serial.printf("PSRAM Free: %u bytes\n", ESP.getFreePsram());
Serial.printf("PSRAM Total: %u bytes\n", ESP.getPsramSize());

Check heap:

Serial.printf("Free Heap: %u bytes\n", ESP.getFreeHeap());

📦 Dependencies

Library Version Purpose
LVGL 8.3.7 UI framework
Arduino-ESP32 2.0.x ESP32 core
LittleFS (built-in) Filesystem for GIFs
WiFi (built-in) Network connectivity
HTTPClient (built-in) Moonraker API
ArduinoJson 6.x JSON parsing

🔗 Related Documentation

User Documentation

Installation Guides

External Resources


🤝 Contributing

Before You Start

  1. Read the code style guide above
  2. Review existing state machine logic in HYBRID_DISPLAY.md
  3. Understand the layer architecture in UI_CUSTOMIZATION.md

Making Changes

  1. Fork the repository
  2. Create a feature branch (git checkout -b feature/my-feature)
  3. Test thoroughly (all 6 displays if possible)
  4. Document your changes (update relevant .md files)
  5. Submit a pull request

Code Review Checklist

  • Code follows naming conventions
  • No memory leaks (test with ESP.getFreeHeap())
  • FPS remains above 55 (profile with lv_refr_get_fps_avg())
  • Serial logs added for debugging
  • Documentation updated
  • Tested on real hardware (not just emulator)

💡 Tips & Tricks

Optimize GIF File Size

# Use ezgif.com or ImageMagick
convert input.gif -resize 240x240 -colors 256 -coalesce -layers optimize output.gif

Target: <200KB per GIF


Quick PSRAM Test

void test_psram() {
    uint8_t* test = (uint8_t*)ps_malloc(1024 * 1024);  // Allocate 1MB
    if (test) {
        Serial.println("PSRAM allocation OK");
        free(test);
    } else {
        Serial.println("PSRAM allocation FAILED");
    }
}

Debug Screen Transitions

void _ui_screen_change_debug(lv_obj_t ** target, ...) {
    Serial.printf("[Screen] Changing from %p to %p\n", lv_scr_act(), *target);
    _ui_screen_change(target, anim, time, delay, user_data);
}

❓ FAQ

Q: How do I add a custom screen?

A: See HYBRID_DISPLAY.md - Add New State

Q: Why is my FPS dropping below 50?

A: Check:

  1. GIF file size (should be <200KB)
  2. Double buffering enabled in lv_conf.h
  3. SPI speed (should be 80MHz, not 40MHz)
  4. Minimize label updates (only update on change)

Q: Can I use LVGL 9?

A: Not yet. KNOMI V2 firmware is built for LVGL 8.3.7. Porting to LVGL 9 requires significant changes.

Q: How do I debug PSRAM issues?

A: Add this to setup():

Serial.printf("PSRAM: %s\n", psramFound() ? "FOUND" : "NOT FOUND");
Serial.printf("PSRAM Size: %u bytes\n", ESP.getPsramSize());
Serial.printf("PSRAM Free: %u bytes\n", ESP.getFreePsram());

📧 Support


Happy Coding! 🚀


Last Updated: December 2, 2025 Version: 1.0.0