Browse Source

Parameter header generator

Benjamin Harris 1 tháng trước cách đây
mục cha
commit
c60ae9c0ff
2 tập tin đã thay đổi với 86 bổ sung0 xóa
  1. 1 0
      README.md
  2. 85 0
      params_html.h

+ 1 - 0
README.md

@@ -13,6 +13,7 @@ An Arduino sketch for the **Waveshare ESP32-S3 Zero** that provides a WiFi inter
 | **DSP soft reset** | `POST /dsp_reset` | Restart DSP execution without reloading EEPROM |
 | **GPIO register control** | `GET/POST /gpio` | Read and write GPIO All Register; GP0–GP3 toggle buttons in UI |
 | **Runtime parameter tuner** | `GET/POST /param` | Read/write any param RAM address live; safeload writes for glitch-free updates |
+| **Parameter header export** | — | Client-side export of `dsp_params.h` with `#define` constants for all tuner rows |
 | **NVS credential storage** | — | WiFi credentials stored in NVS; survive reboots |
 | **AP config portal** | SoftAP `ModulosDSP-Setup` | Browser-based WiFi setup on first boot or connect failure |
 | **WiFi credential reset** | `POST /wifi_reset` | Clear NVS and reboot into AP setup mode |

+ 85 - 0
params_html.h

@@ -62,6 +62,9 @@ static const char PARAMS_HTML[] PROGMEM = R"HTML(
       <button class="btn btn-outline-secondary btn-sm" onclick="readAll()">
         <i class="fa fa-refresh"></i> Read All
       </button>
+      <button class="btn btn-outline-secondary btn-sm" onclick="generateHeader()">
+        <i class="fa fa-file-code-o"></i> Export .h File
+      </button>
       <button class="btn btn-outline-danger btn-sm" onclick="clearRows()">
         <i class="fa fa-trash"></i> Clear All
       </button>
@@ -264,6 +267,88 @@ function saveState() {
   try { localStorage.setItem('modulos_dsp_params', JSON.stringify(rows)); } catch(e) {}
 }
 
+function toDefine(label, addr) {
+  var s = label.trim().toUpperCase();
+  s = s.replace(/[^A-Z0-9]+/g, '_');   // non-alphanumeric runs → underscore
+  s = s.replace(/^_+|_+$/g, '');        // trim leading/trailing underscores
+  if (!s || /^[0-9]/.test(s)) {
+    // empty or starts with digit — fall back to address
+    return 'PARAM_0x' + ('000' + addr.toString(16).toUpperCase()).slice(-4);
+  }
+  return 'PARAM_' + s;
+}
+
+function generateHeader() {
+  var rows = document.getElementById('paramRows').children;
+  if (rows.length === 0) {
+    alert('No parameters to export. Add some parameters first.');
+    return;
+  }
+
+  // Collect valid rows
+  var defines = [];
+  var seen = {};
+  for (var i = 0; i < rows.length; i++) {
+    var id = parseInt(rows[i].id.replace('row-', ''));
+    var addr = getAddr(id);
+    if (addr === null) continue;
+    var label = document.getElementById('lbl-' + id).value;
+    var name = toDefine(label, addr);
+    // Deduplicate: second occurrence becomes NAME_2, third NAME_3, etc.
+    if (seen[name]) {
+      seen[name]++;
+      name = name + '_' + seen[name];
+    } else {
+      seen[name] = 1;
+    }
+    defines.push({
+      name: name,
+      addr: '0x' + ('000' + addr.toString(16).toUpperCase()).slice(-4),
+      label: label.trim()
+    });
+  }
+
+  if (defines.length === 0) {
+    alert('No valid addresses found. Check address fields contain 0x0000–0x03FF.');
+    return;
+  }
+
+  // Align #define values to longest name
+  var maxLen = 0;
+  defines.forEach(function(d) { if (d.name.length > maxLen) maxLen = d.name.length; });
+
+  var now = new Date().toISOString().slice(0, 19).replace('T', ' ');
+  var host = window.location.hostname;
+  var lines = [
+    '// ModulosDSP — DSP Parameter Addresses',
+    '// Generated: ' + now,
+    '// Device:    ' + host,
+    '//',
+    '// Use with DSPWriter::safeload_writeRegister(PARAM_NAME, value, true);',
+    '//',
+    '#pragma once',
+    '',
+    '// Parameter RAM (ADAU1401/1701 — 5.23 fixed-point, 4 bytes/word, 0x0000–0x03FF)'
+  ];
+
+  defines.forEach(function(d) {
+    var pad = new Array(maxLen - d.name.length + 3).join(' ');
+    var comment = d.label ? ('  // ' + d.label) : '';
+    lines.push('#define ' + d.name + pad + d.addr + comment);
+  });
+
+  var content = lines.join('\n') + '\n';
+  var blob = new Blob([content], { type: 'text/plain' });
+  var url = URL.createObjectURL(blob);
+  var a = document.createElement('a');
+  a.href = url;
+  a.download = 'dsp_params.h';
+  document.body.appendChild(a);
+  a.click();
+  document.body.removeChild(a);
+  URL.revokeObjectURL(url);
+}
+
 function loadState() {
   try {
     var s = localStorage.getItem('modulos_dsp_params');