ESP32-Bit-Pirate Compatibility with Different ESP32 Variants: A Complete Hardware Support Guide

The ESP32-Bit-Pirate firmware supports multiple ESP32 variants through PlatformIO environment definitions and compile-time feature flags that conditionally include board-specific code.

This open-source hardware hacking tool by geo-tp uses a layered architecture to maintain compatibility across ESP32-S3 development kits, M5Stack devices, and custom boards—without duplicating core logic. This article explains exactly how the project achieves ESP32-Bit-Pirate compatibility with different ESP32 variants and how to build for your specific hardware.

How Multi-Board Support Works in ESP32-Bit-Pirate

The firmware employs a compile-time abstraction layer rather than runtime detection. This approach keeps the binary size minimal and eliminates performance overhead from dynamic board probing.

The Three-Layer Architecture

Layer Purpose Key File
PlatformIO environments Define board IDs, ESP-IDF platform, and -DDEVICE_… macros platformio.ini
Device macro selection Instantiate the correct Board class based on the active macro src/main.cpp
Board-specific implementations Contain hardware glue code wrapped in #if defined() guards src/Boards/<BoardName>/*Board.cpp

All hardware differences—pin assignments, peripheral availability, display drivers—are expressed as pre-processor macros. The core transformers, services, and controllers remain identical across every variant.

Supported ESP32 Variants (pioarduino Branch)

The following table lists officially supported devices as defined in platformio.ini:

Device Macro PlatformIO board Value Hardware
DEVICE_S3DEVKIT esp32-s3-devkitc-1 Generic ESP32-S3 DevKit
DEVICE_STICKS3 esp32-s3-devkitc-1 (custom flags) M5Stack Stick S3
DEVICE_M5STAMPS3 m5stack-stamps3 M5Stack Stamp S3
DEVICE_CARDPUTER / DEVICE_CARDPUTERADV m5stack-stamps3 M5Stack Cardputer (standard & advanced)
DEVICE_TDISPLAYS3 esp32-s3-devkitc1-n16r8 LilyGo T-Display S3
DEVICE_WAVESHARE_S3_GEEK esp32-s3-devkitc1-n16r2 Waveshare S3 Geek
DEVICE_VISION_MASTER_T190 esp32-s3-devkitc1-n16r8 Heltec Vision Master T190
DEVICE_TEMBEDS3 / DEVICE_TEMBEDS3CC1101 esp32-s3-devkitc-1 M5Stack T-Embed S3 (with/without CC1101)
DEVICE_XIAO_ESP32S3 esp32-s3-devkitc-1 Seeed XIAO ESP32-S3
DEVICE_CUSTOM esp32-s3-devkitc-1 User-defined ESP32-S3 board

Adding a new board requires only a new [env:…] block with the appropriate -DDEVICE_… flag and optionally a small wrapper class in src/Boards/.

Building for Your ESP32 Variant

Step 1: Select the PlatformIO Environment

Run PlatformIO with the -e flag targeting your hardware:


# Generic ESP32-S3 DevKit

pio run -e s3-devkit

# M5Stack Stick S3

pio run -e m5stack-sticks3

# M5Stack Cardputer

pio run -e cardputer

# T-Display S3

pio run -e tdisplay-s3

Step 2: Configure a Custom Board (Optional)

For unsupported hardware, use the built-in custom environment. Edit the pin macros in the Custom board profile section of platformio.ini:

[env:custom]
board = esp32-s3-devkitc-1
build_flags =
    -DDEVICE_CUSTOM
    -DUART_RX_PIN=17
    -DUART_TX_PIN=18
    -DI2C_SDA_PIN=8
    -DI2C_SCL_PIN=9
    ; -DCUSTOM_DISPLAY_DRIVER_ST7789
    ; -DLED_TYPE_RGB

Then build with:

pio run -e custom

Step 3: Verify Device Detection

At runtime, the firmware prints the active device in the welcome banner. In src/main.cpp around line 94, this confirms your build target:

Serial.println("Starting ESP32-Bit-Pirate on " + String(DEVICE_NAME) + " ...");

Expected output:

Starting ESP32-Bit-Pirate on DEVICE_STICKS3 ...

Code-Level Device Abstraction

Board Class Instantiation in main.cpp

The entry point uses conditional compilation to select the correct Board implementation:

// src/main.cpp (excerpt)
#include "Boards/S3DevKit/S3DevKitBoard.h"
#include "Boards/StickS3/StickS3Board.h"
#include "Boards/Cardputer/CardputerBoard.h"
// ... other board headers

#if defined(DEVICE_S3DEVKIT)
    S3DevKitBoard board;
