Teletype 3.2+ feature requests and discussions

Hey everyone! I just preordered two Disting EX and am looking forward to integrating them into my Teletype workflow. I have some more general questions about TT with regards to the 3.2 firmware I’ll need to upgrade to. I’ll start with two for now.

  1. Will 3.2 still run scripts I run on my current firmware? I’ve only begun using TT for i2c stuff with JustType, so I’m wondering if I can reenter and continue to run vanilla scripts from TT after I update.

  2. I’m assuming, based on what I’ve read in the “Teletype Disting EX Integration” thread that it should be possible to send i2c ops to Disting EX, while also sending CV and trigs through the outs of the panel in a single script, correct? I know it’s possible in current firmware, but was wondering because of that wild screen in some of @scanner_darkly’s Instagram videos at the top of the other thread. :joy:

Part of the reason I want to know is because I’m hoping I don’t need a second TT to run vanilla scripts and one for Disting i2c shenanigans. Thanks!

This is the playground I’m putting together:

I will probably be posting in the appropriate thread for guidance on the best way to route i2c with more detailed plans, but this setup will provide me with the ability to connect different combinations of Grid, Norns, 16n, Polyend Tracker, and a Sensel Morph for any kind of idea I get.

  1. yes, you should be able to run your current scripts after updating the firmware. you do need to save your scenes to a USB stick first before updating the firmware, as it will erase anything currently saved.

  2. yes, you can definitely control CV and gate outputs and use i2c ops at the same time.

that’s quite an i2c heavy setup, you’ll likely need to spend some time getting it to work reliably - the easiest approach is to add devices 1 by 1 confirming it still works properly after adding each one.

1 Like

Thanks for answering my questions. And yeah, I have some thinking to do about i2c… I was planning for two distinct i2c networks in here. My initial thought is that one network will be TXb and ER-301 (so I can tweak the 301 with 16n) and the other will be TT, TXi, TXo, the two Disting EX and possibly Just Friends. I think both of those should work on their own… but will obviously have to see. I appreciate the advice!

Are glitches in the Ctrl+H section worth mentioning as bugs?

In my book, yes! Worst case you get redirected to proper bug reporting :+1:

TT+JF4.0 beta has arrived! July is but a memory but dual JF are now: teletype.hex (688.0 KB)

JF Selection OPs:
Set primary JF internal follower address to 1 or 2 (nonvolatile save to JF memory). You must perform JF.ADDR 2 with only one JF on the I2C bus! Then plug your primary JF in. Otherwise you will just change the address of both units.

Select JF 1 or 2 as primary for all OPs below. Other JF will be considered secondary.

Channel selection, where relevant:
1 thru 6 = primary JF channel 1-6
0 = all six channels on primary JF
7 thru 12 = secondary JF channel 1-6
-1 = all channels of both JF
(not implemented: all six channels on secondary JF)

New Synth/Geode OPs:

Set channel x pitch to y (legato pitch change).

Equivalent to JF.NOTE but alternates between primary and secondary JF evey 6 notes. Mix both JF outputs for 12-voice polyphony.

Reset JF.POLY note counter.

New MODs:
JF0: ...
Subsequent command will excute for both primary JF and secondary JF (e.g. JF0: JF.MODE 1 for dual synth/geode mode).

JF1: ...
Subsequent command will treat JF address 1 as primary.

JF2: ...
Subsequent command will treat JF address 2 as primary.

Updated existent JF OPs (channel behavior as noted above):
TR x y
JF.VTR x y
JF.TUNE x y z
JF.VOX x y z

New switch position getter OPs:
Returns 1 for sound, 0 for cycle.

Returns 0, 1, or 2 depending on Transient / Sustain / Cycle switch position.

Most of the knob + CV value getter OPs (not listed here) seem unstable in testing (n=2) and will likely be removed before incorporating into the official TT firmware. PM me for details if you’d like to test!

EDIT: I haven’t tested this with JF4.1 yet but I am hopeful that the stability of knob getter OPs (already included in the above beta) has been improved: JF.RAMP, JF.CURVE, JF.INTONE, and JF.TIME should return the value of the given knob + CV on the jack. JF.FM should return only the knob value. Previously these commands were causing JF to crash after several calls, requiring a reboot. Let me know how they are for you!


So, all the new features are JF oriented, right?

Should I update both TT and JF in sync for this to not-break something?

