add: 逻辑分析仪可设置采样频率
This commit is contained in:
@@ -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