-
tinyUSB questions for @hathach and @pigrew regarding USBTMC:Many thanks for an awesome library. There is a lot of good capabilities here, now I just need to figure out how best to use them! —————— I’m working to extend tannewt’s TinyLogicFriend project that uses tinyUSB to make microcontroller boards into basic digital logic analyzers. Where I can use help: I am struggling to understand the best way of streaming the data from the device back to sigrok host via the USBTMC connection. I would like to get your recommendation on structuring this based on the USBTMC example that you provided. (I have read that a “circular” buffer would be the best method for this kind of streaming operation, but I’m not sure if there is an easy way to implement in tinyUSB.) My main questions:
I’d appreciate if you can suggest which callbacks functions (and the —————- A few other questions, please don’t feel like you have to answer them all:
—————- For reference I’m tracking my project here. Since this is a test and measurement tool, I’m using the tinyUSB’s USBTMC example as the framework. (With BulkIn and BulkOut endpoints). I’m integrating the TinyLogicFriend with the sigrok logic analyzer software package. Status: I have sigrok successfully sending and receiving SCPI text commands and measurement settings to the TinyLogicFriend via USBTMC. Now I am turning to the main communication for the logic analyzer data streaming. I would like to operate in either capture or streaming mode, but my first work is to setup streaming mode (where the data is measured from the pins and buffered onto the USB bus at the same time). Capabilities I want:
|
Beta Was this translation helpful? Give feedback.
Replies: 3 comments 6 replies
-
I forgot to mention, here is my hacked up USBTMC example with the SCPI parser integrated to decode and respond to commands: https://github.com/kmatch98/tinyusb/tree/master/examples/device/usbtmc/src Now my main focus is on figuring out how to RUN and stream back the data. |
Beta Was this translation helpful? Give feedback.
-
The TinyUSB USBTMC driver is not optimized for streaming operations (e.g., all of a message's data must be available before a message is sent, and data is copied between buffers a few times without DMA). However, it is definitely usable at lower data rates. USBTMC is fundamentally different than CDC. CDC is two streams of data, in and out. USBTMC is message based. For SCPI, each IN message is a reply to an OUT query. In and OUT messages do not happen simultaneously, one has to wait for the other to finish (which is different than CDC). With that in mind, a good SCPI syntax can be developed.
I would suggest finding an existing commercial instrument, and copying its SCPI syntax. You'll find that results are generally broken down into smaller "messages". For example, the KeySight 34465A can store 10,000 points in its internal buffers. The host sends a "R?" query that will return as many datapoints as are already measured (and remove those from the internal buffer). For USBTMC during a read, the host specifies a maximum message length. If the reply message is that exact length, it can be specified if the message is the full thing or a partial reply (EOM bit). There is a limitation in the TinyUSB USBTMC class driver that the full reply message must be known and in memory when the reply starts being sent. Since the host specifies the length, you shouldn't depend on the max length being short. Circular buffers or ping-pong buffers are appropriate data structures for you to stream the data into. You could use the tinyUSB queue structure or an interrupt-safe circular buffer. With the above class driver limitation, I would suggest following what the 34465A does, and have a "R?" command that fetches all available already streamed data or a "DATA:REMOVE?" command which will first waits for a particular amount of data to be available before initiating the reply. You could implement a "DATA:POINts:EVENt:THReshold" event register to allow a SRQ to be thrown when the proper amount of data is available before a read. So, I can imagine a transaction like:
The USBTMC device can either NOT reply until the data is available (causing the host viRead to block) or it can use a service-request (SRQ), and the host waits for the SRQ before it requests data. In general, avoid timeouts for SCPI read/write. (Timeouts are OK when waiting for a SRQ).
Use a bit of a status register, for a "complete" indication. Be aware that a lot of the USBTMC class driver is trying to be able to handle abort scenarios. USBTMC messages can be aborted at any time, using a "request and acknowledge" system. So, study the USBTMC and USB488 specifications, and study example instruments. Streaming is more complicated than how I've used the class driver so far. I hope that this will clear up some of the issues you've been having. Without me actually writing your program, it's hard to say exactly what you need to write in your "usbtmc_iter" function. I had contemplated including libscpi into the example, but at that time I thought I shouldn't include any external dependencies. It might be a good idea for the future, so that the example is more easily used. |
Beta Was this translation helpful? Give feedback.
-
I’m making this as answered. Thank you! |
Beta Was this translation helpful? Give feedback.
The TinyUSB USBTMC driver is not optimized for streaming operations (e.g., all of a message's data must be available before a message is sent, and data is copied between buffers a few times without DMA). However, it is definitely usable at lower data rates.
USBTMC is fundamentally different than CDC. CDC is two streams of data, in and out. USBTMC is message based. For SCPI, each IN message is a reply to an OUT query. In and OUT messages do not happen simultaneously, one has to wait for the other to finish (which is different than CDC). With that in mind, a good SCPI syntax can be developed.