Telex: Teletype expanders

If you don’t want to do it yourself, you could get in contact with somebody who already does kits for modules and has a shop, Synthcube, Modular Addict, Thonk come to mind. That would take away most of the hassle of having to sell/ship stuff.

1 Like

Yup. Also, there are a number of manufacturers who specialize in Eurorack module assembly that could help boost availability as well. Didn’t mean to sound negative above - just wanted to be clear that the current run will be sold out soon and there isn’t currently a scheduled resupply. :wink:

If there is a small amount of additional demand, the existing maker community should be able to handle it . Just look at Instagram - there are tons of O_C out there at this point. :slight_smile: :slight_smile:

If the demand is higher, either through non-lines Teletype users wanting in on the game and/or existing users wanting to add a few more to their setup, I can look to more automated methods of manufacture in the future and hopefully figure something out that works. :astonished: :astonished: :astonished:

Here is a shot of the v.015A firmware creation in progress … on a plane! The oscilloscope display represents two CV outputs running oscillators and logarithmic envelopes. The blue one is running at medium LFO rates and the purple one is running at extremely slow LFO rates, creating a periodic, random-feeling pulse of varying height:

Here are two scripts running on CV 1 and 2. The first shifts an oscillator to run in the range of 0V to 5V. The second inverts and envelope to trigger downward to zero from 5V.

Scripts work like this; for CV 1:

TO.CV.SET 1 VV 250
TO.OSC.LFO 1 600

It creates an oscillator that covers the range of +/- 2.5V and then shifts it up 2.5V.

The second uses the way that envelopes interact with offsets and negative voltages to create an envelope that rests at 5V and drops to 0V.

TO.CV.SET 2 V -5

This creates an envelope that will pulse from 0V to -5V and then shifts that center point up by 5V using an offset. A 1s metronome is pinging the envelope with TO.ENV.TRIG 2.

Here is another shot showing the clear difference between linear and logarithmic envelopes:

L 1 2: TO.CV.SET I V 10
L 1 2: TO.OSC.FQ I 110
L 1 2: TO.ENV.DEC I 1000
L 1 2: TO.ENV.ACT I 1

Both CV outputs are set to oscillate +/- 10V and both are given envelopes that decay over a second and trigger every second. Only CV 1 is set to logarithmic mode (mode 1 covers the 10V range). A periodic 1s metronome is pinging both envelopes with L 1 2: TO.ENV.TRIG I. The logarithmic curve is fixed due to CPU constraints and is consistent with the Teletype’s LOG curve (e.g. pow(N, 4)).


BTW: found a tiny bug; updated the release to .015A. Go Jet-Lag induced insomnia!!

I’ll make a demo showing off the new metronome stuff tomorrow. Back to bed now. :slight_smile:

1 Like

Thanks for that update, it opens up a lot of possibilities !

So the logarithmic curve of the enveloppe isn’t adjustable ? I mean, it can be eather 0 for linear or 1 for that exact same curve but nothing in beetween (sorry I’m not sure to have understood that part :wink: ).

JUst amazing!!! How “hi-rez” are you able to get the osc’s? I have JF but one of the big draws to the expanders was the osc banks and the envelopes…

On a plane! Boss :slight_smile:

For v.015, sort of. There are modes that reduce the range of the curve. Mode 1 spreads it over 0-10V, Mode 2 is 0-5V, Mode 4 is 0-2.5V, and so on.

You see - we’re pretty maxed out in CPU resources with being able to have 4 CV + 4 TR outputs with envelopes, audio rate oscillators, amplitude slewing, pitch slewing, waveform morphing, internal metronomes, pulse timers, and i2c communications all happening simultaneously at a sampling rate of 15,625Hz. Frankly, I’m dazzled by what I’ve been able to squeak out of it.

Computing Log curves is expensive computationally. I was deeply skeptical of being able to squeeze it in, but with more CPU optimization and a miserly approach, it worked!

I’m considering attempting to include another log table in the future - and maybe seeing if I can get some sort of morphing from linear to log. BUT - no promises; I will also have to find more performance optimizations in order to shoehorn it in. We’re pretty maxed out.

Ok. More demos.

Here is a video demonstration of the unified metronome control and the clock multiplier. Patch to follow.


