1 // 2 // Copyright (c) 2010-2023 Antmicro 3 // 4 // This file is licensed under the MIT License. 5 // Full license text is available in 'licenses/MIT.txt'. 6 // 7 using System; 8 using System.Collections.Generic; 9 using Antmicro.Renode.Core; 10 using Antmicro.Renode.Core.Structure.Registers; 11 using Antmicro.Renode.Logging; 12 using Antmicro.Renode.Peripherals.Bus; 13 using Antmicro.Renode.Utilities; 14 15 namespace Antmicro.Renode.Peripherals.UART 16 { 17 public class K6xF_UART : UARTBase, IBytePeripheral, IKnownSize 18 { K6xF_UART(IMachine machine)19 public K6xF_UART(IMachine machine) : base(machine) 20 { 21 baudRateDivValue = 0; 22 transmitQueue = new Queue<byte>(); 23 24 var registersMap = new Dictionary<long, ByteRegister> 25 { 26 {(long)Registers.BaudRateHigh, new ByteRegister(this) 27 .WithTaggedFlag("LBKDIE", 7) 28 .WithTaggedFlag("RXEDGIE", 6) 29 .WithTaggedFlag("SBNS", 5) 30 .WithValueField(0, 5, writeCallback: (_, value) => 31 { 32 // setting the high bits of the baud rate factor 33 BitHelper.ReplaceBits(ref baudRateDivValue, (uint)value, 5, 8); 34 },name: "SBR") 35 }, 36 {(long)Registers.BaudRateLow, new ByteRegister(this) 37 .WithValueField(0, 8, writeCallback: (_, value) => 38 { 39 // setting the low bits of the baud rate factor 40 BitHelper.ReplaceBits(ref baudRateDivValue, (uint)value, 8); 41 },name: "SBR") 42 }, 43 {(long)Registers.Control2, new ByteRegister(this) 44 .WithFlag(7, out transmitterIRQEnabled, name: "TIE") 45 .WithTaggedFlag("TCIE", 6) 46 .WithFlag(5, out receiverIRQEnabled, name: "RIE") 47 .WithTaggedFlag("ILIE", 4) 48 .WithFlag(3, out transmitterEnabled, name: "TE") 49 .WithFlag(2, out receiverEnabled, name: "RE") 50 .WithTaggedFlag("RWU", 1) 51 .WithTaggedFlag("SBK", 0) 52 .WithWriteCallback((_, __) => 53 { 54 UpdateInterrupts(); 55 }) 56 }, 57 {(long)Registers.Status1, new ByteRegister(this) 58 .WithFlag(7, FieldMode.Read, valueProviderCallback: _ => 59 { 60 return transmitQueue.Count <= transmitWatermark; 61 },name: "TDRE") 62 .WithTaggedFlag("TC", 6) 63 .WithFlag(5, FieldMode.Read, valueProviderCallback: _ => 64 { 65 return Count >= receiverWatermark; 66 }, name: "RDRF") 67 .WithTaggedFlag("IDLE", 4) 68 .WithTaggedFlag("OR", 3) 69 .WithTaggedFlag("NF", 2) 70 .WithTaggedFlag("FE", 1) 71 }, 72 {(long)Registers.Status2, new ByteRegister(this) 73 .WithTaggedFlag("LBKDIF", 7) 74 .WithTaggedFlag("RXEDGIF", 6) 75 .WithTaggedFlag("MSBF", 5) 76 .WithTaggedFlag("RXINV", 4) 77 .WithTaggedFlag("RWUID", 3) 78 .WithTaggedFlag("BRK13", 2) 79 .WithTaggedFlag("LBKDE", 1) 80 .WithTaggedFlag("RAF", 0) 81 }, 82 {(long)Registers.Data, new ByteRegister(this) 83 .WithValueField(0, 8, 84 writeCallback: (_, b) => 85 { 86 if(!transmitterEnabled.Value) 87 { 88 this.Log(LogLevel.Warning, "Transmitter not enabled"); 89 return; 90 } 91 transmitQueue.Enqueue((byte)b); 92 TransmitData(); 93 UpdateInterrupts(); 94 }, 95 valueProviderCallback: _ => 96 { 97 if(!receiverEnabled.Value) 98 { 99 return 0; 100 } 101 if(!TryGetCharacter(out var character)) 102 { 103 this.Log(LogLevel.Warning, "Trying to read data from empty receive fifo"); 104 } 105 UpdateInterrupts(); 106 return character; 107 }, 108 name: "RT") 109 }, 110 {(long)Registers.Control4, new ByteRegister(this) 111 .WithTaggedFlag("MAEN1", 7) 112 .WithTaggedFlag("MAEN2", 6) 113 .WithTaggedFlag("M10", 5) 114 .WithValueField(0, 5, out baudRateFineAdjustValue, name: "BRFA") 115 }, 116 {(long)Registers.ExtendedData, new ByteRegister(this) 117 .WithTaggedFlag("NOISY", 7) 118 .WithTaggedFlag("PARITYE", 6) 119 .WithReservedBits(0,6) 120 }, 121 {(long)Registers.FIFOStatus, new ByteRegister(this) 122 .WithTaggedFlag("TXEMPT", 7) 123 .WithTaggedFlag("RXEMPT", 6) 124 .WithReservedBits(3,3) 125 .WithTaggedFlag("RXOF", 2) 126 .WithTaggedFlag("TXOF", 1) 127 .WithTaggedFlag("RXUF", 0) 128 }, 129 {(long)Registers.FIFOTransmitWatermark, new ByteRegister(this) 130 .WithValueField(0, 8, FieldMode.Write | FieldMode.Read, 131 writeCallback: (_, b) => 132 { 133 if(transmitterEnabled.Value) 134 { 135 this.Log(LogLevel.Warning, "Cannot set transmitter watermark when transmitter is enabled"); 136 return; 137 } 138 transmitWatermark = (uint)b; 139 UpdateInterrupts(); 140 }, 141 valueProviderCallback: _ => 142 { 143 return transmitWatermark; 144 }, 145 name: "TXWATER") 146 }, 147 {(long)Registers.FIFOReceiveWatermark, new ByteRegister(this) 148 .WithValueField(0, 8, FieldMode.Write | FieldMode.Read, 149 writeCallback: (_, b) => 150 { 151 if(receiverEnabled.Value) 152 { 153 this.Log(LogLevel.Warning, "Cannot set receiver watermark when receiver is enabled"); 154 return; 155 } 156 receiverWatermark = (uint)b; 157 UpdateInterrupts(); 158 }, 159 valueProviderCallback: _ => 160 { 161 return receiverWatermark; 162 }, 163 name: "RXWATER") 164 }, 165 {(long)Registers.FIFOReceiveCount, new ByteRegister(this) 166 .WithValueField(0,8, FieldMode.Read, valueProviderCallback: _ => 167 { 168 return (uint)Count; 169 },name: "RXCOUNT") 170 } 171 }; 172 173 IRQ = new GPIO(); 174 registers = new ByteRegisterCollection(this, registersMap); 175 } 176 ReadByte(long offset)177 public byte ReadByte(long offset) 178 { 179 return registers.Read(offset); 180 } 181 WriteByte(long offset, byte value)182 public void WriteByte(long offset, byte value) 183 { 184 registers.Write(offset, value); 185 } 186 CharWritten()187 protected override void CharWritten() 188 { 189 UpdateInterrupts(); 190 } 191 QueueEmptied()192 protected override void QueueEmptied() 193 { 194 // do nothing 195 } 196 197 public long Size => 0x1000; 198 199 public GPIO IRQ { get; private set; } 200 201 //TODO should be calculated based upon UART clock 202 public override uint BaudRate => 115200; 203 public override Bits StopBits => Bits.One; 204 public override Parity ParityBit => Parity.Even; 205 TransmitData()206 private void TransmitData() 207 { 208 if(transmitQueue.Count < transmitWatermark) 209 { 210 return; 211 } 212 213 while(transmitQueue.Count != 0) 214 { 215 var b = transmitQueue.Dequeue(); 216 this.TransmitCharacter((byte)b); 217 } 218 } 219 UpdateInterrupts()220 private void UpdateInterrupts() 221 { 222 IRQ.Set((transmitterEnabled.Value && transmitterIRQEnabled.Value) || 223 (receiverEnabled.Value && receiverIRQEnabled.Value && Count >= receiverWatermark)); 224 } 225 226 private uint baudRateDivValue; 227 private uint receiverWatermark = 0; 228 private uint transmitWatermark = 0; 229 230 private readonly Queue<byte> transmitQueue; 231 private readonly ByteRegisterCollection registers; 232 private readonly IValueRegisterField baudRateFineAdjustValue; 233 private readonly IFlagRegisterField receiverEnabled; 234 private readonly IFlagRegisterField transmitterEnabled; 235 private readonly IFlagRegisterField transmitterIRQEnabled; 236 private readonly IFlagRegisterField receiverIRQEnabled; 237 238 private enum Registers 239 { 240 BaudRateHigh = 0x00, 241 BaudRateLow = 0x01, 242 Control1 = 0x02, 243 Control2 = 0x03, 244 Status1 = 0x04, 245 Status2 = 0x05, 246 Control3 = 0x06, 247 Data = 0x07, 248 MatchAddress1 = 0x08, 249 MatchAddress2 = 0x09, 250 Control4 = 0x0A, 251 Control5 = 0x0B, 252 ExtendedData = 0x0C, 253 Modem = 0x0D, 254 Infrared = 0x0E, 255 FIFOParameters = 0x10, 256 FIFOControl = 0x11, 257 FIFOStatus = 0x12, 258 FIFOTransmitWatermark = 0x13, 259 FIFOTransmitCount = 0x14, 260 FIFOReceiveWatermark = 0x15, 261 FIFOReceiveCount = 0x16, 262 Control7816 = 0x18, 263 InterruptEnable7816 = 0x19, 264 InterruptStatus7816 = 0x1A, 265 WaitParameter7816 = 0x1B, 266 WaitN7816 = 0x1C, 267 WaitFD7816 = 0x1D, 268 ErrorThreshold = 0x1E, 269 TransmitLength = 0x1F 270 } 271 272 private enum TransmitCompleteFlagValues 273 { 274 Active = 0, 275 Idle = 1 276 } 277 } 278 } 279