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.
readwrite
$bytes_in = $spi->readwrite( $bytes_out )->get
Performs a complete SPI transaction; assert the SS pin, synchronously clock the data given by the plain byte string $bytes_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 bytes clocked in are eventually returned as the result of the returned future.
write
$spi->write( $bytes )->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.
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
$bytes_in = $spi->readwrite_no_ss( $bytes_out )->get
$spi->write_no_ss( $bytes )->get
Lower-level access methods to directly perform a byte 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( $bytes_out );
})
->then( sub {
( $bytes_in ) = @_;
$spi->release_ss
});
These methods are provided for situations where it is not possible to know in advance all the bytes to be sent out in an SPI transaction; where the chip driver code must inspect some of the bytes incoming 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. However, as an implementation detail, a device adapter module could implement the higher- level methods by using the lower ones as described above, if that would be an efficient implementation.
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>