diff --git a/SJA1000_CAN.cs b/SJA1000_CAN.cs
index 150a4fd..4d7d699 100644
--- a/SJA1000_CAN.cs
+++ b/SJA1000_CAN.cs
@@ -1,480 +1,510 @@
-//
-// SJA1000 CAN 控制器外设实现(简化版)
-// 仅支持 PeliCAN 模式的标准帧,不考虑 BasicCAN、扩展帧、错误处理、多帧、验收滤波和发送中断。
-// 寄存器地址映射基于 PeliCAN 模式,包含 MOD, CMR, SR, IR, IER, BTR0, BTR1, OCR, RXERR, TXERR,
-// 发送缓冲区(地址 16-26)、RBSA 和 CDR。命令寄存器位2=RRB,位3=CDO。
-// 接收为单帧,无 FIFO,无数据溢出处理。
-// 所有寄存器可随时读写,无复位模式限制。
-//
-// author: Generated based on UART16550 template
-//
-
-using System;
-using System.Text;
-using System.Collections.Generic;
-using Antmicro.Renode.Core;
-using Antmicro.Renode.Logging;
-using Antmicro.Renode.Peripherals.Bus;
-using Antmicro.Renode.Utilities;
-using Antmicro.Renode.Time;
-
-namespace Antmicro.Renode.Peripherals.CustomPeripherals
-{
- ///
- /// 简化版 SJA1000 CAN 控制器(PeliCAN 模式,仅标准帧)
- ///
- public class SJA1000_CAN : IDoubleWordPeripheral, IBytePeripheral, IKnownSize
- {
- public SJA1000_CAN(IMachine machine)
- {
- this.machine = machine;
- IRQ = new GPIO();
-
- txBuffer = new byte[11];
- rxBuffer = new byte[11];
-
- Reset();
- }
-
- public void Reset()
- {
- mod = 0;
- ier = 0;
- btr0 = 0;
- btr1 = 0;
- ocr = 0;
- rxerr = 0;
- txerr = 0;
- rbsa = 0;
- cdr = 0;
-
- sr_tbs = 1; // 发送缓冲区初始为空闲
- sr_rbs = 0; // 接收缓冲区初始为空
- ir = 0;
-
- Array.Clear(txBuffer, 0, txBuffer.Length);
- Array.Clear(rxBuffer, 0, rxBuffer.Length);
-
- UpdateInterrupts();
-
- this.Log(LogLevel.Info, "SJA1000 CAN controller reset (simplified)");
- }
-
- // ================ IBusPeripheral 接口实现 ================
-
- public uint ReadDoubleWord(long offset)
- {
- return ReadByte(offset);
- }
-
- public void WriteDoubleWord(long offset, uint value)
- {
- WriteByte(offset, (byte)value);
- }
-
- public byte ReadByte(long offset)
- {
- byte value = 0;
- switch ((Registers)offset)
- {
- case Registers.MOD:
- value = mod;
- this.Log(LogLevel.Info, "Read MOD: 0x{0:X2}", value);
- break;
-
- case Registers.CMR:
- // 命令寄存器只写,读返回0
- this.Log(LogLevel.Info, "Read CMR (always 0)");
- value = 0;
- break;
-
- case Registers.SR:
- value = (byte)((sr_tbs << 2) | sr_rbs); // BS 恒为0
- this.Log(LogLevel.Info, "Read SR: TBS={0}, RBS={1} -> 0x{2:X2}", sr_tbs, sr_rbs, value);
- break;
-
- case Registers.IR:
- value = ir;
- // 读 IR 后清零,但需要根据当前 RBS 重新评估 RI(电平触发)
- ir = 0;
- UpdateIrFromRbs();
- UpdateInterrupts();
- this.Log(LogLevel.Info, "Read IR: 0x{0:X2}, cleared", value);
- break;
-
- case Registers.IER:
- value = ier;
- this.Log(LogLevel.Info, "Read IER: 0x{0:X2}", value);
- break;
-
- case Registers.BTR0:
- value = btr0;
- break;
- case Registers.BTR1:
- value = btr1;
- break;
- case Registers.OCR:
- value = ocr;
- break;
- case Registers.RXERR:
- value = rxerr;
- break;
- case Registers.TXERR:
- value = txerr;
- break;
- case Registers.RBSA:
- value = rbsa;
- break;
- case Registers.CDR:
- value = cdr;
- break;
-
- // 发送/接收缓冲区地址 16-26
- case Registers.TX_FRAME_INFO:
- case Registers.TX_ID1:
- case Registers.TX_ID2:
- case Registers.TX_DATA1:
- case Registers.TX_DATA2:
- case Registers.TX_DATA3:
- case Registers.TX_DATA4:
- case Registers.TX_DATA5:
- case Registers.TX_DATA6:
- case Registers.TX_DATA7:
- case Registers.TX_DATA8:
- int bufIndex = (int)(offset - (long)Registers.TX_FRAME_INFO);
- if (sr_rbs == 1)
- {
- // 接收缓冲区有数据时,读返回接收帧的内容
- value = rxBuffer[bufIndex/4];
- this.Log(LogLevel.Info, "Read RX buffer[{0}]: 0x{1:X2}", bufIndex/4, value);
- }
- else
- {
- //否则返回发送缓冲区的内容(通常无意义)
- value = txBuffer[bufIndex/4];
- this.Log(LogLevel.Info, "Read TX buffer[{0}]: 0x{1:X2}", bufIndex/4, value);
-
- }
- break;
-
- default:
- // 未实现的寄存器返回0
- this.Log(LogLevel.Info, "Read from unimplemented offset 0x{0:X}", offset);
- value = 0;
- break;
- }
- return value;
- }
-
- public void WriteByte(long offset, byte value)
- {
- switch ((Registers)offset)
- {
- case Registers.MOD:
- mod = value;
- this.Log(LogLevel.Info, "Write MOD: 0x{0:X2}", value);
- break;
-
- case Registers.CMR:
- // 命令寄存器只写,处理命令
- this.Log(LogLevel.Info, "Write CMR: 0x{0:X2}", value);
- if ((value & CMR_TR) != 0)
- {
- // 发送请求
- if (sr_tbs == 1)
- {
- sr_tbs = 0; // 锁定发送缓冲区
- /*** 测试 ***/
- GetTxBufferDataString();
- }
- else
- {
- this.Log(LogLevel.Warning, "Send request while TBS=0 ignored");
- }
- }
- if ((value & CMR_RRB) != 0)
- {
- // 释放接收缓冲器
- sr_rbs = 0;
- UpdateIrFromRbs();
- UpdateInterrupts();
- this.Log(LogLevel.Info, "Receive buffer released");
- }
- if ((value & CMR_CDO) != 0)
- {
- // 清除数据溢出(无操作)
- this.Log(LogLevel.Info, "Clear data overflow (no effect)");
- }
- break;
-
- case Registers.SR:
- if (sr_tbs == 1)
- {
- sr_tbs = 0;
- }
- else
- {
- sr_tbs = 1;
- }
- if (sr_rbs == 1)
- {
- sr_rbs = 0;
- }
- else
- {
- sr_rbs = 1;
- }
- break;
- case Registers.IR:
- // 只读,忽略写
- this.Log(LogLevel.Warning, "Attempted write to read-only IR");
- break;
-
- case Registers.IER:
- ier = (byte)(value & 0x01); // 只使用 bit0 (RIE)
- UpdateIrFromRbs();
- UpdateInterrupts();
- this.Log(LogLevel.Info, "Write IER: 0x{0:X2}", ier);
- break;
-
- case Registers.BTR0:
- btr0 = value;
- this.Log(LogLevel.Info, "Write BTR0: 0x{0:X2}", value);
- break;
- case Registers.BTR1:
- btr1 = value;
- this.Log(LogLevel.Info, "Write BTR1: 0x{0:X2}", value);
- break;
- case Registers.OCR:
- ocr = value;
- this.Log(LogLevel.Info, "Write OCR: 0x{0:X2}", value);
- break;
- case Registers.RXERR:
- rxerr = value;
- this.Log(LogLevel.Info, "Write RXERR: 0x{0:X2}", value);
- break;
- case Registers.TXERR:
- txerr = value;
- this.Log(LogLevel.Info, "Write TXERR: 0x{0:X2}", value);
- break;
- case Registers.RBSA:
- rbsa = value;
- this.Log(LogLevel.Info, "Write RBSA: 0x{0:X2}", value);
- break;
- case Registers.CDR:
- cdr = value;
- this.Log(LogLevel.Info, "Write CDR: 0x{0:X2}", value);
- break;
-
- // 发送缓冲区写入
- case Registers.TX_FRAME_INFO:
- case Registers.TX_ID1:
- case Registers.TX_ID2:
- case Registers.TX_DATA1:
- case Registers.TX_DATA2:
- case Registers.TX_DATA3:
- case Registers.TX_DATA4:
- case Registers.TX_DATA5:
- case Registers.TX_DATA6:
- case Registers.TX_DATA7:
- case Registers.TX_DATA8:
- int bufIndex = (int)(offset - (long)Registers.TX_FRAME_INFO);
- if (sr_tbs == 1)
- {
- txBuffer[bufIndex/4] = value;
- this.Log(LogLevel.Info, "Write TX buffer[{0}]: 0x{1:X2}", bufIndex/4, value);
- }
- else
- {
- this.Log(LogLevel.Warning, "Write to TX buffer while TBS=0 ignored");
- }
- break;
-
- default:
- // 未实现的寄存器忽略写
- this.Log(LogLevel.Info, "Write to unimplemented offset 0x{0:X} = 0x{1:X2}", offset, value);
- break;
- }
- }
-
- // ================ 公共方法与事件 ================
-
-
-
-
- private void UpdateIrFromRbs()
- {
- if (sr_rbs == 1)
- ir |= IR_RI;
- else
- // ir &= (byte)~IR_RI;
- ir = (byte)(ir & ~IR_RI);
- }
-
- private void UpdateInterrupts()
- {
- bool interrupt = ((ir & IR_RI) != 0) && ((ier & IER_RIE) != 0);
- IRQ.Set(interrupt);
- if (interrupt)
- {
- machine.ScheduleAction(TimeInterval.FromMicroseconds(1), _ =>
- {
- IRQ.Set(false);
- });
- this.Log(LogLevel.Info, "Interrupt asserted (RI)");
- }
- else
- {
- this.Log(LogLevel.Info, "Interrupt deasserted");
- }
- }
- private readonly object lockObject = new object(); // 用于线程安全的锁对象
-
- public string GetTxBufferDataString()
- {
- if(sr_tbs ==1)
- {
- Console.WriteLine("sr_tbs=1");
- return null;
- }
- lock (lockObject)
- {
- var sb = new StringBuilder();
- for (int i = 0; i < txBuffer.Length; i++)
- {
- if (i > 0) sb.Append(" ");
- sb.Append(txBuffer[i].ToString("X2"));
- }
- string result = sb.ToString();
- Console.WriteLine("GetTxBufferDataString returning: " + result);
- Array.Clear(txBuffer, 0, txBuffer.Length);
- sr_tbs = 1;
- return result;
- }
- }
-
- public void SendRxBufferDataString(string frameString)
- {
- lock (lockObject)
- {
-
-
- if (string.IsNullOrWhiteSpace(frameString))
- {
- Console.WriteLine("ReceiveFrame: empty string, ignored");
- return;
- }
- if (sr_rbs==1)
- {
- Console.WriteLine("rxBuffer is full");
- return;
- }
- Array.Clear(rxBuffer, 0, rxBuffer.Length);
- string[] parts = frameString.Split(new[] { ' ', '\t' }, StringSplitOptions.RemoveEmptyEntries);
- int count = Math.Min(parts.Length, rxBuffer.Length);
-
- for (int i = 0; i < count; i++)
- {
- string part = parts[i].Trim();
- if (byte.TryParse(part, System.Globalization.NumberStyles.HexNumber,
- System.Globalization.CultureInfo.InvariantCulture, out byte b))
- {
- rxBuffer[i] = b;
- }
- else
- {
- Console.WriteLine($"ReceiveFrame: invalid hex byte '{part}' at index {i}, set to 0");
- rxBuffer[i] = 0;
- }
- }
-
- sr_rbs = 1;
- UpdateIrFromRbs();
- UpdateInterrupts();
-
- // 打印 rxBuffer 内容
- var sb = new StringBuilder();
- sb.Append("RX Buffer after receive: ");
- for (int i = 0; i < rxBuffer.Length; i++)
- {
- if (i > 0) sb.Append(" ");
- sb.Append(rxBuffer[i].ToString("X2"));
- }
- Console.WriteLine(sb.ToString());
-
- Console.WriteLine($"Frame received from string: {frameString}");
- }
- }
- // ================ 属性 ================
-
- public long Size => 0x80; // 地址范围 0-31
-
- public GPIO IRQ { get; }
-
- // ================ 寄存器枚举 ================
-
- private enum Registers : long
- {
- MOD = 0x00,
- CMR = 0x04,
- SR = 0x08,
- IR = 0x0C,
- IER = 0x10,
- BTR0 = 0x18,
- BTR1 = 0x1C,
- OCR = 0x20,
- RXERR = 0x38, // 14
- TXERR = 0x3C, // 15
- TX_FRAME_INFO = 0x40, // 16
- TX_ID1 = 0x44,
- TX_ID2 = 0x48,
- TX_DATA1 = 0x4C,
- TX_DATA2 = 0x50,
- TX_DATA3 = 0x54,
- TX_DATA4 = 0x58,
- TX_DATA5 = 0x5C,
- TX_DATA6 = 0x60,
- TX_DATA7 = 0x64,
- TX_DATA8 = 0x68, // 26
- RBSA = 0x78, // 30
- CDR = 0x7C, // 31
-
- }
-
- // ================ 常量位定义 ================
-
- private const byte CMR_TR = 0x01; // 发送请求 (bit0)
- private const byte CMR_RRB = 0x04; // 释放接收缓冲器 (bit2)
- private const byte CMR_CDO = 0x08; // 清除数据溢出 (bit3)
-
- private const byte SR_BS = 0x80; // 总线状态 (bit7) - 本模拟中恒0
- private const byte SR_TBS = 0x04; // 发送缓冲器状态 (bit2)
- private const byte SR_RBS = 0x01; // 接收缓冲器状态 (bit0)
-
- private const byte IR_RI = 0x01; // 接收中断 (bit0)
-
- private const byte IER_RIE = 0x01; // 接收中断使能 (bit0)
-
- // ================ 私有字段 ================
-
- private readonly IMachine machine;
-
- // 寄存器存储
- private byte mod;
- private byte ier;
- private byte btr0, btr1;
- private byte ocr;
- private byte rxerr, txerr;
- private byte rbsa;
- private byte cdr;
-
- // 状态位
- private byte sr_tbs; // 1=空闲
- private byte sr_rbs; // 1=有数据
-
- private byte ir; // 仅 bit0 有效
-
- private readonly byte[] txBuffer; // 地址16-26
- private readonly byte[] rxBuffer; // 当前接收帧
- }
-}
+//
+// SJA1000 CAN 控制器外设实现(简化版,支持发送/接收队列,提高速率)
+// 仅支持 PeliCAN 模式的标准帧,不考虑 BasicCAN、扩展帧、错误处理、多帧、验收滤波和发送中断。
+// 寄存器地址映射基于 PeliCAN 模式,包含 MOD, CMR, SR, IR, IER, BTR0, BTR1, OCR, RXERR, TXERR,
+// 发送缓冲区(地址 16-26)、RBSA 和 CDR。命令寄存器位2=RRB,位3=CDO。
+// 接收为单帧,无 FIFO,无数据溢出处理。
+// 所有寄存器可随时读写,无复位模式限制。
+//
+// author: Generated based on UART16550 template
+//
+
+using System;
+using System.Text;
+using System.Collections.Generic;
+using Antmicro.Renode.Core;
+using Antmicro.Renode.Logging;
+using Antmicro.Renode.Peripherals.Bus;
+using Antmicro.Renode.Utilities;
+using Antmicro.Renode.Time;
+
+namespace Antmicro.Renode.Peripherals.CustomPeripherals
+{
+ ///
+ /// 简化版 SJA1000 CAN 控制器(PeliCAN 模式,仅标准帧)
+ ///
+ public class SJA1000_CAN : IDoubleWordPeripheral, IBytePeripheral, IKnownSize
+ {
+ public SJA1000_CAN(IMachine machine)
+ {
+ this.machine = machine;
+ IRQ = new GPIO();
+
+ txBuffer = new byte[11];
+ rxBuffer = new byte[11];
+ txFrameQueue = new Queue(); // 新增:发送队列
+ rxFrameQueue = new Queue(); // 新增:接收队列
+
+ Reset();
+ }
+
+ public void Reset()
+ {
+ mod = 0;
+ ier = 0;
+ btr0 = 0;
+ btr1 = 0;
+ ocr = 0;
+ rxerr = 0;
+ txerr = 0;
+ rbsa = 0;
+ cdr = 0;
+
+ sr_tbs = 1; // 发送缓冲区初始为空闲
+ sr_rbs = 0; // 接收缓冲区初始为空
+ ir = 0;
+
+ Array.Clear(txBuffer, 0, txBuffer.Length);
+ Array.Clear(rxBuffer, 0, rxBuffer.Length);
+ txFrameQueue.Clear(); // 清空发送队列
+ rxFrameQueue.Clear(); // 清空接收队列
+
+ UpdateInterrupts();
+
+ this.Log(LogLevel.Info, "SJA1000 CAN controller reset (simplified)");
+ }
+
+ // ================ IBusPeripheral 接口实现 ================
+
+ public uint ReadDoubleWord(long offset)
+ {
+ return ReadByte(offset);
+ }
+
+ public void WriteDoubleWord(long offset, uint value)
+ {
+ WriteByte(offset, (byte)value);
+ }
+
+ public byte ReadByte(long offset)
+ {
+ byte value = 0;
+ switch ((Registers)offset)
+ {
+ case Registers.MOD:
+ value = mod;
+ this.Log(LogLevel.Info, "Read MOD: 0x{0:X2}", value);
+ break;
+
+ case Registers.CMR:
+ // 命令寄存器只写,读返回0
+ this.Log(LogLevel.Info, "Read CMR (always 0)");
+ value = 0;
+ break;
+
+ case Registers.SR:
+ value = (byte)((sr_tbs << 2) | sr_rbs); // BS 恒为0
+ this.Log(LogLevel.Info, "Read SR: TBS={0}, RBS={1} -> 0x{2:X2}", sr_tbs, sr_rbs, value);
+ break;
+
+ case Registers.IR:
+ value = ir;
+ // 读 IR 后清零,但需要根据当前 RBS 重新评估 RI(电平触发)
+ ir = 0;
+ UpdateIrFromRbs();
+ UpdateInterrupts();
+ this.Log(LogLevel.Info, "Read IR: 0x{0:X2}, cleared", value);
+ break;
+
+ case Registers.IER:
+ value = ier;
+ this.Log(LogLevel.Info, "Read IER: 0x{0:X2}", value);
+ break;
+
+ case Registers.BTR0:
+ value = btr0;
+ break;
+ case Registers.BTR1:
+ value = btr1;
+ break;
+ case Registers.OCR:
+ value = ocr;
+ break;
+ case Registers.RXERR:
+ value = rxerr;
+ break;
+ case Registers.TXERR:
+ value = txerr;
+ break;
+ case Registers.RBSA:
+ value = rbsa;
+ break;
+ case Registers.CDR:
+ value = cdr;
+ break;
+
+ // 发送/接收缓冲区地址 16-26
+ case Registers.TX_FRAME_INFO:
+ case Registers.TX_ID1:
+ case Registers.TX_ID2:
+ case Registers.TX_DATA1:
+ case Registers.TX_DATA2:
+ case Registers.TX_DATA3:
+ case Registers.TX_DATA4:
+ case Registers.TX_DATA5:
+ case Registers.TX_DATA6:
+ case Registers.TX_DATA7:
+ case Registers.TX_DATA8:
+ int bufIndex = (int)(offset - (long)Registers.TX_FRAME_INFO);
+ if (sr_rbs == 1)
+ {
+ // 接收缓冲区有数据时,读返回接收帧的内容
+ value = rxBuffer[bufIndex/4];
+ this.Log(LogLevel.Info, "Read RX buffer[{0}]: 0x{1:X2}", bufIndex/4, value);
+ }
+ else
+ {
+ //否则返回发送缓冲区的内容(通常无意义)
+ value = txBuffer[bufIndex/4];
+ this.Log(LogLevel.Info, "Read TX buffer[{0}]: 0x{1:X2}", bufIndex/4, value);
+
+ }
+ break;
+
+ default:
+ // 未实现的寄存器返回0
+ this.Log(LogLevel.Info, "Read from unimplemented offset 0x{0:X}", offset);
+ value = 0;
+ break;
+ }
+ return value;
+ }
+
+ public void WriteByte(long offset, byte value)
+ {
+ switch ((Registers)offset)
+ {
+ case Registers.MOD:
+ mod = value;
+ this.Log(LogLevel.Info, "Write MOD: 0x{0:X2}", value);
+ break;
+
+ case Registers.CMR:
+ // 命令寄存器只写,处理命令
+ this.Log(LogLevel.Info, "Write CMR: 0x{0:X2}", value);
+ if ((value & CMR_TR) != 0)
+ {
+ // 发送请求
+ if (sr_tbs == 1)
+ {
+ // 将当前 txBuffer 复制一份加入发送队列
+ var frame = new byte[11];
+ Array.Copy(txBuffer, frame, 11);
+ lock (lockObject)
+ {
+ txFrameQueue.Enqueue(frame);
+ }
+ // 清空发送缓冲区,并立即释放 TBS,允许 CPU 继续写入下一帧
+ Array.Clear(txBuffer, 0, txBuffer.Length);
+ sr_tbs = 1;
+ this.Log(LogLevel.Info, "Frame enqueued for transmission, queue size: {0}", txFrameQueue.Count);
+ }
+ else
+ {
+ this.Log(LogLevel.Warning, "Send request while TBS=0 ignored");
+ }
+ }
+ if ((value & CMR_RRB) != 0)
+ {
+ // 释放接收缓冲器:尝试从接收队列中加载下一帧
+ lock (lockObject)
+ {
+ LoadNextRxFrame();
+ }
+ this.Log(LogLevel.Info, "Receive buffer released");
+ }
+ if ((value & CMR_CDO) != 0)
+ {
+ // 清除数据溢出(无操作)
+ this.Log(LogLevel.Info, "Clear data overflow (no effect)");
+ }
+ break;
+
+ case Registers.SR:
+ if (sr_tbs == 1)
+ {
+ sr_tbs = 0;
+ }
+ else
+ {
+ sr_tbs = 1;
+ }
+ if (sr_rbs == 1)
+ {
+ sr_rbs = 0;
+ }
+ else
+ {
+ sr_rbs = 1;
+ }
+ break;
+ case Registers.IR:
+ // 只读,忽略写
+ this.Log(LogLevel.Warning, "Attempted write to read-only IR");
+ break;
+
+ case Registers.IER:
+ ier = (byte)(value & 0x01); // 只使用 bit0 (RIE)
+ UpdateIrFromRbs();
+ UpdateInterrupts();
+ this.Log(LogLevel.Info, "Write IER: 0x{0:X2}", ier);
+ break;
+
+ case Registers.BTR0:
+ btr0 = value;
+ this.Log(LogLevel.Info, "Write BTR0: 0x{0:X2}", value);
+ break;
+ case Registers.BTR1:
+ btr1 = value;
+ this.Log(LogLevel.Info, "Write BTR1: 0x{0:X2}", value);
+ break;
+ case Registers.OCR:
+ ocr = value;
+ this.Log(LogLevel.Info, "Write OCR: 0x{0:X2}", value);
+ break;
+ case Registers.RXERR:
+ rxerr = value;
+ this.Log(LogLevel.Info, "Write RXERR: 0x{0:X2}", value);
+ break;
+ case Registers.TXERR:
+ txerr = value;
+ this.Log(LogLevel.Info, "Write TXERR: 0x{0:X2}", value);
+ break;
+ case Registers.RBSA:
+ rbsa = value;
+ this.Log(LogLevel.Info, "Write RBSA: 0x{0:X2}", value);
+ break;
+ case Registers.CDR:
+ cdr = value;
+ this.Log(LogLevel.Info, "Write CDR: 0x{0:X2}", value);
+ break;
+
+ // 发送缓冲区写入
+ case Registers.TX_FRAME_INFO:
+ case Registers.TX_ID1:
+ case Registers.TX_ID2:
+ case Registers.TX_DATA1:
+ case Registers.TX_DATA2:
+ case Registers.TX_DATA3:
+ case Registers.TX_DATA4:
+ case Registers.TX_DATA5:
+ case Registers.TX_DATA6:
+ case Registers.TX_DATA7:
+ case Registers.TX_DATA8:
+ int bufIndex = (int)(offset - (long)Registers.TX_FRAME_INFO);
+ if (sr_tbs == 1)
+ {
+ txBuffer[bufIndex/4] = value;
+ this.Log(LogLevel.Info, "Write TX buffer[{0}]: 0x{1:X2}", bufIndex/4, value);
+ }
+ else
+ {
+ this.Log(LogLevel.Warning, "Write to TX buffer while TBS=0 ignored");
+ }
+ break;
+
+ default:
+ // 未实现的寄存器忽略写
+ this.Log(LogLevel.Info, "Write to unimplemented offset 0x{0:X} = 0x{1:X2}", offset, value);
+ break;
+ }
+ }
+
+ // ================ 公共方法与事件 ================
+
+ private void UpdateIrFromRbs()
+ {
+ if (sr_rbs == 1)
+ ir |= IR_RI;
+ else
+ ir = (byte)(ir & ~IR_RI);
+ }
+
+ private void UpdateInterrupts()
+ {
+ bool interrupt = ((ir & IR_RI) != 0) && ((ier & IER_RIE) != 0);
+ IRQ.Set(interrupt);
+ if (interrupt)
+ {
+ machine.ScheduleAction(TimeInterval.FromMicroseconds(1), _ =>
+ {
+ IRQ.Set(false);
+ });
+ this.Log(LogLevel.Info, "Interrupt asserted (RI)");
+ }
+ else
+ {
+ this.Log(LogLevel.Info, "Interrupt deasserted");
+ }
+ }
+ private readonly object lockObject = new object(); // 用于线程安全的锁对象
+
+ ///
+ /// 获取发送队列中所有帧的字符串表示(每帧以空格分隔的十六进制字节,帧间用换行分隔)
+ /// 调用后清空发送队列。
+ ///
+ public string GetTxBufferDataString()
+ {
+ lock (lockObject)
+ {
+ if (txFrameQueue.Count == 0)
+ {
+ Console.WriteLine("GetTxBufferDataString: no frames in TX queue");
+ return null;
+ }
+ var sb = new StringBuilder();
+ while (txFrameQueue.Count > 0)
+ {
+ var frame = txFrameQueue.Dequeue();
+ for (int i = 0; i < frame.Length; i++)
+ {
+ if (i > 0) sb.Append(" ");
+ sb.Append(frame[i].ToString("X2"));
+ }
+ sb.AppendLine(); // 帧间换行
+ }
+ string result = sb.ToString().TrimEnd();
+ Console.WriteLine("GetTxBufferDataString returning: " + result);
+ return result;
+ }
+ }
+
+ ///
+ /// 外部接口注入一帧接收数据(11字节的十六进制字符串,空格分隔)
+ /// 可多次调用以注入多帧,帧将存入接收队列。
+ ///
+ public void SendRxBufferDataString(string frameString)
+ {
+ lock (lockObject)
+ {
+ if (string.IsNullOrWhiteSpace(frameString))
+ {
+ Console.WriteLine("SendRxBufferDataString: empty string, ignored");
+ return;
+ }
+ string[] parts = frameString.Split(new[] { ' ', '\t' }, StringSplitOptions.RemoveEmptyEntries);
+ if (parts.Length != 11)
+ {
+ Console.WriteLine($"SendRxBufferDataString: expected 11 bytes, got {parts.Length}, ignored");
+ return;
+ }
+ byte[] frame = new byte[11];
+ for (int i = 0; i < 11; i++)
+ {
+ string part = parts[i].Trim();
+ if (!byte.TryParse(part, System.Globalization.NumberStyles.HexNumber,
+ System.Globalization.CultureInfo.InvariantCulture, out byte b))
+ {
+ Console.WriteLine($"SendRxBufferDataString: invalid hex byte '{part}' at index {i}, set to 0");
+ b = 0;
+ }
+ frame[i] = b;
+ }
+ rxFrameQueue.Enqueue(frame);
+ Console.WriteLine($"Frame enqueued to RX queue, size: {rxFrameQueue.Count}");
+
+ // 如果当前接收缓冲区空闲,立即加载第一帧
+ if (sr_rbs == 0)
+ {
+ LoadNextRxFrame();
+ }
+ }
+ }
+
+ // 从接收队列中加载下一帧到 rxBuffer,并更新状态
+ private void LoadNextRxFrame()
+ {
+ if (rxFrameQueue.Count > 0)
+ {
+ var frame = rxFrameQueue.Dequeue();
+ Array.Copy(frame, rxBuffer, 11);
+ sr_rbs = 1;
+ UpdateIrFromRbs();
+ UpdateInterrupts();
+ Console.WriteLine("Loaded next RX frame into buffer, queue remaining: {0}", rxFrameQueue.Count);
+ }
+ else
+ {
+ sr_rbs = 0;
+ UpdateIrFromRbs();
+ UpdateInterrupts();
+ Console.WriteLine("RX queue empty, buffer cleared");
+ }
+ }
+
+ // ================ 属性 ================
+
+ public long Size => 0x80; // 地址范围 0-31
+
+ public GPIO IRQ { get; }
+
+ // ================ 寄存器枚举 ================
+
+ private enum Registers : long
+ {
+ MOD = 0x00,
+ CMR = 0x04,
+ SR = 0x08,
+ IR = 0x0C,
+ IER = 0x10,
+ BTR0 = 0x18,
+ BTR1 = 0x1C,
+ OCR = 0x20,
+ RXERR = 0x38, // 14
+ TXERR = 0x3C, // 15
+ TX_FRAME_INFO = 0x40, // 16
+ TX_ID1 = 0x44,
+ TX_ID2 = 0x48,
+ TX_DATA1 = 0x4C,
+ TX_DATA2 = 0x50,
+ TX_DATA3 = 0x54,
+ TX_DATA4 = 0x58,
+ TX_DATA5 = 0x5C,
+ TX_DATA6 = 0x60,
+ TX_DATA7 = 0x64,
+ TX_DATA8 = 0x68, // 26
+ RBSA = 0x78, // 30
+ CDR = 0x7C, // 31
+
+ }
+
+ // ================ 常量位定义 ================
+
+ private const byte CMR_TR = 0x01; // 发送请求 (bit0)
+ private const byte CMR_RRB = 0x04; // 释放接收缓冲器 (bit2)
+ private const byte CMR_CDO = 0x08; // 清除数据溢出 (bit3)
+
+ private const byte SR_BS = 0x80; // 总线状态 (bit7) - 本模拟中恒0
+ private const byte SR_TBS = 0x04; // 发送缓冲器状态 (bit2)
+ private const byte SR_RBS = 0x01; // 接收缓冲器状态 (bit0)
+
+ private const byte IR_RI = 0x01; // 接收中断 (bit0)
+
+ private const byte IER_RIE = 0x01; // 接收中断使能 (bit0)
+
+ // ================ 私有字段 ================
+
+ private readonly IMachine machine;
+
+ // 寄存器存储
+ private byte mod;
+ private byte ier;
+ private byte btr0, btr1;
+ private byte ocr;
+ private byte rxerr, txerr;
+ private byte rbsa;
+ private byte cdr;
+
+ // 状态位
+ private byte sr_tbs; // 1=空闲
+ private byte sr_rbs; // 1=有数据
+
+ private byte ir; // 仅 bit0 有效
+
+ private readonly byte[] txBuffer; // 临时发送缓冲区(单帧)
+ private readonly byte[] rxBuffer; // 当前接收帧(单帧)
+
+ private readonly Queue txFrameQueue; // 发送队列
+ private readonly Queue rxFrameQueue; // 接收队列
+ }
+}
\ No newline at end of file