From 0f22b92e35621d93179e1be3eaf99da8e92457c7 Mon Sep 17 00:00:00 2001 From: Nicholas Sherlock Date: Sat, 31 Jan 2015 00:41:41 +1300 Subject: [PATCH 1/4] 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 2/4] 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 3/4] 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 4/4] 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