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
- PHP 8.3+
ext-ftdi^0.4.0microscrap/ftdi^0.4.0
Confirm ext-ftdi is loaded:
php -m | grep ftdiInstall package:
composer require microscrap/mpsseComposer autoloads src/Helpers/mpsse.php, which registers global helpers.
<?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);<?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);Wrapper for MPSSE::open(...). Returns null if the underlying context did not open.
Wrapper for MPSSE::close(...).
All methods below are static methods on Microscrap\Bindings\MPSSE\MPSSE.
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
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
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
getAck(MPSSEContext $ctx): intsetAck(MPSSEContext $ctx, int $ack): voidsendAcks(MPSSEContext $ctx): voidsendNacks(MPSSEContext $ctx): void
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
version(): int
This package ships typed enums in Microscrap\Bindings\MPSSE\Enums:
MPSSEModeMPSSEInterfaceMPSSEEndiannessMPSSEClockRateMPSSECommandMPSSEAckMPSSEPinMPSSEGpioPinMpsseSupportedDevice
Run the feature suite:
./vendor/bin/pestRun with coverage:
XDEBUG_MODE=coverage ./vendor/bin/pest --coverageImplemented 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%
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.
MIT. See LICENSE.md.