Telex: Teletype expanders


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.

Teletype 2.0 beta (release candidate 2 released 13th July 2017)

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.


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.


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:


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.


I downloaded the video and Zaprudered it frame by frame. The Teletype is fully booted before the 2 LEDs come on :confused:

According to this post, you can define your own startup_early_hook to run code even earlier in the boot process.

Right, just tried my own TXo, with DEL 210: TO.TR.P 1 in the I script, I get no pulse at power on. With DEL 211: TO.TR.P 1 in the I, I do get a pulse.

That’s with a Doepfer LCB w/PSU3.


Announcing TELEX Firmware v.016

TELEXo Changes:

  • Recompiled reducing Teensy startup to 175ms (from 400ms)
  • Optimized memory for LED and Quantization Tables (moved to FLASH)
  • Fixed updates to envelope AD times while the envelopes are active and in that segment

TELEXi Changes

  • Recompiled reducing Teensy startup to 175ms (from 400ms)

Get them here:

Remember: make sure your Teensy is not connected to Euro-power when updating the firmware! Instructions for firmware updates are in your manual and on the main GitHub page.

@sam & @tehn -

I was able to reduce the startup time for the TELEX so that no additional delay is needed on the Teletype - although we still may need to add a little one on the TT to keep it from racing Ansible and others to the starting line.

Turns out, at some point a 400ms delay was added to the Teensy prior to calling the USB initialization to reduce complaints when people were trying to use components that weren’t ready because the Teensy started up “too fast”.

I modified “pins_teensy.c” on line 586 from 400 to 175. This should capture my case and @sam’s case - which was a little slower. I could go lower - but I didn’t want to push any of the components to unstable places (especially the DAC).

// for background about this startup delay, please see these conversations
// reduced to 175 from 400 for the TXo firmware

I’ll be putting some instructions for this on the GitHub site for the TELEX tomorrow for those that want to compile it themselves. Unfortunately, you have to go in and modify the code in your Arduino directory. It applies to everything you compile for the Teensy. (Shudder.)

Here is the nice forum where I got some help (saving me a lot of time):

Finally, thanks for inspiring further investigation. I’m glad we could keep startup as zippy as possible. :slight_smile: :slight_smile: :slight_smile:


Hey folks, what is the setup for using the onboard ADSR as a VCA?


Not next to mine but if I recall you setup the oscillator ( cv level 10, Osc to a freq greater than 0) then set up a trigger , then set up an envelope.


Thanks…but I guess I’m missing the routing part. Say you have CV 1 operating as an oscillator. And CV 2 as an envelope. What is the mechanism for routing the oscillator audio and having that envelop CV control the level?


Nevermind…stumbled onto the solution. So you enable oscillator on CV 1, then enable envelope on the same CV 1. Then TO.ENV.TRIG 1 1 pings that envelope…it’s as if a VCA is built into that one CV out. (As it says in the manual…duh…but until I experienced the operation, it didn’t make sense.).


Now that I’m wrapping my head around this…I want to build this up as a travel machine someday. :sunglasses: