import { createInjectionState } from "@vueuse/core"; import { shallowRef, reactive, ref, computed } from "vue"; import { Mutex } from "async-mutex"; import { CaptureConfig, CaptureStatus, LogicAnalyzerClient, GlobalCaptureMode, SignalOperator, SignalTriggerConfig, SignalValue, AnalyzerChannelDiv, AnalyzerClockDiv, } from "@/APIClient"; import { AuthManager } from "@/utils/AuthManager"; import { useAlertStore } from "@/components/Alert"; import { useRequiredInjection } from "@/utils/Common"; export type LogicDataType = { x: number[]; y: number[][]; // 8 channels of digital data (0 or 1) xUnit: "s" | "ms" | "us" | "ns"; }; // 通道接口定义 export type Channel = { enabled: boolean; label: string; color: string; }; // 全局模式选项 const globalModes = [ { value: GlobalCaptureMode.AND, label: "AND", description: "所有条件都满足时触发", }, { value: GlobalCaptureMode.OR, label: "OR", description: "任一条件满足时触发", }, { value: GlobalCaptureMode.NAND, label: "NAND", description: "AND的非" }, { value: GlobalCaptureMode.NOR, label: "NOR", description: "OR的非" }, ]; // 操作符选项 const operators = [ { value: SignalOperator.Equal, label: "=" }, { value: SignalOperator.NotEqual, label: "≠" }, { value: SignalOperator.LessThan, label: "<" }, { value: SignalOperator.LessThanOrEqual, label: "≤" }, { value: SignalOperator.GreaterThan, label: ">" }, { value: SignalOperator.GreaterThanOrEqual, label: "≥" }, ]; // 信号值选项 const signalValues = [ { value: SignalValue.Logic0, label: "0" }, { value: SignalValue.Logic1, label: "1" }, { value: SignalValue.NotCare, label: "X" }, { value: SignalValue.Rise, label: "↑" }, { value: SignalValue.Fall, label: "↓" }, { value: SignalValue.RiseOrFall, label: "↕" }, { value: SignalValue.NoChange, label: "—" }, { value: SignalValue.SomeNumber, label: "#" }, ]; // 通道组选项 const channelDivOptions = [ { value: 1, label: "1通道", description: "启用1个通道 (CH0)" }, { value: 2, label: "2通道", description: "启用2个通道 (CH0-CH1)" }, { value: 4, label: "4通道", description: "启用4个通道 (CH0-CH3)" }, { value: 8, label: "8通道", description: "启用8个通道 (CH0-CH7)" }, { value: 16, label: "16通道", description: "启用16个通道 (CH0-CH15)" }, { value: 32, label: "32通道", description: "启用32个通道 (CH0-CH31)" }, ]; const ClockDivOptions = [ { value: AnalyzerClockDiv.DIV1, label: "120MHz", description: "采样频率120MHz", }, { value: AnalyzerClockDiv.DIV2, label: "60MHz", description: "采样频率60MHz", }, { value: AnalyzerClockDiv.DIV4, label: "30MHz", description: "采样频率30MHz", }, { value: AnalyzerClockDiv.DIV8, label: "15MHz", description: "采样频率15MHz", }, { value: AnalyzerClockDiv.DIV16, label: "7.5MHz", description: "采样频率7.5MHz", }, { value: AnalyzerClockDiv.DIV32, label: "3.75MHz", description: "采样频率3.75MHz", }, { value: AnalyzerClockDiv.DIV64, label: "1.875MHz", description: "采样频率1.875MHz", }, { value: AnalyzerClockDiv.DIV128, label: "937.5KHz", description: "采样频率937.5KHz", }, ]; // 捕获深度限制常量 const CAPTURE_LENGTH_MIN = 1024; // 最小捕获深度 1024 const CAPTURE_LENGTH_MAX = 0x10000000 - 0x01000000; // 最大捕获深度 // 预捕获深度限制常量 const PRE_CAPTURE_LENGTH_MIN = 2; // 最小预捕获深度 2 // 默认颜色数组 const defaultColors = [ "#FF5733", "#33FF57", "#3357FF", "#FF33F5", "#F5FF33", "#33FFF5", "#FF8C33", "#8C33FF", ]; // 添加逻辑分析仪基础频率常量 const BASE_LOGIC_ANALYZER_FREQUENCY = 120_000_000; // 120MHz基础频率 const [useProvideLogicAnalyzer, useLogicAnalyzerState] = createInjectionState( () => { const logicData = shallowRef(); const alert = useRequiredInjection(useAlertStore); // 添加互斥锁 const operationMutex = new Mutex(); // 触发设置相关状态 const currentGlobalMode = ref(GlobalCaptureMode.AND); const currentChannelDiv = ref(8); // 默认启用8个通道 const captureLength = ref(CAPTURE_LENGTH_MIN); // 捕获深度,默认为最小值 const preCaptureLength = ref(PRE_CAPTURE_LENGTH_MIN); // 预捕获深度,默认0 const currentclockDiv = ref(AnalyzerClockDiv.DIV1); // 默认时钟分频为1 const isApplying = ref(false); const isCapturing = ref(false); // 添加捕获状态标识 // 通道配置 const channels = reactive( Array.from({ length: 32 }, (_, index) => ({ enabled: index < 8, // 默认启用前8个通道 label: `CH${index}`, color: defaultColors[index % defaultColors.length], // 使用模运算避免数组越界 })), ); // 32个信号通道的配置 const signalConfigs = reactive( Array.from( { length: 32 }, (_, index) => new SignalTriggerConfig({ signalIndex: index, operator: SignalOperator.Equal, value: SignalValue.NotCare, }), ), ); // 计算启用的通道数量 const enabledChannelCount = computed( () => channels.filter((channel) => channel.enabled).length, ); // 添加计算属性:获取通道名称数组 const channelNames = computed(() => channels.map((channel) => channel.label), ); // 添加计算属性:获取启用通道的名称数组 const enabledChannels = computed(() => channels.filter((channel) => channel.enabled), ); // 计算属性:根据当前时钟分频获取实际采样频率 const currentSampleFrequency = computed(() => { const divValue = Math.pow(2, currentclockDiv.value); return BASE_LOGIC_ANALYZER_FREQUENCY / divValue; }); // 计算属性:获取当前采样周期(纳秒) const currentSamplePeriodNs = computed(() => { return 1_000_000_000 / currentSampleFrequency.value; }); // 转换通道数字到枚举值 const getChannelDivEnum = (channelCount: number): AnalyzerChannelDiv => { switch (channelCount) { case 1: return AnalyzerChannelDiv.ONE; case 2: return AnalyzerChannelDiv.TWO; case 4: return AnalyzerChannelDiv.FOUR; case 8: return AnalyzerChannelDiv.EIGHT; case 16: return AnalyzerChannelDiv.XVI; case 32: return AnalyzerChannelDiv.XXXII; default: return AnalyzerChannelDiv.EIGHT; } }; // 验证捕获深度 const validateCaptureLength = ( value: number, ): { valid: boolean; message?: string } => { if (!Number.isInteger(value)) { return { valid: false, message: "捕获深度必须是整数" }; } if (value < CAPTURE_LENGTH_MIN) { return { valid: false, message: `捕获深度不能小于 ${CAPTURE_LENGTH_MIN}`, }; } if (value > CAPTURE_LENGTH_MAX) { return { valid: false, message: `捕获深度不能大于 ${CAPTURE_LENGTH_MAX.toLocaleString()}`, }; } return { valid: true }; }; // 验证预捕获深度 const validatePreCaptureLength = ( value: number, currentCaptureLength: number, ): { valid: boolean; message?: string } => { if (!Number.isInteger(value)) { return { valid: false, message: "预捕获深度必须是整数" }; } if (value < PRE_CAPTURE_LENGTH_MIN) { return { valid: false, message: `预捕获深度不能小于 ${PRE_CAPTURE_LENGTH_MIN}`, }; } if (value >= currentCaptureLength) { return { valid: false, message: `预捕获深度不能大于等于捕获深度 (${currentCaptureLength})`, }; } return { valid: true }; }; // 设置捕获深度 const setCaptureLength = (value: number) => { const validation = validateCaptureLength(value); if (!validation.valid) { alert?.error(validation.message!, 3000); return false; } // 检查预捕获深度是否仍然有效 if (preCaptureLength.value >= value) { preCaptureLength.value = Math.max(0, value - 1); alert?.warn(`预捕获深度已自动调整为 ${preCaptureLength.value}`, 3000); } captureLength.value = value; return true; }; // 设置预捕获深度 const setPreCaptureLength = (value: number) => { const validation = validatePreCaptureLength(value, captureLength.value); if (!validation.valid) { alert?.error(validation.message!, 3000); return false; } preCaptureLength.value = value; return true; }; // 设置通道组 const setChannelDiv = (channelCount: number) => { // 验证通道数量是否有效 if (!channelDivOptions.find((option) => option.value === channelCount)) { console.error(`无效的通道组设置: ${channelCount}`); return; } currentChannelDiv.value = channelCount; // 禁用所有通道 channels.forEach((channel) => { channel.enabled = false; }); // 启用指定数量的通道(从CH0开始) for (let i = 0; i < channelCount && i < channels.length; i++) { channels[i].enabled = true; } const option = channelDivOptions.find( (opt) => opt.value === channelCount, ); alert?.success(`已设置为${option?.label}`, 2000); }; const setGlobalMode = (mode: GlobalCaptureMode) => { currentGlobalMode.value = mode; const modeOption = globalModes.find((m) => m.value === mode); alert?.info(`全局触发模式已设置为 ${modeOption?.label}`, 2000); }; const setClockDiv = (mode: AnalyzerClockDiv) => { currentclockDiv.value = mode; const modeOption = ClockDivOptions.find((m) => m.value === mode); alert?.info(`时钟分频已设置为 ${modeOption?.label}`, 2000); }; const resetConfiguration = () => { currentGlobalMode.value = GlobalCaptureMode.AND; currentChannelDiv.value = 8; // 重置为默认的8通道 currentclockDiv.value = AnalyzerClockDiv.DIV1; // 重置为默认采样频率 setChannelDiv(8); // 重置为默认的8通道 signalConfigs.forEach((signal) => { signal.operator = SignalOperator.Equal; signal.value = SignalValue.NotCare; }); alert?.info("配置已重置", 2000); }; // 添加设置逻辑数据的方法 const setLogicData = (data: LogicDataType) => { logicData.value = data; }; const getCaptureData = async () => { try { const client = AuthManager.createClient(LogicAnalyzerClient); // 获取捕获数据,使用当前设置的捕获长度 const base64Data = await client.getCaptureData(captureLength.value); // 将base64数据转换为bytes const binaryString = atob(base64Data); const bytes = new Uint8Array(binaryString.length); for (let i = 0; i < binaryString.length; i++) { bytes[i] = binaryString.charCodeAt(i); } // 根据当前通道数量解析数据 const channelCount = currentChannelDiv.value; const timeStepNs = currentSamplePeriodNs.value; let sampleCount: number; let x: number[]; let y: number[][]; if (channelCount === 1) { // 1通道:每个字节包含8个时间单位的数据 sampleCount = bytes.length * 8; // 创建时间轴 x = Array.from( { length: sampleCount }, (_, i) => (i * timeStepNs) / 1000, ); // 转换为微秒 // 创建通道数据数组 y = Array.from({ length: 1 }, () => new Array(sampleCount)); // 解析数据:每个字节的8个位对应8个时间单位 for (let byteIndex = 0; byteIndex < bytes.length; byteIndex++) { const byte = bytes[byteIndex]; for (let bitIndex = 0; bitIndex < 8; bitIndex++) { const timeIndex = byteIndex * 8 + bitIndex; y[0][timeIndex] = (byte >> bitIndex) & 1; } } } else if (channelCount === 2) { // 2通道:每个字节包含4个时间单位的数据 sampleCount = bytes.length * 4; // 创建时间轴 x = Array.from( { length: sampleCount }, (_, i) => (i * timeStepNs) / 1000, ); // 转换为微秒 // 创建通道数据数组 y = Array.from({ length: 2 }, () => new Array(sampleCount)); // 解析数据:每个字节的8个位对应4个时间单位的2通道数据 // 位分布:[T3_CH1, T3_CH0, T2_CH1, T2_CH0, T1_CH1, T1_CH0, T0_CH1, T0_CH0] for (let byteIndex = 0; byteIndex < bytes.length; byteIndex++) { const byte = bytes[byteIndex]; for (let timeUnit = 0; timeUnit < 4; timeUnit++) { const timeIndex = byteIndex * 4 + timeUnit; const bitOffset = timeUnit * 2; y[0][timeIndex] = (byte >> bitOffset) & 1; // CH0 y[1][timeIndex] = (byte >> (bitOffset + 1)) & 1; // CH1 } } } else if (channelCount === 4) { // 4通道:每个字节包含2个时间单位的数据 sampleCount = bytes.length * 2; // 创建时间轴 x = Array.from( { length: sampleCount }, (_, i) => (i * timeStepNs) / 1000, ); // 转换为微秒 // 创建通道数据数组 y = Array.from({ length: 4 }, () => new Array(sampleCount)); // 解析数据:每个字节的8个位对应2个时间单位的4通道数据 // 位分布:[T1_CH3, T1_CH2, T1_CH1, T1_CH0, T0_CH3, T0_CH2, T0_CH1, T0_CH0] for (let byteIndex = 0; byteIndex < bytes.length; byteIndex++) { const byte = bytes[byteIndex]; // 处理第一个时间单位(低4位) const timeIndex1 = byteIndex * 2; for (let channel = 0; channel < 4; channel++) { y[channel][timeIndex1] = (byte >> channel) & 1; } // 处理第二个时间单位(高4位) const timeIndex2 = byteIndex * 2 + 1; for (let channel = 0; channel < 4; channel++) { y[channel][timeIndex2] = (byte >> (channel + 4)) & 1; } } } else if (channelCount === 8) { // 8通道:每个字节包含1个时间单位的8个通道数据 sampleCount = bytes.length; // 创建时间轴 x = Array.from( { length: sampleCount }, (_, i) => (i * timeStepNs) / 1000, ); // 转换为微秒 // 创建8个通道的数据 y = Array.from({ length: 8 }, () => new Array(sampleCount)); // 解析每个字节的8个位到对应通道 for (let i = 0; i < sampleCount; i++) { const byte = bytes[i]; for (let channel = 0; channel < 8; channel++) { // bit0对应ch0, bit1对应ch1, ..., bit7对应ch7 y[channel][i] = (byte >> channel) & 1; } } } else if (channelCount === 16) { // 16通道:每2个字节包含1个时间单位的16个通道数据 sampleCount = bytes.length / 2; // 创建时间轴 x = Array.from( { length: sampleCount }, (_, i) => (i * timeStepNs) / 1000, ); // 转换为微秒 // 创建16个通道的数据 y = Array.from({ length: 16 }, () => new Array(sampleCount)); // 解析数据:每2个字节为一个时间单位 for (let timeIndex = 0; timeIndex < sampleCount; timeIndex++) { const byteIndex = timeIndex * 2; const byte1 = bytes[byteIndex]; // [7:0] const byte2 = bytes[byteIndex + 1]; // [15:8] // 处理低8位通道 [7:0] for (let channel = 0; channel < 8; channel++) { y[channel][timeIndex] = (byte1 >> channel) & 1; } // 处理高8位通道 [15:8] for (let channel = 0; channel < 8; channel++) { y[channel + 8][timeIndex] = (byte2 >> channel) & 1; } } } else if (channelCount === 32) { // 32通道:每4个字节包含1个时间单位的32个通道数据 sampleCount = bytes.length / 4; // 创建时间轴 x = Array.from( { length: sampleCount }, (_, i) => (i * timeStepNs) / 1000, ); // 转换为微秒 // 创建32个通道的数据 y = Array.from({ length: 32 }, () => new Array(sampleCount)); // 解析数据:每4个字节为一个时间单位 for (let timeIndex = 0; timeIndex < sampleCount; timeIndex++) { const byteIndex = timeIndex * 4; const byte1 = bytes[byteIndex]; // [7:0] const byte2 = bytes[byteIndex + 1]; // [15:8] const byte3 = bytes[byteIndex + 2]; // [23:16] const byte4 = bytes[byteIndex + 3]; // [31:24] // 处理 [7:0] for (let channel = 0; channel < 8; channel++) { y[channel][timeIndex] = (byte1 >> channel) & 1; } // 处理 [15:8] for (let channel = 0; channel < 8; channel++) { y[channel + 8][timeIndex] = (byte2 >> channel) & 1; } // 处理 [23:16] for (let channel = 0; channel < 8; channel++) { y[channel + 16][timeIndex] = (byte3 >> channel) & 1; } // 处理 [31:24] for (let channel = 0; channel < 8; channel++) { y[channel + 24][timeIndex] = (byte4 >> channel) & 1; } } } else { throw new Error(`不支持的通道数量: ${channelCount}`); } // 设置逻辑数据 const logicData: LogicDataType = { x, y, xUnit: "us", // 微秒单位 }; setLogicData(logicData); } catch (error) { console.error("获取捕获数据失败:", error); alert?.error("获取捕获数据失败", 3000); } }; const startCapture = async () => { // 检查是否有其他操作正在进行 if (operationMutex.isLocked()) { alert.warn("有其他操作正在进行中,请稍后再试", 3000); return; } isCapturing.value = true; const release = await operationMutex.acquire(); try { const client = AuthManager.createClient(LogicAnalyzerClient); // 1. 先应用配置 alert?.info("正在应用配置...", 2000); // 准备配置数据 - 包含所有32个通道,未启用的通道设置为默认值 const allSignals = signalConfigs.map((signal, index) => { if (channels[index].enabled) { // 启用的通道使用用户配置的触发条件 return signal; } else { // 未启用的通道设置为默认触发条件 return new SignalTriggerConfig({ signalIndex: index, operator: SignalOperator.Equal, value: SignalValue.NotCare, }); } }); const config = new CaptureConfig({ globalMode: currentGlobalMode.value, channelDiv: getChannelDivEnum(currentChannelDiv.value), captureLength: captureLength.value, preCaptureLength: preCaptureLength.value, clockDiv: currentclockDiv.value, signalConfigs: allSignals, }); // 发送配置 const configSuccess = await client.configureCapture(config); if (!configSuccess) { throw new Error("配置应用失败"); } const enabledChannelCount = channels.filter((ch) => ch.enabled).length; alert?.success( `配置已应用,启用了 ${enabledChannelCount} 个通道,捕获深度: ${captureLength.value}`, 2000, ); // 2. 设置捕获模式为开始捕获 const captureStarted = await client.setCaptureMode(true, false); if (!captureStarted) { throw new Error("无法启动捕获"); } alert?.info("开始捕获信号...", 2000); // 3. 轮询捕获状态 let captureCompleted = false; while (isCapturing.value) { const status = await client.getCaptureStatus(); // 检查是否捕获完成 if (status === CaptureStatus.CaptureDone) { captureCompleted = true; break; } // 检查是否仍在捕获中 if ( status === CaptureStatus.CaptureBusy || status === CaptureStatus.CaptureOn || status === CaptureStatus.CaptureForce ) { // 等待500毫秒后继续轮询 await new Promise((resolve) => setTimeout(resolve, 500)); continue; } // 其他状态视为错误 // throw new Error(`捕获状态异常: ${status}`); } // 如果捕获被停止,不继续处理数据 if (!captureCompleted) { alert?.info("捕获已停止", 2000); return; } await getCaptureData(); alert.success(`捕获完成!`, 3000); } catch (error) { console.error("捕获失败:", error); alert?.error( `捕获失败: ${error instanceof Error ? error.message : "未知错误"}`, 3000, ); } finally { isCapturing.value = false; release(); } }; const stopCapture = async () => { // 检查是否正在捕获 if (!isCapturing.value) { alert.warn("当前没有正在进行的捕获操作", 2000); return; } // 设置捕获状态为false,这会使轮询停止 isCapturing.value = false; const release = await operationMutex.acquire(); try { const client = AuthManager.createClient(LogicAnalyzerClient); // 执行强制捕获来停止当前捕获 const forceSuccess = await client.setCaptureMode(false, false); if (!forceSuccess) { throw new Error("无法停止捕获"); } alert.info("已停止强制捕获...", 2000); } catch (error) { console.error("停止捕获失败:", error); alert.error( `停止捕获失败: ${error instanceof Error ? error.message : "未知错误"}`, 3000, ); } finally { release(); } }; const forceCapture = async () => { // 检查是否正在捕获 if (!isCapturing.value) { alert.warn("当前没有正在进行的捕获操作", 2000); return; } const release = await operationMutex.acquire(); try { const client = AuthManager.createClient(LogicAnalyzerClient); // 执行强制捕获来停止当前捕获 const forceSuccess = await client.setCaptureMode(true, true); if (!forceSuccess) { throw new Error("无法执行强制捕获"); } await getCaptureData(); alert.success(`强制捕获完成!`, 3000); } catch (error) { console.error("强制捕获失败:", error); alert.error( `强制捕获失败: ${error instanceof Error ? error.message : "未知错误"}`, 3000, ); } finally { release(); } }; // 添加检查操作状态的计算属性 const isOperationInProgress = computed( () => isApplying.value || isCapturing.value || operationMutex.isLocked(), ); // 添加生成测试数据的方法 const generateTestData = () => { const sampleRate = currentSampleFrequency.value; // 使用当前设置的采样频率 const duration = 0.001; // 1ms的数据 const points = Math.floor(sampleRate * duration); const x = Array.from( { length: points }, (_, i) => (i * currentSamplePeriodNs.value) / 1000, // 时间轴,单位:微秒 ); // Generate 8 channels with different digital patterns const y = [ // Channel 0: Clock signal 1MHz Array.from( { length: points }, (_, i) => Math.floor((1_000_000 * i) / sampleRate) % 2, ), // Channel 1: Clock/2 signal 500kHz Array.from( { length: points }, (_, i) => Math.floor((500_000 * i) / sampleRate) % 2, ), // Channel 2: Clock/4 signal 250kHz Array.from( { length: points }, (_, i) => Math.floor((250_000 * i) / sampleRate) % 2, ), // Channel 3: Clock/8 signal 125kHz Array.from( { length: points }, (_, i) => Math.floor((125_000 * i) / sampleRate) % 2, ), // Channel 4: Data signal (pseudo-random pattern) Array.from({ length: points }, (_, i) => Math.abs(Math.floor(Math.sin(i * 0.001) * 10) % 2), ), // Channel 5: Enable signal (periodic pulse) Array.from({ length: points }, (_, i) => Math.floor(i / 250) % 10 < 3 ? 1 : 0, ), // Channel 6: Reset signal (occasional pulse) Array.from({ length: points }, (_, i) => Math.floor(i / 1000) % 20 === 0 ? 1 : 0, ), // Channel 7: Status signal (slow changing) Array.from({ length: points }, (_, i) => Math.floor(i / 5000) % 2), ]; // 同时更新通道标签为更有意义的名称 const testChannelNames = [ "CLK", "CLK/2", "CLK/4", "CLK/8", "PWM", "ENABLE", "RESET", "STATUS", ]; channels.forEach((channel, index) => { channel.label = testChannelNames[index]; }); // 设置逻辑数据 setChannelDiv(8); setLogicData({ x, y, xUnit: "us" }); // 改为微秒单位 alert?.success("测试数据生成成功", 2000); }; return { // 原有的逻辑数据 logicData, // 触发设置状态 currentGlobalMode, currentChannelDiv, // 导出当前通道组状态 captureLength, // 导出捕获深度 preCaptureLength, // 导出预捕获深度 currentclockDiv, // 导出当前采样频率状态 isApplying, isCapturing, // 导出捕获状态 isOperationInProgress, // 导出操作进行状态 channels, signalConfigs, enabledChannelCount, channelNames, enabledChannels, currentSampleFrequency, // 导出当前采样频率 currentSamplePeriodNs, // 导出当前采样周期 // 选项数据 globalModes, operators, signalValues, channelDivOptions, // 导出通道组选项 ClockDivOptions, // 导出采样频率选项 // 捕获深度常量和验证 CAPTURE_LENGTH_MIN, CAPTURE_LENGTH_MAX, PRE_CAPTURE_LENGTH_MIN, validateCaptureLength, validatePreCaptureLength, setCaptureLength, setPreCaptureLength, // 触发设置方法 setChannelDiv, // 导出设置通道组方法 setGlobalMode, setClockDiv, // 导出设置采样频率方法 resetConfiguration, setLogicData, startCapture, forceCapture, stopCapture, generateTestData, }; }, ); export { useProvideLogicAnalyzer, useLogicAnalyzerState };