TO.M.ACT 1 1
L 1 4: TO.CV I VV 250
L 1 4: TO.OSC.LFO I * I 50
L 1 4: TO.OSC.CTR I VV 250



Here is what is going on:

  • TR 1 is pulsing on eighth notes (clock divider 2); patched to “snare”
  • TR 2 is changing its division each time SCRIPT 1 is triggered (wrapping from 3 to 7); patched to “hat”
  • TR 3 & 4 are pulsing on the beat (quarter notes); patched to SCRIPT 1 and “bd”
  • CV 1-4 are oscillating at different LFO rates between 0 and 5V; patched to the pitch controls for the “hat” and “snare”

The TO.M.* commands work on ALL metronomes within a device (e.g. TO.TR 1-4). They save a lot of loops in scripts and allow for hard sync between the metronomes.

The multiplier (TO.TR.M.MUL) is smart and only will shift its division on the next clock cycle. It is independent of both the DIV and COUNT operators, allowing some really wacky interactions. The above example is simple for clarity sake. :slight_smile:


Aiming to get the next beta out by Monday with this in it.


1 Like

The 4 oscillators run at 15,625Hz - which means a max frequency of 7.8125 kilohertz. The outputs are 16 bit over +/-10V.

Just running them alone, the oscillators are interpolated and sine waves sound pretty nice. When you start piling on the computational load with waveform morphing, envelopes, etc., the interpolation turns off. The other waveforms (triangle, saw, and square/pulse) are not band-limited or antialiased and thus have a nice grunge to them.

The TELEX run the CV slew and OSC slew (portamento) at the same sampling rate - so the values are butter-smooth when transitioning. (No nasty k-rate updates making external oscillators stair-step.)

I should note that there are new Teensy processors around with significantly more horsepower (at a higher cost). The firmware should just run. With a few minor tweaks to the code, it should execute comfortably at a much higher sampling rate. One might also want to adjust the CV output circuit to raise the LPF (or not - if you were looking simply to oversample).

BTW: JF is an amazing module; I love mine!!! :heart_decoration:


+1 for hoping someone does another run or offers builds. I’m late to the Teletype party.


this thread is such a great example of lines at work - from a simple idea almost 2 years ago to actual modules. @bpcmusic deserves the highest praise - i’m in awe at the whole process, the attention to details (i’d be happy to have them with paper panels, really, but they look better than some commercial modules!), the insane amount of work you put into this, especially considering you did this work for free. thank you.


quick TXi tip: you can use the knobs as attenuators for the inputs by using SCALE command:

B SCALE 0 V 10 0 A TI.IN 1```

you have to use an extra variable to store `TI.PARAM` because the 2nd line would be too long otherwise.
if you want to use it as an attenuverter (so that it also inverts the value) do this:

B SCALE 0 V 5 0 A TI.IN 1```

Thx @scanner_darkly. I’ve enjoyed every minute of this process and owe many, many people a huge pile of thanks for helping along the way (including you). It really was a group effort. Once I’ve finished sending out the units for this run, I’m going to post a recap with the proper acknowledgments to all who helped make this thing happen. :slight_smile:

Sent out the last of the units that were reserved and had proper survey responses and then payments. We have a surprisingly small number folks that I haven’t heard from since they initially expressed interest. I reached out to them via PM on Friday and they have till 12:00am Monday to respond before I’ll consider their units returned to the pool.

I’m keeping a list of folks who missed out on the initial reservations and are interested in one of these units. If you haven’t already, PM me your email and what you might be interested in. I’ll notify you at some point on Monday via email for what is available and the process for staking a claim.

Still working out the details, but in the hope of closing things out quickly, it will be some sort of first-come, first-serve type of thing until I’m out of units. Ideally this last step gets sorted quickly and I can put away my shipping table and packing supplies before hump day. :slight_smile:

Another v.015 demo:

Quad AD Envelopes with 2xTXi control and EOR + EOC Triggers


L 1 4: TO.CV I V 5
L 1 4: TO.ENV.ACT I 1
L 1 4: TO.ENV.LOOP I 0


A 1; B 1
L 1 4: SCRIPT 8


A + A 1

