1
0
Fork 0
mirror of https://github.com/iNavFlight/inav-configurator.git synced 2025-07-21 15:25:19 +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:
afinogen 2018-01-29 13:55:20 +03:00
commit db31180753
17 changed files with 466 additions and 128 deletions

View file

@ -735,6 +735,15 @@
"configurationSPIProtocol": { "configurationSPIProtocol": {
"message": "RX SPI protocol" "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": { "configurationEepromSaved": {
"message": "EEPROM <span style=\"color: #37a8db\">saved</span>" "message": "EEPROM <span style=\"color: #37a8db\">saved</span>"
}, },
@ -1130,10 +1139,6 @@
"transponderEepromSaved": { "transponderEepromSaved": {
"message": "EEPROM <span style=\"color: #37a8db\">saved</span>" "message": "EEPROM <span style=\"color: #37a8db\">saved</span>"
}, },
"servosFirmwareUpgradeRequired": {
"message": "Servos requires firmware &gt;= 1.10.0. and target support."
},
"servosChangeDirection": { "servosChangeDirection": {
"message": "Change Direction in TX To Match" "message": "Change Direction in TX To Match"
}, },
@ -2320,6 +2325,7 @@
"downloadUpdatesBtn": { "downloadUpdatesBtn": {
"message": "Download new app" "message": "Download new app"
}, },
<<<<<<< HEAD
"tabMissionControl": { "tabMissionControl": {
"message": "Mission Control" "message": "Mission Control"
}, },
@ -2358,5 +2364,14 @@
}, },
"confirm_delete_all_points": { "confirm_delete_all_points": {
"message": "Do you really want to 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"
} }
} }

View file

@ -90,6 +90,8 @@ sources.js = [
'./js/localization.js', './js/localization.js',
'./js/boards.js', './js/boards.js',
'./js/tasks.js', './js/tasks.js',
'./js/servoMixRule.js',
'./js/servoMixRuleCollection.js',
'./main.js', './main.js',
'./tabs/*.js', './tabs/*.js',
'./js/eventFrequencyAnalyzer.js', './js/eventFrequencyAnalyzer.js',

View file

@ -151,7 +151,7 @@ var FC = {
ADJUSTMENT_RANGES = []; ADJUSTMENT_RANGES = [];
SERVO_CONFIG = []; SERVO_CONFIG = [];
SERVO_RULES = []; SERVO_RULES = new ServoMixRuleCollection();
SERIAL_CONFIG = { SERIAL_CONFIG = {
ports: [], ports: [],
@ -950,5 +950,27 @@ var FC = {
}, },
getRcMapLetters: function () { getRcMapLetters: function () {
return ['A', 'E', 'R', 'T', '5', '6', '7', '8']; 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];
} }
}; };

View file

