Revert to working waveform: timeStep += simSpeed, pxPerMs rendering

Restores the real-time ms-based waveform that correctly reflects
clock speed in wave width. Keeps the always-follow auto-scroll fix.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
Jose Luis Montañes
2026-03-19 22:43:24 +01:00
parent fd1173e113
commit 0f4fe27396

View File

@@ -31,8 +31,8 @@ export function recordSample() {
if (!changed && state.timeStep > 0) return; if (!changed && state.timeStep > 0) return;
// Each tick = 1 step (visual width determined by waveZoom px/step) // Manual toggles advance by simSpeed too for consistency
state.timeStep += 1; state.timeStep += state.simSpeed;
gates.forEach(g => { gates.forEach(g => {
if (!waveData[g.id]) waveData[g.id] = []; if (!waveData[g.id]) waveData[g.id] = [];
const arr = waveData[g.id]; const arr = waveData[g.id];
@@ -44,8 +44,8 @@ export function recordSample() {
} }
export function forceRecordSample() { export function forceRecordSample() {
// Each tick = 1 step // Advance time by the current simSpeed (in ms) to reflect real time
state.timeStep += 1; state.timeStep += state.simSpeed;
state.gates.forEach(g => { state.gates.forEach(g => {
if (!state.waveData[g.id]) state.waveData[g.id] = []; if (!state.waveData[g.id]) state.waveData[g.id] = [];
state.waveData[g.id].push({ t: state.timeStep, value: g.value }); state.waveData[g.id].push({ t: state.timeStep, value: g.value });
@@ -73,7 +73,10 @@ export function setEvaluateAll(fn) {
export function updateWaveInfo() { export function updateWaveInfo() {
const totalSamples = Object.values(state.waveData).reduce((sum, arr) => sum + arr.length, 0); const totalSamples = Object.values(state.waveData).reduce((sum, arr) => sum + arr.length, 0);
document.getElementById('wave-info').textContent = `T=${state.timeStep} | ${totalSamples} samples`; const timeLabel = state.timeStep >= 1000
? `${(state.timeStep/1000).toFixed(1)}s`
: `${state.timeStep}ms`;
document.getElementById('wave-info').textContent = `T=${timeLabel} | ${totalSamples} samples`;
} }
export function clearWaveData() { export function clearWaveData() {
@@ -123,33 +126,32 @@ export function drawWaveforms() {
return; return;
} }
// pxPerStep: how many pixels per simulation step // pxPerMs: how many pixels per millisecond of simulation time
const pxPerStep = state.waveZoom; const pxPerMs = state.waveZoom / 100; // waveZoom=20 → 0.2 px/ms
// Total width in pixels for all recorded time // Total width in pixels for all recorded time
const totalPx = state.timeStep * pxPerStep; const totalPx = state.timeStep * pxPerMs;
// Visible width in steps // Visible width in ms
const visibleSteps = wc.width / pxPerStep; const visibleMs = wc.width / pxPerMs;
// Auto-scroll: always follow the latest data, keep cursor at right edge // Auto-scroll: always follow the latest data, keep cursor at right edge
state.waveScroll = Math.max(0, state.timeStep - visibleSteps); state.waveScroll = Math.max(0, state.timeStep - visibleMs);
// Helper: convert simulation step to pixel X // Helper: convert simulation time (ms) to pixel X
const tToX = (t) => (t - state.waveScroll) * pxPerStep; const tToX = (t) => (t - state.waveScroll) * pxPerMs;
// Draw time grid (every gridStep steps) // Draw time grid (every gridMs milliseconds)
let gridStep = 5; let gridMs = 500;
if (pxPerStep * gridStep < 30) gridStep = 10; if (pxPerMs * gridMs < 30) gridMs = 1000;
if (pxPerStep * gridStep < 30) gridStep = 20; if (pxPerMs * gridMs < 30) gridMs = 2000;
if (pxPerStep * gridStep < 30) gridStep = 50; if (pxPerMs * gridMs > 200) gridMs = 200;
if (pxPerStep * gridStep > 200) gridStep = 2; if (pxPerMs * gridMs > 200) gridMs = 100;
if (pxPerStep * gridStep > 200) gridStep = 1;
wctx.strokeStyle = '#151520'; wctx.strokeStyle = '#151520';
wctx.lineWidth = 1; wctx.lineWidth = 1;
const startT = Math.floor(state.waveScroll / gridStep) * gridStep; const startT = Math.floor(state.waveScroll / gridMs) * gridMs;
for (let t = startT; t <= state.timeStep; t += gridStep) { for (let t = startT; t <= state.timeStep; t += gridMs) {
const x = tToX(t); const x = tToX(t);
if (x < 0 || x > wc.width) continue; if (x < 0 || x > wc.width) continue;
wctx.beginPath(); wctx.beginPath();
@@ -160,7 +162,8 @@ export function drawWaveforms() {
wctx.fillStyle = '#333'; wctx.fillStyle = '#333';
wctx.font = '9px monospace'; wctx.font = '9px monospace';
wctx.textAlign = 'center'; wctx.textAlign = 'center';
wctx.fillText(`${t}`, x, 10); const label = t >= 1000 ? `${(t/1000).toFixed(1)}s` : `${t}ms`;
wctx.fillText(label, x, 10);
} }
// Row dividers // Row dividers