Functional v2

This commit is contained in:
Martino Ferrari
2026-05-18 23:28:29 +02:00
parent f06b948c0f
commit bdcdb39d21
3 changed files with 78 additions and 45 deletions
+55 -14
View File
@@ -187,7 +187,9 @@ function checkTrigger(sigs) {
}
}
function fireTrigger(t) {
trig.armed=false; trig.collecting=true; trig.trigTime=t; trig.snapshot=null;
// Clear the previous snapshot here (not in trigArm) so the last waveform
// and trigger marker stay visible while the trigger is rearmed and waiting.
trig.snapshot=null; trig.armed=false; trig.collecting=true; trig.trigTime=t;
updateTrigStatusBadge('waiting'); setAllCardsCollecting(true);
}
function finaliseTriggerCapture() {
@@ -214,7 +216,10 @@ function finaliseTriggerCapture() {
setTimeout(() => { if (trig.enabled && trig.mode==='normal' && !trig.stopped) trigArm(); }, 200);
}
function trigArm() {
trig.snapshot=null; trig.armed=true; trig.collecting=false; trig.prevVal=null;
// Do NOT clear trig.snapshot here — keep the last waveform and trigger marker
// visible while waiting for the next event. fireTrigger() clears it when a new
// trigger actually fires.
trig.armed=true; trig.collecting=false; trig.prevVal=null;
showRearmBtn(false); updateTrigStatusBadge('armed');
cursors.tA = null; cursors.tB = null; updateCursorReadout();
updateCursorBtnVisibility();
@@ -380,6 +385,30 @@ function fmtTrigTick(u, vals) {
});
}
// Draw a vertical marker line at x=0 (the trigger event) in trigger mode.
function drawTriggerMarker(u) {
if (!trig.enabled || !trig.snapshot) return;
const { ctx, bbox } = u;
if (!bbox) return;
const x = u.valToPos(0, 'x', true);
if (x < bbox.left || x > bbox.left + bbox.width) return;
const px = Math.round(x);
ctx.save();
ctx.strokeStyle = 'rgba(203,166,247,0.9)';
ctx.lineWidth = 1.5;
ctx.setLineDash([]);
ctx.beginPath();
ctx.moveTo(px, bbox.top);
ctx.lineTo(px, bbox.top + bbox.height);
ctx.stroke();
// Small "T" label
ctx.fillStyle = 'rgba(203,166,247,0.9)';
ctx.font = 'bold 10px monospace';
ctx.textBaseline = 'top';
ctx.fillText('T', px + 3, bbox.top + 2);
ctx.restore();
}
// Draw custom cursor A/B lines onto the canvas (called from draw hook)
function drawCursorLines(u) {
const { ctx, bbox } = u;
@@ -436,13 +465,13 @@ function makeUPlotOpts(p, inTrigMode) {
series: seriesArr,
axes: [
{ stroke:'#7f849c', grid:{ stroke:'#313244', width:1 }, ticks:{ stroke:'#313244', width:1 },
values: xVals, size: 40 },
values: xVals, size: 36, space: 90 },
{ stroke:'#7f849c', grid:{ stroke:'#313244', width:1 }, ticks:{ stroke:'#313244', width:1 }, size: 50 },
],
legend: { show: false },
padding: [4, 8, 0, 0],
padding: [4, 4, 0, 0],
hooks: {
draw: [ u => drawCursorLines(u) ],
draw: [ u => { drawCursorLines(u); drawTriggerMarker(u); } ],
// Two-hook zoom detection: setSelect flags that the NEXT setScale is user-initiated.
// uPlot fires setSelect → then immediately setScale (when drag.setScale:true).
// All programmatic setScale calls happen without a preceding setSelect, so the
@@ -989,7 +1018,16 @@ document.getElementById('trig-pre').addEventListener('input', e => {
trig.prePercent = parseInt(e.target.value, 10);
document.getElementById('trig-pre-val').textContent = trig.prePercent + '%';
});
document.getElementById('trig-mode').addEventListener('change', e => { trig.mode = e.target.value; });
document.getElementById('trig-mode').addEventListener('change', e => {
trig.mode = e.target.value;
// If a snapshot already exists the trigger has already fired — update button
// visibility immediately so it matches the newly selected mode.
if (trig.snapshot) {
showRearmBtn(trig.mode === 'single');
showStopBtn(trig.mode === 'normal');
updateStopBtn();
}
});
document.getElementById('btn-trig-rearm').addEventListener('click', () => { if (trig.enabled) trigArm(); });
document.getElementById('btn-trig-stop').addEventListener('click', () => {
if (!trig.enabled || trig.mode !== 'normal') return;
@@ -1076,7 +1114,7 @@ function layoutPlotCount(cls) {
// Build a small SVG grid thumbnail for a given cols×rows layout.
function layoutSVG(cols, rows) {
const W = 40, H = 28, GAP = 2, PAD = 2;
const W = 28, H = 20, GAP = 1.5, PAD = 1.5;
const cw = (W - PAD * 2 - GAP * (cols - 1)) / cols;
const ch = (H - PAD * 2 - GAP * (rows - 1)) / rows;
let rects = '';
@@ -1119,12 +1157,17 @@ function applyLayout(cls) {
deletePlot(removeId);
}
// Add missing plots.
// Add missing plots (DOM only — uPlot created below after layout settles).
while (plots.length < needed) addPlot();
setTimeout(() => plots.forEach(p => {
if (p.uplot) p.uplot.setSize({ width: p.div.clientWidth, height: p.div.clientHeight });
}), 120);
// Recreate all uPlot instances once the CSS grid has sized the cells.
// This also updates axis visibility (which axes show labels depends on grid position).
requestAnimationFrame(() => {
plots.forEach(p => createUPlot(p));
setTimeout(() => plots.forEach(p => {
if (p.uplot) p.uplot.setSize({ width: p.div.clientWidth, height: p.div.clientHeight });
}), 60);
});
}
function buildLayoutMenu() {
@@ -1218,9 +1261,7 @@ function addPlot() {
const plotBody = card.querySelector('#pbody-'+id);
const p = { id, traces:[], div: plotBody, needsRedraw:false, xRange:null, uplot:null, ro:null };
plots.push(p);
// Create the uPlot instance (empty) — deferred so DOM has settled
requestAnimationFrame(() => { createUPlot(p); });
// uPlot creation is handled by applyLayout (batch, after DOM settles).
return id;
}