1
0
Fork 0
mirror of https://github.com/betaflight/betaflight-configurator.git synced 2025-07-25 01:05:15 +03:00

Preparing RX and PID tab for rework

This commit is contained in:
skaman82 2015-11-03 01:02:41 +01:00
parent 5506a3277c
commit 98d8eea7f7
9 changed files with 984 additions and 14 deletions

View file

@ -326,7 +326,7 @@ height:21px;
}
.tab-configuration .mixerPreview {
max-width:234px;
max-width:230px;
background-color: #eeeeee;
text-align: center;
float:left;

View file

@ -121,4 +121,32 @@
}
.tab-pid_tuning .top-buttons {
float:right;
}
.tab-pid_tuning .fixed_band {
position: fixed;
bottom: 0px;
width: calc(100% - 0px);
background-color: #e4e4e4;
height: 50px;
box-shadow: rgba(0,0,0,0.00) 0 -3px 8px;
margin-bottom: 0px;
}
@media only screen and (max-width: 1055px), only screen and (max-device-width: 1055px) {
.tab-pid_tuning .fixed_band {
width: calc(100% - -10px);
bottom: 0px;
}
.tab-pid_tuning .fixed_band .save_btn a {
margin-right:10px;
}
}

View file

@ -179,8 +179,9 @@
</form>
<div class="clear-both"></div>
<div class="fixed_band">
<div class="save_btn"><a class="update" href="#" i18n="pidTuningButtonSave"></a>
<a class="refresh" href="#" i18n="pidTuningButtonRefresh"></a>
<div class="save_btn">
<a class="update" href="#" i18n="pidTuningButtonSave"></a>
<a class="refresh" href="#" i18n="pidTuningButtonRefresh"></a>
</div>
</div>
</div>

View file

@ -118,12 +118,14 @@ table.ports tr:first-child td:last-child { border-top-right-radius: 0px; }
position: relative;
height: 50px;
background-color: #e4e4e4;
width: calc(100% -20px);
margin-left: 0px;
width: calc(100% - -10px);
margin-left: -10px;
box-shadow: rgba(0,0,0,0.00) 0 -3px 8px;
bottom: 0px;
margin-bottom: 0px;
}
.tab-ports .fixed_band .save_btn a {
margin-right:10px;
}
}

345
tabs/receiver Kopie.css Normal file
View file

