Grid ops / integration



do you mean grid version getting the 2.2 features? at this point i’m not planning to rebase off the master (once the 2.2 PR is merged) until the grid integration is complete. rebasing will be non trivial as there are several conflicts between the 2.2 and the grid branches, and i would prefer to keep my focus on completing the grid integration.

so my plan is:

  • finish grid integration
  • rebase and probably release one more beta that will have both 2.2 and grid features
  • submit a PR
  • update grid studies and create more scenes for the teletype code exchange

progress update: not much to report unfortunately, it seems being semi-retired makes one way busier than actually having a full time job! i’m trying to free my time for coding but things keep coming up. this should change next week, hopefully, at least until the holidays arrive…


have you ever considered allowing storage of values besides 1 and 0 in a button? could be a great place to sneak in values and syntactically if you are representing sequence steps with buttons, being able to use the value of the button rather than looking something up in the tracker columns might be a lot cleaner.


so, basically, if you do G.BTN.V 1 5 then when the button 1 is pressed G.BTNV would return 5? something like this could be done. the problem with this approach though is that you would have to use scripts to set these values (the beauty of using pattern data is that it has its own tracker editor and is persisted with the scene).


yea that is more or less what i would have in mind. for some uses, tracker would be preferable, but being able to set >1 values would be very useful when using a held button in one group and then setting its value with the press of another button from another group. for situations like this, i think it would help write more concise code.


i like the idea, and from the language perspective it can easily be added without changing anything or introducing any new ops, so i do want to add it.

this does mean though that i will need to introduce a couple of breaking changes - these values have to be stored to flash/usb when storing a scene. button states are already stored, not storing values would make things not intuitive. this means that older scenes might not load properly - i will need to think of a way to avoid that.


Just put along a little polysynth together using the grid operators and the TELEX expanders. Check out the post and a video over in the expanders thread:

Big shout-out to @scanner_darkly for how amazing the grid ops and visualizations are. They are crazy-easy to integrate with and unlock a tremendous amount of power.


so i’ve been thinking more about being able to assign arbitrary values to buttons and i realized i missed an important point. “value” for a button is also a state. so setting a value for a button means changing its state, and assigning a non zero value would have the same effect as pressing the button, which wouldn’t be desirable if you just want to assign a value.

this means adding this would necessitate separating the notions of “state” and “value” for buttons and introducing separate ops to set and get a value. but if we do that, it becomes something that is not really connected to button functionality, it just uses buttons as another way to store/retrieve values, which to me doesn’t feel right… patterns feel like a more appropriate mechanism for something like that.



I have a question about the Simple Sequencer in your study guide. How doe she last line, G.CLR; G.REC A 0 1 8 -3 -2, work? First, does G.CLR clear the whole grid each pulse, and then the whole thing gets re-written, or is it just clearing a single fader?

Second, what is the rectangle command doing? I assume something to do with the faded ‘progress’ bar? But if -3 and -2 are the fill and border…how do those negative numbers interact/work?



sorry to chime in, but I found myself in a similar situation just yesterday and noticed the grid ops reference (a bit burried on the wiki), it should answer your questions


to explain what G.CLR does exactly i need to explain how grid rendering works first.

there are 2 layers - one for controls (buttons, faders etc) and one for explicitly set LEDs. the control layer gets rendered first, and then anything set with G.LED, G.REC or G.RCT will be rendered on top of that. if you didn’t set any individual LEDs (or set them to level of -3) they are essentially “transparent”.

since you only have limited power over how grid controls are displayed (say, pressed buttons are always displayed with maximum brightness level of 15), this gives you the ability to fine tune the UI by drawing on top of other controls. say, you could hide a button by drawing a rectangle over it.

this wouldn’t be very useful by itself but it becomes more so if you use the 2 special brightness levels: -1 dims anything underneath, and -2 brightens it. the simple sequencer puts it to good use by using it to highlight the current step. so in this line:

G.CLR; G.REC A 0 1 8 -3 -2

G.CLR will clear all the previously set LEDs (please note this does not clear controls, just LEDs that were set with G.LED/G.REC/G.RCT). since we don’t set any other LEDs, just the current step, when we advance we can simply clear all and redraw (otherwise we’d have to clear the previous step with G.REC, which would be cumbersome and take more script space). and then we draw a rectangle over the current step with width of 1 and height of 8, fill is not used here (so just set to -3) and the border is set to brighten (-2).


That was helpful indeed. Tnx!


unfortunately, using ansible as a way for teletype to communicate with grid wouldn’t be possible with the current implementation. however there might be another way to switch between keyboard and grid without having to physically replug, as described by @sakul earlier in this thread. i’ve ordered a couple of usb switches and will post here once they arrive and i have a chance to test.


I wonder if would be a good idea to involve @tehn in this. For some reason switch cannot switch the new Arc and it would be great to find a soulution that works for all three controllers or at least learn something about USB switching and monome.


it’s a different scenario though - the monome switch switches same device between 2 hosts. what we need for grid integration is a switch between 2 devices and 1 host.


