Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Interrupt driven callbacks and sends #43

Closed
mink99 opened this issue Apr 22, 2016 · 3 comments
Closed

Interrupt driven callbacks and sends #43

mink99 opened this issue Apr 22, 2016 · 3 comments

Comments

@mink99
Copy link

mink99 commented Apr 22, 2016

Sometimes I get into the situation, that I have to break from the main loop into an inner loop, which will only terminate under a certain condition.

Pseudo code example

void loop()
{
  Midi.read();
  while (1)
  { 
     if (somethingHasHappened() break;
  }
}

While the inner loop is running, midi.read is never executed. Therefore the defined callbacks are never called. Midi thru is interrupted. Not good.

Currently I have a call to midi.read() as the first statement in the implementation of somethingHasHappened(), but I would not consider this as proper design.

An approach to solve this problem would be to run the callbacks interrupt driven. HardwareSerial has already installed an isr to fill the serial ring buffer. We could steal this interrupt, peek the bytes from the port, construct the midi message as in midi.read() , call the midi callbacks, and call the original isr, so that midi.read() will behave as before, except that the callbacks already have been called.

Please discuss ....

@mink99
Copy link
Author

mink99 commented Apr 22, 2016

Additionally an add on could be an automatic or continuous mtc or midi clock generator, this time tied to a timer interrupt.

@franky47
Copy link
Member

While I like the idea of making it asynchronous, I don't think it would be wise to temper with the hardware serial interrupts.

Arduino's HardwareSerial code is a LLD (low level driver) dedicated to interfacing with the hardware, that requires to use interrupts to work efficiently. The library is built on top of that, at the base of the application layer. Then on top of that, the user would write their application code.
Bypassing this layer-based hierarchy often leads to hard to understand/debug programs, IMHO.

Now, I've also been in your situation, where some IO code had to run while another piece of internal code needed to run. In a single-threaded event-based environment, every task (piece of code to run) has to take the least amount of time possible and yield for the next one to be executed without increasing too much the global loop cost. This involves breaking up busy wait loops into passive wait loops (store the data you're working with in the loop, yield, then come back later to continue). This is actually what the library does when 1-byte parsing is enabled: if somehow you end up with many bytes of data in the RX buffer, it won't try and parse/thru/callback everything in one pass, it will yield between each byte so the application code can do stuff too. Depending on the situation, this can help avoiding task bottlenecks, at the expense of a little latency for bulk transfer.

Now for a MIDI clock generator, as Clock messages can be sent at any moment (even between bytes of any other message), tying it to a timer interrupt would be an easy thing, and would not even require to use the library (just send midi::Clock or 0xF8).

@mink99
Copy link
Author

mink99 commented Apr 26, 2016

The midi clock thingie would be a help for the less-experienced developers, as sending clock is something that cannot be done in the main-loop, and to provide correct spp backing will be forgotten in most cases. That is why I suggested to put it not into the core but into an add-on. Or an example.

@franky47 franky47 modified the milestone: Backlog Oct 5, 2016
@franky47 franky47 removed this from the Backlog milestone Feb 11, 2021
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants