1 //
2 // Copyright (c) 2010-2024 Antmicro
3 //
4 // This file is licensed under the MIT License.
5 // Full license text is available in 'licenses/MIT.txt'.
6 //
7 using Antmicro.Renode.Logging;
8 using Antmicro.Renode.Peripherals.UART;
9 using Antmicro.Renode.Peripherals.Miscellaneous.S32K3XX_FlexIOModel;
10 
11 namespace Antmicro.Renode.Peripherals.Miscellaneous
12 {
13     public abstract class UARTDirectionBase
14     {
UARTDirectionBase(IEmulationElement owner, Shifter shifter)15         public UARTDirectionBase(IEmulationElement owner, Shifter shifter)
16         {
17             this.owner = owner;
18             this.shifter = shifter;
19             shifter.ControlOrConfigurationChanged += () => warningsShown = false;
20         }
21 
Reset()22         public virtual void Reset()
23         {
24             warningsShown = false;
25         }
26 
27         // The following properties support also unexpected configurations.
28         public uint BaudRateDivider => (((shifter.Timer?.Compare ?? 0) & 0xFF) + 1) * 2 * (shifter.Timer?.Divider ?? 1);
29         public Bits StopBits => shifter.StopBit == ShifterStopBitConfiguration ? Bits.One : Bits.None;
30 
LogWarnings()31         protected void LogWarnings()
32         {
33             if(warningsShown)
34             {
35                 return;
36             }
37             warningsShown = true;
38 
39             LogCommonWarnings();
40             LogSpecificWarnings();
41         }
42 
LogWarningNonEqual(uint given, uint expected, string configuration, string block)43         protected void LogWarningNonEqual(uint given, uint expected, string configuration, string block)
44         {
45             if(given != expected)
46             {
47                 owner.Log(LogLevel.Warning, "{0}{1} of {2} is unexpected, given 0x{3:X}, expected 0x{4:X}", WarningPrefix, configuration, block, given, expected);
48             }
49         }
50 
LogWarning(string message, params object[] arg)51         protected void LogWarning(string message, params object[] arg)
52         {
53             owner.Log(LogLevel.Warning, WarningPrefix + message, arg);
54         }
55 
LogSpecificWarnings()56         protected abstract void LogSpecificWarnings();
57 
58         protected abstract string WarningPrefix { get; }
59 
60         protected readonly Shifter shifter;
61         protected const uint Compare8bitShift = 2 * 8 - 1;
62         protected const uint ShifterStopBitConfiguration = 0b11;
63 
LogCommonWarnings()64         private void LogCommonWarnings()
65         {
66             LogWarningNonEqual(shifter.StartBit, 0b10, "start bit", shifter.Name);
67             LogWarningNonEqual(shifter.StopBit, ShifterStopBitConfiguration, "stop bit", shifter.Name);
68 
69             if(shifter.Timer == null)
70             {
71                 LogWarning("No timer set for {1}", shifter.Name);
72                 return;
73             }
74 
75             LogWarningNonEqual(shifter.Timer.Compare >> 8, Compare8bitShift, "compare value (upper bits)", shifter.Timer.Name);
76             LogWarningNonEqual((uint)shifter.Timer.Decrement, (uint)TimerDecrement.OnFLEXIOClockDividedBy16, "decrement configuration", shifter.Timer.Name);
77             LogWarningNonEqual((uint)shifter.Timer.StartBit, (uint)TimerStartBit.Always, "start bit", shifter.Timer.Name);
78             LogWarningNonEqual((uint)shifter.Timer.StopBit, (uint)TimerStopBit.OnTimerDisable, "stop bit", shifter.Timer.Name);
79             LogWarningNonEqual((uint)shifter.Timer.Mode, (uint)TimerMode.DualBaud, "mode", shifter.Timer.Name);
80             LogWarningNonEqual((uint)shifter.Timer.OneTimeOperation, (uint)TimerTriggerOneTimeOperation.Normal, "one time operation", shifter.Timer.Name);
81         }
82 
83         private IEmulationElement owner;
84         private bool warningsShown;
85     }
86 }
87