1
0
Fork 0
mirror of https://github.com/iNavFlight/inav-configurator.git synced 2025-07-15 12:25:13 +03:00

whitespace trimming run

This commit is contained in:
cTn 2014-03-08 06:25:15 +01:00
parent 0607ccbff4
commit 9b29f78e3e
44 changed files with 1208 additions and 1208 deletions

View file

@ -1,11 +1,11 @@
/* /*
resizable: false - Keep in mind this only disables the side/corner resizing via mouse, nothing more resizable: false - Keep in mind this only disables the side/corner resizing via mouse, nothing more
maxWidth / maxHeight - is defined to prevent application reaching maximized state through window manager maxWidth / maxHeight - is defined to prevent application reaching maximized state through window manager
We are setting Bounds through setBounds method after window was created because on linux setting Bounds as We are setting Bounds through setBounds method after window was created because on linux setting Bounds as
window.create property seemed to fail, probably because "previous" bounds was used instead according to docs. window.create property seemed to fail, probably because "previous" bounds was used instead according to docs.
bounds - Size and position of the content in the window (excluding the titlebar). bounds - Size and position of the content in the window (excluding the titlebar).
If an id is also specified and a window with a matching id has been shown before, the remembered bounds of the window will be used instead. If an id is also specified and a window with a matching id has been shown before, the remembered bounds of the window will be used instead.
*/ */
function start_app() { function start_app() {
@ -16,19 +16,19 @@ function start_app() {
}, function(createdWindow) { }, function(createdWindow) {
// set window size // set window size
createdWindow.setBounds({'width': 962, 'height': 650}); createdWindow.setBounds({'width': 962, 'height': 650});
// bind events // bind events
createdWindow.onMaximized.addListener(function() { createdWindow.onMaximized.addListener(function() {
createdWindow.restore(); createdWindow.restore();
}); });
createdWindow.onClosed.addListener(function() { createdWindow.onClosed.addListener(function() {
// connectionId is passed from the script side through the chrome.runtime.getBackgroundPage refference // connectionId is passed from the script side through the chrome.runtime.getBackgroundPage refference
// allowing us to automatically close the port when application shut down // allowing us to automatically close the port when application shut down
// save connectionId in separate variable before app_window is destroyed // save connectionId in separate variable before app_window is destroyed
var connectionId = app_window.serial.connectionId; var connectionId = app_window.serial.connectionId;
if (connectionId > 0) { if (connectionId > 0) {
chrome.serial.disconnect(connectionId, function(result) { chrome.serial.disconnect(connectionId, function(result) {
console.log('SERIAL: Connection closed - ' + result); console.log('SERIAL: Connection closed - ' + result);
@ -43,8 +43,8 @@ chrome.app.runtime.onLaunched.addListener(function() {
}); });
chrome.runtime.onInstalled.addListener(function(details) { chrome.runtime.onInstalled.addListener(function(details) {
if (details.reason == 'update') { if (details.reason == 'update') {
var manifest = chrome.runtime.getManifest(); var manifest = chrome.runtime.getManifest();
var options = { var options = {
priority: 0, priority: 0,
type: 'basic', type: 'basic',
@ -53,7 +53,7 @@ chrome.runtime.onInstalled.addListener(function(details) {
iconUrl: '/images/icon_128.png', iconUrl: '/images/icon_128.png',
buttons: [{'title': 'Click this button to start the application'}] buttons: [{'title': 'Click this button to start the application'}]
}; };
chrome.notifications.create('baseflight_update', options, function(notificationId) { chrome.notifications.create('baseflight_update', options, function(notificationId) {
// empty // empty
}); });

View file

@ -21,15 +21,15 @@ a:hover {
} }
input[type="number"]::-webkit-inner-spin-button { input[type="number"]::-webkit-inner-spin-button {
-webkit-appearance: none; -webkit-appearance: none;
display: block; display: block;
opacity: 1; /* required for chromium 33+ beta */ opacity: 1; /* required for chromium 33+ beta */
width: 15px; width: 15px;
background-image: url('../images/arrows.png'); background-image: url('../images/arrows.png');
background-repeat: no-repeat; background-repeat: no-repeat;
border-left: 1px solid silver; border-left: 1px solid silver;
} }
.clear-both { .clear-both {
@ -47,44 +47,44 @@ input[type="number"]::-webkit-inner-spin-button {
#frame { #frame {
height: 25px; height: 25px;
line-height: 25px; line-height: 25px;
-webkit-app-region: drag; -webkit-app-region: drag;
background-color: white; background-color: white;
} }
#frame .title { #frame .title {
float: left; float: left;
margin-left: 15px; margin-left: 15px;
font-weight: bold; font-weight: bold;
/* text-shadow: 1px 1px #e4e4e4; */ /* text-shadow: 1px 1px #e4e4e4; */
} }
#frame .minimize { #frame .minimize {
float: right; float: right;
display: block; display: block;
width: 26px; width: 26px;
height: 20px; height: 20px;
background: url('../images/controls/minimize.png') no-repeat 0 0; background: url('../images/controls/minimize.png') no-repeat 0 0;
} }
#frame .maximize { #frame .maximize {
float: right; float: right;
display: block; display: block;
width: 27px; width: 27px;
height: 20px; height: 20px;
background: url('../images/controls/maximize.png') no-repeat 0 0; background: url('../images/controls/maximize.png') no-repeat 0 0;
} }
#frame .close { #frame .close {
float: right; float: right;
display: block; display: block;
width: 45px; width: 45px;
height: 20px; height: 20px;
background: url('../images/controls/close.png') no-repeat 0 0; background: url('../images/controls/close.png') no-repeat 0 0;
} }
#frame a { #frame a {
@ -93,7 +93,7 @@ input[type="number"]::-webkit-inner-spin-button {
} }
#frame a:hover { #frame a:hover {
/* hover is disabled untill webkit-app-region: drag; starts to fire events or chromium implements native frame */ /* hover is disabled untill webkit-app-region: drag; starts to fire events or chromium implements native frame */
/* background-position: 0px -20px; */ /* background-position: 0px -20px; */
} }
#frame a:active { #frame a:active {
background-position: 0px -40px; background-position: 0px -40px;
@ -101,12 +101,12 @@ input[type="number"]::-webkit-inner-spin-button {
#main-wrapper { #main-wrapper {
width: 940px; width: 940px;
margin: 10px auto 0 auto; margin: 10px auto 0 auto;
padding: 0 10px 0 10px; padding: 0 10px 0 10px;
} }
#port-picker { #port-picker {
float: left; float: left;
height: 22px; height: 22px;
margin-bottom: 10px; margin-bottom: 10px;
} }
@ -116,10 +116,10 @@ input[type="number"]::-webkit-inner-spin-button {
#port-picker select { #port-picker select {
height: 20px; height: 20px;
line-height: 20px; line-height: 20px;
float: left; float: left;
margin-right: 10px; margin-right: 10px;
border: 1px solid silver; border: 1px solid silver;
} }
#port-picker #port { #port-picker #port {
@ -133,19 +133,19 @@ input[type="number"]::-webkit-inner-spin-button {
} }
#port-picker a { #port-picker a {
float: left; float: left;
display: block; display: block;
width: 80px; width: 80px;
height: 18px; height: 18px;
border: 1px solid silver; border: 1px solid silver;
line-height: 18px; line-height: 18px;
text-align: center; text-align: center;
} }
#port-picker a.connect { #port-picker a.connect {
margin-right: 10px; margin-right: 10px;
background-color: #be2222; background-color: #be2222;
color: white; color: white;
} }
@ -161,32 +161,32 @@ input[type="number"]::-webkit-inner-spin-button {
} }
#port-picker input.auto_connect { #port-picker input.auto_connect {
float: left; float: left;
margin-top: 4px; margin-top: 4px;
} }
#port-picker span.auto_connect { #port-picker span.auto_connect {
float: left; float: left;
margin: 3px 0 0 5px; margin: 3px 0 0 5px;
} }
#sensor-status { #sensor-status {
float: right; float: right;
height: 22px; height: 22px;
line-height: 22px; line-height: 22px;
} }
#sensor-status li { #sensor-status li {
float: left; float: left;
margin-left: 10px; margin-left: 10px;
padding: 0 12px 0 12px; padding: 0 12px 0 12px;
height: 18px; height: 18px;
line-height: 18px; line-height: 18px;
color: white; color: white;
text-align: center; text-align: center;
border: 1px solid #c0c0c0; border: 1px solid #c0c0c0;
border-radius: 8px; border-radius: 8px;
background-color: #be2222; background-color: #be2222;
@ -194,45 +194,45 @@ input[type="number"]::-webkit-inner-spin-button {
#sensor-status .on { #sensor-status .on {
background-color: #0d8b13; background-color: #0d8b13;
} }
#log { #log {
margin-bottom: 10px; margin-bottom: 10px;
height: 60px; height: 60px;
border: 1px solid silver; border: 1px solid silver;
background-color: white; background-color: white;
overflow-y: scroll; overflow-y: scroll;
} }
#log .wrapper { #log .wrapper {
padding: 5px; padding: 5px;
-webkit-user-select: text; -webkit-user-select: text;
} }
#tabs { #tabs {
position: absolute; position: absolute;
margin-top: 1px; margin-top: 1px;
z-index: 10; z-index: 10;
font-weight: bold; font-weight: bold;
} }
#tabs li { #tabs li {
float: left; float: left;
margin-right: 5px; margin-right: 5px;
border: 1px solid #848484; border: 1px solid #848484;
border-bottom: 0; border-bottom: 0;
} }
#tabs li a { #tabs li a {
display: block; display: block;
height: 15px; height: 15px;
padding: 5px; padding: 5px;
padding-left: 12px; padding-left: 12px;
padding-right: 12px; padding-right: 12px;
background-color: #d0d0d0; background-color: #d0d0d0;
} }
#tabs li a:hover { #tabs li a:hover {
@ -243,38 +243,38 @@ input[type="number"]::-webkit-inner-spin-button {
} }
#tabs li.active a { #tabs li.active a {
height: 16px; height: 16px;
background-color: white; background-color: white;
} }
#tabs li.active a:hover { #tabs li.active a:hover {
cursor: default; cursor: default;
background-color: white; background-color: white;
} }
#content { #content {
margin-top: 37px; margin-top: 37px;
padding: 10px; padding: 10px;
background-color: white; background-color: white;
height: 429px; height: 429px;
overflow-x: hidden; overflow-x: hidden;
overflow-y: auto; overflow-y: auto;
border: 1px solid #848484; border: 1px solid #848484;
-webkit-transform: rotateX(0deg); /* DO NOT REMOVE! this fixes the UI freezing bug on MAC OS X */ -webkit-transform: rotateX(0deg); /* DO NOT REMOVE! this fixes the UI freezing bug on MAC OS X */
} }
#status-bar { #status-bar {
margin-left: -10px; margin-left: -10px;
margin-top: 10px; margin-top: 10px;
width: 940px; width: 940px;
height: 20px; height: 20px;
line-height: 20px; line-height: 20px;
padding: 0 10px 0 10px; padding: 0 10px 0 10px;
border-top: 1px solid #7d7d79; border-top: 1px solid #7d7d79;
background-color: #bfbeb5; background-color: #bfbeb5;
} }

View file

