FTDI Channel and Base Classes

pybarst.ftdi

FTDI Channel

The Barst FTDI interface. An FTDI channel is a FT device, e.g. the FT2232H which has one or more ports on the device. Each port has a number of digital input / output lines that can be controlled independently.

When a FTDI channel is created, we describe the devices connected to these ports, which could anything from a ADC, to a serial / parallel converter to simple digital input / output pins. The FTDISettings sub-classes are used to initialize these devices.

Driver requirements

In order to create ftdi channels, the ftdi D2XX drivers (http://www.ftdichip.com/Drivers/D2XX.htm) must be installed. In particular, the server dynamically loads the ftd2xx.dll dll from the system path. The server automatically loads the 64 or 32-bit version, depending on whether the server is 32 or 64-bit.

If driver errors arise, either, the driver is not installed, an older version of the driver is installed, or the incorrect 64/32-bit version is installed.

Typical usage

The FTDI channel is different than other channels. For the FTDIChannel, instead of operating on the channel directly, one initializes the channel with FTDISettings derived classes indicating which peripheral FTDIDevice derived devices are connected to the FTDIChannel, and those FTDIDevice devices are manipulated, not the FTDIChannel itself.

So typically, a client creates a FTDIChannel and passes it a list of FTDISettings indicating which peripherals are connected to the FTDIChannel. Then, the client calls FTDIChannel.open_channel() on it, which creates the channel and all its peripherals on the server as well as in the clients FTDIChannel.devices. At that point, other clients can create FTDIChannel instances, which will automatically have their peripherals initialized.

When created, the peripherals themselves are not yet open, so each client has to call open_channel() on the peripherals it wants to communicate with first. Following that, a client can set the global state to active/inactive with set_state() and then start reading/writing to them. Some peripherals support multiple clients reading and/or writing to them at the same time, while others don’t. Some devices support modes where the server continuously reads and sends back data to all the clients that subscribed to the channel.

When a client wants to stop getting data, it can call set_state() to just deactivate the channel, or close_channel_server() to delete the channel from the server altogether, or, close_channel_client() to just close the connection for this client, while leaving the channel’s state on the server unchanged.

Finally, some peripherals support the cancel_read() method, to cancel a continuous read triggered by this client.

Warning

An FTDI channel supports the activation and deactivation of its peripherals independently of each other. When a peripheral is activated, the FTDI channel may change it hardware settings to run as efficiently as possible. As a consequence, the state of the internal buffers may be interrupted. In particular, it’s not recommended to change the state of any peripheral while an FTDIADC is actively sampling because it will disrupt the device.

class pybarst.ftdi.FTDISettings

Bases: object

Base class for the settings describing FTDI devices connected to a FTDI channel. This class is never created directly.

A FTDI channel can control multiple devices connected to its digital pins at the same time. Therefore, when a FTDI channel is created, a list of settings describing each connected device must be supplied to the constructor and is then used by the channel to create the channel and sub-devices for each device connected to the channel. This is the base class for these settings. ADCSettings is an example of a settings class.

See FTDIChannel for more details.

class pybarst.ftdi.FTDIChannel(list channels, BarstServer server, serial=None, desc=None, baudrate=0, **kwargs)

Bases: pybarst.core.server.BarstChannel

An FTDI channel.

An FTDI channel describes a single FTDI device, e.g. a FT2232H or a FT232R. Each FTDI device has one or more peripheral devices connected to it. For example, an ADC board could be interfaced with a PC through the digital port on a FT232R. Similarly, you can read/write directly to the pins of the FTDI channel.

Parameters:
channels: list

A list of instances of FTDISettings derived classes each describing a peripheral device connected to the FTDI port. For each FTDISettings instance, a corresponding FTDIDevice derived class instance (in the same order as in this list) will be created and stored in devices. See devices. Similarly, for each created FTDIDevice instance, FTDIDevice.settings stores the settings with which the device was created.

Note

If this channel already exists on the server, e.g. if a previous client created the channel and now a second client created this channel instance and wants to connect to it. Then this list will be ignored and instead the list of devices will be created from the existing channel on the server, ensuring the devices created are consistent across clients that open them.

server: BarstServer

An instance of a server through which this channel is opened.

serial: bytes

The serial number used to identify the device to open. Either the serial number or the device description, desc, must be provided. See dev_serial for more details.

desc: bytes

The descriptions used to identify the device to open. Either the serial number or the device description, desc, must be provided. See dev_description for more details.

baudrate: unsigned int

The maximum baud rate this channel can use. See baudrate for more details. Defaults to 0. It is not recommended that this be changed.

baudrate

baudrate: ‘DWORD’

The baud rate used by the FTDI channel. The FTDI peripherals run at a specific clock rate controlled by the baud rate. By default, the server sets the channel baudrate to the maximum supported by the devices connected to the channel, as well based on the FTDI channel type.

When supplying a none-zero value for this attribute, the channel baud rate will not exceed that value. Although it is not recommend to change this value, it might be necessary to lower the baud rate here in the face of hardware issues. However, a lower baud rate may adversely affect the devices, in particular the FTDIADC peripheral.

chan_min_buff_in

chan_min_buff_in: ‘DWORD’

Debug information. Describes the number of bytes allocated for the pipe for writing to the server. Read only.

chan_min_buff_out

chan_min_buff_out: ‘DWORD’

Debug information. Describes the number of bytes allocated for the pipe for reading from the server. Read only.

dev_description

dev_description: object

The description of the device. FTDI devices can be opened by their serial numbers and description strings. Read only.

For example:

>>> ft.dev_description
Birch Board rev1 A

Note

For FTDI devices that embed 2 channels in a single device, e.g. the FT2232H, the device still has a single description. So to identify the channel in question, either an A or B is appended to the description.

dev_id

dev_id: ‘DWORD’

The ID of this FTDI device. Read only.

For example:

>>> ft.dev_id
67330064
dev_loc

dev_loc: ‘DWORD’

The location on the USB bus where this FTDI device is connected to. Read only.

For example:

>>> ft.dev_loc
29217
dev_serial

dev_serial: object

The Serial number of this device. Read only.

For example:

>>> ft.dev_serial
FTWR60CBA

Note

For FTDI devices that embed 2 channels in a single device, e.g. the FT2232H, the device still has a single serial number. So to identify the channel in question, either an A or B is appended to the serial number.

dev_type

dev_type: ‘DWORD’

The device type code given by the FTDI driver for this FTDI device. Read only.

For example:

>>> ft.dev_type
6
devices

devices: list

A list of FTDIDevice instances which control the devices connected to this FTDI channel. Each device is a peripheral device connected to the channel, e.g. an ADC, a serial to parallel converter etc. Read only.

>>> server = BarstServer(barst_path=path,
... pipe_name=r'\.\pipe\TestPipe')
>>> server.open_server()
>>> server.get_manager('ftdi')
{'ftdi': {'version': 197127L, 'chan': 0, 'chan_id': 'FTDIMan'}}
# open the channel with two pin devices, one input the other output
>>> read = PinSettings(num_bytes=1, bitmask=0xFF, continuous=False,
... output=False)
>>> write = PinSettings(num_bytes=1, bitmask=0x0F, continuous=False,
... init_val=0xFF, output=True)
# open the channel using its description
>>> ft = FTDIChannel(channels=[read, write], server=server,
... desc='Birch Board rev1 A')
>>> ft.open_channel(alloc=True)
>>> ft.devices
[<pybarst.ftdi.switch.FTDIPinIn object at 0x05338D30>,
<pybarst.ftdi.switch.FTDIPinOut object at 0x05338DB0>]
is_full_speed

is_full_speed: ‘unsigned char’

Describes whether the FTDI channel is a full speed FTDI device. Read only.

is_high_speed

is_high_speed: ‘char’

Describes whether the FTDI channel is a high speed FTDI device. Read only.

is_open

is_open: ‘unsigned char’

Describes whether the FTDI driver has opened this channel. Read only. This does not indicate whether the server has this channel open, just if the driver had it open the last time we checked.

open_channel(self, alloc=False)

See open_channel().

Every time this method is called, devices is updated with a new list of devices. Therefore, any references to the devices that were on the list previously must be updated to the new devices. If the channel already exists on the server, the devices list will be created from the devices which initially created the channel, other devices will be used to create the channel.

Parameters:
alloc: bool

Whether we should create the channel on the server if the channel doesn’t already exist. If False and the channel doesn’t exist yet on the server, an error will be raised. Otherwise, the channel will be created automatically. Defaults to False.

For example:

>>> # create a channel with a read and write pin device
>>> read = PinSettings(num_bytes=1, bitmask=0xFF, continuous=False, output=False)
>>> write = PinSettings(num_bytes=1, bitmask=0x0F, continuous=False, init_val=0xFF, output=True)
>>> ft = FTDIChannel(channels=[read, write], server=server, desc='Birch Board rev1 A')
>>> # create the channel on the server
>>> ft.open_channel(alloc=True)
[<pybarst.ftdi.switch.FTDIPinIn object at 0x05328EB0>, <pybarst.ftdi.switch.FTDIPinOut object at 0x05328F30>]
>>> # close the connection between the client
>>> ft.close_channel_client()
>>> # the channel is still open, but no client is connected
>>> ft.connected
0
>>> # now connect the client again to the exiting channel
>>> ft.open_channel()
[<pybarst.ftdi.switch.FTDIPinIn object at 0x054BF230>, <pybarst.ftdi.switch.FTDIPinOut object at 0x054BF2B0>]
>>> # now delete the channel from the server
>>> ft.close_channel_server()
>>> # re-create the channel on the server
>>> ft.open_channel(alloc=True)
[<pybarst.ftdi.switch.FTDIPinIn object at 0x052F8EB0>, <pybarst.ftdi.switch.FTDIPinOut object at 0x052F8F30>]

In the above example, we created a channel and then closed / opened / deleted / and re-created the channel from a single instance. Similarly, you can create multiple FTDIChannel instances corresponding to the same physical device and do similar operations on each instance independently. However, calling will delete the channel on the server, and all the clients connected will raise exceptions when trying to communicate with it. To resolve it, for each instance you’ll have to call open_channel() to recover the connection to the channel.

set_state(self, int state, flush=False)

Because an FTDI channel is composed of peripheral devices, setting the FTDIChannel itself to inactive/active has no meaning. Therefore, this method doesn’t do anything. Instead, you should set the state of the FTDIDevice instances of the channel.

class pybarst.ftdi.FTDIDevice(int chan, FTDIChannel parent, **kwargs)

Bases: pybarst.core.server.BarstChannel

An abstract class for the peripheral devices that can connect to an FTDI channel.

You don’t instantiate this class or it’s derived classes, instead, it is instantiated by the FTDIChannel in response to FTDISettings instances in its devices parameter and is then stored in its FTDIChannel.devices attribute.

Parameters:
chan: int

The channel number assigned to this channel within the parent FTDI channel.

parent: FTDIChannel

The FTDIChannel of which this device is a peripheral device.

close_channel_server(self)

See close_channel_server() for details. However, you cannot delete a FTDI peripheral device on the server, but instead have to delete the whole FTDIChannel channel. Therefore, this method raises an exception when called.

ft_device_baud

ft_device_baud: ‘DWORD’

The maximum baud rate this device can handle. The channels baud rate is the minimum of all its devices. Read only.

For example:

>>> write.ft_device_baud
200000
ft_device_bitmask

ft_device_bitmask: ‘unsigned char’

The 8-bit bitmask indicating which ports are outputs (1) for this channel. Read only.

For example:

>>> '0b{:08b}'.format(write.ft_device_bitmask)
0b00001111
ft_device_mode

ft_device_mode: ‘unsigned char’

The mode required of this device (whether sync or async bit bang). If both are available we use async. Otherwise, we use the mode supported by all the devices. Read only.

ft_read_device_size

ft_read_device_size: ‘DWORD’

Debug information. The minimum number of bytes required to by this device to read from the FTDI hardware buffer. The actual size is the maximum of all the devices connected to the channel. Read only.

ft_write_buff_size

ft_write_buff_size: ‘DWORD’

Debug information. The maximum number of bytes written / read by the FTDI hardware buffer. The actual read / write buffer size can change as different devices become active / inactive according to their ft_read_device_size and ft_write_device_size , however this is the maximum size, which occurs when all the channel’s devices are active. Read only.

ft_write_device_size

ft_write_device_size: ‘DWORD’

Debug information. The minimum number of bytes required to by this device to write to the FTDI hardware buffer. The actual size is the maximum of all the devices connected to the channel. Read only.

open_channel(self)

See open_channel() for details.

Calling this method will open a new client for communication with the peripheral instance on the server.

parent

parent: pybarst.ftdi._ftdi.FTDIChannel

The FTDIChannel instance to which this device belongs to. Read only.

set_state(self, int state, flush=False)

See set_state() for details.

See the class description for the derived class for more details on how to manipulate state.

settings

settings: pybarst.ftdi._ftdi.FTDISettings

The FTDISettings derived class holding the settings for this peripheral device. Each device type has its corresponding FTDISettings class. Read only.