UX changes for file selection, validations etc.
This commit is contained in:
parent
c59f2e1861
commit
47b8c219ff
@ -1254,6 +1254,7 @@ class ESPLoader {
|
|||||||
await this.run_stub();
|
await this.run_stub();
|
||||||
|
|
||||||
await this.change_baud();
|
await this.change_baud();
|
||||||
|
return chip;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
BIN
assets/esp-logo.png
Normal file
BIN
assets/esp-logo.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 18 KiB |
68
index.html
68
index.html
@ -5,6 +5,7 @@
|
|||||||
<title>ESP Tool</title>
|
<title>ESP Tool</title>
|
||||||
<link rel="stylesheet" href="styles.css" />
|
<link rel="stylesheet" href="styles.css" />
|
||||||
<link rel="stylesheet" href="node_modules/xterm/css/xterm.css" />
|
<link rel="stylesheet" href="node_modules/xterm/css/xterm.css" />
|
||||||
|
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.4.1/css/bootstrap.min.css">
|
||||||
<link
|
<link
|
||||||
href="https://fonts.googleapis.com/css?family=Orbitron"
|
href="https://fonts.googleapis.com/css?family=Orbitron"
|
||||||
rel="stylesheet"
|
rel="stylesheet"
|
||||||
@ -13,52 +14,63 @@
|
|||||||
<script src="node_modules/xterm/lib/xterm.js"></script>
|
<script src="node_modules/xterm/lib/xterm.js"></script>
|
||||||
<script src="https://cdnjs.cloudflare.com/ajax/libs/pako/2.0.3/pako.js"></script>
|
<script src="https://cdnjs.cloudflare.com/ajax/libs/pako/2.0.3/pako.js"></script>
|
||||||
<script src="node_modules/crypto-js/crypto-js.js"></script>
|
<script src="node_modules/crypto-js/crypto-js.js"></script>
|
||||||
|
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.4.1/js/bootstrap.min.js"></script>
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
<h1>ESP Tool</h1>
|
<h1 align="center"><p><img src="../assets/esp-logo.png" width="42" height="42" style="vertical-align:middle"></img> ESP Tool</p></h1>
|
||||||
<div>
|
<h4 align="center">A Serial Flasher utility for Espressif chips</h4>
|
||||||
|
<div class="container">
|
||||||
|
<hr/>
|
||||||
<div id="program">
|
<div id="program">
|
||||||
<h2> Program </h2>
|
<h3> Program </h3>
|
||||||
<label for="baudrates">Baudrate:</label>
|
<label for="baudrates" id="lblBaudrate">Baudrate:</label>
|
||||||
|
<label style="display:none" id="lblConnTo">Connected to device: </label>
|
||||||
<select name="baudrates" id="baudrates">
|
<select name="baudrates" id="baudrates">
|
||||||
<option value="921600">921600</option>
|
<option value="921600">921600</option>
|
||||||
<option value="460800">460800</option>
|
<option value="460800">460800</option>
|
||||||
<option value="230400">230400</option>
|
<option value="230400">230400</option>
|
||||||
<option value="115200">115200</option>
|
<option value="115200">115200</option>
|
||||||
</select>
|
</select>
|
||||||
<input class="button" type="button" id="connectButton" value="Connect" />
|
|
||||||
<input class="button" type="button" id="disconnectButton" value="Disconnect" />
|
<input class="btn btn-info btn-sm" type="button" id="connectButton" value="Connect" />
|
||||||
|
<input class="btn btn-warning btn-sm" type="button" id="disconnectButton" value="Disconnect" />
|
||||||
|
<input class="btn btn-danger btn-sm" type="button" id="eraseButton" value="Erase Flash" />
|
||||||
|
<br><br>
|
||||||
<div id="files">
|
<div id="files">
|
||||||
<br/>
|
<table class="table table-striped" id="fileTable">
|
||||||
<input class="button" type="button" id="eraseButton" value="Erase Flash" />
|
<thead class="thead-light">
|
||||||
<br/>
|
<tr>
|
||||||
<label for="offset1">Bootloader</label>
|
<th>Flash Address</th>
|
||||||
<input type="text" id="offset1" name="offset1" value="0x1000">
|
<th>Selected File</th>
|
||||||
<input type="file" id="selectFile1" name="selected_file1">
|
<th>Remove </th>
|
||||||
<br/>
|
</tr>
|
||||||
<label for="offset2">Partition table</label>
|
</thead>
|
||||||
<input type="text" id="offset2" name="offset2" value="0x8000">
|
<tbody id="tableBody">
|
||||||
<input type="file" id="selectFile2" name="selected_file2">
|
<tr id="row0">
|
||||||
<br/>
|
<td><input type="text" id="offset1" name="offset1" value="0x1000"></td>
|
||||||
<label for="offset3">App</label>
|
<td><input type="file" id="selectFile1" name="selected_file1"></td>
|
||||||
<input type="text" id="offset3" name="offset3" value="0x10000">
|
<td><button class="btn disabled"> Remove </button></td>
|
||||||
<input type="file" id="selectFile3" name="selected_file3">
|
</tr>
|
||||||
<br/>
|
</tbody>
|
||||||
<input class="button" type="button" id="programButton" value="Program" />
|
</table>
|
||||||
|
<input class="btn btn-info btn-sm" type="button" id="addFile" value="Add File" />
|
||||||
|
<input class="btn btn-info btn-sm" type="button" id="programButton" value="Program" />
|
||||||
</div>
|
</div>
|
||||||
<output id="list"></output>
|
<output id="list"></output>
|
||||||
<br/>
|
|
||||||
<hr/>
|
<hr/>
|
||||||
</div>
|
</div>
|
||||||
<div id="console">
|
<div id="console">
|
||||||
<h2>Console </h2>
|
<h3>Console </h3>
|
||||||
<input class="button" type="button" id="consoleStartButton" value="Start" />
|
<label style="display:none" id="lblConsoleFor">Connected to device: </label>
|
||||||
<input class="button" type="button" id="consoleStopButton" value="Stop" />
|
|
||||||
<input class="button" type="button" id="resetButton" value="Reset" />
|
<input class="btn btn-info" type="button" id="consoleStartButton" value="Start" />
|
||||||
|
<input class="btn btn-info" type="button" id="consoleStopButton" value="Stop" />
|
||||||
|
<input class="btn btn-info" type="button" id="resetButton" value="Reset" />
|
||||||
<hr/>
|
<hr/>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
|
||||||
<div id="terminal"></div>
|
<div id="terminal"></div>
|
||||||
|
</div>
|
||||||
|
|
||||||
<script src="index.js" type="module"></script>
|
<script src="index.js" type="module"></script>
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
|
165
index.js
165
index.js
@ -10,7 +10,10 @@ const filesDiv = document.getElementById("files");
|
|||||||
const terminal = document.getElementById("terminal");
|
const terminal = document.getElementById("terminal");
|
||||||
const programDiv = document.getElementById("program");
|
const programDiv = document.getElementById("program");
|
||||||
const consoleDiv = document.getElementById("console");
|
const consoleDiv = document.getElementById("console");
|
||||||
|
const lblBaudrate = document.getElementById("lblBaudrate");
|
||||||
|
const lblConnTo = document.getElementById("lblConnTo");
|
||||||
|
const tableBody = document.getElementById("tableBody");
|
||||||
|
const table = document.getElementById('fileTable');
|
||||||
|
|
||||||
//import { Transport } from './cp210x-webusb.js'
|
//import { Transport } from './cp210x-webusb.js'
|
||||||
import { Transport } from './webserial.js'
|
import { Transport } from './webserial.js'
|
||||||
@ -21,12 +24,14 @@ term.open(terminal);
|
|||||||
|
|
||||||
let device = null;
|
let device = null;
|
||||||
let transport;
|
let transport;
|
||||||
let chip;
|
let chip = "deFault";
|
||||||
let esploader;
|
let esploader;
|
||||||
let file1 = null, file2 = null, file3 = null;
|
let file1 = null;
|
||||||
let connected = false;
|
let connected = false;
|
||||||
|
let index = 1;
|
||||||
|
|
||||||
disconnectButton.style.display = "none";
|
disconnectButton.style.display = "none";
|
||||||
|
eraseButton.style.display = "none";
|
||||||
consoleStopButton.style.display = "none";
|
consoleStopButton.style.display = "none";
|
||||||
filesDiv.style.display = "none";
|
filesDiv.style.display = "none";
|
||||||
|
|
||||||
@ -47,7 +52,7 @@ function convertBinaryStringToUint8Array(bStr) {
|
|||||||
return u8_array;
|
return u8_array;
|
||||||
}
|
}
|
||||||
|
|
||||||
function handleFileSelect1(evt) {
|
function handleFileSelect(evt) {
|
||||||
var file = evt.target.files[0];
|
var file = evt.target.files[0];
|
||||||
console.log(file);
|
console.log(file);
|
||||||
var reader = new FileReader();
|
var reader = new FileReader();
|
||||||
@ -60,39 +65,12 @@ function handleFileSelect1(evt) {
|
|||||||
})(file);
|
})(file);
|
||||||
|
|
||||||
reader.readAsBinaryString(file);
|
reader.readAsBinaryString(file);
|
||||||
|
evt.target.data = file1;
|
||||||
}
|
}
|
||||||
|
|
||||||
function handleFileSelect2(evt) {
|
|
||||||
var file = evt.target.files[0];
|
|
||||||
console.log(file);
|
|
||||||
var reader = new FileReader();
|
|
||||||
|
|
||||||
reader.onload = (function(theFile) {
|
document.getElementById('selectFile1').addEventListener('change', handleFileSelect, false);
|
||||||
return function(e) {
|
|
||||||
file2 = e.target.result;
|
|
||||||
};
|
|
||||||
})(file);
|
|
||||||
|
|
||||||
reader.readAsBinaryString(file);
|
|
||||||
}
|
|
||||||
|
|
||||||
function handleFileSelect3(evt) {
|
|
||||||
var file = evt.target.files[0];
|
|
||||||
console.log(file);
|
|
||||||
var reader = new FileReader();
|
|
||||||
|
|
||||||
reader.onload = (function(theFile) {
|
|
||||||
return function(e) {
|
|
||||||
file3 = e.target.result;
|
|
||||||
};
|
|
||||||
})(file);
|
|
||||||
|
|
||||||
reader.readAsBinaryString(file);
|
|
||||||
}
|
|
||||||
|
|
||||||
document.getElementById('selectFile1').addEventListener('change', handleFileSelect1, false);
|
|
||||||
document.getElementById('selectFile2').addEventListener('change', handleFileSelect2, false);
|
|
||||||
document.getElementById('selectFile3').addEventListener('change', handleFileSelect3, false);
|
|
||||||
function _sleep(ms) {
|
function _sleep(ms) {
|
||||||
return new Promise(resolve => setTimeout(resolve, ms));
|
return new Promise(resolve => setTimeout(resolve, ms));
|
||||||
}
|
}
|
||||||
@ -113,15 +91,20 @@ connectButton.onclick = async () => {
|
|||||||
esploader = new ESPLoader(transport, baudrates.value, term);
|
esploader = new ESPLoader(transport, baudrates.value, term);
|
||||||
connected = true;
|
connected = true;
|
||||||
|
|
||||||
await esploader.main_fn();
|
chip = await esploader.main_fn();
|
||||||
|
|
||||||
await esploader.flash_id();
|
await esploader.flash_id();
|
||||||
} catch(e) {
|
} catch(e) {
|
||||||
}
|
}
|
||||||
|
|
||||||
console.log("Settings done");
|
console.log("Settings done for :" + chip);
|
||||||
|
lblBaudrate.style.display = "none";
|
||||||
|
lblConnTo.innerHTML = "Connected to device: " + chip;
|
||||||
|
lblConnTo.style.display = "block";
|
||||||
baudrates.style.display = "none";
|
baudrates.style.display = "none";
|
||||||
connectButton.style.display = "none";
|
connectButton.style.display = "none";
|
||||||
disconnectButton.style.display = "initial";
|
disconnectButton.style.display = "initial";
|
||||||
|
eraseButton.style.display = "initial";
|
||||||
filesDiv.style.display = "initial";
|
filesDiv.style.display = "initial";
|
||||||
consoleDiv.style.display = "none";
|
consoleDiv.style.display = "none";
|
||||||
}
|
}
|
||||||
@ -141,11 +124,57 @@ resetButton.onclick = async () => {
|
|||||||
|
|
||||||
eraseButton.onclick = async () => {
|
eraseButton.onclick = async () => {
|
||||||
eraseButton.disabled = true;
|
eraseButton.disabled = true;
|
||||||
console.log("Erase Flash");
|
|
||||||
await esploader.erase_flash();
|
await esploader.erase_flash();
|
||||||
eraseButton.disabled = false;
|
eraseButton.disabled = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
addFile.onclick = async () => {
|
||||||
|
var rowCount = table.rows.length;
|
||||||
|
var row = table.insertRow(rowCount);
|
||||||
|
|
||||||
|
//Column 1 - Offset
|
||||||
|
var cell1 = row.insertCell(0);
|
||||||
|
var element1 = document.createElement("input");
|
||||||
|
element1.type = "text";
|
||||||
|
element1.id = "offset" + rowCount;
|
||||||
|
element1.setAttribute('value', '0x8000');
|
||||||
|
cell1.appendChild(element1);
|
||||||
|
|
||||||
|
// Column 2 - File selector
|
||||||
|
var cell2 = row.insertCell(1);
|
||||||
|
var element2 = document.createElement("input");
|
||||||
|
element2.type = "file";
|
||||||
|
element2.id = "selectFile" + rowCount;
|
||||||
|
element2.name = "selected_File" + rowCount;
|
||||||
|
element2.addEventListener('change', handleFileSelect, false);
|
||||||
|
cell2.appendChild(element2);
|
||||||
|
|
||||||
|
// Column 3 - Remove File
|
||||||
|
var cell3 = row.insertCell(2);
|
||||||
|
var element3 = document.createElement("input");
|
||||||
|
element3.type = "button";
|
||||||
|
var btnName = "button" + rowCount;
|
||||||
|
element3.name = btnName;
|
||||||
|
element3.setAttribute('class', "btn");
|
||||||
|
element3.setAttribute('value', 'Remove'); // or element1.value = "button";
|
||||||
|
element3.onclick = function() {
|
||||||
|
removeRow(btnName);
|
||||||
|
}
|
||||||
|
cell3.appendChild(element3);
|
||||||
|
}
|
||||||
|
|
||||||
|
function removeRow(btnName) {
|
||||||
|
var rowCount = table.rows.length;
|
||||||
|
for (var i = 0; i < rowCount; i++) {
|
||||||
|
var row = table.rows[i];
|
||||||
|
var rowObj = row.cells[2].childNodes[0];
|
||||||
|
if (rowObj.name == btnName) {
|
||||||
|
table.deleteRow(i);
|
||||||
|
rowCount--;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
disconnectButton.onclick = async () => {
|
disconnectButton.onclick = async () => {
|
||||||
await transport.disconnect();
|
await transport.disconnect();
|
||||||
term.clear();
|
term.clear();
|
||||||
@ -153,6 +182,8 @@ disconnectButton.onclick = async () => {
|
|||||||
baudrates.style.display = "initial";
|
baudrates.style.display = "initial";
|
||||||
connectButton.style.display = "initial";
|
connectButton.style.display = "initial";
|
||||||
disconnectButton.style.display = "none";
|
disconnectButton.style.display = "none";
|
||||||
|
eraseButton.style.display = "none";
|
||||||
|
lblConnTo.style.display = "none";
|
||||||
filesDiv.style.display = "none";
|
filesDiv.style.display = "none";
|
||||||
consoleDiv.style.display = "initial";
|
consoleDiv.style.display = "initial";
|
||||||
};
|
};
|
||||||
@ -164,7 +195,7 @@ consoleStartButton.onclick = async () => {
|
|||||||
});
|
});
|
||||||
transport = new Transport(device);
|
transport = new Transport(device);
|
||||||
}
|
}
|
||||||
|
lblConsoleFor.style.display = "block";
|
||||||
consoleStartButton.style.display = "none";
|
consoleStartButton.style.display = "none";
|
||||||
consoleStopButton.style.display = "initial";
|
consoleStopButton.style.display = "initial";
|
||||||
programDiv.style.display = "none";
|
programDiv.style.display = "none";
|
||||||
@ -190,19 +221,57 @@ consoleStopButton.onclick = async () => {
|
|||||||
programDiv.style.display = "initial";
|
programDiv.style.display = "initial";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function validate_program_inputs() {
|
||||||
|
let offsetArr = []
|
||||||
|
var rowCount = table.rows.length;
|
||||||
|
var row;
|
||||||
|
let offset = 0;
|
||||||
|
let fileData = null;
|
||||||
|
|
||||||
|
// check for mandatory fields
|
||||||
|
for (let index = 1; index < rowCount; index ++) {
|
||||||
|
row = table.rows[index];
|
||||||
|
|
||||||
|
//offset fields checks
|
||||||
|
var offSetObj = row.cells[0].childNodes[0];
|
||||||
|
offset = parseInt(offSetObj.value);
|
||||||
|
|
||||||
|
// Non-numeric or blank offset
|
||||||
|
if (Number.isNaN(offset))
|
||||||
|
return "Offset field in row " + index + " is not a valid address!"
|
||||||
|
// Repeated offset used
|
||||||
|
else if (offsetArr.includes(offset))
|
||||||
|
return "Offset field in row " + index + " is already in use!";
|
||||||
|
else
|
||||||
|
offsetArr.push(offset);
|
||||||
|
|
||||||
|
var fileObj = row.cells[1].childNodes[0];
|
||||||
|
fileData = fileObj.data;
|
||||||
|
if (fileData == null)
|
||||||
|
return "No file selected for row: " + index + "!";
|
||||||
|
|
||||||
|
}
|
||||||
|
return "success"
|
||||||
|
}
|
||||||
|
|
||||||
programButton.onclick = async () => {
|
programButton.onclick = async () => {
|
||||||
|
var err = validate_program_inputs();
|
||||||
|
if (err != "success")
|
||||||
|
alert(err);
|
||||||
|
|
||||||
let fileArr = [];
|
let fileArr = [];
|
||||||
if (file1 != null) {
|
let offset = 0x1000;
|
||||||
let offset1 = parseInt(document.getElementById("offset1").value);
|
var rowCount = table.rows.length;
|
||||||
fileArr.push({data:file1, address:offset1});
|
var row;
|
||||||
}
|
for (let index = 1; index < rowCount; index ++) {
|
||||||
if (file2 != null) {
|
row = table.rows[index];
|
||||||
let offset2 = parseInt(document.getElementById("offset2").value);
|
var offSetObj = row.cells[0].childNodes[0];
|
||||||
fileArr.push({data:file2, address:offset2});
|
offset = parseInt(offSetObj.value);
|
||||||
}
|
|
||||||
if (file3 != null) {
|
var fileObj = row.cells[1].childNodes[0];
|
||||||
let offset3 = parseInt(document.getElementById("offset3").value);
|
|
||||||
fileArr.push({data:file3, address:offset3});
|
fileArr.push({data:fileObj.data, address:offset});
|
||||||
}
|
}
|
||||||
|
|
||||||
await esploader.write_flash({fileArray: fileArr, flash_size: 'keep'});
|
await esploader.write_flash({fileArray: fileArr, flash_size: 'keep'});
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user