1
0
Fork 0
mirror of https://github.com/betaflight/betaflight.git synced 2025-07-23 08:15:30 +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

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

View file

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

104
js/gui.js
View file

@ -6,7 +6,7 @@ var GUI_control = function() {
this.operating_system;
this.interval_array = [];
this.timeout_array = [];
// check which operating system is user running
if (navigator.appVersion.indexOf("Win") != -1) this.operating_system = "Windows";
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
GUI_control.prototype.interval_add = function(name, code, interval, first) {
var data = {'name': name, 'timer': undefined, 'code': code, 'interval': interval, 'fired': 0, 'paused': false};
if (first == true) {
code(); // execute code
data.fired++; // increment counter
}
data.timer = setInterval(function() {
code(); // execute code
data.fired++; // increment counter
}, interval);
this.interval_array.push(data); // push to primary interval array
};
@ -44,13 +44,13 @@ GUI_control.prototype.interval_remove = function(name) {
for (var i = 0; i < this.interval_array.length; i++) {
if (this.interval_array[i].name == name) {
clearInterval(this.interval_array[i].timer); // stop timer
this.interval_array.splice(i, 1); // remove element/object from array
return true;
}
}
return false;
};
@ -60,11 +60,11 @@ GUI_control.prototype.interval_pause = function(name) {
if (this.interval_array[i].name == name) {
clearInterval(this.interval_array[i].timer);
this.interval_array[i].paused = true;
return true;
}
}
return false;
};
@ -73,19 +73,19 @@ GUI_control.prototype.interval_resume = function(name) {
for (var i = 0; i < this.interval_array.length; i++) {
if (this.interval_array[i].name == name && this.interval_array[i].paused) {
var obj = this.interval_array[i];
obj.timer = setInterval(function() {
obj.code(); // execute code
obj.fired++; // increment counter
}, obj.interval);
obj.paused = false;
return true;
}
}
return false;
};
@ -94,7 +94,7 @@ GUI_control.prototype.interval_resume = function(name) {
GUI_control.prototype.interval_kill_all = function(keep_array) {
var self = this;
var timers_killed = 0;
for (var i = (this.interval_array.length - 1); i >= 0; i--) { // reverse iteration
var keep = false;
if (keep_array) { // only run through the array if it exists
@ -104,17 +104,17 @@ GUI_control.prototype.interval_kill_all = function(keep_array) {
}
});
}
if (!keep) {
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.splice(i, 1); // remove element/object from array
timers_killed++;
}
}
return timers_killed;
};
@ -126,10 +126,10 @@ GUI_control.prototype.timeout_add = function(name, code, timeout) {
// start timer with "cleaning" callback
var timer = setTimeout(function() {
code(); // execute code
self.timeout_remove(name); // cleanup
}, timeout);
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++) {
if (this.timeout_array[i].name == name) {
clearTimeout(this.timeout_array[i].timer); // stop timer
this.timeout_array.splice(i, 1); // remove element/object from array
return true;
}
}
return false;
};
@ -152,15 +152,15 @@ GUI_control.prototype.timeout_remove = function(name) {
// return = returns timers killed in last call
GUI_control.prototype.timeout_kill_all = function() {
var timers_killed = 0;
for (var i = 0; i < this.timeout_array.length; i++) {
clearTimeout(this.timeout_array[i].timer); // stop timer
timers_killed++;
}
this.timeout_array = []; // drop objects
return timers_killed;
};
@ -168,12 +168,12 @@ GUI_control.prototype.timeout_kill_all = function() {
GUI_control.prototype.log = function(message) {
var command_log = $('div#log');
var d = new Date();
var time = ((d.getHours() < 10) ? '0' + d.getHours(): d.getHours())
+ ':' + ((d.getMinutes() < 10) ? '0' + d.getMinutes(): d.getMinutes())
var time = ((d.getHours() < 10) ? '0' + d.getHours(): d.getHours())
+ ':' + ((d.getMinutes() < 10) ? '0' + d.getMinutes(): d.getMinutes())
+ ':' + ((d.getSeconds() < 10) ? '0' + d.getSeconds(): d.getSeconds());
$('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
@ -181,56 +181,56 @@ GUI_control.prototype.log = function(message) {
// default switch doesn't require callback to be set
GUI_control.prototype.tab_switch_cleanup = function(callback) {
MSP.callbacks_cleanup(); // we don't care about any old data that might or might not arrive
switch (this.active_tab) {
case 'initial_setup':
GUI.interval_remove('initial_setup_data_pull');
if (callback) callback();
break;
case 'pid_tuning':
GUI.interval_remove('pid_data_poll');
if (callback) callback();
break;
case 'receiver':
GUI.interval_remove('receiver_poll');
if (callback) callback();
break;
case 'auxiliary_configuration':
GUI.interval_remove('aux_data_poll');
if (callback) callback();
break;
case 'servos':
GUI.interval_remove('servos_data_poll');
if (callback) callback();
break;
case 'gps':
GUI.interval_remove('gps_pull');
if (callback) callback();
break;
case 'motor_outputs':
GUI.interval_remove('motor_poll');
// only enforce mincommand if necessary
if (MOTOR_DATA != undefined) {
var update = false;
for (var i = 0; i < MOTOR_DATA.length; i++) {
if (MOTOR_DATA[i] > MISC.mincommand) {
update = true;
break;
}
}
if (update) {
// send data to mcu
var buffer_out = [];
for (var i = 0; i < 8; i++) {
buffer_out.push(lowByte(MISC.mincommand));
buffer_out.push(highByte(MISC.mincommand));
@ -249,17 +249,17 @@ GUI_control.prototype.tab_switch_cleanup = function(callback) {
case 'sensors':
GUI.interval_kill_all(['port_usage']);
serial.empty_output_buffer();
// 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
$('#content').empty();
if (callback) callback();
break;
case 'cli':
var bufferOut = new ArrayBuffer(5);
var bufView = new Uint8Array(bufferOut);
bufView[0] = 0x65; // e
bufView[1] = 0x78; // x
bufView[2] = 0x69; // i
@ -274,18 +274,18 @@ GUI_control.prototype.tab_switch_cleanup = function(callback) {
GUI.timeout_add('waiting_for_bootup', function() {
CLI_active = false;
CLI_valid = false;
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
});
break;
case 'firmware_flasher':
PortHandler.flush_callbacks();
if (callback) callback();
break;
default:
if (callback) callback();
}

188
js/msp.js
View file

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

View file

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

View file

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

View file

@ -2,55 +2,55 @@ var configuration_received = false;
var CLI_active = false;
var CLI_valid = false;
$(document).ready(function() {
$(document).ready(function() {
$('div#port-picker a.connect').click(function() {
if (GUI.connect_lock != true) { // GUI control overrides the user control
var clicks = $(this).data('clicks');
var selected_port = String($('div#port-picker .port select').val());
var selected_baud = parseInt($('div#port-picker #baud').val());
if (selected_port != '0') {
if (!clicks) {
console.log('Connecting to: ' + selected_port);
GUI.connecting_to = selected_port;
// 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 a.connect').text('Connecting');
$('div#port-picker a.connect').text('Connecting');
serial.connect(selected_port, {bitrate: selected_baud}, onOpen);
} else {
// Disable any active "data pulling" timer
GUI.interval_kill_all();
GUI.tab_switch_cleanup();
GUI.timeout_remove('connecting');
serial.disconnect(onClosed);
GUI.connected_to = false;
// Reset various UI elements
$('span.port-usage').html('0%');
$('.software-version').html('0.0');
$('span.cycle-time').html('0');
MSP.disconnect_cleanup();
configuration_received = false; // reset valid config received variable (used to block tabs while not connected properly)
// unlock port select & baud
$('div#port-picker #port').prop('disabled', false);
if (!GUI.auto_connect) $('div#port-picker #baud').prop('disabled', false);
$(this).text('Connect');
$(this).removeClass('active');
sensor_status(sensors_detected = 0); // reset active sensor indicators
$('#tabs > ul li').removeClass('active'); // de-select any selected tabs
tab_initialize_default();
}
$(this).data("clicks", !clicks);
}
}
@ -61,62 +61,62 @@ $(document).ready(function() {
if (typeof result.auto_connect === 'undefined') {
// auto_connect wasn't saved yet, save and push true to the GUI
GUI.auto_connect = 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');
$('select#baud').val(115200).prop('disabled', true);
// save
chrome.storage.local.set({'auto_connect': true});
} else {
if (result.auto_connect) {
if (result.auto_connect) {
// enabled by user
GUI.auto_connect = 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');
$('select#baud').val(115200).prop('disabled', true);
} else {
} else {
// disabled by user
GUI.auto_connect = 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');
}
}
// bind UI hook to auto-connect checkbos
$('input.auto_connect').change(function() {
GUI.auto_connect = $(this).is(':checked');
// update title/tooltip
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');
$('select#baud').val(115200).prop('disabled', true);
} 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');
if (!GUI.connected_to && !GUI.connecting_to) $('select#baud').prop('disabled', false);
}
chrome.storage.local.set({'auto_connect': GUI.auto_connect});
});
});
PortHandler.initialize();
});
});
function onOpen(openInfo) {
function onOpen(openInfo) {
if (openInfo) {
// update connected_to
GUI.connected_to = GUI.connecting_to;
// reset connecting_to
GUI.connecting_to = false;
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
chrome.storage.local.get('last_used_port', function(result) {
if (typeof result.last_used_port != 'undefined') {
@ -138,12 +138,12 @@ function onOpen(openInfo) {
serial.onReceive.addListener(read_serial);
GUI.interval_add('port_usage', port_usage, 1000, true);
// disconnect after 10 seconds with error if we don't get IDENT data
GUI.timeout_add('connecting', function() {
if (!configuration_received) {
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
}
}, 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>');
send_message(MSP_codes.MSP_IDENT, MSP_codes.MSP_IDENT, false, function() {
GUI.timeout_remove('connecting'); // kill connecting timer
if (CONFIG.version >= firmware_version_accepted) {
// Update UI elements that doesn't need consistent refreshing
$('.software-version').html(CONFIG.version);
configuration_received = true;
$('div#port-picker a.connect').text('Disconnect').addClass('active');
$('#tabs li a:first').click();
@ -170,13 +170,13 @@ function onOpen(openInfo) {
} else {
console.log('Failed to open serial port');
GUI.log('Failed to open serial port', 'red');
$('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
$('div#port-picker #port, div#port-picker #baud, div#port-picker #delay').prop('disabled', false);
// reset data
$('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');
} else { // Something went wrong
GUI.log('<span style="color: red">Failed</span> to close serial port');
}
}
}
function read_serial(info) {
@ -199,7 +199,7 @@ function read_serial(info) {
}
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) + '%');
// reset counter
@ -211,11 +211,11 @@ function sensor_status(sensors_detected) {
if (typeof sensor_status.previous_sensors_detected == 'undefined') {
sensor_status.previous_sensors_detected = 0;
}
// update UI (if necessary)
if (sensor_status.previous_sensors_detected != sensors_detected) {
var e_sensor_status = $('div#sensor-status');
if (bit_check(sensors_detected, 0)) { // Gyroscope & accel detected
$('.gyro', 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');
} else {
$('.baro', e_sensor_status).removeClass('on');
}
}
if (bit_check(sensors_detected, 2)) { // Magnetometer detected
$('.mag', e_sensor_status).addClass('on');
} else {
$('.mag', e_sensor_status).removeClass('on');
}
}
if (bit_check(sensors_detected, 3)) { // GPS detected
$('.gps', e_sensor_status).addClass('on');
} else {
$('.gps', e_sensor_status).removeClass('on');
}
}
if (bit_check(sensors_detected, 4)) { // Sonar detected
$('.sonar', e_sensor_status).addClass('on');
} else {
$('.sonar', e_sensor_status).removeClass('on');
}
// set current value
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
From 921600 down to 1200, i don't recommend getting any lower then that
Official "specs" are from 115200 to 1200
@ -7,20 +7,20 @@
var STM32_protocol = function() {
this.hex; // ref
this.verify_hex;
this.receive_buffer;
this.bytes_to_read = 0; // ref
this.read_callback; // ref
this.upload_time_start;
this.upload_process_alive;
this.status = {
ACK: 0x79, // y
NACK: 0x1F
};
this.command = {
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
@ -35,7 +35,7 @@ var STM32_protocol = function() {
readout_protect: 0x82, // Enables 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.
};
@ -48,14 +48,14 @@ STM32_protocol.prototype.GUI_status = function(string) {
STM32_protocol.prototype.connect = function(hex) {
var self = this;
self.hex = hex;
var selected_port = String($('div#port-picker .port select').val());
var baud = parseInt($('div#port-picker #baud').val());
if (selected_port != '0') {
// popular choices - 921600, 460800, 256000, 230400, 153600, 128000, 115200, 57600, 38400, 28800, 19200
var flashing_bitrate;
switch (GUI.operating_system) {
case 'Windows':
flashing_bitrate = 921600;
@ -68,11 +68,11 @@ STM32_protocol.prototype.connect = function(hex) {
case 'UNIX':
flashing_bitrate = 921600;
break;
default:
flashing_bitrate = 115200;
}
if (!$('input.updating').is(':checked')) {
serial.connect(selected_port, {bitrate: baud}, function(openInfo) {
if (openInfo) {
@ -80,17 +80,17 @@ STM32_protocol.prototype.connect = function(hex) {
// we are connected, disabling connect button in the UI
GUI.connect_lock = true;
var bufferOut = new ArrayBuffer(1);
var bufferView = new Uint8Array(bufferOut);
bufferView[0] = 0x52;
serial.send(bufferOut, function() {
serial.disconnect(function(result) {
if (result) {
if (result) {
serial.connect(selected_port, {bitrate: flashing_bitrate, parityBit: 'even', stopBits: 'one'}, function(openInfo) {
if (openInfo) {
if (openInfo) {
self.initialize();
} else {
GUI.log('<span style="color: red">Failed</span> to open serial port');
@ -107,10 +107,10 @@ STM32_protocol.prototype.connect = function(hex) {
});
} else {
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
GUI.connect_lock = true;
self.initialize();
} else {
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
STM32_protocol.prototype.initialize = function() {
var self = this;
// reset and set some variables before we start
// reset and set some variables before we start
self.receive_buffer = [];
self.verify_hex = [];
self.upload_time_start = microtime();
self.upload_process_alive = false;
// reset progress bar to initial state
self.progress_bar_e = $('.progress');
self.progress_bar_e.val(0);
@ -142,42 +142,42 @@ STM32_protocol.prototype.initialize = function() {
serial.onReceive.addListener(function(info) {
self.read(info);
});
GUI.interval_add('STM32_timeout', function() {
if (self.upload_process_alive) { // process is running
self.upload_process_alive = false;
} else {
console.log('STM32 - timed out, programming failed ...');
STM32.GUI_status('STM32 - timed out, programming: <strong style="color: red">FAILED</strong>');
// protocol got stuck, clear timer and disconnect
GUI.interval_remove('STM32_timeout');
// exit
self.upload_procedure(99);
}
}, 1000);
self.upload_procedure(1);
};
// no input parameters
// 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
var data = new Uint8Array(readInfo.data);
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
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
this.receive_buffer.splice(0, this.bytes_to_read); // remove read bytes
this.bytes_to_read = 0; // reset trigger
this.read_callback(data);
}
};
@ -188,7 +188,7 @@ STM32_protocol.prototype.retrieve = function(n_bytes, callback) {
// data that we need are there, process immediately
var data = this.receive_buffer.slice(0, n_bytes);
this.receive_buffer.splice(0, n_bytes); // remove read bytes
callback(data);
} else {
// 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) {
// flip flag
this.upload_process_alive = true;
var bufferOut = new ArrayBuffer(Array.length);
var bufferView = new Uint8Array(bufferOut);
// set Array values inside bufferView (alternative to for loop)
bufferView.set(Array);
// update references
this.bytes_to_read = bytes_to_read;
this.read_callback = callback;
// empty receive buffer before next command is out
this.receive_buffer = [];
// 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)
// result = true/false
STM32_protocol.prototype.verify_response = function(val, data) {
if (val != 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]);
// disconnect
this.upload_procedure(99);
return false;
}
return true;
};
@ -242,7 +242,7 @@ STM32_protocol.prototype.verify_response = function(val, data) {
// result = true/false
STM32_protocol.prototype.verify_chip_signature = function(signature) {
var available_flash_size = 0;
switch (signature) {
case 0x412: // not tested
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');
break;
}
if (available_flash_size > 0) {
if (this.hex.bytes_total < available_flash_size) {
return true;
} else {
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;
}
}
}
console.log('Chip NOT recognized: ' + signature);
return false;
};
@ -323,16 +323,16 @@ STM32_protocol.prototype.verify_flash = function(first_array, second_array) {
return false;
}
}
console.log('Verification successful, matching: ' + first_array.length + ' bytes');
return true;
};
// step = value depending on current state of upload_procedure
STM32_protocol.prototype.upload_procedure = function(step) {
var self = this;
switch (step) {
case 1:
// 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) {
GUI.interval_remove('stm32_initialize_mcu');
console.log('STM32 - Serial interface initialized on the MCU side');
// proceed to next step
self.upload_procedure(2);
} else {
GUI.interval_remove('stm32_initialize_mcu');
STM32.GUI_status('STM32 Communication with bootloader <span style="color: red">failed</span>');
// disconnect
self.upload_procedure(99);
}
});
if (send_counter++ > 3) {
// stop retrying, its too late to get any response from 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)) {
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
// proceed to next step
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]
var signature = (data[0] << 8) | data[1];
console.log('STM32 - Signature: 0x' + signature.toString(16)); // signature in hex representation
if (self.verify_chip_signature(signature)) {
// proceed to next step
self.upload_procedure(4);
@ -396,7 +396,7 @@ STM32_protocol.prototype.upload_procedure = function(step) {
// erase memory
console.log('Executing global chip erase');
STM32.GUI_status('Erasing');
self.send([self.command.erase, 0xBC], 1, function(reply) { // 0x43 ^ 0xFF
if (self.verify_response(self.status.ACK, 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('Writing data ...');
STM32.GUI_status('<span style="color: green">Flashing ...</span>');
// 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 flashing_block = 0;
var address = self.hex.data[flashing_block].address;
var bytes_flashed = 0;
var bytes_flashed_total = 0; // used for progress bar
var write = function() {
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);
// 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
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
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];
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)) {
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)
var checksum = array_out[0];
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
checksum ^= self.hex.data[flashing_block].data[bytes_flashed];
bytes_flashed++;
}
array_out[array_out.length - 1] = checksum; // checksum (last byte in the array_out array)
address += 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)) {
// update progress bar
self.progress_bar_e.val(bytes_flashed_total / (self.hex.bytes_total * 2) * 100);
// flash another page
write();
}
@ -467,23 +467,23 @@ STM32_protocol.prototype.upload_procedure = function(step) {
// move to another block
if (flashing_block < blocks) {
flashing_block++;
address = self.hex.data[flashing_block].address;
bytes_flashed = 0;
write();
} else {
// all blocks flashed
console.log('Writing: done');
console.log('Verifying data ...');
STM32.GUI_status('<span style="color: green">Verifying ...</span>');
// proceed to next step
self.upload_procedure(6);
}
}
};
// start writing
write();
break;
@ -492,44 +492,44 @@ STM32_protocol.prototype.upload_procedure = function(step) {
var blocks = self.hex.data.length - 1;
var reading_block = 0;
var address = self.hex.data[reading_block].address;
var bytes_verified = 0;
var bytes_verified_total = 0; // used for progress bar
// initialize arrays
for (var i = 0; i <= blocks; i++) {
self.verify_hex.push([]);
}
var reading = function() {
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);
// 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
if (self.verify_response(self.status.ACK, reply)) {
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];
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)) {
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)
if (self.verify_response(self.status.ACK, reply)) {
self.retrieve(bytes_to_read, function(data) {
for (var i = 0; i < data.length; i++) {
self.verify_hex[reading_block].push(data[i]);
}
address += bytes_to_read;
bytes_verified += bytes_to_read;
bytes_verified_total += bytes_to_read;
// 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
reading();
});
@ -543,44 +543,44 @@ STM32_protocol.prototype.upload_procedure = function(step) {
// move to another block
if (reading_block < blocks) {
reading_block++;
address = self.hex.data[reading_block].address;
bytes_verified = 0;
reading();
} else {
// all blocks read, verify
var verify = true;
for (var i = 0; i <= blocks; i++) {
verify = self.verify_flash(self.hex.data[i].data, self.verify_hex[i]);
if (!verify) break;
}
if (verify) {
console.log('Programming: SUCCESSFUL');
STM32.GUI_status('Programming: <strong style="color: green">SUCCESSFUL</strong>');
// update progress bar
self.progress_bar_e.addClass('valid');
// proceed to next step
self.upload_procedure(7);
self.upload_procedure(7);
} else {
console.log('Programming: FAILED');
STM32.GUI_status('Programming: <strong style="color: red">FAILED</strong>');
// update progress bar
self.progress_bar_e.addClass('invalid');
// disconnect
self.upload_procedure(99);
self.upload_procedure(99);
}
}
}
};
// start reading
reading();
break;
@ -594,7 +594,7 @@ STM32_protocol.prototype.upload_procedure = function(step) {
var gt_address = 0x8000000;
var address = [(gt_address >> 24), (gt_address >> 16), (gt_address >> 8), gt_address];
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) {
if (self.verify_response(self.status.ACK, reply)) {
// disconnect
@ -607,15 +607,15 @@ STM32_protocol.prototype.upload_procedure = function(step) {
case 99:
// disconnect
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');
// close connection
serial.disconnect(function(result) {
if (result) { // All went as expected
} else { // Something went wrong
}
// unlocking connect button
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
function read_hex_file(data) {
data = data.split("\n");
// check if there is an empty line in the end of hex file, if there is, remove it
if (data[data.length - 1] == "") {
data.pop();
}
var hexfile_valid = true; // if any of the crc checks failed, this variable flips to false
var result = {
data: [],
end_of_file: false,
bytes_total: 0,
start_linear_address: 0
};
var extended_linear_address = 0;
var next_address = 0;
for (var i = 0; i < data.length && hexfile_valid; i++) {
// each byte is represnted by two chars
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 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)
switch (record_type) {
case 0x00: // data record
case 0x00: // data record
if (address != next_address || next_address == 0) {
result.data.push({'address': extended_linear_address + address, 'bytes': 0, 'data': []});
}
// store address for next comparison
next_address = address + byte_count;
// process data
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
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;
result.data[data_block].data.push(num);
result.data[data_block].bytes++;
result.data[data_block].bytes++;
crc += num;
result.bytes_total++;
}
// change crc to 2's complement
crc = (~crc + 1) & 0xFF;
// verify
// verify
if (crc != checksum) {
hexfile_valid = false;
}
@ -82,7 +82,7 @@ function read_hex_file(data) {
break;
}
}
if (result.end_of_file && hexfile_valid) {
postMessage(result);
} else {
@ -98,11 +98,11 @@ function microtime() {
onmessage = function(event) {
var time_parsing_start = microtime(); // track time
read_hex_file(event.data);
console.log('HEX_PARSER - File parsed in: ' + (microtime() - time_parsing_start).toFixed(4) + ' seconds');
// terminate worker
close();
};