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 System;
8 using System.Collections.Generic;
9 using System.Linq;
10 using Antmicro.Renode.Core.Structure.Registers;
11 using static Antmicro.Renode.Peripherals.Miscellaneous.S32K3XX_FlexIO;
12 
13 namespace Antmicro.Renode.Peripherals.Miscellaneous.S32K3XX_FlexIOModel
14 {
15     public class Timer : ResourceBlock
16     {
BuildRegisters(IResourceBlockOwner owner, int count)17         public static IReadOnlyList<Timer> BuildRegisters(IResourceBlockOwner owner, int count)
18         {
19             var statusFlags = Interrupt.BuildRegisters(owner, count, "TimerStatus", Registers.TimerStatus, Registers.TimerInterruptEnable);
20 
21             return statusFlags.Select((status, index) => BuildTimer(
22                 owner,
23                 index,
24                 status
25             )).ToList().AsReadOnly();
26         }
27 
EncodeShifterAsTriggerSelect(Shifter shifter)28         public static uint EncodeShifterAsTriggerSelect(Shifter shifter)
29         {
30             return shifter.Identifier * 4 + 1;
31         }
32 
33         public event Action ConfigurationChanged;
34         public event Action ControlChanged;
35 
36         public override IEnumerable<Interrupt> Interrupts => new[] { Status };
37         public override string Name => $"Timer{Identifier}";
38 
39         public Interrupt Status { get; }
40         public uint TriggerSelect => (uint)triggerSelect.Value;
41         public TimerTriggerPolarity TriggerPolarity => triggerPolarity.Value;
42         public TimerTriggerSource TriggerSource => triggerSource.Value;
43         public TimerTriggerOneTimeOperation OneTimeOperation => oneTimeOperation.Value;
44         public TimerMode Mode => mode.Value;
45         public TimerOutput Output => output.Value;
46         public TimerDecrement Decrement => decrement.Value;
47         public TimerReset ResetMode => resetMode.Value;
48         public TimerDisable Disable => disable.Value;
49         public TimerEnable Enable => enable.Value;
50         public TimerStopBit StopBit => stopBit.Value;
51         public TimerStartBit StartBit => startBit.Value;
52         public uint Compare
53         {
54             get => (uint)compare.Value;
55             set => compare.Value = value;
56         }
57         public uint Divider
58         {
59             get
60             {
61                 switch(Decrement)
62                 {
63                     case TimerDecrement.OnFLEXIOClockDividedBy16:
64                         return 16;
65                     case TimerDecrement.OnFLEXIOClockDividedBy256:
66                         return 256;
67                     default:
68                         return 1;
69                 }
70             }
71         }
72 
BuildTimer(IResourceBlockOwner owner, int index, Interrupt status)73         private static Timer BuildTimer(IResourceBlockOwner owner, int index, Interrupt status)
74         {
75             Timer timer = null;
76             var offset = index * 4;
77 
78             var controlRegister = (Registers.TimerControl0 + offset).Define(owner)
79                 .WithReservedBits(30, 2)
80                 .WithReservedBits(18, 4)
81                 .WithTag("PINCFG (Timer Pin Configuration)", 16, 2)
82                 .WithReservedBits(13, 3)
83                 .WithTag("PINSEL (Timer Pin Select)", 8, 5)
84                 .WithTaggedFlag("PINPOL (Timer Pin Polarity)", 7)
85                 .WithTaggedFlag("PIPINS (Timer Pin Input Select)", 6)
86                 .WithReservedBits(3, 2);
87 
88             var triggerSelectField = controlRegister.DefineValueField(24, 6, name: "TRGSEL (Trigger Select)");
89             var triggerPolarityField = controlRegister.DefineEnumField<TimerTriggerPolarity>(23, 1, name: "TRGPOL (Trigger Polarity)");
90             var triggerSourceField = controlRegister.DefineEnumField<TimerTriggerSource>(22, 1, name: "TRGSRC (Trigger Source)");
91             var oneTimeOperationField = controlRegister.DefineEnumField<TimerTriggerOneTimeOperation>(5, 1, name: "ONETIM (Timer One Time Operation)");
92             var modeField = controlRegister.DefineEnumField<TimerMode>(0, 3, name: "TIMOD (Timer Mode)");
93             controlRegister.WithChangeCallback((_, __) => timer.ControlChanged?.Invoke());
94 
95             var configurationRegister = (Registers.TimerConfiguration0 + offset).Define(owner)
96                 .WithReservedBits(26, 6)
97                 .WithReservedBits(23, 1)
98                 .WithReservedBits(19, 1)
99                 .WithReservedBits(15, 1)
100                 .WithReservedBits(11, 1)
101                 .WithReservedBits(6, 2)
102                 .WithReservedBits(2, 2)
103                 .WithReservedBits(0, 1);
104 
105             var outputField = configurationRegister.DefineEnumField<TimerOutput>(24, 2, name: "TIMOUT (Timer Output)");
106             var decrementField = configurationRegister.DefineEnumField<TimerDecrement>(20, 3, name: "TIMDEC (Timer Decrement)");
107             var resetField = configurationRegister.DefineEnumField<TimerReset>(16, 3, name: "TIMRST (Timer Reset)");
108             var disableField = configurationRegister.DefineEnumField<TimerDisable>(12, 3, name: "TIMDIS (Timer Disable)");
109             var enableField = configurationRegister.DefineEnumField<TimerEnable>(8, 3, name: "TIMENA (Timer Enable)");
110             var stopBitField = configurationRegister.DefineEnumField<TimerStopBit>(4, 2, name: "TSTOP (Timer Stop Bit)");
111             var startBitField = configurationRegister.DefineEnumField<TimerStartBit>(1, 1, name: "TSTART (Timer Start Bit)");
112             configurationRegister.WithChangeCallback((_, __) => timer.ConfigurationChanged?.Invoke());
113 
114             var compareField = (Registers.TimerCompare0 + offset).Define(owner)
115                 .WithReservedBits(16, 16)
116                 .DefineValueField(0, 16, name: "CMP (Timer Compare Value)");
117 
118             timer = new Timer(
119                 owner,
120                 (uint)index,
121                 status,
122                 triggerSelectField,
123                 triggerPolarityField,
124                 triggerSourceField,
125                 oneTimeOperationField,
126                 modeField,
127                 outputField,
128                 decrementField,
129                 resetField,
130                 disableField,
131                 enableField,
132                 stopBitField,
133                 startBitField,
134                 compareField
135             );
136             return timer;
137         }
138 
Timer(IResourceBlockOwner owner, uint identifier, Interrupt status, IValueRegisterField triggerSelect, IEnumRegisterField<TimerTriggerPolarity> triggerPolarity, IEnumRegisterField<TimerTriggerSource> triggerSource, IEnumRegisterField<TimerTriggerOneTimeOperation> oneTimeOperation, IEnumRegisterField<TimerMode> mode, IEnumRegisterField<TimerOutput> output, IEnumRegisterField<TimerDecrement> decrement, IEnumRegisterField<TimerReset> resetMode, IEnumRegisterField<TimerDisable> disable, IEnumRegisterField<TimerEnable> enable, IEnumRegisterField<TimerStopBit> stopBit, IEnumRegisterField<TimerStartBit> startBit, IValueRegisterField compare )139         private Timer(IResourceBlockOwner owner, uint identifier, Interrupt status,
140                 IValueRegisterField triggerSelect,
141                 IEnumRegisterField<TimerTriggerPolarity> triggerPolarity,
142                 IEnumRegisterField<TimerTriggerSource> triggerSource,
143                 IEnumRegisterField<TimerTriggerOneTimeOperation> oneTimeOperation,
144                 IEnumRegisterField<TimerMode> mode,
145                 IEnumRegisterField<TimerOutput> output,
146                 IEnumRegisterField<TimerDecrement> decrement,
147                 IEnumRegisterField<TimerReset> resetMode,
148                 IEnumRegisterField<TimerDisable> disable,
149                 IEnumRegisterField<TimerEnable> enable,
150                 IEnumRegisterField<TimerStopBit> stopBit,
151                 IEnumRegisterField<TimerStartBit> startBit,
152                 IValueRegisterField compare
153         ) : base(owner, identifier)
154         {
155             Status = status;
156             Status.MaskedFlagChanged += OnInterruptChange;
157 
158             this.triggerSelect = triggerSelect;
159             this.triggerPolarity = triggerPolarity;
160             this.triggerSource = triggerSource;
161             this.oneTimeOperation = oneTimeOperation;
162             this.mode = mode;
163             this.output = output;
164             this.decrement = decrement;
165             this.resetMode = resetMode;
166             this.disable = disable;
167             this.enable = enable;
168             this.stopBit = stopBit;
169             this.startBit = startBit;
170             this.compare = compare;
171         }
172 
173         private readonly IValueRegisterField triggerSelect;
174         private readonly IEnumRegisterField<TimerTriggerPolarity> triggerPolarity;
175         private readonly IEnumRegisterField<TimerTriggerSource> triggerSource;
176         private readonly IEnumRegisterField<TimerTriggerOneTimeOperation> oneTimeOperation;
177         private readonly IEnumRegisterField<TimerMode> mode;
178         private readonly IEnumRegisterField<TimerOutput> output;
179         private readonly IEnumRegisterField<TimerDecrement> decrement;
180         private readonly IEnumRegisterField<TimerReset> resetMode;
181         private readonly IEnumRegisterField<TimerDisable> disable;
182         private readonly IEnumRegisterField<TimerEnable> enable;
183         private readonly IEnumRegisterField<TimerStopBit> stopBit;
184         private readonly IEnumRegisterField<TimerStartBit> startBit;
185         private readonly IValueRegisterField compare;
186     }
187 
188     public enum TimerTriggerPolarity
189     {
190         ActiveHigh = 0,
191         ActiveLow = 1
192     }
193 
194     public enum TimerTriggerSource
195     {
196         External = 0,
197         Internal = 1
198     }
199 
200     public enum TimerTriggerOneTimeOperation
201     {
202         Normal = 0,
203         BlockUntilClear = 1
204     }
205 
206     public enum TimerMode
207     {
208         Disabled = 0b000,
209         DualBaud = 0b001,
210         DualPWMHigh = 0b010,
211         Single = 0b011,
212         SingleDisable = 0b100,
213         DualWord = 0b101,
214         DualPWMLow = 0b110,
215         SingleInputCapture = 0b111
216     }
217 
218     public enum TimerOutput
219     {
220         One = 0b00,
221         Zero = 0b01,
222         OneOnResetToo = 0b10,
223         ZeroOnResetToo = 0b11
224     }
225 
226     public enum TimerDecrement
227     {
228         OnFLEXIOClock = 0b000,
229         OnTriggerInputBothEdgesClockEqualsOutput = 0b001,
230         OnPinInputBothEdges = 0b010,
231         OnTriggerInputBothEdgesClockEqualsTrigger = 0b011,
232         OnFLEXIOClockDividedBy16 = 0b100,
233         OnFLEXIOClockDividedBy256 = 0b101,
234         OnPinInputRisingEdge = 0b110,
235         OnTriggerInputRisingEdge = 0b111
236     }
237 
238     public enum TimerReset
239     {
240         Never = 0b000,
241         OnOutputHigh = 0b001,
242         OnPinEqualToOutput = 0b010,
243         OnTriggerEqualToOutput = 0b011,
244         OnPinRisingEdge = 0b100,
245         Reserved = 0b101,
246         OnTriggerRisingEdge = 0b110,
247         OnTriggerBothEdges = 0b111
248     }
249 
250     public enum TimerDisable
251     {
252         Never = 0b000,
253         OnPreviousTimerDisable = 0b001,
254         OnTimerCompare = 0b010,
255         OnTimerCompareAndTriggerLow = 0b011,
256         OnPinBothEdges = 0b100,
257         OnPinBothEdgesProvidedTriggerIsHigh = 0b101,
258         OnTriggerFallingEdge = 0b110,
259         Reserved = 0b111
260     }
261 
262     public enum TimerEnable
263     {
264         Always = 0b000,
265         OnPreviousTimerEnable = 0b001,
266         OnTriggerHigh = 0b010,
267         OnTriggerHighAndPinHigh = 0b011,
268         OnPinRisingEdge = 0b100,
269         OnPinRisingEdgeAndTriggerHigh = 0b101,
270         OnTriggerRisingEdge = 0b110,
271         OnTriggerBothEdges = 0b111
272     }
273 
274     public enum TimerStopBit
275     {
276         Disabled = 0b00,
277         OnTimerCompare = 0b01,
278         OnTimerDisable = 0b10,
279         OnTimerCompareAndTimerDisable = 0b11
280     }
281 
282     public enum TimerStartBit
283     {
284         Disabled = 0b0,
285         Always = 0b1
286     }
287 }
288