i do think there’s room for this idea, or at least a variation of the implementation. i do see what you’re suggesting as useful for sure. combined with slew and AT. yes!

1 Like

This is definitely an interesting direction. It makes me think of adding a special RAMP variable that has max, min, wrap (rollover / reverse) settings. Sawtooth and triangle shapes become very easy to implement as well having an interesting parameterized way of controlling them (scripting limit changes). It would be somewhat of a combination of O, WRAP, MOD and ADD.

Access would be get/set depending on variable count. Set behaviour would simply accumulate with the internally held value:
CV 1 R 16 // adds sixteen to R, wraps if reaching limit, passes to CV 1.

Make an arpeggiator by mapping the output to the N table:
CV 1 N R 1 // adds 1 to R (set to low limits), then maps to semitones and outputs.

Put the R command in the METRO if you want standard LFO behaviour, with a simple R 1 command.

This would double-up for other counter-style duties rolling in some MOD functionality. This command would trigger every 8th time (provided R.MAX = 8):
IF EZ R 1 : <command>

Like a lot of the above suggestions, the functionality could be reproduced in other ways, but this might be a more efficient way to approach some of the problems.

6 Likes

Love the creativity on this thread!

I’ve been working (in another thread) on a couple of expanders for the Teletype that connect over the II bus. The first one is an output expander (Telex-O). I’ve put a little extra CPU horsepower and DAC resolution than the job calls for in the hopes that I can go a little beyond the current command set. I’ve also designed in some jumpers that can be used to have more than one expander connected to a single Teletype. To these ends, I’d like to propose a few enhancements to the Teletype as a part of this thread:

  1. Separate the II address spaces for module address and for commands. That is, rather than drawing everything from one address space (see ii.h in the skeleton), I suggest that we have one space for device addresses and individual spaces for each module and their commands. (I also have a fantasy that these could also be imported at run time from the USB drive, but I’m a realist in why this could also be a bit of a disaster and am not advocating for it.)

  2. Enable organic addressing of multiple devices of the same type on the II bus. For this, we add the concept of channel for an II device. Channel is used in two ways. First, it is explicitly set and operates on an undecorated device designation like this:

    II TO.CHANNEL 2
    II TO.CV1 V 5
    II TO.CHANNEL 1
    II TO.CV1 V 1

This method eats a line to change channels, but allows for some fun as the channel # can be dynamically altered. The second way is to explicitly call the channel in the device designation:

II TO2.CV1 V 5
II TO1.CV1 V 1

Much more compact when you don’t want to dynamically vary the device’s channel.

  1. For the expander, I’m planning to add some oscillation capabilities on its four CV outputs. Ideally this for LFOs, but the hardware should also be capable of driving things up into the audio range. The outputs are also bipolar, if one wants to use them that way. :slight_smile: Here is what I am thinking:

To address the bipolar nature of the expander and its high-resolution DACs, MIN and MAX flexibly set a scaling range for the CV output (they could even be inverted):

  • MIN - sets the minimum voltage for the CV’s scaled range (default: 0V; range: -10V to +10V)
  • MAX - sets the minimum voltage for the CV’s scaled range (default: +10V; range: -10V to +10V)

To handle oscillation in the expander, these three settings address the rate of oscillation (and would override each other):

  • FREQ - sets the oscillation frequency of the CV output in HZ (default: 0 Hz - no oscillation; range: 0 Hz - ? kHz)
  • PERIOD - sets the oscillation frequency of the CV output in ms
  • CYCLE - sets the oscillation frequency of the CV output in seconds (enabling really long-ass cycles which make me happy)
  • RESET - starts the oscillation over from the beginning

To control the waveform of the oscillation in the expander:

  • WAVE - sets the waveform for the oscillation (e.g. square, triangle, ramp/saw, sine, pulse(s), random, …)
  • SHAPE - a wave shaper that goes from logarithmic to neutral to exponential

NOTE: The existing SLEW command would still have an effect on the waveform as well if it is oscillating on a PERIOD or CYCLE.

This LFO implementation is primarily expander-specific would not replace what has been proposed by @trickyflemming and @Galapagoose (and the awesome RAMP concept above). I do think, however, that some of the functionality could come back into the Teletype within its hardware imposed limits (0V floor and max frequency) if people were interested.

  1. Bi-Directional II is very interesting to me, as is polling via II. The second expander that I’m thinking about has four CV inputs and four independent knobs. I had been planning the latter (polling) to keep it in tune with the TT’s existing CV read metaphor and to also keep the II bus relatively uncluttered. (I only hope that it is fast enough and doesn’t bog down the execution loop - would still need to do R&D to see.)

On a related note, I would love to be able to share the metronome across the bus and sync external devices to it - thereby saving a trigger output. Not that I’m planning to use it for anything in the expanders (initially).

