Teletype PN.POP behavior (and a math OP idea)

I have been using PN.POP (and PN.RM, PN.PUSH etc) quite a bit for the past few days and I don’t think the behavior agrees with the documentation:

PN.POP x

return and remove the value from the end of pattern x (like a stack), destructive to loop length

Emphasis added. What I’m actually seeing is that e.g. PN.POP 1 returns the value (correct), shortens the loop length by one (correct), and leaves the value in place (at odds with the above docs). PN.RM x works correctly (and turns out to be better for this scene), as do the associated PN.PUSH and PN.INS.

I’m running what is likely a unique firmware version of very recent vintage (from the Teletype timing fix thread), so it’s best to confirm this behavior elsewhere–or perhaps adjust the docs if this is considered correct (which I hope it isn’t :slight_smile:)


I also ran into a situation where a square function would be quite helpful: scaling envelope decay times from a series of 16 values (grid ops block of buttons). Maybe others would find it useful too.

My overall commentary on Teletype at this point is that it’s unbelievable what you can do with one scene, one TXo, and a Grid 64. :heart_eyes:

3 Likes

Not going to lie, the Teletype has been one of the most inspiring Eurorack purchases to date

1 Like

As long as accessing the loop doesn’t return the value and shortens it each time, it is technically behaving correctly since it is not destructive to the value, but the loop length itself. Is the data you get back last in, first out?

I can see changing the loop length and setting the now inaccessible value to zero, but would understand if that doesn’t happen.

Interestingly P.RM at any position inside the loop will change the cell after the new end of the loop, e.g. starting with

0
1
2
3
4
5
6
7

with a loop length of 4, P.RM 2 will give you

0
1
3
4
4
5
6
7

with a loop length of 3. This is because P.RM “removes” the specified cell by copying all values after that until the end of the loop to the previous cell, and it seems there’s perhaps an off-by-one error in the loop doing the copy, though some value has to be chosen for the missing cell and this seems like a reasonable one - the other alternative would be to keep the value currently in that cell, in which case I reckon P.RM - P.L 1 and P.POP would be equivalent. P.POP doesn’t copy anything, just shortens the loop.

I am hesitant to (intentionally :p) change any behavior of existing ops in fear that this could break someone’s scene. Possibly new ops could change the entire pattern regardless of the pattern length, if I’m understanding the desired behavior correctly?

1 Like

According to the docs it’s supposed to remove the value, which is the behavior of any other stack I’m aware of.

It becomes a problem when you pop everything off and still have a stale semi-random value in position 0. This scene has two 64-step stack-based sequencers running on patterns 1 and 2. One of the grid controls originally did a PN.POP to remove the last entered value (I found that I liked a PN.RM x 0 better), so I discovered the behavior when I attempted to zero out a sequence and had some random stuck note blaring at me.

Similarly, PN.RM’s docs say:

PN.RM x y
delete index y of pattern x , shift later values up, destructive to loop length

Note the plural “values”. The current behavior (which seems to only operate within the currently active loop length) is like having a RPN calculator with a random number source in the T register: Rolldown operations are liable to inject unexpected values into the stack.

The docs don’t really say that it would be removed from memory, saying only that it is destructive to loop length. And if you replaced it with zero, that’s still a value right?

Technically the data structure is the pattern which is length 64 so it’s not exactly like for like?

I believe that’s exactly what this says (PN.RM):

delete index y of pattern x

… and this bit from PN.POP has a rather precise meaning to just about any programmer:

return and remove the value from the end of pattern x (like a stack)

Since we don’t have the concept of a null value here, the reasonable and expected (by most people, IMO) replacement for a “removed” value is zero (aka logical false, all balls, etc).