PyUSB依赖于一些USB的驱动程序, 这个貌似叫做无驱驱动, 其中libusb是一统天下者, 当然就要用这个咯. 那么问题来了, libusb这个驱动是怎么装到要开发的设备上呢? 在windows下答案是Zadig, 这个和rtlsdr用的方案是一致的.
下载了最新的Zadig然后选list all device, 可选择的列表里只有WinUSB(这是微软的吧?), libusbk(贵圈好乱), libusb-win32. libusb官网不是说和libusb-win32合并了么? 好吧, 只有选这个了. 但这个相当于libusb 0.1版本的, 估计和OS有关, 我是老迈的xp.
装上后, 给Python装上PyUSB(官网下载后, 按里面说明装),
import usb
usb.core.show_devices()
呵呵~好简单~ PyUSB教程, 文档: 建一个bat文件 pydoc -b 运行, 然后在浏览器里找到usb这个package的帮助.
接下来搞PC-FX2-FPGA的Loopback, 悲剧, 在用device那个类的write方法给端点写数据时, 很是诡异, 各种错, 但按照AN61345中描述的用Control Center收发一个文件数据的方法, 工作正常, 经仔细思考, 可能有以下层面问题:
Cypress的FX2LP 工作在slave FIFO + 自动发包模式时, 在向上位机机发送时, 没满一个包是不会发的, 因此数数很重要, 数不对就等着timeout吧.
FPGA部分copy的Cypress的AN61345, 自己只是写了个简单的testbench玩了一下, 与其说是验证功能, 不如说是我学习它的工作原理.
cy7c68013a FW bug, 这个也是copy的AN61345.
PyUSB坑爹 or Python代码问题.
硬件错误.
于是为了简化问题, 上逻辑分析仪, 另外把这个打包的大小改小. 于是我查了 USB Spec 2.0 5.8.3 Bulk Transfer Packet Size Constraints, 并没有直说不能设小, 那就没问题咯, 于是在FX2中改了AUTOINLEN寄存器(slave.c)和Endpoint Descriptor(dscr.asm) 为2B, 尝试python继续各种错, 逻辑分析仪一看, 这是啥情况?
解释: Channel0 为clk, 10M, 由于采样率不够(?)的原因, 因此看起来奇怪, slrd与sloe拉低(有效)是因为看到FLAG A, 也就是EP2 EF(Empty Flag)拉高(不是Empty了), 这是应从FX2读入fpga的FIFO, 读完后由于FLAG A回到低, 此时应是从FPGA的FIFO到FX2, 可以看到FIFOADD选择了EP6, FLAG B是EP6的FF(Full Flag), 高意思是现在不是满的, 可以写. 但此时slwr应该拉低才对啊?
发2 word时, slwr工作正常. 但是, 细节图:
只写了一个word(上升沿写入). 为毛少一个?
纠结一段时间后终于找到问题, 而且是通过fpga的testbench找到的, 在看cy7c68013a的datasheet时, Slave FIFO Synchronous Write的那个图给了我灵感, 在数据读出后, Flag(由FX2驱动)会改变状态, 这个时间是tXFLG, 最大10ns. 于是我在isim里试了一下, 悲剧. 1个word.
2个word, 少发一个. SLWR也只有一个.
always@(*)begin
if((current_loop_back_state == loop_back_read) & (flag_ef == 1'b1))begin
slrd_n = 1'b0;
sloe_n = 1'b0;
end else begin
slrd_n = 1'b1;
sloe_n = 1'b1;
end
end
always@(*) begin
...
loop_back_read:begin
if(flag_ef == 1'b0)
next_loop_back_state = loop_back_wait_flag_ff;
else
next_loop_back_state = loop_back_read;
end
...
问题代码, 这样子生成的组合逻辑, 只要FLAG EF是1, 就会让slrd和sloe拉低. 且会转换状态为wait_flag_ff. 也就是说会在FIFO锁存数据的同时转换状态, 则应是存在一个竞争关系. 于是我把slrd和sloe换为钟控.
搞定.
实测1个word.
后来又发现传输数据时, 多向FPGA内的FIFO写一个数据, 在和Cypress的例程战斗了一段时间后, 我最终放弃了, 自己写了一个状态机, 加一个Xilinx的FIFO IP, 搞定.
全对. :)
接下来实现了从FPGA发送数据到Python.
Python显示实时数据的框架由之前在python下实时显示麦克风波形与频谱提供. 将数据源从pyaudio换为PyUSB, 搞定.