Continuously calling a function

Let me explain what I want to do and maybe someone can tell me if it’s possible.

I would like two momentary pads. One for up, one for down. If I press and hold down on a pad, I would like it to continuously call a LUA function until I release it.

I tried to do this by setting on value to 1 and off value to 0 and then inside the function do while Value == 1. But that just locks up

Haven’t been doing any lua so far, so rationale below is rather generic, but it may help.

If you are able to store a global value somewhere that you can read and write with both pads, then you could create a counter. In the description below I use besides the GlobalValue a variable called Count, which actually counts the amount of increases or decreases while the pad is pressed, and a variable Number that defines the size of the value steps to take.

When/while a pad is pressed:

  • assign Count=0, Number=1,
  • reach a marker(M1)
  • increase/decrease Global Value with Number,
  • increase Count with Number,
  • kick off the Function you need using GlobalValue as input
  • wait for a Period (result of a function using Count and Number as input)
  • go back to marker M1 if the pad is still pressed

I would make Period a function that can do two things: the period length shortens according to the value of Count (so you could accelerate when pressing long), and/or the Number could be increased (so you skip values and thus reduce number transmissions)

There are two things here:

  1. You need a way to determine long-press of a button in order to get your “begin repeat” and “end repeat” events.
  2. You also need something that will periodically run stuff that you give it.

For 1, I think you should be able to do it with a momentary button: on press it’ll send, say, 1 and on release it’ll revert back to zero. I don’t know for certain whether it works that way though.

For 2, you’ll need to use Lua. Have a look at the Timer. Define timer.tick and start it when you detect 1 for the button, and stop it when you detect 0.

unfortunately, the button (either momentary or toggle) only sends the value and/or executes the associated LUA function once per press. For Momentary, if you define both the on and off value then the LUA function you define for it gets called twice (once on press, once on release). If you only define one of the values, the value (ands LUA code) are only sent once.

Spinning the encoder to cover the range of 0 to 32,767 isn’t viable (both from a cramping hand and from a UI point of view) so I’ve been looking at alternate ways to do this. I didn’t think it was practical to use up to 12 slots to do a calculator key style input, but maybe that is best.

Unless I misunderstand what you’re trying to do, this is perfect.

In your Lua function that you attach to the button you call timer.start when button value is 1 and timer.stop when it is 0. The Timer will periodically invoke timer.onTick, which you need to define to perform the increment (or decrement, for the “down” button) by a fixed amount.

Here’s a sketch (in pseudo-code):

timer.onTick = function ()
  currentValue = read current value from parameterMap
  write currentValue+increment to parameterMap
end

function buttonCallback (buttonValue)
  if buttonValue is 1
    timer.start()
  else
    timer.stop()
end

The function itself must contain the loop, so you only need to call it once. The loop is to run as long as the parametervalue equals 1. Or you use a while condition for the loop, (if such thing exists in lua) , or you create a loop yourself by triggering the iteration if the parametervalue =1, and leaving the loop if parametervalue equals 0

This is not correct. Lua runs in an interpreter which (in simplistic terms) means that someone else updates its view of the world and steps it forward — that someone in this case is Electra’s firmware. At each step, Lua executes your code until it returns. Blocking in a while loop like that means your Lua code never returns, which in turn means the firmware doesn’t get a chance to update it with a new view of the world, which in turn means your code just spins and the device appears frozen, as @oldgearguy already found out.

1 Like

Right, I’ve had success in the past using a check on some other asynchronous event with success since things like touching the surface or MIDI inputs still seem to get processed, but that was a specialized approach.

I was trying to get all the patches in sequence from a synth and I wanted to make sure I fully parsed the patch before getting the next one. Simply calling “request a patch dump” and letting the patch.onResponse() handle it didn’t work since it overran things. I had to request a patch, then spin there until the onResponse() code finished parsing and set an “I’m finished” flag before sending the next patch request out.

In this case, I need to have a separate ‘thing’ continuously send or not send MIDI based on a user action.

@akira, I have some time today to look over your code suggestions and hopefully will be able to use those to good effect.

1 Like

@akira Thanks, good to know!

1 Like

@akira is right but there is one exception. The incoming MIDI messages are processed in async fashion and with the highest priority. That means that even if Electra was spinning in an endless loop (in a Lua function) and therefore stopping any other tasks, incoming messages will be still processed and forwarded. That is why you were able to process the incoming MIDI.

As it was mentioned, the timer is the way to go. Imagine the timer to be kind of a virtual loop that allows you to run/check stuff on regular repetitive basis without blocking other tasks. Of course, the work done inside the timer handler should not take too long…