teletype 5.0.0 beta testing

has it really been almost two years?
teletype 5.0.0 is ready for beta testing.


there is a fair number of new features and fixes, so we could really use community’s help with beta testing. please report bugs in this thread, i will post new versions here as we fix bugs.

huge thanks to all the developers and contributors: @3-foot-1, @a773, @alanza, @attowatt, @Byzero, @desolationjones, @Dewb, eiginn, @Lightbreaker, martica.

but also all the amazing folks who inspire this work by doing wonderful things with teletype :black_heart:

new features

  • drum ops [Byzero]
  • support for multiple faderbanks [Lightbreaker]
  • I2C2MIDI ops [attowatt / scanner_darkly]
  • new disting ex ops: dual algorithms, EX.M.N#, EX.M.NO#, EX.M.CC# [scanner_darkly]
  • new op CV.GET [scanner_darkly]
  • new op: SCALE0 [scanner_darkly]
  • new ops: $F, $F1, $F2, $L, $L1, $L2, $S, $S1, $S2, I1, I2, FR [scanner_darkly]
  • improved TR.P accuracy [scanner_darkly]
  • all line endings now accepted for USB files [scanner_darkly]


  • PROB 100 would only execute 99.01% of the time [martica]
  • cache currently-running commands to avoid corruption during SCENE ops [3-foot-1]
  • fix off-by-one error in P.ROT [3-foot-1]
  • fix CROW_Q3 operation [3-foot-1]
  • fix bug when QT.B input was negative [desolationjones]
  • fix bug with G.FDR not being rendered in grid visualizer properly [scanner_darkly]
  • fix EX.LP not returning correct values [scanner_darkly]
  • fix MIDI IN ops channel being off by 1 [scanner_darkly]
  • fix STATE not taking into account the status of DEVICE.FLIP [scanner_darkly]
  • fix BPM rounding error [scanner_darkly]
  • reset M timer when changing metro rate [scanner_darkly]
  • fix KILL not stopping TR pulses in progress [scanner_darkly]


  • remove duplicate Disting cheatsheet section [eiginn]
  • improve page load time in Chrome/Safari [Dewb]
  • fix docs on QT.BX [a773]
  • fix function ops docs [alanza]

platform improvements

  • create a simple Actions workflow for tests [Dewb]
  • separate scene serialization logic from USB disk logic, add scene serialization tests [Dewb]
  • build documentation PDF in Actions workflow [Dewb]
  • suggest TinyTeX as docs-building toolchain [alanza]


installing this firmware will overwrite your existing scenes! back up your scenes using a USB flash drive and make sure to rename files before restoring. this is a beta version, after flashing you will be prompted to press the button to initialize teletype - make sure to do so. update procedure: modular firmware updates | monome/docs

[2023-05-03] 5.0.0 BETA 1 teletype.hex (857.3 KB) (240.8 KB)


teletype.html (1.2 MB) teletype.pdf (784.3 KB)


[2023-05-03] first beta


i’ll be posting descriptions of some of the new fixes/features in this thread over the coming days. some easier ones:

SCALE0 x y z / SCL0 x y z op - this is a handy op for scaling if both lower ranges are 0 (so essentially a shorter way to do SCALE 0 .. 0 .. x)

CV.GET - this op is similar to CV in that it returns the value of a CV output but unlike CV this op takes slewing and offset into account

TR.P now has improved accuracy and can be as short as 1ms - previously it could be off by up to 9ms insta demo


now the more interesting stuff… i’ll copy the doc description for now and will expand later and provide some examples on how to take advantage of these.

$F script

This op will execute a script similarly to SCRIPT op but it will also return a value,
which means you can define a script that calculates something and then use it in an expression.
To set the return value, either place an expression at the end of the script without
assigning it to anything or assign it to the special function return variable FR. If you do
both, FR will be used, and if you don’t do either, zero will be returned.

Let’s say you update script 1 to return the square of X: * X X (which you could also
write as FR * X X). Then you can use it in an expression like this: A + A $F 1.

This op can save space if you have a calculation that is used in multiple places.
Other than returning a value, a function script isn’t different from a regular script
and can perform other actions in addition to calculating something, including calling
other scripts. The same limit of 8 maximum nested calls applies here to prevent infinite loops.

If you need to be able to pass parameters into your function, use $F1 or $F2 ops.

$F1 script param

Same as $F but you can also pass a single parameter into the function. Inside the function
script you can get the parameter using I1 op.

Let’s say you create a script that returns the square of the passed parameter: FR * I1 I1.
You can then calculate the square of a number by executing $F1 value.

$F2 script param1 param2

Same as $F but you can also pass two parameters into a function. Inside the function script
you can get them using I1 and I2 ops.

Let’s say you create a script that returns a randomly selected value out of the two
provided values: FR ? TOSS I1 I2. You can then save space by using $F2 1 X Y instead of
? TOSS X Y. More importantly, you could use it in multiple places, and if you later
want to change the calculation to something else, you just need to update the function script.

$L script line

This op executes the specified script line. This allows you to use a script as a library of sorts,
where each line does something different, so you can use the same script for multiple purposes.
It also allows you to use free lines in a script to extend another script.

