microscrap / mpsse
The MPSSE package that extends the FTDI Package
Requires
- php: ^8.3
- ext-ftdi: ^0.4.0
- microscrap/ftdi: ^0.5.0
Requires (Dev)
- pestphp/pest: ^4
This package is auto-updated.
Last update: 2026-07-06 19:33:26 UTC
README
PHP library that provides MPSSE-oriented SPI/I2C/GPIO operations on top of microscrap/ftdi and the ext-ftdi extension.
This package includes:
- Global helper functions (
mpsse_open,mpsse_close) - A full static-object API via
Microscrap\Bindings\MPSSE\MPSSE - Typed enums for modes, pins, commands, interfaces, endianness, and common clock rates
Requirements
- PHP 8.3+
ext-ftdi^0.4.0microscrap/ftdi^0.4.0
Installation
Confirm ext-ftdi is loaded:
php -m | grep ftdi
Install package:
composer require microscrap/mpsse
Composer autoloads src/Helpers/mpsse.php, which registers global helpers.
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 ($ctx === null) { throw new RuntimeException('Unable to open MPSSE device'); } mpsse_close($ctx);
Static object 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
mpsse_open(...): ?Microscrap\Bindings\MPSSE\MPSSEContext
Wrapper for MPSSE::open(...). Returns null if the underlying context did not open.
mpsse_close(Microscrap\Bindings\MPSSE\MPSSEContext $context): void
Wrapper for MPSSE::close(...).
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
Testing (Pest v4)
Run the feature suite:
./vendor/bin/pest
Run with coverage:
XDEBUG_MODE=coverage ./vendor/bin/pest --coverage
Implemented 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 (SPI transfer in I2C session, bitbang controls in SPI session)
- Helper workflow path:
mpsse_open(...)/mpsse_close(...)on real hardware - Latest measured total line coverage with FT232H attached:
75.0%
Code Completion Scan Results
Source scan summary (from current code):
src/MPSSE.php:41public static methodssrc/Helpers/mpsse.php:2global helper functionssrc/Enums:9enum types
README API sections are aligned to the current scanned symbols.
License
MIT. See LICENSE.md.