On a different tangent: I’ve come to not-like-so-much the wrapping nature of N.S. I’ve made a personal OP that work just like N.S but doesn’t wrap and works correctly with negative degrees. There seems to be some traction towards a non wrapping version, I’d be more than happy to contribute my OP as a drop-in replacement, either as an old school patch or (if I can figure out how) as a PR.

1 Like

You’ll need the latest JF firmware circa July 2020 installed, but nothing will break if you don’t have it.

@ParanormalPatroler this beta is focused solely on JF4.0 features. The Teletype firmware should receive an official release soon; the goal is to cover the latest JF4.0, w/2, and crow functionality.


I’m very excited to share a pair of flexible bit-mask scale OPs for working with 12TET that I made, called N.B and N.BX. I hope they would bring joy to other teletype users, and ultimately I hope they could be considered for adaption into the official firmware.

teletype.hex (703.3 KB) teletype.pdf (641.8 KB) teletype_op_nbx.diff (13.5 KB)

They’re centered around the idea that users can define their own scale on the fly, while still making it easy to use by including a bunch of preset scales. There’s a multi-scale version as well, called N.BX (basically store up to eight scales and use them at the flick of an index). No lookup-tables (doesn’t take up a lot of memory), works with any number of notes in any combination, non-wrapping 1-indexed degree including negative degrees.

Remixed from the manual (for the actual manual, take a look at the attached teletype.pdf) + some added info:
Converts a degree in a user-defined equal temperament scale to a value usable by the CV outputs.

N.B d
Get degree d of scale
N.BX i d
Get degree d of scale at index i

N.B r s
Set scale, r is root note, s is scale, either set with bit mask or by selecting a preset (s < 1). Default root is 0, default scale is Major.
N.BX i r s
Set scale at index i.

Note that N.B is actually addressing scale at index 0 “behind the scenes”, so N.B and N.BX 0 are equivalent.

Examples (note names assumes your oscillator is tuned with 0V=C):

CV 1 N.B 1            ==>  set CV 1 to 1st degree of default scale
                           (C, value corresponding to N 0)
N.B 0 B101011010101   ==>  set scale to C-major (default)
CV 1 N.B 1            ==>  set CV 1 get 1st degree of scale
                           (C, value corresponding to N 0)