@ -2,29 +2,29 @@
// generate mixer // generate mixer
var mixerList = [ var mixerList = [
{name: 'Tricopter', model: 'tricopter', image: 'tri'}, // 1 {name: 'Tricopter', model: 'tricopter', image: 'tri', hasCustomServoMixer: false}, // 1
{name: 'Quad +', model: 'quad_x', image: 'quad_p'}, // 2 {name: 'Quad +', model: 'quad_x', image: 'quad_p', hasCustomServoMixer: false}, // 2
{name: 'Quad X', model: 'quad_x', image: 'quad_x'}, // 3 {name: 'Quad X', model: 'quad_x', image: 'quad_x', hasCustomServoMixer: false}, // 3
{name: 'Bicopter', model: 'custom', image: 'bicopter'}, // 4 {name: 'Bicopter', model: 'custom', image: 'bicopter', hasCustomServoMixer: false}, // 4
{name: 'Gimbal', model: 'custom', image: 'custom'}, // 5 {name: 'Gimbal', model: 'custom', image: 'custom', hasCustomServoMixer: false}, // 5
{name: 'Y6', model: 'y6', image: 'y6'}, // 6 {name: 'Y6', model: 'y6', image: 'y6', hasCustomServoMixer: false}, // 6
{name: 'Hex +', model: 'hex_plus', image: 'hex_p'}, // 7 {name: 'Hex +', model: 'hex_plus', image: 'hex_p', hasCustomServoMixer: false}, // 7
{name: 'Flying Wing', model: 'custom', image: 'flying_wing'}, // 8 {name: 'Flying Wing', model: 'custom', image: 'flying_wing', hasCustomServoMixer: false}, // 8
{name: 'Y4', model: 'y4', image: 'y4'}, // 9 {name: 'Y4', model: 'y4', image: 'y4', hasCustomServoMixer: false}, // 9
{name: 'Hex X', model: 'hex_x', image: 'hex_x'}, // 10 {name: 'Hex X', model: 'hex_x', image: 'hex_x', hasCustomServoMixer: false}, // 10
{name: 'Octo X8', model: 'custom', image: 'octo_x8'}, // 11 {name: 'Octo X8', model: 'custom', image: 'octo_x8', hasCustomServoMixer: false}, // 11
{name: 'Octo Flat +', model: 'custom', image: 'octo_flat_p'}, // 12 {name: 'Octo Flat +', model: 'custom', image: 'octo_flat_p', hasCustomServoMixer: false}, // 12
{name: 'Octo Flat X', model: 'custom', image: 'octo_flat_x'}, // 13 {name: 'Octo Flat X', model: 'custom', image: 'octo_flat_x', hasCustomServoMixer: false}, // 13
{name: 'Airplane', model: 'custom', image: 'airplane'}, // 14 {name: 'Airplane', model: 'custom', image: 'airplane', hasCustomServoMixer: false}, // 14
{name: 'Heli 120', model: 'custom', image: 'custom'}, // 15 {name: 'Heli 120', model: 'custom', image: 'custom', hasCustomServoMixer: false}, // 15
{name: 'Heli 90', model: 'custom', image: 'custom'}, // 16 {name: 'Heli 90', model: 'custom', image: 'custom', hasCustomServoMixer: false}, // 16
{name: 'V-tail Quad', model: 'quad_vtail', image: 'vtail_quad'}, // 17 {name: 'V-tail Quad', model: 'quad_vtail', image: 'vtail_quad', hasCustomServoMixer: false}, // 17
{name: 'Hex H', model: 'custom', image: 'custom'}, // 18 {name: 'Hex H', model: 'custom', image: 'custom', hasCustomServoMixer: false}, // 18
{name: 'PPM to SERVO', model: 'custom', image: 'custom'}, // 19 {name: 'PPM to SERVO', model: 'custom', image: 'custom', hasCustomServoMixer: false}, // 19
{name: 'Dualcopter', model: 'custom', image: 'custom'}, // 20 {name: 'Dualcopter', model: 'custom', image: 'custom', hasCustomServoMixer: false}, // 20
{name: 'Singlecopter', model: 'custom', image: 'custom'}, // 21 {name: 'Singlecopter', model: 'custom', image: 'custom', hasCustomServoMixer: false}, // 21
{name: 'A-tail Quad', model: 'quad_atail', image: 'atail_quad'}, // 22 {name: 'A-tail Quad', model: 'quad_atail', image: 'atail_quad', hasCustomServoMixer: false}, // 22
{name: 'Custom', model: 'custom', image: 'custom'}, // 23 {name: 'Custom', model: 'custom', image: 'custom', hasCustomServoMixer: true}, // 23
{name: 'Custom Airplane', model: 'custom', image: 'custom'}, // 24 {name: 'Custom Airplane', model: 'custom', image: 'custom', hasCustomServoMixer: true}, // 24
{name: 'Custom Tricopter', model: 'custom', image: 'custom'} // 25 {name: 'Custom Tricopter', model: 'custom', image: 'custom', hasCustomServoMixer: true} // 25
]; ];

View file