this is due to a firmware bug in the arc. it does not handle data line disconnection gracefully. the grid works fine.


@scanner_darkly i was looking at the grid ops and wondering: is there a way to detect if multiple buttons are currently pressed? use case: given a row that represents a 16-step sequence, i want to allow selecting a subsequence on that row by pressing two buttons at a time that would identify “start” and “stop” points


good question, it helped me discover a minor bug (“transparent” brightness level -3 is not supported for grid controls, only LEDs), thanks! will fix this in the next version. we can work around it for now though.

now, in general, if you want to track hold+press you would use momentary buttons as their state reflects whether the button is pressed, so you could simply use IF G.BTN.V .. to check that. for your scenario it’s a bit more complicated as we don’t want to be checking all 16 buttons in a row. let’s use a variable and set it to X coordinate of the last pressed button. when a button is released we’ll set it to -1 to indicate nothing is currently pressed. let’s use Z for this, execute Z -1 and add it to the I script.

now create your buttons (i’m using 1 row as an example here):
G.BTX 0 0 0 1 1 0 0 1 16 1

this creates a row of 16 momentary buttons that trigger script 1 when pressed. and here is our script 1:

IF && ! T EQ I Z: Z -1; BREAK

I stores the X coordinate of the button, T stores the state: 1 is pressed, 0 is released (have to store these in variables so the rest of the script fits). 2nd line means: if a button is released, and this is the button that was pressed last (so Z has its X coordinate), reset Z back to -1 and exit. this is so that we properly clear Z for single presses.

3rd line compares G.BTNV (which is stored in T) to zero, if it’s true it’s a release and there is nothing to do, so we break. finally, we know it’s a press, so we check if there is a previously pressed button (Z is not -1). if not, we just set Z and break.

at this point Z contains the previously pressed button, and I contains the currently pressed button (or, more accurately, their X coordinates), and using MIN and MAX we can get our start and end points (which i store in variables A and B here).

one problem here is that we can’t use these momentary buttons for the actual sequencer. so here is a trick: just add latching buttons on top of the momentary ones - but make sure to give them ids that are higher than the ones used for the momentary buttons (controls get rendered in the order of their ids, so you don’t want your momentary buttons hiding your latching ones).

one more trick: to display the currently selected loop the easiest option is to draw a rectangle using the special brightness level of -2 (“brighten”).

so, typing all this is a good way to feel the pain :slight_smile: and it’s just not a very elegant solution to something that would be a fairly common scenario. i’ll think of some better mechanism to handle this, maybe a couple of ops to check if there is a previously pressed button in a group.


Thanks for the thorough answer! I’ll try these techniques soon.

so, typing all this is a good way to feel the pain :slight_smile: and it’s just not a very elegant solution to something that would be a fairly common scenario. i’ll think of some better mechanism to handle this, maybe a couple of ops to check if there is a previously pressed button in a group.

Awesome! My hope was this might motivate some additional ops :slight_smile: I am a new TT user, but I see TT has patterns. I wonder if one or more patterns could be read out for a particular group. The patterns would indicate, e.g., currently pressed buttons in the order they were pressed—either by ID, or X/Y separately, etc. Not sure if this is idiomatic or not…


there is no way in TT to return an array of values from an op, but something similar could be done by providing a method that returns the total number of pressed buttons and then lets you read them using an index. i think for this purpose it might be an overkill though, something simpler like getting an id of the previously pressed button might be sufficient (basically, providing an op that would do what Z variable does in my example above).

another option could be having ops that give you the id of the leftmost/upmost/rightmost/downmost pressed button in a group (i’m leaning towards this option).


new beta! the main addition is fine (gradient) faders. this version also includes er-301 and faderbank support and new pattern and telex ops added by @bpcmusic.

i have to run so have to be brief, i will update the wiki later today or tomorrow. to use new gradient faders a change was made to G.FDR / G.FDX / G.GFD / G.GFX. i’ll illustrate with G.FDR, the new format is:

G.FDR id x y w h type levels script

dir parameter was replaced with type parameter. it’s backwards compatible, but now you also have additional types:

  • 0 - coarse, horizontal bar (same as before)
  • 1 - coarse, vertical bar (same as before)
  • 2 - coarse, horizontal dot
  • 3 - coarse, vertical dot
  • 4 - fine, horizontal bar
  • 5 - fine, vertical bar
  • 6 - fine, horizontal dot
  • 7 - fine, vertical dot

for fine fader types level parameter now means levels - instead of brightness level it indicates how fine a fader is. you can have up to 16 levels per button. in fine faders 2 edge buttons are reserved for inc/dec. pressing on other buttons sets it to “average” for that button. pressing and holding a button and then pressing another will “slide” value (script gets triggered on each value change).

as you see, dot versions are added - this is a nice way to implement radio buttons. G.FDR.N was changed in this version so that it’s 0 based now.

here is an example: (132.6 KB)
teletype.hex (446.8 KB)

Telex: Teletype expanders