1
0
Fork 0
mirror of https://github.com/betaflight/betaflight-configurator.git synced 2025-07-25 09:15:49 +03:00
betaflight-configurator/src/js/tabs/adjustments.js
2020-12-16 15:00:09 +01:00

324 lines
12 KiB
JavaScript

'use strict';
TABS.adjustments = {};
TABS.adjustments.initialize = function (callback) {
const self = this;
GUI.active_tab_ref = this;
GUI.active_tab = 'adjustments';
function get_adjustment_ranges() {
MSP.send_message(MSPCodes.MSP_ADJUSTMENT_RANGES, false, false, get_box_ids);
}
function get_box_ids() {
MSP.send_message(MSPCodes.MSP_BOXIDS, false, false, getRcData);
}
function getRcData() {
MSP.send_message(MSPCodes.MSP_RC, false, false, load_html);
}
function load_html() {
$('#content').load("./tabs/adjustments.html", process_html);
}
MSP.send_message(MSPCodes.MSP_BOXNAMES, false, false, get_adjustment_ranges);
function addAdjustment(adjustmentIndex, adjustmentRange, auxChannelCount) {
const template = $('#tab-adjustments-templates .adjustments .adjustment');
const newAdjustment = template.clone();
$(newAdjustment).attr('id', 'adjustment-' + adjustmentIndex);
$(newAdjustment).data('index', adjustmentIndex);
//
// update selected slot
//
if (semver.lt(FC.CONFIG.apiVersion, API_VERSION_1_42)) {
const adjustmentList = $(newAdjustment).find('.adjustmentSlot .slot');
adjustmentList.val(adjustmentRange.slotIndex);
}
//
// populate source channel select box
//
const channelList = $(newAdjustment).find('.channelInfo .channel');
const channelOptionTemplate = $(channelList).find('option');
channelOptionTemplate.remove();
for (let channelIndex = 0; channelIndex < auxChannelCount; channelIndex++) {
const channelOption = channelOptionTemplate.clone();
channelOption.text('AUX ' + (channelIndex + 1));
channelOption.val(channelIndex);
channelList.append(channelOption);
}
channelList.val(adjustmentRange.auxChannelIndex);
//
// update selected function
//
const functionList = $(newAdjustment).find('.functionSelection .function');
// update list of selected functions
functionList.val(adjustmentRange.adjustmentFunction);
//
// populate function channel select box
//
const switchList = $(newAdjustment).find('.functionSwitchChannel .channel');
const switchOptionTemplate = $(switchList).find('option');
switchOptionTemplate.remove();
let switchOption;
for (let switchIndex = 0; switchIndex < auxChannelCount; switchIndex++) {
switchOption = switchOptionTemplate.clone();
switchOption.text('AUX ' + (switchIndex + 1));
switchOption.val(switchIndex);
switchList.append(switchOption);
}
switchList.val(adjustmentRange.auxSwitchChannelIndex);
//
// configure range
//
const channel_range = {
'min': [ 900 ],
'max': [ 2100 ]
};
let rangeValues = [1300, 1700];
if (adjustmentRange.range != undefined) {
rangeValues = [adjustmentRange.range.start, adjustmentRange.range.end];
}
let rangeElement = $(newAdjustment).find('.range');
$(rangeElement).find('.channel-slider').noUiSlider({
start: rangeValues,
behaviour: 'snap-drag',
margin: 50,
step: 25,
connect: true,
range: channel_range,
format: wNumb({
decimals: 0
})
});
$(newAdjustment).find('.channel-slider').Link('lower').to($(newAdjustment).find('.lowerLimitValue'));
$(newAdjustment).find('.channel-slider').Link('upper').to($(newAdjustment).find('.upperLimitValue'));
$(rangeElement).find(".pips-channel-range").noUiSlider_pips({
mode: 'values',
values: [900, 1000, 1200, 1400, 1500, 1600, 1800, 2000, 2100],
density: 4,
stepped: true
});
//
// add the enable/disable behavior
//
const enableElement = $(newAdjustment).find('.enable');
$(enableElement).data('adjustmentElement', newAdjustment);
$(enableElement).change(function() {
const adjustmentElement = $(this).data('adjustmentElement');
if ($(this).prop("checked")) {
$(adjustmentElement).find(':input').prop("disabled", false);
$(adjustmentElement).find('.channel-slider').removeAttr("disabled");
rangeElement = $(adjustmentElement).find('.range .channel-slider');
const range = $(rangeElement).val();
if (range[0] == range[1]) {
const defaultRangeValues = [1300, 1700];
$(rangeElement).val(defaultRangeValues);
}
} else {
$(adjustmentElement).find(':input').prop("disabled", true);
$(adjustmentElement).find('.channel-slider').attr("disabled", "disabled");
}
// keep this element enabled
$(this).prop("disabled", false);
});
const isEnabled = (adjustmentRange?.range?.start !== adjustmentRange?.range?.end);
$(enableElement).prop("checked", isEnabled).change();
return newAdjustment;
}
function process_html() {
self.adjust_template();
let auxChannelCount = FC.RC.active_channels - 4;
const modeTableBodyElement = $('.tab-adjustments .adjustments tbody');
for (let adjustmentIndex = 0; adjustmentIndex < FC.ADJUSTMENT_RANGES.length; adjustmentIndex++) {
const newAdjustment = addAdjustment(adjustmentIndex, FC.ADJUSTMENT_RANGES[adjustmentIndex], auxChannelCount);
modeTableBodyElement.append(newAdjustment);
}
if (semver.gte(FC.CONFIG.apiVersion, API_VERSION_1_42)) {
$('.tab-adjustments .adjustmentSlotsHelp').hide();
$('.tab-adjustments .adjustmentSlotHeader').hide();
$('.tab-adjustments .adjustmentSlot').hide();
}
// translate to user-selected language
i18n.localizePage();
// UI Hooks
$('a.save').click(function () {
// update internal data structures based on current UI elements
const requiredAdjustmentRangeCount = FC.ADJUSTMENT_RANGES.length;
FC.ADJUSTMENT_RANGES = [];
const defaultAdjustmentRange = {
slotIndex: 0,
auxChannelIndex: 0,
range: {
start: 900,
end: 900
},
adjustmentFunction: 0,
auxSwitchChannelIndex: 0
};
$('.tab-adjustments .adjustments .adjustment').each(function () {
const adjustmentElement = $(this);
if ($(adjustmentElement).find('.enable').prop("checked")) {
const rangeValues = $(this).find('.range .channel-slider').val();
let slotIndex = 0;
if (semver.lt(FC.CONFIG.apiVersion, API_VERSION_1_42)) {
slotIndex = parseInt($(this).find('.adjustmentSlot .slot').val());
}
const adjustmentRange = {
slotIndex: slotIndex,
auxChannelIndex: parseInt($(this).find('.channelInfo .channel').val()),
range: {
start: rangeValues[0],
end: rangeValues[1]
},
adjustmentFunction: parseInt($(this).find('.functionSelection .function').val()),
auxSwitchChannelIndex: parseInt($(this).find('.functionSwitchChannel .channel').val())
};
FC.ADJUSTMENT_RANGES.push(adjustmentRange);
} else {
FC.ADJUSTMENT_RANGES.push(defaultAdjustmentRange);
}
});
for (let adjustmentRangeIndex = FC.ADJUSTMENT_RANGES.length; adjustmentRangeIndex < requiredAdjustmentRangeCount; adjustmentRangeIndex++) {
FC.ADJUSTMENT_RANGES.push(defaultAdjustmentRange);
}
//
// send data to FC
//
mspHelper.sendAdjustmentRanges(save_to_eeprom);
function save_to_eeprom() {
MSP.send_message(MSPCodes.MSP_EEPROM_WRITE, false, false, function () {
GUI.log(i18n.getMessage('adjustmentsEepromSaved'));
});
}
});
function update_marker(auxChannelIndex, channelPosition) {
if (channelPosition < 900) {
channelPosition = 900;
} else if (channelPosition > 2100) {
channelPosition = 2100;
}
const percentage = (channelPosition - 900) / (2100-900) * 100;
$('.adjustments .adjustment').each( function () {
const auxChannelCandidateIndex = $(this).find('.channel').val();
if (auxChannelCandidateIndex != auxChannelIndex) {
return;
}
$(this).find('.range .marker').css('left', percentage + '%');
});
}
// data pulling functions used inside interval timer
function get_rc_data() {
MSP.send_message(MSPCodes.MSP_RC, false, false, update_ui);
}
function update_ui() {
auxChannelCount = FC.RC.active_channels - 4;
for (let auxChannelIndex = 0; auxChannelIndex < auxChannelCount; auxChannelIndex++) {
update_marker(auxChannelIndex, FC.RC.channels[auxChannelIndex + 4]);
}
}
// update ui instantly on first load
update_ui();
// enable data pulling
GUI.interval_add('aux_data_pull', get_rc_data, 50);
// status data pulled via separate timer with static speed
GUI.interval_add('status_pull', function () {
MSP.send_message(MSPCodes.MSP_STATUS);
}, 250, true);
GUI.content_ready(callback);
}
};
TABS.adjustments.cleanup = function (callback) {
if (callback) callback();
};
TABS.adjustments.adjust_template = function () {
const selectFunction = $('#functionSelectionSelect');
let elementsNumber;
if (semver.gte(FC.CONFIG.apiVersion, API_VERSION_1_41)) {
elementsNumber = 31; // OSD Profile Select & LED Profile Select
} else if (semver.gte(FC.CONFIG.apiVersion, API_VERSION_1_40)) {
elementsNumber = 29; // PID Audio
} else if (semver.gte(FC.CONFIG.apiVersion, API_VERSION_1_39)) {
elementsNumber = 26; // PID Audio
} else if (semver.gte(FC.CONFIG.apiVersion, API_VERSION_1_37)) {
elementsNumber = 25; // Horizon Strength
} else {
elementsNumber = 24; // Setpoint transition
}
for (let i = 0; i < elementsNumber; i++) {
selectFunction.append(new Option(i18n.getMessage('adjustmentsFunction' + i), i));
}
// For 1.40, the D Setpoint has been replaced, so we replace it with the correct values
if (semver.gte(FC.CONFIG.apiVersion, API_VERSION_1_40)) {
const element22 = selectFunction.find("option[value='22']");
const element23 = selectFunction.find("option[value='23']");
// Change the "text"
element22.text(i18n.getMessage('adjustmentsFunction22_2'));
element23.text(i18n.getMessage('adjustmentsFunction23_2'));
// Reorder, we insert it with the other FF elements to be coherent...
element22.insertAfter(selectFunction.find("option[value='25']"));
element23.insertAfter(selectFunction.find("option[value='28']"));
}
};