@ -0,0 +1,345 @@
.tab-receiver {
}
.tab-receiver input[type="number"]::-webkit-inner-spin-button {
border: 0;
}
.tab-receiver .help {
padding: 10px;
background-color: #ffcb18;
margin-bottom: 10px;
}
.tab-receiver .bars {
float: left;
width: 45%;
font-weight: bold;
}
.tab-receiver .bars ul {
margin-bottom: 5px;
clear: left;
}
.tab-receiver .bars li {
float: left;
height: 22px;
line-height: 20px;
white-space: nowrap;
}
.tab-receiver .bars .name {
padding: 0 10px 0 0;
width: 50px;
text-align: right;
}
.tab-receiver .bars .meter {
width: calc(100% - 60px);
}
.tab-receiver .bars .meter-bar {
position: relative;
margin-top: 2px;
width: 100%;
height: 15px;
border: 1px solid silver;
background-color: #f4f4f4;
}
.tab-receiver .bars .meter-bar .label {
position: absolute;
width: 50px;
height: 15px;
line-height: 15px;
text-align: center;
color: #474747;
}
.tab-receiver .bars .meter-bar .fill {
position: relative;
overflow: hidden;
width: 50%;
height: 15px;
background-color: green;
}
.tab-receiver .bars .meter-bar .fill .label {
color: white;
}
.tab-receiver .bars ul:nth-of-type(1) .fill {
background-color: #00A8F0;
}
.tab-receiver .bars ul:nth-of-type(2) .fill {
background-color: #C0D800;
}
.tab-receiver .bars ul:nth-of-type(3) .fill {
background-color: #f8921a;
}
.tab-receiver .bars ul:nth-of-type(4) .fill {
background-color: #f02525;
}
.tab-receiver .bars ul:nth-of-type(5) .fill {
background-color: #9440ED;
}
.tab-receiver .bars ul:nth-of-type(6) .fill {
background-color: #45147a;
}
.tab-receiver .bars ul:nth-of-type(7) .fill {
background-color: #cf7a26;
}
.tab-receiver .bars ul:nth-of-type(8) .fill {
background-color: #147a66;
}
.tab-receiver .bars ul:nth-of-type(9) .fill {
background-color: #0609a9;
}
.tab-receiver .bars ul:nth-of-type(10) .fill {
background-color: #7a1445;
}
.tab-receiver .bars ul:nth-of-type(11) .fill {
background-color: #267acf;
}
.tab-receiver .bars ul:nth-of-type(12) .fill {
background-color: #7a6614;
}
.tab-receiver .bars ul:nth-of-type(13) .fill {
background-color: #cf267d;
}
.tab-receiver .bars ul:nth-of-type(14) .fill {
background-color: #7a1464;
}
.tab-receiver .bars ul:nth-of-type(15) .fill {
background-color: #3a7a14;
}
.tab-receiver .bars ul:nth-of-type(16) .fill {
background-color: #14407a;
}
.tab-receiver .tunings {
float: right;
}
.tab-receiver .tunings table {
border-collapse: collapse;
}
.tab-receiver .tunings .throttle {
margin-bottom: 10px;
}
.tab-receiver .tunings .rate {
margin-bottom: 10px;
}
.tab-receiver .tunings .yaw_rate {
margin-left: 127px;
margin-bottom: 10px;
}
.tab-receiver .tunings table, .tab-receiver .tunings table th, .tab-receiver .tunings table td {
padding: 4px;
border: 1px solid #8b8b8b;
}
.tab-receiver .tunings table th {
width: 118px;
}
.tab-receiver .tunings table td {
padding: 1px;
}
.tab-receiver .tunings table tr:nth-child(odd) {
background-color: #ececec;
}
.tab-receiver .tunings table input {
width: 100%;
height: 20px;
line-height: 20px;
text-align: right;
}
.tab-receiver .rssi_channel_wrapper {
float: right;
margin: 10px 0 0 0;
width: 126px;
border: 1px solid #8b8b8b;
border-left: 0;
}
.tab-receiver .rssi_channel_wrapper .head {
height: 15px;
padding: 4px;
text-align: center;
font-weight: bold;
border-bottom: 1px solid #8b8b8b;
background-color: #ececec;
}
.tab-receiver .rssi_channel_wrapper select {
width: 100%;
height: 22px;
padding-left: 5px;
}
.tab-receiver .rcmap_wrapper {
float: right;
position: relative;
margin: 10px 0 0 0;
width: 126px;
border: 1px solid #8b8b8b;
}
.tab-receiver .rcmap_wrapper .head {
height: 15px;
padding: 4px;
text-align: center;
font-weight: bold;
border-bottom: 1px solid #8b8b8b;
background-color: #ececec;
}
.tab-receiver .rcmap_wrapper .head span {
border-bottom: 1px dashed silver;
}
.tab-receiver .hybrid_element input {
position: absolute;
padding-left: 5px;
width: calc(100% - 24px);
height: 22px;
z-index: 2;
}
.tab-receiver .hybrid_element select {
width: 100%;
height: 22px;
z-index: 1;
}
.tab-receiver .curves {
float: right;
}
.tab-receiver .throttle_curve {
margin: 0 10px 10px 0;
width: 220px;
height: 120px;
border: 1px solid silver;
}
.tab-receiver .pitch_roll_curve {
margin: 0 10px 0 0;
width: 220px;
height: 120px;
border: 1px solid silver;
}
.tab-receiver select[name="rx_refresh_rate"] {
float: right;
border: 1px solid silver;
}
.tab-receiver #RX_plot {
width: 100%;
height: 200px;
}
.tab-receiver #RX_plot .line:nth-child(1) {
stroke: #00A8F0;
}
.tab-receiver #RX_plot .line:nth-child(2) {
stroke: #C0D800;
}
.tab-receiver #RX_plot .line:nth-child(3) {
stroke: #f8921a;
}
.tab-receiver #RX_plot .line:nth-child(4) {
stroke: #f02525;
}
.tab-receiver #RX_plot .line:nth-child(5) {
stroke: #9440ED;
}
.tab-receiver #RX_plot .line:nth-child(6) {
stroke: #45147A;
}
.tab-receiver #RX_plot .line:nth-child(7) {
stroke: #CF7A26;
}
.tab-receiver #RX_plot .line:nth-child(8) {
stroke: #147A66;
}
.tab-receiver #RX_plot .line:nth-child(9) {
stroke: #0609a9;
}
.tab-receiver #RX_plot .line:nth-child(10) {
stroke: #7a1445;
}
.tab-receiver #RX_plot .line:nth-child(11) {
stroke: #267acf;
}
.tab-receiver #RX_plot .line:nth-child(12) {
stroke: #7a6614;
}
.tab-receiver #RX_plot .line:nth-child(13) {
stroke: #cf267d;
}
.tab-receiver #RX_plot .line:nth-child(14) {
stroke: #7a1464;
}
.tab-receiver #RX_plot .line:nth-child(15) {
stroke: #3a7a14;
}
.tab-receiver #RX_plot .line:nth-child(16) {
stroke: #14407a;
}
.tab-receiver .buttons {
width: calc(100% - 20px);
position: absolute;
bottom: 10px;
}
.tab-receiver .sticks,
.tab-receiver .update,
.tab-receiver .refresh {
display: block;
float: right;
margin-top: 22px;
height: 28px;
line-height: 28px;
padding: 0 15px 0 15px;
text-align: center;
font-weight: bold;
border: 1px solid silver;
background-color: #ececec;
}
.tab-receiver .sticks,
.tab-receiver .refresh {
margin-right: 10px;
}
.tab-receiver .update:hover,
.tab-receiver .refresh:hover {
background-color: #dedcdc;
}
/* SVG classes*/
.tab-receiver .grid .tick {
stroke: silver;
shape-rendering: crispEdges;
}
.tab-receiver .line {
stroke-width: 2px;
fill: none;
}
.tab-receiver .grid path {
stroke-width: 0;
}
.tab-receiver .axis path, .axis line {
fill: none;
stroke: #000;
shape-rendering: crispEdges;
}

