-
Notifications
You must be signed in to change notification settings - Fork 9
FTDI FT2232HL Support for Arduino Emulator
Phil Schatzmann edited this page Oct 4, 2025
·
9 revisions
Warning: this functionality is experimental and not fully tested. Please provide some feed back to confirm what's working and what's not!
This directory contains the implementation for FTDI FT2232HL support in the Arduino Emulator, providing GPIO, SPI, and I2C functionality through USB.

The FTDI FT2232HL is a dual-channel USB-to-UART/SPI/I2C converter that provides:
- Dual independent channels (Channel A and Channel B)
- MPSSE mode for high-speed serial protocols (SPI, I2C)
- Bitbang mode for GPIO operations
- 16 GPIO pins (8 per channel: ADBUS0-7, BDBUS0-7)
- USB connection to host computer
- External pull-up resistors for I2C (typically 4.7kΩ on SCL and SDA lines)
- GPIO Mode: ADBUS0-ADBUS7 available as digital I/O
-
SPI Mode:
- ADBUS0: SCK (Clock)
- ADBUS1: MOSI (Master Out, Slave In)
- ADBUS2: MISO (Master In, Slave Out)
- ADBUS3-7: Available for CS or other GPIO
-
I2C Mode:
- ADBUS0: SCL (Clock) - requires 4.7kΩ pull-up
- ADBUS1: SDA_OUT (Data Out)
- ADBUS2: SDA_IN (Data In) - requires 4.7kΩ pull-up
- ADBUS3-7: Available for other functions
- GPIO Mode: BDBUS0-BDBUS7 available as digital I/O
- Similar protocol support as Channel A
- libftdi1: FTDI device communication library
- pkg-config: For finding libftdi1 (Linux/macOS)
- FTDI D2XX drivers: Alternative high-performance drivers (optional)
# Install libftdi1 development library and pkg-config
sudo apt-get update
sudo apt-get install libftdi1-dev pkg-config
# Verify installation
pkg-config --libs libftdi1
# Should output: -lftdi1# Install dependencies
sudo apt-get install cmake build-essential libusb-1.0-0-dev
# Clone and build libftdi
git clone https://github.com/libftdi/libftdi.git
cd libftdi
mkdir build && cd build
cmake ..
make
sudo make install
sudo ldconfig# Create udev rule for FTDI devices (prevents need for sudo)
sudo tee /etc/udev/rules.d/99-ftdi.rules << EOF
# FTDI FT232/FT2232 devices
SUBSYSTEM=="usb", ATTRS{idVendor}=="0403", ATTRS{idProduct}=="6001", MODE="0666", GROUP="dialout"
SUBSYSTEM=="usb", ATTRS{idVendor}=="0403", ATTRS{idProduct}=="6010", MODE="0666", GROUP="dialout"
SUBSYSTEM=="usb", ATTRS{idVendor}=="0403", ATTRS{idProduct}=="6011", MODE="0666", GROUP="dialout"
SUBSYSTEM=="usb", ATTRS{idVendor}=="0403", ATTRS{idProduct}=="6014", MODE="0666", GROUP="dialout"
EOF
# Add your user to dialout group
sudo usermod -a -G dialout $USER
# Reload udev rules and restart
sudo udevadm control --reload-rules
sudo udevadm trigger
# Log out and back in, or restart system# Install development libraries
sudo dnf install libftdi1-devel pkgconfig
# Or on older versions:
sudo yum install libftdi1-devel pkgconfig
# Set up permissions (same udev rules as above)# Install from official repository
sudo pacman -S libftdi pkg-config
# Install from AUR for latest version
yay -S libftdi-git# Install Homebrew if not already installed
/bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)"
# Install libftdi
brew install libftdi pkg-config
# Verify installation
pkg-config --libs libftdi1# Install MacPorts, then:
sudo port install libftdi1 +universal# Install dependencies
brew install cmake libusb pkg-config
# Clone and build
git clone https://github.com/libftdi/libftdi.git
cd libftdi
mkdir build && cd build
cmake .. -DCMAKE_INSTALL_PREFIX=/usr/local
make
sudo make install# Install vcpkg
git clone https://github.com/Microsoft/vcpkg.git
cd vcpkg
.\bootstrap-vcpkg.bat
# Install libftdi1
.\vcpkg install libftdi1:x64-windows
# Or for 32-bit: .\vcpkg install libftdi1:x86-windows
# Integrate with Visual Studio
.\vcpkg integrate install-
Download FTDI D2XX drivers:
- Go to FTDI website
- Download "D2XX Direct Drivers" for Windows
- Install the driver package
-
Download libftdi1 binaries:
- Download from libftdi releases
- Extract to
C:\libftdi1\ - Add
C:\libftdi1\binto PATH
# In MSYS2 terminal
pacman -S mingw-w64-x86_64-libftdi mingw-w64-x86_64-pkg-config- Windows 10/11: Drivers are usually installed automatically
- Older Windows: May need manual driver installation from FTDI website
- Driver conflicts: If device doesn't work, check Windows Device Manager
- Virtual Serial Port: Windows may create COM ports - disable if using direct FTDI access
# Linux/macOS: List USB devices
lsusb | grep -i ftdi
# Should show something like: "Bus 001 Device 005: ID 0403:6010 Future Technology Devices International, Ltd FT2232C/D/H Dual UART/FIFO IC"
# Check device permissions (Linux)
ls -l /dev/bus/usb/001/005 # Use actual bus/device numbers
# Should show readable/writable permissions for your user
# Test with libftdi tools (if available)
ftdi_eeprom --help// Simple test program
#include <ftdi.h>
#include <iostream>
int main() {
struct ftdi_context *ftdi = ftdi_new();
if (!ftdi) {
std::cout << "Failed to create FTDI context" << std::endl;
return -1;
}
// Try to open first FTDI device
int ret = ftdi_usb_open(ftdi, 0x0403, 0x6010);
if (ret == 0) {
std::cout << "FTDI device opened successfully!" << std::endl;
ftdi_usb_close(ftdi);
} else {
std::cout << "Failed to open FTDI device: " << ftdi_get_error_string(ftdi) << std::endl;
}
ftdi_free(ftdi);
return 0;
}# Compile test (Linux/macOS)
g++ test_ftdi.cpp -lftdi1 -o test_ftdi
./test_ftdi# Enable FTDI support during configuration
cmake -B build -S . -DUSE_FTDI=ON
# Optional: Also enable other features
cmake -B build -S . -DUSE_FTDI=ON -DUSE_RPI=ON
# Build the project
cmake --build buildcmake_minimum_required(VERSION 3.11...3.19)
# Simple FTDI sketch
arduino_sketch(my_ftdi_project main.ino)
# FTDI sketch with additional libraries
arduino_sketch(sensor_project sensor.ino LIBRARIES MySensorLib)#include "Arduino.h"
#ifdef USE_FTDI
#include "HardwareSetupFTDI.h"
#endif
void setup() {
Serial.begin(115200);
#ifdef USE_FTDI
// Initialize FTDI with default parameters (VID:0x0403, PID:0x6010)
if (FTDI.begin()) {
Serial.println("FTDI initialized successfully");
} else {
Serial.println("FTDI initialization failed");
}
#endif
}void setup() {
// Configure pins
pinMode(0, OUTPUT); // ADBUS0 as output
pinMode(1, INPUT); // ADBUS1 as input
pinMode(8, OUTPUT); // BDBUS0 as output (Channel B)
}
void loop() {
// Digital write/read
digitalWrite(0, HIGH);
int state = digitalRead(1);
// Channel B GPIO
digitalWrite(8, !digitalRead(8)); // Toggle pin 8
delay(1000);
}#include <SPI.h>
void setup() {
SPI.begin();
pinMode(3, OUTPUT); // Use ADBUS3 as chip select
digitalWrite(3, HIGH);
}
void loop() {
digitalWrite(3, LOW); // Select device
SPI.beginTransaction(SPISettings(1000000, MSBFIRST, SPI_MODE0));
uint8_t response = SPI.transfer(0x42);
SPI.endTransaction();
digitalWrite(3, HIGH); // Deselect device
Serial.print("SPI Response: 0x");
Serial.println(response, HEX);
delay(1000);
}#include <Wire.h>
void setup() {
Wire.begin();
Wire.setClock(100000); // 100kHz
}
void loop() {
// Write to I2C device at address 0x48
Wire.beginTransmission(0x48);
Wire.write(0x01); // Register address
Wire.write(0xAB); // Data
uint8_t error = Wire.endTransmission();
if (error == 0) {
Serial.println("I2C write successful");
}
// Read from I2C device
Wire.requestFrom(0x48, 1);
if (Wire.available()) {
uint8_t data = Wire.read();
Serial.print("I2C data: 0x");
Serial.println(data, HEX);
}
delay(1000);
}void setup() {
// Select specific FTDI device by VID/PID
FTDI.setDeviceParams(0x0403, 0x6010);
// Or by description/serial
FTDI.setDeviceParams(0x0403, 0x6010, "My FTDI Device", "FT123456");
if (FTDI.begin()) {
Serial.println("Specific FTDI device found");
}
}class HardwareSetupFTDI {
public:
bool begin(bool asDefault = true);
void end();
void setDeviceParams(int vendor_id, int product_id,
const char* description = nullptr,
const char* serial = nullptr);
HardwareGPIO_FTDI* getGPIO();
HardwareI2C_FTDI* getI2C();
HardwareSPI_FTDI* getSPI();
};
// Global instance
extern HardwareSetupFTDI FTDI;-
GPIO:
pinMode(),digitalWrite(),digitalRead() - SPI: Full SPI library compatibility
- I2C: Full Wire library compatibility
- No analog I/O (analogRead/analogWrite) - FT2232HL is digital only
- No PWM support - use external PWM controller if needed
- No tone generation - use external buzzer controller
- No pulse measurement functions - would require custom implementation
- Check USB connection
- Verify device permissions (
sudoor udev rules) - Ensure correct VID/PID values
- Install libftdi1-dev package
- Check pkg-config can find libftdi1:
pkg-config --libs libftdi1
- Verify pull-up resistors on SCL and SDA (typically 4.7kΩ)
- Check device address (7-bit vs 8-bit addressing)
- Ensure proper connections
- Verify wiring: SCK, MOSI, MISO connections
- Check SPI mode and clock settings
- Ensure proper chip select timing
# After installing dependencies above
cmake -B build -S . -DUSE_FTDI=ON
cmake --build build
# Run example
./build/examples/ftdi-test/ftdi-test# Same as Linux after installing via Homebrew
cmake -B build -S . -DUSE_FTDI=ON
cmake --build build# Using vcpkg toolchain
cmake -B build -S . -DUSE_FTDI=ON -DCMAKE_TOOLCHAIN_FILE=C:/vcpkg/scripts/buildsystems/vcpkg.cmake
cmake --build build --config Release
# Or open in Visual Studio and build# In MSYS2 MinGW64 terminal
cmake -B build -S . -DUSE_FTDI=ON -G "MinGW Makefiles"
cmake --build build- Permission denied: Check udev rules and user groups
-
Library not found: Run
sudo ldconfigafter installation -
CMake can't find libftdi1: Install
pkg-configpackage
- Homebrew not found: Install Homebrew first
-
Library architecture mismatch: Use
brew install libftdi --universal - Permission issues: Usually not needed on macOS
- Driver not installed: Install FTDI D2XX drivers from FTDI website
- Library not found: Ensure libftdi1 DLLs are in PATH
- COM port conflicts: Disable VCP drivers in Windows Device Manager if using direct access
Enable debug logging:
void setup() {
Serial.begin(115200);
Logger.setLevel(LogLevel::Debug); // Enable debug messages
}- GPIO: Suitable for moderate-speed digital I/O
- SPI: Up to ~10MHz clock speeds supported
- I2C: Standard (100kHz) and Fast (400kHz) modes supported
- Latency: USB communication introduces some latency compared to native hardware