feat: 添加debugger后端api,并修改waveformdisplay使其更加通用

This commit is contained in:
SikongJueluo 2025-07-29 15:45:45 +08:00
parent a4192659d1
commit 23d4459406
No known key found for this signature in database
6 changed files with 697 additions and 103 deletions

View File

@ -0,0 +1,251 @@
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Cors;
using Microsoft.AspNetCore.Mvc;
using Peripherals.DebuggerClient;
namespace server.Controllers;
/// <summary>
/// FPGA调试器控制器
/// </summary>
[ApiController]
[Route("api/[controller]")]
[Authorize]
public class DebuggerController : ControllerBase
{
private static readonly NLog.Logger logger = NLog.LogManager.GetCurrentClassLogger();
/// <summary>
/// 获取调试器实例
/// </summary>
private DebuggerClient? GetDebugger()
{
try
{
var userName = User.Identity?.Name;
if (string.IsNullOrEmpty(userName))
return null;
using var db = new Database.AppDataConnection();
var userRet = db.GetUserByName(userName);
if (!userRet.IsSuccessful || !userRet.Value.HasValue)
return null;
var user = userRet.Value.Value;
if (user.BoardID == Guid.Empty)
return null;
var boardRet = db.GetBoardByID(user.BoardID);
if (!boardRet.IsSuccessful || !boardRet.Value.HasValue)
return null;
var board = boardRet.Value.Value;
return new DebuggerClient(board.IpAddr, board.Port, 1);
}
catch (Exception ex)
{
logger.Error(ex, "获取调试器实例时发生异常");
return null;
}
}
/// <summary>
/// 设置捕获模式
/// </summary>
[HttpPost("SetMode")]
[EnableCors("Users")]
[ProducesResponseType(typeof(bool), StatusCodes.Status200OK)]
[ProducesResponseType(StatusCodes.Status400BadRequest)]
[ProducesResponseType(StatusCodes.Status500InternalServerError)]
[ProducesResponseType(StatusCodes.Status401Unauthorized)]
public async Task<IActionResult> SetMode([FromBody] CaptureMode mode)
{
try
{
var debugger = GetDebugger();
if (debugger == null)
return BadRequest("用户未绑定有效的实验板");
var result = await debugger.SetMode(mode);
if (!result.IsSuccessful)
{
logger.Error($"设置捕获模式失败: {result.Error}");
return StatusCode(StatusCodes.Status500InternalServerError, "设置捕获模式失败");
}
return Ok(result.Value);
}
catch (Exception ex)
{
logger.Error(ex, "设置捕获模式时发生异常");
return StatusCode(StatusCodes.Status500InternalServerError, "操作失败,请稍后重试");
}
}
/// <summary>
/// 启动触发器
/// </summary>
[HttpPost("StartTrigger")]
[EnableCors("Users")]
[ProducesResponseType(typeof(bool), StatusCodes.Status200OK)]
[ProducesResponseType(StatusCodes.Status400BadRequest)]
[ProducesResponseType(StatusCodes.Status500InternalServerError)]
[ProducesResponseType(StatusCodes.Status401Unauthorized)]
public async Task<IActionResult> StartTrigger()
{
try
{
var debugger = GetDebugger();
if (debugger == null)
return BadRequest("用户未绑定有效的实验板");
var result = await debugger.StartTrigger();
if (!result.IsSuccessful)
{
logger.Error($"启动触发器失败: {result.Error}");
return StatusCode(StatusCodes.Status500InternalServerError, "启动触发器失败");
}
return Ok(result.Value);
}
catch (Exception ex)
{
logger.Error(ex, "启动触发器时发生异常");
return StatusCode(StatusCodes.Status500InternalServerError, "操作失败,请稍后重试");
}
}
/// <summary>
/// 读取触发器状态标志
/// </summary>
[HttpGet("ReadFlag")]
[EnableCors("Users")]
[ProducesResponseType(typeof(byte), StatusCodes.Status200OK)]
[ProducesResponseType(StatusCodes.Status400BadRequest)]
[ProducesResponseType(StatusCodes.Status500InternalServerError)]
[ProducesResponseType(StatusCodes.Status401Unauthorized)]
public async Task<IActionResult> ReadFlag()
{
try
{
var debugger = GetDebugger();
if (debugger == null)
return BadRequest("用户未绑定有效的实验板");
var result = await debugger.ReadFlag();
if (!result.IsSuccessful)
{
logger.Error($"读取触发器状态标志失败: {result.Error}");
return StatusCode(StatusCodes.Status500InternalServerError, "读取触发器状态标志失败");
}
return Ok(result.Value);
}
catch (Exception ex)
{
logger.Error(ex, "读取触发器状态标志时发生异常");
return StatusCode(StatusCodes.Status500InternalServerError, "操作失败,请稍后重试");
}
}
/// <summary>
/// 清除触发器状态标志
/// </summary>
[HttpPost("ClearFlag")]
[EnableCors("Users")]
[ProducesResponseType(typeof(bool), StatusCodes.Status200OK)]
[ProducesResponseType(StatusCodes.Status400BadRequest)]
[ProducesResponseType(StatusCodes.Status500InternalServerError)]
[ProducesResponseType(StatusCodes.Status401Unauthorized)]
public async Task<IActionResult> ClearFlag()
{
try
{
var debugger = GetDebugger();
if (debugger == null)
return BadRequest("用户未绑定有效的实验板");
var result = await debugger.ClearFlag();
if (!result.IsSuccessful)
{
logger.Error($"清除触发器状态标志失败: {result.Error}");
return StatusCode(StatusCodes.Status500InternalServerError, "清除触发器状态标志失败");
}
return Ok(result.Value);
}
catch (Exception ex)
{
logger.Error(ex, "清除触发器状态标志时发生异常");
return StatusCode(StatusCodes.Status500InternalServerError, "操作失败,请稍后重试");
}
}
/// <summary>
/// 读取捕获数据
/// </summary>
[HttpGet("ReadData")]
[EnableCors("Users")]
[ProducesResponseType(typeof(string), StatusCodes.Status200OK)]
[ProducesResponseType(StatusCodes.Status400BadRequest)]
[ProducesResponseType(StatusCodes.Status500InternalServerError)]
[ProducesResponseType(StatusCodes.Status401Unauthorized)]
public async Task<IActionResult> ReadData([FromQuery] ushort offset = 0)
{
try
{
var debugger = GetDebugger();
if (debugger == null)
return BadRequest("用户未绑定有效的实验板");
var result = await debugger.ReadData(offset);
if (!result.IsSuccessful)
{
logger.Error($"读取捕获数据失败: {result.Error}");
return StatusCode(StatusCodes.Status500InternalServerError, "读取捕获数据失败");
}
// 返回Base64编码
var base64Data = Convert.ToBase64String(result.Value);
return Ok(base64Data);
}
catch (Exception ex)
{
logger.Error(ex, "读取捕获数据时发生异常");
return StatusCode(StatusCodes.Status500InternalServerError, "操作失败,请稍后重试");
}
}
/// <summary>
/// 刷新调试器状态
/// </summary>
[HttpPost("Refresh")]
[EnableCors("Users")]
[ProducesResponseType(typeof(bool), StatusCodes.Status200OK)]
[ProducesResponseType(StatusCodes.Status400BadRequest)]
[ProducesResponseType(StatusCodes.Status500InternalServerError)]
[ProducesResponseType(StatusCodes.Status401Unauthorized)]
public async Task<IActionResult> Refresh()
{
try
{
var debugger = GetDebugger();
if (debugger == null)
return BadRequest("用户未绑定有效的实验板");
var result = await debugger.Refresh();
if (!result.IsSuccessful)
{
logger.Error($"刷新调试器状态失败: {result.Error}");
return StatusCode(StatusCodes.Status500InternalServerError, "刷新调试器状态失败");
}
return Ok(result.Value);
}
catch (Exception ex)
{
logger.Error(ex, "刷新调试器状态时发生异常");
return StatusCode(StatusCodes.Status500InternalServerError, "操作失败,请稍后重试");
}
}
}