@ -17,27 +17,27 @@ function configuration_backup() {
}); });
}); });
}); });
var backup = function() { var backup = function() {
var chosenFileEntry = null; var chosenFileEntry = null;
var accepts = [{ var accepts = [{
extensions: ['txt'] extensions: ['txt']
}]; }];
// generate timestamp for the backup file // generate timestamp for the backup file
var d = new Date(); var d = new Date();
var now = d.getUTCFullYear() + '.' + d.getDate() + '.' + (d.getMonth() + 1) + '.' + d.getHours() + '.' + d.getMinutes(); var now = d.getUTCFullYear() + '.' + d.getDate() + '.' + (d.getMonth() + 1) + '.' + d.getHours() + '.' + d.getMinutes();
// create or load the file // create or load the file
chrome.fileSystem.chooseEntry({type: 'saveFile', suggestedName: 'bf_mw_backup_' + now, accepts: accepts}, function(fileEntry) { chrome.fileSystem.chooseEntry({type: 'saveFile', suggestedName: 'bf_mw_backup_' + now, accepts: accepts}, function(fileEntry) {
if (!fileEntry) { if (!fileEntry) {
console.log('No file selected, backup aborted.'); console.log('No file selected, backup aborted.');
return; return;
} }
chosenFileEntry = fileEntry; chosenFileEntry = fileEntry;
// echo/console log path specified // echo/console log path specified
chrome.fileSystem.getDisplayPath(chosenFileEntry, function(path) { chrome.fileSystem.getDisplayPath(chosenFileEntry, function(path) {
@ -50,7 +50,7 @@ function configuration_backup() {
chrome.fileSystem.isWritableEntry(fileEntryWritable, function(isWritable) { chrome.fileSystem.isWritableEntry(fileEntryWritable, function(isWritable) {
if (isWritable) { if (isWritable) {
chosenFileEntry = fileEntryWritable; chosenFileEntry = fileEntryWritable;
// create config object that will be used to store all downloaded data // create config object that will be used to store all downloaded data
var configuration = { var configuration = {
'firmware_version': CONFIG.version, 'firmware_version': CONFIG.version,
@ -61,29 +61,29 @@ function configuration_backup() {
'AccelTrim': CONFIG.accelerometerTrims, 'AccelTrim': CONFIG.accelerometerTrims,
'MISC': MISC 'MISC': MISC
}; };
// crunch the config object // crunch the config object
var serialized_config_object = JSON.stringify(configuration); 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 var blob = new Blob([serialized_config_object], {type: 'text/plain'}); // first parameter for Blob needs to be an array
chosenFileEntry.createWriter(function(writer) { chosenFileEntry.createWriter(function(writer) {
writer.onerror = function (e) { writer.onerror = function (e) {
console.error(e); console.error(e);
}; };
var truncated = false; var truncated = false;
writer.onwriteend = function() { writer.onwriteend = function() {
if (!truncated) { if (!truncated) {
// onwriteend will be fired again when truncation is finished // onwriteend will be fired again when truncation is finished
truncated = true; truncated = true;
writer.truncate(blob.size); writer.truncate(blob.size);
return; return;
} }
console.log('Write SUCCESSFUL'); console.log('Write SUCCESSFUL');
}; };
writer.write(blob); writer.write(blob);
}, function (e) { }, function (e) {
console.error(e); console.error(e);
@ -100,25 +100,25 @@ function configuration_backup() {
function configuration_restore() { function configuration_restore() {
var chosenFileEntry = null; var chosenFileEntry = null;
var accepts = [{ var accepts = [{
extensions: ['txt'] extensions: ['txt']
}]; }];
// load up the file // load up the file
chrome.fileSystem.chooseEntry({type: 'openFile', accepts: accepts}, function(fileEntry) { chrome.fileSystem.chooseEntry({type: 'openFile', accepts: accepts}, function(fileEntry) {
if (!fileEntry) { if (!fileEntry) {
console.log('No file selected, restore aborted.'); console.log('No file selected, restore aborted.');
return; return;
} }
chosenFileEntry = fileEntry; chosenFileEntry = fileEntry;
// echo/console log path specified // echo/console log path specified
chrome.fileSystem.getDisplayPath(chosenFileEntry, function(path) { chrome.fileSystem.getDisplayPath(chosenFileEntry, function(path) {
console.log('Restore file path: ' + path); console.log('Restore file path: ' + path);
}); });
// read contents into variable // read contents into variable
chosenFileEntry.file(function(file) { chosenFileEntry.file(function(file) {
@ -131,31 +131,31 @@ function configuration_restore() {
reader.abort(); reader.abort();
} }
}; };
reader.onloadend = function(e) { reader.onloadend = function(e) {
if (e.total != 0 && e.total == e.loaded) { if (e.total != 0 && e.total == e.loaded) {
console.log('Read SUCCESSFUL'); console.log('Read SUCCESSFUL');
try { // check if string provided is a valid JSON try { // check if string provided is a valid JSON
var deserialized_configuration_object = JSON.parse(e.target.result); var deserialized_configuration_object = JSON.parse(e.target.result);
} catch (e) { } catch (e) {
// data provided != valid json object // data provided != valid json object
console.log('Data provided != valid JSON string, restore aborted.'); console.log('Data provided != valid JSON string, restore aborted.');
return; return;
} }
// replacing "old configuration" with configuration from backup file // replacing "old configuration" with configuration from backup file
var configuration = deserialized_configuration_object; var configuration = deserialized_configuration_object;
// some configuration.VERSION code goes here? will see // some configuration.VERSION code goes here? will see
PIDs = configuration.PID; PIDs = configuration.PID;
AUX_CONFIG_values = configuration.AUX_val; AUX_CONFIG_values = configuration.AUX_val;
RC_tuning = configuration.RC; RC_tuning = configuration.RC;
CONFIG.accelerometerTrims = configuration.AccelTrim; CONFIG.accelerometerTrims = configuration.AccelTrim;
MISC = configuration.MISC; MISC = configuration.MISC;
// all of the arrays/objects are set, upload changes // all of the arrays/objects are set, upload changes
configuration_upload(); configuration_upload();
} }
@ -177,11 +177,11 @@ function configuration_upload() {
var PID_buffer_needle = 0; var PID_buffer_needle = 0;
for (var i = 0; i < PIDs.length; i++) { for (var i = 0; i < PIDs.length; i++) {
switch (i) { switch (i) {
case 0: case 0:
case 1: case 1:
case 2: case 2:
case 3: case 3:
case 7: case 7:
case 8: case 8:
case 9: case 9:
PID_buffer_out[PID_buffer_needle] = parseInt(PIDs[i][0] * 10); PID_buffer_out[PID_buffer_needle] = parseInt(PIDs[i][0] * 10);
@ -193,20 +193,20 @@ function configuration_upload() {
PID_buffer_out[PID_buffer_needle + 1] = parseInt(PIDs[i][1] * 100); PID_buffer_out[PID_buffer_needle + 1] = parseInt(PIDs[i][1] * 100);
PID_buffer_out[PID_buffer_needle + 2] = parseInt(PIDs[i][2]); PID_buffer_out[PID_buffer_needle + 2] = parseInt(PIDs[i][2]);
break; break;
case 5: case 5:
case 6: case 6:
PID_buffer_out[PID_buffer_needle] = parseInt(PIDs[i][0] * 10); PID_buffer_out[PID_buffer_needle] = parseInt(PIDs[i][0] * 10);
PID_buffer_out[PID_buffer_needle + 1] = parseInt(PIDs[i][1] * 100); PID_buffer_out[PID_buffer_needle + 1] = parseInt(PIDs[i][1] * 100);
PID_buffer_out[PID_buffer_needle + 2] = parseInt(PIDs[i][2] * 1000); PID_buffer_out[PID_buffer_needle + 2] = parseInt(PIDs[i][2] * 1000);
break; break;
} }
PID_buffer_needle += 3; PID_buffer_needle += 3;
} }
// Send over the PID changes // Send over the PID changes
send_message(MSP_codes.MSP_SET_PID, PID_buffer_out, false, function() { send_message(MSP_codes.MSP_SET_PID, PID_buffer_out, false, function() {
rc_tuning(); rc_tuning();
}); });
var rc_tuning = function() { var rc_tuning = function() {
// RC Tuning section // RC Tuning section
@ -218,23 +218,23 @@ function configuration_upload() {
RC_tuning_buffer_out[4] = parseInt(RC_tuning.dynamic_THR_PID * 100); RC_tuning_buffer_out[4] = parseInt(RC_tuning.dynamic_THR_PID * 100);
RC_tuning_buffer_out[5] = parseInt(RC_tuning.throttle_MID * 100); RC_tuning_buffer_out[5] = parseInt(RC_tuning.throttle_MID * 100);
RC_tuning_buffer_out[6] = parseInt(RC_tuning.throttle_EXPO * 100); RC_tuning_buffer_out[6] = parseInt(RC_tuning.throttle_EXPO * 100);
// Send over the RC_tuning changes // Send over the RC_tuning changes
send_message(MSP_codes.MSP_SET_RC_TUNING, RC_tuning_buffer_out, false, function() { send_message(MSP_codes.MSP_SET_RC_TUNING, RC_tuning_buffer_out, false, function() {
aux(); aux();
}); });
}; };
var aux = function() { var aux = function() {
// AUX section // AUX section
var AUX_val_buffer_out = new Array(); var AUX_val_buffer_out = new Array();
var needle = 0; var needle = 0;
for (var i = 0; i < AUX_CONFIG_values.length; i++) { for (var i = 0; i < AUX_CONFIG_values.length; i++) {
AUX_val_buffer_out[needle++] = lowByte(AUX_CONFIG_values[i]); AUX_val_buffer_out[needle++] = lowByte(AUX_CONFIG_values[i]);
AUX_val_buffer_out[needle++] = highByte(AUX_CONFIG_values[i]); AUX_val_buffer_out[needle++] = highByte(AUX_CONFIG_values[i]);
} }
// Send over the AUX changes // Send over the AUX changes
send_message(MSP_codes.MSP_SET_BOX, AUX_val_buffer_out, false, function() { send_message(MSP_codes.MSP_SET_BOX, AUX_val_buffer_out, false, function() {
trim(); trim();
@ -248,7 +248,7 @@ function configuration_upload() {
buffer_out[0] = lowByte(CONFIG.accelerometerTrims[0]); buffer_out[0] = lowByte(CONFIG.accelerometerTrims[0]);
buffer_out[1] = highByte(CONFIG.accelerometerTrims[0]); buffer_out[1] = highByte(CONFIG.accelerometerTrims[0]);
buffer_out[2] = lowByte(CONFIG.accelerometerTrims[1]); buffer_out[2] = lowByte(CONFIG.accelerometerTrims[1]);
buffer_out[3] = highByte(CONFIG.accelerometerTrims[1]); buffer_out[3] = highByte(CONFIG.accelerometerTrims[1]);
// Send over the new trims // Send over the new trims
send_message(MSP_codes.MSP_SET_ACC_TRIM, buffer_out, false, function() { send_message(MSP_codes.MSP_SET_ACC_TRIM, buffer_out, false, function() {
@ -282,7 +282,7 @@ function configuration_upload() {
buffer_out[19] = MISC.vbatmincellvoltage; buffer_out[19] = MISC.vbatmincellvoltage;
buffer_out[20] = MISC.vbatmaxcellvoltage; buffer_out[20] = MISC.vbatmaxcellvoltage;
buffer_out[21] = 0; // vbatlevel_crit (unused) buffer_out[21] = 0; // vbatlevel_crit (unused)
// Send ove the new MISC // Send ove the new MISC
send_message(MSP_codes.MSP_SET_MISC, buffer_out, false, function() { send_message(MSP_codes.MSP_SET_MISC, buffer_out, false, function() {
// Save changes to EEPROM // Save changes to EEPROM
@ -290,5 +290,5 @@ function configuration_upload() {
GUI.log('EEPROM <span style="color: green">saved</span>'); GUI.log('EEPROM <span style="color: green">saved</span>');
}); });
}); });
}; };
} }

View file

@ -10,7 +10,7 @@ var CONFIG = {
activeSensors: 0, activeSensors: 0,
mode: 0, mode: 0,
profile: 0, profile: 0,
uid: [0, 0, 0], uid: [0, 0, 0],
accelerometerTrims: [0, 0] accelerometerTrims: [0, 0]
}; };
@ -71,7 +71,7 @@ var GPS_DATA = {
distanceToHome: 0, distanceToHome: 0,
ditectionToHome: 0, ditectionToHome: 0,
update: 0, update: 0,
// baseflight specific gps stuff // baseflight specific gps stuff
chn: new Array(), chn: new Array(),
svid: new Array(), svid: new Array(),

104
js/gui.js
View file

@ -6,7 +6,7 @@ var GUI_control = function() {
this.operating_system; this.operating_system;
this.interval_array = []; this.interval_array = [];
this.timeout_array = []; this.timeout_array = [];
// check which operating system is user running // check which operating system is user running
if (navigator.appVersion.indexOf("Win") != -1) this.operating_system = "Windows"; if (navigator.appVersion.indexOf("Win") != -1) this.operating_system = "Windows";
else if (navigator.appVersion.indexOf("Mac") != -1) this.operating_system = "MacOS"; else if (navigator.appVersion.indexOf("Mac") != -1) this.operating_system = "MacOS";
@ -23,19 +23,19 @@ var GUI_control = function() {
// first = true/false if code should be ran initially before next timer interval hits // first = true/false if code should be ran initially before next timer interval hits
GUI_control.prototype.interval_add = function(name, code, interval, first) { GUI_control.prototype.interval_add = function(name, code, interval, first) {
var data = {'name': name, 'timer': undefined, 'code': code, 'interval': interval, 'fired': 0, 'paused': false}; var data = {'name': name, 'timer': undefined, 'code': code, 'interval': interval, 'fired': 0, 'paused': false};
if (first == true) { if (first == true) {
code(); // execute code code(); // execute code
data.fired++; // increment counter data.fired++; // increment counter
} }
data.timer = setInterval(function() { data.timer = setInterval(function() {
code(); // execute code code(); // execute code
data.fired++; // increment counter data.fired++; // increment counter
}, interval); }, interval);
this.interval_array.push(data); // push to primary interval array this.interval_array.push(data); // push to primary interval array
}; };
@ -44,13 +44,13 @@ GUI_control.prototype.interval_remove = function(name) {
for (var i = 0; i < this.interval_array.length; i++) { for (var i = 0; i < this.interval_array.length; i++) {
if (this.interval_array[i].name == name) { if (this.interval_array[i].name == name) {
clearInterval(this.interval_array[i].timer); // stop timer clearInterval(this.interval_array[i].timer); // stop timer
this.interval_array.splice(i, 1); // remove element/object from array this.interval_array.splice(i, 1); // remove element/object from array
return true; return true;
} }
} }
return false; return false;
}; };
@ -60,11 +60,11 @@ GUI_control.prototype.interval_pause = function(name) {
if (this.interval_array[i].name == name) { if (this.interval_array[i].name == name) {
clearInterval(this.interval_array[i].timer); clearInterval(this.interval_array[i].timer);
this.interval_array[i].paused = true; this.interval_array[i].paused = true;
return true; return true;
} }
} }
return false; return false;
}; };
@ -73,19 +73,19 @@ GUI_control.prototype.interval_resume = function(name) {
for (var i = 0; i < this.interval_array.length; i++) { for (var i = 0; i < this.interval_array.length; i++) {
if (this.interval_array[i].name == name && this.interval_array[i].paused) { if (this.interval_array[i].name == name && this.interval_array[i].paused) {
var obj = this.interval_array[i]; var obj = this.interval_array[i];
obj.timer = setInterval(function() { obj.timer = setInterval(function() {
obj.code(); // execute code obj.code(); // execute code
obj.fired++; // increment counter obj.fired++; // increment counter
}, obj.interval); }, obj.interval);
obj.paused = false; obj.paused = false;
return true; return true;
} }
} }
return false; return false;
}; };
@ -94,7 +94,7 @@ GUI_control.prototype.interval_resume = function(name) {
GUI_control.prototype.interval_kill_all = function(keep_array) { GUI_control.prototype.interval_kill_all = function(keep_array) {
var self = this; var self = this;
var timers_killed = 0; var timers_killed = 0;
for (var i = (this.interval_array.length - 1); i >= 0; i--) { // reverse iteration for (var i = (this.interval_array.length - 1); i >= 0; i--) { // reverse iteration
var keep = false; var keep = false;
if (keep_array) { // only run through the array if it exists if (keep_array) { // only run through the array if it exists
@ -104,17 +104,17 @@ GUI_control.prototype.interval_kill_all = function(keep_array) {
} }
}); });
} }
if (!keep) { if (!keep) {
clearInterval(this.interval_array[i].timer); // stop timer clearInterval(this.interval_array[i].timer); // stop timer
this.interval_array[i].timer = undefined; // set timer property to undefined (mostly for debug purposes, but it doesn't hurt to have it here) this.interval_array[i].timer = undefined; // set timer property to undefined (mostly for debug purposes, but it doesn't hurt to have it here)
this.interval_array.splice(i, 1); // remove element/object from array this.interval_array.splice(i, 1); // remove element/object from array
timers_killed++; timers_killed++;
} }
} }
return timers_killed; return timers_killed;
}; };
@ -126,10 +126,10 @@ GUI_control.prototype.timeout_add = function(name, code, timeout) {
// start timer with "cleaning" callback // start timer with "cleaning" callback
var timer = setTimeout(function() { var timer = setTimeout(function() {
code(); // execute code code(); // execute code
self.timeout_remove(name); // cleanup self.timeout_remove(name); // cleanup
}, timeout); }, timeout);
this.timeout_array.push({'name': name, 'timer': timer, 'timeout': timeout}); // push to primary timeout array this.timeout_array.push({'name': name, 'timer': timer, 'timeout': timeout}); // push to primary timeout array
}; };
@ -138,13 +138,13 @@ GUI_control.prototype.timeout_remove = function(name) {
for (var i = 0; i < this.timeout_array.length; i++) { for (var i = 0; i < this.timeout_array.length; i++) {
if (this.timeout_array[i].name == name) { if (this.timeout_array[i].name == name) {
clearTimeout(this.timeout_array[i].timer); // stop timer clearTimeout(this.timeout_array[i].timer); // stop timer
this.timeout_array.splice(i, 1); // remove element/object from array this.timeout_array.splice(i, 1); // remove element/object from array
return true; return true;
} }
} }
return false; return false;
}; };
@ -152,15 +152,15 @@ GUI_control.prototype.timeout_remove = function(name) {
// return = returns timers killed in last call // return = returns timers killed in last call
GUI_control.prototype.timeout_kill_all = function() { GUI_control.prototype.timeout_kill_all = function() {
var timers_killed = 0; var timers_killed = 0;
for (var i = 0; i < this.timeout_array.length; i++) { for (var i = 0; i < this.timeout_array.length; i++) {
clearTimeout(this.timeout_array[i].timer); // stop timer clearTimeout(this.timeout_array[i].timer); // stop timer
timers_killed++; timers_killed++;
} }
this.timeout_array = []; // drop objects this.timeout_array = []; // drop objects
return timers_killed; return timers_killed;
}; };
@ -168,12 +168,12 @@ GUI_control.prototype.timeout_kill_all = function() {
GUI_control.prototype.log = function(message) { GUI_control.prototype.log = function(message) {
var command_log = $('div#log'); var command_log = $('div#log');
var d = new Date(); var d = new Date();
var time = ((d.getHours() < 10) ? '0' + d.getHours(): d.getHours()) var time = ((d.getHours() < 10) ? '0' + d.getHours(): d.getHours())
+ ':' + ((d.getMinutes() < 10) ? '0' + d.getMinutes(): d.getMinutes()) + ':' + ((d.getMinutes() < 10) ? '0' + d.getMinutes(): d.getMinutes())
+ ':' + ((d.getSeconds() < 10) ? '0' + d.getSeconds(): d.getSeconds()); + ':' + ((d.getSeconds() < 10) ? '0' + d.getSeconds(): d.getSeconds());
$('div.wrapper', command_log).append('<p>' + time + ' -- ' + message + '</p>'); $('div.wrapper', command_log).append('<p>' + time + ' -- ' + message + '</p>');
command_log.scrollTop($('div.wrapper', command_log).height()); command_log.scrollTop($('div.wrapper', command_log).height());
}; };
// Method is called every time a valid tab change event is received // Method is called every time a valid tab change event is received
@ -181,56 +181,56 @@ GUI_control.prototype.log = function(message) {
// default switch doesn't require callback to be set // default switch doesn't require callback to be set
GUI_control.prototype.tab_switch_cleanup = function(callback) { 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 MSP.callbacks_cleanup(); // we don't care about any old data that might or might not arrive
switch (this.active_tab) { switch (this.active_tab) {
case 'initial_setup': case 'initial_setup':
GUI.interval_remove('initial_setup_data_pull'); GUI.interval_remove('initial_setup_data_pull');
if (callback) callback(); if (callback) callback();
break; break;
case 'pid_tuning': case 'pid_tuning':
GUI.interval_remove('pid_data_poll'); GUI.interval_remove('pid_data_poll');
if (callback) callback(); if (callback) callback();
break; break;
case 'receiver': case 'receiver':
GUI.interval_remove('receiver_poll'); GUI.interval_remove('receiver_poll');
if (callback) callback(); if (callback) callback();
break; break;
case 'auxiliary_configuration': case 'auxiliary_configuration':
GUI.interval_remove('aux_data_poll'); GUI.interval_remove('aux_data_poll');
if (callback) callback(); if (callback) callback();
break; break;
case 'servos': case 'servos':
GUI.interval_remove('servos_data_poll'); GUI.interval_remove('servos_data_poll');
if (callback) callback(); if (callback) callback();
break; break;
case 'gps': case 'gps':
GUI.interval_remove('gps_pull'); GUI.interval_remove('gps_pull');
if (callback) callback(); if (callback) callback();
break; break;
case 'motor_outputs': case 'motor_outputs':
GUI.interval_remove('motor_poll'); GUI.interval_remove('motor_poll');
// only enforce mincommand if necessary // only enforce mincommand if necessary
if (MOTOR_DATA != undefined) { if (MOTOR_DATA != undefined) {
var update = false; var update = false;
for (var i = 0; i < MOTOR_DATA.length; i++) { for (var i = 0; i < MOTOR_DATA.length; i++) {
if (MOTOR_DATA[i] > MISC.mincommand) { if (MOTOR_DATA[i] > MISC.mincommand) {
update = true; update = true;
break; break;
} }
} }
if (update) { if (update) {
// send data to mcu // send data to mcu
var buffer_out = []; var buffer_out = [];
for (var i = 0; i < 8; i++) { for (var i = 0; i < 8; i++) {
buffer_out.push(lowByte(MISC.mincommand)); buffer_out.push(lowByte(MISC.mincommand));
buffer_out.push(highByte(MISC.mincommand)); buffer_out.push(highByte(MISC.mincommand));
@ -249,17 +249,17 @@ GUI_control.prototype.tab_switch_cleanup = function(callback) {
case 'sensors': case 'sensors':
GUI.interval_kill_all(['port_usage']); GUI.interval_kill_all(['port_usage']);
serial.empty_output_buffer(); serial.empty_output_buffer();
// sensor data tab uses scrollbars, emptying the content before loading another tab // sensor data tab uses scrollbars, emptying the content before loading another tab
// prevents scrollbar exposure to any of the tabs while new content is loaded in // prevents scrollbar exposure to any of the tabs while new content is loaded in
$('#content').empty(); $('#content').empty();
if (callback) callback(); if (callback) callback();
break; break;
case 'cli': case 'cli':
var bufferOut = new ArrayBuffer(5); var bufferOut = new ArrayBuffer(5);
var bufView = new Uint8Array(bufferOut); var bufView = new Uint8Array(bufferOut);
bufView[0] = 0x65; // e bufView[0] = 0x65; // e
bufView[1] = 0x78; // x bufView[1] = 0x78; // x
bufView[2] = 0x69; // i bufView[2] = 0x69; // i
@ -274,18 +274,18 @@ GUI_control.prototype.tab_switch_cleanup = function(callback) {
GUI.timeout_add('waiting_for_bootup', function() { GUI.timeout_add('waiting_for_bootup', function() {
CLI_active = false; CLI_active = false;
CLI_valid = false; CLI_valid = false;
if (callback) callback(); if (callback) callback();
}, 5000); // if we dont allow enough time to reboot, CRC of "first" command sent will fail, keep an eye for this one }, 5000); // if we dont allow enough time to reboot, CRC of "first" command sent will fail, keep an eye for this one
}); });
break; break;
case 'firmware_flasher': case 'firmware_flasher':
PortHandler.flush_callbacks(); PortHandler.flush_callbacks();
if (callback) callback(); if (callback) callback();
break; break;
default: default:
if (callback) callback(); if (callback) callback();
} }

188
js/msp.js
View file

@ -21,7 +21,7 @@ var MSP_codes = {
MSP_WP: 118, MSP_WP: 118,
MSP_BOXIDS: 119, MSP_BOXIDS: 119,
MSP_SERVO_CONF: 120, MSP_SERVO_CONF: 120,
MSP_SET_RAW_RC: 200, MSP_SET_RAW_RC: 200,
MSP_SET_RAW_GPS: 201, MSP_SET_RAW_GPS: 201,
MSP_SET_PID: 202, MSP_SET_PID: 202,
@ -36,14 +36,14 @@ var MSP_codes = {
MSP_SET_HEAD: 211, MSP_SET_HEAD: 211,
MSP_SET_SERVO_CONF: 212, MSP_SET_SERVO_CONF: 212,
MSP_SET_MOTOR: 214, MSP_SET_MOTOR: 214,
// MSP_BIND: 240, // MSP_BIND: 240,
MSP_EEPROM_WRITE: 250, MSP_EEPROM_WRITE: 250,
MSP_DEBUGMSG: 253, MSP_DEBUGMSG: 253,
MSP_DEBUG: 254, MSP_DEBUG: 254,
// Additional baseflight commands that are not compatible with MultiWii // Additional baseflight commands that are not compatible with MultiWii
MSP_UID: 160, // Unique device ID MSP_UID: 160, // Unique device ID
MSP_ACC_TRIM: 240, // get acc angle trim values MSP_ACC_TRIM: 240, // get acc angle trim values
@ -63,29 +63,29 @@ var MSP = {
message_buffer: undefined, message_buffer: undefined,
message_buffer_uint8_view: undefined, message_buffer_uint8_view: undefined,
message_checksum: 0, message_checksum: 0,
callbacks: [], callbacks: [],
packet_error: 0, packet_error: 0,
callbacks_cleanup: function() { callbacks_cleanup: function() {
for (var i = 0; i < this.callbacks.length; i++) { for (var i = 0; i < this.callbacks.length; i++) {
clearInterval(this.callbacks[i].timer); clearInterval(this.callbacks[i].timer);
} }
this.callbacks = []; this.callbacks = [];
}, },
disconnect_cleanup: function() { disconnect_cleanup: function() {
this.state = 0; // reset packet state for "clean" initial entry (this is only required if user hot-disconnects) this.state = 0; // reset packet state for "clean" initial entry (this is only required if user hot-disconnects)
this.packet_error = 0; // reset CRC packet error counter for next session this.packet_error = 0; // reset CRC packet error counter for next session
this.callbacks_cleanup(); this.callbacks_cleanup();
} }
}; };
MSP.read = function(readInfo) { MSP.read = function(readInfo) {
var data = new Uint8Array(readInfo.data); var data = new Uint8Array(readInfo.data);
for (var i = 0; i < data.length; i++) { for (var i = 0; i < data.length; i++) {
switch (this.state) { switch (this.state) {
case 0: // sync char 1 case 0: // sync char 1
@ -106,24 +106,24 @@ MSP.read = function(readInfo) {
} else { // unknown } else { // unknown
message_status = 0; message_status = 0;
} }
this.state++; this.state++;
break; break;
case 3: case 3:
this.message_length_expected = data[i]; this.message_length_expected = data[i];
this.message_checksum = data[i]; this.message_checksum = data[i];
// setup arraybuffer // setup arraybuffer
this.message_buffer = new ArrayBuffer(this.message_length_expected); this.message_buffer = new ArrayBuffer(this.message_length_expected);
this.message_buffer_uint8_view = new Uint8Array(this.message_buffer); this.message_buffer_uint8_view = new Uint8Array(this.message_buffer);
this.state++; this.state++;
break; break;
case 4: case 4:
this.code = data[i]; this.code = data[i];
this.message_checksum ^= data[i]; this.message_checksum ^= data[i];
if (this.message_length_expected != 0) { // standard message if (this.message_length_expected != 0) { // standard message
this.state++; this.state++;
} else { // MSP_ACC_CALIBRATION, etc... } else { // MSP_ACC_CALIBRATION, etc...
@ -134,7 +134,7 @@ MSP.read = function(readInfo) {
this.message_buffer_uint8_view[this.message_length_received] = data[i]; this.message_buffer_uint8_view[this.message_length_received] = data[i];
this.message_checksum ^= data[i]; this.message_checksum ^= data[i];
this.message_length_received++; this.message_length_received++;
if (this.message_length_received >= this.message_length_expected) { if (this.message_length_received >= this.message_length_expected) {
this.state++; this.state++;
} }
@ -145,24 +145,24 @@ MSP.read = function(readInfo) {
this.process_data(this.code, this.message_buffer, this.message_length_expected); this.process_data(this.code, this.message_buffer, this.message_length_expected);
} else { } else {
console.log('code: ' + this.code + ' - crc failed'); console.log('code: ' + this.code + ' - crc failed');
this.packet_error++; this.packet_error++;
$('span.packet-error').html(this.packet_error); $('span.packet-error').html(this.packet_error);
} }
// Reset variables // Reset variables
this.message_length_received = 0; this.message_length_received = 0;
this.state = 0; this.state = 0;
break; break;
} }
char_counter++; char_counter++;
} }
}; };
MSP.process_data = function(code, message_buffer, message_length) { MSP.process_data = function(code, message_buffer, message_length) {
var data = new DataView(message_buffer, 0); // DataView (allowing us to view arrayBuffer as struct/union) var data = new DataView(message_buffer, 0); // DataView (allowing us to view arrayBuffer as struct/union)
switch (code) { switch (code) {
case MSP_codes.MSP_IDENT: case MSP_codes.MSP_IDENT:
CONFIG.version = parseFloat((data.getUint8(0) / 100).toFixed(2)); CONFIG.version = parseFloat((data.getUint8(0) / 100).toFixed(2));
@ -176,7 +176,7 @@ MSP.process_data = function(code, message_buffer, message_length) {
CONFIG.activeSensors = data.getUint16(4, 1); CONFIG.activeSensors = data.getUint16(4, 1);
CONFIG.mode = data.getUint32(6, 1); CONFIG.mode = data.getUint32(6, 1);
CONFIG.profile = data.getUint8(10); CONFIG.profile = data.getUint8(10);
sensor_status(CONFIG.activeSensors); sensor_status(CONFIG.activeSensors);
$('span.cycle-time').html(CONFIG.cycleTime); $('span.cycle-time').html(CONFIG.cycleTime);
break; break;
@ -186,7 +186,7 @@ MSP.process_data = function(code, message_buffer, message_length) {
SENSOR_DATA.accelerometer[0] = data.getInt16(0, 1) / 512; SENSOR_DATA.accelerometer[0] = data.getInt16(0, 1) / 512;
SENSOR_DATA.accelerometer[1] = data.getInt16(2, 1) / 512; SENSOR_DATA.accelerometer[1] = data.getInt16(2, 1) / 512;
SENSOR_DATA.accelerometer[2] = data.getInt16(4, 1) / 512; SENSOR_DATA.accelerometer[2] = data.getInt16(4, 1) / 512;
// properly scaled // properly scaled
SENSOR_DATA.gyroscope[0] = data.getInt16(6, 1) * (4 / 16.4); SENSOR_DATA.gyroscope[0] = data.getInt16(6, 1) * (4 / 16.4);
SENSOR_DATA.gyroscope[1] = data.getInt16(8, 1) * (4 / 16.4); SENSOR_DATA.gyroscope[1] = data.getInt16(8, 1) * (4 / 16.4);
@ -201,29 +201,29 @@ MSP.process_data = function(code, message_buffer, message_length) {
var needle = 0; var needle = 0;
for (var i = 0; i < 8; i++) { for (var i = 0; i < 8; i++) {
SERVO_DATA[i] = data.getUint16(needle, 1); SERVO_DATA[i] = data.getUint16(needle, 1);
needle += 2; needle += 2;
} }
break; break;
case MSP_codes.MSP_MOTOR: case MSP_codes.MSP_MOTOR:
var needle = 0; var needle = 0;
for (var i = 0; i < 8; i++) { for (var i = 0; i < 8; i++) {
MOTOR_DATA[i] = data.getUint16(needle, 1); MOTOR_DATA[i] = data.getUint16(needle, 1);
needle += 2; needle += 2;
} }
break; break;
case MSP_codes.MSP_RC: case MSP_codes.MSP_RC:
RC.roll = data.getUint16(0, 1); RC.roll = data.getUint16(0, 1);
RC.pitch = data.getUint16(2, 1); RC.pitch = data.getUint16(2, 1);
RC.yaw = data.getUint16(4, 1); RC.yaw = data.getUint16(4, 1);
RC.throttle = data.getUint16(6, 1); RC.throttle = data.getUint16(6, 1);
RC.AUX1 = data.getUint16(8, 1); RC.AUX1 = data.getUint16(8, 1);
RC.AUX2 = data.getUint16(10, 1); RC.AUX2 = data.getUint16(10, 1);
RC.AUX3 = data.getUint16(12, 1); RC.AUX3 = data.getUint16(12, 1);
RC.AUX4 = data.getUint16(14, 1); RC.AUX4 = data.getUint16(14, 1);
break; break;
case MSP_codes.MSP_RAW_GPS: case MSP_codes.MSP_RAW_GPS:
GPS_DATA.fix = data.getUint8(0); GPS_DATA.fix = data.getUint8(0);
GPS_DATA.numSat = data.getUint8(1); GPS_DATA.numSat = data.getUint8(1);
@ -232,26 +232,26 @@ MSP.process_data = function(code, message_buffer, message_length) {
GPS_DATA.alt = data.getUint16(10, 1); GPS_DATA.alt = data.getUint16(10, 1);
GPS_DATA.speed = data.getUint16(12, 1); GPS_DATA.speed = data.getUint16(12, 1);
GPS_DATA.ground_course = data.getUint16(14, 1); GPS_DATA.ground_course = data.getUint16(14, 1);
break; break;
case MSP_codes.MSP_COMP_GPS: case MSP_codes.MSP_COMP_GPS:
GPS_DATA.distanceToHome = data.getUint16(0, 1); GPS_DATA.distanceToHome = data.getUint16(0, 1);
GPS_DATA.directionToHome = data.getUint16(2, 1); GPS_DATA.directionToHome = data.getUint16(2, 1);
GPS_DATA.update = data.getUint8(4); GPS_DATA.update = data.getUint8(4);
break; break;
case MSP_codes.MSP_ATTITUDE: case MSP_codes.MSP_ATTITUDE:
SENSOR_DATA.kinematicsX = data.getInt16(0, 1) / 10.0; SENSOR_DATA.kinematicsX = data.getInt16(0, 1) / 10.0;
SENSOR_DATA.kinematicsY = data.getInt16(2, 1) / 10.0; SENSOR_DATA.kinematicsY = data.getInt16(2, 1) / 10.0;
SENSOR_DATA.kinematicsZ = data.getInt16(4, 1); SENSOR_DATA.kinematicsZ = data.getInt16(4, 1);
break; break;
case MSP_codes.MSP_ALTITUDE: case MSP_codes.MSP_ALTITUDE:
SENSOR_DATA.altitude = parseFloat((data.getInt32(0, 1) / 100.0).toFixed(2)); // correct scale factor SENSOR_DATA.altitude = parseFloat((data.getInt32(0, 1) / 100.0).toFixed(2)); // correct scale factor
break; break;
case MSP_codes.MSP_ANALOG: case MSP_codes.MSP_ANALOG:
ANALOG.voltage = data.getUint8(0) / 10.0; ANALOG.voltage = data.getUint8(0) / 10.0;
ANALOG.power = data.getUint16(1, 1); ANALOG.power = data.getUint16(1, 1);
ANALOG.rssi = data.getUint16(3, 1); ANALOG.rssi = data.getUint16(3, 1);
ANALOG.amperage = data.getUint16(5, 1); ANALOG.amperage = data.getUint16(5, 1);
break; break;
case MSP_codes.MSP_RC_TUNING: case MSP_codes.MSP_RC_TUNING:
RC_tuning.RC_RATE = parseFloat((data.getUint8(0) / 100).toFixed(2)); RC_tuning.RC_RATE = parseFloat((data.getUint8(0) / 100).toFixed(2));
RC_tuning.RC_EXPO = parseFloat((data.getUint8(1) / 100).toFixed(2)); RC_tuning.RC_EXPO = parseFloat((data.getUint8(1) / 100).toFixed(2));
@ -260,17 +260,17 @@ MSP.process_data = function(code, message_buffer, message_length) {
RC_tuning.dynamic_THR_PID = parseFloat((data.getUint8(4) / 100).toFixed(2)); RC_tuning.dynamic_THR_PID = parseFloat((data.getUint8(4) / 100).toFixed(2));
RC_tuning.throttle_MID = parseFloat((data.getUint8(5) / 100).toFixed(2)); RC_tuning.throttle_MID = parseFloat((data.getUint8(5) / 100).toFixed(2));
RC_tuning.throttle_EXPO = parseFloat((data.getUint8(6) / 100).toFixed(2)); RC_tuning.throttle_EXPO = parseFloat((data.getUint8(6) / 100).toFixed(2));
break; break;
case MSP_codes.MSP_PID: case MSP_codes.MSP_PID:
// PID data arrived, we need to scale it and save to appropriate bank / array // PID data arrived, we need to scale it and save to appropriate bank / array
for (var i = 0, needle = 0; i < (message_length / 3); i++, needle += 3) { for (var i = 0, needle = 0; i < (message_length / 3); i++, needle += 3) {
// main for loop selecting the pid section // main for loop selecting the pid section
switch (i) { switch (i) {
case 0: case 0:
case 1: case 1:
case 2: case 2:
case 3: case 3:
case 7: case 7:
case 8: case 8:
case 9: case 9:
PIDs[i][0] = data.getUint8(needle) / 10; PIDs[i][0] = data.getUint8(needle) / 10;
@ -282,24 +282,24 @@ MSP.process_data = function(code, message_buffer, message_length) {
PIDs[i][1] = data.getUint8(needle + 1) / 100; PIDs[i][1] = data.getUint8(needle + 1) / 100;
PIDs[i][2] = data.getUint8(needle + 2) / 1000; PIDs[i][2] = data.getUint8(needle + 2) / 1000;
break; break;
case 5: case 5:
case 6: case 6:
PIDs[i][0] = data.getUint8(needle) / 10; PIDs[i][0] = data.getUint8(needle) / 10;
PIDs[i][1] = data.getUint8(needle + 1) / 100; PIDs[i][1] = data.getUint8(needle + 1) / 100;
PIDs[i][2] = data.getUint8(needle + 2) / 1000; PIDs[i][2] = data.getUint8(needle + 2) / 1000;
break; break;
} }
} }
break; break;
case MSP_codes.MSP_BOX: case MSP_codes.MSP_BOX:
// dump previous data (if there was any) // dump previous data (if there was any)
AUX_CONFIG_values = new Array(); AUX_CONFIG_values = new Array();
// fill in current data // fill in current data
for (var i = 0; i < data.byteLength; i += 2) { // + 2 because uint16_t = 2 bytes for (var i = 0; i < data.byteLength; i += 2) { // + 2 because uint16_t = 2 bytes
AUX_CONFIG_values.push(data.getUint16(i, 1)); AUX_CONFIG_values.push(data.getUint16(i, 1));
} }
break; break;
case MSP_codes.MSP_MISC: // 22 bytes case MSP_codes.MSP_MISC: // 22 bytes
MISC.PowerTrigger1 = data.getInt16(0, 1); MISC.PowerTrigger1 = data.getInt16(0, 1);
MISC.minthrottle = data.getUint16(2, 1); // 0-2000 MISC.minthrottle = data.getUint16(2, 1); // 0-2000
@ -313,29 +313,29 @@ MSP.process_data = function(code, message_buffer, message_length) {
MISC.vbatmincellvoltage = data.getUint8(19, 1) / 10; // 10-50 MISC.vbatmincellvoltage = data.getUint8(19, 1) / 10; // 10-50
MISC.vbatmaxcellvoltage = data.getUint8(20, 1) / 10; // 10-50 MISC.vbatmaxcellvoltage = data.getUint8(20, 1) / 10; // 10-50
MISC.empty = data.getUint8(21, 1); MISC.empty = data.getUint8(21, 1);
break; break;
case MSP_codes.MSP_MOTOR_PINS: case MSP_codes.MSP_MOTOR_PINS:
console.log(data); console.log(data);
break; break;
case MSP_codes.MSP_BOXNAMES: case MSP_codes.MSP_BOXNAMES:
AUX_CONFIG = []; // empty the array as new data is coming in AUX_CONFIG = []; // empty the array as new data is coming in
var buff = new Array(); var buff = new Array();
for (var i = 0; i < data.byteLength; i++) { for (var i = 0; i < data.byteLength; i++) {
if (data.getUint8(i) == 0x3B) { // ; (delimeter char) if (data.getUint8(i) == 0x3B) { // ; (delimeter char)
AUX_CONFIG.push(String.fromCharCode.apply(null, buff)); // convert bytes into ASCII and save as strings AUX_CONFIG.push(String.fromCharCode.apply(null, buff)); // convert bytes into ASCII and save as strings
// empty buffer // empty buffer
buff = []; buff = [];
} else { } else {
buff.push(data.getUint8(i)); buff.push(data.getUint8(i));
} }
} }
break; break;
case MSP_codes.MSP_PIDNAMES: case MSP_codes.MSP_PIDNAMES:
console.log(data); console.log(data);
break; break;
case MSP_codes.MSP_WP: case MSP_codes.MSP_WP:
console.log(data); console.log(data);
break; break;
@ -345,43 +345,43 @@ MSP.process_data = function(code, message_buffer, message_length) {
case MSP_codes.MSP_SERVO_CONF: case MSP_codes.MSP_SERVO_CONF:
// drop previous data // drop previous data
SERVO_CONFIG = []; SERVO_CONFIG = [];
for (var i = 0; i < 56; i += 7) { for (var i = 0; i < 56; i += 7) {
var arr = { var arr = {
'min': data.getInt16(i, 1), 'min': data.getInt16(i, 1),
'max': data.getInt16(i + 2, 1), 'max': data.getInt16(i + 2, 1),
'middle': data.getInt16(i + 4, 1), 'middle': data.getInt16(i + 4, 1),
'rate': data.getInt8(i + 6) 'rate': data.getInt8(i + 6)
}; };
SERVO_CONFIG.push(arr); SERVO_CONFIG.push(arr);
} }
break; break;
case MSP_codes.MSP_SET_RAW_RC: case MSP_codes.MSP_SET_RAW_RC:
break; break;
case MSP_codes.MSP_SET_RAW_GPS: case MSP_codes.MSP_SET_RAW_GPS:
break; break;
case MSP_codes.MSP_SET_PID: case MSP_codes.MSP_SET_PID:
console.log('PID settings saved'); console.log('PID settings saved');
break; break;
case MSP_codes.MSP_SET_BOX: case MSP_codes.MSP_SET_BOX:
console.log('AUX Configuration saved'); console.log('AUX Configuration saved');
break; break;
case MSP_codes.MSP_SET_RC_TUNING: case MSP_codes.MSP_SET_RC_TUNING:
console.log('RC Tuning saved'); console.log('RC Tuning saved');
break; break;
case MSP_codes.MSP_ACC_CALIBRATION: case MSP_codes.MSP_ACC_CALIBRATION:
console.log('Accel calibration executed'); console.log('Accel calibration executed');
break; break;
case MSP_codes.MSP_MAG_CALIBRATION: case MSP_codes.MSP_MAG_CALIBRATION:
console.log('Mag calibration executed'); console.log('Mag calibration executed');
break; break;
case MSP_codes.MSP_SET_MISC: case MSP_codes.MSP_SET_MISC:
console.log('MISC Configuration saved'); console.log('MISC Configuration saved');
break; break;
case MSP_codes.MSP_RESET_CONF: case MSP_codes.MSP_RESET_CONF:
console.log('Settings Reset'); console.log('Settings Reset');
// With new flight software settings in place, we have to re-pull // With new flight software settings in place, we have to re-pull
// latest values // latest values
send_message(MSP_codes.MSP_IDENT, MSP_codes.MSP_IDENT); send_message(MSP_codes.MSP_IDENT, MSP_codes.MSP_IDENT);
@ -390,22 +390,22 @@ MSP.process_data = function(code, message_buffer, message_length) {
send_message(MSP_codes.MSP_RC_TUNING, MSP_codes.MSP_RC_TUNING); send_message(MSP_codes.MSP_RC_TUNING, MSP_codes.MSP_RC_TUNING);
send_message(MSP_codes.MSP_BOXNAMES, MSP_codes.MSP_BOXNAMES); send_message(MSP_codes.MSP_BOXNAMES, MSP_codes.MSP_BOXNAMES);
send_message(MSP_codes.MSP_BOX, MSP_codes.MSP_BOX); send_message(MSP_codes.MSP_BOX, MSP_codes.MSP_BOX);
// baseflight specific // baseflight specific
send_message(MSP_codes.MSP_UID, MSP_codes.MSP_UID); send_message(MSP_codes.MSP_UID, MSP_codes.MSP_UID);
send_message(MSP_codes.MSP_ACC_TRIM, MSP_codes.MSP_ACC_TRIM); send_message(MSP_codes.MSP_ACC_TRIM, MSP_codes.MSP_ACC_TRIM);
break; break;
case MSP_codes.MSP_SELECT_SETTING: case MSP_codes.MSP_SELECT_SETTING:
console.log('Profile selected'); console.log('Profile selected');
break; break;
case MSP_codes.MSP_SET_SERVO_CONF: case MSP_codes.MSP_SET_SERVO_CONF:
console.log('Servo Configuration saved'); console.log('Servo Configuration saved');
break; break;
case MSP_codes.MSP_EEPROM_WRITE: case MSP_codes.MSP_EEPROM_WRITE:
console.log('Settings Saved in EEPROM'); console.log('Settings Saved in EEPROM');
break; break;
case MSP_codes.MSP_DEBUGMSG: case MSP_codes.MSP_DEBUGMSG:
break; break;
case MSP_codes.MSP_DEBUG: case MSP_codes.MSP_DEBUG:
for (var i = 0; i < 4; i++) for (var i = 0; i < 4; i++)
SENSOR_DATA.debug[i] = data.getInt16((2 * i), 1); SENSOR_DATA.debug[i] = data.getInt16((2 * i), 1);
@ -429,39 +429,39 @@ MSP.process_data = function(code, message_buffer, message_length) {
case MSP_codes.MSP_GPSSVINFO: case MSP_codes.MSP_GPSSVINFO:
if (data.byteLength > 0) { if (data.byteLength > 0) {
var numCh = data.getUint8(0); var numCh = data.getUint8(0);
var needle = 1; var needle = 1;
for (var i = 0; i < numCh; i++) { for (var i = 0; i < numCh; i++) {
GPS_DATA.chn[i] = data.getUint8(needle); GPS_DATA.chn[i] = data.getUint8(needle);
GPS_DATA.svid[i] = data.getUint8(needle + 1); GPS_DATA.svid[i] = data.getUint8(needle + 1);
GPS_DATA.quality[i] = data.getUint8(needle + 2); GPS_DATA.quality[i] = data.getUint8(needle + 2);
GPS_DATA.cno[i] = data.getUint8(needle + 3); GPS_DATA.cno[i] = data.getUint8(needle + 3);
needle += 4; needle += 4;
} }
} }
break; break;
default: default:
console.log('Unknown code detected: ' + code); console.log('Unknown code detected: ' + code);
} }
// trigger callbacks, cleanup/remove callback after trigger // trigger callbacks, cleanup/remove callback after trigger
for (var i = (this.callbacks.length - 1); i >= 0; i--) { // itterating in reverse because we use .splice which modifies array length for (var i = (this.callbacks.length - 1); i >= 0; i--) { // itterating in reverse because we use .splice which modifies array length
if (this.callbacks[i].code == code) { if (this.callbacks[i].code == code) {
// saving current obj for after-callback comparison // saving current obj for after-callback comparison
var obj = this.callbacks[i]; var obj = this.callbacks[i];
// remove timeout // remove timeout
clearInterval(obj.timer); clearInterval(obj.timer);
// fire callback // fire callback
if (obj.callback) obj.callback({'command': code, 'data': data, 'length': message_length}); if (obj.callback) obj.callback({'command': code, 'data': data, 'length': message_length});
// remove object from array // remove object from array
// we need to check if the callback object still exists as it could have been touched/moved/removed in callback routine // we need to check if the callback object still exists as it could have been touched/moved/removed in callback routine
var index = this.callbacks.indexOf(obj); var index = this.callbacks.indexOf(obj);
if (index > -1) this.callbacks.splice(index, 1); if (index > -1) this.callbacks.splice(index, 1);
} }
} }
@ -470,26 +470,26 @@ MSP.process_data = function(code, message_buffer, message_length) {
function send_message(code, data, callback_sent, callback_msp) { function send_message(code, data, callback_sent, callback_msp) {
var bufferOut; var bufferOut;
var bufView; var bufView;
// always reserve 6 bytes for protocol overhead ! // always reserve 6 bytes for protocol overhead !
if (typeof data === 'object') { if (typeof data === 'object') {
var size = data.length + 6; var size = data.length + 6;
var checksum = 0; var checksum = 0;
bufferOut = new ArrayBuffer(size); bufferOut = new ArrayBuffer(size);
bufView = new Uint8Array(bufferOut); bufView = new Uint8Array(bufferOut);
bufView[0] = 36; // $ bufView[0] = 36; // $
bufView[1] = 77; // M bufView[1] = 77; // M
bufView[2] = 60; // < bufView[2] = 60; // <
bufView[3] = data.length; bufView[3] = data.length;
bufView[4] = code; bufView[4] = code;
checksum = bufView[3] ^ bufView[4]; checksum = bufView[3] ^ bufView[4];
for (var i = 0; i < data.length; i++) { for (var i = 0; i < data.length; i++) {
bufView[i + 5] = data[i]; bufView[i + 5] = data[i];
checksum ^= bufView[i + 5]; checksum ^= bufView[i + 5];
} }
@ -497,7 +497,7 @@ function send_message(code, data, callback_sent, callback_msp) {
} else { } else {
bufferOut = new ArrayBuffer(7); bufferOut = new ArrayBuffer(7);
bufView = new Uint8Array(bufferOut); bufView = new Uint8Array(bufferOut);
bufView[0] = 36; // $ bufView[0] = 36; // $
bufView[1] = 77; // M bufView[1] = 77; // M
bufView[2] = 60; // < bufView[2] = 60; // <
@ -514,14 +514,14 @@ function send_message(code, data, callback_sent, callback_msp) {
return false; // skips the code below return false; // skips the code below
} }
} }
var obj = {'code': code, 'callback': (callback_msp) ? callback_msp : false}; var obj = {'code': code, 'callback': (callback_msp) ? callback_msp : false};
obj.timer = setInterval(function() { obj.timer = setInterval(function() {
console.log('MSP data request timed-out: ' + code); console.log('MSP data request timed-out: ' + code);
serial.send(bufferOut, function(writeInfo) {}); serial.send(bufferOut, function(writeInfo) {});
}, 1000); // we should be able to define timeout in the future }, 1000); // we should be able to define timeout in the future
MSP.callbacks.push(obj); MSP.callbacks.push(obj);
serial.send(bufferOut, function(writeInfo) { serial.send(bufferOut, function(writeInfo) {
@ -529,6 +529,6 @@ function send_message(code, data, callback_sent, callback_msp) {
if (callback_sent) callback_sent(); if (callback_sent) callback_sent();
} }
}); });
return true; return true;
} }

View file

@ -1,7 +1,7 @@
function port_handler() { function port_handler() {
this.main_timeout_reference; this.main_timeout_reference;
this.initial_ports = false; this.initial_ports = false;
this.port_detected_callbacks = []; this.port_detected_callbacks = [];
this.port_removed_callbacks = []; this.port_removed_callbacks = [];
} }
@ -13,12 +13,12 @@ port_handler.prototype.initialize = function() {
port_handler.prototype.check = function() { port_handler.prototype.check = function() {
var self = this; var self = this;
serial.getDevices(function(current_ports) { serial.getDevices(function(current_ports) {
// port got removed or initial_ports wasn't initialized yet // port got removed or initial_ports wasn't initialized yet
if (self.array_difference(self.initial_ports, current_ports).length > 0 || !self.initial_ports) { if (self.array_difference(self.initial_ports, current_ports).length > 0 || !self.initial_ports) {
var removed_ports = self.array_difference(self.initial_ports, current_ports); var removed_ports = self.array_difference(self.initial_ports, current_ports);
if (self.initial_ports != false) { if (self.initial_ports != false) {
if (removed_ports.length > 1) { if (removed_ports.length > 1) {
console.log('PortHandler - Removed: ' + removed_ports); console.log('PortHandler - Removed: ' + removed_ports);
@ -26,7 +26,7 @@ port_handler.prototype.check = function() {
console.log('PortHandler - Removed: ' + removed_ports[0]); console.log('PortHandler - Removed: ' + removed_ports[0]);
} }
} }
// disconnect "UI" if necessary // disconnect "UI" if necessary
// Keep in mind that this routine can not fire during atmega32u4 reboot procedure !!! // Keep in mind that this routine can not fire during atmega32u4 reboot procedure !!!
if (GUI.connected_to) { if (GUI.connected_to) {
@ -36,35 +36,35 @@ port_handler.prototype.check = function() {
} }
} }
} }
self.update_port_select(current_ports); self.update_port_select(current_ports);
// trigger callbacks (only after initialization) // trigger callbacks (only after initialization)
if (self.initial_ports) { if (self.initial_ports) {
for (var i = (self.port_removed_callbacks.length - 1); i >= 0; i--) { for (var i = (self.port_removed_callbacks.length - 1); i >= 0; i--) {
var obj = self.port_removed_callbacks[i]; var obj = self.port_removed_callbacks[i];
// remove timeout // remove timeout
clearTimeout(obj.timer); clearTimeout(obj.timer);
// trigger callback // trigger callback
obj.code(removed_ports); obj.code(removed_ports);
// remove object from array // remove object from array
var index = self.port_removed_callbacks.indexOf(obj); var index = self.port_removed_callbacks.indexOf(obj);
if (index > -1) self.port_removed_callbacks.splice(index, 1); if (index > -1) self.port_removed_callbacks.splice(index, 1);
} }
} }
// auto-select last used port (only during initialization) // auto-select last used port (only during initialization)
if (!self.initial_ports) { if (!self.initial_ports) {
chrome.storage.local.get('last_used_port', function(result) { chrome.storage.local.get('last_used_port', function(result) {
// if last_used_port was set, we try to select it // if last_used_port was set, we try to select it
if (result.last_used_port) { if (result.last_used_port) {
current_ports.forEach(function(port) { current_ports.forEach(function(port) {
if (port == result.last_used_port) { if (port == result.last_used_port) {
console.log('Selecting last used port: ' + result.last_used_port); console.log('Selecting last used port: ' + result.last_used_port);
$('div#port-picker .port select').val(result.last_used_port); $('div#port-picker .port select').val(result.last_used_port);
} }
}); });
@ -73,7 +73,7 @@ port_handler.prototype.check = function() {
} }
}); });
} }
if (!self.initial_ports) { if (!self.initial_ports) {
// initialize // initialize
self.initial_ports = current_ports; self.initial_ports = current_ports;
@ -83,26 +83,26 @@ port_handler.prototype.check = function() {
} }
} }
} }
// new port detected // new port detected
var new_ports = self.array_difference(current_ports, self.initial_ports); var new_ports = self.array_difference(current_ports, self.initial_ports);
if (new_ports.length) { if (new_ports.length) {
if (new_ports.length > 1) { if (new_ports.length > 1) {
console.log('PortHandler - Found: ' + new_ports); console.log('PortHandler - Found: ' + new_ports);
} else { } else {
console.log('PortHandler - Found: ' + new_ports[0]); console.log('PortHandler - Found: ' + new_ports[0]);
} }
self.update_port_select(current_ports); self.update_port_select(current_ports);
// select / highlight new port, if connected -> select connected port // select / highlight new port, if connected -> select connected port
if (!GUI.connected_to) { if (!GUI.connected_to) {
$('div#port-picker .port select').val(new_ports[0]); $('div#port-picker .port select').val(new_ports[0]);
} else { } else {
$('div#port-picker .port select').val(GUI.connected_to); $('div#port-picker .port select').val(GUI.connected_to);
} }
// start connect procedure (if statement is valid) // start connect procedure (if statement is valid)
if (GUI.auto_connect && !GUI.connecting_to && !GUI.connected_to) { if (GUI.auto_connect && !GUI.connecting_to && !GUI.connected_to) {
// we need firmware flasher protection over here // we need firmware flasher protection over here
@ -112,25 +112,25 @@ port_handler.prototype.check = function() {
}, 50); // small timeout so we won't get any nasty connect errors due to system initializing the bus }, 50); // small timeout so we won't get any nasty connect errors due to system initializing the bus
} }
} }
// trigger callbacks // trigger callbacks
for (var i = (self.port_detected_callbacks.length - 1); i >= 0; i--) { for (var i = (self.port_detected_callbacks.length - 1); i >= 0; i--) {
var obj = self.port_detected_callbacks[i]; var obj = self.port_detected_callbacks[i];
// remove timeout // remove timeout
clearTimeout(obj.timer); clearTimeout(obj.timer);
// trigger callback // trigger callback
obj.code(new_ports); obj.code(new_ports);
// remove object from array // remove object from array
var index = self.port_detected_callbacks.indexOf(obj); var index = self.port_detected_callbacks.indexOf(obj);
if (index > -1) self.port_detected_callbacks.splice(index, 1); if (index > -1) self.port_detected_callbacks.splice(index, 1);
} }
self.initial_ports = current_ports; self.initial_ports = current_ports;
} }
self.main_timeout_reference = setTimeout(function() { self.main_timeout_reference = setTimeout(function() {
self.check(); self.check();
}, 250); }, 250);
@ -139,27 +139,27 @@ port_handler.prototype.check = function() {
port_handler.prototype.update_port_select = function(ports) { port_handler.prototype.update_port_select = function(ports) {
$('div#port-picker .port select').html(''); // drop previous one $('div#port-picker .port select').html(''); // drop previous one
if (ports.length > 0) { if (ports.length > 0) {
for (var i = 0; i < ports.length; i++) { for (var i = 0; i < ports.length; i++) {
$('div#port-picker .port select').append($("<option/>", {value: ports[i], text: ports[i]})); $('div#port-picker .port select').append($("<option/>", {value: ports[i], text: ports[i]}));
} }
} else { } else {
$('div#port-picker .port select').append($("<option/>", {value: 0, text: 'No Ports'})); $('div#port-picker .port select').append($("<option/>", {value: 0, text: 'No Ports'}));
} }
}; };
port_handler.prototype.port_detected = function(name, code, timeout, ignore_timeout) { port_handler.prototype.port_detected = function(name, code, timeout, ignore_timeout) {
var self = this; var self = this;
var obj = {'name': name, 'code': code, 'timeout': (timeout) ? timeout : 10000}; var obj = {'name': name, 'code': code, 'timeout': (timeout) ? timeout : 10000};
if (!ignore_timeout) { if (!ignore_timeout) {
obj.timer = setTimeout(function() { obj.timer = setTimeout(function() {
console.log('PortHandler - timeout - ' + obj.name); console.log('PortHandler - timeout - ' + obj.name);
// trigger callback // trigger callback
code(false); code(false);
// remove object from array // remove object from array
var index = self.port_detected_callbacks.indexOf(obj); var index = self.port_detected_callbacks.indexOf(obj);
if (index > -1) self.port_detected_callbacks.splice(index, 1); if (index > -1) self.port_detected_callbacks.splice(index, 1);
@ -168,7 +168,7 @@ port_handler.prototype.port_detected = function(name, code, timeout, ignore_time
obj.timer = false; obj.timer = false;
obj.timeout = false; obj.timeout = false;
} }
this.port_detected_callbacks.push(obj); this.port_detected_callbacks.push(obj);
return obj; return obj;
@ -177,14 +177,14 @@ port_handler.prototype.port_detected = function(name, code, timeout, ignore_time
port_handler.prototype.port_removed = function(name, code, timeout, ignore_timeout) { port_handler.prototype.port_removed = function(name, code, timeout, ignore_timeout) {
var self = this; var self = this;
var obj = {'name': name, 'code': code, 'timeout': (timeout) ? timeout : 10000}; var obj = {'name': name, 'code': code, 'timeout': (timeout) ? timeout : 10000};
if (!ignore_timeout) { if (!ignore_timeout) {
obj.timer = setTimeout(function() { obj.timer = setTimeout(function() {
console.log('PortHandler - timeout - ' + obj.name); console.log('PortHandler - timeout - ' + obj.name);
// trigger callback // trigger callback
code(false); code(false);
// remove object from array // remove object from array
var index = self.port_removed_callbacks.indexOf(obj); var index = self.port_removed_callbacks.indexOf(obj);
if (index > -1) self.port_removed_callbacks.splice(index, 1); if (index > -1) self.port_removed_callbacks.splice(index, 1);
@ -193,44 +193,44 @@ port_handler.prototype.port_removed = function(name, code, timeout, ignore_timeo
obj.timer = false; obj.timer = false;
obj.timeout = false; obj.timeout = false;
} }
this.port_removed_callbacks.push(obj); this.port_removed_callbacks.push(obj);
return obj; return obj;
}; };
// accepting single level array with "value" as key // accepting single level array with "value" as key
port_handler.prototype.array_difference = function(firstArray, secondArray) { port_handler.prototype.array_difference = function(firstArray, secondArray) {
var cloneArray = []; var cloneArray = [];
// create hardcopy // create hardcopy
for (var i = 0; i < firstArray.length; i++) { for (var i = 0; i < firstArray.length; i++) {
cloneArray.push(firstArray[i]); cloneArray.push(firstArray[i]);
} }
for (var i = 0; i < secondArray.length; i++) { for (var i = 0; i < secondArray.length; i++) {
if (cloneArray.indexOf(secondArray[i]) != -1) { if (cloneArray.indexOf(secondArray[i]) != -1) {
cloneArray.splice(cloneArray.indexOf(secondArray[i]), 1); cloneArray.splice(cloneArray.indexOf(secondArray[i]), 1);
} }
} }
return cloneArray; return cloneArray;
}; };
port_handler.prototype.flush_callbacks = function() { port_handler.prototype.flush_callbacks = function() {
var killed = 0; var killed = 0;
for (var i = this.port_detected_callbacks.length - 1; i >= 0; i--) { for (var i = this.port_detected_callbacks.length - 1; i >= 0; i--) {
if (this.port_detected_callbacks[i].timer) clearTimeout(this.port_detected_callbacks[i].timer); if (this.port_detected_callbacks[i].timer) clearTimeout(this.port_detected_callbacks[i].timer);
this.port_detected_callbacks.splice(i, 1); this.port_detected_callbacks.splice(i, 1);
killed++; killed++;
} }
for (var i = this.port_removed_callbacks.length - 1; i >= 0; i--) { for (var i = this.port_removed_callbacks.length - 1; i >= 0; i--) {
if (this.port_removed_callbacks[i].timer) clearTimeout(this.port_removed_callbacks[i].timer); if (this.port_removed_callbacks[i].timer) clearTimeout(this.port_removed_callbacks[i].timer);
this.port_removed_callbacks.splice(i, 1); this.port_removed_callbacks.splice(i, 1);
killed++; killed++;
} }

View file

@ -2,25 +2,25 @@ var serial = {
connectionId: -1, connectionId: -1,
bytes_received: 0, bytes_received: 0,
bytes_sent: 0, bytes_sent: 0,
transmitting: false, transmitting: false,
output_buffer: [], output_buffer: [],
connect: function(path, options, callback) { connect: function(path, options, callback) {
var self = this; var self = this;
chrome.serial.connect(path, options, function(connectionInfo) { chrome.serial.connect(path, options, function(connectionInfo) {
if (connectionInfo !== undefined) { if (connectionInfo !== undefined) {
self.connectionId = connectionInfo.connectionId; self.connectionId = connectionInfo.connectionId;
self.bytes_received = 0; self.bytes_received = 0;
self.bytes_sent = 0; self.bytes_sent = 0;
self.onReceive.addListener(function log_bytes_received(info) { self.onReceive.addListener(function log_bytes_received(info) {
self.bytes_received += info.data.byteLength; self.bytes_received += info.data.byteLength;
}); });
console.log('SERIAL: Connection opened with ID: ' + connectionInfo.connectionId + ', Baud: ' + connectionInfo.bitrate); console.log('SERIAL: Connection opened with ID: ' + connectionInfo.connectionId + ', Baud: ' + connectionInfo.bitrate);
callback(connectionInfo); callback(connectionInfo);
} else { } else {
console.log('SERIAL: Failed to open serial port'); console.log('SERIAL: Failed to open serial port');
@ -30,25 +30,25 @@ var serial = {
}, },
disconnect: function(callback) { disconnect: function(callback) {
var self = this; var self = this;
self.empty_output_buffer(); self.empty_output_buffer();
// remove listeners // remove listeners
for (var i = (self.onReceive.listeners.length - 1); i >= 0; i--) { for (var i = (self.onReceive.listeners.length - 1); i >= 0; i--) {
self.onReceive.removeListener(self.onReceive.listeners[i]); self.onReceive.removeListener(self.onReceive.listeners[i]);
} }
chrome.serial.disconnect(this.connectionId, function(result) { chrome.serial.disconnect(this.connectionId, function(result) {
if (result) { if (result) {
console.log('SERIAL: Connection with ID: ' + self.connectionId + ' closed'); console.log('SERIAL: Connection with ID: ' + self.connectionId + ' closed');
} else { } else {
console.log('SERIAL: Failed to close connection with ID: ' + self.connectionId + ' closed'); console.log('SERIAL: Failed to close connection with ID: ' + self.connectionId + ' closed');
} }
console.log('SERIAL: Statistics - Sent: ' + self.bytes_sent + ' bytes, Received: ' + self.bytes_received + ' bytes'); console.log('SERIAL: Statistics - Sent: ' + self.bytes_sent + ' bytes, Received: ' + self.bytes_received + ' bytes');
self.connectionId = -1; self.connectionId = -1;
callback(result); callback(result);
}); });
}, },
@ -58,7 +58,7 @@ var serial = {
devices_array.forEach(function(device) { devices_array.forEach(function(device) {
devices.push(device.path); devices.push(device.path);
}); });
callback(devices); callback(devices);
}); });
}, },
@ -68,54 +68,54 @@ var serial = {
send: function(data, callback) { send: function(data, callback) {
var self = this; var self = this;
self.output_buffer.push({'data': data, 'callback': callback}); self.output_buffer.push({'data': data, 'callback': callback});
if (!self.transmitting) { if (!self.transmitting) {
self.transmitting = true; self.transmitting = true;
var sending = function() { var sending = function() {
// store inside separate variables in case array gets destroyed // store inside separate variables in case array gets destroyed
var data = self.output_buffer[0].data; var data = self.output_buffer[0].data;
var callback = self.output_buffer[0].callback; var callback = self.output_buffer[0].callback;
chrome.serial.send(self.connectionId, data, function(sendInfo) { chrome.serial.send(self.connectionId, data, function(sendInfo) {
callback(sendInfo); callback(sendInfo);
self.output_buffer.shift(); self.output_buffer.shift();
self.bytes_sent += sendInfo.bytesSent; self.bytes_sent += sendInfo.bytesSent;
if (self.output_buffer.length) { if (self.output_buffer.length) {
// keep the buffer withing reasonable limits // keep the buffer withing reasonable limits
while (self.output_buffer.length > 500) { while (self.output_buffer.length > 500) {
self.output_buffer.pop(); self.output_buffer.pop();
} }
sending(); sending();
} else { } else {
self.transmitting = false; self.transmitting = false;
} }
}); });
}; };
sending(); sending();
} }
}, },
onReceive: { onReceive: {
listeners: [], listeners: [],
addListener: function(function_reference) { addListener: function(function_reference) {
var listener = chrome.serial.onReceive.addListener(function_reference); var listener = chrome.serial.onReceive.addListener(function_reference);
this.listeners.push(function_reference); this.listeners.push(function_reference);
}, },
removeListener: function(function_reference) { removeListener: function(function_reference) {
for (var i = (this.listeners.length - 1); i >= 0; i--) { for (var i = (this.listeners.length - 1); i >= 0; i--) {
if (this.listeners[i] == function_reference) { if (this.listeners[i] == function_reference) {
chrome.serial.onReceive.removeListener(function_reference); chrome.serial.onReceive.removeListener(function_reference);
this.listeners.splice(i, 1); this.listeners.splice(i, 1);
break; break;
} }
} }
} }
}, },
empty_output_buffer: function() { empty_output_buffer: function() {

View file

@ -2,55 +2,55 @@ var configuration_received = false;
var CLI_active = false; var CLI_active = false;
var CLI_valid = false; var CLI_valid = false;
$(document).ready(function() { $(document).ready(function() {
$('div#port-picker a.connect').click(function() { $('div#port-picker a.connect').click(function() {
if (GUI.connect_lock != true) { // GUI control overrides the user control if (GUI.connect_lock != true) { // GUI control overrides the user control
var clicks = $(this).data('clicks'); var clicks = $(this).data('clicks');
var selected_port = String($('div#port-picker .port select').val()); var selected_port = String($('div#port-picker .port select').val());
var selected_baud = parseInt($('div#port-picker #baud').val()); var selected_baud = parseInt($('div#port-picker #baud').val());
if (selected_port != '0') { if (selected_port != '0') {
if (!clicks) { if (!clicks) {
console.log('Connecting to: ' + selected_port); console.log('Connecting to: ' + selected_port);
GUI.connecting_to = selected_port; GUI.connecting_to = selected_port;
// lock port select & baud while we are connecting / connected // lock port select & baud while we are connecting / connected
$('div#port-picker #port, div#port-picker #baud, div#port-picker #delay').prop('disabled', true); $('div#port-picker #port, div#port-picker #baud, div#port-picker #delay').prop('disabled', true);
$('div#port-picker a.connect').text('Connecting'); $('div#port-picker a.connect').text('Connecting');
serial.connect(selected_port, {bitrate: selected_baud}, onOpen); serial.connect(selected_port, {bitrate: selected_baud}, onOpen);
} else { } else {
// Disable any active "data pulling" timer // Disable any active "data pulling" timer
GUI.interval_kill_all(); GUI.interval_kill_all();
GUI.tab_switch_cleanup(); GUI.tab_switch_cleanup();
GUI.timeout_remove('connecting'); GUI.timeout_remove('connecting');
serial.disconnect(onClosed); serial.disconnect(onClosed);
GUI.connected_to = false; GUI.connected_to = false;
// Reset various UI elements // Reset various UI elements
$('span.port-usage').html('0%'); $('span.port-usage').html('0%');
$('.software-version').html('0.0'); $('.software-version').html('0.0');
$('span.cycle-time').html('0'); $('span.cycle-time').html('0');
MSP.disconnect_cleanup(); MSP.disconnect_cleanup();
configuration_received = false; // reset valid config received variable (used to block tabs while not connected properly) configuration_received = false; // reset valid config received variable (used to block tabs while not connected properly)
// unlock port select & baud // unlock port select & baud
$('div#port-picker #port').prop('disabled', false); $('div#port-picker #port').prop('disabled', false);
if (!GUI.auto_connect) $('div#port-picker #baud').prop('disabled', false); if (!GUI.auto_connect) $('div#port-picker #baud').prop('disabled', false);
$(this).text('Connect'); $(this).text('Connect');
$(this).removeClass('active'); $(this).removeClass('active');
sensor_status(sensors_detected = 0); // reset active sensor indicators sensor_status(sensors_detected = 0); // reset active sensor indicators
$('#tabs > ul li').removeClass('active'); // de-select any selected tabs $('#tabs > ul li').removeClass('active'); // de-select any selected tabs
tab_initialize_default(); tab_initialize_default();
} }
$(this).data("clicks", !clicks); $(this).data("clicks", !clicks);
} }
} }
@ -61,62 +61,62 @@ $(document).ready(function() {
if (typeof result.auto_connect === 'undefined') { if (typeof result.auto_connect === 'undefined') {
// auto_connect wasn't saved yet, save and push true to the GUI // auto_connect wasn't saved yet, save and push true to the GUI
GUI.auto_connect = true; GUI.auto_connect = true;
$('input.auto_connect').prop('checked', true); $('input.auto_connect').prop('checked', true);
$('input.auto_connect, span.auto_connect').prop('title', 'Auto-Connect: Enabled - Configurator automatically tries to connect when new port is detected'); $('input.auto_connect, span.auto_connect').prop('title', 'Auto-Connect: Enabled - Configurator automatically tries to connect when new port is detected');
$('select#baud').val(115200).prop('disabled', true); $('select#baud').val(115200).prop('disabled', true);
// save // save
chrome.storage.local.set({'auto_connect': true}); chrome.storage.local.set({'auto_connect': true});
} else { } else {
if (result.auto_connect) { if (result.auto_connect) {
// enabled by user // enabled by user
GUI.auto_connect = true; GUI.auto_connect = true;
$('input.auto_connect').prop('checked', true); $('input.auto_connect').prop('checked', true);
$('input.auto_connect, span.auto_connect').prop('title', 'Auto-Connect: Enabled - Configurator automatically tries to connect when new serial port is detected'); $('input.auto_connect, span.auto_connect').prop('title', 'Auto-Connect: Enabled - Configurator automatically tries to connect when new serial port is detected');
$('select#baud').val(115200).prop('disabled', true); $('select#baud').val(115200).prop('disabled', true);
} else { } else {
// disabled by user // disabled by user
GUI.auto_connect = false; GUI.auto_connect = false;
$('input.auto_connect').prop('checked', false); $('input.auto_connect').prop('checked', false);
$('input.auto_connect, span.auto_connect').prop('title', 'Auto-Connect: Disabled - User needs to select the correct serial port and click "Connect" button on its own'); $('input.auto_connect, span.auto_connect').prop('title', 'Auto-Connect: Disabled - User needs to select the correct serial port and click "Connect" button on its own');
} }
} }
// bind UI hook to auto-connect checkbos // bind UI hook to auto-connect checkbos
$('input.auto_connect').change(function() { $('input.auto_connect').change(function() {
GUI.auto_connect = $(this).is(':checked'); GUI.auto_connect = $(this).is(':checked');
// update title/tooltip // update title/tooltip
if (GUI.auto_connect) { if (GUI.auto_connect) {
$('input.auto_connect, span.auto_connect').prop('title', 'Auto-Connect: Enabled - Configurator automatically tries to connect when new port is detected'); $('input.auto_connect, span.auto_connect').prop('title', 'Auto-Connect: Enabled - Configurator automatically tries to connect when new port is detected');
$('select#baud').val(115200).prop('disabled', true); $('select#baud').val(115200).prop('disabled', true);
} else { } else {
$('input.auto_connect, span.auto_connect').prop('title', 'Auto-Connect: Disabled - User needs to select the correct serial port and click "Connect" button on its own'); $('input.auto_connect, span.auto_connect').prop('title', 'Auto-Connect: Disabled - User needs to select the correct serial port and click "Connect" button on its own');
if (!GUI.connected_to && !GUI.connecting_to) $('select#baud').prop('disabled', false); if (!GUI.connected_to && !GUI.connecting_to) $('select#baud').prop('disabled', false);
} }
chrome.storage.local.set({'auto_connect': GUI.auto_connect}); chrome.storage.local.set({'auto_connect': GUI.auto_connect});
}); });
}); });
PortHandler.initialize(); PortHandler.initialize();
}); });
function onOpen(openInfo) { function onOpen(openInfo) {
if (openInfo) { if (openInfo) {
// update connected_to // update connected_to
GUI.connected_to = GUI.connecting_to; GUI.connected_to = GUI.connecting_to;
// reset connecting_to // reset connecting_to
GUI.connecting_to = false; GUI.connecting_to = false;
GUI.log('Serial port <span style="color: green">successfully</span> opened with ID: ' + openInfo.connectionId); GUI.log('Serial port <span style="color: green">successfully</span> opened with ID: ' + openInfo.connectionId);
// save selected port with chrome.storage if the port differs // save selected port with chrome.storage if the port differs
chrome.storage.local.get('last_used_port', function(result) { chrome.storage.local.get('last_used_port', function(result) {
if (typeof result.last_used_port != 'undefined') { if (typeof result.last_used_port != 'undefined') {
@ -138,12 +138,12 @@ function onOpen(openInfo) {
serial.onReceive.addListener(read_serial); serial.onReceive.addListener(read_serial);
GUI.interval_add('port_usage', port_usage, 1000, true); GUI.interval_add('port_usage', port_usage, 1000, true);
// disconnect after 10 seconds with error if we don't get IDENT data // disconnect after 10 seconds with error if we don't get IDENT data
GUI.timeout_add('connecting', function() { GUI.timeout_add('connecting', function() {
if (!configuration_received) { if (!configuration_received) {
GUI.log('No configuration received within <span style="color: red">10 seconds</span>, communication <span style="color: red">failed</span>'); GUI.log('No configuration received within <span style="color: red">10 seconds</span>, communication <span style="color: red">failed</span>');
$('div#port-picker a.connect').click(); // disconnect $('div#port-picker a.connect').click(); // disconnect
} }
}, 10000); }, 10000);
@ -153,11 +153,11 @@ function onOpen(openInfo) {
GUI.log('Unique device ID <span style="color: green">received</span> - <strong>0x' + CONFIG.uid[0].toString(16) + CONFIG.uid[1].toString(16) + CONFIG.uid[2].toString(16) + '</strong>'); GUI.log('Unique device ID <span style="color: green">received</span> - <strong>0x' + CONFIG.uid[0].toString(16) + CONFIG.uid[1].toString(16) + CONFIG.uid[2].toString(16) + '</strong>');
send_message(MSP_codes.MSP_IDENT, MSP_codes.MSP_IDENT, false, function() { send_message(MSP_codes.MSP_IDENT, MSP_codes.MSP_IDENT, false, function() {
GUI.timeout_remove('connecting'); // kill connecting timer GUI.timeout_remove('connecting'); // kill connecting timer
if (CONFIG.version >= firmware_version_accepted) { if (CONFIG.version >= firmware_version_accepted) {
// Update UI elements that doesn't need consistent refreshing // Update UI elements that doesn't need consistent refreshing
$('.software-version').html(CONFIG.version); $('.software-version').html(CONFIG.version);
configuration_received = true; configuration_received = true;
$('div#port-picker a.connect').text('Disconnect').addClass('active'); $('div#port-picker a.connect').text('Disconnect').addClass('active');
$('#tabs li a:first').click(); $('#tabs li a:first').click();
@ -170,13 +170,13 @@ function onOpen(openInfo) {
} else { } else {
console.log('Failed to open serial port'); console.log('Failed to open serial port');
GUI.log('Failed to open serial port', 'red'); GUI.log('Failed to open serial port', 'red');
$('div#port-picker a.connect').text('Connect'); $('div#port-picker a.connect').text('Connect');
$('div#port-picker a.connect').removeClass('active'); $('div#port-picker a.connect').removeClass('active');
// unlock port select & baud // unlock port select & baud
$('div#port-picker #port, div#port-picker #baud, div#port-picker #delay').prop('disabled', false); $('div#port-picker #port, div#port-picker #baud, div#port-picker #delay').prop('disabled', false);
// reset data // reset data
$('div#port-picker a.connect').data("clicks", false); $('div#port-picker a.connect').data("clicks", false);
} }
@ -187,7 +187,7 @@ function onClosed(result) {
GUI.log('Serial port <span style="color: green">successfully</span> closed'); GUI.log('Serial port <span style="color: green">successfully</span> closed');
} else { // Something went wrong } else { // Something went wrong
GUI.log('<span style="color: red">Failed</span> to close serial port'); GUI.log('<span style="color: red">Failed</span> to close serial port');
} }
} }
function read_serial(info) { function read_serial(info) {
@ -199,7 +199,7 @@ function read_serial(info) {
} }
function port_usage() { function port_usage() {
var port_usage = (char_counter * 10 / parseInt($('div#port-picker #baud').val())) * 100; var port_usage = (char_counter * 10 / parseInt($('div#port-picker #baud').val())) * 100;
$('span.port-usage').html(parseInt(port_usage) + '%'); $('span.port-usage').html(parseInt(port_usage) + '%');
// reset counter // reset counter
@ -211,11 +211,11 @@ function sensor_status(sensors_detected) {
if (typeof sensor_status.previous_sensors_detected == 'undefined') { if (typeof sensor_status.previous_sensors_detected == 'undefined') {
sensor_status.previous_sensors_detected = 0; sensor_status.previous_sensors_detected = 0;
} }
// update UI (if necessary) // update UI (if necessary)
if (sensor_status.previous_sensors_detected != sensors_detected) { if (sensor_status.previous_sensors_detected != sensors_detected) {
var e_sensor_status = $('div#sensor-status'); var e_sensor_status = $('div#sensor-status');
if (bit_check(sensors_detected, 0)) { // Gyroscope & accel detected if (bit_check(sensors_detected, 0)) { // Gyroscope & accel detected
$('.gyro', e_sensor_status).addClass('on'); $('.gyro', e_sensor_status).addClass('on');
$('.accel', e_sensor_status).addClass('on'); $('.accel', e_sensor_status).addClass('on');
@ -228,26 +228,26 @@ function sensor_status(sensors_detected) {
$('.baro', e_sensor_status).addClass('on'); $('.baro', e_sensor_status).addClass('on');
} else { } else {
$('.baro', e_sensor_status).removeClass('on'); $('.baro', e_sensor_status).removeClass('on');
} }
if (bit_check(sensors_detected, 2)) { // Magnetometer detected if (bit_check(sensors_detected, 2)) { // Magnetometer detected
$('.mag', e_sensor_status).addClass('on'); $('.mag', e_sensor_status).addClass('on');
} else { } else {
$('.mag', e_sensor_status).removeClass('on'); $('.mag', e_sensor_status).removeClass('on');
} }
if (bit_check(sensors_detected, 3)) { // GPS detected if (bit_check(sensors_detected, 3)) { // GPS detected
$('.gps', e_sensor_status).addClass('on'); $('.gps', e_sensor_status).addClass('on');
} else { } else {
$('.gps', e_sensor_status).removeClass('on'); $('.gps', e_sensor_status).removeClass('on');
} }
if (bit_check(sensors_detected, 4)) { // Sonar detected if (bit_check(sensors_detected, 4)) { // Sonar detected
$('.sonar', e_sensor_status).addClass('on'); $('.sonar', e_sensor_status).addClass('on');
} else { } else {
$('.sonar', e_sensor_status).removeClass('on'); $('.sonar', e_sensor_status).removeClass('on');
} }
// set current value // set current value
sensor_status.previous_sensors_detected = sensors_detected; sensor_status.previous_sensors_detected = sensors_detected;
} }

View file

@ -1,4 +1,4 @@
/* /*
STM32 F103 serial bus seems to properly initialize with quite a huge auto-baud range STM32 F103 serial bus seems to properly initialize with quite a huge auto-baud range
From 921600 down to 1200, i don't recommend getting any lower then that From 921600 down to 1200, i don't recommend getting any lower then that
Official "specs" are from 115200 to 1200 Official "specs" are from 115200 to 1200
@ -7,20 +7,20 @@
var STM32_protocol = function() { var STM32_protocol = function() {
this.hex; // ref this.hex; // ref
this.verify_hex; this.verify_hex;
this.receive_buffer; this.receive_buffer;
this.bytes_to_read = 0; // ref this.bytes_to_read = 0; // ref
this.read_callback; // ref this.read_callback; // ref
this.upload_time_start; this.upload_time_start;
this.upload_process_alive; this.upload_process_alive;
this.status = { this.status = {
ACK: 0x79, // y ACK: 0x79, // y
NACK: 0x1F NACK: 0x1F
}; };
this.command = { this.command = {
get: 0x00, // Gets the version and the allowed commands supported by the current version of the bootloader get: 0x00, // Gets the version and the allowed commands supported by the current version of the bootloader
get_ver_r_protect_s: 0x01, // Gets the bootloader version and the Read Protection status of the Flash memory get_ver_r_protect_s: 0x01, // Gets the bootloader version and the Read Protection status of the Flash memory
@ -35,7 +35,7 @@ var STM32_protocol = function() {
readout_protect: 0x82, // Enables the read protection readout_protect: 0x82, // Enables the read protection
readout_unprotect: 0x92 // Disables the read protection readout_unprotect: 0x92 // Disables the read protection
}; };
// Erase (x043) and Extended Erase (0x44) are exclusive. A device may support either the Erase command or the Extended Erase command but not both. // Erase (x043) and Extended Erase (0x44) are exclusive. A device may support either the Erase command or the Extended Erase command but not both.
}; };
@ -48,14 +48,14 @@ STM32_protocol.prototype.GUI_status = function(string) {
STM32_protocol.prototype.connect = function(hex) { STM32_protocol.prototype.connect = function(hex) {
var self = this; var self = this;
self.hex = hex; self.hex = hex;
var selected_port = String($('div#port-picker .port select').val()); var selected_port = String($('div#port-picker .port select').val());
var baud = parseInt($('div#port-picker #baud').val()); var baud = parseInt($('div#port-picker #baud').val());
if (selected_port != '0') { if (selected_port != '0') {
// popular choices - 921600, 460800, 256000, 230400, 153600, 128000, 115200, 57600, 38400, 28800, 19200 // popular choices - 921600, 460800, 256000, 230400, 153600, 128000, 115200, 57600, 38400, 28800, 19200
var flashing_bitrate; var flashing_bitrate;
switch (GUI.operating_system) { switch (GUI.operating_system) {
case 'Windows': case 'Windows':
flashing_bitrate = 921600; flashing_bitrate = 921600;
@ -68,11 +68,11 @@ STM32_protocol.prototype.connect = function(hex) {
case 'UNIX': case 'UNIX':
flashing_bitrate = 921600; flashing_bitrate = 921600;
break; break;
default: default:
flashing_bitrate = 115200; flashing_bitrate = 115200;
} }
if (!$('input.updating').is(':checked')) { if (!$('input.updating').is(':checked')) {
serial.connect(selected_port, {bitrate: baud}, function(openInfo) { serial.connect(selected_port, {bitrate: baud}, function(openInfo) {
if (openInfo) { if (openInfo) {
@ -80,17 +80,17 @@ STM32_protocol.prototype.connect = function(hex) {
// we are connected, disabling connect button in the UI // we are connected, disabling connect button in the UI
GUI.connect_lock = true; GUI.connect_lock = true;
var bufferOut = new ArrayBuffer(1); var bufferOut = new ArrayBuffer(1);
var bufferView = new Uint8Array(bufferOut); var bufferView = new Uint8Array(bufferOut);
bufferView[0] = 0x52; bufferView[0] = 0x52;
serial.send(bufferOut, function() { serial.send(bufferOut, function() {
serial.disconnect(function(result) { serial.disconnect(function(result) {
if (result) { if (result) {
serial.connect(selected_port, {bitrate: flashing_bitrate, parityBit: 'even', stopBits: 'one'}, function(openInfo) { serial.connect(selected_port, {bitrate: flashing_bitrate, parityBit: 'even', stopBits: 'one'}, function(openInfo) {
if (openInfo) { if (openInfo) {
self.initialize(); self.initialize();
} else { } else {
GUI.log('<span style="color: red">Failed</span> to open serial port'); GUI.log('<span style="color: red">Failed</span> to open serial port');
@ -107,10 +107,10 @@ STM32_protocol.prototype.connect = function(hex) {
}); });
} else { } else {
serial.connect(selected_port, {bitrate: flashing_bitrate, parityBit: 'even', stopBits: 'one'}, function(openInfo) { serial.connect(selected_port, {bitrate: flashing_bitrate, parityBit: 'even', stopBits: 'one'}, function(openInfo) {
if (openInfo) { if (openInfo) {
// we are connected, disabling connect button in the UI // we are connected, disabling connect button in the UI
GUI.connect_lock = true; GUI.connect_lock = true;
self.initialize(); self.initialize();
} else { } else {
GUI.log('<span style="color: red">Failed</span> to open serial port'); GUI.log('<span style="color: red">Failed</span> to open serial port');
@ -126,14 +126,14 @@ STM32_protocol.prototype.connect = function(hex) {
// initialize certain variables and start timers that oversee the communication // initialize certain variables and start timers that oversee the communication
STM32_protocol.prototype.initialize = function() { STM32_protocol.prototype.initialize = function() {
var self = this; var self = this;
// reset and set some variables before we start // reset and set some variables before we start
self.receive_buffer = []; self.receive_buffer = [];
self.verify_hex = []; self.verify_hex = [];
self.upload_time_start = microtime(); self.upload_time_start = microtime();
self.upload_process_alive = false; self.upload_process_alive = false;
// reset progress bar to initial state // reset progress bar to initial state
self.progress_bar_e = $('.progress'); self.progress_bar_e = $('.progress');
self.progress_bar_e.val(0); self.progress_bar_e.val(0);
@ -142,42 +142,42 @@ STM32_protocol.prototype.initialize = function() {
serial.onReceive.addListener(function(info) { serial.onReceive.addListener(function(info) {
self.read(info); self.read(info);
}); });
GUI.interval_add('STM32_timeout', function() { GUI.interval_add('STM32_timeout', function() {
if (self.upload_process_alive) { // process is running if (self.upload_process_alive) { // process is running
self.upload_process_alive = false; self.upload_process_alive = false;
} else { } else {
console.log('STM32 - timed out, programming failed ...'); console.log('STM32 - timed out, programming failed ...');
STM32.GUI_status('STM32 - timed out, programming: <strong style="color: red">FAILED</strong>'); STM32.GUI_status('STM32 - timed out, programming: <strong style="color: red">FAILED</strong>');
// protocol got stuck, clear timer and disconnect // protocol got stuck, clear timer and disconnect
GUI.interval_remove('STM32_timeout'); GUI.interval_remove('STM32_timeout');
// exit // exit
self.upload_procedure(99); self.upload_procedure(99);
} }
}, 1000); }, 1000);
self.upload_procedure(1); self.upload_procedure(1);
}; };
// no input parameters // no input parameters
// this method should be executed every 1 ms via interval timer // this method should be executed every 1 ms via interval timer
STM32_protocol.prototype.read = function(readInfo) { STM32_protocol.prototype.read = function(readInfo) {
// routine that fills the buffer // routine that fills the buffer
var data = new Uint8Array(readInfo.data); var data = new Uint8Array(readInfo.data);
for (var i = 0; i < data.length; i++) { for (var i = 0; i < data.length; i++) {
this.receive_buffer.push(data[i]); this.receive_buffer.push(data[i]);
} }
// routine that fetches data from buffer if statement is true // routine that fetches data from buffer if statement is true
if (this.receive_buffer.length >= this.bytes_to_read && this.bytes_to_read != 0) { if (this.receive_buffer.length >= this.bytes_to_read && this.bytes_to_read != 0) {
var data = this.receive_buffer.slice(0, this.bytes_to_read); // bytes requested var data = this.receive_buffer.slice(0, this.bytes_to_read); // bytes requested
this.receive_buffer.splice(0, this.bytes_to_read); // remove read bytes this.receive_buffer.splice(0, this.bytes_to_read); // remove read bytes
this.bytes_to_read = 0; // reset trigger this.bytes_to_read = 0; // reset trigger
this.read_callback(data); this.read_callback(data);
} }
}; };
@ -188,7 +188,7 @@ STM32_protocol.prototype.retrieve = function(n_bytes, callback) {
// data that we need are there, process immediately // data that we need are there, process immediately
var data = this.receive_buffer.slice(0, n_bytes); var data = this.receive_buffer.slice(0, n_bytes);
this.receive_buffer.splice(0, n_bytes); // remove read bytes this.receive_buffer.splice(0, n_bytes); // remove read bytes
callback(data); callback(data);
} else { } else {
// still waiting for data, add callback // still waiting for data, add callback
@ -203,38 +203,38 @@ STM32_protocol.prototype.retrieve = function(n_bytes, callback) {
STM32_protocol.prototype.send = function(Array, bytes_to_read, callback) { STM32_protocol.prototype.send = function(Array, bytes_to_read, callback) {
// flip flag // flip flag
this.upload_process_alive = true; this.upload_process_alive = true;
var bufferOut = new ArrayBuffer(Array.length); var bufferOut = new ArrayBuffer(Array.length);
var bufferView = new Uint8Array(bufferOut); var bufferView = new Uint8Array(bufferOut);
// set Array values inside bufferView (alternative to for loop) // set Array values inside bufferView (alternative to for loop)
bufferView.set(Array); bufferView.set(Array);
// update references // update references
this.bytes_to_read = bytes_to_read; this.bytes_to_read = bytes_to_read;
this.read_callback = callback; this.read_callback = callback;
// empty receive buffer before next command is out // empty receive buffer before next command is out
this.receive_buffer = []; this.receive_buffer = [];
// send over the actual data // send over the actual data
serial.send(bufferOut, function(writeInfo) {}); serial.send(bufferOut, function(writeInfo) {});
}; };
// val = single byte to be verified // val = single byte to be verified
// data = response of n bytes from mcu (array) // data = response of n bytes from mcu (array)
// result = true/false // result = true/false
STM32_protocol.prototype.verify_response = function(val, data) { STM32_protocol.prototype.verify_response = function(val, data) {
if (val != data[0]) { if (val != data[0]) {
console.log('STM32 Communication failed, wrong response, expected: ' + val + ' received: ' + data[0]); console.log('STM32 Communication failed, wrong response, expected: ' + val + ' received: ' + data[0]);
STM32.GUI_status('STM32 Communication <span style="color: red">failed</span>, wrong response, expected: ' + val + ' received: ' + data[0]); STM32.GUI_status('STM32 Communication <span style="color: red">failed</span>, wrong response, expected: ' + val + ' received: ' + data[0]);
// disconnect // disconnect
this.upload_procedure(99); this.upload_procedure(99);
return false; return false;
} }
return true; return true;
}; };
@ -242,7 +242,7 @@ STM32_protocol.prototype.verify_response = function(val, data) {
// result = true/false // result = true/false
STM32_protocol.prototype.verify_chip_signature = function(signature) { STM32_protocol.prototype.verify_chip_signature = function(signature) {
var available_flash_size = 0; var available_flash_size = 0;
switch (signature) { switch (signature) {
case 0x412: // not tested case 0x412: // not tested
console.log('Chip recognized as F1 Low-density'); console.log('Chip recognized as F1 Low-density');
@ -297,19 +297,19 @@ STM32_protocol.prototype.verify_chip_signature = function(signature) {
console.log('Chip recognized as F3 STM32F30xxx, STM32F31xxx'); console.log('Chip recognized as F3 STM32F30xxx, STM32F31xxx');
break; break;
} }
if (available_flash_size > 0) { if (available_flash_size > 0) {
if (this.hex.bytes_total < available_flash_size) { if (this.hex.bytes_total < available_flash_size) {
return true; return true;
} else { } else {
console.log('Supplied hex is bigger then flash available on the chip, HEX: ' + this.hex.bytes_total + ' bytes, limit = ' + available_flash_size + ' bytes'); console.log('Supplied hex is bigger then flash available on the chip, HEX: ' + this.hex.bytes_total + ' bytes, limit = ' + available_flash_size + ' bytes');
return false; return false;
} }
} }
console.log('Chip NOT recognized: ' + signature); console.log('Chip NOT recognized: ' + signature);
return false; return false;
}; };
@ -323,16 +323,16 @@ STM32_protocol.prototype.verify_flash = function(first_array, second_array) {
return false; return false;
} }
} }
console.log('Verification successful, matching: ' + first_array.length + ' bytes'); console.log('Verification successful, matching: ' + first_array.length + ' bytes');
return true; return true;
}; };
// step = value depending on current state of upload_procedure // step = value depending on current state of upload_procedure
STM32_protocol.prototype.upload_procedure = function(step) { STM32_protocol.prototype.upload_procedure = function(step) {
var self = this; var self = this;
switch (step) { switch (step) {
case 1: case 1:
// initialize serial interface on the MCU side, auto baud rate settings // initialize serial interface on the MCU side, auto baud rate settings
@ -342,18 +342,18 @@ STM32_protocol.prototype.upload_procedure = function(step) {
if (reply[0] == 0x7F || reply[0] == self.status.ACK || reply[0] == self.status.NACK) { if (reply[0] == 0x7F || reply[0] == self.status.ACK || reply[0] == self.status.NACK) {
GUI.interval_remove('stm32_initialize_mcu'); GUI.interval_remove('stm32_initialize_mcu');
console.log('STM32 - Serial interface initialized on the MCU side'); console.log('STM32 - Serial interface initialized on the MCU side');
// proceed to next step // proceed to next step
self.upload_procedure(2); self.upload_procedure(2);
} else { } else {
GUI.interval_remove('stm32_initialize_mcu'); GUI.interval_remove('stm32_initialize_mcu');
STM32.GUI_status('STM32 Communication with bootloader <span style="color: red">failed</span>'); STM32.GUI_status('STM32 Communication with bootloader <span style="color: red">failed</span>');
// disconnect // disconnect
self.upload_procedure(99); self.upload_procedure(99);
} }
}); });
if (send_counter++ > 3) { if (send_counter++ > 3) {
// stop retrying, its too late to get any response from MCU // stop retrying, its too late to get any response from MCU
GUI.interval_remove('stm32_initialize_mcu'); GUI.interval_remove('stm32_initialize_mcu');
@ -366,7 +366,7 @@ STM32_protocol.prototype.upload_procedure = function(step) {
if (self.verify_response(self.status.ACK, data)) { if (self.verify_response(self.status.ACK, data)) {
self.retrieve(data[1] + 1 + 1, function(data) { // data[1] = number of bytes that will follow [ 1 except current and ACKs] self.retrieve(data[1] + 1 + 1, function(data) { // data[1] = number of bytes that will follow [ 1 except current and ACKs]
console.log('STM32 - Bootloader version: ' + (parseInt(data[0].toString(16)) / 10).toFixed(1)); // convert dec to hex, hex to dec and add floating point console.log('STM32 - Bootloader version: ' + (parseInt(data[0].toString(16)) / 10).toFixed(1)); // convert dec to hex, hex to dec and add floating point
// proceed to next step // proceed to next step
self.upload_procedure(3); self.upload_procedure(3);
}); });
@ -380,7 +380,7 @@ STM32_protocol.prototype.upload_procedure = function(step) {
self.retrieve(data[1] + 1 + 1, function(data) { // data[1] = number of bytes that will follow [ 1 (N = 1 for STM32), except for current byte and ACKs] self.retrieve(data[1] + 1 + 1, function(data) { // data[1] = number of bytes that will follow [ 1 (N = 1 for STM32), except for current byte and ACKs]
var signature = (data[0] << 8) | data[1]; var signature = (data[0] << 8) | data[1];
console.log('STM32 - Signature: 0x' + signature.toString(16)); // signature in hex representation console.log('STM32 - Signature: 0x' + signature.toString(16)); // signature in hex representation
if (self.verify_chip_signature(signature)) { if (self.verify_chip_signature(signature)) {
// proceed to next step // proceed to next step
self.upload_procedure(4); self.upload_procedure(4);
@ -396,7 +396,7 @@ STM32_protocol.prototype.upload_procedure = function(step) {
// erase memory // erase memory
console.log('Executing global chip erase'); console.log('Executing global chip erase');
STM32.GUI_status('Erasing'); STM32.GUI_status('Erasing');
self.send([self.command.erase, 0xBC], 1, function(reply) { // 0x43 ^ 0xFF self.send([self.command.erase, 0xBC], 1, function(reply) { // 0x43 ^ 0xFF
if (self.verify_response(self.status.ACK, reply)) { if (self.verify_response(self.status.ACK, reply)) {
self.send([0xFF, 0x00], 1, function(reply) { self.send([0xFF, 0x00], 1, function(reply) {
@ -404,9 +404,9 @@ STM32_protocol.prototype.upload_procedure = function(step) {
console.log('Erasing: done'); console.log('Erasing: done');
console.log('Writing data ...'); console.log('Writing data ...');
STM32.GUI_status('<span style="color: green">Flashing ...</span>'); STM32.GUI_status('<span style="color: green">Flashing ...</span>');
// proceed to next step // proceed to next step
self.upload_procedure(5); self.upload_procedure(5);
} }
}); });
} }
@ -417,36 +417,36 @@ STM32_protocol.prototype.upload_procedure = function(step) {
var blocks = self.hex.data.length - 1; var blocks = self.hex.data.length - 1;
var flashing_block = 0; var flashing_block = 0;
var address = self.hex.data[flashing_block].address; var address = self.hex.data[flashing_block].address;
var bytes_flashed = 0; var bytes_flashed = 0;
var bytes_flashed_total = 0; // used for progress bar var bytes_flashed_total = 0; // used for progress bar
var write = function() { var write = function() {
if (bytes_flashed < self.hex.data[flashing_block].bytes) { if (bytes_flashed < self.hex.data[flashing_block].bytes) {
var bytes_to_write = ((bytes_flashed + 128) <= self.hex.data[flashing_block].bytes) ? 128 : (self.hex.data[flashing_block].bytes - bytes_flashed); var bytes_to_write = ((bytes_flashed + 128) <= self.hex.data[flashing_block].bytes) ? 128 : (self.hex.data[flashing_block].bytes - bytes_flashed);
// console.log('STM32 - Writing to: 0x' + address.toString(16) + ', ' + bytes_to_write + ' bytes'); // console.log('STM32 - Writing to: 0x' + address.toString(16) + ', ' + bytes_to_write + ' bytes');
self.send([self.command.write_memory, 0xCE], 1, function(reply) { // 0x31 ^ 0xFF self.send([self.command.write_memory, 0xCE], 1, function(reply) { // 0x31 ^ 0xFF
if (self.verify_response(self.status.ACK, reply)) { if (self.verify_response(self.status.ACK, reply)) {
// address needs to be transmitted as 32 bit integer, we need to bit shift each byte out and then calculate address checksum // address needs to be transmitted as 32 bit integer, we need to bit shift each byte out and then calculate address checksum
var address_arr = [(address >> 24), (address >> 16), (address >> 8), address]; var address_arr = [(address >> 24), (address >> 16), (address >> 8), address];
var address_checksum = address_arr[0] ^ address_arr[1] ^ address_arr[2] ^ address_arr[3]; var address_checksum = address_arr[0] ^ address_arr[1] ^ address_arr[2] ^ address_arr[3];
self.send([address_arr[0], address_arr[1], address_arr[2], address_arr[3], address_checksum], 1, function(reply) { // write start address + checksum self.send([address_arr[0], address_arr[1], address_arr[2], address_arr[3], address_checksum], 1, function(reply) { // write start address + checksum
if (self.verify_response(self.status.ACK, reply)) { if (self.verify_response(self.status.ACK, reply)) {
var array_out = new Array(bytes_to_write + 2); // 2 byte overhead [N, ...., checksum] var array_out = new Array(bytes_to_write + 2); // 2 byte overhead [N, ...., checksum]
array_out[0] = bytes_to_write - 1; // number of bytes to be written (to write 128 bytes, N must be 127, to write 256 bytes, N must be 255) array_out[0] = bytes_to_write - 1; // number of bytes to be written (to write 128 bytes, N must be 127, to write 256 bytes, N must be 255)
var checksum = array_out[0]; var checksum = array_out[0];
for (var i = 0; i < bytes_to_write; i++) { for (var i = 0; i < bytes_to_write; i++) {
array_out[i + 1] = self.hex.data[flashing_block].data[bytes_flashed]; // + 1 because of the first byte offset array_out[i + 1] = self.hex.data[flashing_block].data[bytes_flashed]; // + 1 because of the first byte offset
checksum ^= self.hex.data[flashing_block].data[bytes_flashed]; checksum ^= self.hex.data[flashing_block].data[bytes_flashed];
bytes_flashed++; bytes_flashed++;
} }
array_out[array_out.length - 1] = checksum; // checksum (last byte in the array_out array) array_out[array_out.length - 1] = checksum; // checksum (last byte in the array_out array)
address += bytes_to_write; address += bytes_to_write;
bytes_flashed_total += bytes_to_write bytes_flashed_total += bytes_to_write
@ -454,7 +454,7 @@ STM32_protocol.prototype.upload_procedure = function(step) {
if (self.verify_response(self.status.ACK, reply)) { if (self.verify_response(self.status.ACK, reply)) {
// update progress bar // update progress bar
self.progress_bar_e.val(bytes_flashed_total / (self.hex.bytes_total * 2) * 100); self.progress_bar_e.val(bytes_flashed_total / (self.hex.bytes_total * 2) * 100);
// flash another page // flash another page
write(); write();
} }
@ -467,23 +467,23 @@ STM32_protocol.prototype.upload_procedure = function(step) {
// move to another block // move to another block
if (flashing_block < blocks) { if (flashing_block < blocks) {
flashing_block++; flashing_block++;
address = self.hex.data[flashing_block].address; address = self.hex.data[flashing_block].address;
bytes_flashed = 0; bytes_flashed = 0;
write(); write();
} else { } else {
// all blocks flashed // all blocks flashed
console.log('Writing: done'); console.log('Writing: done');
console.log('Verifying data ...'); console.log('Verifying data ...');
STM32.GUI_status('<span style="color: green">Verifying ...</span>'); STM32.GUI_status('<span style="color: green">Verifying ...</span>');
// proceed to next step // proceed to next step
self.upload_procedure(6); self.upload_procedure(6);
} }
} }
}; };
// start writing // start writing
write(); write();
break; break;
@ -492,44 +492,44 @@ STM32_protocol.prototype.upload_procedure = function(step) {
var blocks = self.hex.data.length - 1; var blocks = self.hex.data.length - 1;
var reading_block = 0; var reading_block = 0;
var address = self.hex.data[reading_block].address; var address = self.hex.data[reading_block].address;
var bytes_verified = 0; var bytes_verified = 0;
var bytes_verified_total = 0; // used for progress bar var bytes_verified_total = 0; // used for progress bar
// initialize arrays // initialize arrays
for (var i = 0; i <= blocks; i++) { for (var i = 0; i <= blocks; i++) {
self.verify_hex.push([]); self.verify_hex.push([]);
} }
var reading = function() { var reading = function() {
if (bytes_verified < self.hex.data[reading_block].bytes) { if (bytes_verified < self.hex.data[reading_block].bytes) {
var bytes_to_read = ((bytes_verified + 128) <= self.hex.data[reading_block].bytes) ? 128 : (self.hex.data[reading_block].bytes - bytes_verified); var bytes_to_read = ((bytes_verified + 128) <= self.hex.data[reading_block].bytes) ? 128 : (self.hex.data[reading_block].bytes - bytes_verified);
// console.log('STM32 - Reading from: 0x' + address.toString(16) + ', ' + bytes_to_read + ' bytes'); // console.log('STM32 - Reading from: 0x' + address.toString(16) + ', ' + bytes_to_read + ' bytes');
self.send([self.command.read_memory, 0xEE], 1, function(reply) { // 0x11 ^ 0xFF self.send([self.command.read_memory, 0xEE], 1, function(reply) { // 0x11 ^ 0xFF
if (self.verify_response(self.status.ACK, reply)) { if (self.verify_response(self.status.ACK, reply)) {
var address_arr = [(address >> 24), (address >> 16), (address >> 8), address]; var address_arr = [(address >> 24), (address >> 16), (address >> 8), address];
var address_checksum = address_arr[0] ^ address_arr[1] ^ address_arr[2] ^ address_arr[3]; var address_checksum = address_arr[0] ^ address_arr[1] ^ address_arr[2] ^ address_arr[3];
self.send([address_arr[0], address_arr[1], address_arr[2], address_arr[3], address_checksum], 1, function(reply) { // read start address + checksum self.send([address_arr[0], address_arr[1], address_arr[2], address_arr[3], address_checksum], 1, function(reply) { // read start address + checksum
if (self.verify_response(self.status.ACK, reply)) { if (self.verify_response(self.status.ACK, reply)) {
var bytes_to_read_n = bytes_to_read - 1; var bytes_to_read_n = bytes_to_read - 1;
self.send([bytes_to_read_n, (~bytes_to_read_n) & 0xFF], 1, function(reply) { // bytes to be read + checksum XOR(complement of bytes_to_read_n) self.send([bytes_to_read_n, (~bytes_to_read_n) & 0xFF], 1, function(reply) { // bytes to be read + checksum XOR(complement of bytes_to_read_n)
if (self.verify_response(self.status.ACK, reply)) { if (self.verify_response(self.status.ACK, reply)) {
self.retrieve(bytes_to_read, function(data) { self.retrieve(bytes_to_read, function(data) {
for (var i = 0; i < data.length; i++) { for (var i = 0; i < data.length; i++) {
self.verify_hex[reading_block].push(data[i]); self.verify_hex[reading_block].push(data[i]);
} }
address += bytes_to_read; address += bytes_to_read;
bytes_verified += bytes_to_read; bytes_verified += bytes_to_read;
bytes_verified_total += bytes_to_read; bytes_verified_total += bytes_to_read;
// update progress bar // update progress bar
self.progress_bar_e.val((self.hex.bytes_total + bytes_verified_total) / (self.hex.bytes_total * 2) * 100); self.progress_bar_e.val((self.hex.bytes_total + bytes_verified_total) / (self.hex.bytes_total * 2) * 100);
// verify another page // verify another page
reading(); reading();
}); });
@ -543,44 +543,44 @@ STM32_protocol.prototype.upload_procedure = function(step) {
// move to another block // move to another block
if (reading_block < blocks) { if (reading_block < blocks) {
reading_block++; reading_block++;
address = self.hex.data[reading_block].address; address = self.hex.data[reading_block].address;
bytes_verified = 0; bytes_verified = 0;
reading(); reading();
} else { } else {
// all blocks read, verify // all blocks read, verify
var verify = true; var verify = true;
for (var i = 0; i <= blocks; i++) { for (var i = 0; i <= blocks; i++) {
verify = self.verify_flash(self.hex.data[i].data, self.verify_hex[i]); verify = self.verify_flash(self.hex.data[i].data, self.verify_hex[i]);
if (!verify) break; if (!verify) break;
} }
if (verify) { if (verify) {
console.log('Programming: SUCCESSFUL'); console.log('Programming: SUCCESSFUL');
STM32.GUI_status('Programming: <strong style="color: green">SUCCESSFUL</strong>'); STM32.GUI_status('Programming: <strong style="color: green">SUCCESSFUL</strong>');
// update progress bar // update progress bar
self.progress_bar_e.addClass('valid'); self.progress_bar_e.addClass('valid');
// proceed to next step // proceed to next step
self.upload_procedure(7); self.upload_procedure(7);
} else { } else {
console.log('Programming: FAILED'); console.log('Programming: FAILED');
STM32.GUI_status('Programming: <strong style="color: red">FAILED</strong>'); STM32.GUI_status('Programming: <strong style="color: red">FAILED</strong>');
// update progress bar // update progress bar
self.progress_bar_e.addClass('invalid'); self.progress_bar_e.addClass('invalid');
// disconnect // disconnect
self.upload_procedure(99); self.upload_procedure(99);
} }
} }
} }
}; };
// start reading // start reading
reading(); reading();
break; break;
@ -594,7 +594,7 @@ STM32_protocol.prototype.upload_procedure = function(step) {
var gt_address = 0x8000000; var gt_address = 0x8000000;
var address = [(gt_address >> 24), (gt_address >> 16), (gt_address >> 8), gt_address]; var address = [(gt_address >> 24), (gt_address >> 16), (gt_address >> 8), gt_address];
var address_checksum = address[0] ^ address[1] ^ address[2] ^ address[3]; var address_checksum = address[0] ^ address[1] ^ address[2] ^ address[3];
self.send([address[0], address[1], address[2], address[3], address_checksum], 1, function(reply) { self.send([address[0], address[1], address[2], address[3], address_checksum], 1, function(reply) {
if (self.verify_response(self.status.ACK, reply)) { if (self.verify_response(self.status.ACK, reply)) {
// disconnect // disconnect
@ -607,15 +607,15 @@ STM32_protocol.prototype.upload_procedure = function(step) {
case 99: case 99:
// disconnect // disconnect
GUI.interval_remove('STM32_timeout'); // stop STM32 timeout timer (everything is finished now) GUI.interval_remove('STM32_timeout'); // stop STM32 timeout timer (everything is finished now)
console.log('Script finished after: ' + (microtime() - self.upload_time_start).toFixed(4) + ' seconds'); console.log('Script finished after: ' + (microtime() - self.upload_time_start).toFixed(4) + ' seconds');
// close connection // close connection
serial.disconnect(function(result) { serial.disconnect(function(result) {
if (result) { // All went as expected if (result) { // All went as expected
} else { // Something went wrong } else { // Something went wrong
} }
// unlocking connect button // unlocking connect button
GUI.connect_lock = false; GUI.connect_lock = false;
}); });

View file

@ -3,24 +3,24 @@
// if hex file wasn't valid (crc check failed on any of the lines), result will be false // if hex file wasn't valid (crc check failed on any of the lines), result will be false
function read_hex_file(data) { function read_hex_file(data) {
data = data.split("\n"); data = data.split("\n");
// check if there is an empty line in the end of hex file, if there is, remove it // check if there is an empty line in the end of hex file, if there is, remove it
if (data[data.length - 1] == "") { if (data[data.length - 1] == "") {
data.pop(); data.pop();
} }
var hexfile_valid = true; // if any of the crc checks failed, this variable flips to false var hexfile_valid = true; // if any of the crc checks failed, this variable flips to false
var result = { var result = {
data: [], data: [],
end_of_file: false, end_of_file: false,
bytes_total: 0, bytes_total: 0,
start_linear_address: 0 start_linear_address: 0
}; };
var extended_linear_address = 0; var extended_linear_address = 0;
var next_address = 0; var next_address = 0;
for (var i = 0; i < data.length && hexfile_valid; i++) { for (var i = 0; i < data.length && hexfile_valid; i++) {
// each byte is represnted by two chars // each byte is represnted by two chars
var byte_count = parseInt(data[i].substr(1, 2), 16); var byte_count = parseInt(data[i].substr(1, 2), 16);
@ -28,33 +28,33 @@ function read_hex_file(data) {
var record_type = parseInt(data[i].substr(7, 2), 16); var record_type = parseInt(data[i].substr(7, 2), 16);
var content = data[i].substr(9, byte_count * 2); // still in string format var content = data[i].substr(9, byte_count * 2); // still in string format
var checksum = parseInt(data[i].substr(9 + byte_count * 2, 2), 16); // (this is a 2's complement value) var checksum = parseInt(data[i].substr(9 + byte_count * 2, 2), 16); // (this is a 2's complement value)
switch (record_type) { switch (record_type) {
case 0x00: // data record case 0x00: // data record
if (address != next_address || next_address == 0) { if (address != next_address || next_address == 0) {
result.data.push({'address': extended_linear_address + address, 'bytes': 0, 'data': []}); result.data.push({'address': extended_linear_address + address, 'bytes': 0, 'data': []});
} }
// store address for next comparison // store address for next comparison
next_address = address + byte_count; next_address = address + byte_count;
// process data // process data
var crc = byte_count + parseInt(data[i].substr(3, 2), 16) + parseInt(data[i].substr(5, 2), 16) + record_type; var crc = byte_count + parseInt(data[i].substr(3, 2), 16) + parseInt(data[i].substr(5, 2), 16) + record_type;
for (var needle = 0; needle < byte_count * 2; needle += 2) { // * 2 because of 2 hex chars per 1 byte for (var needle = 0; needle < byte_count * 2; needle += 2) { // * 2 because of 2 hex chars per 1 byte
var num = parseInt(content.substr(needle, 2), 16); // get one byte in hex and convert it to decimal var num = parseInt(content.substr(needle, 2), 16); // get one byte in hex and convert it to decimal
var data_block = result.data.length - 1; var data_block = result.data.length - 1;
result.data[data_block].data.push(num); result.data[data_block].data.push(num);
result.data[data_block].bytes++; result.data[data_block].bytes++;
crc += num; crc += num;
result.bytes_total++; result.bytes_total++;
} }
// change crc to 2's complement // change crc to 2's complement
crc = (~crc + 1) & 0xFF; crc = (~crc + 1) & 0xFF;
// verify // verify
if (crc != checksum) { if (crc != checksum) {
hexfile_valid = false; hexfile_valid = false;
} }
@ -82,7 +82,7 @@ function read_hex_file(data) {
break; break;
} }
} }
if (result.end_of_file && hexfile_valid) { if (result.end_of_file && hexfile_valid) {
postMessage(result); postMessage(result);
} else { } else {
@ -98,11 +98,11 @@ function microtime() {
onmessage = function(event) { onmessage = function(event) {
var time_parsing_start = microtime(); // track time var time_parsing_start = microtime(); // track time
read_hex_file(event.data); read_hex_file(event.data);
console.log('HEX_PARSER - File parsed in: ' + (microtime() - time_parsing_start).toFixed(4) + ' seconds'); console.log('HEX_PARSER - File parsed in: ' + (microtime() - time_parsing_start).toFixed(4) + ' seconds');
// terminate worker // terminate worker
close(); close();
}; };

View file

@ -3,9 +3,9 @@
<head> <head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" /> <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<meta name="author" content="cTn" /> <meta name="author" content="cTn" />
<link type="text/css" rel="stylesheet" href="./css/style.css" media="all" /> <link type="text/css" rel="stylesheet" href="./css/style.css" media="all" />
<script type="text/javascript" src="./js/libraries/google-analytics-bundle.js"></script> <script type="text/javascript" src="./js/libraries/google-analytics-bundle.js"></script>
<script type="text/javascript" src="./js/libraries/flotr2.min.js"></script> <script type="text/javascript" src="./js/libraries/flotr2.min.js"></script>
<script type="text/javascript" src="./js/libraries/jquery-2.1.0.min.js"></script> <script type="text/javascript" src="./js/libraries/jquery-2.1.0.min.js"></script>
@ -19,7 +19,7 @@
<script type="text/javascript" src="./js/backup_restore.js"></script> <script type="text/javascript" src="./js/backup_restore.js"></script>
<script type="text/javascript" src="./js/stm32.js"></script> <script type="text/javascript" src="./js/stm32.js"></script>
<!-- Various tabs are divided into separate files (for clarity) --> <!-- Various tabs are divided into separate files (for clarity) -->
<script type="text/javascript" src="./tabs/default.js"></script> <script type="text/javascript" src="./tabs/default.js"></script>
<script type="text/javascript" src="./tabs/initial_setup.js"></script> <script type="text/javascript" src="./tabs/initial_setup.js"></script>
<script type="text/javascript" src="./tabs/pid_tuning.js"></script> <script type="text/javascript" src="./tabs/pid_tuning.js"></script>
@ -31,7 +31,7 @@
<script type="text/javascript" src="./tabs/sensors.js"></script> <script type="text/javascript" src="./tabs/sensors.js"></script>
<script type="text/javascript" src="./tabs/cli.js"></script> <script type="text/javascript" src="./tabs/cli.js"></script>
<script type="text/javascript" src="./tabs/firmware_flasher.js"></script> <script type="text/javascript" src="./tabs/firmware_flasher.js"></script>
<!-- Various tab styles are divided into separate files (for clarity) --> <!-- Various tab styles are divided into separate files (for clarity) -->
<link type="text/css" rel="stylesheet" href="./tabs/default.css" media="all" /> <link type="text/css" rel="stylesheet" href="./tabs/default.css" media="all" />
<link type="text/css" rel="stylesheet" href="./tabs/initial_setup.css" media="all" /> <link type="text/css" rel="stylesheet" href="./tabs/initial_setup.css" media="all" />
@ -82,7 +82,7 @@
<span class="auto_connect">Auto-Connect</span> <span class="auto_connect">Auto-Connect</span>
</label> </label>
</li> </li>
</ul> </ul>
</div> </div>
<div id="sensor-status"> <div id="sensor-status">
<ul> <ul>
@ -112,11 +112,11 @@
<li class="tab_cli"><a href="#">CLI</a></li> <li class="tab_cli"><a href="#">CLI</a></li>
</ul> </ul>
<div class="clear-both"></div> <div class="clear-both"></div>
</div> </div>
<div id="content"> <div id="content">
</div> </div>
<div id="status-bar"> <div id="status-bar">
Port utilization: <span class="port-usage">0%</span> | Port utilization: <span class="port-usage">0%</span> |
Packet error: <span class="packet-error">0</span> | Packet error: <span class="packet-error">0</span> |
Firmware Version: <span class="software-version">0.0</span> | Firmware Version: <span class="software-version">0.0</span> |
Cycle Time: <span class="cycle-time">0</span> Cycle Time: <span class="cycle-time">0</span>
@ -124,4 +124,4 @@
</div> </div>
</div> </div>
</body> </body>
</html> </html>

96
main.js
View file

@ -12,24 +12,24 @@ var service = analytics.getService('ice_cream_app');
var ga_tracker = service.getTracker('UA-32728876-6'); var ga_tracker = service.getTracker('UA-32728876-6');
ga_tracker.sendAppView('Application Started'); ga_tracker.sendAppView('Application Started');
// Google Analytics stuff end // Google Analytics stuff end
$(document).ready(function() { $(document).ready(function() {
// bind controls // bind controls
$('#frame .minimize').click(function() { $('#frame .minimize').click(function() {
chrome.app.window.current().minimize(); chrome.app.window.current().minimize();
}); });
$('#frame .maximize').click(function() { $('#frame .maximize').click(function() {
chrome.app.window.current().maximize(); chrome.app.window.current().maximize();
}); });
$('#frame .close').click(function() { $('#frame .close').click(function() {
chrome.app.window.current().close(); chrome.app.window.current().close();
}); });
// alternative - window.navigator.appVersion.match(/Chrome\/([0-9.]*)/)[1]; // alternative - window.navigator.appVersion.match(/Chrome\/([0-9.]*)/)[1];
GUI.log('Running - OS: <strong>' + GUI.operating_system + '</strong>, ' + GUI.log('Running - OS: <strong>' + GUI.operating_system + '</strong>, ' +
'Chrome: <strong>' + window.navigator.appVersion.replace(/.*Chrome\/([0-9.]*).*/,"$1") + '</strong>, ' + 'Chrome: <strong>' + window.navigator.appVersion.replace(/.*Chrome\/([0-9.]*).*/,"$1") + '</strong>, ' +
'Configurator: <strong>' + chrome.runtime.getManifest().version + '</strong>'); 'Configurator: <strong>' + chrome.runtime.getManifest().version + '</strong>');
@ -47,7 +47,7 @@ $(document).ready(function() {
case 'UNIX': case 'UNIX':
break; break;
} }
// Tabs // Tabs
var tabs = $('#tabs > ul'); var tabs = $('#tabs > ul');
$('a', tabs).click(function() { $('a', tabs).click(function() {
@ -56,19 +56,19 @@ $(document).ready(function() {
GUI.log('You need to connect before you can view any of the tabs', 'red'); GUI.log('You need to connect before you can view any of the tabs', 'red');
return; return;
} }
var self = this; var self = this;
GUI.tab_switch_cleanup(function() { GUI.tab_switch_cleanup(function() {
// disable previously active tab highlight // disable previously active tab highlight
$('li', tabs).removeClass('active'); $('li', tabs).removeClass('active');
// get tab class name (there should be only one class listed) // get tab class name (there should be only one class listed)
var tab = $(self).parent().prop('class'); var tab = $(self).parent().prop('class');
// Highlight selected tab // Highlight selected tab
$(self).parent().addClass('active'); $(self).parent().addClass('active');
switch (tab) { switch (tab) {
case 'tab_initial_setup': case 'tab_initial_setup':
tab_initialize_initial_setup(); tab_initialize_initial_setup();
@ -93,27 +93,27 @@ $(document).ready(function() {
break; break;
case 'tab_sensors': case 'tab_sensors':
tab_initialize_sensors(); tab_initialize_sensors();
break; break;
case 'tab_cli': case 'tab_cli':
tab_initialize_cli(); tab_initialize_cli();
break; break;
} }
}); });
} }
}); });
tab_initialize_default(); tab_initialize_default();
// listen to all input change events and adjust the value within limits if necessary // listen to all input change events and adjust the value within limits if necessary
$("#content").on('focus', 'input[type="number"]', function() { $("#content").on('focus', 'input[type="number"]', function() {
var element = $(this); var element = $(this);
var val = element.val(); var val = element.val();
if (!isNaN(val)) { if (!isNaN(val)) {
element.data('previousValue', parseFloat(val)); element.data('previousValue', parseFloat(val));
} }
}); });
$("#content").on('keydown', 'input[type="number"]', function(e) { $("#content").on('keydown', 'input[type="number"]', function(e) {
// whitelist all that we need for numeric control // whitelist all that we need for numeric control
if ((e.keyCode >= 96 && e.keyCode <= 105) || (e.keyCode >= 48 && e.keyCode <= 57)) { // allow numpad and standard number keypad if ((e.keyCode >= 96 && e.keyCode <= 105) || (e.keyCode >= 48 && e.keyCode <= 57)) { // allow numpad and standard number keypad
@ -126,40 +126,40 @@ $(document).ready(function() {
e.preventDefault(); e.preventDefault();
} }
}); });
$("#content").on('change', 'input[type="number"]', function() { $("#content").on('change', 'input[type="number"]', function() {
var element = $(this); var element = $(this);
var min = parseFloat(element.prop('min')); var min = parseFloat(element.prop('min'));
var max = parseFloat(element.prop('max')); var max = parseFloat(element.prop('max'));
var step = parseFloat(element.prop('step')); var step = parseFloat(element.prop('step'));
var val = parseFloat(element.val()); var val = parseFloat(element.val());
// only adjust minimal end if bound is set // only adjust minimal end if bound is set
if (element.prop('min')) { if (element.prop('min')) {
if (val < min) element.val(min); if (val < min) element.val(min);
} }
// only adjust maximal end if bound is set // only adjust maximal end if bound is set
if (element.prop('max')) { if (element.prop('max')) {
if (val > max) element.val(max); if (val > max) element.val(max);
} }
// if entered value is illegal use previous value instead // if entered value is illegal use previous value instead
if (isNaN(val)) { if (isNaN(val)) {
element.val(element.data('previousValue')); element.val(element.data('previousValue'));
} }
// if step is not set or step is int and value is float use previous value instead // if step is not set or step is int and value is float use previous value instead
if (isNaN(step) || step % 1 === 0) { if (isNaN(step) || step % 1 === 0) {
if (val % 1 !== 0) { if (val % 1 !== 0) {
element.val(element.data('previousValue')); element.val(element.data('previousValue'));
} }
} }
// if step is set and is float and value is int, convert to float, keep decimal places in float according to step *experimental* // if step is set and is float and value is int, convert to float, keep decimal places in float according to step *experimental*
if (!isNaN(step) && step % 1 !== 0) { if (!isNaN(step) && step % 1 !== 0) {
var decimal_places = String(step).split('.')[1].length; var decimal_places = String(step).split('.')[1].length;
if (val % 1 === 0) { if (val % 1 === 0) {
element.val(val.toFixed(decimal_places)); element.val(val.toFixed(decimal_places));
} else if (String(val).split('.')[1].length != decimal_places) { } else if (String(val).split('.')[1].length != decimal_places) {
@ -178,10 +178,10 @@ function microtime() {
/* /*
function add_custom_spinners() { function add_custom_spinners() {
var spinner_element = '<div class="spinner"><div class="up"></div><div class="down"></div></div>'; var spinner_element = '<div class="spinner"><div class="up"></div><div class="down"></div></div>';
$('input[type="number"]').each(function() { $('input[type="number"]').each(function() {
var input = $(this); var input = $(this);
// only add new spinner if one doesn't already exist // only add new spinner if one doesn't already exist
if (!input.next().hasClass('spinner')) { if (!input.next().hasClass('spinner')) {
var isInt = true; var isInt = true;
@ -194,62 +194,62 @@ function add_custom_spinners() {
isInt = false; isInt = false;
} }
} }
// make space for spinner // make space for spinner
input.width(input.width() - 16); input.width(input.width() - 16);
// add spinner // add spinner
input.after(spinner_element); input.after(spinner_element);
// get spinner refference // get spinner refference
var spinner = input.next(); var spinner = input.next();
// bind UI hooks to spinner // bind UI hooks to spinner
$('.up', spinner).click(function() { $('.up', spinner).click(function() {
up(); up();
}); });
$('.up', spinner).mousedown(function() { $('.up', spinner).mousedown(function() {
GUI.timeout_add('spinner', function() { GUI.timeout_add('spinner', function() {
GUI.interval_add('spinner', function() { GUI.interval_add('spinner', function() {
up(); up();
}, 100, true); }, 100, true);
}, 250); }, 250);
}); });
$('.up', spinner).mouseup(function() { $('.up', spinner).mouseup(function() {
GUI.timeout_remove('spinner'); GUI.timeout_remove('spinner');
GUI.interval_remove('spinner'); GUI.interval_remove('spinner');
}); });
$('.up', spinner).mouseleave(function() { $('.up', spinner).mouseleave(function() {
GUI.timeout_remove('spinner'); GUI.timeout_remove('spinner');
GUI.interval_remove('spinner'); GUI.interval_remove('spinner');
}); });
$('.down', spinner).click(function() { $('.down', spinner).click(function() {
down(); down();
}); });
$('.down', spinner).mousedown(function() { $('.down', spinner).mousedown(function() {
GUI.timeout_add('spinner', function() { GUI.timeout_add('spinner', function() {
GUI.interval_add('spinner', function() { GUI.interval_add('spinner', function() {
down(); down();
}, 100, true); }, 100, true);
}, 250); }, 250);
}); });
$('.down', spinner).mouseup(function() { $('.down', spinner).mouseup(function() {
GUI.timeout_remove('spinner'); GUI.timeout_remove('spinner');
GUI.interval_remove('spinner'); GUI.interval_remove('spinner');
}); });
$('.down', spinner).mouseleave(function() { $('.down', spinner).mouseleave(function() {
GUI.timeout_remove('spinner'); GUI.timeout_remove('spinner');
GUI.interval_remove('spinner'); GUI.interval_remove('spinner');
}); });
var up = function() { var up = function() {
if (isInt) { if (isInt) {
var current_value = parseInt(input.val()); var current_value = parseInt(input.val());
@ -258,13 +258,13 @@ function add_custom_spinners() {
var current_value = parseFloat(input.val()); var current_value = parseFloat(input.val());
var step = parseFloat(input.prop('step')); var step = parseFloat(input.prop('step'));
var step_decimals = input.prop('step').length - 2; var step_decimals = input.prop('step').length - 2;
input.val((current_value + step).toFixed(step_decimals)); input.val((current_value + step).toFixed(step_decimals));
} }
input.change(); input.change();
}; };
var down = function() { var down = function() {
if (isInt) { if (isInt) {
var current_value = parseInt(input.val()); var current_value = parseInt(input.val());
@ -273,10 +273,10 @@ function add_custom_spinners() {
var current_value = parseFloat(input.val()); var current_value = parseFloat(input.val());
var step = parseFloat(input.prop('step')); var step = parseFloat(input.prop('step'));
var step_decimals = input.prop('step').length - 2; var step_decimals = input.prop('step').length - 2;
input.val((current_value - step).toFixed(step_decimals)); input.val((current_value - step).toFixed(step_decimals));
} }
input.change(); input.change();
}; };
} }

View file

@ -2,20 +2,20 @@
"manifest_version": 2, "manifest_version": 2,
"minimum_chrome_version": "33", "minimum_chrome_version": "33",
"version": "0.29", "version": "0.29",
"author": "cTn", "author": "cTn",
"name": "Baseflight - Configurator", "name": "Baseflight - Configurator",
"short_name": "baseflight", "short_name": "baseflight",
"description": "Crossplatform configuration tool for Baseflight flight control system", "description": "Crossplatform configuration tool for Baseflight flight control system",
"offline_enabled": true, "offline_enabled": true,
"app": { "app": {
"background": { "background": {
"scripts": [ "background.js" ] "scripts": [ "background.js" ]
} }
}, },
"permissions": [ "permissions": [
"https://www.google-analytics.com/", "https://www.google-analytics.com/",
"https://*.github.com/", "https://*.github.com/",
@ -26,7 +26,7 @@
"clipboardWrite", "clipboardWrite",
"notifications" "notifications"
], ],
"icons": { "icons": {
"128": "images/icon_128.png" "128": "images/icon_128.png"
} }

View file

@ -6,18 +6,18 @@
} }
.tab-auxiliary_configuration .heads li { .tab-auxiliary_configuration .heads li {
float: left; float: left;
width: 182px; width: 182px;
height: 22px; height: 22px;
line-height: 22px; line-height: 22px;
text-align: center; text-align: center;
font-weight: bold; font-weight: bold;
border: 1px solid #8b8b8b; border: 1px solid #8b8b8b;
border-bottom: 0; border-bottom: 0;
border-left: 0; border-left: 0;
background-color: #ececec; background-color: #ececec;
} }
.tab-auxiliary_configuration .heads li:first-child { .tab-auxiliary_configuration .heads li:first-child {
@ -31,12 +31,12 @@
} }
.tab-auxiliary_configuration .boxes { .tab-auxiliary_configuration .boxes {
width: 100%; width: 100%;
border-collapse: collapse; border-collapse: collapse;
} }
.tab-auxiliary_configuration .boxes th, .tab-auxiliary_configuration .boxes td { .tab-auxiliary_configuration .boxes th, .tab-auxiliary_configuration .boxes td {
line-height: 22px; line-height: 22px;
text-align: center; text-align: center;
border: 1px solid #8b8b8b; border: 1px solid #8b8b8b;
} }
.tab-auxiliary_configuration .boxes .name { .tab-auxiliary_configuration .boxes .name {
@ -53,27 +53,27 @@
} }
.tab-auxiliary_configuration .boxes td input { .tab-auxiliary_configuration .boxes td input {
position: absolute; position: absolute;
margin-top: -6px; margin-top: -6px;
margin-left: -6px; margin-left: -6px;
} }
.tab-auxiliary_configuration .boxes tr:nth-child(odd) { .tab-auxiliary_configuration .boxes tr:nth-child(odd) {
background-color: #ececec; background-color: #ececec;
} }
.tab-auxiliary_configuration .update { .tab-auxiliary_configuration .update {
display: block; display: block;
float: right; float: right;
margin-top: 10px; margin-top: 10px;
height: 28px; height: 28px;
line-height: 28px; line-height: 28px;
padding: 0 15px 0 15px; padding: 0 15px 0 15px;
text-align: center; text-align: center;
font-weight: bold; font-weight: bold;
border: 1px solid silver; border: 1px solid silver;
background-color: #ececec; background-color: #ececec;
} }

View file

@ -21,7 +21,7 @@
<th>HIGH</th> <th>HIGH</th>
<th>LOW</th> <th>LOW</th>
<th>MED</th> <th>MED</th>
<th>HIGH</th> <th>HIGH</th>
</tr> </tr>
</table> </table>
<a class="update" href="#" title="">Save</a> <a class="update" href="#" title="">Save</a>

View file

@ -13,7 +13,7 @@ function tab_initialize_auxiliary_configuration() {
box_check(AUX_CONFIG_values[i], 0) + box_check(AUX_CONFIG_values[i], 0) +
box_check(AUX_CONFIG_values[i], 1) + box_check(AUX_CONFIG_values[i], 1) +
box_check(AUX_CONFIG_values[i], 2) + box_check(AUX_CONFIG_values[i], 2) +
box_check(AUX_CONFIG_values[i], 3) + box_check(AUX_CONFIG_values[i], 3) +
box_check(AUX_CONFIG_values[i], 4) + box_check(AUX_CONFIG_values[i], 4) +
box_check(AUX_CONFIG_values[i], 5) + box_check(AUX_CONFIG_values[i], 5) +
@ -24,12 +24,12 @@ function tab_initialize_auxiliary_configuration() {
box_check(AUX_CONFIG_values[i], 9) + box_check(AUX_CONFIG_values[i], 9) +
box_check(AUX_CONFIG_values[i], 10) + box_check(AUX_CONFIG_values[i], 10) +
box_check(AUX_CONFIG_values[i], 11) + box_check(AUX_CONFIG_values[i], 11) +
'</tr>' '</tr>'
); );
} }
// UI Hooks // UI Hooks
$('a.update').click(function() { $('a.update').click(function() {
// catch the input changes // catch the input changes
var main_needle = 0; var main_needle = 0;
@ -40,34 +40,34 @@ function tab_initialize_auxiliary_configuration() {
} else { } else {
AUX_CONFIG_values[main_needle] = bit_clear(AUX_CONFIG_values[main_needle], needle); AUX_CONFIG_values[main_needle] = bit_clear(AUX_CONFIG_values[main_needle], needle);
} }
needle++; needle++;
if (needle >= 12) { // 4 aux * 3 checkboxes = 12 bits per line if (needle >= 12) { // 4 aux * 3 checkboxes = 12 bits per line
main_needle++; main_needle++;
needle = 0; needle = 0;
} }
}); });
// send over the data // send over the data
var AUX_val_buffer_out = new Array(); var AUX_val_buffer_out = new Array();
var needle = 0; var needle = 0;
for (var i = 0; i < AUX_CONFIG_values.length; i++) { for (var i = 0; i < AUX_CONFIG_values.length; i++) {
AUX_val_buffer_out[needle++] = lowByte(AUX_CONFIG_values[i]); AUX_val_buffer_out[needle++] = lowByte(AUX_CONFIG_values[i]);
AUX_val_buffer_out[needle++] = highByte(AUX_CONFIG_values[i]); AUX_val_buffer_out[needle++] = highByte(AUX_CONFIG_values[i]);
} }
send_message(MSP_codes.MSP_SET_BOX, AUX_val_buffer_out); send_message(MSP_codes.MSP_SET_BOX, AUX_val_buffer_out);
// Save changes to EEPROM // Save changes to EEPROM
send_message(MSP_codes.MSP_EEPROM_WRITE, MSP_codes.MSP_EEPROM_WRITE, false, function() { send_message(MSP_codes.MSP_EEPROM_WRITE, MSP_codes.MSP_EEPROM_WRITE, false, function() {
GUI.log('EEPROM <span style="color: green">saved</span>'); GUI.log('EEPROM <span style="color: green">saved</span>');
var element = $('a.update'); var element = $('a.update');
element.addClass('success'); element.addClass('success');
GUI.timeout_add('success_highlight', function() { GUI.timeout_add('success_highlight', function() {
element.removeClass('success'); element.removeClass('success');
}, 2000); }, 2000);
@ -80,16 +80,16 @@ function tab_initialize_auxiliary_configuration() {
send_message(MSP_codes.MSP_RC, MSP_codes.MSP_RC, false, function() { send_message(MSP_codes.MSP_RC, MSP_codes.MSP_RC, false, function() {
for (var i = 0; i < AUX_CONFIG.length; i++) { for (var i = 0; i < AUX_CONFIG.length; i++) {
if (bit_check(CONFIG.mode, i)) { if (bit_check(CONFIG.mode, i)) {
$('td.name').eq(i).addClass('on').removeClass('off'); $('td.name').eq(i).addClass('on').removeClass('off');
} else { } else {
$('td.name').eq(i).removeClass('on').removeClass('off'); $('td.name').eq(i).removeClass('on').removeClass('off');
if (AUX_CONFIG_values[i] > 0) { if (AUX_CONFIG_values[i] > 0) {
$('td.name').eq(i).addClass('off'); $('td.name').eq(i).addClass('off');
} }
} }
} }
box_highlight(RC.AUX1, 2); box_highlight(RC.AUX1, 2);
box_highlight(RC.AUX2, 5); box_highlight(RC.AUX2, 5);
box_highlight(RC.AUX3, 8); box_highlight(RC.AUX3, 8);
@ -114,7 +114,7 @@ function box_check(num, pos) {
function box_highlight(val, aux_num) { function box_highlight(val, aux_num) {
var tr = $('table.boxes tr'); var tr = $('table.boxes tr');
var pos = 0; // < 1300 var pos = 0; // < 1300
if (val > 1300 && val < 1700) { if (val > 1300 && val < 1700) {
pos = 1; pos = 1;
} else if (val > 1700) { } else if (val > 1700) {

View file

@ -7,48 +7,48 @@
.tab-cli .window { .tab-cli .window {
margin-top: 10px; margin-top: 10px;
height: 350px; height: 350px;
padding: 5px; padding: 5px;
overflow-y: scroll; overflow-y: scroll;
overflow-x: hidden; overflow-x: hidden;
font-family: monospace; font-family: monospace;
color: white; color: white;
border: 1px solid silver; border: 1px solid silver;
background-color: black; background-color: black;
-webkit-user-select: text; -webkit-user-select: text;
} }
.tab-cli textarea { .tab-cli textarea {
margin-top: 8px; margin-top: 8px;
display: block; display: block;
height: 20px; height: 20px;
line-height: 20px; line-height: 20px;
padding-left: 5px; padding-left: 5px;
border: 1px solid silver; border: 1px solid silver;
resize: none; resize: none;
} }
.tab-cli .copy { .tab-cli .copy {
display: block; display: block;
position: absolute; position: absolute;
bottom: 55px; bottom: 55px;
right: 40px; right: 40px;
height: 28px; height: 28px;
line-height: 28px; line-height: 28px;
padding: 0 15px 0 15px; padding: 0 15px 0 15px;
text-align: center; text-align: center;
font-weight: bold; font-weight: bold;
border: 1px solid silver; border: 1px solid silver;
background-color: #ececec; background-color: #ececec;
} }

View file

@ -1,6 +1,6 @@
<div class="tab-cli"> <div class="tab-cli">
<p> <p>
<span style="color: red;">Note</span>: Leaving CLI tab or pressing Disconnect will <strong>automatically</strong> <span style="color: red;">Note</span>: Leaving CLI tab or pressing Disconnect will <strong>automatically</strong>
send "<strong>exit</strong>" to the board, which will make the controller save all the changes and <span style="color: red">restart</span>. send "<strong>exit</strong>" to the board, which will make the controller save all the changes and <span style="color: red">restart</span>.
</p> </p>
<div class="window"> <div class="window">

View file

@ -24,17 +24,17 @@ cli_history = new CliHistory();
function tab_initialize_cli() { function tab_initialize_cli() {
ga_tracker.sendAppView('CLI Page'); ga_tracker.sendAppView('CLI Page');
GUI.active_tab = 'cli'; GUI.active_tab = 'cli';
// remove any active interval for delayed command // remove any active interval for delayed command
MSP.callbacks_cleanup(); MSP.callbacks_cleanup();
$('#content').load("./tabs/cli.html", function() { $('#content').load("./tabs/cli.html", function() {
CLI_active = true; CLI_active = true;
// Enter CLI mode // Enter CLI mode
var bufferOut = new ArrayBuffer(1); var bufferOut = new ArrayBuffer(1);
var bufView = new Uint8Array(bufferOut); var bufView = new Uint8Array(bufferOut);
bufView[0] = 0x23; // # bufView[0] = 0x23; // #
serial.send(bufferOut, function(writeInfo) {}); serial.send(bufferOut, function(writeInfo) {});
@ -46,11 +46,11 @@ function tab_initialize_cli() {
var out_arr = out_string.split("\n"); var out_arr = out_string.split("\n");
cli_history.add(out_string.trim()); cli_history.add(out_string.trim());
var timeout_needle = 0; var timeout_needle = 0;
for (var i = 0; i < out_arr.length; i++) { for (var i = 0; i < out_arr.length; i++) {
send_slowly(out_arr, i, timeout_needle++); send_slowly(out_arr, i, timeout_needle++);
} }
$('.tab-cli textarea').val(''); $('.tab-cli textarea').val('');
} }
}); });
@ -64,19 +64,19 @@ function tab_initialize_cli() {
if (event.keyCode in keyDown) if (event.keyCode in keyDown)
textarea.val(cli_history.next()); textarea.val(cli_history.next());
}); });
// apply dynamic width to the textarea element according to cli window width (minus padding and border width) // apply dynamic width to the textarea element according to cli window width (minus padding and border width)
$('div.tab-cli textarea').width($('div.tab-cli .window').outerWidth() - 7); $('div.tab-cli textarea').width($('div.tab-cli .window').outerWidth() - 7);
// give input element user focus // give input element user focus
$('.tab-cli textarea').focus(); $('.tab-cli textarea').focus();
$('.tab-cli .copy').click(function() { $('.tab-cli .copy').click(function() {
var text = $('.tab-cli .window .wrapper').html(); var text = $('.tab-cli .window .wrapper').html();
text = text.replace(/<br\s*\/?>/mg,"\n"); // replacing br tags with \n to keep some of the formating text = text.replace(/<br\s*\/?>/mg,"\n"); // replacing br tags with \n to keep some of the formating
var copyFrom = $('<textarea/>'); var copyFrom = $('<textarea/>');
copyFrom.text(text); copyFrom.text(text);
$('body').append(copyFrom); $('body').append(copyFrom);
copyFrom.select(); copyFrom.select();
@ -88,7 +88,7 @@ function tab_initialize_cli() {
function send_slowly(out_arr, i, timeout_needle) { function send_slowly(out_arr, i, timeout_needle) {
GUI.timeout_add('CLI_send_slowly', function() { GUI.timeout_add('CLI_send_slowly', function() {
var bufferOut = new ArrayBuffer(out_arr[i].length + 1); var bufferOut = new ArrayBuffer(out_arr[i].length + 1);
var bufView = new Uint8Array(bufferOut); var bufView = new Uint8Array(bufferOut);
for (var c_key = 0; c_key < out_arr[i].length; c_key++) { for (var c_key = 0; c_key < out_arr[i].length; c_key++) {
@ -105,7 +105,7 @@ function send_slowly(out_arr, i, timeout_needle) {
line feed = LF = \n = 0x0A = 10 line feed = LF = \n = 0x0A = 10
carriage return = CR = \r = 0x0D = 13 carriage return = CR = \r = 0x0D = 13
MAC only understands CR MAC only understands CR
Linux and Unix only understand LF Linux and Unix only understand LF
Windows understands (both) CRLF Windows understands (both) CRLF
@ -117,23 +117,23 @@ var CLI_validate_text = "";
function handle_CLI(readInfo) { function handle_CLI(readInfo) {
var data = new Uint8Array(readInfo.data); var data = new Uint8Array(readInfo.data);
var text = ""; var text = "";
for (var i = 0; i < data.length; i++) { for (var i = 0; i < data.length; i++) {
if (CLI_valid) { if (CLI_valid) {
if (data[i] == 27 || sequence_elements > 0) { // ESC + other if (data[i] == 27 || sequence_elements > 0) { // ESC + other
sequence_elements++; sequence_elements++;
// delete previous space // delete previous space
if (sequence_elements == 1) { if (sequence_elements == 1) {
text = text.substring(0, text.length -1); text = text.substring(0, text.length -1);
} }
// Reset // Reset
if (sequence_elements >= 5) { if (sequence_elements >= 5) {
sequence_elements = 0; sequence_elements = 0;
} }
} }
if (sequence_elements == 0) { if (sequence_elements == 0) {
switch (data[i]) { switch (data[i]) {
case 10: // line feed case 10: // line feed
@ -154,20 +154,20 @@ function handle_CLI(readInfo) {
// try to catch part of valid CLI enter message // try to catch part of valid CLI enter message
CLI_validate_text += String.fromCharCode(data[i]); CLI_validate_text += String.fromCharCode(data[i]);
} }
char_counter++; char_counter++;
} }
if (!CLI_valid && CLI_validate_text.indexOf('CLI') != -1) { if (!CLI_valid && CLI_validate_text.indexOf('CLI') != -1) {
CLI_valid = true; CLI_valid = true;
CLI_validate_text = ""; CLI_validate_text = "";
text = "Entering CLI Mode, type 'exit' to return, or 'help'<br /><br /># "; text = "Entering CLI Mode, type 'exit' to return, or 'help'<br /><br /># ";
} }
$('.tab-cli .window .wrapper').append(text); $('.tab-cli .window .wrapper').append(text);
$('.tab-cli .window').scrollTop($('.tab-cli .window .wrapper').height()); $('.tab-cli .window').scrollTop($('.tab-cli .window .wrapper').height());
// there seems to be some sort of initial rendering glitch in 33+, we will force redraw/refill // there seems to be some sort of initial rendering glitch in 33+, we will force redraw/refill
$('.tab-cli .window .wrapper').css('webkitTransform', 'scale(1)'); $('.tab-cli .window .wrapper').css('webkitTransform', 'scale(1)');
} }

View file

@ -1,11 +1,11 @@
.welcome { .welcome {
float: left; float: left;
width: 494px; width: 494px;
height: 171px; height: 171px;
padding: 5px; padding: 5px;
border: 1px solid silver; border: 1px solid silver;
} }
.welcome a { .welcome a {
@ -14,27 +14,27 @@
.changelog { .changelog {
margin-left: 514px; margin-left: 514px;
margin-bottom: 10px; margin-bottom: 10px;
border: 1px solid silver; border: 1px solid silver;
} }
.changelog .title { .changelog .title {
line-height: 20px; line-height: 20px;
text-align: center; text-align: center;
font-weight: bold; font-weight: bold;
color: white; color: white;
border-bottom: 1px solid silver; border-bottom: 1px solid silver;
background-color: #3f4241; background-color: #3f4241;
} }
.changelog .wrapper { .changelog .wrapper {
height: 150px; height: 150px;
padding: 5px; padding: 5px;
overflow-y: scroll; overflow-y: scroll;
overflow-x: hidden; overflow-x: hidden;
-webkit-user-select: text; -webkit-user-select: text;
} }
.changelog .wrapper span { .changelog .wrapper span {
@ -45,20 +45,20 @@
} }
.donate { .donate {
float: left; float: left;
width: 504px; width: 504px;
padding: 0 0 5px 0; padding: 0 0 5px 0;
border: 1px solid silver; border: 1px solid silver;
} }
.donate .title { .donate .title {
line-height: 20px; line-height: 20px;
text-align: center; text-align: center;
font-weight: bold; font-weight: bold;
color: white; color: white;
border-bottom: 1px solid silver; border-bottom: 1px solid silver;
background-color: #3f4241; background-color: #3f4241;
} }
@ -67,24 +67,24 @@
} }
.donate a { .donate a {
display: block; display: block;
width: 74px; width: 74px;
height: 21px; height: 21px;
margin: auto; margin: auto;
} }
.firmware_flasher { .firmware_flasher {
display: block; display: block;
float: right; float: right;
height: 28px; height: 28px;
line-height: 28px; line-height: 28px;
padding: 0 15px 0 15px; padding: 0 15px 0 15px;
text-align: center; text-align: center;
font-weight: bold; font-weight: bold;
border: 1px solid silver; border: 1px solid silver;
background-color: #ececec; background-color: #ececec;
} }

View file

@ -21,7 +21,7 @@
This utility is fully <strong>open source</strong> and is available free of charge to all <strong>baseflight</strong> users.<br /> This utility is fully <strong>open source</strong> and is available free of charge to all <strong>baseflight</strong> users.<br />
If you found the utility useful, please consider <strong>supporting</strong> its development by donating.<br /> If you found the utility useful, please consider <strong>supporting</strong> its development by donating.<br />
</p> </p>
<a href="http://goo.gl/xQMKN" target="_blank" title="Donate"><img src="./images/btn_donate_SM.gif" alt="Paypal" /></a> <a href="http://goo.gl/xQMKN" target="_blank" title="Donate"><img src="./images/btn_donate_SM.gif" alt="Paypal" /></a>
</div> </div>
<a class="firmware_flasher" href="#">Firmware Flasher</a> <a class="firmware_flasher" href="#">Firmware Flasher</a>
</div> </div>

View file

@ -1,10 +1,10 @@
function tab_initialize_default() { function tab_initialize_default() {
GUI.active_tab = 'default'; GUI.active_tab = 'default';
$('#content').load("./tabs/default.html", function() { $('#content').load("./tabs/default.html", function() {
// load changelog content // load changelog content
$('div.changelog.configurator .wrapper').load('./changelog.html'); $('div.changelog.configurator .wrapper').load('./changelog.html');
// UI Hooks // UI Hooks
$('a.firmware_flasher').click(function() { $('a.firmware_flasher').click(function() {
tab_initialize_firmware_flasher(); tab_initialize_firmware_flasher();

View file

@ -6,7 +6,7 @@
} }
.tab-firmware_flasher .info .progress { .tab-firmware_flasher .info .progress {
width: 140px; width: 140px;
border: 1px solid silver; border: 1px solid silver;
} }
.tab-firmware_flasher .info .progress::-webkit-progress-value { .tab-firmware_flasher .info .progress::-webkit-progress-value {
@ -20,10 +20,10 @@
} }
.tab-firmware_flasher .note { .tab-firmware_flasher .note {
float: left; float: left;
margin-bottom: 10px; margin-bottom: 10px;
padding: 5px; padding: 5px;
border: 1px dotted silver; border: 1px dotted silver;
} }
.tab-firmware_flasher .note p { .tab-firmware_flasher .note p {
@ -42,15 +42,15 @@
a.load_file, a.load_remote_file { a.load_file, a.load_remote_file {
display: block; display: block;
float: left; float: left;
margin: 0 10px 0 0; margin: 0 10px 0 0;
padding: 0 10px 0 10px; padding: 0 10px 0 10px;
height: 20px; height: 20px;
line-height: 20px; line-height: 20px;
text-align: center; text-align: center;
font-weight: bold; font-weight: bold;
border: 1px solid silver; border: 1px solid silver;
background-color: #ececec; background-color: #ececec;
} }
@ -60,14 +60,14 @@ a.load_file:hover, a.load_remote_file:hover {
a.flash_firmware { a.flash_firmware {
display: block; display: block;
float: left; float: left;
padding: 0 10px 0 10px; padding: 0 10px 0 10px;
height: 20px; height: 20px;
line-height: 20px; line-height: 20px;
text-align: center; text-align: center;
font-weight: bold; font-weight: bold;
border: 1px solid silver; border: 1px solid silver;
background-color: #ececec; background-color: #ececec;
} }
@ -84,35 +84,35 @@ a.flash_firmware:hover {
a.back { a.back {
display: block; display: block;
position: absolute; position: absolute;
bottom: 10px; bottom: 10px;
height: 28px; height: 28px;
line-height: 28px; line-height: 28px;
padding: 0 15px 0 15px; padding: 0 15px 0 15px;
text-align: center; text-align: center;
font-weight: bold; font-weight: bold;
border: 1px solid silver; border: 1px solid silver;
background-color: #ececec; background-color: #ececec;
} }
a.back:hover { a.back:hover {
background-color: #dedcdc; background-color: #dedcdc;
} }
.warning { .warning {
width: 620px; width: 620px;
border: 1px solid silver; border: 1px solid silver;
} }
.warning .title { .warning .title {
line-height: 20px; line-height: 20px;
text-align: center; text-align: center;
font-weight: bold; font-weight: bold;
color: white; color: white;
border-bottom: 1px solid silver; border-bottom: 1px solid silver;
background-color: #cd4c4c; background-color: #cd4c4c;
} }
@ -121,20 +121,20 @@ a.back:hover {
} }
.tab-firmware_flasher .git_info { .tab-firmware_flasher .git_info {
display: none; display: none;
width: 620px; width: 620px;
margin-bottom: 10px; margin-bottom: 10px;
border: 1px solid silver; border: 1px solid silver;
} }
.tab-firmware_flasher .git_info .title { .tab-firmware_flasher .git_info .title {
line-height: 20px; line-height: 20px;
text-align: center; text-align: center;
font-weight: bold; font-weight: bold;
color: white; color: white;
border-bottom: 1px solid silver; border-bottom: 1px solid silver;
background-color: #3f4241; background-color: #3f4241;
} }

View file

@ -4,7 +4,7 @@
<strong>Size:</strong><span class="size">0 bytes</span><br /> <strong>Size:</strong><span class="size">0 bytes</span><br />
<strong>Status:</strong><span class="status">Firmware not loaded</span><br /> <strong>Status:</strong><span class="status">Firmware not loaded</span><br />
<strong>Progress:</strong><progress class="progress" value="0" min="0" max="100"></progress> <strong>Progress:</strong><progress class="progress" value="0" min="0" max="100"></progress>
</div> </div>
<div class="note"> <div class="note">
<p> <p>
If you are flashing board with <strong>baseflight</strong> already flashed (updating), leave this checkbox unchecked.<br /> If you are flashing board with <strong>baseflight</strong> already flashed (updating), leave this checkbox unchecked.<br />
@ -27,7 +27,7 @@
<strong>Date:</strong> <span class="date"></span><br /> <strong>Date:</strong> <span class="date"></span><br />
<strong>Message:</strong> <span class="message"></span> <strong>Message:</strong> <span class="message"></span>
</p> </p>
</div> </div>
<div class="warning"> <div class="warning">
<div class="title">Warning</div> <div class="title">Warning</div>
<p> <p>

View file

@ -1,10 +1,10 @@
function tab_initialize_firmware_flasher() { function tab_initialize_firmware_flasher() {
ga_tracker.sendAppView('Firmware Flasher'); ga_tracker.sendAppView('Firmware Flasher');
GUI.active_tab = 'firmware_flasher'; GUI.active_tab = 'firmware_flasher';
var intel_hex = false; // standard intel hex in string format var intel_hex = false; // standard intel hex in string format
var parsed_hex = false; // parsed raw hex in array format var parsed_hex = false; // parsed raw hex in array format
$('#content').load("./tabs/firmware_flasher.html", function() { $('#content').load("./tabs/firmware_flasher.html", function() {
// UI Hooks // UI Hooks
$('a.load_file').click(function() { $('a.load_file').click(function() {
@ -14,14 +14,14 @@ function tab_initialize_firmware_flasher() {
console.log('No valid file selected, aborting'); console.log('No valid file selected, aborting');
return; return;
} }
// hide github info (if it exists) // hide github info (if it exists)
$('div.git_info').slideUp(); $('div.git_info').slideUp();
chrome.fileSystem.getDisplayPath(fileEntry, function(path) { chrome.fileSystem.getDisplayPath(fileEntry, function(path) {
console.log('Loading file from: ' + path); console.log('Loading file from: ' + path);
$('span.path').html(path); $('span.path').html(path);
fileEntry.file(function(file) { fileEntry.file(function(file) {
var reader = new FileReader(); var reader = new FileReader();
@ -32,20 +32,20 @@ function tab_initialize_firmware_flasher() {
reader.abort(); reader.abort();
} }
}; };
reader.onloadend = function(e) { reader.onloadend = function(e) {
if (e.total != 0 && e.total == e.loaded) { if (e.total != 0 && e.total == e.loaded) {
console.log('File loaded'); console.log('File loaded');
intel_hex = e.target.result; intel_hex = e.target.result;
parse_hex(intel_hex, function(data) { parse_hex(intel_hex, function(data) {
parsed_hex = data; parsed_hex = data;
if (parsed_hex) { if (parsed_hex) {
STM32.GUI_status('<span style="color: green">Firmware loaded, ready for flashing</span>'); STM32.GUI_status('<span style="color: green">Firmware loaded, ready for flashing</span>');
$('a.flash_firmware').removeClass('locked'); $('a.flash_firmware').removeClass('locked');
$('span.size').html(parsed_hex.bytes_total + ' bytes'); $('span.size').html(parsed_hex.bytes_total + ' bytes');
} else { } else {
STM32.GUI_status('<span style="color: red">HEX file appears to be corrupted</span>'); STM32.GUI_status('<span style="color: red">HEX file appears to be corrupted</span>');
@ -59,18 +59,18 @@ function tab_initialize_firmware_flasher() {
}); });
}); });
}); });
$('a.load_remote_file').click(function() { $('a.load_remote_file').click(function() {
$.get('https://raw.github.com/multiwii/baseflight/master/obj/baseflight.hex', function(data) { $.get('https://raw.github.com/multiwii/baseflight/master/obj/baseflight.hex', function(data) {
intel_hex = data; intel_hex = data;
parse_hex(intel_hex, function(data) { parse_hex(intel_hex, function(data) {
parsed_hex = data; parsed_hex = data;
if (parsed_hex) { if (parsed_hex) {
STM32.GUI_status('<span style="color: green">Remote Firmware loaded, ready for flashing</span>'); STM32.GUI_status('<span style="color: green">Remote Firmware loaded, ready for flashing</span>');
$('a.flash_firmware').removeClass('locked'); $('a.flash_firmware').removeClass('locked');
$('span.path').html('Using remote Firmware'); $('span.path').html('Using remote Firmware');
$('span.size').html(parsed_hex.bytes_total + ' bytes'); $('span.size').html(parsed_hex.bytes_total + ' bytes');
} else { } else {
@ -81,25 +81,25 @@ function tab_initialize_firmware_flasher() {
STM32.GUI_status('<span style="color: red">Failed to load remote firmware</span>'); STM32.GUI_status('<span style="color: red">Failed to load remote firmware</span>');
$('a.flash_firmware').addClass('locked'); $('a.flash_firmware').addClass('locked');
}); });
$.get('https://api.github.com/repos/multiwii/baseflight/commits?page=1&per_page=1&path=obj/baseflight.hex', function(data) { $.get('https://api.github.com/repos/multiwii/baseflight/commits?page=1&per_page=1&path=obj/baseflight.hex', function(data) {
var data = data[0]; var data = data[0];
var d = new Date(data.commit.author.date); var d = new Date(data.commit.author.date);
var date = ('0' + (d.getMonth() + 1)).slice(-2) + '.' + ('0' + (d.getDate() + 1)).slice(-2) + '.' + d.getFullYear(); var date = ('0' + (d.getMonth() + 1)).slice(-2) + '.' + ('0' + (d.getDate() + 1)).slice(-2) + '.' + d.getFullYear();
date += ' @ ' + ('0' + d.getHours()).slice(-2) + ':' + ('0' + d.getMinutes()).slice(-2); date += ' @ ' + ('0' + d.getHours()).slice(-2) + ':' + ('0' + d.getMinutes()).slice(-2);
$('div.git_info .committer').html(data.commit.author.name); $('div.git_info .committer').html(data.commit.author.name);
$('div.git_info .date').html(date); $('div.git_info .date').html(date);
$('div.git_info .message').html(data.commit.message); $('div.git_info .message').html(data.commit.message);
$('div.git_info').slideDown(); $('div.git_info').slideDown();
}); });
}); });
$('a.flash_firmware').click(function() { $('a.flash_firmware').click(function() {
if (!$(this).hasClass('locked')) { if (!$(this).hasClass('locked')) {
if (!GUI.connect_lock) { // button disabled while flashing is in progress if (!GUI.connect_lock) { // button disabled while flashing is in progress
if (parsed_hex != false) { if (parsed_hex != false) {
STM32.connect(parsed_hex); STM32.connect(parsed_hex);
} else { } else {
STM32.GUI_status('<span style="color: red">Firmware not loaded</span>'); STM32.GUI_status('<span style="color: red">Firmware not loaded</span>');
@ -107,12 +107,12 @@ function tab_initialize_firmware_flasher() {
} }
} }
}); });
chrome.storage.local.get('no_reboot_sequence', function(result) { chrome.storage.local.get('no_reboot_sequence', function(result) {
if (typeof result.no_reboot_sequence === 'undefined') { if (typeof result.no_reboot_sequence === 'undefined') {
// wasn't saved yet, save and push false to the GUI // wasn't saved yet, save and push false to the GUI
chrome.storage.local.set({'no_reboot_sequence': false}); chrome.storage.local.set({'no_reboot_sequence': false});
$('input.updating').prop('checked', false); $('input.updating').prop('checked', false);
} else { } else {
if (result.no_reboot_sequence) { if (result.no_reboot_sequence) {
@ -122,27 +122,27 @@ function tab_initialize_firmware_flasher() {
$('input.updating').prop('checked', false); $('input.updating').prop('checked', false);
} }
} }
// bind UI hook so the status is saved on change // bind UI hook so the status is saved on change
$('input.updating').change(function() { $('input.updating').change(function() {
var status = $(this).is(':checked'); var status = $(this).is(':checked');
if (status) { if (status) {
$('label.flash_on_connect_wrapper').show(); $('label.flash_on_connect_wrapper').show();
} else { } else {
$('label.flash_on_connect_wrapper').hide(); $('label.flash_on_connect_wrapper').hide();
$('input.flash_on_connect').prop('checked', false).change(); $('input.flash_on_connect').prop('checked', false).change();
} }
chrome.storage.local.set({'no_reboot_sequence': status}, function() {}); chrome.storage.local.set({'no_reboot_sequence': status}, function() {});
}); });
}); });
chrome.storage.local.get('flash_on_connect', function(result) { chrome.storage.local.get('flash_on_connect', function(result) {
if (typeof result.flash_on_connect === 'undefined') { if (typeof result.flash_on_connect === 'undefined') {
// wasn't saved yet, save and push false to the GUI // wasn't saved yet, save and push false to the GUI
chrome.storage.local.set({'flash_on_connect': false}); chrome.storage.local.set({'flash_on_connect': false});
$('input.flash_on_connect').prop('checked', false); $('input.flash_on_connect').prop('checked', false);
} else { } else {
if (result.flash_on_connect) { if (result.flash_on_connect) {
@ -151,27 +151,27 @@ function tab_initialize_firmware_flasher() {
$('input.flash_on_connect').prop('checked', false); $('input.flash_on_connect').prop('checked', false);
} }
} }
$('input.flash_on_connect').change(function() { $('input.flash_on_connect').change(function() {
var status = $(this).is(':checked'); var status = $(this).is(':checked');
if (status) { if (status) {
var flashing_port; var flashing_port;
var start = function() { var start = function() {
PortHandler.port_detected('flash_next_device', function(result) { PortHandler.port_detected('flash_next_device', function(result) {
flashing_port = result[0]; flashing_port = result[0];
GUI.log('Detected: <strong>' + flashing_port + '</strong> - triggering flash on connect'); GUI.log('Detected: <strong>' + flashing_port + '</strong> - triggering flash on connect');
console.log('Detected: ' + flashing_port + ' - triggering flash on connect'); console.log('Detected: ' + flashing_port + ' - triggering flash on connect');
// Trigger regular Flashing sequence // Trigger regular Flashing sequence
$('a.flash_firmware').click(); $('a.flash_firmware').click();
// Detect port removal to create a new callback // Detect port removal to create a new callback
end(); end();
}, false, true); }, false, true);
}; };
var end = function() { var end = function() {
PortHandler.port_removed('flashed_device_removed', function(result) { PortHandler.port_removed('flashed_device_removed', function(result) {
for (var i = 0; i < result.length; i++) { for (var i = 0; i < result.length; i++) {
@ -179,28 +179,28 @@ function tab_initialize_firmware_flasher() {
// flashed device removed // flashed device removed
GUI.log('Removed: <strong>' + flashing_port + '</strong> - ready for next device'); GUI.log('Removed: <strong>' + flashing_port + '</strong> - ready for next device');
console.log('Removed: ' + flashing_port + ' - ready for next device'); console.log('Removed: ' + flashing_port + ' - ready for next device');
flashing_port = false; flashing_port = false;
start(); start();
return; return;
} }
} }
// different device removed, we need to retry // different device removed, we need to retry
end(); end();
}, false, true); }, false, true);
}; };
start(); start();
} else { } else {
PortHandler.flush_callbacks(); PortHandler.flush_callbacks();
} }
chrome.storage.local.set({'flash_on_connect': status}, function() {}); chrome.storage.local.set({'flash_on_connect': status}, function() {});
}).change(); }).change();
}); });
$('a.back').click(function() { $('a.back').click(function() {
if (!GUI.connect_lock) { // button disabled while flashing is in progress if (!GUI.connect_lock) { // button disabled while flashing is in progress
GUI.tab_switch_cleanup(function() { GUI.tab_switch_cleanup(function() {
@ -216,12 +216,12 @@ function tab_initialize_firmware_flasher() {
function parse_hex(str, callback) { function parse_hex(str, callback) {
// parsing hex in different thread // parsing hex in different thread
var worker = new Worker('./js/workers/hex_parser.js'); var worker = new Worker('./js/workers/hex_parser.js');
// "callback" // "callback"
worker.onmessage = function (event) { worker.onmessage = function (event) {
callback(event.data); callback(event.data);
}; };
// send data/string over for processing // send data/string over for processing
worker.postMessage(str); worker.postMessage(str);
} }

View file

@ -3,10 +3,10 @@
.tab-gps .GPS_info { .tab-gps .GPS_info {
float: left; float: left;
display: block; display: block;
width: 170px; width: 170px;
border: 1px solid silver; border: 1px solid silver;
} }
.tab-gps .GPS_info table { .tab-gps .GPS_info table {
@ -15,11 +15,11 @@
} }
.tab-gps .GPS_signal_strength { .tab-gps .GPS_signal_strength {
float: left; float: left;
margin-left: 10px; margin-left: 10px;
width: 200px; width: 200px;
border: 1px solid silver; border: 1px solid silver;
} }
.tab-gps .GPS_signal_strength table { .tab-gps .GPS_signal_strength table {
@ -29,11 +29,11 @@
.tab-gps .GPS_info .head, .tab-gps .GPS_info .head,
.tab-gps .GPS_signal_strength .head { .tab-gps .GPS_signal_strength .head {
display: block; display: block;
text-align: center; text-align: center;
line-height: 20px; line-height: 20px;
font-weight: bold; font-weight: bold;
border-bottom: 1px solid silver; border-bottom: 1px solid silver;
background-color: #ececec; background-color: #ececec;
} }

View file

@ -25,7 +25,7 @@
<tr> <tr>
<td>Dist to Home:</td> <td>Dist to Home:</td>
<td class="distToHome">0</td> <td class="distToHome">0</td>
</tr> </tr>
</table> </table>
</div> </div>
<div class="GPS_signal_strength"> <div class="GPS_signal_strength">
@ -110,12 +110,12 @@
<td>0</td> <td>0</td>
<td>0</td> <td>0</td>
<td><progress value="0" max="16"></progress></td> <td><progress value="0" max="16"></progress></td>
</tr> </tr>
<tr> <tr>
<td>0</td> <td>0</td>
<td>0</td> <td>0</td>
<td><progress value="0" max="16"></progress></td> <td><progress value="0" max="16"></progress></td>
</tr> </tr>
</table> </table>
</div> </div>
</div> </div>

View file

@ -1,7 +1,7 @@
function tab_initialize_gps () { function tab_initialize_gps () {
ga_tracker.sendAppView('GPS Page'); ga_tracker.sendAppView('GPS Page');
GUI.active_tab = 'gps'; GUI.active_tab = 'gps';
send_message(MSP_codes.MSP_RAW_GPS, MSP_codes.MSP_RAW_GPS, false, function() { send_message(MSP_codes.MSP_RAW_GPS, MSP_codes.MSP_RAW_GPS, false, function() {
$('#content').load("./tabs/gps.html", function() { $('#content').load("./tabs/gps.html", function() {
// enable data pulling // enable data pulling
@ -13,10 +13,10 @@ function tab_initialize_gps () {
$('.GPS_info td.speed').html(GPS_DATA.speed + ' cm/s'); $('.GPS_info td.speed').html(GPS_DATA.speed + ' cm/s');
$('.GPS_info td.sats').html(GPS_DATA.numSat); $('.GPS_info td.sats').html(GPS_DATA.numSat);
$('.GPS_info td.distToHome').html(GPS_DATA.distanceToHome + ' m'); $('.GPS_info td.distToHome').html(GPS_DATA.distanceToHome + ' m');
// Update GPS Signal Strengths // Update GPS Signal Strengths
var e_ss_table = $('div.GPS_signal_strength table tr:not(.titles)'); var e_ss_table = $('div.GPS_signal_strength table tr:not(.titles)');
for (var i = 0; i < GPS_DATA.chn.length; i++) { for (var i = 0; i < GPS_DATA.chn.length; i++) {
var row = e_ss_table.eq(i); var row = e_ss_table.eq(i);
@ -24,7 +24,7 @@ function tab_initialize_gps () {
$('td', row).eq(1).html(GPS_DATA.quality[i]); $('td', row).eq(1).html(GPS_DATA.quality[i]);
$('td', row).eq(2).find('progress').val(GPS_DATA.cno[i]); $('td', row).eq(2).find('progress').val(GPS_DATA.cno[i]);
} }
send_message(MSP_codes.MSP_STATUS, MSP_codes.MSP_STATUS); send_message(MSP_codes.MSP_STATUS, MSP_codes.MSP_STATUS);
send_message(MSP_codes.MSP_RAW_GPS, MSP_codes.MSP_RAW_GPS); send_message(MSP_codes.MSP_RAW_GPS, MSP_codes.MSP_RAW_GPS);
send_message(MSP_codes.MSP_GPSSVINFO, MSP_codes.MSP_GPSSVINFO); send_message(MSP_codes.MSP_GPSSVINFO, MSP_codes.MSP_GPSSVINFO);

View file

@ -6,16 +6,16 @@
} }
.tab-initial_setup .section a { .tab-initial_setup .section a {
display: block; display: block;
float: left; float: left;
width: 170px; width: 170px;
height: 24px; height: 24px;
line-height: 24px; line-height: 24px;
text-align: center; text-align: center;
font-weight: bold; font-weight: bold;
border: 1px solid silver; border: 1px solid silver;
background-color: #ececec; background-color: #ececec;
} }
@ -38,61 +38,61 @@
} }
.tab-initial_setup .section p { .tab-initial_setup .section p {
margin-left: 180px; margin-left: 180px;
padding: 5px; padding: 5px;
border: 1px dotted silver; border: 1px dotted silver;
} }
#interactive_block { #interactive_block {
float: left; float: left;
height: 280px; height: 280px;
width: 400px; width: 400px;
border: 1px solid silver; border: 1px solid silver;
background-color: white; background-color: white;
} }
#interactive_block .model { #interactive_block .model {
display: block; display: block;
margin: 10px 0 0 10px; margin: 10px 0 0 10px;
font-weight: bold; font-weight: bold;
} }
#interactive_block a.reset { #interactive_block a.reset {
position: absolute; position: absolute;
display: block; display: block;
margin-left: 10px; margin-left: 10px;
margin-top: 215px; margin-top: 215px;
height: 28px; height: 28px;
line-height: 28px; line-height: 28px;
padding: 0 15px 0 15px; padding: 0 15px 0 15px;
text-align: center; text-align: center;
font-weight: bold; font-weight: bold;
border: 1px solid silver; border: 1px solid silver;
background-color: #ececec; background-color: #ececec;
z-index: 100; z-index: 100;
} }
#interactive_block a.reset:hover { #interactive_block a.reset:hover {
background-color: #dedcdc; background-color: #dedcdc;
} }
#perspective { #perspective {
-webkit-perspective: 800; -webkit-perspective: 800;
-webkit-perspective-origin: 50% 150px; /* 150px = (350px / 2) - 25px */ -webkit-perspective-origin: 50% 150px; /* 150px = (350px / 2) - 25px */
} }
#cube { #cube {
position: relative; position: relative;
top: 110px; top: 110px;
left: 150px; /* (916px / 2) - 50px */ left: 150px; /* (916px / 2) - 50px */
height: 100px; height: 100px;
width: 100px; width: 100px;
-webkit-transform-style: preserve-3d; -webkit-transform-style: preserve-3d;
} }
#cubePITCH { #cubePITCH {
@ -103,7 +103,7 @@
} }
#cube .face { #cube .face {
position: absolute; position: absolute;
color: white; color: white;
font-size: 25px; font-size: 25px;
text-align: center; text-align: center;
@ -114,7 +114,7 @@
line-height: 200px; line-height: 200px;
font-size: 20px; font-size: 20px;
-webkit-transform: rotateX(-90deg) translateZ(-50px); -webkit-transform: rotateX(-90deg) translateZ(-50px);
background-color: purple; background-color: purple;
} }
@ -122,7 +122,7 @@
width: 100px; width: 100px;
height: 50px; height: 50px;
line-height: 50px; line-height: 50px;
-webkit-transform: translateZ(100px); -webkit-transform: translateZ(100px);
background-color: blue; background-color: blue;
} }
@ -130,7 +130,7 @@
width: 200px; width: 200px;
height: 50px; height: 50px;
line-height: 50px; line-height: 50px;
-webkit-transform: rotateY(90deg); -webkit-transform: rotateY(90deg);
background-color: green; background-color: green;
} }
@ -138,7 +138,7 @@
width: 100px; width: 100px;
height: 50px; height: 50px;
line-height: 50px; line-height: 50px;
-webkit-transform: rotateY(180deg) translateZ(100px); -webkit-transform: rotateY(180deg) translateZ(100px);
background-color: black; background-color: black;
} }
@ -146,7 +146,7 @@
width: 200px; width: 200px;
height: 50px; height: 50px;
line-height: 50px; line-height: 50px;
-webkit-transform: rotateY(-90deg) translateZ(100px); -webkit-transform: rotateY(-90deg) translateZ(100px);
background-color: red; background-color: red;
} }
@ -154,19 +154,19 @@
width: 100px; width: 100px;
height: 200px; height: 200px;
line-height: 200px; line-height: 200px;
-webkit-transform: rotateX(90deg) translateZ(100px); -webkit-transform: rotateX(90deg) translateZ(100px);
background-color: silver; background-color: silver;
} }
.tab-initial_setup .battery, .tab-initial_setup .battery,
.tab-initial_setup .throttle, .tab-initial_setup .throttle,
.tab-initial_setup .acc-trim, .tab-initial_setup .acc-trim,
.tab-initial_setup .magnetometer { .tab-initial_setup .magnetometer {
float: left; float: left;
display: block; display: block;
margin-left: 10px; margin-left: 10px;
border: 1px solid silver; border: 1px solid silver;
} }
.tab-initial_setup .magnetometer { .tab-initial_setup .magnetometer {
@ -177,11 +177,11 @@
.tab-initial_setup .acc-trim .head, .tab-initial_setup .acc-trim .head,
.tab-initial_setup .magnetometer .head { .tab-initial_setup .magnetometer .head {
display: block; display: block;
text-align: center; text-align: center;
line-height: 20px; line-height: 20px;
font-weight: bold; font-weight: bold;
border-bottom: 1px solid silver; border-bottom: 1px solid silver;
background-color: #ececec; background-color: #ececec;
} }
@ -203,24 +203,24 @@
float: left; float: left;
width: 100px; width: 100px;
height: 22px; height: 22px;
margin-bottom: 2px; margin-bottom: 2px;
line-height: 22px; line-height: 22px;
} }
.tab-initial_setup .battery dd { .tab-initial_setup .battery dd {
height: 22px; height: 22px;
margin-left: 100px; margin-left: 100px;
margin-bottom: 2px; margin-bottom: 2px;
line-height: 22px; line-height: 22px;
} }
.tab-initial_setup .battery input { .tab-initial_setup .battery input {
width: 70px; width: 70px;
height: 20px; height: 20px;
line-height: 20px; line-height: 20px;
border: 1px solid silver; border: 1px solid silver;
text-align: center; text-align: center;
} }
@ -228,24 +228,24 @@
float: left; float: left;
width: 85px; width: 85px;
height: 22px; height: 22px;
margin-bottom: 2px; margin-bottom: 2px;
line-height: 22px; line-height: 22px;
} }
.tab-initial_setup .throttle dd { .tab-initial_setup .throttle dd {
height: 22px; height: 22px;
margin-left: 85px; margin-left: 85px;
margin-bottom: 2px; margin-bottom: 2px;
line-height: 22px; line-height: 22px;
} }
.tab-initial_setup .throttle input { .tab-initial_setup .throttle input {
width: 70px; width: 70px;
height: 20px; height: 20px;
line-height: 20px; line-height: 20px;
border: 1px solid silver; border: 1px solid silver;
text-align: center; text-align: center;
} }
@ -254,12 +254,12 @@
width: 40px; width: 40px;
height: 22px; height: 22px;
line-height: 22px; line-height: 22px;
margin-bottom: 2px; margin-bottom: 2px;
} }
.tab-initial_setup .acc-trim dd { .tab-initial_setup .acc-trim dd {
height: 22px; height: 22px;
margin-left: 40px; margin-left: 40px;
margin-bottom: 2px; margin-bottom: 2px;
} }
@ -267,7 +267,7 @@
width: 70px; width: 70px;
height: 20px; height: 20px;
line-height: 20px; line-height: 20px;
border: 1px solid silver; border: 1px solid silver;
text-align: center; text-align: center;
} }
@ -276,13 +276,13 @@
width: 100px; width: 100px;
height: 20px; height: 20px;
line-height: 22px; line-height: 22px;
margin-bottom: 2px; margin-bottom: 2px;
} }
.tab-initial_setup .magnetometer dd { .tab-initial_setup .magnetometer dd {
height: 20px; height: 20px;
line-height: 22px; line-height: 22px;
margin-left: 100px; margin-left: 100px;
margin-bottom: 2px; margin-bottom: 2px;
} }
@ -290,23 +290,23 @@
width: 70px; width: 70px;
height: 20px; height: 20px;
line-height: 20px; line-height: 20px;
border: 1px solid silver; border: 1px solid silver;
text-align: center; text-align: center;
} }
.tab-initial_setup .update { .tab-initial_setup .update {
display: block; display: block;
float: left; float: left;
margin: 10px 0 0 10px; margin: 10px 0 0 10px;
width: 80px; width: 80px;
height: 20px; height: 20px;
line-height: 20px; line-height: 20px;
text-align: center; text-align: center;
font-weight: bold; font-weight: bold;
border: 1px solid silver; border: 1px solid silver;
background-color: #ececec; background-color: #ececec;
} }
@ -319,19 +319,19 @@
.tab-initial_setup .compass-wrapper { .tab-initial_setup .compass-wrapper {
display: none; display: none;
position: absolute; position: absolute;
bottom: 10px; bottom: 10px;
right: 10px; right: 10px;
border: 1px solid silver; border: 1px solid silver;
border-radius: 50%; border-radius: 50%;
} }
.tab-initial_setup #compass { .tab-initial_setup #compass {
position: relative; position: relative;
width: 150px; width: 150px;
height: 150px; height: 150px;
border: 6px dashed silver; border: 6px dashed silver;
border-radius: 50%; border-radius: 50%;
} }
@ -340,68 +340,68 @@
font-weight: bold; font-weight: bold;
} }
.tab-initial_setup #compass span:nth-child(1) { .tab-initial_setup #compass span:nth-child(1) {
left: 70px; left: 70px;
top: 5px; top: 5px;
} }
.tab-initial_setup #compass span:nth-child(2) { .tab-initial_setup #compass span:nth-child(2) {
right: 5px; right: 5px;
top: 70px; top: 70px;
} }
.tab-initial_setup #compass span:nth-child(3) { .tab-initial_setup #compass span:nth-child(3) {
left: 70px; left: 70px;
bottom: 5px; bottom: 5px;
} }
.tab-initial_setup #compass span:nth-child(4) { .tab-initial_setup #compass span:nth-child(4) {
left: 5px; left: 5px;
top: 70px; top: 70px;
} }
.tab-initial_setup #compass .pointer { .tab-initial_setup #compass .pointer {
position: absolute; position: absolute;
height: 150px; height: 150px;
width: 150px; width: 150px;
-webkit-transform: rotate(0deg); -webkit-transform: rotate(0deg);
} }
.tab-initial_setup #compass .pointer .tip { .tab-initial_setup #compass .pointer .tip {
position: absolute; position: absolute;
margin-top: 14px; margin-top: 14px;
margin-left: -6px; margin-left: -6px;
width: 0; width: 0;
height: 0; height: 0;
border-left: 10px solid transparent; border-left: 10px solid transparent;
border-right: 10px solid transparent; border-right: 10px solid transparent;
border-bottom: 30px solid red; border-bottom: 30px solid red;
} }
.tab-initial_setup #compass .pointer .stick { .tab-initial_setup #compass .pointer .stick {
position: absolute; position: absolute;
display: block; display: block;
margin-top: -22px; margin-top: -22px;
margin-right: 69px; margin-right: 69px;
width: 4px; width: 4px;
height: 30px; height: 30px;
background-color: black; background-color: black;
} }
.tab-initial_setup #compass .value { .tab-initial_setup #compass .value {
position: relative; position: relative;
top: 75px; top: 75px;
left: 53px; left: 53px;
width: 40px; width: 40px;
height: 16px; height: 16px;
line-height: 16px; line-height: 16px;
text-align: center; text-align: center;
background-color: #f2f2f2; background-color: #f2f2f2;
border: 1px solid silver; border: 1px solid silver;
} }

View file

@ -1,28 +1,28 @@
function tab_initialize_initial_setup() { function tab_initialize_initial_setup() {
ga_tracker.sendAppView('Initial Setup'); ga_tracker.sendAppView('Initial Setup');
GUI.active_tab = 'initial_setup'; GUI.active_tab = 'initial_setup';
send_message(MSP_codes.MSP_ACC_TRIM, MSP_codes.MSP_ACC_TRIM, false, function() { send_message(MSP_codes.MSP_ACC_TRIM, MSP_codes.MSP_ACC_TRIM, false, function() {
send_message(MSP_codes.MSP_MISC, MSP_codes.MSP_MISC, false, function() { send_message(MSP_codes.MSP_MISC, MSP_codes.MSP_MISC, false, function() {
$('#content').load("./tabs/initial_setup.html", function() { $('#content').load("./tabs/initial_setup.html", function() {
var yaw_fix = 0.0; var yaw_fix = 0.0;
// Fill in misc stuff // Fill in misc stuff
$('input[name="mincellvoltage"]').val(MISC.vbatmincellvoltage); $('input[name="mincellvoltage"]').val(MISC.vbatmincellvoltage);
$('input[name="maxcellvoltage"]').val(MISC.vbatmaxcellvoltage); $('input[name="maxcellvoltage"]').val(MISC.vbatmaxcellvoltage);
$('input[name="voltagescale"]').val(MISC.vbatscale); $('input[name="voltagescale"]').val(MISC.vbatscale);
$('input[name="minthrottle"]').val(MISC.minthrottle); $('input[name="minthrottle"]').val(MISC.minthrottle);
$('input[name="maxthrottle"]').val(MISC.maxthrottle); $('input[name="maxthrottle"]').val(MISC.maxthrottle);
$('input[name="failsafe_throttle"]').val(MISC.failsafe_throttle); $('input[name="failsafe_throttle"]').val(MISC.failsafe_throttle);
$('input[name="mincommand"]').val(MISC.mincommand); $('input[name="mincommand"]').val(MISC.mincommand);
$('input[name="mag_declination"]').val(MISC.mag_declination / 10); $('input[name="mag_declination"]').val(MISC.mag_declination / 10);
// Fill in the accel trimms from CONFIG object // Fill in the accel trimms from CONFIG object
$('input[name="pitch"]').val(CONFIG.accelerometerTrims[0]); $('input[name="pitch"]').val(CONFIG.accelerometerTrims[0]);
$('input[name="roll"]').val(CONFIG.accelerometerTrims[1]); $('input[name="roll"]').val(CONFIG.accelerometerTrims[1]);
// Display multiType // Display multiType
var str = ''; var str = '';
switch (CONFIG.multiType) { switch (CONFIG.multiType) {
@ -64,13 +64,13 @@ function tab_initialize_initial_setup() {
case 14: // AIRPLANE case 14: // AIRPLANE
str = 'Airplane'; str = 'Airplane';
break; break;
case 15: // Heli 120 case 15: // Heli 120
str = 'Heli 120'; str = 'Heli 120';
break; break;
case 16: // Heli 90 case 16: // Heli 90
str = 'Heli 90'; str = 'Heli 90';
break; break;
case 17: // Vtail case 17: // Vtail
str = 'Vtail'; str = 'Vtail';
break; break;
case 18: // HEX6 H case 18: // HEX6 H
@ -86,43 +86,43 @@ function tab_initialize_initial_setup() {
str = 'Singlecopter'; str = 'Singlecopter';
break; break;
} }
$('span.model').html('Model: ' + str); $('span.model').html('Model: ' + str);
// UI Hooks // UI Hooks
$('a.calibrateAccel').click(function() { $('a.calibrateAccel').click(function() {
var self = $(this); var self = $(this);
if (!self.hasClass('calibrating')) { if (!self.hasClass('calibrating')) {
self.addClass('calibrating'); self.addClass('calibrating');
// During this period MCU won't be able to process any serial commands because its locked in a for/while loop // 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 // until this operation finishes, sending more commands through data_poll() will result in serial buffer overflow
GUI.interval_pause('initial_setup_data_pull'); GUI.interval_pause('initial_setup_data_pull');
send_message(MSP_codes.MSP_ACC_CALIBRATION, MSP_codes.MSP_ACC_CALIBRATION, false, function() { send_message(MSP_codes.MSP_ACC_CALIBRATION, MSP_codes.MSP_ACC_CALIBRATION, false, function() {
GUI.log('Accelerometer calibration started'); GUI.log('Accelerometer calibration started');
}); });
GUI.timeout_add('button_reset', function() { GUI.timeout_add('button_reset', function() {
GUI.interval_resume('initial_setup_data_pull'); GUI.interval_resume('initial_setup_data_pull');
GUI.log('Accelerometer calibration finished'); GUI.log('Accelerometer calibration finished');
self.removeClass('calibrating'); self.removeClass('calibrating');
}, 2000); }, 2000);
} }
}); });
$('a.calibrateMag').click(function() { $('a.calibrateMag').click(function() {
var self = $(this); var self = $(this);
if (!self.hasClass('calibrating')) { if (!self.hasClass('calibrating')) {
self.addClass('calibrating'); self.addClass('calibrating');
send_message(MSP_codes.MSP_MAG_CALIBRATION, MSP_codes.MSP_MAG_CALIBRATION, false, function() { send_message(MSP_codes.MSP_MAG_CALIBRATION, MSP_codes.MSP_MAG_CALIBRATION, false, function() {
GUI.log('Magnetometer calibration started'); GUI.log('Magnetometer calibration started');
}); });
GUI.timeout_add('button_reset', function() { GUI.timeout_add('button_reset', function() {
GUI.log('Magnetometer calibration finished'); GUI.log('Magnetometer calibration finished');
self.removeClass('calibrating'); self.removeClass('calibrating');
@ -133,38 +133,38 @@ function tab_initialize_initial_setup() {
$('a.resetSettings').click(function() { $('a.resetSettings').click(function() {
send_message(MSP_codes.MSP_RESET_CONF, MSP_codes.MSP_RESET_CONF, false, function() { send_message(MSP_codes.MSP_RESET_CONF, MSP_codes.MSP_RESET_CONF, false, function() {
GUI.log('Settings restored to <strong>default</strong>'); GUI.log('Settings restored to <strong>default</strong>');
GUI.tab_switch_cleanup(function() { GUI.tab_switch_cleanup(function() {
tab_initialize_initial_setup(); tab_initialize_initial_setup();
}); });
}); });
}); });
$('a.update').click(function() { $('a.update').click(function() {
CONFIG.accelerometerTrims[0] = parseInt($('input[name="pitch"]').val()); CONFIG.accelerometerTrims[0] = parseInt($('input[name="pitch"]').val());
CONFIG.accelerometerTrims[1] = parseInt($('input[name="roll"]').val()); CONFIG.accelerometerTrims[1] = parseInt($('input[name="roll"]').val());
var buffer_out = new Array(); var buffer_out = new Array();
buffer_out[0] = lowByte(CONFIG.accelerometerTrims[0]); buffer_out[0] = lowByte(CONFIG.accelerometerTrims[0]);
buffer_out[1] = highByte(CONFIG.accelerometerTrims[0]); buffer_out[1] = highByte(CONFIG.accelerometerTrims[0]);
buffer_out[2] = lowByte(CONFIG.accelerometerTrims[1]); buffer_out[2] = lowByte(CONFIG.accelerometerTrims[1]);
buffer_out[3] = highByte(CONFIG.accelerometerTrims[1]); buffer_out[3] = highByte(CONFIG.accelerometerTrims[1]);
// Send over the new trims // Send over the new trims
send_message(MSP_codes.MSP_SET_ACC_TRIM, buffer_out); send_message(MSP_codes.MSP_SET_ACC_TRIM, buffer_out);
MISC.vbatmincellvoltage = parseFloat($('input[name="mincellvoltage"]').val()) * 10; MISC.vbatmincellvoltage = parseFloat($('input[name="mincellvoltage"]').val()) * 10;
MISC.vbatmaxcellvoltage = parseFloat($('input[name="maxcellvoltage"]').val()) * 10; MISC.vbatmaxcellvoltage = parseFloat($('input[name="maxcellvoltage"]').val()) * 10;
MISC.vbatscale = parseInt($('input[name="voltagescale"]').val()); MISC.vbatscale = parseInt($('input[name="voltagescale"]').val());
MISC.minthrottle = parseInt($('input[name="minthrottle"]').val()); MISC.minthrottle = parseInt($('input[name="minthrottle"]').val());
MISC.maxthrottle = parseInt($('input[name="maxthrottle"]').val()); MISC.maxthrottle = parseInt($('input[name="maxthrottle"]').val());
MISC.failsafe_throttle = parseInt($('input[name="failsafe_throttle"]').val()); MISC.failsafe_throttle = parseInt($('input[name="failsafe_throttle"]').val());
MISC.mincommand = parseInt($('input[name="mincommand"]').val()); MISC.mincommand = parseInt($('input[name="mincommand"]').val());
MISC.mag_declination = parseFloat($('input[name="mag_declination"]').val()) * 10; MISC.mag_declination = parseFloat($('input[name="mag_declination"]').val()) * 10;
// we also have to fill the unsupported bytes // we also have to fill the unsupported bytes
var buffer_out = new Array(); var buffer_out = new Array();
buffer_out[0] = 0; // powerfailmeter buffer_out[0] = 0; // powerfailmeter
@ -189,56 +189,56 @@ function tab_initialize_initial_setup() {
buffer_out[19] = MISC.vbatmincellvoltage; buffer_out[19] = MISC.vbatmincellvoltage;
buffer_out[20] = MISC.vbatmaxcellvoltage; buffer_out[20] = MISC.vbatmaxcellvoltage;
buffer_out[21] = 0; // vbatlevel_crit (unused) buffer_out[21] = 0; // vbatlevel_crit (unused)
// Send over new misc // Send over new misc
send_message(MSP_codes.MSP_SET_MISC, buffer_out); send_message(MSP_codes.MSP_SET_MISC, buffer_out);
// Save changes to EEPROM // Save changes to EEPROM
send_message(MSP_codes.MSP_EEPROM_WRITE, MSP_codes.MSP_EEPROM_WRITE, false, function() { send_message(MSP_codes.MSP_EEPROM_WRITE, MSP_codes.MSP_EEPROM_WRITE, false, function() {
GUI.log('EEPROM <span style="color: green">saved</span>'); GUI.log('EEPROM <span style="color: green">saved</span>');
var element = $('a.update'); var element = $('a.update');
element.addClass('success'); element.addClass('success');
GUI.timeout_add('success_highlight', function() { GUI.timeout_add('success_highlight', function() {
element.removeClass('success'); element.removeClass('success');
}, 2000); }, 2000);
}); });
}); });
// reset yaw button hook // reset yaw button hook
$('div#interactive_block > a.reset').click(function() { $('div#interactive_block > a.reset').click(function() {
yaw_fix = SENSOR_DATA.kinematicsZ * - 1.0; yaw_fix = SENSOR_DATA.kinematicsZ * - 1.0;
console.log("YAW reset to 0"); console.log("YAW reset to 0");
}); });
$('#content .backup').click(configuration_backup); $('#content .backup').click(configuration_backup);
$('#content .restore').click(configuration_restore); $('#content .restore').click(configuration_restore);
GUI.interval_add('initial_setup_data_pull', function() { GUI.interval_add('initial_setup_data_pull', function() {
// Update voltage indicator // Update voltage indicator
$('.bat-voltage').html(ANALOG.voltage + ' V'); $('.bat-voltage').html(ANALOG.voltage + ' V');
// Request new data, if transmission fails it doesn't matter as new transmission will be requested after 50ms // Request new data, if transmission fails it doesn't matter as new transmission will be requested after 50ms
send_message(MSP_codes.MSP_STATUS, MSP_codes.MSP_STATUS, false, function() { // cycle time, active sensors, etc... send_message(MSP_codes.MSP_STATUS, MSP_codes.MSP_STATUS, false, function() { // cycle time, active sensors, etc...
send_message(MSP_codes.MSP_ANALOG, MSP_codes.MSP_ANALOG, false, function() { // battery voltage send_message(MSP_codes.MSP_ANALOG, MSP_codes.MSP_ANALOG, false, function() { // battery voltage
send_message(MSP_codes.MSP_ATTITUDE, MSP_codes.MSP_ATTITUDE, false, function() { // kinematics send_message(MSP_codes.MSP_ATTITUDE, MSP_codes.MSP_ATTITUDE, false, function() { // kinematics
// Update cube // Update cube
var cube = $('div#cube'); var cube = $('div#cube');
cube.css('-webkit-transform', 'rotateY(' + ((SENSOR_DATA.kinematicsZ * -1.0) - yaw_fix) + 'deg)'); cube.css('-webkit-transform', 'rotateY(' + ((SENSOR_DATA.kinematicsZ * -1.0) - yaw_fix) + 'deg)');
$('#cubePITCH', cube).css('-webkit-transform', 'rotateX(' + SENSOR_DATA.kinematicsY + 'deg)'); $('#cubePITCH', cube).css('-webkit-transform', 'rotateX(' + SENSOR_DATA.kinematicsY + 'deg)');
$('#cubeROLL', cube).css('-webkit-transform', 'rotateZ(' + SENSOR_DATA.kinematicsX + 'deg)'); $('#cubeROLL', cube).css('-webkit-transform', 'rotateZ(' + SENSOR_DATA.kinematicsX + 'deg)');
/* /*
// Update Compass // Update Compass
$('div#compass .pointer').css('-webkit-transform', 'rotate(' + (SENSOR_DATA.kinematicsZ) + 'deg)'); $('div#compass .pointer').css('-webkit-transform', 'rotate(' + (SENSOR_DATA.kinematicsZ) + 'deg)');
$('div#compass .value').html(SENSOR_DATA.kinematicsZ + '&deg;'); $('div#compass .value').html(SENSOR_DATA.kinematicsZ + '&deg;');
*/ */
}); });
}); });
}); });
}, 50, true); }, 50, true);
}); });
}); });

View file

@ -1,5 +1,5 @@
.tab-motor_outputs { .tab-motor_outputs {
} }
.tab-motor_outputs .right.servos { .tab-motor_outputs .right.servos {
margin-right: -10px; margin-right: -10px;
} }
@ -10,7 +10,7 @@
float: left; float: left;
width: 42px; width: 42px;
margin-right: 10px; margin-right: 10px;
text-align: center; text-align: center;
} }
.tab-motor_outputs .titles .active { .tab-motor_outputs .titles .active {
@ -18,24 +18,24 @@
} }
.tab-motor_outputs .m-block { .tab-motor_outputs .m-block {
float: left; float: left;
width: 40px; width: 40px;
height: 160px; height: 160px;
margin-right: 10px; margin-right: 10px;
border: 1px solid silver; border: 1px solid silver;
background-color: #e9e9e9; background-color: #e9e9e9;
} }
.tab-motor_outputs .indicator { .tab-motor_outputs .indicator {
position: absolute; position: absolute;
width: 40px; width: 40px;
} }
.tab-motor_outputs p { .tab-motor_outputs p {
margin-top: 20px; margin-top: 20px;
padding: 5px; padding: 5px;
border: 1px dotted silver; border: 1px dotted silver;
} }
.tab-motor_outputs .motor_testing { .tab-motor_outputs .motor_testing {
@ -46,7 +46,7 @@
} }
.tab-motor_outputs .motor_testing .sliders input { .tab-motor_outputs .motor_testing .sliders input {
-webkit-appearance: slider-vertical; -webkit-appearance: slider-vertical;
width: 48px; width: 48px;
} }
.tab-motor_outputs .motor_testing .values { .tab-motor_outputs .motor_testing .values {
@ -54,23 +54,23 @@
} }
.tab-motor_outputs .motor_testing .values li { .tab-motor_outputs .motor_testing .values li {
float: left; float: left;
width: 51px; width: 51px;
text-align: center; text-align: center;
} }
.tab-motor_outputs .motor_testing .notice { .tab-motor_outputs .motor_testing .notice {
float: right; float: right;
width: 420px; width: 420px;
margin-top: 20px; margin-top: 20px;
padding: 5px; padding: 5px;
border: 1px dotted silver; border: 1px dotted silver;
} }
.tab-motor_outputs .motor_testing .notice input[type="checkbox"] { .tab-motor_outputs .motor_testing .notice input[type="checkbox"] {
margin-left: 5px; margin-left: 5px;
vertical-align: middle; vertical-align: middle;
} }

View file

@ -46,7 +46,7 @@
<div class="clear-both"></div> <div class="clear-both"></div>
<p> <p>
Bars on the <strong>left</strong> are representing raw PWM signal for <strong>ESCs</strong>.<br /> Bars on the <strong>left</strong> are representing raw PWM signal for <strong>ESCs</strong>.<br />
Bars on the <strong>right</strong> are representing raw PWM signal for <strong>Servos</strong>.<br /> Bars on the <strong>right</strong> are representing raw PWM signal for <strong>Servos</strong>.<br />
</p> </p>
<div class="motor_testing"> <div class="motor_testing">
<div class="left"> <div class="left">

View file

@ -1,7 +1,7 @@
function tab_initialize_motor_outputs() { function tab_initialize_motor_outputs() {
ga_tracker.sendAppView('Motor Outputs Page'); ga_tracker.sendAppView('Motor Outputs Page');
GUI.active_tab = 'motor_outputs'; GUI.active_tab = 'motor_outputs';
send_message(MSP_codes.MSP_MISC, MSP_codes.MSP_MISC, false, function() { send_message(MSP_codes.MSP_MISC, MSP_codes.MSP_MISC, false, function() {
send_message(MSP_codes.MSP_MOTOR, MSP_codes.MSP_MOTOR, false, function() { send_message(MSP_codes.MSP_MOTOR, MSP_codes.MSP_MOTOR, false, function() {
$('#content').load("./tabs/motor_outputs.html", function() { $('#content').load("./tabs/motor_outputs.html", function() {
@ -9,64 +9,64 @@ function tab_initialize_motor_outputs() {
if (bit_check(CONFIG.capability, 2)) { if (bit_check(CONFIG.capability, 2)) {
$('div.motor_testing').show(); $('div.motor_testing').show();
} }
var number_of_valid_outputs = (MOTOR_DATA.indexOf(0) > -1) ? MOTOR_DATA.indexOf(0) : 8; var number_of_valid_outputs = (MOTOR_DATA.indexOf(0) > -1) ? MOTOR_DATA.indexOf(0) : 8;
$('input.min').val(MISC.mincommand); $('input.min').val(MISC.mincommand);
$('input.max').val(MISC.maxthrottle); $('input.max').val(MISC.maxthrottle);
$('div.sliders input').prop('min', MISC.mincommand); $('div.sliders input').prop('min', MISC.mincommand);
$('div.sliders input').prop('max', MISC.maxthrottle); $('div.sliders input').prop('max', MISC.maxthrottle);
$('div.sliders input').val(MISC.mincommand); $('div.sliders input').val(MISC.mincommand);
$('div.values li:not(:last)').html(MISC.mincommand); $('div.values li:not(:last)').html(MISC.mincommand);
// UI hooks // UI hooks
$('div.sliders input:not(.master)').change(function() { $('div.sliders input:not(.master)').change(function() {
var index = $(this).index(); var index = $(this).index();
$('div.values li').eq(index).html($(this).val()); $('div.values li').eq(index).html($(this).val());
// send data to mcu // send data to mcu
var buffer_out = []; var buffer_out = [];
for (var i = 0; i < 8; i++) { for (var i = 0; i < 8; i++) {
var val = parseInt($('div.sliders input').eq(i).val()); var val = parseInt($('div.sliders input').eq(i).val());
buffer_out.push(lowByte(val)); buffer_out.push(lowByte(val));
buffer_out.push(highByte(val)); buffer_out.push(highByte(val));
} }
send_message(MSP_codes.MSP_SET_MOTOR, buffer_out); send_message(MSP_codes.MSP_SET_MOTOR, buffer_out);
}); });
$('div.sliders input.master').change(function() { $('div.sliders input.master').change(function() {
var val = $(this).val(); var val = $(this).val();
$('div.sliders input:not(:disabled, :last)').val(val); $('div.sliders input:not(:disabled, :last)').val(val);
$('div.values li:not(:last)').slice(0, number_of_valid_outputs).html(val); $('div.values li:not(:last)').slice(0, number_of_valid_outputs).html(val);
$('div.sliders input:not(:last):first').change(); $('div.sliders input:not(:last):first').change();
}); });
$('div.notice input[type="checkbox"]').change(function() { $('div.notice input[type="checkbox"]').change(function() {
if ($(this).is(':checked')) { if ($(this).is(':checked')) {
$('div.sliders input').slice(0, number_of_valid_outputs).prop('disabled', false); $('div.sliders input').slice(0, number_of_valid_outputs).prop('disabled', false);
// unlock master slider // unlock master slider
$('div.sliders input:last').prop('disabled', false); $('div.sliders input:last').prop('disabled', false);
} else { } else {
// disable sliders / min max // disable sliders / min max
$('div.sliders input').prop('disabled', true); $('div.sliders input').prop('disabled', true);
// change all values to default // change all values to default
$('div.sliders input').val(1000); $('div.sliders input').val(1000);
$('div.values li:not(:last)').html(1000); $('div.values li:not(:last)').html(1000);
// trigger change event so values are sent to mcu // trigger change event so values are sent to mcu
$('div.sliders input').change(); $('div.sliders input').change();
} }
}); });
// enable Motor data pulling // enable Motor data pulling
GUI.interval_add('motor_poll', function() { GUI.interval_add('motor_poll', function() {
// Request New data // Request New data
@ -74,26 +74,26 @@ function tab_initialize_motor_outputs() {
send_message(MSP_codes.MSP_MOTOR, MSP_codes.MSP_MOTOR, false, function() { send_message(MSP_codes.MSP_MOTOR, MSP_codes.MSP_MOTOR, false, function() {
send_message(MSP_codes.MSP_SERVO, MSP_codes.MSP_SERVO, false, function() { send_message(MSP_codes.MSP_SERVO, MSP_codes.MSP_SERVO, false, function() {
// Update UI // Update UI
var block_height = $('div.m-block:first').height(); var block_height = $('div.m-block:first').height();
for (var i = 0; i < MOTOR_DATA.length; i++) { for (var i = 0; i < MOTOR_DATA.length; i++) {
var data = MOTOR_DATA[i] - 1000; var data = MOTOR_DATA[i] - 1000;
var margin_top = block_height - (data * (block_height / 1000)); var margin_top = block_height - (data * (block_height / 1000));
var height = (data * (block_height / 1000)); var height = (data * (block_height / 1000));
var color = parseInt(data * 0.256); var color = parseInt(data * 0.256);
$('.motor-' + i + ' .indicator').css({'margin-top' : margin_top + 'px', 'height' : height + 'px', 'background-color' : 'rgb(' + color + ',0,0)'}); $('.motor-' + i + ' .indicator').css({'margin-top' : margin_top + 'px', 'height' : height + 'px', 'background-color' : 'rgb(' + color + ',0,0)'});
} }
for (var i = 0; i < SERVO_DATA.length; i++) { for (var i = 0; i < SERVO_DATA.length; i++) {
var data = SERVO_DATA[i] - 1000; var data = SERVO_DATA[i] - 1000;
var margin_top = block_height - (data * (block_height / 1000)); var margin_top = block_height - (data * (block_height / 1000));
var height = (data * (block_height / 1000)); var height = (data * (block_height / 1000));
var color = parseInt(data * 0.256); var color = parseInt(data * 0.256);
$('.servo-' + i + ' .indicator').css({'margin-top' : margin_top + 'px', 'height' : height + 'px', 'background-color' : 'rgb(' + color + ',0,0)'}); $('.servo-' + i + ' .indicator').css({'margin-top' : margin_top + 'px', 'height' : height + 'px', 'background-color' : 'rgb(' + color + ',0,0)'});
} }
}); });
}); });
}); });

View file

@ -5,11 +5,11 @@
} }
.tab-pid_tuning table { .tab-pid_tuning table {
float: left; float: left;
border-collapse: collapse; border-collapse: collapse;
} }
.tab-pid_tuning table, .tab-pid_tuning table,
.tab-pid_tuning table th, .tab-pid_tuning table th,
.tab-pid_tuning table td { .tab-pid_tuning table td {
padding: 4px; padding: 4px;
border: 1px solid #8b8b8b; border: 1px solid #8b8b8b;
@ -35,32 +35,32 @@
width: 96px; width: 96px;
height: 20px; height: 20px;
line-height: 20px; line-height: 20px;
padding: 0 5px 0 5px; padding: 0 5px 0 5px;
text-align: right; text-align: right;
} }
.tab-pid_tuning .profile { .tab-pid_tuning .profile {
float: left; float: left;
margin-top: 10px; margin-top: 10px;
width: 70px; width: 70px;
border: 1px solid silver; border: 1px solid silver;
} }
.tab-pid_tuning .profile .head { .tab-pid_tuning .profile .head {
display: block; display: block;
text-align: center; text-align: center;
line-height: 20px; line-height: 20px;
font-weight: bold; font-weight: bold;
border-bottom: 1px solid silver; border-bottom: 1px solid silver;
background-color: #ececec; background-color: #ececec;
} }
.tab-pid_tuning .profile input { .tab-pid_tuning .profile input {
padding-left: 30px; padding-left: 30px;
width: 40px; width: 40px;
height: 20px; height: 20px;
line-height: 20px; line-height: 20px;
@ -78,23 +78,23 @@
.tab-pid_tuning .refresh { .tab-pid_tuning .refresh {
display: block; display: block;
float: right; float: right;
margin-top: 10px; margin-top: 10px;
height: 28px; height: 28px;
line-height: 28px; line-height: 28px;
padding: 0 15px 0 15px; padding: 0 15px 0 15px;
text-align: center; text-align: center;
font-weight: bold; font-weight: bold;
border: 1px solid silver; border: 1px solid silver;
background-color: #ececec; background-color: #ececec;
} }
.tab-pid_tuning .refresh { .tab-pid_tuning .refresh {
margin-right: 10px; margin-right: 10px;
} }
.tab-pid_tuning .update:hover, .tab-pid_tuning .update:hover,
.tab-pid_tuning .refresh:hover { .tab-pid_tuning .refresh:hover {
background-color: #dedcdc; background-color: #dedcdc;

View file

@ -1,7 +1,7 @@
function tab_initialize_pid_tuning() { function tab_initialize_pid_tuning() {
ga_tracker.sendAppView('PID Tuning'); ga_tracker.sendAppView('PID Tuning');
GUI.active_tab = 'pid_tuning'; GUI.active_tab = 'pid_tuning';
send_message(MSP_codes.MSP_PID, MSP_codes.MSP_PID, false, function() { send_message(MSP_codes.MSP_PID, MSP_codes.MSP_PID, false, function() {
send_message(MSP_codes.MSP_RC_TUNING, MSP_codes.MSP_RC_TUNING, false, function() { send_message(MSP_codes.MSP_RC_TUNING, MSP_codes.MSP_RC_TUNING, false, function() {
$('#content').load("./tabs/pid_tuning.html", function() { $('#content').load("./tabs/pid_tuning.html", function() {
@ -10,220 +10,220 @@ function tab_initialize_pid_tuning() {
$('.pid_tuning .ROLL input').each(function() { $('.pid_tuning .ROLL input').each(function() {
switch (i) { switch (i) {
case 0: case 0:
$(this).val(PIDs[0][i++].toFixed(1)); $(this).val(PIDs[0][i++].toFixed(1));
break; break;
case 1: case 1:
$(this).val(PIDs[0][i++].toFixed(3)); $(this).val(PIDs[0][i++].toFixed(3));
break; break;
case 2: case 2:
$(this).val(PIDs[0][i++].toFixed(0)); $(this).val(PIDs[0][i++].toFixed(0));
break; break;
} }
}); });
i = 0; i = 0;
$('.pid_tuning .PITCH input').each(function() { $('.pid_tuning .PITCH input').each(function() {
switch (i) { switch (i) {
case 0: case 0:
$(this).val(PIDs[1][i++].toFixed(1)); $(this).val(PIDs[1][i++].toFixed(1));
break; break;
case 1: case 1:
$(this).val(PIDs[1][i++].toFixed(3)); $(this).val(PIDs[1][i++].toFixed(3));
break; break;
case 2: case 2:
$(this).val(PIDs[1][i++].toFixed(0)); $(this).val(PIDs[1][i++].toFixed(0));
break; break;
} }
}); });
i = 0; i = 0;
$('.pid_tuning .YAW input').each(function() { $('.pid_tuning .YAW input').each(function() {
switch (i) { switch (i) {
case 0: case 0:
$(this).val(PIDs[2][i++].toFixed(1)); $(this).val(PIDs[2][i++].toFixed(1));
break; break;
case 1: case 1:
$(this).val(PIDs[2][i++].toFixed(3)); $(this).val(PIDs[2][i++].toFixed(3));
break; break;
case 2: case 2:
$(this).val(PIDs[2][i++].toFixed(0)); $(this).val(PIDs[2][i++].toFixed(0));
break; break;
} }
}); });
i = 0; i = 0;
$('.pid_tuning .ALT input').each(function() { $('.pid_tuning .ALT input').each(function() {
switch (i) { switch (i) {
case 0: case 0:
$(this).val(PIDs[3][i++].toFixed(1)); $(this).val(PIDs[3][i++].toFixed(1));
break; break;
case 1: case 1:
$(this).val(PIDs[3][i++].toFixed(3)); $(this).val(PIDs[3][i++].toFixed(3));
break; break;
case 2: case 2:
$(this).val(PIDs[3][i++].toFixed(0)); $(this).val(PIDs[3][i++].toFixed(0));
break; break;
} }
}); });
i = 0; i = 0;
$('.pid_tuning .Pos input').each(function() { $('.pid_tuning .Pos input').each(function() {
$(this).val(PIDs[4][i++].toFixed(2)); $(this).val(PIDs[4][i++].toFixed(2));
}); });
i = 0; i = 0;
$('.pid_tuning .PosR input').each(function() { $('.pid_tuning .PosR input').each(function() {
switch (i) { switch (i) {
case 0: case 0:
$(this).val(PIDs[5][i++].toFixed(1)); $(this).val(PIDs[5][i++].toFixed(1));
break; break;
case 1: case 1:
$(this).val(PIDs[5][i++].toFixed(2)); $(this).val(PIDs[5][i++].toFixed(2));
break; break;
case 2: case 2:
$(this).val(PIDs[5][i++].toFixed(3)); $(this).val(PIDs[5][i++].toFixed(3));
break; break;
} }
}); });
i = 0; i = 0;
$('.pid_tuning .NavR input').each(function() { $('.pid_tuning .NavR input').each(function() {
switch (i) { switch (i) {
case 0: case 0:
$(this).val(PIDs[6][i++].toFixed(1)); $(this).val(PIDs[6][i++].toFixed(1));
break; break;
case 1: case 1:
$(this).val(PIDs[6][i++].toFixed(2)); $(this).val(PIDs[6][i++].toFixed(2));
break; break;
case 2: case 2:
$(this).val(PIDs[6][i++].toFixed(3)); $(this).val(PIDs[6][i++].toFixed(3));
break; break;
} }
}); });
i = 0; i = 0;
$('.pid_tuning .LEVEL input').each(function() { $('.pid_tuning .LEVEL input').each(function() {
switch (i) { switch (i) {
case 0: case 0:
$(this).val(PIDs[7][i++].toFixed(1)); $(this).val(PIDs[7][i++].toFixed(1));
break; break;
case 1: case 1:
$(this).val(PIDs[7][i++].toFixed(2)); $(this).val(PIDs[7][i++].toFixed(2));
break; break;
case 2: case 2:
$(this).val(PIDs[7][i++].toFixed(0)); $(this).val(PIDs[7][i++].toFixed(0));
break; break;
} }
}); });
i = 0; i = 0;
$('.pid_tuning .MAG input').each(function() { $('.pid_tuning .MAG input').each(function() {
$(this).val(PIDs[8][i++].toFixed(1)); $(this).val(PIDs[8][i++].toFixed(1));
}); });
i = 0; i = 0;
$('.pid_tuning .Vario input').each(function() { $('.pid_tuning .Vario input').each(function() {
switch (i) { switch (i) {
case 0: case 0:
$(this).val(PIDs[9][i++].toFixed(1)); $(this).val(PIDs[9][i++].toFixed(1));
break; break;
case 1: case 1:
$(this).val(PIDs[9][i++].toFixed(3)); $(this).val(PIDs[9][i++].toFixed(3));
break; break;
case 2: case 2:
$(this).val(PIDs[9][i++].toFixed(0)); $(this).val(PIDs[9][i++].toFixed(0));
break; break;
} }
}); });
// Fill in data from RC_tuning object // Fill in data from RC_tuning object
$('.rate-tpa input[name="roll-pitch"]').val(RC_tuning.roll_pitch_rate.toFixed(2)); $('.rate-tpa input[name="roll-pitch"]').val(RC_tuning.roll_pitch_rate.toFixed(2));
$('.rate-tpa input[name="yaw"]').val(RC_tuning.yaw_rate.toFixed(2)); $('.rate-tpa input[name="yaw"]').val(RC_tuning.yaw_rate.toFixed(2));
$('.rate-tpa input[name="tpa"]').val(RC_tuning.dynamic_THR_PID.toFixed(2)); $('.rate-tpa input[name="tpa"]').val(RC_tuning.dynamic_THR_PID.toFixed(2));
// Fill in currently selected profile // Fill in currently selected profile
$('input[name="profile"]').val(CONFIG.profile + 1); // +1 because the range is 0-2 $('input[name="profile"]').val(CONFIG.profile + 1); // +1 because the range is 0-2
// UI Hooks // UI Hooks
$('input[name="profile"]').change(function() { $('input[name="profile"]').change(function() {
var profile = parseInt($(this).val()); var profile = parseInt($(this).val());
send_message(MSP_codes.MSP_SELECT_SETTING, [profile - 1], false, function() { send_message(MSP_codes.MSP_SELECT_SETTING, [profile - 1], false, function() {
GUI.log('Loaded Profile: <strong>' + profile + '</strong>'); GUI.log('Loaded Profile: <strong>' + profile + '</strong>');
GUI.tab_switch_cleanup(function() { GUI.tab_switch_cleanup(function() {
tab_initialize_pid_tuning(); tab_initialize_pid_tuning();
}); });
}); });
}); });
$('a.refresh').click(function() { $('a.refresh').click(function() {
GUI.tab_switch_cleanup(function() { GUI.tab_switch_cleanup(function() {
GUI.log('PID data <strong>refreshed</strong>'); GUI.log('PID data <strong>refreshed</strong>');
tab_initialize_pid_tuning(); tab_initialize_pid_tuning();
}); });
}); });
$('a.update').click(function() { $('a.update').click(function() {
// Catch all the changes and stuff the inside PIDs array // Catch all the changes and stuff the inside PIDs array
var i = 0; var i = 0;
$('table.pid_tuning tr.ROLL input').each(function() { $('table.pid_tuning tr.ROLL input').each(function() {
PIDs[0][i++] = parseFloat($(this).val()); PIDs[0][i++] = parseFloat($(this).val());
}); });
i = 0; i = 0;
$('table.pid_tuning tr.PITCH input').each(function() { $('table.pid_tuning tr.PITCH input').each(function() {
PIDs[1][i++] = parseFloat($(this).val()); PIDs[1][i++] = parseFloat($(this).val());
}); });
i = 0; i = 0;
$('table.pid_tuning tr.YAW input').each(function() { $('table.pid_tuning tr.YAW input').each(function() {
PIDs[2][i++] = parseFloat($(this).val()); PIDs[2][i++] = parseFloat($(this).val());
}); });
i = 0; i = 0;
$('table.pid_tuning tr.ALT input').each(function() { $('table.pid_tuning tr.ALT input').each(function() {
PIDs[3][i++] = parseFloat($(this).val()); PIDs[3][i++] = parseFloat($(this).val());
}); });
i = 0; i = 0;
$('table.pid_tuning tr.Vario input').each(function() { $('table.pid_tuning tr.Vario input').each(function() {
PIDs[9][i++] = parseFloat($(this).val()); PIDs[9][i++] = parseFloat($(this).val());
}); });
i = 0; i = 0;
$('table.pid_tuning tr.Pos input').each(function() { $('table.pid_tuning tr.Pos input').each(function() {
PIDs[4][i++] = parseFloat($(this).val()); PIDs[4][i++] = parseFloat($(this).val());
}); });
i = 0; i = 0;
$('table.pid_tuning tr.PosR input').each(function() { $('table.pid_tuning tr.PosR input').each(function() {
PIDs[5][i++] = parseFloat($(this).val()); PIDs[5][i++] = parseFloat($(this).val());
}); });
i = 0; i = 0;
$('table.pid_tuning tr.NavR input').each(function() { $('table.pid_tuning tr.NavR input').each(function() {
PIDs[6][i++] = parseFloat($(this).val()); PIDs[6][i++] = parseFloat($(this).val());
}); });
i = 0; i = 0;
$('table.pid_tuning tr.LEVEL input').each(function() { $('table.pid_tuning tr.LEVEL input').each(function() {
PIDs[7][i++] = parseFloat($(this).val()); PIDs[7][i++] = parseFloat($(this).val());
}); });
i = 0; i = 0;
$('table.pid_tuning tr.MAG input').each(function() { $('table.pid_tuning tr.MAG input').each(function() {
PIDs[8][i++] = parseFloat($(this).val()); PIDs[8][i++] = parseFloat($(this).val());
}); });
var PID_buffer_out = new Array(); var PID_buffer_out = new Array();
for (var i = 0, needle = 0; i < PIDs.length; i++, needle += 3) { for (var i = 0, needle = 0; i < PIDs.length; i++, needle += 3) {
switch (i) { switch (i) {
case 0: case 0:
case 1: case 1:
case 2: case 2:
case 3: case 3:
case 7: case 7:
case 8: case 8:
case 9: case 9:
PID_buffer_out[needle] = parseInt(PIDs[i][0] * 10); PID_buffer_out[needle] = parseInt(PIDs[i][0] * 10);
@ -235,23 +235,23 @@ function tab_initialize_pid_tuning() {
PID_buffer_out[needle + 1] = parseInt(PIDs[i][1] * 100); PID_buffer_out[needle + 1] = parseInt(PIDs[i][1] * 100);
PID_buffer_out[needle + 2] = parseInt(PIDs[i][2]); PID_buffer_out[needle + 2] = parseInt(PIDs[i][2]);
break; break;
case 5: case 5:
case 6: case 6:
PID_buffer_out[needle] = parseInt(PIDs[i][0] * 10); PID_buffer_out[needle] = parseInt(PIDs[i][0] * 10);
PID_buffer_out[needle + 1] = parseInt(PIDs[i][1] * 100); PID_buffer_out[needle + 1] = parseInt(PIDs[i][1] * 100);
PID_buffer_out[needle + 2] = parseInt(PIDs[i][2] * 1000); PID_buffer_out[needle + 2] = parseInt(PIDs[i][2] * 1000);
break; break;
} }
} }
// Send over the PID changes // Send over the PID changes
send_message(MSP_codes.MSP_SET_PID, PID_buffer_out); send_message(MSP_codes.MSP_SET_PID, PID_buffer_out);
// catch RC_tuning changes // catch RC_tuning changes
RC_tuning.roll_pitch_rate = parseFloat($('.rate-tpa input[name="roll-pitch"]').val()); RC_tuning.roll_pitch_rate = parseFloat($('.rate-tpa input[name="roll-pitch"]').val());
RC_tuning.yaw_rate = parseFloat($('.rate-tpa input[name="yaw"]').val()); RC_tuning.yaw_rate = parseFloat($('.rate-tpa input[name="yaw"]').val());
RC_tuning.dynamic_THR_PID = parseFloat($('.rate-tpa input[name="tpa"]').val()); RC_tuning.dynamic_THR_PID = parseFloat($('.rate-tpa input[name="tpa"]').val());
var RC_tuning_buffer_out = new Array(); var RC_tuning_buffer_out = new Array();
RC_tuning_buffer_out[0] = parseInt(RC_tuning.RC_RATE * 100); RC_tuning_buffer_out[0] = parseInt(RC_tuning.RC_RATE * 100);
RC_tuning_buffer_out[1] = parseInt(RC_tuning.RC_EXPO * 100); RC_tuning_buffer_out[1] = parseInt(RC_tuning.RC_EXPO * 100);
@ -260,17 +260,17 @@ function tab_initialize_pid_tuning() {
RC_tuning_buffer_out[4] = parseInt(RC_tuning.dynamic_THR_PID * 100); RC_tuning_buffer_out[4] = parseInt(RC_tuning.dynamic_THR_PID * 100);
RC_tuning_buffer_out[5] = parseInt(RC_tuning.throttle_MID * 100); RC_tuning_buffer_out[5] = parseInt(RC_tuning.throttle_MID * 100);
RC_tuning_buffer_out[6] = parseInt(RC_tuning.throttle_EXPO * 100); RC_tuning_buffer_out[6] = parseInt(RC_tuning.throttle_EXPO * 100);
// Send over the RC_tuning changes // Send over the RC_tuning changes
send_message(MSP_codes.MSP_SET_RC_TUNING, RC_tuning_buffer_out); send_message(MSP_codes.MSP_SET_RC_TUNING, RC_tuning_buffer_out);
// Save changes to EEPROM // Save changes to EEPROM
send_message(MSP_codes.MSP_EEPROM_WRITE, MSP_codes.MSP_EEPROM_WRITE, false, function() { send_message(MSP_codes.MSP_EEPROM_WRITE, MSP_codes.MSP_EEPROM_WRITE, false, function() {
GUI.log('EEPROM <span style="color: green">saved</span>'); GUI.log('EEPROM <span style="color: green">saved</span>');
var element = $('a.update'); var element = $('a.update');
element.addClass('success'); element.addClass('success');
GUI.timeout_add('success_highlight', function() { GUI.timeout_add('success_highlight', function() {
element.removeClass('success'); element.removeClass('success');
}, 2000); }, 2000);
@ -283,5 +283,5 @@ function tab_initialize_pid_tuning() {
}, 50); }, 50);
}); });
}); });
}); });
} }

View file

@ -9,7 +9,7 @@
.tab-receiver .bars ul { .tab-receiver .bars ul {
height: 20px; height: 20px;
line-height: 20px; line-height: 20px;
margin-bottom: 5px; margin-bottom: 5px;
} }
.tab-receiver .bars li { .tab-receiver .bars li {
@ -21,7 +21,7 @@
.tab-receiver .bars .meter meter { .tab-receiver .bars .meter meter {
width: 200px; width: 200px;
height: 20px; height: 20px;
border: 1px solid silver; border: 1px solid silver;
} }
.tab-receiver .bars .value { .tab-receiver .bars .value {
@ -49,20 +49,20 @@
} }
.tab-receiver .tunings table tr:nth-child(odd) { .tab-receiver .tunings table tr:nth-child(odd) {
background-color: #ececec; background-color: #ececec;
} }
.tab-receiver .tunings table input { .tab-receiver .tunings table input {
width: 116px; width: 116px;
height: 20px; height: 20px;
line-height: 20px; line-height: 20px;
padding: 0 5px 0 5px; padding: 0 5px 0 5px;
text-align: right; text-align: right;
} }
.tab-receiver #RX_plot { .tab-receiver #RX_plot {
margin: auto; margin: auto;
margin-top: 20px; margin-top: 20px;
width: 880px; width: 880px;
height: 200px; height: 200px;
} }
.tab-receiver .curves { .tab-receiver .curves {
@ -70,10 +70,10 @@
} }
.tab-receiver .throttle_curve { .tab-receiver .throttle_curve {
margin: 0 10px 10px 0; margin: 0 10px 10px 0;
width: 220px; width: 220px;
height: 58px; height: 58px;
border: 1px solid silver; border: 1px solid silver;
} }
.tab-receiver .pitch_roll_curve { .tab-receiver .pitch_roll_curve {
@ -81,24 +81,24 @@
width: 220px; width: 220px;
height: 58px; height: 58px;
border: 1px solid silver; border: 1px solid silver;
} }
.tab-receiver .update, .tab-receiver .update,
.tab-receiver .refresh { .tab-receiver .refresh {
display: block; display: block;
float: right; float: right;
margin-top: 22px; margin-top: 22px;
height: 28px; height: 28px;
line-height: 28px; line-height: 28px;
padding: 0 15px 0 15px; padding: 0 15px 0 15px;
text-align: center; text-align: center;
font-weight: bold; font-weight: bold;
border: 1px solid silver; border: 1px solid silver;
background-color: #ececec; background-color: #ececec;
} }
@ -115,6 +115,6 @@
.tab-receiver select[name="rx_refresh_rate"] { .tab-receiver select[name="rx_refresh_rate"] {
float: right; float: right;
margin-right: 20px; margin-right: 20px;
border: 1px solid silver; border: 1px solid silver;
} }

View file

@ -39,7 +39,7 @@
<li class="name">AUX4</li> <li class="name">AUX4</li>
<li class="meter"><meter min="900" max="2100"></meter></li> <li class="meter"><meter min="900" max="2100"></meter></li>
<li class="value"></li> <li class="value"></li>
</ul> </ul>
</div> </div>
<div class="tunings"> <div class="tunings">
<table class="throttle"> <table class="throttle">

View file

@ -1,7 +1,7 @@
function tab_initialize_receiver() { function tab_initialize_receiver() {
ga_tracker.sendAppView('Receiver Page'); ga_tracker.sendAppView('Receiver Page');
GUI.active_tab = 'receiver'; GUI.active_tab = 'receiver';
send_message(MSP_codes.MSP_RC_TUNING, MSP_codes.MSP_RC_TUNING, false, function() { send_message(MSP_codes.MSP_RC_TUNING, MSP_codes.MSP_RC_TUNING, false, function() {
send_message(MSP_codes.MSP_RC, MSP_codes.MSP_RC, false, function() { send_message(MSP_codes.MSP_RC, MSP_codes.MSP_RC, false, function() {
$('#content').load("./tabs/receiver.html", function() { $('#content').load("./tabs/receiver.html", function() {
@ -11,28 +11,28 @@ function tab_initialize_receiver() {
$('.tunings .rate input[name="rate"]').val(RC_tuning.RC_RATE.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 .rate input[name="expo"]').val(RC_tuning.RC_EXPO.toFixed(2));
// Setup plot variables and plot it self // Setup plot variables and plot it self
var samples_i = 300; var samples_i = 300;
RX_plot_data = new Array(8); RX_plot_data = new Array(8);
for (var i = 0; i < 8; i++) { for (var i = 0; i < 8; i++) {
RX_plot_data[i] = new Array(); RX_plot_data[i] = new Array();
} }
for (var i = 0; i <= 300; i++) { for (var i = 0; i <= 300; i++) {
RX_plot_data[0].push([i, 0]); RX_plot_data[0].push([i, 0]);
RX_plot_data[1].push([i, 0]); RX_plot_data[1].push([i, 0]);
RX_plot_data[2].push([i, 0]); RX_plot_data[2].push([i, 0]);
RX_plot_data[3].push([i, 0]); RX_plot_data[3].push([i, 0]);
RX_plot_data[4].push([i, 0]); RX_plot_data[4].push([i, 0]);
RX_plot_data[5].push([i, 0]); RX_plot_data[5].push([i, 0]);
RX_plot_data[6].push([i, 0]); RX_plot_data[6].push([i, 0]);
RX_plot_data[7].push([i, 0]); RX_plot_data[7].push([i, 0]);
} }
e_RX_plot = document.getElementById("RX_plot"); e_RX_plot = document.getElementById("RX_plot");
RX_plot_options = { RX_plot_options = {
title: "Channel width (us)", title: "Channel width (us)",
shadowSize: 0, shadowSize: 0,
@ -50,9 +50,9 @@ function tab_initialize_receiver() {
legend : { legend : {
position: "we", position: "we",
backgroundOpacity: 0 backgroundOpacity: 0
} }
}; };
chrome.storage.local.get('rx_refresh_rate', function(result) { chrome.storage.local.get('rx_refresh_rate', function(result) {
if (typeof result.rx_refresh_rate != 'undefined') { if (typeof result.rx_refresh_rate != 'undefined') {
$('select[name="rx_refresh_rate"]').val(result.rx_refresh_rate).change(); $('select[name="rx_refresh_rate"]').val(result.rx_refresh_rate).change();
@ -60,49 +60,49 @@ function tab_initialize_receiver() {
$('select[name="rx_refresh_rate"]').change(); // start with default value $('select[name="rx_refresh_rate"]').change(); // start with default value
} }
}); });
// UI Hooks // UI Hooks
// curves // curves
$('.tunings .throttle input').change(function() { $('.tunings .throttle input').change(function() {
setTimeout(function() { setTimeout(function() {
var mid = parseFloat($('.tunings .throttle input[name="mid"]').val()); var mid = parseFloat($('.tunings .throttle input[name="mid"]').val());
var expo = parseFloat($('.tunings .throttle input[name="expo"]').val()); var expo = parseFloat($('.tunings .throttle input[name="expo"]').val());
var throttle_curve = $('.throttle_curve canvas').get(0); var throttle_curve = $('.throttle_curve canvas').get(0);
var context = throttle_curve.getContext("2d"); var context = throttle_curve.getContext("2d");
context.clearRect(0, 0, 220, 58); context.clearRect(0, 0, 220, 58);
// math magic by englishman // math magic by englishman
var midx = 220 * mid; var midx = 220 * mid;
var midxl = midx * .5; var midxl = midx * .5;
var midxr = (((220 - midx) * .5) + midx); var midxr = (((220 - midx) * .5) + midx);
var midy = 58 - (midx * (58 / 220)); var midy = 58 - (midx * (58 / 220));
var midyl = 58 - ((58 - midy) * .5 *(expo + 1)); var midyl = 58 - ((58 - midy) * .5 *(expo + 1));
var midyr = (midy / 2) * (expo + 1); var midyr = (midy / 2) * (expo + 1);
context.beginPath(); context.beginPath();
context.moveTo(0, 58); context.moveTo(0, 58);
context.quadraticCurveTo(midxl, midyl, midx, midy); context.quadraticCurveTo(midxl, midyl, midx, midy);
context.moveTo(midx, midy); context.moveTo(midx, midy);
context.quadraticCurveTo(midxr, midyr, 220, 0); context.quadraticCurveTo(midxr, midyr, 220, 0);
context.lineWidth = 2; context.lineWidth = 2;
context.stroke(); context.stroke();
}, 0); // race condition, that should always trigger after all events are processed }, 0); // race condition, that should always trigger after all events are processed
}).change(); }).change();
$('.tunings .rate input').change(function() { $('.tunings .rate input').change(function() {
setTimeout(function() { setTimeout(function() {
var rate = parseFloat($('.tunings .rate input[name="rate"]').val()); var rate = parseFloat($('.tunings .rate input[name="rate"]').val());
var expo = parseFloat($('.tunings .rate input[name="expo"]').val()); var expo = parseFloat($('.tunings .rate input[name="expo"]').val());
var pitch_roll_curve = $('.pitch_roll_curve canvas').get(0); var pitch_roll_curve = $('.pitch_roll_curve canvas').get(0);
var context = pitch_roll_curve.getContext("2d"); var context = pitch_roll_curve.getContext("2d");
context.clearRect(0, 0, 220, 58); context.clearRect(0, 0, 220, 58);
// math magic by englishman // math magic by englishman
var ratey = 58 * rate; var ratey = 58 * rate;
context.beginPath(); context.beginPath();
context.moveTo(0, 58); context.moveTo(0, 58);
context.quadraticCurveTo(110, 58 - ((ratey / 2) * (1 - expo)), 220, 58 - ratey); context.quadraticCurveTo(110, 58 - ((ratey / 2) * (1 - expo)), 220, 58 - ratey);
@ -110,7 +110,7 @@ function tab_initialize_receiver() {
context.stroke(); context.stroke();
}, 0); // race condition, that should always trigger after all events are processed }, 0); // race condition, that should always trigger after all events are processed
}).change(); }).change();
$('a.refresh').click(function() { $('a.refresh').click(function() {
send_message(MSP_codes.MSP_RC_TUNING, MSP_codes.MSP_RC_TUNING, false, function() { send_message(MSP_codes.MSP_RC_TUNING, MSP_codes.MSP_RC_TUNING, false, function() {
// fill in data from RC_tuning // fill in data from RC_tuning
@ -119,21 +119,21 @@ function tab_initialize_receiver() {
$('.tunings .rate input[name="rate"]').val(RC_tuning.RC_RATE.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 .rate input[name="expo"]').val(RC_tuning.RC_EXPO.toFixed(2));
// update visual representation // update visual representation
$('.tunings .throttle input').change(); $('.tunings .throttle input').change();
$('.tunings .rate input').change(); $('.tunings .rate input').change();
}); });
}); });
$('a.update').click(function() { $('a.update').click(function() {
// catch RC_tuning changes // catch RC_tuning changes
RC_tuning.throttle_MID = parseFloat($('.tunings .throttle input[name="mid"]').val()); RC_tuning.throttle_MID = parseFloat($('.tunings .throttle input[name="mid"]').val());
RC_tuning.throttle_EXPO = parseFloat($('.tunings .throttle input[name="expo"]').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_RATE = parseFloat($('.tunings .rate input[name="rate"]').val());
RC_tuning.RC_EXPO = parseFloat($('.tunings .rate input[name="expo"]').val()); RC_tuning.RC_EXPO = parseFloat($('.tunings .rate input[name="expo"]').val());
var RC_tuning_buffer_out = new Array(); var RC_tuning_buffer_out = new Array();
RC_tuning_buffer_out[0] = parseInt(RC_tuning.RC_RATE * 100); RC_tuning_buffer_out[0] = parseInt(RC_tuning.RC_RATE * 100);
RC_tuning_buffer_out[1] = parseInt(RC_tuning.RC_EXPO * 100); RC_tuning_buffer_out[1] = parseInt(RC_tuning.RC_EXPO * 100);
@ -142,57 +142,57 @@ function tab_initialize_receiver() {
RC_tuning_buffer_out[4] = parseInt(RC_tuning.dynamic_THR_PID * 100); RC_tuning_buffer_out[4] = parseInt(RC_tuning.dynamic_THR_PID * 100);
RC_tuning_buffer_out[5] = parseInt(RC_tuning.throttle_MID * 100); RC_tuning_buffer_out[5] = parseInt(RC_tuning.throttle_MID * 100);
RC_tuning_buffer_out[6] = parseInt(RC_tuning.throttle_EXPO * 100); RC_tuning_buffer_out[6] = parseInt(RC_tuning.throttle_EXPO * 100);
// Send over the RC_tuning changes // Send over the RC_tuning changes
send_message(MSP_codes.MSP_SET_RC_TUNING, RC_tuning_buffer_out); send_message(MSP_codes.MSP_SET_RC_TUNING, RC_tuning_buffer_out);
// Save changes to EEPROM // Save changes to EEPROM
send_message(MSP_codes.MSP_EEPROM_WRITE, MSP_codes.MSP_EEPROM_WRITE, false, function() { send_message(MSP_codes.MSP_EEPROM_WRITE, MSP_codes.MSP_EEPROM_WRITE, false, function() {
GUI.log('EEPROM <span style="color: green">saved</span>'); GUI.log('EEPROM <span style="color: green">saved</span>');
var element = $('a.update'); var element = $('a.update');
element.addClass('success'); element.addClass('success');
GUI.timeout_add('success_highlight', function() { GUI.timeout_add('success_highlight', function() {
element.removeClass('success'); element.removeClass('success');
}, 2000); }, 2000);
}); });
}); });
$('select[name="rx_refresh_rate"]').change(function() { $('select[name="rx_refresh_rate"]').change(function() {
var plot_update_rate = parseInt($(this).val()); var plot_update_rate = parseInt($(this).val());
// timer initialization // timer initialization
GUI.interval_remove('receiver_poll'); GUI.interval_remove('receiver_poll');
// enable RC data pulling // enable RC data pulling
GUI.interval_add('receiver_poll', function() { GUI.interval_add('receiver_poll', function() {
// Update UI with latest data // Update UI with latest data
$('.tab-receiver meter:eq(0)').val(RC.throttle); $('.tab-receiver meter:eq(0)').val(RC.throttle);
$('.tab-receiver .value:eq(0)').html(RC.throttle); $('.tab-receiver .value:eq(0)').html(RC.throttle);
$('.tab-receiver meter:eq(1)').val(RC.pitch); $('.tab-receiver meter:eq(1)').val(RC.pitch);
$('.tab-receiver .value:eq(1)').html(RC.pitch); $('.tab-receiver .value:eq(1)').html(RC.pitch);
$('.tab-receiver meter:eq(2)').val(RC.roll); $('.tab-receiver meter:eq(2)').val(RC.roll);
$('.tab-receiver .value:eq(2)').html(RC.roll); $('.tab-receiver .value:eq(2)').html(RC.roll);
$('.tab-receiver meter:eq(3)').val(RC.yaw); $('.tab-receiver meter:eq(3)').val(RC.yaw);
$('.tab-receiver .value:eq(3)').html(RC.yaw); $('.tab-receiver .value:eq(3)').html(RC.yaw);
$('.tab-receiver meter:eq(4)').val(RC.AUX1); $('.tab-receiver meter:eq(4)').val(RC.AUX1);
$('.tab-receiver .value:eq(4)').html(RC.AUX1); $('.tab-receiver .value:eq(4)').html(RC.AUX1);
$('.tab-receiver meter:eq(5)').val(RC.AUX2); $('.tab-receiver meter:eq(5)').val(RC.AUX2);
$('.tab-receiver .value:eq(5)').html(RC.AUX2); $('.tab-receiver .value:eq(5)').html(RC.AUX2);
$('.tab-receiver meter:eq(6)').val(RC.AUX3); $('.tab-receiver meter:eq(6)').val(RC.AUX3);
$('.tab-receiver .value:eq(6)').html(RC.AUX3); $('.tab-receiver .value:eq(6)').html(RC.AUX3);
$('.tab-receiver meter:eq(7)').val(RC.AUX4); $('.tab-receiver meter:eq(7)').val(RC.AUX4);
$('.tab-receiver .value:eq(7)').html(RC.AUX4); $('.tab-receiver .value:eq(7)').html(RC.AUX4);
// push latest data to the main array // push latest data to the main array
RX_plot_data[0].push([samples_i, RC.throttle]); RX_plot_data[0].push([samples_i, RC.throttle]);
RX_plot_data[1].push([samples_i, RC.pitch]); RX_plot_data[1].push([samples_i, RC.pitch]);
@ -201,7 +201,7 @@ function tab_initialize_receiver() {
RX_plot_data[4].push([samples_i, RC.AUX1]); RX_plot_data[4].push([samples_i, RC.AUX1]);
RX_plot_data[5].push([samples_i, RC.AUX2]); RX_plot_data[5].push([samples_i, RC.AUX2]);
RX_plot_data[6].push([samples_i, RC.AUX3]); RX_plot_data[6].push([samples_i, RC.AUX3]);
RX_plot_data[7].push([samples_i, RC.AUX4]); RX_plot_data[7].push([samples_i, RC.AUX4]);
// Remove old data from array // Remove old data from array
while (RX_plot_data[0].length > 300) { while (RX_plot_data[0].length > 300) {
@ -214,10 +214,10 @@ function tab_initialize_receiver() {
RX_plot_data[6].shift(); RX_plot_data[6].shift();
RX_plot_data[7].shift(); RX_plot_data[7].shift();
}; };
// redraw plot // redraw plot
Flotr.draw(e_RX_plot, [ Flotr.draw(e_RX_plot, [
{data: RX_plot_data[0], label: "THROTTLE"}, {data: RX_plot_data[0], label: "THROTTLE"},
{data: RX_plot_data[1], label: "PITCH"}, {data: RX_plot_data[1], label: "PITCH"},
{data: RX_plot_data[2], label: "ROLL"}, {data: RX_plot_data[2], label: "ROLL"},
{data: RX_plot_data[3], label: "YAW"}, {data: RX_plot_data[3], label: "YAW"},
@ -225,17 +225,17 @@ function tab_initialize_receiver() {
{data: RX_plot_data[5], label: "AUX2"}, {data: RX_plot_data[5], label: "AUX2"},
{data: RX_plot_data[6], label: "AUX3"}, {data: RX_plot_data[6], label: "AUX3"},
{data: RX_plot_data[7], label: "AUX4"} ], RX_plot_options); {data: RX_plot_data[7], label: "AUX4"} ], RX_plot_options);
samples_i++; samples_i++;
// Request new data // Request new data
send_message(MSP_codes.MSP_STATUS, MSP_codes.MSP_STATUS); send_message(MSP_codes.MSP_STATUS, MSP_codes.MSP_STATUS);
send_message(MSP_codes.MSP_RC, MSP_codes.MSP_RC); send_message(MSP_codes.MSP_RC, MSP_codes.MSP_RC);
}, plot_update_rate, true); }, plot_update_rate, true);
chrome.storage.local.set({'rx_refresh_rate': plot_update_rate}); chrome.storage.local.set({'rx_refresh_rate': plot_update_rate});
}); });
}); });
}); });
}); });

View file

@ -24,20 +24,20 @@
.tab-sensors #debug4 { .tab-sensors #debug4 {
height: 120px; height: 120px;
} }
.tab-sensors select { .tab-sensors select {
float: right; float: right;
border: 1px solid silver; border: 1px solid silver;
} }
/* Flotr related styles */ /* Flotr related styles */
.flotr-legend { .flotr-legend {
padding: 2px; padding: 2px;
margin-left: 31px; margin-left: 31px;
top: 20px; top: 20px;
border: 0; border: 0;
background-color: white; background-color: white;
opacity: 0.75; opacity: 0.75;
} }

View file

@ -48,7 +48,7 @@
<option value="250">250 ms</option> <option value="250">250 ms</option>
<option value="500">500 ms</option> <option value="500">500 ms</option>
<option value="1000">1000 ms</option> <option value="1000">1000 ms</option>
</select> </select>
<div class="clear-both"></div> <div class="clear-both"></div>
<div id="baro"></div> <div id="baro"></div>
<select title="Debug refresh rate" name="debug_refresh_rate"> <select title="Debug refresh rate" name="debug_refresh_rate">

View file

@ -1,69 +1,69 @@
function tab_initialize_sensors() { function tab_initialize_sensors() {
ga_tracker.sendAppView('Sensor Page'); ga_tracker.sendAppView('Sensor Page');
GUI.active_tab = 'sensors'; GUI.active_tab = 'sensors';
$('#content').load("./tabs/sensors.html", function() { $('#content').load("./tabs/sensors.html", function() {
// Always start with default/empty sensor data array, clean slate all // Always start with default/empty sensor data array, clean slate all
for (var i = 0; i < 3; i++) SENSOR_DATA.accelerometer[i] = 0; for (var i = 0; i < 3; i++) SENSOR_DATA.accelerometer[i] = 0;
for (var i = 0; i < 3; i++) SENSOR_DATA.gyroscope[i] = 0; for (var i = 0; i < 3; i++) SENSOR_DATA.gyroscope[i] = 0;
for (var i = 0; i < 3; i++) SENSOR_DATA.magnetometer[i] = 0; for (var i = 0; i < 3; i++) SENSOR_DATA.magnetometer[i] = 0;
for (var i = 0; i < 4; i++) SENSOR_DATA.debug[i] = 0; for (var i = 0; i < 4; i++) SENSOR_DATA.debug[i] = 0;
// Setup variables // Setup variables
var samples_gyro_i = 300; var samples_gyro_i = 300;
var samples_accel_i = 300; var samples_accel_i = 300;
var samples_mag_i = 300; var samples_mag_i = 300;
var samples_baro_i = 300; var samples_baro_i = 300;
var samples_debug_i = 300; var samples_debug_i = 300;
var gyro_data = new Array(3); var gyro_data = new Array(3);
var accel_data = new Array(3); var accel_data = new Array(3);
var mag_data = new Array(3); var mag_data = new Array(3);
var baro_data = new Array(1); var baro_data = new Array(1);
var debug_data = new Array(4); var debug_data = new Array(4);
gyro_data[0] = new Array(); gyro_data[0] = new Array();
gyro_data[1] = new Array(); gyro_data[1] = new Array();
gyro_data[2] = new Array(); gyro_data[2] = new Array();
accel_data[0] = new Array(); accel_data[0] = new Array();
accel_data[1] = new Array(); accel_data[1] = new Array();
accel_data[2] = new Array(); accel_data[2] = new Array();
mag_data[0] = new Array(); mag_data[0] = new Array();
mag_data[1] = new Array(); mag_data[1] = new Array();
mag_data[2] = new Array(); mag_data[2] = new Array();
baro_data[0] = new Array(); baro_data[0] = new Array();
for (var i = 0; i < 4; i++) debug_data[i] = new Array(); for (var i = 0; i < 4; i++) debug_data[i] = new Array();
for (var i = 0; i <= 300; i++) { for (var i = 0; i <= 300; i++) {
gyro_data[0].push([i, 0]); gyro_data[0].push([i, 0]);
gyro_data[1].push([i, 0]); gyro_data[1].push([i, 0]);
gyro_data[2].push([i, 0]); gyro_data[2].push([i, 0]);
accel_data[0].push([i, 0]); accel_data[0].push([i, 0]);
accel_data[1].push([i, 0]); accel_data[1].push([i, 0]);
accel_data[2].push([i, 0]); accel_data[2].push([i, 0]);
mag_data[0].push([i, 0]); mag_data[0].push([i, 0]);
mag_data[1].push([i, 0]); mag_data[1].push([i, 0]);
mag_data[2].push([i, 0]); mag_data[2].push([i, 0]);
baro_data[0].push([i, 0]); baro_data[0].push([i, 0]);
for (var j = 0; j < 4; j++) debug_data[j].push([i, 0]); for (var j = 0; j < 4; j++) debug_data[j].push([i, 0]);
} }
// plot specific stuff // plot specific stuff
var e_graph_gyro = document.getElementById("gyro"); var e_graph_gyro = document.getElementById("gyro");
var e_graph_accel = document.getElementById("accel"); var e_graph_accel = document.getElementById("accel");
var e_graph_mag = document.getElementById("mag"); var e_graph_mag = document.getElementById("mag");
var e_graph_baro = document.getElementById("baro"); var e_graph_baro = document.getElementById("baro");
var e_graph_debug1 = document.getElementById("debug1"); var e_graph_debug1 = document.getElementById("debug1");
var e_graph_debug2 = document.getElementById("debug2"); var e_graph_debug2 = document.getElementById("debug2");
var e_graph_debug3 = document.getElementById("debug3"); var e_graph_debug3 = document.getElementById("debug3");
var e_graph_debug4 = document.getElementById("debug4"); var e_graph_debug4 = document.getElementById("debug4");
var gyro_options = { var gyro_options = {
title: "Gyroscope (deg/s)", title: "Gyroscope (deg/s)",
shadowSize: 0, shadowSize: 0,
@ -83,7 +83,7 @@ function tab_initialize_sensors() {
backgroundOpacity: 0 backgroundOpacity: 0
} }
}; };
var accel_options = { var accel_options = {
title: "Accelerometer (g)", title: "Accelerometer (g)",
shadowSize: 0, shadowSize: 0,
@ -103,7 +103,7 @@ function tab_initialize_sensors() {
backgroundOpacity: 0 backgroundOpacity: 0
} }
}; };
var mag_options = { var mag_options = {
title: "Magnetometer (Ga)", title: "Magnetometer (Ga)",
shadowSize: 0, shadowSize: 0,
@ -121,7 +121,7 @@ function tab_initialize_sensors() {
backgroundOpacity: 0 backgroundOpacity: 0
} }
}; };
var baro_options = { var baro_options = {
title: "Barometer (meters)", title: "Barometer (meters)",
shadowSize: 0, shadowSize: 0,
@ -157,7 +157,7 @@ function tab_initialize_sensors() {
backgroundOpacity: 0 backgroundOpacity: 0
} }
}; };
var debug2_options = {}; var debug2_options = {};
for (var key in debug1_options) debug2_options[key] = debug1_options[key]; for (var key in debug1_options) debug2_options[key] = debug1_options[key];
debug2_options.title = "Debug2"; debug2_options.title = "Debug2";
@ -169,81 +169,81 @@ function tab_initialize_sensors() {
var debug4_options = {}; var debug4_options = {};
for (var key in debug1_options) debug4_options[key] = debug1_options[key]; for (var key in debug1_options) debug4_options[key] = debug1_options[key];
debug4_options.title = "Debug4"; debug4_options.title = "Debug4";
// set refresh speeds according to configuration saved in storage // set refresh speeds according to configuration saved in storage
chrome.storage.local.get('sensor_refresh_rates', function(result) { chrome.storage.local.get('sensor_refresh_rates', function(result) {
if (typeof result.sensor_refresh_rates != 'undefined') { if (typeof result.sensor_refresh_rates != 'undefined') {
$('.tab-sensors select').eq(0).val(result.sensor_refresh_rates.gyro); // gyro $('.tab-sensors select').eq(0).val(result.sensor_refresh_rates.gyro); // gyro
$('.tab-sensors select').eq(1).val(result.sensor_refresh_rates.accel); // accel $('.tab-sensors select').eq(1).val(result.sensor_refresh_rates.accel); // accel
$('.tab-sensors select').eq(2).val(result.sensor_refresh_rates.mag); // mag $('.tab-sensors select').eq(2).val(result.sensor_refresh_rates.mag); // mag
$('.tab-sensors select').eq(3).val(result.sensor_refresh_rates.baro); // baro $('.tab-sensors select').eq(3).val(result.sensor_refresh_rates.baro); // baro
$('.tab-sensors select').eq(4).val(result.sensor_refresh_rates.debug); // debug $('.tab-sensors select').eq(4).val(result.sensor_refresh_rates.debug); // debug
$('.tab-sensors select').change(); // start polling data by triggering refresh rate change event $('.tab-sensors select').change(); // start polling data by triggering refresh rate change event
} else { } else {
// start polling immediatly (as there is no configuration saved in the storage) // start polling immediatly (as there is no configuration saved in the storage)
$('.tab-sensors select').change(); // start polling data by triggering refresh rate change event $('.tab-sensors select').change(); // start polling data by triggering refresh rate change event
} }
}); });
$('.tab-sensors select').change(function() { $('.tab-sensors select').change(function() {
// if any of the select fields change value, all of the select values are grabbed // if any of the select fields change value, all of the select values are grabbed
// and timers are re-initialized with the new settings // and timers are re-initialized with the new settings
var rates = { var rates = {
'gyro': parseInt($('.tab-sensors select').eq(0).val()), 'gyro': parseInt($('.tab-sensors select').eq(0).val()),
'accel': parseInt($('.tab-sensors select').eq(1).val()), 'accel': parseInt($('.tab-sensors select').eq(1).val()),
'mag': parseInt($('.tab-sensors select').eq(2).val()), 'mag': parseInt($('.tab-sensors select').eq(2).val()),
'baro': parseInt($('.tab-sensors select').eq(3).val()), 'baro': parseInt($('.tab-sensors select').eq(3).val()),
'debug': parseInt($('.tab-sensors select').eq(4).val()) 'debug': parseInt($('.tab-sensors select').eq(4).val())
}; };
// handling of "data pulling" is a little bit funky here, as MSP_RAW_IMU contains values for gyro/accel/mag but not baro // handling of "data pulling" is a little bit funky here, as MSP_RAW_IMU contains values for gyro/accel/mag but not baro
// this means that setting a slower refresh rate on any of the attributes would have no effect // this means that setting a slower refresh rate on any of the attributes would have no effect
// what we will do instead is = determinate the fastest refresh rate for those 3 attributes, use that as a "polling rate" // what we will do instead is = determinate the fastest refresh rate for those 3 attributes, use that as a "polling rate"
// and use the "slower" refresh rates only for re-drawing the graphs (to save resources/computing power) // and use the "slower" refresh rates only for re-drawing the graphs (to save resources/computing power)
var fastest = rates.gyro; var fastest = rates.gyro;
if (rates.accel < fastest) { if (rates.accel < fastest) {
fastest = rates.accel; fastest = rates.accel;
} }
if (rates.mag < fastest) { if (rates.mag < fastest) {
fastest = rates.mag; fastest = rates.mag;
} }
// timer initialization // timer initialization
GUI.interval_kill_all(['port_handler', 'port_usage']); GUI.interval_kill_all(['port_handler', 'port_usage']);
// data pulling timers // data pulling timers
GUI.interval_add('status_pull', function() { GUI.interval_add('status_pull', function() {
send_message(MSP_codes.MSP_STATUS, MSP_codes.MSP_STATUS); send_message(MSP_codes.MSP_STATUS, MSP_codes.MSP_STATUS);
}, 50); }, 50);
GUI.interval_add('IMU_pull', function() { GUI.interval_add('IMU_pull', function() {
send_message(MSP_codes.MSP_RAW_IMU, MSP_codes.MSP_RAW_IMU); send_message(MSP_codes.MSP_RAW_IMU, MSP_codes.MSP_RAW_IMU);
}, fastest); }, fastest);
GUI.interval_add('altitude_pull', function() { GUI.interval_add('altitude_pull', function() {
send_message(MSP_codes.MSP_ALTITUDE, MSP_codes.MSP_ALTITUDE); send_message(MSP_codes.MSP_ALTITUDE, MSP_codes.MSP_ALTITUDE);
baro_data[0].push([samples_baro_i, SENSOR_DATA.altitude]); baro_data[0].push([samples_baro_i, SENSOR_DATA.altitude]);
// Remove old data from array // Remove old data from array
while (baro_data[0].length > 300) { while (baro_data[0].length > 300) {
baro_data[0].shift(); baro_data[0].shift();
} }
Flotr.draw(e_graph_baro, [ Flotr.draw(e_graph_baro, [
{data: baro_data[0], label: "X - meters [" + SENSOR_DATA.altitude.toFixed(2) + "]"} ], baro_options); {data: baro_data[0], label: "X - meters [" + SENSOR_DATA.altitude.toFixed(2) + "]"} ], baro_options);
samples_baro_i++; samples_baro_i++;
}, rates.baro); }, rates.baro);
GUI.interval_add('debug_pull', function() { GUI.interval_add('debug_pull', function() {
send_message(MSP_codes.MSP_DEBUG, MSP_codes.MSP_DEBUG); send_message(MSP_codes.MSP_DEBUG, MSP_codes.MSP_DEBUG);
for (var i = 0; i < 4; i++) { for (var i = 0; i < 4; i++) {
debug_data[i].push([samples_debug_i, SENSOR_DATA.debug[i]]); debug_data[i].push([samples_debug_i, SENSOR_DATA.debug[i]]);
@ -264,68 +264,68 @@ function tab_initialize_sensors() {
samples_debug_i++; samples_debug_i++;
}, rates.debug); }, rates.debug);
// processing timers // processing timers
GUI.interval_add('process_gyro', function() { GUI.interval_add('process_gyro', function() {
gyro_data[0].push([samples_gyro_i, SENSOR_DATA.gyroscope[0]]); gyro_data[0].push([samples_gyro_i, SENSOR_DATA.gyroscope[0]]);
gyro_data[1].push([samples_gyro_i, SENSOR_DATA.gyroscope[1]]); gyro_data[1].push([samples_gyro_i, SENSOR_DATA.gyroscope[1]]);
gyro_data[2].push([samples_gyro_i, SENSOR_DATA.gyroscope[2]]); gyro_data[2].push([samples_gyro_i, SENSOR_DATA.gyroscope[2]]);
// Remove old data from array // Remove old data from array
while (gyro_data[0].length > 300) { while (gyro_data[0].length > 300) {
gyro_data[0].shift(); gyro_data[0].shift();
gyro_data[1].shift(); gyro_data[1].shift();
gyro_data[2].shift(); gyro_data[2].shift();
} }
Flotr.draw(e_graph_gyro, [
{data: gyro_data[0], label: "X - rate [" + SENSOR_DATA.gyroscope[0].toFixed(2) + "]"},
{data: gyro_data[1], label: "Y - rate [" + SENSOR_DATA.gyroscope[1].toFixed(2) + "]"},
{data: gyro_data[2], label: "Z - rate [" + SENSOR_DATA.gyroscope[2].toFixed(2) + "]"} ], gyro_options);
Flotr.draw(e_graph_gyro, [
{data: gyro_data[0], label: "X - rate [" + SENSOR_DATA.gyroscope[0].toFixed(2) + "]"},
{data: gyro_data[1], label: "Y - rate [" + SENSOR_DATA.gyroscope[1].toFixed(2) + "]"},
{data: gyro_data[2], label: "Z - rate [" + SENSOR_DATA.gyroscope[2].toFixed(2) + "]"} ], gyro_options);
samples_gyro_i++; samples_gyro_i++;
}, rates.gyro, true); }, rates.gyro, true);
GUI.interval_add('process_accel', function() { GUI.interval_add('process_accel', function() {
accel_data[0].push([samples_accel_i, SENSOR_DATA.accelerometer[0]]); accel_data[0].push([samples_accel_i, SENSOR_DATA.accelerometer[0]]);
accel_data[1].push([samples_accel_i, SENSOR_DATA.accelerometer[1]]); accel_data[1].push([samples_accel_i, SENSOR_DATA.accelerometer[1]]);
accel_data[2].push([samples_accel_i, SENSOR_DATA.accelerometer[2]]); accel_data[2].push([samples_accel_i, SENSOR_DATA.accelerometer[2]]);
// Remove old data from array // Remove old data from array
while (accel_data[0].length > 300) { while (accel_data[0].length > 300) {
accel_data[0].shift(); accel_data[0].shift();
accel_data[1].shift(); accel_data[1].shift();
accel_data[2].shift(); accel_data[2].shift();
} }
Flotr.draw(e_graph_accel, [ Flotr.draw(e_graph_accel, [
{data: accel_data[1], label: "X - acceleration [" + SENSOR_DATA.accelerometer[0].toFixed(2) + "]"}, {data: accel_data[1], label: "X - acceleration [" + SENSOR_DATA.accelerometer[0].toFixed(2) + "]"},
{data: accel_data[0], label: "Y - acceleration [" + SENSOR_DATA.accelerometer[1].toFixed(2) + "]"}, {data: accel_data[0], label: "Y - acceleration [" + SENSOR_DATA.accelerometer[1].toFixed(2) + "]"},
{data: accel_data[2], label: "Z - acceleration [" + SENSOR_DATA.accelerometer[2].toFixed(2) + "]"} ], accel_options); {data: accel_data[2], label: "Z - acceleration [" + SENSOR_DATA.accelerometer[2].toFixed(2) + "]"} ], accel_options);
samples_accel_i++; samples_accel_i++;
}, rates.accel, true); }, rates.accel, true);
GUI.interval_add('process_mag', function() { GUI.interval_add('process_mag', function() {
mag_data[0].push([samples_mag_i, SENSOR_DATA.magnetometer[0]]); mag_data[0].push([samples_mag_i, SENSOR_DATA.magnetometer[0]]);
mag_data[1].push([samples_mag_i, SENSOR_DATA.magnetometer[1]]); mag_data[1].push([samples_mag_i, SENSOR_DATA.magnetometer[1]]);
mag_data[2].push([samples_mag_i, SENSOR_DATA.magnetometer[2]]); mag_data[2].push([samples_mag_i, SENSOR_DATA.magnetometer[2]]);
// Remove old data from array // Remove old data from array
while (mag_data[0].length > 300) { while (mag_data[0].length > 300) {
mag_data[0].shift(); mag_data[0].shift();
mag_data[1].shift(); mag_data[1].shift();
mag_data[2].shift(); mag_data[2].shift();
} }
Flotr.draw(e_graph_mag, [ Flotr.draw(e_graph_mag, [
{data: mag_data[1], label: "X - Ga [" + SENSOR_DATA.magnetometer[0].toFixed(2) + "]"}, {data: mag_data[1], label: "X - Ga [" + SENSOR_DATA.magnetometer[0].toFixed(2) + "]"},
{data: mag_data[0], label: "Y - Ga [" + SENSOR_DATA.magnetometer[1].toFixed(2) + "]"}, {data: mag_data[0], label: "Y - Ga [" + SENSOR_DATA.magnetometer[1].toFixed(2) + "]"},
{data: mag_data[2], label: "Z - Ga [" + SENSOR_DATA.magnetometer[2].toFixed(2) + "]"} ], mag_options); {data: mag_data[2], label: "Z - Ga [" + SENSOR_DATA.magnetometer[2].toFixed(2) + "]"} ], mag_options);
samples_mag_i++; samples_mag_i++;
}, rates.mag, true); }, rates.mag, true);
// store current/latest refresh rates in the storage // store current/latest refresh rates in the storage
chrome.storage.local.set({'sensor_refresh_rates': rates}); chrome.storage.local.set({'sensor_refresh_rates': rates});
}); });

View file

@ -3,56 +3,56 @@
.tab-servos input[type="number"]::-webkit-inner-spin-button { .tab-servos input[type="number"]::-webkit-inner-spin-button {
border: 0; border: 0;
} }
.tab-servos .supported_wrapper, .tab-servos .supported_wrapper,
.tab-servos .direction_wrapper { .tab-servos .direction_wrapper {
display: none; display: none;
} }
.tab-servos .title { .tab-servos .title {
margin-top: 10px; margin-top: 10px;
line-height: 20px; line-height: 20px;
text-align: center; text-align: center;
font-weight: bold; font-weight: bold;
border: 1px solid #8b8b8b; border: 1px solid #8b8b8b;
border-bottom: 0; border-bottom: 0;
background-color: #ececec; background-color: #ececec;
} }
.tab-servos table.directions td.direction select { .tab-servos table.directions td.direction select {
height: 19px; height: 19px;
line-height: 19px; line-height: 19px;
} }
.tab-servos table { .tab-servos table {
width: 100%; width: 100%;
border-collapse: collapse; border-collapse: collapse;
} }
.tab-servos table th { .tab-servos table th {
line-height: 20px; line-height: 20px;
text-align: center; text-align: center;
border: 1px solid #8b8b8b; border: 1px solid #8b8b8b;
} }
.tab-servos table td { .tab-servos table td {
padding: 1px; padding: 1px;
border: 1px solid #8b8b8b; border: 1px solid #8b8b8b;
} }
.tab-servos table .main { .tab-servos table .main {
font-weight: bold; font-weight: bold;
text-align: center; text-align: center;
background-color: #ececec; background-color: #ececec;
} }
.tab-servos table input[type="number"] { .tab-servos table input[type="number"] {
width: 65px; width: 65px;
height: 20px; height: 20px;
padding-right: 5px; padding-right: 5px;
line-height: 20px; line-height: 20px;
text-align: right; text-align: right;
} }
.tab-servos table .channel input[type="checkbox"]:first-child { .tab-servos table .channel input[type="checkbox"]:first-child {
@ -67,34 +67,34 @@
.tab-servos .direction .name { .tab-servos .direction .name {
float: left; float: left;
display: block; display: block;
width: 60px; width: 60px;
} }
.tab-servos .direction .alternate { .tab-servos .direction .alternate {
float: left; float: left;
display: block; display: block;
width: 60px; width: 60px;
} }
.tab-servos .direction .first { .tab-servos .direction .first {
float: left; float: left;
margin: 2px 10px 0 20px; margin: 2px 10px 0 20px;
} }
.tab-servos .direction .second { .tab-servos .direction .second {
float: left; float: left;
margin: 2px 10px 0 0; margin: 2px 10px 0 0;
} }
.tab-servos .direction .rate { .tab-servos .direction .rate {
width: 200px; width: 200px;
height: 20px; height: 20px;
text-align: center; text-align: center;
} }
.tab-servos .live { .tab-servos .live {
float: left; float: left;
margin-top: 10px; margin-top: 10px;
} }
.tab-servos .live span { .tab-servos .live span {
@ -107,17 +107,17 @@
.tab-servos .update { .tab-servos .update {
display: block; display: block;
float: right; float: right;
margin-top: 10px; margin-top: 10px;
height: 28px; height: 28px;
line-height: 28px; line-height: 28px;
padding: 0 15px 0 15px; padding: 0 15px 0 15px;
text-align: center; text-align: center;
font-weight: bold; font-weight: bold;
border: 1px solid silver; border: 1px solid silver;
background-color: #ececec; background-color: #ececec;
} }

View file

@ -8,7 +8,7 @@
function tab_initialize_servos() { function tab_initialize_servos() {
ga_tracker.sendAppView('Servos'); ga_tracker.sendAppView('Servos');
GUI.active_tab = 'servos'; GUI.active_tab = 'servos';
// request current Servos Config // request current Servos Config
send_message(MSP_codes.MSP_IDENT, MSP_codes.MSP_IDENT, false, function() { send_message(MSP_codes.MSP_IDENT, MSP_codes.MSP_IDENT, false, function() {
send_message(MSP_codes.MSP_SERVO_CONF, MSP_codes.MSP_SERVO_CONF, false, function() { send_message(MSP_codes.MSP_SERVO_CONF, MSP_codes.MSP_SERVO_CONF, false, function() {
@ -16,35 +16,35 @@ function tab_initialize_servos() {
$('#content').load("./tabs/servos.html", function() { $('#content').load("./tabs/servos.html", function() {
// drop previous table // drop previous table
$('div.tab-servos table.fields tr:not(:first)').remove(); $('div.tab-servos table.fields tr:not(:first)').remove();
var model = $('div.tab-servos strong.model'); var model = $('div.tab-servos strong.model');
var supported_models = [1, 4, 5, 8, 14, 20, 21]; var supported_models = [1, 4, 5, 8, 14, 20, 21];
switch (CONFIG.multiType) { switch (CONFIG.multiType) {
case 1: // TRI case 1: // TRI
// looking ok so far // looking ok so far
model.html('TRI'); model.html('TRI');
process_directions('YAW', 5, 0); process_directions('YAW', 5, 0);
process_servos('Yaw Servo', '', 5, false); process_servos('Yaw Servo', '', 5, false);
break; break;
case 4: // BI case 4: // BI
// looking ok so far // looking ok so far
model.html('BI'); model.html('BI');
process_directions('L YAW', 4, 1); process_directions('L YAW', 4, 1);
process_directions('R YAW', 5, 1); process_directions('R YAW', 5, 1);
process_directions('L NICK', 4, 0); process_directions('L NICK', 4, 0);
process_directions('R NICK', 5, 0); process_directions('R NICK', 5, 0);
process_servos('Left Servo', '', 4, false); process_servos('Left Servo', '', 4, false);
process_servos('Right Servo', '', 5, false); process_servos('Right Servo', '', 5, false);
break; break;
case 5: // Gimbal case 5: // Gimbal
// needs to be verified // needs to be verified
model.html('Gimbal'); model.html('Gimbal');
// rate // rate
process_servos('Pitch Servo', '', 0, 2); process_servos('Pitch Servo', '', 0, 2);
process_servos('Roll Servo', '', 1, 2); process_servos('Roll Servo', '', 1, 2);
@ -52,18 +52,18 @@ function tab_initialize_servos() {
case 8: // Flying Wing case 8: // Flying Wing
// looking ok so far // looking ok so far
model.html('Flying Wing'); model.html('Flying Wing');
process_directions('L ROLL', 3, 1); process_directions('L ROLL', 3, 1);
process_directions('R ROLL', 4, 1); process_directions('R ROLL', 4, 1);
process_directions('L NICK', 3, 0); process_directions('L NICK', 3, 0);
process_directions('R NICK', 4, 0); process_directions('R NICK', 4, 0);
process_servos('Left Wing', '', 3, false); process_servos('Left Wing', '', 3, false);
process_servos('Right Wing', '', 4, false); process_servos('Right Wing', '', 4, false);
break; break;
case 14: // Airplane case 14: // Airplane
model.html('Airplane'); model.html('Airplane');
// rate // rate
process_servos('Wing 1', '', 3, 2); process_servos('Wing 1', '', 3, 2);
process_servos('Wing 2', '', 4, 2); process_servos('Wing 2', '', 4, 2);
@ -73,38 +73,38 @@ function tab_initialize_servos() {
case 20: // Dualcopter case 20: // Dualcopter
// looking ok so far // looking ok so far
model.html('Dualcopter'); model.html('Dualcopter');
process_directions('PITCH', 4, 0); process_directions('PITCH', 4, 0);
process_directions('ROLL', 5, 0); process_directions('ROLL', 5, 0);
process_servos('Roll', '', 5, false); process_servos('Roll', '', 5, false);
process_servos('Nick', '', 4, false); process_servos('Nick', '', 4, false);
break; break;
case 21: // Singlecopter case 21: // Singlecopter
// looking ok so far // looking ok so far
model.html('Singlecopter'); model.html('Singlecopter');
process_servos('Right', 'R YAW', 3, true); process_servos('Right', 'R YAW', 3, true);
process_servos('Left', 'L YAW', 4, true); process_servos('Left', 'L YAW', 4, true);
process_servos('Front', 'F YAW', 5, true); process_servos('Front', 'F YAW', 5, true);
process_servos('Rear', 'YAW', 6, true); process_servos('Rear', 'YAW', 6, true);
break; break;
default: default:
model.html("This model doesn't support servos"); model.html("This model doesn't support servos");
// implementation of feature servo_tilt // implementation of feature servo_tilt
if (AUX_CONFIG.indexOf('CAMSTAB') > -1 || AUX_CONFIG.indexOf('CAMTRIG') > -1) { if (AUX_CONFIG.indexOf('CAMSTAB') > -1 || AUX_CONFIG.indexOf('CAMTRIG') > -1) {
// Gimbal on // Gimbal on
// needs to be verified // needs to be verified
model.html('Gimbal / Tilt Servos'); model.html('Gimbal / Tilt Servos');
// rate // rate
process_servos('Pitch Servo', '', 0, 2); process_servos('Pitch Servo', '', 0, 2);
process_servos('Roll Servo', '', 1, 2); process_servos('Roll Servo', '', 1, 2);
} }
} }
// 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, table.fields select, table.fields input').change(function() {
if ($('div.live input').is(':checked')) { if ($('div.live input').is(':checked')) {
@ -112,14 +112,14 @@ function tab_initialize_servos() {
GUI.timeout_add('servos_update', servos_update, 10); GUI.timeout_add('servos_update', servos_update, 10);
} }
}); });
$('a.update').click(function() { $('a.update').click(function() {
// standard check for supported_models + custom implementation for feature servo_tilt // standard check for supported_models + custom implementation for feature servo_tilt
if (supported_models.indexOf(CONFIG.multiType) != -1 || AUX_CONFIG.indexOf('CAMSTAB') > -1 || AUX_CONFIG.indexOf('CAMTRIG') > -1) { if (supported_models.indexOf(CONFIG.multiType) != -1 || AUX_CONFIG.indexOf('CAMSTAB') > -1 || AUX_CONFIG.indexOf('CAMTRIG') > -1) {
servos_update(true); servos_update(true);
} }
}); });
// enable data pulling // enable data pulling
GUI.interval_add('servos_data_poll', function() { GUI.interval_add('servos_data_poll', function() {
send_message(MSP_codes.MSP_STATUS, MSP_codes.MSP_STATUS); send_message(MSP_codes.MSP_STATUS, MSP_codes.MSP_STATUS);
@ -135,24 +135,24 @@ function servos_update(save_to_eeprom) {
$('div.tab-servos table.directions tr:not(".main")').each(function() { $('div.tab-servos table.directions tr:not(".main")').each(function() {
var info = $('select', this).data('info'); var info = $('select', this).data('info');
var val = parseInt($('select', this).val()); var val = parseInt($('select', this).val());
// in this stage we need to know which bitfield and which bitposition needs to be flipped // in this stage we need to know which bitfield and which bitposition needs to be flipped
if (val) SERVO_CONFIG[info.obj].rate = bit_set(SERVO_CONFIG[info.obj].rate, info.bitpos); if (val) SERVO_CONFIG[info.obj].rate = bit_set(SERVO_CONFIG[info.obj].rate, info.bitpos);
else SERVO_CONFIG[info.obj].rate = bit_clear(SERVO_CONFIG[info.obj].rate, info.bitpos); else SERVO_CONFIG[info.obj].rate = bit_clear(SERVO_CONFIG[info.obj].rate, info.bitpos);
}); });
// update the rest // update the rest
$('div.tab-servos table.fields tr:not(".main")').each(function() { $('div.tab-servos table.fields tr:not(".main")').each(function() {
var info = $(this).data('info'); var info = $(this).data('info');
if ($('.middle input', this).is(':disabled')) { if ($('.middle input', this).is(':disabled')) {
var val = $('.channel input:checked', this).index(); var val = $('.channel input:checked', this).index();
SERVO_CONFIG[info.obj].middle = parseInt(val); SERVO_CONFIG[info.obj].middle = parseInt(val);
} else { } else {
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());
@ -160,42 +160,42 @@ function servos_update(save_to_eeprom) {
if ($('.direction input', this).length) { if ($('.direction input', this).length) {
if ($('.direction input:first', this).is(':checked')) SERVO_CONFIG[info.obj].rate = bit_set(SERVO_CONFIG[info.obj].rate, 0); if ($('.direction input:first', this).is(':checked')) SERVO_CONFIG[info.obj].rate = bit_set(SERVO_CONFIG[info.obj].rate, 0);
else SERVO_CONFIG[info.obj].rate = bit_clear(SERVO_CONFIG[info.obj].rate, 0); else SERVO_CONFIG[info.obj].rate = bit_clear(SERVO_CONFIG[info.obj].rate, 0);
if ($('.direction input:last', this).is(':checked')) SERVO_CONFIG[info.obj].rate = bit_set(SERVO_CONFIG[info.obj].rate, 1); if ($('.direction input:last', this).is(':checked')) SERVO_CONFIG[info.obj].rate = bit_set(SERVO_CONFIG[info.obj].rate, 1);
else SERVO_CONFIG[info.obj].rate = bit_clear(SERVO_CONFIG[info.obj].rate, 1); else SERVO_CONFIG[info.obj].rate = bit_clear(SERVO_CONFIG[info.obj].rate, 1);
} else if ($('.direction select', this).length) { } else if ($('.direction select', this).length) {
var val = parseInt($('.direction select', this).val()); var val = parseInt($('.direction select', this).val());
SERVO_CONFIG[info.obj].rate = val; SERVO_CONFIG[info.obj].rate = val;
} }
}); });
// send settings over to mcu // send settings over to mcu
var buffer_out = []; var buffer_out = [];
var needle = 0; var needle = 0;
for (var i = 0; i < SERVO_CONFIG.length; i++) { for (var i = 0; i < SERVO_CONFIG.length; i++) {
buffer_out[needle++] = lowByte(SERVO_CONFIG[i].min); buffer_out[needle++] = lowByte(SERVO_CONFIG[i].min);
buffer_out[needle++] = highByte(SERVO_CONFIG[i].min); buffer_out[needle++] = highByte(SERVO_CONFIG[i].min);
buffer_out[needle++] = lowByte(SERVO_CONFIG[i].max); buffer_out[needle++] = lowByte(SERVO_CONFIG[i].max);
buffer_out[needle++] = highByte(SERVO_CONFIG[i].max); buffer_out[needle++] = highByte(SERVO_CONFIG[i].max);
buffer_out[needle++] = lowByte(SERVO_CONFIG[i].middle); buffer_out[needle++] = lowByte(SERVO_CONFIG[i].middle);
buffer_out[needle++] = highByte(SERVO_CONFIG[i].middle); buffer_out[needle++] = highByte(SERVO_CONFIG[i].middle);
buffer_out[needle++] = lowByte(SERVO_CONFIG[i].rate); buffer_out[needle++] = lowByte(SERVO_CONFIG[i].rate);
} }
send_message(MSP_codes.MSP_SET_SERVO_CONF, buffer_out); send_message(MSP_codes.MSP_SET_SERVO_CONF, buffer_out);
if (save_to_eeprom) { if (save_to_eeprom) {
// Save changes to EEPROM // Save changes to EEPROM
send_message(MSP_codes.MSP_EEPROM_WRITE, MSP_codes.MSP_EEPROM_WRITE, false, function() { send_message(MSP_codes.MSP_EEPROM_WRITE, MSP_codes.MSP_EEPROM_WRITE, false, function() {
GUI.log('EEPROM <span style="color: green">saved</span>'); GUI.log('EEPROM <span style="color: green">saved</span>');
var element = $('a.update'); var element = $('a.update');
element.addClass('success'); element.addClass('success');
GUI.timeout_add('success_highlight', function() { GUI.timeout_add('success_highlight', function() {
element.removeClass('success'); element.removeClass('success');
}, 2000); }, 2000);
@ -205,9 +205,9 @@ function servos_update(save_to_eeprom) {
function process_directions(name, obj, bitpos) { function process_directions(name, obj, bitpos) {
$('div.direction_wrapper').show(); $('div.direction_wrapper').show();
var val; var val;
$('div.tab-servos table.directions').append('\ $('div.tab-servos table.directions').append('\
<tr>\ <tr>\
<td class="name" style="text-align: center">' + name + '</td>\ <td class="name" style="text-align: center">' + name + '</td>\
@ -219,7 +219,7 @@ function process_directions(name, obj, bitpos) {
</td>\ </td>\
</tr>\ </tr>\
'); ');
if (bit_check(SERVO_CONFIG[obj].rate, bitpos)) val = 1; if (bit_check(SERVO_CONFIG[obj].rate, bitpos)) val = 1;
else val = 0; else val = 0;
@ -229,7 +229,7 @@ function process_directions(name, obj, bitpos) {
function process_servos(name, alternate, obj, directions) { function process_servos(name, alternate, obj, directions) {
$('div.supported_wrapper').show(); $('div.supported_wrapper').show();
$('div.tab-servos table.fields').append('\ $('div.tab-servos table.fields').append('\
<tr> \ <tr> \
<td style="text-align: center">' + name + '</td>\ <td style="text-align: center">' + name + '</td>\
@ -251,40 +251,40 @@ function process_servos(name, alternate, obj, directions) {
<input class="second" type="checkbox"/><span class="alternate">' + alternate + '</span>\ <input class="second" type="checkbox"/><span class="alternate">' + alternate + '</span>\
</td>\ </td>\
</tr> \ </tr> \
'); ');
if (SERVO_CONFIG[obj].middle <= 7) { if (SERVO_CONFIG[obj].middle <= 7) {
$('div.tab-servos table.fields tr:last td.middle input').prop('disabled', true); $('div.tab-servos table.fields tr:last td.middle input').prop('disabled', true);
$('div.tab-servos table.fields tr:last td.channel').find('input').eq(SERVO_CONFIG[obj].middle).prop('checked', true); $('div.tab-servos table.fields tr:last td.channel').find('input').eq(SERVO_CONFIG[obj].middle).prop('checked', true);
} }
if (directions == true) { if (directions == true) {
$('div.tab-servos table.fields tr:last td.direction input:first').prop('checked', bit_check(SERVO_CONFIG[obj].rate, 0)); $('div.tab-servos table.fields tr:last td.direction input:first').prop('checked', bit_check(SERVO_CONFIG[obj].rate, 0));
$('div.tab-servos table.fields tr:last td.direction input:last').prop('checked', bit_check(SERVO_CONFIG[obj].rate, 1)); $('div.tab-servos table.fields tr:last td.direction input:last').prop('checked', bit_check(SERVO_CONFIG[obj].rate, 1));
} else if (directions == 2) { } else if (directions == 2) {
// removing checkboxes // removing checkboxes
$('div.tab-servos table.fields tr:last td.direction').html(''); $('div.tab-servos table.fields tr:last td.direction').html('');
// adding select box and generating options // adding select box and generating options
$('div.tab-servos table.fields tr:last td.direction').append('\ $('div.tab-servos table.fields tr:last td.direction').append('\
<select class="rate" name="rate"></select>\ <select class="rate" name="rate"></select>\
'); ');
var select = $('div.tab-servos table.fields tr:last td.direction select'); var select = $('div.tab-servos table.fields tr:last td.direction select');
for (var i = 100; i > -101; i--) { for (var i = 100; i > -101; i--) {
select.append('<option value="' + i + '">Rate: ' + i + '%</option>'); select.append('<option value="' + i + '">Rate: ' + i + '%</option>');
} }
// select current rate // select current rate
select.val(SERVO_CONFIG[obj].rate); select.val(SERVO_CONFIG[obj].rate);
} else { } else {
// removing checkboxes // removing checkboxes
$('div.tab-servos table.fields tr:last td.direction').html(''); $('div.tab-servos table.fields tr:last td.direction').html('');
} }
$('div.tab-servos table.fields tr:last').data('info', {'obj': obj}); $('div.tab-servos table.fields tr:last').data('info', {'obj': obj});
// UI hooks // UI hooks
$('div.tab-servos table.fields tr:last td.channel').find('input').click(function() { $('div.tab-servos table.fields tr:last td.channel').find('input').click(function() {
if($(this).is(':checked')) { if($(this).is(':checked')) {