更新:
非同期Cバージョンを作成しましたが、正常に動作します。
速度の問題はPythonのGILが原因であることが判明しました。その動作を微調整する方法があります。sys.setcheckinterval(interval)
間隔をゼロ(デフォルトは100)に設定すると、低速の問題が修正されます。あとは、他の問題の原因を突き止めるだけです(すべてのピクセルが塗りつぶされているわけではありません)。これは意味がありません。usbmonは、すべての通信が行われていることを示します。libusbのデバッグメッセージングは、異常なことは何も示していません。usbmonの出力を取得して、同期と非同期を比較する必要があると思います。usbmonが示すデータは、一見正しいように見えます(最初のバイトは0x96または0x95である必要があります)。
以下の元の質問、S。Lottで述べたように、これはUSBLCDコントローラー用です。発信エンドポイントメソッドであるdrv_sendには3つの異なるバージョンがあります。以下に違いを説明しました。非同期USB操作の概要を説明すると役立つかもしれません。同期USB操作は同じように機能することに注意してください。同期的に実行されるだけです。
非同期I/Oは5ステップのプロセスと見なすことができます。
- 割り当て:libusb_transferを割り当てます(これはself.transferです)
- 充填:実行する転送に関する情報をlibusb_transferインスタンスに入力します(libusb_fill_bulk_transfer)
- 提出:libusbに転送の提出を依頼します(libusb_submit_transfer)
- 完了処理:libusb_transfer構造(libusb_handle_eventsおよびlibusb_handle_events_timeout)で転送結果を調べます
- 割り当て解除:リソースのクリーンアップ(以下には表示されていません)
元の質問:
私は3つの異なるバージョンを持っています。人は完全に同期し、人は半非同期であり、最後は完全に非同期です。違いは、同期により、制御しているLCDディスプレイに期待されるピクセルが完全に表示され、非常に高速であるということです。半非同期バージョンは、ディスプレイの一部にしか表示されませんが、それでも非常に高速です。非同期バージョンは非常に遅く、表示の一部しか表示されません。ピクセルが完全に入力されていない理由と、非同期バージョンが本当に遅い理由に困惑しています。手がかりはありますか?
完全同期バージョンは次のとおりです。
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
半非同期バージョンは次のとおりです。
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))
これが完全非同期バージョンです。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))
そして、ここでキューが空になります。これは、gobjectタイムアウトのコールバックです。
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