TeensyDAQ: Communicating experimental data over USB

DysonTheSphere

New member
Hello everyone!
I am a computer scientist working for a research university and have embarked on a journey to create an open-source data acquisition solution for researchers and STEM students utilizing the Teensy 4.1. I am VERY new to embedded development but have strong proficiency in C/C++.
I suspect that over the coming months I will become a regular around here, and hopefully not just a bearer of dead-weight.

Pardon my initial ignorance but I have a few questions for you maestros of all things Teensy.

Serial USB Communication​

A key design goal of TeensyDAQ is to create configuration files for experiments in a Jupyter Notebook that are sent serially over USB to the Teensy. It is critical that the Teensy is able to relay information back to the host machine as it becomes available.
Sidenote: I know that Jupyter Notebooks are sandboxed but am planning on using File I/O from a separate python script with pyusb to circumvent this issue.
Naturally I want to provide a facility from which an experimental run can be suspended or terminated mid-run. The USB Serial page offers a code sample that appears to be polling-based. While I'm sure this is great for highly choreographed USB communication (like sending data between sensor reads), per my (limited) knowledge this would require shifting CPU context from handling data acquisition to checking if any USB messages have come through the wire. It's my current understanding that what I really need is to utilize interrupts from the USB_nUSBINTR (pg. 2462 of Processor Reference Manual) in order to keep CPU context on data acquisition while treating incoming USB communication as the exception rather than the rule.
I have looked through the headers in /cores/teensy4/ and found that serialEvent*.cpp/.h has no implementation.
Is this an unsolved problem and I'll have to go deeper than Teensyduino provides (implement new functionality to support the USB Interrupt Register)?
Or am I simply missing/misunderstanding something?

ADC and DAC​

Another key design goal is to accurately time 100kHz 12 bit analog input sampling with true analog rather than PWM, I see that from the reference manual (pg. 3401-3402) this should be feasible with "10/11 bit accuracy". Is this simply a matter of using analogReadRes(12) and analogRead() on the correct pins (24-25 per this thread)?
Inversely, does a true analog out exist?

I appreciate any suggestions, comments and criticisms.
Thank you all for your time and expertise.
 
I have looked through the headers in /cores/teensy4/ and found that serialEvent*.cpp/.h has no implementation.
Is this an unsolved problem and I'll have to go deeper than Teensyduino provides (implement new functionality to support the USB Interrupt Register)?
Or am I simply missing/misunderstanding something?
There's no default implementation of the serialEvent functions because they're weak symbols; they don't exist unless the user program implements them. If you do implement them, the yield() function (executed when loop() returns and in a few other places) will check for pending data and call serialEvent() if necessary.
You don't want to hook the USB interrupt, that gets used for all sorts of things in addition to data arriving.
 
There's no default implementation of the serialEvent functions because they're weak symbols; they don't exist unless the user program implements them. If you do implement them, the yield() function (executed when loop() returns and in a few other places) will check for pending data and call serialEvent() if necessary.
You don't want to hook the USB interrupt, that gets used for all sorts of things in addition to data arriving.
Thanks for the reply!
I'm not quite sure I understand what you meant by the USB interrupt being used for purposes other than the arrival of data, what else would be setting a flag on the SRE register (StartOfFrame received, bit 7) other than receiving an initial Start of Frame packet?

EDIT: My apologies, it appears that is the enable bit, it looks like the SRI bit is actually responsible for triggering the interrupt.
 
Thanks for the reply!
I'm not quite sure I understand what you meant by the USB interrupt being used for purposes other than the arrival of data, what else would be setting a flag on the SRE register (StartOfFrame received, bit 7) other than receiving an initial Start of Frame packet?

EDIT: My apologies, it appears that is the enable bit, it looks like the SRI bit is actually responsible for triggering the interrupt.
Start of Frame doesn't indicate arrival of data, it just indicates a new bus cycle. This occurs every 125ms for high speed devices.
Even if it did, incoming data may not necessarily be for the serial interface; it may be for a different endpoint (e.g. a control transfer or one of the other interfaces).
 
Start of Frame doesn't indicate arrival of data, it just indicates a new bus cycle. This occurs every 125ms for high speed devices.
Even if it did, incoming data may not necessarily be for the serial interface; it may be for a different endpoint (e.g. a control transfer or one of the other interfaces).
Got it, thank you for the explanation.
So without USB interrupts perhaps a solution would be to check for Serial.available() after sending a measurement? I have to send data back anyways so I might as well check for a received message after I send something back.
 
Back
Top