From: Scott S. <sis...@gm...> - 2009-11-13 13:07:42
|
Well, I'm back. Remember me? I was trying to get the asynchronous API to work through Python ctypes a couple months ago. Ok, it's been a while. Well, I'm having the exact same problem in C++ that I was having in Python. The USB device I'm controlling is the picoLCDGraphic display. This has 4 controller chips, and when I send data meant to clear the LCD, the rightmost chip isn't cleared. Actually, it looks clear after the first transfer, but continuing with the steps results in the one chip not cleared, if that makes sense. I have a working C version (very basic) that doesn't have any problems. I've gone over them both making sure I'm not missing anything, but they're exactly the same. The biggest difference is, with the C++ version, I'm running on top of Qt. The Python version ran on top of pyGTK. Is there anything particular about GUI environments that would cause problems with libusb? |
From: Scott S. <sis...@gm...> - 2009-11-14 01:57:00
|
Oh I forgot about this part. First, here's a little code. void DrvPicoGraphics::DrvSend(unsigned char *data, int size) { class DrvSendCB : public PGSendCallback { struct libusb_device_handle *devh_; struct libusb_transfer *lcd_transfer_; DrvPicoGraphics *visitor_; public: DrvSendCB(DrvPicoGraphics *v, struct libusb_device_handle *devh, struct libusb_transfer *transfer, unsigned char *data, int size ) : PGSendCallback(data, size) { visitor_ = v; devh_ = devh; lcd_transfer_ = transfer; } void operator()() { libusb_fill_interrupt_transfer(lcd_transfer_, devh_, LIBUSB_ENDPOINT_OUT + 1, data_, size_, DrvPicoGraphicsSendCB, visitor_, 0); libusb_submit_transfer(lcd_transfer_); } }; DrvSendCB *cb = new DrvSendCB(this, devh_, lcd_transfer_, data, size); command_queue_.push_back(cb); } Now, the idea is that I place the functor in a queue for execution from a separate thread; that way the GUI isn't interrupted. Ok, so if I change the above code so that the transfer is sent right away instead, it works fine. This is exactly how the Python version acted as well. I always thought it had to do with Python's GIL or something, but apparently it's the design. Oh I should mention. These callbacks are executed according to a lock. When one's executed, a lock is set, preventing further callbacks executing. Then when the transfer's callback is executed, that lock's cleared, starting the process over. On Fri, Nov 13, 2009 at 7:07 AM, Scott Sibley <sis...@gm...> wrote: > Well, I'm back. Remember me? I was trying to get the asynchronous API to > work through Python ctypes a couple months ago. Ok, it's been a while. > > Well, I'm having the exact same problem in C++ that I was having in Python. > The USB device I'm controlling is the picoLCDGraphic display. This has 4 > controller chips, and when I send data meant to clear the LCD, the rightmost > chip isn't cleared. Actually, it looks clear after the first transfer, but > continuing with the steps results in the one chip not cleared, if that makes > sense. > > I have a working C version (very basic) that doesn't have any problems. > I've gone over them both making sure I'm not missing anything, but they're > exactly the same. The biggest difference is, with the C++ version, I'm > running on top of Qt. The Python version ran on top of pyGTK. Is there > anything particular about GUI environments that would cause problems with > libusb? > |
From: Scott S. <sis...@gm...> - 2009-11-15 07:27:26
|
After going over usbmon output I figured out what was wrong. Now I have a new issue. It's slow as molasses. Well, it's not fast enough to keep up with all that I'm throwing at it, and I'm not even close to a stress case. It's worlds slower than driving a RS-232 device. What might I do to speed things up? Each "blit" sends 32 transfers -- half 44 bytes, other half 38 bytes -- with 2624 bytes total. I'm waiting for each transfer to finish before sending the next one. Last time I tried to stack transfers my entire GUI environment locked up. Is it safe to send "however-many" transfers at a time? |
From: Hans P. S. <hse...@c2...> - 2009-11-15 10:13:53
|
On Sunday 15 November 2009 08:27:15 Scott Sibley wrote: > After going over usbmon output I figured out what was wrong. > > Now I have a new issue. It's slow as molasses. Well, it's not fast enough > to keep up with all that I'm throwing at it, and I'm not even close to a > stress case. It's worlds slower than driving a RS-232 device. > > What might I do to speed things up? Each "blit" sends 32 transfers -- half > 44 bytes, other half 38 bytes -- with 2624 bytes total. I'm waiting for > each transfer to finish before sending the next one. Last time I tried to > stack transfers my entire GUI environment locked up. Is it safe to send > "however-many" transfers at a time? Hi, Usually you want to avoid shorter USB transfers if you want performance. For the sake of the matter: In FreeBSD 8.0 there is a BSD specific USB API which allows you to send multiple frames per URB, and the frames will then be executed in hardware back-to-back, I.E. faster than one transfer every 125us for High Speed USB. or 1ms for Full Speed USB. In comparison to Linux, this back-to-back queuing is not dynamic, but hardwired with each transfer, so there will only be one event to userland for each "multi-URB" so to speak. Remember: If you just want to send 44 bytes in a transfer, the DMA structure requirement in the USB Host controller will be higher than that, and consequently the protocol is not efficient. --HPS |
From: Scott S. <sis...@gm...> - 2009-11-15 08:02:24
|
Yeah, stacking works, but it's still too slow. Maybe I'm doing something wrong entirely. I know USB has to be faster than RS-232. Hell, even 19200 baud rate is beating this! Although to be fair, the text driver sends a lot less bytes. :) You can't double buffer for the usb LCD; you have to send all pixels on every update, regardless if you just need to update one pixel. Mind taking a look at the source? http://code.google.com/p/lcdcontrol/source/browse/trunk/DrvPicoGraphics.cpp On Sun, Nov 15, 2009 at 1:27 AM, Scott Sibley <sis...@gm...> wrote: > After going over usbmon output I figured out what was wrong. > > Now I have a new issue. It's slow as molasses. Well, it's not fast enough > to keep up with all that I'm throwing at it, and I'm not even close to a > stress case. It's worlds slower than driving a RS-232 device. > > What might I do to speed things up? Each "blit" sends 32 transfers -- half > 44 bytes, other half 38 bytes -- with 2624 bytes total. I'm waiting for each > transfer to finish before sending the next one. Last time I tried to stack > transfers my entire GUI environment locked up. Is it safe to send > "however-many" transfers at a time? > > |
From: Scott S. <sis...@gm...> - 2009-11-15 10:12:15
|
I figured out a solution. Instead of updating the LCD every blit, I just update pixel data every blit, and update the LCD itself every 100ms, stacking two transfers. Seems to be doing alright. On Sun, Nov 15, 2009 at 2:02 AM, Scott Sibley <sis...@gm...> wrote: > Yeah, stacking works, but it's still too slow. Maybe I'm doing something > wrong entirely. I know USB has to be faster than RS-232. Hell, even 19200 > baud rate is beating this! Although to be fair, the text driver sends a lot > less bytes. :) You can't double buffer for the usb LCD; you have to send all > pixels on every update, regardless if you just need to update one pixel. > > Mind taking a look at the source? > http://code.google.com/p/lcdcontrol/source/browse/trunk/DrvPicoGraphics.cpp > > > On Sun, Nov 15, 2009 at 1:27 AM, Scott Sibley <sis...@gm...> wrote: > >> After going over usbmon output I figured out what was wrong. >> >> Now I have a new issue. It's slow as molasses. Well, it's not fast enough >> to keep up with all that I'm throwing at it, and I'm not even close to a >> stress case. It's worlds slower than driving a RS-232 device. >> >> What might I do to speed things up? Each "blit" sends 32 transfers -- half >> 44 bytes, other half 38 bytes -- with 2624 bytes total. I'm waiting for each >> transfer to finish before sending the next one. Last time I tried to stack >> transfers my entire GUI environment locked up. Is it safe to send >> "however-many" transfers at a time? >> >> > |