This op behaves similarly to $F op in that it can be used as a function in an expression
by setting the return value with FR. Let’s say the first line in script 1 is this: FR * X X.
You can then get the square of X by executing $L 1 1.

If you want to use it as a function and you need to pass some parameters into it, use
$L1 / $L2 ops.

This op is also useful if you have a loop that doesn’t fit on one line - define the line
later in the script and then reference it in the loop:

L 1 6: A + A $L 1 3

Don’t forget to add BREAK before the line so that it’s not executed when the whole script
is executed. If you use this technique, you can also save space by using $S op which executes
a line within the same script.

$L1 script line param

Execute the specified script line as a function that takes 1 parameter.

$L2 script line param1 param2

Execute the specified script line as a function that takes 2 parameters.

$S line

This is exactly the same as $L $ line but saves you space on not having to specify the script
number if the line you want to execute is within the same script.

$S1 line param

This is exactly the same as $L1 $ line param but saves you space on not having to specify
the script number if the line you want to execute is within the same script.

$S2 line param1 param2

This is exactly the same as $L2 $ line param1 param2 but saves you space on not having
to specify the script number if the line you want to execute is within the same script.


This op returns the first parameter when a script is called as a function using
$F1 / $F2 / $L1 / $L2 / $S1 / $S2 ops. If the script is called
using other ops, this op will return zero.


This op returns the second parameter when a script is called as a function using
$F2 / $L2 / $S2 ops. If the script is called using other ops, this op will return zero.

FR x

Use this op to get or set the return value in a script that is called as a function.


LOL, boots upside down! Upon reboot things are right side up :slight_smile:

DEVICE.FLIP would set you right also. I don’t know if it’s possible to commit that state when building firmware?

@scanner_darkly these are amazing. Actual functions with arguments! It’s like a whole new device.

1 Like

it should show a message when you power it up asking you to press the button - you want to press it (this warning is only shown when you flash non official releases). if you press the button, it will initialize teletype properly.

Wow! I’ve often wondered how it might be possible to implement functions in the teletype language, but couldn’t have dreamed of such a simple, non-disruptive and elegant solution. Bravo! (I haven’t downloaded this yet, but intrigued to see how it handles recursion…)


I don’t know how often I wished for something like the function calls. As far as I am concerned, this is the biggest functional improvement since the release. Amazing! And being able to address both of my 16ns is also awesome. Thanks so much to everyone involved in the development! Can’t wait to get home and try it out.


Amazing, that should take care of any available free time during this summer :sun_with_face: massive thanks for this, lots of super handy stuff packed in there!


Echoing the “this is amazing” sentiments above with my own: this is amazing!

The new function syntax is so elegant and powerful. I’m already trying to imagine what strange behaviour is going to emerge when combining functions with global variables (A, B, X, Y, etc) that are modified by other scripts. A single “function script” becomes a parameterized family of functions that can be changed on the fly.

So cool. Can’t wait to try this out.


Adding to the chorus here. I have done so much weird stuff to try to approximate functions and I’m beyond excited to play around with this. Have embraced the teletype constraints and in a way I’m happy this wasn’t around when I started… but this is a very welcome opening up.

Something that isn’t immediately obvious to me: do the functions take up script slots or are there two new “scripts” available in f1 and f2?

Thanks to everyone for the ongoing creativity. This is a remarkable little corner of the world.

EDIT: Rereading and wow $L might secretly be the coolest thing in here.


wow! so much good stuff in here :heart_eyes:

thanks to @scanner_darkly and everyone else that made contributions! can’t wait to dig in :partying_face: :partying_face: :partying_face:


Agreed! Imagine using $L P.NEXT P.NEXT in the metro script… sequenced code execution mayhem!


We finally have achieved a version of @tehn ’s timeline concept :slightly_smiling_face:


also love that timeline made it into crow via @Galapagoose a decade later


So, that’s basically one-line scripts that can be triggered from other scripts ?
I’m having a hard time figuring this out.

Ah, it’s more like a list of sequential commands where the playback can be manipulated. Very much possible now by loading up the pattern with addresses for individual lines of scripts, as described above by @SimonKirby .


it works the same way as SCRIPTso you can call a script recursively (or you could call script 1 from script 2 which calls script 1…), but it will limit the maximum recursion depth to 8 to avoid infinite loops.

i’ve also refactored the code to make it easier to do mods to increase the script count - check out script.h.

no new scripts - any existing script can be used as a function script.

one very useful application for executing a script line is that now if you have a loop that doesn’t fit on one line, you can place it within the same script instead of having to use another script. you can even have two or more enclosed loops within one script:

L 1 9: A I; $S 3
L 0 2: $S 4

I’m away from the Teletype just now so can’t test it, but does that mean it has an implicit stack for return variables, so you could do a factorial calculation like:


IF EQ I1 1: 1
ELSE: * I1 $F1 1 - I1 1

thanks for the practical example of using script lines…
i see tons of folks excited by the possibilities of functions and wanna get a better sense of why

sorry if the answer is obvious to most users but what’s something possible now (w/ functions) that wouldn’t have been before? it sounds exciting and i’d like to wrap my head around this if i can