FastEPD

repository·main·Indexed 41 days ago

https://github.com/bitbank2/fastepd

A C++ library for driving parallel e-ink displays on ESP32 hardware and Raspberry Pi. It features a modern API with optimizations for compressed fonts and graphics, and includes support for hardware like EPDiy V7, M5Stack PaperS3, and Inkplate. The ecosystem includes JPEGDEC, an optimized JPEG decoder for MCUs, and the fontconvert tool for generating C header files from TTF fonts.

Tokens
4.1K
Snippets
12
Records
22
Agent score
52%

What's inside FastEPD

  1. Overview of FastEPD

    main
    FastEPD is a complete solution designed for driving parallel e-ink displays (similar to Kindle displays) on ESP32-based hardware. It is designed as a clean, maintainable alternative to existing libraries like EPDiy, offering a simplified API and specialized features such as compressed fonts and graphics, as well as flexible display update mechanisms.
  2. Overview of JPEGDEC features

    main

    JPEGDEC is an optimized JPEG decoder designed for microcontrollers (MCUs) with as little as 20K of RAM (e.g., Cortex-M0+). It is optimized for speed and provides several key features:

    • Flexible Data Sources: Supports JPEG data from memory (FLASH/RAM), SDCard, or custom media via callbacks.
    • Fast Downscaling: Includes built-in options for 1/2, 1/4, and 1/8 scaling.
    • Exif Support: Option to detect and decode embedded Exif thumbnails.
    • Dithering: Supports Floyd-Steinberg error diffusion dithering to 1, 2, or 4-bpp grayscale output, which is ideal for e-paper displays.
    • Portability: The core C code is portable and has no external dependencies.
  3. Implement Callback functions for JPEGDEC

    main

    JPEGDEC uses a callback-based design to isolate decoding logic from hardware-specific I/O and display drivers. The functions you must implement depend on your data source:

    1. Decoding from Memory (RAM/FLASH)

    If your JPEG data is already in memory, you only need to provide one callback:

    • Draw function: A function to receive and draw (or store) each block of image pixels emitted by the library.

    2. Decoding from External Media (e.g., SDCard)

    If you are reading from an external source, you must provide five callback functions:

    • Draw function: To handle pixel blocks.
    • open: To open the file.
    • close: To close the file.
    • read: To read data from the file.
    • seek: To move the file pointer.

    Architecture Note for ESP32/ESP8266

    On Harvard Architecture MCUs like ESP32 or ESP8266, when decoding from memory, you must use the specific open function corresponding to your storage: openRAM or openFLASH.

  4. How show_img handles image bit depth and panel selection

    main

    The tool automatically manages image conversion and panel selection based on the input image and configuration:

    • Image Conversion: Images with 2 or more bits per pixel are automatically converted to either 2-bit grayscale or b/w/r/y depending on the chosen display. Images larger than the panel resolution will cause an error.
    • Panel Selection: For black/white panels, if both panel_1bit and panel_2bit are defined in the configuration, show_img selects the appropriate one based on the input image.
    • Update Modes:
      • 1-bit mode: Supports fast and partial updates.
      • 2-bit mode: Grayscale mode does not support fast or partial updates; it defaults to full updates.
      • Automatic Fallback: All update modes (including fast and partial) automatically become full when displaying images that require more than 1-bit per pixel.
  5. Run the WiFi image download and JPEG render example

    main

    This example demonstrates downloading a JPEG image via WiFi and rendering it to an e-paper display using the Bitbank2 JPEG decoder (jpegdec). This method is optimized for speed by copying decoded rows directly into the 4 BPP e-paper framebuffer in PSRAM, bypassing per-pixel drawing at the cost of software rotation and gamma correction.

    Prerequisites

    Because this example uses the Bitbank2 JPEG decoder as an external component, you must initialize the submodules before building:

    git submodule update --init --recursive

    This will place the decoder in components/jpegdec.

    git submodule update --init --recursive
  6. Configure WiFi and display settings for the image example

    main

    Before building the example, you must configure your network credentials and display dimensions in the main/settings.h file.

    Edit main/settings.h with the following parameters:

    • ESP_WIFI_SSID: Your WiFi network name.
    • ESP_WIFI_PASSWORD: Your WiFi password.
    • EPD_WIDTH: The width of your e-paper display.
    • EPD_HEIGHT: The height of your e-paper display.
    • IMG_URL: The URL of the image to download. The default uses loremflickr.com with dimensions interpolated from your EPD_WIDTH and EPD_HEIGHT.
    // Edit the file: main/settings.h
    // WiFi configuration
    #define ESP_WIFI_SSID     "WIFI NAME"
    #define ESP_WIFI_PASSWORD ""
    // Add your display dimensions:
    #define EPD_WIDTH 1200
    #define EPD_HEIGHT 825
    // This is then also used here:
    #define IMG_URL "https://loremflickr.com/" STR(EPD_WIDTH) "/" STR(EPD_HEIGHT)
  7. Enable I2C on Raspberry Pi

    main

    FastEPD requires the I2C interface to be enabled on your Raspberry Pi. You can enable this using the raspi-config utility by following these steps:

    1. Run sudo raspi-config in your terminal.
    2. Navigate to Interface Options.
    3. Select I2C and enable it.
    sudo raspi-config
  8. Convert TTF fonts using fontconvert

    main

    The fontconvert tool is used to generate C header files (.h) from TrueType Font (.ttf) files. This process allows you to specify the font size and the specific range of character codes to include in the output.

    Character ranges typically used:

    • 32 to 127: Standard ASCII set.
    • 128 to 255: Extended ASCII set (Microsoft's CP1252), which includes symbols and accented characters for European Latin languages.

    Note: The strings passed to FastEPD must be in ASCII or UTF-8 format.

    ./fontconvert <source.ttf> <output.h> <size> <start> <end>
    
    # Example: Create an 80pt Roboto-Black font with full ASCII and extended ASCII (32-255)
    ./fontconvert Roboto-Black.ttf Roboto_Black_80.h 80 32 255
  9. Configure SPI0 Chip Select for IT8951 HAT on Raspberry Pi

    main

    To use the IT8951 HAT with this code on a Raspberry Pi, you must modify the SPI0 configuration to change or disable the default CE0 (chip select0) line. This is required because the IT8951 HAT uses BCM 27 for chip select instead of the default pin.

    1. Open /boot/firmware/config.txt on your Raspberry Pi.
    2. Add the following line to the configuration: dtoverlay=spi0-1cs,cs0_pin=27

    Failure to apply this change will prevent the code from working.

    dtoverlay=spi0-1cs,cs0_pin=27
  10. Configure SPI0 Chip Select for IT8951 on Raspberry Pi

    main

    To use the IT8951 HAT with a Raspberry Pi, you must reconfigure the SPI0 chip select (CE0) line. By default, CE0 is used by the system, but the IT8951 HAT requires it to be moved to BCM 27 (an unused pin) to function correctly.

    1. Open /boot/firmware/config.txt on your Raspberry Pi.
    2. Add the following line to the configuration: dtoverlay=spi0-1cs,cs0_pin=27
    3. This configuration disables the default CE0 and assigns the chip select to BCM 27.

    Note: The code will not work without this specific change.

    dtoverlay=spi0-1cs,cs0_pin=27
  11. How to provide JPEG data from memory

    main

    To use JPEG images stored in your program's FLASH or RAM, you must convert the binary JPEG files into C arrays.

    1. Use a tool like image_to_c or xxd to convert the binary file into a C-style byte array.
    2. Ensure you use the const (and PROGMEM if applicable to your architecture) modifier so the data is stored in FLASH rather than consuming RAM.

    Example of a data array structure:

    const uint8_t my_jpeg_data[] = { 0xFF, 0xD8, ... };