This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
This repository contains example applications for the LEDCube matrixserver framework. All applications use CMake and depend on the matrixserver framework being installed.
# Build all enabled applications
mkdir -p build && cd build && cmake .. && make
# Build individual application
cd build && make <application_name>The build system automatically detects Raspberry Pi platforms via /boot/LICENCE.broadcom and enables additional applications:
- All platforms: CubeTestApp, PixelFlow3
- Raspberry Pi only: ImuTest, PixelFlow, PixelFlow2, Rainbow
Applications require the matrixserver framework (version >= 0.3) to be installed. The build
system automatically checks ./matrixserver/install/ first, then falls back to system paths.
Core dependencies:
- matrixapplication library >= 0.3 (from matrixserver framework)
- Boost (thread, log, system components)
- Imlib2 (image processing)
When iterating on the matrixserver framework alongside the example apps, the canonical
flow is to build matrixserver and make install it into matrixserver/install/, then
build the example apps. Example apps' find_package(matrixapplication) looks at
matrixserver/install/ first via CMAKE_PREFIX_PATH, so the build links the freshly
installed library and headers.
Runtime caveat: the example apps' CMake bakes only LC_RPATH = /usr/local/lib into
each binary. After make install to a local prefix, the build uses the freshly
installed lib (so the API is verified), but at runtime the dynamic loader still falls
back to /usr/local/lib/libmatrixapplication.dylib — the previously installed system
copy. The binary will silently run against the old library.
To actually run an example app against a freshly built matrixserver, point the loader at the install tree before launching:
# macOS
export DYLD_LIBRARY_PATH=$(pwd)/matrixserver/install/lib
# Linux
export LD_LIBRARY_PATH=$(pwd)/matrixserver/install/lib
./build/bin/SnakeAlternatives: sudo make install matrixserver to /usr/local (replaces the system
copy), or install_name_tool -add_rpath …/matrixserver/install/lib build/bin/<App>
post-build on macOS.
cd matrixserver/build && cmake .. && make testAll && ./tests/testAllThe testAll target is excluded from the default make build (EXCLUDE_FROM_ALL) — build it explicitly with make testAll when you want to run tests.
Tests use Catch2 (single-header, v2) and cover:
- Color: constructors, arithmetic with saturation, HSV conversion, equality
- Screen: pixel read/write, bounds checking, clear/fill/fade, metadata
- COBS: encoding/decoding, stream decoder with split packets
- AnimationParams: parameter registration, get/set, protobuf serialization
Tests are also run in all three CI workflows (AMD64 simulator, ARM64 simulator, RPi).
Generate Debian packages: make package
- Creates .deb files with dependency on matrixserver package
- Applications install to
/home/pi/APPSon Raspberry Pi
All example applications follow a common inheritance pattern:
3D Cube Applications (inherit from CubeApplication):
- CubeTestApp - Basic 3D functionality demonstration and testing
- Snake - Multi-player 3D Snake game with joystick input and AI opponents
- Genetic - Genetic algorithm color evolution visualization
- Blackout3D - Minimal interactive 3D application template
- Breakout3D - Full-featured 3D Breakout game with physics and multiplayer
2D Matrix Applications (inherit from MatrixApplication):
- Rainbow - Particle system with IMU integration (Raspberry Pi only)
- Picture - Image display with animation support and file watching
- Genetic - Genetic algorithm running on 2D matrix displays
Animation/Effects Applications:
- PixelFlow/PixelFlow2/PixelFlow3 - Fluid dynamics particle simulations
class MyApp : public CubeApplication {
public:
MyApp() : CubeApplication(30) {} // 30 FPS
bool loop() override {
clear(); // Clear 3D space
// ... rendering logic ...
render(); // Render to displays
return true; // Continue running
}
};3D Volumetric Rendering (CubeApplication):
setPixel3D(Vector3i pos, Color color)- Set individual voxelsdrawLine3D(Vector3i start, Vector3i end, Color color)- 3D line drawingdrawText(ScreenNumber screen, Vector2i pos, Color color, string text)- Text on cube facesclear()- Clear all voxelsrender()- Send frame to server
Screen Management:
- Six screens available: front, right, back, left, top, bottom
CharacterBitmaps::centeredfor automatic text centering- Screen-specific text rendering for cube faces
Input Integration:
- Joystick support for interactive applications
- IMU (MPU6050) integration on Raspberry Pi
- ADC (ADS1000) sensor support
Applications connect to matrixserver instances using:
- Default: TCP localhost:2017
- Fallback: IPC (boost message queue) for local communication
- Alternative: Unix sockets
There is exactly one server executable, matrix_server. The renderer is
selected at runtime via --backend=<name>:
simulator— software development/testing (always available)fpga-ftdi— FTDI USB interface for FPGA boardsfpga-rpispi— Raspberry Pi SPI interfacergb-matrix— Raspberry Pi GPIO matrix panels
Hardware backends are only selectable when compiled in via
-DHARDWARE_BACKEND=… (semicolon-separated list of FPGA_FTDI,
FPGA_RPISPI, RGB_MATRIX). matrix_server --help lists the backends
present in the current binary.
-
Start the matrixserver (from
matrixserver/directory):./build/server/matrix_server # default: --backend=simulator ./build/server/matrix_server --backend=fpga-ftdi # FPGA hardware (if compiled in)
-
Build and run example application:
cd build && make cubetestapp && ./cubetestapp
-
Applications automatically connect to running server and begin rendering
- Applications specify target FPS in constructor (1-200 range)
- Framework handles automatic frame rate regulation
- Performance monitoring available through load tracking
- Thread-safe rendering with configurable timing
The MPU6050 sensor (used in Rainbow and other IMU-enabled applications) supports configurable orientation corrections. Instead of hardcoded rotations, the sensor now reads orientation settings from matrixServerConfig.json via three rotation planes:
Configuration in matrixServerConfig.json:
{
"imuOrientation": {
"xyRotationDeg": 0.0,
"xzRotationDeg": 45.0,
"yzRotationDeg": 0.0
}
}Rotation Planes:
xyRotationDeg: Rotation in the XY plane (around Z axis)xzRotationDeg: Rotation in the XZ plane (around Y axis)yzRotationDeg: Rotation in the YZ plane (around X axis)
Defaults: All rotations default to 0° when the field is absent, maintaining backwards compatibility with existing configurations.
Usage in Applications:
// Applications using IMU (e.g., Rainbow)
class Rainbow : public MatrixApplication {
public:
Rainbow() : MatrixApplication(40) {
// MPU6050 automatically loads orientation from config
imu.init();
}
bool loop() override {
auto acceleration = imu.getAcceleration(); // Already orientation-corrected
// ... use acceleration data ...
}
};The orientation correction is applied internally in the Mpu6050::applyOrientation() method, making it transparent to applications.
A minimal 3D application that demonstrates the basic structure:
// Blackout3D.cpp - Minimal template
#include "Blackout3D.h"
Blackout3D::Blackout3D() : CubeApplication(20, "cube10.local") {
// Constructor: 20 FPS, connect to specific host
}
bool Blackout3D::loop() {
clear(); // Clear all voxels
// Add your 3D rendering logic here
render(); // Send frame to server
return true; // Continue running
}Usage: Perfect starting point for new 3D applications. Modify the loop() method to add custom 3D graphics and interactions.
A complete 3D Breakout game featuring:
- Multi-player support (2 players with joysticks)
- Physics-based ball movement and collision detection
- Block destruction with scoring system
- AI opponents when joysticks not available
- High score persistence
// Key game mechanics from breakoutgame.cpp
class BreakoutGame : public CubeApplication {
private:
enum GameState { pregame, ingame, postgame };
std::vector<Player*> players_;
std::vector<Ball*> balls_;
std::vector<Block*> blocks_;
public:
BreakoutGame() : CubeApplication(40, "192.168.188.106") {
// Initialize with 40 FPS, connect to specific IP
reset();
updateHighScoreFromToFile();
}
bool loop() override {
switch(gameState_) {
case pregame:
// Show instructions and wait for start
drawText(front, Vector2i(CharacterBitmaps::centered, 20),
Color::white(), "PRESS A TO PLAY");
break;
case ingame:
clear();
ballLoop(); // Update ball physics
blockLoop(); // Handle block collisions
playerLoop(); // Update player paddles
// Render game elements
for(auto ball : balls_) ball->render();
break;
case postgame:
// Show scores and winner
break;
}
render();
return true;
}
};Key Features:
- Ball Physics: Vector-based movement with collision reflection
- Player Controls: Joystick input with AI fallback for missing controllers
- Scoring System: Points for hitting blocks, penalties for missed balls
- Power-ups: Slow motion (R button), rocket ball (B button)
3D Snake game supporting up to 8 players with AI:
// Key initialization from snake.cpp
Snake::Snake() : CubeApplication(40, "192.168.188.106") {
float startSpeed = 0.2;
// Create up to 8 players with different colors
players.push_back(new Player(this, 0, getRandomPointOnScreen(top).cast<float>(),
Vector3f(0, startSpeed, 0), Color::green(), 10));
players.push_back(new Player(this, 1, getRandomPointOnScreen(top).cast<float>(),
Vector3f(0, startSpeed, 0), Color::red(), 10));
// ... more players
// Scatter food across all cube faces
for (int i = 0; i < 20; i++) {
food.push_back(new Food(this, getRandomPointOnScreen(front), Color::randomBlue() * 2));
food.push_back(new Food(this, getRandomPointOnScreen(right), Color::randomBlue() * 2));
// ... all faces
}
}Display static images or animations on the cube:
// picture.cpp - Image loading and display
Picture::Picture(int argc, char *argv[]) : CubeApplication(40, "192.168.188.106") {
// Parse command line arguments
if (argc > 1) {
filepath = std::string(argv[argc - 1]); // Last argument is image path
if (argc == 4 && std::string(argv[1]) == "-s") {
// Speed control: -s <speed> <imagefile>
animationPrescale = std::stoi(argv[2]);
}
}
if (!loadImage(filepath)) {
error = true;
}
}
bool Picture::loadImage(std::string path) {
if (autoload.loadImage(path.data())) {
// Check for proper cube format: 384px wide (6 faces × 64px)
if (autoload.getWidth() == 384 && autoload.getHeight() % 64 == 0) {
lastModificationTime = fs::last_write_time(fs::path(path));
return true;
}
}
return false;
}Image Requirements:
- Dimensions: 384×64 pixels (6 cube faces × 64px width)
- Animation: Multiple 64px height sections for frame animation
- Auto-reload: Watches file modification time for live updates
Command Line Usage:
./picture ~/images/mycube.png # Static display
./picture -s 10 ~/images/animation.png # Slower animationColor evolution using genetic algorithms:
// genetic.cpp - Evolutionary color matching
class Genetic : public MatrixApplication {
private:
struct citizen { uint32_t dna; };
citizen* children_;
citizen* parents_;
uint32_t target_;
int popSize_;
public:
Genetic() : MatrixApplication(40, "192.168.188.106") {
popSize_ = 64 * 64; // Full matrix population
children_ = new citizen[popSize_];
parents_ = new citizen[popSize_];
target_ = rand() & 0xFFFFFF; // Random color target
// Initialize random population
for (int i = 0; i < popSize_; ++i) {
children_[i].dna = rand() & 0xFFFFFF;
}
}
bool loop() override {
swap(); // Parents ← Children
sort(); // Sort by fitness
mate(); // Create new generation
// Display population on matrix
for(int i = 0; i < popSize_; i++) {
int c = children_[i].dna;
int x = i % 64;
int y = i / 64;
for(auto screen : screens) {
screen->setPixel(x, y, R(c), G(c), B(c));
}
}
// Check convergence and set new target
if(is85PercentFit()) {
target_ = rand() & 0xFFFFFF;
}
render();
return true;
}
};# Build all applications
mkdir -p build && cd build && cmake .. && make
# Build individual applications
make cubetestapp # Basic 3D test
make snake # 3D Snake game
make breakout3d # 3D Breakout game
make picture # Image display
make picture # Image display
make genetic # Genetic algorithm
# Run with specific parameters
./picture ~/images/cube_animation.png
./picture -s 5 ~/images/slow_animation.png