You've already forked torvalds-GuitarPedal
mirror of
https://github.com/torvalds/GuitarPedal.git
synced 2026-08-18 21:26:54 +00:00
'Software' was the directory everything that was not KiCad ended up in, which stopped describing anything a while ago - Validation and the web app are software too. Worse, it put the shared parts inside the firmware, where they read as the firmware's own. They are not. Effects/ has three consumers built from it: the firmware, Validation's bench, and the web app's controls, all generated from the same POT: comments by gen_effects.py. Audio/ has two - the bench compiles the same biquads, the same envelope followers and the same single_sample(), which is the whole reason a measurement on a workstation says anything about the pedal. Neither belongs under Firmware/, so neither is under it any more: Effects/ one file per effect Audio/ the DSP they are built from, and the audio loop Firmware/ the rest of what runs on the pedal, and the submodules WebMIDI/ the web app scripts/ what the build runs Validation/ unchanged Hardware/, Documentation/, Images/ CMakeLists.txt and the wrapper Makefile move to the top with them, because the build now consumes four of those directories and generates into a fifth. board.local and build/ come along; MIDI_CC_MAP.md is generated into Documentation/ rather than into the old Software/ root. scripts/ goes with the build rather than staying under the firmware, because six of the ten had nothing to do with the firmware: gen_effects.py reads Effects/ and writes to three different places, pow2/log2/quarter_sine generate Audio/'s tables, check-readme.py compares Effects/ against the README, and server.py serves the web app. Four of them are invoked from Validation, which was reaching into Firmware/ for tooling - the same burying this commit is undoing. The four that really are about the firmware are ELF checks the top-level build drives anyway, and a second scripts directory would only be a second place to look. C includes say "Audio/foo.h" and the generated map says "Effects/bar.h", with the repository root on the include path for both the firmware and the bench. Spelling the directory out rather than relying on a bare name is what keeps Audio/cycles.h shimmable: a quoted include searches the including file's own directory first. The submodules are renamed as well as moved. git mv updates their paths but leaves the section names, and 'Software/pico-sdk' surviving in .gitmodules would be the word this commit removes, still load-bearing. That meant the nested modules under pico-sdk too - six .git files pointing into .git/modules/Software - which is why 'git submodule update --init --recursive' is worth running once after pulling this. Verified rather than assumed: a clean configure and build, make check (failing only on the missing-eeprom case it already failed on), check-effects, all four analysis pages reproducing every series and drawing every chart, and a flash to the board that still measures a routed reverb where it did before. One latent bug fell out of it. bench/coeff declared only quarter_sine.h of the three generated math tables, and Audio/util.h includes pow2.h and log2.h as well - so building that target with an empty gen/ could never have worked. 'make bench' builds bench/bench first, which generates all three, so it stayed hidden until this rebuilt everything from nothing. Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
214 lines
9.6 KiB
HTML
214 lines
9.6 KiB
HTML
<!DOCTYPE html>
|
|
<html lang="en">
|
|
<head>
|
|
<meta charset="UTF-8">
|
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|
<title>RP2350 Pedal Controller</title>
|
|
<link rel="manifest" href="manifest.json">
|
|
<link rel="icon" type="image/x-icon" href="favicon.ico">
|
|
<link rel="apple-touch-icon" href="icon-192.png">
|
|
<link rel="stylesheet" href="style.css">
|
|
</head>
|
|
<body>
|
|
<div class="app-container">
|
|
<header class="glass-panel app-header">
|
|
<!-- Everything the header says, as opposed to everything it does.
|
|
None of it is worth a line of its own: the title is a device
|
|
name you already know, and the faults are absent nearly
|
|
always. Together they are one small line under the controls,
|
|
and the colour is what you actually read in the moment. -->
|
|
<div class="header-status">
|
|
<h1 id="app-title" class="title-disconnected">RP2350 Pedal</h1>
|
|
<div id="pedal-status" class="pedal-status hidden" role="status" aria-live="polite">
|
|
<span id="status-clip" class="status-clip hidden">CLIP</span>
|
|
<span id="status-drop" class="status-drop hidden">DROP</span>
|
|
<!-- Not a transient like the other two, but the same channel:
|
|
something is wrong and you want to know now. -->
|
|
<span id="status-board" class="status-board hidden" title="">BOARD</span>
|
|
<!-- Old but working hardware: worth noticing, not worth
|
|
alarming anybody about, so muted rather than red. -->
|
|
<span id="status-early" class="status-early hidden" title="">EARLY BOARD</span>
|
|
</div>
|
|
</div>
|
|
<div class="header-controls">
|
|
<div class="burger-wrap">
|
|
<button id="burger-btn" class="action-btn" title="Menu"
|
|
aria-haspopup="true" aria-expanded="false">☰</button>
|
|
<div id="global-menu" class="menu-dropdown hidden" role="menu">
|
|
<!-- The scene labels are filled in from the picker, so it
|
|
always says which one it is about to overwrite. -->
|
|
<button id="global-save-scene-btn" role="menuitem">💾 Save Scene</button>
|
|
<button id="global-load-scene-btn" role="menuitem">📂 Load Scene</button>
|
|
<button id="global-unroute-btn" role="menuitem">⏏ Unroute All Effects</button>
|
|
<hr>
|
|
<button id="update-app-btn" role="menuitem">⬇️ Update App</button>
|
|
<button id="open-bindings-btn" role="menuitem">🎛️ Physical Controls…</button>
|
|
<button id="open-settings-btn" role="menuitem">🔌 MIDI Connection…</button>
|
|
<hr>
|
|
<button id="global-program-btn" class="danger-item" role="menuitem">⚠️ Reboot to Programming Mode</button>
|
|
</div>
|
|
</div>
|
|
<!-- Which scene you're on is worth seeing without opening
|
|
anything. Acting on it is not: Save overwrites the eeprom
|
|
and Load throws away what you have, so both sit behind the
|
|
menu where you can't reach them by accident. -->
|
|
<div class="header-scenes">
|
|
<select id="global-scene-select" title="Scene">
|
|
<!-- Options injected via JS -->
|
|
</select>
|
|
</div>
|
|
<button id="tuner-btn" class="action-btn" title="Tuner Mode">🎵</button>
|
|
<label class="switch" title="Global Enable">
|
|
<input type="checkbox" id="global-enable">
|
|
<span class="slider round"></span>
|
|
</label>
|
|
</div>
|
|
</header>
|
|
|
|
<!-- Tuner Panel -->
|
|
<div id="tuner-panel" class="glass-panel hidden">
|
|
<div class="tuner-header">
|
|
<h2>Tuner</h2>
|
|
<div style="display: flex; gap: 15px; align-items: center;">
|
|
<label style="color: var(--text-muted); display: flex; align-items: center; gap: 8px; cursor: pointer;">
|
|
<input type="checkbox" id="tuner-synth-toggle"> Play Tones
|
|
</label>
|
|
<button id="close-tuner-btn" class="action-btn" title="Exit Tuner">✕</button>
|
|
</div>
|
|
</div>
|
|
<div class="tuner-chromatic-display">
|
|
<div class="tuner-note" id="tuner-chromatic-note">--</div>
|
|
<div class="tuner-cents" id="tuner-chromatic-cents">0¢</div>
|
|
<div class="tuner-vol" id="tuner-chromatic-vol">V: 0</div>
|
|
</div>
|
|
<div class="tuner-meter-container">
|
|
<div class="tuner-meter-center"></div>
|
|
<div id="tuner-needle" class="tuner-needle"></div>
|
|
</div>
|
|
<div class="tuner-strings" id="tuner-poly-strings">
|
|
<!-- Strings dynamically added here -->
|
|
</div>
|
|
</div>
|
|
|
|
<main id="effects-container">
|
|
<!-- Effect cards populated dynamically -->
|
|
</main>
|
|
|
|
<!-- Panel Backdrop -->
|
|
<div id="panel-backdrop" class="hidden"></div>
|
|
|
|
<!-- Reached from the menu. Set once and then left alone, which is
|
|
why it isn't in the menu itself. -->
|
|
<div id="settings-panel" class="glass-panel dialog-panel hidden" role="dialog" aria-modal="true">
|
|
<div class="panel-header">
|
|
<h2>MIDI Connection</h2>
|
|
<button id="close-settings" class="action-btn" title="Close">✕</button>
|
|
</div>
|
|
<div class="dialog-body">
|
|
<div class="menu-section">
|
|
<h3>Devices</h3>
|
|
<div class="menu-field">
|
|
<label for="midi-input-select">Input</label>
|
|
<select id="midi-input-select" class="menu-select"></select>
|
|
</div>
|
|
<div class="menu-field">
|
|
<label for="midi-output-select">Output</label>
|
|
<select id="midi-output-select" class="menu-select"></select>
|
|
</div>
|
|
</div>
|
|
<!-- What is on the other end. Here because this is the dialog
|
|
you open when something is not working, and "the pedal is
|
|
running firmware from before the change you are looking for"
|
|
is high on the list of reasons. -->
|
|
<div class="menu-section">
|
|
<h3>Pedal</h3>
|
|
<p class="menu-hint" id="identity-info">Not connected.</p>
|
|
</div>
|
|
<div class="menu-section">
|
|
<h3>Channel</h3>
|
|
<!-- The same value as the Settings card's "MIDI Ch" pot, and
|
|
the same control underneath - see bindMidiChannel(). It
|
|
is repeated here because this is where you come looking
|
|
when Control Change stops working, and the channel is the
|
|
usual reason. -->
|
|
<div class="menu-field">
|
|
<select id="midi-channel-select" class="menu-select"></select>
|
|
</div>
|
|
<p class="menu-hint">The pedal filters Control Change and Program
|
|
Change by this, so bypass, the tuner and scene changes need it to
|
|
match. Parameter edits are SysEx and work either way — which is
|
|
how this dialog can still fix it when it is wrong.</p>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- The pedal has one knob and one footswitch and no way at all to
|
|
say what either of them is for. This is where that gets said,
|
|
and it is the only place it is written down. -->
|
|
<div id="bindings-panel" class="glass-panel dialog-panel hidden" role="dialog" aria-modal="true">
|
|
<div class="panel-header">
|
|
<h2>Physical Controls</h2>
|
|
<button id="close-bindings" class="action-btn" title="Close">✕</button>
|
|
</div>
|
|
<div class="dialog-body">
|
|
<div class="menu-section">
|
|
<div id="bindings-rows"></div>
|
|
<p class="menu-hint" id="bindings-hint">Not connected.</p>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Active Pot Panel -->
|
|
<div id="active-pot-panel" class="glass-panel bottom-panel hidden">
|
|
<div class="panel-header">
|
|
<div class="active-pot-info">
|
|
<span id="active-pot-title">Effect - Pot</span>
|
|
<span id="active-pot-value" class="pot-value">0</span>
|
|
</div>
|
|
<button id="close-active-pot" class="action-btn" title="Close">✕</button>
|
|
</div>
|
|
<div class="active-pot-slider-container">
|
|
<input type="range" id="active-pot-slider" class="large-slider" min="0" max="120" value="60">
|
|
</div>
|
|
<!-- The knob is the one control you can reach without the app, so
|
|
the shortcut to point it here belongs next to the thing it
|
|
would be pointed at. -->
|
|
<div class="active-pot-knob">
|
|
<button id="assign-knob-btn" class="action-btn">Assign knob</button>
|
|
<span id="knob-target-hint" class="menu-hint"></span>
|
|
</div>
|
|
</div>
|
|
|
|
</div>
|
|
|
|
<script src="effects.js"></script>
|
|
<script src="app.js"></script>
|
|
<script>
|
|
// Keep the service worker away from local development. Unregistering
|
|
// one does not stop it controlling the page - the active worker stays
|
|
// in charge of already-controlled clients until they all go away - so
|
|
// a stale app.js can happily survive several reloads and an "Update
|
|
// App" or three. The PWA only matters for the deployed copy anyway.
|
|
//
|
|
// IS_LOCAL_DEV comes from app.js, which is loaded above.
|
|
if ('serviceWorker' in navigator) {
|
|
if (IS_LOCAL_DEV) {
|
|
// And clean up after any worker registered here previously
|
|
navigator.serviceWorker.getRegistrations()
|
|
.then(regs => regs.forEach(reg => reg.unregister()));
|
|
} else {
|
|
window.addEventListener('load', () => {
|
|
navigator.serviceWorker.register('./service-worker.js')
|
|
.then(registration => {
|
|
console.log('ServiceWorker registration successful');
|
|
})
|
|
.catch(err => {
|
|
console.log('ServiceWorker registration failed: ', err);
|
|
});
|
|
});
|
|
}
|
|
}
|
|
</script>
|
|
</body>
|
|
</html>
|