N.B 2 B101011010101   ==>  set scale to D-major
CV 1 N.B 3            ==>  set CV 1 to 3rd degree of scale
                           (F#, value corresponding to N 6)
N.B 3 B100101010010   ==>  set scale to Eb-minor pentatonic
CV 1 N.B 2            ==>  set CV 1 to 2nd degree of scale
                           (Gb, value corresponding to N 6)
N.B 5 -3              ==>  set scale to F-lydian using preset
N.BX 1 3 B100101010010   ==>  set scale at index 1 to Eb-minor pentatonic
CV N.BX 1 2              ==>  set CV 1 to 2nd degree of scale
                              (Gb, value corresponding to N 6)
N.BX 2 5 -3              ==>  set scale at index 2 to F-lydian using preset

Values of s less than 1 sets the bit-mask to a preset scale:

0: Ionian (major)
-1: Dorian
-2: Phrygian
-3: Lydian
-4: Mixolydian
-5: Aeolean (natural minor)
-6: Locrian
-7: Melodic minor
-8: Harmonic minor
-9: Major pentatonic
-10: Minor pentatonic
-11 Whole note (1st Messiaen mode)
-12 Octatonic (half-whole, 2nd Messiaen mode)
-13 Octatonic (whole-half)
-14 3rd Messiaen mode
-15 4th Messiaen mode
-16 5th Messiaen mode
-17 6th Messiaen mode
-18 7th Messiaen mode
-19 Augmented

Questions (ultimately for @scanner_darkly):

  1. I strongly feel that the user should be able to setup scales with the B binary notation. However it seems that B is “backwards”, which at places shows when using these OPs. I suppose we’re pretty set on the way B works?
  2. N.B and N.BX are defined almost identical in the source, I’d like to make a single setter core and a single getter core, similar to the chaos OPs, and then call the core in for instance op_N_BX_set and op_N_B_set (the difference would be that op_N_B_set always works on scale at index 0). However I’m not sure where (which file) it would be most appropriate to put the core functions?
  3. At the moment, there are 8 scales indexable by i. A friend suggested adding more, to be able to chain scales. Since each index takes up just two ints of memory (one for the root and one for the bit mask), I think the number could be higher, any thoughts on this?
  4. There are a few magic numbers in the code, like the number of indexable scales, I’d like to use #define instead, where should I place such #define?

This is a great addition! Really like these new ops, they are very straight forward to understand and very musical! I for one would love to have them merged with the official firmware.


1 Like

Cool! Great addition - reminds me strongly of the Euclidean scale theory , first introduced (afaik) by Carla Scaletti in the Kyma environment. She discovered that it turns out 12tet intervallic divisions share the same kind of remainder division generating algorithms as the now famous Euclidean Rhythm ones


Teletype is becoming quite the amazing melody machine! Wherever we land with N.B, I can modify QT.B to draw upon the same scale. N.BX also suggests the existence of QT.BX, so I had better read up on how that would work :sweat_smile:

The 12-bit scale masks present some challenges w.r.t. readability and bitwise manipulation. Thoughts below:

  • <<< and >>> OPs won’t work as expected because you push bits into the 4 unused slots.
    • Perhaps we should have some scale rotation OPs which are constrained to 12 bits?
  • Root as MSB or LSB: The readability of B101011010101 for C-major is good because it reads left-to-right like a keyboard, but now you need to use BGET X 11 to check the root bit instead of BGET X 0.
    • I think this is a fair trade-off. I’d rather have to remember to reverse a bitwise OP than type the scale in backwards every time. I recall @Joe had similar feelings when I released QT.B and DEL.B, which are currently backwards from N.B's bit order. QT.B can change to match N.B but DEL.B must remain right-to-left bit order.
    • Alternatively, the B entry method could be reversed!

this would make it an exception and would go against the standard number notation, so it would be counterintuitive to anybody not aware of the exception, so my vote would be against it. a better option would be to either have a special “reversed binary” notation with its own identifier, or an op that would reverse it for you.

these ops are all in maths.c, right? i would just put it there.

are you worried about the memory consumption? i don’t think extra 16 (or even more) bytes would be concern so i’d say go for it.

if you define any structs or variables in math.h that use these defines i’d put it there, otherwise they can go to math.c.

thank you @a773 ! Absolutely brilliant addition.

1 Like

Thanks, I’m a bit slow, not sure what you’re suggesting. I guess you suggest that I reverse the expected order of bits in N.B(X), add a new BREV function and a new R reverse-binary token?

I just wrote a BREV, but I think an R reverse-binary token (sorry not sure what’s the correct word, I’d like the user to write “R101” instead of ""BREV 101) would be great as well. However matching is happening in match_token.rl, not really the place for reversing function. Is there a good place to place this reverse_bits function? It could be used both in match_token.rl and in my BREV function in maths.c…

EDIT: Placed it in helpers.c, seems decent, or?

i meant adding a special number type, reversed binary, which would be specified with R or RB: R1010.

if we add that i don’t think we need a conversion op - i was suggesting it as an alternative option to the above. also, it’s less characters with a dedicated format instead of a conversion op.

1 Like

Ok cool, so you suggest i change my scale OPs to work with R instead of B, right?

Now both are done, i guess there’s no harm in having both R and BREV?

not sure why would you need to change your ops? at the end it’s the same number, we’re just talking about different representations of it:

B1111000011110000 == R0000111100001111 == XF0F0 == 32767

i don’t really see the point of having an op to reverse if we have a way to specify the reversed format - once you type it in it’ll get converted to decimal format anyway, so it’s just simpler to type R... instead of BREV B...

1 Like

Ok, sorry for the confusion, let me be clear:

My N.B r s takes a bit mask in s for selecting which notes in the octave should be present in the scale. I would like to make it as easy to use as possible, so (with root = 0 = C) user would use B101000000000 for setting a scale of C and D. No problem that’s working. So what if someone wants to set a scale with BSET, which has bit 0, LSB "to the right? This user would have to set notes “from above” and not “from below” (bit 0 is top most note, bit 11 is lowest note) as they did when typing with B101000000000.


  1. Keep my OPs as they were, no R or BREV introduced, users should be aware that setting a scale with BSET will operate “from above”
  2. Reverse the operation of my OP and suggest users use R... (reversed binary)

Agreed, I just though that since I already implemented both R... and BREV, they might both be useful to have in teletype. Obviously R... is handy when typing in, but cant be used programatically, whereas BREV would go into the bit-wise tool-box already containing BGET, BCLR, >>> and such.

1 Like