Skip to content

A C++23 library for controlling Waveshare e-paper displays on Raspberry Pi.

License

Notifications You must be signed in to change notification settings

johanns/libepaper

Folders and files

NameName
Last commit message
Last commit date

Latest commit

Β 

History

80 Commits
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 

Repository files navigation

C++23 E-Paper Display Library

A C++23 library for controlling Waveshare e-paper displays on Raspberry Pi, featuring transparent sleep/wake management and a fluent builder API.

C++23 License: MIT

See docs for complete documentation.

✨ Quick Example

#include <epaper/core/device.hpp>
#include <epaper/core/display.hpp>
#include <epaper/drivers/epd27.hpp>  // Use your driver
#include <epaper/graphics/font.hpp>

using namespace epaper;

int main() {
    Device device;
    device.init().value();

    // Replace EPD27 with your driver (EPD27, MockDriver, etc.)
    auto display = create_display<EPD27, MonoFramebuffer>(device, DisplayMode::BlackWhite,
                                         Orientation::Landscape90).value();

    display->clear(Color::White);
    display->draw(
        display->text("Hello, libepaper!")
            .at(20, 70)
            .font(&Font::font24())
            .foreground(Color::Black)
            .background(Color::White)
            .build()
    );
    display->refresh();

    return 0;
}

πŸ‘‰ See examples/ for complete applications.

🎯 Features

  • Multiple Display Modes: Black/white, 4-level grayscale, and color displays (BWR, BWY, Spectra 6-color)
  • Complete Drawing API: Points, lines, rectangles, circles, text rendering with multiple font sizes
  • Image Support: Load and display PNG/JPEG images with automatic color conversion and dithering
  • Flexible Orientation: Rotate display 0Β°, 90Β°, 180Β°, 270Β° with automatic coordinate transformation
  • Transparent Power Management: Auto-sleep prevents burn-in, auto-wake on refreshβ€”zero manual intervention
  • Hardware Abstraction: Compile-time driver selection with MockDriver for testing without physical hardware
  • Multiple Framebuffer Types: Single-plane (mono/grayscale) and multi-plane (color) with automatic color mapping
  • Builder Pattern API: Fluent, chainable drawing commands with sensible defaults
  • Comprehensive Error Handling: Type-safe error propagation with std::expected (no exceptions)
  • C++23: Built with concepts, std::span, ranges, and zero-cost abstractions

Driver Selection

All drivers are compiled into the library. To use a driver:

  1. Include the driver header for your display:

    #include <epaper/drivers/epd27.hpp>       // Waveshare 2.7" B/W
    #include <epaper/drivers/mock_driver.hpp> // Software-only testing
  2. Use the driver class in create_display<>():

     auto display = create_display<EPD27, MonoFramebuffer>(device, DisplayMode::BlackWhite,
                                         Orientation::Landscape90).value();

Available Drivers

Driver Hardware Dimensions Color Support
EPD27 Waveshare 2.7" 176Γ—264 B/W, Grayscale4
MockDriver Software only Configurable B/W (outputs PNG)

πŸ“– See Doxygen documentation for detailed driver API specifications

πŸš€ Quick Start

Use as a dependency in your CMake project

Link the libepaper target via CMake FetchContent:

include(FetchContent)

FetchContent_Declare(
     epaper
     GIT_REPOSITORY https://github.com/johanns/libepaper
     GIT_TAG        main
)
FetchContent_MakeAvailable(epaper)

add_executable(my_app src/main.cpp)
target_link_libraries(my_app PRIVATE libepaper)

Then build your project as usual (Debug or Release mode).

Run examples from the repository

  1. Install dependencies and set up the system:

    ./bin/setup
  2. Build the library (Release by default, use --type Debug for debug builds):

    ./bin/build
    # ./bin/build --type Debug
  3. Run an example:

    ./build/examples/crypto_dashboard/crypto_dashboard

🧩 Alternative Integration Options

For other integration methods:

Option A β€” Vendored submodule with add_subdirectory

git submodule add https://github.com/johanns/libepaper external/libepaper
git submodule update --init --recursive
add_subdirectory(external/libepaper)
add_executable(my_app src/main.cpp)
target_link_libraries(my_app PRIVATE libepaper)

Option B β€” System-wide installation

cd libepaper
./bin/setup
cmake -S . -B build -DCMAKE_BUILD_TYPE=Release
cmake --build build -j
sudo cmake --install build
find_path(EPAPER_INCLUDE_DIR epaper/display.hpp PATH_SUFFIXES epaper)
find_library(EPAPER_LIBRARY NAMES epaper)

