Teletype 3.+ feature requests and discussion


Yes, this works with just tele_ii_tx twice. I didn’t have to change anything on the Ansible side for that. Also happy to discover that I could use tele_ii_rx with multiple addresses when reading LED state without causing TT to hang waiting for non-active apps to respond.

1 Like

thinking of some interesting ways to use this… with earthsea this could be used to transfer sequences from teletype. or you could even use earthsea to record sequences from external sequencers (via tt input or telexi).

with grid ops this could also be used to have 2 grids control the same app (it’s probably not going to be fast enough to poll for all LED states and transfer them to the 2nd grid but doing some basic reflection of the main grid and passing presses from the 2nd grid should be doable).

1 Like

works great, and lots of fun:

in this video i’m using it to randomize/reset current parameter and to set the sequence length with the tt knob. using another grid to trigger tt scripts.

are you using address 0 for any of the i2c stuff?


Awesome, thanks for trying it out!

The only addresses I used were II_KR_ADDR, II_MP_ADDR, II_LV_ADDR, II_CY_ADDR, and ES - just sending the messages to all the relevant addresses for a Grid/Arc command seems to work pretty well. The broadcast address would probably be more efficient but I was hesitant to do that since it seems like you might only want Teletype manipulating the grid for one device rather than everything on the bus.

1 Like

Hello sorry to bug
As my placement and timing for this question is probably off
(Such is the way of my life)
Any way
Can I fire off a scene from a script?

1 Like

you can’t execute a scene from a script but you can switch to a different scene with SCENE op, then use it to switch back.

this is a better thread for general questions: Teletype workflow, basics, and questions


Not sure if this is the place to request this, or if its possible, but more 16n integration would be nice.
FADER.MAP x y z to constrain cv values of fader x between y and z.
FADER.SCALE x set scale to be used for fader quantization.
FADER.QT x return quantize value of fader x to scale
FADER.N x return note value of fader x to scale

Monome ecosystem firmware development backlog

i purposely kept the implementation simple in order to maximize the out-the-door “hackability” of the unit. That said, it shares the same i2c framework with the TXi. Porting those features over and including them would be a fairly easy exercise.

1 Like

I love your Telex modules and their awesome functionality is what inspired me to request similar for the 16n.

1 Like

Interestingly I thought I had messed this up because suddenly all my ANS.G.LED reads were coming back 27, but turns out I had a different Ansible firmware image loaded. This is maybe straying into a development question for another thread, but what’s odd is that I do initialize this value before the reads:

    d[0] = 0;
    tele_ii_rx(II_KR_ADDR, d, 1);
    tele_ii_rx(II_MP_ADDR, d, 1);
    tele_ii_rx(ES, d, 1);
    cs_push(cs, d[0]);

So what I don’t quite understand is why tele_ii_rx is reading 0x1b from one or more of these addresses when nothing there should be responding to the message I sent. The command bytes I chose but might not be the best long-term are:

#define II_GRID_KEY     16
#define II_GRID_LED     17
#define II_ARC_ENC      24
#define II_ARC_LED      25

so I don’t think there should be any collisions. Not clear to me if this is at the protocol level, a quirk of the driver stack, or something else I’m missing.

Unrelated: should Arc rings be numbered 1-4 for ANS.A ops instead of 0-3? Not sure what’s conventional with Arc – Grid ops are zero-indexed so I stuck with that, but TT/Telex (and Lua :bird:) start at 1.


Okay so this is fantastic fun:

A ANS.G.LED 6 7            # Kria note page button
IF GT A 4: BREAK           # <= 4 when not on note page
ANS.G.P 6 7; ANS.G.P 6 7   # press it twice to go to alt-note
X RRAND 0 15; Y RRAND 0 6
ANS.G.P 5 7                # go back to trigger page

However this is kind of verbose and potentially hard to decipher since you have to figure out the placement of the page buttons you want and do LED brightness comparisons to check state. But what if you had:

KR.PG     # read the active page 
          # maybe 1-10?
          # - odd primary pages
          # - even alt pages
          # - 8 for future duration alt page
          # - 9-10 for scale + pattern
KR.PG x   # set the active page
          # returning the page before the change

