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

> Explore ESP32 Bit Pirate compatibility across various ESP32 variants. Discover hardware support details and ensure seamless integration with this comprehensive guide.

- Repository: [Geo/ESP32-Bit-Pirate](https://github.com/geo-tp/ESP32-Bit-Pirate)
- Tags: compatibility-guide
- Published: 2026-08-02

---

**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`](https://github.com/geo-tp/ESP32-Bit-Pirate/blob/main/platformio.ini) |
| **Device macro selection** | Instantiate the correct `Board` class based on the active macro | [`src/main.cpp`](https://github.com/geo-tp/ESP32-Bit-Pirate/blob/main/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`](https://github.com/geo-tp/ESP32-Bit-Pirate/blob/main/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:

```bash

# 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`](https://github.com/geo-tp/ESP32-Bit-Pirate/blob/main/platformio.ini):

```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:

```bash
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`](https://github.com/geo-tp/ESP32-Bit-Pirate/blob/main/src/main.cpp) around line 94, this confirms your build target:

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

```

Expected output:

```text
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:

```cpp
// 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`](https://github.com/geo-tp/ESP32-Bit-Pirate/blob/main/UartController.cpp) adapts:

```cpp
// 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`](https://github.com/geo-tp/ESP32-Bit-Pirate/blob/main/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/main/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/main/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`](https://github.com/geo-tp/ESP32-Bit-Pirate/blob/main/Board.cpp) | Hardware-specific initialization (e.g., [[`StickS3Board.cpp`](https://github.com/geo-tp/ESP32-Bit-Pirate/blob/main/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/main/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`](https://github.com/geo-tp/ESP32-Bit-Pirate/blob/main/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`](https://github.com/geo-tp/ESP32-Bit-Pirate/blob/main/platformio.ini) with `-DDEVICE_YOURBOARD`, define your pin macros in `build_flags`, and optionally add a [`YourBoardBoard.cpp`](https://github.com/geo-tp/ESP32-Bit-Pirate/blob/main/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`](https://github.com/geo-tp/ESP32-Bit-Pirate/blob/main/src/main.cpp) when no `DEVICE_…` macro is active. Verify your [`platformio.ini`](https://github.com/geo-tp/ESP32-Bit-Pirate/blob/main/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.