add: 逻辑分析仪可设置采样频率
This commit is contained in:
		@@ -58,6 +58,10 @@ public class LogicAnalyzerController : ControllerBase
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        public AnalyzerChannelDiv ChannelDiv { get; set; } = AnalyzerChannelDiv.EIGHT;
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// 时钟分频系数
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        public AnalyzerClockDiv ClockDiv { get; set; } = AnalyzerClockDiv.DIV1;
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// 信号触发配置列表
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        public SignalTriggerConfig[] SignalConfigs { get; set; } = Array.Empty<SignalTriggerConfig>();
 | 
			
		||||
@@ -248,6 +252,7 @@ public class LogicAnalyzerController : ControllerBase
 | 
			
		||||
    /// <param name="capture_length">深度</param>
 | 
			
		||||
    /// <param name="pre_capture_length">预采样深度</param>
 | 
			
		||||
    /// <param name="channel_div">有效通道(0-[1],1-[2],2-[4],3-[8],4-[16],5-[32])</param>
 | 
			
		||||
    /// <param name="clock_div">采样时钟分频系数</param>
 | 
			
		||||
    /// <returns>操作结果</returns>
 | 
			
		||||
    [HttpPost("SetCaptureParams")]
 | 
			
		||||
    [EnableCors("Users")]
 | 
			
		||||