91
tabs/receiver Kopie.html Normal file
View file

@ -0,0 +1,91 @@
<div id="content-watermark"></div>
<div class="tab-receiver">
<div class="help">
<p i18n="receiverHelp"></p>
</div>
<div class="bars">
</div>
<div class="tunings">
<table class="throttle">
<tr>
<th i18n="receiverThrottleMid"></th>
<th i18n="receiverThrottleExpo"></th>
</tr>
<tr>
<td><input type="number" name="mid" step="0.01" min="0" max="1" /></td>
<td><input type="number" name="expo" step="0.01" min="0" max="1" /></td>
</tr>
</table>
<table class="rate">
<tr>
<th i18n="receiverRcRate"></th>
<th i18n="receiverRcExpo"></th>
</tr>
<tr>
<td><input type="number" name="rate" step="0.01" min="0" max="2.5" /></td>
<td><input type="number" name="expo" step="0.01" min="0" max="1" /></td>
</tr>
</table>
<table class="yaw_rate">
<tr>
<th i18n="receiverRcYawExpo"></th>
</tr>
<tr>
<td><input type="number" name="yaw_expo" step="0.01" min="0" max="1" /></td>
</tr>
</table>
<div class="rssi_channel_wrapper">
<div class="head" i18n="receiverRssiChannel"></div>
<select name="rssi_channel">
<!-- list generated here -->
</select>
</div>
<div class="rcmap_wrapper">
<div class="head">
<span i18n="receiverChannelMap" i18n_title="receiverChannelMapTitle"></span>
</div>
<div class="hybrid_element">
<input type="text" name="rcmap" spellcheck="false" />
<select class="hybrid_helper" name="rcmap_helper">
<option value="AETR1234">Default</option>
<option value="AETR1234">Futaba / Hitec</option>
<option value="TAER1234">JR / Spektrum / Graupner</option>
</select>
</div>
</div>
</div>
<div class="curves">
<div class="throttle_curve">
<canvas width="220" height="120"></canvas>
</div>
<div class="pitch_roll_curve">
<canvas width="220" height="120"></canvas>
</div>
</div>
<div class="clear-both"></div>
<select name="rx_refresh_rate" i18n_title="receiverRefreshRateTitle">
<option value="10">10 ms</option>
<option value="20">20 ms</option>
<option value="30">30 ms</option>
<option value="40">40 ms</option>
<option value="50" selected="selected">50 ms</option>
<option value="100">100 ms</option>
<option value="250">250 ms</option>
<option value="500">500 ms</option>
<option value="1000">1000 ms</option>
</select>
<div class="clear-both"></div>
<svg id="RX_plot">
<g class="grid x" transform="translate(40, 180)"></g>
<g class="grid y" transform="translate(40, 10)"></g>
<g class="data" transform="translate(41, 1)"></g>
<g class="axis x" transform="translate(40, 180)"></g>
<g class="axis y" transform="translate(40, 10)"></g>
</svg>
<div class="buttons">
<a class="update" href="#" i18n="receiverButtonSave"></a>
<a class="refresh" href="#" i18n="receiverButtonRefresh"></a>
<a class="sticks" href="#" i18n="receiverButtonSticks"></a>
</div>
</div>