add_executable(my_app src/main.cpp)
target_include_directories(my_app PRIVATE ${EPAPER_INCLUDE_DIR})
target_link_libraries(my_app PRIVATE ${EPAPER_LIBRARY} gpiod m)

βš™οΈ Build Configuration

Build with Release (default) or Debug optimization:

Using our script:

./bin/build                      # Release (default, EPD27 driver)
./bin/build --type Debug         # Debug build
./bin/build --driver Mock tests  # Build tests with MockDriver (no hardware)
./bin/build examples --type Release

Using raw CMake:

# Standard build
cmake -S . -B build -DCMAKE_BUILD_TYPE=Release
cmake --build build -j

# Build with MockDriver for testing without hardware
cmake -S . -B build -DCMAKE_BUILD_TYPE=Release -DLIBEPAPER_DRIVER=Mock
cmake --build build -j
./build/tests/test_drawing_primitives  # Outputs PNG to mock_output/

πŸ“š Documentation

The library provides multiple documentation resources:

πŸ“– API Documentation

  • Doxygen Reference - Comprehensive API documentation with:

    • Detailed class and function documentation
    • Usage examples for major APIs
    • Type reference (enums, structs, concepts)
    • Implementation notes and algorithm details

    Generate locally with: doxygen (outputs to doxygen/html/)

πŸ“˜ Guides

Document Description
Examples Tutorials and working examples
Contributing Guide Commit format and PR process

πŸ’‘ Quick Reference

Core Concepts:

  • Display: Unified interface coordinating driver and framebuffer (epaper::Display)
  • Driver: Hardware abstraction (SPI/GPIO communication) (Driver concept)
  • Framebuffer: Pixel buffer with color encoding (MonoFramebuffer)
  • Builder API: Fluent drawing commands (Builders)

Essential Headers:

#include <epaper/core/device.hpp>      // Device initialization
#include <epaper/core/display.hpp>     // Display interface
#include <epaper/drivers/epd27.hpp>    // Hardware driver (replace with your driver)
#include <epaper/graphics/font.hpp>    // Bitmap fonts (font8-font24)
#include <epaper/io/image_io.hpp>      // PNG/JPEG loading

Common Patterns:

// 1. Initialize device
Device device;
device.init().value();

// 2. Create display with driver
auto display = create_display<EPD27>(device, DisplayMode::BlackWhite).value();

// 3. Drawing operations
display->clear(Color::White);
display->line({0, 0}, {100, 100}).color(Color::Black).draw();
display->rectangle({10, 10}, {50, 50}).fill(DrawFill::Full).draw();

// 4. Refresh to hardware
display->refresh();

// 5. Power management (optional - auto-sleep enabled by default)
display->sleep();  // Manual sleep
display->wake();   // Manual wake

🀝 Contributing

We welcome contributions! Please see CONTRIBUTING.md for our commit format and PR process.

πŸ—οΈ Adding New Display Support

The abstract driver interface makes adding new displays straightforward:

  1. Implement the Driver concept (see driver_concepts.hpp)
  2. Create driver-specific pin configuration struct
  3. Implement display protocol (init, refresh, sleep/wake)
  4. Add comprehensive Doxygen documentation

Reference Implementation: See EPD27 driver for a complete example.

Driver Interface Requirements:

  • Satisfy Driver concept constraints (width(), height(), init(), display(), etc.)
  • Define driver_traits specialization for capability advertisement
  • Use std::expected<T, Error> for all fallible operations
  • Follow RAII patterns for resource management

Testing: Use MockDriver for development without hardware.

πŸ”§ Development

Requirements

  • Raspberry Pi OS, Debian 12 (Bookworm), or Ubuntu 24.04 (Jammy Jellyfish)
  • C++23 capable compiler (GCC 14+ or Clang 18+)
  • CMake 3.25+
  • libgpiod library (user-space GPIO access)
  • Raspberry Pi with SPI enabled
  • User in gpio and spi groups (no sudo required)

πŸ“„ License

MIT License - see LICENSE file for details. Copyright (c) 2021 - 2026 Johanns Gregorian (https://github.com/johanns)

About

A C++23 library for controlling Waveshare e-paper displays on Raspberry Pi.

Topics

Resources

License

Contributing

Stars

Watchers

Forks

Packages

No packages published