Merge branch 'master' into advanced-tuning-tab

pull/108/head
Pawel Spychalski (DzikuVx) 8 years ago
commit 01569e7df8

@ -1927,5 +1927,8 @@
},
"tabAdvancedTuningTitle": {
"message": "Advanced tuning"
},
"presetApplyHead": {
"message": "Applies following settings:"
}
}

@ -0,0 +1,20 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Generator: Adobe Illustrator 19.1.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
<svg version="1.1" id="Ebene_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
viewBox="0 0 76.5 76.3" style="enable-background:new 0 0 76.5 76.3;" xml:space="preserve">
<style type="text/css">
.st0{fill:#FFFFFF;stroke:#37A8DB;stroke-width:5;stroke-miterlimit:10;}
.st1{fill:#37A8DB;}
</style>
<g>
<g>
<circle class="st0" cx="39.4" cy="38.4" r="33.3"/>
</g>
<g>
<path class="st1" d="M29.5,25.4l-4.9-4.9h-2.5v2.5l4.9,4.9L29.5,25.4z M32,18h2.5v4.9H32V18L32,18z M41.9,30.3h4.9v2.5h-4.9V30.3z
M44.3,22.9v-2.5h-2.5l-4.9,5l2.5,2.5L44.3,22.9z M19.6,30.3h4.9v2.5h-4.9V30.3z M32,40.2h2.5v4.9H32V40.2L32,40.2z M22.1,40.2
v2.5h2.5l4.9-4.9l-2.5-2.5L22.1,40.2z M58.6,52L34.1,27.5c-0.7-0.7-1.9-0.7-2.6,0l-2.3,2.3c-0.7,0.7-0.7,1.9,0,2.6L53.7,57
c0.7,0.7,1.9,0.7,2.6,0l2.3-2.3C59.4,53.9,59.4,52.7,58.6,52z M38.2,39l-7.4-7.4l2.5-2.5l7.4,7.4L38.2,39z"/>
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 1.1 KiB

@ -0,0 +1,36 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Generator: Adobe Illustrator 19.1.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
<svg version="1.1" id="Ebene_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
viewBox="0 0 76.5 76.3" style="enable-background:new 0 0 76.5 76.3;" xml:space="preserve">
<style type="text/css">
.st0{fill:#FFFFFF;stroke:#ADADAD;stroke-width:5;stroke-miterlimit:10;}
.st1{fill:#FFFFFF;}
.st2{fill:#37A8DB;}
.st3{fill:none;stroke:#606060;stroke-miterlimit:10;}
</style>
<g>
<g>
<circle class="st0" cx="39.4" cy="38.4" r="33.3"/>
<g>
<circle class="st1" cx="15.1" cy="15.9" r="11.4"/>
<circle class="st2" cx="15.1" cy="15.9" r="9.3"/>
</g>
<g>
<g>
<g>
<path class="st1" d="M18.9,14.6l-0.2-0.4c0.6-1.4,0.6-1.4,0.5-1.5l-0.8-0.8l-0.1-0.1h-0.1c0,0-0.2,0-1.4,0.5l-0.4-0.2
c-0.6-1.4-0.6-1.4-0.8-1.4h-1.1c-0.2,0-0.2,0-0.8,1.4l-0.4,0.2c-0.8-0.3-1.3-0.5-1.4-0.5h-0.1l-0.8,0.8
c-0.1,0.1-0.2,0.2,0.5,1.5l-0.2,0.4c-1.4,0.6-1.4,0.6-1.4,0.8v1.1c0,0.2,0,0.2,1.4,0.7l0.2,0.4c-0.6,1.4-0.6,1.4-0.5,1.5
l0.8,0.8l0.1,0.1h0.1c0,0,0.2,0,1.4-0.5l0.4,0.2c0.6,1.4,0.6,1.4,0.8,1.4h1.1c0.2,0,0.2,0,0.8-1.4l0.4-0.2
c0.8,0.3,1.3,0.5,1.4,0.5h0.1l0.8-0.8c0.1-0.1,0.2-0.2-0.5-1.5l0.2-0.4c1.4-0.6,1.4-0.6,1.4-0.8v-1.1
C20.3,15.2,20.3,15.1,18.9,14.6z M15.1,17.7c-1,0-1.8-0.8-1.8-1.8s0.8-1.8,1.8-1.8s1.8,0.8,1.8,1.8
C16.9,16.9,16.1,17.7,15.1,17.7z"/>
</g>
</g>
</g>
</g>
<path class="st3" d="M62.1,45.7v-5.9l-19.2-9.2c0.1-2.9,0.2-6.6,0.2-7.6c0-4.1-3.3-5.5-3.6-5.6l0,0l0,0c-0.3,0.2-3.6,1.5-3.6,5.6
c0,0.9,0.1,4.6,0.2,7.6L16,39.8l0,5.9l20.9-4.3c0.2,3.9,0.1,5.2,0.3,8.4l-4.6,3.2v2.7l5.2-1.6c0.1,2.1,1.3,3.4,1.3,3.4h0.3h0h0.3
c0,0,1.2-1.2,1.3-3.4l5.2,1.6v-2.7l-4.6-3.2c0.2-3.3,0.1-4.5,0.3-8.4L62.1,45.7z"/>
</g>
</svg>

After

Width:  |  Height:  |  Size: 1.8 KiB

@ -0,0 +1,58 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Generator: Adobe Illustrator 19.1.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
<svg version="1.1" id="Ebene_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
viewBox="-61 62.7 76.5 76.3" style="enable-background:new -61 62.7 76.5 76.3;" xml:space="preserve">
<style type="text/css">
.st0{fill:#FFFFFF;stroke:#ADADAD;stroke-width:5;stroke-miterlimit:10;}
.st1{fill:#FFFFFF;}
.st2{fill:#37A8DB;}
.st3{fill:none;stroke:#606060;stroke-miterlimit:10;}
.st4{fill:#606060;}
</style>
<g>
<g>
<circle class="st0" cx="-21.6" cy="101.1" r="33.3"/>
<g>
<circle class="st1" cx="-45.9" cy="78.6" r="11.4"/>
<circle class="st2" cx="-45.9" cy="78.6" r="9.3"/>
</g>
<g>
<g>
<g>
<path class="st1" d="M-42.1,77.3l-0.2-0.4c0.6-1.4,0.6-1.4,0.5-1.5l-0.8-0.8l-0.1-0.1h-0.1c0,0-0.2,0-1.4,0.5l-0.4-0.2
c-0.6-1.4-0.6-1.4-0.8-1.4h-1.1c-0.2,0-0.2,0-0.8,1.4l-0.4,0.2c-0.8-0.3-1.3-0.5-1.4-0.5h-0.1l-0.8,0.8
c-0.1,0.1-0.2,0.2,0.5,1.5l-0.2,0.4c-1.4,0.6-1.4,0.6-1.4,0.8v1.1c0,0.2,0,0.2,1.4,0.7l0.2,0.4c-0.6,1.4-0.6,1.4-0.5,1.5
l0.8,0.8l0.1,0.1h0.1c0,0,0.2,0,1.4-0.5l0.4,0.2c0.6,1.4,0.6,1.4,0.8,1.4h1.1c0.2,0,0.2,0,0.8-1.4l0.4-0.2
c0.8,0.3,1.3,0.5,1.4,0.5h0.1l0.8-0.8c0.1-0.1,0.2-0.2-0.5-1.5l0.2-0.4c1.4-0.6,1.4-0.6,1.4-0.8V78
C-40.7,77.9-40.7,77.8-42.1,77.3z M-45.9,80.4c-1,0-1.8-0.8-1.8-1.8s0.8-1.8,1.8-1.8s1.8,0.8,1.8,1.8S-44.9,80.4-45.9,80.4z"/>
</g>
</g>
</g>
</g>
<g>
<g>
<g>
<path class="st3" d="M-9.4,110.7c-0.1,0-0.1-0.1-0.2-0.1c-1.6-0.7-2.8-1.3-4.2-3.6s-2.1-3.4-2.2-5.1c0.1-1.6,0.9-2.7,2.2-5
s2.6-2.9,4.2-3.6c0.1,0,0.1-0.1,0.2-0.1c0.7-0.3,1.2-1.1,1.2-1.9c0-1.2-0.9-2.1-2.1-2.1c-0.9,0-1.7,0.6-2,1.4
c-1.3,2.1-2.3,3-4.2,4.5s-4,2.4-5.1,2.4h-0.2c-1.1,0-3.2-0.9-5.1-2.4c-1.8-1.5-2.9-2.3-4.2-4.5c-0.3-0.8-1.1-1.4-2-1.4
c-1.2,0-2.1,0.9-2.1,2.1c0,0.8,0.5,1.6,1.2,1.9c0.1,0,0.1,0.1,0.2,0.1c1.7,0.7,2.9,1.3,4.3,3.6c1.4,2.3,2.1,3.4,2.2,5.1
c-0.1,1.6-0.9,2.7-2.2,5c-1.4,2.3-2.6,2.9-4.2,3.6c-0.1,0-0.1,0.1-0.2,0.1c-0.7,0.3-1.2,1.1-1.2,1.9c0,1.2,0.9,2.1,2.1,2.1
c0.9,0,1.7-0.6,2-1.4c1.3-2.1,2.3-3,4.2-4.5c1.9-1.5,4-2.4,5.1-2.4h0.2c1.1,0,3.2,0.9,5.1,2.4c1.8,1.5,2.9,2.3,4.2,4.5
c0.3,0.8,1.1,1.4,2,1.4c1.2,0,2.1-0.9,2.1-2.1C-8.2,111.8-8.7,111-9.4,110.7z"/>
</g>
</g>
<path class="st4" d="M-32,96c-0.3,0.1-0.7,0.1-1,0.1c-2.7,0-4.8-2.2-4.8-4.8s2.2-4.8,4.8-4.8s4.8,2.2,4.8,4.8c0,0.2,0,0.4-0.1,0.7
l0.9,0.6c0.1-0.4,0.1-0.8,0.1-1.3c0-3.2-2.6-5.8-5.8-5.8s-5.8,2.6-5.8,5.8c0,3.2,2.6,5.8,5.8,5.8c0.6,0,1.1-0.1,1.7-0.2L-32,96z"
/>
<path class="st4" d="M-10.2,85.5c-3.2,0-5.8,2.6-5.8,5.8c0,0.5,0.1,0.9,0.2,1.3l0.9-0.6c0-0.2-0.1-0.5-0.1-0.7
c0-2.7,2.2-4.8,4.8-4.8s4.8,2.2,4.8,4.8c0,2.6-2.2,4.8-4.8,4.8c-0.3,0-0.6,0-1-0.1l-0.6,0.9c0.5,0.1,1,0.2,1.6,0.2
c3.2,0,5.8-2.6,5.8-5.8C-4.4,88.1-7,85.5-10.2,85.5z"/>
<path class="st4" d="M-32,108c-0.3-0.1-0.7-0.1-1-0.1c-2.7,0-4.8,2.2-4.8,4.8s2.2,4.8,4.8,4.8s4.8-2.2,4.8-4.8
c0-0.2,0-0.4-0.1-0.7l0.9-0.6c0.1,0.4,0.1,0.8,0.1,1.3c0,3.2-2.6,5.8-5.8,5.8s-5.8-2.6-5.8-5.8s2.6-5.8,5.8-5.8
c0.6,0,1.1,0.1,1.7,0.2L-32,108z"/>
<path class="st4" d="M-10.2,118.5c-3.2,0-5.8-2.6-5.8-5.8c0-0.5,0.1-0.9,0.2-1.3l0.9,0.6c0,0.2-0.1,0.5-0.1,0.7
c0,2.7,2.2,4.8,4.8,4.8s4.8-2.2,4.8-4.8s-2.2-4.8-4.8-4.8c-0.3,0-0.6,0-1,0.1l-0.6-0.9c0.5-0.1,1-0.2,1.6-0.2
c3.2,0,5.8,2.6,5.8,5.8C-4.4,115.9-7,118.5-10.2,118.5z"/>
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 3.4 KiB

@ -0,0 +1,38 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Generator: Adobe Illustrator 19.1.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
<svg version="1.1" id="Ebene_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
viewBox="0 0 76.5 76.3" style="enable-background:new 0 0 76.5 76.3;" xml:space="preserve">
<style type="text/css">
.st0{fill:#FFFFFF;stroke:#ADADAD;stroke-width:5;stroke-miterlimit:10;}
.st1{fill:#FFFFFF;}
.st2{fill:#37A8DB;}
.st3{fill:none;stroke:#606060;stroke-miterlimit:10;}
</style>
<g>
<g>
<circle class="st0" cx="39.4" cy="38.4" r="33.3"/>
<g>
<circle class="st1" cx="15.1" cy="15.9" r="11.4"/>
<circle class="st2" cx="15.1" cy="15.9" r="9.3"/>
</g>
<g>
<g>
<g>
<path class="st1" d="M18.9,14.6l-0.2-0.4c0.6-1.4,0.6-1.4,0.5-1.5l-0.8-0.8l-0.1-0.1h-0.1c0,0-0.2,0-1.4,0.5l-0.4-0.2
c-0.6-1.4-0.6-1.4-0.8-1.4h-1.1c-0.2,0-0.2,0-0.8,1.4l-0.4,0.2c-0.8-0.3-1.3-0.5-1.4-0.5h-0.1l-0.8,0.8
c-0.1,0.1-0.2,0.2,0.5,1.5l-0.2,0.4c-1.4,0.6-1.4,0.6-1.4,0.8v1.1c0,0.2,0,0.2,1.4,0.7l0.2,0.4c-0.6,1.4-0.6,1.4-0.5,1.5
l0.8,0.8l0.1,0.1h0.1c0,0,0.2,0,1.4-0.5l0.4,0.2c0.6,1.4,0.6,1.4,0.8,1.4h1.1c0.2,0,0.2,0,0.8-1.4l0.4-0.2
c0.8,0.3,1.3,0.5,1.4,0.5h0.1l0.8-0.8c0.1-0.1,0.2-0.2-0.5-1.5l0.2-0.4c1.4-0.6,1.4-0.6,1.4-0.8v-1.1
C20.3,15.2,20.3,15.1,18.9,14.6z M15.1,17.7c-1,0-1.8-0.8-1.8-1.8s0.8-1.8,1.8-1.8s1.8,0.8,1.8,1.8S16.1,17.7,15.1,17.7z"/>
</g>
</g>
</g>
</g>
<g>
<path class="st3" d="M42.1,26c-0.3-0.1-0.5-0.3-0.7-0.3c-0.3,0-1.6,0-2.1,0c-0.1,0-0.2,0-0.2,0c-0.5,0-1.8,0-2.1,0
c-0.2,0-0.4,0.1-0.7,0.3C35.6,26.3,16,37.8,16,37.8v8.4l0.6-0.1v-1.6l18.2-3.3l0.4-0.5v-1.5h3v1.3h2.1v-1.3h3v1.5l0.4,0.5
l18.2,3.3v1.6l0.6,0.1v-8.4C62.4,37.8,42.8,26.3,42.1,26z"/>
<path class="st3" d="M39.7,40.9c0,0.5-0.2,0.7-0.5,0.9c-0.2-0.1-0.5-0.4-0.5-0.9v-0.2h1.1V40.9z"/>
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 1.9 KiB

@ -1,817 +0,0 @@
'use strict';
// code below is highly experimental, although it runs fine on latest firmware
// the data inside nested objects needs to be verified if deep copy works properly
function configuration_backup(callback) {
var activeProfile = null,
profilesN = 3;
var configuration = {
'generatedBy': chrome.runtime.getManifest().version,
'apiVersion': CONFIG.apiVersion,
'profiles': [],
};
var profileSpecificData = [
MSPCodes.MSP_PID,
MSPCodes.MSP_RC_TUNING,
MSPCodes.MSP_ACC_TRIM,
MSPCodes.MSP_SERVO_CONFIGURATIONS,
MSPCodes.MSP_MODE_RANGES,
MSPCodes.MSP_ADJUSTMENT_RANGES
];
function update_profile_specific_data_list() {
if (semver.lt(CONFIG.apiVersion, "1.12.0")) {
profileSpecificData.push(MSPCodes.MSP_CHANNEL_FORWARDING);
} else {
profileSpecificData.push(MSPCodes.MSP_SERVO_MIX_RULES);
}
if (semver.gte(CONFIG.apiVersion, "1.15.0")) {
profileSpecificData.push(MSPCodes.MSP_RC_DEADBAND);
}
}
update_profile_specific_data_list();
MSP.send_message(MSPCodes.MSP_STATUS, false, false, function () {
activeProfile = CONFIG.profile;
select_profile();
});
function select_profile() {
if (activeProfile > 0) {
MSP.send_message(MSPCodes.MSP_SELECT_SETTING, [0], false, fetch_specific_data);
} else {
fetch_specific_data();
}
}
function fetch_specific_data() {
var fetchingProfile = 0,
codeKey = 0;
function fetch_specific_data_item() {
if (fetchingProfile < profilesN) {
MSP.send_message(profileSpecificData[codeKey], false, false, function () {
codeKey++;
if (codeKey < profileSpecificData.length) {
fetch_specific_data_item();
} else {
configuration.profiles.push({
'PID': jQuery.extend(true, {}, PID),
'PIDs': jQuery.extend(true, [], PIDs),
'RC': jQuery.extend(true, {}, RC_tuning),
'AccTrim': jQuery.extend(true, [], CONFIG.accelerometerTrims),
'ServoConfig': jQuery.extend(true, [], SERVO_CONFIG),
'ServoRules': jQuery.extend(true, [], SERVO_RULES),
'ModeRanges': jQuery.extend(true, [], MODE_RANGES),
'AdjustmentRanges': jQuery.extend(true, [], ADJUSTMENT_RANGES)
});
if (semver.gte(CONFIG.apiVersion, "1.15.0")) {
configuration.profiles[fetchingProfile].RCdeadband = jQuery.extend(true, {}, RC_deadband);
}
codeKey = 0;
fetchingProfile++;
MSP.send_message(MSPCodes.MSP_SELECT_SETTING, [fetchingProfile], false, fetch_specific_data_item);
}
});
} else {
MSP.send_message(MSPCodes.MSP_SELECT_SETTING, [activeProfile], false, fetch_unique_data);
}
}
// start fetching
fetch_specific_data_item();
}
var uniqueData = [
MSPCodes.MSP_MISC,
MSPCodes.MSP_RX_MAP,
MSPCodes.MSP_BF_CONFIG,
MSPCodes.MSP_CF_SERIAL_CONFIG,
MSPCodes.MSP_LED_STRIP_CONFIG,
MSPCodes.MSP_LED_COLORS
];
function update_unique_data_list() {
if (semver.gte(CONFIG.apiVersion, "1.8.0")) {
uniqueData.push(MSPCodes.MSP_LOOP_TIME);
uniqueData.push(MSPCodes.MSP_ARMING_CONFIG);
}
if (semver.gte(CONFIG.apiVersion, "1.14.0")) {
uniqueData.push(MSPCodes.MSP_3D);
}
if (semver.gte(CONFIG.apiVersion, "1.15.0")) {
uniqueData.push(MSPCodes.MSP_SENSOR_ALIGNMENT);
uniqueData.push(MSPCodes.MSP_RX_CONFIG);
uniqueData.push(MSPCodes.MSP_FAILSAFE_CONFIG);
uniqueData.push(MSPCodes.MSP_RXFAIL_CONFIG);
}
if (semver.gte(CONFIG.apiVersion, "1.19.0")) {
uniqueData.push(MSPCodes.MSP_LED_STRIP_MODECOLOR);
}
}
update_unique_data_list();
function fetch_unique_data() {
var codeKey = 0;
function fetch_unique_data_item() {
if (codeKey < uniqueData.length) {
MSP.send_message(uniqueData[codeKey], false, false, function () {
codeKey++;
fetch_unique_data_item();
});
} else {
configuration.MISC = jQuery.extend(true, {}, MISC);
configuration.RCMAP = jQuery.extend(true, [], RC_MAP);
configuration.BF_CONFIG = jQuery.extend(true, {}, BF_CONFIG);
configuration.SERIAL_CONFIG = jQuery.extend(true, {}, SERIAL_CONFIG);
configuration.LED_STRIP = jQuery.extend(true, [], LED_STRIP);
configuration.LED_COLORS = jQuery.extend(true, [], LED_COLORS);
if (semver.gte(CONFIG.apiVersion, "1.19.0")) {
configuration.LED_MODE_COLORS = jQuery.extend(true, [], LED_MODE_COLORS);
}
if (semver.gte(CONFIG.apiVersion, "1.8.0")) {
configuration.FC_CONFIG = jQuery.extend(true, {}, FC_CONFIG);
configuration.ARMING_CONFIG = jQuery.extend(true, {}, ARMING_CONFIG);
}
if (semver.gte(CONFIG.apiVersion, "1.14.0")) {
configuration._3D = jQuery.extend(true, {}, _3D);
}
if (semver.gte(CONFIG.apiVersion, "1.15.0")) {
configuration.SENSOR_ALIGNMENT = jQuery.extend(true, {}, SENSOR_ALIGNMENT);
configuration.RX_CONFIG = jQuery.extend(true, {}, RX_CONFIG);
configuration.FAILSAFE_CONFIG = jQuery.extend(true, {}, FAILSAFE_CONFIG);
configuration.RXFAIL_CONFIG = jQuery.extend(true, [], RXFAIL_CONFIG);
}
save();
}
}
// start fetching
fetch_unique_data_item();
}
function save() {
var chosenFileEntry = null;
var accepts = [{
extensions: ['txt']
}];
// generate timestamp for the backup file
var d = new Date(),
now = (d.getMonth() + 1) + '.' + d.getDate() + '.' + d.getFullYear() + '.' + d.getHours() + '.' + d.getMinutes();
// create or load the file
chrome.fileSystem.chooseEntry({type: 'saveFile', suggestedName: 'inav_backup_' + now, accepts: accepts}, function (fileEntry) {
if (chrome.runtime.lastError) {
console.error(chrome.runtime.lastError.message);
return;
}
if (!fileEntry) {
console.log('No file selected, backup aborted.');
return;
}
chosenFileEntry = fileEntry;
// echo/console log path specified
chrome.fileSystem.getDisplayPath(chosenFileEntry, function (path) {
console.log('Backup file path: ' + path);
});
// change file entry from read only to read/write
chrome.fileSystem.getWritableEntry(chosenFileEntry, function (fileEntryWritable) {
// check if file is writable
chrome.fileSystem.isWritableEntry(fileEntryWritable, function (isWritable) {
if (isWritable) {
chosenFileEntry = fileEntryWritable;
// crunch the config object
var serialized_config_object = JSON.stringify(configuration);
var blob = new Blob([serialized_config_object], {type: 'text/plain'}); // first parameter for Blob needs to be an array
chosenFileEntry.createWriter(function (writer) {
writer.onerror = function (e) {
console.error(e);
};
var truncated = false;
writer.onwriteend = function () {
if (!truncated) {
// onwriteend will be fired again when truncation is finished
truncated = true;
writer.truncate(blob.size);
return;
}
console.log('Write SUCCESSFUL');
if (callback) callback();
};
writer.write(blob);
}, function (e) {
console.error(e);
});
} else {
// Something went wrong or file is set to read only and cannot be changed
console.log('File appears to be read only, sorry.');
}
});
});
});
}
}
function configuration_restore(callback) {
var chosenFileEntry = null;
var accepts = [{
extensions: ['txt']
}];
// load up the file
chrome.fileSystem.chooseEntry({type: 'openFile', accepts: accepts}, function (fileEntry) {
if (chrome.runtime.lastError) {
console.error(chrome.runtime.lastError.message);
return;
}
if (!fileEntry) {
console.log('No file selected, restore aborted.');
return;
}
chosenFileEntry = fileEntry;
// echo/console log path specified
chrome.fileSystem.getDisplayPath(chosenFileEntry, function (path) {
console.log('Restore file path: ' + path);
});
// read contents into variable
chosenFileEntry.file(function (file) {
var reader = new FileReader();
reader.onprogress = function (e) {
if (e.total > 1048576) { // 1 MB
// dont allow reading files bigger then 1 MB
console.log('File limit (1 MB) exceeded, aborting');
reader.abort();
}
};
reader.onloadend = function (e) {
if (e.total != 0 && e.total == e.loaded) {
console.log('Read SUCCESSFUL');
try { // check if string provided is a valid JSON
var configuration = JSON.parse(e.target.result);
} catch (e) {
// data provided != valid json object
console.log('Data provided != valid JSON string, restore aborted.');
return;
}
// validate
if (typeof configuration.generatedBy !== 'undefined' && compareVersions(configuration.generatedBy, CONFIGURATOR.backupFileMinVersionAccepted)) {
if (!migrate(configuration)) {
GUI.log(chrome.i18n.getMessage('backupFileUnmigratable'));
return;
}
configuration_upload(configuration, callback);
} else {
GUI.log(chrome.i18n.getMessage('backupFileIncompatible'));
}
}
};
reader.readAsText(file);
});
});
function compareVersions(generated, required) {
if (generated == undefined) {
return false;
}
return semver.gte(generated, required);
}
function migrate(configuration) {
var appliedMigrationsCount = 0;
var migratedVersion = configuration.generatedBy;
GUI.log(chrome.i18n.getMessage('configMigrationFrom', [migratedVersion]));
if (!compareVersions(migratedVersion, '0.59.1')) {
// variable was renamed
configuration.MISC.rssi_channel = configuration.MISC.rssi_aux_channel;
configuration.MISC.rssi_aux_channel = undefined;
migratedVersion = '0.59.1';
GUI.log(chrome.i18n.getMessage('configMigratedTo', [migratedVersion]));
appliedMigrationsCount++;
}
if (!compareVersions(migratedVersion, '0.60.1')) {
// LED_STRIP support was added.
if (!configuration.LED_STRIP) {
configuration.LED_STRIP = [];
}
migratedVersion = '0.60.1';
GUI.log(chrome.i18n.getMessage('configMigratedTo', [migratedVersion]));
appliedMigrationsCount++;
}
if (!compareVersions(migratedVersion, '0.61.0')) {
// Changing PID controller via UI was added.
if (!configuration.PIDs && configuration.PID) {
configuration.PIDs = configuration.PID;
}
migratedVersion = '0.61.0';
GUI.log(chrome.i18n.getMessage('configMigratedTo', [migratedVersion]));
appliedMigrationsCount++;
}
if (!compareVersions(migratedVersion, '0.63.0')) {
// LED Strip was saved as object instead of array.
if (typeof(configuration.LED_STRIP) == 'object') {
var fixed_led_strip = [];
var index = 0;
while (configuration.LED_STRIP[index]) {
fixed_led_strip.push(configuration.LED_STRIP[index++]);
}
configuration.LED_STRIP = fixed_led_strip;
}
for (var profileIndex = 0; profileIndex < 3; profileIndex++) {
var RC = configuration.profiles[profileIndex].RC;
// TPA breakpoint was added
if (!RC.dynamic_THR_breakpoint) {
RC.dynamic_THR_breakpoint = 1500; // firmware default
}
// Roll and pitch rates were split
RC.roll_rate = RC.roll_pitch_rate;
RC.pitch_rate = RC.roll_pitch_rate;
}
migratedVersion = '0.63.0';
GUI.log(chrome.i18n.getMessage('configMigratedTo', [migratedVersion]));
appliedMigrationsCount++;
}
if (configuration.apiVersion == undefined) {
configuration.apiVersion = "1.0.0" // a guess that will satisfy the rest of the code
}
// apiVersion previously stored without patchlevel
if (!semver.parse(configuration.apiVersion)) {
configuration.apiVersion += ".0";
if (!semver.parse(configuration.apiVersion)) {
return false;
}
}
if (compareVersions(migratedVersion, '0.63.0') && !compareVersions(configuration.apiVersion, '1.7.0')) {
// Serial configuation redesigned, 0.63.0 saves old and new configurations.
var ports = [];
for (var portIndex = 0; portIndex < configuration.SERIAL_CONFIG.ports.length; portIndex++) {
var oldPort = configuration.SERIAL_CONFIG.ports[portIndex];
var newPort = {
identifier: oldPort.identifier,
functions: [],
msp_baudrate: String(configuration.SERIAL_CONFIG.mspBaudRate),
gps_baudrate: String(configuration.SERIAL_CONFIG.gpsBaudRate),
telemetry_baudrate: 'AUTO',
blackbox_baudrate: '115200',
};
switch(oldPort.scenario) {
case 1: // MSP, CLI, TELEMETRY, SMARTPORT TELEMETRY, GPS-PASSTHROUGH
case 5: // MSP, CLI, GPS-PASSTHROUGH
case 8: // MSP ONLY
newPort.functions.push('MSP');
break;
case 2: // GPS
newPort.functions.push('GPS');
break;
case 3: // RX_SERIAL
newPort.functions.push('RX_SERIAL');
break;
case 10: // BLACKBOX ONLY
newPort.functions.push('BLACKBOX');
break;
case 11: // MSP, CLI, BLACKBOX, GPS-PASSTHROUGH
newPort.functions.push('MSP');
newPort.functions.push('BLACKBOX');
break;
}
ports.push(newPort);
}
configuration.SERIAL_CONFIG = {
ports: ports
};
appliedMigrationsCount++;
}
if (compareVersions(migratedVersion, '0.63.0') && !compareVersions(configuration.apiVersion, '1.8.0')) {
// api 1.8 exposes looptime and arming config
if (configuration.FC_CONFIG == undefined) {
configuration.FC_CONFIG = {
loopTime: 3500
};
}
if (configuration.ARMING_CONFIG == undefined) {
configuration.ARMING_CONFIG = {
auto_disarm_delay: 5,
disarm_kill_switch: 1
};
}
appliedMigrationsCount++;
}
if (compareVersions(migratedVersion, '0.63.0')) {
// backups created with 0.63.0 for firmwares with api < 1.8 were saved with incorrect looptime
if (configuration.FC_CONFIG.loopTime == 0) {
//reset it to the default
configuration.FC_CONFIG.loopTime = 3500;
}
}
if (semver.lt(migratedVersion, '0.66.0')) {
// api 1.12 updated servo configuration protocol and added servo mixer rules
for (var profileIndex = 0; profileIndex < configuration.profiles.length; profileIndex++) {
if (semver.eq(configuration.apiVersion, '1.10.0')) {
// drop two unused servo configurations
while (configuration.profiles[profileIndex].ServoConfig.length > 8) {
configuration.profiles[profileIndex].ServoConfig.pop();
}
}
for (var i = 0; i < configuration.profiles[profileIndex].ServoConfig.length; i++) {
var servoConfig = profiles[profileIndex].ServoConfig;
servoConfig[i].angleAtMin = 45;
servoConfig[i].angleAtMax = 45;
servoConfig[i].reversedInputSources = 0;
// set the rate to 0 if an invalid value is detected.
if (servoConfig[i].rate < -100 || servoConfig[i].rate > 100) {
servoConfig[i].rate = 0;
}
}
configuration.profiles[profileIndex].ServoRules = [];
}
migratedVersion = '0.66.0';
appliedMigrationsCount++;
}
if (compareVersions(migratedVersion, '0.66.0') && !compareVersions(configuration.apiVersion, '1.14.0')) {
// api 1.14 exposes 3D configuration
if (configuration._3D == undefined) {
configuration._3D = {
deadband3d_low: 1406,
deadband3d_high: 1514,
neutral3d: 1460,
deadband3d_throttle: 50
};
}
appliedMigrationsCount++;
}
if (compareVersions(migratedVersion, '0.66.0') && !compareVersions(configuration.apiVersion, '1.15.0')) {
// api 1.15 exposes RCdeadband and sensor alignment
for (var profileIndex = 0; profileIndex < configuration.profiles.length; profileIndex++) {
if (configuration.profiles[profileIndex].RCdeadband == undefined) {
configuration.profiles[profileIndex].RCdeadband = {
deadband: 0,
yaw_deadband: 0,
alt_hold_deadband: 40,
};
}
}
if (configuration.SENSOR_ALIGNMENT == undefined) {
configuration.SENSOR_ALIGNMENT = {
align_gyro: 0,
align_acc: 0,
align_mag: 0
};
}
// api 1.15 exposes RX_CONFIG, FAILSAFE_CONFIG and RXFAIL_CONFIG configuration
if (configuration.RX_CONFIG == undefined) {
configuration.RX_CONFIG = {
serialrx_provider: 0,
spektrum_sat_bind: 0,
midrc: 1500,
mincheck: 1100,
maxcheck: 1900,
rx_min_usec: 885,
rx_max_usec: 2115,
nrf24rx_protocol: 0,
nrf24rx_id: 0
};
}
if (configuration.FAILSAFE_CONFIG == undefined) {
configuration.FAILSAFE_CONFIG = {
failsafe_delay: 10,
failsafe_off_delay: 200,
failsafe_throttle: 1000,
failsafe_kill_switch: 0,
failsafe_throttle_low_delay: 100,
failsafe_procedure: 0
};
}
if (configuration.RXFAIL_CONFIG == undefined) {
configuration.RXFAIL_CONFIG = [
{mode: 0, value: 1500},
{mode: 0, value: 1500},
{mode: 0, value: 1500},
{mode: 0, value: 875}
];
for (var i = 0; i < 14; i++) {
var rxfailChannel = {
mode: 1,
value: 1500
};
configuration.RXFAIL_CONFIG.push(rxfailChannel);
}
}
appliedMigrationsCount++;
}
if (compareVersions(migratedVersion, '1.2.0')) {
// old version of the configurator incorrectly had a 'disabled' option for GPS SBAS mode.
if (MISC.gps_ubx_sbas < 0) {
MISC.gps_ubx_sbas = 0;
}
migratedVersion = '1.2.0';
appliedMigrationsCount++;
}
if (!compareVersions(migratedVersion, '1.2.0')) {
// LED_COLORS & LED_MODE_COLORS support was added.
if (!configuration.LED_COLORS) {
configuration.LED_COLORS = [];
}
if (!configuration.LED_MODE_COLORS) {
configuration.LED_MODE_COLORS = [];
}
migratedVersion = '1.3.1';
GUI.log(chrome.i18n.getMessage('configMigratedTo', [migratedVersion]));
appliedMigrationsCount++;
}
if (appliedMigrationsCount > 0) {
GUI.log(chrome.i18n.getMessage('configMigrationSuccessful', [appliedMigrationsCount]));
}
return true;
}
function configuration_upload(configuration, callback) {
function upload() {
var activeProfile = null,
profilesN = 3;
var profileSpecificData = [
MSPCodes.MSP_SET_PID,
MSPCodes.MSP_SET_RC_TUNING,
MSPCodes.MSP_SET_ACC_TRIM
];
if (semver.gte(CONFIG.apiVersion, "1.15.0")) {
profileSpecificData.push(MSPCodes.MSP_SET_RC_DEADBAND);
}
MSP.send_message(MSPCodes.MSP_STATUS, false, false, function () {
activeProfile = CONFIG.profile;
select_profile();
});
function select_profile() {
if (activeProfile > 0) {
MSP.send_message(MSPCodes.MSP_SELECT_SETTING, [0], false, upload_specific_data);
} else {
upload_specific_data();
}
}
function upload_specific_data() {
var savingProfile = 0,
codeKey = 0;
function load_objects(profile) {
PID = configuration.profiles[profile].PID;
PIDs = configuration.profiles[profile].PIDs;
RC_tuning = configuration.profiles[profile].RC;
CONFIG.accelerometerTrims = configuration.profiles[profile].AccTrim;
SERVO_CONFIG = configuration.profiles[profile].ServoConfig;
SERVO_RULES = configuration.profiles[profile].ServoRules;
MODE_RANGES = configuration.profiles[profile].ModeRanges;
ADJUSTMENT_RANGES = configuration.profiles[profile].AdjustmentRanges;
RC_deadband = configuration.profiles[profile].RCdeadband;
}
function upload_using_specific_commands() {
MSP.send_message(profileSpecificData[codeKey], mspHelper.crunch(profileSpecificData[codeKey]), false, function () {
codeKey++;
if (codeKey < profileSpecificData.length) {
upload_using_specific_commands();
} else {
codeKey = 0;
savingProfile++;
if (savingProfile < profilesN) {
load_objects(savingProfile);
MSP.send_message(MSPCodes.MSP_EEPROM_WRITE, false, false, function () {
MSP.send_message(MSPCodes.MSP_SELECT_SETTING, [savingProfile], false, upload_using_specific_commands);
});
} else {
MSP.send_message(MSPCodes.MSP_EEPROM_WRITE, false, false, function () {
MSP.send_message(MSPCodes.MSP_SELECT_SETTING, [activeProfile], false, upload_unique_data);
});
}
}
});
}
function upload_servo_mix_rules() {
mspHelper.sendServoMixRules(upload_servo_configuration);
}
function upload_servo_configuration() {
mspHelper.sendServoConfigurations(upload_mode_ranges);
}
function upload_mode_ranges() {
mspHelper.sendModeRanges(upload_adjustment_ranges);
}
function upload_adjustment_ranges() {
mspHelper.sendAdjustmentRanges(upload_using_specific_commands);
}
// start uploading
load_objects(0);
upload_servo_configuration();
}
function upload_unique_data() {
var codeKey = 0;
var uniqueData = [
MSPCodes.MSP_SET_MISC,
MSPCodes.MSP_SET_RX_MAP,
MSPCodes.MSP_SET_BF_CONFIG,
MSPCodes.MSP_SET_CF_SERIAL_CONFIG
];
function update_unique_data_list() {
if (semver.gte(CONFIG.apiVersion, "1.8.0")) {
uniqueData.push(MSPCodes.MSP_SET_LOOP_TIME);
uniqueData.push(MSPCodes.MSP_SET_ARMING_CONFIG);
}
if (semver.gte(CONFIG.apiVersion, "1.14.0")) {
uniqueData.push(MSPCodes.MSP_SET_3D);
}
if (semver.gte(CONFIG.apiVersion, "1.15.0")) {
uniqueData.push(MSPCodes.MSP_SET_SENSOR_ALIGNMENT);
uniqueData.push(MSPCodes.MSP_SET_RX_CONFIG);
uniqueData.push(MSPCodes.MSP_SET_FAILSAFE_CONFIG);
}
}
function load_objects() {
MISC = configuration.MISC;
RC_MAP = configuration.RCMAP;
BF_CONFIG = configuration.BF_CONFIG;
SERIAL_CONFIG = configuration.SERIAL_CONFIG;
LED_STRIP = configuration.LED_STRIP;
LED_COLORS = configuration.LED_COLORS;
LED_MODE_COLORS = configuration.LED_MODE_COLORS;
ARMING_CONFIG = configuration.ARMING_CONFIG;
FC_CONFIG = configuration.FC_CONFIG;
_3D = configuration._3D;
SENSOR_ALIGNMENT = configuration.SENSOR_ALIGNMENT;
RX_CONFIG = configuration.RX_CONFIG;
FAILSAFE_CONFIG = configuration.FAILSAFE_CONFIG;
RXFAIL_CONFIG = configuration.RXFAIL_CONFIG;
}
function send_unique_data_item() {
if (codeKey < uniqueData.length) {
MSP.send_message(uniqueData[codeKey], mspHelper.crunch(uniqueData[codeKey]), false, function () {
codeKey++;
send_unique_data_item();
});
} else {
send_led_strip_config();
}
}
load_objects();
update_unique_data_list();
// start uploading
send_unique_data_item();
}
function send_led_strip_config() {
mspHelper.sendLedStripConfig(send_led_strip_colors);
}
function send_led_strip_colors() {
mspHelper.sendLedStripColors(send_led_strip_mode_colors);
}
function send_led_strip_mode_colors() {
if (semver.gte(CONFIG.apiVersion, "1.19.0"))
mspHelper.sendLedStripModeColors(send_rxfail_config);
else
send_rxfail_config();
}
function send_rxfail_config() {
if (semver.gte(CONFIG.apiVersion, "1.15.0")) {
mspHelper.sendRxFailConfig(save_to_eeprom);
} else {
save_to_eeprom();
}
}
function save_to_eeprom() {
MSP.send_message(MSPCodes.MSP_EEPROM_WRITE, false, false, reboot);
}
function reboot() {
GUI.log(chrome.i18n.getMessage('eeprom_saved_ok'));
GUI.tab_switch_cleanup(function() {
MSP.send_message(MSPCodes.MSP_SET_REBOOT, false, false, reinitialize);
});
}
function reinitialize() {
GUI.log(chrome.i18n.getMessage('deviceRebooting'));
GUI.timeout_add('waiting_for_bootup', function waiting_for_bootup() {
MSP.send_message(MSPCodes.MSP_IDENT, false, false, function () {
GUI.log(chrome.i18n.getMessage('deviceReady'));
if (callback) callback();
});
}, 1500); // 1500 ms seems to be just the right amount of delay to prevent data request timeouts
}
}
upload();
}
}

@ -0,0 +1,77 @@
'use s';
var helper = helper || {};
/**
* Simple analyzer that returns frequency of events using 5s buffer
* Usage: register periodic events with 'put', then call 'get' to get results
*/
helper.eventFrequencyAnalyzer = (function () {
var privateScope = {},
publicScope = {},
bufferPeriod = 5000;
privateScope.data = {};
privateScope.output = {};
privateScope.intervalHandler;
/**
* Periodically executed aggregation task
* @returns {{}|*}
*/
publicScope.analyze = function () {
privateScope.output = {};
for (var i in privateScope.data) {
if (privateScope.data.hasOwnProperty(i)) {
privateScope.output[i] = privateScope.data[i] / bufferPeriod * 1000;
}
}
privateScope.data = {};
return privateScope.output;
};
/**
* Return event list with frequencies
* @returns {{}|*}
*/
publicScope.get = function () {
return privateScope.output;
};
/**
* Returns raw data
* @returns {{}|*}
*/
publicScope.getRaw = function () {
return privateScope.data;
};
/**
* Put event into analyzer
* @param {object} event
*/
publicScope.put = function (event) {
if (privateScope.data[event]) {
privateScope.data[event]++;
} else {
privateScope.data[event] = 1;
}
};
/**
*
* @param {number} buffer buffer length in milliseconds
*/
publicScope.setBufferPeriod = function (buffer) {
bufferPeriod = buffer;
clearInterval(privateScope.intervalHandler);
privateScope.intervalHandler = setInterval(publicScope.analyze, bufferPeriod);
};
privateScope.intervalHandler = setInterval(publicScope.analyze, bufferPeriod);
return publicScope;
})();

@ -251,7 +251,8 @@ var FC = {
yawItermIgnoreRate: null,
yawPLimit: null,
axisAccelerationLimitRollPitch: null,
axisAccelerationLimitYaw: null
axisAccelerationLimitYaw: null,
dtermSetpointWeight: null
};
INAV_PID_CONFIG = {

@ -11,8 +11,6 @@ var GUI_control = function () {
this.active_tab;
this.tab_switch_in_progress = false;
this.operating_system;
this.interval_array = [];
this.timeout_array = [];
this.defaultAllowedTabsWhenDisconnected = [
'landing',
'firmware_flasher',
@ -52,162 +50,6 @@ var GUI_control = function () {
else this.operating_system = "Unknown";
};
// Timer managing methods
// name = string
// code = function reference (code to be executed)
// interval = time interval in miliseconds
// first = true/false if code should be ran initially before next timer interval hits
GUI_control.prototype.interval_add = function (name, code, interval, first) {
var data = {'name': name, 'timer': null, 'code': code, 'interval': interval, 'fired': 0, 'paused': false};
if (first == true) {
code(); // execute code
data.fired++; // increment counter
}
data.timer = setInterval(function() {
code(); // execute code
data.fired++; // increment counter
}, interval);
this.interval_array.push(data); // push to primary interval array
return data;
};
// name = string
GUI_control.prototype.interval_remove = function (name) {
for (var i = 0; i < this.interval_array.length; i++) {
if (this.interval_array[i].name == name) {
clearInterval(this.interval_array[i].timer); // stop timer
this.interval_array.splice(i, 1); // remove element/object from array
return true;
}
}
return false;
};
// name = string
GUI_control.prototype.interval_pause = function (name) {
for (var i = 0; i < this.interval_array.length; i++) {
if (this.interval_array[i].name == name) {
clearInterval(this.interval_array[i].timer);
this.interval_array[i].paused = true;
return true;
}
}
return false;
};
// name = string
GUI_control.prototype.interval_resume = function (name) {
for (var i = 0; i < this.interval_array.length; i++) {
if (this.interval_array[i].name == name && this.interval_array[i].paused) {
var obj = this.interval_array[i];
obj.timer = setInterval(function() {
obj.code(); // execute code
obj.fired++; // increment counter
}, obj.interval);
obj.paused = false;
return true;
}
}
return false;
};
// input = array of timers thats meant to be kept, or nothing
// return = returns timers killed in last call
GUI_control.prototype.interval_kill_all = function (keep_array) {
var self = this;
var timers_killed = 0;
for (var i = (this.interval_array.length - 1); i >= 0; i--) { // reverse iteration
var keep = false;
if (keep_array) { // only run through the array if it exists
keep_array.forEach(function (name) {
if (self.interval_array[i].name == name) {
keep = true;
}
});
}
if (!keep) {
clearInterval(this.interval_array[i].timer); // stop timer
this.interval_array.splice(i, 1); // remove element/object from array
timers_killed++;
}
}
return timers_killed;
};
// name = string
// code = function reference (code to be executed)
// timeout = timeout in miliseconds
GUI_control.prototype.timeout_add = function (name, code, timeout) {
var self = this;
var data = {'name': name, 'timer': null, 'timeout': timeout};
// start timer with "cleaning" callback
data.timer = setTimeout(function() {
code(); // execute code
// remove object from array
var index = self.timeout_array.indexOf(data);
if (index > -1) self.timeout_array.splice(index, 1);
}, timeout);
this.timeout_array.push(data); // push to primary timeout array
return data;
};
// name = string
GUI_control.prototype.timeout_remove = function (name) {
for (var i = 0; i < this.timeout_array.length; i++) {
if (this.timeout_array[i].name == name) {
clearTimeout(this.timeout_array[i].timer); // stop timer
this.timeout_array.splice(i, 1); // remove element/object from array
return true;
}
}
return false;
};
// no input paremeters
// return = returns timers killed in last call
GUI_control.prototype.timeout_kill_all = function () {
var timers_killed = 0;
for (var i = 0; i < this.timeout_array.length; i++) {
clearTimeout(this.timeout_array[i].timer); // stop timer
timers_killed++;
}
this.timeout_array = []; // drop objects
return timers_killed;
};
// message = string
GUI_control.prototype.log = function (message) {
var command_log = $('div#log');
@ -234,7 +76,8 @@ GUI_control.prototype.log = function (message) {
// default switch doesn't require callback to be set
GUI_control.prototype.tab_switch_cleanup = function (callback) {
MSP.callbacks_cleanup(); // we don't care about any old data that might or might not arrive
GUI.interval_kill_all(); // all intervals (mostly data pulling) needs to be removed on tab switch
helper.interval.killAll(['global_data_refresh']);
if (this.active_tab) {
TABS[this.active_tab].cleanup(callback);

@ -0,0 +1,137 @@
'use strict';
var helper = helper || {};
helper.interval = (function () {
var privateScope = {},
publicScope = {};
privateScope.intervals = [];
/**
*
* @param {String} name
* @param {Function} code function reference (code to be executed)
* @param {int} interval time interval in milliseconds
* @param {boolean=} first true/false if code should be ran initially before next timer interval hits
* @returns {{name: *, timer: null, code: *, interval: *, fired: number, paused: boolean}}
*/
publicScope.add = function (name, code, interval, first) {
/*
* Kill existing interval with this name if exists
*/
publicScope.remove(name);
var data = {
'name': name,
'timer': null,
'code': code,
'interval': interval,
'fired': 0,
'paused': false
};
if (first == true) {
code(); // execute code
data.fired++; // increment counter
}
data.timer = setInterval(function() {
code();
data.fired++;
}, interval);
privateScope.intervals.push(data);
return data;
};
/**
* Method removes and stop execution of interval callback
* @param {string} name
* @returns {boolean}
*/
publicScope.remove = function (name) {
for (var i = 0; i < privateScope.intervals.length; i++) {
if (privateScope.intervals[i].name == name) {
clearInterval(privateScope.intervals[i].timer); // stop timer
privateScope.intervals.splice(i, 1);
return true;
}
}
return false;
};
/**
*
* @param {string} name
* @returns {boolean}
*/
publicScope.pause = function (name) {
for (var i = 0; i < privateScope.intervals.length; i++) {
if (privateScope.intervals[i].name == name) {
clearInterval(privateScope.intervals[i].timer);
privateScope.intervals[i].paused = true;
return true;
}
}
return false;
};
/**
*
* @param {string} name
* @returns {boolean}
*/
publicScope.resume = function (name) {
for (var i = 0; i < privateScope.intervals.length; i++) {
if (privateScope.intervals[i].name == name && privateScope.intervals[i].paused) {
var obj = privateScope.intervals[i];
obj.timer = setInterval(function() {
obj.code(); // execute code
obj.fired++; // increment counter
}, obj.interval);
obj.paused = false;
return true;
}
}
return false;
};
/**
*
* @param {=} keep_array
* @returns {number}
*/
publicScope.killAll = function (keep_array) {
var timers_killed = 0;
for (var i = (privateScope.intervals.length - 1); i >= 0; i--) { // reverse iteration
var keep = false;
if (keep_array) { // only run through the array if it exists
keep_array.forEach(function (name) {
if (privateScope.intervals[i].name == name) {
keep = true;
}
});
}
if (!keep) {
clearInterval(privateScope.intervals[i].timer); // stop timer
privateScope.intervals.splice(i, 1); // remove element/object from array
timers_killed++;
}
}
return timers_killed;
};
return publicScope;
})();

@ -114,6 +114,11 @@ var MSP = {
bufView,
i;
/*
* For debug reasons, check how ofter MSP frames are executed
*/
helper.eventFrequencyAnalyzer.put(code);
// always reserve 6 bytes for protocol overhead !
if (data) {
var size = data.length + 6,
@ -172,7 +177,7 @@ var MSP = {
console.log('MSP data request timed-out: ' + code);
serial.send(bufferOut, false);
}, 1000); // we should be able to define timeout in the future
}, serial.getTimeout()); // we should be able to define timeout in the future
}
MSP.callbacks.push(obj);

@ -61,7 +61,7 @@ var MSPCodes = {
MSP_SET_SENSOR_CONFIG: 97,
// Multiwii MSP commands
MSP_IDENT: 100,
MSP_IDENT: 100, //deprecated, do not use
MSP_STATUS: 101,
MSP_RAW_IMU: 102,
MSP_SERVO: 103,

@ -45,6 +45,7 @@ var mspHelper = (function (gui) {
if (!dataHandler.unsupported) switch (dataHandler.code) {
case MSPCodes.MSP_IDENT:
//FIXME remove this frame when proven not needed
console.log('Using deprecated msp command: MSP_IDENT');
// Deprecated
CONFIG.version = parseFloat((data.getUint8(0) / 100).toFixed(2));
@ -53,6 +54,7 @@ var mspHelper = (function (gui) {
CONFIG.capability = data.getUint32(3, true);
break;
case MSPCodes.MSP_STATUS:
console.log('Using deprecated msp command: MSP_STATUS');
CONFIG.cycleTime = data.getUint16(0, true);
CONFIG.i2cError = data.getUint16(2, true);
CONFIG.activeSensors = data.getUint16(4, true);
@ -86,6 +88,7 @@ var mspHelper = (function (gui) {
sensor_status(CONFIG.activeSensors);
}
gui.updateStatusBar();
gui.updateProfileChange();
break;
case MSPCodes.MSP_SENSOR_STATUS:
@ -574,14 +577,12 @@ var mspHelper = (function (gui) {
offset++;
FAILSAFE_CONFIG.failsafe_throttle = data.getUint16(offset, true);
offset += 2;
if (semver.gte(CONFIG.apiVersion, "1.15.0")) {
FAILSAFE_CONFIG.failsafe_kill_switch = data.getUint8(offset);
offset++;
FAILSAFE_CONFIG.failsafe_throttle_low_delay = data.getUint16(offset, true);
offset += 2;
FAILSAFE_CONFIG.failsafe_procedure = data.getUint8(offset);
offset++;
}
FAILSAFE_CONFIG.failsafe_kill_switch = data.getUint8(offset);
offset++;
FAILSAFE_CONFIG.failsafe_throttle_low_delay = data.getUint16(offset, true);
offset += 2;
FAILSAFE_CONFIG.failsafe_procedure = data.getUint8(offset);
offset++;
break;
case MSPCodes.MSP_RXFAIL_CONFIG:
@ -842,6 +843,11 @@ var mspHelper = (function (gui) {
PID_ADVANCED.rollPitchItermIgnoreRate = data.getUint16(0, true);
PID_ADVANCED.yawItermIgnoreRate = data.getUint16(2, true);
PID_ADVANCED.yawPLimit = data.getUint16(4, true);
if (semver.gte(CONFIG.flightControllerVersion, "1.6.0")) {
PID_ADVANCED.dtermSetpointWeight = data.getUint8(9);
}
PID_ADVANCED.axisAccelerationLimitRollPitch = data.getUint16(13, true);
PID_ADVANCED.axisAccelerationLimitYaw = data.getUint16(15, true);
break;
@ -995,10 +1001,7 @@ var mspHelper = (function (gui) {
case MSPCodes.MSP_SET_RC_TUNING:
buffer.push(Math.round(RC_tuning.RC_RATE * 100));
buffer.push(Math.round(RC_tuning.RC_EXPO * 100));
if (semver.lt(CONFIG.apiVersion, "1.7.0")) {
buffer.push(Math.round(RC_tuning.roll_pitch_rate * 100));
buffer.push(Math.round(RC_tuning.yaw_rate * 100));
} else if (FC.isRatesInDps()) {
if (FC.isRatesInDps()) {
buffer.push(Math.round(RC_tuning.roll_rate / 10));
buffer.push(Math.round(RC_tuning.pitch_rate / 10));
buffer.push(Math.round(RC_tuning.yaw_rate / 10));
@ -1011,13 +1014,9 @@ var mspHelper = (function (gui) {
buffer.push(RC_tuning.dynamic_THR_PID);
buffer.push(Math.round(RC_tuning.throttle_MID * 100));
buffer.push(Math.round(RC_tuning.throttle_EXPO * 100));
if (semver.gte(CONFIG.apiVersion, "1.7.0")) {
buffer.push(lowByte(RC_tuning.dynamic_THR_breakpoint));
buffer.push(highByte(RC_tuning.dynamic_THR_breakpoint));
}
if (semver.gte(CONFIG.apiVersion, "1.10.0")) {
buffer.push(Math.round(RC_tuning.RC_YAW_EXPO * 100));
}
buffer.push(lowByte(RC_tuning.dynamic_THR_breakpoint));
buffer.push(highByte(RC_tuning.dynamic_THR_breakpoint));
buffer.push(Math.round(RC_tuning.RC_YAW_EXPO * 100));
break;
case MSPCodes.MSP_SET_RX_MAP:
@ -1095,12 +1094,10 @@ var mspHelper = (function (gui) {
buffer.push(FAILSAFE_CONFIG.failsafe_off_delay);
buffer.push(lowByte(FAILSAFE_CONFIG.failsafe_throttle));
buffer.push(highByte(FAILSAFE_CONFIG.failsafe_throttle));
if (semver.gte(CONFIG.apiVersion, "1.15.0")) {
buffer.push(FAILSAFE_CONFIG.failsafe_kill_switch);
buffer.push(lowByte(FAILSAFE_CONFIG.failsafe_throttle_low_delay));
buffer.push(highByte(FAILSAFE_CONFIG.failsafe_throttle_low_delay));
buffer.push(FAILSAFE_CONFIG.failsafe_procedure);
}
buffer.push(FAILSAFE_CONFIG.failsafe_kill_switch);
buffer.push(lowByte(FAILSAFE_CONFIG.failsafe_throttle_low_delay));
buffer.push(highByte(FAILSAFE_CONFIG.failsafe_throttle_low_delay));
buffer.push(FAILSAFE_CONFIG.failsafe_procedure);
break;
case MSPCodes.MSP_SET_TRANSPONDER_CONFIG:
@ -1262,7 +1259,13 @@ var mspHelper = (function (gui) {
buffer.push(0); //BF: currentProfile->pidProfile.deltaMethod
buffer.push(0); //BF: currentProfile->pidProfile.vbatPidCompensation
buffer.push(0); //BF: currentProfile->pidProfile.setpointRelaxRatio
buffer.push(0); //BF: currentProfile->pidProfile.dtermSetpointWeight
if (semver.gte(CONFIG.flightControllerVersion, "1.6.0")) {
buffer.push(PID_ADVANCED.dtermSetpointWeight);
} else {
buffer.push(0);
}
buffer.push(0); // reserved
buffer.push(0); // reserved
buffer.push(0); //BF: currentProfile->pidProfile.itermThrottleGain
@ -1718,6 +1721,11 @@ var mspHelper = (function (gui) {
/*
* Basic sending methods used for chaining purposes
*/
/**
* @deprecated
* @param callback
*/
self.loadMspIdent = function (callback) {
MSP.send_message(MSPCodes.MSP_IDENT, false, false, callback);
};
@ -1810,14 +1818,18 @@ var mspHelper = (function (gui) {
}
};
self.loadRcDeadband = function (callback) {
if (semver.gte(CONFIG.apiVersion, "1.15.0")) {
MSP.send_message(MSPCodes.MSP_RC_DEADBAND, false, false, callback);
self.loadSensorStatus = function (callback) {
if (semver.gte(CONFIG.flightControllerVersion, "1.5.0")) {
MSP.send_message(MSPCodes.MSP_SENSOR_STATUS, false, false, callback);
} else {
callback();
}
};
self.loadRcDeadband = function (callback) {
MSP.send_message(MSPCodes.MSP_RC_DEADBAND, false, false, callback);
};
self.loadRcMap = function (callback) {
MSP.send_message(MSPCodes.MSP_RX_MAP, false, false, callback);
};
@ -1830,6 +1842,10 @@ var mspHelper = (function (gui) {
MSP.send_message(MSPCodes.MSP_ACC_TRIM, false, false, callback);
};
self.loadAnalog = function (callback) {
MSP.send_message(MSPCodes.MSP_ANALOG, false, false, callback);
};
self.saveToEeprom = function saveToEeprom(callback) {
MSP.send_message(MSPCodes.MSP_EEPROM_WRITE, false, false, callback);
};

@ -0,0 +1,128 @@
'use strict';
var helper = helper || {};
helper.periodicStatusUpdater = (function () {
var publicScope = {},
privateScope = {};
/**
*
* @param {number=} baudSpeed
* @returns {number}
*/
publicScope.getUpdateInterval = function (baudSpeed) {
if (!baudSpeed) {
baudSpeed = 115200;
}
if (baudSpeed >= 115200) {
return 200;
} else if (baudSpeed >= 57600) {
return 400;
} else if (baudSpeed >= 38400) {
return 500;
} else if (baudSpeed >= 19200) {
return 600;
} else if (baudSpeed >= 9600) {
return 750;
} else {
return 1000;
}
};
privateScope.updateView = function () {
var active = ((Date.now() - MSP.analog_last_received_timestamp) < publicScope.getUpdateInterval(serial.bitrate) * 3);
for (var i = 0; i < AUX_CONFIG.length; i++) {
if (AUX_CONFIG[i] == 'ARM') {
if (bit_check(CONFIG.mode, i))
$(".armedicon").css({
'background-image': 'url(images/icons/cf_icon_armed_active.svg)'
});
else
$(".armedicon").css({
'background-image': 'url(images/icons/cf_icon_armed_grey.svg)'
});
}
if (AUX_CONFIG[i] == 'FAILSAFE') {
if (bit_check(CONFIG.mode, i))
$(".failsafeicon").css({
'background-image': 'url(images/icons/cf_icon_failsafe_active.svg)'
});
else
$(".failsafeicon").css({
'background-image': 'url(images/icons/cf_icon_failsafe_grey.svg)'
});
}
}
if (ANALOG != undefined) {
var nbCells = Math.floor(ANALOG.voltage / MISC.vbatmaxcellvoltage) + 1;
if (ANALOG.voltage == 0)
nbCells = 1;
var min = MISC.vbatmincellvoltage * nbCells;
var max = MISC.vbatmaxcellvoltage * nbCells;
var warn = MISC.vbatwarningcellvoltage * nbCells;
$(".battery-status").css({
width: ((ANALOG.voltage - min) / (max - min) * 100) + "%",
display: 'inline-block'
});
if (active) {
$(".linkicon").css({
'background-image': 'url(images/icons/cf_icon_link_active.svg)'
});
} else {
$(".linkicon").css({
'background-image': 'url(images/icons/cf_icon_link_grey.svg)'
});
}
if (ANALOG.voltage < warn) {
$(".battery-status").css('background-color', '#D42133');
} else {
$(".battery-status").css('background-color', '#59AA29');
}
$(".battery-legend").text(ANALOG.voltage + " V");
}
$('#quad-status_wrapper').show();
};
publicScope.run = function () {
if (!CONFIGURATOR.connectionValid) {
return;
}
$(".quad-status-contents").css({
display: 'inline-block'
});
if (GUI.active_tab != 'cli') {
if (semver.gte(CONFIG.flightControllerVersion, "1.5.0")) {
MSP.send_message(MSPCodes.MSP_SENSOR_STATUS, false, false);
}
if (semver.gte(CONFIG.flightControllerVersion, "1.2.0")) {
MSP.send_message(MSPCodes.MSP_STATUS_EX, false, false);
} else {
MSP.send_message(MSPCodes.MSP_STATUS, false, false);
}
MSP.send_message(MSPCodes.MSP_ANALOG, false, false);
privateScope.updateView();
}
};
return publicScope;
})();

@ -112,7 +112,7 @@ PortHandler.check = function () {
if (GUI.auto_connect && !GUI.connecting_to && !GUI.connected_to) {
// we need firmware flasher protection over here
if (GUI.active_tab != 'firmware_flasher') {
GUI.timeout_add('auto-connect_timeout', function () {
helper.timeout.add('auto-connect_timeout', function () {
$('div#port-picker a.connect').click();
}, 100); // timeout so bus have time to initialize after being detected by the system
}

@ -154,7 +154,7 @@ STM32_protocol.prototype.initialize = function () {
self.read(info);
});
GUI.interval_add('STM32_timeout', function () {
helper.interval.add('STM32_timeout', function () {
if (self.upload_process_alive) { // process is running
self.upload_process_alive = false;
} else {
@ -166,7 +166,7 @@ STM32_protocol.prototype.initialize = function () {
googleAnalytics.sendEvent('Flashing', 'Programming', 'timeout');
// protocol got stuck, clear timer and disconnect
GUI.interval_remove('STM32_timeout');
helper.interval.remove('STM32_timeout');
// exit
self.upload_procedure(99);
@ -361,10 +361,10 @@ STM32_protocol.prototype.upload_procedure = function (step) {
$('span.progressLabel').text('Contacting bootloader ...');
var send_counter = 0;
GUI.interval_add('stm32_initialize_mcu', function () { // 200 ms interval (just in case mcu was already initialized), we need to break the 2 bytes command requirement
helper.interval.add('stm32_initialize_mcu', function () { // 200 ms interval (just in case mcu was already initialized), we need to break the 2 bytes command requirement
self.send([0x7F], 1, function (reply) {
if (reply[0] == 0x7F || reply[0] == self.status.ACK || reply[0] == self.status.NACK) {
GUI.interval_remove('stm32_initialize_mcu');
helper.interval.remove('stm32_initialize_mcu');
console.log('STM32 - Serial interface initialized on the MCU side');
// proceed to next step
@ -373,7 +373,7 @@ STM32_protocol.prototype.upload_procedure = function (step) {
$('span.progressLabel').text('Communication with bootloader failed');
self.progress_bar_e.addClass('invalid');
GUI.interval_remove('stm32_initialize_mcu');
helper.interval.remove('stm32_initialize_mcu');
// disconnect
self.upload_procedure(99);
@ -387,8 +387,8 @@ STM32_protocol.prototype.upload_procedure = function (step) {
$('span.progressLabel').text('No response from the bootloader, programming: FAILED');
self.progress_bar_e.addClass('invalid');
GUI.interval_remove('stm32_initialize_mcu');
GUI.interval_remove('STM32_timeout');
helper.interval.remove('stm32_initialize_mcu');
helper.interval.remove('STM32_timeout');
// exit
self.upload_procedure(99);
@ -749,7 +749,7 @@ STM32_protocol.prototype.upload_procedure = function (step) {
break;
case 99:
// disconnect
GUI.interval_remove('STM32_timeout'); // stop STM32 timeout timer (everything is finished now)
helper.interval.remove('STM32_timeout'); // stop STM32 timeout timer (everything is finished now)
// close connection
serial.disconnect(function (result) {

@ -292,6 +292,18 @@ var serial = {
emptyOutputBuffer: function () {
this.outputBuffer = [];
this.transmitting = false;
},
/**
* Default timeout value for serial messages
* @returns {number} [ms]
*/
getTimeout: function () {
if (serial.bitrate >= 57600) {
return 1000;
} else {
return 2000;
}
}
};

@ -35,8 +35,8 @@ $(document).ready(function () {
}, 5000);
} else {
GUI.timeout_add('waiting_for_bootup', function waiting_for_bootup() {
MSP.send_message(MSPCodes.MSP_IDENT, false, false, function () {
helper.timeout.add('waiting_for_bootup', function waiting_for_bootup() {
MSP.send_message(MSPCodes.MSP_STATUS, false, false, function () {
//noinspection JSUnresolvedVariable
GUI.log(chrome.i18n.getMessage('deviceReady'));
//noinspection JSValidateTypes
@ -98,15 +98,15 @@ $(document).ready(function () {
serial.connect(selected_port, {bitrate: selected_baud}, onOpen);
} else {
GUI.timeout_kill_all();
GUI.interval_kill_all();
var wasConnected = CONFIGURATOR.connectionValid;
helper.timeout.killAll(['global_data_refresh']);
helper.interval.killAll(['global_data_refresh']);
GUI.tab_switch_cleanup();
GUI.tab_switch_in_progress = false;
serial.disconnect(onClosed);
var wasConnected = CONFIGURATOR.connectionValid;
GUI.connected_to = false;
CONFIGURATOR.connectionValid = false;
GUI.allowedTabs = GUI.defaultAllowedTabsWhenDisconnected.slice();
@ -213,7 +213,7 @@ function onOpen(openInfo) {
serial.onReceive.addListener(read_serial);
// disconnect after 10 seconds with error if we don't get IDENT data
GUI.timeout_add('connecting', function () {
helper.timeout.add('connecting', function () {
if (!CONFIGURATOR.connectionValid) {
GUI.log(chrome.i18n.getMessage('noConfigurationReceived'));
@ -307,25 +307,24 @@ function onOpen(openInfo) {
}
function onConnect() {
GUI.timeout_remove('connecting'); // kill connecting timer
helper.timeout.remove('connecting'); // kill connecting timer
$('div#connectbutton a.connect_state').text(chrome.i18n.getMessage('disconnect')).addClass('active');
$('div#connectbutton a.connect').addClass('active');
$('#tabs ul.mode-disconnected').hide();
$('#tabs ul.mode-connected').show();
if (semver.gte(CONFIG.flightControllerVersion, "1.2.0")) {
MSP.send_message(MSPCodes.MSP_STATUS_EX, false, false);
} else {
MSP.send_message(MSPCodes.MSP_STATUS, false, false);
}
MSP.send_message(MSPCodes.MSP_DATAFLASH_SUMMARY, false, false);
$('#sensor-status').show();
$('#portsinput').hide();
$('#dataflash_wrapper_global').show();
startLiveDataRefreshTimer();
/*
* Get BOXNAMES since it is used for some reason....
*/
MSP.send_message(MSPCodes.MSP_BOXNAMES, false, false);
helper.interval.add('global_data_refresh', helper.periodicStatusUpdater.run, helper.periodicStatusUpdater.getUpdateInterval(serial.bitrate), false);
}
function onClosed(result) {
@ -459,116 +458,32 @@ function lowByte(num) {
}
function update_dataflash_global() {
var supportsDataflash = DATAFLASH.totalSize > 0;
if (supportsDataflash){
$(".noflash_global").css({
display: 'none'
});
$(".dataflash-contents_global").css({
display: 'block'
});
$(".dataflash-free_global").css({
width: (100-(DATAFLASH.totalSize - DATAFLASH.usedSize) / DATAFLASH.totalSize * 100) + "%",
display: 'block'
});
$(".dataflash-free_global div").text('Dataflash: free ' + formatFilesize(DATAFLASH.totalSize - DATAFLASH.usedSize));
} else {
$(".noflash_global").css({
display: 'block'
});
$(".dataflash-contents_global").css({
display: 'none'
});
}
}
function startLiveDataRefreshTimer() {
// live data refresh
GUI.timeout_add('data_refresh', function () { update_live_status(); }, 100);
}
function update_live_status() {
var supportsDataflash = DATAFLASH.totalSize > 0;
if (supportsDataflash) {
var statuswrapper = $('#quad-status_wrapper');
$(".noflash_global").css({
display: 'none'
});
$(".quad-status-contents").css({
display: 'inline-block'
});
$(".dataflash-contents_global").css({
display: 'block'
});
if (GUI.active_tab != 'cli') {
MSP.send_message(MSPCodes.MSP_BOXNAMES, false, false);
if (semver.gte(CONFIG.flightControllerVersion, "1.2.0"))
MSP.send_message(MSPCodes.MSP_STATUS_EX, false, false);
else
MSP.send_message(MSPCodes.MSP_STATUS, false, false);
MSP.send_message(MSPCodes.MSP_ANALOG, false, false);
}
$(".dataflash-free_global").css({
width: (100 - (DATAFLASH.totalSize - DATAFLASH.usedSize) / DATAFLASH.totalSize * 100) + "%",
display: 'block'
});
$(".dataflash-free_global div").text('Dataflash: free ' + formatFilesize(DATAFLASH.totalSize - DATAFLASH.usedSize));
} else {
$(".noflash_global").css({
display: 'block'
});
var active = ((Date.now() - MSP.analog_last_received_timestamp) < 300);
for (var i = 0; i < AUX_CONFIG.length; i++) {
if (AUX_CONFIG[i] == 'ARM') {
if (bit_check(CONFIG.mode, i))
$(".armedicon").css({
'background-image': 'url(images/icons/cf_icon_armed_active.svg)'
});
else
$(".armedicon").css({
'background-image': 'url(images/icons/cf_icon_armed_grey.svg)'
});
}
if (AUX_CONFIG[i] == 'FAILSAFE') {
if (bit_check(CONFIG.mode, i))
$(".failsafeicon").css({
'background-image': 'url(images/icons/cf_icon_failsafe_active.svg)'
});
else
$(".failsafeicon").css({
'background-image': 'url(images/icons/cf_icon_failsafe_grey.svg)'
});
}
}
if (ANALOG != undefined) {
var nbCells = Math.floor(ANALOG.voltage / MISC.vbatmaxcellvoltage) + 1;
if (ANALOG.voltage == 0)
nbCells = 1;
var min = MISC.vbatmincellvoltage * nbCells;
var max = MISC.vbatmaxcellvoltage * nbCells;
var warn = MISC.vbatwarningcellvoltage * nbCells;
$(".battery-status").css({
width: ((ANALOG.voltage - min) / (max - min) * 100) + "%",
display: 'inline-block'
});
if (active) {
$(".linkicon").css({
'background-image': 'url(images/icons/cf_icon_link_active.svg)'
});
} else {
$(".linkicon").css({
'background-image': 'url(images/icons/cf_icon_link_grey.svg)'
});
}
if (ANALOG.voltage < warn) {
$(".battery-status").css('background-color', '#D42133');
} else {
$(".battery-status").css('background-color', '#59AA29');
}
$(".battery-legend").text(ANALOG.voltage + " V");
$(".dataflash-contents_global").css({
display: 'none'
});
}
statuswrapper.show();
GUI.timeout_remove('data_refresh');
startLiveDataRefreshTimer();
}
function specificByte(num, pos) {

@ -0,0 +1,27 @@
'use strict';
var helper = helper || {};
helper.task = (function () {
var publicScope = {},
privateScope = {};
privateScope.getStatusPullInterval = function () {
//TODO use serial connection speed to determine update interval
return 250;
};
publicScope.statusPullStart = function () {
helper.interval.add('status_pull', function () {
MSP.send_message(MSPCodes.MSP_STATUS, false, false, function () {
if (semver.gte(CONFIG.flightControllerVersion, "1.5.0")) {
MSP.send_message(MSPCodes.MSP_SENSOR_STATUS);
}
});
}, privateScope.getStatusPullInterval(), true);
};
return publicScope;
})();

@ -0,0 +1,66 @@
'use strict';
var helper = helper || {};
helper.timeout = (function () {
var privateScope = {},
publicScope = {};
privateScope.timeouts = [];
/**
*
* @param {string} name
* @param {function } code
* @param {number} timeout
* @returns {{name: *, timer: null, timeout: *}}
*/
publicScope.add = function (name, code, timeout) {
var data = {'name': name, 'timer': null, 'timeout': timeout};
// start timer with "cleaning" callback
data.timer = setTimeout(function() {
code(); // execute code
// remove object from array
var index = privateScope.timeouts.indexOf(data);
if (index > -1) privateScope.timeouts.splice(index, 1);
}, timeout);
privateScope.timeouts.push(data); // push to primary timeout array
return data;
};
publicScope.remove = function (name) {
for (var i = 0; i < privateScope.timeouts.length; i++) {
if (privateScope.timeouts[i].name == name) {
clearTimeout(privateScope.timeouts[i].timer); // stop timer
privateScope.timeouts.splice(i, 1); // remove element/object from array
return true;
}
}
return false;
};
/**
*
* @returns {number} number of killed timeouts
*/
publicScope.killAll = function () {
var timers_killed = 0;
for (var i = 0; i < privateScope.timeouts.length; i++) {
clearTimeout(privateScope.timeouts[i].timer); // stop timer
timers_killed++;
}
privateScope.timeouts = []; // drop objects
return timers_killed;
};
return publicScope;
})();

@ -51,6 +51,8 @@
<script type="text/javascript" src="./js/libraries/inflection.min.js"></script>
<script type="text/javascript" src="./js/libraries/bluebird.min.js"></script>
<script type="text/javascript" src="./js/injected_methods.js"></script>
<script type="text/javascript" src="./js/intervals.js"></script>
<script type="text/javascript" src="./js/timeouts.js"></script>
<script type="text/javascript" src="./js/gui.js"></script>
<script type="text/javascript" src="./js/msp/MSPCodes.js"></script>
<script type="text/javascript" src="./js/msp/MSPHelper.js"></script>
@ -63,11 +65,11 @@
<script type="text/javascript" src="./js/data_storage.js"></script>
<script type="text/javascript" src="./js/fc.js"></script>
<script type="text/javascript" src="./js/msp.js"></script>
<script type="text/javascript" src="./js/backup_restore.js"></script>
<script type="text/javascript" src="./js/protocols/stm32.js"></script>
<script type="text/javascript" src="./js/protocols/stm32usbdfu.js"></script>
<script type="text/javascript" src="./js/localization.js"></script>
<script type="text/javascript" src="./js/boards.js"></script>
<script type="text/javascript" src="./js/tasks.js"></script>
<script type="text/javascript" src="./main.js"></script>
<script type="text/javascript" src="./tabs/landing.js"></script>
<script type="text/javascript" src="./tabs/setup.js"></script>
@ -92,6 +94,8 @@
<script type="text/javascript" src="./tabs/osd.js"></script>
<script type="text/javascript" src="./tabs/profiles.js"></script>
<script type="text/javascript" src="./tabs/advanced_tuning.js"></script>
<script type="text/javascript" src="./js/eventFrequencyAnalyzer.js"></script>
<script type="text/javascript" src="./js/periodicStatusUpdater.js"></script>
<title></title>
</head>
<body>

@ -1,7 +1,7 @@
{
"manifest_version": 2,
"minimum_chrome_version": "38",
"version": "1.5.2",
"version": "1.6.0",
"author": "Several",
"name": "INAV - Configurator",
"short_name": "INAV",

@ -1,7 +1,7 @@
{
"name": "inav-configurator",
"description": "INAV Configurator",
"version": "1.5.0",
"version": "1.6.0",
"main": "main.html",
"default_locale": "en",
"scripts": {

@ -269,16 +269,7 @@ TABS.adjustments.initialize = function (callback) {
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);
if (semver.gte(CONFIG.flightControllerVersion, "1.5.0")) {
MSP.send_message(MSPCodes.MSP_SENSOR_STATUS);
}
}, 250, true);
helper.interval.add('aux_data_pull', get_rc_data, 50);
GUI.content_ready(callback);
}

@ -288,16 +288,7 @@ TABS.auxiliary.initialize = function (callback) {
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);
if (semver.gte(CONFIG.flightControllerVersion, "1.5.0")) {
MSP.send_message(MSPCodes.MSP_SENSOR_STATUS);
}
}, 250, true);
helper.interval.add('aux_data_pull', get_rc_data, 50);
GUI.content_ready(callback);
}

@ -55,7 +55,7 @@ TABS.cli.initialize = function (callback) {
// give input element user focus
textarea.focus();
GUI.timeout_add('enter_cli', function enter_cli() {
helper.timeout.add('enter_cli', function enter_cli() {
// Enter CLI mode
var bufferOut = new ArrayBuffer(1);
var bufView = new Uint8Array(bufferOut);
@ -88,7 +88,7 @@ TABS.cli.history.next = function () {
};
TABS.cli.sendSlowly = function (out_arr, i, timeout_needle) {
GUI.timeout_add('CLI_send_slowly', function () {
helper.timeout.add('CLI_send_slowly', function () {
var bufferOut = new ArrayBuffer(out_arr[i].length + 1);
var bufView = new Uint8Array(bufferOut);
@ -202,7 +202,7 @@ TABS.cli.cleanup = function (callback) {
// (another approach is however much more complicated):
// we can setup an interval asking for data lets say every 200ms, when data arrives, callback will be triggered and tab switched
// we could probably implement this someday
GUI.timeout_add('waiting_for_bootup', function waiting_for_bootup() {
helper.timeout.add('waiting_for_bootup', function waiting_for_bootup() {
if (callback) callback();
}, 1000); // if we dont allow enough time to reboot, CRC of "first" command sent will fail, keep an eye for this one
CONFIGURATOR.cliActive = false;

@ -13,7 +13,6 @@ TABS.configuration.initialize = function (callback, scrollPosition) {
var loadChainer = new MSPChainerClass();
loadChainer.setChain([
mspHelper.loadMspIdent,
mspHelper.loadBfConfig,
mspHelper.loadMisc,
mspHelper.loadArmingConfig,
@ -23,8 +22,7 @@ TABS.configuration.initialize = function (callback, scrollPosition) {
mspHelper.loadSensorAlignment,
mspHelper.loadAdvancedConfig,
mspHelper.loadINAVPidConfig,
mspHelper.loadSensorConfig,
mspHelper.loadAccTrim
mspHelper.loadSensorConfig
]);
loadChainer.setExitPoint(load_html);
loadChainer.execute();
@ -632,20 +630,10 @@ TABS.configuration.initialize = function (callback, scrollPosition) {
saveChainer.execute();
});
// status data pulled via separate timer with static speed
GUI.interval_add('status_pull', function status_pull() {
MSP.send_message(MSPCodes.MSP_STATUS);
if (semver.gte(CONFIG.flightControllerVersion, "1.5.0")) {
MSP.send_message(MSPCodes.MSP_SENSOR_STATUS);
}
}, 250, true);
GUI.interval_add('config_load_analog', function () {
MSP.send_message(MSPCodes.MSP_ANALOG, false, false, function () {
$('#batteryvoltage').val([ANALOG.voltage.toFixed(1)]);
$('#batterycurrent').val([ANALOG.amperage.toFixed(2)]);
});
}, 250, true); // 4 fps
helper.interval.add('config_load_analog', function () {
$('#batteryvoltage').val([ANALOG.voltage.toFixed(1)]);
$('#batterycurrent').val([ANALOG.amperage.toFixed(2)]);
}, 100, true); // 10 fps
GUI.content_ready(callback);
}
};

@ -4,60 +4,34 @@
<div class="cf_doc_version_bt">
<a id="button-documentation" href="https://github.com/iNavFlight/inav/releases" target="_blank"></a>
</div>
<div class="note newpane">
<div class="note">
<div class="note_spacer">
<p i18n="failsafeFeaturesHelpNew"></p>
</p>
</div>
</div>
<div class="note oldpane">
<div class="note_spacer">
<p i18n="failsafeFeaturesHelpOld"></p>
</p>
<p data-i18n="failsafeFeaturesHelpNew"></p>
</div>
</div>
<div class="leftWrapper">
<div class="gui_box grey oldpane">
<div class="gui_box_titlebar">
<div class="spacer_box_title" i18n="failsafePaneTitleOld"></div>
</div>
<div class="spacer_box">
<div class="checkbox">
<div class="numberspacer" >
<input type="checkbox" name="failsafe_feature" class="feature toggle rxFailsafe" id="failsafe_feature" />
</div>
<label for="failsafe_feature"><span i18n="failsafeFeatureItemOld"></span>
</label>
</div>
<div class="number">
<label> <input type="number" name="failsafe_throttle_old" min="0" max="2000" /> <span
i18n="failsafeThrottleItemOld"></span>
</label>
</div>
</div>
</div>
<div class="gui_box grey newpane">
<div class="gui_box grey">
<div class="gui_box_titlebar">
<div class="spacer_box_title" i18n="failsafePulsrangeTitle"></div>
<div class="helpicon cf_tip" i18n_title="failsafePulsrangeHelp"></div>
<div class="spacer_box_title" data-i18n="failsafePulsrangeTitle"></div>
<div class="helpicon cf_tip" data-i18n_title="failsafePulsrangeHelp"></div>
</div>
<div class="spacer_box">
<div class="number">
<label> <input type="number" name="rx_min_usec" min="750" max="2250" /> <span
i18n="failsafeRxMinUsecItem"></span>
data-i18n="failsafeRxMinUsecItem"></span>
</label>
</div>
<div class="number">
<label> <input type="number" name="rx_max_usec" min="750" max="2250" /> <span
i18n="failsafeRxMaxUsecItem"></span>
data-i18n="failsafeRxMaxUsecItem"></span>
</label>
</div>
</div>
</div>
<div class="gui_box grey stage1 newpane">
<div class="gui_box grey stage1">
<div class="gui_box_titlebar">
<div class="spacer_box_title" i18n="failsafeChannelFallbackSettingsTitle"></div>
<div class="helpicon cf_tip" i18n_title="failsafeChannelFallbackSettingsHelp"></div>
<div class="spacer_box_title" data-i18n="failsafeChannelFallbackSettingsTitle"></div>
<div class="helpicon cf_tip" data-i18n_title="failsafeChannelFallbackSettingsHelp"></div>
</div>
<div class="spacer_box">
<div class="activechannellist">
@ -67,67 +41,67 @@
</div>
</div>
<div class="rightWrapper">
<div class="gui_box grey newpane">
<div class="gui_box grey">
<div class="gui_box_titlebar">
<div class="spacer_box_title" i18n="failsafeStageTwoSettingsTitle"></div>
<div class="spacer_box_title" data-i18n="failsafeStageTwoSettingsTitle"></div>
</div>
<div class="spacer_box">
<div class="checkbox">
<div class="numberspacer" >
<input type="checkbox" name="failsafe_feature_new" class="feature toggle rxFailsafe" id="failsafe_feature_new" />
</div>
<label for="failsafe_feature_new"><span i18n="failsafeFeatureItem"></span>
<label for="failsafe_feature_new"><span data-i18n="failsafeFeatureItem"></span>
</label>
<div class="helpicon cf_tip" i18n_title="failsafeFeatureHelp"></div>
<div class="helpicon cf_tip" data-i18n_title="failsafeFeatureHelp"></div>
</div>
<div class="checkbox stage2">
<div class="numberspacer" >
<input type="checkbox" name="failsafe_kill_switch" class="toggle" id="failsafe_kill_switch" />
</div>
<label for="failsafe_kill_switch"><span i18n="failsafeKillSwitchItem"></span>
<label for="failsafe_kill_switch"><span data-i18n="failsafeKillSwitchItem"></span>
</label>
<div class="helpicon cf_tip" i18n_title="failsafeKillSwitchHelp"></div>
<div class="helpicon cf_tip" data-i18n_title="failsafeKillSwitchHelp"></div>
</div>
<div class="number stage2">
<label> <input type="number" name="failsafe_delay" min="0" max="2000" /> <span
i18n="failsafeDelayItem"></span>
data-i18n="failsafeDelayItem"></span>
</label>
<div class="helpicon cf_tip" i18n_title="failsafeDelayHelp"></div>
<div class="helpicon cf_tip" data-i18n_title="failsafeDelayHelp"></div>
</div>
<div class="number stage2">
<label> <input type="number" name="failsafe_throttle_low_delay" min="0" max="2000" /> <span
i18n="failsafeThrottleLowItem"></span>
data-i18n="failsafeThrottleLowItem"></span>
</label>
<div class="helpicon cf_tip" i18n_title="failsafeThrottleLowHelp"></div>
<div class="helpicon cf_tip" data-i18n_title="failsafeThrottleLowHelp"></div>
</div>
<!-- radio buttons -->
<div class="subline stage2" i18n="failsafeSubTitle1"></div>
<div class="subline stage2" data-i18n="failsafeSubTitle1"></div>
<div class="radioarea pro1 stage2">
<div class="radiobuttons"><input class="procedure" id="drop" name="group1" type="radio"/>
<label for="drop" i18n="failsafeProcedureItemSelect2"></label>
<label for="drop" data-i18n="failsafeProcedureItemSelect2"></label>
</div>
</div>
<div class="radioarea pro2 stage2">
<div class="radiobuttons"><input class="procedure" id="land" name="group1" type="radio" checked/>
<label for="land" i18n="failsafeProcedureItemSelect1"></label>
<label for="land" data-i18n="failsafeProcedureItemSelect1"></label>
</div>
<div class="proceduresettings">
<div class="number">
<label> <input type="number" name="failsafe_throttle" min="0" max="2000" /> <span
i18n="failsafeThrottleItem"></span>
data-i18n="failsafeThrottleItem"></span>
</label>
</div>
<div class="number">
<label> <input type="number" name="failsafe_off_delay" min="0" max="2000" /> <span
i18n="failsafeOffDelayItem"></span>
data-i18n="failsafeOffDelayItem"></span>
</label>
<div class="helpicon cf_tip" i18n_title="failsafeOffDelayHelp"></div>
<div class="helpicon cf_tip" data-i18n_title="failsafeOffDelayHelp"></div>
</div>
</div>
</div>
<div class="radioarea pro4 stage2">
<div class="radiobuttons"><input class="procedure" id="rth" name="group1" type="radio"/>
<label for="rth" i18n="failsafeProcedureItemSelect3"></label>
<label for="rth" data-i18n="failsafeProcedureItemSelect3"></label>
</div>
</div>
</div>
@ -136,7 +110,7 @@
</div>
<div class="content_toolbar">
<div class="btn save_btn">
<a class="save" href="#" i18n="configurationButtonSave"></a>
<a class="save" href="#" data-i18n="configurationButtonSave"></a>
</div>
</div>
</div>

@ -3,7 +3,6 @@
TABS.failsafe = {};
TABS.failsafe.initialize = function (callback, scrollPosition) {
var self = this;
if (GUI.active_tab != 'failsafe') {
GUI.active_tab = 'failsafe';
@ -38,7 +37,6 @@ TABS.failsafe.initialize = function (callback, scrollPosition) {
MSP.send_message(MSPCodes.MSP_RC, false, false, load_config);
}
// BEGIN Support for pre API version 1.15.0
function load_config() {
MSP.send_message(MSPCodes.MSP_BF_CONFIG, false, false, load_misc);
}
@ -46,22 +44,12 @@ TABS.failsafe.initialize = function (callback, scrollPosition) {
function load_misc() {
MSP.send_message(MSPCodes.MSP_MISC, false, false, load_html);
}
// END (Support for pre API version 1.15.0
function load_html() {
$('#content').load("./tabs/failsafe.html", process_html);
}
var apiVersionGte1_15_0 = semver.gte(CONFIG.apiVersion, "1.15.0");
// Uncomment next line for testing older functionality on newer API version
//apiVersionGte1_15_0 = false;
if(apiVersionGte1_15_0) {
MSP.send_message(MSPCodes.MSP_IDENT, false, false, load_rx_config);
} else {
MSP.send_message(MSPCodes.MSP_IDENT, false, false, load_config);
}
load_rx_config();
function process_html() {
var failsafeFeature;
@ -69,62 +57,50 @@ TABS.failsafe.initialize = function (callback, scrollPosition) {
// translate to user-selected language
localize();
// Conditionally hide the old or the new control pane's
if(apiVersionGte1_15_0) {
var oldPane = $('div.oldpane');
oldPane.prop("disabled", true);
oldPane.hide();
} else {
var newPane = $('div.newpane');
newPane.prop("disabled", true);
newPane.hide();
}
if(apiVersionGte1_15_0) {
// generate labels for assigned aux modes
var auxAssignment = [],
i,
element;
for (var channelIndex = 0; channelIndex < RC.active_channels - 4; channelIndex++) {
auxAssignment.push("");
}
// generate labels for assigned aux modes
var auxAssignment = [],
i,
element;
for (var modeIndex = 0; modeIndex < AUX_CONFIG.length; modeIndex++) {
for (var channelIndex = 0; channelIndex < RC.active_channels - 4; channelIndex++) {
auxAssignment.push("");
}
var modeId = AUX_CONFIG_IDS[modeIndex];
for (var modeIndex = 0; modeIndex < AUX_CONFIG.length; modeIndex++) {
// scan mode ranges to find assignments
for (var modeRangeIndex = 0; modeRangeIndex < MODE_RANGES.length; modeRangeIndex++) {
var modeRange = MODE_RANGES[modeRangeIndex];
var modeId = AUX_CONFIG_IDS[modeIndex];
if (modeRange.id != modeId) {
continue;
}
// scan mode ranges to find assignments
for (var modeRangeIndex = 0; modeRangeIndex < MODE_RANGES.length; modeRangeIndex++) {
var modeRange = MODE_RANGES[modeRangeIndex];
var range = modeRange.range;
if (!(range.start < range.end)) {
continue; // invalid!
}
if (modeRange.id != modeId) {
continue;
}
auxAssignment[modeRange.auxChannelIndex] += "<span class=\"modename\">" + AUX_CONFIG[modeIndex] + "</span>";
var range = modeRange.range;
if (!(range.start < range.end)) {
continue; // invalid!
}
auxAssignment[modeRange.auxChannelIndex] += "<span class=\"modename\">" + AUX_CONFIG[modeIndex] + "</span>";
}
}
// generate full channel list
var channelNames = [
chrome.i18n.getMessage('controlAxisRoll'),
chrome.i18n.getMessage('controlAxisPitch'),
chrome.i18n.getMessage('controlAxisYaw'),
chrome.i18n.getMessage('controlAxisThrottle')
],
fullChannels_e = $('div.activechannellist'),
aux_index = 1,
aux_assignment_index = 0;
for (i = 0; i < RXFAIL_CONFIG.length; i++) {
if (i < channelNames.length) {
fullChannels_e.append('\
// generate full channel list
var channelNames = [
chrome.i18n.getMessage('controlAxisRoll'),
chrome.i18n.getMessage('controlAxisPitch'),
chrome.i18n.getMessage('controlAxisYaw'),
chrome.i18n.getMessage('controlAxisThrottle')
],
fullChannels_e = $('div.activechannellist'),
aux_index = 1,
aux_assignment_index = 0;
for (i = 0; i < RXFAIL_CONFIG.length; i++) {
if (i < channelNames.length) {
fullChannels_e.append('\
<div class="number">\
<div class="channelprimary">\
<span>' + channelNames[i] + '</span>\
@ -137,8 +113,8 @@ TABS.failsafe.initialize = function (callback, scrollPosition) {
</div>\
</div>\
');
} else {
fullChannels_e.append('\
} else {
fullChannels_e.append('\
<div class="number">\
<div class="channelauxiliary">\
<span class="channelname">' + chrome.i18n.getMessage("controlAxisAux" + (aux_index++)) + '</span>\
@ -153,169 +129,147 @@ TABS.failsafe.initialize = function (callback, scrollPosition) {
<div class="auxiliary"><input type="number" name="aux_value" min="750" max="2250" id="' + i + '"/></div>\
</div>\
');
}
}
}
var channel_mode_array = [];
$('.number', fullChannels_e).each(function () {
channel_mode_array.push($('select.aux_set' , this));
});
var channel_value_array = [];
$('.number', fullChannels_e).each(function () {
channel_value_array.push($('input[name="aux_value"]' , this));
});
var channelMode = $('select.aux_set');
var channelValue = $('input[name="aux_value"]');
// UI hooks
channelMode.change(function () {
var currentMode = parseInt($(this).val());
var i = parseInt($(this).prop("id"));
RXFAIL_CONFIG[i].mode = currentMode;
if (currentMode == 2) {
channel_value_array[i].prop("disabled", false);
channel_value_array[i].show();
} else {
channel_value_array[i].prop("disabled", true);
channel_value_array[i].hide();
}
});
// UI hooks
channelValue.change(function () {
var i = parseInt($(this).prop("id"));
RXFAIL_CONFIG[i].value = parseInt($(this).val());
});
// for some odd reason chrome 38+ changes scroll according to the touched select element
// i am guessing this is a bug, since this wasn't happening on 37
// code below is a temporary fix, which we will be able to remove in the future (hopefully)
$('#content').scrollTop((scrollPosition) ? scrollPosition : 0);
// fill stage 1 Valid Pulse Range Settings
$('input[name="rx_min_usec"]').val(RX_CONFIG.rx_min_usec);
$('input[name="rx_max_usec"]').val(RX_CONFIG.rx_max_usec);
// fill fallback settings (mode and value) for all channels
for (i = 0; i < RXFAIL_CONFIG.length; i++) {
channel_value_array[i].val(RXFAIL_CONFIG[i].value);
channel_mode_array[i].val(RXFAIL_CONFIG[i].mode);
channel_mode_array[i].change();
}
var channel_mode_array = [];
$('.number', fullChannels_e).each(function () {
channel_mode_array.push($('select.aux_set', this));
});
// fill stage 2 fields
failsafeFeature = $('input[name="failsafe_feature_new"]');
failsafeFeature.change(function () {
if ($(this).is(':checked')) {
$('div.stage2').show();
} else {
$('div.stage2').hide();
}
});
failsafeFeature.prop('checked', bit_check(BF_CONFIG.features, 8));
failsafeFeature.change();
$('input[name="failsafe_throttle"]').val(FAILSAFE_CONFIG.failsafe_throttle);
$('input[name="failsafe_off_delay"]').val(FAILSAFE_CONFIG.failsafe_off_delay);
$('input[name="failsafe_throttle_low_delay"]').val(FAILSAFE_CONFIG.failsafe_throttle_low_delay);
$('input[name="failsafe_delay"]').val(FAILSAFE_CONFIG.failsafe_delay);
// set stage 2 failsafe procedure
$('input[type="radio"].procedure').change(function () {
var element = $(this),
checked = element.is(':checked'),
id = element.attr('id');
switch(id) {
case 'drop':
if (checked) {
$('input[name="failsafe_throttle"]').prop("disabled", true);
$('input[name="failsafe_off_delay"]').prop("disabled", true);
}
break;
case 'land':
if (checked) {
$('input[name="failsafe_throttle"]').prop("disabled", false);
$('input[name="failsafe_off_delay"]').prop("disabled", false);
}
break;
}
});
switch(FAILSAFE_CONFIG.failsafe_procedure) {
default:
case 0:
element = $('input[id="land"]') ;
element.prop('checked', true);
element.change();
break;
case 1:
element = $('input[id="drop"]');
element.prop('checked', true);
element.change();
break;
case 2:
element = $('input[id="rth"]');
element.prop('checked', true);
element.change();
break;
var channel_value_array = [];
$('.number', fullChannels_e).each(function () {
channel_value_array.push($('input[name="aux_value"]', this));
});
var channelMode = $('select.aux_set');
var channelValue = $('input[name="aux_value"]');
// UI hooks
channelMode.change(function () {
var currentMode = parseInt($(this).val());
var i = parseInt($(this).prop("id"));
RXFAIL_CONFIG[i].mode = currentMode;
if (currentMode == 2) {
channel_value_array[i].prop("disabled", false);
channel_value_array[i].show();
} else {
channel_value_array[i].prop("disabled", true);
channel_value_array[i].hide();
}
});
// set stage 2 kill switch option
$('input[name="failsafe_kill_switch"]').prop('checked', FAILSAFE_CONFIG.failsafe_kill_switch);
// UI hooks
channelValue.change(function () {
var i = parseInt($(this).prop("id"));
RXFAIL_CONFIG[i].value = parseInt($(this).val());
});
// for some odd reason chrome 38+ changes scroll according to the touched select element
// i am guessing this is a bug, since this wasn't happening on 37
// code below is a temporary fix, which we will be able to remove in the future (hopefully)
$('#content').scrollTop((scrollPosition) ? scrollPosition : 0);
// fill stage 1 Valid Pulse Range Settings
$('input[name="rx_min_usec"]').val(RX_CONFIG.rx_min_usec);
$('input[name="rx_max_usec"]').val(RX_CONFIG.rx_max_usec);
// fill fallback settings (mode and value) for all channels
for (i = 0; i < RXFAIL_CONFIG.length; i++) {
channel_value_array[i].val(RXFAIL_CONFIG[i].value);
channel_mode_array[i].val(RXFAIL_CONFIG[i].mode);
channel_mode_array[i].change();
}
// fill stage 2 fields
failsafeFeature = $('input[name="failsafe_feature_new"]');
failsafeFeature.change(function () {
if ($(this).is(':checked')) {
$('div.stage2').show();
} else {
$('div.stage2').hide();
}
});
} else {
failsafeFeature.prop('checked', bit_check(BF_CONFIG.features, 8));
failsafeFeature.change();
$('input[name="failsafe_throttle"]').val(FAILSAFE_CONFIG.failsafe_throttle);
$('input[name="failsafe_off_delay"]').val(FAILSAFE_CONFIG.failsafe_off_delay);
$('input[name="failsafe_throttle_low_delay"]').val(FAILSAFE_CONFIG.failsafe_throttle_low_delay);
$('input[name="failsafe_delay"]').val(FAILSAFE_CONFIG.failsafe_delay);
// set stage 2 failsafe procedure
$('input[type="radio"].procedure').change(function () {
var element = $(this),
checked = element.is(':checked'),
id = element.attr('id');
switch (id) {
case 'drop':
if (checked) {
$('input[name="failsafe_throttle"]').prop("disabled", true);
$('input[name="failsafe_off_delay"]').prop("disabled", true);
}
break;
// set FAILSAFE feature option (pre API 1.15.0)
failsafeFeature = $('input[name="failsafe_feature"]');
failsafeFeature.prop('checked', bit_check(BF_CONFIG.features, 8));
case 'land':
if (checked) {
$('input[name="failsafe_throttle"]').prop("disabled", false);
$('input[name="failsafe_off_delay"]').prop("disabled", false);
}
break;
}
});
// fill failsafe_throttle field (pre API 1.15.0)
$('input[name="failsafe_throttle_old"]').val(MISC.failsafe_throttle);
switch (FAILSAFE_CONFIG.failsafe_procedure) {
default:
case 0:
element = $('input[id="land"]');
element.prop('checked', true);
element.change();
break;
case 1:
element = $('input[id="drop"]');
element.prop('checked', true);
element.change();
break;
case 2:
element = $('input[id="rth"]');
element.prop('checked', true);
element.change();
break;
}
// set stage 2 kill switch option
$('input[name="failsafe_kill_switch"]').prop('checked', FAILSAFE_CONFIG.failsafe_kill_switch);
$('a.save').click(function () {
// gather data that doesn't have automatic change event bound
if(apiVersionGte1_15_0) {
RX_CONFIG.rx_min_usec = parseInt($('input[name="rx_min_usec"]').val());
RX_CONFIG.rx_max_usec = parseInt($('input[name="rx_max_usec"]').val());
// get FAILSAFE feature option (>= API 1.15.0)
if ($('input[name="failsafe_feature_new"]').is(':checked')) {
BF_CONFIG.features = bit_set(BF_CONFIG.features, 8);
} else {
BF_CONFIG.features = bit_clear(BF_CONFIG.features, 8);
}
RX_CONFIG.rx_min_usec = parseInt($('input[name="rx_min_usec"]').val());
RX_CONFIG.rx_max_usec = parseInt($('input[name="rx_max_usec"]').val());
FAILSAFE_CONFIG.failsafe_throttle = parseInt($('input[name="failsafe_throttle"]').val());
FAILSAFE_CONFIG.failsafe_off_delay = parseInt($('input[name="failsafe_off_delay"]').val());
FAILSAFE_CONFIG.failsafe_throttle_low_delay = parseInt($('input[name="failsafe_throttle_low_delay"]').val());
FAILSAFE_CONFIG.failsafe_delay = parseInt($('input[name="failsafe_delay"]').val());
if( $('input[id="land"]').is(':checked')) {
FAILSAFE_CONFIG.failsafe_procedure = 0;
} else if( $('input[id="drop"]').is(':checked')) {
FAILSAFE_CONFIG.failsafe_procedure = 1;
} else if( $('input[id="rth"]').is(':checked')) {
FAILSAFE_CONFIG.failsafe_procedure = 2;
}
FAILSAFE_CONFIG.failsafe_kill_switch = $('input[name="failsafe_kill_switch"]').is(':checked') ? 1 : 0;
// get FAILSAFE feature option (>= API 1.15.0)
if ($('input[name="failsafe_feature_new"]').is(':checked')) {
BF_CONFIG.features = bit_set(BF_CONFIG.features, 8);
} else {
// get FAILSAFE feature option (pre API 1.15.0)
if ($('input[name="failsafe_feature"]').is(':checked')) {
BF_CONFIG.features = bit_set(BF_CONFIG.features, 8);
} else {
BF_CONFIG.features = bit_clear(BF_CONFIG.features, 8);
}
BF_CONFIG.features = bit_clear(BF_CONFIG.features, 8);
}
// get failsafe_throttle field value (pre API 1.15.0)
MISC.failsafe_throttle = parseInt($('input[name="failsafe_throttle_old"]').val());
FAILSAFE_CONFIG.failsafe_throttle = parseInt($('input[name="failsafe_throttle"]').val());
FAILSAFE_CONFIG.failsafe_off_delay = parseInt($('input[name="failsafe_off_delay"]').val());
FAILSAFE_CONFIG.failsafe_throttle_low_delay = parseInt($('input[name="failsafe_throttle_low_delay"]').val());
FAILSAFE_CONFIG.failsafe_delay = parseInt($('input[name="failsafe_delay"]').val());
if ($('input[id="land"]').is(':checked')) {
FAILSAFE_CONFIG.failsafe_procedure = 0;
} else if ($('input[id="drop"]').is(':checked')) {
FAILSAFE_CONFIG.failsafe_procedure = 1;
} else if ($('input[id="rth"]').is(':checked')) {
FAILSAFE_CONFIG.failsafe_procedure = 2;
}
FAILSAFE_CONFIG.failsafe_kill_switch = $('input[name="failsafe_kill_switch"]').is(':checked') ? 1 : 0;
function save_failssafe_config() {
MSP.send_message(MSPCodes.MSP_SET_FAILSAFE_CONFIG, mspHelper.crunch(MSPCodes.MSP_SET_FAILSAFE_CONFIG), false, save_rxfail_config);
}
@ -328,12 +282,6 @@ TABS.failsafe.initialize = function (callback, scrollPosition) {
MSP.send_message(MSPCodes.MSP_SET_BF_CONFIG, mspHelper.crunch(MSPCodes.MSP_SET_BF_CONFIG), false, save_to_eeprom);
}
// BEGIN pre API 1.15.0 save functions
function save_misc() {
MSP.send_message(MSPCodes.MSP_SET_MISC, mspHelper.crunch(MSPCodes.MSP_SET_MISC), false, save_to_eeprom);
}
// END pre API 1.15.0 save functions
function save_to_eeprom() {
MSP.send_message(MSPCodes.MSP_EEPROM_WRITE, false, false, reboot);
}
@ -341,7 +289,7 @@ TABS.failsafe.initialize = function (callback, scrollPosition) {
function reboot() {
GUI.log(chrome.i18n.getMessage('configurationEepromSaved'));
GUI.tab_switch_cleanup(function() {
GUI.tab_switch_cleanup(function () {
MSP.send_message(MSPCodes.MSP_SET_REBOOT, false, false, reinitialize);
});
}
@ -351,22 +299,9 @@ TABS.failsafe.initialize = function (callback, scrollPosition) {
GUI.handleReconnect($('.tab_failsafe a'));
}
if(apiVersionGte1_15_0) {
MSP.send_message(MSPCodes.MSP_SET_RX_CONFIG, mspHelper.crunch(MSPCodes.MSP_SET_RX_CONFIG), false, save_failssafe_config);
} else {
MSP.send_message(MSPCodes.MSP_SET_BF_CONFIG, mspHelper.crunch(MSPCodes.MSP_SET_BF_CONFIG), false, save_misc);
}
MSP.send_message(MSPCodes.MSP_SET_RX_CONFIG, mspHelper.crunch(MSPCodes.MSP_SET_RX_CONFIG), false, save_failssafe_config);
});
// status data pulled via separate timer with static speed
GUI.interval_add('status_pull', function status_pull() {
MSP.send_message(MSPCodes.MSP_STATUS);
if (semver.gte(CONFIG.flightControllerVersion, "1.5.0")) {
MSP.send_message(MSPCodes.MSP_SENSOR_STATUS);
}
}, 250, true);
GUI.content_ready(callback);
}
};

@ -513,7 +513,7 @@ TABS.firmware_flasher.initialize = function (callback) {
console.log('Detected: ' + port + ' - triggering flash on connect');
// Trigger regular Flashing sequence
GUI.timeout_add('initialization_timeout', function () {
helper.timeout.add('initialization_timeout', function () {
$('a.flash_firmware').click();
}, 100); // timeout so bus have time to initialize after being detected by the system
} else {

@ -13,7 +13,7 @@ TABS.gps.initialize = function (callback) {
$('#content').load("./tabs/gps.html", process_html);
}
MSP.send_message(MSPCodes.MSP_STATUS, false, false, load_html);
load_html();
function set_online(){
$('#connect').hide();
@ -102,7 +102,7 @@ TABS.gps.initialize = function (callback) {
}
// enable data pulling
GUI.interval_add('gps_pull', function gps_update() {
helper.interval.add('gps_pull', function gps_update() {
// avoid usage of the GPS commands until a GPS sensor is detected for targets that are compiled without GPS support.
if (!have_sensor(CONFIG.activeSensors, 'gps')) {
//return;
@ -111,16 +111,6 @@ TABS.gps.initialize = function (callback) {
get_raw_gps_data();
}, 75, true);
// status data pulled via separate timer with static speed
GUI.interval_add('status_pull', function status_pull() {
MSP.send_message(MSPCodes.MSP_STATUS);
if (semver.gte(CONFIG.flightControllerVersion, "1.5.0")) {
MSP.send_message(MSPCodes.MSP_SENSOR_STATUS);
}
}, 250, true);
//check for internet connection on load
if (navigator.onLine) {
console.log('Online');

@ -65,8 +65,8 @@ TABS.logging.initialize = function (callback) {
}
}
GUI.interval_add('log_data_poll', log_data_poll, parseInt($('select.speed').val()), true); // refresh rate goes here
GUI.interval_add('write_data', function write_data() {
helper.interval.add('log_data_poll', log_data_poll, parseInt($('select.speed').val()), true); // refresh rate goes here
helper.interval.add('write_data', function write_data() {
if (log_buffer.length) { // only execute when there is actual data to write
if (fileWriter.readyState == 0 || fileWriter.readyState == 2) {
append_to_file(log_buffer.join('\n'));
@ -87,7 +87,7 @@ TABS.logging.initialize = function (callback) {
GUI.log(chrome.i18n.getMessage('loggingErrorOneProperty'));
}
} else {
GUI.interval_kill_all();
helper.interval.killAll(['global_data_refresh']);
$('.speed').prop('disabled', false);
$(this).text(chrome.i18n.getMessage('loggingStart'));

@ -142,16 +142,7 @@ TABS.modes.initialize = function (callback) {
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 status_pull() {
MSP.send_message(MSPCodes.MSP_STATUS);
if (semver.gte(CONFIG.flightControllerVersion, "1.5.0")) {
MSP.send_message(MSPCodes.MSP_SENSOR_STATUS);
}
}, 250, true);
helper.interval.add('aux_data_pull', get_rc_data, 50);
GUI.content_ready(callback);
}

@ -19,10 +19,6 @@ TABS.motors.initialize = function (callback) {
googleAnalytics.sendAppView('Motors');
}
function get_arm_status() {
MSP.send_message(MSPCodes.MSP_STATUS, false, false, load_config);
}
function load_config() {
MSP.send_message(MSPCodes.MSP_BF_CONFIG, false, false, load_3d);
}
@ -40,7 +36,7 @@ TABS.motors.initialize = function (callback) {
$('#content').load("./tabs/motors.html", process_html);
}
MSP.send_message(MSPCodes.MSP_MISC, false, false, get_arm_status);
MSP.send_message(MSPCodes.MSP_MISC, false, false, load_config);
function update_arm_status() {
self.armed = bit_check(CONFIG.mode, 0);
@ -182,7 +178,7 @@ TABS.motors.initialize = function (callback) {
$motorsEnableTestMode.prop('checked', false);
$motorsEnableTestMode.prop('disabled', true);
update_model(CONFIG.multiType);
update_model(BF_CONFIG.mixerConfiguration);
// Always start with default/empty sensor data array, clean slate all
initSensorData();
@ -239,9 +235,9 @@ TABS.motors.initialize = function (callback) {
accelHelpers = initGraphHelpers('#accel', samples_accel_i, [-scale, scale]);
// timer initialization
GUI.interval_kill_all(['motor_and_status_pull']);
helper.interval.killAll(['motor_and_status_pull', 'global_data_refresh']);
GUI.interval_add('IMU_pull', function imu_data_pull() {
helper.interval.add('IMU_pull', function imu_data_pull() {
MSP.send_message(MSPCodes.MSP_RAW_IMU, false, false, update_accel_graph);
}, rate, true);
@ -448,23 +444,6 @@ TABS.motors.initialize = function (callback) {
$motorsEnableTestMode.change();
// data pulling functions used inside interval timer
function periodicUpdateHandler() {
MSP.send_message(MSPCodes.MSP_STATUS);
if (semver.gte(CONFIG.flightControllerVersion, "1.5.0")) {
getPeriodicSensorStatus();
} else {
getPeriodicMotorOutput();
}
}
function getPeriodicSensorStatus() {
MSP.send_message(MSPCodes.MSP_SENSOR_STATUS, false, false, getPeriodicMotorOutput);
}
function getPeriodicMotorOutput() {
MSP.send_message(MSPCodes.MSP_MOTOR, false, false, getPeriodicServoOutput);
}
@ -475,7 +454,7 @@ TABS.motors.initialize = function (callback) {
var full_block_scale = MISC.maxthrottle - MISC.mincommand;
function update_ui() {
function update_ui() {
var previousArmState = self.armed;
var block_height = $('div.m-block:first').height();
@ -519,7 +498,7 @@ TABS.motors.initialize = function (callback) {
}
// enable Status and Motor data pulling
GUI.interval_add('motor_and_status_pull', periodicUpdateHandler, 75, true);
helper.interval.add('motor_and_status_pull', getPeriodicMotorOutput, 75, true);
GUI.content_ready(callback);
}

@ -10,7 +10,6 @@ TABS.pid_tuning.initialize = function (callback) {
var loadChainer = new MSPChainerClass();
loadChainer.setChain([
mspHelper.loadStatus,
mspHelper.loadPidNames,
mspHelper.loadPidData,
mspHelper.loadRcTuningData,
@ -289,11 +288,6 @@ TABS.pid_tuning.initialize = function (callback) {
send_pids();
});
// status data pulled via separate timer with static speed
GUI.interval_add('status_pull', function status_pull() {
MSP.send_message(MSPCodes.MSP_STATUS);
}, 250, true);
GUI.content_ready(callback);
}
};

@ -96,12 +96,6 @@ TABS.ports.initialize = function (callback, scrollPosition) {
function update_ui() {
if (semver.lt(CONFIG.apiVersion, "1.6.0")) {
$(".tab-ports").removeClass("supported");
return;
}
$(".tab-ports").addClass("supported");
var portIdentifierToNameMapping = {
@ -221,15 +215,6 @@ TABS.ports.initialize = function (callback, scrollPosition) {
$('a.save').click(on_save_handler);
// status data pulled via separate timer with static speed
GUI.interval_add('status_pull', function status_pull() {
MSP.send_message(MSPCodes.MSP_STATUS);
if (semver.gte(CONFIG.flightControllerVersion, "1.5.0")) {
MSP.send_message(MSPCodes.MSP_SENSOR_STATUS);
}
}, 250, true);
GUI.content_ready(callback);
}

@ -1,27 +1,148 @@
#presets-list option {
.tab-configuration #presets-list option {
padding: 0.4em;
cursor: pointer;
}
.preset__head {
.tab-configuration .preset__head {
color: #37a8db;
margin-top: 15px;
}
.preset__description {
margin-top: 1em;
.tab-configuration .preset__description {
margin-top: 3px;
}
.preset__features {
margin-top: 1em;
.tab-configuration .preset__description span {
margin-top: 5px;
font-family: 'open_sansregular', Arial, serif;
}
.preset__feature {
list-style: disc;
.tab-configuration .preset__features {
margin-top: 0px;
}
.tab-configuration .preset__feature {
list-style: inside disc;
list-style-type: afar;
color: #37a8db;
margin-left: 1.5em;
}
.preset__feature-text {
.tab-configuration .preset__feature-text {
color: #000000;
margin-left: -0.5em;
}
.tab-configuration #preset-image {
width: 120px;
height: 120px;
background-image:url(../images/icons/peset_default.svg);
background-size:contain;
background-repeat:no-repeat;
float: left;
margin-right: 20px;
}
.tab-configuration .clearboth {
width:100%;
clear:both;
}
.tab-configuration .preset__list-wrapper {
background-color: #525252;
background: #525252 -webkit-linear-gradient(top, transparent, rgba(0, 0, 0, 0.35));
min-height: 400px;
border-right: 3px solid #37a8db;
overflow:hidden;
border-top-left-radius: 3px;
border-bottom-left-radius: 3px;
box-shadow: inset -10px 0px 20px rgba(50,50,50, 0.5);
}
.tab-configuration .list-menu ul {
}
.tab-configuration .list-menu li {
border-bottom: 1px solid rgba(0, 0, 0, 0.30);
}
.tab-configuration .list-menu li:last-child {
border-bottom: none;
}
.tab-configuration .list-menu li a {
font-family: 'open_sansregular', Arial, serif;
display:block;
height:30px;
line-height: 30px;
font-size: 13px;
padding-left: 10px;
text-shadow: 0 1px rgba(0, 0, 0, 0.45);
border-top: solid 1px rgba(255, 255, 255, 0.07);
color: #999999;
overflow: hidden;
}
.tab-configuration .list-menu li a:hover {
background-color: rgba(128, 128, 128, 0.50);
color: white;
text-shadow: 0 1px rgba(0, 0, 0, 0.45);
}
.tab-configuration .preset {
width: calc(75% - 5px);
}
.tab-configuration .preset-spacer {
padding: 20px;
float:left;
width: calc(100% - 38px);
}
.tab-configuration .list-menu li.active a {
background-color: #37a8db;
text-shadow: 0 1px rgba(0, 0, 0, 0.45);
color: white;
}
.tab-configuration .airplane {
width: 100%;
height: 100%;
background-image:url(../images/icons/peset_plane.svg);
}
.tab-configuration .flyingwing {
width: 100%;
height: 100%;
background-image:url(../images/icons/peset_wing.svg);
}
.tab-configuration .multirotor {
width: 100%;
height: 100%;
background-image:url(../images/icons/peset_quad.svg);
}
.tab-configuration .preset .top {
background-color: #e6e6e6;
box-shadow: inset 0px -5px 5px rgba(50,50,50, 0.1);
border-top-right-radius: 3px;
}
.tab-configuration .preset .bottom {
border-bottom-right-radius: 3px;
}
.tab-configuration .modal__content h1 {
margin-top: 20px;
margin-bottom: 0px;
}
.tab-configuration #details-head {
display: none;
float: left;
width: 100%;
margin-bottom: 5px;
}

@ -1,37 +1,29 @@
<div class="tab-configuration tab-profiles toolbar_fixed_bottom">
<div class="content_wrapper">
<div class="tab_title" data-i18n="tabPresets">Presets</div>
<div class="cf_column third_left">
<div class="spacer_right">
<div class="gui_box grey">
<div class="gui_box_titlebar">
<div class="spacer_box_title" data-i18n="presetsPreset"></div>
</div>
<div class="spacer_box">
<div class="select">
<select id="presets-list" class="full-width" size="8">
<!-- list generated here -->
</select>
</div>
</div>
</div>
</div>
</div>
<div class="cf_column twothird">
<div class="cf_column full">
<div class="gui_box grey">
<div class="gui_box_titlebar">
<div class="spacer_box_title" data-i18n="presetsDescription"></div>
<div class="cf_column fourth preset__list-wrapper">
<div class="select">
<ul id="presets-list" class="full-width list-menu">
<!-- list generated here -->
</ul>
</div>
</div>
<div class="spacer_box preset">
<h2 id="preset-name" class="preset__head"></h2>
<p id="preset-description" class="preset__description"></p>
<ul id="preset-features" class="preset__features"></ul>
<div class="threefourth_left preset">
<div class="preset-spacer top">
<div id="preset-image"></div>
<h2 id="preset-name" class="preset__head"></h2>
<div id="preset-info" data-i18n="presetApplyDescription"></div>
<p id="preset-description" class="preset__description"></p>
</div>
<div class="preset-spacer bottom">
<div id="details-head"><p data-i18n="presetApplyHead"></p></div>
<ul id="preset-features" class="preset__features"></ul>
</div>
</div>
</div>
</div>
<div id="presetApplyContent" class="is-hidden">
<div class="modal__content">
<h1 class="modal__title modal__title--warning" data-i18n="presetsApplyHeader"></h1>
@ -41,7 +33,6 @@
<a id="execute-button" class="modal__button modal__button--main" data-i18n="presetsButtonSaveAndReboot"></a>
</div>
</div>
<div class="clear-both"></div>
</div>
<div class="content_toolbar">

@ -40,24 +40,25 @@ presets.defaultValues = {
presets.presets = [
{
name: 'Default Preset',
description: "INAV default Quad X configuration",
features: [],
description: "INAV Quad X configuration",
features: ["Default INAV Settings"],
applyDefaults: ["PIDs", "INAV_PID_CONFIG", "ADVANCED_CONFIG", "RC_tuning", "PID_ADVANCED", "FILTER_CONFIG", "FC_CONFIG"],
settings: [
presets.elementHelper("BF_CONFIG", "mixerConfiguration", 3)
]
],
type: 'multirotor'
},
{
name: '5" Racer',
description: "210-250 class racer with F3/F4 CPU on 4S battery",
description: "210-250 class racer with F3/F4 CPU on 4S battery<br>" +
"<span>400g-650g weight, 2000KV - 2600KV motors, 5 inch propellers, MPU6000 or MPU6050 gyro, no GPS capabilities</span>",
features: [
"4S battery",
"2000KV - 2600KV motors",
"5 inch propellers",
"400g-650g weight",
"F3 or F4 CPU",
"MPU6000 or MPU6050 gyro",
"No GPS capabilities"
"Asynchronous processing",
"OneShot125 at 2kHz",
"800dps rates",
"Dterm and gyro notch filter",
"Increased LPF cutoff frequencies",
"Improved PID defaults"
],
applyDefaults: ["PIDs", "INAV_PID_CONFIG", "ADVANCED_CONFIG", "RC_tuning", "PID_ADVANCED", "FILTER_CONFIG", "FC_CONFIG"],
settings: [
@ -84,17 +85,18 @@ presets.presets = [
presets.elementHelper("PIDs", 0, [43, 40, 20]), //ROLL PIDs
presets.elementHelper("PIDs", 1, [58, 50, 22]), //PITCH PIDs
presets.elementHelper("PIDs", 2, [70, 45, 0]) //YAW PIDs
]
],
type: 'multirotor'
},
{
name: '10" General Purpose',
description: "450-600 class general purpose multirotor",
description: "450-600 class general purpose multirotor <br><span>10.kg - 1.4kg weight, 10 inch propellers, <br>F1, F3 or F4 CPU, MPU6000 or MPU6050 gyro, GPS optional.</span>",
features: [
"10 inch propellers",
"0.kg - 1.4kg weight",
"F1, F3 or F4 CPU",
"MPU6000 or MPU6050 gyro",
"GPS optional"
"Asynchronous gyro processing",
"400dps rates",
"Dterm and gyro notch filter",
"Increased LPF cutoff frequencies",
"Improved PID defaults"
],
applyDefaults: ["PIDs", "INAV_PID_CONFIG", "ADVANCED_CONFIG", "RC_tuning", "PID_ADVANCED", "FILTER_CONFIG", "FC_CONFIG"],
settings: [
@ -121,17 +123,20 @@ presets.presets = [
presets.elementHelper("PIDs", 0, [75, 30, 18]), //ROLL PIDs
presets.elementHelper("PIDs", 1, [75, 30, 18]), //PITCH PIDs
presets.elementHelper("PIDs", 2, [85, 45, 0]) //YAW PIDs
]
],
type: 'multirotor'
},
{
name: '12" General Purpose',
description: "550 and above general purpose multirotor",
description: "550 and above general purpose multirotor<br>" +
"<span>12 inch propellers, 1.4kg-2kg weight, F3 or F4 CPU, MPU6000 or MPU6050 gyro, GPS optional</span>",
features: [
"12 inch propellers",
"1.4kg-2kg weight",
"F3 or F4 CPU",
"MPU6000 or MPU6050 gyro",
"GPS optional"
"Asynchronous gyro processing",
"180dps rates",
"Limited rate acceleration",
"Dterm and gyro notch filter",
"Increased LPF cutoff frequencies",
"Improved PID defaults"
],
applyDefaults: ["PIDs", "INAV_PID_CONFIG", "ADVANCED_CONFIG", "RC_tuning", "PID_ADVANCED", "FILTER_CONFIG", "FC_CONFIG"],
settings: [
@ -159,12 +164,16 @@ presets.presets = [
presets.elementHelper("PIDs", 1, [80, 30, 18]), //PITCH PIDs
presets.elementHelper("PIDs", 2, [85, 45, 0]), //YAW PIDs
presets.elementHelper("PIDs", 7, [10, 7, 75]) //Level PIDs
]
],
type: 'multirotor'
},
{
name: "Airplane General",
description: "General setup for airplanes",
features: [
"Adjusted gyro filtering",
"Adjusted PIDs",
"Adjusted rates"
],
applyDefaults: ["PIDs", "INAV_PID_CONFIG", "ADVANCED_CONFIG", "RC_tuning", "PID_ADVANCED", "FILTER_CONFIG", "FC_CONFIG"],
settings: [
@ -177,14 +186,17 @@ presets.presets = [
presets.elementHelper("RC_tuning", "yaw_rate", 90),
presets.elementHelper("ADVANCED_CONFIG", "gyroSync", 1),
presets.elementHelper("INAV_PID_CONFIG", "gyroscopeLpf", 1)
]
],
type: 'airplane'
},
{
name: "600mm Flying Wing",
description: "Small flying wing on multirotor racer parts",
description: "Small flying wing on multirotor racer parts<br>" +
"<span>300g-500g weight, 3S-4S battery</span>",
features: [
"3S-4S battery",
"300g-500g weight"
"Adjusted gyro filtering",
"Adjusted PIDs",
"Adjusted rates"
],
applyDefaults: ["PIDs", "INAV_PID_CONFIG", "ADVANCED_CONFIG", "RC_tuning", "PID_ADVANCED", "FILTER_CONFIG", "FC_CONFIG"],
settings: [
@ -195,7 +207,8 @@ presets.presets = [
presets.elementHelper("RC_tuning", "pitch_rate", 150),
presets.elementHelper("ADVANCED_CONFIG", "gyroSync", 1),
presets.elementHelper("INAV_PID_CONFIG", "gyroscopeLpf", 1)
]
],
type: 'flyingwing'
}
];
@ -256,7 +269,6 @@ TABS.profiles.initialize = function (callback, scrollPosition) {
}
loadChainer.setChain([
mspHelper.loadMspIdent,
mspHelper.loadBfConfig,
mspHelper.loadLoopTime,
mspHelper.loadINAVPidConfig,
@ -322,14 +334,19 @@ TABS.profiles.initialize = function (callback, scrollPosition) {
var $features = $('#preset-features');
$('#preset-image').html('<div class="' + preset.type + '"></div>');
$('#preset-name').html(preset.name);
$('#preset-description').html(preset.description);
document.getElementById('preset-info').style.display = "none";
document.getElementById('details-head').style.display = "block";
$features.find('*').remove();
for (var i in preset.features) {
if (preset.features.hasOwnProperty(i)) {
$features.append('<li class="preset__feature"><span class="preset__feature-text">' + preset.features[i] + "</span></li>");
}
}
@ -339,12 +356,20 @@ TABS.profiles.initialize = function (callback, scrollPosition) {
var $presetList = $('#presets-list');
GUI.fillSelect($presetList, presets.model.extractPresetNames(presets.presets));
var presetsList = presets.model.extractPresetNames(presets.presets);
$presetList.change(function () {
currentPresetId = $presetList.val();
for(var preset in presetsList) {
$presetList.append( '<li class="preset__element-wrapper"><a href="#" class="preset__element-link" data-val="' + preset + '">' + presetsList[preset] + '</a></li>');
}
$('.preset__element-link').click(function () {
currentPresetId = $(this).data('val');
currentPreset = presets.presets[currentPresetId];
fillPresetDescription(currentPreset);
$presetList.find('li').removeClass('active');
$(this).parent().addClass('active');
$('#save-button').removeClass('disabled');
});
@ -368,13 +393,6 @@ TABS.profiles.initialize = function (callback, scrollPosition) {
content: $('#presetApplyContent')
});
GUI.interval_add('status_pull', function status_pull() {
MSP.send_message(MSPCodes.MSP_STATUS);
if (semver.gte(CONFIG.flightControllerVersion, "1.5.0")) {
MSP.send_message(MSPCodes.MSP_SENSOR_STATUS);
}
}, 250, true);
GUI.content_ready(callback);
}
};

@ -41,11 +41,7 @@ TABS.receiver.initialize = function (callback) {
$('.tunings .rate input[name="rate"]').val(RC_tuning.RC_RATE.toFixed(2));
$('.tunings .rate input[name="expo"]').val(RC_tuning.RC_EXPO.toFixed(2));
$('.tunings .yaw_rate input[name="yaw_expo"]').val(RC_tuning.RC_YAW_EXPO.toFixed(2));
if (semver.lt(CONFIG.apiVersion, "1.10.0")) {
$('.tunings .yaw_rate input[name="yaw_expo"]').hide();
}
$('.tunings .yaw_rate input[name="yaw_expo"]').val(RC_tuning.RC_YAW_EXPO.toFixed(2));
chrome.storage.local.get('rx_refresh_rate', function (result) {
if (result.rx_refresh_rate) {
@ -55,12 +51,8 @@ TABS.receiver.initialize = function (callback) {
}
});
if (semver.lt(CONFIG.apiVersion, "1.15.0")) {
$('.deadband').hide();
} else {
$('.deadband input[name="yaw_deadband"]').val(RC_deadband.yaw_deadband);
$('.deadband input[name="deadband"]').val(RC_deadband.deadband);
}
$('.deadband input[name="yaw_deadband"]').val(RC_deadband.yaw_deadband);
$('.deadband input[name="deadband"]').val(RC_deadband.deadband);
// generate bars
var bar_names = [
@ -295,10 +287,8 @@ TABS.receiver.initialize = function (callback) {
RC_tuning.RC_EXPO = parseFloat($('.tunings .rate input[name="expo"]').val());
RC_tuning.RC_YAW_EXPO = parseFloat($('.tunings .yaw_rate input[name="yaw_expo"]').val());
if (semver.gte(CONFIG.apiVersion, "1.15.0")) {
RC_deadband.yaw_deadband = parseInt($('.deadband input[name="yaw_deadband"]').val());
RC_deadband.deadband = parseInt($('.deadband input[name="deadband"]').val());
}
RC_deadband.yaw_deadband = parseInt($('.deadband input[name="yaw_deadband"]').val());
RC_deadband.deadband = parseInt($('.deadband input[name="deadband"]').val());
// catch rc map
var RC_MAP_Letters = ['A', 'E', 'R', 'T', '1', '2', '3', '4'];
@ -320,12 +310,7 @@ TABS.receiver.initialize = function (callback) {
}
function save_rc_configs() {
var next_callback = save_to_eeprom;
if (semver.gte(CONFIG.apiVersion, "1.15.0")) {
MSP.send_message(MSPCodes.MSP_SET_RC_DEADBAND, mspHelper.crunch(MSPCodes.MSP_SET_RC_DEADBAND), false, next_callback);
} else {
next_callback();
}
MSP.send_message(MSPCodes.MSP_SET_RC_DEADBAND, mspHelper.crunch(MSPCodes.MSP_SET_RC_DEADBAND), false, save_to_eeprom);
}
function save_to_eeprom() {
@ -464,21 +449,12 @@ TABS.receiver.initialize = function (callback) {
}
// timer initialization
GUI.interval_remove('receiver_pull');
helper.interval.remove('receiver_pull');
// enable RC data pulling
GUI.interval_add('receiver_pull', get_rc_data, plot_update_rate, true);
helper.interval.add('receiver_pull', get_rc_data, plot_update_rate, true);
});
// status data pulled via separate timer with static speed
GUI.interval_add('status_pull', function status_pull() {
MSP.send_message(MSPCodes.MSP_STATUS);
if (semver.gte(CONFIG.flightControllerVersion, "1.5.0")) {
MSP.send_message(MSPCodes.MSP_SENSOR_STATUS);
}
}, 250, true);
GUI.content_ready(callback);
}
};

@ -356,29 +356,29 @@ TABS.sensors.initialize = function (callback) {
});
// timer initialization
GUI.interval_kill_all(['status_pull']);
helper.interval.killAll(['status_pull', 'global_data_refresh']);
// data pulling timers
if (checkboxes[0] || checkboxes[1] || checkboxes[2]) {
GUI.interval_add('IMU_pull', function imu_data_pull() {
helper.interval.add('IMU_pull', function imu_data_pull() {
MSP.send_message(MSPCodes.MSP_RAW_IMU, false, false, update_imu_graphs);
}, fastest, true);
}
if (checkboxes[3]) {
GUI.interval_add('altitude_pull', function altitude_data_pull() {
helper.interval.add('altitude_pull', function altitude_data_pull() {
MSP.send_message(MSPCodes.MSP_ALTITUDE, false, false, update_altitude_graph);
}, rates.baro, true);
}
if (checkboxes[4]) {
GUI.interval_add('sonar_pull', function sonar_data_pull() {
helper.interval.add('sonar_pull', function sonar_data_pull() {
MSP.send_message(MSPCodes.MSP_SONAR, false, false, update_sonar_graphs);
}, rates.sonar, true);
}
if (checkboxes[5]) {
GUI.interval_add('debug_pull', function debug_data_pull() {
helper.interval.add('debug_pull', function debug_data_pull() {
MSP.send_message(MSPCodes.MSP_DEBUG, false, false, update_debug_graphs);
}, rates.debug, true);
}
@ -443,15 +443,6 @@ TABS.sensors.initialize = function (callback) {
}
});
// status data pulled via separate timer with static speed
GUI.interval_add('status_pull', function status_pull() {
MSP.send_message(MSPCodes.MSP_STATUS);
if (semver.gte(CONFIG.flightControllerVersion, "1.5.0")) {
MSP.send_message(MSPCodes.MSP_SENSOR_STATUS);
}
}, 250, true);
GUI.content_ready(callback);
});
};

@ -14,17 +14,7 @@ TABS.servos.initialize = function (callback) {
}
function get_servo_mix_rules() {
MSP.send_message(MSPCodes.MSP_SERVO_MIX_RULES, false, false, get_channel_forwarding);
}
function get_channel_forwarding() {
var nextFunction = get_rc_data;
if (semver.lt(CONFIG.apiVersion, "1.12.0")) {
MSP.send_message(MSPCodes.MSP_CHANNEL_FORWARDING, false, false, nextFunction);
} else {
nextFunction();
}
MSP.send_message(MSPCodes.MSP_SERVO_MIX_RULES, false, false, get_rc_data);
}
function get_rc_data() {
@ -39,11 +29,11 @@ TABS.servos.initialize = function (callback) {
$('#content').load("./tabs/servos.html", process_html);
}
MSP.send_message(MSPCodes.MSP_IDENT, false, false, get_servo_configurations);
get_servo_configurations();
function update_ui() {
if (semver.lt(CONFIG.apiVersion, "1.12.0") || SERVO_CONFIG.length == 0) {
if (SERVO_CONFIG.length == 0) {
$(".tab-servos").removeClass("supported");
return;
@ -171,7 +161,7 @@ TABS.servos.initialize = function (callback) {
$('table.directions select, table.directions input, table.fields select, table.fields input').change(function () {
if ($('div.live input').is(':checked')) {
// apply small delay as there seems to be some funky update business going wrong
GUI.timeout_add('servos_update', servos_update, 10);
helper.timeout.add('servos_update', servos_update, 10);
}
});
@ -188,15 +178,6 @@ TABS.servos.initialize = function (callback) {
// translate to user-selected language
localize();
// status data pulled via separate timer with static speed
GUI.interval_add('status_pull', function () {
MSP.send_message(MSPCodes.MSP_STATUS);
if (semver.gte(CONFIG.flightControllerVersion, "1.5.0")) {
MSP.send_message(MSPCodes.MSP_SENSOR_STATUS);
}
}, 250, true);
GUI.content_ready(callback);
}
};

@ -34,18 +34,6 @@
<div class="default_btn">
<a class="resetSettings" href="#" data-i18n="initialSetupButtonReset"></a>
</div>
<div class="half">
<div class="spacer_right halfbuttons">
<div class="default_btn half">
<a class="backup" href="#" data-i18n="initialSetupButtonBackup"></a>
</div>
</div>
</div>
<div class="half">
<div class="default_btn half">
<a class="restore" href="#" data-i18n="initialSetupButtonRestore"></a>
</div>
</div>
</div>
</div>
<div class="threefourth_right setupinfo">
@ -58,9 +46,6 @@
<div class="cell_setup">
<span data-i18n="initialSetupResetText"></span>
</div>
<div class="cell_setup">
<span data-i18n="initialSetupBackupRestoreText"></span>
</div>
</div>
</div>
<div class="modelwrapper"></div>

@ -16,8 +16,6 @@ TABS.setup.initialize = function (callback) {
var loadChainer = new MSPChainerClass();
loadChainer.setChain([
mspHelper.loadStatus,
mspHelper.loadMspIdent,
mspHelper.loadBfConfig,
mspHelper.loadMisc
]);
@ -36,12 +34,6 @@ TABS.setup.initialize = function (callback) {
GUI_control.prototype.log("<span style='color: red; font-weight: bolder'><strong>" + chrome.i18n.getMessage("logPwmOutputDisabled") + "</strong></span>");
}
if (semver.lt(CONFIG.apiVersion, CONFIGURATOR.backupRestoreMinApiVersionAccepted)) {
$('#content .backup').addClass('disabled');
$('#content .restore').addClass('disabled');
GUI.log(chrome.i18n.getMessage('initialSetupBackupAndRestoreApiVersion', [CONFIG.apiVersion, CONFIGURATOR.backupRestoreMinApiVersionAccepted]));
}
// initialize 3D
self.initialize3D();
@ -70,15 +62,16 @@ TABS.setup.initialize = function (callback) {
// During this period MCU won't be able to process any serial commands because its locked in a for/while loop
// until this operation finishes, sending more commands through data_poll() will result in serial buffer overflow
GUI.interval_pause('setup_data_pull');
helper.interval.pause('setup_data_pull');
MSP.send_message(MSPCodes.MSP_ACC_CALIBRATION, false, false, function () {
GUI.log(chrome.i18n.getMessage('initialSetupAccelCalibStarted'));
$('#accel_calib_running').show();
$('#accel_calib_rest').hide();
});
GUI.timeout_add('button_reset', function () {
GUI.interval_resume('setup_data_pull');
helper.timeout.add('button_reset', function () {
helper.interval.resume('setup_data_pull');
GUI.log(chrome.i18n.getMessage('initialSetupAccelCalibEnded'));
@ -101,7 +94,7 @@ TABS.setup.initialize = function (callback) {
$('#mag_calib_rest').hide();
});
GUI.timeout_add('button_reset', function () {
helper.timeout.add('button_reset', function () {
GUI.log(chrome.i18n.getMessage('initialSetupMagCalibEnded'));
self.removeClass('calibrating');
$('#mag_calib_running').hide();
@ -131,29 +124,6 @@ TABS.setup.initialize = function (callback) {
console.log('YAW reset to 0 deg, fix: ' + self.yaw_fix + ' deg');
});
$('#content .backup').click(function () {
if ($(this).hasClass('disabled')) {
return;
}
configuration_backup(function () {
GUI.log(chrome.i18n.getMessage('initialSetupBackupSuccess'));
googleAnalytics.sendEvent('Configuration', 'Backup', 'true');
});
});
$('#content .restore').click(function () {
if ($(this).hasClass('disabled')) {
return;
}
configuration_restore(function () {
GUI.log(chrome.i18n.getMessage('initialSetupRestoreSuccess'));
googleAnalytics.sendEvent('Configuration', 'Restore', 'true');
// get latest settings
TABS.setup.initialize();
});
});
// cached elements
var bat_voltage_e = $('.bat-voltage'),
bat_mah_drawn_e = $('.bat-mah-drawn'),
@ -168,19 +138,6 @@ TABS.setup.initialize = function (callback) {
heading_e = $('dd.heading');
function get_slow_data() {
MSP.send_message(MSPCodes.MSP_STATUS);
if (semver.gte(CONFIG.flightControllerVersion, "1.5.0")) {
MSP.send_message(MSPCodes.MSP_SENSOR_STATUS);
}
MSP.send_message(MSPCodes.MSP_ANALOG, false, false, function () {
bat_voltage_e.text(chrome.i18n.getMessage('initialSetupBatteryValue', [ANALOG.voltage]));
bat_mah_drawn_e.text(chrome.i18n.getMessage('initialSetupBatteryMahValue', [ANALOG.mAhdrawn]));
bat_mah_drawing_e.text(chrome.i18n.getMessage('initialSetupBatteryAValue', [ANALOG.amperage.toFixed(2)]));
rssi_e.text(chrome.i18n.getMessage('initialSetupRSSIValue', [((ANALOG.rssi / 1023) * 100).toFixed(0)]));
});
if (have_sensor(CONFIG.activeSensors, 'gps')) {
MSP.send_message(MSPCodes.MSP_RAW_GPS, false, false, function () {
var gpsFixType = chrome.i18n.getMessage('gpsFixNone');
@ -206,8 +163,14 @@ TABS.setup.initialize = function (callback) {
});
}
GUI.interval_add('setup_data_pull_fast', get_fast_data, 33, true); // 30 fps
GUI.interval_add('setup_data_pull_slow', get_slow_data, 250, true); // 4 fps
helper.interval.add('setup_data_pull_fast', get_fast_data, 40, true); // 25 fps
helper.interval.add('setup_data_pull_slow', get_slow_data, 250, true); // 4 fps
helper.interval.add('gui_analog_update', function () {
bat_voltage_e.text(chrome.i18n.getMessage('initialSetupBatteryValue', [ANALOG.voltage]));
bat_mah_drawn_e.text(chrome.i18n.getMessage('initialSetupBatteryMahValue', [ANALOG.mAhdrawn]));
bat_mah_drawing_e.text(chrome.i18n.getMessage('initialSetupBatteryAValue', [ANALOG.amperage.toFixed(2)]));
rssi_e.text(chrome.i18n.getMessage('initialSetupRSSIValue', [((ANALOG.rssi / 1023) * 100).toFixed(0)]));
}, 100, true);
function updateArminFailure() {
var flagNames = FC.getArmingFlags();
@ -226,7 +189,7 @@ TABS.setup.initialize = function (callback) {
/*
* 1fps update rate will be fully enough
*/
GUI.interval_add('updateArminFailure', updateArminFailure, 500, true);
helper.interval.add('updateArminFailure', updateArminFailure, 500, true);
GUI.content_ready(callback);
}
@ -281,7 +244,7 @@ TABS.setup.initialize3D = function () {
//
// load the model including materials
if (useWebGlRenderer) {
model_file = mixerList[CONFIG.multiType - 1].model;
model_file = mixerList[BF_CONFIG.mixerConfiguration - 1].model;
} else {
model_file = 'fallback'
}

@ -91,14 +91,6 @@ TABS.transponder.initialize = function (callback, scrollPosition) {
save_transponder_config();
});
}
// status data pulled via separate timer with static speed
GUI.interval_add('status_pull', function status_pull() {
MSP.send_message(MSPCodes.MSP_STATUS);
if (semver.gte(CONFIG.flightControllerVersion, "1.5.0")) {
MSP.send_message(MSPCodes.MSP_SENSOR_STATUS);
}
}, 250, true);
GUI.content_ready(callback);
}

Loading…
Cancel
Save