|
@@ -166,24 +166,33 @@ static const char INDEX_HTML[] PROGMEM = R"HTML(
|
|
|
</div>
|
|
</div>
|
|
|
<div class="card-body">
|
|
<div class="card-body">
|
|
|
<p class="text-muted small mb-3">I²C 0x50 • 32 768 bytes • 64-byte pages</p>
|
|
<p class="text-muted small mb-3">I²C 0x50 • 32 768 bytes • 64-byte pages</p>
|
|
|
- <form method="POST" action="/upload" enctype="multipart/form-data">
|
|
|
|
|
- <div class="mb-3">
|
|
|
|
|
- <label class="form-label fw-semibold">DSP firmware binary</label>
|
|
|
|
|
- <input class="form-control" type="file" name="bin" required>
|
|
|
|
|
- <div class="form-text">Export from SigmaStudio: <em>Action → Export System Files</em></div>
|
|
|
|
|
- </div>
|
|
|
|
|
- <div class="mb-3 form-check">
|
|
|
|
|
- <input class="form-check-input" type="checkbox" name="verify" value="1" id="verifyChk" checked>
|
|
|
|
|
- <label class="form-check-label" for="verifyChk">Verify after write (CRC32)</label>
|
|
|
|
|
|
|
+ <div class="mb-3">
|
|
|
|
|
+ <label class="form-label fw-semibold">DSP firmware binary</label>
|
|
|
|
|
+ <input class="form-control" type="file" id="binFile" accept=".bin">
|
|
|
|
|
+ <div class="form-text">Export from SigmaStudio: <em>Action → Export System Files</em></div>
|
|
|
|
|
+ </div>
|
|
|
|
|
+ <div class="mb-3 form-check">
|
|
|
|
|
+ <input class="form-check-input" type="checkbox" id="verifyChk" checked>
|
|
|
|
|
+ <label class="form-check-label" for="verifyChk">Verify after write (CRC32 readback)</label>
|
|
|
|
|
+ </div>
|
|
|
|
|
+ <button style="background-color:#114378;border-color:#114378;color:#e8b434;"
|
|
|
|
|
+ type="button" class="btn w-100" id="uploadBtn" onclick="startUpload()">
|
|
|
|
|
+ <i class="fa fa-upload"></i> Upload and Program
|
|
|
|
|
+ </button>
|
|
|
|
|
+
|
|
|
|
|
+ <!-- Progress -->
|
|
|
|
|
+ <div id="uploadProgress" style="display:none;" class="mt-3">
|
|
|
|
|
+ <div class="progress mb-2" style="height:6px;">
|
|
|
|
|
+ <div class="progress-bar progress-bar-striped progress-bar-animated"
|
|
|
|
|
+ style="width:100%;background-color:#114378;"></div>
|
|
|
</div>
|
|
</div>
|
|
|
- <button style="background-color:#114378;border-color:#114378;color:#e8b434;"
|
|
|
|
|
- type="submit" class="btn w-100">
|
|
|
|
|
- <i class="fa fa-upload"></i> Upload and Program
|
|
|
|
|
- </button>
|
|
|
|
|
- </form>
|
|
|
|
|
- <p class="mt-3 mb-0">
|
|
|
|
|
- <a href="/status" class="text-muted small">View upload status</a>
|
|
|
|
|
- </p>
|
|
|
|
|
|
|
+ <p class="text-center text-muted small mb-0">
|
|
|
|
|
+ <i class="fa fa-circle-o-notch fa-spin"></i> Writing to EEPROM…
|
|
|
|
|
+ </p>
|
|
|
|
|
+ </div>
|
|
|
|
|
+
|
|
|
|
|
+ <!-- Result -->
|
|
|
|
|
+ <div id="uploadResult" style="display:none;" class="mt-3"></div>
|
|
|
</div>
|
|
</div>
|
|
|
</div>
|
|
</div>
|
|
|
|
|
|
|
@@ -323,6 +332,59 @@ function toggleGpioPin(pin) {
|
|
|
fetchGpio();
|
|
fetchGpio();
|
|
|
setInterval(fetchGpio, 5000);
|
|
setInterval(fetchGpio, 5000);
|
|
|
|
|
|
|
|
|
|
+function startUpload() {
|
|
|
|
|
+ var fileInput = document.getElementById('binFile');
|
|
|
|
|
+ if (!fileInput.files || !fileInput.files.length) {
|
|
|
|
|
+ alert('Please select a firmware binary (.bin) first.');
|
|
|
|
|
+ return;
|
|
|
|
|
+ }
|
|
|
|
|
+ var file = fileInput.files[0];
|
|
|
|
|
+ var formData = new FormData();
|
|
|
|
|
+ if (document.getElementById('verifyChk').checked) formData.append('verify', '1');
|
|
|
|
|
+ formData.append('bin', file, file.name);
|
|
|
|
|
+
|
|
|
|
|
+ document.getElementById('uploadBtn').disabled = true;
|
|
|
|
|
+ document.getElementById('uploadProgress').style.display = 'block';
|
|
|
|
|
+ document.getElementById('uploadResult').style.display = 'none';
|
|
|
|
|
+
|
|
|
|
|
+ var xhr = new XMLHttpRequest();
|
|
|
|
|
+ xhr.open('POST', '/upload', true);
|
|
|
|
|
+ xhr.onload = function() {
|
|
|
|
|
+ document.getElementById('uploadProgress').style.display = 'none';
|
|
|
|
|
+ document.getElementById('uploadBtn').disabled = false;
|
|
|
|
|
+ var div = document.getElementById('uploadResult');
|
|
|
|
|
+ div.style.display = 'block';
|
|
|
|
|
+ if (xhr.status === 200) {
|
|
|
|
|
+ try {
|
|
|
|
|
+ var d = JSON.parse(xhr.responseText);
|
|
|
|
|
+ div.innerHTML =
|
|
|
|
|
+ '<div class="alert alert-success mb-0">' +
|
|
|
|
|
+ '<strong><i class="fa fa-check-circle"></i> Programmed OK</strong><br>' +
|
|
|
|
|
+ '<span class="small">Bytes written: <code>' + d.bytes + '</code></span><br>' +
|
|
|
|
|
+ '<span class="small">CRC32: <code>' + d.crc.toUpperCase() + '</code></span>' +
|
|
|
|
|
+ (d.verified ? '<br><span class="small"><i class="fa fa-check"></i> Verified against EEPROM readback</span>' : '') +
|
|
|
|
|
+ '</div>';
|
|
|
|
|
+ } catch(e) {
|
|
|
|
|
+ div.innerHTML = '<div class="alert alert-success mb-0"><i class="fa fa-check-circle"></i> Upload complete.</div>';
|
|
|
|
|
+ }
|
|
|
|
|
+ } else {
|
|
|
|
|
+ div.innerHTML =
|
|
|
|
|
+ '<div class="alert alert-danger mb-0">' +
|
|
|
|
|
+ '<strong><i class="fa fa-times-circle"></i> Upload failed</strong><br>' +
|
|
|
|
|
+ '<span class="small text-muted">Check the Serial monitor for details.</span>' +
|
|
|
|
|
+ '</div>';
|
|
|
|
|
+ }
|
|
|
|
|
+ };
|
|
|
|
|
+ xhr.onerror = function() {
|
|
|
|
|
+ document.getElementById('uploadProgress').style.display = 'none';
|
|
|
|
|
+ document.getElementById('uploadBtn').disabled = false;
|
|
|
|
|
+ var div = document.getElementById('uploadResult');
|
|
|
|
|
+ div.style.display = 'block';
|
|
|
|
|
+ div.innerHTML = '<div class="alert alert-danger mb-0"><i class="fa fa-times-circle"></i> Connection lost during upload.</div>';
|
|
|
|
|
+ };
|
|
|
|
|
+ xhr.send(formData);
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
function wifiReset() {
|
|
function wifiReset() {
|
|
|
if (!confirm('Clear WiFi credentials and reboot into setup mode?')) return;
|
|
if (!confirm('Clear WiFi credentials and reboot into setup mode?')) return;
|
|
|
var box = document.getElementById('wifiResetResult');
|
|
var box = document.getElementById('wifiResetResult');
|