Thx for letting me chime in!

b

4 Likes

All of these sound great. I’d love to see the teletype blossom while maintaining the elegance of the original. The expander seems so ripe with promise. I can’t wait to see what comes next, while still exploring what currently is.

1 Like

LFO ability would be so incredibly useful. Excited to try that !

So there is nothing particularly magical about the II op. Here is the entire source code for it:

static void op_II() {
	int16_t a = pop();
	int16_t b = pop();
	update_ii(a,b);
}

At the moment, the II op takes 2 numbers and transmits them both over the i2c bus, any 2 16bit numbers you like. (WW.PRESET, etc, are just constants, you can type numbers in instead if you want to save characters!) Essentially the way the op works is tied directly to the i2c implementation.

I propose that we separate the way the op works from the way the protocol works, we should depreciate the II op. Instead we could create an op specific to each device, ES, WW, etc. That way each device can have an op (or series of ops) sympathetic to it’s use.

(Also, I think @tehn has started working on variable length i2c messages.)

The next thing I my todo list is to try and simplify some of the teletype code regarding ops. I’d like to make it much easier for people to write there own ones.

1 Like

this is exactly my intention. there are a couple new modules coming up (not all made my me, note) that will use multi-length i2c messages. these will do exactly what you mention-- break free from the II op and be their own standalone ops.

the II op is good however for very simple parameter transaction-- and i think it makes sense to spell out the entire param name ie WW.RESET for code readability.

i also have bidirectional i2c working, though i haven’t written a test op. just tested via backend code.

3 Likes

502 errors ate my previous reply - good ideas in regards to the expander.

perhaps the channel number itself should be a parameter - this way you can both do a one line command for a specific channel, or use a variable to dynamically select a channel, again with one line.

also a great idea to take advantage of the expander’s own processor and delegate some tasks to it, LFO/oscillators being a good example. envelopes with different shapes as well to compliment SLEW.

+1 on device specific II, and it would be good to have the ability to not have a fixed number of parameters somehow.

Just to second that higher resolution on slew would be fantastic, so that complex envelopes can be generated. As it is, i noticed some harshness in TT when using the SLEW and feeding to an external VCA as envelope. On certain signals i can definitely hear the “steppiness” of it.

(Though i have not tried that with the newest version of TT, and am not sure if the increase in resolution happened with the recent firmware. I remember this was discussed at some point.)

This is something I’ve been thinking about ever since I got the Teletype. My approach (for sine LFOs specifically) has been to fill up all 64 steps of one of the pattern banks with values from a lookup table (which works reasonably well) but it would be great to have a more elegant solution.

agreed! though i haven’t sound-tested it myself (but should!)

hilarious point being, the “expander” will have almost 3 times the processing power (i think?) as the actual TT unit. so yes, by all means make use of the high resolution potentials.

1 Like

how about this idea then: re-implement the TT engine in the expander itself (probably fairly straight forward port? and another thing to consider for TT refactoring) and add the ability to transfer parsed scripts into expanders… this would require the expander having its own storage though so they could continue operating independently even after a power cycle.

1 Like

i don’t think we’ve maxed out the avr32, so that shouldn’t be the motivation.

the idea of self-contained automatons is certainly interesting to me. but we may also be approaching feature saturation. will ponder further.

yeah, i meant more as a standalone automaton that could be edited from a teletype. and yeah, feature creep! but taking even further, it could simply execute one script but then allow for storing a library of scripts which could then be selected from teletype, so you could have modules that would change their function with TT serving as the ‘control tower’. modular that would change ‘modules’ under CV control.

Sorry if this is in the thread somewhere (didn’t see it though I’m sure it’s been talked about), but I wonder if we could put a SCRIPT command on the table to trigger other scripts? Chaining scripts is a great way to get around the command limit for scripts and is something I find myself frequently wanting. (The pattern generally is a bunch of scripts that update variables and patterns that delegate to a shared script that updates CVs and TRs.) A simple guard would have to prevent recursion but I don’t think it’d be too hard.

Curious if anyone else would find this handy?

this exists now! enjoy!

1 Like

That was quick! :wink:

Actually, this is a little hilarious. I have teletype.c open at the moment and sure enough op_SCRIPT is right there. The issue, as it happens, is somewhere in my code. Classic case of looking for a zebra instead of a horse.

Now back to the debugger!

1 Like

I think it would be cool if there was something like Max’s UZI operator, useful for multiply trigger with a unique line.
:wink:

2 Likes

totally agree @kkempes
see earlier in this thread:

:slight_smile:

2 Likes

Also,
I’d like we can play with envelopes on the CV outs.
Maybe you can define parameters like CV.EXP 1-4 and CV.LOG 1-4 next to CV.OFF, CV.SLEW.

Ciao