NAME

Device::Chip::Adapter - an abstraction of a hardware communication device

DESCRIPTION

This package describes an interfaces tha classes can use to implement a driver to provide access to some means of connecting an electronic chip or hardware module to a computer. An instance implementing this interface provides some means to send electrical signals to a connected chip or module, and receive replies back from it; this device is called the adapter. This is provided as a service to some instance of the related interface, Device::Chip.

It is suggested that a driver for a particular adapter provides a concrete class named within the Device::Chip::Adapter heirarchy, adding the basic name of the product or means of communication as a suffix; for example the driver for communication device based on the FDTI range of devices would be called:

   package Device::Chip::Adapter::FTDI;

This package provides a base class that such a specific implementation class could use as a superclass, but it is not required to. The important detail is that it provides the interface described by this documentation.

UTILITY CONSTRUCTOR

new_from_description

   $adapter = Device::Chip::Adapter->new_from_description( $DESC )

This utility method is provided to allow end-user programs a convenient way to construct a useable Device::Chip::Adapter instance from a given single string value. This string takes the form of a the main name of the adapter class (minus the leading Device::Chip::Adapter:: prefix), optionally followed by a single colon and some comma-separated options. Each option takes the form of a name and value, separated by equals sign. For example:

   FTDI
   FTDI:
   FTDI:product=0x0601
   BusPirate:serial=/dev/ttyUSB3,baud=57600

This utility method splits off the base name from the optional suffix, and splits the options into an even-sized name/value list. It loads the class implied by the base name and invokes a method called new_from_description on it. This is passed the even-sized name/value list obtained by splitting the option string. Any option named without a value will be passed having the value 1, as a convenience for options that are simple boolean flags.

If the class does not provide the new_from_description method (and of course, simply inheriting the base class one from here does not count), then if there are no other options given, the plain new constructor is invoked instead. If this is not possible because there are user-specified options that must be honoured, then an exception is thrown instead.

Note for example that in the case above, the product option would be passed to the FTDI adapter class still as a string value; it is likely that this class would want to implement a new_from_description method to parse that using the oct operator into a plain integer.

It is intended that this method is used for creating an adapter that a standalone program can use from a description string specified by the user; likely in a commandline option or environment variable.

METHODS

The following methods documented with a trailing call to ->get return Future instances.

make_protocol

   $protocol = $adapter->make_protocol( $pname )->get

Returns an object that satisfies one of the interfaces documented below in "PROTOCOLS", depending on the protocol name given by $pname. This should be one of the following values:

   GPIO
   SPI
   I2C

It is unspecified what class these objects should belong to. In particular, it is permitted that an adapter could even return itself as the protocol implementation, provided it has the methods to satisfy the interface for that particular protocol. This is especially convenient in the case that the adapter is only capable of one kind of protocol.

shutdown

   $adapter->shutdown

Shuts down the adapter in whatever manner is appropriate at the end of the lifetime of the containing program; or at least, at the point when the program has finished using the connected device.

This method is allowed to block; it does not yield a Future. It is suitable to call from a DESTROY method or END block.

PROTOCOLS

The following methods are common to all protocol instances:

sleep

   $protocol->sleep( $secs )->get

Causes a fixed delay, given in (fractional) seconds. Adapter module authors should attempt to perform this delay concurrently, overlapping IO with other operations where possible.

configure

   $protocol->configure( %args )->get

Sets configuration options for the protocol. The actual set of options available will depend on the type of the protocol.

Chip drivers should attempt to bundle their changes together into as few configure calls as possible, because adapters may find it most efficient to apply multiple changes in one go.

power

   $protocol->power( $on )->get

Switches on or off the power to the actual chip or module, if such ability is provided by the adapter.

list_gpios

   @pin_names = $protocol->list_gpios

Returns a list of the names of GPIO pins that are available for the chip driver to use. This list would depend on the pins available on the adapter itself, minus any pins that are in use by the protocol itself.

Adapters should name GPIO pins in a way that makes sense from the hardware; for example MOSI, SDA, DTR, Q0, etc...

write_gpios

   $protocol->write_gpios( \%pin_values )->get

Sets the named GPIO pins as driven outputs, and gives their new values. Any GPIO pins not named are left as they are; either driving outputs at the current state, or high-impedence inputs.

Pins are specified as a HASH reference, mapping pin names (as returned by the "list_gpios" method) to boolean logic levels.

read_gpios

   \%pin_values = $protocol->read_gpios( \@pin_names )->get;

Sets the named GPIO pins as high-impedence inputs, and reads their current state. Any GPIO pins not named here are left as they are; either driving outputs at the current state, or other inputs.

Pins are specified in an ARRAY reference giving the names of pins (as returned by the "list_gpios" method); read values are given in the returned HASH reference which maps pin names to boolean logic levels.

tris_gpios

   $protocol->tris_gpios( \@pin_names )->get;

Sets the named GPIO pins as high-impedence inputs ("tristate"). Any GPIO pins not named here are left as they are.

This method is similar to "read_gpios" except that it does not return the current pin values to the caller. Adapter implementations may implement this by simply calling "read_gpios" or they may have a more efficient variant that does not have to transfer these extra readings back from the adapter hardware.

