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