67 lines
1.9 KiB
JavaScript
67 lines
1.9 KiB
JavaScript
// Clock simulation engine
|
|
import { state } from './state.js';
|
|
import { evaluateAll } from './gates.js';
|
|
import { forceRecordSample } from './waveform.js';
|
|
|
|
export function simTick() {
|
|
// Toggle all CLOCK gates
|
|
state.gates.forEach(g => {
|
|
if (g.type === 'CLOCK') {
|
|
g.value = g.value ? 0 : 1;
|
|
}
|
|
});
|
|
evaluateAll();
|
|
// Force record even if evaluateAll didn't detect change
|
|
if (state.recording && state.waveformVisible) {
|
|
forceRecordSample();
|
|
}
|
|
}
|
|
|
|
export function startSim() {
|
|
if (state.simRunning) return;
|
|
const hasClocks = state.gates.some(g => g.type === 'CLOCK');
|
|
if (!hasClocks) return;
|
|
|
|
state.simRunning = true;
|
|
|
|
// Auto-open waveform panel
|
|
if (!state.waveformVisible) {
|
|
state.waveformVisible = true;
|
|
document.getElementById('waveform-panel').classList.add('visible');
|
|
document.getElementById('sim-btn').classList.add('active');
|
|
// Trigger resize via event so renderer picks it up
|
|
window.dispatchEvent(new Event('resize'));
|
|
}
|
|
|
|
state.simInterval = setInterval(simTick, state.simSpeed);
|
|
updateSimUI();
|
|
}
|
|
|
|
export function stopSim() {
|
|
state.simRunning = false;
|
|
if (state.simInterval) clearInterval(state.simInterval);
|
|
state.simInterval = null;
|
|
updateSimUI();
|
|
}
|
|
|
|
export function updateSimUI() {
|
|
const btn = document.getElementById('sim-run-btn');
|
|
if (state.simRunning) {
|
|
btn.textContent = '⏹ Stop';
|
|
btn.classList.add('active');
|
|
} else {
|
|
btn.textContent = '▶ Run';
|
|
btn.classList.remove('active');
|
|
}
|
|
document.getElementById('sim-speed-label').textContent = `${state.simSpeed}ms`;
|
|
}
|
|
|
|
export function adjustSpeed(delta) {
|
|
state.simSpeed = Math.max(50, Math.min(2000, state.simSpeed + delta));
|
|
if (state.simRunning) {
|
|
clearInterval(state.simInterval);
|
|
state.simInterval = setInterval(simTick, state.simSpeed);
|
|
}
|
|
updateSimUI();
|
|
}
|