@@ -255,7 +260,7 @@ public class LogicAnalyzerController : ControllerBase
 | 
			
		||||
    [ProducesResponseType(StatusCodes.Status400BadRequest)]
 | 
			
		||||
    [ProducesResponseType(StatusCodes.Status500InternalServerError)]
 | 
			
		||||
    [ProducesResponseType(StatusCodes.Status401Unauthorized)]
 | 
			
		||||
    public async Task<IActionResult> SetCaptureParams(int capture_length, int pre_capture_length, AnalyzerChannelDiv channel_div)
 | 
			
		||||
    public async Task<IActionResult> SetCaptureParams(int capture_length, int pre_capture_length, AnalyzerChannelDiv channel_div, AnalyzerClockDiv clock_div)
 | 
			
		||||
    {
 | 
			
		||||
        try
 | 
			
		||||
        {
 | 
			
		||||
@@ -269,18 +274,18 @@ public class LogicAnalyzerController : ControllerBase
 | 
			
		||||
            if (analyzer == null)
 | 
			
		||||
                return BadRequest("用户未绑定有效的实验板");
 | 
			
		||||
 | 
			
		||||
            var result = await analyzer.SetCaptureParams(capture_length, pre_capture_length, channel_div);
 | 
			
		||||
            var result = await analyzer.SetCaptureParams(capture_length, pre_capture_length, channel_div, clock_div);
 | 
			
		||||
            if (!result.IsSuccessful)
 | 
			
		||||
            {
 | 
			
		||||
                logger.Error($"设置深度、预采样深度、有效通道失败: {result.Error}");
 | 
			
		||||
                return StatusCode(StatusCodes.Status500InternalServerError, "设置深度、预采样深度、有效通道失败");
 | 
			
		||||
                logger.Error($"设置深度、预采样深度、有效通道、时钟分频失败: {result.Error}");
 | 
			
		||||
                return StatusCode(StatusCodes.Status500InternalServerError, "设置深度、预采样深度、有效通道、时钟分频失败");
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            return Ok(result.Value);
 | 
			
		||||
        }
 | 
			
		||||
        catch (Exception ex)
 | 
			
		||||
        {
 | 
			
		||||
            logger.Error(ex, "设置深度、预采样深度、有效通道失败时发生异常");
 | 
			
		||||
            logger.Error(ex, "设置深度、预采样深度、有效通道、时钟分频失败时发生异常");
 | 
			
		||||
            return StatusCode(StatusCodes.Status500InternalServerError, "操作失败,请稍后重试");
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
@@ -332,7 +337,7 @@ public class LogicAnalyzerController : ControllerBase
 | 
			
		||||
            }
 | 
			
		||||
            // 设置深度、预采样深度、有效通道
 | 
			
		||||
            var paramsResult = await analyzer.SetCaptureParams(
 | 
			
		||||
                config.CaptureLength, config.PreCaptureLength, config.ChannelDiv);
 | 
			
		||||
                config.CaptureLength, config.PreCaptureLength, config.ChannelDiv, config.ClockDiv);
 | 
			
		||||
            if (!paramsResult.IsSuccessful)
 | 
			
		||||
            {
 | 
			
		||||
                logger.Error($"设置深度、预采样深度、有效通道失败: {paramsResult.Error}");
 | 
			
		||||
 
 | 
			
		||||
@@ -67,6 +67,7 @@ static class AnalyzerAddr
 | 
			
		||||
    public const UInt32 LOAD_NUM_ADDR = BASE + 0x0000_0002;
 | 
			
		||||
    public const UInt32 PRE_LOAD_NUM_ADDR = BASE + 0x0000_0003;
 | 
			
		||||
    public const UInt32 CAHNNEL_DIV_ADDR = BASE + 0x0000_0004;
 | 
			
		||||
    public const UInt32 CLOCK_DIV_ADDR = BASE + 0x0000_0005;
 | 
			
		||||
    public const UInt32 DMA1_START_WRITE_ADDR = DMA1_BASE + 0x0000_0012;
 | 
			
		||||
    public const UInt32 DMA1_END_WRITE_ADDR = DMA1_BASE + 0x0000_0013;
 | 
			
		||||
    public const UInt32 DMA1_CAPTURE_CTRL_ADDR = DMA1_BASE + 0x0000_0014;
 | 
			
		||||
@@ -138,6 +139,52 @@ public enum GlobalCaptureMode
 | 
			
		||||
    NOR = 0b11
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/// <summary>
 | 
			
		||||
/// 逻辑分析仪采样时钟分频系数
 | 
			
		||||
/// </summary>
 | 
			
		||||
public enum AnalyzerClockDiv
 | 
			
		||||
{
 | 
			
		||||
    /// <summary> 
 | 
			
		||||
    /// 1分频
 | 
			
		||||
    /// </summary>
 | 
			
		||||
    DIV1 = 0x0000_0000,
 | 
			
		||||
 | 
			
		||||
    /// <summary> 
 | 
			
		||||
    /// 2分频
 | 
			
		||||
    /// </summary>
 | 
			
		||||
    DIV2 = 0x0000_0001,
 | 
			
		||||
 | 
			
		||||
    /// <summary> 
 | 
			
		||||
    /// 4分频
 | 
			
		||||
    /// </summary>
 | 
			
		||||
    DIV4 = 0x0000_0002,
 | 
			
		||||
 | 
			
		||||
    /// <summary> 
 | 
			
		||||
    /// 8分频
 | 
			
		||||
    /// </summary>
 | 
			
		||||
    DIV8 = 0x0000_0003,
 | 
			
		||||
 | 
			
		||||
    /// <summary> 
 | 
			
		||||
    /// 16分频
 | 
			
		||||
    /// </summary>
 | 
			
		||||
    DIV16 = 0x0000_0004,
 | 
			
		||||
 | 
			
		||||
    /// <summary> 
 | 
			
		||||
    /// 32分频
 | 
			
		||||
    /// </summary>
 | 
			
		||||
    DIV32 = 0x0000_0005,
 | 
			
		||||
 | 
			
		||||
    /// <summary>
 | 
			
		||||
    /// 64分频
 | 
			
		||||
    /// </summary>
 | 
			
		||||
    DIV64 = 0x0000_0006,
 | 
			
		||||
 | 
			
		||||
    /// <summary>
 | 
			
		||||
    /// 128分频
 | 
			
		||||
    /// </summary>
 | 
			
		||||
    DIV128 = 0x0000_0007
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/// <summary>
 | 
			
		||||
/// 信号M的操作符枚举
 | 
			
		||||
/// </summary>
 | 
			
		||||
@@ -387,13 +434,14 @@ public class Analyzer
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /// <summary>
 | 
			
		||||
    /// 设置逻辑分析仪的深度、预采样深度、有效通道
 | 
			
		||||
    /// 设置逻辑分析仪的深度、预采样深度、有效通道、分频系数
 | 
			
		||||
    /// </summary>
 | 
			
		||||
    /// <param name="capture_length">深度</param>
 | 
			
		||||
    /// <param name="pre_capture_length">预采样深度</param>
 | 
			
		||||
    /// <param name="channel_div">有效通道(0-[1],1-[2],2-[4],3-[8],4-[16],5-[32])</param>
 | 
			
		||||
    /// <param name="clock_div">采样时钟分频系数</param>
 | 
			
		||||
    /// <returns>操作结果,成功返回true,否则返回异常信息</returns>
 | 
			
		||||
    public async ValueTask<Result<bool>> SetCaptureParams(int capture_length, int pre_capture_length, AnalyzerChannelDiv channel_div)
 | 
			
		||||
    public async ValueTask<Result<bool>> SetCaptureParams(int capture_length, int pre_capture_length, AnalyzerChannelDiv channel_div, AnalyzerClockDiv clock_div)
 | 
			
		||||
    {
 | 
			
		||||
        if (capture_length == 0) capture_length = 1;
 | 
			
		||||
        if (pre_capture_length == 0) pre_capture_length = 1;
 | 
			
		||||
@@ -462,6 +510,19 @@ public class Analyzer
 | 
			
		||||
                return new(new Exception("Failed to set CAHNNEL_DIV_ADDR"));
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
        {
 | 
			
		||||
            var ret = await UDPClientPool.WriteAddr(this.ep, this.taskID, AnalyzerAddr.CLOCK_DIV_ADDR, (UInt32)clock_div, this.timeout);
 | 
			
		||||
            if (!ret.IsSuccessful)
 | 
			
		||||
            {
 | 
			
		||||
                logger.Error($"Failed to set CLOCK_DIV_ADDR: {ret.Error}");
 | 
			
		||||
                return new(ret.Error);
 | 
			
		||||
            }
 | 
			
		||||
            if (!ret.Value)
 | 
			
		||||
            {
 | 
			
		||||
                logger.Error("WriteAddr to CLOCK_DIV_ADDR returned false");
 | 
			
		||||
                return new(new Exception("Failed to set CLOCK_DIV_ADDR"));
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
        return true;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -16,7 +16,7 @@ public class HttpHdmiVideoStreamService : BackgroundService
 | 
			
		||||
{
 | 
			
		||||
    private readonly NLog.Logger logger = NLog.LogManager.GetCurrentClassLogger();
 | 
			
		||||
    private HttpListener? _httpListener;
 | 
			
		||||
    private readonly int _serverPort = 4322;
 | 
			
		||||
    private readonly int _serverPort = 6666;
 | 
			
		||||
    private readonly ConcurrentDictionary<string, HdmiIn> _hdmiInDict = new();
 | 
			
		||||
    private bool _isEnabled = true;
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -3948,9 +3948,10 @@ export class LogicAnalyzerClient {
 | 
			
		||||
     * @param capture_length (optional) 深度
 | 
			
		||||
     * @param pre_capture_length (optional) 预采样深度
 | 
			
		||||
     * @param channel_div (optional) 有效通道(0-[1],1-[2],2-[4],3-[8],4-[16],5-[32])
 | 
			
		||||
     * @param clock_div (optional) 采样时钟分频系数
 | 
			
		||||
     * @return 操作结果
 | 
			
		||||
     */
 | 
			
		||||
    setCaptureParams(capture_length: number | undefined, pre_capture_length: number | undefined, channel_div: AnalyzerChannelDiv | undefined, cancelToken?: CancelToken): Promise<boolean> {
 | 
			
		||||
    setCaptureParams(capture_length: number | undefined, pre_capture_length: number | undefined, channel_div: AnalyzerChannelDiv | undefined, clock_div: AnalyzerClockDiv | undefined, cancelToken?: CancelToken): Promise<boolean> {
 | 
			
		||||
        let url_ = this.baseUrl + "/api/LogicAnalyzer/SetCaptureParams?";
 | 
			
		||||
        if (capture_length === null)
 | 
			
		||||
            throw new Error("The parameter 'capture_length' cannot be null.");
 | 
			
		||||
@@ -3964,6 +3965,10 @@ export class LogicAnalyzerClient {
 | 
			
		||||
            throw new Error("The parameter 'channel_div' cannot be null.");
 | 
			
		||||
        else if (channel_div !== undefined)
 | 
			
		||||
            url_ += "channel_div=" + encodeURIComponent("" + channel_div) + "&";
 | 
			
		||||
        if (clock_div === null)
 | 
			
		||||
            throw new Error("The parameter 'clock_div' cannot be null.");
 | 
			
		||||
        else if (clock_div !== undefined)
 | 
			
		||||
            url_ += "clock_div=" + encodeURIComponent("" + clock_div) + "&";
 | 
			
		||||
        url_ = url_.replace(/[?&]$/, "");
 | 
			
		||||
 | 
			
		||||
        let options_: AxiosRequestConfig = {
 | 
			
		||||
@@ -8233,6 +8238,18 @@ export enum AnalyzerChannelDiv {
 | 
			
		||||
    XXXII = 5,
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/** 逻辑分析仪采样时钟分频系数 */
 | 
			
		||||
export enum AnalyzerClockDiv {
 | 
			
		||||
    DIV1 = 0,
 | 
			
		||||
    DIV2 = 1,
 | 
			
		||||
    DIV4 = 2,
 | 
			
		||||
    DIV8 = 3,
 | 
			
		||||
    DIV16 = 4,
 | 
			
		||||
    DIV32 = 5,
 | 
			
		||||
    DIV64 = 6,
 | 
			
		||||
    DIV128 = 7,
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/** 捕获配置 */
 | 
			
		||||
export class CaptureConfig implements ICaptureConfig {
 | 
			
		||||
    /** 全局触发模式 */
 | 
			
		||||
@@ -8243,6 +8260,8 @@ export class CaptureConfig implements ICaptureConfig {
 | 
			
		||||
    preCaptureLength!: number;
 | 
			
		||||
    /** 有效通道 */
 | 
			
		||||
    channelDiv!: AnalyzerChannelDiv;
 | 
			
		||||
    /** 时钟分频系数 */
 | 
			
		||||
    clockDiv!: AnalyzerClockDiv;
 | 
			
		||||
    /** 信号触发配置列表 */
 | 
			
		||||
    signalConfigs!: SignalTriggerConfig[];
 | 
			
		||||
 | 
			
		||||
@@ -8264,6 +8283,7 @@ export class CaptureConfig implements ICaptureConfig {
 | 
			
		||||
            this.captureLength = _data["captureLength"];
 | 
			
		||||
            this.preCaptureLength = _data["preCaptureLength"];
 | 
			
		||||
            this.channelDiv = _data["channelDiv"];
 | 
			
		||||
            this.clockDiv = _data["clockDiv"];
 | 
			
		||||
            if (Array.isArray(_data["signalConfigs"])) {
 | 
			
		||||
                this.signalConfigs = [] as any;
 | 
			
		||||
                for (let item of _data["signalConfigs"])
 | 
			
		||||
@@ -8285,6 +8305,7 @@ export class CaptureConfig implements ICaptureConfig {
 | 
			
		||||
        data["captureLength"] = this.captureLength;
 | 
			
		||||
        data["preCaptureLength"] = this.preCaptureLength;
 | 
			
		||||
        data["channelDiv"] = this.channelDiv;
 | 
			
		||||
        data["clockDiv"] = this.clockDiv;
 | 
			
		||||
        if (Array.isArray(this.signalConfigs)) {
 | 
			
		||||
            data["signalConfigs"] = [];
 | 
			
		||||
            for (let item of this.signalConfigs)
 | 
			
		||||
@@ -8304,6 +8325,8 @@ export interface ICaptureConfig {
 | 
			
		||||
    preCaptureLength: number;
 | 
			
		||||
    /** 有效通道 */
 | 
			
		||||
    channelDiv: AnalyzerChannelDiv;
 | 
			
		||||
    /** 时钟分频系数 */
 | 
			
		||||
    clockDiv: AnalyzerClockDiv;
 | 
			
		||||
    /** 信号触发配置列表 */
 | 
			
		||||
    signalConfigs: SignalTriggerConfig[];
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -10,6 +10,7 @@ import {
 | 
			
		||||
  SignalTriggerConfig,
 | 
			
		||||
  SignalValue,
 | 
			
		||||
  AnalyzerChannelDiv,
 | 
			
		||||
  AnalyzerClockDiv,
 | 
			
		||||
} from "@/APIClient";
 | 
			
		||||
import { AuthManager } from "@/utils/AuthManager";
 | 
			
		||||
import { useAlertStore } from "@/components/Alert";
 | 
			
		||||
@@ -30,16 +31,8 @@ export type Channel = {
 | 
			
		||||
 | 
			
		||||
// 全局模式选项
 | 
			
		||||
const globalModes = [
 | 
			
		||||
  {
 | 
			
		||||
    value: GlobalCaptureMode.AND,
 | 
			
		||||
    label: "AND",
 | 
			
		||||
    description: "所有条件都满足时触发",
 | 
			
		||||
  },
 | 
			
		||||
  {
 | 
			
		||||
    value: GlobalCaptureMode.OR,
 | 
			
		||||
    label: "OR",
 | 
			
		||||
    description: "任一条件满足时触发",
 | 
			
		||||
  },
 | 
			
		||||
  {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的非" },
 | 
			
		||||
];
 | 
			
		||||
@@ -76,12 +69,23 @@ const channelDivOptions = [
 | 
			
		||||
  { 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 = 0; // 最小预捕获深度 0
 | 
			
		||||
const PRE_CAPTURE_LENGTH_MIN = 2; // 最小预捕获深度 2
 | 
			
		||||
 | 
			
		||||
// 默认颜色数组
 | 
			
		||||
const defaultColors = [
 | 
			
		||||
@@ -95,9 +99,8 @@ const defaultColors = [
 | 
			
		||||
  "#8C33FF",
 | 
			
		||||
];
 | 
			
		||||
 | 
			
		||||
// 添加逻辑分析仪频率常量
 | 
			
		||||
const LOGIC_ANALYZER_FREQUENCY = 125_000_000; // 125MHz
 | 
			
		||||
const SAMPLE_PERIOD_NS = 1_000_000_000 / LOGIC_ANALYZER_FREQUENCY; // 采样周期,单位:纳秒
 | 
			
		||||
// 添加逻辑分析仪基础频率常量
 | 
			
		||||
const BASE_LOGIC_ANALYZER_FREQUENCY = 120_000_000; // 120MHz基础频率
 | 
			
		||||
 | 
			
		||||
const [useProvideLogicAnalyzer, useLogicAnalyzerState] = createInjectionState(
 | 
			
		||||
  () => {
 | 
			
		||||
@@ -112,6 +115,7 @@ const [useProvideLogicAnalyzer, useLogicAnalyzerState] = createInjectionState(
 | 
			
		||||
    const currentChannelDiv = ref<number>(8); // 默认启用8个通道
 | 
			
		||||
    const captureLength = ref<number>(CAPTURE_LENGTH_MIN); // 捕获深度,默认为最小值
 | 
			
		||||
    const preCaptureLength = ref<number>(PRE_CAPTURE_LENGTH_MIN); // 预捕获深度,默认0
 | 
			
		||||
    const currentclockDiv = ref<AnalyzerClockDiv>(AnalyzerClockDiv.DIV1); // 默认时钟分频为1
 | 
			
		||||
    const isApplying = ref(false);
 | 
			
		||||
    const isCapturing = ref(false); // 添加捕获状态标识
 | 
			
		||||
 | 
			
		||||
@@ -152,6 +156,17 @@ const [useProvideLogicAnalyzer, useLogicAnalyzerState] = createInjectionState(
 | 
			
		||||
      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) {
 | 
			
		||||
@@ -252,9 +267,16 @@ const [useProvideLogicAnalyzer, useLogicAnalyzerState] = createInjectionState(
 | 
			
		||||
      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) => {
 | 
			
		||||
@@ -285,7 +307,7 @@ const [useProvideLogicAnalyzer, useLogicAnalyzerState] = createInjectionState(
 | 
			
		||||
 | 
			
		||||
        // 根据当前通道数量解析数据
 | 
			
		||||
        const channelCount = currentChannelDiv.value;
 | 
			
		||||
        const timeStepNs = SAMPLE_PERIOD_NS;
 | 
			
		||||
        const timeStepNs = currentSamplePeriodNs.value;
 | 
			
		||||
        
 | 
			
		||||
        let sampleCount: number;
 | 
			
		||||
        let x: number[];
 | 
			
		||||
@@ -528,6 +550,7 @@ const [useProvideLogicAnalyzer, useLogicAnalyzerState] = createInjectionState(
 | 
			
		||||
          channelDiv: getChannelDivEnum(currentChannelDiv.value),
 | 
			
		||||
          captureLength: captureLength.value,
 | 
			
		||||
          preCaptureLength: preCaptureLength.value,
 | 
			
		||||
          clockDiv: currentclockDiv.value,
 | 
			
		||||
          signalConfigs: allSignals,
 | 
			
		||||
        });
 | 
			
		||||
 | 
			
		||||
@@ -666,13 +689,13 @@ const [useProvideLogicAnalyzer, useLogicAnalyzerState] = createInjectionState(
 | 
			
		||||
 | 
			
		||||
    // 添加生成测试数据的方法
 | 
			
		||||
    const generateTestData = () => {
 | 
			
		||||
      const sampleRate = LOGIC_ANALYZER_FREQUENCY; // 使用实际的逻辑分析仪频率
 | 
			
		||||
      const sampleRate = currentSampleFrequency.value; // 使用当前设置的采样频率
 | 
			
		||||
      const duration = 0.001; // 1ms的数据
 | 
			
		||||
      const points = Math.floor(sampleRate * duration);
 | 
			
		||||
 | 
			
		||||
      const x = Array.from(
 | 
			
		||||
        { length: points },
 | 
			
		||||
        (_, i) => (i * SAMPLE_PERIOD_NS) / 1000, // 时间轴,单位:微秒
 | 
			
		||||
        (_, i) => (i * currentSamplePeriodNs.value) / 1000, // 时间轴,单位:微秒
 | 
			
		||||
      );
 | 
			
		||||
 | 
			
		||||
      // Generate 8 channels with different digital patterns
 | 
			
		||||
@@ -745,6 +768,7 @@ const [useProvideLogicAnalyzer, useLogicAnalyzerState] = createInjectionState(
 | 
			
		||||
      currentChannelDiv, // 导出当前通道组状态
 | 
			
		||||
      captureLength, // 导出捕获深度
 | 
			
		||||
      preCaptureLength, // 导出预捕获深度
 | 
			
		||||
      currentclockDiv, // 导出当前采样频率状态
 | 
			
		||||
      isApplying,
 | 
			
		||||
      isCapturing, // 导出捕获状态
 | 
			
		||||
      isOperationInProgress, // 导出操作进行状态
 | 
			
		||||
@@ -753,12 +777,15 @@ const [useProvideLogicAnalyzer, useLogicAnalyzerState] = createInjectionState(
 | 
			
		||||
      enabledChannelCount,
 | 
			
		||||
      channelNames,
 | 
			
		||||
      enabledChannels,
 | 
			
		||||
      currentSampleFrequency, // 导出当前采样频率
 | 
			
		||||
      currentSamplePeriodNs, // 导出当前采样周期
 | 
			
		||||
 | 
			
		||||
      // 选项数据
 | 
			
		||||
      globalModes,
 | 
			
		||||
      operators,
 | 
			
		||||
      signalValues,
 | 
			
		||||
      channelDivOptions, // 导出通道组选项
 | 
			
		||||
      ClockDivOptions, // 导出采样频率选项
 | 
			
		||||
 | 
			
		||||
      // 捕获深度常量和验证
 | 
			
		||||
      CAPTURE_LENGTH_MIN,
 | 
			
		||||
@@ -772,6 +799,7 @@ const [useProvideLogicAnalyzer, useLogicAnalyzerState] = createInjectionState(
 | 
			
		||||
      // 触发设置方法
 | 
			
		||||
      setChannelDiv, // 导出设置通道组方法
 | 
			
		||||
      setGlobalMode,
 | 
			
		||||
      setClockDiv, // 导出设置采样频率方法
 | 
			
		||||
      resetConfiguration,
 | 
			
		||||
      setLogicData,
 | 
			
		||||
      startCapture,
 | 
			
		||||
 
 | 
			
		||||
@@ -81,6 +81,44 @@
 | 
			
		||||
              {{ currentChannelDivDescription }}
 | 
			
		||||
            </p>
 | 
			
		||||
          </div>
 | 
			
		||||
          <div class="flex flex-col gap-2">
 | 
			
		||||
            <label class="block text-sm font-semibold antialiased text-slate-800">
 | 
			
		||||
              采样频率
 | 
			
		||||
            </label>
 | 
			
		||||
            <div class="relative w-[200px]">
 | 
			
		||||
              <button 
 | 
			
		||||
                tabindex="0" 
 | 
			
		||||
                type="button" 
 | 
			
		||||
                class="flex items-center gap-4 justify-between h-max outline-none focus:outline-none text-slate-600 bg-transparent ring-transparent border border-slate-200 transition-all duration-300 ease-in disabled:opacity-50 disabled:pointer-events-none select-none text-start text-sm rounded-md py-2 px-2.5 ring shadow-sm hover:border-slate-800 hover:ring-slate-800/10 focus:border-slate-800 focus:ring-slate-800/10 w-full"
 | 
			
		||||
                @click="toggleClockDivDropdown"
 | 
			
		||||
                :aria-expanded="showClockDivDropdown"
 | 
			
		||||
                aria-haspopup="listbox" 
 | 
			
		||||
                role="combobox"
 | 
			
		||||
              >
 | 
			
		||||
                <span>{{ currentClockDivLabel }}</span>
 | 
			
		||||
                <svg viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg" color="currentColor" class="h-[1em] w-[1em] translate-x-0.5 stroke-[1.5]">
 | 
			
		||||
                  <path d="M17 8L12 3L7 8" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round"></path>
 | 
			
		||||
                  <path d="M17 16L12 21L7 16" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round"></path>
 | 
			
		||||
                </svg>
 | 
			
		||||
              </button>
 | 
			
		||||
              <input readonly style="display:none" :value="currentclockDiv" />
 | 
			
		||||
              <!-- 下拉菜单 -->
 | 
			
		||||
              <div v-if="showClockDivDropdown" class="absolute top-full left-0 right-0 mt-1 bg-white border border-slate-200 rounded-md shadow-lg z-50">
 | 
			
		||||
                <div
 | 
			
		||||
                  v-for="option in ClockDivOptions"
 | 
			
		||||
                  :key="option.value"
 | 
			
		||||
                  @click="selectClockDiv(option.value)"
 | 
			
		||||
                  class="px-3 py-2 text-sm text-slate-700 hover:bg-slate-100 cursor-pointer"
 | 
			
		||||
                  :class="{ 'bg-slate-100': option.value === currentclockDiv }"
 | 
			
		||||
                >
 | 
			
		||||
                  {{ option.label }}
 | 
			
		||||
                </div>
 | 
			
		||||
              </div>
 | 
			
		||||
            </div>
 | 
			
		||||
            <p class="flex items-center text-xs text-slate-400">
 | 
			
		||||
              {{ currentClockDivDescription }}
 | 
			
		||||
            </p>
 | 
			
		||||
          </div>
 | 
			
		||||
          <div class="flex flex-col gap-2">
 | 
			
		||||
            <label class="block text-sm font-semibold antialiased">
 | 
			
		||||
              捕获深度
 | 
			
		||||
@@ -277,6 +315,7 @@ import { useLogicAnalyzerState } from "./LogicAnalyzerManager";
 | 
			
		||||
const {
 | 
			
		||||
  currentGlobalMode,
 | 
			
		||||
  currentChannelDiv,
 | 
			
		||||
  currentclockDiv,
 | 
			
		||||
  captureLength,
 | 
			
		||||
  preCaptureLength,
 | 
			
		||||
  isApplying,
 | 
			
		||||
@@ -287,6 +326,7 @@ const {
 | 
			
		||||
  operators,
 | 
			
		||||
  signalValues,
 | 
			
		||||
  channelDivOptions,
 | 
			
		||||
  ClockDivOptions,
 | 
			
		||||
  CAPTURE_LENGTH_MIN,
 | 
			
		||||
  CAPTURE_LENGTH_MAX,
 | 
			
		||||
  PRE_CAPTURE_LENGTH_MIN,
 | 
			
		||||
@@ -296,12 +336,14 @@ const {
 | 
			
		||||
  setPreCaptureLength,
 | 
			
		||||
  setChannelDiv,
 | 
			
		||||
  setGlobalMode,
 | 
			
		||||
  setClockDiv,
 | 
			
		||||
  resetConfiguration,
 | 
			
		||||
} = useRequiredInjection(useLogicAnalyzerState);
 | 
			
		||||
 | 
			
		||||
// 下拉菜单状态
 | 
			
		||||
const showGlobalModeDropdown = ref(false);
 | 
			
		||||
const showChannelDivDropdown = ref(false);
 | 
			
		||||
const showClockDivDropdown = ref(false);
 | 
			
		||||
 | 
			
		||||
// 处理捕获深度变化
 | 
			
		||||
const handleCaptureLengthChange = () => {
 | 
			
		||||
@@ -362,11 +404,24 @@ const currentChannelDivDescription = computed(() => {
 | 
			
		||||
  return option ? option.description : '';
 | 
			
		||||
});
 | 
			
		||||
 | 
			
		||||
// 计算属性:获取当前采样频率的标签
 | 
			
		||||
const currentClockDivLabel = computed(() => {
 | 
			
		||||
  const option = ClockDivOptions.find(opt => opt.value === currentclockDiv.value);
 | 
			
		||||
  return option ? option.label : '';
 | 
			
		||||
});
 | 
			
		||||
 | 
			
		||||
// 计算属性:获取当前采样频率的描述
 | 
			
		||||
const currentClockDivDescription = computed(() => {
 | 
			
		||||
  const option = ClockDivOptions.find(opt => opt.value === currentclockDiv.value);
 | 
			
		||||
  return option ? option.description : '';
 | 
			
		||||
});
 | 
			
		||||
 | 
			
		||||
// 全局模式下拉菜单相关函数
 | 
			
		||||
const toggleGlobalModeDropdown = () => {
 | 
			
		||||
  showGlobalModeDropdown.value = !showGlobalModeDropdown.value;
 | 
			
		||||
  if (showGlobalModeDropdown.value) {
 | 
			
		||||
    showChannelDivDropdown.value = false;
 | 
			
		||||
    showClockDivDropdown.value = false;
 | 
			
		||||
  }
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
@@ -380,6 +435,7 @@ const toggleChannelDivDropdown = () => {
 | 
			
		||||
  showChannelDivDropdown.value = !showChannelDivDropdown.value;
 | 
			
		||||
  if (showChannelDivDropdown.value) {
 | 
			
		||||
    showGlobalModeDropdown.value = false;
 | 
			
		||||
    showClockDivDropdown.value = false;
 | 
			
		||||
  }
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
@@ -388,12 +444,27 @@ const selectChannelDiv = (value: number) => {
 | 
			
		||||
  showChannelDivDropdown.value = false;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
// 采样频率下拉菜单相关函数
 | 
			
		||||
const toggleClockDivDropdown = () => {
 | 
			
		||||
  showClockDivDropdown.value = !showClockDivDropdown.value;
 | 
			
		||||
  if (showClockDivDropdown.value) {
 | 
			
		||||
    showGlobalModeDropdown.value = false;
 | 
			
		||||
    showChannelDivDropdown.value = false;
 | 
			
		||||
  }
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
const selectClockDiv = (value: any) => {
 | 
			
		||||
  setClockDiv(value);
 | 
			
		||||
  showClockDivDropdown.value = false;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
// 点击其他地方关闭下拉菜单
 | 
			
		||||
const handleClickOutside = (event: MouseEvent) => {
 | 
			
		||||
  const target = event.target as HTMLElement;
 | 
			
		||||
  if (!target.closest('.relative')) {
 | 
			
		||||
    showGlobalModeDropdown.value = false;
 | 
			
		||||
    showChannelDivDropdown.value = false;
 | 
			
		||||
    showClockDivDropdown.value = false;
 | 
			
		||||
  }
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user