@ -10,6 +10,9 @@ var MSPCodes = {
MSP_INAV_PID: 6, MSP_INAV_PID: 6,
MSP_SET_INAV_PID: 7, MSP_SET_INAV_PID: 7,
MSP_NAME: 10,
MSP_SET_NAME: 11,
MSP_NAV_POSHOLD: 12, MSP_NAV_POSHOLD: 12,
MSP_SET_NAV_POSHOLD: 13, MSP_SET_NAV_POSHOLD: 13,
MSP_CALIBRATION_DATA: 14, MSP_CALIBRATION_DATA: 14,

View file

@ -355,6 +355,20 @@ var mspHelper = (function (gui) {
} }
break; break;
case MSPCodes.MSP_SERVO_MIX_RULES: 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; break;
case MSPCodes.MSP_SERVO_CONFIGURATIONS: case MSPCodes.MSP_SERVO_CONFIGURATIONS:
@ -1106,6 +1120,11 @@ var mspHelper = (function (gui) {
case MSPCodes.MSP_OSD_CHAR_WRITE: case MSPCodes.MSP_OSD_CHAR_WRITE:
console.log('OSD char uploaded'); console.log('OSD char uploaded');
break; break;
case MSPCodes.MSP_NAME:
break;
case MSPCodes.MSP_SET_NAME:
console.log("Craft name set");
break;
case MSPCodes.MSPV2_SETTING: case MSPCodes.MSPV2_SETTING:
break; break;
case MSPCodes.MSPV2_SET_SETTING: case MSPCodes.MSPV2_SET_SETTING:
@ -1693,7 +1712,6 @@ var mspHelper = (function (gui) {
nextFunction(); nextFunction();
} }
function send_next_servo_configuration() { function send_next_servo_configuration() {
var buffer = []; var buffer = [];
@ -1736,24 +1754,41 @@ var mspHelper = (function (gui) {
} }
MSP.send_message(MSPCodes.MSP_SET_SERVO_CONFIGURATION, buffer, false, nextFunction); MSP.send_message(MSPCodes.MSP_SET_SERVO_CONFIGURATION, buffer, false, nextFunction);
} }
};
//FIXME looks like this is not used and not ever implemented self.sendServoMixer = function (onCompleteCallback) {
//noinspection JSUnusedLocalSymbols var nextFunction = sendMixer,
function send_channel_forwarding() { servoIndex = 0;
if (SERVO_RULES.length == 0) {
onCompleteCallback();
} else {
nextFunction();
}
function sendMixer() {
var buffer = []; var buffer = [];
for (var i = 0; i < SERVO_CONFIG.length; i++) { // send one at a time, with index
var out = SERVO_CONFIG[i].indexOfChannelToForward;
if (out == undefined) {
out = 255; // Cleanflight defines "CHANNEL_FORWARDING_DISABLED" as "(uint8_t)0xFF"
}
buffer.push(out);
}
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; 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; return self;
})(GUI); })(GUI);

View file

@ -9,7 +9,7 @@ var MSPChainerClass = function () {
self.exitPoint = null; self.exitPoint = null;
self.chainIndex = 0; self.chainIndex = 0;
self.setChain = function(chain) { self.setChain = function (chain) {
self.chain = chain; self.chain = chain;
}; };
@ -21,12 +21,12 @@ var MSPChainerClass = function () {
self.chainIndex++; self.chainIndex++;
if (self.chain[self.chainIndex]) { if (self.chain[self.chainIndex]) {
self.chain[self.chainIndex](self.returnCallback); self.chain[self.chainIndex](self.returnCallback);
} else { } else if (self.exitPoint) {
self.exitPoint(); self.exitPoint();
} }
}; };
self.execute = function() { self.execute = function () {
self.chainIndex = 0; self.chainIndex = 0;
self.chain[self.chainIndex](self.returnCallback); self.chain[self.chainIndex](self.returnCallback);
}; };

45
js/servoMixRule.js Normal file
View 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;
};

View 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;
};

View file

