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 eachFTDISettings
instance, a correspondingFTDIDevice
derived class instance (in the same order as in this list) will be created and stored indevices
. Seedevices
. Similarly, for each createdFTDIDevice
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, otherdevices
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 callopen_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 theFTDIDevice
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 toFTDISettings
instances in its devices parameter and is then stored in itsFTDIChannel.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 wholeFTDIChannel
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
andft_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 correspondingFTDISettings
class. Read only.