Accurate control of button repeat rate: Difference between revisions

From FlightGear wiki
Jump to navigation Jump to search
mNo edit summary
Line 35: Line 35:
var myFunction = timedControl.new();
var myFunction = timedControl.new();
</syntaxhighlight>
</syntaxhighlight>
While creating myFunction, it sets ''last_busy'' to 0 (line 2) and ''time_dur'' to 1.0 (line 4).


and set the repeat rate to 0.25 seconds with
and set the repeat rate to 0.25 seconds with
Line 45: Line 46:


''myFunction.timeout_dur = 0.25''. ''myFunction'' points to the function in memory, ''.timout_dur'' then points to where ''timeout_dur'' exists in memory and changes its value to 0.25. Line 4 of the code set it to 1.0, just so it has ''a'' value.
''myFunction.timeout_dur = 0.25''. ''myFunction'' points to the function in memory, ''.timout_dur'' then points to where ''timeout_dur'' exists in memory and changes its value to 0.25. Line 4 of the code set it to 1.0, just so it has ''a'' value.
Now we need something for the joystick button to call. Here we are using ''do'', but you could just as easily use ''perform'', or ''activate'', or anything else.
<syntaxhighlight lang="php" line>
myFunction.do =  func(step) me._call(me._do, step);
</syntaxhighlight>
Here, ''step'' is 1 for button pressed, and 0 for mod-up, pretty much standard for repeatable button code.
When ''myFunction.do'' is called it executes ''me._call(me._do, step)''. It calls lines 10 onwards of ''timedControl'', passing ''me._do'' and ''step'' as parameters. The ''me'' is the way ''timedControl'' references itself, so if you have multiple buttons using the method, using ''me'' makes sure that you are always using the right ''timeout_dur'' or ''last_busy'', etc.
Now let's look at lines 10 onwards of ''timedControl''.
Line 10 receives the call ''_call'' with the parameters ''me._do'' and ''step'', which it renames to ''fn'' and ''arg.''
Line 11: If the value of ''arg'', and hence the value of ''step'' is 0, it means mod-up (the button was released.) It sets the value of ''last_busy'' to 0 and returns. ''It does nothing further''.
Line 12: Ignore for the moment.
Line 13: Ignore for the moment.
Line 14: Sets the variable ''time'' to ''system''. This is the current date and time, accurate to fractions of a millisecond.
Line 15: Remember, ''last_busy';' was initialised to 0. This line checks if the sum of ''timeout_dur'' and ''last_busy'' is more than the current time. It isn't, since ''last_busy'' is 0.
Line 16: ''last_busy'' is set to current time.
Line 18: The function returns, calling ''fn'' with parameter ''arg''.
Now ''fn'' is ''me._do''. ''me'' is of course ''myFunction''. So it is going to call a function by the name of ''myFunction._do''. This is the actual code that must be executed when the joystick button is pressed. So we are going to need
<syntaxhighlight lang="php" line>
myFunction._do =  func(step) {
  ....
}
</syntaxhighlight>





Revision as of 07:11, 22 July 2013

WIP.png Work in progress
This article or section will be worked on in the upcoming hours or days.
See history for the latest developments.

Background

Sometimes you might want to have control over the speed that a repeatable button works - maybe you want it to repeat exactly every 1.325 seconds, or you just want to slow it down. At the end of this article you will be shown how to use a button to set the frequency of a radio. This is certainly a time when the default (system) repeat rate of a button is too fast.

How it is done

The secret is in having a method of preventing a button from repeating until our chosen time has elapsed. It is possible, but messy, especially if you are doing this with a number of buttons, to do it inside the code for each button. It is much better to create a new type of button code. For this we need a class, and then create instances of this class for each controlled button. This, incidentally, is OOP, or Object Oriented Programming.

Here is thew code to create the new class. It is called timedControl. I have added (unnecessary) open lines between each member of the class to make understanding easier.

var timedControl = {
      last_busy: 0,

      timeout_dur: 1.0,

      new: func() {
          return { parents:[me] };
      },

      _call: func(fn, arg) {
        if (!arg) { me.last_busy = 0; return; }
        if (me.timeout_dur != nil) {
          if ((me.timeout_dur == -1) and me.last_busy != 0) return;
          var time = systime();
          if (time < me.timeout_dur + me.last_busy) return;
          me.last_busy = time;
        }
        return call(fn, [arg], me);
      }
};

Let's assume that we have a function, myFunction, which must only repeat every 0.25 seconds. We create it with

var myFunction = timedControl.new();

While creating myFunction, it sets last_busy to 0 (line 2) and time_dur to 1.0 (line 4).

and set the repeat rate to 0.25 seconds with

myFunction.timeout_dur = 0.25;

How it works

var myFunction = timedControl.new() calls lines 6, 7, 8 of timedControl. This creates a new instance of timedControl named myFunction and returns a pointer to it. Now, whenever you use myControl it will point to where it exists in memory.

myFunction.timeout_dur = 0.25. myFunction points to the function in memory, .timout_dur then points to where timeout_dur exists in memory and changes its value to 0.25. Line 4 of the code set it to 1.0, just so it has a value.

Now we need something for the joystick button to call. Here we are using do, but you could just as easily use perform, or activate, or anything else.

myFunction.do =  func(step) me._call(me._do, step);

Here, step is 1 for button pressed, and 0 for mod-up, pretty much standard for repeatable button code.

When myFunction.do is called it executes me._call(me._do, step). It calls lines 10 onwards of timedControl, passing me._do and step as parameters. The me is the way timedControl references itself, so if you have multiple buttons using the method, using me makes sure that you are always using the right timeout_dur or last_busy, etc.

Now let's look at lines 10 onwards of timedControl. Line 10 receives the call _call with the parameters me._do and step, which it renames to fn and arg. Line 11: If the value of arg, and hence the value of step is 0, it means mod-up (the button was released.) It sets the value of last_busy to 0 and returns. It does nothing further. Line 12: Ignore for the moment. Line 13: Ignore for the moment. Line 14: Sets the variable time to system. This is the current date and time, accurate to fractions of a millisecond. Line 15: Remember, last_busy';' was initialised to 0. This line checks if the sum of timeout_dur and last_busy is more than the current time. It isn't, since last_busy is 0. Line 16: last_busy is set to current time. Line 18: The function returns, calling fn with parameter arg.

Now fn is me._do. me is of course myFunction. So it is going to call a function by the name of myFunction._do. This is the actual code that must be executed when the joystick button is pressed. So we are going to need

myFunction._do =  func(step) {
  ....
}