私は非同期Cバージョンを書いていました。
スピードの問題は、PythonのGILが原因であることが判明しました。その動作を微調整する方法があります。 sys.setcheckinterval(interval)
間隔をゼロ(デフォルトは100)に設定すると、低速の問題が修正されます。今残っているのは、他の問題を引き起こしていることです(すべてのピクセルが満たされているわけではありません)。これは意味をなさない。 usbmonはすべての通信が通過していることを示します。 libusbのデバッグメッセージングでは、普通のことは何も表示されません。私はusbmonの出力を取って、同期と非同期を比較する必要があると思います。 usbmonが示すデータは一見して正しいように見えます(最初のバイトは0x96または0x95でなければなりません)。
元の質問では、Lott氏は以下のように、USB LCDコントローラ用です。 drv_sendの3つの異なるバージョンがあります。これは発信エンドポイント方式です。私は以下の違いを説明しました。おそらく、私が非同期USB操作の概要を説明すると助けになるでしょう。 syncrhonous USB操作は同じ方法で動作することに注意してください。それは同期しているということだけです。
私たちは、5段階のプロセスとして、非同期I/Oを表示することができます。
- 配分:転送あなたについての情報をlibusb_transferインスタンスを移入:libusb_transfer(これはself.transferある)
- フィリングを配分します転送を提出するのlibusbを頼む(libusb_submit_transfer)
- 完了取扱い:libusb_transfer構造に転送結果を調べ(libusb_handle_eventsとlibusb_handle_events_(libusb_fill_bulk_transfer)
- 提出を実行したいですタイムアウト)
- 割り当て解除:私は、3つの異なるバージョンを持っている
:リソース(以下に示されていない)
元の質問をクリーンアップします。 1つは完全に同期、1つは半非同期、最後は完全非同期です。相違点は、同期が完全に表示されているLCDディスプレイのピクセル数がで、実際にはです。半非同期バージョンは、ディスプレイの一部に表示されるのはですが、それでもまだ非常に高速ですです。非同期バージョンは実際には遅く、はディスプレイの一部分のみを満たします。ピクセルが完全に埋め込まれていない理由、すなわちがなぜ非同期バージョンが本当に遅いのかわかりません。手がかりは?ここで
def drv_send(self, data):
if not self.Connected():
return
def f(d):
self.drv_locked = True
buffer = ''
for c in data:
buffer = buffer + chr(c)
length = len(buffer)
out_buffer = cast(buffer, POINTER(c_ubyte))
libusb_fill_bulk_transfer(self.transfer, self.handle, LIBUSB_ENDPOINT_OUT + 1, out_buffer, length, self.cb_send_transfer, None, 0)
lib.libusb_submit_transfer(self.transfer)
while self.drv_locked:
r = lib.libusb_handle_events(None)
if r < 0:
if r == LIBUSB_ERROR_INTERRUPTED:
continue
lib.libusb_cancel_transfer(transfer)
while self.drv_locked:
if lib.libusb_handle_events(None) < 0:
break
self.count += 1
self.command_queue.put(Command(f, data))
を完全に非同期バージョンです:ここでは半非同期バージョンです
def drv_send(self, data):
if not self.Connected():
return
self.drv_locked = True
buffer = ''
for c in data:
buffer = buffer + chr(c)
length = len(buffer)
out_buffer = cast(buffer, POINTER(c_ubyte))
libusb_fill_bulk_transfer(self.transfer, self.handle, LIBUSB_ENDPOINT_OUT + 1, out_buffer, length, self.cb_send_transfer, None, 0)
lib.libusb_submit_transfer(self.transfer)
while self.drv_locked:
r = lib.libusb_handle_events(None)
if r < 0:
if r == LIBUSB_ERROR_INTERRUPTED:
continue
lib.libusb_cancel_transfer(transfer)
while self.drv_locked:
if lib.libusb_handle_events(None) < 0:
break
self.count += 1
:
はここで完全に同期したバージョンです。 device_pollはスレッド自体にあります。
def device_poll(self):
while self.Connected():
tv = TIMEVAL(1, 0)
r = lib.libusb_handle_events_timeout(None, byref(tv))
if r < 0:
break
def drv_send(self, data):
if not self.Connected():
return
def f(d):
self.drv_locked = True
buffer = ''
for c in data:
buffer = buffer + chr(c)
length = len(buffer)
out_buffer = cast(buffer, POINTER(c_ubyte))
libusb_fill_bulk_transfer(self.transfer, self.handle, LIBUSB_ENDPOINT_OUT + 1, out_buffer, length, self.cb_send_transfer, None, 0)
lib.libusb_submit_transfer(self.transfer)
self.count += 1
self.command_queue.put(Command(f, data))
ここでキューが空になっています。これは、オブジェクトのタイムアウトのコールバックです。
def command_worker(self):
if self.drv_locked: # or time.time() - self.command_time < self.command_rate:
return True
try:
tmp = self.command_queue.get_nowait()
except Queue.Empty:
return True
tmp.func(*tmp.args)
self.command_time = time.time()
return True
ここに転送のコールバックがあります。ロックされた状態をfalseに戻すだけで、操作が終了したことを示します。
def cb_send_transfer(self, transfer):
if transfer[0].status.value != LIBUSB_TRANSFER_COMPLETED:
error("%s: transfer status %d" % (self.name, transfer.status))
print "cb_send_transfer", self.count
self.drv_locked = False
まあ、私はpyusbを使用していません。 pyusbは同期転送のみをサポートするlibusb-0.1に基づいているため、libusb-1.0をPythonのctypesでラップしています。第二に、私は速度の問題を修正しましたが、この他の問題も速度に関連していないのかどうか疑問に思います。第三に、私は転送を分析するためにusbmonを使用しています。私はどのように速度を分析するか分からない。とにかく、誰かがついにこれに答えようとしていたことを知って嬉しい:) – Scott
さて、私はlibusb開発者が提案した非同期Cバージョンを書いています。いくつかの髪を引っ張った後、私は正常に動作するようになった。それは本当に奇妙な問題です。 usbmonは転送が完了していることを示しています。コールバックが呼び出されています。私はこの時点で他に何ができるのか分かりません。 – Scott
「エンドポイントサイズ」という意味がわかりません。私は1バイトと8バイトでしたが、どちらも正しいです。両方とも0x96で始まり、8バイトの転送に続いて7個のゼロが続きます。 – Scott