diff --git a/server/src/Controllers/DebuggerController.cs b/server/src/Controllers/DebuggerController.cs
new file mode 100644
index 0000000..f8de240
--- /dev/null
+++ b/server/src/Controllers/DebuggerController.cs
@@ -0,0 +1,251 @@
+using Microsoft.AspNetCore.Authorization;
+using Microsoft.AspNetCore.Cors;
+using Microsoft.AspNetCore.Mvc;
+using Peripherals.DebuggerClient;
+
+namespace server.Controllers;
+
+///
+/// FPGA调试器控制器
+///
+[ApiController]
+[Route("api/[controller]")]
+[Authorize]
+public class DebuggerController : ControllerBase
+{
+ private static readonly NLog.Logger logger = NLog.LogManager.GetCurrentClassLogger();
+
+ ///
+ /// 获取调试器实例
+ ///
+ 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;
+ }
+ }
+
+ ///
+ /// 设置捕获模式
+ ///
+ [HttpPost("SetMode")]
+ [EnableCors("Users")]
+ [ProducesResponseType(typeof(bool), StatusCodes.Status200OK)]
+ [ProducesResponseType(StatusCodes.Status400BadRequest)]
+ [ProducesResponseType(StatusCodes.Status500InternalServerError)]
+ [ProducesResponseType(StatusCodes.Status401Unauthorized)]
+ public async Task 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, "操作失败,请稍后重试");
+ }
+ }
+
+ ///
+ /// 启动触发器
+ ///
+ [HttpPost("StartTrigger")]
+ [EnableCors("Users")]
+ [ProducesResponseType(typeof(bool), StatusCodes.Status200OK)]
+ [ProducesResponseType(StatusCodes.Status400BadRequest)]
+ [ProducesResponseType(StatusCodes.Status500InternalServerError)]
+ [ProducesResponseType(StatusCodes.Status401Unauthorized)]
+ public async Task 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, "操作失败,请稍后重试");
+ }
+ }
+
+ ///
+ /// 读取触发器状态标志
+ ///
+ [HttpGet("ReadFlag")]
+ [EnableCors("Users")]
+ [ProducesResponseType(typeof(byte), StatusCodes.Status200OK)]
+ [ProducesResponseType(StatusCodes.Status400BadRequest)]
+ [ProducesResponseType(StatusCodes.Status500InternalServerError)]
+ [ProducesResponseType(StatusCodes.Status401Unauthorized)]
+ public async Task 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, "操作失败,请稍后重试");
+ }
+ }
+
+ ///
+ /// 清除触发器状态标志
+ ///
+ [HttpPost("ClearFlag")]
+ [EnableCors("Users")]
+ [ProducesResponseType(typeof(bool), StatusCodes.Status200OK)]
+ [ProducesResponseType(StatusCodes.Status400BadRequest)]
+ [ProducesResponseType(StatusCodes.Status500InternalServerError)]
+ [ProducesResponseType(StatusCodes.Status401Unauthorized)]
+ public async Task 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, "操作失败,请稍后重试");
+ }
+ }
+
+ ///
+ /// 读取捕获数据
+ ///
+ [HttpGet("ReadData")]
+ [EnableCors("Users")]
+ [ProducesResponseType(typeof(string), StatusCodes.Status200OK)]
+ [ProducesResponseType(StatusCodes.Status400BadRequest)]
+ [ProducesResponseType(StatusCodes.Status500InternalServerError)]
+ [ProducesResponseType(StatusCodes.Status401Unauthorized)]
+ public async Task 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, "操作失败,请稍后重试");
+ }
+ }
+
+ ///
+ /// 刷新调试器状态
+ ///
+ [HttpPost("Refresh")]
+ [EnableCors("Users")]
+ [ProducesResponseType(typeof(bool), StatusCodes.Status200OK)]
+ [ProducesResponseType(StatusCodes.Status400BadRequest)]
+ [ProducesResponseType(StatusCodes.Status500InternalServerError)]
+ [ProducesResponseType(StatusCodes.Status401Unauthorized)]
+ public async Task 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, "操作失败,请稍后重试");
+ }
+ }
+}
diff --git a/src/APIClient.ts b/src/APIClient.ts
index bc9e52f..b9c507e 100644
--- a/src/APIClient.ts
+++ b/src/APIClient.ts
@@ -1637,6 +1637,362 @@ export class DDSClient {
}
}
+export class DebuggerClient {
+ private http: { fetch(url: RequestInfo, init?: RequestInit): Promise };
+ private baseUrl: string;
+ protected jsonParseReviver: ((key: string, value: any) => any) | undefined = undefined;
+
+ constructor(baseUrl?: string, http?: { fetch(url: RequestInfo, init?: RequestInit): Promise }) {
+ this.http = http ? http : window as any;
+ this.baseUrl = baseUrl ?? "http://127.0.0.1:5000";
+ }
+
+ /**
+ * 设置捕获模式
+ */
+ setMode(mode: string): Promise {
+ 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 {
+ 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 : 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(null as any);
+ }
+
+ /**
+ * 启动触发器
+ */
+ startTrigger(): Promise {
+ 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 {
+ 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 : 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(null as any);
+ }
+
+ /**
+ * 读取触发器状态标志
+ */
+ readFlag(): Promise {
+ 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 {
+ 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 : 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(null as any);
+ }
+
+ /**
+ * 清除触发器状态标志
+ */
+ clearFlag(): Promise {
+ 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 {
+ 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 : 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(null as any);
+ }
+
+ /**
+ * 读取捕获数据
+ * @param offset (optional)
+ */
+ readData(offset: number | undefined): Promise {
+ 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 {
+ 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 : 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(null as any);
+ }
+
+ /**
+ * 刷新调试器状态
+ */
+ refresh(): Promise {
+ 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 {
+ 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 : 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(null as any);
+ }
+}
+
export class JtagClient {
private http: { fetch(url: RequestInfo, init?: RequestInit): Promise };
private baseUrl: string;
diff --git a/src/components/WaveformDisplay/WaveformDisplay.vue b/src/components/WaveformDisplay/WaveformDisplay.vue
index 3650595..91549eb 100644
--- a/src/components/WaveformDisplay/WaveformDisplay.vue
+++ b/src/components/WaveformDisplay/WaveformDisplay.vue
@@ -2,12 +2,12 @@
-
-
- 暂无逻辑分析数据
-
-
+
+
+
+
+
+
暂无数据
+
+