Python 基于 FTDI FT2232H 实现 SPI 通信控制
本文介绍了使用 Python 语言配合 ctypes 库调用 FTDI ftd2xx.dll 动态链接库,通过 FT2232H 芯片的 MPSSE 模式实现 SPI 通信控制的代码示例。
核心功能
- 设备初始化与 MPSSE 模式配置
- 时钟频率设置与 CS 信号控制
- 寄存器读写(单字节、连续、增量)
- EEPROM 操作支持
代码实现
import os
import time
import array
import ctypes
from ctypes import *
from enum import Enum
import math
import re
class Device_status(Enum):
FT_OK = 0
FT_INVALID_HANDLE = 1
FT_DEVICE_NOT_FOUND = 2
FT_DEVICE_NOT_OPENED = 3
FT_IO_ERROR = 4
FT_INSUFFICIENT_RESOURCES = 5
FT_INVALID_PARAMETER = 6
FT_INVALID_BAUD_RATE = 7
FT_DEVICE_NOT_OPENED_FOR_ERASE = 8
FT_DEVICE_NOT_OPENED_FOR_WRITE = 9
FT_FAILED_TO_WRITE_DEVICE = 10
FT_EEPROM_READ_FAILED = 11
FT_EEPROM_WRITE_FAILED = 12
FT_EEPROM_ERASE_FAILED = 13
FT_EEPROM_NOT_PRESENT = 14
FT_EEPROM_NOT_PROGRAMMED = 15
FT_INVALID_ARGS = 16
FT_NOT_SUPPORTED = 17
FT_OTHER_ERROR = 18
FT_DEVICE_LIST_NOT_READY = 19
MemSize = 512
SPIDATALENGTH = 11
READ = 0xC0
WRITE = 0xA0
WREN = 0x98
ERAL = 0x90
BAD_COMMAND_RESPONSE = 0xFA
MSB_RISING_EDGE_CLOCK_BYTE_OUT = 0x10
MSB_FALLING_EDGE_CLOCK_BYTE_OUT = 0x11
MSB_RISING_EDGE_CLOCK_BIT_OUT = 0x12
MSB_FALLING_EDGE_CLOCK_BIT_OUT = 0x13
MSB_RISING_EDGE_CLOCK_BYTE_IN = 0x20
MSB_RISING_EDGE_CLOCK_BIT_IN = 0x22
MSB_FALLING_EDGE_CLOCK_BYTE_IN = 0x24
MSB_FALLING_EDGE_CLOCK_BIT_IN = 0x26
class OutBuffer(ctypes.Structure):
_fields_ = [('data', ctypes.c_ubyte * 65535)]
class InBuffer(ctypes.Structure):
_fields_ = [('data', ctypes.c_ubyte * 65535)]
class OutDataBuffer(ctypes.Structure):
_fields_ = [('data', ctypes.c_ubyte * MemSize)]
class InDataBuffer(ctypes.Structure):
_fields_ = [('data', ctypes.c_ubyte * MemSize)]
class FT_DEVICE_LIST_INFO_NODE(ctypes.Structure):
_fields_ = [
('flags', ctypes.c_ulong),
('type', ctypes.c_ulong),
('id', ctypes.c_ulong),
('locId', ctypes.c_ulong),
('serial_number', ctypes.c_char * 16),
('description', ctypes.c_char * 64),
('devInfo', ctypes.c_char_p),
('ft_handle', ctypes.c_void_p)
]
class SPI:
def __init__(self):
self.output_buffer = OutBuffer()
self.input_buffer = InBuffer()
self.clock_div = 29
self.num_bytes_to_send = 0
self.num_bytes_send = ctypes.c_ulong()
self.num_bytes_read = ctypes.c_ulong()
self.num_input_buffer = ctypes.c_ulong()
self.byte_data_read = 0
self.mem_addr = 0x00
self.data_out_buffer = OutDataBuffer()
self.data_in_buffer = InDataBuffer()
self.ft_status = 0
self.dummy_rd = 8
self.dummy_wr = 8
self.high_addr = 0
self.bit_wr_flag = 0
self.ftdiHandle = ctypes.c_void_p()
self.ftd2xx = ctypes.cdll.LoadLibrary
current_dir = os.path.dirname(os.path.abspath(__file__))
file_name = os.path.join(current_dir, 'ftd2xx64.dll')
self.lib_ftd2xx = self.ftd2xx(file_name)
self.debug = 0
self.reg_config_all_file_path = r'D:\reg_config_all.txt'
self.reg_config_file_path = r'D:\reg_config.txt'
fid = open(self.reg_config_file_path, 'w')
fid.write('{}\t{}\t{}\n'.format('Type'.ljust(2, ' '), 'Addr'.ljust(10, ' '), 'Value'.ljust(10, ' ')))
fid.close()
fid = open(self.reg_config_all_file_path, 'w')
fid.write('Type\tBit_h\tBit_l\tAddr\tBalue\n')
fid.close()
@staticmethod
def split_list(lst, size):
result = []
for i in range(0, len(lst), size):
result.append(lst[i:i + size])
return result
@staticmethod
def set_reg(data, bit_h, bit_l, val, bit_len=32):
b_len = bit_h - bit_l + 1
if val > 2 ** (bit_h - bit_l + 1) - 1:
raise ValueError('val={}超过 bit 位宽{}.'.format(val, b_len))
data_bin = bin(data)[2:].rjust(bit_len, '0')
data_bin_list = list(data_bin)[::-1]
val_bin = bin(val)[2:].rjust(b_len, '0')
val_bin_list = list(val_bin)[::-1]
k = 0
for i in range(bit_l, bit_h + 1):
data_bin_list[i] = val_bin_list[k]
k += 1
data_final = ''.join(data_bin_list[::-1])
return int(data_final, 2)
def SPI_CSEnable(self):
for i in range(5):
self.output_buffer.data[self.num_bytes_to_send] = 0x80
self.num_bytes_to_send += 1
self.output_buffer.data[self.num_bytes_to_send] = 0x00
self.num_bytes_to_send += 1
self.output_buffer.data[self.num_bytes_to_send] = 0x0b
self.num_bytes_to_send += 1
def SPI_CSDisable(self):
for loop in range(5):
self.output_buffer.data[self.num_bytes_to_send] = 0x80
self.num_bytes_to_send += 1
self.output_buffer.data[self.num_bytes_to_send] = 0x08
self.num_bytes_to_send += 1
self.output_buffer.data[self.num_bytes_to_send] = 0x0b
self.num_bytes_to_send += 1
def ft2232_write(self, addr, value):
addr = addr >> 2
high_addr = addr >> 20
if high_addr != self.high_addr:
self.ft2232_write_high_addr(high_addr)
addr = addr & 0xFFFFF
self.num_bytes_send = ctypes.c_ulong(0)
self.SPI_CSEnable()
self.output_buffer.data[self.num_bytes_to_send] = MSB_FALLING_EDGE_CLOCK_BIT_OUT
self.num_bytes_to_send += 1
self.output_buffer.data[self.num_bytes_to_send] = 3
self.num_bytes_to_send += 1
self.output_buffer.data[self.num_bytes_to_send] = 0b00010000
self.num_bytes_to_send += 1
self.output_buffer.data[self.num_bytes_to_send] = MSB_FALLING_EDGE_CLOCK_BIT_OUT
self.num_bytes_to_send += 1
self.output_buffer.data[self.num_bytes_to_send] = 3
self.num_bytes_to_send += 1
self.output_buffer.data[self.num_bytes_to_send] = ((addr >> 16) & 0xF) << 4
self.num_bytes_to_send += 1
self.output_buffer.data[self.num_bytes_to_send] = MSB_FALLING_EDGE_CLOCK_BYTE_OUT
self.num_bytes_to_send += 1
self.output_buffer.data[self.num_bytes_to_send] = 1
self.num_bytes_to_send += 1
self.output_buffer.data[self.num_bytes_to_send] = 0
self.num_bytes_to_send += 1
self.output_buffer.data[self.num_bytes_to_send] = (addr >> 8) & 0xFF
self.num_bytes_to_send += 1
self.output_buffer.data[self.num_bytes_to_send] = addr & 0xFF
self.num_bytes_to_send += 1
self.output_buffer.data[self.num_bytes_to_send] = MSB_FALLING_EDGE_CLOCK_BYTE_OUT
self.num_bytes_to_send += 1
self.output_buffer.data[self.num_bytes_to_send] = 3
self.num_bytes_to_send += 1
self.output_buffer.data[self.num_bytes_to_send] = 0
self.num_bytes_to_send += 1
self.output_buffer.data[self.num_bytes_to_send] = (value >> 24) & 0xFF
self.num_bytes_to_send += 1
self.output_buffer.data[self.num_bytes_to_send] = (value >> 16) & 0xFF
self.num_bytes_to_send += 1
self.output_buffer.data[self.num_bytes_to_send] = (value >> 8) & 0xFF
self.num_bytes_to_send += 1
self.output_buffer.data[self.num_bytes_to_send] = value & 0xFF
self.num_bytes_to_send += 1
self.output_buffer.data[self.num_bytes_to_send] = MSB_FALLING_EDGE_CLOCK_BYTE_OUT
self.num_bytes_to_send += 1
self.output_buffer.data[self.num_bytes_to_send] = math.ceil(self.dummy_wr/8) - 1
self.num_bytes_to_send += 1
self.output_buffer.data[self.num_bytes_to_send] = 0
self.num_bytes_to_send += 1
self.SPI_CSDisable()
ft_status = self.lib_ftd2xx.FT_Write(self.ftdiHandle, self.output_buffer.data, self.num_bytes_to_send, byref(self.num_bytes_send))
ft_status = self.lib_ftd2xx.FT_Read(self.ftdiHandle, self.input_buffer.data, 4, byref(self.num_bytes_read))
self.num_bytes_to_send = 0
return ft_status
def ft2232_write_inc(self, value):
self.num_bytes_send = ctypes.c_ulong(0)
self.SPI_CSEnable()
self.output_buffer.data[self.num_bytes_to_send] = MSB_FALLING_EDGE_CLOCK_BIT_OUT
self.num_bytes_to_send += 1
self.output_buffer.data[self.num_bytes_to_send] = 3
self.num_bytes_to_send += 1
self.output_buffer.data[self.num_bytes_to_send] = 0b00110000
self.num_bytes_to_send += 1
self.output_buffer.data[self.num_bytes_to_send] = MSB_FALLING_EDGE_CLOCK_BYTE_OUT
self.num_bytes_to_send += 1
self.output_buffer.data[self.num_bytes_to_send] = 3
self.num_bytes_to_send += 1
self.output_buffer.data[self.num_bytes_to_send] = 0
self.num_bytes_to_send += 1
self.output_buffer.data[self.num_bytes_to_send] = (value >> 24) & 0xFF
self.num_bytes_to_send += 1
self.output_buffer.data[self.num_bytes_to_send] = (value >> 16) & 0xFF
self.num_bytes_to_send += 1
self.output_buffer.data[self.num_bytes_to_send] = (value >> 8) & 0xFF
self.num_bytes_to_send += 1
self.output_buffer.data[self.num_bytes_to_send] = value & 0xFF
self.num_bytes_to_send += 1
self.output_buffer.data[self.num_bytes_to_send] = MSB_FALLING_EDGE_CLOCK_BYTE_OUT
self.num_bytes_to_send += 1
self.output_buffer.data[self.num_bytes_to_send] = math.ceil(self.dummy_wr / 8) - 1
self.num_bytes_to_send += 1
self.output_buffer.data[self.num_bytes_to_send] = 0
self.num_bytes_to_send += 1
self.SPI_CSDisable()
ft_status = self.lib_ftd2xx.FT_Write(self.ftdiHandle, self.output_buffer.data, self.num_bytes_to_send, byref(self.num_bytes_send))
self.num_bytes_to_send = 0
return ft_status
def ft2232_read_con(self, addr, length):
addr = addr >> 2
high_addr = addr >> 20
if high_addr != self.high_addr:
self.ft2232_write_high_addr(high_addr)
addr = addr & 0xFFFFF
self.num_bytes_send = ctypes.c_ulong(0)
self.SPI_CSEnable()
self.output_buffer.data[self.num_bytes_to_send] = MSB_FALLING_EDGE_CLOCK_BIT_OUT
self.num_bytes_to_send += 1
self.output_buffer.data[self.num_bytes_to_send] = 3
self.num_bytes_to_send += 1
self.output_buffer.data[self.num_bytes_to_send] = 0b10000000
self.num_bytes_to_send += 1
self.output_buffer.data[self.num_bytes_to_send] = MSB_FALLING_EDGE_CLOCK_BIT_OUT
self.num_bytes_to_send += 1
self.output_buffer.data[self.num_bytes_to_send] = 3
self.num_bytes_to_send += 1
self.output_buffer.data[self.num_bytes_to_send] = ((addr >> 16) & 0xF) << 4
self.num_bytes_to_send += 1
self.output_buffer.data[self.num_bytes_to_send] = MSB_FALLING_EDGE_CLOCK_BYTE_OUT
self.num_bytes_to_send += 1
self.output_buffer.data[self.num_bytes_to_send] = 1
self.num_bytes_to_send += 1
self.output_buffer.data[self.num_bytes_to_send] = 0
self.num_bytes_to_send += 1
self.output_buffer.data[self.num_bytes_to_send] = (addr >> 8) & 0xFF
self.num_bytes_to_send += 1
self.output_buffer.data[self.num_bytes_to_send] = addr & 0xFF
self.num_bytes_to_send += 1
for i in range(length):
self.output_buffer.data[self.num_bytes_to_send] = MSB_FALLING_EDGE_CLOCK_BYTE_IN
self.num_bytes_to_send += 1
self.output_buffer.data[self.num_bytes_to_send] = 4
self.num_bytes_to_send += 1
self.output_buffer.data[self.num_bytes_to_send] = 0
self.num_bytes_to_send += 1
self.SPI_CSDisable()
ft_status = self.lib_ftd2xx.FT_Write(self.ftdiHandle, self.output_buffer.data, self.num_bytes_to_send, byref(self.num_bytes_send))
ft_status = self.lib_ftd2xx.FT_Read(self.ftdiHandle, self.input_buffer.data, length*5, byref(self.num_bytes_read))
bdata = []
for n in range(int(length)):
bdata.append(hex(((self.input_buffer.data[1+5*n] << 24) + (self.input_buffer.data[2+5*n] << 16) + (self.input_buffer.data[3+5*n] << 8) + self.input_buffer.data[4+5*n])))
self.num_bytes_to_send = 0
return bdata
def ft2232_write_con(self, addr, data_list):
addr = addr >> 2
high_addr = addr >> 20
if high_addr != self.high_addr:
self.ft2232_write_high_addr(high_addr)
addr = addr & 0xFFFFF
self.num_bytes_send = ctypes.c_ulong(0)
self.SPI_CSEnable()
self.output_buffer.data[self.num_bytes_to_send] = MSB_FALLING_EDGE_CLOCK_BIT_OUT
self.num_bytes_to_send += 1
self.output_buffer.data[self.num_bytes_to_send] = 3
self.num_bytes_to_send += 1
self.output_buffer.data[self.num_bytes_to_send] = 0b10010000
self.num_bytes_to_send += 1
self.output_buffer.data[self.num_bytes_to_send] = MSB_FALLING_EDGE_CLOCK_BIT_OUT
self.num_bytes_to_send += 1
self.output_buffer.data[self.num_bytes_to_send] = 3
self.num_bytes_to_send += 1
self.output_buffer.data[self.num_bytes_to_send] = ((addr >> 16) & 0xF) << 4
self.num_bytes_to_send += 1
self.output_buffer.data[self.num_bytes_to_send] = MSB_FALLING_EDGE_CLOCK_BYTE_OUT
self.num_bytes_to_send += 1
self.output_buffer.data[self.num_bytes_to_send] = 1
self.num_bytes_to_send += 1
self.output_buffer.data[self.num_bytes_to_send] = 0
self.num_bytes_to_send += 1
self.output_buffer.data[self.num_bytes_to_send] = (addr >> 8) & 0xFF
self.num_bytes_to_send += 1
self.output_buffer.data[self.num_bytes_to_send] = addr & 0xFF
self.num_bytes_to_send += 1
for i in range(len(data_list)):
value = data_list[i]
self.output_buffer.data[self.num_bytes_to_send] = MSB_FALLING_EDGE_CLOCK_BYTE_OUT
self.num_bytes_to_send += 1
self.output_buffer.data[self.num_bytes_to_send] = 3
self.num_bytes_to_send += 1
self.output_buffer.data[self.num_bytes_to_send] = 0
self.num_bytes_to_send += 1
self.output_buffer.data[self.num_bytes_to_send] = (value >> 24) & 0xFF
self.num_bytes_to_send += 1
self.output_buffer.data[self.num_bytes_to_send] = (value >> 16) & 0xFF
self.num_bytes_to_send += 1
self.output_buffer.data[self.num_bytes_to_send] = (value >> 8) & 0xFF
self.num_bytes_to_send += 1
self.output_buffer.data[self.num_bytes_to_send] = value & 0xFF
self.num_bytes_to_send += 1
self.output_buffer.data[self.num_bytes_to_send] = MSB_FALLING_EDGE_CLOCK_BYTE_OUT
self.num_bytes_to_send += 1
self.output_buffer.data[self.num_bytes_to_send] = (math.ceil(self.dummy_wr / 8) - 1)
self.num_bytes_to_send += 1
self.output_buffer.data[self.num_bytes_to_send] = 0
self.num_bytes_to_send += 1
self.output_buffer.data[self.num_bytes_to_send] = 0
self.num_bytes_to_send += 1
self.SPI_CSDisable()
ft_status = self.lib_ftd2xx.FT_Write(self.ftdiHandle, self.output_buffer.data, self.num_bytes_to_send, byref(self.num_bytes_send))
self.num_bytes_to_send = 0
return ft_status
def ft2232_write_dly(self, dummy_wr):
self.num_bytes_send = ctypes.c_ulong(0)
self.SPI_CSEnable()
dummy_wr = math.ceil(dummy_wr/8) * 8
self.output_buffer.data[self.num_bytes_to_send] = MSB_FALLING_EDGE_CLOCK_BIT_OUT
self.num_bytes_to_send += 1
self.output_buffer.data[self.num_bytes_to_send] = 3
self.num_bytes_to_send += 1
self.output_buffer.data[self.num_bytes_to_send] = 0b01010000
self.num_bytes_to_send += 1
self.output_buffer.data[self.num_bytes_to_send] = MSB_FALLING_EDGE_CLOCK_BIT_OUT
self.num_bytes_to_send += 1
self.output_buffer.data[self.num_bytes_to_send] = 7
self.num_bytes_to_send += 1
self.output_buffer.data[self.num_bytes_to_send] = dummy_wr
self.num_bytes_to_send += 1
self.SPI_CSDisable()
ft_status = self.lib_ftd2xx.FT_Write(self.ftdiHandle, self.output_buffer.data, self.num_bytes_to_send, byref(self.num_bytes_send))
self.num_bytes_to_send = 0
self.dummy_wr = dummy_wr
return ft_status
def ft2232_write_high_addr(self, high_addr):
self.num_bytes_send = ctypes.c_ulong(0)
self.SPI_CSEnable()
self.output_buffer.data[self.num_bytes_to_send] = MSB_FALLING_EDGE_CLOCK_BIT_OUT
self.num_bytes_to_send += 1
self.output_buffer.data[self.num_bytes_to_send] = 3
self.num_bytes_to_send += 1
self.output_buffer.data[self.num_bytes_to_send] = 0b01100000
self.num_bytes_to_send += 1
self.output_buffer.data[self.num_bytes_to_send] = MSB_FALLING_EDGE_CLOCK_BIT_OUT
self.num_bytes_to_send += 1
self.output_buffer.data[self.num_bytes_to_send] = 7
self.num_bytes_to_send += 1
self.output_buffer.data[self.num_bytes_to_send] = high_addr >> 2
self.num_bytes_to_send += 1
self.output_buffer.data[self.num_bytes_to_send] = MSB_FALLING_EDGE_CLOCK_BIT_OUT
self.num_bytes_to_send += 1
self.output_buffer.data[self.num_bytes_to_send] = 1
self.num_bytes_to_send += 1
self.output_buffer.data[self.num_bytes_to_send] = (high_addr & 0x3) << 6
self.num_bytes_to_send += 1
self.SPI_CSDisable()
ft_status = self.lib_ftd2xx.FT_Write(self.ftdiHandle, self.output_buffer.data, self.num_bytes_to_send, byref(self.num_bytes_send))
self.num_bytes_to_send = 0
self.high_addr = high_addr
return ft_status
def write(self, addr, value):
if self.debug == 0:
self.ft2232_write(addr, value)
if self.bit_wr_flag == 0:
with open(self.reg_config_file_path, 'r') as fid:
lines = fid.readlines()
fid.close()
if len(lines) > 1:
if 'delay' in lines[-1] or '[R]' in lines[-1] or '#' in lines[-1]:
last_addr = 0x0
else:
last_addr = int(re.split('\t', lines[-1])[1].strip(), 16)
else:
last_addr = 0x0
if last_addr == addr:
final_lines = lines[:-1]
final_lines.append('[W]:\t{}\t{}\n'.format(hex(addr).ljust(10, ' '), hex(value).ljust(10, ' ')))
else:
final_lines = lines
final_lines.append('[W]:\t{}\t{}\n'.format(hex(addr), hex(value)))
with open(self.reg_config_file_path, 'w') as fid:
for line in final_lines:
fid.write(line)
fid.close()
with open(self.reg_config_all_file_path, 'a+') as fid:
fid.write('[W]:\t{}\t{}\t{}\t{}\n'.format(
hex(addr).ljust(10, ' '), hex(value).ljust(10, ' '), '-'.ljust(2, ' '), '-'.ljust(2, ' ', )))
fid.close()
def write_bits(self, addr, bit_h, bit_l, value):
self.bit_wr_flag = 1
if self.debug == 0:
data = int(self.read(addr), 16)
w_data = self.set_reg(data, bit_h, bit_l, value)
self.write(addr, w_data)
self.bit_wr_flag = 0
with open(self.reg_config_file_path, 'r') as fid:
lines = fid.readlines()
fid.close()
if len(lines) > 1:
if 'delay' in lines[-1] or '[R]' in lines[-1] or '#' in lines[-1]:
last_addr = 0x0
else:
last_addr = int(re.split('\t', lines[-1])[1].strip(), 16)
else:
last_addr = 0x0
if last_addr == addr:
final_lines = lines[:-1]
final_lines.append('[W]:\t{}\t{}\n'.format(hex(addr).ljust(10, ' '), hex(w_data).ljust(10, ' ')))
else:
final_lines = lines
final_lines.append('[W]:\t{}\t{}\n'.format(hex(addr), hex(w_data)))
with open(self.reg_config_file_path, 'w') as fid:
for line in final_lines:
fid.write(line)
fid.close()
with open(self.reg_config_all_file_path, 'a+') as fid:
fid.write('[W]:\t{}\t{}\t{}\t{}\n'.format(
hex(addr).ljust(10, ' '), hex(value).ljust(10, ' '), str(bit_h).ljust(2, ' '), str(bit_l).ljust(2, ' ', )))
fid.close()
def ft2232_read(self, addr):
self.num_bytes_send = ctypes.c_ulong(0)
addr = addr >> 2
high_addr = addr >> 20
if high_addr != self.high_addr:
self.ft2232_write_high_addr(high_addr)
addr = addr & 0xFFFFF
self.SPI_CSEnable()
self.output_buffer.data[self.num_bytes_to_send] = MSB_FALLING_EDGE_CLOCK_BIT_OUT
self.num_bytes_to_send += 1
self.output_buffer.data[self.num_bytes_to_send] = 3
self.num_bytes_to_send += 1
self.output_buffer.data[self.num_bytes_to_send] = 0b00000000
self.num_bytes_to_send += 1
self.output_buffer.data[self.num_bytes_to_send] = MSB_FALLING_EDGE_CLOCK_BIT_OUT
self.num_bytes_to_send += 1
self.output_buffer.data[self.num_bytes_to_send] = 3
self.num_bytes_to_send += 1
self.output_buffer.data[self.num_bytes_to_send] = ((addr >> 16) & 0xF) << 4
self.num_bytes_to_send += 1
self.output_buffer.data[self.num_bytes_to_send] = MSB_FALLING_EDGE_CLOCK_BYTE_OUT
self.num_bytes_to_send += 1
self.output_buffer.data[self.num_bytes_to_send] = 1
self.num_bytes_to_send += 1
self.output_buffer.data[self.num_bytes_to_send] = 0
self.num_bytes_to_send += 1
self.output_buffer.data[self.num_bytes_to_send] = (addr >> 8) & 0xFF
self.num_bytes_to_send += 1
self.output_buffer.data[self.num_bytes_to_send] = addr & 0xFF
self.num_bytes_to_send += 1
self.output_buffer.data[self.num_bytes_to_send] = MSB_FALLING_EDGE_CLOCK_BIT_OUT
self.num_bytes_to_send += 1
self.output_buffer.data[self.num_bytes_to_send] = self.dummy_rd - 1
self.num_bytes_to_send += 1
self.output_buffer.data[self.num_bytes_to_send] = 0
self.num_bytes_to_send += 1
self.output_buffer.data[self.num_bytes_to_send] = MSB_FALLING_EDGE_CLOCK_BYTE_IN
self.num_bytes_to_send += 1
self.output_buffer.data[self.num_bytes_to_send] = 3
self.num_bytes_to_send += 1
self.output_buffer.data[self.num_bytes_to_send] = 0
self.num_bytes_to_send += 1
self.SPI_CSDisable()
ft_status = self.lib_ftd2xx.FT_Write(self.ftdiHandle, self.output_buffer.data, self.num_bytes_to_send, byref(self.num_bytes_send))
self.num_bytes_to_send = 0
ft_status = self.lib_ftd2xx.FT_Read(self.ftdiHandle, self.input_buffer.data, 4, byref(self.num_bytes_read))
bdata = ((self.input_buffer.data[0] << 24) +(self.input_buffer.data[1] << 16) +(self.input_buffer.data[2] << 8) + self.input_buffer.data[3])
return hex(bdata)[2:].upper()
def ft2232_read_inc(self):
self.num_bytes_send = ctypes.c_ulong(0)
self.SPI_CSEnable()
self.output_buffer.data[self.num_bytes_to_send] = MSB_FALLING_EDGE_CLOCK_BIT_OUT
self.num_bytes_to_send += 1
self.output_buffer.data[self.num_bytes_to_send] = 3
self.num_bytes_to_send += 1
self.output_buffer.data[self.num_bytes_to_send] = 0b00100000
self.num_bytes_to_send += 1
self.output_buffer.data[self.num_bytes_to_send] = MSB_FALLING_EDGE_CLOCK_BYTE_OUT
self.num_bytes_to_send += 1
self.output_buffer.data[self.num_bytes_to_send] = math.ceil(self.dummy_rd/8) - 1 + 4
self.num_bytes_to_send += 1
self.output_buffer.data[self.num_bytes_to_send] = 0
self.num_bytes_to_send += 1
self.output_buffer.data[self.num_bytes_to_send] = MSB_FALLING_EDGE_CLOCK_BYTE_OUT
self.num_bytes_to_send += 1
self.output_buffer.data[self.num_bytes_to_send] = 3
self.num_bytes_to_send += 1
self.output_buffer.data[self.num_bytes_to_send] = 0
self.num_bytes_to_send += 1
self.SPI_CSDisable()
ft_status = self.lib_ftd2xx.FT_Write(self.ftdiHandle, self.output_buffer.data, self.num_bytes_to_send, byref(self.num_bytes_send))
self.num_bytes_to_send = 0
ft_status = self.lib_ftd2xx.FT_Read(self.ftdiHandle, self.input_buffer.data, 4, byref(self.num_bytes_read))
bdata = ((self.input_buffer.data[0] << 24) +(self.input_buffer.data[1] << 16) +(self.input_buffer.data[2] << 8) + self.input_buffer.data[3])
return hex(bdata)[2:].upper()
def ft2232_read_dly(self, dummy_rd):
self.num_bytes_send = ctypes.c_ulong(0)
self.SPI_CSEnable()
dummy_rd = math.ceil(dummy_rd / 8) * 8
self.output_buffer.data[self.num_bytes_to_send] = MSB_FALLING_EDGE_CLOCK_BIT_OUT
self.num_bytes_to_send += 1
self.output_buffer.data[self.num_bytes_to_send] = 3
self.num_bytes_to_send += 1
self.output_buffer.data[self.num_bytes_to_send] = 0b01000000
self.num_bytes_to_send += 1
self.output_buffer.data[self.num_bytes_to_send] = MSB_FALLING_EDGE_CLOCK_BIT_OUT
self.num_bytes_to_send += 1
self.output_buffer.data[self.num_bytes_to_send] = 7
self.num_bytes_to_send += 1
self.output_buffer.data[self.num_bytes_to_send] = dummy_rd
self.num_bytes_to_send += 1
self.SPI_CSDisable()
ft_status = self.lib_ftd2xx.FT_Write(self.ftdiHandle, self.output_buffer.data, self.num_bytes_to_send, byref(self.num_bytes_send))
self.num_bytes_to_send = 0
self.dummy_rd = dummy_rd
return ft_status
def read(self, addr):
if self.debug == 0:
b_data = self.ft2232_read(addr)
else:
b_data = '0'
if self.bit_wr_flag == 0:
with open(self.reg_config_file_path, 'a+') as fid:
fid.write('[R]:\t{}\t{}\n'.format(
hex(addr).ljust(10, ' '), b_data.ljust(10, ' ')))
fid.close()
with open(self.reg_config_all_file_path, 'a+') as fid:
fid.write('[R]:\t{}\t0x{}\n'.format(
hex(addr).ljust(10, ' '), b_data.ljust(10, ' ')))
fid.close()
return b_data
def read_bits(self, addr, bit_h, bit_l):
self.bit_wr_flag = 1
if self.debug == 0:
data = self.read(addr)
else:
data = '0'
self.bit_wr_flag = 0
data_bin = bin(int(data, 16))[2:].rjust(32, '0')
data_list = list(data_bin)
data_list.reverse()
data_ret = data_list[bit_l:bit_h + 1]
data_ret.reverse()
ret = ''.join(data_ret)
data_hex = hex(int(ret, 2))[2:]
with open(self.reg_config_file_path, 'a+') as fid:
fid.write('[R]:\t{}\t{}\n'.format(
hex(addr).ljust(10, ' '), data.ljust(10, ' ')))
fid.close()
with open(self.reg_config_all_file_path, 'a+') as fid:
fid.write('[R]:\t{}\t0x{}\t{}\t{}\n'.format(
hex(addr).ljust(10, ' '), data.ljust(10, ' '), str(bit_h).ljust(2, ' '), str(bit_l).ljust(2, ' ', )))
fid.close()
return data_hex
def SPI_Initial(self, ft_handle):
ft_status = self.lib_ftd2xx.FT_ResetDevice(ft_handle)
ft_status |= self.lib_ftd2xx.FT_GetQueueStatus(ft_handle, byref(self.num_input_buffer))
if ft_status == Device_status.FT_OK.value and self.num_input_buffer.value > 0:
ft_status |= self.lib_ftd2xx.FT_Read(ft_handle, self.input_buffer, self.num_input_buffer, self.num_bytes_read)
ft_status |= self.lib_ftd2xx.FT_SetUSBParameters(ft_handle, 65535, 65535)
ft_status |= self.lib_ftd2xx.FT_SetChars(ft_handle, False, 0, False, 0)
ft_status |= self.lib_ftd2xx.FT_SetTimeouts(ft_handle, 3000, 3000)
ft_status |= self.lib_ftd2xx.FT_SetLatencyTimer(ft_handle, 1)
ft_status |= self.lib_ftd2xx.FT_SetBitMode(ft_handle, 0x0, 0x00)
ft_status |= self.lib_ftd2xx.FT_SetBitMode(ft_handle, 0x0, 0x02)
if ft_status != Device_status.FT_OK.value:
print("fail on initialize FT2232H device ! ")
return False
time.sleep(0.05)
self.num_bytes_to_send = 0
self.output_buffer.data[self.num_bytes_to_send] = 0xAA
self.num_bytes_to_send += 1
ft_status = self.lib_ftd2xx.FT_Write(ft_handle, self.output_buffer.data, self.num_bytes_to_send, byref(self.num_bytes_send))
self.num_bytes_to_send = 0
while self.num_input_buffer.value == 0 and ft_status == Device_status.FT_OK.value:
ft_status = self.lib_ftd2xx.FT_GetQueueStatus(ft_handle, byref(self.num_input_buffer))
b_command_echod = False
ft_status = self.lib_ftd2xx.FT_Read(ft_handle, self.input_buffer.data, self.num_input_buffer, byref(self.num_bytes_read))
for dw_count in range(0, self.num_bytes_read.value - 1):
if self.input_buffer.data[dw_count] == 0xFA and self.input_buffer.data[dw_count + 1] == 0xAA:
b_command_echod = True
break
if not b_command_echod:
print("fail to synchronize MPSSE with command '0xAA' \n")
return False
self.num_bytes_to_send = 0
self.output_buffer.data[self.num_bytes_to_send] = 0xAB
self.num_bytes_to_send += 1
ft_status = self.lib_ftd2xx.FT_Write(ft_handle, self.output_buffer.data, self.num_bytes_to_send, byref(self.num_bytes_send))
self.num_bytes_to_send = 0
while (self.num_input_buffer == 0) and (ft_status == Device_status.FT_OK):
ft_status = self.lib_ftd2xx.FT_GetQueueStatus(ft_handle, byref(self.num_input_buffer))
b_command_echod = False
ft_status = self.lib_ftd2xx.FT_Read(ft_handle, self.input_buffer.data, self.num_input_buffer, byref(self.num_bytes_read))
for dw_count in range(0, self.num_bytes_read.value - 1):
if self.input_buffer.data[dw_count] == 0xFA and self.input_buffer.data[dw_count + 1] == 0xAB:
b_command_echod = True
break
if not b_command_echod:
print("fail to synchronize MPSSE with command '0xAB' \n")
return False
self.output_buffer.data[self.num_bytes_to_send] = 0x8A
self.num_bytes_to_send += 1
self.output_buffer.data[self.num_bytes_to_send] = 0x97
self.num_bytes_to_send += 1
self.output_buffer.data[self.num_bytes_to_send] = 0x8D
self.num_bytes_to_send += 1
ft_status = self.lib_ftd2xx.FT_Write(ft_handle, self.output_buffer.data, self.num_bytes_to_send, byref(self.num_bytes_send))
self.num_bytes_to_send = 0
self.output_buffer.data[self.num_bytes_to_send] = 0x80
self.num_bytes_to_send += 1
self.output_buffer.data[self.num_bytes_to_send] = 0x00
self.num_bytes_to_send += 1
self.output_buffer.data[self.num_bytes_to_send] = 0x0b
self.num_bytes_to_send += 1
self.output_buffer.data[self.num_bytes_to_send] = 0x86
self.num_bytes_to_send += 1
self.output_buffer.data[self.num_bytes_to_send] = ctypes.c_ubyte(self.clock_div & 0xFF)
self.num_bytes_to_send += 1
self.output_buffer.data[self.num_bytes_to_send] = ctypes.c_ubyte(self.clock_div >> 8)
self.num_bytes_to_send += 1
ft_status = self.lib_ftd2xx.FT_Write(ft_handle, self.output_buffer.data, self.num_bytes_to_send, byref(self.num_bytes_send))
self.num_bytes_to_send = 0
time.sleep(0.02)
self.output_buffer.data[self.num_bytes_to_send] = 0x85
self.num_bytes_to_send += 1
ft_status = self.lib_ftd2xx.FT_Write(ft_handle, self.output_buffer.data, self.num_bytes_to_send, byref(self.num_bytes_send))
self.num_bytes_to_send = 0
time.sleep(0.03)
print("SPI initial successful\n")
return True
def SPI_WriteByte2RandomAddr(self, ft_handle, address, bdata):
self.num_bytes_send = ctypes.c_ulong(0)
self.SPI_CSEnable()
self.output_buffer.data[self.num_bytes_to_send] = MSB_FALLING_EDGE_CLOCK_BIT_OUT
self.num_bytes_to_send += 1
self.output_buffer.data[self.num_bytes_to_send] = 2
self.num_bytes_to_send += 1
self.output_buffer.data[self.num_bytes_to_send] = WRITE
self.num_bytes_to_send += 1
self.output_buffer.data[self.num_bytes_to_send] = MSB_FALLING_EDGE_CLOCK_BIT_OUT
self.num_bytes_to_send += 1
self.output_buffer.data[self.num_bytes_to_send] = 7
self.num_bytes_to_send += 1
self.output_buffer.data[self.num_bytes_to_send] = ctypes.c_ubyte(address)
self.num_bytes_to_send += 1
self.output_buffer.data[self.num_bytes_to_send] = MSB_FALLING_EDGE_CLOCK_BYTE_OUT
self.num_bytes_to_send += 1
self.output_buffer.data[self.num_bytes_to_send] = 1
self.num_bytes_to_send += 1
self.output_buffer.data[self.num_bytes_to_send] = 0
self.num_bytes_to_send += 1
self.output_buffer.data[self.num_bytes_to_send] = bdata >> 8
self.num_bytes_to_send += 1
self.output_buffer.data[self.num_bytes_to_send] = bdata & 0xff
self.num_bytes_to_send += 1
self.SPI_CSDisable()
ft_status = self.lib_ftd2xx.FT_Write(ft_handle, self.output_buffer.data, self.num_bytes_to_send, byref(self.num_bytes_send))
self.num_bytes_to_send = 0
return ft_status
def SPI_ReadByteRandomAddr(self, ft_handle, address):
self.num_bytes_send = ctypes.c_ulong(0)
self.SPI_CSEnable()
self.output_buffer.data[self.num_bytes_to_send] = MSB_FALLING_EDGE_CLOCK_BIT_OUT
self.num_bytes_to_send += 1
self.output_buffer.data[self.num_bytes_to_send] = 2
self.num_bytes_to_send += 1
self.output_buffer.data[self.num_bytes_to_send] = READ
self.num_bytes_to_send += 1
self.output_buffer.data[self.num_bytes_to_send] = MSB_FALLING_EDGE_CLOCK_BIT_OUT
self.num_bytes_to_send += 1
self.output_buffer.data[self.num_bytes_to_send] = 7
self.num_bytes_to_send += 1
self.output_buffer.data[self.num_bytes_to_send] = ctypes.c_ubyte(address)
self.num_bytes_to_send += 1
self.output_buffer.data[self.num_bytes_to_send] = MSB_FALLING_EDGE_CLOCK_BYTE_IN
self.num_bytes_to_send += 1
self.output_buffer.data[self.num_bytes_to_send] = 0x01
self.num_bytes_to_send += 1
self.output_buffer.data[self.num_bytes_to_send] = 0x00
self.num_bytes_to_send += 1
self.SPI_CSDisable()
ft_status = self.lib_ftd2xx.FT_Write(ft_handle, self.output_buffer.data, self.num_bytes_to_send, byref(self.num_bytes_send))
self.num_bytes_to_send = 0
ft_status = self.lib_ftd2xx.FT_Read(ft_handle, self.input_buffer.data, 2, byref(self.num_bytes_read))
bdata = [((self.input_buffer.data[0] << 8) + self.input_buffer.data[1])]
return ft_status
def ft2232_init(self):
self.lib_ftd2xx.FT_Close(self.ftdiHandle)
numDevs = ctypes.c_ulong()
devInfo = FT_DEVICE_LIST_INFO_NODE()
ft_status = self.lib_ftd2xx.FT_CreateDeviceInfoList(ctypes.byref(numDevs))
if ft_status == Device_status.FT_OK.value:
print("Number of devices is {}".format(numDevs.value))
else:
print("error")
return 1
if int(numDevs.value) > 0:
devInfo = (FT_DEVICE_LIST_INFO_NODE * numDevs.value)()
ft_status = self.lib_ftd2xx.FT_GetDeviceInfoList(devInfo, byref(numDevs))
if ft_status == Device_status.FT_OK.value:
for i in range(numDevs.value):
print("Dev %d:" % i)
print(" Flags=0x{}".format(devInfo[i].flags))
print(" Type=0x{}".format(devInfo[i].type))
print(" ID=0x{}".format(devInfo[i].id))
print(" LocId=0x{}".format(devInfo[i].locId))
print(" SerialNumber={}".format(devInfo[i].serial_number))
print(" Description={}".format(devInfo[i].description))
print(" ft_handle=0x{}".format(devInfo[i].ft_handle))
else:
return 1
ft_status = self.lib_ftd2xx.FT_Open(1, byref(self.ftdiHandle))
print(ft_status)
if ft_status != Device_status.FT_OK.value:
raise ValueError("Can't open FT2232H device!")
return 1
else:
print("Successfully open FT2232H device!")
if self.SPI_Initial(self.ftdiHandle):
ReadByte = 0
for i in range(MemSize):
self.data_out_buffer.data[i] = i
ft_status = self.lib_ftd2xx.FT_GetQueueStatus(self.ftdiHandle, byref(self.num_bytes_read))
if ft_status != Device_status.FT_OK.value and self.num_input_buffer.value > 0:
self.lib_ftd2xx.FT_Read(self.ftdiHandle, self.input_buffer.data, self.num_input_buffer, byref(self.num_bytes_read))
def set_dummy_rd(self, dummy_rd):
self.ft2232_read_dly(dummy_rd)
def set_dummy_wr(self, dummy_wr):
self.ft2232_write_dly(dummy_wr)
def read_inc(self):
b_data = self.ft2232_read_inc()
return b_data
def write_inc(self, value):
self.ft2232_write_inc(value)
def read_con(self, addr, length):
if length > 65536:
raise ValueError('Data is too large to write, must be less than 65536.')
data = []
count = math.ceil(length/512)
for n in range(count):
if length/512 > 1:
bdata = self.ft2232_read_con(addr+n*(512*4), 512)
else:
bdata = self.ft2232_read_con(addr + n * (512 * 4), length)
data = data+bdata
return data
def write_con(self, addr, data_list):
if len(data_list) > 65536:
raise ValueError('Data is too large to write, must be less than 65536.')
max_len = 512
w_data_list = self.split_list(data_list, max_len)
for n in range(len(w_data_list)):
self.ft2232_write_con(addr+n*(512*4), w_data_list[n])
def spi_sleep(self, sec):
time.sleep(sec)
with open(self.reg_config_all_file_path, 'a+') as fid:
fid.write('delay {}s\n'.format(str(sec)))
fid.close()
with open(self.reg_config_file_path, 'a+') as fid:
fid.write('delay {}s\n'.format(str(sec)))
fid.close()
if __name__ == "__main__":
spi = SPI()
spi.ft2232_init()
for i in range(3):
spi.set_dummy_wr(dummy_wr=0x8)
spi.set_dummy_rd(dummy_rd=0x8)
print(spi.read(0xA0000448))

