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;
// Each tick = 1 step (visual width determined by waveZoom px/step)
state.timeStep += 1;
// Manual toggles advance by simSpeed too for consistency
state.timeStep += state.simSpeed;
gates.forEach(g => {
if (!waveData[g.id]) waveData[g.id] = [];
const arr = waveData[g.id];
@@ -44,8 +44,8 @@ export function recordSample() {
}
export function forceRecordSample() {
// Each tick = 1 step
state.timeStep += 1;
// Advance time by the current simSpeed (in ms) to reflect real time
state.timeStep += state.simSpeed;
state.gates.forEach(g => {
if (!state.waveData[g.id]) state.waveData[g.id] = [];
state.waveData[g.id].push({ t: state.timeStep, value: g.value });
@@ -73,7 +73,10 @@ export function setEvaluateAll(fn) {
export function updateWaveInfo() {
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() {
@@ -123,33 +126,32 @@ export function drawWaveforms() {
return;
}
// pxPerStep: how many pixels per simulation step
const pxPerStep = state.waveZoom;
// pxPerMs: how many pixels per millisecond of simulation time
const pxPerMs = state.waveZoom / 100; // waveZoom=20 → 0.2 px/ms
// Total width in pixels for all recorded time
const totalPx = state.timeStep * pxPerStep;
const totalPx = state.timeStep * pxPerMs;
// Visible width in steps
const visibleSteps = wc.width / pxPerStep;
// Visible width in ms
const visibleMs = wc.width / pxPerMs;
// 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
const tToX = (t) => (t - state.waveScroll) * pxPerStep;
// Helper: convert simulation time (ms) to pixel X
const tToX = (t) => (t - state.waveScroll) * pxPerMs;
// Draw time grid (every gridStep steps)
let gridStep = 5;
if (pxPerStep * gridStep < 30) gridStep = 10;
if (pxPerStep * gridStep < 30) gridStep = 20;
if (pxPerStep * gridStep < 30) gridStep = 50;
if (pxPerStep * gridStep > 200) gridStep = 2;
if (pxPerStep * gridStep > 200) gridStep = 1;
// Draw time grid (every gridMs milliseconds)
let gridMs = 500;
if (pxPerMs * gridMs < 30) gridMs = 1000;
if (pxPerMs * gridMs < 30) gridMs = 2000;
if (pxPerMs * gridMs > 200) gridMs = 200;
if (pxPerMs * gridMs > 200) gridMs = 100;
wctx.strokeStyle = '#151520';
wctx.lineWidth = 1;
const startT = Math.floor(state.waveScroll / gridStep) * gridStep;
for (let t = startT; t <= state.timeStep; t += gridStep) {
const startT = Math.floor(state.waveScroll / gridMs) * gridMs;
for (let t = startT; t <= state.timeStep; t += gridMs) {
const x = tToX(t);
if (x < 0 || x > wc.width) continue;
wctx.beginPath();
@@ -160,7 +162,8 @@ export function drawWaveforms() {
wctx.fillStyle = '#333';
wctx.font = '9px monospace';
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