The London Perl and Raku Workshop takes place on 26th Oct 2024. If your company depends on Perl, please consider sponsoring and/or attending.

NAME

Device::FTDI::MPSSE - use the MPSSE mode of an FDTI chip

DESCRIPTION

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:

FUTURES AND BUFFERING

Unlike most Future-returning modules, it is not usually necessary to actually store the results of returned Future instances from most of these methods. The $mpsse object itself will store them.

Especially in cases of set_* or 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.

CONSTRUCTOR

new

$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.

METHODS

Any of the following methods documented with a trailing ->get call return Future instances.

set_bit_order

$mpsse->set_bit_order( $lsbfirst )

Configures the bit order of subsequent "write_bytes" or "readwrite_bytes" calls.

Takes either of the following exported constants

MSBFIRST, LSBFIRST

set_clock_edges

$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

CLOCK_FALLING, CLOCK_RISING

write_bytes

read_bytes

readwrite_bytes

$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 write_ and 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 DO pin.

For the read_ and readwrite_ methods, the returned future will yield the bytes that were received in the DI pin during this time.

write_bits

read_bits

readwrite_bits

$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.

For the write_ and 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.

For the read_ and 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.

write_gpio

$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.

read_gpio

$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.

tris_gpio

$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

DBUS, CBUS

set_loopback

$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.

set_clock_divisor

$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 )

set_clkdiv5

$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.

set_3phase_clock

$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.

set_adaptive_clock

$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.

set_open_collector

$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.

sleep

$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.

TODO

  • Implement future await semantics when pending read and alarms are both present. This will require working out how libftdi works with timeouts.

AUTHOR

Paul Evans <leonerd@leonerd.org.uk>