277 lines
7 KiB
Text
277 lines
7 KiB
Text
# LX Vario S3 by Benedikt Wolf (D-ECHO) based on
|
|
|
|
# A3XX Lower ECAM Canvas
|
|
# Joshua Davidson (it0uchpods)
|
|
|
|
# THANKS TO Colin Geniet (SoundPitchController), original developers of the ilec-sc7 (WooT)
|
|
|
|
# Information based on manual http://www.lx-avionik.de/wp/download/manuals/LXS3ManualGermanVer0100.pdf
|
|
#######################################
|
|
|
|
## REQUIRES:
|
|
## * second altimeter module enabled from <sim><instrumentation>
|
|
## * power supply from systems/electrical/outputs/S3
|
|
## (opt) * vario sound set up in the aircraft's sound file (see S3-sound.txt as an example)
|
|
|
|
#####################
|
|
## Version 05/2020 ##
|
|
#####################
|
|
## Features of this version:
|
|
## * use maketimer, only update visible pages
|
|
## * use props.nas, store in local variables where sensible
|
|
## * store instrument directory in variable
|
|
## * clarity through indentation
|
|
## * use functions for common functionality
|
|
## * clean up listeners
|
|
|
|
var S3_start = nil;
|
|
var S3_main = nil;
|
|
var S3_display = nil;
|
|
|
|
var s3 = props.globals.initNode("/instrumentation/s3");
|
|
|
|
var start_prop = s3.initNode("start", 0.0, "DOUBLE");
|
|
var pushknob_prop = s3.initNode("knob-pushed", 0, "BOOL");
|
|
|
|
var te_rdg = s3.initNode("te-reading-mps", 0.0, "DOUBLE");
|
|
var te_avg = s3.initNode("te-average-mps", 0.0, "DOUBLE");
|
|
var volume = s3.initNode("volume", 0.5, "DOUBLE");
|
|
|
|
var alt = props.globals.initNode("instrumentation/altimeter[1]/indicated-altitude-ft", 0.0, "DOUBLE");
|
|
var volt_prop = props.globals.initNode("/systems/electrical/outputs/S3", 0.0, "DOUBLE");
|
|
|
|
var mc = s3.initNode("mc", 1.5, "DOUBLE");
|
|
|
|
var needle = s3.initNode( "needle-deg", 0.0, "DOUBLE" );
|
|
|
|
var instrument_dir = "Aircraft/Instruments-3d/glider/vario/S3/";
|
|
|
|
var canvas_S3_base = {
|
|
init: func(canvas_group, file) {
|
|
var font_mapper = func(family, weight) {
|
|
return "LiberationFonts/LiberationSans-Bold.ttf";
|
|
};
|
|
|
|
|
|
canvas.parsesvg(canvas_group, file, {'font-mapper': font_mapper});
|
|
|
|
var svg_keys = me.getKeys();
|
|
|
|
foreach(var key; svg_keys) {
|
|
me[key] = canvas_group.getElementById(key);
|
|
}
|
|
|
|
me.page = canvas_group;
|
|
|
|
return me;
|
|
},
|
|
getKeys: func() {
|
|
return [];
|
|
},
|
|
update: func() {
|
|
var start = start_prop.getDoubleValue();
|
|
var volts = volt_prop.getDoubleValue();
|
|
if ( start == 1 and volts > 9 ) {
|
|
S3_start.page.hide();
|
|
S3_main.page.show();
|
|
S3_main.update();
|
|
} else if ( start > 0 and start < 1 and volts > 9 ){
|
|
S3_main.page.hide();
|
|
S3_start.page.show();
|
|
} else {
|
|
S3_main.page.hide();
|
|
S3_start.page.hide();
|
|
}
|
|
},
|
|
};
|
|
|
|
|
|
var canvas_S3_main = {
|
|
new: func(canvas_group, file) {
|
|
var m = { parents: [canvas_S3_main , canvas_S3_base] };
|
|
m.init(canvas_group, file);
|
|
|
|
return m;
|
|
},
|
|
getKeys: func() {
|
|
return ["altitude","average","average.needle","mccready.needle"];
|
|
},
|
|
update: func() {
|
|
|
|
#Altimeter
|
|
me["altitude"].setText( sprintf( "%4d", math.round( alt.getDoubleValue() * FT2M ) ) );
|
|
|
|
|
|
#Average climbrate
|
|
var av = te_avg.getDoubleValue();
|
|
me["average"].setText(sprintf("%2.1f", av));
|
|
if(av<5 and av>-5){
|
|
var av2=av;
|
|
}else if(av<-5){
|
|
var av2=-5;
|
|
}else if(av>5){
|
|
var av2=5;
|
|
}
|
|
me["average.needle"].setRotation(av2*D2R*24);
|
|
|
|
#McCready
|
|
me["mccready.needle"].setRotation( mc.getDoubleValue()*D2R*24 );
|
|
}
|
|
|
|
};
|
|
|
|
|
|
var canvas_S3_start = {
|
|
new: func(canvas_group, file) {
|
|
var m = { parents: [canvas_S3_start , canvas_S3_base] };
|
|
m.init(canvas_group, file);
|
|
|
|
return m;
|
|
},
|
|
getKeys: func() {
|
|
return [];
|
|
},
|
|
update: func() {
|
|
}
|
|
|
|
};
|
|
|
|
var s3_update = maketimer(0.2, func() { canvas_S3_base.update() } );
|
|
s3_update.simulatedTime = 1;
|
|
|
|
var vario_needle_ctrl = func {
|
|
if( start_prop.getDoubleValue() == 1.0 ){
|
|
needle.setDoubleValue( math.clamp( te_rdg.getDoubleValue() * 24, -132, 132 ) ); # max deflection: 132 deg at +- 5.5 m/s
|
|
} else {
|
|
needle.setDoubleValue( 0.0 );
|
|
}
|
|
}
|
|
|
|
var needle_update = maketimer( 0.0, vario_needle_ctrl );
|
|
needle_update.simulatedTime = 1;
|
|
|
|
var ls = setlistener("sim/signals/fdm-initialized", func {
|
|
S3_display = canvas.new({
|
|
"name": "S3",
|
|
"size": [320, 240],
|
|
"view": [320, 240],
|
|
"mipmapping": 1
|
|
});
|
|
S3_display.addPlacement({"node": "S3.display"});
|
|
var groupMain = S3_display.createGroup();
|
|
var groupStart = S3_display.createGroup();
|
|
|
|
|
|
S3_main = canvas_S3_main.new(groupMain, instrument_dir~"S3_main.svg");
|
|
S3_start = canvas_S3_start.new(groupStart, instrument_dir~"S3_start.svg");
|
|
|
|
s3_update.start();
|
|
needle_update.start();
|
|
|
|
removelistener(ls);
|
|
});
|
|
|
|
var i=0;
|
|
|
|
var check_off = func () {
|
|
if( pushknob_prop.getBoolValue() and i<50){
|
|
i=i+1;
|
|
settimer(check_off, 0.1);
|
|
}else if( pushknob_prop.getBoolValue() and i >= 50){
|
|
i=0;
|
|
start_prop.setDoubleValue( 0.0 ); #put proper shutdown routine here later
|
|
}else{
|
|
i=0;
|
|
}
|
|
}
|
|
|
|
var check_electric_off = func () {
|
|
if( volt_prop.getDoubleValue() < 9.0 and start_prop.getDoubleValue() != 0.0 ){
|
|
start_prop.setDoubleValue( 0.0 );
|
|
}
|
|
}
|
|
|
|
|
|
setlistener(pushknob_prop, func {
|
|
if( pushknob_prop.getBoolValue() ) {
|
|
if( volt_prop.getDoubleValue() >= 9.0 and start_prop.getDoubleValue() == 0.0 ){
|
|
interpolate(start_prop, 1, 4 );
|
|
} else {
|
|
check_electric_off();
|
|
}
|
|
check_off();
|
|
}
|
|
});
|
|
|
|
|
|
setlistener(volt_prop, func {
|
|
check_electric_off();
|
|
});
|
|
|
|
|
|
|
|
#The following code is based on the ILEC SC7 e-vario and computes the different values shown by the display and the mechanical needle
|
|
io.include("Aircraft/Generic/soaring-instrumentation-sdk.nas");
|
|
|
|
####################################
|
|
#### INSTRUMENT SETUP ####
|
|
####################################
|
|
|
|
# Vario sound pitch controller by Colin Geniet (for ASK21), thanks!
|
|
#
|
|
# var vario_sound = SoundPitchController.new(
|
|
# input: Object connected to the pitch controller input, e.g. a variometer reading.
|
|
# max_pitch: (optional) Maximum sound frequency factor, the output will be
|
|
# in the range [1/max_pitch, max_pitch], default 2.
|
|
# max_input: Value of input for which max_pitch is reached.
|
|
# on_update: (optional) function to call whenever a new output is available
|
|
|
|
var SoundPitchController = {
|
|
parents: [InstrumentComponent],
|
|
|
|
new: func(input, max_input, max_pitch = 2, on_update = nil) {
|
|
return {
|
|
parents: [me],
|
|
input: input,
|
|
max_pitch: max_pitch,
|
|
max_input: max_input,
|
|
on_update: on_update,
|
|
};
|
|
},
|
|
|
|
update: func {
|
|
var input = math.clamp(me.input.output, -me.max_input, me.max_input);
|
|
me.output = math.pow(me.max_pitch, input / me.max_input);
|
|
|
|
if (me.on_update != nil) me.on_update(me.output);
|
|
},
|
|
};
|
|
|
|
var probe = TotalEnergyProbe.new();
|
|
|
|
var s3_needle = Dampener.new(
|
|
input: probe,
|
|
dampening: 1.5,
|
|
on_update: update_prop("/instrumentation/s3/te-reading-mps"));#1.5 is default dampening value according to POH
|
|
|
|
var averager = Averager.new(
|
|
input: probe,
|
|
buffer_size: 20,
|
|
on_update: update_prop("/instrumentation/s3/te-average-mps")); #20s is default time according to POH
|
|
|
|
var s3_sound = SoundPitchController.new(
|
|
input: s3_needle,
|
|
max_input: 5,
|
|
on_update: update_prop("/instrumentation/s3/sound-pitch"));
|
|
|
|
# Wrap everything together into an instrument
|
|
var fast_instruments = UpdateLoop.new(
|
|
update_period: 0,
|
|
components: [probe, s3_needle, s3_sound],
|
|
enable: 1);
|
|
|
|
var slow_instruments = UpdateLoop.new(
|
|
update_period: 1,
|
|
components: [averager],
|
|
enable: 1);
|
|
|