MSFS2020 Short, Long and Double Press Button Configuration - MobiFlight/MobiFlight-Connector GitHub Wiki

[!NOTE]
MobiFlight version 10 contains built-in support for long press, and repeating events when holding a button down.

Update: Double press has been added to this tutorial

In addition to the Short and Long press configurations, a double (quick short) press has been added. With this RPN configuration one button can be used to control three functions. Because the programming is quite different for this case, we will present it as a separate section at the bottom of this document.

How to do a Short and Long Press Button Configuration

This RPN trick is also included in the RPN Tips and Tricks document. It has been revised to present the simpler form of this setup first and the more complex form, which utilizes an output config, second. A very similar technique (simpler form) has been found already being used in the simulator RPN code. Some airplanes have controls with two different functions for a short versus a long press of a button. At the time of this writing, Mobiflight 9.2.0 does not have this function, although it is planned for a future release. Meanwhile, here is a way to hack this functionality. It is not pretty, but it works. Please note that this code is RPN and is executed on the simulator side, so you can read L:, E: and A: variables, and/or make any calls to H: or K: events, as may be required.

Simple Technique - One Input Config

The simple form can be used whenever you wish to execute two different events just one time. One will execute if you do a short press, the other will execute if you do a long press. For this example we will setup the short press to be a button press shorter than 0.25 seconds. The long press will be 0.25 seconds or longer. To keep things simple, the code structure is presented with a clear marker for where you should put your event code.

We will define code for both the On Press and the On Release events of a button input config. Begin by creating a new input config in MF Connector. Any name can be used, for this example let's name it "Short Long Press". The simple form of this technique uses only this input config.

For the button ON PRESS event:

(E:SIMULATION TIME,second) 0.25 + (>L:myTshort)

This short code sets a timer when the button is pressed). We read the current simulation time, add 0.25 seconds to it and store it in another user Lvar: myTshort. The 0.25 seconds is the minimum amount of time the button must remain pressed, in order to trigger the long press event. It is added to the current time to store the time limit for the short press. You can adjust this to your own preference, but 0.25 seems to work fairly well.

For the button ON RELEASE event:

