def get_ports(cls, serial: str = None): found_devices = [] if serial is not None: if not serial.endswith('(I2C)'): return found_devices serial = serial[:-5] try: found = Ftdi.find_all([(Ftdi.DEFAULT_VENDOR, 0x6014)], nocache=True) except USBError: return found_devices except ValueError: return found_devices for d in found: if serial is not None: if d[2] == serial: found_devices.append(cls(d[2])) return found_devices else: found_devices.append(cls(d[2])) return found_devices
def find(): supported = {'pm342': (0x0403, 0x6011)} vps = supported.values() products = [] for vid, pid, serial, interfaces, description in Ftdi.find_all(vps): product = Product(vid, pid, description, serial) products.append(product) return products
def get_ports(cls, serial=None): found_devices = list() found = Ftdi.find_all([(Ftdi.DEFAULT_VENDOR, 0x6014)]) for d in found: if serial is not None: if d[2] == serial: return cls(d[0], d[1], d[2], d[3], d[4]) else: found_devices.append(cls(d[0], d[1], d[2], d[3], d[4])) return found_devices
class FTDI_DAQ(Instrument): _ports = [] _port = None _last_byte = chr(0) _aliases = {} def __init__(self, name, serial=None, port='A', baudrate=115200): ''' discover and initialize Tunnel_DAC hardware Input: serial - serial number of the FTDI converter channel - 2 character channel id the DAC is connected to; the first byte identifies the channel (A..D for current devices) the second byte identifies the bit within that channel (0..7) numdacs - number of DACs daisy-chained on that line delay - communications delay assumed between PC and the USB converter ''' logging.info(__name__ + ': Initializing instrument Tunnel_DAC') Instrument.__init__(self, name, tags=['physical']) self._conn = Ftdi() # VIDs and PIDs of converters used vps = [ (0x0403, 0x6011), # FTDI UM4232H 4ch (0x0403, 0x6014) # FTDI UM232H 1ch ] # explicitly clear device cache of UsbTools #UsbTools.USBDEVICES = [] # find all devices and obtain serial numbers devs = self._conn.find_all(vps) # filter list by serial number if provided if (serial != None): devs = [dev for dev in devs if dev[2] == serial] if (len(devs) == 0): logging.error(__name__ + ': failed to find matching FTDI devices.') elif (len(devs) > 1): logging.error( __name__ + ': more than one converter found and no serial number given.') logging.info(__name__ + ': available devices are: %s.' % str([dev[2] for dev in devs])) vid, pid, self._serial, ports, description = devs[0] self._ports = [chr(ord('A') + i) for i in range(ports)] # open device (self._port, bit) = self._parse_channel_string(port) self._conn.open(vid, pid, interface=ord(self._port) - ord('A') + 1, serial=self._serial) logging.info(__name__ + ': using converter with serial #%s' % self._serial) self._conn.set_bitmode(0xFF, Ftdi.BITMODE_BITBANG) self._set_baudrate(baudrate) # provide user interface self.add_parameter('port', type=str, flags=Instrument.FLAG_GET) #self.add_parameter('aliases', type=types.DictType, flags=Instrument.FLAG_GETSET) self.add_function('digital_out') self.add_function('digital_stream') self.add_function('set_aliases') self.add_function('get_aliases') def do_get_port(self): return self._port def set_aliases(self, aliases): ''' define channel aliases accepts a dictionary that resolves alias names to internal channel names ''' self._aliases = aliases def get_aliases(self): ''' retrieve channel aliases ''' return self._aliases def digital_out(self, channel, status): ''' set a bit/byte on a FTDI channel ''' (port, bit) = self._parse_channel_string(channel) if (bit != None): if (status): byte = chr(ord(self._last_byte) | (1 << bit)) else: byte = chr(ord(self._last_byte) & ~(1 << bit)) else: byte = chr(0xff) if status else chr(0) self._conn.write_data(byte) self._last_byte = byte def digital_stream(self, channel, samples, rate): ''' write a serial bit/byte stream to the device rate max 6 MHz for ft4232h chip ''' (port, bit) = self._parse_channel_string(channel) # convert bit stream into byte stream if (bit != None): byte = 1 << bit samples = [(chr(ord(self._last_byte) | byte) if x else (chr(ord(self._last_byte) & ~byte))) for x in BitArray(samples)] # output data on the device self._set_baudrate(rate) self._conn.write_data(''.join(samples)) self._last_byte = samples[-1] def _parse_channel_string(self, channel): ''' parses a channel string into a (port, bit) tuple ''' # translate aliases if (self._aliases.has_key(channel)): channel = self._aliases[channel] # parse & mangle channel string m = re.match('(?P<port>[A-Z]+[0-9]*)(?P<bit>:[0-9]+)?', channel).groupdict() if (m == None): raise ValueError('channel identifier %s not understood.' % channel) port = m['port'] if (m['bit'] != None): bit = int(m['bit'].lstrip(':')) else: bit = None # check if the channel exists on this device if (not (port in self._ports)): raise ValueError('prot %s not supported by this device.' % port) if ((self._port != None) and (port != self._port)): raise ValueError( 'this implementation can not change the port identifier outside __init__.' ) if ((bit != None) and ((bit < 0) or (bit > 7))): raise ValueError('bit number must be between 0 and 7, not %d.' % bit) return (port, bit) def _set_baudrate(self, baudrate): ''' change baud rate of the FTDIs serial engine ''' # 80k generates bit durations of 12.5us, 80 is magic :( # magic?: 4 from incorrect BITBANG handling of pyftdi, 2.5 from 120MHz instead of 48MHz clock of H devices self._baudrate = baudrate self._conn.set_baudrate(baudrate / 80)
from pyftdi.ftdi import Ftdi import codecs import sys import time from random import randint VID = 0x0403 PID = 0x6010 #BAUDRATE = 9600 BAUDRATE = 921600 if __name__ == '__main__': ft = Ftdi() dev_list = ft.find_all([(VID, PID)], True) if (len(dev_list) > 0): print("Device found:\n\t", dev_list) ft.open(vendor=VID, product=PID, interface=2) print("Opened device!") # if you don't do this, first byte sent never arrives to the other side # if you happen to know why, let us know :) # dummy = self.ft.read_data(1) #empty buffer else: print("Device not connected!") exit() ft.set_baudrate(BAUDRATE) print("Baudrate set to {}".format(BAUDRATE)) #ft.read_data_bytes(1) N = 2 i = 0 fifo_rd = []
from pyftdi.ftdi import Ftdi from time import sleep ftdi1 = Ftdi() ftdi1.open(vendor=0x403, product=0x6015, interface=1) vps = [(0x0403, 0x6015)] for x in range(5): print("If#1: ", hex(ftdi1.poll_modem_status())) print("Read Pins:", bin(ftdi1.read_pins())) print("Devices:", bin(ftdi1.find_all(vps))) sleep(0.500) ftdi1.close()
import pygame import time # Pygame init pygame.init() size = width, height = 752, 480 black = 0, 0, 0 screen = pygame.display.set_mode(size) ls = [(0x0403, 0x6014)] datasize = 16 + 752 * 480 + 752 + 16 ret = Ftdi() print(ret.find_all(ls)) ret.open(1027, 24596) ret.set_bitmode(0xff, 0) time.sleep(1) ret.set_bitmode(0xff, 0x40) ret.set_latency_timer(2) ret.read_data_set_chunksize(65536) ret.write_data_set_chunksize(65536) ret.set_flowctrl('hw') try: ret.write_data(b'S') except ValueError: print('Cannot write')
#!/usr/bin/env python from pyftdi.ftdi import Ftdi ft232h_pid = (Ftdi.PRODUCT_IDS[Ftdi.FTDI_VENDOR]['ft232h']) id_tuple = (Ftdi.FTDI_VENDOR, ft232h_pid) devices = Ftdi.find_all([id_tuple]) if devices: for device in devices: print(device) else: print('No FT232H devices found.')
class FTDI_DAQ(Instrument): _ports = [] _port = None _last_byte = chr(0) _aliases = {} def __init__(self, name, serial = None, port = 'A', baudrate = 115200): ''' discover and initialize Tunnel_DAC hardware Input: serial - serial number of the FTDI converter channel - 2 character channel id the DAC is connected to; the first byte identifies the channel (A..D for current devices) the second byte identifies the bit within that channel (0..7) numdacs - number of DACs daisy-chained on that line delay - communications delay assumed between PC and the USB converter ''' logging.info(__name__+ ': Initializing instrument Tunnel_DAC') Instrument.__init__(self, name, tags=['physical']) self._conn = Ftdi() # VIDs and PIDs of converters used vps = [ (0x0403, 0x6011), # FTDI UM4232H 4ch (0x0403, 0x6014) # FTDI UM232H 1ch ] # explicitly clear device cache of UsbTools #UsbTools.USBDEVICES = [] # find all devices and obtain serial numbers devs = self._conn.find_all(vps) # filter list by serial number if provided if(serial != None): devs = [dev for dev in devs if dev[2] == serial] if(len(devs) == 0): logging.error(__name__ + ': failed to find matching FTDI devices.') elif(len(devs) > 1): logging.error(__name__ + ': more than one converter found and no serial number given.') logging.info(__name__ + ': available devices are: %s.'%str([dev[2] for dev in devs])) vid, pid, self._serial, ports, description = devs[0] self._ports = [chr(ord('A') + i) for i in range(ports)] # open device (self._port, bit) = self._parse_channel_string(port) self._conn.open(vid, pid, interface = ord(self._port) - ord('A') + 1, serial = self._serial) logging.info(__name__ + ': using converter with serial #%s'%self._serial) self._conn.set_bitmode(0xFF, Ftdi.BITMODE_BITBANG) self._set_baudrate(baudrate) # provide user interface self.add_parameter('port', type=types.StringType, flags=Instrument.FLAG_GET) #self.add_parameter('aliases', type=types.DictType, flags=Instrument.FLAG_GETSET) self.add_function('digital_out') self.add_function('digital_stream') self.add_function('set_aliases') self.add_function('get_aliases') def do_get_port(self): return self._port def set_aliases(self, aliases): ''' define channel aliases accepts a dictionary that resolves alias names to internal channel names ''' self._aliases = aliases def get_aliases(self): ''' retrieve channel aliases ''' return self._aliases def digital_out(self, channel, status): ''' set a bit/byte on a FTDI channel ''' (port, bit) = self._parse_channel_string(channel) if(bit != None): if(status): byte = chr(ord(self._last_byte) | (1<<bit)) else: byte = chr(ord(self._last_byte) & ~(1<<bit)) else: byte = chr(0xff) if status else chr(0) self._conn.write_data(byte) self._last_byte = byte def digital_stream(self, channel, samples, rate): ''' write a serial bit/byte stream to the device ''' (port, bit) = self._parse_channel_string(channel) # convert bit stream into byte stream if(bit != None): byte = 1<<bit samples = [(chr(ord(self._lastbyte) | byte) if x else (chr(ord(self._lastbyte) & ~byte))) for x in BitArray(samples)] # output data on the device self._set_baudrate(rate) self._conn.write_data(samples) self._last_byte = samples[-1] def _parse_channel_string(self, channel): ''' parses a channel string into a (port, bit) tuple ''' # translate aliases if(self._aliases.has_key(channel)): channel = self._aliases[channel] # parse & mangle channel string m = re.match('(?P<port>[A-Z]+[0-9]*)(?P<bit>:[0-9]+)?', channel).groupdict() if(m == None): raise ValueError('channel identifier %s not understood.'%channel) port = m['port'] if(m['bit'] != None): bit = int(m['bit'].lstrip(':')) else: bit = None # check if the channel exists on this device if(not (port in self._ports)): raise ValueError('prot %s not supported by this device.'%port) if((self._port != None) and (port != self._port)): raise ValueError('this implementation can not change the port identifier outside __init__.') if((bit != None) and ((bit < 0) or (bit > 7))): raise ValueError('bit number must be between 0 and 7, not %d.'%bit) return (port, bit) def _set_baudrate(self, baudrate): ''' change baud rate of the FTDIs serial engine ''' # 80k generates bit durations of 12.5us, 80 is magic :( # magic?: 4 from incorrect BITBANG handling of pyftdi, 2.5 from 120MHz instead of 48MHz clock of H devices self._baudrate = baudrate self._conn.set_baudrate(baudrate/80)
class Tunnel_DAC(Instrument): def __init__(self, name, serial = None, channel = 'A0', numdacs=3, delay = 1e-3): ''' discover and initialize Tunnel_DAC hardware Input: serial - serial number of the FTDI converter channel - 2 character channel id the DAC is connected to; the first byte identifies the channel (A..D for current devices) the second byte identifies the bit within that channel (0..7) numdacs - number of DACs daisy-chained on that line delay - communications delay assumed between PC and the USB converter ''' logging.info(__name__+ ': Initializing instrument Tunnel_DAC') Instrument.__init__(self, name, tags=['physical']) self._conn = Ftdi() # VIDs and PIDs of converters used vps = [ (0x0403, 0x6011), # FTDI UM4232H 4ch (0x0403, 0x6014) # FTDI UM232H 1ch ] # explicitly clear device cache of UsbTools #UsbTools.USBDEVICES = [] # find all devices and obtain serial numbers devs = self._conn.find_all(vps) # filter list by serial number if provided if(serial != None): devs = [dev for dev in devs if dev[2] == serial] if(len(devs) == 0): logging.error(__name__ + ': failed to find matching FTDI devices.') elif(len(devs) > 1): logging.error(__name__ + ': more than one converter found and no serial number given.') logging.info(__name__ + ': available devices are: %s.'%str([dev[2] for dev in devs])) vid, pid, self._serial, channels, description = devs[0] # parse channel string if(len(channel) != 2): logging.error(__name__ + ': channel identifier must be a string of length 2. ex. A0, D5.') self._channel = 1 + ord(channel[0]) - ord('A') self._bit = ord(channel[1]) - ord('0') if((self._channel < 1) or (self._channel > channels)): logging.error(__name__ + ': channel %c is not supported by this device.'%(chr(ord('A')+self._channel-1))) if((self._bit < 0) or (self._bit > 7)): logging.error(__name__ + ': subchannel must be between 0 and 7, not %d.'%self._bit) # open device self._conn.open(vid, pid, interface = self._channel, serial = self._serial) logging.info(__name__ + ': using converter with serial #%s'%self._serial) self._conn.set_bitmode(0xFF, Ftdi.BITMODE_BITBANG) # 80k generates bit durations of 12.5us, 80 is magic :( # magic?: 4 from incorrect BITBANG handling of pyftdi, 2.5 from 120MHz instead of 48MHz clock of H devices # original matlab code uses 19kS/s self._conn.set_baudrate(19000/80) # house keeping self._numdacs = numdacs self._sleeptime = (10. + 16.*self._numdacs)*12.5e-6 + delay # 1st term from hardware parameters, 2nd term from USB self._minval = -5000. self._maxval = 5000. self._resolution = 16 # DAC resolution in bits self._voltages = [0.]*numdacs self.add_parameter('voltage', type=types.FloatType, flags=Instrument.FLAG_SET, channels=(1, self._numdacs), minval = self._minval, maxval = self._maxval, units='mV', format = '%.02f') # tags=['sweep'] self.add_function('set_voltages') self.add_function('commit') def _encode(self, data, channel = 0, bits_per_item = 16, big_endian = True): ''' convert binary data into line symbols the tunnel electronic DAC logic box triggers on rising signal edges and samples data after 18us. we use a line code with three bits of duration 12us, where a logical 1 is encoded as B"110" and a logical 0 is encoded as B"100". the line data is returned as a byte string with three bytes/symbol. Input: data - a vector of data entities (usually a string or list of integers) channel - a number in [0, 7] specifying the output bit on the USB-to-UART chip bits_per_item - number of bits to extract from each element of the data vector ''' # build line code for the requested channel line_1 = chr(1<<channel) line_0 = chr(0) line_code = [''.join([line_0, line_1, line_1]), ''.join([line_0, line_1, line_0])] # do actual encoding result = [] result.append(10*line_0) for item in data: for bit in (range(bits_per_item-1, -1, -1) if big_endian else range(0, bits_per_item)): result.append(line_code[1 if(item & (1<<bit)) else 0]) result.append(10*line_0) return ''.join(result) def commit(self): ''' send updated parameter values to the physical DACs via USB ''' # normalize, scale, clip voltages voltages = [-1+2*(x-self._minval)/(self._maxval-self._minval) for x in self._voltages] voltages = [max(-2**(self._resolution-1), min(2**(self._resolution-1)-1, int(2**(self._resolution-1)*x))) for x in voltages] # encode and send data = self._encode(reversed(voltages), self._bit, self._resolution) self._conn.write_data(data) # wait for the FTDI fifo to clock the data to the DACs sleep(self._sleeptime) def do_set_voltage(self, value, channel): ''' immediately update voltage on channel ch parameter checking is done by qtlab ''' self._voltages[channel-1] = value self.commit() def set_voltages(self, valuedict): ''' update voltages on several channels simultaneously todo: update instrument panel display ''' for channel, value in valuedict.iteritems(): # bounds checking & clipping if((channel < 1) or (channel > self._numdacs)): logging.error(__name__ + ': channel %d out of range.'%channel) continue value = float(value) if((value < self._minval) or (value >= self._maxval)): logging.error(__name__ + ': value %f out of range. clipping.'%value) value = max(self._minval, min(self._maxval, value)) # does not handle maxval correctly self._voltages[channel-1] = value self.commit()