Author Topic: Wish: DigiUSB update with blocking IO option, buffer size adjustment, tx buffer remaining bytes  (Read 3944 times)

Bluebie

  • Sr. Member
  • ****
  • Posts: 486
My wishlist for DigiUSB:

1) expose a function which returns an integer: how many bytes have not yet transmitted to the host computer? call it something like 'DigiUSB.queuedBytes()'
2) expose a function for blocking IO: while(DigiUSB.queuedBytes()) { DigiUSB.refresh() }, call it 'DigiUSB.transmit()', 'DigiUSB.drain()', or 'DigiUSB.flush()' - I think I like transmit() the best of the three. I'd like to see flush() included too as a method alias for compsci people like me.
3) a definable constant to set the size of the ring buffers - DIGIUSB_BUFFER_SIZE or something like that
4) "gets" function which DigiUSB.refresh() until it receives a specified character or reaches a length: DigiUSB.getString(char* buffer, int terminator, int max_length) - first arg is pointer to char* buffer, int is a '\n' sort of character terminator, or -1 if no terminator, int max_length would typically be sizeof(buffer), protecting against buffer overflows or specifying how many chars to read when terminator is -1.
5) An update to DigiUSB wire protocol to transmit and receive more than one byte at a time:
    For device-to-pc bytes, return a pointer to the ring buffer and set return length to length of remaining bytes to transmit, or end of ring buffer's memory, whichever is shorter. With this change, the ring buffer should be able to be cleared in two USB requests worst case, and requires no extra memory allocation - currently it would take 128 usb requests to clear the transmit buffer.
    For pc-to-device writing, a usbFunctionWrite function should be added to receive bytes as data in bulk. Another USB request should be added for pc to probe device asking "How many bytes do you have free in your receive buffer?" so it can then transmit no more than that many bytes in the next write request. If the buffer gets full, pc can keep asking how many free bytes there are until there's a non-zero response before pushing more in. Yay! No more ring buffer overflows!

One of the biggest problems I've had with DigiUSB is writing messages in to it which overflow the ring buffer and getting corrupt messages on the host end as a result, and having no reliable way to wait until the buffer is clear before adding more bytes. Usually blocking IO makes more sense to me, as my loops tend to sample some data, then write it to the host, where the host writing segment should be fully complete before going back in to the sampling stage. The most important thing to me is a way to detect when the transmit buffer has drained so I can loop on DigiUSB.refresh() till host has received the whole message. Currently I have loops like for (int i = 0; i < 1000; i++) DigiUSB.refresh(); but if the host PC gets busy for a moment, the buffer sometimes doesn't clear and my program overflows the transmit buffer, so host pc's next reading attempts get corrupt data.

I think functions like println should return immediately unless they need to block and loop on DigiUSB.refresh() to avoid overflowing transmit buffer. If user program needs to freeze to avoid buffer corruption, so be it! If user wants to fully drain the buffer before moving on, they should opt in to that by calling DigiUSB.transmit().

Major version number of DigiUSB's usb enumeration stage should be incremented if any of the wire protocol changes are done, so programs can detect how they should talk to the device.
« Last Edit: December 28, 2012, 04:58:06 pm by Bluebie »

percentcer

  • Newbie
  • *
  • Posts: 1
Hey, not sure if you\'re still having issues with this but I ran into the same thing today...  I added some code to the DigiUSBDevice which helps solve it:

int DigiUSBDevice::tx_remaining() {
  return RING_BUFFER_SIZE - (RING_BUFFER_SIZE + _tx_buffer->head - _tx_buffer->tail) % RING_BUFFER_SIZE;
}


and an example of it in use:

if ( DigiUSB.tx_remaining() > MIN_CHARS ) {
    DigiUSB.println(reading);
}

This will return the remaining number of bytes in the tx buffer, so you can check beforehand if you have enough room (sizeof(\"some string\")).