mirror of
https://github.com/iNavFlight/inav-configurator.git
synced 2025-07-19 14:25:13 +03:00
Merge branch 'master' of https://github.com/iNavFlight/inav-configurator into mission-planer
Fix conflicts: _locales/en/messages.json
This commit is contained in:
commit
db31180753
17 changed files with 466 additions and 128 deletions
|
@ -735,6 +735,15 @@
|
|||
"configurationSPIProtocol": {
|
||||
"message": "RX SPI protocol"
|
||||
},
|
||||
"configurationPersonalization": {
|
||||
"message": "Personalization"
|
||||
},
|
||||
"configurationCraftName": {
|
||||
"message": "Craft Name"
|
||||
},
|
||||
"configurationCraftNameHelp": {
|
||||
"message": "Craft name. Can be displayed by OSD and by compatible RC systems."
|
||||
},
|
||||
"configurationEepromSaved": {
|
||||
"message": "EEPROM <span style=\"color: #37a8db\">saved</span>"
|
||||
},
|
||||
|
@ -1130,10 +1139,6 @@
|
|||
"transponderEepromSaved": {
|
||||
"message": "EEPROM <span style=\"color: #37a8db\">saved</span>"
|
||||
},
|
||||
|
||||
"servosFirmwareUpgradeRequired": {
|
||||
"message": "Servos requires firmware >= 1.10.0. and target support."
|
||||
},
|
||||
"servosChangeDirection": {
|
||||
"message": "Change Direction in TX To Match"
|
||||
},
|
||||
|
@ -2320,6 +2325,7 @@
|
|||
"downloadUpdatesBtn": {
|
||||
"message": "Download new app"
|
||||
},
|
||||
<<<<<<< HEAD
|
||||
"tabMissionControl": {
|
||||
"message": "Mission Control"
|
||||
},
|
||||
|
@ -2358,5 +2364,14 @@
|
|||
},
|
||||
"confirm_delete_all_points": {
|
||||
"message": "Do you really want to delete all points?"
|
||||
},
|
||||
"servoMixer": {
|
||||
"message": "Servo mixer"
|
||||
},
|
||||
"servoMixerDelete": {
|
||||
"message": "Delete"
|
||||
},
|
||||
"servoMixerAdd": {
|
||||
"message": "Add new mixer rule"
|
||||
}
|
||||
}
|
||||
|
|
|
@ -90,6 +90,8 @@ sources.js = [
|
|||
'./js/localization.js',
|
||||
'./js/boards.js',
|
||||
'./js/tasks.js',
|
||||
'./js/servoMixRule.js',
|
||||
'./js/servoMixRuleCollection.js',
|
||||
'./main.js',
|
||||
'./tabs/*.js',
|
||||
'./js/eventFrequencyAnalyzer.js',
|
||||
|
|
24
js/fc.js
24
js/fc.js
|
@ -151,7 +151,7 @@ var FC = {
|
|||
ADJUSTMENT_RANGES = [];
|
||||
|
||||
SERVO_CONFIG = [];
|
||||
SERVO_RULES = [];
|
||||
SERVO_RULES = new ServoMixRuleCollection();
|
||||
|
||||
SERIAL_CONFIG = {
|
||||
ports: [],
|
||||
|
@ -950,5 +950,27 @@ var FC = {
|
|||
},
|
||||
getRcMapLetters: function () {
|
||||
return ['A', 'E', 'R', 'T', '5', '6', '7', '8'];
|
||||
},
|
||||
getServoMixInputNames: function () {
|
||||
return [
|
||||
'Stabilised Roll',
|
||||
'Stabilised Pitch',
|
||||
'Stabilised Yaw',
|
||||
'Stabilised Throttle',
|
||||
'RC Roll',
|
||||
'RC Pitch',
|
||||
'RC Yaw',
|
||||
'RC Throttle',
|
||||
'RC Channel 5',
|
||||
'RC Channel 6',
|
||||
'RC Channel 7',
|
||||
'RC Channel 8',
|
||||
'Gimbal Pitch',
|
||||
'Gimbal Roll',
|
||||
'Flaps'
|
||||
];
|
||||
},
|
||||
getServoMixInputName: function (input) {
|
||||
return getServoMixInputNames()[input];
|
||||
}
|
||||
};
|
||||
|
|
50
js/model.js
50
js/model.js
|
@ -2,29 +2,29 @@
|
|||
|
||||
// generate mixer
|
||||
var mixerList = [
|
||||
{name: 'Tricopter', model: 'tricopter', image: 'tri'}, // 1
|
||||
{name: 'Quad +', model: 'quad_x', image: 'quad_p'}, // 2
|
||||
{name: 'Quad X', model: 'quad_x', image: 'quad_x'}, // 3
|
||||
{name: 'Bicopter', model: 'custom', image: 'bicopter'}, // 4
|
||||
{name: 'Gimbal', model: 'custom', image: 'custom'}, // 5
|
||||
{name: 'Y6', model: 'y6', image: 'y6'}, // 6
|
||||
{name: 'Hex +', model: 'hex_plus', image: 'hex_p'}, // 7
|
||||
{name: 'Flying Wing', model: 'custom', image: 'flying_wing'}, // 8
|
||||
{name: 'Y4', model: 'y4', image: 'y4'}, // 9
|
||||
{name: 'Hex X', model: 'hex_x', image: 'hex_x'}, // 10
|
||||
{name: 'Octo X8', model: 'custom', image: 'octo_x8'}, // 11
|
||||
{name: 'Octo Flat +', model: 'custom', image: 'octo_flat_p'}, // 12
|
||||
{name: 'Octo Flat X', model: 'custom', image: 'octo_flat_x'}, // 13
|
||||
{name: 'Airplane', model: 'custom', image: 'airplane'}, // 14
|
||||
{name: 'Heli 120', model: 'custom', image: 'custom'}, // 15
|
||||
{name: 'Heli 90', model: 'custom', image: 'custom'}, // 16
|
||||
{name: 'V-tail Quad', model: 'quad_vtail', image: 'vtail_quad'}, // 17
|
||||
{name: 'Hex H', model: 'custom', image: 'custom'}, // 18
|
||||
{name: 'PPM to SERVO', model: 'custom', image: 'custom'}, // 19
|
||||
{name: 'Dualcopter', model: 'custom', image: 'custom'}, // 20
|
||||
{name: 'Singlecopter', model: 'custom', image: 'custom'}, // 21
|
||||
{name: 'A-tail Quad', model: 'quad_atail', image: 'atail_quad'}, // 22
|
||||
{name: 'Custom', model: 'custom', image: 'custom'}, // 23
|
||||
{name: 'Custom Airplane', model: 'custom', image: 'custom'}, // 24
|
||||
{name: 'Custom Tricopter', model: 'custom', image: 'custom'} // 25
|
||||
{name: 'Tricopter', model: 'tricopter', image: 'tri', hasCustomServoMixer: false}, // 1
|
||||
{name: 'Quad +', model: 'quad_x', image: 'quad_p', hasCustomServoMixer: false}, // 2
|
||||
{name: 'Quad X', model: 'quad_x', image: 'quad_x', hasCustomServoMixer: false}, // 3
|
||||
{name: 'Bicopter', model: 'custom', image: 'bicopter', hasCustomServoMixer: false}, // 4
|
||||
{name: 'Gimbal', model: 'custom', image: 'custom', hasCustomServoMixer: false}, // 5
|
||||
{name: 'Y6', model: 'y6', image: 'y6', hasCustomServoMixer: false}, // 6
|
||||
{name: 'Hex +', model: 'hex_plus', image: 'hex_p', hasCustomServoMixer: false}, // 7
|
||||
{name: 'Flying Wing', model: 'custom', image: 'flying_wing', hasCustomServoMixer: false}, // 8
|
||||
{name: 'Y4', model: 'y4', image: 'y4', hasCustomServoMixer: false}, // 9
|
||||
{name: 'Hex X', model: 'hex_x', image: 'hex_x', hasCustomServoMixer: false}, // 10
|
||||
{name: 'Octo X8', model: 'custom', image: 'octo_x8', hasCustomServoMixer: false}, // 11
|
||||
{name: 'Octo Flat +', model: 'custom', image: 'octo_flat_p', hasCustomServoMixer: false}, // 12
|
||||
{name: 'Octo Flat X', model: 'custom', image: 'octo_flat_x', hasCustomServoMixer: false}, // 13
|
||||
{name: 'Airplane', model: 'custom', image: 'airplane', hasCustomServoMixer: false}, // 14
|
||||
{name: 'Heli 120', model: 'custom', image: 'custom', hasCustomServoMixer: false}, // 15
|
||||
{name: 'Heli 90', model: 'custom', image: 'custom', hasCustomServoMixer: false}, // 16
|
||||
{name: 'V-tail Quad', model: 'quad_vtail', image: 'vtail_quad', hasCustomServoMixer: false}, // 17
|
||||
{name: 'Hex H', model: 'custom', image: 'custom', hasCustomServoMixer: false}, // 18
|
||||
{name: 'PPM to SERVO', model: 'custom', image: 'custom', hasCustomServoMixer: false}, // 19
|
||||
{name: 'Dualcopter', model: 'custom', image: 'custom', hasCustomServoMixer: false}, // 20
|
||||
{name: 'Singlecopter', model: 'custom', image: 'custom', hasCustomServoMixer: false}, // 21
|
||||
{name: 'A-tail Quad', model: 'quad_atail', image: 'atail_quad', hasCustomServoMixer: false}, // 22
|
||||
{name: 'Custom', model: 'custom', image: 'custom', hasCustomServoMixer: true}, // 23
|
||||
{name: 'Custom Airplane', model: 'custom', image: 'custom', hasCustomServoMixer: true}, // 24
|
||||
{name: 'Custom Tricopter', model: 'custom', image: 'custom', hasCustomServoMixer: true} // 25
|
||||
];
|
||||
|
|
|
@ -10,6 +10,9 @@ var MSPCodes = {
|
|||
MSP_INAV_PID: 6,
|
||||
MSP_SET_INAV_PID: 7,
|
||||
|
||||
MSP_NAME: 10,
|
||||
MSP_SET_NAME: 11,
|
||||
|
||||
MSP_NAV_POSHOLD: 12,
|
||||
MSP_SET_NAV_POSHOLD: 13,
|
||||
MSP_CALIBRATION_DATA: 14,
|
||||
|
|
|
@ -355,6 +355,20 @@ var mspHelper = (function (gui) {
|
|||
}
|
||||
break;
|
||||
case MSPCodes.MSP_SERVO_MIX_RULES:
|
||||
SERVO_RULES.flush();
|
||||
|
||||
if (data.byteLength % 7 === 0) {
|
||||
for (i = 0; i < data.byteLength; i += 7) {
|
||||
SERVO_RULES.put(new ServoMixRule(
|
||||
data.getInt8(i + 0, true),
|
||||
data.getInt8(i + 1, true),
|
||||
data.getInt8(i + 2, true),
|
||||
data.getInt8(i + 3, true)
|
||||
));
|
||||
}
|
||||
}
|
||||
SERVO_RULES.cleanup();
|
||||
|
||||
break;
|
||||
|
||||
case MSPCodes.MSP_SERVO_CONFIGURATIONS:
|
||||
|
@ -1106,6 +1120,11 @@ var mspHelper = (function (gui) {
|
|||
case MSPCodes.MSP_OSD_CHAR_WRITE:
|
||||
console.log('OSD char uploaded');
|
||||
break;
|
||||
case MSPCodes.MSP_NAME:
|
||||
break;
|
||||
case MSPCodes.MSP_SET_NAME:
|
||||
console.log("Craft name set");
|
||||
break;
|
||||
case MSPCodes.MSPV2_SETTING:
|
||||
break;
|
||||
case MSPCodes.MSPV2_SET_SETTING:
|
||||
|
@ -1693,7 +1712,6 @@ var mspHelper = (function (gui) {
|
|||
nextFunction();
|
||||
}
|
||||
|
||||
|
||||
function send_next_servo_configuration() {
|
||||
|
||||
var buffer = [];
|
||||
|
@ -1736,24 +1754,41 @@ var mspHelper = (function (gui) {
|
|||
}
|
||||
MSP.send_message(MSPCodes.MSP_SET_SERVO_CONFIGURATION, buffer, false, nextFunction);
|
||||
}
|
||||
};
|
||||
|
||||
//FIXME looks like this is not used and not ever implemented
|
||||
//noinspection JSUnusedLocalSymbols
|
||||
function send_channel_forwarding() {
|
||||
self.sendServoMixer = function (onCompleteCallback) {
|
||||
var nextFunction = sendMixer,
|
||||
servoIndex = 0;
|
||||
|
||||
if (SERVO_RULES.length == 0) {
|
||||
onCompleteCallback();
|
||||
} else {
|
||||
nextFunction();
|
||||
}
|
||||
|
||||
function sendMixer() {
|
||||
|
||||
var buffer = [];
|
||||
|
||||
for (var i = 0; i < SERVO_CONFIG.length; i++) {
|
||||
var out = SERVO_CONFIG[i].indexOfChannelToForward;
|
||||
if (out == undefined) {
|
||||
out = 255; // Cleanflight defines "CHANNEL_FORWARDING_DISABLED" as "(uint8_t)0xFF"
|
||||
}
|
||||
buffer.push(out);
|
||||
}
|
||||
// send one at a time, with index
|
||||
|
||||
var servoRule = SERVO_RULES.get()[servoIndex];
|
||||
|
||||
buffer.push(servoIndex);
|
||||
buffer.push(servoRule.getTarget());
|
||||
buffer.push(servoRule.getInput());
|
||||
buffer.push(servoRule.getRate());
|
||||
buffer.push(servoRule.getSpeed());
|
||||
buffer.push(0);
|
||||
buffer.push(0);
|
||||
buffer.push(0);
|
||||
|
||||
// prepare for next iteration
|
||||
servoIndex++;
|
||||
if (servoIndex == 16) { //This is the last rule. Not pretty, but we have to send all rules
|
||||
nextFunction = onCompleteCallback;
|
||||
|
||||
MSP.send_message(MSPCodes.MSP_SET_CHANNEL_FORWARDING, buffer, false, nextFunction);
|
||||
}
|
||||
MSP.send_message(MSPCodes.MSP_SET_SERVO_MIX_RULE, buffer, false, nextFunction);
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -2548,5 +2583,46 @@ var mspHelper = (function (gui) {
|
|||
}
|
||||
};
|
||||
|
||||
self.loadServoConfiguration = function (callback) {
|
||||
MSP.send_message(MSPCodes.MSP_SERVO_CONFIGURATIONS, false, false, callback);
|
||||
};
|
||||
|
||||
self.loadServoMixRules = function (callback) {
|
||||
MSP.send_message(MSPCodes.MSP_SERVO_MIX_RULES, false, false, callback);
|
||||
}
|
||||
|
||||
self.getCraftName = function(callback) {
|
||||
if (semver.gt(CONFIG.flightControllerVersion, "1.8.0")) {
|
||||
MSP.send_message(MSPCodes.MSP_NAME, false, false, function(resp) {
|
||||
var name = "";
|
||||
for (var ii = 0; ii < resp.data.byteLength; ii++) {
|
||||
var c = resp.data.readU8();
|
||||
if (c != 0) {
|
||||
name += String.fromCharCode(c);
|
||||
}
|
||||
}
|
||||
if (callback) {
|
||||
callback(name);
|
||||
}
|
||||
});
|
||||
} else if (callback) {
|
||||
callback(null);
|
||||
}
|
||||
};
|
||||
|
||||
self.setCraftName = function(name, callback) {
|
||||
if (semver.gt(CONFIG.flightControllerVersion, "1.8.0")) {
|
||||
var data = [];
|
||||
name = name || "";
|
||||
for (var ii = 0; ii < name.length; ii++) {
|
||||
data.push(name.charCodeAt(ii));
|
||||
}
|
||||
MSP.send_message(MSPCodes.MSP_SET_NAME, data, false, callback);
|
||||
} else if (callback) {
|
||||
callback();
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
return self;
|
||||
})(GUI);
|
||||
|
|
|
@ -9,7 +9,7 @@ var MSPChainerClass = function () {
|
|||
self.exitPoint = null;
|
||||
self.chainIndex = 0;
|
||||
|
||||
self.setChain = function(chain) {
|
||||
self.setChain = function (chain) {
|
||||
self.chain = chain;
|
||||
};
|
||||
|
||||
|
@ -21,12 +21,12 @@ var MSPChainerClass = function () {
|
|||
self.chainIndex++;
|
||||
if (self.chain[self.chainIndex]) {
|
||||
self.chain[self.chainIndex](self.returnCallback);
|
||||
} else {
|
||||
} else if (self.exitPoint) {
|
||||
self.exitPoint();
|
||||
}
|
||||
};
|
||||
|
||||
self.execute = function() {
|
||||
self.execute = function () {
|
||||
self.chainIndex = 0;
|
||||
self.chain[self.chainIndex](self.returnCallback);
|
||||
};
|
||||
|
|
45
js/servoMixRule.js
Normal file
45
js/servoMixRule.js
Normal file
|
@ -0,0 +1,45 @@
|
|||
/*global $*/
|
||||
'use strict';
|
||||
|
||||
var ServoMixRule = function (target, input, rate, speed) {
|
||||
|
||||
var self = {};
|
||||
|
||||
self.getTarget = function () {
|
||||
return target;
|
||||
};
|
||||
|
||||
self.setTarget = function (data) {
|
||||
target = data;
|
||||
};
|
||||
|
||||
self.getInput = function () {
|
||||
return input;
|
||||
};
|
||||
|
||||
self.setInput = function (data) {
|
||||
input = data;
|
||||
};
|
||||
|
||||
self.getRate = function () {
|
||||
return rate;
|
||||
};
|
||||
|
||||
self.setRate = function (data) {
|
||||
rate = data;
|
||||
};
|
||||
|
||||
self.getSpeed = function () {
|
||||
return speed;
|
||||
};
|
||||
|
||||
self.setSpeed = function (data) {
|
||||
speed = data;
|
||||
};
|
||||
|
||||
self.isUsed = function () {
|
||||
return rate !== 0;
|
||||
};
|
||||
|
||||
return self;
|
||||
};
|
49
js/servoMixRuleCollection.js
Normal file
49
js/servoMixRuleCollection.js
Normal file
|
@ -0,0 +1,49 @@
|
|||
/*global $, ServoMixRule*/
|
||||
'use strict';
|
||||
|
||||
var ServoMixRuleCollection = function () {
|
||||
|
||||
var self = {};
|
||||
var data = [];
|
||||
|
||||
self.put = function (element) {
|
||||
data.push(element);
|
||||
};
|
||||
|
||||
self.get = function () {
|
||||
return data;
|
||||
};
|
||||
|
||||
self.drop = function (index) {
|
||||
data[index].setRate(0);
|
||||
self.cleanup();
|
||||
};
|
||||
|
||||
self.flush = function () {
|
||||
data = [];
|
||||
};
|
||||
|
||||
self.cleanup = function () {
|
||||
var tmpData = [];
|
||||
|
||||
data.forEach(function (element) {
|
||||
if (element.isUsed()) {
|
||||
tmpData.push(element);
|
||||
}
|
||||
});
|
||||
|
||||
data = tmpData;
|
||||
};
|
||||
|
||||
self.inflate = function () {
|
||||
while (self.hasFreeSlots()) {
|
||||
self.put(new ServoMixRule(0, 0, 0, 0));
|
||||
}
|
||||
}
|
||||
|
||||
self.hasFreeSlots = function () {
|
||||
return data.length < 16;
|
||||
};
|
||||
|
||||
return self;
|
||||
};
|
9
main.css
9
main.css
|
@ -1326,6 +1326,15 @@ dialog {
|
|||
float: left;
|
||||
}
|
||||
|
||||
.default_btn.narrow {
|
||||
width: auto;
|
||||
margin-bottom: 0;
|
||||
}
|
||||
|
||||
.default_btn.narrow a {
|
||||
padding: 5px;
|
||||
}
|
||||
|
||||
.default_btn a {
|
||||
padding: 5px 0 5px 0;
|
||||
text-align: center;
|
||||
|
|
|
@ -20,9 +20,8 @@
|
|||
font-weight: bold;
|
||||
}
|
||||
|
||||
.config-section .number input,
|
||||
.tab-configuration .number input {
|
||||
width: 65px;
|
||||
.config-section input,
|
||||
.tab-configuration input {
|
||||
padding-left: 3px;
|
||||
height: 20px;
|
||||
line-height: 20px;
|
||||
|
@ -34,8 +33,17 @@
|
|||
font-weight: normal;
|
||||
}
|
||||
|
||||
.tab-configuration .number .disabled {
|
||||
.config-section .number input,
|
||||
.tab-configuration .number input {
|
||||
width: 65px;
|
||||
}
|
||||
|
||||
.config-section .string input,
|
||||
.tab-configuration .string input {
|
||||
width: 130px;
|
||||
}
|
||||
|
||||
.tab-configuration .disabled {
|
||||
background-color: #ececec;
|
||||
}
|
||||
|
||||
|
@ -226,6 +234,10 @@ hr {
|
|||
left: 2em;
|
||||
}
|
||||
|
||||
.config-section .string label {
|
||||
left: 175px;
|
||||
}
|
||||
|
||||
.config-section .radio input {
|
||||
margin-top: 3px;
|
||||
margin-left: 5px;
|
||||
|
|
|
@ -50,7 +50,16 @@
|
|||
background-color: #f9f9f9;
|
||||
}
|
||||
|
||||
.tab-servos table tr:first-child {
|
||||
#servo-mix-table input {
|
||||
width: 75px;
|
||||
}
|
||||
|
||||
#servo-mix-table .btn {
|
||||
float: none;
|
||||
}
|
||||
|
||||
#servo-config-table tr:first-child,
|
||||
#servo-mix-table thead tr {
|
||||
border-left: 1px solid #e4e4e4;
|
||||
border-right: 1px solid #e4e4e4;
|
||||
background-color: #828885;
|
||||
|
@ -154,22 +163,6 @@
|
|||
bottom: 10px;
|
||||
}
|
||||
|
||||
.tab-servos .require-support {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.tab-servos.supported .require-support {
|
||||
display: block;
|
||||
}
|
||||
|
||||
.tab-servos .require-upgrade {
|
||||
display: block;
|
||||
}
|
||||
|
||||
.tab-servos.supported .require-upgrade {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.tab-servos .live span {
|
||||
margin-right: 10px;
|
||||
}
|
||||
|
|
|
@ -212,6 +212,21 @@
|
|||
</div>
|
||||
</div>
|
||||
|
||||
<div class="config-section gui_box grey config-personalization">
|
||||
<div class="gui_box_titlebar">
|
||||
<div class="spacer_box_title" data-i18n="configurationPersonalization"></div>
|
||||
</div>
|
||||
<div class="spacer_box">
|
||||
<div class="string">
|
||||
<input maxlength="16" id="craft_name" name="craft_name" />
|
||||
<label for="craft_name">
|
||||
<span data-i18n="configurationCraftName"></span>
|
||||
</label>
|
||||
<div class="helpicon cf_tip" data-i18n_title="configurationCraftNameHelp"></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
<!--Right column begins here-->
|
||||
|
|
|
@ -10,6 +10,18 @@ TABS.configuration.initialize = function (callback, scrollPosition) {
|
|||
googleAnalytics.sendAppView('Configuration');
|
||||
}
|
||||
|
||||
var craftName = null;
|
||||
var loadCraftName = function(callback) {
|
||||
mspHelper.getCraftName(function(name) {
|
||||
craftName = name;
|
||||
callback();
|
||||
});
|
||||
};
|
||||
|
||||
var saveCraftName = function(callback) {
|
||||
mspHelper.setCraftName(craftName, callback);
|
||||
};
|
||||
|
||||
var loadChainer = new MSPChainerClass();
|
||||
|
||||
loadChainer.setChain([
|
||||
|
@ -22,7 +34,8 @@ TABS.configuration.initialize = function (callback, scrollPosition) {
|
|||
mspHelper.loadSensorAlignment,
|
||||
mspHelper.loadAdvancedConfig,
|
||||
mspHelper.loadINAVPidConfig,
|
||||
mspHelper.loadSensorConfig
|
||||
mspHelper.loadSensorConfig,
|
||||
loadCraftName
|
||||
]);
|
||||
loadChainer.setExitPoint(load_html);
|
||||
loadChainer.execute();
|
||||
|
@ -41,6 +54,7 @@ TABS.configuration.initialize = function (callback, scrollPosition) {
|
|||
mspHelper.saveAdvancedConfig,
|
||||
mspHelper.saveINAVPidConfig,
|
||||
mspHelper.saveSensorConfig,
|
||||
saveCraftName,
|
||||
mspHelper.saveToEeprom
|
||||
]);
|
||||
saveChainer.setExitPoint(reboot);
|
||||
|
@ -597,6 +611,14 @@ TABS.configuration.initialize = function (callback, scrollPosition) {
|
|||
});
|
||||
});
|
||||
|
||||
// Craft name
|
||||
if (craftName != null) {
|
||||
$('.config-personalization').show();
|
||||
$('input[name="craft_name"]').val(craftName);
|
||||
} else {
|
||||
// craft name not supported by the firmware
|
||||
$('.config-personalization').hide();
|
||||
}
|
||||
|
||||
$('a.save').click(function () {
|
||||
// gather data that doesn't have automatic change event bound
|
||||
|
@ -635,6 +657,8 @@ TABS.configuration.initialize = function (callback, scrollPosition) {
|
|||
SENSOR_ALIGNMENT.align_acc = parseInt(orientation_acc_e.val());
|
||||
SENSOR_ALIGNMENT.align_mag = parseInt(orientation_mag_e.val());
|
||||
|
||||
craftName = $('input[name="craft_name"]').val();
|
||||
|
||||
var rxTypes = FC.getRxTypes();
|
||||
|
||||
function is_using_rx_type(name) {
|
||||
|
|
|
@ -421,7 +421,7 @@ OSD.constants = {
|
|||
{
|
||||
name: 'FLYMODE',
|
||||
id: 7,
|
||||
preview: 'STAB'
|
||||
preview: 'ACRO'
|
||||
},
|
||||
{
|
||||
name: 'MESSAGES',
|
||||
|
|
|
@ -1,13 +1,12 @@
|
|||
<!--suppress HtmlFormInputWithoutLabel -->
|
||||
<div class="tab-servos toolbar_fixed_bottom">
|
||||
<div class="content_wrapper">
|
||||
<div class="tab_title" data-i18n="tabServos">Servos</div>
|
||||
<div class="cf_doc_version_bt">
|
||||
<a id="button-documentation" href="" target="_blank"></a>
|
||||
</div>
|
||||
<div class="require-support">
|
||||
<div>
|
||||
<div class="title" data-i18n="servosChangeDirection"></div>
|
||||
<table class="fields">
|
||||
<table id="servo-config-table" class="fields">
|
||||
<tr class="main">
|
||||
<th width="110px" data-i18n="servosName"></th>
|
||||
<th data-i18n="servosMid"></th>
|
||||
|
@ -23,9 +22,28 @@
|
|||
<input type="checkbox" class="togglemedium" /> <span data-i18n="servosLiveMode"></span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="note require-upgrade">
|
||||
<div class="note_spacer">
|
||||
<p data-i18n="servosFirmwareUpgradeRequired"></p>
|
||||
<div class="clear-both"></div>
|
||||
<div id="servo-mix-table-wrapper" class="margin-top">
|
||||
<div class="tab_title" data-i18n="servoMixer">Servo mixer</div>
|
||||
<div class="btn default_btn narrow pull-right" style="margin-bottom: 15px">
|
||||
<a href="#" data-role="role-add" data-i18n="servoMixerAdd"></a>
|
||||
</div>
|
||||
<table id="servo-mix-table">
|
||||
<thead>
|
||||
<tr>
|
||||
<th style="width: 75px">Servo</th>
|
||||
<th>Input</th>
|
||||
<th>Weight</th>
|
||||
<th>Speed</th>
|
||||
<th style="width: 75px"></th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
|
||||
</tbody>
|
||||
</table>
|
||||
<div class="btn default_btn narrow pull-right" style="margin-bottom: 15px">
|
||||
<a href="#" data-role="role-add" data-i18n="servoMixerAdd"></a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
|
159
tabs/servos.js
159
tabs/servos.js
|
@ -9,44 +9,102 @@ TABS.servos.initialize = function (callback) {
|
|||
googleAnalytics.sendAppView('Servos');
|
||||
}
|
||||
|
||||
function get_servo_configurations() {
|
||||
MSP.send_message(MSPCodes.MSP_SERVO_CONFIGURATIONS, false, false, get_servo_mix_rules);
|
||||
}
|
||||
var loadChainer = new MSPChainerClass();
|
||||
|
||||
function get_servo_mix_rules() {
|
||||
MSP.send_message(MSPCodes.MSP_SERVO_MIX_RULES, false, false, get_rc_data);
|
||||
}
|
||||
loadChainer.setChain([
|
||||
mspHelper.loadServoConfiguration,
|
||||
mspHelper.loadRcData,
|
||||
mspHelper.loadBfConfig,
|
||||
mspHelper.loadServoMixRules
|
||||
]);
|
||||
loadChainer.setExitPoint(load_html);
|
||||
loadChainer.execute();
|
||||
|
||||
function get_rc_data() {
|
||||
MSP.send_message(MSPCodes.MSP_RC, false, false, get_boxnames_data);
|
||||
}
|
||||
var saveChainer = new MSPChainerClass();
|
||||
|
||||
function get_boxnames_data() {
|
||||
MSP.send_message(MSPCodes.MSP_BOXNAMES, false, false, load_html);
|
||||
}
|
||||
saveChainer.setChain([
|
||||
mspHelper.sendServoConfigurations,
|
||||
mspHelper.sendServoMixer,
|
||||
mspHelper.saveToEeprom
|
||||
]);
|
||||
saveChainer.setExitPoint(function () {
|
||||
GUI.log(chrome.i18n.getMessage('servosEepromSave'));
|
||||
SERVO_RULES.cleanup();
|
||||
renderServoMixRules();
|
||||
});
|
||||
|
||||
function load_html() {
|
||||
$('#content').load("./tabs/servos.html", process_html);
|
||||
}
|
||||
|
||||
get_servo_configurations();
|
||||
function renderServoMixRules() {
|
||||
|
||||
var $servoMixTable = $('#servo-mix-table'),
|
||||
$servoMixTableBody = $servoMixTable.find('tbody');
|
||||
|
||||
/*
|
||||
* Process servo mix table UI
|
||||
*/
|
||||
var rules = SERVO_RULES.get();
|
||||
$servoMixTableBody.find("*").remove();
|
||||
for (servoRuleIndex in rules) {
|
||||
if (rules.hasOwnProperty(servoRuleIndex)) {
|
||||
const servoRule = rules[servoRuleIndex];
|
||||
|
||||
$servoMixTableBody.append('\
|
||||
<tr>\
|
||||
<td><input type="number" class="mix-rule-servo" step="1" min="0" max="7" /></td>\
|
||||
<td><select class="mix-rule-input"></select></td>\
|
||||
<td><input type="number" class="mix-rule-rate" step="1" min="-100" max="100" /></td>\
|
||||
<td><input type="number" class="mix-rule-speed" step="1" min="0" max="255" /></td>\
|
||||
<td><span class="btn default_btn narrow"><a href="#" data-role="role-delete" data-i18n="servoMixerDelete"></a></span></td>\
|
||||
</tr>\
|
||||
');
|
||||
|
||||
const $row = $servoMixTableBody.find('tr:last');
|
||||
|
||||
GUI.fillSelect($row.find(".mix-rule-input"), FC.getServoMixInputNames(), servoRule.getInput());
|
||||
|
||||
$row.find(".mix-rule-input").val(servoRule.getInput()).change(function () {
|
||||
servoRule.setInput($(this).val());
|
||||
});
|
||||
|
||||
$row.find(".mix-rule-servo").val(servoRule.getTarget()).change(function () {
|
||||
servoRule.setTarget($(this).val());
|
||||
});
|
||||
|
||||
$row.find(".mix-rule-rate").val(servoRule.getRate()).change(function () {
|
||||
servoRule.setRate($(this).val());
|
||||
});
|
||||
|
||||
$row.find(".mix-rule-speed").val(servoRule.getSpeed()).change(function () {
|
||||
servoRule.setSpeed($(this).val());
|
||||
});
|
||||
|
||||
$row.find("[data-role='role-delete']").attr("data-index", servoRuleIndex);
|
||||
}
|
||||
|
||||
}
|
||||
localize();
|
||||
}
|
||||
|
||||
function update_ui() {
|
||||
|
||||
var i,
|
||||
$tabServos = $(".tab-servos");
|
||||
$tabServos = $(".tab-servos"),
|
||||
$servoConfigTable = $('#servo-config-table'),
|
||||
$servoMixTable = $('#servo-mix-table'),
|
||||
$servoMixTableBody = $servoMixTable.find('tbody');
|
||||
|
||||
if (SERVO_CONFIG.length == 0) {
|
||||
$tabServos.removeClass("supported");
|
||||
$tabServos.addClass("is-hidden");
|
||||
return;
|
||||
}
|
||||
|
||||
$tabServos.addClass("supported");
|
||||
|
||||
var servoCheckbox = '';
|
||||
var servoHeader = '';
|
||||
for (i = 0; i < RC.active_channels-4; i++) {
|
||||
servoHeader = servoHeader + '<th class="short">CH' + (i+5) + '</th>';
|
||||
for (i = 0; i < RC.active_channels - 4; i++) {
|
||||
servoHeader = servoHeader + '<th class="short">CH' + (i + 5) + '</th>';
|
||||
}
|
||||
servoHeader = servoHeader + '<th data-i18n="servosDirectionAndRate"></th>';
|
||||
|
||||
|
@ -54,18 +112,16 @@ TABS.servos.initialize = function (callback) {
|
|||
servoCheckbox = servoCheckbox + '<td class="channel"><input type="checkbox"/></td>';
|
||||
}
|
||||
|
||||
$('div.tab-servos table.fields tr.main').append(servoHeader);
|
||||
$servoConfigTable.find('tr.main').append(servoHeader);
|
||||
|
||||
function process_servos(name, alternate, obj) {
|
||||
|
||||
$('div.supported_wrapper').show();
|
||||
|
||||
$('div.tab-servos table.fields').append('\
|
||||
$servoConfigTable.append('\
|
||||
<tr> \
|
||||
<td style="text-align: center">' + name + '</td>\
|
||||
<td class="middle"><input type="number" min="500" max="2500" value="' + SERVO_CONFIG[obj].middle + '" /></td>\
|
||||
<td class="min"><input type="number" min="500" max="2500" value="' + SERVO_CONFIG[obj].min +'" /></td>\
|
||||
<td class="max"><input type="number" min="500" max="2500" value="' + SERVO_CONFIG[obj].max +'" /></td>\
|
||||
<td class="min"><input type="number" min="500" max="2500" value="' + SERVO_CONFIG[obj].min + '" /></td>\
|
||||
<td class="max"><input type="number" min="500" max="2500" value="' + SERVO_CONFIG[obj].max + '" /></td>\
|
||||
' + servoCheckbox + '\
|
||||
<td class="direction">\
|
||||
</td>\
|
||||
|
@ -73,13 +129,13 @@ TABS.servos.initialize = function (callback) {
|
|||
');
|
||||
|
||||
if (SERVO_CONFIG[obj].indexOfChannelToForward >= 0) {
|
||||
$('div.tab-servos table.fields tr:last td.channel input').eq(SERVO_CONFIG[obj].indexOfChannelToForward).prop('checked', true);
|
||||
$servoConfigTable.find('tr:last td.channel input').eq(SERVO_CONFIG[obj].indexOfChannelToForward).prop('checked', true);
|
||||
}
|
||||
|
||||
// adding select box and generating options
|
||||
$('div.tab-servos table.fields tr:last td.direction').append('<select class="rate" name="rate"></select>');
|
||||
$servoConfigTable.find('tr:last td.direction').append('<select class="rate" name="rate"></select>');
|
||||
|
||||
var select = $('div.tab-servos table.fields tr:last td.direction select');
|
||||
var select = $servoConfigTable.find('tr:last td.direction select');
|
||||
|
||||
for (var i = FC.MAX_SERVO_RATE; i >= FC.MIN_SERVO_RATE; i--) {
|
||||
select.append('<option value="' + i + '">Rate: ' + i + '%</option>');
|
||||
|
@ -88,20 +144,20 @@ TABS.servos.initialize = function (callback) {
|
|||
// select current rate
|
||||
select.val(SERVO_CONFIG[obj].rate);
|
||||
|
||||
$('div.tab-servos table.fields tr:last').data('info', {'obj': obj});
|
||||
$servoConfigTable.find('tr:last').data('info', { 'obj': obj });
|
||||
|
||||
// UI hooks
|
||||
|
||||
// only one checkbox for indicating a channel to forward can be selected at a time, perhaps a radio group would be best here.
|
||||
$('div.tab-servos table.fields tr:last td.channel input').click(function () {
|
||||
if($(this).is(':checked')) {
|
||||
$servoConfigTable.find('tr:last td.channel input').click(function () {
|
||||
if ($(this).is(':checked')) {
|
||||
$(this).parent().parent().find('.channel input').not($(this)).prop('checked', false);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
function servos_update(save_configuration_to_eeprom) {
|
||||
$('div.tab-servos table.fields tr:not(".main")').each(function () {
|
||||
$servoConfigTable.find('tr:not(".main")').each(function () {
|
||||
var info = $(this).data('info');
|
||||
|
||||
|
||||
|
@ -113,42 +169,28 @@ TABS.servos.initialize = function (callback) {
|
|||
|
||||
SERVO_CONFIG[info.obj].indexOfChannelToForward = channelIndex;
|
||||
|
||||
|
||||
SERVO_CONFIG[info.obj].middle = parseInt($('.middle input', this).val());
|
||||
SERVO_CONFIG[info.obj].min = parseInt($('.min input', this).val());
|
||||
SERVO_CONFIG[info.obj].max = parseInt($('.max input', this).val());
|
||||
SERVO_CONFIG[info.obj].rate = parseInt($('.direction select', this).val());
|
||||
});
|
||||
|
||||
//
|
||||
// send data to FC
|
||||
//
|
||||
//FIXME investigate why the same frame is sent twice
|
||||
mspHelper.sendServoConfigurations(send_servo_mixer_rules);
|
||||
|
||||
function send_servo_mixer_rules() {
|
||||
mspHelper.sendServoConfigurations(save_to_eeprom);
|
||||
}
|
||||
|
||||
function save_to_eeprom() {
|
||||
if (save_configuration_to_eeprom) {
|
||||
MSP.send_message(MSPCodes.MSP_EEPROM_WRITE, false, false, function () {
|
||||
GUI.log(chrome.i18n.getMessage('servosEepromSave'));
|
||||
});
|
||||
}
|
||||
}
|
||||
//Save configuration to FC
|
||||
SERVO_RULES.cleanup();
|
||||
SERVO_RULES.inflate();
|
||||
saveChainer.execute();
|
||||
|
||||
}
|
||||
|
||||
// drop previous table
|
||||
$('div.tab-servos table.fields tr:not(:first)').remove();
|
||||
$servoConfigTable.find('tr:not(:first)').remove();
|
||||
|
||||
for (var servoIndex = 0; servoIndex < 8; servoIndex++) {
|
||||
process_servos('Servo ' + servoIndex, '', servoIndex, false);
|
||||
}
|
||||
|
||||
// UI hooks for dynamically generated elements
|
||||
$('table.directions select, table.directions input, table.fields select, table.fields input').change(function () {
|
||||
$('table.directions select, table.directions input, #servo-config-table select, #servo-config-table input').change(function () {
|
||||
if ($('div.live input').is(':checked')) {
|
||||
// apply small delay as there seems to be some funky update business going wrong
|
||||
helper.timeout.add('servos_update', servos_update, 10);
|
||||
|
@ -159,6 +201,19 @@ TABS.servos.initialize = function (callback) {
|
|||
servos_update(true);
|
||||
});
|
||||
|
||||
$servoMixTableBody.on('click', "[data-role='role-delete']", function (event) {
|
||||
SERVO_RULES.drop($(event.currentTarget).attr("data-index"));
|
||||
renderServoMixRules();
|
||||
});
|
||||
|
||||
$("[data-role='role-add']").click(function () {
|
||||
if (SERVO_RULES.hasFreeSlots()) {
|
||||
SERVO_RULES.put(new ServoMixRule(0, 0, 0, 0));
|
||||
renderServoMixRules();
|
||||
}
|
||||
});
|
||||
|
||||
renderServoMixRules();
|
||||
}
|
||||
|
||||
function process_html() {
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue