MobiFlight / MobiFlight-Connector

MobiFlight is an open source project that allows you to create your own home cockpit for your favorite flight simulator in a flexible, affordable and extremely user-friendly way.
https://mobiflight.com
MIT License
236 stars 105 forks source link

Feature request: button repeat on long press #308

Closed MobiFlight-Admin closed 1 year ago

MobiFlight-Admin commented 3 years ago

Use case: Many avionics like the G1000 have repeating button events for long press. Like, selecting the vertical speed or airspeed hold value (there are two buttons instead of a rotary wheel). The G1000 map joystick lets you pan the map when you deflect and hold the stick. An engine starter could invoke automatic start once you press and hold a button for a given time. Generally useful for cockpits with simple push buttons, for things that you do not want to do accidentally.

Design

New tabs in InputConfigWizard: Long Press | Long Release

[Issue created by tigert: 2021-02-13] [Last updated on bitbucket: 2021-06-08]

[Comment created by tigert: 2021-06-08] Been thinking about this a bit recently, and wanted to share some thoughts:

Basically we are talking about values that, when triggered, do not immediately change, but rather are passed to a “pipe” that manipulates the value over time in a given fashion, based on the input value.

Simulator input --> [ filter: start value, end value, time, function ] --> Output

A repeat “filter” would have a timer and a function that turns the value on and off based on some parameters (interval, on-time, off-time). You could create a key repeat event with this to your GPS or autopilot button (think G1000 “nose up/down” buttons) or a blinking warning light.

Then you could have animate filter that would use a function to make the change happen over given amount of time. If it is a boolean, it just waits before doing a change. If it is a value change, it would gradually change over the given time. A good example of these is documented here for example: https://developer.roblox.com/en-us/api-reference/enum/EasingStyle. This would be pretty useful for analog gauges

For booleans, you don’t have any intermediate values, so maybe a delay would be the logical equivalent.

And I guess using the animation filter in a repeat would also make sense (more natural looking flashing lights that simulate an incandescent light bulb instead of a led).

I found this kind of library, though I am not sure if I can judge its usefulness, but it seems to have a test app on the demo repository: https://github.com/mobius3/tweeny and https://github.com/mobius3/tweeny-demos for an example demo program.

Additionally, the above library appears to support creating loops, so maybe we could create the whole repeat functionality in it?

[Comment created by tigert: 2021-03-09] I wonder what would be a use case for keeping repeating buttons in ON position apart from making such a case accidentally, and how big of a problem that would be in practice?

I mean one could for example do beacon and strobe lights with actual leds as a crazy example, using the repeat events of the light switch if those existed - or make a landing gear warning light logic based on throttle position, flap switch and landing gear position. But those are kind of a special case and I don’t think you would get very many of them at once?

On the other hand, having a generic repeating programmable on/off timer might also be useful, for things like blinking warning lights.

[Comment created by DocMoebiuz: 2021-03-02] Interesting. I first thought of adding the long press / release as a new button event, so that it is actually tracked on the arduino side rather than on the mobiflight connector side (pure software).
I am not really keen on making it configurable on the arduino side because this basically requires a new button type and the upgrade logic for old button types.

Adding long press and long release is really a simple addition to the current firmware. Repeat however is more complicated because I am not sure how well it works if we have several switches in ON position and they all fire repeatedly.

So yeah, it looks tempting to realize it in Software only.

[Comment created by tigert: 2021-02-14] … ”for things you don’t want to do accidentally, or do want to adjust the value for a larger amount, and there is no rotary encoder.”

elral commented 2 years ago

Maybe we should have another thought about implementing this in the firmware. I am using my own button routine for my G1000, where I need the repeat function for the pan knob, with success for a while. I implemented this before the RPN solution was available. This repeat function is part of a set of key functions I used before. Available functions are key press, key release, key repeat, key short press, key long press and key long press repeat. But not all can be used the same time, they must be grouped into let's say key modes (see below).

However, if this or something similiar should be implemented into the firmware, a new button device has to be defined (due to backwards compatibility). This new device must have the possibility to define a key mode and at least two parameters (time for repeat start and repeat next). This would mean also modifications an the UI side. Also required is a "stable" time base (function must be called every 10ms), but with the changes implemented in the last weeks I do not see a big problem on this topic. The device with the biggest prcessing time is the LCD which takes ~12ms (20x4 characters). That means every time the LCD gets written the processing of the buttons is delayed by 2ms, which will not be recognized by the user (assuming a write to 7Segment will not happen at the exactly same time as to the LCD). The other effect would be, that 13 Bytes instead of 4 Bytes for the button class is required in the new implemented deviceBuffer. A rough calcution shows that even with this increased memory consumption this fits into the deviceBuffer. On the config side, which is stored in the EEPROM, this would require 6 more Byte per Button (mode, start time, repeat time plus delimiter). With the new changes only names are stored in the "configBuffer" (now named nameBuffer), so increasing the area in the EEPROM has no effect. The biggest topic I see for implementing this in the firmware, major changes would be required to use this also for the input shifters. So I am still unsure where the best place would be for implementing, in the firmware (where I am tending to) or the Connector.

At least, these functions are based on threads from a german forum from a long time ago. I just transferred it to a class with minor adaptions.

As mentioned above, following the modes which are possible and which can be combined: image

neilenns commented 2 years ago

major changes would be required to use this also for the input shifters

I would honestly just say input shifters only support basic buttons for input. From what I've seen it's only ever a handful of buttons on a given panel that need something beyond basic onpress/onrelease, so those buttons can be wired directly to the Arduino.

DocMoebiuz commented 2 years ago

Ok my thoughts on this: on the one hand it would be cool to have the event come from the arduino firmware. we can extend the IDs for the button events easily. What i am a bit afraid of is that timings like after how many ms is it a long press, after how many ms shall we trigger on repeat and how quickly shall it repeat, etc - the configuration might be even plane specific than button specific.

With these thoughts in mind I believe a software based version might be more flexible and can become plane config specific and it would be easier to extend if new features or modification options are asked for.

If we track the button state on the MF Connector side then we can also easily use them in preconditions.

elral commented 2 years ago

the configuration might be even plane specific than button specific.

This is a very goog point which absolutely votes for implementing it on the connector side. Hadn't this in mind.