diff --git a/_locales/en/messages.json b/_locales/en/messages.json
index f38f80d8..969a1a0a 100755
--- a/_locales/en/messages.json
+++ b/_locales/en/messages.json
@@ -12,7 +12,7 @@
"options_improve_configurator": {
"message": "Send anonymous usage data to the developer team"
},
-
+
"connect": {
"message": "Connect"
},
@@ -41,7 +41,7 @@
"backupFileIncompatible": {
"message": "Backup file provided was generated for previous version of the configurator and is incompatible with this version of configurator. Sorry"
},
-
+
"backupFileUnmigratable": {
"message": "Backup file provided was generated by a previous version of the configurator and is not migratable. Sorry."
},
@@ -102,14 +102,16 @@
"tabLogging": {
"message": "Logging"
},
-
+ "tabDataflash": {
+ "message": "Dataflash"
+ },
"tabAdjustments": {
"message": "Adjustments"
},
"tabAuxiliary": {
"message": "Modes"
},
-
+
"serialPortOpened": {
"message": "Serial port successfully opened with ID: $1"
},
@@ -122,21 +124,21 @@
"serialPortClosedFail": {
"message": "Failed to close serial port"
},
-
+
"noConfigurationReceived": {
"message": "No configuration received within 10 seconds , communication failed "
},
"firmwareVersionNotSupported": {
"message": "This firmware version is not supported . Please upgrade to firmware that supports api version $1 or higher. Use CLI for backup before flashing. CLI backup/restore procedure is in the documention."
},
-
+
"tabSwitchConnectionRequired": {
"message": "You need to connect before you can view any of the tabs."
},
"tabSwitchWaitForOperation": {
"message": "You can't do this right now, please wait for current operation to finish ..."
- },
-
+ },
+
"tabSwitchUpgradeRequired": {
"message": "You need to upgrade your firmware before you can use the $1 tab."
},
@@ -352,6 +354,9 @@
"initialSetupGPSHead": {
"message": "GPS"
},
+ "initialSetupInstrumentsHead": {
+ "message": "Instruments"
+ },
"initialSetupButtonSave": {
"message": "Save"
},
@@ -402,7 +407,7 @@
},
"configurationFailsafe": {
"message": "Receiver failsafe"
- },
+ },
"configurationRSSI": {
"message": "RSSI (Signal Strength)"
},
@@ -412,7 +417,7 @@
"configurationFeaturesHelp": {
"message": "Note: Not all combinations of features are valid. When the flight controller firmware detects invalid feature combinations conflicting features will be disabled.Note: Configure serial ports before enabling the features that will use the ports."
},
-
+
"configurationBoardAlignment": {
"message": "Board Alignment"
},
@@ -703,7 +708,7 @@
"adjustmentsEepromSaved": {
"message": "EEPROM saved "
},
-
+
"servosModel": {
"message": "Model:"
@@ -843,7 +848,46 @@
"message": "Automatically loaded previous log file: $1 "
},
- "firmwareFlasherReleaseSummaryHead": {
+ "dataflashNote": {
+ "message": "Blackbox flight logs can be recorded to your flight controller's onboard dataflash chip."
+ },
+ "dataflashNotSupportedNote": {
+ "message": "Your flight controller does not have a compatible dataflash chip available."
+ },
+ "dataflashButtonSaveFile": {
+ "message": "Save flash to file..."
+ },
+ "dataflashButtonErase": {
+ "message": "Erase flash"
+ },
+ "dataflashConfirmEraseTitle": {
+ "message": "Confirm dataflash erase"
+ },
+ "dataflashConfirmEraseNote": {
+ "message": "This will erase any Blackbox logs or other data contained in the dataflash which will take about 20 seconds, are you sure?"
+ },
+ "dataflashSavingTitle": {
+ "message": "Saving dataflash to file"
+ },
+ "dataflashSavingNote": {
+ "message": "Saving could take several minutes, please wait."
+ },
+ "dataflashSavingNoteAfter": {
+ "message": "Save completed! Press \"Ok\" to continue."
+ },
+ "dataflashButtonSaveCancel": {
+ "message": "Cancel"
+ },
+ "dataflashButtonSaveDismiss": {
+ "message": "Ok"
+ },
+ "dataflashButtonEraseConfirm": {
+ "message": "Yes, erase dataflash"
+ },
+ "dataflashButtonEraseCancel": {
+ "message": "Cancel"
+ },
+ "firmwareFlasherReleaseSummaryHead": {
"message": "Release info"
},
"firmwareFlasherReleaseName": {
@@ -876,7 +920,7 @@
"firmwareFlasherTargetWarning": {
"message": "IMPORTANT : Ensure you flash a file appropriate for your target. Flashing a binary for the wrong target can cause bad things to happen."
},
-
+
"firmwareFlasherPath": {
"message": "Path:"
},
@@ -976,7 +1020,7 @@
"firmwareFlasherFailedToLoadOnlineFirmware": {
"message": "Failed to load remote firmware"
},
-
+
"ledStripHelp": {
"message": "The flight controller can control colors and effects of individual LEDs on a strip. Configure LEDs on the grid, configure wiring order then attach LEDs on your aircraft according to grid positions."
},
diff --git a/changelog.html b/changelog.html
index 5fe12b59..d9552283 100644
--- a/changelog.html
+++ b/changelog.html
@@ -1,3 +1,9 @@
+2015.02.03 - 0.62.0 - cleanflight
+
+ - Add flight indicators to setup screen tab.
+ - Fix to fallback 3D model.
+ - Add support for SP Racing F3.
+
2015.02.03 - 0.61.0 - cleanflight
- Support changing PID controller - there new PID controllers in 1.7.0 firmware.
diff --git a/images/flightindicators/altitude_pressure.svg b/images/flightindicators/altitude_pressure.svg
new file mode 100644
index 00000000..5c1b195d
--- /dev/null
+++ b/images/flightindicators/altitude_pressure.svg
@@ -0,0 +1,106 @@
+
+
+
+
+
+ 990
+ 985
+ 980
+ 995
+ 1000
+ 1005
+ 1010
+ 1015
+ 1020
+ 1025
+ 1030
+
+ 1035
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/images/flightindicators/altitude_ticks.svg b/images/flightindicators/altitude_ticks.svg
new file mode 100644
index 00000000..a2ccffb9
--- /dev/null
+++ b/images/flightindicators/altitude_ticks.svg
@@ -0,0 +1,96 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+0
+ALT
+1
+2
+3
+4
+5
+6
+7
+8
+9
+
+
+
+
+
+
+
+
+
+
+
+FEET
+100
+1000 FEET
+CALIBRATED TO 25 000 FEET
+
diff --git a/images/flightindicators/fi_box.svg b/images/flightindicators/fi_box.svg
new file mode 100644
index 00000000..e7187b7d
--- /dev/null
+++ b/images/flightindicators/fi_box.svg
@@ -0,0 +1,20 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/images/flightindicators/fi_circle.svg b/images/flightindicators/fi_circle.svg
new file mode 100644
index 00000000..1a569211
--- /dev/null
+++ b/images/flightindicators/fi_circle.svg
@@ -0,0 +1,23 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/images/flightindicators/fi_needle.svg b/images/flightindicators/fi_needle.svg
new file mode 100644
index 00000000..e94e94e0
--- /dev/null
+++ b/images/flightindicators/fi_needle.svg
@@ -0,0 +1,22 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/images/flightindicators/fi_needle_small.svg b/images/flightindicators/fi_needle_small.svg
new file mode 100644
index 00000000..983087b1
--- /dev/null
+++ b/images/flightindicators/fi_needle_small.svg
@@ -0,0 +1,27 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/images/flightindicators/fi_tc_airplane.svg b/images/flightindicators/fi_tc_airplane.svg
new file mode 100644
index 00000000..e9904889
--- /dev/null
+++ b/images/flightindicators/fi_tc_airplane.svg
@@ -0,0 +1,34 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/images/flightindicators/heading_mechanics.svg b/images/flightindicators/heading_mechanics.svg
new file mode 100644
index 00000000..8020d309
--- /dev/null
+++ b/images/flightindicators/heading_mechanics.svg
@@ -0,0 +1,49 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/images/flightindicators/heading_yaw.svg b/images/flightindicators/heading_yaw.svg
new file mode 100644
index 00000000..1d0f4e2b
--- /dev/null
+++ b/images/flightindicators/heading_yaw.svg
@@ -0,0 +1,205 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/images/flightindicators/horizon_back.svg b/images/flightindicators/horizon_back.svg
new file mode 100644
index 00000000..e7e2d0a0
--- /dev/null
+++ b/images/flightindicators/horizon_back.svg
@@ -0,0 +1,11 @@
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/images/flightindicators/horizon_ball.svg b/images/flightindicators/horizon_ball.svg
new file mode 100644
index 00000000..d25a50b0
--- /dev/null
+++ b/images/flightindicators/horizon_ball.svg
@@ -0,0 +1,137 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/images/flightindicators/horizon_circle.svg b/images/flightindicators/horizon_circle.svg
new file mode 100644
index 00000000..8598d37a
--- /dev/null
+++ b/images/flightindicators/horizon_circle.svg
@@ -0,0 +1,33 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/images/flightindicators/horizon_mechanics.svg b/images/flightindicators/horizon_mechanics.svg
new file mode 100644
index 00000000..d1f6c008
--- /dev/null
+++ b/images/flightindicators/horizon_mechanics.svg
@@ -0,0 +1,30 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/images/flightindicators/speed_mechanics.svg b/images/flightindicators/speed_mechanics.svg
new file mode 100644
index 00000000..47d31f6c
--- /dev/null
+++ b/images/flightindicators/speed_mechanics.svg
@@ -0,0 +1,61 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+20
+40
+60
+80
+100
+120
+140
+160
+KNOTS
+AIR SPEED
+0
+
diff --git a/images/flightindicators/turn_coordinator.svg b/images/flightindicators/turn_coordinator.svg
new file mode 100644
index 00000000..a1525b22
--- /dev/null
+++ b/images/flightindicators/turn_coordinator.svg
@@ -0,0 +1,382 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ NO PITCH INFORMATION
+ D.C. ELEC.
+ TURN COORDINATOR
+
+
+
+
+ 2 MIN.
+ R
+ L
+
+
+
+
+
+
+
+
+
+
diff --git a/images/flightindicators/vertical_mechanics.svg b/images/flightindicators/vertical_mechanics.svg
new file mode 100644
index 00000000..71bb9398
--- /dev/null
+++ b/images/flightindicators/vertical_mechanics.svg
@@ -0,0 +1,93 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+0
+
+
+
+
+UP
+DOWN
+1
+1
+.5
+.5
+1 .5
+1 .5
+2
+VERTICAL SPEED
+1000FT PER MIN
+
diff --git a/images/light-wide-1.svg b/images/light-wide-1.svg
new file mode 100644
index 00000000..89172d5c
--- /dev/null
+++ b/images/light-wide-1.svg
@@ -0,0 +1,131 @@
+
+
+
+
+
+
+
+
+
+
+
+ image/svg+xml
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/js/data_storage.js b/js/data_storage.js
index 2ee6be15..343a9658 100755
--- a/js/data_storage.js
+++ b/js/data_storage.js
@@ -1,7 +1,7 @@
'use strict';
var CONFIGURATOR = {
- 'releaseDate': 1422922675433, // new Date().getTime() - 2015.01.29
+ 'releaseDate': 1424462791805, // new Date().getTime() - 2015.02.20
'apiVersionAccepted': 1.2,
'backupRestoreMinApiVersionAccepted': 1.5,
'pidControllerChangeMinApiVersion': 1.5,
@@ -149,3 +149,10 @@ var MISC = {
vbatmaxcellvoltage: 0,
vbatwarningcellvoltage: 0
};
+
+var DATAFLASH = {
+ ready: false,
+ sectors: 0,
+ totalSize: 0,
+ usedSize: 0
+};
diff --git a/js/gui.js b/js/gui.js
index f6007a9b..89fab7d7 100644
--- a/js/gui.js
+++ b/js/gui.js
@@ -25,6 +25,7 @@ var GUI_control = function () {
'gps',
'led_strip',
'logging',
+ 'dataflash',
'modes',
'motors',
'pid_tuning',
diff --git a/js/libraries/flightindicators.css b/js/libraries/flightindicators.css
new file mode 100644
index 00000000..3dbe0fe2
--- /dev/null
+++ b/js/libraries/flightindicators.css
@@ -0,0 +1,52 @@
+/*
+* jQuery Flight Indicators plugin
+* By Sébastien Matton (seb_matton@hotmail.com)
+* Published under GPLv3 License.
+*
+* https://github.com/sebmatton/jQuery-Flight-Indicators
+*/
+
+/* Global block of an indicator*/
+div.instrument {
+ width: 250px;
+ height: 250px;
+ position: relative;
+ display: inline-block;
+ overflow: hidden;
+}
+
+/* The box containing any element of an indicator */
+div.instrument .box {
+ position: absolute;
+ top: 0;
+ left: 0;
+ width: 100%;
+ height: 100%;
+}
+
+/* Default transformations */
+
+div.instrument.attitude div.roll {
+ transform: rotate(0deg);
+}
+div.instrument.attitude div.roll div.pitch {
+ top: 0%;
+}
+div.instrument.heading div.yaw {
+ transform: rotate(0deg);
+}
+div.instrument.vario div.vario {
+ transform: rotate(0deg);
+}
+div.instrument.speed div.airspeed {
+ transform: rotate(90deg);
+}
+div.instrument.altimeter div.pressure {
+ transform: rotate(40deg);
+}
+div.instrument.altimeter div.needle {
+ transform: rotate(90deg);
+}
+div.instrument.altimeter div.needleSmall {
+ transform: rotate(90deg);
+}
diff --git a/js/libraries/jquery.flightindicators.js b/js/libraries/jquery.flightindicators.js
new file mode 100644
index 00000000..1a954bff
--- /dev/null
+++ b/js/libraries/jquery.flightindicators.js
@@ -0,0 +1,173 @@
+/*
+* jQuery Flight Indicators plugin
+* By Sébastien Matton (seb_matton@hotmail.com)
+* Published under GPLv3 License.
+*
+* https://github.com/sebmatton/jQuery-Flight-Indicators
+*/
+(function($) {
+ function FlightIndicator( placeholder, type, options ) {
+ // Initial configuration
+ var attitude = this;
+ var settings = $.extend({
+ size : 200,
+ roll : 0,
+ pitch : 0,
+ turn : 0,
+ heading: 0,
+ vario: 0,
+ airspeed: 0,
+ altitude: 0,
+ pressure: 1000,
+ showBox : true,
+ img_directory : 'img/'
+ }, options );
+
+ var constants = {
+ pitch_bound:30,
+ vario_bound : 1.95,
+ airspeed_bound_l : 0,
+ airspeed_bound_h : 160
+ }
+
+ // Creation of the instrument
+ placeholder.each(function(){
+ switch(type){
+ case 'heading':
+ $(this).html('
');
+ _setHeading(settings.heading);
+ break;
+ case 'variometer':
+ $(this).html(' ');
+ _setVario(settings.vario);
+ break;
+ case 'turn_coordinator':
+ $(this).html(' ');
+ _setTurn(settings.turn);
+ break;
+ case 'airspeed':
+ $(this).html(' ');
+ _setAirSpeed(settings.airspeed);
+ break
+ case 'altimeter':
+ $(this).html(' ');
+ _setAltitude(settings.altitude);
+ _setPressure(settings.pressure);
+ break;
+ default:
+ $(this).html(' ');
+ _setRoll(settings.roll);
+ _setPitch(settings.pitch);
+ }
+ $(this).find('div.instrument').css({height : settings.size, width : settings.size});
+ $(this).find('div.instrument img.box.background').toggle(settings.showBox);
+ });
+
+ // Private methods
+ function _setRoll(roll){
+ placeholder.each(function(){
+ $(this).find('div.instrument.attitude div.roll').css('transform', 'rotate('+roll+'deg)');
+ });
+ }
+
+ function _setPitch(pitch){
+ // alert(pitch);
+ if(pitch>constants.pitch_bound){pitch = constants.pitch_bound;}
+ else if(pitch<-constants.pitch_bound){pitch = -constants.pitch_bound;}
+ placeholder.each(function(){
+ $(this).find('div.instrument.attitude div.roll div.pitch').css('top', pitch*0.7 + '%');
+ });
+ }
+
+ function _setHeading(heading){
+ placeholder.each(function(){
+ $(this).find('div.instrument.heading div.heading').css('transform', 'rotate(' + -heading + 'deg)');
+ });
+ }
+
+ function _setTurn(turn){
+ placeholder.each(function(){
+ $(this).find('div.instrument.turn_coordinator div.turn').css('transform', 'rotate('+turn+'deg)');
+ });
+ }
+
+ function _setVario(vario){
+ if(vario > constants.vario_bound){vario = constants.vario_bound;}
+ else if(vario < -constants.vario_bound){vario = -constants.vario_bound;}
+ vario = vario*90;
+ placeholder.each(function(){
+ $(this).find('div.instrument.vario div.vario').css('transform', 'rotate(' + vario + 'deg)');
+ });
+ }
+
+ function _setAirSpeed(speed){
+ if(speed > constants.airspeed_bound_h){speed = constants.airspeed_bound_h;}
+ else if(speed < constants.airspeed_bound_l){speed = constants.airspeed_bound_l;}
+ speed = 90+speed*2;
+ placeholder.each(function(){
+ $(this).find('div.instrument.airspeed div.speed').css('transform', 'rotate(' + speed + 'deg)');
+ });
+ }
+
+ function _setAltitude(altitude){
+ var needle = 90 + altitude%1000 * 360 / 1000;
+ var needleSmall = altitude / 10000 * 360;
+ placeholder.each(function(){
+ $(this).find('div.instrument.altimeter div.needle').css('transform', 'rotate(' + needle + 'deg)');
+ $(this).find('div.instrument.altimeter div.needleSmall').css('transform', 'rotate(' + needleSmall + 'deg)');
+ });
+ }
+
+ function _setPressure(pressure){
+ pressure = 2*pressure - 1980;
+ placeholder.each(function(){
+ $(this).find('div.instrument.altimeter div.pressure').css('transform', 'rotate(' + pressure + 'deg)');
+ });
+ }
+
+ function _resize(size){
+ placeholder.each(function(){
+ $(this).find('div.instrument').css({height : size, width : size});
+ });
+ }
+
+ function _showBox(){
+ placeholder.each(function(){
+ $(this).find('img.box.background').show();
+ });
+ }
+
+ function _hideBox(){
+ placeholder.each(function(){
+ $(this).find('img.box.background').hide();
+ });
+ }
+
+ // Public methods
+ this.setRoll = function(roll){_setRoll(roll);}
+ this.setPitch = function(pitch){_setPitch(pitch);}
+ this.setHeading = function(heading){_setHeading(heading);}
+ this.setTurn = function(turn){_setTurn(turn);}
+ this.setVario = function(vario){_setVario(vario);}
+ this.setAirSpeed = function(speed){_setAirSpeed(speed);}
+ this.setAltitude = function(altitude){_setAltitude(altitude);}
+ this.setPressure = function(pressure){_setPressure(pressure);}
+ this.resize = function(size){_resize(size);}
+ this.showBox = function(){_showBox();}
+ this.hideBox = function(){_hideBox();}
+
+ return attitude;
+ };
+
+ // Extension to jQuery
+ $.flightIndicator = function(placeholder, type, options){
+ var flightIndicator = new FlightIndicator($(placeholder), type, options)
+ return flightIndicator;
+ }
+
+ $.fn.flightIndicator = function(data, type, options){
+ return this.each(function(){
+ $.flightIndicator(this, type, options);
+ });
+ }
+}( jQuery ));
diff --git a/js/msp.js b/js/msp.js
index 3e437965..b251f9c2 100644
--- a/js/msp.js
+++ b/js/msp.js
@@ -22,6 +22,9 @@ var MSP_codes = {
MSP_SONAR: 58,
MSP_PID_CONTROLLER: 59,
MSP_SET_PID_CONTROLLER: 60,
+ MSP_DATAFLASH_SUMMARY: 70,
+ MSP_DATAFLASH_READ: 71,
+ MSP_DATAFLASH_ERASE: 72,
// Multiwii MSP commands
MSP_IDENT: 100,
@@ -671,8 +674,26 @@ var MSP = {
case MSP_codes.MSP_SET_LED_STRIP_CONFIG:
console.log('Led strip config saved');
break;
-
-
+ case MSP_codes.MSP_DATAFLASH_SUMMARY:
+ if (data.byteLength >= 13) {
+ DATAFLASH.ready = (data.getUint8(0) & 1) != 0;
+ DATAFLASH.sectors = data.getUint32(1, 1);
+ DATAFLASH.totalSize = data.getUint32(5, 1);
+ DATAFLASH.usedSize = data.getUint32(9, 1);
+ } else {
+ // Firmware version too old to support MSP_DATAFLASH_SUMMARY
+ DATAFLASH.ready = false;
+ DATAFLASH.sectors = 0;
+ DATAFLASH.totalSize = 0;
+ DATAFLASH.usedSize = 0;
+ }
+ break;
+ case MSP_codes.MSP_DATAFLASH_READ:
+ // No-op, let callback handle it
+ break;
+ case MSP_codes.MSP_DATAFLASH_ERASE:
+ console.log("Data flash erase begun...");
+ break;
case MSP_codes.MSP_SET_MODE_RANGE:
console.log('Mode range saved');
break;
@@ -798,6 +819,9 @@ var MSP = {
}
};
+/**
+ * Encode the request body for the MSP request with the given code and return it as an array of bytes.
+ */
MSP.crunch = function (code) {
var buffer = [];
@@ -959,6 +983,27 @@ MSP.crunch = function (code) {
return buffer;
};
+/**
+ * Send a request to read a block of data from the dataflash at the given address and pass that address and a dataview
+ * of the returned data to the given callback (or null for the data if an error occured).
+ */
+MSP.dataflashRead = function(address, onDataCallback) {
+ MSP.send_message(MSP_codes.MSP_DATAFLASH_READ, [address & 0xFF, (address >> 8) & 0xFF, (address >> 16) & 0xFF, (address >> 24) & 0xFF],
+ false, function(response) {
+ var chunkAddress = response.data.getUint32(0, 1);
+
+ // Verify that the address of the memory returned matches what the caller asked for
+ if (chunkAddress == address) {
+ /* Strip that address off the front of the reply and deliver it separately so the caller doesn't have to
+ * figure out the reply format:
+ */
+ onDataCallback(address, new DataView(response.data.buffer, response.data.byteOffset + 4, response.data.buffer.byteLength - 4));
+ } else {
+ // Report error
+ onDataCallback(address, null);
+ }
+ });
+} ;
MSP.sendModeRanges = function(onCompleteCallback) {
var nextFunction = send_next_mode_range;
diff --git a/js/serial_backend.js b/js/serial_backend.js
index c8c9b687..b8892f69 100755
--- a/js/serial_backend.js
+++ b/js/serial_backend.js
@@ -247,44 +247,67 @@ function sensor_status(sensors_detected) {
}
// 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');
- } else {
- $('.gyro', e_sensor_status).removeClass('on');
- $('.accel', e_sensor_status).removeClass('on');
- }
-
- if (bit_check(sensors_detected, 1)) { // Barometer 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;
+ if (sensor_status.previous_sensors_detected == sensors_detected) {
+ return;
}
+
+ // set current value
+ sensor_status.previous_sensors_detected = sensors_detected;
+
+ var e_sensor_status = $('div#sensor-status');
+
+ if (have_sensor(sensors_detected, 'acc')) {
+ $('.accel', e_sensor_status).addClass('on');
+ } else {
+ $('.accel', e_sensor_status).removeClass('on');
+ }
+
+ if (have_sensor(sensors_detected, 'gyro')) {
+ $('.gyro', e_sensor_status).addClass('on');
+ } else {
+ $('.gyro', e_sensor_status).removeClass('on');
+ }
+
+ if (have_sensor(sensors_detected, 'baro')) {
+ $('.baro', e_sensor_status).addClass('on');
+ } else {
+ $('.baro', e_sensor_status).removeClass('on');
+ }
+
+ if (have_sensor(sensors_detected, 'mag')) {
+ $('.mag', e_sensor_status).addClass('on');
+ } else {
+ $('.mag', e_sensor_status).removeClass('on');
+ }
+
+ if (have_sensor(sensors_detected, 'gps')) {
+ $('.gps', e_sensor_status).addClass('on');
+ } else {
+ $('.gps', e_sensor_status).removeClass('on');
+ }
+
+ if (have_sensor(sensors_detected, 'sonar')) {
+ $('.sonar', e_sensor_status).addClass('on');
+ } else {
+ $('.sonar', e_sensor_status).removeClass('on');
+ }
+}
+
+function have_sensor(sensors_detected, sensor_code) {
+ switch(sensor_code) {
+ case 'acc':
+ case 'gyro':
+ return bit_check(sensors_detected, 0);
+ case 'baro':
+ return bit_check(sensors_detected, 1);
+ case 'mag':
+ return bit_check(sensors_detected, 2);
+ case 'gps':
+ return bit_check(sensors_detected, 3);
+ case 'sonar':
+ return bit_check(sensors_detected, 4);
+ }
+ return false;
}
function highByte(num) {
diff --git a/main.css b/main.css
index cc8918d5..b0b4c3b9 100755
--- a/main.css
+++ b/main.css
@@ -39,21 +39,33 @@ input[type="number"]::-webkit-inner-spin-button {
height: calc(100% - 5px);
}
+#content-watermark {
+ position: absolute;
+ bottom: 40px;
+ left: 0;
+ right: 0;
+ z-index: 1;
+ overflow: hidden;
+ background-image: url("images/light-wide-1.svg");
+ background-repeat: no-repeat;
+ background-position: 50% 0%;
+ background-size: 600px;
+ height: 174px;
+ opacity: 0.25;
+}
+
#watermark {
position: absolute;
- text-align: center;
- top: 35px;
- left: 0;
- bottom: 0;
+ top: 30px;
+ height: 67px;
right: 0;
z-index: -1;
overflow: hidden;
-
- font-family: monospace;
- color: grey;
- font-size: 50px;
- font-variant: small-caps;
- letter-spacing: 0.5em;
+ background-image: url("images/light-wide-1.svg");
+ background-repeat: no-repeat;
+ width: 340px;
+ background-position: 0px 0px;
+ background-size: 85%;
}
#port-picker {
@@ -353,3 +365,14 @@ input[type="number"]::-webkit-inner-spin-button {
text-align: center;
font-weight: bold;
}
+
+dialog {
+ background-color: white;
+ padding: 1em;
+ height: auto;
+ margin: auto auto;
+ position: absolute;
+ width: 50%;
+ border-radius: 5px;
+ border: 1px solid silver;
+}
\ No newline at end of file
diff --git a/main.html b/main.html
index f6ace554..e7afaf49 100755
--- a/main.html
+++ b/main.html
@@ -7,6 +7,7 @@
+
@@ -22,6 +23,7 @@
+
@@ -35,6 +37,7 @@
+
@@ -68,6 +71,7 @@
+
@@ -122,7 +126,7 @@
@@ -146,6 +150,7 @@
+
diff --git a/main.js b/main.js
index 374f4cdc..fa3d54b6 100755
--- a/main.js
+++ b/main.js
@@ -153,6 +153,9 @@ $(document).ready(function () {
case 'logging':
TABS.logging.initialize(content_ready);
break;
+ case 'dataflash':
+ TABS.dataflash.initialize(content_ready);
+ break;
case 'cli':
TABS.cli.initialize(content_ready);
break;
diff --git a/manifest.json b/manifest.json
index 6fccb3e3..e6ce46b0 100644
--- a/manifest.json
+++ b/manifest.json
@@ -1,7 +1,7 @@
{
"manifest_version": 2,
"minimum_chrome_version": "38",
- "version": "0.61.0",
+ "version": "0.62.0",
"author": "Hydra",
"name": "Cleanflight - Configurator",
"short_name": "cleanflight",
diff --git a/resources/motor_order/airplane.svg b/resources/motor_order/airplane.svg
index 7a6a596a..a97ea0f7 100644
--- a/resources/motor_order/airplane.svg
+++ b/resources/motor_order/airplane.svg
@@ -1,73 +1,73 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/resources/motor_order/atail_quad.svg b/resources/motor_order/atail_quad.svg
index 74641eb8..63b93848 100644
--- a/resources/motor_order/atail_quad.svg
+++ b/resources/motor_order/atail_quad.svg
@@ -1,44 +1,44 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/resources/motor_order/bicopter.svg b/resources/motor_order/bicopter.svg
index 95b2ca75..6d866dc7 100644
--- a/resources/motor_order/bicopter.svg
+++ b/resources/motor_order/bicopter.svg
@@ -1,52 +1,52 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/resources/motor_order/flying_wing.svg b/resources/motor_order/flying_wing.svg
index 638f120d..46365398 100644
--- a/resources/motor_order/flying_wing.svg
+++ b/resources/motor_order/flying_wing.svg
@@ -1,55 +1,55 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/resources/motor_order/hex_p.svg b/resources/motor_order/hex_p.svg
index 03830b8d..eab82b7c 100644
--- a/resources/motor_order/hex_p.svg
+++ b/resources/motor_order/hex_p.svg
@@ -1,58 +1,58 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/resources/motor_order/hex_x.svg b/resources/motor_order/hex_x.svg
index ae28e357..4e3a02d7 100644
--- a/resources/motor_order/hex_x.svg
+++ b/resources/motor_order/hex_x.svg
@@ -1,58 +1,58 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/resources/motor_order/octo_flat_p.svg b/resources/motor_order/octo_flat_p.svg
index 7dc6460e..5b880729 100644
--- a/resources/motor_order/octo_flat_p.svg
+++ b/resources/motor_order/octo_flat_p.svg
@@ -1,72 +1,72 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/resources/motor_order/octo_flat_x.svg b/resources/motor_order/octo_flat_x.svg
index 4031ab79..9493a4b2 100644
--- a/resources/motor_order/octo_flat_x.svg
+++ b/resources/motor_order/octo_flat_x.svg
@@ -1,72 +1,72 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/resources/motor_order/octo_x8.svg b/resources/motor_order/octo_x8.svg
index 236b3cf2..8e28d095 100644
--- a/resources/motor_order/octo_x8.svg
+++ b/resources/motor_order/octo_x8.svg
@@ -1,76 +1,76 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/resources/motor_order/quad_p.svg b/resources/motor_order/quad_p.svg
index 7424e1b3..25609e84 100644
--- a/resources/motor_order/quad_p.svg
+++ b/resources/motor_order/quad_p.svg
@@ -1,44 +1,44 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/resources/motor_order/quad_x.svg b/resources/motor_order/quad_x.svg
index de045e36..7ae53a0b 100644
--- a/resources/motor_order/quad_x.svg
+++ b/resources/motor_order/quad_x.svg
@@ -1,44 +1,44 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/resources/motor_order/tri.svg b/resources/motor_order/tri.svg
index 8f30f934..5ff940c8 100644
--- a/resources/motor_order/tri.svg
+++ b/resources/motor_order/tri.svg
@@ -1,51 +1,51 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/resources/motor_order/vtail_quad.svg b/resources/motor_order/vtail_quad.svg
index 654fa686..6ec31ef6 100644
--- a/resources/motor_order/vtail_quad.svg
+++ b/resources/motor_order/vtail_quad.svg
@@ -1,44 +1,44 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/resources/motor_order/y4.svg b/resources/motor_order/y4.svg
index 6edfcfa2..5f7a539f 100644
--- a/resources/motor_order/y4.svg
+++ b/resources/motor_order/y4.svg
@@ -1,45 +1,45 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/resources/motor_order/y6.svg b/resources/motor_order/y6.svg
index ef1ee801..b830dd46 100644
--- a/resources/motor_order/y6.svg
+++ b/resources/motor_order/y6.svg
@@ -1,61 +1,61 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/tabs/cli.html b/tabs/cli.html
index 3c9c585e..f83d8620 100644
--- a/tabs/cli.html
+++ b/tabs/cli.html
@@ -1,3 +1,4 @@
+
diff --git a/tabs/dataflash.css b/tabs/dataflash.css
new file mode 100644
index 00000000..a6885d53
--- /dev/null
+++ b/tabs/dataflash.css
@@ -0,0 +1,192 @@
+.tab-dataflash .info {
+ margin: 0 0 10px 0;
+ position: relative;
+}
+.tab-dataflash .info .progressLabel {
+ position: absolute;
+
+ width: 100%;
+ height: 26px;
+
+ top: 0;
+ left: 0;
+
+ text-align: center;
+ line-height: 24px;
+
+ color: white;
+ font-weight: bold;
+
+ /* text-shadow: 1px 0px 2px rgba(0, 0, 0, 0.9);*/
+}
+.tab-dataflash .note {
+ padding: 5px;
+ border: 1px dashed silver;
+ margin-bottom: 8px;
+}
+.tab-dataflash .properties {
+ margin-top: 10px;
+}
+.tab-dataflash .dataflash-info {
+ overflow:hidden;
+}
+.tab-dataflash .dataflash-info dt {
+ float: left;
+ width: 12em;
+ height: 20px;
+ line-height: 20px;
+
+ font-weight: bold;
+}
+.tab-dataflash .dataflash-info dd {
+ display: block;
+ height: 20px;
+ line-height: 20px;
+}
+.tab-dataflash .speed {
+ margin-top: 5px;
+ width: 80px;
+
+ border: 1px solid silver;
+}
+.tab-dataflash .info {
+ margin-top: 10px;
+}
+.tab-dataflash .info dt {
+ float: left;
+ width: 120px;
+ height: 20px;
+ line-height: 20px;
+
+ font-weight: bold;
+}
+.tab-dataflash .info dd {
+ display: block;
+ margin-left: 130px;
+ height: 20px;
+ line-height: 20px;
+}
+.tab-dataflash .buttons {
+ width: calc(100% - 20px);
+
+ position: absolute;
+ bottom: 10px;
+}
+.tab-dataflash .buttons a {
+ display: block;
+ float: right;
+
+ margin-left: 10px;
+
+ height: 28px;
+ line-height: 28px;
+
+ padding: 0 15px 0 15px;
+
+ text-align: center;
+ font-weight: bold;
+
+ border: 1px solid silver;
+ background-color: #ececec;
+}
+.tab-dataflash .buttons a:hover {
+ background-color: #dedcdc;
+}
+.tab-dataflash .buttons a.disabled {
+ cursor: default;
+ color: #999;
+ pointer-events: none;
+}
+.tab-dataflash .dataflash-progress {
+ display: none;
+}
+.tab-dataflash .dataflash-contents {
+ margin:9px 16px;
+
+ border:1px solid silver;
+ background-color:#eee;
+
+ display:flex;
+ flex-direction:row;
+ flex-wrap:nowrap;
+ justify-content:flex-start;
+
+ border-radius:6px;
+}
+.tab-dataflash .dataflash-contents li {
+ height:26px;
+ position:relative;
+}
+.tab-dataflash .dataflash-contents li div {
+ position:absolute;
+ top:26px;
+ margin-top:4px;
+ text-align:center;
+ left: 0;
+ right: 0;
+}
+.tab-dataflash .dataflash-used {
+ background-color:#bcf;
+}
+.tab-dataflash progress::-webkit-progress-bar {
+ height:24px;
+ background-color:#eee;
+}
+.tab-dataflash progress::-webkit-progress-value {
+ background-color:#bcf;
+}
+
+.tab-dataflash dialog {
+ width:40em;
+}
+.tab-dataflash dialog .buttons {
+ position:static;
+ margin-top: 2em;
+ overflow: hidden;
+ width:auto;
+}
+.tab-dataflash dialog h3 {
+ margin-bottom: 0.5em;
+}
+
+.dataflash-confirm-erase .dataflash-erase-progress {
+ height:125px;
+ display:none;
+}
+.dataflash-confirm-erase.erasing .dataflash-erase-progress {
+ display:block;
+}
+.dataflash-confirm-erase.erasing h3,
+.dataflash-confirm-erase.erasing .erase-flash-confirm,
+.dataflash-confirm-erase.erasing .dataflash-confirm-erase-note {
+ display:none;
+}
+
+.tab-dataflash progress {
+ display:block;
+ width:100%;
+ margin:1em 0;
+}
+
+.dataflash-saving .dataflash-saving-after {
+ display:none;
+}
+.dataflash-saving.done .dataflash-saving-before {
+ display:none;
+}
+.dataflash-saving.done .dataflash-saving-after {
+ display:block;
+}
+
+.require-dataflash {
+ display:none;
+}
+.tab-dataflash.supported .require-dataflash {
+ display:block;
+}
+.require-no-dataflash {
+ display:block;
+}
+.tab-dataflash.supported .require-no-dataflash {
+ display:none;
+}
\ No newline at end of file
diff --git a/tabs/dataflash.html b/tabs/dataflash.html
new file mode 100644
index 00000000..70d46b89
--- /dev/null
+++ b/tabs/dataflash.html
@@ -0,0 +1,67 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
Erase in progress, please wait...
+
+
+
+
+
+
+
+
+
+
+
+
+
Dataflash contents
+
+
+
+ Used space
+
+
+
+
+ Free space
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/tabs/dataflash.js b/tabs/dataflash.js
new file mode 100644
index 00000000..90980c5c
--- /dev/null
+++ b/tabs/dataflash.js
@@ -0,0 +1,240 @@
+'use strict';
+
+TABS.dataflash = {};
+TABS.dataflash.initialize = function (callback) {
+ var
+ self = this,
+ saveCancelled, eraseCancelled;
+
+ if (GUI.active_tab != 'dataflash') {
+ GUI.active_tab = 'dataflash';
+ googleAnalytics.sendAppView('dataflash');
+ }
+
+ var
+ requested_properties = [],
+ samples = 0,
+ requests = 0,
+ log_buffer = [];
+
+ if (CONFIGURATOR.connectionValid) {
+ MSP.send_message(MSP_codes.MSP_DATAFLASH_SUMMARY, false, false, function() {
+ $('#content').load("./tabs/dataflash.html", function() {
+ create_html();
+ });
+ });
+ }
+
+ function formatFilesize(bytes) {
+ if (bytes < 1024) {
+ return bytes + "B";
+ }
+
+ var kilobytes = bytes / 1024;
+
+ if (kilobytes < 1024) {
+ return Math.round(kilobytes) + "kB";
+ }
+
+ var megabytes = kilobytes / 1024;
+
+ return megabytes.toFixed(1) + "MB";
+ }
+
+ function update_html() {
+ if (DATAFLASH.usedSize > 0) {
+ $(".tab-dataflash .dataflash-used").css({
+ width: (DATAFLASH.usedSize / DATAFLASH.totalSize * 100) + "%",
+ display: 'block'
+ });
+
+ $(".tab-dataflash .dataflash-used div").text('Used space ' + formatFilesize(DATAFLASH.usedSize));
+ } else {
+ $(".tab-dataflash .dataflash-used").css({
+ display: 'none'
+ });
+ }
+
+ if (DATAFLASH.totalSize - DATAFLASH.usedSize > 0) {
+ $(".tab-dataflash .dataflash-free").css({
+ width: ((DATAFLASH.totalSize - DATAFLASH.usedSize) / DATAFLASH.totalSize * 100) + "%",
+ display: 'block'
+ });
+ $(".tab-dataflash .dataflash-free div").text('Free space ' + formatFilesize(DATAFLASH.totalSize - DATAFLASH.usedSize));
+ } else {
+ $(".tab-dataflash .dataflash-free").css({
+ display: 'none'
+ });
+ }
+
+ $(".tab-dataflash a.erase-flash, .tab-dataflash a.save-flash").toggleClass("disabled", DATAFLASH.usedSize == 0);
+ }
+
+ function create_html() {
+ var
+ supportsDataflash = DATAFLASH.totalSize > 0;
+
+ // translate to user-selected language
+ localize();
+
+ $(".tab-dataflash").toggleClass("supported", supportsDataflash);
+
+ if (supportsDataflash) {
+ // UI hooks
+ $('.tab-dataflash a.erase-flash').click(ask_to_erase_flash);
+
+ $('.tab-dataflash a.erase-flash-confirm').click(flash_erase);
+ $('.tab-dataflash a.erase-flash-cancel').click(flash_erase_cancel);
+
+ $('.tab-dataflash a.save-flash').click(flash_save_begin);
+ $('.tab-dataflash a.save-flash-cancel').click(flash_save_cancel);
+ $('.tab-dataflash a.save-flash-dismiss').click(dismiss_saving_dialog);
+
+ update_html();
+ }
+
+ if (callback) callback();
+ }
+
+ // IO related methods
+ function zeroPad(value, width) {
+ value = "" + value;
+
+ while (value.length < width) {
+ value = "0" + value;
+ }
+
+ return value;
+ }
+
+ function flash_save_cancel() {
+ saveCancelled = true;
+ }
+
+ function show_saving_dialog() {
+ $(".dataflash-saving progress").attr("value", 0);
+ saveCancelled = false;
+ $(".dataflash-saving").removeClass("done");
+
+ $(".dataflash-saving")[0].showModal();
+ }
+
+ function dismiss_saving_dialog() {
+ $(".dataflash-saving")[0].close();
+ }
+
+ function mark_saving_dialog_done() {
+ $(".dataflash-saving").addClass("done");
+ }
+
+ function flash_save_begin() {
+ var
+ maxBytes = DATAFLASH.usedSize;
+
+ if (GUI.connected_to) {
+ prepare_file(function(fileWriter) {
+ var
+ nextAddress = 0;
+
+ show_saving_dialog();
+
+ function onChunkRead(chunkAddress, chunkDataView) {
+ // If we didn't get a zero-byte chunk (indicating end-of-file), request more
+ if (chunkDataView.byteLength > 0) {
+ nextAddress += chunkDataView.byteLength;
+
+ $(".dataflash-saving progress").attr("value", nextAddress / maxBytes * 100);
+
+ var
+ blob = new Blob([chunkDataView]);
+
+ fileWriter.write(blob);
+
+ if (saveCancelled || nextAddress >= maxBytes) {
+ if (saveCancelled) {
+ dismiss_saving_dialog();
+ } else {
+ mark_saving_dialog_done();
+ }
+ } else {
+ MSP.dataflashRead(nextAddress, onChunkRead);
+ }
+ } else {
+ mark_saving_dialog_done();
+ }
+ }
+
+ MSP.dataflashRead(nextAddress, onChunkRead);
+ });
+ }
+ }
+
+ function prepare_file(onComplete) {
+ var
+ date = new Date(),
+ filename = 'blackbox_log_' + date.getFullYear() + '-' + zeroPad(date.getMonth() + 1, 2) + '-'
+ + zeroPad(date.getDate(), 2) + '_' + zeroPad(date.getHours(), 2) + zeroPad(date.getMinutes(), 2)
+ + zeroPad(date.getSeconds(), 2);
+
+ chrome.fileSystem.chooseEntry({type: 'saveFile', suggestedName: filename,
+ accepts: [{extensions: ['TXT']}]}, function(fileEntry) {
+ if (!fileEntry) {
+ console.log('No file selected');
+ return;
+ }
+
+ // echo/console log path specified
+ chrome.fileSystem.getDisplayPath(fileEntry, function(path) {
+ console.log('Dataflash dump file path: ' + path);
+ });
+
+ fileEntry.createWriter(function (fileWriter) {
+ fileWriter.onerror = function (e) {
+ console.error(e);
+
+ // stop logging if the procedure was/is still running
+ };
+
+ onComplete(fileWriter);
+ }, function (e) {
+ // File is not readable or does not exist!
+ console.error(e);
+ });
+ });
+ }
+
+ function ask_to_erase_flash() {
+ eraseCancelled = false;
+ $(".dataflash-confirm-erase").removeClass('erasing');
+
+ $(".dataflash-confirm-erase")[0].showModal();
+ }
+
+ function poll_for_erase_completion() {
+ MSP.send_message(MSP_codes.MSP_DATAFLASH_SUMMARY, false, false, function() {
+ update_html();
+ if (!eraseCancelled) {
+ if (DATAFLASH.ready) {
+ $(".dataflash-confirm-erase")[0].close();
+ } else {
+ setTimeout(poll_for_erase_completion, 500);
+ }
+ }
+ });
+ }
+
+ function flash_erase() {
+ $(".dataflash-confirm-erase").addClass('erasing');
+
+ MSP.send_message(MSP_codes.MSP_DATAFLASH_ERASE, false, false, poll_for_erase_completion);
+ }
+
+ function flash_erase_cancel() {
+ eraseCancelled = true;
+ $(".dataflash-confirm-erase")[0].close();
+ }
+};
+
+TABS.dataflash.cleanup = function (callback) {
+ if (callback) callback();
+};
\ No newline at end of file
diff --git a/tabs/gps.html b/tabs/gps.html
index c6bce689..61a4f82b 100644
--- a/tabs/gps.html
+++ b/tabs/gps.html
@@ -122,4 +122,4 @@
-
\ No newline at end of file
+
diff --git a/tabs/gps.js b/tabs/gps.js
index 227858a2..251c88a8 100644
--- a/tabs/gps.js
+++ b/tabs/gps.js
@@ -13,7 +13,7 @@ TABS.gps.initialize = function (callback) {
$('#content').load("./tabs/gps.html", process_html);
}
- MSP.send_message(MSP_codes.MSP_RAW_GPS, false, false, load_html);
+ MSP.send_message(MSP_codes.MSP_STATUS, false, false, load_html);
function process_html() {
// translate to user-selected language
@@ -57,7 +57,14 @@ TABS.gps.initialize = function (callback) {
}
// enable data pulling
- GUI.interval_add('gps_pull', get_raw_gps_data, 75, true);
+ GUI.interval_add('gps_pull', function gps_update() {
+ // avoid usage of the GPS commands until a GPS sensor is detected for targets that are compiled without GPS support.
+ if (!have_sensor(CONFIG.activeSensors, 'gps')) {
+ return;
+ }
+
+ get_raw_gps_data();
+ }, 75, true);
// status data pulled via separate timer with static speed
GUI.interval_add('status_pull', function status_pull() {
diff --git a/tabs/logging.html b/tabs/logging.html
index b5cf7ef0..035ce8fd 100644
--- a/tabs/logging.html
+++ b/tabs/logging.html
@@ -1,3 +1,4 @@
+
diff --git a/tabs/modes.html b/tabs/modes.html
index c0b92e17..7edabe59 100644
--- a/tabs/modes.html
+++ b/tabs/modes.html
@@ -10,4 +10,4 @@
-
\ No newline at end of file
+
diff --git a/tabs/motors.html b/tabs/motors.html
index 06ec582c..16314209 100644
--- a/tabs/motors.html
+++ b/tabs/motors.html
@@ -1,3 +1,4 @@
+
\ No newline at end of file
+
diff --git a/tabs/pid_tuning.html b/tabs/pid_tuning.html
index e4a21fb7..01e8a4c3 100644
--- a/tabs/pid_tuning.html
+++ b/tabs/pid_tuning.html
@@ -1,3 +1,4 @@
+
diff --git a/tabs/ports.html b/tabs/ports.html
index d042f702..f2804468 100644
--- a/tabs/ports.html
+++ b/tabs/ports.html
@@ -1,3 +1,4 @@
+
diff --git a/tabs/receiver.html b/tabs/receiver.html
index dd875c73..efb1e63a 100644
--- a/tabs/receiver.html
+++ b/tabs/receiver.html
@@ -1,3 +1,4 @@
+
diff --git a/tabs/sensors.html b/tabs/sensors.html
index 905a5ca3..aeb00d61 100644
--- a/tabs/sensors.html
+++ b/tabs/sensors.html
@@ -1,3 +1,4 @@
+
diff --git a/tabs/setup.css b/tabs/setup.css
index 19dca296..f5b3fc64 100644
--- a/tabs/setup.css
+++ b/tabs/setup.css
@@ -22,7 +22,7 @@
border: 1px solid silver;
background-color: #ececec;
-
+
white-space: nowrap;
}
.tab-setup .section a:hover {
@@ -156,6 +156,7 @@
}
.tab-setup .block.gps {
width: 185px;
+ margin-bottom: 10px;
}
.tab-setup .block.gps .fields {
padding: 5px 5px 3px 5px;
@@ -178,6 +179,9 @@
line-height: 20px;
}
+.tab-setup .block.instruments {
+ width: 185px;
+}
.tab-setup .buttons {
width: calc(100% - 20px);
@@ -201,4 +205,4 @@
}
.tab-setup .update:hover {
background-color: #dedcdc;
-}
\ No newline at end of file
+}
diff --git a/tabs/setup.html b/tabs/setup.html
index c39cd7aa..9168ebf7 100644
--- a/tabs/setup.html
+++ b/tabs/setup.html
@@ -50,5 +50,10 @@
+
+
+
+
+
-
\ No newline at end of file
+
diff --git a/tabs/setup.js b/tabs/setup.js
index 73347b46..8e8f49f3 100644
--- a/tabs/setup.js
+++ b/tabs/setup.js
@@ -41,7 +41,7 @@ TABS.setup.initialize = function (callback) {
if (CONFIG.apiVersion < CONFIGURATOR.backupRestoreMinApiVersionAccepted) {
$('#content .backup').addClass('disabled');
$('#content .restore').addClass('disabled');
-
+
GUI.log(chrome.i18n.getMessage('initialSetupBackupAndRestoreApiVersion', [CONFIG.apiVersion, CONFIGURATOR.backupRestoreMinApiVersionAccepted]));
}
// initialize 3D
@@ -55,6 +55,8 @@ TABS.setup.initialize = function (callback) {
$('a.calibrateMag').addClass('disabled');
}
+ self.initializeInstruments();
+
// UI Hooks
$('a.calibrateAccel').click(function () {
var self = $(this);
@@ -153,7 +155,7 @@ TABS.setup.initialize = function (callback) {
function get_slow_data() {
MSP.send_message(MSP_codes.MSP_STATUS);
-
+
MSP.send_message(MSP_codes.MSP_ANALOG, false, false, function () {
bat_voltage_e.text(chrome.i18n.getMessage('initialSetupBatteryValue', [ANALOG.voltage]));
bat_mah_drawn_e.text(chrome.i18n.getMessage('initialSetupBatteryMahValue', [ANALOG.mAhdrawn]));
@@ -161,18 +163,21 @@ TABS.setup.initialize = function (callback) {
rssi_e.text(chrome.i18n.getMessage('initialSetupRSSIValue', [((ANALOG.rssi / 1023) * 100).toFixed(0)]));
});
- MSP.send_message(MSP_codes.MSP_RAW_GPS, false, false, function () {
- gpsFix_e.html((GPS_DATA.fix) ? chrome.i18n.getMessage('gpsFixTrue') : chrome.i18n.getMessage('gpsFixFalse'));
- gpsSats_e.text(GPS_DATA.numSat);
- gpsLat_e.text((GPS_DATA.lat / 10000000).toFixed(4) + ' deg');
- gpsLon_e.text((GPS_DATA.lon / 10000000).toFixed(4) + ' deg');
- });
+ if (have_sensor(CONFIG.activeSensors, 'gps')) {
+ MSP.send_message(MSP_codes.MSP_RAW_GPS, false, false, function () {
+ gpsFix_e.html((GPS_DATA.fix) ? chrome.i18n.getMessage('gpsFixTrue') : chrome.i18n.getMessage('gpsFixFalse'));
+ gpsSats_e.text(GPS_DATA.numSat);
+ gpsLat_e.text((GPS_DATA.lat / 10000000).toFixed(4) + ' deg');
+ gpsLon_e.text((GPS_DATA.lon / 10000000).toFixed(4) + ' deg');
+ });
+ }
}
function get_fast_data() {
MSP.send_message(MSP_codes.MSP_ATTITUDE, false, false, function () {
heading_e.text(chrome.i18n.getMessage('initialSetupheading', [SENSOR_DATA.kinematics[2]]));
self.render3D();
+ self.updateInstruments();
});
}
@@ -183,6 +188,18 @@ TABS.setup.initialize = function (callback) {
}
};
+TABS.setup.initializeInstruments = function() {
+ var options = {size:90, showBox : false, img_directory: 'images/flightindicators/'};
+ var attitude = $.flightIndicator('#attitude', 'attitude', options);
+ var heading = $.flightIndicator('#heading', 'heading', options);
+
+ this.updateInstruments = function() {
+ attitude.setRoll(SENSOR_DATA.kinematics[0]);
+ attitude.setPitch(SENSOR_DATA.kinematics[1]);
+ heading.setHeading(SENSOR_DATA.kinematics[2]);
+ };
+};
+
TABS.setup.initialize3D = function (compatibility) {
var self = this,
loader, canvas, wrapper, renderer, camera, scene, light, light2, modelWrapper, model, model_file,
@@ -199,7 +216,7 @@ TABS.setup.initialize3D = function (compatibility) {
renderer = new THREE.WebGLRenderer({canvas: canvas.get(0), alpha: true, antialias: true});
useWebGlRenderer = true;
} else {
-
+
renderer = new THREE.CanvasRenderer({canvas: canvas.get(0), alpha: true});
}
@@ -212,7 +229,7 @@ TABS.setup.initialize3D = function (compatibility) {
} else {
model_file = 'fallback'
}
-
+
// Temporary workaround for 'custom' model until akfreak's custom model is merged.
var useLegacyCustomModel = false;
if (model_file == 'custom') {
@@ -254,6 +271,10 @@ TABS.setup.initialize3D = function (compatibility) {
scene.add(modelWrapper);
this.render3D = function () {
+ if (!model) {
+ return;
+ }
+
// compute the changes
model.rotation.x = (SENSOR_DATA.kinematics[1] * -1.0) * 0.017453292519943295;
modelWrapper.rotation.y = ((SENSOR_DATA.kinematics[2] * -1.0) - self.yaw_fix) * 0.017453292519943295;