View File

@ -1637,6 +1637,362 @@ export class DDSClient {
}
}
export class DebuggerClient {
private http: { fetch(url: RequestInfo, init?: RequestInit): Promise<Response> };
private baseUrl: string;
protected jsonParseReviver: ((key: string, value: any) => any) | undefined = undefined;
constructor(baseUrl?: string, http?: { fetch(url: RequestInfo, init?: RequestInit): Promise<Response> }) {
this.http = http ? http : window as any;
this.baseUrl = baseUrl ?? "http://127.0.0.1:5000";
}
/**
*
*/
setMode(mode: string): Promise<boolean> {
let url_ = this.baseUrl + "/api/Debugger/SetMode";
url_ = url_.replace(/[?&]$/, "");
const content_ = JSON.stringify(mode);
let options_: RequestInit = {
body: content_,
method: "POST",
headers: {
"Content-Type": "application/json",
"Accept": "application/json"
}
};
return this.http.fetch(url_, options_).then((_response: Response) => {
return this.processSetMode(_response);
});
}
protected processSetMode(response: Response): Promise<boolean> {
const status = response.status;
let _headers: any = {}; if (response.headers && response.headers.forEach) { response.headers.forEach((v: any, k: any) => _headers[k] = v); };
if (status === 200) {
return response.text().then((_responseText) => {
let result200: any = null;
let resultData200 = _responseText === "" ? null : JSON.parse(_responseText, this.jsonParseReviver);
result200 = resultData200 !== undefined ? resultData200 : <any>null;
return result200;
});
} else if (status === 400) {
return response.text().then((_responseText) => {
let result400: any = null;
let resultData400 = _responseText === "" ? null : JSON.parse(_responseText, this.jsonParseReviver);
result400 = ProblemDetails.fromJS(resultData400);
return throwException("A server side error occurred.", status, _responseText, _headers, result400);
});
} else if (status === 500) {
return response.text().then((_responseText) => {
return throwException("A server side error occurred.", status, _responseText, _headers);
});
} else if (status === 401) {
return response.text().then((_responseText) => {
let result401: any = null;
let resultData401 = _responseText === "" ? null : JSON.parse(_responseText, this.jsonParseReviver);
result401 = ProblemDetails.fromJS(resultData401);
return throwException("A server side error occurred.", status, _responseText, _headers, result401);
});
} else if (status !== 200 && status !== 204) {
return response.text().then((_responseText) => {
return throwException("An unexpected server error occurred.", status, _responseText, _headers);
});
}
return Promise.resolve<boolean>(null as any);
}
/**
*
*/
startTrigger(): Promise<boolean> {
let url_ = this.baseUrl + "/api/Debugger/StartTrigger";
url_ = url_.replace(/[?&]$/, "");
let options_: RequestInit = {
method: "POST",
headers: {
"Accept": "application/json"
}
};
return this.http.fetch(url_, options_).then((_response: Response) => {
return this.processStartTrigger(_response);
});
}
protected processStartTrigger(response: Response): Promise<boolean> {
const status = response.status;
let _headers: any = {}; if (response.headers && response.headers.forEach) { response.headers.forEach((v: any, k: any) => _headers[k] = v); };
if (status === 200) {
return response.text().then((_responseText) => {
let result200: any = null;
let resultData200 = _responseText === "" ? null : JSON.parse(_responseText, this.jsonParseReviver);
result200 = resultData200 !== undefined ? resultData200 : <any>null;
return result200;
});
} else if (status === 400) {
return response.text().then((_responseText) => {
let result400: any = null;
let resultData400 = _responseText === "" ? null : JSON.parse(_responseText, this.jsonParseReviver);
result400 = ProblemDetails.fromJS(resultData400);
return throwException("A server side error occurred.", status, _responseText, _headers, result400);
});
} else if (status === 500) {
return response.text().then((_responseText) => {
return throwException("A server side error occurred.", status, _responseText, _headers);
});
} else if (status === 401) {
return response.text().then((_responseText) => {
let result401: any = null;
let resultData401 = _responseText === "" ? null : JSON.parse(_responseText, this.jsonParseReviver);
result401 = ProblemDetails.fromJS(resultData401);
return throwException("A server side error occurred.", status, _responseText, _headers, result401);
});
} else if (status !== 200 && status !== 204) {
return response.text().then((_responseText) => {
return throwException("An unexpected server error occurred.", status, _responseText, _headers);
});
}
return Promise.resolve<boolean>(null as any);
}
/**
*
*/
readFlag(): Promise<number> {
let url_ = this.baseUrl + "/api/Debugger/ReadFlag";
url_ = url_.replace(/[?&]$/, "");
let options_: RequestInit = {
method: "GET",
headers: {
"Accept": "application/json"
}
};
return this.http.fetch(url_, options_).then((_response: Response) => {
return this.processReadFlag(_response);
});
}
protected processReadFlag(response: Response): Promise<number> {
const status = response.status;
let _headers: any = {}; if (response.headers && response.headers.forEach) { response.headers.forEach((v: any, k: any) => _headers[k] = v); };
if (status === 200) {
return response.text().then((_responseText) => {
let result200: any = null;
let resultData200 = _responseText === "" ? null : JSON.parse(_responseText, this.jsonParseReviver);
result200 = resultData200 !== undefined ? resultData200 : <any>null;
return result200;
});
} else if (status === 400) {
return response.text().then((_responseText) => {
let result400: any = null;
let resultData400 = _responseText === "" ? null : JSON.parse(_responseText, this.jsonParseReviver);
result400 = ProblemDetails.fromJS(resultData400);
return throwException("A server side error occurred.", status, _responseText, _headers, result400);
});
} else if (status === 500) {
return response.text().then((_responseText) => {
return throwException("A server side error occurred.", status, _responseText, _headers);
});
} else if (status === 401) {
return response.text().then((_responseText) => {
let result401: any = null;
let resultData401 = _responseText === "" ? null : JSON.parse(_responseText, this.jsonParseReviver);
result401 = ProblemDetails.fromJS(resultData401);
return throwException("A server side error occurred.", status, _responseText, _headers, result401);
});
} else if (status !== 200 && status !== 204) {
return response.text().then((_responseText) => {
return throwException("An unexpected server error occurred.", status, _responseText, _headers);
});
}
return Promise.resolve<number>(null as any);
}
/**
*
*/
clearFlag(): Promise<boolean> {
let url_ = this.baseUrl + "/api/Debugger/ClearFlag";
url_ = url_.replace(/[?&]$/, "");
let options_: RequestInit = {
method: "POST",
headers: {
"Accept": "application/json"
}
};
return this.http.fetch(url_, options_).then((_response: Response) => {
return this.processClearFlag(_response);
});
}
protected processClearFlag(response: Response): Promise<boolean> {
const status = response.status;
let _headers: any = {}; if (response.headers && response.headers.forEach) { response.headers.forEach((v: any, k: any) => _headers[k] = v); };
if (status === 200) {
return response.text().then((_responseText) => {
let result200: any = null;
let resultData200 = _responseText === "" ? null : JSON.parse(_responseText, this.jsonParseReviver);
result200 = resultData200 !== undefined ? resultData200 : <any>null;
return result200;
});
} else if (status === 400) {
return response.text().then((_responseText) => {
let result400: any = null;
let resultData400 = _responseText === "" ? null : JSON.parse(_responseText, this.jsonParseReviver);
result400 = ProblemDetails.fromJS(resultData400);
return throwException("A server side error occurred.", status, _responseText, _headers, result400);
});
} else if (status === 500) {
return response.text().then((_responseText) => {
return throwException("A server side error occurred.", status, _responseText, _headers);
});
} else if (status === 401) {
return response.text().then((_responseText) => {
let result401: any = null;
let resultData401 = _responseText === "" ? null : JSON.parse(_responseText, this.jsonParseReviver);
result401 = ProblemDetails.fromJS(resultData401);
return throwException("A server side error occurred.", status, _responseText, _headers, result401);
});
} else if (status !== 200 && status !== 204) {
return response.text().then((_responseText) => {
return throwException("An unexpected server error occurred.", status, _responseText, _headers);
});
}
return Promise.resolve<boolean>(null as any);
}
/**
*
* @param offset (optional)
*/
readData(offset: number | undefined): Promise<string> {
let url_ = this.baseUrl + "/api/Debugger/ReadData?";
if (offset === null)
throw new Error("The parameter 'offset' cannot be null.");
else if (offset !== undefined)
url_ += "offset=" + encodeURIComponent("" + offset) + "&";
url_ = url_.replace(/[?&]$/, "");
let options_: RequestInit = {
method: "GET",
headers: {
"Accept": "application/json"
}
};
return this.http.fetch(url_, options_).then((_response: Response) => {
return this.processReadData(_response);
});
}
protected processReadData(response: Response): Promise<string> {
const status = response.status;
let _headers: any = {}; if (response.headers && response.headers.forEach) { response.headers.forEach((v: any, k: any) => _headers[k] = v); };
if (status === 200) {
return response.text().then((_responseText) => {
let result200: any = null;
let resultData200 = _responseText === "" ? null : JSON.parse(_responseText, this.jsonParseReviver);
result200 = resultData200 !== undefined ? resultData200 : <any>null;
return result200;
});
} else if (status === 400) {
return response.text().then((_responseText) => {
let result400: any = null;
let resultData400 = _responseText === "" ? null : JSON.parse(_responseText, this.jsonParseReviver);
result400 = ProblemDetails.fromJS(resultData400);
return throwException("A server side error occurred.", status, _responseText, _headers, result400);
});
} else if (status === 500) {
return response.text().then((_responseText) => {
return throwException("A server side error occurred.", status, _responseText, _headers);
});
} else if (status === 401) {
return response.text().then((_responseText) => {
let result401: any = null;
let resultData401 = _responseText === "" ? null : JSON.parse(_responseText, this.jsonParseReviver);
result401 = ProblemDetails.fromJS(resultData401);
return throwException("A server side error occurred.", status, _responseText, _headers, result401);
});
} else if (status !== 200 && status !== 204) {
return response.text().then((_responseText) => {
return throwException("An unexpected server error occurred.", status, _responseText, _headers);
});
}
return Promise.resolve<string>(null as any);
}
/**
*
*/
refresh(): Promise<boolean> {
let url_ = this.baseUrl + "/api/Debugger/Refresh";
url_ = url_.replace(/[?&]$/, "");
let options_: RequestInit = {
method: "POST",
headers: {
"Accept": "application/json"
}
};
return this.http.fetch(url_, options_).then((_response: Response) => {
return this.processRefresh(_response);
});
}
protected processRefresh(response: Response): Promise<boolean> {
const status = response.status;
let _headers: any = {}; if (response.headers && response.headers.forEach) { response.headers.forEach((v: any, k: any) => _headers[k] = v); };
if (status === 200) {
return response.text().then((_responseText) => {
let result200: any = null;
let resultData200 = _responseText === "" ? null : JSON.parse(_responseText, this.jsonParseReviver);
result200 = resultData200 !== undefined ? resultData200 : <any>null;
return result200;
});
} else if (status === 400) {
return response.text().then((_responseText) => {
let result400: any = null;
let resultData400 = _responseText === "" ? null : JSON.parse(_responseText, this.jsonParseReviver);
result400 = ProblemDetails.fromJS(resultData400);
return throwException("A server side error occurred.", status, _responseText, _headers, result400);
});
} else if (status === 500) {
return response.text().then((_responseText) => {
return throwException("A server side error occurred.", status, _responseText, _headers);
});
} else if (status === 401) {
return response.text().then((_responseText) => {
let result401: any = null;
let resultData401 = _responseText === "" ? null : JSON.parse(_responseText, this.jsonParseReviver);
result401 = ProblemDetails.fromJS(resultData401);
return throwException("A server side error occurred.", status, _responseText, _headers, result401);
});
} else if (status !== 200 && status !== 204) {
return response.text().then((_responseText) => {
return throwException("An unexpected server error occurred.", status, _responseText, _headers);
});
}
return Promise.resolve<boolean>(null as any);
}
}
export class JtagClient {
private http: { fetch(url: RequestInfo, init?: RequestInit): Promise<Response> };
private baseUrl: string;

View File

@ -2,12 +2,12 @@
<div
class="w-full"
:class="{
'h-48': !analyzer.logicData.value,
'h-150': analyzer.logicData.value,
'h-48': !props.data,
'h-150': props.data,
}"
>
<v-chart
v-if="analyzer.logicData.value"
v-if="props.data"
class="w-full h-full"
:option="option"
autoresize
@ -17,17 +17,20 @@
v-else
class="w-full h-full flex flex-col gap-6 items-center justify-center"
>
<div class="text-center">
<h3 class="text-xl font-semibold text-slate-600 mb-2">
暂无逻辑分析数据
</h3>
</div>
<template v-if="hasSlot">
<slot />
</template>
<template v-else>
<div class="text-center">
<h3 class="text-xl font-semibold text-slate-600 mb-2">暂无数据</h3>
</div>
</template>
</div>
</div>
</template>
<script setup lang="ts">
import { computed, shallowRef } from "vue";
import { computed, shallowRef, useSlots } from "vue";
import VChart from "vue-echarts";
// Echarts
@ -56,9 +59,8 @@ import type {
XAXisOption,
YAXisOption,
} from "echarts/types/dist/shared";
import { useRequiredInjection } from "@/utils/Common";
import { isUndefined } from "lodash";
import { useWaveformManager } from "./WaveformManager";
import type { LogicDataType } from ".";
use([
TooltipComponent,
@ -81,7 +83,12 @@ type EChartsOption = ComposeOption<
| MarkLineComponentOption
>;
const analyzer = useRequiredInjection(useWaveformManager);
const props = defineProps<{
data?: LogicDataType;
}>();
const slots = useSlots();
const hasSlot = computed(() => !!slots.default && slots.default().length > 0);
//
const updateOptions = shallowRef({
@ -91,13 +98,13 @@ const updateOptions = shallowRef({
});
const option = computed((): EChartsOption => {
if (isUndefined(analyzer.logicData.value)) return {};
if (isUndefined(props.data)) return {};
// 使y
const enabledChannels = analyzer.logicData.value.y.filter(
const enabledChannels = props.data.y.filter(
(channel) => channel.enabled,
);
const enabledChannelIndices = analyzer.logicData.value.y
const enabledChannelIndices = props.data.y
.map((channel, index) => (channel.enabled ? index : -1))
.filter((index) => index !== -1);
@ -124,11 +131,11 @@ const option = computed((): EChartsOption => {
{
type: "category",
boundaryGap: true,
data: analyzer.logicData.value.x.map((x) => x.toFixed(3)),
data: props.data.x.map((x) => x.toFixed(3)),
axisLabel: {
formatter: (value: string) =>
analyzer.logicData.value
? `${value}${analyzer.logicData.value.xUnit}`
props.data
? `${value}${props.data.xUnit}`
: `${value}`,
},
},
@ -157,7 +164,7 @@ const option = computed((): EChartsOption => {
const series: LineSeriesOption[] = [];
enabledChannelIndices.forEach(
(originalIndex: number, displayIndex: number) => {
const channel = analyzer.logicData.value!.y[originalIndex];
const channel = props.data!.y[originalIndex];
if (channel.type === "logic") {
// logic
series.push({
@ -182,7 +189,7 @@ const option = computed((): EChartsOption => {
});
} else if (channel.type === "number") {
const values = channel.value;
const xArr = analyzer.logicData.value!.x;
const xArr = props.data!.x;
//
function buildVcdLine(valArr: number[], high: number, low: number) {
const points: { x: number; y: number }[] = [];
@ -208,7 +215,8 @@ const option = computed((): EChartsOption => {
let lastIdx = 0;
//
function formatValue(val: number) {
if (channel.base === "hex") return "0x" + val.toString(16).toUpperCase();
if (channel.base === "hex")
return "0x" + val.toString(16).toUpperCase();
if (channel.base === "bin") return "0b" + val.toString(2);
return val.toString();
}
@ -314,12 +322,12 @@ const option = computed((): EChartsOption => {
},
formatter: (params: any) => {
if (Array.isArray(params) && params.length > 0) {
const timeValue = analyzer.logicData.value!.x[params[0].dataIndex];
const timeValue = props.data!.x[params[0].dataIndex];
const dataIndex = params[0].dataIndex;
let tooltip = `Time: ${timeValue.toFixed(3)}${analyzer.logicData.value!.xUnit}<br/>`;
let tooltip = `Time: ${timeValue.toFixed(3)}${props.data!.xUnit}<br/>`;
enabledChannelIndices.forEach(
(originalIndex: number, displayIndex: number) => {
const channel = analyzer.logicData.value!.y[originalIndex];
const channel = props.data!.y[originalIndex];
if (channel.type === "logic") {
const channelName = channel.name;
const originalValue = channel.value[dataIndex];

View File

@ -1,73 +0,0 @@
import { createInjectionState } from "@vueuse/core";
import { shallowRef } from "vue";
export type LogicDataType = {
x: number[];
y: {
enabled: boolean;
type: "logic" | "number";
name: string;
color: string;
value: number[];
base: "bin" | "dec" | "hex";
}[];
xUnit: "s" | "ms" | "us" | "ns";
};
// 生成4路测试数据的函数
export function generateTestData(): LogicDataType {
// 生成时间轴数据 (0-100ns每1ns一个采样点)
const timePoints = Array.from({ length: 101 }, (_, i) => i);
return {
x: timePoints,
y: [
{
enabled: true,
type: "logic",
name: "CLK",
color: "#ff0000",
value: timePoints.map((t) => t % 2), // 时钟信号每1ns翻转
base: "bin",
},
{
enabled: true,
type: "logic",
name: "RESET",
color: "#00ff00",
value: timePoints.map((t) => (t < 10 ? 1 : 0)), // 复位信号前10ns为高电平
base: "bin",
},
{
enabled: true,
type: "number",
name: "DATA",
color: "#0000ff",
value: timePoints.map((t) => Math.floor(t / 4) % 16), // 计数器每4ns递增
base: "hex",
},
{
enabled: true,
type: "logic",
name: "ENABLE",
color: "#ff8800",
value: timePoints.map((t) => (t >= 20 && t < 80 ? 1 : 0)), // 使能信号20-80ns为高电平
base: "bin",
},
],
xUnit: "ns",
};
}
const [useProvideWaveformManager, useWaveformManager] = createInjectionState(
() => {
const logicData = shallowRef<LogicDataType>();
return {
logicData,
generateTestData,
};
},
);
export { useProvideWaveformManager, useWaveformManager };

View File

@ -1,5 +1,61 @@
import WaveformDisplay from "./WaveformDisplay.vue";
export {
WaveformDisplay
export type LogicDataType = {
x: number[];
y: {
enabled: boolean;
type: "logic" | "number";
name: string;
color: string;
value: number[];
base: "bin" | "dec" | "hex";
}[];
xUnit: "s" | "ms" | "us" | "ns";
};
// 生成4路测试数据的函数
export function generateTestData(): LogicDataType {
// 生成时间轴数据 (0-100ns每1ns一个采样点)
const timePoints = Array.from({ length: 101 }, (_, i) => i);
return {
x: timePoints,
y: [
{
enabled: true,
type: "logic",
name: "CLK",
color: "#ff0000",
value: timePoints.map((t) => t % 2), // 时钟信号每1ns翻转
base: "bin",
},
{
enabled: true,
type: "logic",
name: "RESET",
color: "#00ff00",
value: timePoints.map((t) => (t < 10 ? 1 : 0)), // 复位信号前10ns为高电平
base: "bin",
},
{
enabled: true,
type: "number",
name: "DATA",
color: "#0000ff",
value: timePoints.map((t) => Math.floor(t / 4) % 16), // 计数器每4ns递增
base: "hex",
},
{
enabled: true,
type: "logic",
name: "ENABLE",
color: "#ff8800",
value: timePoints.map((t) => (t >= 20 && t < 80 ? 1 : 0)), // 使能信号20-80ns为高电平
base: "bin",
},
],
xUnit: "ns",
};
}
export { WaveformDisplay };

View File

@ -103,15 +103,11 @@ import { isNull, toNumber } from "lodash";
import { onMounted, ref, watch } from "vue";
import Debugger from "./Debugger.vue";
import { useProvideLogicAnalyzer } from "@/components/LogicAnalyzer";
import { useProvideWaveformManager } from "@/components/WaveformDisplay/WaveformManager";
import { useProvideOscilloscope } from "@/components/Oscilloscope/OscilloscopeManager";
const analyzer = useProvideLogicAnalyzer();
const waveformManager = useProvideWaveformManager();
const oscilloscopeManager = useProvideOscilloscope();
waveformManager.logicData.value = waveformManager.generateTestData();
const checkID = useLocalStorage("checkID", 1);
//