microscrap / mpsse
MPSSE SPI/I2C/GPIO helpers extending the FTDI package
Package info
pkg:composer/microscrap/mpsse
Requires
- php: ^8.4|^8.5|^8.6
- ext-ftdi: ^0.7.0
- microscrap/ftdi: ^0.7.0
Requires (Dev)
- pestphp/pest: ^4
Suggests
- scrapyard-io/gpio-framework: ^0.7 — higher-level FTDI UART / USB / MPSSE adapters
This package is auto-updated.
Last update: 2026-08-10 21:46:10 UTC
README
Docs (production): ScrapyardIO · microscrap/mpsse 0.7.x
PHP library that provides MPSSE-oriented SPI / I²C / GPIO operations on top of microscrap/ftdi and the ext-ftdi extension. Pure-PHP port of libmpsse patterns via Microscrap\Bindings\MPSSE\MPSSE.
This is the bindings package — not the native extension. Ecosystem docs: 0.7.x.
Highlights
- Global helper functions (
mpsse_open,mpsse_close, pin helpers, …) - Full static API via
Microscrap\Bindings\MPSSE\MPSSE - Typed enums for modes, pins, commands, interfaces, endianness, clock rates, and supported devices (FULLY UPPERCASE cases)
- Built on
ext-ftdi^0.7.0+microscrap/ftdi^0.7.0
Requirements
- PHP
^8.4|^8.5|^8.6 - ext-ftdi
^0.7.0— php-io-extensions/ftdi - microscrap/ftdi
^0.7.0 - Runtime dependency of ext-ftdi:
- Debian/Ubuntu/Raspberry Pi OS:
libftdi1-2(dev package for builds:libftdi1-dev) - macOS:
brew install libftdi
- Debian/Ubuntu/Raspberry Pi OS:
Installation
Confirm ext-ftdi is loaded:
php -m | grep ftdi
Install package:
composer require microscrap/mpsse:^0.7.0
Composer autoloads src/Helpers/mpsse.php, registering global helpers when the name is free (function_exists guard).
Suggested peer:
composer require scrapyard-io/gpio-framework:^0.7 # higher adapters
There is no ServiceProvider / Chassis discovery in this package — bindings only.
Usage
Helper style
<?php use Microscrap\Bindings\MPSSE\Enums\MPSSEMode; use Microscrap\Bindings\MPSSE\Enums\MPSSEEndianness; use Microscrap\Bindings\MPSSE\Enums\MPSSEInterface; use Microscrap\Bindings\MPSSE\Enums\MPSSEClockRate; $ctx = mpsse_open( 0x0403, 0x6014, MPSSEMode::SPI0, MPSSEClockRate::ONE_MHZ->value, MPSSEEndianness::MSB, MPSSEInterface::IFACE_A ); if (is_null($ctx)) { throw new RuntimeException('Unable to open MPSSE device'); } mpsse_close($ctx);
Static API style
<?php use Microscrap\Bindings\MPSSE\MPSSE; use Microscrap\Bindings\MPSSE\Enums\MPSSEMode; use Microscrap\Bindings\MPSSE\Enums\MPSSEEndianness; use Microscrap\Bindings\MPSSE\Enums\MPSSEClockRate; use Microscrap\Bindings\MPSSE\Enums\MpsseSupportedDevice; $ctx = MPSSE::openDevice( MpsseSupportedDevice::FT232H, MPSSEMode::SPI0, MPSSEClockRate::ONE_MHZ->value, MPSSEEndianness::MSB ); if (! $ctx->open) { throw new RuntimeException(MPSSE::errorString($ctx)); } MPSSE::start($ctx); MPSSE::write($ctx, "\x9F"); // SPI flash JEDEC ID command (example) $id = MPSSE::read($ctx, 3); MPSSE::stop($ctx); MPSSE::close($ctx);
Global Helper API
Helpers are defined only when the name is free (function_exists guard).
mpsse_open(...): ?Microscrap\Bindings\MPSSE\MPSSEContext
Wrapper for MPSSE::open(...). Returns null if the underlying context did not open. Optional string &$error receives MPSSE::errorString(...) on failure.
mpsse_close(Microscrap\Bindings\MPSSE\MPSSEContext $context): void
Wrapper for MPSSE::close(...).
mpsse_check_ftdi_device(string $device): bool
Returns whether $device matches a FtdiProductId case name.
mpsse_configure_pin_direction(MPSSEContext $ctx, int $pin, bool $asOutput): int
Wrapper for MPSSE::configurePinDirection(...).
mpsse_pin_high / mpsse_pin_low / mpsse_pin_state / mpsse_read_pins
Thin wrappers for the matching MPSSE:: pin helpers.
Static Method API
All methods below are static methods on Microscrap\Bindings\MPSSE\MPSSE.
Open/close
openSupported(MPSSEMode $mode, int $freq, MPSSEEndianness $endianness): ?MPSSEContextopen(int $vid, int $pid, MPSSEMode $mode, int $freq, MPSSEEndianness $endianness, MPSSEInterface $iface, string $description = '', ?string $serial = null): MPSSEContextopenDevice(MpsseSupportedDevice $device, MPSSEMode $mode, int $freq, MPSSEEndianness $endianness, MPSSEInterface $iface = MPSSEInterface::IFACE_A, ?string $serial = null): MPSSEContextopenIndex(int $vid, int $pid, MPSSEMode $mode, int $freq, MPSSEEndianness $endianness, MPSSEInterface $iface, string $description, ?string $serial, int $index): MPSSEContextclose(MPSSEContext $ctx): voiderrorString(?MPSSEContext $ctx): string
Mode/clock/session controls
setMode(MPSSEContext $ctx, MPSSEEndianness $endianness): intenableBitmode(MPSSEContext $ctx, bool $tf): voidsetClock(MPSSEContext $ctx, int $freq): intgetClock(MPSSEContext $ctx): intgetVid(MPSSEContext $ctx): intgetPid(MPSSEContext $ctx): intgetDescription(MPSSEContext $ctx): stringsetLoopback(MPSSEContext $ctx, bool $enable): intsetCSIdle(MPSSEContext $ctx, bool $idle): voiddisableHardwareChipSelect(MPSSEContext $ctx): intenableHardwareChipSelect(MPSSEContext $ctx): intflushAfterRead(MPSSEContext $ctx, bool $tf): voidstart(MPSSEContext $ctx): intstop(MPSSEContext $ctx): int
Data transfer
write(MPSSEContext $ctx, string $data): intread(MPSSEContext $ctx, int $size): ?stringwriteBits(MPSSEContext $ctx, int $bits, int $size): intreadBits(MPSSEContext $ctx, int $size): inttransfer(MPSSEContext $ctx, string $data): ?stringfastWrite(MPSSEContext $ctx, string $data): intfastRead(MPSSEContext $ctx, int $size): ?stringfastTransfer(MPSSEContext $ctx, string $wdata): ?string
ACK/NACK controls (I2C-oriented)
getAck(MPSSEContext $ctx): intsetAck(MPSSEContext $ctx, int $ack): voidsendAcks(MPSSEContext $ctx): voidsendNacks(MPSSEContext $ctx): void
GPIO/bitbang helpers
pinHigh(MPSSEContext $ctx, int $pin): intpinLow(MPSSEContext $ctx, int $pin): intsetDirection(MPSSEContext $ctx, int $direction): intwritePins(MPSSEContext $ctx, int $data): intreadPins(MPSSEContext $ctx): intpinState(MPSSEContext $ctx, int $pin, int $state): intconfigurePinDirection(MPSSEContext $ctx, int $pin, bool $asOutput): inttristate(MPSSEContext $ctx): int
Misc
version(): int
Enums
This package ships typed enums in Microscrap\Bindings\MPSSE\Enums:
MPSSEModeMPSSEInterfaceMPSSEEndiannessMPSSEClockRateMPSSECommandMPSSEAckMPSSEPinMPSSEGpioPinMpsseSupportedDevice
Cases are FULLY UPPERCASE. No class-level constants.
Testing (Pest v4)
Run the feature suite:
./vendor/bin/pest
Run with coverage:
XDEBUG_MODE=coverage ./vendor/bin/pest --coverage
Feature coverage includes:
ext-ftdiinstallation check (extension_loaded('ftdi')+ semantic version format check)- No-hardware fallback paths: invalid VID/PID open failure and closed-context guard behavior
- FT232H hardware workflows (open → configure → start → transfer → stop → close)
- SPI loopback, GPIO pin control, bitbang, and I2C session/ACK flows in required call order
- Wrong-workflow assertions on mode mismatches
- Helper workflow path:
mpsse_open(...)/mpsse_close(...)on real hardware
License
MIT. See LICENSE.md.