add: 为逻辑分析仪添加了深度、预存储深度、通道组设置

This commit is contained in:
alivender
2025-07-31 13:14:23 +08:00
parent 3257a68407
commit 6b701658d1
8 changed files with 1012 additions and 718 deletions

View File

@@ -45,7 +45,18 @@ public class LogicAnalyzerController : ControllerBase
/// 全局触发模式
/// </summary>
public GlobalCaptureMode GlobalMode { get; set; }
/// <summary>
/// 捕获深度
/// </summary>
public int CaptureLength { get; set; } = 2048 * 32;
/// <summary>
/// 预采样深度
/// </summary>
public int PreCaptureLength { get; set; } = 2048;
/// <summary>
/// 有效通道
/// </summary>
public AnalyzerChannelDiv ChannelDiv { get; set; } = AnalyzerChannelDiv.EIGHT;
/// <summary>
/// 信号触发配置列表
/// </summary>
@@ -77,7 +88,7 @@ public class LogicAnalyzerController : ControllerBase
return null;
var board = boardRet.Value.Value;
return new Analyzer(board.IpAddr, board.Port, 2);
return new Analyzer(board.IpAddr, board.Port, 0);
}
catch (Exception ex)
{
@@ -208,8 +219,8 @@ public class LogicAnalyzerController : ControllerBase
{
try
{
if (signalIndex < 0 || signalIndex > 7)
return BadRequest("信号索引必须在0-7之间");
if (signalIndex < 0 || signalIndex > 31)
return BadRequest("信号索引必须在0-31之间");
var analyzer = GetAnalyzer();
if (analyzer == null)
@@ -231,6 +242,48 @@ public class LogicAnalyzerController : ControllerBase
}
}
/// <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>
/// <returns>操作结果</returns>
[HttpPost("SetCaptureParams")]
[EnableCors("Users")]
[ProducesResponseType(typeof(bool), StatusCodes.Status200OK)]
[ProducesResponseType(StatusCodes.Status400BadRequest)]
[ProducesResponseType(StatusCodes.Status500InternalServerError)]
[ProducesResponseType(StatusCodes.Status401Unauthorized)]
public async Task<IActionResult> SetCaptureParams(int capture_length, int pre_capture_length, AnalyzerChannelDiv channel_div)
{
try
{
if (capture_length < 0 || capture_length > 2048*32)
return BadRequest("采样深度设置错误");
if (pre_capture_length < 0 || pre_capture_length >= capture_length)
return BadRequest("预采样深度必须小于捕获深度");
var analyzer = GetAnalyzer();
if (analyzer == null)
return BadRequest("用户未绑定有效的实验板");
var result = await analyzer.SetCaptureParams(capture_length, pre_capture_length, channel_div);
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>
@@ -264,8 +317,8 @@ public class LogicAnalyzerController : ControllerBase
// 设置信号触发模式
foreach (var signalConfig in config.SignalConfigs)
{
if (signalConfig.SignalIndex < 0 || signalConfig.SignalIndex > 7)
return BadRequest($"信号索引{signalConfig.SignalIndex}超出范围0-7");
if (signalConfig.SignalIndex < 0 || signalConfig.SignalIndex > 31)
return BadRequest($"信号索引{signalConfig.SignalIndex}超出范围0-31");
var signalResult = await analyzer.SetSignalTrigMode(
signalConfig.SignalIndex, signalConfig.Operator, signalConfig.Value);
@@ -276,6 +329,14 @@ public class LogicAnalyzerController : ControllerBase
$"设置信号{signalConfig.SignalIndex}触发模式失败");
}
}
// 设置深度、预采样深度、有效通道
var paramsResult = await analyzer.SetCaptureParams(
config.CaptureLength, config.PreCaptureLength, config.ChannelDiv);
if (!paramsResult.IsSuccessful)
{
logger.Error($"设置深度、预采样深度、有效通道失败: {paramsResult.Error}");
return StatusCode(StatusCodes.Status500InternalServerError, "设置深度、预采样深度、有效通道失败");
}
return Ok(true);
}
@@ -330,7 +391,7 @@ public class LogicAnalyzerController : ControllerBase
[ProducesResponseType(StatusCodes.Status400BadRequest)]
[ProducesResponseType(StatusCodes.Status500InternalServerError)]
[ProducesResponseType(StatusCodes.Status401Unauthorized)]
public async Task<IActionResult> GetCaptureData()
public async Task<IActionResult> GetCaptureData(int capture_length = 2048 * 32)
{
try
{
@@ -338,7 +399,7 @@ public class LogicAnalyzerController : ControllerBase
if (analyzer == null)
return BadRequest("用户未绑定有效的实验板");
var result = await analyzer.ReadCaptureData();
var result = await analyzer.ReadCaptureData(capture_length);
if (!result.IsSuccessful)
{
logger.Error($"读取捕获数据失败: {result.Error}");

View File

@@ -46,17 +46,26 @@ static class AnalyzerAddr
/// 111 SOME NUMBER <br/>
/// </summary>
public static readonly UInt32[] SIGNAL_TRIG_MODE = {
BASE + 0x0000_0010,
BASE + 0x0000_0011,
BASE + 0x0000_0012,
BASE + 0x0000_0013,
BASE + 0x0000_0014,
BASE + 0x0000_0015,
BASE + 0x0000_0016,
BASE + 0x0000_0017,
BASE + 0x0000_0010, BASE + 0x0000_0011,
BASE + 0x0000_0012, BASE + 0x0000_0013,
BASE + 0x0000_0014, BASE + 0x0000_0015,
BASE + 0x0000_0016, BASE + 0x0000_0017,
BASE + 0x0000_0018, BASE + 0x0000_0019,
BASE + 0x0000_001A, BASE + 0x0000_001B,
BASE + 0x0000_001C, BASE + 0x0000_001D,
BASE + 0x0000_001E, BASE + 0x0000_001F,
BASE + 0x0000_0020, BASE + 0x0000_0021,
BASE + 0x0000_0022, BASE + 0x0000_0023,
BASE + 0x0000_0024, BASE + 0x0000_0025,
BASE + 0x0000_0026, BASE + 0x0000_0027,
BASE + 0x0000_0028, BASE + 0x0000_0029,
BASE + 0x0000_002A, BASE + 0x0000_002B,
BASE + 0x0000_002C, BASE + 0x0000_002D,
BASE + 0x0000_002E, BASE + 0x0000_002F
};
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 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;
@@ -198,6 +207,37 @@ public enum SignalValue : byte
SomeNumber = 0b111 // SOME NUMBER
}
/// <summary>
/// 逻辑分析仪有效通道数
/// </summary>
public enum AnalyzerChannelDiv
{
/// <summary>
/// 1路
/// </summary>
ONE = 0x0000_0000,
/// <summary>
/// 2路
/// </summary>
TWO = 0x0000_0001,
/// <summary>
/// 4路
/// </summary>
FOUR = 0x0000_0002,
/// <summary>
/// 8路
/// </summary>
EIGHT = 0x0000_0003,
/// <summary>
/// 16路
/// </summary>
XVI = 0x0000_0004,
/// <summary>
/// 32路
/// </summary>
XXXII = 0x0000_0005
}
/// <summary>
/// FPGA逻辑分析仪客户端用于控制FPGA上的逻辑分析仪模块进行信号捕获和分析
/// </summary>
@@ -239,58 +279,6 @@ public class Analyzer
/// <returns>操作结果成功返回true否则返回异常信息</returns>
public async ValueTask<Result<bool>> SetCaptureMode(bool captureOn, bool force)
{
{
var ret = await UDPClientPool.WriteAddr(this.ep, this.taskID, AnalyzerAddr.LOAD_NUM_ADDR, AnalyzerAddr.CAPTURE_DATA_LENGTH - 1, this.timeout);
if (!ret.IsSuccessful)
{
logger.Error($"Failed to set LOAD_NUM_ADDR: {ret.Error}");
return new(ret.Error);
}
if (!ret.Value)
{
logger.Error("WriteAddr to LOAD_NUM_ADDR returned false");
return new(new Exception("Failed to set LOAD_NUM_ADDR"));
}
}
{
var ret = await UDPClientPool.WriteAddr(this.ep, this.taskID, AnalyzerAddr.PRE_LOAD_NUM_ADDR, AnalyzerAddr.CAPTURE_DATA_PRELOAD - 1, this.timeout);
if (!ret.IsSuccessful)
{
logger.Error($"Failed to set PRE_LOAD_NUM_ADDR: {ret.Error}");
return new(ret.Error);
}
if (!ret.Value)
{
logger.Error("WriteAddr to PRE_LOAD_NUM_ADDR returned false");
return new(new Exception("Failed to set PRE_LOAD_NUM_ADDR"));
}
}
{
var ret = await UDPClientPool.WriteAddr(this.ep, this.taskID, AnalyzerAddr.DMA1_START_WRITE_ADDR, AnalyzerAddr.STORE_OFFSET_ADDR, this.timeout);
if (!ret.IsSuccessful)
{
logger.Error($"Failed to set DMA1_START_WRITE_ADDR: {ret.Error}");
return new(ret.Error);
}
if (!ret.Value)
{
logger.Error("WriteAddr to DMA1_START_WRITE_ADDR returned false");
return new(new Exception("Failed to set DMA1_START_WRITE_ADDR"));
}
}
{
var ret = await UDPClientPool.WriteAddr(this.ep, this.taskID, AnalyzerAddr.DMA1_END_WRITE_ADDR, AnalyzerAddr.STORE_OFFSET_ADDR + AnalyzerAddr.CAPTURE_DATA_LENGTH - 1, this.timeout);
if (!ret.IsSuccessful)
{
logger.Error($"Failed to set DMA1_END_WRITE_ADDR: {ret.Error}");
return new(ret.Error);
}
if (!ret.Value)
{
logger.Error("WriteAddr to DMA1_END_WRITE_ADDR returned false");
return new(new Exception("Failed to set DMA1_END_WRITE_ADDR"));
}
}
// 构造寄存器值
UInt32 value = 0;
if (captureOn) value |= 1 << 0;
@@ -380,7 +368,7 @@ public class Analyzer
return new(new ArgumentException($"Signal index must be 0~{AnalyzerAddr.SIGNAL_TRIG_MODE.Length}"));
// 计算模式值: [2:0] 信号值, [5:3] 操作符
UInt32 mode = ((UInt32)op << 3) | (UInt32) val;
UInt32 mode = ((UInt32)op << 3) | (UInt32)val;
var addr = AnalyzerAddr.SIGNAL_TRIG_MODE[signalIndex];
var ret = await UDPClientPool.WriteAddr(this.ep, this.taskID, addr, mode, this.timeout);
@@ -397,17 +385,96 @@ public class Analyzer
return true;
}
/// <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>
/// <returns>操作结果成功返回true否则返回异常信息</returns>
public async ValueTask<Result<bool>> SetCaptureParams(int capture_length, int pre_capture_length, AnalyzerChannelDiv channel_div)
{
if (capture_length == 0) capture_length = 1;
if (pre_capture_length == 0) pre_capture_length = 1;
{
var ret = await UDPClientPool.WriteAddr(this.ep, this.taskID, AnalyzerAddr.LOAD_NUM_ADDR, (UInt32)(capture_length - 1), this.timeout);
if (!ret.IsSuccessful)
{
logger.Error($"Failed to set LOAD_NUM_ADDR: {ret.Error}");
return new(ret.Error);
}
if (!ret.Value)
{
logger.Error("WriteAddr to LOAD_NUM_ADDR returned false");
return new(new Exception("Failed to set LOAD_NUM_ADDR"));
}
}
{
var ret = await UDPClientPool.WriteAddr(this.ep, this.taskID, AnalyzerAddr.PRE_LOAD_NUM_ADDR, (UInt32)(pre_capture_length - 1), this.timeout);
if (!ret.IsSuccessful)
{
logger.Error($"Failed to set PRE_LOAD_NUM_ADDR: {ret.Error}");
return new(ret.Error);
}
if (!ret.Value)
{
logger.Error("WriteAddr to PRE_LOAD_NUM_ADDR returned false");
return new(new Exception("Failed to set PRE_LOAD_NUM_ADDR"));
}
}
{
var ret = await UDPClientPool.WriteAddr(this.ep, this.taskID, AnalyzerAddr.DMA1_START_WRITE_ADDR, AnalyzerAddr.STORE_OFFSET_ADDR, this.timeout);
if (!ret.IsSuccessful)
{
logger.Error($"Failed to set DMA1_START_WRITE_ADDR: {ret.Error}");
return new(ret.Error);
}
if (!ret.Value)
{
logger.Error("WriteAddr to DMA1_START_WRITE_ADDR returned false");
return new(new Exception("Failed to set DMA1_START_WRITE_ADDR"));
}
}
{
var ret = await UDPClientPool.WriteAddr(this.ep, this.taskID, AnalyzerAddr.DMA1_END_WRITE_ADDR, AnalyzerAddr.STORE_OFFSET_ADDR + (UInt32)(capture_length - 1), this.timeout);
if (!ret.IsSuccessful)
{
logger.Error($"Failed to set DMA1_END_WRITE_ADDR: {ret.Error}");
return new(ret.Error);
}
if (!ret.Value)
{
logger.Error("WriteAddr to DMA1_END_WRITE_ADDR returned false");
return new(new Exception("Failed to set DMA1_END_WRITE_ADDR"));
}
}
{
var ret = await UDPClientPool.WriteAddr(this.ep, this.taskID, AnalyzerAddr.CAHNNEL_DIV_ADDR, (UInt32)channel_div, this.timeout);
if (!ret.IsSuccessful)
{
logger.Error($"Failed to set CAHNNEL_DIV_ADDR: {ret.Error}");
return new(ret.Error);
}
if (!ret.Value)
{
logger.Error("WriteAddr to CAHNNEL_DIV_ADDR returned false");
return new(new Exception("Failed to set CAHNNEL_DIV_ADDR"));
}
}
return true;
}
/// <summary>
/// 读取捕获的波形数据
/// </summary>
/// <returns>操作结果成功返回byte[],否则返回异常信息</returns>
public async ValueTask<Result<byte[]>> ReadCaptureData()
public async ValueTask<Result<byte[]>> ReadCaptureData(int capture_length = 2048 * 32)
{
var ret = await UDPClientPool.ReadAddr4BytesAsync(
this.ep,
this.taskID,
AnalyzerAddr.STORE_OFFSET_ADDR,
AnalyzerAddr.CAPTURE_DATA_LENGTH,
capture_length,
this.timeout
);
if (!ret.IsSuccessful)
@@ -416,7 +483,7 @@ public class Analyzer
return new(ret.Error);
}
var data = ret.Value;
if (data == null || data.Length != AnalyzerAddr.CAPTURE_DATA_LENGTH * 4)
if (data == null || data.Length != capture_length * 4)
{
logger.Error($"Capture data length mismatch: {data?.Length}");
return new(new Exception("Capture data length mismatch"));