Device::FTDI::MPSSE - use the MPSSE mode of an FDTI chip
This module provides convenient methods to access the Multi-Protocol Synchronous Serial Engine (MPSSE) mode of certain FTDI chips. It provides methods to wrap the various commands that control the MPSSE and interpret their responses.
The following subclasses exist to simplify implementation of particular serial protocols:
Especially in cases of
write_ methods, the caller is free to drop them in void context.
You should, however, be aware of the deferred nature of the activities of these methods. The reason they return futures is that none of these methods really acts immediately on the chip. Instead, pending commands are stored internally in a buffer, and emitted at once to the chip over USB, where it can act on them all, and send all the responses at once. The reason to do this is to gain a much improved performance over the USB connection.
Because of this, while it is not necessary to wait on or call "get" in Future on every returned future, it is required that the very last of a sequence of operations is waited on (usually by calling its
get method). When implementing library functions it is usually sufficient simply to let the last operation be returned in non-void context to the caller, so the caller can await it themself.
$mpsse = Device::FTDI::MPSSE->new( %args )
An instance of this class needs a Device::FTDI object to operate on. Either it can be provided as a single named argument called
ftdi, or this constructor will build one by passing the other named arguments to "new" in Device::FTDI, except that it applies a default
product parameter of the product ID identifying the FT232H device.
This constructor performs all the necessary setup to initialse the MPSSE.
Any of the following methods documented with a trailing
->get call return Future instances.
$mpsse->set_bit_order( $lsbfirst )
Takes either of the following exported constants
$mpsse->set_clock_edges( $rdclock, $wrclock )
Configures the clocking sense of subsequent read or write operations.
Each value should be one of the following constants
$mpsse->write_bytes( $data_out )->get $data_in = $mpsse->read_bytes( $len )->get $data_in = $mpsse->readwrite_bytes( $data_out )->get
Perform a bytewise clocked serial transfer. These are the "main" methods of the class; they invoke the main core of the MPSSE.
In each case, the
CLK pin will count the specified length of bytes of transfer. For the
readwrite_ methods this count is implied by the length of the inbound buffer; during the operation the specified bytes will be sent out of the
readwrite_ methods, the returned future will yield the bytes that were received in the
DI pin during this time.
$mpsse->write_bits( $bitlen, $bits_out )->get $bits_in = $mpsse->read_bits( $bitlen )->get $bits_in = $mpsse->readwrite_bits( $bitlen, $bits_out )->get
Performs a bitwise clocked serial transfer of between 1 and 8 single bits.
In each case, the
CLK pin will count the specified length of bits of transfer.
readwrite_ methods individal bits of the given byte will be clocked out of the
DO pin. In
MSBFIRST mode, this will start from the highest bit of the byte; in
LSBFIRST mode, this will start from the lowest. The remaining bits will be ignored.
readwrite_ methods, the returned future will yield the bits that were received in the
DI pin during this time. In
MSBFIRST mode, the bits returned by the chip will start from the highest bit of the byte; in
LSBFIRST they will start from the lowest. The other bits will be set to zero.
$mpsse->write_gpio( $port, $val, $mask )->get
Write a new value to the pins on a GPIO port, setting them to outputs. This method affects only the pins specified by the
$mask bitmask, on the specified port. Pins not covered by the mask remain unaffected; they remain in their previous driven or input state.
$val = $mpsse->read_gpio( $port, $mask )->get
Reads the state of the pins on a GPIO port. The returned future will yield an 8-bit integer. This method sets the pins covered by
$mask as inputs. Pins not covered by the mask remain unaffected; they remain in their previous driven or input state.
$mpsse->tris_gpio( $port, $mask )->get
"tristate" the pins on a GPIO port; i.e. set them as high-Z inputs rather than driven outputs. This method affects only the pins specified by the
$mask bitmask, on the specified port. Pin not covered by the mask remain unaffected. This is equivalent to
read_gpio except that it does not consume an extra byte of return value.
In each of the above methods, the GPIO port is specified by one of the following exported constants
$mpsse->set_loopback( $on )->get
If enabled, loopback mode bypasses the actual IO pins from the chip and connects the chip's internal output to its own input. This can be useful for testing whether the chip is mostly functioning correctly.
$mpsse->set_clock_divisor( $div )->get
Sets the divider the chip uses to determine the output clock frequency. The eventual frequency will be
$freq_Hz = 12E6 / (( 1 + $div ) * 2 )
$mpsse->set_clkdiv5( $on )->get
Disables or enables the divide-by-5 clock prescaler.
Some FTDI chips are capable of faster clock speeds. These chips use a base frequency of 60MHz rather than 12MHz, but divide it down by 5 by default to remain compatible with code unaware of this. To access the higher speeds available on these chips, disable the divider by using this method. The clock rate implied by
set_clock_divisor will then be 5 times faster.
$mpsse->set_3phase_clock( $on )->get
If enabled, data is clocked in/out using a 3-phase strategy compatible with the I2C protocol. If this is set, the effective clock rate becomes 2/3 that implied by the clock divider.
$mpsse->set_adaptive_clock( $on )->get
If enabled, the chip waits for acknowledgement of a clock signal on the
GPIOL3 pin before continuing for every bit transferred. This may be used by ARM processors.
$mpsse->set_open_collector( $dbus, $cbus )->get
Only on FT232H chips.
Enables open-collector mode on the output pins given by the bitmasks. This mode is useful to avoid bus drive contention, especially when implementing I2C.
$mpsse->sleep( $secs )->get
Returns a future that becomes done after the given delay time, in (fractional) seconds.
Note that this method is currently experimental, and only behaves correctly when either a read future or a sleep future are outstanding. If there are both then the current implementation will fail with an exception.
Implement future await semantics when pending read and alarms are both present. This will require working out how libftdi works with timeouts.
Paul Evans <firstname.lastname@example.org>