Reworking MIDI RX, how midi sent to Grid is processed

Each control element has a dedicated LED, with options for custom RGB colors, intensity change and LED animations. These are all powerful features to provide feedback on interactions with Grid and controlled parameters. But what happens, when the parameter states are not set by turning a knob on a controller, but it’s reported from the controlled software or hardware back to Grid?

Well you go to the system events, select the midi rx event and try to figure out how to map changes to specific control elements. It’s not an intuitive process, I think we could do better.

Let’s discuss what kind of bidirectional communication is the most useful for you. Do you know an example where this works right? What would you except from Grid, when you send such data to it? Should it work with standard MIDI, sysex or else?

We already started to work on support for scaled value pickup, so this might be interesting not only for encoders, but potmeters as well.


I’ve been experimenting with setting up my new grid controllers (4 x en16),
as a 8x8 grid of RGB Led encoders, that reflect a RGB matrix on my pc, using bidirectional communication.

I use the grid to set values with the encoders in relative mode, so when I turn an encoder, midi is sent to my software. Then a value is read from my matrix, on either the red, green or blue channel, then it’s adjusted by the encoder increment or decrement, and the final value is sent back to the grid controller, updating the LED in question.

I can choose which channel I’m interacting with either by paging, or simply inside the software.

further more, when I recall a preset, or saved state for the matrix on the software side, all the RGB values are sent out to the controller, in order to reflect the updated state of the matrix (64 x 3 values, index/RGB).

So far I can make it work just fine, but I have a few questions about ways to optimize, and improve the code and functionality.

My experiments so far include; sending different midi commands, in order to address the 3 independent RGB values,

control-change for red.
note-on for green.
after-touch for blue.
then using a lookup object inside grid editor, we can map the midi.cmd’s to indices.

cmd → color-channel
176 → 0 (control-change)
144 → 1 (note-on)
160 → 2 (after-touch)

Alternatively I’ve been to differentiate between the RGB color variables, which eliminates the need for the lookup object.
red = cc on channel 1
green = cc on Ch 2
blue = cc on Ch 3

then I setup a self variable in the Init-page called rgb = {0, 0, 0}
so I can later set the RGB values on the individual grid elements like this:
element[i].rgb[color-channel] = midi.param2*2
then finally update the led color:
led_color(i, 2, element[i].rgb[0], element[i].rgb[1], element[i].rgb[2])

However when I set all the values when recalling on the pc,
all the 64 x 3 values (cells x color-channels), have to be limited to 10ms intervals.
If I attempt to send midi out to the grid controller any faster,
I seem to encounter errors, either stuck Led’s, or entire controllers blinking,
so I have to limit the speed at which I update the controller which isn’t ideal.
64 x 3 x 10ms ~= 2 seconds per update.

I’ve tried limiting the frequency at which the Led’s update,
by introducing if statements in the midi RX actions,
so that led_color will only change when the blue channel is updated,
Since I send out red, green and blue for every cell,
there is no need to update until all three have been received.

another potential bottleneck is the fact that I can’t seem to address individual grid controllers when I want to.
If I sent a midi message to grid, all the devices receive the same message,
hence I need to filter messages on the midi RX actions, using module_position_x() and module_position_y(), and more if statements,
that ensure that the device Led’s only update when the midi.param1 is within the range of the controller. which may be inefficient.

pos = (module_position_x()*16)+((module_position_y()+1)//8)
if param1>=pos and param1<(pos+16) then
i = param1 - pos;
element[i].argb[ch] = param2 << 1
if ch == 2 then
led_color(i, 2, element[i].argb[0], element[i].argb[1], element[i].argb[2])

I also tried changing to code to using bitwise operators instead of multiplication and division, where possible,
but it doesn’t seem to have an effect on efficiency, or the allowed minimal update refresh-rate.

pos = (module_position_x()*16)+((module_position_y()+1)//8)
pos = (module_position_x()<<4)+((module_position_y()+1)>>3)

I’ve worked with other DAW controllers, that are able to update almost instantly, through regular USB 2/3 ports (no USB-c),
devices like the icon Qcon daw controllers, or novation launchpads, can update super fast,
so I’m wondering if there are any obvious ways to speed up the communication from pc to grid devices?
or if I’m simply misunderstanding how to leverage the grid studio correctly.

I’d like to test sending midi sysEx messages to the grid devices midi RX page,
but I can’t find any documentation on how to parse sysEx on the grid device side,
only info on sending sysEx from Grid and out.
Maybe sysEx would be a faster way to communicate, since I could format a single long message,
containing all 64 x 3 values wrapped within a single sysEx message.
Instead of sending 64 x 3 separate messages out vie USB.

  • sorry for the long rant, but I’d rather provide as many details as possible,
    so hopefully it’s easier to understand my experience with bidirectional communication on grid so far.

I look forward to any suggestions on how to optimize my setup further,
and perhaps more options will be available in the future, if midi RX is getting reworked.

Either way, I’m loving the controller so far!

  • Svend/Gussi


Thank you for the well explained post.

This is a really complex issue as the real problem itself lies indeed in the way Grid modules work as a system when using MIDI RX.
As you summarized, all messages sent to Grid are sent to all individual modules, where they have to be sorted/filtered with conditional statements under the MIDIRX event.

So right now, the limiting factor for MIDI RX is the following as I understand it is the following.

When receiving MIDI, each message is forwarded to the other modules to make sure no message is lost. So the hosted module sends these out on side PCBs to conneected Grid modules and waits for the messages to arrive on the other modules.
But now, if the hosted module receives a new message during this time from either the computer or any other module as it’s waiting will cause the errors you experienced.

Now normally this shouldn’t happen, because the serial communication between modules should be faster than the messages received from the computer, but in multimodule setups, this becomes a very complicated routing issue and all communication slows down.

Currently the hosted Grid has no idea if the messages properly arrived to all modules until they really get there and in a circular setup, like yours with 8x8 grid matrices messages will bounce in all directions slowing this process down further.

So the MIDI RX rework should deal with exactly this behavior. We’re attempting to make the way Grids spread messages between each other smarter, faster and prevent loops like this from happening.

This is my thoughts on the matter. Keep in mind that I’m not the engineer dealing with the protocol itself but this is my understanding of the issue.

(Small note on your earlier question, there is no way to parse SysEx on Grid yet, but we’ll make this happen, since many of you asked for it. SysEx could be a way to solve this, I agree. Reducing the number of messages you send is the key in the current form of MIDI RX.)

Thank you for sharing your experiences, we’ll be able to use this as an example setup that should work perfectly, but it just doesn’t.

Thank you for the reply,

just as a quick side note,
I did also test the 4 x en16 grid devices side by side, in a 16x4 setup.
And the issues with whole devices flashing (usually blue on all Leds),
where still present, and as far as I remember, limiting the update frequency on the midi messages from my pc to grid at ~10ms was still necessary for stability.

For now I’ll keep testing,
and keep you updated if I find a better solution.