Probably this particular example can be achieved with less communication expense and head scratching, but I imagine you could easily get much weirder. I’m just immensely enjoying Kria Plays Kria over here. Such a good jam buddy!

Monome ecosystem firmware development backlog

yeah not sure what might be causing it. the command bytes you chose seem fine. i should mention that ii.h is not the definite list of all the commands used, some firmware could just use its own constants, it’s more of a recommendation to put any new commands there. i don’t think that’s the case here though, i checked the ansible code and i only see commands defined in ii.h. one theory is that maybe due to sending to several addresses at once something gets garbled and it misinterprets the command.

for teletype the convention that was agreed on in one of the tt threads was that we should make everything 0-based (even though there are some ops that use the 1-based convention). also, LV.CV and CY.CV ops are 0 based.

re - page ops - had the same thought, will definitely help with both making usage of ANS.G more predictable and efficient, and will help with something like where you emulate a bunch of presses, say, to randomize some parameters, and you are triggering that script from some external source, but you don’t want this to be applied on every page. and probably doesn’t need to be app specific, but could add another op to return what app is currently running?

also thinking, might be useful to have ops to emulate module button presses?

1 Like
Monome ecosystem firmware development backlog
Teletype I2C protocol

another idea for the new ops - performance recorder.

have one grid attached to ansible, another grid attached to teletype. create a script that reacts to grid presses and passes them to ansible. another button enables recording - in addition to passing presses to ansible it stores them in pattern banks. another script can “play” stored grid press sequences.

this can be used as a way to quickly store/invoke key combos, or a way to record a performance. if you use this with multiple scenes you could in theory automate your whole performance… (especially if we add an op to switch ansible apps).


Okay so there is some bug I haven’t figured out with the return values but here’s a first pass:

(outdated and buggy, current build below)

ansible.hex (247.2 KB - 79c8b51)
teletype.hex (574.8 KB - c2acdc3)

Ops added in addition to those above:

ANS.APP [x]  # get/set current app
KR.PG [x]    # get/set current kria page

The KR.PG numbering is as above, the ANS.APP ordering I just followed the order from ansible_mode_t, namely:

0 - levels
1 - cycles
2 - kria
3 - meadowphysics
4 - midi standard
5 - midi arp
6 - tt expander

The intention is for the set ops to return the value of the app/page before it was changed, making it easier to store/restore the state in a script. Something is messed up with this though - I can see (via print_dbg) the right response value being passed to ii_tx_queue on the Ansible side but am getting a lot of stuff back like 255 or that 27 again.

I moved the Ansible implementations for all these module-wide ops into a ii_ansible handler in main.c, and the other I2C handlers just call that function in their default: case. So these command values have to not collide with any of the commands accepted by any apps - I chose 15 for II_ANSIBLE_APP. However the caller still does not know which app is active and so has to tele_ii_tx/tele_ii_rx every app address in the ANS.APP functions - I’m guessing something here is what’s breaking the return values.

One exciting thing that didn’t click for me until I was nearly done implementing this is that with an ANS.APP op that lets you jump to any app from any other, the sufficiently dedicated Teletype programmer can use Kria or Cycles without ever involving any physical Grid or Arc hardware.


have you tried addressing just one specific app to see if that helps with the issue? fwiw i did a quick test with the previous version you posted and not seeing any garbage data.


I tried with a single address and with a couple different orderings for the reads, like all the transmits followed by all the receives, or this kinda thing:

