Extensibility Guide: Creating Custom Drivers¶
This guide explains how to implement a custom display driver (DrawSurface) to support hardware not included by default in the PixelRoot32 engine (e.g., monochromatic OLED displays, e-Ink screens, or non-standard SPI displays).
1. Inherit from BaseDrawSurface¶
The easiest way to create a driver is to inherit from pixelroot32::graphics::BaseDrawSurface. This class provides default implementations for most primitive methods (lines, circles, rectangles) using drawPixel().
#include <graphics/BaseDrawSurface.h>
#include <iostream>
class MyCustomDriver : public pixelroot32::graphics::BaseDrawSurface {
public:
void init() override {
// Initialize hardware (SPI, I2C, etc.)
std::cout << "Hardware initialized" << std::endl;
}
void drawPixel(int x, int y, uint16_t color) override {
// Logic to write a pixel to your buffer or hardware
}
void clearBuffer() override {
// Logic to clear the buffer
}
void sendBuffer() override {
// Logic to send the buffer to the physical display (Flush)
}
};
2. Injecting the Driver into the Engine¶
Once you have your class, you can inject it into the engine using the PIXELROOT32_CUSTOM_DISPLAY macro. The engine will take ownership of the pointer and handle memory deallocation automatically upon shutdown.
#include <core/Engine.h>
#include "MyCustomDriver.h"
void setup() {
// Create the configuration using our driver
auto driver = std::make_unique<MyCustomDriver>();
auto config = PIXELROOT32_CUSTOM_DISPLAY(driver.release(), 240, 240);
// Initialize the engine with this configuration
// Note: Use std::move to transfer ownership of the config
Engine engine(std::move(config));
engine.init();
engine.run();
}
3. Memory Considerations¶
- Ownership: By using
PIXELROOT32_CUSTOM_DISPLAY, you transfer ownership of the object to the engine. Do not attempt to delete the pointer manually. - Smart Pointers: Internally, the engine uses
std::unique_ptrto manage the driver. - Performance:
BaseDrawSurfaceuses generic algorithms for lines and circles that calldrawPixel(). If your hardware supports acceleration for these primitives, you can override the methods (e.g.,drawLine,drawFilledRectangle) to achieve better performance.
4. Mandatory vs. Optional Methods¶
| Method | Mandatory | Description |
|---|---|---|
init() | Yes | Initial hardware configuration. |
drawPixel() | Yes | The foundation of all rendering. |
sendBuffer() | Yes | Sends data to the display. |
clearBuffer() | Yes | Clears the screen/buffer. |
setOffset() | No | Sets X/Y hardware alignment offset. |
setRotation() | No | BaseDrawSurface handles this internally. |
drawLine() | No | Optimized in BaseDrawSurface. |
drawRectangle() | No | Optimized in BaseDrawSurface. |
drawCircle() | No | Optimized in BaseDrawSurface. |
PixelRoot32 - Extensible Driver System (Bridge Pattern)