@ -1326,6 +1326,15 @@ dialog {
float: left; float: left;
} }
.default_btn.narrow {
width: auto;
margin-bottom: 0;
}
.default_btn.narrow a {
padding: 5px;
}
.default_btn a { .default_btn a {
padding: 5px 0 5px 0; padding: 5px 0 5px 0;
text-align: center; text-align: center;

View file

@ -20,9 +20,8 @@
font-weight: bold; font-weight: bold;
} }
.config-section .number input, .config-section input,
.tab-configuration .number input { .tab-configuration input {
width: 65px;
padding-left: 3px; padding-left: 3px;
height: 20px; height: 20px;
line-height: 20px; line-height: 20px;
@ -34,8 +33,17 @@
font-weight: normal; font-weight: normal;
} }
.tab-configuration .number .disabled { .config-section .number input,
.tab-configuration .number input {
width: 65px; width: 65px;
}
.config-section .string input,
.tab-configuration .string input {
width: 130px;
}
.tab-configuration .disabled {
background-color: #ececec; background-color: #ececec;
} }
@ -226,6 +234,10 @@ hr {
left: 2em; left: 2em;
} }
.config-section .string label {
left: 175px;
}
.config-section .radio input { .config-section .radio input {
margin-top: 3px; margin-top: 3px;
margin-left: 5px; margin-left: 5px;

View file

@ -50,7 +50,16 @@
background-color: #f9f9f9; 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-left: 1px solid #e4e4e4;
border-right: 1px solid #e4e4e4; border-right: 1px solid #e4e4e4;
background-color: #828885; background-color: #828885;
@ -154,22 +163,6 @@
bottom: 10px; 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 { .tab-servos .live span {
margin-right: 10px; margin-right: 10px;
} }

View file

@ -212,6 +212,21 @@
</div> </div>
</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> </div>
<!--Right column begins here--> <!--Right column begins here-->

View file

@ -10,6 +10,18 @@ TABS.configuration.initialize = function (callback, scrollPosition) {
googleAnalytics.sendAppView('Configuration'); 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(); var loadChainer = new MSPChainerClass();
loadChainer.setChain([ loadChainer.setChain([
@ -22,7 +34,8 @@ TABS.configuration.initialize = function (callback, scrollPosition) {
mspHelper.loadSensorAlignment, mspHelper.loadSensorAlignment,
mspHelper.loadAdvancedConfig, mspHelper.loadAdvancedConfig,
mspHelper.loadINAVPidConfig, mspHelper.loadINAVPidConfig,
mspHelper.loadSensorConfig mspHelper.loadSensorConfig,
loadCraftName
]); ]);
loadChainer.setExitPoint(load_html); loadChainer.setExitPoint(load_html);
loadChainer.execute(); loadChainer.execute();
@ -41,6 +54,7 @@ TABS.configuration.initialize = function (callback, scrollPosition) {
mspHelper.saveAdvancedConfig, mspHelper.saveAdvancedConfig,
mspHelper.saveINAVPidConfig, mspHelper.saveINAVPidConfig,
mspHelper.saveSensorConfig, mspHelper.saveSensorConfig,
saveCraftName,
mspHelper.saveToEeprom mspHelper.saveToEeprom
]); ]);
saveChainer.setExitPoint(reboot); 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 () { $('a.save').click(function () {
// gather data that doesn't have automatic change event bound // 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_acc = parseInt(orientation_acc_e.val());
SENSOR_ALIGNMENT.align_mag = parseInt(orientation_mag_e.val()); SENSOR_ALIGNMENT.align_mag = parseInt(orientation_mag_e.val());
craftName = $('input[name="craft_name"]').val();
var rxTypes = FC.getRxTypes(); var rxTypes = FC.getRxTypes();
function is_using_rx_type(name) { function is_using_rx_type(name) {

View file

@ -421,7 +421,7 @@ OSD.constants = {
{ {
name: 'FLYMODE', name: 'FLYMODE',
id: 7, id: 7,
preview: 'STAB' preview: 'ACRO'
}, },
{ {
name: 'MESSAGES', name: 'MESSAGES',

View file

@ -1,13 +1,12 @@
<!--suppress HtmlFormInputWithoutLabel -->
<div class="tab-servos toolbar_fixed_bottom"> <div class="tab-servos toolbar_fixed_bottom">
<div class="content_wrapper"> <div class="content_wrapper">
<div class="tab_title" data-i18n="tabServos">Servos</div> <div class="tab_title" data-i18n="tabServos">Servos</div>
<div class="cf_doc_version_bt"> <div class="cf_doc_version_bt">
<a id="button-documentation" href="" target="_blank"></a> <a id="button-documentation" href="" target="_blank"></a>
</div> </div>
<div class="require-support"> <div>
<div class="title" data-i18n="servosChangeDirection"></div> <div class="title" data-i18n="servosChangeDirection"></div>
<table class="fields"> <table id="servo-config-table" class="fields">
<tr class="main"> <tr class="main">
<th width="110px" data-i18n="servosName"></th> <th width="110px" data-i18n="servosName"></th>
<th data-i18n="servosMid"></th> <th data-i18n="servosMid"></th>
@ -23,9 +22,28 @@
<input type="checkbox" class="togglemedium" /> <span data-i18n="servosLiveMode"></span> <input type="checkbox" class="togglemedium" /> <span data-i18n="servosLiveMode"></span>
</div> </div>
</div> </div>
<div class="note require-upgrade"> <div class="clear-both"></div>
<div class="note_spacer"> <div id="servo-mix-table-wrapper" class="margin-top">
<p data-i18n="servosFirmwareUpgradeRequired"></p> <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> </div>
</div> </div>

View file

@ -9,44 +9,102 @@ TABS.servos.initialize = function (callback) {
googleAnalytics.sendAppView('Servos'); googleAnalytics.sendAppView('Servos');
} }
function get_servo_configurations() { var loadChainer = new MSPChainerClass();
MSP.send_message(MSPCodes.MSP_SERVO_CONFIGURATIONS, false, false, get_servo_mix_rules);
}
function get_servo_mix_rules() { loadChainer.setChain([
MSP.send_message(MSPCodes.MSP_SERVO_MIX_RULES, false, false, get_rc_data); mspHelper.loadServoConfiguration,
} mspHelper.loadRcData,
mspHelper.loadBfConfig,
mspHelper.loadServoMixRules
]);
loadChainer.setExitPoint(load_html);
loadChainer.execute();
function get_rc_data() { var saveChainer = new MSPChainerClass();
MSP.send_message(MSPCodes.MSP_RC, false, false, get_boxnames_data);
}
function get_boxnames_data() { saveChainer.setChain([
MSP.send_message(MSPCodes.MSP_BOXNAMES, false, false, load_html); mspHelper.sendServoConfigurations,
} mspHelper.sendServoMixer,
mspHelper.saveToEeprom
]);
saveChainer.setExitPoint(function () {
GUI.log(chrome.i18n.getMessage('servosEepromSave'));
SERVO_RULES.cleanup();
renderServoMixRules();
});
function load_html() { function load_html() {
$('#content').load("./tabs/servos.html", process_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() { function update_ui() {
var i, 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) { if (SERVO_CONFIG.length == 0) {
$tabServos.removeClass("supported"); $tabServos.addClass("is-hidden");
return; return;
} }
$tabServos.addClass("supported");
var servoCheckbox = ''; var servoCheckbox = '';
var servoHeader = ''; var servoHeader = '';
for (i = 0; i < RC.active_channels-4; i++) { for (i = 0; i < RC.active_channels - 4; i++) {
servoHeader = servoHeader + '<th class="short">CH' + (i+5) + '</th>'; servoHeader = servoHeader + '<th class="short">CH' + (i + 5) + '</th>';
} }
servoHeader = servoHeader + '<th data-i18n="servosDirectionAndRate"></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>'; 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) { function process_servos(name, alternate, obj) {
$('div.supported_wrapper').show(); $servoConfigTable.append('\
$('div.tab-servos table.fields').append('\
<tr> \ <tr> \
<td style="text-align: center">' + name + '</td>\ <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="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="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="max"><input type="number" min="500" max="2500" value="' + SERVO_CONFIG[obj].max + '" /></td>\
' + servoCheckbox + '\ ' + servoCheckbox + '\
<td class="direction">\ <td class="direction">\
</td>\ </td>\
@ -73,13 +129,13 @@ TABS.servos.initialize = function (callback) {
'); ');
if (SERVO_CONFIG[obj].indexOfChannelToForward >= 0) { 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 // 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--) { for (var i = FC.MAX_SERVO_RATE; i >= FC.MIN_SERVO_RATE; i--) {
select.append('<option value="' + i + '">Rate: ' + i + '%</option>'); select.append('<option value="' + i + '">Rate: ' + i + '%</option>');
@ -88,20 +144,20 @@ TABS.servos.initialize = function (callback) {
// select current rate // select current rate
select.val(SERVO_CONFIG[obj].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 // 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. // 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 () { $servoConfigTable.find('tr:last td.channel input').click(function () {
if($(this).is(':checked')) { if ($(this).is(':checked')) {
$(this).parent().parent().find('.channel input').not($(this)).prop('checked', false); $(this).parent().parent().find('.channel input').not($(this)).prop('checked', false);
} }
}); });
} }
function servos_update(save_configuration_to_eeprom) { 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'); var info = $(this).data('info');
@ -113,42 +169,28 @@ TABS.servos.initialize = function (callback) {
SERVO_CONFIG[info.obj].indexOfChannelToForward = channelIndex; SERVO_CONFIG[info.obj].indexOfChannelToForward = channelIndex;
SERVO_CONFIG[info.obj].middle = parseInt($('.middle input', this).val()); SERVO_CONFIG[info.obj].middle = parseInt($('.middle input', this).val());
SERVO_CONFIG[info.obj].min = parseInt($('.min 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].max = parseInt($('.max input', this).val());
SERVO_CONFIG[info.obj].rate = parseInt($('.direction select', this).val()); SERVO_CONFIG[info.obj].rate = parseInt($('.direction select', this).val());
}); });
// //Save configuration to FC
// send data to FC SERVO_RULES.cleanup();
// SERVO_RULES.inflate();
//FIXME investigate why the same frame is sent twice saveChainer.execute();
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'));
});
}
}
} }
// drop previous table // 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++) { for (var servoIndex = 0; servoIndex < 8; servoIndex++) {
process_servos('Servo ' + servoIndex, '', servoIndex, false); process_servos('Servo ' + servoIndex, '', servoIndex, false);
} }
// UI hooks for dynamically generated elements // 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')) { if ($('div.live input').is(':checked')) {
// apply small delay as there seems to be some funky update business going wrong // apply small delay as there seems to be some funky update business going wrong
helper.timeout.add('servos_update', servos_update, 10); helper.timeout.add('servos_update', servos_update, 10);
@ -159,6 +201,19 @@ TABS.servos.initialize = function (callback) {
servos_update(true); 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() { function process_html() {