static uint8_t ansible_addrs[] = {

static void op_ANS_APP_set(const void* NOTUSED(data), scene_state_t *NOTUSED(ss),
                           exec_state_t *NOTUSED(es),
                           command_state_t *cs) {
    uint8_t cmd = II_ANSIBLE_APP;
    int16_t n = cs_pop(cs);
    uint8_t d[] = { cmd, n };

    for (uint8_t i = 0; i < sizeof(ansible_addrs); i++) {
        tele_ii_tx(ansible_addrs[i], d, 2);
        d[0] = 255;
        tele_ii_rx(ansible_addrs[i], d, 1);
        if (d[0] < 27) {
            cs_push(cs, d[0]);
        d[0] = cmd;
    cs_push(cs, -1);

Sometimes it works, but still wind up getting a lot of 255s and -1s returned from the op, sometimes I’ve also seen 27. 255 seems like it would be something returning a -1 on the Ansible side and the sign getting lost, if it weren’t for the response value looking fine when printed from the Ansible side. The 27 it turns out comes from here when there’s nothing in the i2c receive queue.

The app consistently changes just fine, and the debug prints are right. I think the problem has gotta be something to do with how set_mode is gonna wind up reconfiguring the I2C peripheral and someone or other gets confused. I thought putting set_mode before sending back the response should work, because the configuration should be done after that, and thought maybe since Teletype was trying to check every address that it should wind up seeing the message even though it would be sent whichever one we switched to. However both set_mode followed by ii_tx_queue and the opposite order seem to show pretty consistent behavior.

Meant to respond this - I haven’t yet wrapped my head around how the key press vs key hold timer setup and control flow works, so I was less confident implementing these. Also I should do this more consistently for the hardware emulation ops but I ignore ANS.G/ANS.G.P ops if you’re in preset mode since this seemed dangerous. Maybe need another op to toggle the safety on presets.


strange, there must be some significance to the value but at a glance i’m not sure what exactly. and strange it wouldn’t work properly with a single address. i have a feeling there might be something else going on as a single read from a single app should be pretty reliable. just to rule out the op itself not being defined properly, could you try running the tests?

i haven’t thought of that - entirely possible. are you seeing the issue with just ANS.APP or others as well?

agreed, i think this makes sense.


Hm, getting an odd compile error here even on master. I’ve been building both Ansible and Teletype firmwares with this Docker image, e.g.

$ git clone --recursive
$ docker run --rm -it -v "$(pwd)/teletype":/target dewb/monome-build bash
root@586fef5bc691:/target# cd tests && make clean && make test
rm -f tests
rm -rf tests.dSYM
rm -f *.o


cc -o tests main.o log.o match_token_tests.o op_mod_tests.o parser_tests.o process_tests.o turtle_tests.o ../src/teletype.o ../src/command.o ../src/helpers.o ../src/every.o ../src/match_token.o ../src/scanner.o ../src/state.o ../src/table.o ../src/turtle.o ../src/chaos.o ../src/ops/op.o ../src/ops/ansible.c ../src/ops/controlflow.o ../src/ops/delay.o ../src/ops/earthsea.o ../src/ops/er301.o ../src/ops/fader.o ../src/ops/hardware.o ../src/ops/justfriends.o ../src/ops/meadowphysics.o ../src/ops/metronome.o ../src/ops/maths.o ../src/ops/orca.o ../src/ops/patterns.o ../src/ops/queue.o ../src/ops/stack.o ../src/ops/telex.o ../src/ops/variables.o ../src/ops/whitewhale.o ../src/ops/turtle.o ../src/ops/init.o ../src/ops/grid_ops.o ../src/ops/matrixarchate.o ../src/ops/wslash.o ../src/ops/seed.o ../libavr32/src/euclidean/data.o ../libavr32/src/euclidean/euclidean.o ../libavr32/src/util.o ../libavr32/src/random.o -std=c99 -g -Wall -fno-common -DSIM -I../src -I../libavr32/src
 (No such file or directory)
Makefile:33: recipe for target 'test' failed
make: *** [test] Error 2

All the files listed in this cc command do exist at this point in the build, as does the greatest/greenest script and /usr/bin/awk, so not sure what file it’s talking about, but I do notice that interestingly this lists ansible.c rather than ansible.o. Changing that gives the same error.

1 Like

yeah, should be ansible.o, looks like a typo in makefile.
sent you a PM, let’s move dev discussion there!

1 Like

I’m going to try and make my first button interface, today. Sort of mimicking a Lorre Mill Keyed Mosstone. Getting ready I’m wondering if it would be possible to add one more param to the G.BTX? I know there are many, many already, but here’s my thinking. If we could define spacing between objects, like buttons, we would be able to more easily create multiple groups of similar, but not the same (eg alternating level so adjacent buttons can be identified more easily). Or, if space was not at a premium, separation between objects could make the UI more easily readable.
BTW - I’m really just getting started with this - is ‘objects’ the correct term for buttons, faders, etc?

Monome ecosystem firmware development backlog