This script uses two TXi to set the attack and decay speeds for the four envelopes on a single TXo. It sets the envelopes to loop infinitely (loop value of 0). The envelope’s end of rise (EOR) and end of cycle (EOC) triggers are routed together to the TR output corresponding with the envelope number (CV 1 => TR 1). Each metronome pulse (set it as fast as you want) reads the 8 param knobs and updates the envelopes’ attack and release parameters.

One of the things I noticed is that the envelopes don’t update their attack or decay rates mid-cycle. I’ll put it on the list for a future release. Should be easy. :wink:


@sam - moving TX startup speed details to the Expander thread.

@tehn suggested optimizations:

My initial thoughts:

So I went to test the theory.

I was able to move some lookup tables to stay in flash memory (with a slight lookup penalty). This decreased the app size from taking up 70% of the Teensy’s dynamic memory to taking up 11%. I was super-confident that the test would improve startup speed significantly.

All I got for that MASSIVE reduction was a little under 10ms improvement in startup time.

Next, I’ll do some more code tests - but I have a feeling now that it is less about code and more about the circuit taking time to get the Teensy up to 1.7V - which starts its boot sequence.

I’d wondered if that may be an issue too. You might be able to test it as a theory by doing a warm reboot.

To what extent is it PSU dependent too?

At any rate, we want to delay the I script as we don’t want a race even with Ansible (which takes approx the same time to boot).

Do you want to figure out your best worst case, er, you know what I mean… and we can add 10% to it.

Gonna scope it up tonight and see what is going on. I’ll share my results.

1 Like

Hmm. Hooked up the scope. Not what I expected either.

Blue channel is recording power-on. Red channel is recording a hard-coded TR pulse at the end of the initialization function.

I’m not sure where in this sequence I actually flipped the switch. We’re dealing with milliseconds and me holding the probe against the Teensy V-in and ground. I’ll assume it is right around that voltage spike in blue.

What I see is that the Teensy power rises to 1.7V quite quickly. Then, it is less that 400ms between that power on and the pulse execution.

I have a secondary pulse being sent from the Teletype at init on a delay of 181ms. It blinks at exactly the same time (give or take a few ms) as the red pulse. I don’t have a 3+ channel scope to show it here.

So…the theory of super-slow voltage rise due to my circuit seems to not necessarily be the case.

When I profiled my init function, the whole thing took less than a millisecond. I’ll check it again tonight.

Hmmm. Wish there was a “boot faster” button. That would make this easier. :slight_smile:

Just looking through the setup() function.

Are you 100% sure you’re building with the DEBUG code disabled? Otherwise this line

while (!Serial);

will stop the world until the serial port initialises.

edit: can you try manually setting a GPIO high right at the beginning of the setup function and measuring that. I’ve noticed a lot of pointers and calls to new, it’s possible that you’re over taxing the allocator. Looking at the code, you could probably eliminate all the calls to new and the pointers (as far as I can tell there is no dynamic allocation needed e.g no calls to delete). Do you know much about RAII style C++?

edit: not sure the use of new will cause the hundreds of milliseconds delay though… is it possible there is some before main code hidden somewhere?

100%. With no USB connected, it would have never started up as it would be waiting forever for the serial connection. :slight_smile:

I will this evening when I’m back from the office and a dinner. On second thought, might be more like early tomorrow morning as I’ve not had the best of luck with wine and probes in the past. :wink:

It doesn’t. When I measured it, it didn’t look like the init function took over 1ms to execute.

At this point, I’m really not sure where the delay is coming from. Need to root around some more to see if I can identify any more potential culprits.

Will check again tonight/tomorrow morning.

1 Like

Try a blank sketch with nothing in it apart from turning a GPIO on? That will give you the absolute baseline. (Well, not without replacing the Teensyduino framework.)

After you’ve sobered up though :tropical_drink: :sunglasses:

1 Like

Ok. Test complete.

Right there with you, @sam; was planning to create an empty sketch with only the LED set. Here is the code:

And, what is going on is so evident visually that I didn’t need to wait till the wine-free morning in order to scope it. :slight_smile:

  • The TXo on the left is running the full module code is getting TO.TR.P 1 delayed at 191ms.
  • On the right, the code above is executing with a pulse on TR 1 and nothing else; no additional libraries, no additional code…

Video follows:


Time to get more paper towels and dig in.