(E:SIMULATION TIME,second) (L:myTshort) < if{ 
   (### Here goes your short press event ###) }
els{ 
   (### Here goes your long press event ###) }
0 (>L:myTshort)

This code is executed when the button is released, indicating the end of the short or long press event. We first check the time elapsed to see if it is less than the time limit stored in "L:myTshort". The short press code is executed only if the button has been pressed for less than 0.25 seconds. Since myTshort has the time limit of the short press, if at the time the button is release, the time is less than the limit, it was a short press. So, the code executes the short press command.

If the time elapsed is longer than the time limit in myTshort, then it was a long press and the "els" clause is executed instead. Any event can be called in this way: read any variable, set Lvars, call H: or K: events, etc.

Since this ON RELEASE event is the end of the short or long press event, we reset all the variables used back to 0 and the code is ready for the next button press.

More Complex Setup for Event Repetition - One Input and One Output config

This section expands the simpler form to be able to call an event repeatedly, as long as the button is held pressed. To achieve this, we will need to use an output configuration in addition to the input configuration used before.

Input Config

The On Press event is virtually identical to the above example, except we will include one additional control variable to flag to the output config that the event has started, so that proper actions are taken in the output config. We also introduce another time variable Lvar used to control the repetition time of the event in the output config.

For the On Press:

1 (>L:myBtn) (E:SIMULATION TIME,second) 0.25 + d (>L:myTshort) (>L:myTlong)

The Lvar to indicate that the button is pressed is set to 1. The short press time limit is set in the same manner as before and we initialize one additional Lvar to keep track of the repetition times during the long press.

For the On Release event:

(E:SIMULATION TIME,second) (L:myTshort) < if{ 
   (### Here goes your short press event ###) } 
0 (>L:myBtn) 0 (>L:myTshort) 0 (>L:myTlong)

Note that in comparison to the first example, the On Release is a bit simpler, because all of the long press actions will happen in the output config. Since this ON RELEASE event is the end of the short or long press event, we reset all the variables used back to 0 and the code is ready for the next button press.

Output Config

The long press is handled in an output config because we need to repeatedly check the time beyond the 0.25 second limit, which cannot be done from an input config. During the entire time of the long press myBtn will have a value of 1. Create an output config and name it "Long Press". We will put some code in the Variable field.

(L:myBtn) (E:SIMULATION TIME,second) (L:myTlong) > and if{ 
   (L:myTlong) 0.5 + (>L:myTlong) 
   (### Here goes your repeating long press event ###) } 

The first part of this code checks that myBtn is 1 (button is pressed) and the current time is greater than myTlong. Remember myTlong contains the time limit of the long press, so any time greater means the button has been held for more than the time limit for the long press. So we have a long press. If true, then we execute the long press code. If false, the button is not pressed, so we do nothing and just skip to the end.

The second part of this code is the actual long press event. First the myTlong is increased by 0.5 seconds and stored in myTlong. This is the time limit for the next repetition long press event. In this example we use 0.5 seconds as the repetition time. You can adjust it to whatever suits your application. Using values lower than 0.2 seconds (5 repetitions per second) is not recommended, so that the repetition time is comfortably larger than the simulator cycle time. The long press event is repeated for as long as the button is held down. Any event can be executed: reading or setting Lvars, calling H: or K: events.

Long and short presses could be used also to simulate the push and pull functions of certain encoders like in the A320 airplane. The encoder button could be used to select COM or NAV with short press and Mhz and Khz with a long press. On a simple button, short press could be used to select from a menu, and the long press to return. The possibilities are wide open.

Short, Long and Double Press

Still a third type of press is possible with the double press: i.e. two quick presses of a button. Here we will cover how to add this function with RPN. It requires one input (On Press and On Release) configuration, and one output configuration.

Input Configuration

Create a new input configuration and in the input tab select the button you wish to configure.

ON PRESS

Select MSFS2020 Custom Input and enter the following:

1 (>L:myBtn)
(L:myClick) 0 == if{ 
(E:SIMULATION TIME, second) 0.4 + (>L:myTshort) 
1 (>L:myClick) } els{ 2 (>L:myClick) }

Notes on the On Press code:

  1. The myBtn Lvar is set to 1 to indicate the button is pressed. This will be used in the output config.
  2. If myClick is 0, meaning we are at the start of the process, the timer myTshort is set to 0.4 seconds ahead from now. This time window was increased from the 0.25 seconds used in the previous case for short and long presses. This works well, but it can be adjusted to your liking.
  3. myClick is then set to 1 to indicate the first press is complete.
  4. If myClick was anything other than 0 at the beginning (actually, it can only be 1 if not 0), we set it to 2, meaning this is the second press within the 0.4 second timer window.

ON RELEASE

The On Release code will process the Long and the Double Press events.

0 (>L:myBtn)
(E:SIMULATION TIME, second) (L:myTshort) > (L:myClick) 1 == and if{ 
   (### Here goes your Long Press event code ###) 
   0 s0 (>L:myTshort) l0 (>L:myClick) }
(L:myClick) 2 == if{ 
   (### Here goes your Double Press event code ###)
   0 s0 (>L:myTshort) l0 (>L:myClick) }

Notes on the On Release code:

  1. myBtn is set to 0, indicating the button is no longer pressed.
  2. If the 0.4 seconds timer expired and myClick is equal to 1, meaning the first press was pressed long, the Long Press event is executed.
  3. On the other hand, if myClick is equal to 2, the second press was made within the 0.4 seconds timer, so no timer needs to be checked and the Double Press event is executed.
  4. In both cases the timer and click variables are reset back to 0 to restart the process.

Output Configuration

Create a new output configuration to run this code with every simulation cycle. The output configuration is necessary because, in the case of the single press, we have to wait for the 0.4 second timer to expire to determine that there was only one press within the time window. This check cannot be done from an input config that executes only once.

(E:SIMULATION TIME,second) (L:myTshort) > (L:myClick) 1 ==  (L:myBtn) ! and and if{ 
(### Here goes your Short Press event code ###)
0 s0 (>L:myTshort) l0 (>L:myClick) } }

Notes on the Output config code:

  1. If the 0.4 second timer has expired AND myClick is equal to 1 (meaning only 1 press) AND myBtn is not pressed (meaning the button is released and it is not a long press), then the Short Press code is executed.
  2. Then all variables are reset to restart the process.