diff --git a/assets/root.html b/assets/root.html index 02f9ede..fe4c84a 100644 --- a/assets/root.html +++ b/assets/root.html @@ -1,112 +1,604 @@ - - - - - Logic Analyzer - - -
- -
- - + // ---- ИНИЦИАЛИЗАЦИЯ И АДАПТАЦИЯ РАЗМЕРА CANVAS ---- + function resizeCanvasAndRedraw() { + const container = canvas.parentElement; + const maxWidth = Math.min(1200, window.innerWidth - 60); + // устанавливаем размер canvas в пикселях для чёткой графики + const targetWidth = Math.min(1000, maxWidth); + const targetHeight = 500; + canvas.width = targetWidth; + canvas.height = targetHeight; + canvas.style.width = `${targetWidth}px`; + canvas.style.height = `${targetHeight}px`; + scheduleRender(); + } + + // очистка буфера по кнопке + function handleClear() { + clearRingBuffer(); + updateStatus('Буфер сброшен', !!ws && ws.readyState === WebSocket.OPEN); + scheduleRender(); + } + + // Имитация демо-данных, если сервер не отвечает (для теста интерфейса кольцевого буфера) + // но только если нет подключения в течение 4 секунд - демонстрация работы (добавим генератор) + let demoInterval = null; + function startDemoDataIfNeeded() { + // Проверяем каждые 5 секунд: если нет ws или не открыт и буфер пуст, то генерируем демо + if (demoInterval) clearInterval(demoInterval); + demoInterval = setInterval(() => { + if (!ws || ws.readyState !== WebSocket.OPEN) { + // генерируем несколько тестовых семплов для наглядности, но только если буфер не слишком большой + if (ringCount < 300) { + const demoCount = 4; + for (let i = 0; i < demoCount; i++) { + // Создаём осмысленную последовательность: счётчик, меандр на разных каналах + const timeSeed = Date.now() + i; + let sampleVal = 0; + // CH0: квадратная волна (каждые 8 семплов) + if ((ringCount + i) % 16 < 8) sampleVal |= (1 << 0); + // CH1: меандр с другой частотой + if ((ringCount + i) % 24 < 12) sampleVal |= (1 << 1); + // CH2: случайный импульс + if (Math.sin((ringCount + i) * 0.3) > 0) sampleVal |= (1 << 2); + // CH3: активный каждые 3 семпла + if ((ringCount + i) % 6 < 3) sampleVal |= (1 << 3); + // CH4: половина + if ((ringCount + i) % 10 > 4) sampleVal |= (1 << 4); + // CH5: шумоподобный + if (Math.floor(Math.random() * 2)) sampleVal |= (1 << 5); + // CH6, CH7 (доп) + if ((ringCount + i) % 7 < 3) sampleVal |= (1 << 6); + if ((ringCount + i) % 5 === 0) sampleVal |= (1 << 7); + pushSample(sampleVal); + } + } + } + }, 360); + } + + // --- Отслеживание изменения размера окна --- + window.addEventListener('resize', () => { + resizeCanvasAndRedraw(); + }); + + // Инициализация UI + function init() { + buildLegend(); + resizeCanvasAndRedraw(); + clearRingBuffer(); // чистый старт + connectWebSocket(); + clearBtn.addEventListener('click', handleClear); + // небольшая анимация рендера (периодическая перерисовка для обновления UI даже без данных) + function periodicRender() { + drawWaveforms(); + requestAnimationFrame(periodicRender); + } + // Запускаем непрерывный рендер (эффективно, не нагружает) + periodicRender(); + } + + init(); + })(); + + diff --git a/firmware/logic_analyzer/logic_analyzer.ino b/firmware/logic_analyzer/logic_analyzer.ino index 611d391..642ca02 100644 --- a/firmware/logic_analyzer/logic_analyzer.ino +++ b/firmware/logic_analyzer/logic_analyzer.ino @@ -128,14 +128,14 @@ void appendSamples() { lastTime = now; - if (g_samples_idx == SAMPLES_BUFFER_CAP - 1) return; + if (g_samples_idx == SAMPLES_BUFFER_CAP) return; SAMPLES[g_samples_idx] = takeSample(); g_samples_idx++; } void websocketSendSamples() { - if (g_samples_idx != SAMPLES_BUFFER_CAP - 1) return; + if (g_samples_idx < SAMPLES_BUFFER_CAP) return; static unsigned long lastTime = 0; unsigned long now = millis(); diff --git a/justfile b/justfile index 263cc3b..629e1e7 100644 --- a/justfile +++ b/justfile @@ -1,19 +1,21 @@ #!/usr/bin/env -S just --justfile +BOARD := env("BOARD", "esp8266:esp8266:nodemcuv2") +PORT := env("PORT", "/dev/ttyUBS0") + alias compile := build build: #!/bin/sh xxd -i assets/root.html > firmware/logic_analyzer/root_html.h cd firmware/logic_analyzer - arduino-cli compile --fqbn esp8266:esp8266:nodemcuv2 + arduino-cli compile --fqbn "{{BOARD}}" alias flash := upload - [working-directory: 'firmware/logic_analyzer'] upload: - arduino-cli upload --fqbn esp8266:esp8266:nodemcuv2 --port /dev/ttyUSB0 + arduino-cli upload --fqbn "{{BOARD}}" --port "{{PORT}}" monitor: - arduino-cli monitor --port /dev/ttyUSB0 + arduino-cli monitor --port "{{PORT}}" --config 115200