1 //
2 // Copyright (c) 2010-2023 Antmicro
3 // Copyright (c) 2011-2015 Realtime Embedded
4 //
5 // This file is licensed under the MIT License.
6 // Full license text is available in 'licenses/MIT.txt'.
7 //
8 using System;
9 using System.Collections.Generic;
10 using Antmicro.Renode.Core;
11 using Antmicro.Renode.Core.Structure;
12 using Antmicro.Renode.Logging;
13 using Antmicro.Migrant;
14 using Antmicro.Migrant.Hooks;
15 
16 namespace Antmicro.Renode.Peripherals.UART
17 {
18     public abstract class UARTBase : NullRegistrationPointPeripheralContainer<IUART>, IUART
19     {
UARTBase(IMachine machine)20         protected UARTBase(IMachine machine) : base(machine)
21         {
22             queue = new Queue<byte>();
23             innerLock = new object();
24         }
25 
WriteChar(byte value)26         public virtual void WriteChar(byte value)
27         {
28             lock(innerLock)
29             {
30                 if(!IsReceiveEnabled)
31                 {
32                     this.Log(LogLevel.Debug, "UART or receive disabled; dropping the character written: '{0}'", (char)value);
33                     return;
34                 }
35 
36                 queue.Enqueue(value);
37                 CharWritten();
38             }
39         }
40 
Reset()41         public override void Reset()
42         {
43             ClearBuffer();
44         }
45 
Register(IUART uart, NullRegistrationPoint registrationPoint)46         public override void Register(IUART uart, NullRegistrationPoint registrationPoint)
47         {
48             base.Register(uart, registrationPoint);
49             ConnectEvents();
50         }
51 
Unregister(IUART uart)52         public override void Unregister(IUART uart)
53         {
54             base.Unregister(uart);
55 
56             this.CharReceived -= uart.WriteChar;
57             uart.CharReceived -= this.WriteChar;
58         }
59 
60         [field: Transient]
61         public event Action<byte> CharReceived;
62 
CharWritten()63         protected abstract void CharWritten();
QueueEmptied()64         protected abstract void QueueEmptied();
65 
TryGetCharacter(out byte character, bool peek = false)66         protected bool TryGetCharacter(out byte character, bool peek = false)
67         {
68             lock(innerLock)
69             {
70                 if(queue.Count == 0)
71                 {
72                     character = default(byte);
73                     return false;
74                 }
75                 if(peek)
76                 {
77                     character = queue.Peek();
78                 }
79                 else
80                 {
81                     character = queue.Dequeue();
82                 }
83                 if(queue.Count == 0)
84                 {
85                     QueueEmptied();
86                 }
87                 return true;
88             }
89         }
90 
TransmitCharacter(byte character)91         protected void TransmitCharacter(byte character)
92         {
93             CharReceived?.Invoke(character);
94         }
95 
ClearBuffer()96         protected void ClearBuffer()
97         {
98             lock(innerLock)
99             {
100                 queue.Clear();
101                 QueueEmptied();
102             }
103         }
104 
105         protected int Count
106         {
107             get
108             {
109                 lock(innerLock)
110                 {
111                     return queue.Count;
112                 }
113             }
114         }
115 
116         protected readonly object innerLock;
117         private readonly Queue<byte> queue;
118 
119         public abstract Bits StopBits { get; }
120 
121         public abstract Parity ParityBit { get; }
122 
123         public abstract uint BaudRate { get; }
124 
125         protected virtual bool IsReceiveEnabled => true;
126 
127         [PostDeserialization]
ConnectEvents()128         private void ConnectEvents()
129         {
130             if(RegisteredPeripheral != null)
131             {
132                 this.CharReceived += RegisteredPeripheral.WriteChar;
133                 RegisteredPeripheral.CharReceived += this.WriteChar;
134             }
135         }
136     }
137 }
138 
139