TELETYPE: Multiple metronomes?

In addition to using the M script, is it possible to use a delayed recursive function to implement multiple metronomes at different tempos? eg:

TR.P 1

I am not having any luck - it seems to repeat once and then stop.

1 Like

maybe it’s because you start the recursion before it can output a trigger? I would try to swap the lines. Also I am not sure if endless loops are possible?

The same thing happens whichever way the lines are ordered, unfortunately. I think there might be some sort of check happening somewhere wrt recursion that is shutting it down?

Yes, I suppose it’s more that - the order should not matter since the DEL 300. I was still in sleepy and overlooked that…:sleeping:

You could try it with a stackable/multed cable feedback though:

DEL 300: TR.P 1

Afaik you get a max recursion depth of 8 in v.2.0. Which version of the firmware are you using.
You might want to look into the TELEX-O expansion btw. That would give you multiple metronomes.

teletype 2.0

yup super keen for TELEXo. I’ve put my name down with bpcmusic for the next batch.

Hmmmm, that should work. Bit of a head scratcher… but I think I know what’s going on…

Bonus points if anyone else can figure it out:

This is the code the runs the delays:

    for (int16_t i = 0; i < DELAY_SIZE; i++) {
        if (ss->delay.time[i]) {
            ss->delay.time[i] -= time;
            if (ss->delay.time[i] <= 0) {
                run_command(ss, &ss->delay.commands[i]);
                ss->delay.time[i] = 0;
                if (ss->delay.count == 0) tele_has_delays(false);

and this is the code that adds a delay:

static void mod_DEL_func(scene_state_t *ss, exec_state_t *NOTUSED(es),
                         command_state_t *cs,
                         const tele_command_t *post_command) {
    int16_t i = 0;
    int16_t a = cs_pop(cs);

    if (a < 1) a = 1;

    while (ss->delay.time[i] != 0 && i != DELAY_SIZE) i++;

    if (i < DELAY_SIZE) {
        tele_has_delays(ss->delay.count > 0);
        ss->delay.time[i] = a;

        copy_command(&ss->delay.commands[i], post_command);

is this C? C++?

I don’t really understand how time / delay size / i are all working together here, but is it something to do with how tele_has_delays is set to false after the delay.commands are run?

1 Like

It’s C.

If ss->delay.time[i] - time == 0, then the while scan in mode_DEL_func may identify the current delay slot as the first empty one. Setting ss->delay.time[i] to 0 after the delayed commands are run will erase the newly scheduled delay time.

… I think :slight_smile:

edit: easy fix, such as:

if (ss->delay.time[i] <= 0) {
    ss->delay.time[i] = 1;
    run_command(ss, &ss->delay.commands[i]);
1 Like

Damn, It’s hard for me to read this code just because of the brackets at the end of the lines :slight_smile:.

1 Like

The code is well-indented, so you can practically ignore them when reading it.

Miss one while writing the code, however, and you’ll have a problem at compile time.

1 Like

Well, after about 15-20 years writing code with brackets on a new line my brain expects them where they’re not in that case, and parsing this code is genuinely harder…

I’m not saying it’s wrong (well, a little bit :wink:), more that I’m not optimized to read it efficiently.

I will probably want to change a few things in the code at some point so I’ll have to get used to it I guess :slight_smile:.

1 Like

I actually gave up trying to think what the exact mechanism was after I noticed that the delay command array was being mutated while it was being iterated through. I’ve seen that bug before too many times.

Interesting point: you can make the original code work by adding a dummy DEL command in…


And now we have temporal recursion.

Anyway, as to the solution, I would probably be more in favour of a 2 step process, first extract the now commands into a temporary array, then execute them. Even better would be to create functions that do such things and place them in state.c, then the higher level code doesn’t need to worry about fiddling with arrays.

I’ve made an issue on GitHub. I haven’t got time to fix it yet (school holidays haven’t ended here in the UK, so things are still quite hectic). Hopefully I’ll get to it in a few weeks. (Thanks to @capogreco for reporting it.)

The code has been auto-formatted with clang-format, there is a thread somewhere on here where we discussed the options we would use.

It’s worth it for the consistency, especially with code from multiple contributors (you should have seen it beforehand). But you do end up in the situation where nobody is entirely happy with it (except me, as I choose most of the options, but then I did most of the work…).


Having the exact opposite issue here. After some years of mainly Java and JS, reading C-Sharp and PHP conventions hurts a bit. Aren’t we condemned creatures of habit :smile:

I try to avoid letting perfect become the enemy of good, but I agree with you about preference. But a sound, low-cost 1-line patch with a magic number (or an inverse one!) and no perceivable concurrency side-effects looks attractive next to refactoring.

Yes, but one of the delay slots will now be chewed up with a delay that doesn’t run, at least as far as delay count is concerned. The counter will keep ticking up with each iteration, so whatever it gets used for may have problems.

Plus, where are those bonus points?!?!

Yeah, it’s always a hard call. From my point of view, it’s just continuing a processing of encapsulating more and more low level bit fiddling with higher level functions. I spent ages doing that for other parts of the Teletype code base, so doing it here feels like second nature to me.

I’m not suggesting anyway make serious use of it. More that it was an interesting experimental proof of the bug we’ve seen.

Here you go: :100:

(I spent for more time than is strictly necessary looking for that emoji)

1 Like

I performed the workaround patch this morning, and it solves the problem. I pasted the patch on the issue tracker as a temporary solution if anyone else would like to update their own codebase in the meantime.

1 Like

Interestingly, this patch allows you to tap in a sequence with the F1 key.


I’ve merged the changes that @sliderule made to fix this, so the bits will make it into the next release (whenever that is):

It’s actually a pretty cool thing to play about with.

This video is Andrew Sorenson talking about temporal recursion (which is what this type of code is).