Multiple interrupts

Status
Not open for further replies.

Geoff W

New member
I have wired up and programmed a Teensy 3.2 to receive and transmit a MIDI serial datastream. The purpose is to introduce a short preset delay between the data from an organ keyboard and the sound production from a synthesizer. I want to simulate the acoustics of a large church where the keyboards are a long way from the pipes so there is a delay between hearing what you play.

There are two parts to the process: (1) read and detect NoteON / NoteOFF events in the datastream and store them with a timestamp and (2) transmit each event after the preset delay has expired. The datasream runs at 31250 baud but the actual rate of events depend on when the keys are pressed… say a max of 16 /sec. There are three bytes per key pressed. A typical delay would be 250msec. I have tried storing a timestamp with the event and then checking if the delay for that event has expired using millis but this doesn't seem to work as the data arrival/storing and the delay expiry are really asynchronous.

Is there a way to use the Teensy 3.2 interrupts to trigger the transmission of each event after its delay has expired? It looks like there are four that can be active at any time but I think I would need up to 16. Thanks.

Here is the 'read/store' code and the current 'transmit after delay' code:
Screen Shot 2016-07-21 at 10.07.45.pngScreen Shot 2016-07-21 at 10.08.07.png
 
You've defined Note_event as 15 x 1, but you're using it as 15 x 2.

I would define a structure containing all the items you need for a data event, and then instantiate an array of these. This approach helps avoid issues like this, and the ones you get with parallel arrays.
 
You've defined Note_event as 15 x 1, but you're using it as 15 x 2.

I would define a structure containing all the items you need for a data event, and then instantiate an array of these. This approach helps avoid issues like this, and the ones you get with parallel arrays.

Thanks for spotting that! I agree with your point about one array but I used two because the note events are bytes and the time item need to be a long type. I guess I could make the array all long and convert to byte when using the note elements?
 
You need two 'Note_pointers' one pointing to the oldest element in the array, this is the 'read' pointer for the next note to resend. Then you need a 'write' pointer, pointing to where you should save the next incoming note and time stamp.
You can also use one note pointer and one event counter, so new notes are saved at position NOTE_pointer+NOTE_count.
 
Thanks for the info, mlu. I have modified the sketch to have two pointers as you suggest and it works! It seems to need a short delay of 1-2ms in the whole cycle otherwise no input is read. Also with a lot of input (fast playing on the keyboard) it misses some NoteOFF events which makes it hard to keep playing. I guess this happens when the Teensy UART buffer gets full. Thanks for your help.
Screen Shot 2016-07-24 at 11.22.43.pngScreen Shot 2016-07-24 at 11.22.26.png
 
Nice to hear it works, a few small things that might help:

If you make all the note data stuff and the time comparison calculations into unsigned 32 bit values (uint32_t) then you will avoid issues with overflow of the millis() counter, as it is you will get negative time_compare values when the millis() counter overflows stalling your flow of data. There is no need in midi for any signed integer values.

EDIT: If you will reboot your construction more often than every 49 days, then there will be no millis wraparound to worry about, and you can use your method of storing a LARGE value to signal an unset event.

Secondly, if the buffer is increased to 16 entries (any power of two), you can do the pointer increments and wrapping around to 0 using an and mask
Code:
read_pointer = (read_pointer + 1)&0x0F;
This is not critical but it will save a few clock cycles.

It also seems that you add the delay_millis twice, both when reading incoming events, and when testing if its time to send the oldes event.
 
Last edited:
Status
Not open for further replies.
Back
Top