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