using System; using System.Collections.Generic; using Antmicro.Renode.Core; using Antmicro.Renode.Peripherals.Bus; using Antmicro.Renode.Logging; namespace Antmicro.Renode.Peripherals.ThermalOC { public class ThermalOC1 : IDoubleWordPeripheral, IKnownSize { private readonly Dictionary registerMap; private readonly object lockObject = new object(); private readonly uint baseAddress; private const uint REG_HEAT_1_8 = 0x20; // 1-8路加热输出 private const uint REG_HEAT_9_16 = 0x24; // 9-16路加热输出 private const uint REG_HEAT_17_24 = 0x28; // 17-24路加热输出 private const uint REG_HEAT_25_32 = 0x2C; // 25-32路加热输出 private const uint REG_HEAT_33_40 = 0x30; // 33-40路加热输出 private const uint REG_HEAT_41_48 = 0x34; // 41-48路加热输出 private const uint REG_HEAT_49_56 = 0x38; // 49-56路加热输出 private const uint REG_HEAT_57_64 = 0x3C; // 57-64路加热输出 private readonly (uint offset, int start, int end)[] registers = new[] { (REG_HEAT_1_8, 1, 8), (REG_HEAT_9_16, 9, 16), (REG_HEAT_17_24, 17, 24), (REG_HEAT_25_32, 25, 32), (REG_HEAT_33_40, 33, 40), (REG_HEAT_41_48, 41, 48), (REG_HEAT_49_56, 49, 56), (REG_HEAT_57_64, 57, 64) }; public ThermalOC1(IMachine machine) { baseAddress = 0x22000000; registerMap = new Dictionary(); InitializeRegisters(); LogInitializationInfo(); } private void InitializeRegisters() { lock (lockObject) { foreach (var reg in registers) { registerMap[reg.offset] = 0x00; } } } private void LogInitializationInfo() { this.Log(LogLevel.Info, "=========================================="); this.Log(LogLevel.Info, "热控OC1初始化完成"); this.Log(LogLevel.Info, "基地址: 0x{0:X8}", baseAddress); this.Log(LogLevel.Info, "每个寄存器控制8路加热输出"); this.Log(LogLevel.Info, "共64路加热输出通道 (通道1-64)"); this.Log(LogLevel.Info, "寄存器定义: 低8位有效,1表示输出,0表示关闭"); this.Log(LogLevel.Info, "位对应关系: D0=通道起始, D7=通道起始+7"); this.Log(LogLevel.Info, "所有通道初始状态: 关闭"); this.Log(LogLevel.Info, ""); this.Log(LogLevel.Info, "寄存器地址映射:"); foreach (var reg in registers) { uint fullAddress = baseAddress + reg.offset; this.Log(LogLevel.Info, " 地址0x{0:X8} (偏移0x{1:X2}), 控制通道{2}-{3}", fullAddress, reg.offset, reg.start, reg.end); } this.Log(LogLevel.Info, "=========================================="); } private string GetBinaryString(byte value) { return Convert.ToString(value, 2).PadLeft(8, '0'); } private string GetChannelStatus(byte value, int start) { List active = new List(); for (int i = 0; i < 8; i++) { if ((value & (1 << i)) != 0) { active.Add($"通道{start + i}"); } } return active.Count > 0 ? string.Join(", ", active) : "无"; } public uint ReadDoubleWord(long offset) { lock (lockObject) { uint fullAddress = baseAddress + (uint)offset; foreach (var reg in registers) { if (offset == reg.offset) { if (registerMap.TryGetValue(offset, out byte value)) { string binary = GetBinaryString(value); string channels = GetChannelStatus(value, reg.start); this.Log(LogLevel.Info, "热控OC1读取: 地址0x{0:X8} (偏移0x{1:X2})", fullAddress, offset); this.Log(LogLevel.Info, " 十六进制: 0x{0:X2}", value); this.Log(LogLevel.Info, " 二进制: {0} (D7-D0)", binary); this.Log(LogLevel.Info, " 开启通道: {0}", channels); return value; } break; } } this.Log(LogLevel.Warning, "热控OC1读取未定义地址: 0x{0:X8}", fullAddress); return 0; } } public void WriteDoubleWord(long offset, uint value) { lock (lockObject) { uint fullAddress = baseAddress + (uint)offset; byte writeValue = (byte)(value & 0xFF); foreach (var reg in registers) { if (offset == reg.offset) { byte oldValue = registerMap.ContainsKey(offset) ? registerMap[offset] : (byte)0; registerMap[offset] = writeValue; string oldBinary = GetBinaryString(oldValue); string newBinary = GetBinaryString(writeValue); string newChannels = GetChannelStatus(writeValue, reg.start); this.Log(LogLevel.Info, "热控OC1写入: 地址0x{0:X8} (偏移0x{1:X2})", fullAddress, offset); this.Log(LogLevel.Info, " 写入值: 0x{0:X2} (二进制: {1})", writeValue, newBinary); this.Log(LogLevel.Info, " 原值: 0x{0:X2} (二进制: {1})", oldValue, oldBinary); this.Log(LogLevel.Info, " 开启通道: {0}", newChannels); return; } } this.Log(LogLevel.Warning, "热控OC1尝试写入未定义地址: 0x{0:X8}, 值0x{1:X2}", fullAddress, writeValue); } } public void Reset() { lock (lockObject) { registerMap.Clear(); InitializeRegisters(); } this.Log(LogLevel.Info, "热控OC1 (基地址0x{0:X8}) 已复位", baseAddress); } public long Size => 0x40; } }