Problem to solve
- ZLG 适配器在接收帧时没有正确处理特有的 txEchoed 回显标记
- ZLG 适配器支持比全局总线回显模式更细粒度的帧级别回显控制
麻烦评估一下是否需要实现?
最终目标
// 1. 使用总线全局回显模式(原有方式)
bus.Options.WorkMode = ChannelWorkMode.Echo;
bus.Transmit(frame);
// 2. 使用单帧回显(新增方式,无需总线回显模式)
var frameWithEcho = CanFrame.Fd(id, data)
{
Flags = FrameFlags.Echo // 设置帧级别的回显请求
};
bus.Transmit(frameWithEcho); // 即使总线不在回显模式,该帧也会被回显
Proposal
1、通用api修改
新增 FrameFlags.Echo 标志(CanFrame.cs)
[Flags]
public enum FrameFlags : ushort
{
None = 0,
Ext = 1,
Rtr = 2,
Brs = 4,
Esi = 8,
Error = 16,
Echo = 32 // 新增: 软件级发送回显请求标志
}
在 CanFrameView 和 CanFrame中新增 IsEchoRequested 属性 public bool IsEchoRequested => (Flags & FrameFlags.Echo) != 0;
在 CanFrame 的工厂方法中添加 isEchoRequested 参数以方便使用
在以下工厂方法中添加可选的 isEchoRequested 参数:
- CanFrame.Classic() (两个重载)
- CanFrame.Fd() (两个重载)
这样用户可以更方便地创建带回显请求的帧,而不需要手动设置 Flags。
2、ZLG适配器修改
新增细粒度回显特性标志 ( ZlgEnums.cs )
[Flags]
public enum ZlgFeature
{
None = 0x0,
MergeReceive = 0x4,
SkipBitRate = 0x8,
PerFrameEcho = 0x10 // 新增: 细粒度单帧回显支持
}
修复接收时的回显标记处理 ( ZlgUtils.cs )
- 在 FromZCANDataClassic() 和 FromZCANDataFd() 中设置 IsEcho = pObj.data.fdData.txEchoed,这两个方法在从 ZCANDataObj 转换时,忽略了 txEchoed 标记,导致通过合并接收方式收到的回显帧无法被识别
// 设置 IsEcho
return new CanReceiveData(result) { IsEcho = pObj.data.fdData.txEchoed };
- 在 ZlgCanFdTransceiver.Receive() 中检查 TX_ECHO_FLAG,在从 ZCAN_ReceiveFD_Data 转换时,没有检查 TX_ECHO_FLAG ,导致通过独立通道接收方式收到的回显帧无法被识别
public IEnumerable<CanReceiveData> Receive(ICanBus<IBusRTOptionsConfigurator> bus, int count = 1, int timeOut = 0)
{
var pool = ArrayPool<ZCAN_ReceiveFD_Data>.Shared;
var buf = pool.Rent(ZCAN.BATCH_COUNT);
try
{
while (count > 0)
{
var recCount = ZCAN.ZCAN_ReceiveFD(((ZlgCanBus)bus).Handle, buf, (uint)count, remaining);
for (int i = 0; i < recCount; i++)
{
// 检查 TX_ECHO_FLAG 来判断是否为回显帧
var isEcho = (buf[i].frame.flags & ZCAN.TX_ECHO_FLAG) != 0;
yield return new CanReceiveData(buf[i].frame.FromReceiveData(bus.Options.BufferAllocator))
{
// ZLG timestamp is in microseconds
ReceiveTimestamp = TimeSpan.FromTicks((long)buf[i].timestamp * 10),
IsEcho = isEcho // 设置回显标记
};
}
count -= (int)recCount;
}
}
finally
{
pool.Return(buf);
}
}
实现帧级别的回显控制 ( ZlgUtils.cs )
在所有发送转换方法中实现:bool shouldEcho = frame.IsEchoRequested || echo; // 帧级别优先,否则使用总线设置
在所有 ZLG Provider 中启用新特性
Alternatives considered
在 FrameFlags 中添加软件级 Echo 标志,但我看FrameFlags中的其它枚举是对应的硬件含义,添加一个软件的Echo是否不太好?
考虑将回显控制移到 API 参数层面而非标志层面(如果语义一致性很重要)
如果需要保持 FrameFlags 只包含硬件协议位的语义一致性,可以:
- 从 FrameFlags 中移除 Echo 标志
- 在 ITransceiver.Transmit() 和 ICanBus.Transmit() 系列方法中添加可选的 requestEcho 参数
- 或者创建一个包含 requestEcho 字段的发送选项类
这样可以保持 API 的语义一致性,但需要修改通用 API。
Areas
Problem to solve
麻烦评估一下是否需要实现?
最终目标
Proposal
1、通用api修改
新增 FrameFlags.Echo 标志(CanFrame.cs)
在 CanFrameView 和 CanFrame中新增 IsEchoRequested 属性
public bool IsEchoRequested => (Flags & FrameFlags.Echo) != 0;在 CanFrame 的工厂方法中添加 isEchoRequested 参数以方便使用
在以下工厂方法中添加可选的 isEchoRequested 参数:
这样用户可以更方便地创建带回显请求的帧,而不需要手动设置 Flags。
2、ZLG适配器修改
新增细粒度回显特性标志 ( ZlgEnums.cs )
修复接收时的回显标记处理 ( ZlgUtils.cs )
实现帧级别的回显控制 ( ZlgUtils.cs )
在所有发送转换方法中实现:
bool shouldEcho = frame.IsEchoRequested || echo; // 帧级别优先,否则使用总线设置在所有 ZLG Provider 中启用新特性
Alternatives considered
在 FrameFlags 中添加软件级 Echo 标志,但我看FrameFlags中的其它枚举是对应的硬件含义,添加一个软件的Echo是否不太好?
考虑将回显控制移到 API 参数层面而非标志层面(如果语义一致性很重要)
如果需要保持 FrameFlags 只包含硬件协议位的语义一致性,可以:
这样可以保持 API 的语义一致性,但需要修改通用 API。
Areas