#elif defined(DEVICE_STICKS3)
    StickS3Board board;
#elif defined(DEVICE_CARDPUTER) || defined(DEVICE_CARDPUTERADV)
    CardputerBoard board;
#elif defined(DEVICE_CUSTOM)
    CustomBoard board;
#else
    #error "No device defined. Check platformio.ini build_flags."
#endif

void setup() {
    board.init();
    // ... common initialization
}

Peripheral Configuration with Build Flags

Peripheral pin assignments come from build_flags, not hardcoded values. Here's how UartController.cpp adapts:

// src/Controllers/UartController.cpp (excerpt)
#ifdef DEVICE_STICKS3
  // Stick S3 uses UART pins 4 (RX) and 5 (TX) as defined in env
  Serial1.begin(UART_BAUD, SERIAL_8N1, UART_RX_PIN, UART_TX_PIN);
#else
  // All other boards use generic UART pins from env
  Serial1.begin(UART_BAUD, SERIAL_8N1, UART_RX_PIN, UART_TX_PIN);
#endif

Because UART_RX_PIN and UART_TX_PIN are defined per-environment in platformio.ini, the same source compiles correctly for every board without modification.

Feature Toggles for Optional Hardware

Optional features are controlled by uncommenting -D flags in your environment:

Flag Enables
CUSTOM_DISPLAY_DRIVER_ST7789 / SSD1306 / ILI9341 Display support
LED_TYPE_RGB / LED_TYPE_SINGLE RGB or single-color LED
HAS_LORA LoRa radio (SX1262/SX1276)
HAS_CC1101 CC1101 sub-GHz transceiver
JTAG_ENABLE JTAG debugging interface

This modular approach lets you adapt a board that lacks a particular peripheral without touching source code.

Key Source Files for Understanding Compatibility

File What It Contains
[platformio.ini](https://github.com/geo-tp/ESP32-Bit-Pirate/blob/pioarduino/platformio.ini) All board definitions, pin mappings, and feature flags
[src/main.cpp](https://github.com/geo-tp/ESP32-Bit-Pirate/blob/pioarduino/src/main.cpp) Device macro selection and board class instantiation
src/Boards/*/Board.h + Board.cpp Hardware-specific initialization (e.g., [StickS3Board.cpp](https://github.com/geo-tp/ESP32-Bit-Pirate/blob/pioarduino/src/Boards/StickS3/StickS3Board.cpp))
src/Controllers/*Controller.cpp Peripherals with conditional compilation (e.g., [UartController.cpp](https://github.com/geo-tp/ESP32-Bit-Pirate/blob/pioarduino/src/Controllers/UartController.cpp))

Summary

  • ESP32-Bit-Pirate compatibility with different ESP32 variants is achieved through PlatformIO environments and compile-time macros, not runtime detection.
  • Each board gets a unique DEVICE_… flag (e.g., -DDEVICE_STICKS3) that selects the correct Board class and peripheral configuration.
  • Pin assignments and optional features are controlled via build_flags in platformio.ini, keeping the core codebase unified.
  • Adding support for new hardware requires only a new environment block and optionally a small wrapper class in src/Boards/.
  • The DEVICE_CUSTOM environment provides a template for unsupported ESP32-S3 boards with configurable pin mappings.

Frequently Asked Questions

What ESP32 chips does ESP32-Bit-Pirate support?

The firmware targets ESP32-S3 exclusively. All supported variants in the pioarduino branch use ESP32-S3 silicon. The original ESP32 (classic) and ESP32-C3/S2 are not supported due to peripheral and memory requirements.

How do I add support for a new ESP32-S3 board?

Create a new [env:yourboard] entry in platformio.ini with -DDEVICE_YOURBOARD, define your pin macros in build_flags, and optionally add a YourBoardBoard.cpp class in src/Boards/YourBoard/. Copy an existing board implementation as a starting template.

Why does my build fail with "No device defined"?

This error originates from the #error directive in src/main.cpp when no DEVICE_… macro is active. Verify your platformio.ini environment includes the correct -DDEVICE_… flag in build_flags and that you're building with the matching -e environment name.

Can I use the same firmware binary on different ESP32 boards?

No. Because hardware differences are resolved at compile time, you must build separate binaries for each board type. The resulting .bin file is specific to the target device and will not function correctly on different hardware.

Have a question about this repo?

These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:

Share the following with your agent to get started:
curl -s "https://instagit.com/install.md"

Works with
Claude Codex Cursor VS Code OpenClaw Any MCP Client

Maintain an open-source project? Get it listed too →