From 0f22b92e35621d93179e1be3eaf99da8e92457c7 Mon Sep 17 00:00:00 2001 From: Nicholas Sherlock Date: Sat, 31 Jan 2015 00:41:41 +1300 Subject: [PATCH 01/10] Add dataflash tab: Very basic functionality is working --- _locales/en/messages.json | 11 +++- js/data_storage.js | 5 ++ js/gui.js | 1 + js/msp.js | 39 +++++++++++- main.html | 3 + main.js | 3 + tabs/dataflash.css | 81 ++++++++++++++++++++++++ tabs/dataflash.html | 14 ++++ tabs/dataflash.js | 130 ++++++++++++++++++++++++++++++++++++++ 9 files changed, 284 insertions(+), 3 deletions(-) create mode 100644 tabs/dataflash.css create mode 100644 tabs/dataflash.html create mode 100644 tabs/dataflash.js diff --git a/_locales/en/messages.json b/_locales/en/messages.json index f38f80d8..7efa5fbd 100755 --- a/_locales/en/messages.json +++ b/_locales/en/messages.json @@ -102,7 +102,9 @@ "tabLogging": { "message": "Logging" }, - + "tabDataflash": { + "message": "Dataflash" + }, "tabAdjustments": { "message": "Adjustments" }, @@ -843,6 +845,13 @@ "message": "Automatically loaded previous log file: $1" }, + "dataflashButtonSaveFile": { + "message": "Save flash to file..." + }, + "dataflashButtonErase": { + "message": "Erase flash" + }, + "firmwareFlasherReleaseSummaryHead": { "message": "Release info" }, diff --git a/js/data_storage.js b/js/data_storage.js index 7d3f4bcb..1c4e1fbb 100755 --- a/js/data_storage.js +++ b/js/data_storage.js @@ -149,3 +149,8 @@ var MISC = { vbatmaxcellvoltage: 0, vbatwarningcellvoltage: 0 }; + +var DATAFLASH = { + sectors: 0, + totalSize: 0 +}; \ No newline at end of file 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/msp.js b/js/msp.js index 309dc55c..bb03ecd5 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, @@ -666,8 +669,16 @@ var MSP = { case MSP_codes.MSP_SET_LED_STRIP_CONFIG: console.log('Led strip config saved'); break; - - + case MSP_codes.MSP_DATAFLASH_SUMMARY: + DATAFLASH.sectors = data.getUint32(0, 1); + DATAFLASH.totalSize = data.getUint32(4, 1); + break; + case MSP_codes.MSP_DATAFLASH_READ: + // No-op, let callback handle it + break; + case MSP_codes.MSP_DATAFLASH_ERASE: + console.log("Data flash erased"); + break; case MSP_codes.MSP_SET_MODE_RANGE: console.log('Mode range saved'); break; @@ -793,6 +804,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 = []; @@ -950,6 +964,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/main.html b/main.html index f6ace554..79bf742a 100755 --- a/main.html +++ b/main.html @@ -22,6 +22,7 @@ + @@ -68,6 +69,7 @@ + @@ -146,6 +148,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/tabs/dataflash.css b/tabs/dataflash.css new file mode 100644 index 00000000..669151b8 --- /dev/null +++ b/tabs/dataflash.css @@ -0,0 +1,81 @@ +.tab-dataflash { +} +.tab-dataflash .dataflash-info dd{ + +} + +.tab-dataflash .note { + padding: 5px; + border: 1px dashed silver; +} +.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 .back { + display: none; +} \ No newline at end of file diff --git a/tabs/dataflash.html b/tabs/dataflash.html new file mode 100644 index 00000000..8b227371 --- /dev/null +++ b/tabs/dataflash.html @@ -0,0 +1,14 @@ +
    +

    Dataflash

    +
    +
    Capacity (bytes)
    +
    +
    Capacity (sectors)
    +
    +
    + +
    + + +
    +
    \ No newline at end of file diff --git a/tabs/dataflash.js b/tabs/dataflash.js new file mode 100644 index 00000000..38d846d3 --- /dev/null +++ b/tabs/dataflash.js @@ -0,0 +1,130 @@ +'use strict'; + +TABS.dataflash = {}; +TABS.dataflash.initialize = function (callback) { + var self = this; + + 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", process_html); + }); + } + + function process_html() { + // translate to user-selected language + localize(); + + $(".tab-dataflash .dataflash-capacity").text(DATAFLASH.totalSize); + $(".tab-dataflash .dataflash-sectors").text(DATAFLASH.sectors); + + // UI hooks + $('.tab-dataflash a.erase_flash').click(erase_flash); + + $('.tab-dataflash a.save_to_file').click(stream_flash_to_file); + + if (callback) callback(); + } + + // IO related methods + function zeroPad(value, width) { + value = "" + value; + + while (value.length < width) { + value = "0" + value; + } + + return value; + } + + function stream_flash_to_file() { + if (GUI.connected_to) { + prepare_file(function(fileWriter) { + var + nextAddress = 0; + + function onChunkRead(chunkAddress, chunkDataView) { + // If we didn't get a zero-byte chunk (indicating end-of-file), request more + if (chunkDataView.byteLength > 0) { + var blob = new Blob([chunkDataView]); + + fileWriter.write(blob); + + nextAddress += chunkDataView.byteLength; + MSP.dataflashRead(nextAddress, onChunkRead); + } + } + + 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); + }); + + prepare_writer(fileEntry, onComplete); + }); + } + + function prepare_writer(fileEntry, onComplete) { + fileEntry.createWriter(function (fileWriter) { + fileWriter.onerror = function (e) { + console.error(e); + + // stop logging if the procedure was/is still running + }; + + fileWriter.onwriteend = function () { + }; + + onComplete(fileWriter); + }, function (e) { + // File is not readable or does not exist! + console.error(e); + }); + } + + function erase_flash() { + /* var dialog = $("lol"); + + $("body").append(dialog); + + dialog[0].showModal(); + + TODO modal dialog to confirm erase */ + + MSP.send_message(MSP_codes.MSP_DATAFLASH_ERASE, false, false, function(data) { + + }); + } +}; + +TABS.dataflash.cleanup = function (callback) { + if (callback) callback(); +}; \ No newline at end of file From 49741b45a83ec54c06f0f9af8f44fba87b779c77 Mon Sep 17 00:00:00 2001 From: Nicholas Sherlock Date: Fri, 13 Feb 2015 21:05:36 +1300 Subject: [PATCH 02/10] Add progress dialogs for flash save and erase --- _locales/en/messages.json | 31 ++++++- js/data_storage.js | 4 +- js/msp.js | 8 +- main.css | 11 +++ tabs/dataflash.css | 108 ++++++++++++++++++++- tabs/dataflash.html | 67 +++++++++++-- tabs/dataflash.js | 191 +++++++++++++++++++++++++++++--------- 7 files changed, 357 insertions(+), 63 deletions(-) diff --git a/_locales/en/messages.json b/_locales/en/messages.json index 7efa5fbd..364d4e44 100755 --- a/_locales/en/messages.json +++ b/_locales/en/messages.json @@ -845,13 +845,42 @@ "message": "Automatically loaded previous log file: $1" }, + "dataflashNote": { + "message": "Blackbox flight logs can be stored on the onboard dataflash chip if your flight controller supports one." + }, "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" }, diff --git a/js/data_storage.js b/js/data_storage.js index 1c4e1fbb..9e397de8 100755 --- a/js/data_storage.js +++ b/js/data_storage.js @@ -151,6 +151,8 @@ var MISC = { }; var DATAFLASH = { + ready: false, sectors: 0, - totalSize: 0 + totalSize: 0, + usedSize: 0 }; \ No newline at end of file diff --git a/js/msp.js b/js/msp.js index bb03ecd5..466266d1 100644 --- a/js/msp.js +++ b/js/msp.js @@ -670,14 +670,16 @@ var MSP = { console.log('Led strip config saved'); break; case MSP_codes.MSP_DATAFLASH_SUMMARY: - DATAFLASH.sectors = data.getUint32(0, 1); - DATAFLASH.totalSize = data.getUint32(4, 1); + 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); break; case MSP_codes.MSP_DATAFLASH_READ: // No-op, let callback handle it break; case MSP_codes.MSP_DATAFLASH_ERASE: - console.log("Data flash erased"); + console.log("Data flash erase begun..."); break; case MSP_codes.MSP_SET_MODE_RANGE: console.log('Mode range saved'); diff --git a/main.css b/main.css index cc8918d5..c0661677 100755 --- a/main.css +++ b/main.css @@ -353,3 +353,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/tabs/dataflash.css b/tabs/dataflash.css index 669151b8..50404d5b 100644 --- a/tabs/dataflash.css +++ b/tabs/dataflash.css @@ -1,12 +1,28 @@ -.tab-dataflash { -} -.tab-dataflash .dataflash-info dd{ - +.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; @@ -76,6 +92,88 @@ .tab-dataflash .buttons a:hover { background-color: #dedcdc; } -.tab-dataflash .buttons .back { +.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; } \ No newline at end of file diff --git a/tabs/dataflash.html b/tabs/dataflash.html index 8b227371..484372ca 100644 --- a/tabs/dataflash.html +++ b/tabs/dataflash.html @@ -1,14 +1,63 @@
    -

    Dataflash

    -
    -
    Capacity (bytes)
    -
    -
    Capacity (sectors)
    -
    -
    +
    +
    + + +

    +
    +
    + +
    +
    +

    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 index 38d846d3..e2460385 100644 --- a/tabs/dataflash.js +++ b/tabs/dataflash.js @@ -2,39 +2,93 @@ TABS.dataflash = {}; TABS.dataflash.initialize = function (callback) { - var self = this; + var + self = this, + saveCancelled, eraseCancelled; if (GUI.active_tab != 'dataflash') { GUI.active_tab = 'dataflash'; googleAnalytics.sendAppView('dataflash'); } - var requested_properties = [], + 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", process_html); + $('#content').load("./tabs/dataflash.html", function() { + create_html(); + }); }); } - function process_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() { // translate to user-selected language localize(); - $(".tab-dataflash .dataflash-capacity").text(DATAFLASH.totalSize); - $(".tab-dataflash .dataflash-sectors").text(DATAFLASH.sectors); - // UI hooks - $('.tab-dataflash a.erase_flash').click(erase_flash); - - $('.tab-dataflash a.save_to_file').click(stream_flash_to_file); + $('.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; @@ -46,21 +100,60 @@ TABS.dataflash.initialize = function (callback) { return value; } - function stream_flash_to_file() { + 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) { - var blob = new Blob([chunkDataView]); + nextAddress += chunkDataView.byteLength; + + $(".dataflash-saving progress").attr("value", nextAddress / maxBytes * 100); + + var + blob = new Blob([chunkDataView]); fileWriter.write(blob); - - nextAddress += chunkDataView.byteLength; - MSP.dataflashRead(nextAddress, onChunkRead); + + if (saveCancelled || nextAddress >= maxBytes) { + if (saveCancelled) { + dismiss_saving_dialog(); + } else { + mark_saving_dialog_done(); + } + } else { + MSP.dataflashRead(nextAddress, onChunkRead); + } + } else { + mark_saving_dialog_done(); } } @@ -88,41 +181,51 @@ TABS.dataflash.initialize = function (callback) { console.log('Dataflash dump file path: ' + path); }); - prepare_writer(fileEntry, onComplete); - }); - } + fileEntry.createWriter(function (fileWriter) { + fileWriter.onerror = function (e) { + console.error(e); - function prepare_writer(fileEntry, onComplete) { - fileEntry.createWriter(function (fileWriter) { - fileWriter.onerror = function (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); - - // stop logging if the procedure was/is still running - }; - - fileWriter.onwriteend = function () { - }; - - onComplete(fileWriter); - }, function (e) { - // File is not readable or does not exist! - console.error(e); + }); }); } - function erase_flash() { - /* var dialog = $("lol"); - - $("body").append(dialog); - - dialog[0].showModal(); - - TODO modal dialog to confirm erase */ - - MSP.send_message(MSP_codes.MSP_DATAFLASH_ERASE, false, false, function(data) { - + 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) { From ed285992da48e2d387e16411ec0379bf659d9b12 Mon Sep 17 00:00:00 2001 From: Nicholas Sherlock Date: Mon, 16 Feb 2015 18:05:24 +1300 Subject: [PATCH 03/10] Detect support for flash chip and disable tab if not available --- _locales/en/messages.json | 5 +- tabs/dataflash.css | 13 +++++ tabs/dataflash.html | 111 +++++++++++++++++++------------------- tabs/dataflash.js | 27 ++++++---- 4 files changed, 91 insertions(+), 65 deletions(-) diff --git a/_locales/en/messages.json b/_locales/en/messages.json index 364d4e44..939acaa7 100755 --- a/_locales/en/messages.json +++ b/_locales/en/messages.json @@ -846,7 +846,10 @@ }, "dataflashNote": { - "message": "Blackbox flight logs can be stored on the onboard dataflash chip if your flight controller supports one." + "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..." diff --git a/tabs/dataflash.css b/tabs/dataflash.css index 50404d5b..a6885d53 100644 --- a/tabs/dataflash.css +++ b/tabs/dataflash.css @@ -176,4 +176,17 @@ } .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 index 484372ca..a3a391a4 100644 --- a/tabs/dataflash.html +++ b/tabs/dataflash.html @@ -1,63 +1,66 @@
    -
    -
    - - -

    -
    +
    +
    -
    -
    -

    Erase in progress, please wait...

    + +

    +
    -
    + +
    +
    +

    Erase in progress, please wait...

    +
    +
    + +
    + + +
    +
    + + +

    +
    +
    +
    + + + +
    + +
    +
    +
    +
    +
    + +
    + +
    +
    +
    + +

    Dataflash contents

    +
      +
    • +
      + Used space +
      +
    • +
    • +
      + Free space +
      +
    • +
    - - + +
    - - - -

    -
    -
    -
    - - - -
    - -
    -
    -
    -
    -
    - -
    - -
    -
    -
    - -

    Dataflash contents

    -
      -
    • -
      - Used space -
      -
    • -
    • -
      - Free space -
      -
    • -
    - - -
    - - +
    +
    \ No newline at end of file diff --git a/tabs/dataflash.js b/tabs/dataflash.js index e2460385..90980c5c 100644 --- a/tabs/dataflash.js +++ b/tabs/dataflash.js @@ -71,20 +71,27 @@ TABS.dataflash.initialize = function (callback) { } function create_html() { + var + supportsDataflash = DATAFLASH.totalSize > 0; + // translate to user-selected language localize(); - // UI hooks - $('.tab-dataflash a.erase-flash').click(ask_to_erase_flash); + $(".tab-dataflash").toggleClass("supported", supportsDataflash); - $('.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 (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(); } From d0ae8dd9211c4800d52a969b49a88b1e9b98ba52 Mon Sep 17 00:00:00 2001 From: Nicholas Sherlock Date: Mon, 16 Feb 2015 19:13:09 +1300 Subject: [PATCH 04/10] Show "dataflash unsupported" for old versions missing new MSP commands --- js/msp.js | 16 ++++++++++++---- 1 file changed, 12 insertions(+), 4 deletions(-) diff --git a/js/msp.js b/js/msp.js index 2f09c20e..1fea8bb3 100644 --- a/js/msp.js +++ b/js/msp.js @@ -675,10 +675,18 @@ var MSP = { console.log('Led strip config saved'); break; case MSP_codes.MSP_DATAFLASH_SUMMARY: - 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); + 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 From f89aaa101136d91344ca42bce5f168253e3d184f Mon Sep 17 00:00:00 2001 From: Richard Birkby Date: Thu, 19 Feb 2015 20:39:57 +0000 Subject: [PATCH 05/10] Add flight instruments to setup tab --- _locales/en/messages.json | 29 +- images/flightindicators/altitude_pressure.svg | 106 +++++ images/flightindicators/altitude_ticks.svg | 96 +++++ images/flightindicators/fi_box.svg | 20 + images/flightindicators/fi_circle.svg | 23 ++ images/flightindicators/fi_needle.svg | 22 + images/flightindicators/fi_needle_small.svg | 27 ++ images/flightindicators/fi_tc_airplane.svg | 34 ++ images/flightindicators/heading_mechanics.svg | 49 +++ images/flightindicators/heading_yaw.svg | 205 ++++++++++ images/flightindicators/horizon_back.svg | 11 + images/flightindicators/horizon_ball.svg | 137 +++++++ images/flightindicators/horizon_circle.svg | 33 ++ images/flightindicators/horizon_mechanics.svg | 30 ++ images/flightindicators/speed_mechanics.svg | 61 +++ images/flightindicators/turn_coordinator.svg | 382 ++++++++++++++++++ .../flightindicators/vertical_mechanics.svg | 93 +++++ js/libraries/flightindicators.css | 52 +++ js/libraries/jquery.flightindicators.js | 173 ++++++++ main.html | 2 + tabs/gps.html | 2 +- tabs/modes.html | 2 +- tabs/motors.html | 4 +- tabs/setup.css | 8 +- tabs/setup.html | 7 +- tabs/setup.js | 26 +- 26 files changed, 1610 insertions(+), 24 deletions(-) create mode 100644 images/flightindicators/altitude_pressure.svg create mode 100644 images/flightindicators/altitude_ticks.svg create mode 100644 images/flightindicators/fi_box.svg create mode 100644 images/flightindicators/fi_circle.svg create mode 100644 images/flightindicators/fi_needle.svg create mode 100644 images/flightindicators/fi_needle_small.svg create mode 100644 images/flightindicators/fi_tc_airplane.svg create mode 100644 images/flightindicators/heading_mechanics.svg create mode 100644 images/flightindicators/heading_yaw.svg create mode 100644 images/flightindicators/horizon_back.svg create mode 100644 images/flightindicators/horizon_ball.svg create mode 100644 images/flightindicators/horizon_circle.svg create mode 100644 images/flightindicators/horizon_mechanics.svg create mode 100644 images/flightindicators/speed_mechanics.svg create mode 100644 images/flightindicators/turn_coordinator.svg create mode 100644 images/flightindicators/vertical_mechanics.svg create mode 100644 js/libraries/flightindicators.css create mode 100644 js/libraries/jquery.flightindicators.js diff --git a/_locales/en/messages.json b/_locales/en/messages.json index f38f80d8..7275ff4e 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." }, @@ -109,7 +109,7 @@ "tabAuxiliary": { "message": "Modes" }, - + "serialPortOpened": { "message": "Serial port successfully opened with ID: $1" }, @@ -122,21 +122,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 +352,9 @@ "initialSetupGPSHead": { "message": "GPS" }, + "initialSetupInstrumentsHead": { + "message": "Instruments" + }, "initialSetupButtonSave": { "message": "Save" }, @@ -402,7 +405,7 @@ }, "configurationFailsafe": { "message": "Receiver failsafe" - }, + }, "configurationRSSI": { "message": "RSSI (Signal Strength)" }, @@ -412,7 +415,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 +706,7 @@ "adjustmentsEepromSaved": { "message": "EEPROM saved" }, - + "servosModel": { "message": "Model:" @@ -843,7 +846,7 @@ "message": "Automatically loaded previous log file: $1" }, - "firmwareFlasherReleaseSummaryHead": { + "firmwareFlasherReleaseSummaryHead": { "message": "Release info" }, "firmwareFlasherReleaseName": { @@ -876,7 +879,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 +979,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/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 +CALIBRATEDTO25 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 PITCHINFORMATION + 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/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/main.html b/main.html index f6ace554..3ffd7778 100755 --- a/main.html +++ b/main.html @@ -7,6 +7,7 @@ + @@ -35,6 +36,7 @@ + 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/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..8eed6ef3 100644 --- a/tabs/motors.html +++ b/tabs/motors.html @@ -49,7 +49,7 @@
    - +
    Motors
      @@ -111,4 +111,4 @@
    - \ No newline at end of file + 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 865885e9..3c5cae13 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])); @@ -174,6 +176,10 @@ TABS.setup.initialize = function (callback) { heading_e.text(chrome.i18n.getMessage('initialSetupheading', [SENSOR_DATA.kinematics[2]])); self.render3D(); }); + + MSP.send_message(MSP_codes.MSP_RAW_IMU, false, false, function () { + self.updateInstruments(); + }); } GUI.interval_add('setup_data_pull_fast', get_fast_data, 33, true); // 30 fps @@ -183,6 +189,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.magnetometer[0] * 360); + }; +}; + TABS.setup.initialize3D = function (compatibility) { var self = this, loader, canvas, wrapper, renderer, camera, scene, light, light2, modelWrapper, model, model_file, @@ -199,7 +217,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 +230,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') { From 60b44d61fa00a7677ef2b52f5da004ec250dda16 Mon Sep 17 00:00:00 2001 From: Richard Birkby Date: Fri, 20 Feb 2015 01:52:09 +0000 Subject: [PATCH 06/10] Use correct heading value --- tabs/setup.js | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/tabs/setup.js b/tabs/setup.js index 3c5cae13..c4c2932d 100644 --- a/tabs/setup.js +++ b/tabs/setup.js @@ -175,10 +175,7 @@ TABS.setup.initialize = function (callback) { MSP.send_message(MSP_codes.MSP_ATTITUDE, false, false, function () { heading_e.text(chrome.i18n.getMessage('initialSetupheading', [SENSOR_DATA.kinematics[2]])); self.render3D(); - }); - - MSP.send_message(MSP_codes.MSP_RAW_IMU, false, false, function () { - self.updateInstruments(); + self.updateInstruments(); }); } @@ -197,7 +194,7 @@ TABS.setup.initializeInstruments = function() { this.updateInstruments = function() { attitude.setRoll(SENSOR_DATA.kinematics[0]); attitude.setPitch(SENSOR_DATA.kinematics[1]); - heading.setHeading(SENSOR_DATA.magnetometer[0] * 360); + heading.setHeading(SENSOR_DATA.kinematics[2]); }; }; From 31fd70935156d9fb78d8d346ee5800b028fa80ec Mon Sep 17 00:00:00 2001 From: Dominic Clifton Date: Fri, 20 Feb 2015 20:11:01 +0000 Subject: [PATCH 07/10] Update changelog, bump verson and prepare for release. --- changelog.html | 6 ++++++ js/data_storage.js | 2 +- manifest.json | 2 +- 3 files changed, 8 insertions(+), 2 deletions(-) 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/js/data_storage.js b/js/data_storage.js index 2ee6be15..31be24de 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, 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", From 7bdd010eb07b370530c8a3d9a648505879260e96 Mon Sep 17 00:00:00 2001 From: Dominic Clifton Date: Mon, 23 Feb 2015 21:27:55 +0000 Subject: [PATCH 08/10] Avoid using GPS commands for targets that do not have GPS support compiled in. --- js/serial_backend.js | 97 +++++++++++++++++++++++++++----------------- tabs/gps.js | 11 ++++- tabs/setup.js | 18 +++++--- 3 files changed, 81 insertions(+), 45 deletions(-) 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/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/setup.js b/tabs/setup.js index fe61d808..8e8f49f3 100644 --- a/tabs/setup.js +++ b/tabs/setup.js @@ -163,12 +163,14 @@ 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() { @@ -269,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; From 46a0054d784ba638435257ee6b75e5cea43f0983 Mon Sep 17 00:00:00 2001 From: Dominic Clifton Date: Tue, 24 Feb 2015 02:06:00 +0000 Subject: [PATCH 09/10] Add SVG watermark image to log view and some tabs. --- main.css | 32 ++++++++++++++++++++++---------- main.html | 2 +- tabs/cli.html | 1 + tabs/dataflash.html | 1 + tabs/logging.html | 1 + tabs/motors.html | 1 + tabs/pid_tuning.html | 1 + tabs/ports.html | 1 + tabs/receiver.html | 1 + tabs/sensors.html | 1 + 10 files changed, 31 insertions(+), 11 deletions(-) diff --git a/main.css b/main.css index c0661677..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 { diff --git a/main.html b/main.html index 432ef9c8..e7afaf49 100755 --- a/main.html +++ b/main.html @@ -126,7 +126,7 @@

    -
    CleanFlight
    +
    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.html b/tabs/dataflash.html index a3a391a4..70d46b89 100644 --- a/tabs/dataflash.html +++ b/tabs/dataflash.html @@ -1,3 +1,4 @@ +
    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/motors.html b/tabs/motors.html index 8eed6ef3..16314209 100644 --- a/tabs/motors.html +++ b/tabs/motors.html @@ -1,3 +1,4 @@ +
    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 @@ +

    From db6b44b1171832bf2b24dae40227692a1b7e5bd6 Mon Sep 17 00:00:00 2001 From: Dominic Clifton Date: Tue, 24 Feb 2015 22:32:55 +0000 Subject: [PATCH 10/10] Image missing from previous commit. --- images/light-wide-1.svg | 131 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 131 insertions(+) create mode 100644 images/light-wide-1.svg 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 + + + + + + + + + + + + + + + + + + + +