467
tabs/receiver Kopie.js Normal file
View file

@ -0,0 +1,467 @@
'use strict';
TABS.receiver = {
rateChartHeight: 120
};
TABS.receiver.initialize = function (callback) {
var self = this;
if (GUI.active_tab != 'receiver') {
GUI.active_tab = 'receiver';
googleAnalytics.sendAppView('Receiver');
}
function get_misc_data() {
MSP.send_message(MSP_codes.MSP_MISC, false, false, get_rc_data);
}
function get_rc_data() {
MSP.send_message(MSP_codes.MSP_RC, false, false, get_rc_map);
}
function get_rc_map() {
MSP.send_message(MSP_codes.MSP_RX_MAP, false, false, load_config);
}
// Fetch features so we can check if RX_MSP is enabled:
function load_config() {
MSP.send_message(MSP_codes.MSP_BF_CONFIG, false, false, load_html);
}
function load_html() {
$('#content').load("./tabs/receiver.html", process_html);
}
MSP.send_message(MSP_codes.MSP_RC_TUNING, false, false, get_misc_data);
function process_html() {
// translate to user-selected language
localize();
// fill in data from RC_tuning
$('.tunings .throttle input[name="mid"]').val(RC_tuning.throttle_MID.toFixed(2));
$('.tunings .throttle input[name="expo"]').val(RC_tuning.throttle_EXPO.toFixed(2));
$('.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();
}
chrome.storage.local.get('rx_refresh_rate', function (result) {
if (result.rx_refresh_rate) {
$('select[name="rx_refresh_rate"]').val(result.rx_refresh_rate).change();
} else {
$('select[name="rx_refresh_rate"]').change(); // start with default value
}
});
// generate bars
var bar_names = [
chrome.i18n.getMessage('controlAxisRoll'),
chrome.i18n.getMessage('controlAxisPitch'),
chrome.i18n.getMessage('controlAxisYaw'),
chrome.i18n.getMessage('controlAxisThrottle')
],
bar_container = $('.tab-receiver .bars'),
aux_index = 1;
for (var i = 0; i < RC.active_channels; i++) {
var name;
if (i < bar_names.length) {
name = bar_names[i];
} else {
name = chrome.i18n.getMessage("controlAxisAux" + (aux_index++));
}
bar_container.append('\
<ul>\
<li class="name">' + name + '</li>\
<li class="meter">\
<div class="meter-bar">\
<div class="label"></div>\
<div class="fill">\
<div class="label"></div>\
</div>\
</div>\
</li>\
</ul>\
');
}
// we could probably use min and max throttle for the range, will see
var meter_scale = {
'min': 800,
'max': 2200
};
var meter_fill_array = [];
$('.meter .fill', bar_container).each(function () {
meter_fill_array.push($(this));
});
var meter_label_array = [];
$('.meter', bar_container).each(function () {
meter_label_array.push($('.label' , this));
});
// correct inner label margin on window resize (i don't know how we could do this in css)
self.resize = function () {
var containerWidth = $('.meter:first', bar_container).width(),
labelWidth = $('.meter .label:first', bar_container).width(),
margin = (containerWidth / 2) - (labelWidth / 2);
for (var i = 0; i < meter_label_array.length; i++) {
meter_label_array[i].css('margin-left', margin);
}
};
$(window).on('resize', self.resize).resize(); // trigger so labels get correctly aligned on creation
// handle rcmap & rssi aux channel
var RC_MAP_Letters = ['A', 'E', 'R', 'T', '1', '2', '3', '4'];
var strBuffer = [];
for (var i = 0; i < RC_MAP.length; i++) {
strBuffer[RC_MAP[i]] = RC_MAP_Letters[i];
}
// reconstruct
var str = strBuffer.join('');
// set current value
$('input[name="rcmap"]').val(str);
// validation / filter
var last_valid = str;
$('input[name="rcmap"]').on('input', function () {
var val = $(this).val();
// limit length to max 8
if (val.length > 8) {
val = val.substr(0, 8);
$(this).val(val);
}
});
$('input[name="rcmap"]').focusout(function () {
var val = $(this).val(),
strBuffer = val.split(''),
duplicityBuffer = [];
if (val.length != 8) {
$(this).val(last_valid);
return false;
}
// check if characters inside are all valid, also check for duplicity
for (var i = 0; i < val.length; i++) {
if (RC_MAP_Letters.indexOf(strBuffer[i]) < 0) {
$(this).val(last_valid);
return false;
}
if (duplicityBuffer.indexOf(strBuffer[i]) < 0) {
duplicityBuffer.push(strBuffer[i]);
} else {
$(this).val(last_valid);
return false;
}
}
});
// handle helper
$('select[name="rcmap_helper"]').val(0); // go out of bounds
$('select[name="rcmap_helper"]').change(function () {
$('input[name="rcmap"]').val($(this).val());
});
// rssi
var rssi_channel_e = $('select[name="rssi_channel"]');
rssi_channel_e.append('<option value="0">Disabled</option>');
for (var i = 0; i < RC.active_channels; i++) {
rssi_channel_e.append('<option value="' + i + '">' + i + '</option>');
}
$('select[name="rssi_channel"]').val(MISC.rssi_channel);
var rateHeight = TABS.receiver.rateChartHeight;
// UI Hooks
// curves
$('.tunings .throttle input').on('input change', function () {
setTimeout(function () { // let global validation trigger and adjust the values first
var throttleMidE = $('.tunings .throttle input[name="mid"]'),
throttleExpoE = $('.tunings .throttle input[name="expo"]'),
mid = parseFloat(throttleMidE.val()),
expo = parseFloat(throttleExpoE.val()),
throttle_curve = $('.throttle_curve canvas').get(0),
context = throttle_curve.getContext("2d");
// local validation to deal with input event
if (mid >= parseFloat(throttleMidE.prop('min')) &&
mid <= parseFloat(throttleMidE.prop('max')) &&
expo >= parseFloat(throttleExpoE.prop('min')) &&
expo <= parseFloat(throttleExpoE.prop('max'))) {
// continue
} else {
return;
}
// math magic by englishman
var midx = 220 * mid,
midxl = midx * 0.5,
midxr = (((220 - midx) * 0.5) + midx),
midy = rateHeight - (midx * (rateHeight / 220)),
midyl = rateHeight - ((rateHeight - midy) * 0.5 *(expo + 1)),
midyr = (midy / 2) * (expo + 1);
// draw
context.clearRect(0, 0, 220, rateHeight);
context.beginPath();
context.moveTo(0, rateHeight);
context.quadraticCurveTo(midxl, midyl, midx, midy);
context.moveTo(midx, midy);
context.quadraticCurveTo(midxr, midyr, 220, 0);
context.lineWidth = 2;
context.stroke();
}, 0);
}).trigger('input');
$('.tunings .rate input').on('input change', function () {
setTimeout(function () { // let global validation trigger and adjust the values first
var rateE = $('.tunings .rate input[name="rate"]'),
expoE = $('.tunings .rate input[name="expo"]'),
rate = parseFloat(rateE.val()),
expo = parseFloat(expoE.val()),
pitch_roll_curve = $('.pitch_roll_curve canvas').get(0),
context = pitch_roll_curve.getContext("2d");
// local validation to deal with input event
if (rate >= parseFloat(rateE.prop('min')) &&
rate <= parseFloat(rateE.prop('max')) &&
expo >= parseFloat(expoE.prop('min')) &&
expo <= parseFloat(expoE.prop('max'))) {
// continue
} else {
return;
}
// math magic by englishman
var ratey = rateHeight * rate;
// draw
context.clearRect(0, 0, 220, rateHeight);
context.beginPath();
context.moveTo(0, rateHeight);
context.quadraticCurveTo(110, rateHeight - ((ratey / 2) * (1 - expo)), 220, rateHeight - ratey);
context.lineWidth = 2;
context.stroke();
}, 0);
}).trigger('input');
$('a.refresh').click(function () {
MSP.send_message(MSP_codes.MSP_RC_TUNING, false, false, function () {
GUI.log(chrome.i18n.getMessage('receiverDataRefreshed'));
// fill in data from RC_tuning
$('.tunings .throttle input[name="mid"]').val(RC_tuning.throttle_MID.toFixed(2));
$('.tunings .throttle input[name="expo"]').val(RC_tuning.throttle_EXPO.toFixed(2));
$('.tunings .rate input[name="rate"]').val(RC_tuning.RC_RATE.toFixed(2));
$('.tunings .rate input[name="expo"]').val(RC_tuning.RC_EXPO.toFixed(2));
// update visual representation
$('.tunings .throttle input').change();
$('.tunings .rate input').change();
});
});
$('a.update').click(function () {
// catch RC_tuning changes
RC_tuning.throttle_MID = parseFloat($('.tunings .throttle input[name="mid"]').val());
RC_tuning.throttle_EXPO = parseFloat($('.tunings .throttle input[name="expo"]').val());
RC_tuning.RC_RATE = parseFloat($('.tunings .rate input[name="rate"]').val());
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());
// catch rc map
var RC_MAP_Letters = ['A', 'E', 'R', 'T', '1', '2', '3', '4'];
var strBuffer = $('input[name="rcmap"]').val().split('');
for (var i = 0; i < RC_MAP.length; i++) {
RC_MAP[i] = strBuffer.indexOf(RC_MAP_Letters[i]);
}
// catch rssi aux
MISC.rssi_channel = parseInt($('select[name="rssi_channel"]').val());
function save_rc_map() {
MSP.send_message(MSP_codes.MSP_SET_RX_MAP, MSP.crunch(MSP_codes.MSP_SET_RX_MAP), false, save_misc);
}
function save_misc() {
MSP.send_message(MSP_codes.MSP_SET_MISC, MSP.crunch(MSP_codes.MSP_SET_MISC), false, save_to_eeprom);
}
function save_to_eeprom() {
MSP.send_message(MSP_codes.MSP_EEPROM_WRITE, false, false, function () {
GUI.log(chrome.i18n.getMessage('receiverEepromSaved'));
});
}
MSP.send_message(MSP_codes.MSP_SET_RC_TUNING, MSP.crunch(MSP_codes.MSP_SET_RC_TUNING), false, save_rc_map);
});
$("a.sticks").click(function() {
var
windowWidth = 370,
windowHeight = 510;
chrome.app.window.create("/tabs/receiver_msp.html", {
id: "receiver_msp",
innerBounds: {
minWidth: windowWidth, minHeight: windowHeight,
width: windowWidth, height: windowHeight,
maxWidth: windowWidth, maxHeight: windowHeight
},
alwaysOnTop: true
}, function(createdWindow) {
// Give the window a callback it can use to send the channels (otherwise it can't see those objects)
createdWindow.contentWindow.setRawRx = function(channels) {
if (CONFIGURATOR.connectionValid && GUI.active_tab != 'cli') {
MSP.setRawRx(channels);
return true;
} else {
return false;
}
}
});
});
// Only show the MSP control sticks if the MSP Rx feature is enabled
$("a.sticks").toggle(bit_check(BF_CONFIG.features, 14 /* RX_MSP */));
$('select[name="rx_refresh_rate"]').change(function () {
var plot_update_rate = parseInt($(this).val(), 10);
// save update rate
chrome.storage.local.set({'rx_refresh_rate': plot_update_rate});
function get_rc_data() {
MSP.send_message(MSP_codes.MSP_RC, false, false, update_ui);
}
// setup plot
var RX_plot_data = new Array(RC.active_channels);
for (var i = 0; i < RX_plot_data.length; i++) {
RX_plot_data[i] = [];
}
var samples = 0,
svg = d3.select("svg"),
RX_plot_e = $('#RX_plot'),
margin = {top: 20, right: 0, bottom: 10, left: 40},
width, height, widthScale, heightScale;
function update_receiver_plot_size() {
width = RX_plot_e.width() - margin.left - margin.right;
height = RX_plot_e.height() - margin.top - margin.bottom;
widthScale.range([0, width]);
heightScale.range([height, 0]);
}
function update_ui() {
// update bars with latest data
for (var i = 0; i < RC.active_channels; i++) {
meter_fill_array[i].css('width', ((RC.channels[i] - meter_scale.min) / (meter_scale.max - meter_scale.min) * 100).clamp(0, 100) + '%');
meter_label_array[i].text(RC.channels[i]);
}
// push latest data to the main array
for (var i = 0; i < RC.active_channels; i++) {
RX_plot_data[i].push([samples, RC.channels[i]]);
}
// Remove old data from array
while (RX_plot_data[0].length > 300) {
for (var i = 0; i < RX_plot_data.length; i++) {
RX_plot_data[i].shift();
}
}
// update required parts of the plot
widthScale = d3.scale.linear().
domain([(samples - 299), samples]);
heightScale = d3.scale.linear().
domain([800, 2200]);
update_receiver_plot_size();
var xGrid = d3.svg.axis().
scale(widthScale).
orient("bottom").
tickSize(-height, 0, 0).
tickFormat("");
var yGrid = d3.svg.axis().
scale(heightScale).
orient("left").
tickSize(-width, 0, 0).
tickFormat("");
var xAxis = d3.svg.axis().
scale(widthScale).
orient("bottom").
tickFormat(function (d) {return d;});
var yAxis = d3.svg.axis().
scale(heightScale).
orient("left").
tickFormat(function (d) {return d;});
var line = d3.svg.line().
x(function (d) {return widthScale(d[0]);}).
y(function (d) {return heightScale(d[1]);});
svg.select(".x.grid").call(xGrid);
svg.select(".y.grid").call(yGrid);
svg.select(".x.axis").call(xAxis);
svg.select(".y.axis").call(yAxis);
var data = svg.select("g.data"),
lines = data.selectAll("path").data(RX_plot_data, function (d, i) {return i;}),
newLines = lines.enter().append("path").attr("class", "line");
lines.attr('d', line);
samples++;
}
// timer initialization
GUI.interval_remove('receiver_pull');
// enable RC data pulling
GUI.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(MSP_codes.MSP_STATUS);
}, 250, true);
if (callback) callback();
}
};
TABS.receiver.cleanup = function (callback) {
$(window).off('resize', this.resize);
if (callback) callback();
};