GPIO PROTOCOL

The GPIO protocol adds no new abilities or methods; it is the most basic form of protocol that simply provides access to the generic GPIO pins of the device.

SPI PROTOCOL

Configuration Options

The following configuration options are recognised:

mode => 0 | 1 | 2 | 3

The numbered SPI mode used to communicate with the chip.

max_bitrate => INT

The highest speed, in bits per second, that the chip can accept. The adapter must pick a rate that is no higher than this. Note specifically that not all adapters are able to choose a rate arbitrarily, and so the actually communication may happen at some rate slower than this.

wordsize => INT

The number of bits per word transferred. Many drivers will not be able to accept a number other than 8.

For values less than 8, the value should be taken from the least-significant bits of each byte given to the readwrite or write methods.

For values greater than 8, use character strings with wide codepoints inside; such as created by the chr() function.

readwrite

   $words_in = $spi->readwrite( $words_out )->get

Performs a complete SPI transaction; assert the SS pin, synchronously clock the data given by the $words_out out of the MOSI pin of the adapter while simultaneously capturing the data coming in to the MISO pin, then release the SS pin again. The values clocked in are eventually returned as the result of the returned future.

write

   $spi->write( $words )->get

A variant of readwrite where the caller does not intend to make use of the data returned by the device, and so the adapter does not need to return it. This may or may not make a material difference to the actual communication with the adapter or device; it could be implemented simply by calling the readwrite method and ignoring the return value.

read

   $words = $spi->read( $len )->get

A variant of readwrite where the chip will not care what data is written to it, so the caller does not need to supply it. This may or may not make a material difference to the actual communication with the adapter or device; it could be implemented simply by calling the readwrite method and passing in some constant string of appropriate length.

write_then_read

    $words_in = $spi->write_then_read( $words_out, $len_in )->get

Performs a complete SPI transaction; assert the SS pin, synchronously clock the data given by $words_out out of the MOSI pin of the adapter, then clock in more data from the MISO pin, finally releasing the SS pin again. These two operations must be performed within a single assert-and-release SS cycle. It is unspecified what values will be sent out during the read phase; adapters should typically send all-bits-low or all-bits-high, but in general may not allow configuration of what that will be.

This differs from the /readwrite method in that it works sequentially; sending out words while ignoring the result, then reading in words while sending unspecified data.

assert_ss

release_ss

   $spi->assert_ss->get

   $spi->release_ss->get

Lower-level access methods to directly assert or release the SS pin of the adapter. These would typically be used in conjunction with "readwrite_no_ss" or "write_no_ss".

readwrite_no_ss

write_no_ss

read_no_ss

   $words_in = $spi->readwrite_no_ss( $words_out )->get

   $spi->write_no_ss( $words )->get

   $words = $spi->read_no_ss( $len )->get

Lower-level access methods to directly perform a data transfer across the MOSI/MISO pins of the adapter, without touching the SS pin. A complete SPI transaction can be performed in conjunction with the "assert_ss" and "release_ss" methods.

   $spi->assert_ss
      ->then( sub {
         $spi->readwrite_no_ss( $words_out );
      })
      ->then( sub {
         ( $words_in ) = @_;
         $spi->release_ss->then_done( $words_in );
      });

These methods are provided for situations where it is not possible to know in advance all the data to be sent out in an SPI transaction; where the chip driver code must inspect some of the incoming data before it can determine what else needs to be sent, but when these must all be sent in one SS-asserted transaction.

Because they perform multiple independent operations on the underlying adapter, these lower-level methods may be less efficient than using the single higher-level methods of "readwrite" and "write". As such, they should only be used when the combined higher-level method cannot be used.

Note that many of these methods can be synthesized from other simpler ones. A convenient abstract base class, Device::Chip::ProtocolBase::SPI, can be used to do this, providing wrappers for some methods implemented using others. This reduces the number of distinct methods that need to be provided. Implementations may still, and are encouraged to, provide "better" versions of those methods if they can be provided more efficiently than simply wrapping others.

I2C PROTOCOL

Configuration Options

The following configuration options are recognised:

addr => INT

The (7-bit) slave address for the chip this protocol is communicating with.

max_bitrate => INT

The highest speed, in bits per second, that the chip can accept. The adapter must pick a rate that is no higher than this. Note specifically that not all adapters are able to choose a rate arbitrarily, and so the actually communication may happen at some rate slower than this.

write

    $i2c->write( $bytes_out )->get

Performs a complete I²C transaction to send the given bytes to the slave chip. This includes the start condition, sending the addressing byte (which is implied; it should not be included in $bytes_out) and ending in the stop condition.

read

    $bytes_in = $i2c->read( $len_in )->get

Performs a complete I²C transaction to receive the given number of bytes back from the slave chip. This includes the start condition, sending the addressing byte and ending in a stop condition.

write_then_read

    $bytes_in = $i2c->write_then_read( $bytes_out, $len_in )->get

Performs a complete I²C transaction to first send the given bytes to the slave chip then reads the give number of bytes back, returning them. These two operations must be performed within a single I²C transaction using a repeated start condition.

AUTHOR

Paul Evans <leonerd@leonerd.org.uk>