View file

@ -343,3 +343,31 @@
stroke: #000;
shape-rendering: crispEdges;
}
.tab-receiver .fixed_band {
position: fixed;
bottom: 0px;
width: calc(100% - 0px);
background-color: #e4e4e4;
height: 50px;
box-shadow: rgba(0,0,0,0.00) 0 -3px 8px;
margin-bottom: 0px;
}
@media only screen and (max-width: 1055px), only screen and (max-device-width: 1055px) {
.tab-receiver .fixed_band {
width: calc(100% - -10px);
bottom: 0px;
}
.tab-receiver .fixed_band .save_btn a {
margin-right:10px;
}
}

View file

@ -1,9 +1,13 @@
<div id="content-watermark"></div>
<div class="tab-receiver">
<div class="help">
<div class="tab_title" i18n="tabPorts">Ports</div>
<div class="cf_doc_version_bt">
<a id="button-documentation" href="https://github.com/cleanflight/cleanflight/releases" target="_blank"></a>
</div>
<div class="note" style="margin-bottom:20px;">
<div class="note_spacer">
<p i18n="receiverHelp"></p>
</div>
</div>
</div>
<div class="bars">
</div>
<div class="tunings">
@ -83,9 +87,13 @@
<g class="axis x" transform="translate(40, 180)"></g>
<g class="axis y" transform="translate(40, 10)"></g>
</svg>
<div class="buttons">
<a class="update" href="#" i18n="receiverButtonSave"></a>
<div class="fixed_band">
<div class="save_btn">
<a class="update" href="#" i18n="receiverButtonSave"></a>
<a class="refresh" href="#" i18n="receiverButtonRefresh"></a>
<a class="sticks" href="#" i18n="receiverButtonSticks"></a>
</div>
</div>
</div>
</div>
</div>